diff --git a/addons/product_matrix/static/src/js/section_and_note_widget.js b/addons/product_matrix/static/src/js/section_and_note_widget.js index c59efc06e50..5d9499e52e0 100644 --- a/addons/product_matrix/static/src/js/section_and_note_widget.js +++ b/addons/product_matrix/static/src/js/section_and_note_widget.js @@ -131,6 +131,7 @@ SectionAndNoteFieldOne2Many.include({ }).open(); MatrixDialog.opened(function () { + MatrixDialog.$content.closest('.o_dialog_container').removeClass('d-none'); if (editedCellAttributes.length > 0) { var str = editedCellAttributes.toString(); MatrixDialog.$content.find('.o_matrix_input').filter((k, v) => v.attributes.ptav_ids.nodeValue === str)[0].focus(); diff --git a/addons/sale/controllers/variant.py b/addons/sale/controllers/variant.py index 3afdc19bd8d..694d8561040 100644 --- a/addons/sale/controllers/variant.py +++ b/addons/sale/controllers/variant.py @@ -23,6 +23,7 @@ class VariantController(http.Controller): combination = product.product_template_attribute_value_ids res.update({ 'is_combination_possible': product_template._is_combination_possible(combination=combination, parent_combination=parent_combination), + 'parent_exclusions': product_template._get_parent_attribute_exclusions(parent_combination=parent_combination) }) return res diff --git a/addons/sale/static/src/js/variant_mixin.js b/addons/sale/static/src/js/variant_mixin.js index 4447be0ada0..ab7aea9a0a7 100644 --- a/addons/sale/static/src/js/variant_mixin.js +++ b/addons/sale/static/src/js/variant_mixin.js @@ -49,29 +49,50 @@ var VariantMixin = { * @returns {Deferred} */ _getCombinationInfo: function (ev) { - var self = this; - if ($(ev.target).hasClass('variant_custom_value')) { return Promise.resolve(); } - var $parent = $(ev.target).closest('.js_product'); - var qty = $parent.find('input[name="add_qty"]').val(); - var combination = this.getSelectedVariantValues($parent); - var parentCombination = $parent.find('ul[data-attribute_exclusions]').data('attribute_exclusions').parent_combination; - var productTemplateId = parseInt($parent.find('.product_template_id').val()); + const $parent = $(ev.target).closest('.js_product'); + const combination = this.getSelectedVariantValues($parent); + let parentCombination; - self._checkExclusions($parent, combination); + if ($parent.hasClass('main_product')) { + parentCombination = $parent.find('ul[data-attribute_exclusions]').data('attribute_exclusions').parent_combination; + const $optProducts = $parent.parent().find(`[data-parent-unique-id='${$parent.data('uniqueId')}']`); + + for (const optionalProduct of $optProducts) { + const $currentOptionalProduct = $(optionalProduct); + const childCombination = this.getSelectedVariantValues($currentOptionalProduct); + const productTemplateId = parseInt($currentOptionalProduct.find('.product_template_id').val()); + ajax.jsonRpc(this._getUri('/sale/get_combination_info'), 'call', { + 'product_template_id': productTemplateId, + 'product_id': this._getProductId($currentOptionalProduct), + 'combination': childCombination, + 'add_qty': parseInt($currentOptionalProduct.find('input[name="add_qty"]').val()), + 'pricelist_id': this.pricelistId || false, + 'parent_combination': combination, + }).then((combinationData) => { + this._onChangeCombination(ev, $currentOptionalProduct, combinationData); + this._checkExclusions($currentOptionalProduct, childCombination, combinationData.parent_exclusions); + }); + } + } else { + parentCombination = this.getSelectedVariantValues( + $parent.parent().find('.js_product.in_cart.main_product') + ); + } return ajax.jsonRpc(this._getUri('/sale/get_combination_info'), 'call', { - 'product_template_id': productTemplateId, + 'product_template_id': parseInt($parent.find('.product_template_id').val()), 'product_id': this._getProductId($parent), 'combination': combination, - 'add_qty': parseInt(qty), + 'add_qty': parseInt($parent.find('input[name="add_qty"]').val()), 'pricelist_id': this.pricelistId || false, 'parent_combination': parentCombination, - }).then(function (combinationData) { - self._onChangeCombination(ev, $parent, combinationData); + }).then((combinationData) => { + this._onChangeCombination(ev, $parent, combinationData); + this._checkExclusions($parent, combination, combinationData.parent_exclusions); }); }, @@ -105,6 +126,7 @@ var VariantMixin = { .data('custom_product_template_attribute_value_id') !== parseInt(attributeValueId)) { $variantContainer.find('.variant_custom_value').remove(); + const previousCustomValue = $customInput.attr("previous_custom_value"); var $input = $('', { type: 'text', 'data-custom_product_template_attribute_value_id': attributeValueId, @@ -115,6 +137,9 @@ var VariantMixin = { $input.attr('placeholder', attributeValueName); $input.addClass('custom_value_radio'); $variantContainer.append($input); + if (previousCustomValue) { + $input.val(previousCustomValue); + } $input[0].focus(); } } else { @@ -153,8 +178,8 @@ var VariantMixin = { onChangeAddQuantity: function (ev) { var $parent; - if ($(ev.currentTarget).closest('.oe_optional_products_modal').length > 0){ - $parent = $(ev.currentTarget).closest('.oe_optional_products_modal'); + if ($(ev.currentTarget).closest('.oe_advanced_configurator_modal').length > 0){ + $parent = $(ev.currentTarget).closest('.oe_advanced_configurator_modal'); } else if ($(ev.currentTarget).closest('form').length > 0){ $parent = $(ev.currentTarget).closest('form'); } else { @@ -246,16 +271,10 @@ var VariantMixin = { /** * Will return the list of selected product.template.attribute.value ids - * For the modal, the "main product"'s attribute values are stored in the - * "unchanged_value_ids" data - * * @param {$.Element} $container the container to look into */ getSelectedVariantValues: function ($container) { var values = []; - var unchangedValues = $container - .find('div.oe_unchanged_value_ids') - .data('unchanged_value_ids') || []; var variantsValuesSelectors = [ 'input.js_variant_change:checked', @@ -265,7 +284,7 @@ var VariantMixin = { values.push(+$(el).val()); }); - return values.concat(unchangedValues); + return values; }, /** @@ -325,13 +344,18 @@ var VariantMixin = { * @private * @param {$.Element} $parent the parent container to apply exclusions * @param {Array} combination the selected combination of product attribute values + * @param {Array} parentExclusions the exclusions induced by the variant selection of the parent product + * For example chair cannot have steel legs if the parent Desk doesn't have steel legs */ - _checkExclusions: function ($parent, combination) { + _checkExclusions: function ($parent, combination, parentExclusions) { var self = this; var combinationData = $parent .find('ul[data-attribute_exclusions]') .data('attribute_exclusions'); + if (parentExclusions && combinationData.parent_exclusions) { + combinationData.parent_exclusions = parentExclusions; + } $parent .find('option, input, label, .o_variant_pills') .removeClass('css_not_available') @@ -565,6 +589,11 @@ var VariantMixin = { */ _toggleDisable: function ($parent, isCombinationPossible) { $parent.toggleClass('css_not_available', !isCombinationPossible); + if ($parent.hasClass('in_cart')) { + const primaryButton = $parent.parents('.modal-content').find('.modal-footer .btn-primary'); + primaryButton.prop('disabled', !isCombinationPossible); + primaryButton.toggleClass('disabled', !isCombinationPossible); + } }, /** * Updates the product image. diff --git a/addons/sale/static/src/scss/product_configurator.scss b/addons/sale/static/src/scss/product_configurator.scss index f3f2669bd97..84a4fa8ad47 100644 --- a/addons/sale/static/src/scss/product_configurator.scss +++ b/addons/sale/static/src/scss/product_configurator.scss @@ -218,16 +218,11 @@ label.css_attribute_color.css_not_available { } } -.modal.o_technical_modal .oe_optional_products_modal .btn.js_add_cart_json { +.modal.o_technical_modal .oe_advanced_configurator_modal .btn.js_add_cart_json { padding: 0.075rem 0.75rem; } .js_product { - &.in_cart { - .js_add_cart_variants { - display: none; - } - } .td-product_name { word-wrap: break-word; diff --git a/addons/sale_product_configurator/controllers/main.py b/addons/sale_product_configurator/controllers/main.py index d207d41694e..541246ba703 100644 --- a/addons/sale_product_configurator/controllers/main.py +++ b/addons/sale_product_configurator/controllers/main.py @@ -28,10 +28,10 @@ class ProductConfiguratorController(http.Controller): 'product_combination': product_combination }) - @http.route(['/sale_product_configurator/show_optional_products'], type='json', auth="user", methods=['POST']) - def show_optional_products(self, product_id, variant_values, pricelist_id, **kw): + @http.route(['/sale_product_configurator/show_advanced_configurator'], type='json', auth="user", methods=['POST']) + def show_advanced_configurator(self, product_id, variant_values, pricelist_id, **kw): pricelist = self._get_pricelist(pricelist_id) - return self._show_optional_products(product_id, variant_values, pricelist, False, **kw) + return self._show_advanced_configurator(product_id, variant_values, pricelist, False, **kw) @http.route(['/sale_product_configurator/optional_product_items'], type='json', auth="user", methods=['POST']) def optional_product_items(self, product_id, pricelist_id, **kw): @@ -56,14 +56,9 @@ class ProductConfiguratorController(http.Controller): 'add_qty': add_qty, }) - def _show_optional_products(self, product_id, variant_values, pricelist, handle_stock, **kw): + def _show_advanced_configurator(self, product_id, variant_values, pricelist, handle_stock, **kw): product = request.env['product.product'].browse(int(product_id)) combination = request.env['product.template.attribute.value'].browse(variant_values) - has_optional_products = product.optional_product_ids.filtered(lambda p: p._is_add_to_cart_possible(combination)) - - if not has_optional_products: - return False - add_qty = int(kw.get('add_qty', 1)) no_variant_attribute_values = combination.filtered( @@ -80,6 +75,7 @@ class ProductConfiguratorController(http.Controller): 'variant_values': variant_values, 'pricelist': pricelist, 'handle_stock': handle_stock, + 'already_configured': kw.get("already_configured", False) }) def _get_pricelist(self, pricelist_id, pricelist_fallback=False): diff --git a/addons/sale_product_configurator/static/src/js/product_configurator_controller.js b/addons/sale_product_configurator/static/src/js/product_configurator_controller.js index 008e6e65fea..6346adeba18 100644 --- a/addons/sale_product_configurator/static/src/js/product_configurator_controller.js +++ b/addons/sale_product_configurator/static/src/js/product_configurator_controller.js @@ -52,6 +52,9 @@ var ProductConfiguratorFormController = FormController.extend({ if (this.renderer.state.context.configuratorMode === 'options') { this.$el.closest('.modal').addClass('d-none'); } + + const renderSecondOnly = this.renderer.state.context.configuratorMode !== 'edit'; + this.$el.closest('.o_dialog_container').toggleClass('d-none', renderSecondOnly); }, //-------------------------------------------------------------------------- @@ -237,7 +240,9 @@ var ProductConfiguratorFormController = FormController.extend({ */ _onModalConfirm: function () { this._wasConfirmed = true; - this._addProducts(this.optionalProductsModal.getSelectedProducts()); + this.optionalProductsModal.getAndCreateSelectedProducts().then((products) => { + this._addProducts(products); + }); }, /** @@ -247,9 +252,9 @@ var ProductConfiguratorFormController = FormController.extend({ * @private */ _onModalClose: function () { - if (this.renderer.state.context.configuratorMode === 'options' + if (['options', 'add'].includes(this.renderer.state.context.configuratorMode) && this._wasConfirmed !== true) { - this.do_action({type: 'ir.actions.act_window_close'}); + this.do_action({type: 'ir.actions.act_window_close'}); } }, diff --git a/addons/sale_product_configurator/static/src/js/product_configurator_modal.js b/addons/sale_product_configurator/static/src/js/product_configurator_modal.js index b495100abe7..424b52418d6 100644 --- a/addons/sale_product_configurator/static/src/js/product_configurator_modal.js +++ b/addons/sale_product_configurator/static/src/js/product_configurator_modal.js @@ -58,7 +58,7 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, VariantMixin, { this.container = parent; this.pricelistId = params.pricelistId; this.previousModalHeight = params.previousModalHeight; - this.dialogClass = 'oe_optional_products_modal'; + this.dialogClass = 'oe_advanced_configurator_modal'; this._productImageField = 'image_128'; this._opened.then(function () { @@ -73,7 +73,7 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, VariantMixin, { willStart: function () { var self = this; - var uri = this._getUri("/sale_product_configurator/show_optional_products"); + var uri = this._getUri("/sale_product_configurator/show_advanced_configurator"); var getModalContent = ajax.jsonRpc(uri, 'call', { product_id: self.rootProduct.product_id, variant_values: self.rootProduct.variant_values, @@ -178,18 +178,27 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, VariantMixin, { * {Array} no_variant_attribute_values * @public */ - getSelectedProducts: function () { + getAndCreateSelectedProducts: async function () { var self = this; - var products = [this.rootProduct]; - this.$modal.find('.js_product.in_cart:not(.main_product)').each(function () { - var $item = $(this); + const products = []; + let productCustomVariantValues; + let noVariantAttributeValues; + for (const product of self.$modal.find('.js_product.in_cart')) { + var $item = $(product); var quantity = parseInt($item.find('input[name="add_qty"]').val(), 10); - var parentUniqueId = this.dataset.parentUniqueId; - var uniqueId = this.dataset.uniqueId; - var productCustomVariantValues = self.getCustomVariantValues($(this)); - var noVariantAttributeValues = self.getNoVariantAttributeValues($(this)); + var parentUniqueId = product.dataset.parentUniqueId; + var uniqueId = product.dataset.uniqueId; + productCustomVariantValues = self.getCustomVariantValues($item); + noVariantAttributeValues = self.getNoVariantAttributeValues($item); + + const productID = await self.selectOrCreateProduct( + $item, + parseInt($item.find('input.product_id').val(), 10), + parseInt($item.find('input.product_template_id').val(), 10), + true + ); products.push({ - 'product_id': parseInt($item.find('input.product_id').val(), 10), + 'product_id': productID, 'product_template_id': parseInt($item.find('input.product_template_id').val(), 10), 'quantity': quantity, 'parent_unique_id': parentUniqueId, @@ -197,8 +206,7 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, VariantMixin, { 'product_custom_attribute_values': productCustomVariantValues, 'no_variant_attribute_values': noVariantAttributeValues }); - }); - + } return products; }, @@ -229,14 +237,18 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, VariantMixin, { text: $productDescription.text() })); - $.each(this.rootProduct.product_custom_attribute_values, function (){ - $updatedDescription.append($('
').text('image variant option src changed').insertAfter('.oe_optional_products_modal .js_product:eq(1) .product-name'); + $('
').text('image variant option src changed').insertAfter('.oe_advanced_configurator_modal .js_product:eq(1) .product-name'); } } }, { - extra_trigger: '.oe_optional_products_modal .js_product:eq(1) div:contains("image variant option src changed")', - trigger: '.oe_optional_products_modal .js_product:eq(1) input[data-value_name="Steel"]', + extra_trigger: '.oe_advanced_configurator_modal .js_product:eq(1) div:contains("image variant option src changed")', + trigger: '.oe_advanced_configurator_modal .js_product:eq(1) input[data-value_name="Steel"]', }, { trigger: 'button span:contains(Confirm)', - extra_trigger: '.oe_optional_products_modal', + extra_trigger: '.oe_advanced_configurator_modal', run: 'click' }, { trigger: 'td.o_data_cell:contains("Customizable Desk (TEST) (Custom, White, PAV9, PAV5, PAV1)")', diff --git a/addons/sale_product_configurator/static/tests/tours/product_configurator_edition_ui.js b/addons/sale_product_configurator/static/tests/tours/product_configurator_edition_ui.js index dc7663d6417..8f908ef9fcb 100644 --- a/addons/sale_product_configurator/static/tests/tours/product_configurator_edition_ui.js +++ b/addons/sale_product_configurator/static/tests/tours/product_configurator_edition_ui.js @@ -31,22 +31,24 @@ tour.register('sale_product_configurator_edition_tour', { trigger: 'ul.ui-autocomplete a:contains("Customizable Desk (TEST)")', run: 'click' }, { - trigger: '.configurator_container span:contains("Steel")', + trigger: '.main_product span:contains("Steel")', run: function () { $('input.product_id').change(function () { - $('.o_sale_product_configurator_add').attr('request_count', 1); + $('.show .modal-footer .btn-primary').attr('request_count', 1); }); } }, { - trigger: '.configurator_container span:contains("Aluminium")' + trigger: '.main_product span:contains("Aluminium")' }, { - trigger: '.o_sale_product_configurator_add[request_count="1"]', + trigger: '.btn-primary[request_count="1"]', + extra_trigger: '.show .modal-footer', run: function (){} // used to sync with "get_combination_info" completion }, { - trigger: '.o_sale_product_configurator_add:not(.disabled)' + trigger: '.btn-primary:not(.disabled)', + extra_trigger: '.show .modal-footer', }, { trigger: 'button span:contains(Confirm)', - extra_trigger: '.oe_optional_products_modal', + extra_trigger: '.oe_advanced_configurator_modal', run: 'click' }, { trigger: 'td.o_data_cell:contains("Customizable Desk (TEST) (Aluminium, White)")', diff --git a/addons/sale_product_configurator/static/tests/tours/product_configurator_optional_products_ui.js b/addons/sale_product_configurator/static/tests/tours/product_configurator_optional_products_ui.js index c566ce5b1da..e1ae2f75948 100644 --- a/addons/sale_product_configurator/static/tests/tours/product_configurator_optional_products_ui.js +++ b/addons/sale_product_configurator/static/tests/tours/product_configurator_optional_products_ui.js @@ -30,8 +30,6 @@ tour.register('sale_product_configurator_optional_products_tour', { }, { trigger: 'ul.ui-autocomplete a:contains("Customizable Desk (TEST)")', run: 'click' -}, { - trigger: '.o_sale_product_configurator_add' }, { trigger: 'tr:has(.td-product_name:contains("Office Chair Black")) .js_add', }, { @@ -52,7 +50,7 @@ tour.register('sale_product_configurator_optional_products_tour', { trigger: 'tr:has(.td-product_name:contains("Conference Chair")) + tr:has(.td-product_name:contains("Chair floor protection"))' }, { trigger: 'button span:contains(Confirm)', - extra_trigger: '.oe_optional_products_modal', + extra_trigger: '.oe_advanced_configurator_modal', run: 'click' }, { trigger: 'tr:has(td.o_data_cell:contains("Customizable Desk")) td.o_data_cell:contains("2.0")', diff --git a/addons/sale_product_configurator/static/tests/tours/product_configurator_pricelist_ui.js b/addons/sale_product_configurator/static/tests/tours/product_configurator_pricelist_ui.js index af97bf1f7c7..532e806a536 100644 --- a/addons/sale_product_configurator/static/tests/tours/product_configurator_pricelist_ui.js +++ b/addons/sale_product_configurator/static/tests/tours/product_configurator_pricelist_ui.js @@ -61,23 +61,20 @@ tour.stepUtils.showAppsMenuItem(), content: "check price for 2", trigger: 'span.oe_currency_value:contains("600.00")', run: function () {} // check price (pricelist has discount for 2) -}, { - content: "click add", - trigger: '.o_sale_product_configurator_add:not(.disabled)' }, { content: "check we are on the add modal", trigger: '.td-product_name:contains("Customizable Desk (TEST) (Steel, White)")', - extra_trigger: '.oe_optional_products_modal', + extra_trigger: '.oe_advanced_configurator_modal', run: 'click' }, { content: "add conference chair", trigger: '.js_product:has(strong:contains(Conference Chair)) .js_add', - extra_trigger: '.oe_optional_products_modal .js_product:has(strong:contains(Conference Chair))', + extra_trigger: '.oe_advanced_configurator_modal .js_product:has(strong:contains(Conference Chair))', run: 'click' }, { content: "add chair floor protection", trigger: '.js_product:has(strong:contains(Chair floor protection)) .js_add', - extra_trigger: '.oe_optional_products_modal .js_product:has(strong:contains(Chair floor protection))', + extra_trigger: '.oe_advanced_configurator_modal .js_product:has(strong:contains(Chair floor protection))', run: 'click' }, { content: "verify configurator final price", // tax excluded @@ -85,7 +82,7 @@ tour.stepUtils.showAppsMenuItem(), }, { content: "add to SO", trigger: 'button span:contains(Confirm)', - extra_trigger: '.oe_optional_products_modal', + extra_trigger: '.oe_advanced_configurator_modal', run: 'click' }, { content: "verify SO final price excluded", diff --git a/addons/sale_product_configurator/static/tests/tours/product_configurator_single_custom_attribute_ui.js b/addons/sale_product_configurator/static/tests/tours/product_configurator_single_custom_attribute_ui.js index 8b1db607579..aab9074d415 100644 --- a/addons/sale_product_configurator/static/tests/tours/product_configurator_single_custom_attribute_ui.js +++ b/addons/sale_product_configurator/static/tests/tours/product_configurator_single_custom_attribute_ui.js @@ -32,26 +32,24 @@ tour.register('sale_product_configurator_single_custom_attribute_tour', { trigger: 'ul.ui-autocomplete a:contains("Customizable Desk (TEST)")', run: 'click' }, { - trigger: '.configurator_container span:contains("Aluminium")', + trigger: '.oe_advanced_configurator_modal span:contains("Aluminium")', run: function () { // used to check that the radio is NOT rendered - if ($('.configurator_container ul[data-attribute_id].d-none input[data-value_name="single product attribute value"]').length === 1) { - $('.configurator_container').addClass('tour_success'); + if ($('.oe_advanced_configurator_modal ul[data-attribute_id].d-none input[data-value_name="single product attribute value"]').length === 1) { + $('.oe_advanced_configurator_modal').addClass('tour_success'); } } }, { - trigger: '.configurator_container.tour_success', + trigger: '.oe_advanced_configurator_modal.tour_success', run: function () { //check } }, { - trigger: '.configurator_container .variant_custom_value', + trigger: '.oe_advanced_configurator_modal .variant_custom_value', run: 'text great single custom value' -}, { - trigger: '.o_sale_product_configurator_add', }, { trigger: 'button span:contains(Confirm)', - extra_trigger: '.oe_optional_products_modal', + extra_trigger: '.oe_advanced_configurator_modal', run: 'click' }, { trigger: 'td.o_data_cell:contains("single product attribute value: great single custom value")', diff --git a/addons/sale_product_configurator/static/tests/tours/product_configurator_ui.js b/addons/sale_product_configurator/static/tests/tours/product_configurator_ui.js index fad1fbd3309..4eb22b94063 100644 --- a/addons/sale_product_configurator/static/tests/tours/product_configurator_ui.js +++ b/addons/sale_product_configurator/static/tests/tours/product_configurator_ui.js @@ -35,10 +35,10 @@ tour.register('sale_product_configurator_tour', { trigger: 'ul.ui-autocomplete a:contains("Customizable Desk (TEST)")', run: 'click' }, { - trigger: '.configurator_container span:contains("Steel")', + trigger: '.main_product span:contains("Steel")', run: function () {}, }, { - trigger: '.configurator_container span:contains("Aluminium")', + trigger: '.main_product span:contains("Aluminium")', run: 'click' }, { trigger: 'span.oe_currency_value:contains("800.40")', @@ -46,26 +46,24 @@ tour.register('sale_product_configurator_tour', { }, { trigger: 'input[data-value_name="Black"]' }, { - trigger: '.o_sale_product_configurator_add.disabled' + trigger: '.btn-primary.disabled', + extra_trigger: '.show .modal-footer' }, { trigger: 'input[data-value_name="White"]' }, { - trigger: '.o_sale_product_configurator_add:not(.disabled)' + trigger: '.btn-primary:not(.disabled)', + extra_trigger: '.show .modal-footer' }, { - trigger: 'span:contains("Aluminium")', - extra_trigger: '.oe_optional_products_modal', - run: 'click' -}, { - trigger: '.js_product:has(strong:contains(Conference Chair)) .js_add', - extra_trigger: '.oe_optional_products_modal .js_product:has(strong:contains(Conference Chair))', + trigger: 'span:contains("Aluminium"):eq(1)', + extra_trigger: '.oe_advanced_configurator_modal', run: 'click' }, { trigger: '.js_product:has(strong:contains(Chair floor protection)) .js_add', - extra_trigger: '.oe_optional_products_modal .js_product:has(strong:contains(Chair floor protection))', + extra_trigger: '.oe_advanced_configurator_modal', run: 'click' }, { trigger: 'button span:contains(Confirm)', - extra_trigger: '.oe_optional_products_modal', + extra_trigger: '.oe_advanced_configurator_modal', id: "quotation_product_selected", run: 'click' }, diff --git a/addons/sale_product_configurator/tests/test_sale_product_configurator_ui.py b/addons/sale_product_configurator/tests/test_sale_product_configurator_ui.py index 427a7dcdb9f..95ab4df737a 100644 --- a/addons/sale_product_configurator/tests/test_sale_product_configurator_ui.py +++ b/addons/sale_product_configurator/tests/test_sale_product_configurator_ui.py @@ -5,7 +5,7 @@ import odoo.tests from .common import TestProductConfiguratorCommon -@odoo.tests.tagged('post_install', '-at_install') +@odoo.tests.tagged('post_install', '-at_install', 'kzh') class TestUi(odoo.tests.HttpCase, TestProductConfiguratorCommon): def setUp(self): diff --git a/addons/sale_product_configurator/views/templates.xml b/addons/sale_product_configurator/views/templates.xml index 215d6d49590..a5e04bbb18d 100644 --- a/addons/sale_product_configurator/views/templates.xml +++ b/addons/sale_product_configurator/views/templates.xml @@ -32,6 +32,8 @@ +
Option not available
').text('image variant option src changed').insertAfter('.oe_optional_products_modal .js_product:eq(1) .product-name'); + $('
').text('image variant option src changed').insertAfter('.oe_advanced_configurator_modal .js_product:eq(1) .product-name'); } } }, { - extra_trigger: '.oe_optional_products_modal .js_product:eq(1) div:contains("image variant option src changed")', - trigger: '.oe_optional_products_modal .js_product:eq(1) input[data-value_name="Steel"]', -}, { - trigger: 'li.js_attribute_value span:contains(Aluminium)', - extra_trigger: '.oe_optional_products_modal', - run: 'click' + extra_trigger: '.oe_advanced_configurator_modal .js_product:eq(1) div:contains("image variant option src changed")', + trigger: '.oe_advanced_configurator_modal .js_product:eq(1) input[data-value_name="Steel"]', }, { trigger: '.oe_price span:contains(22.90)', run: function (){}, // check }, { - trigger: '.oe_optional_products_modal .js_product:has(strong:contains(Conference Chair)) .js_add', - extra_trigger: '.oe_optional_products_modal .js_product:has(strong:contains(Conference Chair))', + trigger: '.oe_advanced_configurator_modal .js_product:has(strong:contains(Conference Chair)) .js_add', + extra_trigger: '.oe_advanced_configurator_modal .js_product:has(strong:contains(Conference Chair))', run: 'click' }, { - trigger: '.oe_optional_products_modal .js_product:has(strong:contains(Chair floor protection)) .js_add', - extra_trigger: '.oe_optional_products_modal .js_product:has(strong:contains(Chair floor protection))', + trigger: '.oe_advanced_configurator_modal .js_product:has(strong:contains(Chair floor protection)) .js_add', + extra_trigger: '.oe_advanced_configurator_modal .js_product:has(strong:contains(Chair floor protection))', run: 'click' }, { - trigger: 'span:contains(1,269.80)', + trigger: 'span:contains(1,257.00)', run: function (){}, // check }, { trigger: 'button:has(span:contains(Proceed to Checkout))',