details:   https://code.tryton.org/tryton/commit/13d2279f2154
branch:    default
user:      Nicolas Évrard <[email protected]>
date:      Thu Feb 13 01:02:11 2025 +0100
description:
        Consider in-leaf with a unique value as constrained for domain inversion

        Closes #13869
diffstat:

 sao/src/common.js                         |  15 ++-----
 sao/tests/sao.js                          |  54 +++++++++++++++++++++++++++++++
 tryton/tryton/common/domain_inversion.py  |   9 ++--
 trytond/trytond/tests/test_tools.py       |  33 ++++++++++++++++++
 trytond/trytond/tools/domain_inversion.py |   9 ++--
 5 files changed, 100 insertions(+), 20 deletions(-)

diffs (215 lines):

diff -r 191f2e9503a1 -r 13d2279f2154 sao/src/common.js
--- a/sao/src/common.js Wed Feb 12 18:59:33 2025 +0100
+++ b/sao/src/common.js Thu Feb 13 01:02:11 2025 +0100
@@ -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 -r 191f2e9503a1 -r 13d2279f2154 sao/tests/sao.js
--- a/sao/tests/sao.js  Wed Feb 12 18:59:33 2025 +0100
+++ b/sao/tests/sao.js  Thu Feb 13 01:02:11 2025 +0100
@@ -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 -r 191f2e9503a1 -r 13d2279f2154 tryton/tryton/common/domain_inversion.py
--- a/tryton/tryton/common/domain_inversion.py  Wed Feb 12 18:59:33 2025 +0100
+++ b/tryton/tryton/common/domain_inversion.py  Thu Feb 13 01:02:11 2025 +0100
@@ -79,9 +79,9 @@
         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 @@
                 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 @@
                 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 -r 191f2e9503a1 -r 13d2279f2154 trytond/trytond/tests/test_tools.py
--- a/trytond/trytond/tests/test_tools.py       Wed Feb 12 18:59:33 2025 +0100
+++ b/trytond/trytond/tests/test_tools.py       Thu Feb 13 01:02:11 2025 +0100
@@ -596,6 +596,39 @@
         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 -r 191f2e9503a1 -r 13d2279f2154 trytond/trytond/tools/domain_inversion.py
--- a/trytond/trytond/tools/domain_inversion.py Wed Feb 12 18:59:33 2025 +0100
+++ b/trytond/trytond/tools/domain_inversion.py Thu Feb 13 01:02:11 2025 +0100
@@ -79,9 +79,9 @@
         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 @@
                 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 @@
                 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_)):

Reply via email to