[FIX] spreadsheet: get ODOO.FILTER.VALUE with from/to filter
- create a from/to date filter with let's say "my filter"
as its title.
- in the spreadsheet, `=ODOO.FILTER.VALUE("my filter")`
=> the function doesn't return anything
closes odoo/odoo#146213
Task: 3584650
Related: odoo/enterprise#52871
Signed-off-by: Pierre Rousseau (pro) <pro@odoo.com>
This commit is contained in:
@@ -41,7 +41,8 @@ const MONTHS = {
|
||||
december: { value: 12, granularity: "month" },
|
||||
};
|
||||
|
||||
const { UuidGenerator, createEmptyExcelSheet, createEmptySheet } = spreadsheet.helpers;
|
||||
const { UuidGenerator, createEmptyExcelSheet, createEmptySheet, toXC, toNumber } =
|
||||
spreadsheet.helpers;
|
||||
const uuidGenerator = new UuidGenerator();
|
||||
|
||||
export class GlobalFiltersUIPlugin extends spreadsheet.UIPlugin {
|
||||
@@ -230,17 +231,29 @@ export class GlobalFiltersUIPlugin extends spreadsheet.UIPlugin {
|
||||
const value = this.getGlobalFilterValue(filter.id);
|
||||
switch (filter.type) {
|
||||
case "text":
|
||||
return value || "";
|
||||
return [[{ value: value || "" }]];
|
||||
case "date": {
|
||||
if (filter.rangeType === "from_to") {
|
||||
const locale = this.getters.getLocale();
|
||||
const from = {
|
||||
value: value.from && toNumber(value.from, locale),
|
||||
format: locale.dateFormat,
|
||||
};
|
||||
const to = {
|
||||
value: value.to && toNumber(value.to, locale),
|
||||
format: locale.dateFormat,
|
||||
};
|
||||
return [[from], [to]];
|
||||
}
|
||||
if (value && typeof value === "string") {
|
||||
const type = RELATIVE_DATE_RANGE_TYPES.find((type) => type.type === value);
|
||||
if (!type) {
|
||||
return "";
|
||||
return [[{ value: "" }]];
|
||||
}
|
||||
return type.description.toString();
|
||||
return [[{ value: type.description.toString() }]];
|
||||
}
|
||||
if (!value || value.yearOffset === undefined) {
|
||||
return "";
|
||||
return [[{ value: "" }]];
|
||||
}
|
||||
const periodOptions = getPeriodOptions(DateTime.local());
|
||||
const year = String(DateTime.local().year + value.yearOffset);
|
||||
@@ -251,11 +264,11 @@ export class GlobalFiltersUIPlugin extends spreadsheet.UIPlugin {
|
||||
periodStr =
|
||||
MONTHS[value.period] && String(MONTHS[value.period].value).padStart(2, "0");
|
||||
}
|
||||
return periodStr ? periodStr + "/" + year : year;
|
||||
return [[{ value: periodStr ? periodStr + "/" + year : year }]];
|
||||
}
|
||||
case "relation":
|
||||
if (!value?.length || !this.orm) {
|
||||
return "";
|
||||
return [[{ value: "" }]];
|
||||
}
|
||||
if (!this.recordsDisplayName[filter.id]) {
|
||||
this.orm
|
||||
@@ -267,9 +280,9 @@ export class GlobalFiltersUIPlugin extends spreadsheet.UIPlugin {
|
||||
sheetId: this.getters.getActiveSheetId(),
|
||||
});
|
||||
});
|
||||
return "";
|
||||
return [[{ value: "" }]];
|
||||
}
|
||||
return this.recordsDisplayName[filter.id].join(", ");
|
||||
return [[{ value: this.recordsDisplayName[filter.id].join(", ") }]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,20 +544,32 @@ export class GlobalFiltersUIPlugin extends spreadsheet.UIPlugin {
|
||||
const styleId = getItemId({ bold: true }, data.styles);
|
||||
|
||||
const cells = {};
|
||||
cells["A1"] = { content: _t("Filter"), style: styleId };
|
||||
cells["B1"] = { content: _t("Value"), style: styleId };
|
||||
let row = 2;
|
||||
cells["A1"] = { content: "Filter", style: styleId };
|
||||
cells["B1"] = { content: "Value", style: styleId };
|
||||
let numberOfCols = 2; // at least 2 cols (filter title and filter value)
|
||||
let filterRowIndex = 1; // first row is the column titles
|
||||
for (const filter of this.getters.getGlobalFilters()) {
|
||||
const content = this.getters.getFilterDisplayValue(filter.label);
|
||||
cells[`A${row}`] = { content: filter.label };
|
||||
cells[`B${row}`] = { content };
|
||||
row++;
|
||||
cells[`A${filterRowIndex + 1}`] = { content: filter.label };
|
||||
const result = this.getFilterDisplayValue(filter.label);
|
||||
for (const colIndex in result) {
|
||||
numberOfCols = Math.max(numberOfCols, Number(colIndex) + 2);
|
||||
for (const rowIndex in result[colIndex]) {
|
||||
const cell = result[colIndex][rowIndex];
|
||||
const xc = toXC(Number(colIndex) + 1, Number(rowIndex) + filterRowIndex);
|
||||
cells[xc] = { content: cell.value.toString() };
|
||||
if (cell.format) {
|
||||
const formatId = getItemId(cell.format, data.formats);
|
||||
cells[xc].format = formatId;
|
||||
}
|
||||
}
|
||||
}
|
||||
filterRowIndex += result[0].length;
|
||||
}
|
||||
const sheet = {
|
||||
...createEmptySheet(uuidGenerator.uuidv4(), _t("Active Filters")),
|
||||
cells,
|
||||
colNumber: 2,
|
||||
rowNumber: this.getters.getGlobalFilters().length + 1,
|
||||
colNumber: numberOfCols,
|
||||
rowNumber: filterRowIndex,
|
||||
};
|
||||
data.sheets.push(sheet);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { migrate } from "@spreadsheet/o_spreadsheet/migration";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { loadBundle } from "@web/core/assets";
|
||||
|
||||
const { toCartesian } = helpers;
|
||||
const { formatValue, isDefined, toCartesian } = helpers;
|
||||
|
||||
export async function fetchSpreadsheetModel(env, resModel, resId) {
|
||||
const { data, revisions } = await env.services.orm.call(resModel, "join_spreadsheet_session", [
|
||||
@@ -82,9 +82,14 @@ export async function freezeOdooData(model) {
|
||||
|
||||
function exportGlobalFiltersToSheet(model, data) {
|
||||
model.getters.exportSheetWithActiveFilters(data);
|
||||
const locale = model.getters.getLocale();
|
||||
for (const filter of data.globalFilters) {
|
||||
const content = model.getters.getFilterDisplayValue(filter.label);
|
||||
filter["value"] = content;
|
||||
filter["value"] = content
|
||||
.flat()
|
||||
.filter(isDefined)
|
||||
.map(({ value, format }) => formatValue(value, { format, locale }))
|
||||
.join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@ const ODOO_FILTER_VALUE = {
|
||||
description: _t("Return the current value of a spreadsheet filter."),
|
||||
args: [arg("filter_name (string)", _t("The label of the filter whose value to return."))],
|
||||
category: "Odoo",
|
||||
compute: function (filterName) {
|
||||
const unEscapedFilterName = toString(filterName).replaceAll('\\"', '"');
|
||||
computeValueAndFormat: function (filterName) {
|
||||
const unEscapedFilterName = toString(filterName.value).replaceAll('\\"', '"');
|
||||
return this.getters.getFilterDisplayValue(unEscapedFilterName);
|
||||
},
|
||||
returns: ["STRING"],
|
||||
|
||||
@@ -48,6 +48,7 @@ import { GlobalFiltersUIPlugin } from "@spreadsheet/global_filters/plugins/globa
|
||||
import { migrate } from "@spreadsheet/o_spreadsheet/migration";
|
||||
import { toRangeData } from "../utils/zones";
|
||||
import { PivotUIPlugin } from "@spreadsheet/pivot/index";
|
||||
import { getEvaluatedCell } from "../utils/getters";
|
||||
const { DateTime } = luxon;
|
||||
const { toZone } = helpers;
|
||||
|
||||
@@ -891,6 +892,85 @@ QUnit.module("spreadsheet > Global filters model", {}, () => {
|
||||
assert.equal(getCellValue(model, "A10"), ``);
|
||||
});
|
||||
|
||||
QUnit.test("ODOO.FILTER.VALUE date from/to without values", async function (assert) {
|
||||
const model = await createModelWithDataSource();
|
||||
setCellContent(model, "A1", `=ODOO.FILTER.VALUE("Date Filter")`);
|
||||
await addGlobalFilter(model, {
|
||||
id: "42",
|
||||
type: "date",
|
||||
label: "Date Filter",
|
||||
rangeType: "from_to",
|
||||
});
|
||||
assert.equal(getEvaluatedCell(model, "A1").value, "");
|
||||
assert.equal(getEvaluatedCell(model, "A2").value, "");
|
||||
});
|
||||
|
||||
QUnit.test("ODOO.FILTER.VALUE date from/to with only from defined", async function (assert) {
|
||||
const model = await createModelWithDataSource();
|
||||
setCellContent(model, "A1", `=ODOO.FILTER.VALUE("Date Filter")`);
|
||||
await addGlobalFilter(model, {
|
||||
id: "42",
|
||||
type: "date",
|
||||
label: "Date Filter",
|
||||
rangeType: "from_to",
|
||||
});
|
||||
await setGlobalFilterValue(model, {
|
||||
id: "42",
|
||||
value: {
|
||||
from: "2020-01-01",
|
||||
},
|
||||
});
|
||||
assert.equal(getEvaluatedCell(model, "A1").value, 43831);
|
||||
assert.equal(getEvaluatedCell(model, "A1").format, "m/d/yyyy");
|
||||
assert.equal(getEvaluatedCell(model, "A1").formattedValue, "1/1/2020");
|
||||
assert.equal(getEvaluatedCell(model, "B1").value, "");
|
||||
});
|
||||
|
||||
QUnit.test("ODOO.FILTER.VALUE date from/to with only to defined", async function (assert) {
|
||||
const model = await createModelWithDataSource();
|
||||
setCellContent(model, "A1", `=ODOO.FILTER.VALUE("Date Filter")`);
|
||||
await addGlobalFilter(model, {
|
||||
id: "42",
|
||||
type: "date",
|
||||
label: "Date Filter",
|
||||
rangeType: "from_to",
|
||||
});
|
||||
await setGlobalFilterValue(model, {
|
||||
id: "42",
|
||||
value: {
|
||||
to: "2020-01-01",
|
||||
},
|
||||
});
|
||||
assert.equal(getEvaluatedCell(model, "A1").value, "");
|
||||
assert.equal(getEvaluatedCell(model, "B1").value, 43831);
|
||||
assert.equal(getEvaluatedCell(model, "B1").format, "m/d/yyyy");
|
||||
assert.equal(getEvaluatedCell(model, "B1").formattedValue, "1/1/2020");
|
||||
});
|
||||
|
||||
QUnit.test("ODOO.FILTER.VALUE date from/to with from and to defined", async function (assert) {
|
||||
const model = await createModelWithDataSource();
|
||||
setCellContent(model, "A1", `=ODOO.FILTER.VALUE("Date Filter")`);
|
||||
await addGlobalFilter(model, {
|
||||
id: "42",
|
||||
type: "date",
|
||||
label: "Date Filter",
|
||||
rangeType: "from_to",
|
||||
});
|
||||
await setGlobalFilterValue(model, {
|
||||
id: "42",
|
||||
value: {
|
||||
from: "2020-01-01",
|
||||
to: "2021-01-01",
|
||||
},
|
||||
});
|
||||
assert.equal(getEvaluatedCell(model, "A1").value, 43831);
|
||||
assert.equal(getEvaluatedCell(model, "A1").format, "m/d/yyyy");
|
||||
assert.equal(getEvaluatedCell(model, "A1").formattedValue, "1/1/2020");
|
||||
assert.equal(getEvaluatedCell(model, "B1").value, 44197);
|
||||
assert.equal(getEvaluatedCell(model, "B1").format, "m/d/yyyy");
|
||||
assert.equal(getEvaluatedCell(model, "B1").formattedValue, "1/1/2021");
|
||||
});
|
||||
|
||||
QUnit.test("ODOO.FILTER.VALUE relation filter", async function (assert) {
|
||||
const model = await createModelWithDataSource({
|
||||
mockRPC: function (route, { method, args }) {
|
||||
@@ -1362,7 +1442,7 @@ QUnit.module("spreadsheet > Global filters model", {}, () => {
|
||||
await addGlobalFilter(model, THIS_YEAR_GLOBAL_FILTER);
|
||||
const [filter] = model.getters.getGlobalFilters();
|
||||
assert.strictEqual(
|
||||
model.getters.getFilterDisplayValue(filter.label),
|
||||
model.getters.getFilterDisplayValue(filter.label)[0][0].value,
|
||||
String(new Date().getFullYear())
|
||||
);
|
||||
});
|
||||
@@ -1383,11 +1463,43 @@ QUnit.module("spreadsheet > Global filters model", {}, () => {
|
||||
assert.equal(filterSheet.cells["B1"].content, "Value");
|
||||
assert.equal(
|
||||
filterSheet.cells["B2"].content,
|
||||
model.getters.getFilterDisplayValue(filter.label)
|
||||
model.getters.getFilterDisplayValue(filter.label)[0][0].value
|
||||
);
|
||||
model.exportXLSX(); // should not crash
|
||||
});
|
||||
|
||||
QUnit.test("Export from/to global filters for excel", async function (assert) {
|
||||
const model = await createModelWithDataSource();
|
||||
await addGlobalFilter(model, {
|
||||
id: "42",
|
||||
type: "date",
|
||||
label: "Date Filter",
|
||||
rangeType: "from_to",
|
||||
});
|
||||
await setGlobalFilterValue(model, {
|
||||
id: "42",
|
||||
value: {
|
||||
from: "2020-01-01",
|
||||
to: "2021-01-01",
|
||||
},
|
||||
});
|
||||
const [filter] = model.getters.getGlobalFilters();
|
||||
const filterPlugin = model["handlers"].find(
|
||||
(handler) => handler instanceof GlobalFiltersUIPlugin
|
||||
);
|
||||
const exportData = { styles: {}, formats: {}, sheets: [] };
|
||||
filterPlugin.exportForExcel(exportData);
|
||||
const filterSheet = exportData.sheets[0];
|
||||
assert.equal(filterSheet.cells["A1"].content, "Filter");
|
||||
assert.equal(filterSheet.cells["A2"].content, filter.label);
|
||||
assert.equal(filterSheet.cells["B1"].content, "Value");
|
||||
assert.equal(filterSheet.cells["B2"].content, 43831);
|
||||
assert.equal(filterSheet.cells["C2"].content, 44197);
|
||||
assert.equal(filterSheet.cells["B2"].format, 1);
|
||||
assert.equal(filterSheet.cells["C2"].format, 1);
|
||||
assert.strictEqual(exportData.formats[1], "m/d/yyyy");
|
||||
});
|
||||
|
||||
QUnit.test("Date filter automatic default value for years filter", async function (assert) {
|
||||
const label = "This year";
|
||||
const { model } = await createSpreadsheetWithPivot();
|
||||
@@ -1498,7 +1610,7 @@ QUnit.module("spreadsheet > Global filters model", {}, () => {
|
||||
rangeType: "relative",
|
||||
});
|
||||
assert.equal(
|
||||
model.getters.getFilterDisplayValue(label),
|
||||
model.getters.getFilterDisplayValue(label)[0][0].value,
|
||||
RELATIVE_DATE_RANGE_TYPES[1].description
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { freezeOdooData } from "../../src/helpers/model";
|
||||
import { createSpreadsheetWithChart } from "../utils/chart";
|
||||
import { setCellContent } from "../utils/commands";
|
||||
import { setCellContent, setGlobalFilterValue } from "../utils/commands";
|
||||
import { getCell, getEvaluatedCell } from "../utils/getters";
|
||||
import { createSpreadsheetWithPivot } from "../utils/pivot";
|
||||
import { createModelWithDataSource } from "@spreadsheet/../tests/utils/model";
|
||||
@@ -106,4 +106,31 @@ QUnit.module("freezing spreadsheet", {}, function () {
|
||||
assert.strictEqual(data.globalFilters[0].label, "This Year");
|
||||
assert.strictEqual(data.globalFilters[0].value, new Date().getFullYear().toString());
|
||||
});
|
||||
|
||||
QUnit.test("from/to global filters are exported", async function (assert) {
|
||||
const model = await createModelWithDataSource();
|
||||
await addGlobalFilter(model, {
|
||||
id: "42",
|
||||
type: "date",
|
||||
label: "Date Filter",
|
||||
rangeType: "from_to",
|
||||
});
|
||||
await setGlobalFilterValue(model, {
|
||||
id: "42",
|
||||
value: {
|
||||
from: "2020-01-01",
|
||||
to: "2021-01-01",
|
||||
},
|
||||
});
|
||||
const data = await freezeOdooData(model);
|
||||
const filterSheet = data.sheets[1];
|
||||
assert.strictEqual(filterSheet.cells.B2.content, "43831");
|
||||
assert.strictEqual(filterSheet.cells.C2.content, "44197");
|
||||
assert.strictEqual(filterSheet.cells.B2.format, 1);
|
||||
assert.strictEqual(filterSheet.cells.C2.format, 1);
|
||||
assert.strictEqual(data.formats[1], "m/d/yyyy");
|
||||
assert.strictEqual(data.globalFilters.length, 1);
|
||||
assert.strictEqual(data.globalFilters[0].label, "Date Filter");
|
||||
assert.strictEqual(data.globalFilters[0].value, "1/1/2020, 1/1/2021");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user