[FIX] base_automation: allow multiple automation rules for same trigger
Steps to reproduce: - Install base_automation_hr_contract and helpdesk - Setup two automation rules with model "Helpdesk Ticket" and "On incoming message" as trigger - Create a ticket in helpdesk Issues: Traceback is shown because `_message_post` doesn't have the origin attributes. This is due to the closure being wrong as explained here: https://github.com/odoo/odoo/blob/e2ad568e6cd4de2d721149eb76d04f58c8510191/addons/base_automation/models/base_automation.py#L686-L691 Solution: Encapsulate the `_message_post` function definition, so that each times we patch message_post we patch it with a new function. This wasn't the case before since `_message_post` wasn't isolated. This solution is similar to the other method patched. https://github.com/odoo/odoo/blob/e2ad568e6cd4de2d721149eb76d04f58c8510191/addons/base_automation/models/base_automation.py#L711-L734 opw-3758851 closes odoo/odoo#155596 Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
@@ -810,6 +810,28 @@ class BaseAutomation(models.Model):
|
||||
|
||||
return base_automation_onchange
|
||||
|
||||
def make_message_post():
|
||||
def _message_post(self, *args, **kwargs):
|
||||
message = _message_post.origin(self, *args, **kwargs)
|
||||
# Don't execute automations for a message emitted during
|
||||
# the run of automations for a real message
|
||||
# Don't execute if we know already that a message is only internal
|
||||
message_sudo = message.sudo().with_context(active_test=False)
|
||||
if "__action_done" in self.env.context or message_sudo.is_internal or message_sudo.subtype_id.internal:
|
||||
return message
|
||||
if message_sudo.message_type in ('notification', 'auto_comment', 'user_notification'):
|
||||
return message
|
||||
|
||||
# always execute actions when the author is a customer
|
||||
mail_trigger = "on_message_received" if message_sudo.author_id.partner_share else "on_message_sent"
|
||||
automations = self.env['base.automation']._get_actions(self, [mail_trigger])
|
||||
for automation in automations.with_context(old_values=None):
|
||||
records = automation._filter_pre(self)
|
||||
automation._process(records)
|
||||
|
||||
return message
|
||||
return _message_post
|
||||
|
||||
patched_models = defaultdict(set)
|
||||
|
||||
def patch(model, name, method):
|
||||
@@ -853,27 +875,7 @@ class BaseAutomation(models.Model):
|
||||
self.env.registry.clear_cache('templates')
|
||||
|
||||
if automation_rule.model_id.is_mail_thread and automation_rule.trigger in MAIL_TRIGGERS:
|
||||
def _message_post(self, *args, **kwargs):
|
||||
message = _message_post.origin(self, *args, **kwargs)
|
||||
# Don't execute automations for a message emitted during
|
||||
# the run of automations for a real message
|
||||
# Don't execute if we know already that a message is only internal
|
||||
message_sudo = message.sudo().with_context(active_test=False)
|
||||
if "__action_done" in self.env.context or message_sudo.is_internal or message_sudo.subtype_id.internal:
|
||||
return message
|
||||
if message_sudo.message_type in ('notification', 'auto_comment', 'user_notification'):
|
||||
return message
|
||||
|
||||
# always execute actions when the author is a customer
|
||||
mail_trigger = "on_message_received" if message_sudo.author_id.partner_share else "on_message_sent"
|
||||
automations = self.env['base.automation']._get_actions(self, [mail_trigger])
|
||||
for automation in automations.with_context(old_values=None):
|
||||
records = automation._filter_pre(self)
|
||||
automation._process(records)
|
||||
|
||||
return message
|
||||
|
||||
patch(Model, "message_post", _message_post)
|
||||
patch(Model, "message_post", make_message_post())
|
||||
|
||||
def _unregister_hook(self):
|
||||
""" Remove the patches installed by _register_hook() """
|
||||
|
||||
@@ -1027,6 +1027,34 @@ class TestCompute(common.TransactionCase):
|
||||
obj.message_post(author_id=ext_partner.id, subtype_xmlid="mail.mt_comment")
|
||||
self.assertTrue(obj.active)
|
||||
|
||||
def test_multiple_mail_triggers(self):
|
||||
lead_model = self.env["ir.model"]._get("base.automation.lead.test")
|
||||
with self.assertRaises(ValidationError):
|
||||
create_automation(self, trigger="on_message_sent", model_id=lead_model.id)
|
||||
|
||||
lead_thread_model = self.env["ir.model"]._get("base.automation.lead.thread.test")
|
||||
|
||||
create_automation(self, trigger="on_message_sent", model_id=lead_thread_model.id, _actions={
|
||||
"state": "object_write",
|
||||
"update_path": "active",
|
||||
"update_boolean_value": "false"
|
||||
})
|
||||
create_automation(self, trigger="on_message_sent", model_id=lead_thread_model.id, _actions={
|
||||
"state": "object_write",
|
||||
"evaluation_type": "equation",
|
||||
"update_path": "name",
|
||||
"value": "record.name + '!'"
|
||||
})
|
||||
|
||||
ext_partner = self.env["res.partner"].create({"name": "ext", "email": "email@server.com"})
|
||||
internal_partner = self.env["res.users"].browse(2).partner_id
|
||||
|
||||
obj = self.env["base.automation.lead.thread.test"].create({"name": "test"})
|
||||
obj.message_subscribe([ext_partner.id, internal_partner.id])
|
||||
|
||||
obj.message_post(author_id=internal_partner.id, message_type="comment", subtype_xmlid="mail.mt_comment")
|
||||
self.assertFalse(obj.active)
|
||||
self.assertEqual(obj.name, "test!")
|
||||
|
||||
@common.tagged("post_install", "-at_install")
|
||||
class TestHttp(common.HttpCase):
|
||||
|
||||
Reference in New Issue
Block a user