From 5376b60af0808da57d4b5c65ecdcb8ee7188d1e9 Mon Sep 17 00:00:00 2001 From: "Ricardo Gomes Rodrigues (rigr)" Date: Mon, 5 Dec 2022 11:01:20 +0000 Subject: [PATCH] [IMP] base, web: add `not like` and `not ilike` operators for the JS Odoo domain Currently the `not like` and `not ilike` operators are available for the Odoo domain in Python but not in JS. This commit adds these two operators in the JS Odoo domain too for better code clarity. For instance: `[('fiscal_country_codes', 'not like', 'AR')]` instead of `['|', ('fiscal_country_codes', 'like', 'AR')]` Part-of: odoo/odoo#106221 --- addons/web/static/src/core/domain.js | 10 ++++++++++ addons/web/static/tests/core/domain_tests.js | 18 ++++++++++++++++-- odoo/tests/common.py | 4 ++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/core/domain.js b/addons/web/static/src/core/domain.js index d2252ed2bb2..2dabe7bf484 100644 --- a/addons/web/static/src/core/domain.js +++ b/addons/web/static/src/core/domain.js @@ -243,6 +243,11 @@ function matchCondition(record, condition) { return false; } return fieldValue.indexOf(value) >= 0; + case "not like": + if (fieldValue === false) { + return false; + } + return fieldValue.indexOf(value) === -1; case "=like": if (fieldValue === false) { return false; @@ -253,6 +258,11 @@ function matchCondition(record, condition) { return false; } return fieldValue.toLowerCase().indexOf(value.toLowerCase()) >= 0; + case "not ilike": + if (fieldValue === false) { + return false; + } + return fieldValue.toLowerCase().indexOf(value.toLowerCase()) === -1; case "=ilike": if (fieldValue === false) { return false; diff --git a/addons/web/static/tests/core/domain_tests.js b/addons/web/static/tests/core/domain_tests.js index 3195b0cfd19..321fc154d6a 100644 --- a/addons/web/static/tests/core/domain_tests.js +++ b/addons/web/static/tests/core/domain_tests.js @@ -88,8 +88,8 @@ QUnit.module("domain", {}, () => { assert.ok(new Domain(["!", ["group_method", "=", "count"]]).contains(record)); }); - QUnit.test("like, =like, ilike and =ilike", function (assert) { - assert.expect(16); + QUnit.test("like, =like, ilike, =ilike, not like and not ilike", function (assert) { + assert.expect(28); assert.ok(new Domain([["a", "like", "value"]]).contains({ a: "value" })); assert.ok(new Domain([["a", "like", "value"]]).contains({ a: "some value" })); @@ -110,6 +110,20 @@ QUnit.module("domain", {}, () => { assert.ok(new Domain([["a", "=ilike", "%value"]]).contains({ a: "some value" })); assert.ok(new Domain([["a", "=ilike", "%value"]]).contains({ a: "Some Value" })); assert.notOk(new Domain([["a", "=ilike", "%value"]]).contains({ a: false })); + + assert.notOk(new Domain([["a", "not like", "value"]]).contains({ a: "value" })); + assert.notOk(new Domain([["a", "not like", "value"]]).contains({ a: "some value" })); + assert.ok(new Domain([["a", "not like", "value"]]).contains({ a: "Some Value" })); + assert.ok(new Domain([["a", "not like", "value"]]).contains({ a: "something" })); + assert.ok(new Domain([["a", "not like", "value"]]).contains({ a: "Something" })); + assert.notOk(new Domain([["a", "not like", "value"]]).contains({ a: false })); + + assert.notOk(new Domain([["a", "not ilike", "value"]]).contains({ a: "value" })); + assert.notOk(new Domain([["a", "not ilike", "value"]]).contains({ a: "some value" })); + assert.notOk(new Domain([["a", "not ilike", "value"]]).contains({ a: "Some Value" })); + assert.ok(new Domain([["a", "not ilike", "value"]]).contains({ a: "something" })); + assert.ok(new Domain([["a", "not ilike", "value"]]).contains({ a: "Something" })); + assert.notOk(new Domain([["a", "not ilike", "value"]]).contains({ a: false })); }); QUnit.test("complex domain", function (assert) { diff --git a/odoo/tests/common.py b/odoo/tests/common.py index c7eb7268770..eee5facd318 100644 --- a/odoo/tests/common.py +++ b/odoo/tests/common.py @@ -2298,6 +2298,10 @@ class Form(object): '>': operator.gt, 'in': lambda a, b: (a in b) if isinstance(b, (tuple, list)) else (b in a), 'not in': lambda a, b: (a not in b) if isinstance(b, (tuple, list)) else (b not in a), + 'like': lambda a, b: a and b and isinstance(a, str) and isinstance(b, str) and a in b, + 'ilike': lambda a, b: a and b and isinstance(a, str) and isinstance(b, str) and a.lower() in b.lower(), + 'not like': lambda a, b: a and b and isinstance(a, str) and isinstance(b, str) and a not in b, + 'not ilike': lambda a, b: a and b and isinstance(a, str) and isinstance(b, str) and a.lower() not in b.lower(), } def _get_context(self, field): c = self._view['contexts'].get(field)