diff --git a/addons/web/static/src/views/kanban/progress_bar_hook.js b/addons/web/static/src/views/kanban/progress_bar_hook.js index a6d155cc876..33c53a9cde4 100644 --- a/addons/web/static/src/views/kanban/progress_bar_hook.js +++ b/addons/web/static/src/views/kanban/progress_bar_hook.js @@ -30,6 +30,14 @@ function _createFilterDomain(fieldName, bars, value) { return filterDomain; } +function _groupsToAggregateValues(groups, groupBy, fields) { + const groupByFieldName = groupBy[0].split(":")[0]; + return groups.map((g) => { + const groupInfo = extractInfoFromGroupData(g, groupBy, fields); + return Object.assign(groupInfo.aggregates, { [groupByFieldName]: groupInfo.serverValue }); + }); +} + class ProgressBarState { constructor(progressAttributes, model, aggregateFields, activeBars = {}) { this.progressAttributes = progressAttributes; @@ -185,22 +193,19 @@ class ProgressBarState { bars, activeBar.value ); - const { context, groupBy, resModel } = this.model.root; + const { context, fields, groupBy, resModel } = this.model.root; const kwargs = { context }; - const fieldNames = this._aggregateFields.map((f) => f.name); - const fields = [...fieldNames, group.groupByField.name]; + const fieldNames = [...this._aggregateFields.map((f) => f.name), group.groupByField.name]; const domain = filterDomain ? Domain.and([group.groupDomain, filterDomain]).toList() : group.groupDomain; return this.model.orm - .webReadGroup(resModel, domain, fields, groupBy, kwargs) + .webReadGroup(resModel, domain, fieldNames, groupBy, kwargs) .then((res) => { if (res.length) { - const resGroup = _findGroup(res.groups, group.groupByField, group.serverValue); - activeBar.aggregates = { - ...resGroup, - [group.groupByField.name]: group.serverValue, - }; + const groupByField = group.groupByField; + const aggrValues = _groupsToAggregateValues(res.groups, groupBy, fields); + activeBar.aggregates = _findGroup(aggrValues, groupByField, group.serverValue); } }); } @@ -239,10 +244,7 @@ class ProgressBarState { groupBy, kwargs ); - this._aggregateValues = res.groups.map((r) => { - const groupInfo = extractInfoFromGroupData(r, groupBy, fields); - return { ...groupInfo.aggregates, [firstGroupByName]: groupInfo.serverValue }; - }); + this._aggregateValues = _groupsToAggregateValues(res.groups, groupBy, fields); } async _updateProgressBar() { diff --git a/addons/web/static/tests/helpers/mock_server.js b/addons/web/static/tests/helpers/mock_server.js index e22fe96064e..fe7bb8c092a 100644 --- a/addons/web/static/tests/helpers/mock_server.js +++ b/addons/web/static/tests/helpers/mock_server.js @@ -1327,6 +1327,9 @@ export class MockServer { for (const group of groups) { const records = this.getRecords(modelName, group.__domain || []); let groupByValue = group[groupBy]; // always technical value here + if (Array.isArray(groupByValue)) { + groupByValue = groupByValue[1]; + } // special case for bool values: rpc call response with capitalized strings if (!(groupByValue in data)) { diff --git a/addons/web/static/tests/views/kanban/kanban_view_tests.js b/addons/web/static/tests/views/kanban/kanban_view_tests.js index 194c5b49e37..206bad364c6 100644 --- a/addons/web/static/tests/views/kanban/kanban_view_tests.js +++ b/addons/web/static/tests/views/kanban/kanban_view_tests.js @@ -10417,6 +10417,123 @@ QUnit.module("Views", (hooks) => { assert.verifySteps(["web_read_group", "read_progress_bar", "web_search_read"]); }); + QUnit.test( + "progress bar with aggregates: activate bars (grouped by boolean)", + async (assert) => { + serverData.models.partner.records = [ + { foo: "yop", bar: true, int_field: 1 }, + { foo: "yop", bar: true, int_field: 2 }, + { foo: "blip", bar: true, int_field: 4 }, + { foo: "gnap", bar: true, int_field: 8 }, + ]; + + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + +
+ +
+
+
`, + groupBy: ["bar"], + }); + + assert.deepEqual(getTooltips(target, 0), ["2 yop", "1 gnap", "1 blip"]); + assert.deepEqual(getCounters(target), ["15"]); + + await click(getProgressBars(target, 0)[0]); + assert.deepEqual(getCounters(target), ["3"]); + + await click(getProgressBars(target, 0)[2]); + assert.deepEqual(getCounters(target), ["4"]); + + await click(getProgressBars(target, 0)[2]); + assert.deepEqual(getCounters(target), ["15"]); + } + ); + + QUnit.test( + "progress bar with aggregates: activate bars (grouped by many2one)", + async (assert) => { + serverData.models.partner.records = [ + { foo: "yop", product_id: 3, int_field: 1 }, + { foo: "yop", product_id: 3, int_field: 2 }, + { foo: "blip", product_id: 3, int_field: 4 }, + { foo: "gnap", product_id: 3, int_field: 8 }, + ]; + + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + +
+ +
+
+
`, + groupBy: ["product_id"], + }); + + assert.deepEqual(getTooltips(target, 0), ["2 yop", "1 gnap", "1 blip"]); + assert.deepEqual(getCounters(target), ["15"]); + + await click(getProgressBars(target, 0)[0]); + assert.deepEqual(getCounters(target), ["3"]); + + await click(getProgressBars(target, 0)[2]); + assert.deepEqual(getCounters(target), ["4"]); + + await click(getProgressBars(target, 0)[2]); + assert.deepEqual(getCounters(target), ["15"]); + } + ); + + QUnit.test("progress bar with aggregates: activate bars (grouped by date)", async (assert) => { + serverData.models.partner.records = [ + { foo: "yop", date: "2023-10-08", int_field: 1 }, + { foo: "yop", date: "2023-10-08", int_field: 2 }, + { foo: "blip", date: "2023-10-08", int_field: 4 }, + { foo: "gnap", date: "2023-10-08", int_field: 8 }, + ]; + + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + +
+ +
+
+
`, + groupBy: ["date:week"], + }); + + assert.deepEqual(getTooltips(target, 0), ["2 yop", "1 gnap", "1 blip"]); + assert.deepEqual(getCounters(target), ["15"]); + + await click(getProgressBars(target, 0)[0]); + assert.deepEqual(getCounters(target), ["3"]); + + await click(getProgressBars(target, 0)[2]); + assert.deepEqual(getCounters(target), ["4"]); + + await click(getProgressBars(target, 0)[2]); + assert.deepEqual(getCounters(target), ["15"]); + }); + QUnit.test("load more should load correct records after drag&drop event", async (assert) => { // Add a sequence number and initialize serverData.models.partner.records.forEach((el, i) => (el.sequence = i)); @@ -13944,7 +14061,7 @@ QUnit.module("Views", (hooks) => { }); QUnit.test("scroll on group unfold and progressbar click", async (assert) => { - assert.expect(7); + assert.expect(15); await makeView({ type: "kanban", @@ -13959,17 +14076,21 @@ QUnit.module("Views", (hooks) => { `, groupBy: ["product_id"], async mockRPC(route, args, performRPC) { + assert.step(args.method); if (args.method === "web_read_group") { const result = await performRPC(route, args); if (result.groups.length) { result.groups[0].__fold = false; - result.groups[1].__fold = true; + if (result.groups[1]) { + result.groups[1].__fold = true; + } } return result; } }, }); + assert.verifySteps(["get_views", "web_read_group", "read_progress_bar", "web_search_read"]); const content = target.querySelector(".o_content"); content.scrollTo = (params) => { assert.step("scrolled"); @@ -13977,12 +14098,12 @@ QUnit.module("Views", (hooks) => { }; await click(getProgressBars(target, 0)[0]); - assert.verifySteps(["scrolled"]); + assert.verifySteps(["web_read_group", "web_search_read", "scrolled"]); const column1 = getColumn(target, 1); assert.hasClass(column1, "o_column_folded"); await click(column1); - assert.verifySteps(["scrolled"]); + assert.verifySteps(["web_search_read", "scrolled"]); }); QUnit.test(