[REF] web,mail,account: orm service: move context in kwargs

This commit standardizes the API of orm service functions by adding
a "kwargs" parameter, s.t. one can always use those functions even
if the target model overrides the corresponding method to add the
support of a given kwargs. Furthermore, to simplify those function
API, and to close the gap between the js and python APIs, we moved
the "context" argument inside the kwargs.

closes odoo/odoo#99018

Related: odoo/enterprise#30830
Signed-off-by: Samuel Degueldre <sad@odoo.com>
This commit is contained in:
Aaron Bohy
2022-08-30 20:23:17 +02:00
parent 002a76eaaa
commit bedce02bb7
9 changed files with 85 additions and 94 deletions
@@ -27,7 +27,7 @@ export class AccountFileUploader extends Component {
datas: file.data,
};
const att_id = await this.orm.create("ir.attachment", [att_data], {
...this.props.extraContext, ...this.env.searchModel.context,
context: { ...this.props.extraContext, ...this.env.searchModel.context },
});
this.attachmentIdsToProcess.push(att_id);
}
+8 -8
View File
@@ -171,24 +171,24 @@ registerModel({
return this.env.services.rpc(route, rpcParameters, { silent, ...rpcSettings });
} else {
const { args, method, model, kwargs = {} } = params;
const { context, domain, fields, groupBy, ...ormOptions } = kwargs;
const { domain, fields, groupBy } = kwargs;
const ormService = 'shadow' in options ? this.env.services.orm.silent : this.env.services.orm;
switch (method) {
case 'create':
return ormService.create(model, args[0], context);
return ormService.create(model, args[0], kwargs);
case 'read':
return ormService.read(model, args[0], args.length > 1 ? args[1] : undefined, {}, context);
return ormService.read(model, args[0], args.length > 1 ? args[1] : undefined, kwargs);
case 'read_group':
return ormService.readGroup(model, domain, fields, groupBy, ormOptions, context);
return ormService.readGroup(model, domain, fields, groupBy, kwargs);
case 'search':
return ormService.search(model, args[0], ormOptions, context);
return ormService.search(model, args[0], kwargs);
case 'search_read':
return ormService.searchRead(model, domain, fields, ormOptions, context);
return ormService.searchRead(model, domain, fields, kwargs);
case 'unlink':
return ormService.unlink(model, args[0], context);
return ormService.unlink(model, args[0], kwargs);
case 'write':
return ormService.write(model, args[0], args[1], context);
return ormService.write(model, args[0], args[1], kwargs);
default:
return ormService.call(model, method, args, kwargs);
}
+21 -22
View File
@@ -109,23 +109,23 @@ export class ORM {
return this.rpc(url, params, { silent: this._silent });
}
create(model, records, context) {
create(model, records, kwargs = {}) {
validateArray("records", records);
for (const record of records) {
validateObject("record", record);
}
return this.call(model, "create", records, { context });
return this.call(model, "create", records, kwargs);
}
nameGet(model, ids, context) {
nameGet(model, ids, kwargs = {}) {
validatePrimitiveList("ids", "number", ids);
if (!ids.length) {
return Promise.resolve([]);
}
return this.call(model, "name_get", [ids], { context });
return this.call(model, "name_get", [ids], kwargs);
}
read(model, ids, fields, kwargs = {}, context = {}) {
read(model, ids, fields, kwargs = {}) {
validatePrimitiveList("ids", "number", ids);
if (fields) {
validatePrimitiveList("fields", "string", fields);
@@ -133,43 +133,43 @@ export class ORM {
if (!ids.length) {
return Promise.resolve([]);
}
return this.call(model, "read", [ids, fields], { ...kwargs, context });
return this.call(model, "read", [ids, fields], kwargs);
}
readGroup(model, domain, fields, groupby, kwargs = {}, context = {}) {
readGroup(model, domain, fields, groupby, kwargs = {}) {
validateArray("domain", domain);
validatePrimitiveList("fields", "string", fields);
validatePrimitiveList("groupby", "string", groupby);
return this.call(model, "read_group", [], { ...kwargs, domain, fields, groupby, context });
return this.call(model, "read_group", [], { ...kwargs, domain, fields, groupby });
}
search(model, domain, kwargs = {}, context = {}) {
search(model, domain, kwargs = {}) {
validateArray("domain", domain);
return this.call(model, "search", [domain], { ...kwargs, context });
return this.call(model, "search", [domain], kwargs);
}
searchRead(model, domain, fields, kwargs = {}, context = {}) {
searchRead(model, domain, fields, kwargs = {}) {
validateArray("domain", domain);
if (fields) {
validatePrimitiveList("fields", "string", fields);
}
return this.call(model, "search_read", [], { ...kwargs, context, domain, fields });
return this.call(model, "search_read", [], { ...kwargs, domain, fields });
}
searchCount(model, domain, context = {}) {
searchCount(model, domain, kwargs = {}) {
validateArray("domain", domain);
return this.call(model, "search_count", [domain], { context });
return this.call(model, "search_count", [domain], kwargs);
}
unlink(model, ids, context) {
unlink(model, ids, kwargs = {}) {
validatePrimitiveList("ids", "number", ids);
if (!ids.length) {
return true;
}
return this.call(model, "unlink", [ids], { context });
return this.call(model, "unlink", [ids], kwargs);
}
webReadGroup(model, domain, fields, groupby, kwargs = {}, context = {}) {
webReadGroup(model, domain, fields, groupby, kwargs = {}) {
validateArray("domain", domain);
validatePrimitiveList("fields", "string", fields);
validatePrimitiveList("groupby", "string", groupby);
@@ -178,20 +178,19 @@ export class ORM {
groupby,
domain,
fields,
context,
});
}
webSearchRead(model, domain, fields, kwargs = {}, context = {}) {
webSearchRead(model, domain, fields, kwargs = {}) {
validateArray("domain", domain);
validatePrimitiveList("fields", "string", fields);
return this.call(model, "web_search_read", [], { ...kwargs, domain, fields, context });
return this.call(model, "web_search_read", [], { ...kwargs, domain, fields });
}
write(model, ids, data, context) {
write(model, ids, data, kwargs = {}) {
validatePrimitiveList("ids", "number", ids);
validateObject("data", data);
return this.call(model, "write", [ids, data], { context });
return this.call(model, "write", [ids, data], kwargs);
}
}
@@ -413,8 +413,10 @@ export class GraphModel extends Model {
domain.arrayRepr,
measures,
groupBy.map((gb) => gb.spec),
{ lazy: false }, // what is this thing???
{ fill_temporal: true, ...this.searchParams.context }
{
lazy: false, // what is this thing???
context: { fill_temporal: true, ...this.searchParams.context },
}
)
.then((data) => {
const dataPoints = [];
@@ -752,7 +752,7 @@ export class PivotModel extends Model {
this.metaData = metaData;
} else {
metaData.activeMeasures.push(fieldName);
let config = { metaData, data: this.data };
const config = { metaData, data: this.data };
await this._loadData(config);
}
this.nextActiveMeasures = null;
@@ -955,14 +955,13 @@ export class PivotModel extends Model {
const groupDomain = this._getGroupDomain(group, config);
const measureSpecs = this._getMeasureSpecs(config);
const groupBy = rowGroupBy.concat(colGroupBy);
const options = { lazy: false };
const kwargs = { lazy: false, context: this.searchParams.context };
const subGroups = await this.orm.readGroup(
config.metaData.resModel,
groupDomain,
measureSpecs,
groupBy,
options,
this.searchParams.context
kwargs
);
return {
group: group,
+36 -45
View File
@@ -160,9 +160,9 @@ class RequestBatcherORM extends ORM {
* @param {object} context
* @returns {Promise<[number, string][]>}
*/
async nameGet(resModel, resIds, context) {
const pairs = await this.batch(resIds, ["name_get", resModel, context], (resIds) =>
super.nameGet(resModel, resIds, context)
async nameGet(resModel, resIds, kwargs) {
const pairs = await this.batch(resIds, ["name_get", resModel, kwargs], (resIds) =>
super.nameGet(resModel, resIds, kwargs)
);
return pairs.filter(([id]) => resIds.includes(id));
}
@@ -179,9 +179,9 @@ class RequestBatcherORM extends ORM {
* @param {string[]} fields
* @returns {Promise<Object[]>}
*/
async read(resModel, resIds, fields, kwargs, context) {
const records = await this.batch(resIds, ["read", resModel, fields, context], (resIds) =>
super.read(resModel, resIds, fields, {}, context)
async read(resModel, resIds, fields, kwargs) {
const records = await this.batch(resIds, ["read", resModel, fields, kwargs], (resIds) =>
super.read(resModel, resIds, fields, kwargs)
);
return records.filter((r) => resIds.includes(r.id));
}
@@ -195,9 +195,9 @@ class RequestBatcherORM extends ORM {
* @param {number[]} resIds
* @returns {Promise<boolean>}
*/
async unlink(resModel, resIds, context) {
return this.batch(resIds, ["unlink", resModel, context], (resIds) =>
super.unlink(resModel, resIds, context)
async unlink(resModel, resIds, kwargs) {
return this.batch(resIds, ["unlink", resModel, kwargs], (resIds) =>
super.unlink(resModel, resIds, kwargs)
);
}
@@ -1202,16 +1202,12 @@ export class Record extends DataPoint {
if (!fieldNames.length) {
return {};
}
const [serverValues] = await this.model.orm.read(
this.resModel,
[this.resId],
fieldNames,
{},
{
const [serverValues] = await this.model.orm.read(this.resModel, [this.resId], fieldNames, {
context: {
bin_size: true,
...this.context,
}
);
},
});
return this._parseServerValues(serverValues);
}
@@ -1259,6 +1255,7 @@ export class Record extends DataPoint {
const keys = Object.keys(changes);
const hasChanges = this.isVirtual || keys.length;
const shouldReload = hasChanges ? !options.noReload : false;
const context = this.context;
if (this.isVirtual) {
if (keys.length === 1 && keys[0] === "display_name") {
@@ -1270,7 +1267,7 @@ export class Record extends DataPoint {
);
this.resId = resId;
} else {
this.resId = await this.model.orm.create(this.resModel, [changes], this.context);
this.resId = await this.model.orm.create(this.resModel, [changes], { context });
}
delete this.virtualId;
this.data.id = this.resId;
@@ -1278,7 +1275,7 @@ export class Record extends DataPoint {
this.invalidateCache();
} else if (keys.length > 0) {
try {
await this.model.orm.write(this.resModel, [this.resId], changes, this.context);
await this.model.orm.write(this.resModel, [this.resId], changes, { context });
} catch (e) {
if (!this.isInEdition) {
await Promise.all([this.model.reloadRecords(this.resId), this.load()]);
@@ -1481,14 +1478,10 @@ class DynamicList extends DataPoint {
let resIds;
if (isSelected) {
if (this.isDomainSelected) {
resIds = await this.model.orm.search(
this.resModel,
this.domain,
{
limit: session.active_ids_limit,
},
this.context
);
resIds = await this.model.orm.search(this.resModel, this.domain, {
limit: session.active_ids_limit,
context: this.context,
});
} else {
resIds = this.selection.map((r) => r.resId);
}
@@ -1574,7 +1567,8 @@ class DynamicList extends DataPoint {
confirm: async () => {
const resIds = validSelection.map((r) => r.resId);
try {
await this.model.orm.write(this.resModel, resIds, changes, this.context);
const context = this.context;
await this.model.orm.write(this.resModel, resIds, changes, { context });
this.invalidateCache();
validSelection.forEach((record) => {
record.selected = false;
@@ -1706,7 +1700,7 @@ class DynamicList extends DataPoint {
// Read the actual values set by the server and update the records
const result = await this.model.keepLast.add(
this.model.orm.read(resModel, ids, [handleField], {}, this.context)
this.model.orm.read(resModel, ids, [handleField], { context: this.context })
);
for (const recordData of result) {
const record = records.find((r) => r.resId === recordData.id);
@@ -1924,18 +1918,22 @@ export class DynamicRecordList extends DynamicList {
* @returns {Promise<Record[]>}
*/
async _loadRecords() {
const options = {
const kwargs = {
limit: this.limit,
offset: this.offset,
order: orderByToString(this.orderBy),
count_limit: this.countLimit + 1,
context: {
bin_size: true,
...this.context,
},
};
if (this.loadedCount > this.limit) {
// This condition means that we are reloading a list of records
// that has been manually extended: we need to load exactly the
// same amount of records.
options.limit = this.loadedCount;
options.offset = 0;
kwargs.limit = this.loadedCount;
kwargs.offset = 0;
}
const { records: rawRecords, length } =
this.data ||
@@ -1943,11 +1941,7 @@ export class DynamicRecordList extends DynamicList {
this.resModel,
this.domain,
this.fieldNames,
options,
{
bin_size: true,
...this.context,
}
kwargs
));
const records = await Promise.all(
@@ -2243,8 +2237,8 @@ export class DynamicGroupList extends DynamicList {
expand: this.expand,
offset: this.offset,
limit: this.limit,
},
this.context
context: this.context,
}
);
this.count = length;
@@ -2788,12 +2782,9 @@ export class StaticList extends DataPoint {
}
// 2) fetch values for non loaded records
if (resIds.length) {
const result = await this.model.orm.read(
this.resModel,
resIds,
orderFieldNames,
this.context
);
const result = await this.model.orm.read(this.resModel, resIds, orderFieldNames, {
context: this.context,
});
for (const values of result) {
const resId = values.id;
recordValues[resId] = {};
@@ -279,7 +279,7 @@ export class ExportDataDialog extends Component {
resource: this.props.root.resModel,
},
],
this.props.context
{ context: this.props.context }
);
this.state.isEditingTemplate = false;
this.state.templateId = id;
@@ -316,7 +316,7 @@ export class ExportDataDialog extends Component {
text: this.env._t("Do you really want to delete this export template?"),
delete: async () => {
const id = Number(this.state.templateId);
await this.orm.unlink("ir.exports", [id], this.props.context);
await this.orm.unlink("ir.exports", [id], { context: this.props.context });
this.templates.splice(
this.templates.findIndex((i) => i.id === id),
1
@@ -52,7 +52,8 @@ QUnit.test("context is combined with user context in read request", async (asser
const [query, rpc] = makeFakeRPC();
serviceRegistry.add("rpc", rpc);
const env = await makeTestEnv();
await env.services.orm.read("my.model", [3], ["id", "descr"], {}, { earth: "isfucked" });
const context = { earth: "isfucked" };
await env.services.orm.read("my.model", [3], ["id", "descr"], { context });
assert.strictEqual(query.route, "/web/dataset/call_kw/my.model/read");
assert.deepEqual(query.params, {
args: [[3], ["id", "descr"]],
@@ -118,7 +119,8 @@ QUnit.test("nameGet method", async (assert) => {
const [query, rpc] = makeFakeRPC();
serviceRegistry.add("rpc", rpc);
const env = await makeTestEnv();
await env.services.orm.nameGet("sale.order", [2, 5], { complete: true });
const context = { complete: true };
await env.services.orm.nameGet("sale.order", [2, 5], { context });
assert.strictEqual(query.route, "/web/dataset/call_kw/sale.order/name_get");
assert.deepEqual(query.params, {
args: [[2, 5]],
@@ -139,13 +141,11 @@ QUnit.test("read method", async (assert) => {
const [query, rpc] = makeFakeRPC();
serviceRegistry.add("rpc", rpc);
const env = await makeTestEnv();
await env.services.orm.read(
"sale.order",
[2, 5],
["name", "amount"],
{ load: "none" },
{ abc: 3 }
);
const context = { abc: 3 };
await env.services.orm.read("sale.order", [2, 5], ["name", "amount"], {
load: "none",
context,
});
assert.strictEqual(query.route, "/web/dataset/call_kw/sale.order/read");
assert.deepEqual(query.params, {
args: [
@@ -8278,7 +8278,7 @@ QUnit.module("Views", (hooks) => {
assert.verifySteps([
`translate args ["partner",1,"foo"]`,
`translate context {"lang":"en","uid":7,"tz":"taht"}`,
`search_read translations args: [] ; kwargs: {"context":{"lang":"en","uid":7,"tz":"taht"},"domain":[["res_id","=",1],["name","=","partner_type,foo"],["lang","in",["CUST","CUST2"]]],"fields":["lang","src","value"]}`,
`search_read translations args: [] ; kwargs: {"domain":[["res_id","=",1],["name","=","partner_type,foo"],["lang","in",["CUST","CUST2"]]],"fields":["lang","src","value"],"context":{"lang":"en","uid":7,"tz":"taht"}}`,
]);
assert.containsOnce(target, ".modal");