diff --git a/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm.js b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm.js index 20016e5d3e8a..aee17d915cd7 100644 --- a/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm.js +++ b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm.js @@ -1,19 +1,16 @@ -import {Component, onWillUpdateProps} from "@odoo/owl"; import {evaluateBooleanExpr, evaluateExpr} from "@web/core/py_js/py"; +import {Component, onWillRender} from "@odoo/owl"; import {Domain} from "@web/core/domain"; import {Record} from "@web/model/relational_model/record"; import {getFieldContext} from "@web/model/relational_model/utils"; export class X2Many2DMatrixRenderer extends Component { setup() { - this.columns = this._getColumns(); - this.rows = this._getRows(); - this.matrix = this._getMatrix(); - - onWillUpdateProps((newProps) => { - this.columns = this._getColumns(newProps.list.records); - this.rows = this._getRows(newProps.list.records); - this.matrix = this._getMatrix(newProps.list.records); + onWillRender(() => { + const records = this.list.records; + this.columns = this._getColumns(records); + this.rows = this._getRows(records); + this.matrix = this._getMatrix(records, this.rows, this.columns); }); } @@ -53,7 +50,7 @@ export class X2Many2DMatrixRenderer extends Component { return rows; } - _getPointOfRecord(record) { + _getPointOfRecord(record, rows, columns) { let xValue = record.data[this.matrixFields.x]; if (record.fields[this.matrixFields.x].type === "many2one") { xValue = xValue[0]; @@ -63,20 +60,20 @@ export class X2Many2DMatrixRenderer extends Component { yValue = yValue[0]; } - const x = this.columns.findIndex((c) => c.value === xValue); - const y = this.rows.findIndex((r) => r.value === yValue); + const x = columns.findIndex((c) => c.value === xValue); + const y = rows.findIndex((r) => r.value === yValue); return {x, y}; } - _getMatrix(records = this.list.records) { - const matrix = this.rows.map(() => - new Array(this.columns.length).fill(null).map(() => { + _getMatrix(records = this.list.records, rows, columns) { + const matrix = rows.map(() => + new Array(columns.length).fill(null).map(() => { return {value: 0, records: []}; }) ); records.forEach((record) => { const value = record.data[this.matrixFields.value]; - const {x, y} = this._getPointOfRecord(record); + const {x, y} = this._getPointOfRecord(record, rows, columns); matrix[y][x].value += value; matrix[y][x].records.push(record); }); diff --git a/web_widget_x2many_2d_matrix/static/tests/web_widget_x2many_2d_matrix.test.js b/web_widget_x2many_2d_matrix/static/tests/web_widget_x2many_2d_matrix.test.js index 942132b12d0c..c3f8575a7dda 100644 --- a/web_widget_x2many_2d_matrix/static/tests/web_widget_x2many_2d_matrix.test.js +++ b/web_widget_x2many_2d_matrix/static/tests/web_widget_x2many_2d_matrix.test.js @@ -1,5 +1,12 @@ -import {defineModels, fields, models, mountView} from "@web/../tests/web_test_helpers"; +import { + contains, + defineModels, + fields, + models, + mountView, +} from "@web/../tests/web_test_helpers"; import {describe, expect, test} from "@odoo/hoot"; +import {queryAll} from "@odoo/hoot-dom"; describe.current.tags("desktop"); @@ -63,12 +70,13 @@ class Line extends models.Model { } defineModels([Line, Main]); -test("matrix displaying float fields are rendered correctly", async () => { - await mountView({ - type: "form", - resModel: "main", - resId: 1, - arch: ` +describe("X2Many2DMatrixRenderer", () => { + test("matrix displaying float fields are rendered correctly", async () => { + await mountView({ + type: "form", + resModel: "main", + resId: 1, + arch: `
@@ -78,17 +86,17 @@ test("matrix displaying float fields are rendered correctly", async () => {
`, + }); + expect(".o_field_widget input").toHaveCount(4); + expect(".col-total").toHaveText("168.00"); }); - expect(".o_field_widget input").toHaveCount(4); - expect(".col-total").toHaveText("168.00"); -}); -test("matrix displaying float fields can be configured", async () => { - await mountView({ - type: "form", - resModel: "main", - resId: 1, - arch: ` + test("matrix displaying float fields can be configured", async () => { + await mountView({ + type: "form", + resModel: "main", + resId: 1, + arch: `
@@ -98,16 +106,16 @@ test("matrix displaying float fields can be configured", async () => {
`, + }); + expect(".o_field_widget input").toHaveValue("42.000"); }); - expect(".o_field_widget input").toHaveValue("42.000"); -}); -test("matrix displaying char fields are rendered correctly", async () => { - await mountView({ - type: "form", - resModel: "main", - resId: 1, - arch: ` + test("matrix displaying char fields are rendered correctly", async () => { + await mountView({ + type: "form", + resModel: "main", + resId: 1, + arch: `
@@ -117,17 +125,17 @@ test("matrix displaying char fields are rendered correctly", async () => {
`, + }); + expect(".o_field_widget input").toHaveCount(4); + expect(".col-total").toHaveCount(0); }); - expect(".o_field_widget input").toHaveCount(4); - expect(".col-total").toHaveCount(0); -}); -test("matrix displaying many2one fields are rendered correctly", async () => { - await mountView({ - type: "form", - resModel: "main", - resId: 1, - arch: ` + test("matrix displaying many2one fields are rendered correctly", async () => { + await mountView({ + type: "form", + resModel: "main", + resId: 1, + arch: `
@@ -137,16 +145,16 @@ test("matrix displaying many2one fields are rendered correctly", async () => {
`, + }); + expect(".o_field_many2one_selection").toHaveCount(4); + expect(".o_form_uri").toHaveCount(0); }); - expect(".o_field_many2one_selection").toHaveCount(4); - expect(".o_form_uri").toHaveCount(0); -}); -test("matrix displaying many2one fields can be configured", async () => { - await mountView({ - type: "form", - resModel: "main", - resId: 1, - arch: ` + test("matrix displaying many2one fields can be configured", async () => { + await mountView({ + type: "form", + resModel: "main", + resId: 1, + arch: `
@@ -156,16 +164,16 @@ test("matrix displaying many2one fields can be configured", async () => {
`, + }); + expect(".o_field_many2one_selection").toHaveCount(2); + expect(".o_form_uri").toHaveCount(2); }); - expect(".o_field_many2one_selection").toHaveCount(2); - expect(".o_form_uri").toHaveCount(2); -}); -test("matrix axis can be clickable", async () => { - await mountView({ - type: "form", - resModel: "main", - resId: 1, - arch: ` + test("matrix axis can be clickable", async () => { + await mountView({ + type: "form", + resModel: "main", + resId: 1, + arch: `
@@ -174,6 +182,51 @@ test("matrix axis can be clickable", async () => {
`, + }); + expect(".o_form_uri").toHaveCount(2); + }); + + test("matrix totals are updated correctly after several edits", async () => { + await mountView({ + type: "form", + resModel: "main", + resId: 1, + arch: ` +
+ + + + + + + +
`, + }); + + expect(".col-total").toHaveText("168.00"); + + const inputs = queryAll(".o_field_widget input"); + // Initial state: [42, 42, 42, 42] -> Total 168 + + await contains(inputs[0]).edit("100"); + // State: [100, 42, 42, 42] -> Total 226 + expect(".col-total").toHaveText("226.00"); + + await contains(inputs[1]).edit("200"); + // State: [100, 200, 42, 42] -> Total 384 + expect(".col-total").toHaveText("384.00"); + + await contains(inputs[2]).edit("50"); + // State: [100, 200, 50, 42] -> Total 392 + expect(".col-total").toHaveText("392.00"); + + await contains(inputs[3]).edit("0"); + // State: [100, 200, 50, 0] -> Total 350 + expect(".col-total").toHaveText("350.00"); + + // Edit the first one again + await contains(inputs[0]).edit("10"); + // State: [10, 200, 50, 0] -> Total 260 + expect(".col-total").toHaveText("260.00"); }); - expect(".o_form_uri").toHaveCount(2); }); diff --git a/web_widget_x2many_2d_matrix/tests/test_web_widget_x2many_2d_matrix.py b/web_widget_x2many_2d_matrix/tests/test_web_widget_x2many_2d_matrix.py index 590738a1e63b..d5ae574625f7 100644 --- a/web_widget_x2many_2d_matrix/tests/test_web_widget_x2many_2d_matrix.py +++ b/web_widget_x2many_2d_matrix/tests/test_web_widget_x2many_2d_matrix.py @@ -5,7 +5,7 @@ class TestWebWidgetX2Many2DMatrix(HttpCase): def test_js(self): self.browser_js( - "/web/tests?headless&loglevel=2&preset=desktop&timeout=15000&id=b42fa5f8", + "/web/tests?headless&loglevel=2&preset=desktop&timeout=15000&filter=X2Many2DMatrixRenderer", "", "", login="admin",