From 324f7c52ba31cd6c842d66aea6c7cb7fdb683584 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Mon, 24 Jan 2022 11:36:27 +0000 Subject: [PATCH] [IMP] website_sale: Let the use choose to stay on products or go to cart Currently, when adding a product to the cart, this is possible to: - Force the user to stay on product page - Redirect the user to the cart page Also, when there are configurable products (with variants), or when there are optional products, a dialog is opening to let the user finalize his choice. This commit adds a new option to "Let the user decide" to be redirected to the cart, or to stay there. For this, we reuse the dialog that was previously reserved to the use cases explained above. Part-of: odoo/odoo#82999 --- .../static/src/js/product_configurator_modal.js | 1 + addons/website_sale/models/res_config_settings.py | 2 +- addons/website_sale/models/website.py | 15 ++++++++++++++- .../static/src/js/website_sale_utils.js | 3 ++- addons/website_sale/views/templates.xml | 2 +- .../controllers/main.py | 3 ++- .../models/__init__.py | 1 + .../models/website.py | 12 ++++++++++++ .../static/src/js/product_configurator_modal.js | 1 + .../static/src/js/website_sale_options.js | 1 + 10 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 addons/website_sale_product_configurator/models/website.py 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 424b52418d6..48895db2f05 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 @@ -79,6 +79,7 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, VariantMixin, { variant_values: self.rootProduct.variant_values, pricelist_id: self.pricelistId || false, add_qty: self.rootProduct.quantity, + force_dialog: self.forceDialog, kwargs: { context: _.extend({ 'quantity': self.rootProduct.quantity diff --git a/addons/website_sale/models/res_config_settings.py b/addons/website_sale/models/res_config_settings.py index 616e8e34ddb..d475b264cdf 100644 --- a/addons/website_sale/models/res_config_settings.py +++ b/addons/website_sale/models/res_config_settings.py @@ -30,7 +30,7 @@ class ResConfigSettings(models.TransientModel): related='website_id.cart_recovery_mail_template_id', readonly=False) cart_abandoned_delay = fields.Float("Abandoned Delay", help="Number of hours after which the cart is considered abandoned.", related='website_id.cart_abandoned_delay', readonly=False) - cart_add_on_page = fields.Boolean("Stay on page after adding to cart", related='website_id.cart_add_on_page', readonly=False) + add_to_cart_action = fields.Selection(related='website_id.add_to_cart_action', readonly=False) terms_url = fields.Char(compute='_compute_terms_url', string="URL", help="A preview will be available at this URL.") module_delivery = fields.Boolean( diff --git a/addons/website_sale/models/website.py b/addons/website_sale/models/website.py index 88e67e3e70b..9c90d1e49f2 100644 --- a/addons/website_sale/models/website.py +++ b/addons/website_sale/models/website.py @@ -61,7 +61,20 @@ class Website(models.Model): shop_extra_field_ids = fields.One2many('website.sale.extra.field', 'website_id', string='E-Commerce Extra Fields') - cart_add_on_page = fields.Boolean("Stay on page after adding to cart", default=True) + add_to_cart_action = fields.Selection( + selection=[ + ('stay', 'Stay on Product Page'), + ('go_to_cart', 'Go to cart'), + ], + default='stay') + account_on_checkout = fields.Selection( + string="Customer Accounts", + selection=[ + ('optional', 'Optional'), + ('disabled', 'Disabled (buy as guest)'), + ('mandatory', 'Mandatory (no guest checkout)'), + ], + default='optional') @api.depends('all_pricelist_ids') def _compute_pricelist_ids(self): diff --git a/addons/website_sale/static/src/js/website_sale_utils.js b/addons/website_sale/static/src/js/website_sale_utils.js index 6d62e816331..0c1f60868ff 100644 --- a/addons/website_sale/static/src/js/website_sale_utils.js +++ b/addons/website_sale/static/src/js/website_sale_utils.js @@ -6,7 +6,8 @@ const wUtils = require('website.utils'); const cartHandlerMixin = { getRedirectOption() { const html = document.documentElement; - this.stayOnPageOption = html.dataset.add2cartRedirect !== '0'; + this.stayOnPageOption = html.dataset.add2cartRedirect === '1'; + this.forceDialog = html.dataset.add2cartRedirect === '2'; }, getCartHandlerOptions(ev) { this.isBuyNow = ev.currentTarget.classList.contains('o_we_buy_now'); diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index 6401a54e7ab..d57da0d0eec 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -2045,7 +2045,7 @@ diff --git a/addons/website_sale_product_configurator/controllers/main.py b/addons/website_sale_product_configurator/controllers/main.py index cca3ae2d37a..11241642138 100644 --- a/addons/website_sale_product_configurator/controllers/main.py +++ b/addons/website_sale_product_configurator/controllers/main.py @@ -18,8 +18,9 @@ class WebsiteSaleProductConfiguratorController(ProductConfiguratorController): 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)) + force_dialog = kw.get('force_dialog') - if not has_optional_products and (product.product_variant_count <= 1 or variant_values): + if not force_dialog and not has_optional_products and (product.product_variant_count <= 1 or variant_values): # The modal is not shown if there are no optional products and # the main product either has no variants or is already configured return False diff --git a/addons/website_sale_product_configurator/models/__init__.py b/addons/website_sale_product_configurator/models/__init__.py index 6064afee178..4929acdec30 100644 --- a/addons/website_sale_product_configurator/models/__init__.py +++ b/addons/website_sale_product_configurator/models/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import sale_order +from . import website diff --git a/addons/website_sale_product_configurator/models/website.py b/addons/website_sale_product_configurator/models/website.py new file mode 100644 index 00000000000..8a8340b0ba9 --- /dev/null +++ b/addons/website_sale_product_configurator/models/website.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class Website(models.Model): + _inherit = 'website' + + add_to_cart_action = fields.Selection( + selection_add=[('force_dialog', "Let the user decide (dialog)")], + ondelete={'force_dialog': 'set default'}) diff --git a/addons/website_sale_product_configurator/static/src/js/product_configurator_modal.js b/addons/website_sale_product_configurator/static/src/js/product_configurator_modal.js index 5b00d2d26ca..339dde30b23 100644 --- a/addons/website_sale_product_configurator/static/src/js/product_configurator_modal.js +++ b/addons/website_sale_product_configurator/static/src/js/product_configurator_modal.js @@ -23,6 +23,7 @@ OptionalProductsModal.include({ init: function (parent, params) { this._super.apply(this, arguments); this.isWebsite = params.isWebsite; + this.forceDialog = params.forceDialog; this.dialogClass = 'oe_advanced_configurator_modal' + (params.isWebsite ? ' oe_website_sale' : ''); }, 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 d95ea5bcfe3..b2ad18b721a 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 @@ -26,6 +26,7 @@ publicWidget.registry.WebsiteSale.include({ cancelButtonText: _t('Continue Shopping'), title: _t('Add to cart'), context: this._getContext(), + forceDialog: this.forceDialog, }).open(); this.optionalProductsModal.on('options_empty', null, this._submitForm.bind(this));