', {
+ text: this.attribute_value_name + ': ' + this.custom_value
+ }));
+ });
+
+ $.each(noVariantAttributeValues, function (){
+ if (this.is_custom !== 'True'){
+ $customAttributeValuesDescription.append($('
', {
+ text: this.attribute_name + ': ' + this.attribute_value_name
+ }));
+ }
+ });
+
+ $productDescription.append($customAttributeValuesDescription);
+ }
+
+ // place it after its parent and its parent options
+ var $tmpOptionParent = $optionParent;
+ while ($tmpOptionParent.length) {
+ $optionParent = $tmpOptionParent;
+ $tmpOptionParent = $modal.find('tr.js_product.in_cart[data-parent-unique-id="' + $optionParent[0].dataset.uniqueId + '"]').last();
+ }
+ $optionParent.after($parent);
+ $parent.addClass('in_cart');
+
+ this.selectOrCreateProduct(
+ $parent,
+ $parent.find('.product_id').val(),
+ productTemplateId,
+ true
+ ).then(function (productId) {
+ $parent.find('.product_id').val(productId);
+
+ ajax.jsonRpc(self._getUri("/sale_product_configurator/optional_product_items"), 'call', {
+ 'product_id': productId,
+ 'pricelist_id': self.pricelistId || false,
+ }).then(function (addedItem) {
+ var $addedItem = $(addedItem);
+ $modal.find('tr:last').after($addedItem);
+
+ self.$el.find('input[name="add_qty"]').trigger('change');
+ self.triggerVariantChange($addedItem);
+
+ // add a unique id to the new products
+ var parentUniqueId = $parent[0].dataset.uniqueId;
+ var parentQty = $parent.find('input[name="add_qty"]').val();
+ $addedItem.filter('.js_product').each(function () {
+ var $el = $(this);
+ var uniqueId = self._getUniqueId(this);
+ this.dataset.uniqueId = uniqueId;
+ this.dataset.parentUniqueId = parentUniqueId;
+ $el.find('input[name="add_qty"]').val(parentQty);
+ });
+
+ if ($selectOptionsText.nextAll('.js_product').length === 0) {
+ // no more optional products to select -> hide the header
+ $selectOptionsText.hide();
+ }
+ });
+ });
+ },
+
+ /**
+ * @private
+ * @see _onAddOrRemoveOption
+ * @param {$.Element} $modal
+ * @param {$.Element} $parent
+ */
+ _onRemoveOption: function ($modal, $parent) {
+ // restore attribute values selection
+ var uniqueId = $parent[0].dataset.parentUniqueId;
+ var qty = $modal.find('tr.js_product.in_cart[data-unique-id="' + uniqueId + '"]').find('input[name="add_qty"]').val();
+ $parent.removeClass('in_cart');
+ $parent.find('.td-product_name').attr("colspan", 2);
+ $parent.find('.td-qty').addClass('d-none');
+ $parent.find('input[name="add_qty"]').val(qty);
+ $parent.find('.custom_attribute_values_description').remove();
+
+ $modal.find('.o_select_options').show();
+
+ var productUniqueId = $parent[0].dataset.uniqueId;
+ this._removeOptionOption($modal, productUniqueId);
+
+ $modal.find('tr:last').after($parent);
+ },
+
+ /**
+ * If the removed product had optional products, remove them as well
+ *
+ * @private
+ * @param {$.Element} $modal
+ * @param {integer} optionUniqueId The removed optional product id
+ */
+ _removeOptionOption: function ($modal, optionUniqueId) {
+ var self = this;
+ $modal.find('tr.js_product[data-parent-unique-id="' + optionUniqueId + '"]').each(function () {
+ var uniqueId = this.dataset.uniqueId;
+ $(this).remove();
+ self._removeOptionOption($modal, uniqueId);
+ });
+ },
+ /**
+ * @override
+ */
+ _onChangeCombination: function (ev, $parent, combination) {
+ $parent
+ .find('.td-product_name .product-name')
+ .first()
+ .text(combination.display_name);
+
+ VariantMixin._onChangeCombination.apply(this, arguments);
+
+ this._computePriceTotal();
+ },
+ /**
+ * Update price total when the quantity of a product is changed
+ *
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onChangeQuantity: function (ev) {
+ var $product = $(ev.target.closest('tr.js_product'));
+ var qty = parseFloat($(ev.currentTarget).val());
+
+ var uniqueId = $product[0].dataset.uniqueId;
+ this.$el.find('tr.js_product:not(.in_cart)[data-parent-unique-id="' + uniqueId + '"] input[name="add_qty"]').each(function () {
+ $(this).val(qty);
+ });
+
+ if (this._triggerPriceUpdateOnChangeQuantity()) {
+ this.onChangeAddQuantity(ev);
+ }
+ if ($product.hasClass('main_product')) {
+ this.rootProduct.quantity = qty;
+ }
+ this.trigger('update_quantity', this.rootProduct.quantity);
+ this._computePriceTotal();
+ },
+
+ /**
+ * When a product is added or when the quantity is changed,
+ * we need to refresh the total price row
+ */
+ _computePriceTotal: function () {
+ if (this.$modal.find('.js_price_total').length) {
+ var price = 0;
+ this.$modal.find('.js_product.in_cart').each(function () {
+ var quantity = parseFloat($(this).find('input[name="add_qty"]').first().val().replace(',', '.') || 1);
+ price += parseFloat($(this).find('.js_raw_price').html()) * quantity;
+ });
+
+ this.$modal.find('.js_price_total .oe_currency_value').text(
+ this._priceToStr(parseFloat(price))
+ );
+ }
+ },
+
+ /**
+ * Extension point for website_sale
+ *
+ * @private
+ */
+ _triggerPriceUpdateOnChangeQuantity: function () {
+ return true;
+ },
+ /**
+ * Returns a unique id for `$el`.
+ *
+ * @private
+ * @param {Element} el
+ * @returns {integer}
+ */
+ _getUniqueId: function (el) {
+ if (!el.dataset.uniqueId) {
+ el.dataset.uniqueId = parseInt(_.uniqueId(), 10);
+ }
+ return el.dataset.uniqueId;
+ },
+});
diff --git a/addons/website_sale_product_configurator/static/src/js/website_sale_options.js b/addons/website_sale_product_configurator/static/src/js/website_sale_options.js
index 890abd554cc..0789dea0e3d 100644
--- a/addons/website_sale_product_configurator/static/src/js/website_sale_options.js
+++ b/addons/website_sale_product_configurator/static/src/js/website_sale_options.js
@@ -3,7 +3,7 @@
import ajax from "web.ajax";
import core from "web.core";
import publicWidget from "web.public.widget";
-import { OptionalProductsModal } from "@sale_product_configurator/js/product_configurator_modal";
+import { OptionalProductsModal } from "@website_sale_product_configurator/js/sale_product_configurator_modal";
import "website_sale.website_sale";
import wsUtils from "website_sale.utils";
diff --git a/addons/sale_product_configurator/views/templates.xml b/addons/website_sale_product_configurator/views/templates.xml
similarity index 95%
rename from addons/sale_product_configurator/views/templates.xml
rename to addons/website_sale_product_configurator/views/templates.xml
index 3872c8d859f..c669fc401c1 100644
--- a/addons/sale_product_configurator/views/templates.xml
+++ b/addons/website_sale_product_configurator/views/templates.xml
@@ -2,7 +2,7 @@
-
+
@@ -38,7 +38,7 @@
-
+
@@ -57,7 +57,7 @@
}'/>
-
+
This combination does not exist.
@@ -118,7 +118,7 @@
-
+
@@ -132,7 +132,7 @@
-
+
|
Available Options: |
-
+
@@ -196,12 +196,12 @@
-
+
|
-
+
|
-
+
not request.is_frontend or (request.is_frontend and is_view_active('website_sale.product_quantity'))
-
+
not request.is_frontend or (request.is_frontend and is_view_active('website_sale.product_quantity'))
diff --git a/addons/website_sale_stock/static/src/js/variant_mixin.js b/addons/website_sale_stock/static/src/js/variant_mixin.js
index e2eca69a5ce..672a211acf3 100644
--- a/addons/website_sale_stock/static/src/js/variant_mixin.js
+++ b/addons/website_sale_stock/static/src/js/variant_mixin.js
@@ -1,7 +1,7 @@
/** @odoo-module alias=website_sale_stock.VariantMixin **/
import {Markup} from "web.utils";
-import VariantMixin from "sale.VariantMixin";
+import VariantMixin from "website_sale.SaleVariantMixin";
import publicWidget from "web.public.widget";
import core from "web.core";
var QWeb = core.qweb;
diff --git a/addons/website_sale_stock_product_configurator/views/product_configurator_templates.xml b/addons/website_sale_stock_product_configurator/views/product_configurator_templates.xml
index 5271a658b09..f9870892a2f 100644
--- a/addons/website_sale_stock_product_configurator/views/product_configurator_templates.xml
+++ b/addons/website_sale_stock_product_configurator/views/product_configurator_templates.xml
@@ -1,6 +1,6 @@
-
+
max(product.sudo()._get_max_available_qty(), 1) if handle_stock and product.type == "product" and not product.allow_out_of_stock_order else None
diff --git a/addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js b/addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js
index c0099db6361..b9e4f125c58 100644
--- a/addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js
+++ b/addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js
@@ -2,7 +2,7 @@
import publicWidget from "web.public.widget";
import wSaleUtils from "website_sale.utils";
-import VariantMixin from "sale.VariantMixin";
+import VariantMixin from "website_sale.SaleVariantMixin";
// VariantMixin events are overridden on purpose here
// to avoid registering them more than once since they are already registered
|