From dcae390fafa88fbb663bd82d5df2eeda7f9944dc Mon Sep 17 00:00:00 2001 From: "David Monnom (moda)" Date: Tue, 26 Sep 2023 10:12:17 +0200 Subject: [PATCH] [IMP] point_of_sale, pos_self_order: save custom product attribute Previously, the custom value of an attribute was not saved in the database when selected via the point of sale or Self Order. The only way to see this value was via the product name. Now, this custom value is saved via the `product.attribute.custom.value` template, in order to follow the behavior of the Sale module. Others fix in this PR: - Prevent to pass to payment page when we are in mobile mode. Only kiosk mode is allowed to do so. - Hide "Modify" button in the cart page when the line is already sent to the server. - Make the language popup behaviour available in mobile mode too. closes odoo/odoo#136612 Signed-off-by: Joseph Caburnay (jcb) --- addons/point_of_sale/models/pos_config.py | 7 +- addons/point_of_sale/models/pos_order.py | 6 ++ addons/point_of_sale/models/product.py | 4 + .../screens/product_screen/product_screen.js | 3 +- .../point_of_sale/static/src/app/store/db.js | 14 ++- .../static/src/app/store/models.js | 95 +++++++++++++------ .../store/models/product_custom_attribute.js | 21 ++++ .../static/src/app/store/pos_store.js | 1 + .../product_configurator_popup.js | 14 ++- .../point_of_sale/static/tests/unit/utils.js | 1 + addons/pos_self_order/__manifest__.py | 1 + addons/pos_self_order/controllers/orders.py | 6 +- addons/pos_self_order/models/pos_order.py | 3 +- .../attribute_selection.js | 32 +++++-- .../attribute_selection.xml | 3 +- .../language_popup/language_popup.js | 2 +- .../static/src/app/models/line.js | 19 +++- .../static/src/app/models/order.js | 2 +- .../src/app/pages/cart_page/cart_page.js | 11 ++- .../src/app/pages/cart_page/cart_page.xml | 6 +- .../src/app/pages/combo_page/combo_page.js | 21 ++-- .../src/app/pages/combo_page/combo_page.xml | 2 +- .../app/pages/product_page/product_page.js | 9 +- .../static/src/app/self_order_service.js | 29 +++--- addons/pos_self_order/static/src/app/utils.js | 14 ++- 25 files changed, 239 insertions(+), 87 deletions(-) create mode 100644 addons/point_of_sale/static/src/app/store/models/product_custom_attribute.js diff --git a/addons/point_of_sale/models/pos_config.py b/addons/point_of_sale/models/pos_config.py index 00c22a7b8fc..22a27a3624c 100644 --- a/addons/point_of_sale/models/pos_config.py +++ b/addons/point_of_sale/models/pos_config.py @@ -719,8 +719,11 @@ class PosConfig(models.Model): """ self.env.cr.execute(query, params + [20000]) product_ids = self.env.cr.fetchall() - products = self.env['product.product'].search_read([('id', 'in', product_ids)], fields=fields) - return products + products = self.env['product.product'].search([('id', 'in', product_ids)]) + product_combo = products.filtered(lambda p: p['detailed_type'] == 'combo') + product_in_combo = product_combo.combo_ids.combo_line_ids.product_id + products_available = products | product_in_combo + return products_available.read(fields) def get_limited_partners_loading(self): self.env.cr.execute(""" diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index a5e2478f580..f77f7547a97 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -1179,6 +1179,10 @@ class PosOrderLine(models.Model): notice = fields.Char(string='Discount Notice') product_id = fields.Many2one('product.product', string='Product', domain=[('sale_ok', '=', True)], required=True, change_default=True) attribute_value_ids = fields.Many2many('product.template.attribute.value', string="Selected Attributes") + custom_attribute_value_ids = fields.One2many( + comodel_name='product.attribute.custom.value', inverse_name='pos_order_line_id', + string="Custom Values", + store=True, readonly=False) price_unit = fields.Float(string='Unit Price', digits=0) qty = fields.Float('Quantity', digits='Product Unit of Measure', default=1) price_subtotal = fields.Float(string='Subtotal w/o Tax', digits=0, @@ -1313,6 +1317,8 @@ class PosOrderLine(models.Model): return { 'id': orderline.id, 'qty': orderline.qty, + 'attribute_value_ids': orderline.attribute_value_ids.ids, + 'custom_attribute_value_ids': orderline.custom_attribute_value_ids.read(['id', 'name', 'custom_product_template_attribute_value_id', 'custom_value'], load=False), 'price_unit': orderline.price_unit, 'skip_change': orderline.skip_change, 'uuid': orderline.uuid, diff --git a/addons/point_of_sale/models/product.py b/addons/point_of_sale/models/product.py index b223e5e5abd..78caf1118ee 100644 --- a/addons/point_of_sale/models/product.py +++ b/addons/point_of_sale/models/product.py @@ -117,6 +117,10 @@ class ProductProduct(models.Model): 'variants': variant_list } +class ProductAttributeCustomValue(models.Model): + _inherit = "product.attribute.custom.value" + + pos_order_line_id = fields.Many2one('pos.order.line', string="PoS Order Line", ondelete='cascade') class UomCateg(models.Model): _inherit = 'uom.category' diff --git a/addons/point_of_sale/static/src/app/screens/product_screen/product_screen.js b/addons/point_of_sale/static/src/app/screens/product_screen/product_screen.js index fec1d3ec129..5d1882bee76 100644 --- a/addons/point_of_sale/static/src/app/screens/product_screen/product_screen.js +++ b/addons/point_of_sale/static/src/app/screens/product_screen/product_screen.js @@ -98,7 +98,6 @@ export class ProductScreen extends ControlButtonsMixin(Component) { this.numberBuffer.sendKey(buttonValue); } - selectLine(orderline) { this.numberBuffer.reset(); this.currentOrder.select_orderline(orderline); @@ -211,7 +210,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) { const { product_id = [], packaging = [] } = await this.orm.silent.call( "pos.session", "find_product_by_barcode", - [odoo.pos_session_id, code.base_code], + [odoo.pos_session_id, code.base_code] ); if (product_id.length) { await this.pos._addProducts(product_id, false); diff --git a/addons/point_of_sale/static/src/app/store/db.js b/addons/point_of_sale/static/src/app/store/db.js index f45345a2d5c..0cccdbd29c6 100644 --- a/addons/point_of_sale/static/src/app/store/db.js +++ b/addons/point_of_sale/static/src/app/store/db.js @@ -35,6 +35,9 @@ export class PosDB { this.product_by_category_id = {}; this.product_packaging_by_barcode = {}; + this.attribute_by_id = {}; + this.attribute_value_by_id = {}; + this.partner_sorted = []; this.partner_by_id = {}; this.partner_by_barcode = {}; @@ -52,6 +55,15 @@ export class PosDB { this.combo_line_by_id = {}; } + add_attributes(attribute) { + for (const attr of Object.values(attribute)) { + this.attribute_by_id[attr.id] = attr; + for (const val of attr.values) { + val.attribute_id = attr.id; + this.attribute_value_by_id[val.id] = val; + } + } + } /** * sets an uuid to prevent conflict in locally stored data between multiple PoS Configs. By * using the uuid of the config the local storage from other configs will not get effected nor @@ -340,7 +352,7 @@ export class PosDB { } } add_packagings(productPackagings) { - productPackagings?.forEach(productPackaging => { + productPackagings?.forEach((productPackaging) => { if (productPackaging.product_id[0] in this.product_by_id) { this.product_packaging_by_barcode[productPackaging.barcode] = productPackaging; } diff --git a/addons/point_of_sale/static/src/app/store/models.js b/addons/point_of_sale/static/src/app/store/models.js index 2aff5054ec5..c18b5969851 100644 --- a/addons/point_of_sale/static/src/app/store/models.js +++ b/addons/point_of_sale/static/src/app/store/models.js @@ -22,6 +22,7 @@ import { ComboConfiguratorPopup } from "./combo_configurator_popup/combo_configu import { ConfirmPopup } from "@point_of_sale/app/utils/confirm_popup/confirm_popup"; import { _t } from "@web/core/l10n/translation"; import { renderToElement } from "@web/core/utils/render"; +import { ProductCustomAttribute } from "./models/product_custom_attribute"; const { DateTime } = luxon; @@ -143,9 +144,10 @@ export class Product extends PosModel { } async getAddProductOptions(code) { let price_extra = 0.0; - let draftPackLotLines, description, packLotLinesToEdit, attribute_value_ids; + let draftPackLotLines, packLotLinesToEdit, attribute_value_ids; let quantity = 1; let comboLines = []; + let attribute_custom_values = {}; if (code && this.pos.db.product_packaging_by_barcode[code.code]) { quantity = this.pos.db.product_packaging_by_barcode[code.code].qty; @@ -165,8 +167,8 @@ export class Product extends PosModel { ); if (confirmed) { - description = payload.selected_attributes.join(", "); attribute_value_ids = payload.attribute_value_ids; + attribute_custom_values = payload.attribute_custom_values; price_extra += payload.price_extra; quantity = payload.quantity; } else { @@ -238,7 +240,7 @@ export class Product extends PosModel { return { draftPackLotLines, quantity, - description, + attribute_custom_values, price_extra, comboLines, attribute_value_ids, @@ -380,13 +382,13 @@ export class Orderline extends PosModel { options.quantity ? this.set_quantity(options.quantity) : this.set_quantity(1); this.discount = 0; this.note = ""; + this.custom_attribute_value_ids = []; this.hasChange = false; this.skipChange = false; this.discountStr = "0"; this.selected = false; - this.description = ""; this.price_extra = 0; - this.full_product_name = options.description || ""; + this.full_product_name = ""; this.id = orderline_id++; this.customerNote = this.customerNote || ""; this.saved_quantity = 0; @@ -404,10 +406,15 @@ export class Orderline extends PosModel { this.price_type = json.price_type; this.set_discount(json.discount); this.set_quantity(json.qty, "do not recompute unit price"); - this.set_description(json.description); this.attribute_value_ids = json.attribute_value_ids || []; this.set_price_extra(json.price_extra); - this.set_full_product_name(json.full_product_name); + this.custom_attribute_value_ids = json.custom_attribute_value_ids.map((attr) => { + if (attr.length > 0) { + attr = attr[2]; + } + return new ProductCustomAttribute(attr); + }); + this.set_full_product_name(); this.id = json.server_id || json.id || orderline_id++; orderline_id = Math.max(this.id + 1, orderline_id); var pack_lot_lines = json.pack_lot_ids; @@ -440,6 +447,7 @@ export class Orderline extends PosModel { } ); orderline.order = null; + orderline.custom_attribute_value_ids = this.custom_attribute_value_ids; orderline.quantity = this.quantity; orderline.quantityStr = this.quantityStr; orderline.discount = this.discount; @@ -555,14 +563,31 @@ export class Orderline extends PosModel { get_discount_str() { return this.discountStr; } - set_description(description) { - this.description = description || ""; - } set_price_extra(price_extra) { this.price_extra = parseFloat(price_extra) || 0.0; } - set_full_product_name(full_product_name) { - this.full_product_name = full_product_name || ""; + set_full_product_name() { + let attributeString = ""; + + if (this.attribute_value_ids && this.attribute_value_ids.length > 0) { + for (const valId of this.attribute_value_ids) { + const value = this.pos.db.attribute_value_by_id[valId]; + if (value.is_custom) { + const customValue = this.custom_attribute_value_ids.find( + (cus) => cus.custom_product_template_attribute_value_id == parseInt(valId) + ); + attributeString += customValue + ? `${value.name}: ${customValue.custom_value}, ` + : `${value.name}, `; + } else { + attributeString += `${value.name}, `; + } + } + attributeString = attributeString.slice(0, -2); + attributeString = `(${attributeString})`; + } + + this.full_product_name = `${this.product.display_name} ${attributeString}`; } get_price_extra() { return this.price_extra; @@ -696,14 +721,7 @@ export class Orderline extends PosModel { return this.product; } get_full_product_name() { - if (this.full_product_name) { - return this.full_product_name; - } - var full_name = this.product.display_name; - if (this.description) { - full_name += ` (${this.description})`; - } - return full_name; + return this.full_product_name || this.product.display_name; } // selects or deselects this orderline set_selected(selected) { @@ -746,7 +764,7 @@ export class Orderline extends PosModel { this.product.tracking === "lot" && (this.pos.picking_type.use_create_lots || this.pos.picking_type.use_existing_lots) ) && - this.description === orderline.description && + this.full_product_name === orderline.full_product_name && orderline.get_customer_note() === this.get_customer_note() && !this.refunded_orderline_id && !this.isPartOfCombo() && @@ -770,6 +788,7 @@ export class Orderline extends PosModel { return { uuid: this.uuid, skip_change: this.skipChange, + custom_attribute_value_ids: this.custom_attribute_value_ids.map((attr) => [0, 0, attr]), qty: this.get_quantity(), price_unit: this.get_unit_price(), price_subtotal: this.get_price_without_tax(), @@ -779,8 +798,7 @@ export class Orderline extends PosModel { tax_ids: [[6, false, this.get_applicable_taxes().map((tax) => tax.id)]], id: this.id, pack_lot_ids: pack_lot_ids, - description: this.description, - attribute_value_ids: this.attribute_value_ids, + attribute_value_ids: this.attribute_value_ids || [], full_product_name: this.get_full_product_name(), price_extra: this.get_price_extra(), customer_note: this.get_customer_note(), @@ -818,6 +836,7 @@ export class Orderline extends PosModel { customer_note: this.get_customer_note(), taxed_lst_unit_price: this.get_taxed_lst_unit_price(), isPartOfCombo: this.isPartOfCombo(), + custom_attribute_value_ids: this.custom_attribute_value_ids, unitDisplayPriceBeforeDiscount: this.getUnitDisplayPriceBeforeDiscount(), }; } @@ -1084,7 +1103,7 @@ export class Orderline extends PosModel { return !selectedLine ? false : last_id === selectedLine.cid; } set_customer_note(note) { - this.customerNote = note; + this.customerNote = note || ""; } get_customer_note() { return this.customerNote; @@ -2106,7 +2125,7 @@ export class Order extends PosModel { this.fix_tax_included_price(line); this.set_orderline_options(line, options); - + line.set_full_product_name(); var to_merge_orderline; for (var i = 0; i < this.orderlines.length; i++) { if (this.orderlines.at(i).can_be_merged_with(line) && options.merge !== false) { @@ -2195,9 +2214,29 @@ export class Order extends PosModel { orderline.set_discount(options.discount); } - if (options.description !== undefined) { - orderline.description += options.description; - orderline.attribute_value_ids = options.attribute_value_ids; + if (options.attribute_value_ids) { + orderline.attribute_value_ids = options.attribute_value_ids || []; + } + + if ( + options.attribute_custom_values && + Object.keys(options.attribute_custom_values).length > 0 + ) { + const customAttributeValues = []; + for (const [id, value] of Object.entries(options.attribute_custom_values)) { + if (!value) { + continue; + } + + customAttributeValues.push( + new ProductCustomAttribute({ + custom_product_template_attribute_value_id: parseInt(id), + custom_value: value, + }) + ); + } + + orderline.custom_attribute_value_ids = customAttributeValues; } if (options.extras !== undefined) { diff --git a/addons/point_of_sale/static/src/app/store/models/product_custom_attribute.js b/addons/point_of_sale/static/src/app/store/models/product_custom_attribute.js new file mode 100644 index 00000000000..eeafb12f92b --- /dev/null +++ b/addons/point_of_sale/static/src/app/store/models/product_custom_attribute.js @@ -0,0 +1,21 @@ +/** @odoo-module */ +import { Reactive } from "@web/core/utils/reactive"; + +export class ProductCustomAttribute extends Reactive { + constructor() { + super(); + this.setup(...arguments); + } + + setup({ id, name, custom_value, custom_product_template_attribute_value_id }) { + this.id = id; + this.name = name; + this.custom_value = custom_value; + this.custom_product_template_attribute_value_id = + custom_product_template_attribute_value_id; + } + + get value() { + return this.custom_value; + } +} 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 1d0b0e88cd0..73e7909c669 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 @@ -263,6 +263,7 @@ export class PosStore extends Reactive { this.pricelists = loadedData["product.pricelist"]; this.default_pricelist = loadedData["default_pricelist"]; this.currency = loadedData["res.currency"]; + this.db.add_attributes(loadedData["attributes_by_ptal_id"]); this.db.add_categories(loadedData["pos.category"]); this.db.add_combos(loadedData["pos.combo"]); this.db.add_combo_lines(loadedData["pos.combo.line"]); diff --git a/addons/point_of_sale/static/src/app/store/product_configurator_popup/product_configurator_popup.js b/addons/point_of_sale/static/src/app/store/product_configurator_popup/product_configurator_popup.js index 8dd95338a7c..bd1aa294a86 100644 --- a/addons/point_of_sale/static/src/app/store/product_configurator_popup/product_configurator_popup.js +++ b/addons/point_of_sale/static/src/app/store/product_configurator_popup/product_configurator_popup.js @@ -34,6 +34,7 @@ export class BaseProductAttribute extends Component { return { value, valueIds, + custom_value: this.state.custom_value, extra, }; } @@ -105,22 +106,27 @@ export class ProductConfiguratorPopup extends AbstractAwaitablePopup { } getPayload() { - const selected_attributes = []; + const attribute_custom_values = []; let attribute_value_ids = []; var price_extra = 0.0; const quantity = this.state.quantity; this.env.attribute_components.forEach((attribute_component) => { - const { value, valueIds, extra } = attribute_component.getValue(); - selected_attributes.push(value); + const { valueIds, extra, custom_value } = attribute_component.getValue(); attribute_value_ids.push(valueIds); + + if (custom_value) { + // for custom values, it will never be a multiple attribute + attribute_custom_values[valueIds[0]] = custom_value; + } + price_extra += extra; }); attribute_value_ids = attribute_value_ids.flat(); return { - selected_attributes, attribute_value_ids, + attribute_custom_values, price_extra, quantity, }; diff --git a/addons/point_of_sale/static/tests/unit/utils.js b/addons/point_of_sale/static/tests/unit/utils.js index 587c771b249..bfc155cd36c 100644 --- a/addons/point_of_sale/static/tests/unit/utils.js +++ b/addons/point_of_sale/static/tests/unit/utils.js @@ -15,6 +15,7 @@ registry.category("mock_server").add("pos.session/load_pos_data", async function "pos.combo.line": [...(this.models["pos.combo.line"]?.records || [])], "product.pricelist": [...(this.models["product.pricelist"]?.records || [])], "pos.payment.method": [...(this.models["pos.payment.method"]?.records || [])], + attributes_by_ptal_id: {}, "res.currency": { id: 1, name: "USD", diff --git a/addons/pos_self_order/__manifest__.py b/addons/pos_self_order/__manifest__.py index a9ced6b3bd9..ad3eaa4707c 100644 --- a/addons/pos_self_order/__manifest__.py +++ b/addons/pos_self_order/__manifest__.py @@ -58,6 +58,7 @@ "web/static/lib/bootstrap/js/dist/carousel.js", 'web/static/lib/bootstrap/js/dist/scrollspy.js', "pos_self_order/static/src/app/**/*", + "point_of_sale/static/src/app/store/models/product_custom_attribute.js", ], # Assets tests "pos_self_order.assets_tests": [ diff --git a/addons/pos_self_order/controllers/orders.py b/addons/pos_self_order/controllers/orders.py index 36646f46b39..4baf2672d06 100644 --- a/addons/pos_self_order/controllers/orders.py +++ b/addons/pos_self_order/controllers/orders.py @@ -241,6 +241,7 @@ class PosSelfOrderController(http.Controller): 'price_unit': child_price_unit, 'price_subtotal': child_tax_results.get('total_excluded'), 'price_subtotal_incl': child_tax_results.get('total_included'), + 'custom_attribute_value_ids': [[0, 0, cAttr] for cAttr in child.get('custom_attribute_value_ids')] if child.get('custom_attribute_value_ids') else [], 'id': child.get('id'), 'order_id': pos_order_id, 'tax_ids': product.taxes_id, @@ -248,7 +249,7 @@ class PosSelfOrderController(http.Controller): 'product_id': child.get('product_id'), 'qty': child.get('qty'), 'customer_note': child.get('customer_note'), - 'attribute_value_ids': child.get('selected_attributes') or [], + 'attribute_value_ids': child.get('attribute_value_ids') or [], 'full_product_name': child.get('full_product_name'), 'combo_parent_uuid': child.get('combo_parent_uuid'), 'combo_id': child.get('combo_id'), @@ -274,7 +275,8 @@ class PosSelfOrderController(http.Controller): 'product_id': line.get('product_id'), 'qty': line.get('qty'), 'customer_note': line.get('customer_note'), - 'attribute_value_ids': line.get('selected_attributes') or [], + 'attribute_value_ids': line.get('attribute_value_ids') or [], + 'custom_attribute_value_ids': [[0, 0, cAttr] for cAttr in line.get('custom_attribute_value_ids')] if line.get('custom_attribute_value_ids') else [], 'full_product_name': line.get('full_product_name'), 'combo_parent_uuid': line.get('combo_parent_uuid'), 'combo_id': line.get('combo_id'), diff --git a/addons/pos_self_order/models/pos_order.py b/addons/pos_self_order/models/pos_order.py index 127877e23bb..f7265eed186 100644 --- a/addons/pos_self_order/models/pos_order.py +++ b/addons/pos_self_order/models/pos_order.py @@ -103,7 +103,8 @@ class PosOrder(models.Model): "price_subtotal": line.price_subtotal, "price_subtotal_incl": line.price_subtotal_incl, "product_id": line.product_id.id, - "selected_attributes": line.attribute_value_ids.ids, + "attribute_value_ids": line.attribute_value_ids.ids, + "custom_attribute_value_ids": line.custom_attribute_value_ids.read(['id', 'name', 'custom_product_template_attribute_value_id', 'custom_value'], load=False), "uuid": line.uuid, "qty": line.qty, "customer_note": line.customer_note, diff --git a/addons/pos_self_order/static/src/app/components/attribute_selection/attribute_selection.js b/addons/pos_self_order/static/src/app/components/attribute_selection/attribute_selection.js index 536ca8ac9f4..e0c5513985b 100644 --- a/addons/pos_self_order/static/src/app/components/attribute_selection/attribute_selection.js +++ b/addons/pos_self_order/static/src/app/components/attribute_selection/attribute_selection.js @@ -1,6 +1,7 @@ /** @odoo-module */ import { Component, useState } from "@odoo/owl"; +import { ProductCustomAttribute } from "@point_of_sale/app/store/models/product_custom_attribute"; import { useSelfOrder } from "@pos_self_order/app/self_order_service"; import { attributeFlatter, attributeFormatter } from "@pos_self_order/app/utils"; @@ -18,7 +19,7 @@ export class AttributeSelection extends Component { editMode: false, showResume: false, showNext: false, - showCustomInput: false, // FIXME: need to implement this correctly here and in the PoS, maybe add a field ? + showCustomInput: false, }); this.selectedValues = useState(this.env.selectedValues); @@ -35,9 +36,16 @@ export class AttributeSelection extends Component { return this.props.product.attributes[this.state.currentAttribute]; } + get availableAttributeValue() { + return this.selfOrder.config.self_ordering_mode === "kiosk" + ? this.attribute.values.filter((a) => !a.is_custom) + : this.attribute.values; + } + get attributeSelected() { const flatAttribute = attributeFlatter(this.selectedValues); - return attributeFormatter(this.selfOrder.attributeById, flatAttribute); + const customAttribute = this.env.customValues; + return attributeFormatter(this.selfOrder.attributeById, flatAttribute, customAttribute); } initAttribute() { @@ -53,12 +61,18 @@ export class AttributeSelection extends Component { } for (const attribute of attributeSingle) { - if (this.selfOrder.editedLine) { - for (const value of attribute.values) { - if (this.selfOrder.editedLine.selected_attributes.includes(value.id)) { + for (const value of attribute.values) { + if (this.selfOrder.editedLine) { + if (this.selfOrder.editedLine.attribute_value_ids.includes(value.id)) { this.selectedValues[attribute.id] = value.id; } } + + if (value.is_custom) { + this.env.customValues[value.id] = new ProductCustomAttribute({ + custom_product_template_attribute_value_id: value.id, + }); + } } } @@ -67,12 +81,18 @@ export class AttributeSelection extends Component { for (const value of attrMulti.values) { if (this.selfOrder.editedLine) { - if (this.selfOrder.editedLine.selected_attributes.includes(value.id)) { + if (this.selfOrder.editedLine.attribute_value_ids.includes(value.id)) { this.selectedValues[attrMulti.id][value.id] = true; } } else { this.selectedValues[attrMulti.id][value.id] = false; } + + if (value.is_custom) { + this.env.customValues[value.id] = new ProductCustomAttribute({ + custom_product_template_attribute_value_id: value.id, + }); + } } } } diff --git a/addons/pos_self_order/static/src/app/components/attribute_selection/attribute_selection.xml b/addons/pos_self_order/static/src/app/components/attribute_selection/attribute_selection.xml index 1ffbd3da77e..a753fe29eb6 100644 --- a/addons/pos_self_order/static/src/app/components/attribute_selection/attribute_selection.xml +++ b/addons/pos_self_order/static/src/app/components/attribute_selection/attribute_selection.xml @@ -12,7 +12,7 @@
- +