Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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);
});
}

Expand Down Expand Up @@ -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];
Expand All @@ -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);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -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");

Expand Down Expand Up @@ -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: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_float">
<list>
Expand All @@ -78,17 +86,17 @@ test("matrix displaying float fields are rendered correctly", async () => {
</list>
</field>
</form>`,
});
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: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_float">
<list>
Expand All @@ -98,16 +106,16 @@ test("matrix displaying float fields can be configured", async () => {
</list>
</field>
</form>`,
});
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: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_char">
<list>
Expand All @@ -117,17 +125,17 @@ test("matrix displaying char fields are rendered correctly", async () => {
</list>
</field>
</form>`,
});
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: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_many2one">
<list>
Expand All @@ -137,16 +145,16 @@ test("matrix displaying many2one fields are rendered correctly", async () => {
</list>
</field>
</form>`,
});
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: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_many2one">
<list>
Expand All @@ -156,16 +164,16 @@ test("matrix displaying many2one fields can be configured", async () => {
</list>
</field>
</form>`,
});
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: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="value_many2one" field_y_axis="value_many2one" field_value="value_float" x_axis_clickable="True" y_axis_clickable="True">
<list>
Expand All @@ -174,6 +182,51 @@ test("matrix axis can be clickable", async () => {
</list>
</field>
</form>`,
});
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: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_float" show_row_totals="True" show_column_totals="True">
<list>
<field name="x" />
<field name="y" />
<field name="value_float" />
</list>
</field>
</form>`,
});

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);
});
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down