From 11ba706626a9bbe5992129b1c32396f87669aeac Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Tue, 6 Feb 2024 16:50:53 +0100 Subject: [PATCH] [FIX] sale_product_configurator: custom attributes update Updates to existing product configurations with custom attributes were not correctly applied on configurator closure. This was probably caused by a recent update in the framework. Nevertheless, to solve the problem, this commit drops the use of custom code used only by the configurator to stick to the standard usage of magic commands. closes odoo/odoo#152934 Signed-off-by: Victor Feyens (vfe) --- .../static/src/js/sale_product_field.js | 19 ++++--- ...t_configurator_custom_value_update_tour.js | 56 +++++++++++++++++++ .../tests/test_sale_product_configurator.py | 10 ++++ 3 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 addons/test_sale_product_configurators/static/tests/tours/product_configurator_custom_value_update_tour.js diff --git a/addons/sale_product_configurator/static/src/js/sale_product_field.js b/addons/sale_product_configurator/static/src/js/sale_product_field.js index e9f6321f155..d886428a740 100644 --- a/addons/sale_product_configurator/static/src/js/sale_product_field.js +++ b/addons/sale_product_configurator/static/src/js/sale_product_field.js @@ -9,31 +9,32 @@ import { ProductConfiguratorDialog } from "./product_configurator_dialog/product async function applyProduct(record, product) { // handle custom values & no variants - const contextRecords = []; + const customAttributesCommands = [ + x2ManyCommands.set([]), // Command.clear isn't supported in static_list/_applyCommands + ]; for (const ptal of product.attribute_lines) { const selectedCustomPTAV = ptal.attribute_values.find( ptav => ptav.is_custom && ptal.selected_attribute_value_ids.includes(ptav.id) ); if (selectedCustomPTAV) { - contextRecords.push({ - default_custom_product_template_attribute_value_id: selectedCustomPTAV.id, - default_custom_value: ptal.customValue, - }); + customAttributesCommands.push( + x2ManyCommands.create(undefined, { + custom_product_template_attribute_value_id: [selectedCustomPTAV.id, "we don't care"], + custom_value: ptal.customValue, + }) + ); }; } - const proms = []; - proms.push(record.data.product_custom_attribute_value_ids.createAndReplace(contextRecords)); - const noVariantPTAVIds = product.attribute_lines.filter( ptal => ptal.create_variant === "no_variant" && ptal.attribute_values.length > 1 ).flatMap(ptal => ptal.selected_attribute_value_ids); - await Promise.all(proms); await record.update({ product_id: [product.id, product.display_name], product_uom_qty: product.quantity, product_no_variant_attribute_value_ids: [x2ManyCommands.set(noVariantPTAVIds)], + product_custom_attribute_value_ids: customAttributesCommands, }); }; diff --git a/addons/test_sale_product_configurators/static/tests/tours/product_configurator_custom_value_update_tour.js b/addons/test_sale_product_configurators/static/tests/tours/product_configurator_custom_value_update_tour.js new file mode 100644 index 00000000000..35d7e093079 --- /dev/null +++ b/addons/test_sale_product_configurators/static/tests/tours/product_configurator_custom_value_update_tour.js @@ -0,0 +1,56 @@ +/** @odoo-module **/ + +import { registry } from "@web/core/registry"; +import { stepUtils } from "@web_tour/tour_service/tour_utils"; +import configuratorTourUtils from "@test_sale_product_configurators/js/tour_utils"; + +registry.category("web_tour.tours").add('sale_product_configurator_custom_value_update_tour', { + url: '/web', + test: true, + steps: () => [stepUtils.showAppsMenuItem(), { + trigger: '.o_app[data-menu-xmlid="sale.sale_menu_root"]', +}, { + trigger: '.o_list_button_add', + extra_trigger: '.o_sale_order', +}, { + trigger: '.o_required_modifier[name=partner_id] input', + run: 'text Tajine Saucisse', +}, { + trigger: '.ui-menu-item > a:contains("Tajine Saucisse")', + auto: true, +}, { + trigger: 'a:contains("Add a product")' +}, { + trigger: 'div[name="product_template_id"] input', + run: 'text Custo', +}, { + trigger: 'ul.ui-autocomplete a:contains("Customizable Desk (TEST)")', +}, +...configuratorTourUtils.selectAndSetCustomAttribute("Customizable Desk (TEST)", "Legs", "Custom", "123"), +configuratorTourUtils.assertProductNameContains("Customizable Desk (TEST) (Custom, White)"), +{ + trigger: 'button:contains(Confirm)', +}, { + trigger: 'td.o_data_cell:contains("Legs: Custom: 123")', + isCheck: true, +}, +...stepUtils.saveForm(), +{ + trigger: 'td.o_data_cell:contains("Legs: Custom: 123")', + isCheck: true, +}, +{ + trigger: 'div[name="product_template_id"]', +}, { + trigger: '.fa-pencil', + extra_trigger: '.o_external_button', +}, +configuratorTourUtils.setCustomAttribute("Customizable Desk (TEST)", "Legs", "123456"), +{ + trigger: 'button:contains(Confirm)', +}, { + trigger: 'td.o_data_cell:contains("Legs: Custom: 123456")', + isCheck: true, +}, +...stepUtils.saveForm(), +]}); diff --git a/addons/test_sale_product_configurators/tests/test_sale_product_configurator.py b/addons/test_sale_product_configurators/tests/test_sale_product_configurator.py index f0720f14f5d..c9c327fbbe4 100644 --- a/addons/test_sale_product_configurators/tests/test_sale_product_configurator.py +++ b/addons/test_sale_product_configurators/tests/test_sale_product_configurator.py @@ -216,3 +216,13 @@ class TestProductConfiguratorUi(HttpCase, TestProductConfiguratorCommon): self.start_tour( "/web", 'sale_product_configurator_recursive_optional_products_tour', login='salesman' ) + + def test_product_configurator_update_custom_values(self): + self.start_tour( + "/web", 'sale_product_configurator_custom_value_update_tour', login='salesman', + ) + order = self.env['sale.order'].search([], order='id desc', limit=1) + self.assertEqual( + order.order_line.product_custom_attribute_value_ids.custom_value, + "123456", + )