From a35cbff36c9bb665142b4472104d68d6a418ab09 Mon Sep 17 00:00:00 2001 From: FrancoisGe Date: Thu, 17 Aug 2023 07:52:51 +0000 Subject: [PATCH] [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) --- .../src/model/relational_model/group.js | 2 +- .../relational_model/relational_model.js | 40 ++++++++++++------- .../src/model/relational_model/utils.js | 3 +- .../web/static/tests/views/list_view_tests.js | 27 +++++++++++++ 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/addons/web/static/src/model/relational_model/group.js b/addons/web/static/src/model/relational_model/group.js index b1afe73d5f7..3fd33a1cc04 100644 --- a/addons/web/static/src/model/relational_model/group.js +++ b/addons/web/static/src/model/relational_model/group.js @@ -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; diff --git a/addons/web/static/src/model/relational_model/relational_model.js b/addons/web/static/src/model/relational_model/relational_model.js index ed6f061b607..07a027c0a51 100644 --- a/addons/web/static/src/model/relational_model/relational_model.js +++ b/addons/web/static/src/model/relational_model/relational_model.js @@ -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({ diff --git a/addons/web/static/src/model/relational_model/utils.js b/addons/web/static/src/model/relational_model/utils.js index 518325898dd..95fd93964bf 100644 --- a/addons/web/static/src/model/relational_model/utils.js +++ b/addons/web/static/src/model/relational_model/utils.js @@ -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; } diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js index b799eaf6205..163d2042b03 100644 --- a/addons/web/static/tests/views/list_view_tests.js +++ b/addons/web/static/tests/views/list_view_tests.js @@ -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: ` + + + + `, + 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",