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 @@
[('customer', '=', True)]
+
+ Test Server Action
+
+
+record = model.browse(context['active_id'])
+if 'partner_id' in context['old_values'][record.id]:
+ record.write({'state': 'draft'})
+
+
+
+
+ Test recursive rule
+ on_write
+
+
+
+
Test rule on secondary record
on_create
+
+
+ Test Server Action Context
+
+
+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)})
+
+
+
+
+ Test rule on write check context
+ on_write
+
+
+
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.