[FIX] spreadsheet: accumulate starting with past data
- Inserting a cumulated graph view inside spreadsheet (e.g. cumulated subscription MRR breakdown), - apply a global filter to filter, let's say on the current month => the first data point does not include data from before the current month (the accumulation starts at 0, even though there is data before) You can also check the MRR evolution subscription dashboard, "MRR over time" chart. Note: with this fix, we assume all "cumulated" charts are also "cumulated_start". Which is true in practice (only one cumulated graph view in the entire codebase) closes odoo/odoo#149084 Task: 3680601 Related: odoo/enterprise#54146 Signed-off-by: Lucas Lefèvre (lul) <lul@odoo.com>
This commit is contained in:
@@ -22,6 +22,7 @@ import { ChartDataSource } from "../data_source/chart_data_source";
|
||||
* @property {string} title
|
||||
* @property {string} background
|
||||
* @property {string} legendPosition
|
||||
* @property {boolean} cumulative
|
||||
*
|
||||
* @typedef OdooChartDefinitionDataSource
|
||||
* @property {MetaData} metaData
|
||||
@@ -38,7 +39,14 @@ export class OdooChart extends AbstractChart {
|
||||
constructor(definition, sheetId, getters) {
|
||||
super(definition, sheetId, getters);
|
||||
this.type = definition.type;
|
||||
this.metaData = definition.metaData;
|
||||
this.metaData = {
|
||||
...definition.metaData,
|
||||
mode: this.type.replace("odoo_", ""),
|
||||
cumulated: definition.cumulative,
|
||||
// if a chart is cumulated, the first data point should take into
|
||||
// account past data, even if a domain on a specific period is applied
|
||||
cumulatedStart: definition.cumulative,
|
||||
};
|
||||
this.searchParams = definition.searchParams;
|
||||
this.legendPosition = definition.legendPosition;
|
||||
this.background = definition.background;
|
||||
@@ -62,10 +70,7 @@ export class OdooChart extends AbstractChart {
|
||||
*/
|
||||
getDefinitionForDataSource() {
|
||||
return {
|
||||
metaData: {
|
||||
...this.metaData,
|
||||
mode: this.type.replace("odoo_", ""),
|
||||
},
|
||||
metaData: this.metaData,
|
||||
searchParams: this.searchParams,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ function createOdooChartRuntime(chart, getters) {
|
||||
const locale = getters.getLocale();
|
||||
const chartJsConfig = getLineConfiguration(chart, labels, locale);
|
||||
const colors = new ChartColors();
|
||||
for (let [index, { label, data }] of datasets.entries()) {
|
||||
for (let [index, { label, data, cumulatedStart }] of datasets.entries()) {
|
||||
const color = colors.next();
|
||||
const backgroundRGBA = colorToRGBA(color);
|
||||
if (chart.stacked) {
|
||||
@@ -59,7 +59,7 @@ function createOdooChartRuntime(chart, getters) {
|
||||
backgroundRGBA.a = LINE_FILL_TRANSPARENCY;
|
||||
}
|
||||
if (chart.cumulative) {
|
||||
let accumulator = 0;
|
||||
let accumulator = cumulatedStart;
|
||||
data = data.map((value) => {
|
||||
accumulator += value;
|
||||
return accumulator;
|
||||
|
||||
@@ -12,6 +12,7 @@ import { THIS_YEAR_GLOBAL_FILTER } from "../../utils/global_filter";
|
||||
import * as spreadsheet from "@odoo/o-spreadsheet";
|
||||
import { makeServerError } from "@web/../tests/helpers/mock_server";
|
||||
import { session } from "@web/session";
|
||||
import { getBasicServerData } from "../../utils/data";
|
||||
|
||||
const { toZone } = spreadsheet.helpers;
|
||||
|
||||
@@ -523,6 +524,52 @@ QUnit.module("spreadsheet > odoo chart plugin", {}, () => {
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("cumulative line chart with past data before domain period", async (assert) => {
|
||||
const serverData = getBasicServerData();
|
||||
serverData.models.partner.records = [
|
||||
{ date: "2020-01-01", probability: 10 },
|
||||
{ date: "2021-01-01", probability: 2 },
|
||||
{ date: "2022-01-01", probability: 3 },
|
||||
{ date: "2022-03-01", probability: 4 },
|
||||
{ date: "2022-06-01", probability: 5 },
|
||||
];
|
||||
const { model } = await createSpreadsheetWithChart({
|
||||
type: "odoo_line",
|
||||
serverData,
|
||||
definition: {
|
||||
type: "odoo_line",
|
||||
metaData: {
|
||||
groupBy: ["date"],
|
||||
measure: "probability",
|
||||
order: null,
|
||||
resModel: "partner",
|
||||
},
|
||||
searchParams: {
|
||||
comparison: null,
|
||||
context: {},
|
||||
domain: [
|
||||
["date", ">=", "2022-01-01"],
|
||||
["date", "<=", "2022-12-31"],
|
||||
],
|
||||
groupBy: [],
|
||||
orderBy: [],
|
||||
},
|
||||
cumulative: true,
|
||||
title: "Partners",
|
||||
dataSourceId: "42",
|
||||
id: "42",
|
||||
},
|
||||
});
|
||||
const sheetId = model.getters.getActiveSheetId();
|
||||
const chartId = model.getters.getChartIds(sheetId)[0];
|
||||
await waitForDataSourcesLoaded(model);
|
||||
|
||||
assert.deepEqual(
|
||||
model.getters.getChartRuntime(chartId).chartJsConfig.data.datasets[0].data,
|
||||
[15, 19, 24]
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Can insert odoo chart from a different model", async (assert) => {
|
||||
const model = await createModelWithDataSource();
|
||||
insertListInSpreadsheet(model, { model: "product", columns: ["name"] });
|
||||
|
||||
@@ -10,9 +10,14 @@ const uuidGenerator = new spreadsheet.helpers.UuidGenerator();
|
||||
/**
|
||||
*
|
||||
* @param {Model} model
|
||||
* @param {string} type
|
||||
* @param {import("@spreadsheet/chart/odoo_chart/odoo_chart").OdooChartDefinition} definition
|
||||
*/
|
||||
export function insertChartInSpreadsheet(model, type = "odoo_bar") {
|
||||
const definition = getChartDefinition(type);
|
||||
export function insertChartInSpreadsheet(
|
||||
model,
|
||||
type = "odoo_bar",
|
||||
definition = getChartDefinition(type)
|
||||
) {
|
||||
model.dispatch("CREATE_CHART", {
|
||||
sheetId: model.getters.getActiveSheetId(),
|
||||
id: definition.id,
|
||||
@@ -26,17 +31,17 @@ export function insertChartInSpreadsheet(model, type = "odoo_bar") {
|
||||
/**
|
||||
*
|
||||
* @param {Object} params
|
||||
* @param {function} [params.definition]
|
||||
* @param {function} [params.mockRPC]
|
||||
* @param {string} [params.type]
|
||||
* @param {import("./data").ServerData} [params.serverData]
|
||||
*
|
||||
* @returns { Promise<{ model: Model, env: Object }>}
|
||||
*/
|
||||
export async function createSpreadsheetWithChart(params = {}) {
|
||||
const model = await createModelWithDataSource({
|
||||
mockRPC: params.mockRPC,
|
||||
});
|
||||
const model = await createModelWithDataSource(params);
|
||||
|
||||
insertChartInSpreadsheet(model, params.type);
|
||||
insertChartInSpreadsheet(model, params.type, params.definition);
|
||||
|
||||
const env = model.config.custom.env;
|
||||
env.model = model;
|
||||
|
||||
Reference in New Issue
Block a user