[FIX] web: prevent crash in graph when grouping/aggregating on m2o

We recently added the possibility of aggregating the graph view on a
many2one field (with count distinct operator).  This is useful, but then
a rare situation could happen: the view could be grouped by the same
field.

In that case, there is a name clash in the read_group, and the result
will be that the [id, nameget] of a m2o field will be used as an
aggregate.

The readgroup method should be improved (its API is a mess), but
meanwhile, we have a solution for this issue: if we group by a m2o, then
it is guaranteed that each group has an aggregate value of 1 for the
same field.
This commit is contained in:
Géry Debongnie
2018-04-10 17:41:12 +02:00
parent 47395c6e51
commit 36b4468d15
2 changed files with 40 additions and 2 deletions
@@ -165,8 +165,19 @@ return AbstractModel.extend({
labels = _.map(this.chart.groupedBy, function (field) {
return self._sanitizeValue(data_pt[field], field);
});
var value = is_count ? data_pt.__count || data_pt[this.chart.groupedBy[0]+'_count'] : data_pt[this.chart.measure];
if (value instanceof Array) {
// when a many2one field is used as a measure AND as a grouped
// field, bad things happen. The server will only return the
// grouped value and will not aggregate it. Since there is a
// nameclash, we are then in the situation where this value is
// an array. Fortunately, if we group by a field, then we can
// say for certain that the group contains exactly one distinct
// value for that field.
value = 1;
}
this.chart.data.push({
value: is_count ? data_pt.__count || data_pt[this.chart.groupedBy[0]+'_count'] : data_pt[this.chart.measure],
value: value,
labels: labels
});
}
+28 -1
View File
@@ -14,7 +14,7 @@ QUnit.module('Views', {
fields: {
foo: {string: "Foo", type: "integer", store: true},
bar: {string: "bar", type: "boolean"},
product_id: {string: "Product", type: "many2one", relation: 'product'},
product_id: {string: "Product", type: "many2one", relation: 'product', store: true},
color_id: {string: "Color", type: "many2one", relation: 'color'},
},
records: [
@@ -529,6 +529,33 @@ QUnit.module('Views', {
done();
});
});
QUnit.test('use a many2one as a measure and as a groupby should work', function (assert) {
assert.expect(2);
var graph = createView({
View: GraphView,
model: "foo",
data: this.data,
arch: '<graph string="Partners">' +
'<field name="product_id" type="row"/>' +
'</graph>',
});
var done = assert.async();
return concurrency.delay(0).then(function () {
// need to set the measure this way because it cannot be set in the
// arch.
graph.$buttons.find('li[data-field="product_id"] a').click();
assert.strictEqual(graph.model.chart.data[0].value, 1,
"should have first datapoint with value 1");
assert.strictEqual(graph.model.chart.data[1].value, 1,
"should have second datapoint with value 1");
graph.destroy();
done();
});
});
});
});