[FIX] web: grouped list with aggregated value

Since the relational model (PR 114024) has been rewritten, in a grouped list
 view, if we have a field with name (value, count, aggregates or length)
and it is aggregatable, then the aggregated value of the group is false.

Why:
When loading the group list data or will process the group. As a result,
values such as "value", "count", etc. are overwritten.

Solution:
We will no longer modify the group data, but only extrat what the Group
DataPoint needs.

How to reproduce:
- Go to a grouped list view with the "value" field aggregateable

Before this commit:
    The value displayed on the group for the value field is wrong

After this commit:
    The value displayed on the group for the value field is correct

closes odoo/odoo#132154

Signed-off-by: Samuel Degueldre (sad) <sad@odoo.com>
This commit is contained in:
FrancoisGe
2023-08-17 11:48:39 +02:00
parent 329ce3e113
commit a35cbff36c
4 changed files with 54 additions and 18 deletions
@@ -18,7 +18,7 @@ export class Group extends DataPoint {
super.setup(...arguments);
this.groupByField = this.fields[config.groupByFieldName];
this.range = data.range;
this._rawValue = data[this.groupByField.name];
this._rawValue = data.rawValue;
/** @type {number} */
this.count = data.count;
this.value = data.value;
@@ -373,7 +373,7 @@ export class RelationalModel extends Model {
config.fields[o.name].group_operator !== undefined)
);
const response = await this._webReadGroup(config, firstGroupByName, orderBy);
const { groups, length } = response;
const { groups: groupsData, length } = response;
const groupBy = config.groupBy.slice(1);
const groupByField = config.fields[config.groupBy[0].split(":")[0]];
const commonConfig = {
@@ -392,25 +392,34 @@ export class RelationalModel extends Model {
}
const proms = [];
let nbOpenGroups = 0;
for (const group of groups) {
const groups = [];
for (const groupData of groupsData) {
const group = {};
// When group_by_no_leaf key is present FIELD_ID_count doesn't exist
// we have to get the count from `__count` instead
// see _read_group_raw in models.py
group.count = group.__count || group[`${firstGroupByName}_count`];
group.count = groupData.__count || groupData[`${firstGroupByName}_count`];
group.length = group.count;
group.range = group.__range ? group.__range[config.groupBy[0]] : null;
delete group.__count;
delete group[`${firstGroupByName}_count`];
delete group.__range;
group.value = getValueFromGroupData(group, groupByField, group[config.groupBy[0]]);
group.displayName = getDisplayNameFromGroupData(groupByField, group[config.groupBy[0]]);
group.aggregates = getAggregatesFromGroupData(group, config.fields);
// delete group[config.groupBy[0]];
group.range = groupData.__range ? groupData.__range[config.groupBy[0]] : null;
group.value = getValueFromGroupData(
groupData,
groupByField,
groupData[config.groupBy[0]],
group.range
);
group.rawValue = groupData[groupByField.name];
group.displayName = getDisplayNameFromGroupData(
groupByField,
groupData[config.groupBy[0]]
);
group.aggregates = getAggregatesFromGroupData(groupData, config.fields);
if (!config.groups[group.value]) {
config.groups[group.value] = {
...commonConfig,
groupByFieldName: groupByField.name,
isFolded: "__fold" in group ? group.__fold : !config.openGroupsByDefault,
isFolded:
"__fold" in groupData ? groupData.__fold : !config.openGroupsByDefault,
extraDomain: false,
value: group.value,
list: {
@@ -433,14 +442,14 @@ export class RelationalModel extends Model {
}
const groupConfig = config.groups[group.value];
groupConfig.list.orderBy = config.orderBy;
groupConfig.initialDomain = group.__domain;
groupConfig.initialDomain = groupData.__domain;
if (groupConfig.extraDomain) {
groupConfig.list.domain = Domain.and([
group.__domain,
groupData.__domain,
groupConfig.extraDomain,
]).toList();
} else {
groupConfig.list.domain = group.__domain;
groupConfig.list.domain = groupData.__domain;
}
const context = {
...config.context,
@@ -472,6 +481,7 @@ export class RelationalModel extends Model {
});
proms.push(prom);
}
groups.push(group);
}
if (groupRecordConfig && Object.keys(groupRecordConfig.activeFields).length) {
const prom = this._loadRecords({
@@ -426,9 +426,8 @@ export function getDisplayNameFromGroupData(field, rawValue) {
* @param {any} rawValue
* @returns {any}
*/
export function getValueFromGroupData(groupData, field, rawValue) {
export function getValueFromGroupData(groupData, field, rawValue, range) {
if (["date", "datetime"].includes(field.type)) {
const range = groupData.range;
if (!range) {
return false;
}
@@ -1994,6 +1994,33 @@ QUnit.module("Views", (hooks) => {
}
);
QUnit.test("group a list view with the aggregable field 'value'", async function (assert) {
serverData.models.foo.fields.value = {
string: "Value",
type: "integer",
group_operator: "sum",
};
for (const record of serverData.models.foo.records) {
record.value = 1;
}
await makeView({
type: "list",
resModel: "foo",
serverData,
arch: `
<tree>
<field name="bar"/>
<field name="value" sum="Sum1"/>
</tree>`,
groupBy: ["bar"],
});
assert.containsN(target, ".o_group_header", 2);
assert.deepEqual(
[...target.querySelectorAll(".o_group_header")].map((el) => el.textContent),
["No (1) 1", "Yes (3) 3"]
);
});
QUnit.test("basic grouped list rendering with groupby m2m field", async function (assert) {
await makeView({
type: "list",