[FIX] mail: insert data in relational field

Before this commit, when a record was identified by relational
fields, we couldn't insert this record by passing data rather than
the records.

We should be able to insert records and data in the models, so
passing data should be ok.

This commit fixes this issue by backporting some code of improvements
and fixes from master. Note that the internal code of model is
written for retrocompatibility, so some added features like
store.Model in diff is ok.

Part-of: odoo/odoo#144999
This commit is contained in:
Alexandre Kühn
2023-12-05 22:40:41 +00:00
parent 0761b4299e
commit 3e443edcf9
2 changed files with 47 additions and 2 deletions
+25 -2
View File
@@ -28,6 +28,7 @@ export function OR(...args) {
}
export function makeStore(env) {
let storeReady = false;
const res = {
// fake store for now, until it becomes a model
/** @type {import("models").Store} */
@@ -115,7 +116,16 @@ export function makeStore(env) {
/** @param {Record} receiver */
set(target, name, val, receiver) {
return Record.MAKE_UPDATE(() => {
if (name === "Model" || !(name in target.Model._fields)) {
if (name === "Model") {
Reflect.set(target, name, val, receiver);
return true;
}
if (target instanceof BaseStore && storeReady && name in Models) {
// "store.Model =" is considered a Model.insert()
res.store[name].insert(val);
return true;
}
if (!(name in target.Model._fields)) {
Reflect.set(target, name, val, receiver);
return true;
}
@@ -388,6 +398,7 @@ export function makeStore(env) {
Model.store = res.store;
res.store[Model.name] = Model;
}
storeReady = true;
return res.store;
}
@@ -1311,8 +1322,20 @@ export class Record {
const obj = new this.Class();
obj.Model = this;
const ids = this._retrieveIdFromData(data);
for (const name in ids) {
if (
ids[name] &&
!Record.isRecord(ids[name]) &&
!Record.isCommand(ids[name]) &&
Record.isRelation(this._fields[name])
) {
// preinsert that record in relational field,
// as it is required to make current local id
ids[name] = this.store[this._fields[name].targetModel].preinsert(ids[name]);
}
}
let record = Object.assign(obj, {
localId: this.localId(data),
localId: this.localId(ids),
...ids,
});
Object.assign(record, { _store: this.store });
@@ -278,3 +278,25 @@ QUnit.test("onAdd hook should see fully inserted data", async (assert) => {
thread.members.add({ name: "John", type: "admin" });
assert.verifySteps(["Thread.onAdd::John.admin"]);
});
QUnit.test("Can insert with relation as id, using relation as data object", async (assert) => {
(class User extends Record {
static id = "name";
name;
settings = Record.one("Settings");
}).register();
(class Settings extends Record {
static id = "user";
pushNotif;
user = Record.one("User", { inverse: "settings" });
}).register();
const store = await start();
store.Settings.insert([
{ pushNotif: true, user: { name: "John" } },
{ pushNotif: false, user: { name: "Paul" } },
]);
assert.ok(store.User.get("John"));
assert.ok(store.User.get("John").settings.pushNotif);
assert.ok(store.User.get("Paul"));
assert.notOk(store.User.get("Paul").settings.pushNotif);
});