diff options
| author | qsm-odoo <qsm@odoo.com> | 2017-03-15 15:19:46 +0100 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2017-03-24 15:03:54 +0100 |
| commit | b2d66d0c1468b9d321d9ffa5782e370e92525a43 (patch) | |
| tree | 96de95d445e28ffe827f3ae7cfa074372593a976 /addons/web/static/src | |
| parent | 874c7aa2dd7708ade32396a4ca4307a6342cfb29 (diff) | |
[FIX] web: properly combine domains with "OR" in CompoundDomain
The CompoundDomain class allows to regroup several domains with an
implicit "AND"; these domains can be either a string, an array or
another CompoundDomain. A CompoundDomain can then be converted to
an array thanks to pyeval.js.
For example, if a CompoundDomain is initialized with `[A, B]` and
`[C]`, the array conversion gave `[A, B, C]` (which is expected).
However, a hackish method was used with CompoundDomain. If one of the
domain of a CompoundDomain is equal to `["|"]` (an array with the
OR operator in it), the two next subdomains were supposed to be joined
by a OR operator. Indeed, for the case of a CompoundDomain initialized
with `["|"]`, `[A]` and `[B]`, the array conversion gave `["|", A, B]`
(which is expected). However, if initialized with `["|"]`, `[A, B]` and
`[C]`, the array conversion gave `["|", A, B, C]` which is very wrong
as what was expected is `["|", "&", A, B, C]`. The problem is that the
given `[A, B]` contains implicit "&" operators.
This commit fixes the problem by normalizing only if the CompoundDomain
starts with a ["|"] or ["!"] array which is the standard odoo case.
This allows to limit breaking custom code (e.g we want a simple "AND"
of `[A]` and `[B]` to stay `[A, B]`, not become `["&", A, B]`).
The commit also modifies a test so that it checks that the problem is
properly solved.
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/js/pyeval.js | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/addons/web/static/src/js/pyeval.js b/addons/web/static/src/js/pyeval.js index c132b8365fb..a651c7d8bfa 100644 --- a/addons/web/static/src/js/pyeval.js +++ b/addons/web/static/src/js/pyeval.js @@ -852,29 +852,60 @@ var eval_domains = function (domains, evaluation_context) { evaluation_context = _.extend(instance.web.pyeval.context(), evaluation_context || {}); var result_domain = []; + // Normalize only if the first domain is the array ["|"] or ["!"] + var need_normalization = ( + domains.length > 0 + && domains[0].length === 1 + && (domains[0][0] === "|" || domains[0][0] === "!") + ); _(domains).each(function (domain) { if (_.isString(domain)) { // wrap raw strings in domain domain = { __ref: 'domain', __debug: domain }; } + var domain_array_to_combine; switch(domain.__ref) { case 'domain': evaluation_context.context = evaluation_context; - result_domain.push.apply( - result_domain, py.eval(domain.__debug, wrap_context(evaluation_context))); + domain_array_to_combine = py.eval(domain.__debug, wrap_context(evaluation_context)); break; case 'compound_domain': var eval_context = eval_contexts([domain.__eval_context]); - result_domain.push.apply( - result_domain, eval_domains( - domain.__domains, _.extend( - {}, evaluation_context, eval_context))); + domain_array_to_combine = eval_domains( + domain.__domains, + _.extend({}, evaluation_context, eval_context) + ); break; default: - result_domain.push.apply(result_domain, domain); + domain_array_to_combine = domain; + } + if (need_normalization) { + domain_array_to_combine = get_normalized_domain(domain_array_to_combine); } + result_domain.push.apply(result_domain, domain_array_to_combine); }); return result_domain; + + /** + * Returns a normalized copy of the given domain array. Normalization is + * is making the implicit "&" at the start of the domain explicit, e.g. + * [A, B, C] would become ["&", "&", A, B, C]. + * + * @param {Array} domain_array + * @returns {Array} normalized copy of the given array + */ + function get_normalized_domain(domain_array) { + var expected = 1; // Holds the number of expected domain expressions + _.each(domain_array, function (item) { + if (item === "&" || item === "|") { + expected++; + } else if (item !== "!") { + expected--; + } + }); + var new_explicit_ands = _.times(-expected, _.constant("&")); + return new_explicit_ands.concat(domain_array); + } }; var eval_groupbys = function (contexts, evaluation_context) { evaluation_context = _.extend(instance.web.pyeval.context(), evaluation_context || {}); @@ -995,7 +1026,7 @@ instance.web._t("Local evaluation failure\n%s\n\n%s"), e.message, JSON.stringify(source)) } - }}; + }}; } d.resolve(result); }, 0); }); |
