diff --git a/mail_post_defer/models/mail_message_schedule.py b/mail_post_defer/models/mail_message_schedule.py index eba9a0340..1adf977b8 100644 --- a/mail_post_defer/models/mail_message_schedule.py +++ b/mail_post_defer/models/mail_message_schedule.py @@ -13,3 +13,14 @@ class MailMessageSchedule(models.Model): return super(MailMessageSchedule, _self)._send_notifications( default_notify_kwargs=default_notify_kwargs ) + + def _group_by_model(self): + """Make sure only mail.thread children are grouped with model.""" + result = super()._group_by_model() + for model, records in result.copy().items(): + # Move records without mail.thread mixin to a False key + if model and not hasattr(model, "_notify_thread"): + result.pop(model) + result.setdefault(False, self.browse()) + result[False] += records + return result diff --git a/mail_post_defer/models/mail_thread.py b/mail_post_defer/models/mail_thread.py index bb657c5b2..20c7737bd 100644 --- a/mail_post_defer/models/mail_thread.py +++ b/mail_post_defer/models/mail_thread.py @@ -1,4 +1,4 @@ -# Copyright 2022-2023 Moduon Team S.L. +# Copyright 2022-2024 Moduon Team S.L. # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). from datetime import datetime, timedelta @@ -12,7 +12,15 @@ class MailThread(models.AbstractModel): def _notify_thread(self, message, msg_vals=False, **kwargs): """Defer emails by default.""" - _self = self + # Remember if the author should be notified when deferring + kwargs.setdefault( + "mail_post_defer_notify_author", + self.env.context.get("mail_notify_author", False), + ) + _self = self.with_context( + mail_notify_author=kwargs["mail_post_defer_notify_author"] + ) + # Don't defer automatically if forcing send if "mail_defer_seconds" not in _self.env.context: force_send = _self.env.context.get("mail_notify_force_send") or kwargs.get( "force_send", False @@ -21,6 +29,7 @@ class MailThread(models.AbstractModel): if not force_send: # If deferring message, give the user some minimal time to revert it _self = _self.with_context(mail_defer_seconds=30) + # Apply deferring defer_seconds = _self.env.context.get("mail_defer_seconds") if defer_seconds: kwargs.setdefault( diff --git a/mail_post_defer/tests/test_mail.py b/mail_post_defer/tests/test_mail.py index 3d717feb4..84a87fd09 100644 --- a/mail_post_defer/tests/test_mail.py +++ b/mail_post_defer/tests/test_mail.py @@ -182,6 +182,40 @@ class MessagePostCase(MailPostDeferCommon): with self.assertRaises(UserError): self.partner_portal._message_update_content(msg, "", []) + def test_model_without_threading(self): + """When models don't inherit from mail.thread, they still work.""" + self.partner_portal.email = "portal@example.com" + with self.mock_mail_gateway(): + self.env["mail.thread"].with_context( + mail_notify_author=True + ).message_notify( + author_id=self.partner_employee.id, + body="test body", + model="res.country", + partner_ids=(self.partner_employee | self.partner_portal).ids, + res_id=self.ref("base.es"), + ) + self.assertNoMail(self.partner_employee | self.partner_portal) + # One minute later, the cron sends the mail + with freezegun.freeze_time("2023-01-02 10:01:00"): + self.env["mail.message.schedule"]._send_notifications_cron() + self.env["mail.mail"].process_email_queue() + self.assertMailMail( + self.partner_portal, + "sent", + author=self.partner_employee, + content="test body", + ) + self.assertMailMail( + self.partner_employee, + "sent", + author=self.partner_employee, + content="test body", + ) + # Safety belt to avoid false positives in this test + self.assertFalse(hasattr(self.env["res.country"], "_notify_thread")) + self.assertTrue(hasattr(self.env["res.partner"], "_notify_thread")) + @tagged("-at_install", "post_install") @freezegun.freeze_time("2023-01-02 10:00:00")