diff options
| author | Pedram (PEBR) <pebr@odoo.com> | 2025-01-14 15:31:55 +0000 |
|---|---|---|
| committer | Andrea Grazioso (agr-odoo) <agr@odoo.com> | 2025-02-08 02:20:58 +0000 |
| commit | df9213eb44e83ea9f4c2f9bb83dae6baf36a0309 (patch) | |
| tree | 1737a536ae5c280aacccb729f4297fc52ff1e440 | |
| parent | 8e6800d365e53e909f533d9f9c6245698b965f99 (diff) | |
[FIX] point_of_sale: correctly connect loaded many2one fields
Before this commit, if a many2one field was loaded with its data,
it would not get connected. For example, in the Chilean localization,
the account_move is loaded when capturing an order, but it would not
get linked, causing an error.
opw-4479284
closes odoo/odoo#196994
X-original-commit: 86fd956e8828117c82d74baa0d7ae04cff93b745
Signed-off-by: David Monnom (moda) <moda@odoo.com>
Signed-off-by: Andrea Grazioso (agr) <agr@odoo.com>
4 files changed, 43 insertions, 19 deletions
diff --git a/addons/point_of_sale/static/src/app/models/related_models.js b/addons/point_of_sale/static/src/app/models/related_models.js index 1d66355cb27..8b0c2885c10 100644 --- a/addons/point_of_sale/static/src/app/models/related_models.js +++ b/addons/point_of_sale/static/src/app/models/related_models.js @@ -131,11 +131,12 @@ function processModelDefs(modelDefs) { } export class Base { - constructor({ models, records, model, dynamicModels }) { + constructor({ models, records, model, dynamicModels, baseData }) { this.models = models; this.records = records; this.model = model; this._dynamicModels = dynamicModels; + this.baseData = baseData; } /** * Called during instantiation when the instance is fully-populated with field values. @@ -290,7 +291,7 @@ export class Base { return this[cacheName]; } get raw() { - return this._raw ?? {}; + return this.baseData[this.id]; } } @@ -441,7 +442,13 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { const Model = modelClasses[model] || Base; const record = reactive( - new Model({ models, records, model: models[model], dynamicModels: opts.dynamicModels }) + new Model({ + models, + records, + model: models[model], + dynamicModels: opts.dynamicModels, + baseData: baseData[model], + }) ); const id = vals["id"]; record.id = id; @@ -454,7 +461,6 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { baseData[model][id] = vals; } - record._raw = baseData[model][id]; records[model].set(id, record); const fields = getFields(model); @@ -563,7 +569,6 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { continue; } else if (name === "id" && vals[name] !== record.id) { records[model].delete(record.id); - delete baseData[model][record.id]; for (const key of indexes[model] || []) { const keyVal = record.raw[key]; @@ -574,6 +579,8 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { } } + delete baseData[model][record.id]; + record.id = vals[name]; records[model].set(record.id, record); baseData[model][record.id] = vals; @@ -584,7 +591,7 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { const field = fields[name]; const comodelName = field.relation; - if (X2MANY_TYPES.has(field.type)) { + if (X2MANY_TYPES.has(field.type) && comodelName in models) { for (const command of vals[name]) { const [type, ...items] = command; if (type === "unlink") { @@ -613,7 +620,6 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { const existingRecords = items.filter((record) => exists(comodelName, record.id) ); - for (const record2 of [...linkedRecs]) { disconnect(field, record, record2); } @@ -622,7 +628,7 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { } } } - } else if (field.type === "many2one") { + } else if (field.type === "many2one" && comodelName in models) { if (vals[name]) { const id = vals[name]?.id || vals[name]; const exist = exists(comodelName, id); @@ -639,7 +645,9 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { const linkedRec = record[name]; disconnect(field, record, linkedRec); } - } else { + } + + if (!RELATION_TYPES.has(field.type)) { record[name] = vals[name]; } } @@ -806,7 +814,7 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { if (field.type === "many2one") { result[name] = record[name]?.id || record.raw[name] || false; } else if (X2MANY_TYPES.has(field.type)) { - const ids = [...record[name]].map((record) => record.id); + const ids = [...record[name]].map((record) => record.id).filter(Boolean); result[name] = ids.length ? ids : (!orm && record.raw[name]) || []; } else if (typeof record[name] === "object") { result[name] = JSON.stringify(record[name]); @@ -946,18 +954,34 @@ export function createRelatedModels(modelDefs, modelClasses = {}, opts = {}) { if (oldRecord && keepLocalRelation) { for (const [field, value] of Object.entries(record)) { - if (field === "id") { + const params = getFields(model)[field]; + if (field === "id" || !params) { continue; } - const params = getFields(model)[field]; - if (params && X2MANY_TYPES.has(params.type)) { + if (X2MANY_TYPES.has(params.type)) { value.push( ...oldRecord[field] .filter((r) => typeof r.id === "string") .map((r) => r.id) ); - record[field] = ["set", value]; + const existingRecords = value + .map((r) => models[params.relation]?.get(r)) + .filter(Boolean); + if (existingRecords.length) { + record[field] = [["set", ...existingRecords]]; + } + } else if ( + params.type === "many2one" && + value && + !exists(params.relation, value) + ) { + const key = `${params.relation}_${value}`; + if (!missingFields[key]) { + missingFields[key] = [[oldRecord, params]]; + } else { + missingFields[key].push([oldRecord, params]); + } } } diff --git a/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js b/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js index 6923e762700..aedb9c9f331 100644 --- a/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js +++ b/addons/point_of_sale/static/src/app/screens/payment_screen/payment_screen.js @@ -301,8 +301,8 @@ export class PaymentScreen extends Component { // 2. Invoice. if (this.shouldDownloadInvoice() && this.currentOrder.is_to_invoice()) { - if (this.currentOrder.account_move) { - await this.invoiceService.downloadPdf(this.currentOrder.account_move); + if (this.currentOrder.raw.account_move) { + await this.invoiceService.downloadPdf(this.currentOrder.raw.account_move); } else { throw { code: 401, diff --git a/addons/point_of_sale/static/src/app/store/pos_store.js b/addons/point_of_sale/static/src/app/store/pos_store.js index 676c7898711..e4ce9287b5a 100644 --- a/addons/point_of_sale/static/src/app/store/pos_store.js +++ b/addons/point_of_sale/static/src/app/store/pos_store.js @@ -1051,7 +1051,7 @@ export class PosStore extends Reactive { * @returns {name: string, id: int, role: string} */ get_cashier() { - this.user.role = this.user._raw.role; + this.user.role = this.user.raw.role; return this.user; } get_cashier_user_id() { diff --git a/addons/pos_online_payment/static/src/overrides/pos_overrides/components/payment_screen/payment_screen.js b/addons/pos_online_payment/static/src/overrides/pos_overrides/components/payment_screen/payment_screen.js index 4c9580b9af8..85e0034f693 100644 --- a/addons/pos_online_payment/static/src/overrides/pos_overrides/components/payment_screen/payment_screen.js +++ b/addons/pos_online_payment/static/src/overrides/pos_overrides/components/payment_screen/payment_screen.js @@ -230,13 +230,13 @@ patch(PaymentScreen.prototype, { } if (isInvoiceRequested) { - if (!orderJSON[0].account_move) { + if (!orderJSON[0].raw.account_move) { this.dialog.add(AlertDialog, { title: _t("Invoice could not be generated"), body: _t("The invoice could not be generated."), }); } else { - await this.invoiceService.downloadPdf(orderJSON[0].account_move); + await this.invoiceService.downloadPdf(orderJSON[0].raw.account_move); } } |
