From d9fafdd08ef0c3c36ba991a442b835eec39360ed Mon Sep 17 00:00:00 2001 From: Joseph Caburnay Date: Mon, 21 Nov 2022 11:19:34 +0000 Subject: [PATCH] [FIX] web: should update group count when deleting records **Issue:** - Open a list view and group the records. Notice the count per group. - BUG: When deleting a record under a group, the count in the group is not updated. **Solution:** When calling `deleteRecords` in the `DynamicGroupList`, we call `deleteRecords` on each group's `list`. This "list" can be `DynamicGroupList` or `DynamicRecordsList`. Regardless which instance calls the `deleteRecords` method, we should take the number of the deleted records and subtract it from the group's current count. If it turned out that the calling object is a `DynamicGroupList`, we should make sure that it returns the ids of the deleted records so that the parent group can update its count as well, that's why we are collecting the deleted record ids. It's not so easy to follow but we can roughly imagine the structure this way: DynamicGroupList -> DynamicGroupList[] -> DynamicRecordsList[] Deleting items from the inner dynamic records list should result to update of the parent group list, and eventually, to the update of the root group list. X-original-commit: 865c1b37f7986f00b85c9e8135e46cc4b2ac70da Part-of: odoo/odoo#106317 --- .../static/src/views/list/list_controller.js | 1 + .../web/static/src/views/relational_model.js | 8 ++- .../web/static/tests/views/list_view_tests.js | 51 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/views/list/list_controller.js b/addons/web/static/src/views/list/list_controller.js index 8b287e0572c..fd35453abd7 100644 --- a/addons/web/static/src/views/list/list_controller.js +++ b/addons/web/static/src/views/list/list_controller.js @@ -448,6 +448,7 @@ export class ListController extends Component { confirm: async () => { const total = root.count; const resIds = await this.model.root.deleteRecords(); + this.model.notify(); if ( root.isDomainSelected && resIds.length === session.active_ids_limit && diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js index 28f0eab2b43..977db751896 100644 --- a/addons/web/static/src/views/relational_model.js +++ b/addons/web/static/src/views/relational_model.js @@ -2201,9 +2201,15 @@ export class DynamicGroupList extends DynamicList { } async deleteRecords() { + const allResIds = []; for (const group of this.groups) { - group.list.deleteRecords(); + const resIds = await group.list.deleteRecords(); + group.count = group.count - resIds.length; + allResIds.push(...resIds); } + // Return the list of all deleted resIds. + // Will be used by the calling group to update its count. + return allResIds; } exportState() { diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js index 6ebc8b7acfc..935c88e521a 100644 --- a/addons/web/static/tests/views/list_view_tests.js +++ b/addons/web/static/tests/views/list_view_tests.js @@ -5185,6 +5185,57 @@ QUnit.module("Views", (hooks) => { ); }); + QUnit.test( + "grouped, update the count of the group (and ancestors) when a record is deleted", + async function (assert) { + serverData.models.foo.records = [ + { id: 121, foo: "blip", bar: true }, + { id: 122, foo: "blip", bar: true }, + { id: 123, foo: "blip", bar: true }, + { id: 124, foo: "blip", bar: true }, + { id: 125, foo: "blip", bar: false }, + { id: 126, foo: "blip", bar: false }, + ]; + await makeView({ + type: "list", + resModel: "foo", + serverData, + arch: /*xml*/ ` + + + `, + groupBy: ["foo", "bar"], + actionMenus: {}, + }); + assert.strictEqual( + target.querySelector(".o_group_header:first-child").textContent.trim(), + "blip (6)" + ); + assert.strictEqual( + target.querySelector(".o_group_header:nth-child(2)").textContent.trim(), + "No (2)" + ); + + const secondNestedGroup = target.querySelector(".o_group_header:nth-child(3)"); + assert.strictEqual(secondNestedGroup.textContent.trim(), "Yes (4)"); + await click(secondNestedGroup); + assert.containsN(target, ".o_data_row", 4); + + await click(target.querySelector(".o_data_row input")); + await toggleActionMenu(target); + await toggleMenuItem(target, "Delete"); + await click(target, ".modal .btn-primary"); + assert.strictEqual( + target.querySelector(".o_group_header:first-child").textContent.trim(), + "blip (5)" + ); + assert.strictEqual( + target.querySelector(".o_group_header:nth-child(3)").textContent.trim(), + "Yes (3)" + ); + } + ); + QUnit.test("pager (ungrouped and grouped mode), default limit", async function (assert) { assert.expect(4);