From 50a893a66e06b68c5f9100267e4f4fcd3b5f70ef Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 1 Mar 2013 11:36:49 +0100 Subject: [PATCH 01/85] [IMP] base_action_rule: add selection field on action rules to indicate when to execute them bzr revid: rco@openerp.com-20130301103649-up2b2yrye2y80e1t --- addons/base_action_rule/base_action_rule.py | 23 ++++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index a3237c1620b..6cca0e8b6b5 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -61,6 +61,9 @@ class base_action_rule(osv.osv): help="When unchecked, the rule is hidden and will not be executed."), 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of rules."), + 'kind': fields.selection( + [('create', 'On Creation'), ('write', 'On Update'), ('cron', 'Based on Timed Condition')], + string='When to Run'), 'trg_date_id': fields.many2one('ir.model.fields', string='Trigger Date', domain="[('model_id', '=', model_id), ('ttype', 'in', ('date', 'datetime'))]"), 'trg_date_range': fields.integer('Delay after trigger date', @@ -133,7 +136,7 @@ class base_action_rule(osv.osv): """ Return a wrapper around `old_create` calling both `old_create` and `_process`, in that order. """ - def wrapper(cr, uid, vals, context=None): + def create(cr, uid, vals, context=None): # avoid loops or cascading actions if context and context.get('action'): return old_create(cr, uid, vals, context=context) @@ -141,8 +144,8 @@ class base_action_rule(osv.osv): context = dict(context or {}, action=True) new_id = old_create(cr, uid, vals, context=context) - # as it is a new record, we do not consider the actions that have a prefilter - action_dom = [('model', '=', model), ('trg_date_id', '=', False), ('filter_pre_id', '=', False)] + # retrieve the action rules to run on creation + action_dom = [('model', '=', model), ('kind', '=', 'create')] action_ids = self.search(cr, uid, action_dom, context=context) # check postconditions, and execute actions on the records that satisfy them @@ -151,13 +154,13 @@ class base_action_rule(osv.osv): self._process(cr, uid, action, [new_id], context=context) return new_id - return wrapper + return create def _wrap_write(self, old_write, model): """ Return a wrapper around `old_write` calling both `old_write` and `_process`, in that order. """ - def wrapper(cr, uid, ids, vals, context=None): + def write(cr, uid, ids, vals, context=None): # avoid loops or cascading actions if context and context.get('action'): return old_write(cr, uid, ids, vals, context=context) @@ -165,8 +168,8 @@ class base_action_rule(osv.osv): context = dict(context or {}, action=True) ids = [ids] if isinstance(ids, (int, long, str)) else ids - # retrieve the action rules to possibly execute - action_dom = [('model', '=', model), ('trg_date_id', '=', False)] + # retrieve the action rules to run on update + action_dom = [('model', '=', model), ('kind', '=', 'write')] action_ids = self.search(cr, uid, action_dom, context=context) actions = self.browse(cr, uid, action_ids, context=context) @@ -185,7 +188,7 @@ class base_action_rule(osv.osv): self._process(cr, uid, action, post_ids, context=context) return True - return wrapper + return write def _register_hook(self, cr, ids=None): """ Wrap the methods `create` and `write` of the models specified by @@ -217,8 +220,8 @@ class base_action_rule(osv.osv): def _check(self, cr, uid, automatic=False, use_new_cursor=False, context=None): """ This Function is called by scheduler. """ context = context or {} - # retrieve all the action rules that have a trg_date_id and no precondition - action_dom = [('trg_date_id', '!=', False), ('filter_pre_id', '=', False)] + # retrieve all the action rules to run based on a timed condition + action_dom = [('kind', '=', 'cron')] action_ids = self.search(cr, uid, action_dom, context=context) for action in self.browse(cr, uid, action_ids, context=context): now = datetime.now() From 51fbcd39fbec0d18c2330b7752f82b58e3266f52 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 1 Mar 2013 12:01:48 +0100 Subject: [PATCH 02/85] [FIX] base_action_rule: adapt tests to rule kinds bzr revid: rco@openerp.com-20130301110148-xq540esqbpofmp10 --- .../tests/base_action_rule_test.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/base_action_rule/tests/base_action_rule_test.py b/addons/base_action_rule/tests/base_action_rule_test.py index 36c928a84e3..25a6df8f884 100644 --- a/addons/base_action_rule/tests/base_action_rule_test.py +++ b/addons/base_action_rule/tests/base_action_rule_test.py @@ -19,8 +19,8 @@ class base_action_rule_test(common.TransactionCase): 'name': "Lead is in done state", 'is_default': False, 'model_id': 'base.action.rule.lead.test', - 'domain' : "[('state','=','done')]", - }, context=context) + 'domain': "[('state','=','done')]", + }, context=context) def create_filter_draft(self, cr, uid, context=None): filter_pool = self.registry('ir.filters') @@ -40,16 +40,16 @@ class base_action_rule_test(common.TransactionCase): 'user_id': self.admin, }, context=context) - def create_rule(self, cr, uid, filter_id=False, filter_pre_id=False, context=None): + def create_rule(self, cr, uid, kind, filter_id=False, filter_pre_id=False, context=None): """ The "Rule 1" says that when a lead goes to the 'draft' state, the responsible for that lead changes to user "demo" """ return self.base_action_rule.create(cr,uid,{ - 'name' : "Rule 1", + 'name': "Rule 1", 'model_id': self.registry('ir.model').search(cr, uid, [('model','=','base.action.rule.lead.test')], context=context)[0], - 'active' : 1, - 'filter_pre_id' : filter_pre_id, - 'filter_id' : filter_id, + 'kind': kind, + 'filter_pre_id': filter_pre_id, + 'filter_id': filter_id, 'act_user_id': self.demo, }, context=context) @@ -64,7 +64,7 @@ class base_action_rule_test(common.TransactionCase): """ cr, uid = self.cr, self.uid filter_draft = self.create_filter_draft(cr, uid) - self.create_rule(cr, uid, filter_pre_id=filter_draft) + self.create_rule(cr, uid, 'write', filter_pre_id=filter_draft) new_lead_id = self.create_lead_test_1(cr, uid) new_lead = self.model.browse(cr, uid, new_lead_id) self.assertEquals(new_lead.state, 'draft') @@ -73,11 +73,11 @@ class base_action_rule_test(common.TransactionCase): def test_01_check_to_state_draft_post(self): """ - Check that a new record (with state = draft) changes its responsible when there is a postcondition filter which check that the state is draft. + Check that a new record changes its responsible when there is a postcondition filter which check that the state is draft. """ cr, uid = self.cr, self.uid filter_draft = self.create_filter_draft(cr, uid) - self.create_rule(cr, uid, filter_id=filter_draft) + self.create_rule(cr, uid, 'create') new_lead_id = self.create_lead_test_1(cr, uid) new_lead = self.model.browse(cr, uid, new_lead_id) self.assertEquals(new_lead.state, 'draft') @@ -95,7 +95,7 @@ class base_action_rule_test(common.TransactionCase): cr, uid = self.cr, self.uid filter_draft = self.create_filter_draft(cr, uid) filter_done = self.create_filter_done(cr, uid) - self.create_rule(cr, uid, filter_pre_id=filter_draft, filter_id=filter_done) + self.create_rule(cr, uid, 'write', filter_pre_id=filter_draft, filter_id=filter_done) new_lead_id = self.create_lead_test_1(cr, uid) new_lead = self.model.browse(cr, uid, new_lead_id) self.assertEquals(new_lead.state, 'draft') @@ -133,7 +133,7 @@ class base_action_rule_test(common.TransactionCase): cr, uid = self.cr, self.uid filter_draft = self.create_filter_draft(cr, uid) filter_done = self.create_filter_done(cr, uid) - self.create_rule(cr, uid, filter_pre_id=filter_draft, filter_id=filter_done) + self.create_rule(cr, uid, 'write', filter_pre_id=filter_draft, filter_id=filter_done) new_lead_id = self.create_lead_test_1(cr, uid) new_lead = self.model.browse(cr, uid, new_lead_id) self.assertEquals(new_lead.state, 'draft') From 9c21a6902ac27e1acf2fe10b7a2463605a958c17 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 1 Mar 2013 12:03:01 +0100 Subject: [PATCH 03/85] [IMP] base_action_rule: update records before executing server actions bzr revid: rco@openerp.com-20130301110301-xu4iaxi7hysmclm4 --- addons/base_action_rule/base_action_rule.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index 6cca0e8b6b5..ba3ef572505 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -108,15 +108,6 @@ class base_action_rule(osv.osv): def _process(self, cr, uid, action, record_ids, context=None): """ process the given action on the records """ - # execute server actions - model = self.pool.get(action.model_id.model) - if action.server_action_ids: - server_action_ids = map(int, action.server_action_ids) - for record in model.browse(cr, uid, record_ids, context): - action_server_obj = self.pool.get('ir.actions.server') - ctx = dict(context, active_model=model._name, active_ids=[record.id], active_id=record.id) - action_server_obj.run(cr, uid, server_action_ids, context=ctx) - # modify records values = {} if 'date_action_last' in model._all_columns: @@ -130,6 +121,15 @@ class base_action_rule(osv.osv): follower_ids = map(int, action.act_followers) model.message_subscribe(cr, uid, record_ids, follower_ids, context=context) + # execute server actions + model = self.pool.get(action.model_id.model) + if action.server_action_ids: + server_action_ids = map(int, action.server_action_ids) + for record in model.browse(cr, uid, record_ids, context): + action_server_obj = self.pool.get('ir.actions.server') + ctx = dict(context, active_model=model._name, active_ids=[record.id], active_id=record.id) + action_server_obj.run(cr, uid, server_action_ids, context=ctx) + return True def _wrap_create(self, old_create, model): From 3bad12f1cfe64f271afa350918aaefb9c01306b7 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 1 Mar 2013 12:27:05 +0100 Subject: [PATCH 04/85] [IMP] base_action_rule: adapt views to new field bzr revid: rco@openerp.com-20130301112705-hqn8wqz1l20ix2tu --- addons/base_action_rule/base_action_rule.py | 15 +++++-- .../base_action_rule_view.xml | 43 +++++++++++-------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index ba3ef572505..176c2bffe28 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -50,6 +50,7 @@ class base_action_rule(osv.osv): _name = 'base.action.rule' _description = 'Action Rules' + _order = 'sequence' _columns = { 'name': fields.char('Rule Name', size=64, required=True), @@ -81,10 +82,10 @@ class base_action_rule(osv.osv): ondelete='restrict', domain="[('model_id', '=', model_id.model)]", help="If present, this condition must be satisfied before the update of the record."), - 'filter_id': fields.many2one('ir.filters', string='After Update Filter', + 'filter_id': fields.many2one('ir.filters', string='Filter', ondelete='restrict', domain="[('model_id', '=', model_id.model)]", - help="If present, this condition must be satisfied after the update of the record."), + help="If present, this condition must be satisfied before executing the action rule."), 'last_run': fields.datetime('Last Run', readonly=1), } @@ -93,7 +94,15 @@ class base_action_rule(osv.osv): 'trg_date_range_type': 'day', } - _order = 'sequence' + def onchange_kind(self, cr, uid, ids, kind, context=None): + clear_fields = [] + if kind == 'create': + clear_fields = ['filter_pre_id', 'trg_date_id', 'trg_date_range', 'trg_date_range_type'] + elif kind == 'write': + clear_fields = ['trg_date_id', 'trg_date_range', 'trg_date_range_type'] + elif kind == 'cron': + clear_fields = ['filter_pre_id'] + return {'value': dict.fromkeys(clear_fields, False)} def _filter(self, cr, uid, action, action_filter, record_ids, context=None): """ filter the list record_ids that satisfy the action filter """ diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml index 25ea4048bad..131b5cef08b 100644 --- a/addons/base_action_rule/base_action_rule_view.xml +++ b/addons/base_action_rule/base_action_rule_view.xml @@ -26,24 +26,32 @@ - - - - - - - + + + + + -

- Select a filter or a timer as condition.
An action rule is checked when you create or modify the "Related Document Model". The precondition filter is checked right before the modification while the postcondition filter is checked after the modification. A precondition filter will therefore not work during a creation.
- To create a new filter:
- - Go to your "Related Document Model" page and set the filter parameters in the "Search" view (Example of filter based on Leads/Opportunities: Creation Date "is equal to" 01/01/2012)
- - In this same "Search" view, select the menu "Save Current Filter", enter the name (Ex: Create the 01/01/2012) and add the option "Share with all users"
+

+ Select when the action must be run, and add filters and/or timing conditions. +
+ In order to create a new filter: +

    +
  • Go to your "Related Document Model" page and set the filter parameters in the "Search" view (Example of filter based on Leads/Opportunities: Creation Date "is equal to" 01/01/2012)
  • +
  • In this same "Search" view, select the menu "Save Current Filter", enter the name (Ex: Create the 01/01/2012) and add the option "Share with all users"
  • +
The filter must therefore be available in this page.

@@ -76,6 +84,7 @@ + From ed498dac73e5c65afb2627968c38460f9b786de0 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 1 Mar 2013 12:33:00 +0100 Subject: [PATCH 05/85] [IMP] crm: adapt action rules to the base.action.rule model change bzr revid: rco@openerp.com-20130301113300-6ezyicr11mg01x38 --- addons/crm/crm_action_rule_demo.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/addons/crm/crm_action_rule_demo.xml b/addons/crm/crm_action_rule_demo.xml index bf1f7d4082f..e52c40e1739 100644 --- a/addons/crm/crm_action_rule_demo.xml +++ b/addons/crm/crm_action_rule_demo.xml @@ -26,6 +26,7 @@ Description: [[object.description]] Set Auto Reminder on leads which are not open since 5 days. 1 + cron 5 @@ -54,12 +55,10 @@ object.write({'section_id': sales_team.id}) Set Auto Followers on leads which are urgent and come from USA. 2 + create - - - 0 - minutes + From f1f15f52b3b37fea23f2dce09ee89fd29cb5d997 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Fri, 1 Mar 2013 14:19:29 +0100 Subject: [PATCH 06/85] [FIX] base_action_rule: undefined variable (due to code move) bzr revid: rco@openerp.com-20130301131929-3q4egd9jpasss88w --- addons/base_action_rule/base_action_rule.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index 176c2bffe28..f759dfd3bbb 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -117,6 +117,8 @@ class base_action_rule(osv.osv): def _process(self, cr, uid, action, record_ids, context=None): """ process the given action on the records """ + model = self.pool.get(action.model_id.model) + # modify records values = {} if 'date_action_last' in model._all_columns: @@ -131,7 +133,6 @@ class base_action_rule(osv.osv): model.message_subscribe(cr, uid, record_ids, follower_ids, context=context) # execute server actions - model = self.pool.get(action.model_id.model) if action.server_action_ids: server_action_ids = map(int, action.server_action_ids) for record in model.browse(cr, uid, record_ids, context): From 2a0245b20c30e564a9d1e89afdc47583fd42d5b6 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 4 Mar 2013 10:49:51 +0100 Subject: [PATCH 07/85] [IMP] base_action_rule: use better value names for new selection field bzr revid: rco@openerp.com-20130304094951-7452svzw0cgzu6jp --- addons/base_action_rule/base_action_rule.py | 14 +++++++------- addons/base_action_rule/base_action_rule_view.xml | 4 ++-- .../tests/base_action_rule_test.py | 8 ++++---- addons/crm/crm_action_rule_demo.xml | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index f759dfd3bbb..4f7215e215a 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -63,7 +63,7 @@ class base_action_rule(osv.osv): 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of rules."), 'kind': fields.selection( - [('create', 'On Creation'), ('write', 'On Update'), ('cron', 'Based on Timed Condition')], + [('on_create', 'On Creation'), ('on_write', 'On Update'), ('on_time', 'Based on Timed Condition')], string='When to Run'), 'trg_date_id': fields.many2one('ir.model.fields', string='Trigger Date', domain="[('model_id', '=', model_id), ('ttype', 'in', ('date', 'datetime'))]"), @@ -96,11 +96,11 @@ class base_action_rule(osv.osv): def onchange_kind(self, cr, uid, ids, kind, context=None): clear_fields = [] - if kind == 'create': + if kind == 'on_create': clear_fields = ['filter_pre_id', 'trg_date_id', 'trg_date_range', 'trg_date_range_type'] - elif kind == 'write': + elif kind == 'on_write': clear_fields = ['trg_date_id', 'trg_date_range', 'trg_date_range_type'] - elif kind == 'cron': + elif kind == 'on_time': clear_fields = ['filter_pre_id'] return {'value': dict.fromkeys(clear_fields, False)} @@ -155,7 +155,7 @@ class base_action_rule(osv.osv): new_id = old_create(cr, uid, vals, context=context) # retrieve the action rules to run on creation - action_dom = [('model', '=', model), ('kind', '=', 'create')] + action_dom = [('model', '=', model), ('kind', '=', 'on_create')] action_ids = self.search(cr, uid, action_dom, context=context) # check postconditions, and execute actions on the records that satisfy them @@ -179,7 +179,7 @@ class base_action_rule(osv.osv): ids = [ids] if isinstance(ids, (int, long, str)) else ids # retrieve the action rules to run on update - action_dom = [('model', '=', model), ('kind', '=', 'write')] + action_dom = [('model', '=', model), ('kind', '=', 'on_write')] action_ids = self.search(cr, uid, action_dom, context=context) actions = self.browse(cr, uid, action_ids, context=context) @@ -231,7 +231,7 @@ class base_action_rule(osv.osv): """ This Function is called by scheduler. """ context = context or {} # retrieve all the action rules to run based on a timed condition - action_dom = [('kind', '=', 'cron')] + action_dom = [('kind', '=', 'on_time')] action_ids = self.search(cr, uid, action_dom, context=context) for action in self.browse(cr, uid, action_ids, context=context): now = datetime.now() diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml index 131b5cef08b..21bf6a0b0c9 100644 --- a/addons/base_action_rule/base_action_rule_view.xml +++ b/addons/base_action_rule/base_action_rule_view.xml @@ -31,12 +31,12 @@ + attrs="{'invisible': [('kind', '!=', 'on_write')]}"/> + attrs="{'invisible': [('kind', '!=', 'on_time')]}"/>