summaryrefslogtreecommitdiff
path: root/addons/lunch/models/lunch_alert.py
blob: 9110f792356e99e94f264c585815822a29ca2b33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import pytz

from odoo import api, fields, models
from odoo.osv import expression

from .lunch_supplier import float_to_time
from datetime import datetime, timedelta

from odoo.addons.base.models.res_partner import _tz_get

WEEKDAY_TO_NAME = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']

class LunchAlert(models.Model):
    """ Alerts to display during a lunch order. An alert can be specific to a
    given day, weekly or daily. The alert is displayed from start to end hour. """
    _name = 'lunch.alert'
    _description = 'Lunch Alert'
    _order = 'write_date desc, id'

    name = fields.Char('Alert Name', required=True, translate=True)
    message = fields.Html('Message', required=True, translate=True)

    mode = fields.Selection([
        ('alert', 'Alert in app'),
        ('chat', 'Chat notification')], string='Display', default='alert')
    recipients = fields.Selection([
        ('everyone', 'Everyone'),
        ('last_week', 'Employee who ordered last week'),
        ('last_month', 'Employee who ordered last month'),
        ('last_year', 'Employee who ordered last year')], string='Recipients', default='everyone')
    notification_time = fields.Float(default=10.0, string='Notification Time')
    notification_moment = fields.Selection([
        ('am', 'AM'),
        ('pm', 'PM')], default='am', required=True)
    tz = fields.Selection(_tz_get, string='Timezone', required=True, default=lambda self: self.env.user.tz or 'UTC')

    until = fields.Date('Show Until')
    recurrency_monday = fields.Boolean('Monday', default=True)
    recurrency_tuesday = fields.Boolean('Tuesday', default=True)
    recurrency_wednesday = fields.Boolean('Wednesday', default=True)
    recurrency_thursday = fields.Boolean('Thursday', default=True)
    recurrency_friday = fields.Boolean('Friday', default=True)
    recurrency_saturday = fields.Boolean('Saturday', default=True)
    recurrency_sunday = fields.Boolean('Sunday', default=True)

    available_today = fields.Boolean('Is Displayed Today',
                                     compute='_compute_available_today', search='_search_available_today')

    active = fields.Boolean('Active', default=True)

    location_ids = fields.Many2many('lunch.location', string='Location')

    _sql_constraints = [
        ('notification_time_range',
            'CHECK(notification_time >= 0 and notification_time <= 12)',
            'Notification time must be between 0 and 12')
    ]

    @api.depends('recurrency_monday', 'recurrency_tuesday', 'recurrency_wednesday',
                 'recurrency_thursday', 'recurrency_friday', 'recurrency_saturday',
                 'recurrency_sunday')
    def _compute_available_today(self):
        today = fields.Date.context_today(self)
        fieldname = 'recurrency_%s' % (WEEKDAY_TO_NAME[today.weekday()])

        for alert in self:
            alert.available_today = alert.until > today if alert.until else True and alert[fieldname]

    def _search_available_today(self, operator, value):
        if (not operator in ['=', '!=']) or (not value in [True, False]):
            return []

        searching_for_true = (operator == '=' and value) or (operator == '!=' and not value)
        today = fields.Date.context_today(self)
        fieldname = 'recurrency_%s' % (WEEKDAY_TO_NAME[today.weekday()])

        return expression.AND([
            [(fieldname, operator, value)],
            expression.OR([
                [('until', '=', False)],
                [('until', '>' if searching_for_true else '<', today)],
            ])
        ])

    def _notify_chat(self):
        records = self.search([('mode', '=', 'chat'), ('active', '=', True)])

        today = fields.Date.today()
        now = fields.Datetime.now()

        for alert in records:
            notification_to = now.astimezone(pytz.timezone(alert.tz)).replace(second=0, microsecond=0, tzinfo=None)
            notification_from = notification_to - timedelta(minutes=5)
            send_at = datetime.combine(fields.Date.today(),
                float_to_time(alert.notification_time, alert.notification_moment))

            if alert.available_today and send_at > notification_from and send_at <= notification_to:
                order_domain = [('state', '!=', 'cancelled')]

                if alert.location_ids.ids:
                    order_domain = expression.AND([order_domain, [('user_id.last_lunch_location_id', 'in', alert.location_ids.ids)]])

                if alert.recipients != 'everyone':
                    weeks = 1

                    if alert.recipients == 'last_month':
                        weeks = 4
                    else:  # last_year
                        weeks = 52

                    delta = timedelta(weeks=weeks)
                    order_domain = expression.AND([order_domain, [('date', '>=', today - delta)]])

                orders = self.env['lunch.order'].search(order_domain).mapped('user_id')
                partner_ids = [user.partner_id.id for user in orders]
                if partner_ids:
                    self.env['mail.thread'].message_notify(body=alert.message, partner_ids=partner_ids)