[FIX] web: Correctly unpack groups data in kanban

Before this commit, the groups returned by `web_read_group` were
unpacked using the current 'group by' field name, and not the entire
'group by' value (potentially including a granularity for date/datetime
fields). This caused mismatches in some cases and the value couldn't be
retrieved.

Also, a needless 'sum_field' parameter was passed to the
'read_progres_bar' calls, which does not exist in the request API.

This commit fixes the first issue and removed the excess parameter.

closes odoo/odoo#100149

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Julien Mougenot
2022-09-15 19:21:06 +02:00
parent d20de3113e
commit f26f555f0c
3 changed files with 114 additions and 24 deletions
@@ -336,6 +336,18 @@ export class KanbanDynamicGroupList extends DynamicGroupList {
});
}
get sumFields() {
const { sumField } = this.model.progressAttributes;
return sumField ? [sumField.name] : [];
}
/**
* @override
*/
get fieldNames() {
return [...super.fieldNames, ...this.sumFields];
}
/**
* After a reload, empty groups are expcted to disappear from the web_read_group.
* However, if the parameters are the same (domain + groupBy), we want to
@@ -357,24 +369,20 @@ export class KanbanDynamicGroupList extends DynamicGroupList {
return;
}
const { fieldName, sumField } = this.model.progressAttributes;
const fieldNames = [];
const gbFieldName = this.groupByField.name;
const promises = {};
if (withProgressBars) {
const domain = Domain.or(groups.map((g) => g.groupDomain)).toList();
fieldNames.push(fieldName);
promises.readProgressBar = this._fetchProgressData(domain);
}
// If we have a sumField, the aggregates must be re-fetched
if (sumField) {
if (this.sumFields.length) {
const domain = Domain.or(groups.map((g) => g.getProgressBarDomain())).toList();
fieldNames.push(sumField.name);
promises.webReadGroup = this.model.orm.webReadGroup(
this.resModel,
domain,
fieldNames,
this.sumFields,
this.groupBy,
{ lazy: true }
);
@@ -387,9 +395,7 @@ export class KanbanDynamicGroupList extends DynamicGroupList {
const result = await promises.webReadGroup;
const groupData = result.groups.map((group) => ({
...group,
[gbFieldName]: Array.isArray(group[gbFieldName])
? group[gbFieldName][0]
: group[gbFieldName],
[gbFieldName]: this._getValueFromGroupData(group, this.firstGroupBy),
}));
for (const group of groups) {
group.updateAggregates(groupData);
@@ -485,16 +491,11 @@ export class KanbanDynamicGroupList extends DynamicGroupList {
* @returns {Promise<Object>}
*/
async _fetchProgressData(domain) {
const { colors, fieldName, help, sumField } = this.model.progressAttributes;
const { colors, fieldName, help } = this.model.progressAttributes;
return this.model.orm.call(this.resModel, "read_progress_bar", [], {
domain,
group_by: this.firstGroupBy,
progress_bar: {
colors,
field: fieldName,
help,
sum_field: sumField && sumField.name,
},
progress_bar: { colors, field: fieldName, help },
context: this.context,
});
}
@@ -2297,6 +2297,26 @@ export class DynamicGroupList extends DynamicList {
return group;
}
/**
* @param {Object} groupData
* @param {string} fieldName
* @returns {any}
*/
_getValueFromGroupData(groupData, fieldName) {
const field = this.fields[fieldName.split(":")[0]];
if (["date", "datetime"].includes(field.type)) {
const range = groupData.__range[fieldName];
if (!range) {
return false;
}
const dateValue = this._parseServerValue(field, range.to);
return dateValue.minus({ [field.type === "date" ? "day" : "second"]: 1 });
} else {
const value = this._parseServerValue(field, groupData[fieldName]);
return Array.isArray(value) ? value[0] : value;
}
}
async _loadGroups() {
const firstGroupByName = this.firstGroupBy.split(":")[0];
const _orderBy = this.orderBy.filter(
@@ -2332,14 +2352,7 @@ export class DynamicGroupList extends DynamicList {
const value = data[key];
switch (key) {
case this.firstGroupBy: {
if (value && ["date", "datetime"].includes(groupByField.type)) {
const dateString = data.__range[this.firstGroupBy].to;
const dateValue = this._parseServerValue(groupByField, dateString);
const granularity = groupByField.type === "date" ? "day" : "second";
groupParams.value = dateValue.minus({ [granularity]: 1 });
} else {
groupParams.value = Array.isArray(value) ? value[0] : value;
}
groupParams.value = this._getValueFromGroupData(data, key);
if (groupByField.type === "selection") {
groupParams.displayName = Object.fromEntries(groupByField.selection)[
groupParams.value
@@ -4666,6 +4666,82 @@ QUnit.module("Views", (hooks) => {
}
);
QUnit.test("Move record in grouped by date, progress bars and sum field", async (assert) => {
serverData.models.partner.records[0].date = "2017-01-08";
serverData.models.partner.records[1].date = "2017-01-09";
serverData.models.partner.records[2].date = "2017-02-08";
serverData.models.partner.records[3].date = "2017-02-10";
await makeView({
type: "kanban",
resModel: "partner",
serverData,
arch: /* xml */ `
<kanban>
<field name="date" allow_group_range_value="true" />
<progressbar field="foo" colors='{"yop": "success", "gnap": "warning", "blip": "danger"}' sum_field="int_field" />
<templates>
<div t-name="kanban-box">
<field name="id" />
</div>
</templates>
</kanban>
`,
groupBy: ["date:month"],
});
assert.containsN(target, ".o_kanban_group", 2);
assert.containsN(
target,
".o_kanban_group:first-child .o_kanban_record",
2,
"1st column should contain 2 records of January month"
);
assert.containsN(
target,
".o_kanban_group:nth-child(2) .o_kanban_record",
2,
"2nd column should contain 2 records of February month"
);
assert.deepEqual(
getProgressBars(0).map((pb) => pb.style.width),
["50%", "50%"]
);
assert.deepEqual(
getProgressBars(1).map((pb) => pb.style.width),
["50%", "50%"]
);
assert.deepEqual(getCounters(), ["19", "13"]);
await dragAndDrop(
".o_kanban_group:first-child .o_kanban_record",
".o_kanban_group:nth-child(2)"
);
assert.containsOnce(
target,
".o_kanban_group:first-child .o_kanban_record",
"Should only have one record remaining"
);
assert.containsN(
target,
".o_kanban_group:nth-child(2) .o_kanban_record",
3,
"Should now have 3 records"
);
assert.deepEqual(
getProgressBars(0).map((pb) => pb.style.width),
["100%"]
);
assert.deepEqual(
getProgressBars(1).map((pb) => pb.style.width),
["33.3333%", "33.3333%", "33.3333%"] // abridged to e-4
);
assert.deepEqual(getCounters(), ["9", "23"]);
});
QUnit.test(
"completely prevent drag and drop if records_draggable set to false",
async (assert) => {