From a97e769ad387ea0cdba4b0a5b5aff9554d5a9518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 30 Oct 2021 02:20:23 +0200 Subject: [PATCH] Evaluate invalid domain if there are many fields We must find the field that is invalid instead of using the first one with a domain constraint. issue10418 review360371002 --- trytond/model/modelstorage.py | 9 +++++--- trytond/tests/modelstorage.py | 20 +++++++++++++++++ trytond/tests/test_modelstorage.py | 35 ++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index bd1536c1a3..2f7bcc4708 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -18,7 +18,7 @@ from trytond.model import Model from trytond.model import fields from trytond.tools import reduce_domain, is_instance_method, grouped_slice from trytond.tools.domain_inversion import ( - domain_inversion, parse as domain_parse) + domain_inversion, eval_domain, parse as domain_parse) from trytond.pyson import PYSONEncoder, PYSONDecoder, PYSON from trytond.const import OPERATORS from trytond.config import config @@ -1236,11 +1236,14 @@ class ModelStorage(Model): else: fields.add(field.name) for field_name in sorted(fields): + env = EvalEnvironment(invalid_record, Relation) invalid_domain = domain_inversion( - domain, field_name, - EvalEnvironment(invalid_record, Relation)) + domain, field_name, env) if isinstance(invalid_domain, bool): continue + if (len(fields) > 1 # no need to evaluate + and eval_domain(invalid_domain, env)): + continue field_def = Relation.fields_get( [field_name], level=level) raise DomainValidationError( diff --git a/trytond/tests/modelstorage.py b/trytond/tests/modelstorage.py index 998848b2ab..b85e0c854a 100644 --- a/trytond/tests/modelstorage.py +++ b/trytond/tests/modelstorage.py @@ -117,6 +117,24 @@ class ModelStorageRelationDomainTarget(ModelSQL): return [('id', '=', -1)] +class ModelStorageRelationMultiDomain(ModelSQL): + "Model stored containing a relation fields with multi domain" + __name__ = 'test.modelstorage.relation_multi_domain' + relation = fields.Many2One( + 'test.modelstorage.relation_multi_domain.target', "Value", + domain=[ + ('test1', '=', True), + ('test2', '=', True), + ]) + + +class ModelStorageRelationMultiDomainTarget(ModelSQL): + "Target of Model stored containing a relation field with multi domain" + __name__ = 'test.modelstorage.relation_multi_domain.target' + test1 = fields.Boolean("Test 1") + test2 = fields.Boolean("Test 2") + + class ModelStorageRelationDomain2(ModelSQL): "Model stored containing a relation field with a domain with 2 level" __name__ = 'test.modelstorage.relation_domain2' @@ -163,6 +181,8 @@ def register(module): ModelStoragePYSONDomain, ModelStorageRelationDomain, ModelStorageRelationDomainTarget, + ModelStorageRelationMultiDomain, + ModelStorageRelationMultiDomainTarget, ModelStorageRelationDomain2, ModelStorageRelationDomain2Target, ModelStorageEvalEnvironment, diff --git a/trytond/tests/test_modelstorage.py b/trytond/tests/test_modelstorage.py index 9a71f42a1b..b888946523 100644 --- a/trytond/tests/test_modelstorage.py +++ b/trytond/tests/test_modelstorage.py @@ -376,6 +376,41 @@ class ModelStorageTestCase(unittest.TestCase): self.assertEqual(cm.exception.domain[0], [('value', '=', 'valid')]) self.assertTrue(cm.exception.domain[1]['value']) + @with_transaction() + def test_relation_domain_multi(self): + "Test relation multi domain" + pool = Pool() + Model = pool.get('test.modelstorage.relation_multi_domain') + Target = pool.get('test.modelstorage.relation_multi_domain.target') + + target, = Target.create([{'test1': True, 'test2': True}]) + + record, = Model.create([{'relation': target.id}]) + + @with_transaction() + def test_relation_domain_multi_invalid(self): + "Test invalid relation multi domain" + pool = Pool() + Model = pool.get('test.modelstorage.relation_multi_domain') + Target = pool.get('test.modelstorage.relation_multi_domain.target') + + target1, target2 = Target.create( + [{'test1': False, 'test2': True}, {'test1': True, 'test2': False}]) + + with self.assertRaises(DomainValidationError) as cm: + Model.create([{ + 'relation': target1.id, + }]) + self.assertEqual(cm.exception.domain[0], [('test1', '=', True)]) + self.assertEqual(cm.exception.domain[1].keys(), {'test1'}) + + with self.assertRaises(DomainValidationError) as cm: + Model.create([{ + 'relation': target2.id, + }]) + self.assertEqual(cm.exception.domain[0], [('test2', '=', True)]) + self.assertEqual(cm.exception.domain[1].keys(), {'test2'}) + @with_transaction() def test_relation_pyson_domain(self): "Test valid relation with PYSON"