diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js index eb9cf7327d0..eeba6456f75 100644 --- a/addons/web/static/src/views/relational_model.js +++ b/addons/web/static/src/views/relational_model.js @@ -80,6 +80,31 @@ function orderByToString(orderBy) { return orderBy.map((o) => `${o.name} ${o.asc ? "ASC" : "DESC"}`).join(", "); } +/** + * @param {RawContext} rawContext + * @param {Context} defaultContext + * @returns {Context} + */ +function processRawContext(rawContext, defaultContext) { + const contexts = []; + if (!rawContext) { + return Object.assign({}, defaultContext); + } + contexts.push({ ...defaultContext, ...rawContext.make() }); + while (rawContext.parent) { + rawContext = rawContext.parent; + const context = rawContext.make(); + for (const key in context) { + if (key.startsWith("default_")) { + delete context[key]; + } + } + contexts.push(context); + } + + return Object.assign({}, ...contexts.reverse()); +} + /** * FIXME: don't know where this function should be: * - on a dataPoint: don't want to make it accessible everywhere (e.g. in Fields) @@ -255,25 +280,7 @@ class DataPoint { // ------------------------------------------------------------------------- get context() { - const contexts = []; - let rawContext = this.rawContext; - if (!rawContext) { - return Object.assign({}, this.defaultContext); - } - contexts.push({ ...this.defaultContext, ...rawContext.make() }); - - while (rawContext.parent) { - rawContext = rawContext.parent; - const context = rawContext.make(); - for (const key in context) { - if (key.startsWith("default_")) { - delete context[key]; - } - } - contexts.push(context); - } - - return Object.assign({}, ...contexts.reverse()); + return processRawContext(this.rawContext, this.defaultContext); } get fieldNames() { @@ -999,7 +1006,15 @@ export class Record extends DataPoint { if (!id && label) { // only display_name given -> do a name_create const res = await this.model.orm.call(relation, "name_create", [label], { - context: this.context, + context: processRawContext({ + parent: this.rawContext, + make: () => { + return makeContext( + [this.activeFields[fieldName].context], + this.evalContext + ); + }, + }), }); // Check if a record is really created. Models without defined // _rec_name cannot create record based on name_create. diff --git a/addons/web/static/tests/views/fields/many2one_field_tests.js b/addons/web/static/tests/views/fields/many2one_field_tests.js index 403e23be9a9..01f68ad3fbf 100644 --- a/addons/web/static/tests/views/fields/many2one_field_tests.js +++ b/addons/web/static/tests/views/fields/many2one_field_tests.js @@ -713,6 +713,44 @@ QUnit.module("Fields", (hooks) => { } ); + QUnit.test( + "many2ones in list views: create a new record with a context", + async function (assert) { + await makeView({ + type: "list", + resModel: "partner", + serverData, + arch: ` + + + `, + context: { + default_yop: 3, + yop: 4, + }, + mockRPC(route, args) { + const { method, model, kwargs } = args; + if (method === "name_create" && model === "user") { + const { context } = kwargs; + assert.step(method); + assert.strictEqual(context.default_test, 1); + assert.strictEqual(context.test, 2); + assert.notOk("default_yop" in context); + assert.strictEqual(context.yop, 4); + } + }, + }); + + await click(target.querySelectorAll(".o_data_cell")[0]); + const input = target.querySelector(".o_field_widget[name=user_id] input"); + await editInput(input, null, "yy"); + await click(target, ".o_field_widget[name=user_id] input"); + await selectDropdownItem(target, "user_id", 'Create "yy"'); + + assert.verifySteps(["name_create"]); + } + ); + QUnit.test( "onchanges on many2ones trigger when editing record in form view", async function (assert) {