[FIX] base_action_rule: prevent double execution only in recursive calls (#15863)

This commit is contained in:
Raphael Collet
2017-03-23 16:02:55 +01:00
committed by GitHub
parent 1505fee0e3
commit 09c7ec59ce
4 changed files with 80 additions and 4 deletions
+9 -4
View File
@@ -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 = {}
@@ -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>
+13
View File
@@ -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):
@@ -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.