11# Copyright 2022-2024 Moduon Team S.L. <info@moduon.team>
22# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
33
4- from datetime import datetime , timedelta
4+ from datetime import timedelta
55
6- from odoo import _ , fields , models
7- from odoo .exceptions import UserError
6+ from odoo import fields , models
87
98
109class MailThread (models .AbstractModel ):
@@ -27,41 +26,45 @@ def _notify_thread(self, message, msg_vals=False, **kwargs):
2726 if defer_seconds :
2827 kwargs .setdefault (
2928 "scheduled_date" ,
30- datetime . utcnow () + timedelta (seconds = defer_seconds ),
29+ fields . Datetime . now () + timedelta (seconds = defer_seconds ),
3130 )
3231 return super (MailThread , _self )._notify_thread (
3332 message , msg_vals = msg_vals , ** kwargs
3433 )
3534
36- def _check_can_update_message_content (self , messages ):
37- """Allow updating unsent messages.
38-
39- Upstream Odoo only allows updating notes. We want to be able to update
40- any message that is not sent yet. When a message is scheduled,
41- notifications and mails will still not exist. Another possibility is
42- that they exist but are not sent yet. In those cases, we are still on
43- time to update it.
44- """
45- # Check that no notification or mail has been sent yet
46- if any (ntf .notification_status == "sent" for ntf in messages .notification_ids ):
47- raise UserError (
48- _ ("Cannot modify message; notifications were already sent." )
49- ) from None
50- if any (mail .state in {"sent" , "received" } for mail in messages .mail_ids ):
51- raise UserError (
52- _ ("Cannot modify message; notifications were already sent." )
53- ) from None
54-
55- # For unsent messages, we're more permissive than the original implementation
56- # Only check the basic restrictions that make sense
57- if any (message .message_type != "comment" for message in messages ):
58- raise UserError (
59- _ ("Only messages type comment can have their content updated" )
35+ def _message_update_content (self , message , / , * , body , ** kwargs ):
36+ # If anything already went out, fall back to the standard behavior
37+ if any (ntf .notification_status == "sent" for ntf in message .notification_ids ):
38+ return super ()._message_update_content (message , body = body , ** kwargs )
39+ scheduled_date = fields .Datetime .now () + timedelta (seconds = 30 )
40+ Schedule = self .env ["mail.message.schedule" ].sudo ()
41+ sched = Schedule .search ([("mail_message_id" , "=" , message .id )], limit = 1 )
42+ if sched :
43+ sched .scheduled_datetime = scheduled_date
44+ # In case emails are already created but not sent yet, cancel queued mails and
45+ # delete the notification (so nothing goes out with old content)
46+ else :
47+ message .mail_ids .filtered (
48+ lambda x : x .state in {"outgoing" , "exception" , "draft" }
49+ ).write ({"state" : "cancel" })
50+ message .notification_ids .filtered (
51+ lambda x : x .notification_status
52+ in {"ready" , "exception" , "canceled" , "bounce" }
53+ ).unlink ()
54+ Schedule .create (
55+ {"mail_message_id" : message .id , "scheduled_datetime" : scheduled_date }
6056 )
61-
62- def _message_update_content (self , * args , ** kwargs ):
63- """Defer messages by extra 30 seconds after updates."""
64- kwargs .setdefault (
65- "scheduled_date" , fields .Datetime .now () + timedelta (seconds = 30 )
66- )
67- return super ()._message_update_content (* args , ** kwargs )
57+ kw = dict (kwargs )
58+ # Drop empty [] for partner_ids, or else Odoo will try to send to nobody
59+ if not kw .get ("partner_ids" ):
60+ kw .pop ("partner_ids" , None )
61+ res = super ()._message_update_content (message , body = body , ** kw )
62+ # Delete empty pending outgoing mails
63+ if empty_messages := message .sudo ()._filter_empty ():
64+ empty_messages .mail_ids .filtered (
65+ lambda mail : mail .state == "outgoing"
66+ ).unlink ()
67+ empty_messages .env ["mail.message.schedule" ].search (
68+ [("mail_message_id" , "in" , empty_messages .ids )]
69+ ).unlink ()
70+ return res
0 commit comments