diff options
| author | Raphael Collet <rco@openerp.com> | 2017-03-23 16:02:55 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-03-23 16:02:55 +0100 |
| commit | 09c7ec59ce1f78865d080a2c2b0ddd7e299d45de (patch) | |
| tree | 9a33bbccae37fe78066dd080b0e2bea470b68053 | |
| parent | 1505fee0e3d2460d062281100d306c279c144236 (diff) | |
[FIX] base_action_rule: prevent double execution only in recursive calls (#15863)
| -rw-r--r-- | addons/base_action_rule/base_action_rule.py | 13 | ||||
| -rw-r--r-- | addons/base_action_rule/base_action_rule_demo.xml | 34 | ||||
| -rw-r--r-- | addons/base_action_rule/test_models.py | 13 | ||||
| -rw-r--r-- | addons/base_action_rule/tests/test_base_action_rule.py | 24 |
4 files changed, 80 insertions, 4 deletions
diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index 1255dfb3be0..1278cc09604 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -175,13 +175,18 @@ class base_action_rule(osv.osv): @openerp.api.multi def _process(self, records): """ Process action ``self`` on the ``records`` that have not been done yet. """ - # filter out the records on which self has already been done, then mark - # remaining records as done (to avoid recursive processing) + # filter out the records on which self has already been done action_done = self._context['__action_done'] - records -= action_done.setdefault(self, records.browse()) + records_done = action_done.get(self, records.browse()) + records -= records_done if not records: return - action_done[self] |= records + + # mark the remaining records as done (to avoid recursive processing) + action_done = dict(action_done) + action_done[self] = records_done + records + self = self.with_context(__action_done=action_done) + records = records.with_context(__action_done=action_done) # modify records values = {} diff --git a/addons/base_action_rule/base_action_rule_demo.xml b/addons/base_action_rule/base_action_rule_demo.xml index c626cd41a3a..fe629e16a17 100644 --- a/addons/base_action_rule/base_action_rule_demo.xml +++ b/addons/base_action_rule/base_action_rule_demo.xml @@ -44,11 +44,45 @@ <field name="filter_domain">[('customer', '=', True)]</field> </record> + <record id="test_action" model="ir.actions.server"> + <field name="name">Test Server Action</field> + <field name="model_id" ref="base_action_rule.model_base_action_rule_lead_test"/> + <field name="code"> +record = model.browse(context['active_id']) +if 'partner_id' in context['old_values'][record.id]: + record.write({'state': 'draft'}) + </field> + </record> + + <record id="test_rule_recursive" model="base.action.rule"> + <field name="name">Test recursive rule</field> + <field name="kind">on_write</field> + <field name="model_id" ref="base_action_rule.model_base_action_rule_lead_test"/> + <field name="server_action_ids" eval="[(4, ref('base_action_rule.test_action'))]"/> + </record> + <record id="test_rule_on_line" model="base.action.rule"> <field name="name">Test rule on secondary record</field> <field name="kind">on_create</field> <field name="model_id" ref="base_action_rule.model_base_action_rule_line_test"/> <field name="act_user_id" ref="base.user_demo"/> </record> + + <record id="test_action_context" model="ir.actions.server"> + <field name="name">Test Server Action Context</field> + <field name="model_id" ref="base_action_rule.model_base_action_rule_lead_test"/> + <field name="code"> +record = model.browse(context['active_id']) +if 'user_id' in context['old_values'][record.id]: + record.write({'is_assigned_to_admin': (record.user_id.id == 1)}) + </field> + </record> + + <record id="test_rule_on_write_check_context" model="base.action.rule"> + <field name="name">Test rule on write check context</field> + <field name="kind">on_write</field> + <field name="model_id" ref="base_action_rule.model_base_action_rule_lead_test"/> + <field name="server_action_ids" eval="[(6, 0, [ref('base_action_rule.test_action_context')])]"/> + </record> </data> </openerp> diff --git a/addons/base_action_rule/test_models.py b/addons/base_action_rule/test_models.py index 2bfb568d762..697f868aab6 100644 --- a/addons/base_action_rule/test_models.py +++ b/addons/base_action_rule/test_models.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from dateutil import relativedelta + import openerp from openerp.osv import fields, osv from openerp import api @@ -33,6 +35,17 @@ class lead_test(osv.Model): } customer = openerp.fields.Boolean(related='partner_id.customer', readonly=True, store=True) + priority = openerp.fields.Boolean() + deadline = openerp.fields.Boolean(compute='_compute_deadline', store=True) + is_assigned_to_admin = openerp.fields.Boolean(string='Assigned to admin user') + + @api.depends('priority') + def _compute_deadline(self): + for record in self: + if not record.priority: + record.deadline = False + else: + record.deadline = openerp.fields.Datetime.from_string(record.create_date) + relativedelta.relativedelta(days=3) @api.cr_uid_ids_context def message_post(self, cr, uid, thread_id, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, context=None, **kwargs): diff --git a/addons/base_action_rule/tests/test_base_action_rule.py b/addons/base_action_rule/tests/test_base_action_rule.py index b6e7d880246..673efbcc37d 100644 --- a/addons/base_action_rule/tests/test_base_action_rule.py +++ b/addons/base_action_rule/tests/test_base_action_rule.py @@ -92,6 +92,30 @@ class base_action_rule_test(common.TransactionCase): self.assertTrue(lead.customer) self.assertEqual(lead.user_id, self.user_demo) + def test_11_recomputed_field(self): + """ + Check that a rule is executed whenever a field is recomputed and the + context contains the target field + """ + partner = self.env.ref('base.res_partner_1') + lead = self.create_lead(state='draft', partner_id=partner.id) + self.assertFalse(lead.deadline, 'There should not be a deadline defined') + # change priority and user; this triggers deadline recomputation, and + # the server action should set the boolean field to True + lead.write({'priority': True, 'user_id': self.user_admin.id}) + self.assertTrue(lead.deadline, 'Deadline should be defined') + self.assertTrue(lead.is_assigned_to_admin, 'Lead should be assigned to admin') + + def test_12_recursive(self): + """ Check that a rule is executed recursively by a secondary change. """ + lead = self.create_lead(state='open') + self.assertEqual(lead.state, 'open') + self.assertEqual(lead.user_id, self.user_admin) + # change partner; this should trigger the rule that modifies the state + partner = self.env.ref('base.res_partner_1') + lead.write({'partner_id': partner.id}) + self.assertEqual(lead.state, 'draft') + def test_20_direct_line(self): """ Check that a rule is executed after creating a line record. |
