diff --git a/addons/web/static/src/views/graph/graph_arch_parser.js b/addons/web/static/src/views/graph/graph_arch_parser.js index a393bf16668..8b7c62cf8c9 100644 --- a/addons/web/static/src/views/graph/graph_arch_parser.js +++ b/addons/web/static/src/views/graph/graph_arch_parser.js @@ -9,7 +9,7 @@ const ORDERS = ["ASC", "DESC", "asc", "desc", null]; export class GraphArchParser { parse(arch, fields = {}) { - const archInfo = { fields, fieldAttrs: {}, groupBy: [] }; + const archInfo = { fields, fieldAttrs: {}, groupBy: [], measures: [] }; visitXML(arch, (node) => { switch (node.tagName) { case "graph": { @@ -67,6 +67,7 @@ export class GraphArchParser { } const isMeasure = node.getAttribute("type") === "measure"; if (isMeasure) { + archInfo.measures.push(fieldName); // the last field with type="measure" (if any) will be used as measure else __count archInfo.measure = fieldName; } else { diff --git a/addons/web/static/src/views/graph/graph_model.js b/addons/web/static/src/views/graph/graph_model.js index 323de10aa6a..35d047c29ef 100644 --- a/addons/web/static/src/views/graph/graph_model.js +++ b/addons/web/static/src/views/graph/graph_model.js @@ -182,6 +182,7 @@ export class GraphModel extends Model { this._normalize(metaData); metaData.measures = computeReportMeasures(metaData.fields, metaData.fieldAttrs, [ + ...(metaData.viewMeasures || []), metaData.measure, ]); diff --git a/addons/web/static/src/views/graph/graph_view.js b/addons/web/static/src/views/graph/graph_view.js index 4b76b37bdc0..08ebf7e4d70 100644 --- a/addons/web/static/src/views/graph/graph_view.js +++ b/addons/web/static/src/views/graph/graph_view.js @@ -37,6 +37,7 @@ export const graphView = { fields: fields, groupBy: archInfo.groupBy, measure: archInfo.measure || "__count", + viewMeasures: archInfo.measures, mode: archInfo.mode || "bar", order: archInfo.order || null, resModel: resModel, diff --git a/addons/web/static/tests/views/graph_view_tests.js b/addons/web/static/tests/views/graph_view_tests.js index 4d088a83bcf..7ebc16ca1a6 100644 --- a/addons/web/static/tests/views/graph_view_tests.js +++ b/addons/web/static/tests/views/graph_view_tests.js @@ -2440,7 +2440,7 @@ QUnit.module("Views", (hooks) => { QUnit.test("process default view description", async function (assert) { assert.expect(1); const propsFromArch = new GraphArchParser().parse(); - assert.deepEqual(propsFromArch, { fields: {}, fieldAttrs: {}, groupBy: [] }); + assert.deepEqual(propsFromArch, { fields: {}, fieldAttrs: {}, groupBy: [], measures: [] }); }); QUnit.test("process simple arch (no field tag)", async function (assert) { @@ -2454,6 +2454,7 @@ QUnit.module("Views", (hooks) => { fields, fieldAttrs: {}, groupBy: [], + measures: [], mode: "line", order: "ASC", }); @@ -2465,6 +2466,7 @@ QUnit.module("Views", (hooks) => { fields, fieldAttrs: {}, groupBy: [], + measures: [], stacked: false, title: "Title", }); @@ -2492,11 +2494,33 @@ QUnit.module("Views", (hooks) => { fighters: { string: "FooFighters" }, }, measure: "revenue", + measures: ["revenue"], groupBy: ["date:day", "foo"], mode: "pie", }); }); + QUnit.test("process arch with non stored field tags of type measure", async function (assert) { + assert.expect(1); + const fields = serverData.models.foo.fields; + fields.revenue.store = false; + const arch = ` + + + + + + `; + const propsFromArch = new GraphArchParser().parse(arch, fields); + assert.deepEqual(propsFromArch, { + fields, + fieldAttrs: {}, + measure: "foo", + measures: ["revenue", "foo"], + groupBy: ["product_id"], + }); + }); + QUnit.test("displaying chart data with three groupbys", async function (assert) { // this test makes sure the line chart shows all data labels (X axis) when // it is grouped by several fields @@ -3078,6 +3102,28 @@ QUnit.module("Views", (hooks) => { assert.strictEqual(getYAxeLabel(graph), "Product"); }); + QUnit.test( + "non store fields defined on the arch are present in the measures", + async function (assert) { + serverData.models.foo.fields.revenue.store = false; + await makeView({ + serverData, + type: "graph", + resModel: "foo", + arch: ` + + + + `, + }); + await toggleMenu(target, "Measures"); + assert.deepEqual( + Array.from(target.querySelectorAll(".o_menu_item")).map((e) => e.innerText.trim()), + ["Foo", "Revenue", "Count"] + ); + } + ); + QUnit.test('graph view "graph_measure" field in context', async function (assert) { assert.expect(6); const graph = await makeView({