From 9b8393167ed760df7a34764105527d2bac27855e Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Fri, 16 Oct 2015 14:54:23 +0200 Subject: [PATCH] Differentiate rules according to their origin --- .../models/changeset_field_rule.py | 67 +++++++++++++++++-- .../models/res_partner_changeset.py | 5 +- .../tests/test_changeset_field_rule.py | 36 ++++++++-- .../views/changeset_field_rule_views.xml | 7 +- 4 files changed, 102 insertions(+), 13 deletions(-) diff --git a/partner_changeset/models/changeset_field_rule.py b/partner_changeset/models/changeset_field_rule.py index 2da4c376c..2346bd36b 100644 --- a/partner_changeset/models/changeset_field_rule.py +++ b/partner_changeset/models/changeset_field_rule.py @@ -19,6 +19,8 @@ # # +from itertools import chain + from openerp import models, fields, api from openerp.tools.cache import ormcache @@ -42,13 +44,41 @@ class ChangesetFieldRule(models.Model): "Validate: manually applied by an administrator.\n" "Never: change never applied.", ) + source_model_id = fields.Many2one( + comodel_name='ir.model', + string='Source Model', + ondelete='cascade', + domain=lambda self: [('id', 'in', self._domain_source_models().ids)], + help="If a source model is defined, the rule will be applied only " + "when the change is made from this origin. " + "Rules without source model are global and applies to all " + "backends.\n" + "Rules with a source model have precedence over global rules, " + "but if a field has no rule with a source model, the global rule " + "is used." + ) _sql_constraints = [ ('model_field_uniq', - 'unique (model_id, field_id)', - 'A rule already exists for this field.') + 'unique (model_id, source_model_id, field_id)', + 'A rule already exists for this field.'), ] + @api.model + def _domain_source_models(self): + """ Returns the models for which we can define rules. + + Example for submodules (replace by the xmlid of the model): + + :: + models = super(ChangesetFieldRule, self)._domain_source_models() + return models | self.env.ref('base.model_res_users') + + Rules without model are global and apply for all models. + + """ + return self.env['ir.model'].browse() + @api.model def _default_model_id(self): return self.env.ref('base.model_res_partner').id @@ -62,9 +92,36 @@ class ChangesetFieldRule(models.Model): @ormcache() @api.model - def get_rules(self, model_name): - rules = self.search([('model_id', '=', model_name)]) - return {rule.field_id.name: rule for rule in rules} + def get_rules(self, model_name, source_model_name): + """ Return the rules for a model + + If the key ``__changeset_rules_source_model`` is provided in the + context with the name of a model, rules for this specific model + will be searched for, if no rule is found, a generic rule + (without source_model_id) will be searched. + + The source model is the model which ask for a change, it will be + for instance ``res.users``, ``lefac.backend`` or ``magellan.backend``. + + The second argument (``source_model_name``) is optional but + cannot be an optional keyword argument otherwise it would not be + in the key for the cache. The callers have to pass ``None`` if + they want only global rules. + """ + if source_model_name: + model_rules = self.search( + [('model_id', '=', model_name), + ('source_model_id.model', '=', source_model_name)], + ) + else: + model_rules = self.browse() + + rules = self.search([('model_id', '=', model_name), + ('source_model_id', '=', False)]) + # model's rules have precedence over global ones so we take the + # global rules first, then we update them with the source + # model's rules + return {rule.field_id.name: rule for rule in chain(rules, model_rules)} @api.model def create(self, vals): diff --git a/partner_changeset/models/res_partner_changeset.py b/partner_changeset/models/res_partner_changeset.py index 229fbb5e2..7484788b9 100644 --- a/partner_changeset/models/res_partner_changeset.py +++ b/partner_changeset/models/res_partner_changeset.py @@ -132,7 +132,10 @@ class ResPartnerChangeset(models.Model): change_model = self.env['res.partner.changeset.change'] write_values = values.copy() changes = [] - rules = self.env['changeset.field.rule'].get_rules(record._model._name) + rules = self.env['changeset.field.rule'].get_rules( + record._model._name, + source_model_name=source_model, + ) for field in values: rule = rules.get(field) if not rule: diff --git a/partner_changeset/tests/test_changeset_field_rule.py b/partner_changeset/tests/test_changeset_field_rule.py index 8ca2cfd53..2054396b9 100644 --- a/partner_changeset/tests/test_changeset_field_rule.py +++ b/partner_changeset/tests/test_changeset_field_rule.py @@ -27,6 +27,7 @@ class TestChangesetFieldRule(common.TransactionCase): def setUp(self): super(TestChangesetFieldRule, self).setUp() self.partner_model_id = self.env.ref('base.model_res_partner').id + self.company_model_id = self.env.ref('base.model_res_company').id self.field_name = self.env.ref('base.field_res_partner_name') self.field_street = self.env.ref('base.field_res_partner_street') @@ -43,9 +44,34 @@ class TestChangesetFieldRule(common.TransactionCase): 'field_id': self.field_street.id, 'action': 'never', }) - get_rules = ChangesetFieldRule.get_rules('res.partner') + get_rules = ChangesetFieldRule.get_rules('res.partner', None) self.assertEqual(get_rules, {'name': rule1, 'street': rule2}) + def test_get_rules_source(self): + ChangesetFieldRule = self.env['changeset.field.rule'] + ChangesetFieldRule.search([]).unlink() + rule1 = ChangesetFieldRule.create({ + 'model_id': self.partner_model_id, + 'field_id': self.field_name.id, + 'action': 'validate', + }) + rule2 = ChangesetFieldRule.create({ + 'model_id': self.partner_model_id, + 'field_id': self.field_street.id, + 'action': 'never', + }) + rule3 = ChangesetFieldRule.create({ + 'model_id': self.partner_model_id, + 'source_model_id': self.company_model_id, + 'field_id': self.field_street.id, + 'action': 'never', + }) + model = ChangesetFieldRule + rules = model.get_rules('res.partner', None) + self.assertEqual(rules, {'name': rule1, 'street': rule2}) + rules = model.get_rules('res.partner', 'res.company') + self.assertEqual(rules, {'name': rule1, 'street': rule3}) + def test_get_rules_cache(self): ChangesetFieldRule = self.env['changeset.field.rule'] ChangesetFieldRule.search([]).unlink() @@ -55,7 +81,7 @@ class TestChangesetFieldRule(common.TransactionCase): 'action': 'validate', }) self.assertEqual( - ChangesetFieldRule.get_rules('res.partner')['name'].action, + ChangesetFieldRule.get_rules('res.partner', None)['name'].action, 'validate', ) # Write on cursor to bypass the cache invalidation for the @@ -64,13 +90,13 @@ class TestChangesetFieldRule(common.TransactionCase): "SET action = 'never' " "WHERE id = %s", (rule.id,)) self.assertEqual( - ChangesetFieldRule.get_rules('res.partner')['name'].action, + ChangesetFieldRule.get_rules('res.partner', None)['name'].action, 'validate', ) rule.action = 'auto' self.assertEqual( - ChangesetFieldRule.get_rules('res.partner')['name'].action, + ChangesetFieldRule.get_rules('res.partner', None)['name'].action, 'auto', ) rule.unlink() - self.assertFalse(ChangesetFieldRule.get_rules('res.partner')) + self.assertFalse(ChangesetFieldRule.get_rules('res.partner', None)) diff --git a/partner_changeset/views/changeset_field_rule_views.xml b/partner_changeset/views/changeset_field_rule_views.xml index f0bbe0c3e..e357890e2 100644 --- a/partner_changeset/views/changeset_field_rule_views.xml +++ b/partner_changeset/views/changeset_field_rule_views.xml @@ -6,8 +6,8 @@ changeset.field.rule - + @@ -22,9 +22,12 @@ + @@ -37,8 +40,8 @@ changeset.field.rule - +