[FIX] web: incomplete record reload in x2many form view context
Steps to reproduce: - Install eLearning - Create or go to an existing course. - Add Content - Fill the name and use Save & Close - Click again in the same content we have just created. - Click on website preview. Issue: Saving a record from a form view that is part of an x2many field would only reload the fields present in the list view. This led to incomplete data being loaded into the model. Solution: - Pass the `viewType` option to `_fetchRecord` to ensure that the record is reloaded in the context of the form view, thereby including all fields. - Add `viewType` to the `saveOptions` in the `basic_relational_model.js` to ensure the correct view context is used during the save operation. This ensures that all fields are reloaded into the model, providing a complete view of the data. opw-3330010 closes odoo/odoo#139968 X-original-commit: 3cec34e659222073b0fba36983eaec9f7bf5514f Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
committed by
Pierre Rousseau
parent
c838944646
commit
4a7d93d089
@@ -797,7 +797,7 @@ export class StaticList extends DataPoint {
|
||||
}
|
||||
|
||||
_getCommands({ withReadonly } = {}) {
|
||||
const { CREATE, UPDATE } = x2ManyCommands;
|
||||
const { CREATE, UPDATE, LINK } = x2ManyCommands;
|
||||
const commands = [];
|
||||
for (const command of this._commands) {
|
||||
if (command[0] === UPDATE && command[1] in this._unknownRecordCommands) {
|
||||
@@ -814,9 +814,16 @@ export class StaticList extends DataPoint {
|
||||
}
|
||||
} else if (command[0] === CREATE || command[0] === UPDATE) {
|
||||
const record = this._cache[command[1]];
|
||||
const values = record._getChanges(record._changes, { withReadonly });
|
||||
if (command[0] === CREATE || Object.keys(values).length) {
|
||||
commands.push([command[0], command[1], values]);
|
||||
if (command[0] === CREATE && record.resId) {
|
||||
// we created a new record, but it has already been saved (e.g. because we clicked
|
||||
// on a view button in the x2many dialog), so replace the CREATE command by a
|
||||
// LINK
|
||||
commands.push([LINK, record.resId]);
|
||||
} else {
|
||||
const values = record._getChanges(record._changes, { withReadonly });
|
||||
if (command[0] === CREATE || Object.keys(values).length) {
|
||||
commands.push([command[0], command[1], values]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
commands.push(command);
|
||||
|
||||
@@ -127,6 +127,7 @@ QUnit.module("Views", (hooks) => {
|
||||
["partner", "Partner"],
|
||||
],
|
||||
},
|
||||
user_id: { string: "User", type: "many2one", relation: "user" },
|
||||
},
|
||||
records: [
|
||||
{
|
||||
@@ -14299,4 +14300,90 @@ QUnit.module("Views", (hooks) => {
|
||||
await editInput(target, "[name='int_field'] input", "42");
|
||||
assert.verifySteps(["get_special_data 9", "get_special_data 42"]);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"x2many field in form dialog view is correctly saved when using a view button",
|
||||
async function (assert) {
|
||||
serverData.actions = {
|
||||
1: {
|
||||
id: 1,
|
||||
name: "Partner",
|
||||
res_model: "partner",
|
||||
type: "ir.actions.act_window",
|
||||
views: [[false, "form"]],
|
||||
view_mode: "form",
|
||||
res_id: 6,
|
||||
},
|
||||
};
|
||||
|
||||
serverData.views = {
|
||||
"partner,false,form": `
|
||||
<form>
|
||||
<field name="display_name"/>
|
||||
</form>`,
|
||||
"partner,false,search": `<search/>`,
|
||||
"user,false,form": `
|
||||
<form>
|
||||
<field name="partner_ids">
|
||||
<tree>
|
||||
<field name="display_name"/>
|
||||
</tree>
|
||||
<form>
|
||||
<header>
|
||||
<button type="action" name="1" string="test"/>
|
||||
</header>
|
||||
<field name="display_name"/>
|
||||
</form>
|
||||
</field>
|
||||
</form>
|
||||
`,
|
||||
"user,false,search": `<search/>`,
|
||||
};
|
||||
|
||||
const webClient = await createWebClient({
|
||||
serverData,
|
||||
mockRPC: (route, { method, args, model }) => {
|
||||
if (method === "web_save") {
|
||||
if (model === "partner") {
|
||||
assert.step(`web_save_partner`);
|
||||
assert.deepEqual(args[1], {
|
||||
display_name: "new value",
|
||||
});
|
||||
} else if (model === "user") {
|
||||
assert.step(`web_save_user`);
|
||||
assert.deepEqual(
|
||||
args[1],
|
||||
{
|
||||
partner_ids: [[4, 6]],
|
||||
},
|
||||
"Should be a LINK_TO command"
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
await doAction(webClient, {
|
||||
res_id: 19,
|
||||
type: "ir.actions.act_window",
|
||||
res_model: "user",
|
||||
view_mode: "form",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
|
||||
assert.containsNone(target, ".o_data_cell");
|
||||
await click(target.querySelector(".o_field_x2many_list_row_add a"));
|
||||
await editInput(target, ".o_field_widget[name=display_name] input", "new value");
|
||||
await click(target, ".modal-dialog .o_form_button_save");
|
||||
await click(target.querySelector(".o_data_cell"));
|
||||
await click(target, "[name='1']");
|
||||
assert.verifySteps(
|
||||
["web_save_partner", "web_save_user"],
|
||||
"Verify that the x2many record is saved (partner is saved, then user is saved with a link to"
|
||||
);
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o_field_widget[name=display_name] input").value,
|
||||
"new value"
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user