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
-
+