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({