From ebc17ee59f5e36eed65dcd737e7b452826721fc5 Mon Sep 17 00:00:00 2001 From: mav-adhoc Date: Fri, 9 Oct 2026 17:46:18 +0000 Subject: [PATCH] [FIX] mail_ux: drop private context keys from scheduled messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit send_context is a Json field and base_automation leaves __action_done in the context: a dict keyed by recordsets. Creating the scheduled message crashed with "TypeError: keys must be str, int, float, bool or None, not base.automation". Resetting the key before _action_schedule_message was not enough: the context dict is shared by reference and base_automation mutates it in place while the composer runs, so the private keys are now dropped where send_context is built. Change note: al pasar una tarea a una etapa con plantilla de mail, a los usuarios con "retraso de envĂ­o" configurado les fallaba el guardado y la etapa no cambiaba. Ahora el mensaje programado se crea sin error. closes ingadhoc/miscellaneous#467 Signed-off-by: Luciano Esperlazza --- mail_ux/models/mail_compose_message.py | 14 ++++++++--- mail_ux/tests/__init__.py | 1 + mail_ux/tests/test_schedule_message.py | 34 ++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 mail_ux/tests/__init__.py create mode 100644 mail_ux/tests/test_schedule_message.py diff --git a/mail_ux/models/mail_compose_message.py b/mail_ux/models/mail_compose_message.py index e007e47c..3abc8511 100644 --- a/mail_ux/models/mail_compose_message.py +++ b/mail_ux/models/mail_compose_message.py @@ -26,8 +26,14 @@ def _action_send_mail(self, auto_commit=False): if not self.env.user.send_message_delay: return super()._action_send_mail(auto_commit=auto_commit) - # Limpiamos __action_done porque odoo guarda una base automation ahi - # Al querer crear el mensaje programado falla por mala definicion de contexto (es un objeto y no un str, int, etc.) - # No es replicable en odoo porque no tienen base automation para schedulear un mensaje - self.with_context(__action_done={})._action_schedule_message() + self._action_schedule_message() return self.env["mail.mail"].sudo(), self.env["mail.message"] + + def _prepare_schedule_message_post_values(self, post_values): + """send_context es un campo Json y base_automation deja en el contexto + claves privadas con recordsets (__action_done): no son serializables.""" + values = super()._prepare_schedule_message_post_values(post_values) + values["send_context"] = { + key: value for key, value in (values.get("send_context") or {}).items() if not key.startswith("__") + } + return values diff --git a/mail_ux/tests/__init__.py b/mail_ux/tests/__init__.py new file mode 100644 index 00000000..4a4b7227 --- /dev/null +++ b/mail_ux/tests/__init__.py @@ -0,0 +1 @@ +from . import test_schedule_message diff --git a/mail_ux/tests/test_schedule_message.py b/mail_ux/tests/test_schedule_message.py new file mode 100644 index 00000000..768c7d7a --- /dev/null +++ b/mail_ux/tests/test_schedule_message.py @@ -0,0 +1,34 @@ +from odoo.tests.common import TransactionCase + + +class TestScheduleMessage(TransactionCase): + def test_send_context_without_private_keys(self): + """send_context is a Json field: a private key holding recordsets + (base_automation's __action_done) makes the insert fail.""" + self.env.user.send_message_delay = 60 + partner = self.env["res.partner"].create({"name": "Test Schedule"}) + composer = ( + self.env["mail.compose.message"] + .with_context( + **{ + "__action_done": {self.env.user: partner}, + "lang": "en_US", + } + ) + .create( + { + "model": "res.partner", + "res_ids": repr(partner.ids), + "subject": "Test", + "body": "

Test

", + } + ) + ) + + composer._action_send_mail() + + scheduled = self.env["mail.scheduled.message"].search( + [("model", "=", "res.partner"), ("res_id", "=", partner.id)] + ) + self.assertEqual(len(scheduled), 1) + self.assertEqual(scheduled.send_context, {"lang": "en_US"})