diff --git a/sao/src/common.js b/sao/src/common.js index 3ab39bfc4d..d7e54434f3 100644 --- a/sao/src/common.js +++ b/sao/src/common.js @@ -2418,12 +2418,10 @@ (expression.length > 2) && (typeof expression[1] == 'string')); }, - constrained_leaf: function(part, boolop) { - if (boolop === undefined) { - boolop = this.and; - } + constrained_leaf: function(part) { var operand = part[1]; - if ((operand === '=') & (boolop === this.and)) { + let value = part[2]; + if ((operand === '=') || ((operand == 'in') && (value.length == 1))) { // We should consider that other domain inversion will set a // correct value to this field return true; @@ -3049,8 +3047,7 @@ ((field in context) && (this.domain_inversion.eval_leaf( part, context, this.domain_inversion.and) || - this.domain_inversion.constrained_leaf( - part, this.domain_inversion.and)))) { + this.domain_inversion.constrained_leaf(part)))) { result.push(true); } else { return false; @@ -3105,9 +3102,7 @@ field = this.base(field); if ((field in context) && (this.domain_inversion.eval_leaf( - part, context, this.domain_inversion.or)) || - this.domain_inversion.constrained_leaf( - part, this.domain_inversion.or)) { + part, context, this.domain_inversion.or))) { return true; } else if ((field in context) && !this.domain_inversion.eval_leaf(part, context, diff --git a/sao/tests/sao.js b/sao/tests/sao.js index f143d0d17b..f00082ba7b 100644 --- a/sao/tests/sao.js +++ b/sao/tests/sao.js @@ -2494,6 +2494,60 @@ 'domain_inversion(' + JSON.stringify(domain) + ', \'x\')'); }); + QUnit.test('DomainInversion unconstrained_inversion', function() { + let domain_inversion = new Sao.common.DomainInversion(); + domain_inversion = domain_inversion.domain_inversion.bind( + domain_inversion); + let compare = Sao.common.compare; + + let domain = [['x', '=', 3], ['y', 'in', ['a', 'b']]]; + QUnit.assert.ok( + compare(domain_inversion(domain, 'x'), [['x', '=', 3]]), + `domain_inversion(${domain}, 'x')`); + QUnit.assert.ok( + compare(domain_inversion(domain, 'x', {'y': 'a'}), [['x', '=', 3]]), + `domain_inversion(${domain}, 'x', {'y': 'a'})`); + QUnit.assert.strictEqual( + domain_inversion(domain, 'x', {'y': 'c'}), false, + `domain_inversion(${domain}, 'x', {'y': 'c'})`); + }); + + QUnit.test('DomainInversion constrained_equal_inversion', function() { + let domain_inversion = new Sao.common.DomainInversion(); + domain_inversion = domain_inversion.domain_inversion.bind( + domain_inversion); + let compare = Sao.common.compare; + + let domain = [['x', '=', 3], ['y', '=', 'a']]; + QUnit.assert.ok( + compare(domain_inversion(domain, 'x'), [['x', '=', 3]]), + `domain_inversion(${domain}, 'x')`); + QUnit.assert.ok( + compare(domain_inversion(domain, 'x', {'y': 'a'}), [['x', '=', 3]]), + `domain_inversion(${domain}, 'x', {'y': 'a'})`); + QUnit.assert.ok( + compare(domain_inversion(domain, 'x', {'y': 'c'}), [['x', '=', 3]]), + `domain_inversion(${domain}, 'x', {'y': 'c'})`); + }); + + QUnit.test('DomainInversion constrained_in_inversion', function() { + let domain_inversion = new Sao.common.DomainInversion(); + domain_inversion = domain_inversion.domain_inversion.bind( + domain_inversion); + let compare = Sao.common.compare; + + let domain = [['x', '=', 3], ['y', 'in', ['a']]]; + QUnit.assert.ok( + compare(domain_inversion(domain, 'x'), [['x', '=', 3]]), + `domain_inversion(${domain}, 'x')`); + QUnit.assert.ok( + compare(domain_inversion(domain, 'x', {'y': 'a'}), [['x', '=', 3]]), + `domain_inversion(${domain}, 'x', {'y': 'a'})`); + QUnit.assert.ok( + compare(domain_inversion(domain, 'x', {'y': 'c'}), [['x', '=', 3]]), + `domain_inversion(${domain}, 'x', {'y': 'c'})`); + }); + QUnit.test('DomainInversion and_inversion', function() { var domain_inversion = new Sao.common.DomainInversion(); domain_inversion = domain_inversion.domain_inversion.bind( diff --git a/tryton/tryton/common/domain_inversion.py b/tryton/tryton/common/domain_inversion.py index 97bc0a9015..cbc18feb8f 100644 --- a/tryton/tryton/common/domain_inversion.py +++ b/tryton/tryton/common/domain_inversion.py @@ -79,9 +79,9 @@ def is_leaf(expression): and isinstance(expression[1], str)) -def constrained_leaf(part, boolop=operator.and_): +def constrained_leaf(part): field, operand, value = part[:3] - if operand == '=' and boolop == operator.and_: + if operand == '=' or (operand == 'in' and len(value) == 1): # We should consider that other domain inversion will set a correct # value to this field return True @@ -502,7 +502,7 @@ class And(object): if (field not in context or field in context and (eval_leaf(part, context, operator.and_) - or constrained_leaf(part, operator.and_))): + or constrained_leaf(part))): result.append(True) else: return False @@ -544,8 +544,7 @@ class Or(And): field = part[0] field = self.base(field) if (field in context - and (eval_leaf(part, context, operator.or_) - or constrained_leaf(part, operator.or_))): + and eval_leaf(part, context, operator.or_)): return True elif (field in context and not eval_leaf(part, context, operator.or_)): diff --git a/trytond/trytond/tests/test_tools.py b/trytond/trytond/tests/test_tools.py index 2e4bceede5..6d91d1e5ea 100644 --- a/trytond/trytond/tests/test_tools.py +++ b/trytond/trytond/tests/test_tools.py @@ -596,6 +596,39 @@ class DomainInversionTestCase(TestCase): domain = [['x.id', '>', 5]] self.assertEqual(domain_inversion(domain, 'x'), [['x.id', '>', 5]]) + def test_unconstrained_inversion(self): + domain = [['x', '=', 3], ['y', 'in', ['a', 'b']]] + + self.assertEqual(domain_inversion(domain, 'x'), [['x', '=', 3]]) + self.assertEqual( + domain_inversion(domain, 'x', {'y': 'a'}), + [['x', '=', 3]]) + self.assertEqual( + domain_inversion(domain, 'x', {'y': 'c'}), + False) + + def test_constrained_equal_inversion(self): + domain = [['x', '=', 3], ['y', '=', 'a']] + + self.assertEqual(domain_inversion(domain, 'x'), [['x', '=', 3]]) + self.assertEqual( + domain_inversion(domain, 'x', {'y': 'a'}), + [['x', '=', 3]]) + self.assertEqual( + domain_inversion(domain, 'x', {'y': 'c'}), + [['x', '=', 3]]) + + def test_constrained_in_inversion(self): + domain = [['x', '=', 3], ['y', 'in', ['a']]] + + self.assertEqual(domain_inversion(domain, 'x'), [['x', '=', 3]]) + self.assertEqual( + domain_inversion(domain, 'x', {'y': 'a'}), + [['x', '=', 3]]) + self.assertEqual( + domain_inversion(domain, 'x', {'y': 'c'}), + [['x', '=', 3]]) + def test_and_inversion(self): domain = [['x', '=', 3], ['y', '>', 5]] self.assertEqual(domain_inversion(domain, 'x'), [['x', '=', 3]]) diff --git a/trytond/trytond/tools/domain_inversion.py b/trytond/trytond/tools/domain_inversion.py index 97bc0a9015..cbc18feb8f 100644 --- a/trytond/trytond/tools/domain_inversion.py +++ b/trytond/trytond/tools/domain_inversion.py @@ -79,9 +79,9 @@ def is_leaf(expression): and isinstance(expression[1], str)) -def constrained_leaf(part, boolop=operator.and_): +def constrained_leaf(part): field, operand, value = part[:3] - if operand == '=' and boolop == operator.and_: + if operand == '=' or (operand == 'in' and len(value) == 1): # We should consider that other domain inversion will set a correct # value to this field return True @@ -502,7 +502,7 @@ class And(object): if (field not in context or field in context and (eval_leaf(part, context, operator.and_) - or constrained_leaf(part, operator.and_))): + or constrained_leaf(part))): result.append(True) else: return False @@ -544,8 +544,7 @@ class Or(And): field = part[0] field = self.base(field) if (field in context - and (eval_leaf(part, context, operator.or_) - or constrained_leaf(part, operator.or_))): + and eval_leaf(part, context, operator.or_)): return True elif (field in context and not eval_leaf(part, context, operator.or_)):