[FIX] spreadsheet: fix set_as_filter action in context menu

Task Description

In some case, when trying to display the context menu on a
pivot cell (doesn't seem to impact PIVOT.HEADER), we get a
traceback caused by the arguments of the formula take into
account in the ´getFiltersMatchingPivot`, called by the
"isVisible" property evaluation of the "set as filter" action.

These errors only rise when using a pivot with "__count" as
measure and a positional argument.

Moreover, when trying to open the context menu with a filter
defined without any field, we get another traceback.

Reproducibility

The first issue  can be reproduced with the following steps:
1. Go to the CRM app
2. Create a pivot view
3. Group the row by Country
4. "Ungroup" the columns (keep only the total)
5. Set "__count" as measure
6. Insert the pivot on a new spreadsheet
7. Edit the pivot formulas to use positional argument for country_id
8. Insert a new filter on the country field
9. Right click on a pivot cell

The second issue can be reproduced with the following steps:
1. Open a spreadsheet with a pivot
2. Add a filter related to the pivot but without any field matching
3. Right-click on a pivot cell

Fix Description

The first issue is coming from the fact we try to get the value related
to a field in the pivot formula using the 2nd and 3rd argument instead
of using the last two arguments of the formula. This is fixed by passing
to getPivotHeaderValue only the last two arguments of the pivot formula.

For the second issue, we simply check that the pivot field is defined
before looking at its name.

Related Task

task-2999181

closes odoo/odoo#102204

X-original-commit: 15e0c8aba57d4e0a8c58f288a4e96f0bc884736c
Related: odoo/enterprise#32303
Signed-off-by: Lucas Lefèvre (lul) <lul@odoo.com>
This commit is contained in:
anhe-odoo
2022-10-05 14:25:51 +02:00
parent 2d80ae6857
commit 1b2ae7fceb
2 changed files with 111 additions and 2 deletions
@@ -192,6 +192,9 @@ export default class PivotUIPlugin extends spreadsheet.UIPlugin {
const evaluatedArgs = args
.map(astToFormula)
.map((arg) => this.getters.evaluateFormula(arg));
if (evaluatedArgs.length <= 2) {
return [];
}
const pivotId = evaluatedArgs[0];
const argField = evaluatedArgs[evaluatedArgs.length - 2];
const filters = this.getters.getGlobalFilters();
@@ -200,8 +203,9 @@ export default class PivotUIPlugin extends spreadsheet.UIPlugin {
for (const filter of filters) {
const dataSource = this.getters.getPivotDataSource(pivotId);
const { field, aggregateOperator: time } = dataSource.parseGroupField(argField);
if (filter.pivotFields[pivotId].field === field.name) {
let value = dataSource.getPivotHeaderValue(evaluatedArgs.slice(1));
const pivotField = filter.pivotFields[pivotId];
if (pivotField && pivotField.field === field.name) {
let value = dataSource.getPivotHeaderValue(evaluatedArgs.slice(-2));
let transformedValue;
const currentValue = this.getters.getGlobalFilterValue(filter.id);
switch (filter.type) {
@@ -1535,6 +1535,111 @@ QUnit.module("spreadsheet > Global filters model", {}, () => {
}
);
QUnit.test(
"getFiltersMatchingPivot return correctly matching filter according to cell formula with __count and positional argument",
async function (assert) {
const { model } = await createSpreadsheetWithPivot({
arch: /*xml*/ `
<pivot>
<field name="product_id" type="row"/>
<field name="__count" type="measure"/>
</pivot>`,
});
setCellContent(model, "B3", '=ODOO.PIVOT(1, "__count", "#product_id", 1)');
await addGlobalFilter(model, {
filter: {
id: "42",
type: "relation",
defaultValue: [],
pivotFields: { 1: { field: "product_id", type: "many2one" } },
},
});
const filters = model.getters.getFiltersMatchingPivot(getCellFormula(model, "B3"));
assert.deepEqual(filters, [
{
filterId: "42",
value: [37],
},
]);
}
);
QUnit.test(
"getFiltersMatchingPivot return correctly matching filter according to cell formula with positional argument",
async function (assert) {
const { model } = await createSpreadsheetWithPivot({
arch: /*xml*/ `
<pivot>
<field name="product_id" type="row"/>
<field name="probability" type="measure"/>
</pivot>`,
});
setCellContent(model, "B3", '=ODOO.PIVOT(1, "probability", "#product_id", 1)');
await addGlobalFilter(model, {
filter: {
id: "42",
type: "relation",
defaultValue: [],
pivotFields: { 1: { field: "product_id", type: "many2one" } },
},
});
const filters = model.getters.getFiltersMatchingPivot(getCellFormula(model, "B3"));
assert.deepEqual(filters, [
{
filterId: "42",
value: [37],
},
]);
}
);
QUnit.test(
"getFiltersMatchingPivot return correctly matching filter when there is a filter with no field defined",
async function (assert) {
const { model } = await createSpreadsheetWithPivot({
arch: /*xml*/ `
<pivot>
<field name="product_id" type="row"/>
<field name="probability" type="measure"/>
</pivot>`,
});
await addGlobalFilter(model, {
filter: {
id: "42",
type: "relation",
defaultValue: [],
pivotFields: {},
},
});
const filters = model.getters.getFiltersMatchingPivot(getCellFormula(model, "B3"));
assert.deepEqual(filters, []);
}
);
QUnit.test(
"getFiltersMatchingPivot return empty filter for cell formula without any argument",
async function (assert) {
const { model } = await createSpreadsheetWithPivot({
arch: /*xml*/ `
<pivot>
<field name="product_id" type="row"/>
<field name="probability" type="measure"/>
</pivot>`,
});
setCellContent(model, "B3", '=ODOO.PIVOT(1, "probability")');
await addGlobalFilter(model, {
filter: {
id: "42",
type: "relation",
defaultValue: [],
pivotFields: { 1: { field: "product_id", type: "many2one" } },
},
});
const filters = model.getters.getFiltersMatchingPivot(getCellFormula(model, "B3"));
assert.deepEqual(filters, []);
}
);
QUnit.test("field matching is removed when pivot is deleted", async function (assert) {
const { model } = await createSpreadsheetWithPivot();
await addGlobalFilter(model, LAST_YEAR_FILTER);