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 1/7] [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 + ) + ) From 2f9d5258fb36ec7b0345862d148a1613bf43ab10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 29 Sep 2023 14:25:39 +0200 Subject: [PATCH 2/7] [FIX] mail: translate server action names Following the recent server action refactoring, it seems translations have been forgotten in the review process. Task-3527758 (Base Automation Refactor Fiximp) Part of Task-3527752 (Mail: The Pre-Major Freeze FixImpLint) Part-of: odoo/odoo#137133 --- addons/mail/models/ir_actions_server.py | 20 ++++++++++++++++---- addons/sms/models/ir_actions_server.py | 5 ++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/addons/mail/models/ir_actions_server.py b/addons/mail/models/ir_actions_server.py index 61937bd3223..23f6552f09f 100644 --- a/addons/mail/models/ir_actions_server.py +++ b/addons/mail/models/ir_actions_server.py @@ -85,13 +85,25 @@ class ServerActions(models.Model): if not action.state or not self.env.context.get('automatic_action_name'): continue if action.state == 'mail_post': - action.name = 'Send email: %s' % action.template_id.name + action.name = _( + 'Send email: %(template_name)s', + template_name=action.template_id.name + ) elif action.state == 'followers': - action.name = 'Add followers: %s' % ', '.join(action.partner_ids.mapped('name')) + action.name = _( + 'Add followers: %(partner_names)s', + partner_names=', '.join(action.partner_ids.mapped('name')) + ) elif action.state == 'remove_followers': - action.name = 'Remove followers: %s' % ', '.join(action.partner_ids.mapped('name')) + action.name = _( + 'Remove followers: %(partner_names)s', + partner_names=', '.join(action.partner_ids.mapped('name')) + ) elif action.state == 'next_activity': - action.name = 'Next activity: %s' % action.activity_summary + action.name = _( + 'Next activity: %(activity_name)s', + activity_name=action.activity_summary or action.activit_type_id.name + ) else: super(ServerActions, action)._compute_name() diff --git a/addons/sms/models/ir_actions_server.py b/addons/sms/models/ir_actions_server.py index a3463ddc483..89c28403f28 100644 --- a/addons/sms/models/ir_actions_server.py +++ b/addons/sms/models/ir_actions_server.py @@ -32,7 +32,10 @@ class ServerActions(models.Model): if not action.state or not self.env.context.get('automatic_action_name'): continue if action.state == 'sms': - action.name = 'Send SMS: %s' % action.sms_template_id.name + action.name = _( + 'Send SMS: %(template_name)s', + template_name=action.sms_template_id.name + ) else: super(ServerActions, action)._compute_name() From b05e7e4da07c4f9788ec2e9c8d002d16733e3498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 29 Sep 2023 16:05:33 +0200 Subject: [PATCH 3/7] [FIX] base, mail, sms: fix server actions naming computation Fix name compute method: * correctly call super in batch; * correctly filter records; * remove dependency on context key (which was missing in triggers); In this commit we also consider the name update should always be done even outside of automated rules context. Having a whole compute method relying on a context key does not makes sense. As server actions are technical records, having the name always being correctly updated is better. Task-3527758 (Base Automation Refactor Fiximp) Part of Task-3527752 (Mail: The Pre-Major Freeze FixImpLint) Part-of: odoo/odoo#137133 --- .../views/base_automation_views.xml | 2 +- addons/mail/models/ir_actions_server.py | 12 ++++++------ addons/sms/models/ir_actions_server.py | 19 ++++++++----------- odoo/addons/base/models/ir_actions.py | 18 +++++++++++------- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/addons/base_automation/views/base_automation_views.xml b/addons/base_automation/views/base_automation_views.xml index 94910894a44..6f392a75f51 100644 --- a/addons/base_automation/views/base_automation_views.xml +++ b/addons/base_automation/views/base_automation_views.xml @@ -88,7 +88,7 @@ name="action_server_ids" widget="one2many" class="o_base_automation_actions_field" - context="{'default_model_id': model_id, 'default_state': False, 'automatic_action_name': True, 'form_view_ref': 'base_automation.view_server_action_form'}" + context="{'default_model_id': model_id, 'default_state': False, 'form_view_ref': 'base_automation.view_server_action_form'}" > diff --git a/addons/mail/models/ir_actions_server.py b/addons/mail/models/ir_actions_server.py index 23f6552f09f..255e18d3f80 100644 --- a/addons/mail/models/ir_actions_server.py +++ b/addons/mail/models/ir_actions_server.py @@ -79,11 +79,12 @@ class ServerActions(models.Model): compute='_compute_activity_info', readonly=False, store=True) - @api.depends('state', 'template_id', 'partner_ids', 'activity_summary') + @api.depends('template_id', 'partner_ids', 'activity_summary') def _compute_name(self): - for action in self: - if not action.state or not self.env.context.get('automatic_action_name'): - continue + to_update = self.filtered( + lambda action: action.state in {'mail_post', 'followers', 'remove_followers', 'next_activity'} + ) + for action in to_update: if action.state == 'mail_post': action.name = _( 'Send email: %(template_name)s', @@ -104,8 +105,7 @@ class ServerActions(models.Model): 'Next activity: %(activity_name)s', activity_name=action.activity_summary or action.activit_type_id.name ) - else: - super(ServerActions, action)._compute_name() + super(ServerActions, self - to_update)._compute_name() @api.depends('model_id', 'state') def _compute_template_id(self): diff --git a/addons/sms/models/ir_actions_server.py b/addons/sms/models/ir_actions_server.py index 89c28403f28..bbdb53af613 100644 --- a/addons/sms/models/ir_actions_server.py +++ b/addons/sms/models/ir_actions_server.py @@ -26,18 +26,15 @@ class ServerActions(models.Model): compute='_compute_sms_method', readonly=False, store=True) - @api.depends('state', 'sms_template_id') + @api.depends('sms_template_id') def _compute_name(self): - for action in self: - if not action.state or not self.env.context.get('automatic_action_name'): - continue - if action.state == 'sms': - action.name = _( - 'Send SMS: %(template_name)s', - template_name=action.sms_template_id.name - ) - else: - super(ServerActions, action)._compute_name() + to_update = self.filtered(lambda action: action.state == 'sms') + for action in to_update: + action.name = _( + 'Send SMS: %(template_name)s', + template_name=action.sms_template_id.name + ) + super(ServerActions, self - to_update)._compute_name() @api.depends('model_id', 'state') def _compute_sms_template_id(self): diff --git a/odoo/addons/base/models/ir_actions.py b/odoo/addons/base/models/ir_actions.py index bbe6cec211a..f5cb8e308be 100644 --- a/odoo/addons/base/models/ir_actions.py +++ b/odoo/addons/base/models/ir_actions.py @@ -533,16 +533,20 @@ class IrActionsServer(models.Model): @api.depends('state', 'update_field_id', 'crud_model_id', 'value') def _compute_name(self): - for action in self: - if not action.state or not self.env.context.get('automatic_action_name'): - continue + for action in self.filtered('state'): if action.state == 'object_write': - action.name = _("Update %s", action.update_field_id.field_description) + action.name = _( + "Update %(field_name)s", + field_name=action.update_field_id.field_description + ) elif action.state == 'object_create': - action.name = _("Create %s with name %s", action.crud_model_id.name, action.value) + action.name = _( + "Create %(model_name)s with name %(value)s", + model_name=action.crud_model_id.name, + value=action.value + ) else: - state_name = dict(action._fields['state']._description_selection(self.env))[action.state] - action.name = state_name + action.name = dict(action._fields['state']._description_selection(self.env))[action.state] @api.onchange('model_id') def _compute_crud_model_id(self): From 5f0d3e805c288c6d8254fb36934b707a3edcbf76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 29 Sep 2023 16:07:27 +0200 Subject: [PATCH 4/7] [FIX] mail: fix activity-based server actions summary computation Summary should be taken from activity types when possible. Task-3527758 (Base Automation Refactor Fiximp) Part of Task-3527752 (Mail: The Pre-Major Freeze FixImpLint) Part-of: odoo/odoo#137133 --- addons/mail/models/ir_actions_server.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/addons/mail/models/ir_actions_server.py b/addons/mail/models/ir_actions_server.py index 255e18d3f80..7a8d417f000 100644 --- a/addons/mail/models/ir_actions_server.py +++ b/addons/mail/models/ir_actions_server.py @@ -103,7 +103,7 @@ class ServerActions(models.Model): elif action.state == 'next_activity': action.name = _( 'Next activity: %(activity_name)s', - activity_name=action.activity_summary or action.activit_type_id.name + activity_name=action.activity_summary or action.activity_type_id.name ) super(ServerActions, self - to_update)._compute_name() @@ -149,7 +149,7 @@ class ServerActions(models.Model): if to_reset: to_reset.activity_type_id = False - @api.depends('state') + @api.depends('state', 'activity_type_id') def _compute_activity_info(self): to_reset = self.filtered(lambda act: act.state != 'next_activity') if to_reset: @@ -161,13 +161,15 @@ class ServerActions(models.Model): to_reset.activity_user_id = False to_reset.activity_user_field_name = False to_default = self.filtered(lambda act: act.state == 'next_activity') - for activity in to_default: - if not activity.activity_date_deadline_range_type: - activity.activity_date_deadline_range_type = 'days' - if not activity.activity_user_type: - activity.activity_user_type = 'specific' - if not activity.activity_user_field_name: - activity.activity_user_field_name = 'user_id' + for action in to_default: + if not action.activity_summary: + action.activity_summary = action.activity_type_id.summary + if not action.activity_date_deadline_range_type: + action.activity_date_deadline_range_type = 'days' + if not action.activity_user_type: + action.activity_user_type = 'specific' + if not action.activity_user_field_name: + action.activity_user_field_name = 'user_id' @api.constrains('activity_date_deadline_range') def _check_activity_date_deadline_range(self): From 5462b30b4fede77b6b5a967b98e9abadcd20ffa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 29 Sep 2023 16:08:18 +0200 Subject: [PATCH 5/7] [FIX] mail, sms: fix {mail/sms}-specific server actions model check Effectively check that mail-specific server action types are triggered only on mail-enabled models that are not transient. Check that mail and sms templates models match their action model by adding constraints. Task-3527758 (Base Automation Refactor Fiximp) Part of Task-3527752 (Mail: The Pre-Major Freeze FixImpLint) Part-of: odoo/odoo#137133 --- addons/mail/models/ir_actions_server.py | 19 ++++++++++++++----- addons/sms/models/ir_actions_server.py | 14 ++++++++++++-- .../models/test_base_automation.py | 6 ++++++ .../security/ir.model.access.csv | 1 + .../test_base_automation/tests/test_flow.py | 10 +++++++--- 5 files changed, 40 insertions(+), 10 deletions(-) diff --git a/addons/mail/models/ir_actions_server.py b/addons/mail/models/ir_actions_server.py index 7a8d417f000..465071f6032 100644 --- a/addons/mail/models/ir_actions_server.py +++ b/addons/mail/models/ir_actions_server.py @@ -78,7 +78,6 @@ class ServerActions(models.Model): 'User Field', compute='_compute_activity_info', readonly=False, store=True) - @api.depends('template_id', 'partner_ids', 'activity_summary') def _compute_name(self): to_update = self.filtered( @@ -176,13 +175,23 @@ class ServerActions(models.Model): if any(action.activity_date_deadline_range < 0 for action in self): raise ValidationError(_("The 'Due Date In' value can't be negative.")) + @api.constrains('model_id', 'template_id') + def _check_mail_template_model(self): + for action in self.filtered(lambda action: action.state == 'mail_post'): + if action.template_id and action.template_id.model_id != action.model_id: + raise ValidationError( + _('Mail template model of %(action_name)s does not match action model.', + action_name=action.name + ) + ) + @api.constrains('state', 'model_id') - def _check_model_coherency(self): + def _check_mail_model_coherency(self): for action in self: - if action.state in ('followers', 'next_activity') and action.model_id.transient: + if action.state in {'mail_post', 'followers', 'remove_followers', 'next_activity'} and action.model_id.transient: raise ValidationError(_("This action cannot be done on transient models.")) - if action.state == 'followers' and not action.model_id.is_mail_thread: - raise ValidationError(_("Add Followers can only be done on a mail thread models")) + if action.state in {'mail_post', 'followers', 'remove_followers'} and not action.model_id.is_mail_thread: + raise ValidationError(_("This action can only be done on a mail thread models")) if action.state == 'next_activity' and not action.model_id.is_mail_activity: raise ValidationError(_("A next activity can only be planned on models that use activities.")) diff --git a/addons/sms/models/ir_actions_server.py b/addons/sms/models/ir_actions_server.py index bbdb53af613..20d978378b0 100644 --- a/addons/sms/models/ir_actions_server.py +++ b/addons/sms/models/ir_actions_server.py @@ -54,12 +54,22 @@ class ServerActions(models.Model): if other: other.sms_method = 'sms' - def _check_model_coherency(self): - super()._check_model_coherency() + @api.constrains('state', 'model_id') + def _check_sms_model_coherency(self): for action in self: if action.state == 'sms' and (action.model_id.transient or not action.model_id.is_mail_thread): raise ValidationError(_("Sending SMS can only be done on a mail.thread or a transient model")) + @api.constrains('model_id', 'template_id') + def _check_sms_template_model(self): + for action in self.filtered(lambda action: action.state == 'sms'): + if action.sms_template_id and action.sms_template_id.model_id != action.model_id: + raise ValidationError( + _('SMS template model of %(action_name)s does not match action model.', + action_name=action.name + ) + ) + def _run_action_sms_multi(self, eval_context=None): # TDE CLEANME: when going to new api with server action, remove action if not self.sms_template_id or self._is_recompute(): diff --git a/addons/test_base_automation/models/test_base_automation.py b/addons/test_base_automation/models/test_base_automation.py index 9f2419c5a06..ea7ebe7c12a 100644 --- a/addons/test_base_automation/models/test_base_automation.py +++ b/addons/test_base_automation/models/test_base_automation.py @@ -42,6 +42,12 @@ class LeadTest(models.Model): return result +class LeadThreadTest(models.Model): + _name = "base.automation.lead.thread.test" + _description = "Automated Rule Test With Thread" + _inherit = ['base.automation.lead.test', 'mail.thread'] + + class LineTest(models.Model): _name = "base.automation.line.test" _description = "Automated Rule Line Test" diff --git a/addons/test_base_automation/security/ir.model.access.csv b/addons/test_base_automation/security/ir.model.access.csv index f3aa6170171..60ff30f2232 100644 --- a/addons/test_base_automation/security/ir.model.access.csv +++ b/addons/test_base_automation/security/ir.model.access.csv @@ -1,5 +1,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_base_automation_lead_test,access_base_automation_lead_test,model_base_automation_lead_test,base.group_system,1,1,1,1 +access_base_automation_lead_thread_test,access_base_automation_lead_thread_test,model_base_automation_lead_thread_test,base.group_system,1,1,1,1 access_base_automation_line_test,access_base_automation_line_test,model_base_automation_line_test,base.group_system,1,1,1,1 access_base_automation_link_test,access_base_automation_link_test,model_base_automation_link_test,base.group_user,1,1,1,1 access_base_automation_linked_test,access_base_automation_linked_test,model_base_automation_linked_test,base.group_user,1,1,1,1 diff --git a/addons/test_base_automation/tests/test_flow.py b/addons/test_base_automation/tests/test_flow.py index 057c77dd793..48d3c1370b9 100644 --- a/addons/test_base_automation/tests/test_flow.py +++ b/addons/test_base_automation/tests/test_flow.py @@ -49,7 +49,7 @@ class BaseAutomationTest(TransactionCaseWithUserDemo): self.test_mail_template_automation = self.env['mail.template'].create( { 'name': 'Template Automation', - 'model_id': self.lead_model.id, + 'model_id': self.env['ir.model']._get_id("base.automation.lead.thread.test"), 'body_html': """<div>Email automation</div>""", } ) @@ -365,7 +365,7 @@ else: deadline_field = self.env.ref("test_base_automation.field_base_automation_lead_test__deadline") create_automation( self, - model_id=self.lead_model.id, + model_id=self.env['ir.model']._get_id('base.automation.lead.thread.test'), trigger='on_create_or_write', trigger_field_ids=[Command.link(deadline_field.id)], filter_pre_domain="[('deadline', '=', False)]", @@ -386,7 +386,11 @@ else: patcher = patch('odoo.addons.mail.models.mail_template.MailTemplate.send_mail', _patched_send_mail) self.startPatcher(patcher) - lead = self.create_lead() + lead = self.env['base.automation.lead.thread.test'].create({ + 'name': "Lead Test", + 'user_id': self.user_root.id, + }) + self.addCleanup(lead.unlink) self.assertEqual(lead.priority, False) self.assertEqual(lead.deadline, False) self.assertEqual(send_mail_count, 0) From 84b8ca626e523c9c8e413366c016185fe11a2975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 29 Sep 2023 16:48:52 +0200 Subject: [PATCH 6/7] [FIX] base_automation: avoid wrong server action view choice When creating new primary views you should always specify the priority to avoid having the specific view used as default. This one is specific to base automation usage of server actions. Also move view in its own file to respect guideines. RIP JEM. Task-3527758 (Base Automation Refactor Fiximp) Part of Task-3527752 (Mail: The Pre-Major Freeze FixImpLint) Part-of: odoo/odoo#137133 --- addons/base_automation/__manifest__.py | 1 + .../views/base_automation_views.xml | 24 +----------------- .../views/ir_actions_server_views.xml | 25 +++++++++++++++++++ 3 files changed, 27 insertions(+), 23 deletions(-) create mode 100644 addons/base_automation/views/ir_actions_server_views.xml diff --git a/addons/base_automation/__manifest__.py b/addons/base_automation/__manifest__.py index c28fc823021..81926b7c1d3 100644 --- a/addons/base_automation/__manifest__.py +++ b/addons/base_automation/__manifest__.py @@ -19,6 +19,7 @@ trigger an automatic reminder email. 'data': [ 'security/ir.model.access.csv', 'data/base_automation_data.xml', + 'views/ir_actions_server_views.xml', 'views/base_automation_views.xml', ], 'assets': { diff --git a/addons/base_automation/views/base_automation_views.xml b/addons/base_automation/views/base_automation_views.xml index 6f392a75f51..469f4f62e1c 100644 --- a/addons/base_automation/views/base_automation_views.xml +++ b/addons/base_automation/views/base_automation_views.xml @@ -88,7 +88,7 @@ name="action_server_ids" widget="one2many" class="o_base_automation_actions_field" - context="{'default_model_id': model_id, 'default_state': False, 'form_view_ref': 'base_automation.view_server_action_form'}" + context="{'default_model_id': model_id, 'default_state': False, 'form_view_ref': 'base_automation.ir_actions_server_view_form_automation'}" > @@ -132,28 +132,6 @@ - - - base.automation.server.action.form - ir.actions.server - primary - - - - 1 - - - Type - - - 1 - - - 1 - - - - base.automation.tree diff --git a/addons/base_automation/views/ir_actions_server_views.xml b/addons/base_automation/views/ir_actions_server_views.xml new file mode 100644 index 00000000000..b7704c7b3cc --- /dev/null +++ b/addons/base_automation/views/ir_actions_server_views.xml @@ -0,0 +1,25 @@ + + + + + ir.actions.server.view.form.automation + ir.actions.server + primary + 32 + + + + 1 + + + Type + + + 1 + + + 1 + + + + From 42958e2f5eb7bf9e921445af0786dac9ba7203e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 29 Sep 2023 16:54:52 +0200 Subject: [PATCH 7/7] [IMP] base, mail, sms: directly limit available models depending on usage Add a computed m2m field giving allowed models for the action. It allows to avoid choosing the wrong models when designing server actions. Remove a test that has no use: it checks a model_id field is available on server action view while we don't want to display it as it is imposed by the rule itself. Task-3527758 (Base Automation Refactor Fiximp) Part of Task-3527752 (Mail: The Pre-Major Freeze FixImpLint) Part-of: odoo/odoo#137133 --- .../models/ir_actions_server.py | 9 ++++++++ addons/mail/models/ir_actions_server.py | 11 ++++++++++ addons/sms/models/ir_actions_server.py | 9 ++++++++ .../static/tests/tour/base_automation_tour.js | 22 ------------------- .../test_base_automation/tests/test_tour.py | 17 -------------- odoo/addons/base/models/ir_actions.py | 8 +++++++ odoo/addons/base/views/ir_actions_views.xml | 8 ++++--- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/addons/base_automation/models/ir_actions_server.py b/addons/base_automation/models/ir_actions_server.py index 7e5b74c1a3c..782da84a3ed 100644 --- a/addons/base_automation/models/ir_actions_server.py +++ b/addons/base_automation/models/ir_actions_server.py @@ -22,3 +22,12 @@ class ServerAction(models.Model): rule_name=action.base_automation_id.name ) ) + + @api.depends('usage') + def _compute_available_model_ids(self): + """ Stricter model limit: based on automation rule """ + super()._compute_available_model_ids() + rule_based = self.filtered(lambda action: action.usage == 'base_automation') + for action in rule_based: + rule_model = action.base_automation_id.model_id + action.available_model_ids = rule_model.ids if rule_model in action.available_model_ids else [] diff --git a/addons/mail/models/ir_actions_server.py b/addons/mail/models/ir_actions_server.py index 465071f6032..a60a7fe0803 100644 --- a/addons/mail/models/ir_actions_server.py +++ b/addons/mail/models/ir_actions_server.py @@ -106,6 +106,17 @@ class ServerActions(models.Model): ) super(ServerActions, self - to_update)._compute_name() + @api.depends('state') + def _compute_available_model_ids(self): + mail_thread_based = self.filtered( + lambda action: action.state in {'mail_post', 'followers', 'remove_followers', 'next_activity'} + ) + if mail_thread_based: + mail_models = self.env['ir.model'].search([('is_mail_thread', '=', True), ('transient', '=', False)]) + for action in mail_thread_based: + action.available_model_ids = mail_models.ids + super(ServerActions, self - mail_thread_based)._compute_available_model_ids() + @api.depends('model_id', 'state') def _compute_template_id(self): to_reset = self.filtered( diff --git a/addons/sms/models/ir_actions_server.py b/addons/sms/models/ir_actions_server.py index 20d978378b0..c2a4a8e1162 100644 --- a/addons/sms/models/ir_actions_server.py +++ b/addons/sms/models/ir_actions_server.py @@ -36,6 +36,15 @@ class ServerActions(models.Model): ) super(ServerActions, self - to_update)._compute_name() + @api.depends('state') + def _compute_available_model_ids(self): + mail_thread_based = self.filtered(lambda action: action.state == 'sms') + if mail_thread_based: + mail_models = self.env['ir.model'].search([('is_mail_thread', '=', True), ('transient', '=', False)]) + for action in mail_thread_based: + action.available_model_ids = mail_models.ids + super(ServerActions, self - mail_thread_based)._compute_available_model_ids() + @api.depends('model_id', 'state') def _compute_sms_template_id(self): to_reset = self.filtered( diff --git a/addons/test_base_automation/static/tests/tour/base_automation_tour.js b/addons/test_base_automation/static/tests/tour/base_automation_tour.js index c771f50e748..d93a6589af1 100644 --- a/addons/test_base_automation/static/tests/tour/base_automation_tour.js +++ b/addons/test_base_automation/static/tests/tour/base_automation_tour.js @@ -431,28 +431,6 @@ registry.category("web_tour.tours").add("test_form_view_resequence_actions", { ], }); -registry.category("web_tour.tours").add("test_form_view_debug", { - test: true, - steps: () => [ - { - trigger: - ".o_form_renderer .o_field_widget[name='action_server_ids'] .o_kanban_view .o_cp_buttons button", - }, - { - trigger: ".modal-content .o_form_renderer", - run() { - const allFields = this.$anchor[0].querySelectorAll(".o_field_widget[name]"); - assertEqual( - Array.from(allFields) - .map((el) => el.getAttribute("name")) - .includes("model_id"), - true - ); - }, - }, - ], -}); - let waitOrmCalls; registry.category("web_tour.tours").add("test_form_view_model_id", { test: true, diff --git a/addons/test_base_automation/tests/test_tour.py b/addons/test_base_automation/tests/test_tour.py index e47d77da1b2..ed3e0028e31 100644 --- a/addons/test_base_automation/tests/test_tour.py +++ b/addons/test_base_automation/tests/test_tour.py @@ -265,23 +265,6 @@ class BaseAutomationTestUi(HttpCase): ["Set Active To False 2", "Set Active To False 0", "Set Active To False 1"], ) - def test_form_view_debug(self): - model = self.env.ref("base.model_res_partner") - automation = self.env["base.automation"].create( - { - "name": "Test", - "trigger": "on_create_or_write", - "model_id": model.id, - } - ) - self.start_tour( - ( - f"/web?debug=1#{_urlencode_kwargs(action=self.env.ref('base_automation.base_automation_act').id, id=automation.id, view_type='form')}" - ), - "test_form_view_debug", - login="admin", - ) - def test_form_view_model_id(self): self.start_tour( ( diff --git a/odoo/addons/base/models/ir_actions.py b/odoo/addons/base/models/ir_actions.py index f5cb8e308be..1f67f6693c2 100644 --- a/odoo/addons/base/models/ir_actions.py +++ b/odoo/addons/base/models/ir_actions.py @@ -485,6 +485,7 @@ class IrActionsServer(models.Model): "based on the sequence. Low number means high priority.") model_id = fields.Many2one('ir.model', string='Model', required=True, ondelete='cascade', index=True, help="Model on which the server action runs.") + available_model_ids = fields.Many2many('ir.model', string='Available Models', compute='_compute_available_model_ids', store=False) model_name = fields.Char(related='model_id.model', string='Model Name', readonly=True, store=True) # Python code code = fields.Text(string='Python Code', groups='base.group_system', @@ -548,6 +549,13 @@ class IrActionsServer(models.Model): else: action.name = dict(action._fields['state']._description_selection(self.env))[action.state] + @api.depends('state') + def _compute_available_model_ids(self): + allowed_models = self.env['ir.model'].search( + [('model', 'in', list(self.env['ir.model.access']._get_allowed_models()))] + ) + self.available_model_ids = allowed_models.ids + @api.onchange('model_id') def _compute_crud_model_id(self): invalid = self.filtered(lambda act: act.crud_model_id != act.model_id) diff --git a/odoo/addons/base/views/ir_actions_views.xml b/odoo/addons/base/views/ir_actions_views.xml index eca3223fda1..fa9fce9728e 100644 --- a/odoo/addons/base/views/ir_actions_views.xml +++ b/odoo/addons/base/views/ir_actions_views.xml @@ -332,9 +332,11 @@ - - - + + +