From a8b08b8e9268478ca8d2d14f2a2d79f11efb309c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 29 Sep 2023 15:12:20 +0200 Subject: [PATCH] [FIX] base_automation: check server actions model match rule model New implementation of automated rules does not check if rule model matches models of its children server actions. This can easily lead to updating records of another model which have nothing in common with the automation rule. Also better write the reset when changing model. Task-3527758 (Base Automation Refactor Fiximp) Part of Task-3527752 (Mail: The Pre-Major Freeze FixImpLint) Part-of: odoo/odoo#137133 --- .../base_automation/models/base_automation.py | 24 +++++++++++++++++-- .../models/ir_actions_server.py | 13 +++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/addons/base_automation/models/base_automation.py b/addons/base_automation/models/base_automation.py index d874a1dc0e8..571dd2b3834 100644 --- a/addons/base_automation/models/base_automation.py +++ b/addons/base_automation/models/base_automation.py @@ -8,7 +8,7 @@ from collections import defaultdict from dateutil.relativedelta import relativedelta -from odoo import _, api, Command, exceptions, fields, models +from odoo import _, api, exceptions, fields, models from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT from odoo.tools import safe_eval @@ -177,6 +177,19 @@ class BaseAutomation(models.Model): CRITICAL_FIELDS = ['model_id', 'active', 'trigger', 'on_change_field_ids'] RANGE_FIELDS = ['trg_date_range', 'trg_date_range_type'] + @api.constrains('model_id', 'action_server_ids') + def _check_action_server_model(self): + for rule in self: + failing_actions = rule.action_server_ids.filtered( + lambda action: action.model_id != rule.model_id + ) + if failing_actions: + raise exceptions.ValidationError( + _('Target model of actions %(action_names)s are different from rule model.', + action_names=', '.join(failing_actions.mapped('name')) + ) + ) + @api.constrains('trigger', 'action_server_ids') def _check_trigger_state(self): for record in self: @@ -196,7 +209,14 @@ class BaseAutomation(models.Model): @api.depends('model_id') def _compute_action_server_ids(self): - self.action_server_ids = [Command.clear()] + """ When changing / setting model, remove actions that are not targeting + the same model anymore. """ + for rule in self.filtered('model_id'): + actions_to_remove = rule.action_server_ids.filtered( + lambda action: action.model_id != rule.model_id + ) + if actions_to_remove: + rule.action_server_ids = [(3, action.id) for action in actions_to_remove] @api.depends('trigger', 'trigger_field_ids') def _compute_trg_date_id(self): diff --git a/addons/base_automation/models/ir_actions_server.py b/addons/base_automation/models/ir_actions_server.py index 0cec609a320..7e5b74c1a3c 100644 --- a/addons/base_automation/models/ir_actions_server.py +++ b/addons/base_automation/models/ir_actions_server.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import fields, models +from odoo import api, exceptions, fields, models, _ class ServerAction(models.Model): @@ -11,3 +11,14 @@ class ServerAction(models.Model): ('base_automation', 'Automation Rule') ], ondelete={'base_automation': 'cascade'}) base_automation_id = fields.Many2one('base.automation', string='Automation Rule', ondelete='cascade') + + @api.constrains('model_id', 'base_automation_id') + def _check_model_coherency_with_automation(self): + for action in self.filtered('base_automation_id'): + if action.model_id != action.base_automation_id.model_id: + raise exceptions.ValidationError( + _("Model of action %(action_name)s should match the one from automated rule %(rule_name)s.", + action_name=action.name, + rule_name=action.base_automation_id.name + ) + )