From d22928b7eda0c2c547798d99c9308010b7fd357b Mon Sep 17 00:00:00 2001 From: Mathieu Duckerts-Antoine Date: Mon, 2 Jan 2023 15:34:37 +0000 Subject: [PATCH] [FIX] web: sample server: populate groups When some true groups have been fetched, the sample server use them to construct the value returned by _mockWebReadGroup, i.e. construct some fake groups. It also populate those groups by assigning them some previously created fake records. It turns out that those fake records did not have the right type when the first group by is a date/datetime field. The record values created (during the group assignation) for that field were luxon.DateTime instances instead of strings like "2022-12-15". This was the root cause of the following problem. Have a kanban view in sample mode and grouped on a date field, then switch to a pivot view grouped on the same date field. A crash occures. That crash is linked to the above mentionned problem in the following way: - open the kanban view (with sample="1" in its arch) - some existing groups are fetched by the relation model but no records exist - the kanban view switches to sample mode and some fake invalid records are created in the sample server (the invalidity of records do not cause visible problems at that time) - switch to the pivot view - the sample server is reused but existingGroups is set to be null, so that _mockWebReadGroup uses the invalid records to create the groups it needs. The crash occures at that step. Forward-Port-Of:: cdd583f74f51086c8d5f243a2a761622229ccc26 closes odoo/odoo#109031 Signed-off-by: Aaron Bohy (aab) Signed-off-by: Mathieu Duckerts-Antoine --- addons/web/static/src/views/sample_server.js | 18 +++++- .../webclient/actions/window_action_tests.js | 64 +++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/views/sample_server.js b/addons/web/static/src/views/sample_server.js index 1d7c5ce7969..4eb5b8fefb3 100644 --- a/addons/web/static/src/views/sample_server.js +++ b/addons/web/static/src/views/sample_server.js @@ -18,6 +18,17 @@ function getSampleFromId(id, sampleTexts) { return sampleTexts[(id - 1) % sampleTexts.length]; } +function serializeGroupValue(value, type) { + switch (type) { + case "date": + return serializeDate(value); + case "datetime": + return serializeDateTime(value); + default: + return value; + } +} + /** * Helper function returning a regular expression specifically matching * a given 'term' in a fieldName. For example `fieldNameRegex('abc')`: @@ -603,7 +614,7 @@ export class SampleServer { } for (const r of this.data[params.model].records) { const group = getSampleFromId(r.id, groups); - r[groupBy] = group.value; + r[groupBy] = serializeGroupValue(group.value, groupByField.type); } this.existingGroupsPopulated = true; } @@ -666,9 +677,12 @@ export class SampleServer { // update count and aggregates for each group const fullGroupBy = params.groupBy[0]; const groupBy = fullGroupBy.split(":")[0]; + const groupByField = this.data[params.model].fields[groupBy]; const records = this.data[params.model].records; for (const g of groups) { - const recordsInGroup = records.filter((r) => r[groupBy] === g.value); + const recordsInGroup = records.filter((r) => { + return r[groupBy] === serializeGroupValue(g.value, groupByField.type); + }); g[`${groupBy}_count`] = recordsInGroup.length; g[fullGroupBy] = g.__rawValue; for (const field of params.fields) { diff --git a/addons/web/static/tests/webclient/actions/window_action_tests.js b/addons/web/static/tests/webclient/actions/window_action_tests.js index 1beef63ea31..d3dbf7f3ad1 100644 --- a/addons/web/static/tests/webclient/actions/window_action_tests.js +++ b/addons/web/static/tests/webclient/actions/window_action_tests.js @@ -2567,4 +2567,68 @@ QUnit.module("ActionManager", (hooks) => { }); assert.containsOnce(target, ".o_list_view"); }); + + QUnit.test("sample server: populate groups", async function (assert) { + serverData.models.partner.records = []; + serverData.views = { + "partner,false,kanban": ` + + + +
+
+
+
+ `, + "partner,false,pivot": ` + + + + `, + "partner,false,search": ``, + }; + const webClient = await createWebClient({ + serverData, + mockRPC(_, args) { + if (args.method === "web_read_group") { + return { + groups: [ + { + date_count: 0, + "write_date:month": "December 2022", + __range: { + "write_date:month": { + from: "2022-12-01", + to: "2023-01-01", + }, + }, + __domain: [ + ["write_date", ">=", "2022-12-01"], + ["write_date", "<", "2023-01-01"], + ], + }, + ], + length: 1, + }; + } + }, + }); + await doAction(webClient, { + res_id: 1, + type: "ir.actions.act_window", + target: "current", + res_model: "partner", + views: [ + [false, "kanban"], + [false, "pivot"], + ], + }); + + assert.containsOnce(target, ".o_kanban_view .o_view_sample_data"); + assert.strictEqual(target.querySelector(".o_column_title").innerText, "December 2022"); + + await cpHelpers.switchView(target, "pivot"); + + assert.containsOnce(target, ".o_pivot_view .o_view_sample_data"); + }); });