[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.
This commit is contained in:
parent
874c7aa2dd
commit
b2d66d0c14
|
@ -852,29 +852,60 @@
|
||||||
var eval_domains = function (domains, evaluation_context) {
|
var eval_domains = function (domains, evaluation_context) {
|
||||||
evaluation_context = _.extend(instance.web.pyeval.context(), evaluation_context || {});
|
evaluation_context = _.extend(instance.web.pyeval.context(), evaluation_context || {});
|
||||||
var result_domain = [];
|
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) {
|
_(domains).each(function (domain) {
|
||||||
if (_.isString(domain)) {
|
if (_.isString(domain)) {
|
||||||
// wrap raw strings in domain
|
// wrap raw strings in domain
|
||||||
domain = { __ref: 'domain', __debug: domain };
|
domain = { __ref: 'domain', __debug: domain };
|
||||||
}
|
}
|
||||||
|
var domain_array_to_combine;
|
||||||
switch(domain.__ref) {
|
switch(domain.__ref) {
|
||||||
case 'domain':
|
case 'domain':
|
||||||
evaluation_context.context = evaluation_context;
|
evaluation_context.context = evaluation_context;
|
||||||
result_domain.push.apply(
|
domain_array_to_combine = py.eval(domain.__debug, wrap_context(evaluation_context));
|
||||||
result_domain, py.eval(domain.__debug, wrap_context(evaluation_context)));
|
|
||||||
break;
|
break;
|
||||||
case 'compound_domain':
|
case 'compound_domain':
|
||||||
var eval_context = eval_contexts([domain.__eval_context]);
|
var eval_context = eval_contexts([domain.__eval_context]);
|
||||||
result_domain.push.apply(
|
domain_array_to_combine = eval_domains(
|
||||||
result_domain, eval_domains(
|
domain.__domains,
|
||||||
domain.__domains, _.extend(
|
_.extend({}, evaluation_context, eval_context)
|
||||||
{}, evaluation_context, eval_context)));
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
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;
|
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) {
|
var eval_groupbys = function (contexts, evaluation_context) {
|
||||||
evaluation_context = _.extend(instance.web.pyeval.context(), 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"),
|
instance.web._t("Local evaluation failure\n%s\n\n%s"),
|
||||||
e.message, JSON.stringify(source))
|
e.message, JSON.stringify(source))
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
d.resolve(result);
|
d.resolve(result);
|
||||||
}, 0); });
|
}, 0); });
|
||||||
|
|
|
@ -500,7 +500,7 @@ openerp.testing.section('eval.edc.nonliterals', {
|
||||||
test('domain with time', {asserts: 1}, function (instance) {
|
test('domain with time', {asserts: 1}, function (instance) {
|
||||||
return instance.edc([
|
return instance.edc([
|
||||||
[['type', '=', 'contract']],
|
[['type', '=', 'contract']],
|
||||||
{ "__domains": [["|"], [["state", "in", ["open", "draft"]]], [["state", "=", "pending"]]],
|
{ "__domains": [["|"], [["state", "in", ["open", "draft"]]], [["type", "=", "contract"], ["state", "=", "pending"]]],
|
||||||
"__eval_context": null,
|
"__eval_context": null,
|
||||||
"__ref": "compound_domain"
|
"__ref": "compound_domain"
|
||||||
},
|
},
|
||||||
|
@ -513,7 +513,8 @@ openerp.testing.section('eval.edc.nonliterals', {
|
||||||
deepEqual(result.domain, [
|
deepEqual(result.domain, [
|
||||||
["type", "=", "contract"],
|
["type", "=", "contract"],
|
||||||
"|", ["state", "in", ["open", "draft"]],
|
"|", ["state", "in", ["open", "draft"]],
|
||||||
["state", "=", "pending"],
|
"&", ["type", "=", "contract"],
|
||||||
|
["state", "=", "pending"],
|
||||||
"|",
|
"|",
|
||||||
"&", ["date", "!=", false],
|
"&", ["date", "!=", false],
|
||||||
["date", "<=", today],
|
["date", "<=", today],
|
||||||
|
|
Loading…
Reference in New Issue