[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
This commit is contained in:
Joseph Caburnay
2022-11-23 13:25:02 +01:00
parent 629b904f32
commit d9fafdd08e
3 changed files with 59 additions and 1 deletions
@@ -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 &&
@@ -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() {
@@ -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*/ `
<tree expand="1">
<field name="foo"/>
</tree>`,
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);