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); }); diff --git a/addons/web/static/test/evals.js b/addons/web/static/test/evals.js index ff97086b019..8dd9a62497e 100644 --- a/addons/web/static/test/evals.js +++ b/addons/web/static/test/evals.js @@ -500,7 +500,7 @@ openerp.testing.section('eval.edc.nonliterals', { test('domain with time', {asserts: 1}, function (instance) { return instance.edc([ [['type', '=', 'contract']], - { "__domains": [["|"], [["state", "in", ["open", "draft"]]], [["state", "=", "pending"]]], + { "__domains": [["|"], [["state", "in", ["open", "draft"]]], [["type", "=", "contract"], ["state", "=", "pending"]]], "__eval_context": null, "__ref": "compound_domain" }, @@ -513,7 +513,8 @@ openerp.testing.section('eval.edc.nonliterals', { deepEqual(result.domain, [ ["type", "=", "contract"], "|", ["state", "in", ["open", "draft"]], - ["state", "=", "pending"], + "&", ["type", "=", "contract"], + ["state", "=", "pending"], "|", "&", ["date", "!=", false], ["date", "<=", today],