[FIX] base_action_rule: prevent double execution only in recursive calls (#15863)
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user