[FIX] web: can't save o2m with not new dirty invalid record

Imagine a form view with a one2many editable list, containing a
required field. Open an existing record, s.t. in the one2many
there's already a sub record. Modify that subrecord, s.t. the
required field is unset (e.g. empty it, or it can be unset from
the beginning, but then modify another field). Then save the main
record. Before this commit, the record could be saved.

In this situation, the modified one2many record isn't valid, so
we shouldn't be allowed to save. The view should remain in edition
and the invalid field should be indicated.

This commit fixes this issue.

closes odoo/odoo#100059

Signed-off-by: Géry Debongnie <ged@odoo.com>
This commit is contained in:
Aaron Bohy
2022-09-13 22:16:08 +02:00
parent 5b62f5a826
commit dd72a40926
2 changed files with 36 additions and 1 deletions
@@ -453,7 +453,7 @@ export class Record extends DataPoint {
async checkX2ManyValidity(fieldName) {
const list = this.data[fieldName];
const record = list.editedRecord;
if (record && record.isNew && !(await record.checkValidity())) {
if (record && !(await record.checkValidity())) {
if (record.canBeAbandoned && !record.isDirty) {
list.abandonRecord(record.id);
} else {
@@ -3654,6 +3654,41 @@ QUnit.module("Fields", (hooks) => {
}
);
QUnit.test("save a record with not new, dirty and invalid subrecord", async function (assert) {
serverData.models.partner.records[0].p = [2];
serverData.models.partner.records[1].display_name = ""; // invalid record
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: `
<form>
<field name="p">
<tree editable="bottom">
<field name="display_name" required="1"/>
<field name="int_field"/>
</tree>
</field>
</form>`,
resId: 1,
mockRPC(route, args) {
if (args.method === "write") {
throw new Error("Should not call write as record is invalid");
}
},
mode: "edit",
});
assert.containsOnce(target, ".o_form_editable");
await click(target.querySelector(".o_data_cell")); // edit the first row
assert.hasClass(target.querySelector(".o_data_row"), "o_selected_row");
await editInput(target, ".o_field_widget[name=int_field] input", 44);
await click(target.querySelector(".o_form_button_save"));
assert.containsOnce(target, ".o_form_editable");
assert.containsOnce(target, ".o_invalid_cell");
});
QUnit.test("editable one2many list, adding, discarding, and pager", async function (assert) {
serverData.models.partner.records[0].turtles = [1];