File: mail_message_schedule.py

package info (click to toggle)
odoo 18.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 878,716 kB
  • sloc: javascript: 927,937; python: 685,670; xml: 388,524; sh: 1,033; sql: 415; makefile: 26
file content (135 lines) | stat: -rw-r--r-- 5,191 bytes parent folder | download
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import json
import logging

from datetime import datetime

from odoo import api, fields, models

_logger = logging.getLogger(__name__)


class MailMessageSchedule(models.Model):
    """ Mail message notification schedule queue.

    This model is used to store the mail messages scheduled. So we can
    delay the sending of the notifications. A scheduled date field already
    exists on the <mail.mail> but it does not allow us to delay the sending
    of the <bus.bus> notifications.
    """
    _name = 'mail.message.schedule'
    _description = 'Scheduled Messages'
    _order = 'scheduled_datetime DESC, id DESC'
    _rec_name = 'mail_message_id'

    mail_message_id = fields.Many2one(
        'mail.message', string='Message',
        ondelete='cascade', required=True)
    notification_parameters = fields.Text('Notification Parameter')
    scheduled_datetime = fields.Datetime(
        'Scheduled Send Date', required=True,
        help='Datetime at which notification should be sent.')

    @api.model_create_multi
    def create(self, vals_list):
        schedules = super().create(vals_list)
        if schedules:
            self.env.ref('mail.ir_cron_send_scheduled_message')._trigger_list(
                set(schedules.mapped('scheduled_datetime'))
            )
        return schedules

    @api.model
    def _send_notifications_cron(self):
        messages_scheduled = self.env['mail.message.schedule'].search(
            [('scheduled_datetime', '<=', datetime.utcnow())]
        )
        if messages_scheduled:
            _logger.info('Send %s scheduled messages', len(messages_scheduled))
            messages_scheduled._send_notifications()

    def force_send(self):
        """ Launch notification process independently from the expected date. """
        return self._send_notifications()

    def _send_notifications(self, default_notify_kwargs=None):
        """ Send notification for scheduled messages.

        :param dict default_notify_kwargs: optional parameters to propagate to
          ``notify_thread``. Those are default values overridden by content of
          ``notification_parameters`` field.
        """
        for model, schedules in self._group_by_model().items():
            if model:
                records = self.env[model].browse(schedules.mapped('mail_message_id.res_id'))
            else:
                records = [self.env['mail.thread']] * len(schedules)

            for record, schedule in zip(records, schedules):
                notify_kwargs = dict(default_notify_kwargs or {}, skip_existing=True)
                try:
                    schedule_notify_kwargs = json.loads(schedule.notification_parameters)
                except Exception:
                    pass
                else:
                    schedule_notify_kwargs.pop('scheduled_date', None)
                    notify_kwargs.update(schedule_notify_kwargs)

                record._notify_thread(schedule.mail_message_id, msg_vals=False, **notify_kwargs)

        self.unlink()
        return True

    @api.model
    def _send_message_notifications(self, messages, default_notify_kwargs=None):
        """ Send scheduled notification for given messages.

        :param <mail.message> messages: scheduled sending related to those messages
          will be sent now;
        :param dict default_notify_kwargs: optional parameters to propagate to
          ``notify_thread``. Those are default values overridden by content of
          ``notification_parameters`` field.

        :return bool: False if no schedule has been found, True otherwise
        """
        messages_scheduled = self.search(
            [('mail_message_id', 'in', messages.ids)]
        )
        if not messages_scheduled:
            return False

        messages_scheduled._send_notifications(default_notify_kwargs=default_notify_kwargs)
        return True

    @api.model
    def _update_message_scheduled_datetime(self, messages, new_datetime):
        """ Update scheduled datetime for scheduled sending related to messages.

        :param <mail.message> messages: scheduled sending related to those messages
          will be updated. Missing one are skipped;
        :param datetime new_datetime: new datetime for sending. New triggers
          are created based on it;

        :return bool: False if no schedule has been found, True otherwise
        """
        messages_scheduled = self.search(
            [('mail_message_id', 'in', messages.ids)]
        )
        if not messages_scheduled:
            return False

        messages_scheduled.scheduled_datetime = new_datetime
        self.env.ref('mail.ir_cron_send_scheduled_message')._trigger(new_datetime)
        return True

    def _group_by_model(self):
        grouped = {}
        for schedule in self:
            model = schedule.mail_message_id.model if schedule.mail_message_id.model and schedule.mail_message_id.res_id else False
            if model not in grouped:
                grouped[model] = schedule
            else:
                grouped[model] += schedule
        return grouped