From 4aec8c28192a1355ed8784c651bbc52f74fa1a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Mon, 12 Apr 2021 20:54:03 +0200 Subject: [PATCH] Use specific search domain for reference field searches issue9997 review324781002 --- src/common.js | 105 ++++++++++++++++++++++++++++++++++++++++++++------ src/model.js | 6 ++- tests/sao.js | 58 ++++++++++++++++++++++++++-- 3 files changed, 151 insertions(+), 18 deletions(-) diff --git a/src/common.js b/src/common.js index f47a7282a6..9bcc030729 100644 --- a/src/common.js +++ b/src/common.js @@ -2371,23 +2371,104 @@ } }, prepare_reference_domain: function(domain, reference) { + + var value2reference = function(value) { + var model = null; + var ref_id = null; + if ((typeof(value) == 'string') && value.contains(',')) { + var split = value.split(','); + var result = split.splice(0, 1); + result.push(split.join(',')); + model = result[0]; + ref_id = result[1]; + if (ref_id != '%') { + ref_id = parseInt(ref_id, 10); + if (isNaN(ref_id)) { + model = null; + ref_id = value; + } + } + } else if ((value instanceof Array) && + (value.length == 2) && + (typeof(value[0]) == 'string') && + ((typeof(value[1]) == 'number') || + (value[1] == '%'))) { + model = value[0]; + ref_id = value[1]; + } else { + ref_id = value; + } + return [model, ref_id]; + }; + if (~['AND', 'OR'].indexOf(domain)) { return domain; } else if (this.is_leaf(domain)) { - if ((domain[0].split('.').length > 1) && - (domain.length > 3)) { - var parts = domain[0].split('.'); - var local_name = parts[0]; - var target_name = parts.slice(1).join('.'); + if (domain[0] == reference) { + var model, ref_id, splitted; + if ((domain[1] == '=') || (domain[1] == '!=')) { + splitted = value2reference(domain[2]); + model = splitted[0]; + ref_id = splitted[1]; + if (model) { + if (ref_id == '%') { + if (domain[1] == '=') { + return [ + reference + '.id', '!=', null, model]; + } else { + return [reference, 'not like', domain[2]]; + } + } + return [ + reference + '.id', domain[1], ref_id, model]; + } + } else if ((domain[1] == 'in') || (domain[1] == 'not in')) { + var model_values = {}; + var break_p = false; + for (var i=0; i < domain[2].length; i++) { + splitted = value2reference(domain[2][i]); + model = splitted[0]; + ref_id = splitted[1]; + if (!model) { + break_p = true; + break; + } + if (!(model in model_values)) { + model_values[model] = []; + } + model_values[model].push(ref_id); + } - if (local_name == reference) { - var where = []; - where.push(target_name); - where = where.concat( - domain.slice(1, 3), domain.slice(4)); - return where; + if (!break_p) { + var ref_ids; + var new_domain; + if (domain[1] == 'in') { + new_domain = ['OR']; + } else { + new_domain = ['AND']; + } + for (model in model_values) { + ref_ids = model_values[model]; + if (~ref_ids.indexOf('%')) { + if (domain[1] == 'in') { + new_domain.push( + [reference + '.id', '!=', null, + model]); + } else { + new_domain.push( + [reference, 'not like', + model + ',%']); + } + } else { + new_domain.push( + [reference + '.id', domain[1], + ref_ids.map(Number), model]); + } + } + return new_domain; + } } - return domain; + return []; } return domain; } else { diff --git a/src/model.js b/src/model.js index 20116f3d9d..a4cedf1219 100644 --- a/src/model.js +++ b/src/model.js @@ -2633,14 +2633,16 @@ screen_domain = inversion.prepare_reference_domain( screen_domain, this.name); return inversion.concat([ - inversion.localize_domain(screen_domain, undefined, true), + inversion.localize_domain(screen_domain, this.name, true), attr_domain]); }, get_models: function(record) { var domains = this.get_domains(record); var inversion = new Sao.common.DomainInversion(); + var screen_domain = inversion.prepare_reference_domain( + domains[0], this.name); return inversion.extract_reference_models( - inversion.concat([domains[0], domains[1]]), + inversion.concat([screen_domain, domains[1]]), this.name); }, _is_empty: function(record) { diff --git a/tests/sao.js b/tests/sao.js index 4165a9c545..b7f00a0116 100644 --- a/tests/sao.js +++ b/tests/sao.js @@ -2848,17 +2848,67 @@ var domain = [['x', 'like', 'A%']]; QUnit.ok(compare( prepare_reference_domain(domain, 'x'), - [['x', 'like', 'A%']])); + [[]])); - domain = [['x.y', 'like', 'A%', 'model']]; + domain = [['x', '=', 'A']]; QUnit.ok(compare( prepare_reference_domain(domain, 'x'), - [['y', 'like', 'A%']])); + [[]])); domain = [['x.y', 'child_of', [1], 'model', 'parent']]; QUnit.ok(compare( prepare_reference_domain(domain, 'x'), - [['y', 'child_of', [1], 'parent']])); + [['x.y', 'child_of', [1], 'model', 'parent']])); + + domain = [['x.y', 'like', 'A%', 'model']]; + QUnit.ok(compare( + prepare_reference_domain(domain, 'x'), + [['x.y', 'like', 'A%', 'model']])); + + domain = [['x', '=', 'model,1']]; + QUnit.ok(compare( + prepare_reference_domain(domain, 'x'), + [['x.id', '=', 1, 'model']])); + + domain = [['x', '!=', 'model,1']]; + QUnit.ok(compare( + prepare_reference_domain(domain, 'x'), + [['x.id', '!=', 1, 'model']])); + + domain = [['x', '=', 'model,%']]; + QUnit.ok(compare( + prepare_reference_domain(domain, 'x'), + [['x.id', '!=', null, 'model']])); + + domain = [['x', '!=', 'model,%']]; + QUnit.ok(compare( + prepare_reference_domain(domain, 'x'), + [['x', 'not like', 'model,%']])); + + domain = [['x', 'in', + ['model_a,1', 'model_b,%', 'model_c,3', 'model_a,2']]]; + QUnit.ok(compare( + prepare_reference_domain(domain, 'x'), + [['OR', + ['x.id', 'in', [1, 2], 'model_a'], + ['x.id', '!=', null, 'model_b'], + ['x.id', 'in', [3], 'model_c'], + ]])); + + domain = [['x', 'not in', + ['model_a,1', 'model_b,%', 'model_c,3', 'model_a,2']]]; + QUnit.ok(compare( + prepare_reference_domain(domain, 'x'), + [['AND', + ['x.id', 'not in', [1, 2], 'model_a'], + ['x', 'not like', 'model_b,%'], + ['x.id', 'not in', [3], 'model_c'], + ]])); + + domain = [['x', 'in', ['model_a,1', 'foo']]]; + QUnit.ok(compare( + prepare_reference_domain(domain, 'x'), + [[]])); }); QUnit.test('DomainInversion.extract_reference_models', function() {