From d96585326bf4e09674c6a95ac99ff24025a5ec39 Mon Sep 17 00:00:00 2001 From: pilarvargas-tecnativa Date: Mon, 26 Feb 2024 14:46:31 +0100 Subject: [PATCH] [MIG] website_sale_coupon_selection_wizard: Migration to version 16.0 TT44379 --- .../website_sale_coupon_selection_wizard | 1 - .../website_sale_loyalty_suggestion_wizard | 1 + .../setup.py | 0 .../README.rst | 32 +- .../__manifest__.py | 24 +- .../controllers/__init__.py | 2 +- .../controllers/main.py | 61 ++-- .../{coupon_page.py => promotion_page.py} | 13 +- .../controllers/promotion_wizard.py | 85 ++++-- .../i18n/es.po | 40 +-- .../website_sale_coupon_selection_wizard.pot | 40 +-- .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 5 +- .../readme/USAGE.rst | 8 +- .../static/description/index.html | 28 +- ...website_sale_loyalty_suggestion_wizard.js} | 74 ++--- ...te_sale_loyalty_suggestion_wizard_mixin.js | 131 +++++++++ ...bsite_sale_loyalty_suggestion_wizard.scss} | 9 - .../templates/promotion_templates.xml | 93 +++--- .../templates/wizard_templates.xml | 275 ++++++++++++++++++ 20 files changed, 677 insertions(+), 246 deletions(-) delete mode 120000 setup/website_sale_coupon_selection_wizard/odoo/addons/website_sale_coupon_selection_wizard create mode 120000 setup/website_sale_loyalty_suggestion_wizard/odoo/addons/website_sale_loyalty_suggestion_wizard rename setup/{website_sale_coupon_selection_wizard => website_sale_loyalty_suggestion_wizard}/setup.py (100%) rename website_sale_loyalty_suggestion_wizard/controllers/{coupon_page.py => promotion_page.py} (59%) rename website_sale_loyalty_suggestion_wizard/static/src/js/{website_sale_coupon_selection_wizard.js => website_sale_loyalty_suggestion_wizard.js} (53%) create mode 100644 website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_loyalty_suggestion_wizard_mixin.js rename website_sale_loyalty_suggestion_wizard/static/src/scss/{website_sale_coupon_selection.scss => website_sale_loyalty_suggestion_wizard.scss} (79%) create mode 100644 website_sale_loyalty_suggestion_wizard/templates/wizard_templates.xml diff --git a/setup/website_sale_coupon_selection_wizard/odoo/addons/website_sale_coupon_selection_wizard b/setup/website_sale_coupon_selection_wizard/odoo/addons/website_sale_coupon_selection_wizard deleted file mode 120000 index 788b7f3a2..000000000 --- a/setup/website_sale_coupon_selection_wizard/odoo/addons/website_sale_coupon_selection_wizard +++ /dev/null @@ -1 +0,0 @@ -../../../../website_sale_coupon_selection_wizard \ No newline at end of file diff --git a/setup/website_sale_loyalty_suggestion_wizard/odoo/addons/website_sale_loyalty_suggestion_wizard b/setup/website_sale_loyalty_suggestion_wizard/odoo/addons/website_sale_loyalty_suggestion_wizard new file mode 120000 index 000000000..b59ab4009 --- /dev/null +++ b/setup/website_sale_loyalty_suggestion_wizard/odoo/addons/website_sale_loyalty_suggestion_wizard @@ -0,0 +1 @@ +../../../../website_sale_loyalty_suggestion_wizard \ No newline at end of file diff --git a/setup/website_sale_coupon_selection_wizard/setup.py b/setup/website_sale_loyalty_suggestion_wizard/setup.py similarity index 100% rename from setup/website_sale_coupon_selection_wizard/setup.py rename to setup/website_sale_loyalty_suggestion_wizard/setup.py diff --git a/website_sale_loyalty_suggestion_wizard/README.rst b/website_sale_loyalty_suggestion_wizard/README.rst index a6f928793..e59ba1075 100644 --- a/website_sale_loyalty_suggestion_wizard/README.rst +++ b/website_sale_loyalty_suggestion_wizard/README.rst @@ -1,13 +1,13 @@ -=============================== -Coupons Selection for eCommerce -=============================== +====================================== +Website Sale Loyalty Suggestion Wizard +====================================== .. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:94c44400c8e0661ca641d2c4de75be1950d9d1107237aa4189128911a9d1b019 + !! source digest: sha256:8c11a0d3f2c9fac24b5e452a5da349a41d86d34df86fa10b103b47acd0babf25 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -17,19 +17,20 @@ Coupons Selection for eCommerce :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsale--promotion-lightgray.png?logo=github - :target: https://github.com/OCA/sale-promotion/tree/15.0/website_sale_coupon_selection_wizard + :target: https://github.com/OCA/sale-promotion/tree/16.0/website_sale_loyalty_suggestion_wizard :alt: OCA/sale-promotion .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/sale-promotion-15-0/sale-promotion-15-0-website_sale_coupon_selection_wizard + :target: https://translation.odoo-community.org/projects/sale-promotion-16-0/sale-promotion-16-0-website_sale_loyalty_suggestion_wizard :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/sale-promotion&target_branch=15.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/sale-promotion&target_branch=16.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -This module allows to apply multi-gift mult-criteria promotion with a fancy wizard on -the eCommerce. +This module makes suggestions for promotions whose rules include a product added to the +cart. It also allows you to configure and apply these promotions with an elegant eCommerce +wizard. **Table of contents** @@ -49,14 +50,14 @@ Option 1: Option 2: -#. Add a product in the promotion criteria. -#. A cart hint will show up. +#. Add a product in the promotion rules. +#. A cart suggestion will appear. #. Add the promotion and configure the options. Option 3: -#. Add a promotion code. -#. If the promotion needs to be configured (i.e.: select the present) +#. Select a suggested promotion in the shopping cart from a list of "Suggested promotions". +#. Add the promotion and configure the options. Bug Tracker =========== @@ -64,7 +65,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -82,6 +83,7 @@ Contributors * `Tecnativa `_: * David Vidal + * Pilar Vargas Maintainers ~~~~~~~~~~~ @@ -104,6 +106,6 @@ Current `maintainer `__: |maintainer-chienandalu| -This module is part of the `OCA/sale-promotion `_ project on GitHub. +This module is part of the `OCA/sale-promotion `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_sale_loyalty_suggestion_wizard/__manifest__.py b/website_sale_loyalty_suggestion_wizard/__manifest__.py index 2cdcde99c..a074315e8 100644 --- a/website_sale_loyalty_suggestion_wizard/__manifest__.py +++ b/website_sale_loyalty_suggestion_wizard/__manifest__.py @@ -1,9 +1,10 @@ # Copyright 2021 Tecnativa - David Vidal # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { - "name": "Coupons Selection for eCommerce", - "summary": "Allows to apply and configure promotions directly from the website", - "version": "15.0.1.0.0", + "name": "Website Sale Loyalty Suggestion Wizard", + "summary": "Suggests promotions and allows you to configure and apply these " + "promotions directly from the website", + "version": "16.0.1.0.0", "development_status": "Beta", "category": "eCommerce", "website": "https://github.com/OCA/sale-promotion", @@ -11,19 +12,16 @@ "maintainers": ["chienandalu"], "license": "AGPL-3", "depends": [ - "sale_coupon_selection_wizard", - "sale_coupon_order_suggestion", - "website_sale_coupon_page", + "sale_loyalty", + "sale_loyalty_order_suggestion", + "website_sale_loyalty_page", ], - "data": ["templates/promotion_templates.xml"], + "data": ["templates/promotion_templates.xml", "templates/wizard_templates.xml"], "assets": { "web.assets_frontend": [ - "/website_sale_coupon_selection_wizard/static/src/scss/" - "website_sale_coupon_selection.scss", - "/sale_coupon_selection_wizard/static/src/js/" - "coupon_selection_wizard_mixin.js", - "/website_sale_coupon_selection_wizard/static/src/js/" - "website_sale_coupon_selection_wizard.js", + "/website_sale_loyalty_suggestion_wizard/static/src/scss/" + "website_sale_loyalty_suggestion_wizard.scss", + "/website_sale_loyalty_suggestion_wizard/static/src/js/*", ] }, } diff --git a/website_sale_loyalty_suggestion_wizard/controllers/__init__.py b/website_sale_loyalty_suggestion_wizard/controllers/__init__.py index 7cde69196..4316008bd 100644 --- a/website_sale_loyalty_suggestion_wizard/controllers/__init__.py +++ b/website_sale_loyalty_suggestion_wizard/controllers/__init__.py @@ -1,3 +1,3 @@ -from . import coupon_page +from . import promotion_page from . import main from . import promotion_wizard diff --git a/website_sale_loyalty_suggestion_wizard/controllers/main.py b/website_sale_loyalty_suggestion_wizard/controllers/main.py index 35f9ea040..57395616c 100644 --- a/website_sale_loyalty_suggestion_wizard/controllers/main.py +++ b/website_sale_loyalty_suggestion_wizard/controllers/main.py @@ -1,63 +1,66 @@ # Copyright 2021 Tecnativa - David Vidal +# Copyright 2024 Tecnativa - Pilar Vargas # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo.http import request, route from odoo.addons.website_sale.controllers.main import WebsiteSale -class WebsiteSaleCouponWizard(WebsiteSale): +class WebsiteSaleLoyaltySuggestionWizard(WebsiteSale): + def _get_sale_loyalty_reward_wizard(self, order, program): + wizard = ( + request.env["sale.loyalty.reward.wizard"] + .with_context(active_id=order.id) + .sudo() + .create({"selected_reward_id": program.reward_ids[:1].id}) + ) + return wizard + @route( ["/promotions//apply"], type="http", auth="public", website=True ) def promotion_program_apply(self, program_id, **kwargs): - program = request.env["coupon.program"].sudo().browse(program_id).exists() + program = request.env["loyalty.program"].sudo().browse(program_id).exists() + request.session.pop("wizard_id", None) if not program or not program.active or not program.is_published: - return + return request.redirect("/shop/cart") # Prevent to apply a promotion to a processed order order = request.website.sale_get_order() if order and order.state != "draft": request.session["sale_order_id"] = None order = request.website.sale_get_order() # We won't apply it twice - if program in (order.no_code_promo_program_ids | order.code_promo_program_id): - return - # If the promotion is directly applicable (promotion code), just apply without - # further ado. - if program.promo_code_usage == "code_needed" and ( - program not in order.sudo()._available_multi_criteria_multi_gift_programs() - ): - return self.pricelist(program.promo_code) + if program in order._get_reward_programs(): + return request.redirect("/shop/cart") # Let's inject some context into the view request.session["promotion_id"] = program.id + request.session["order_id"] = order.id return request.redirect("/shop/cart") - @route() - def pricelist(self, promo, **post): - """When applying a configurable promotion code, we'll offer the customer - to configure it.""" - if promo: - order = request.website.sale_get_order() - program = ( - request.env["coupon.program"] - .sudo() - .search([("promo_code", "=", promo)]) - ) - if program in order.sudo()._available_multi_criteria_multi_gift_programs(): - request.session["promotion_id"] = program.id - return request.redirect("/shop/cart") - return super().pricelist(promo) - @route() def cart(self, **post): + error = request.session.get("error_promo_code") response = super().cart(**post) promotion = request.session.get("promotion_id") + order = request.session.get("sale_order_id") if promotion: - response.qcontext["promotion_id"] = ( - request.env["coupon.program"].sudo().browse(promotion) + program_id = request.env["loyalty.program"].sudo().browse(promotion) + order_id = request.env["sale.order"].browse(order) + wizard_id = self._get_sale_loyalty_reward_wizard(order_id, program_id) + mandatory_program_options = ( + response.qcontext.get("mandatory_program_options") + or wizard_id.loyalty_rule_line_ids ) + response.qcontext["promotion_id"] = program_id + response.qcontext["order_id"] = order_id + response.qcontext["mandatory_program_options"] = mandatory_program_options + if error: + request.session["error_promo_code"] = error return response @route(["/promotions/dismiss"], type="http", auth="public", website=True) def promotion_in_cart_dismiss(self, **kw): request.session.pop("promotion_id", None) + request.session.pop("error_promo_code", None) + request.session.pop("wizard_id", None) return request.redirect("/shop/cart") diff --git a/website_sale_loyalty_suggestion_wizard/controllers/coupon_page.py b/website_sale_loyalty_suggestion_wizard/controllers/promotion_page.py similarity index 59% rename from website_sale_loyalty_suggestion_wizard/controllers/coupon_page.py rename to website_sale_loyalty_suggestion_wizard/controllers/promotion_page.py index fa3166992..3e385fd6c 100644 --- a/website_sale_loyalty_suggestion_wizard/controllers/coupon_page.py +++ b/website_sale_loyalty_suggestion_wizard/controllers/promotion_page.py @@ -2,10 +2,10 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo.http import request, route -from odoo.addons.website_sale_coupon_page.controllers.main import WebsiteSale +from odoo.addons.website_sale_loyalty_page.controllers.main import WebsiteSale -class CouponPage(WebsiteSale): +class LoyaltyPage(WebsiteSale): @route() def promotion(self, **post): """Rules to render the 'Apply promotion' button""" @@ -16,13 +16,8 @@ def promotion(self, **post): promo_values = response.qcontext.get("promos", []) for promo_dict in promo_values: promo_dict["applicable"] = False - promo = request.env["coupon.program"].sudo().browse(promo_dict["id"]) - if ( - promo in (order.no_code_promo_program_ids | order.code_promo_program_id) - ) or ( - promo - not in order.sudo()._available_multi_criteria_multi_gift_programs() - ): + promo = request.env["loyalty.program"].sudo().browse(promo_dict["id"]) + if promo not in order.sudo()._filter_programs_by_rules_with_products(): continue promo_dict["applicable"] = True return response diff --git a/website_sale_loyalty_suggestion_wizard/controllers/promotion_wizard.py b/website_sale_loyalty_suggestion_wizard/controllers/promotion_wizard.py index f2bcfb0d8..2d622910b 100644 --- a/website_sale_loyalty_suggestion_wizard/controllers/promotion_wizard.py +++ b/website_sale_loyalty_suggestion_wizard/controllers/promotion_wizard.py @@ -1,42 +1,79 @@ # Copyright 2021 Tecnativa - David Vidal # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import _ +from odoo.exceptions import ValidationError from odoo.http import request, route -from odoo.addons.sale_coupon_selection_wizard.controllers.main import ( - CouponSelectionWizardController, -) +from odoo.addons.website_sale_loyalty.controllers.main import WebsiteSale -class CouponSelectionWizardController(CouponSelectionWizardController): +class WebsiteSaleLoyaltySuggestionWizardController(WebsiteSale): + def _process_promotion_lines(self, wizard_id, promotion_lines): + for product, qty in promotion_lines.items(): + line = wizard_id.loyalty_rule_line_ids.filtered( + lambda x: x.product_id.id == int(product) + ) + if len(promotion_lines) == 1: + qty = line.units_required - line.units_included + if not qty: + continue + line.units_to_include = qty + + def _process_reward_line_options(self, wizard_id, reward_line_options): + reward_id = wizard_id.selected_reward_id + if reward_id.reward_type == "product": + reward_products = reward_id.reward_product_ids + if len(reward_products) == 1: + wizard_id.selected_product_id = reward_products.id + else: + wizard_id.selected_product_id = ( + int(reward_line_options.get("selected_product_ids", False)[0]) + or wizard_id.selected_product_id.id + ) + + @route( + "/website_sale_loyalty_suggestion_wizard/get_defaults", + type="json", + auth="public", + methods=["POST"], + ) + def get_default_products(self): + program_id = ( + request.env["loyalty.program"] + .sudo() + .browse(request.session.get("promotion_id")) + ) + order_id = request.env["sale.order"].browse( + request.session.get("sale_order_id") + ) + wiz = self._get_sale_loyalty_reward_wizard(order_id, program_id) + return wiz.selected_product_id.ids + @route( - "/website_sale_coupon_selection_wizard/apply", + "/website_sale_loyalty_suggestion_wizard/apply", type="json", auth="public", methods=["POST"], ) def apply_promotion_public( - self, program_id, sale_order_id, promotion_lines, reward_line_options, **kw + self, program_id, promotion_lines, reward_line_options, **kw ): """Frontend controller that wraps common methods and handles errors properly""" - error, sale_form, program = self._try_to_apply_promotion( - program_id, sale_order_id, promotion_lines, reward_line_options, **kw + order_id = request.env["sale.order"].browse( + request.session.get("sale_order_id") ) - if error: - request.session["error_promo_code"] = error + program_id = request.env["loyalty.program"].sudo().browse(program_id) + wiz = self._get_sale_loyalty_reward_wizard(order_id, program_id) + reward_id = reward_line_options.get("reward_id", False) + wiz.selected_reward_id = int(reward_id) or ( + program_id.reward_ids.id if len(program_id.reward_ids) == 1 else False + ) + if wiz.selected_reward_id: + self._process_promotion_lines(wiz, promotion_lines) + self._process_reward_line_options(wiz, reward_line_options) + try: + wiz.action_apply() + except ValidationError as e: + request.session["error_promo_code"] = str(e) return - # Once checked write the new lines and force the code if the promo has one - order = sale_form.save() - promo_applied = self._apply_promotion(order, program, reward_line_options) - if not promo_applied: - request.session["error_promo_code"] = _( - "This promotion can't be applied to this order" - ) request.session.pop("promotion_id", None) request.session.pop("error_promo_code", None) - - @route(website=True) - def configure_promotion(self, program_id, **kw): - if not self._get_order(kw.get("sale_order_id")): - kw["sale_order_id"] = request.website.sale_get_order(force_create=True) - return super().configure_promotion(program_id, **kw) diff --git a/website_sale_loyalty_suggestion_wizard/i18n/es.po b/website_sale_loyalty_suggestion_wizard/i18n/es.po index 64bacf08e..bb79e36d1 100644 --- a/website_sale_loyalty_suggestion_wizard/i18n/es.po +++ b/website_sale_loyalty_suggestion_wizard/i18n/es.po @@ -1,6 +1,6 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * website_sale_coupon_selection_wizard +# * website_sale_loyalty_suggestion_wizard # msgid "" msgstr "" @@ -17,49 +17,49 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.17\n" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion msgid " Configure" msgstr " Configurar" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion msgid "×" msgstr "×" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.website_sale_coupon_suggestion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.website_sale_loyalty_suggestion msgid "Add" msgstr "Añadir" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.promotion_item +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.promotion_item msgid "Apply" msgstr "Aplicar" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion msgid "Close" msgstr "Cerrar" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.website_sale_coupon_suggestion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.website_sale_loyalty_suggestion msgid "Configurable promotions suggested" msgstr "Promociones configurables sugeridas" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion msgid "In order to apply this promotion you need to configure some options." msgstr "Para aplicar esta promoción necesita configurar algunas opciones." -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.website_sale_coupon_suggestion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.website_sale_loyalty_suggestion msgid "Suggested Promotions:" msgstr "Promociones Sugeridas:" -#. module: website_sale_coupon_selection_wizard -#: code:addons/website_sale_coupon_selection_wizard/controllers/promotion_wizard.py:0 +#. module: website_sale_loyalty_suggestion_wizard +#: code:addons/website_sale_loyalty_suggestion_wizard/controllers/promotion_wizard.py:0 #, python-format msgid "This promotion can't be applied to this order" msgstr "Esta promoción no puede ser aplicada en este pedido" diff --git a/website_sale_loyalty_suggestion_wizard/i18n/website_sale_coupon_selection_wizard.pot b/website_sale_loyalty_suggestion_wizard/i18n/website_sale_coupon_selection_wizard.pot index af357d8e9..c0427e5a6 100644 --- a/website_sale_loyalty_suggestion_wizard/i18n/website_sale_coupon_selection_wizard.pot +++ b/website_sale_loyalty_suggestion_wizard/i18n/website_sale_coupon_selection_wizard.pot @@ -1,6 +1,6 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * website_sale_coupon_selection_wizard +# * website_sale_loyalty_suggestion_wizard # msgid "" msgstr "" @@ -13,49 +13,49 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion msgid " Configure" msgstr "" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion msgid "×" msgstr "" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.website_sale_coupon_suggestion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.website_sale_loyalty_suggestion msgid "Add" msgstr "" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.promotion_item +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.promotion_item msgid "Apply" msgstr "" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion msgid "Close" msgstr "" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.website_sale_coupon_suggestion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.website_sale_loyalty_suggestion msgid "Configurable promotions suggested" msgstr "" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.configure_promotion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.configure_promotion msgid "In order to apply this promotion you need to configure some options." msgstr "" -#. module: website_sale_coupon_selection_wizard -#: model_terms:ir.ui.view,arch_db:website_sale_coupon_selection_wizard.website_sale_coupon_suggestion +#. module: website_sale_loyalty_suggestion_wizard +#: model_terms:ir.ui.view,arch_db:website_sale_loyalty_suggestion_wizard.website_sale_loyalty_suggestion msgid "Suggested Promotions:" msgstr "" -#. module: website_sale_coupon_selection_wizard -#: code:addons/website_sale_coupon_selection_wizard/controllers/promotion_wizard.py:0 +#. module: website_sale_loyalty_suggestion_wizard +#: code:addons/website_sale_loyalty_suggestion_wizard/controllers/promotion_wizard.py:0 #, python-format msgid "This promotion can't be applied to this order" msgstr "" diff --git a/website_sale_loyalty_suggestion_wizard/readme/CONTRIBUTORS.rst b/website_sale_loyalty_suggestion_wizard/readme/CONTRIBUTORS.rst index 94b6ba953..c17621ec1 100644 --- a/website_sale_loyalty_suggestion_wizard/readme/CONTRIBUTORS.rst +++ b/website_sale_loyalty_suggestion_wizard/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * `Tecnativa `_: * David Vidal + * Pilar Vargas diff --git a/website_sale_loyalty_suggestion_wizard/readme/DESCRIPTION.rst b/website_sale_loyalty_suggestion_wizard/readme/DESCRIPTION.rst index 24ec2e3d1..39772c61a 100644 --- a/website_sale_loyalty_suggestion_wizard/readme/DESCRIPTION.rst +++ b/website_sale_loyalty_suggestion_wizard/readme/DESCRIPTION.rst @@ -1,2 +1,3 @@ -This module allows to apply multi-gift mult-criteria promotion with a fancy wizard on -the eCommerce. +This module makes suggestions for promotions whose rules include a product added to the +cart. It also allows you to configure and apply these promotions with an elegant eCommerce +wizard. diff --git a/website_sale_loyalty_suggestion_wizard/readme/USAGE.rst b/website_sale_loyalty_suggestion_wizard/readme/USAGE.rst index 11e209ef0..7d4e7eb75 100644 --- a/website_sale_loyalty_suggestion_wizard/readme/USAGE.rst +++ b/website_sale_loyalty_suggestion_wizard/readme/USAGE.rst @@ -8,11 +8,11 @@ Option 1: Option 2: -#. Add a product in the promotion criteria. -#. A cart hint will show up. +#. Add a product in the promotion rules. +#. A cart suggestion will appear. #. Add the promotion and configure the options. Option 3: -#. Add a promotion code. -#. If the promotion needs to be configured (i.e.: select the present) +#. Select a suggested promotion in the shopping cart from a list of "Suggested promotions". +#. Add the promotion and configure the options. diff --git a/website_sale_loyalty_suggestion_wizard/static/description/index.html b/website_sale_loyalty_suggestion_wizard/static/description/index.html index ce2802901..ccf05bf8b 100644 --- a/website_sale_loyalty_suggestion_wizard/static/description/index.html +++ b/website_sale_loyalty_suggestion_wizard/static/description/index.html @@ -4,7 +4,7 @@ -Coupons Selection for eCommerce +Website Sale Loyalty Suggestion Wizard -
-

Coupons Selection for eCommerce

+
+

Website Sale Loyalty Suggestion Wizard

-

Beta License: AGPL-3 OCA/sale-promotion Translate me on Weblate Try me on Runboat

-

This module allows to apply multi-gift mult-criteria promotion with a fancy wizard on -the eCommerce.

+

Beta License: AGPL-3 OCA/sale-promotion Translate me on Weblate Try me on Runboat

+

This module makes suggestions for promotions whose rules include a product added to the +cart. It also allows you to configure and apply these promotions with an elegant eCommerce +wizard.

Table of contents

    @@ -396,14 +397,14 @@

    Usage

    Option 2:

      -
    1. Add a product in the promotion criteria.
    2. -
    3. A cart hint will show up.
    4. +
    5. Add a product in the promotion rules.
    6. +
    7. A cart suggestion will appear.
    8. Add the promotion and configure the options.

    Option 3:

      -
    1. Add a promotion code.
    2. -
    3. If the promotion needs to be configured (i.e.: select the present)
    4. +
    5. Select a suggested promotion in the shopping cart from a list of “Suggested promotions”.
    6. +
    7. Add the promotion and configure the options.
@@ -411,7 +412,7 @@

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -427,6 +428,7 @@

Contributors

@@ -440,7 +442,7 @@

Maintainers

promote its widespread use.

Current maintainer:

chienandalu

-

This module is part of the OCA/sale-promotion project on GitHub.

+

This module is part of the OCA/sale-promotion project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_coupon_selection_wizard.js b/website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_loyalty_suggestion_wizard.js similarity index 53% rename from website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_coupon_selection_wizard.js rename to website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_loyalty_suggestion_wizard.js index 97cefe2af..d18c39e39 100644 --- a/website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_coupon_selection_wizard.js +++ b/website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_loyalty_suggestion_wizard.js @@ -1,18 +1,16 @@ /* Copyright 2021 Tecnativa - David Vidal * License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). */ -odoo.define("website_sale_coupon_selection_wizard", function (require) { +odoo.define("website_sale_loyalty_suggestion_wizard", function (require) { "use strict"; - const CouponSelectionMixin = require("sale_coupon_selection_wizard.CouponSelectionMixin"); + const CouponSelectionMixin = require("website_sale_loyalty_suggestion_wizard.CouponSelectionMixin"); const publicWidget = require("web.public.widget"); const websiteSale = require("website_sale.website_sale"); - publicWidget.registry.WebsiteSaleCouponWizard = publicWidget.Widget.extend( - CouponSelectionMixin, - { + publicWidget.registry.WebsiteSaleLoyaltySuggestionWizard = + publicWidget.Widget.extend(CouponSelectionMixin, { selector: "#o_promo_configure", events: Object.assign({}, CouponSelectionMixin.events || {}, { - "change span.js_promotion_change": "_onChangePromotion", "click .o_coupon_selection_wizard_apply": "apply_promotion", }), /** @@ -29,33 +27,6 @@ odoo.define("website_sale_coupon_selection_wizard", function (require) { $("span.js_promotion_change").trigger("change"); return def; }, - /** - * @private - */ - _onChangePromotion: function () { - this._configure_promotion_cart( - this.program_id, - this.website_sale_order - ); - }, - /** - * Renders the components needed for the promotion - * - * @param {integer} program_id - * @param {integer} website_sale_order - * @returns {Promise} - */ - _configure_promotion_cart: async function (program_id, website_sale_order) { - const configurator = await this._rpc({ - route: "/sale_coupon_selection_wizard/configure", - params: { - program_id: program_id, - sale_order_id: website_sale_order, - }, - }); - const [$o_promo_config_body] = this.$el.find("#o_promo_config_body"); - $o_promo_config_body.insertAdjacentHTML("beforeend", configurator); - }, /** * Communicate the form options to the controller. An object with product id * key and quantity as value is passed to try to apply them to the order and @@ -69,34 +40,39 @@ odoo.define("website_sale_coupon_selection_wizard", function (require) { const $reward_options = $modal.find( "input.reward_optional_input:checked" ); + const $cardBodyContainer = $reward_options.closest( + "div.csw_optional_reward" + ); + const $reward_selected_product = + $cardBodyContainer.find(".bg-info input"); var promotion_values = {}; - // Group by products then clean 0 keys - for (const $input of $wizard_inputs) { - const product_id = $input.dataset.product_id; - promotion_values[product_id] = promotion_values[product_id] || 0; - promotion_values[product_id] += - ($input.value && parseInt($input.value, 10)) || 0; - } - var reward_line_options = {}; - for (const $input of $reward_options) { - const reward_id = $input.name.replace("reward-", ""); - reward_line_options[reward_id] = $input.value; - } + $wizard_inputs.each(function () { + const product_id = this.dataset.product_id; + promotion_values[product_id] = + (promotion_values[product_id] || 0) + + (parseInt(this.value, 10) || 0); + }); + var reward_line_options = { + reward_id: $reward_options.val(), + selected_product_ids: $reward_selected_product + .map(function () { + return this.value; + }) + .get(), + }; await this._rpc({ - route: "/website_sale_coupon_selection_wizard/apply", + route: "/website_sale_loyalty_suggestion_wizard/apply", params: { program_id: this.program_id, sale_order_id: this.website_sale_order, promotion_lines: promotion_values, reward_line_options: reward_line_options, - website_wizard: true, }, }); $("#o_promo_configure_modal").modal("hide"); window.location = "/shop/cart"; }, - } - ); + }); websiteSale.websiteSaleCart.include({ /** diff --git a/website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_loyalty_suggestion_wizard_mixin.js b/website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_loyalty_suggestion_wizard_mixin.js new file mode 100644 index 000000000..b12a044ae --- /dev/null +++ b/website_sale_loyalty_suggestion_wizard/static/src/js/website_sale_loyalty_suggestion_wizard_mixin.js @@ -0,0 +1,131 @@ +odoo.define("website_sale_loyalty_suggestion_wizard.CouponSelectionMixin", function () { + "use strict"; + + var CouponSelectionMixin = { + events: { + "change .js_promotion_item_quantity": "_onchange_quantity", + "click button.csw_add_quantity, button.csw_remove_quantity": + "_onclick_add_or_remove", + "click div.csw_optional_reward": "_onclick_choose_reward", + "click div.csw_optional_product": "_onclick_choose_product", + }, + /** + * When the quantity changes, apply some logic to help the user checking if + * the promotion can be applied or not. + * + * @param {InputEvent} ev + */ + _onchange_quantity: function (ev) { + var $row = $(ev.currentTarget).closest(".row.pl-3.pr-3"); + var $needed_qty_span = $row.find(".csw_criteria_needed_qty"); + var $criteria_icon = $row.find(".csw_criteria_icon"); + var $row_add_buttons = $row.find(".csw_add_quantity"); + var $inputs = $row.find("input"); + var needed_qty = parseInt($needed_qty_span.data("qty"), 10); + var current_row_qty = 0; + _.each($inputs, function (inp) { + current_row_qty += parseInt(inp.value, 10); + }); + needed_qty = Math.max(needed_qty - current_row_qty, 0); + if (needed_qty) { + $needed_qty_span.parent().removeClass("d-none"); + $row_add_buttons.removeAttr("disabled"); + $criteria_icon.removeClass(["fa-certificate", "text-success"]); + $criteria_icon.addClass(["fa-sun-o", "text-warning"]); + $inputs.closest(".card").removeClass("border-success"); + $needed_qty_span.text(needed_qty); + } else { + $needed_qty_span.parent().addClass("d-none"); + $row_add_buttons.attr("disabled", "disabled"); + $criteria_icon.removeClass(["fa-sun-o", "text-warning"]); + $criteria_icon.addClass(["fa-certificate", "text-success"]); + $inputs + .filter(function () { + return this.value !== "0"; + }) + .closest(".card") + .addClass("border-success"); + } + }, + /** + * Buttons circuitry + * + * @param {InputEvent} ev + */ + _onclick_add_or_remove: function (ev) { + ev.preventDefault(); + var $button = $(ev.currentTarget); + var $input = $button.closest(".input-group").find("input"); + var min = parseFloat($input.attr("min") || 0); + var max = parseFloat($input.attr("max") || Infinity); + var previousQty = parseFloat($input.val() || 0, 10); + var quantity = ($button.has(".fa-minus").length ? -1 : 1) + previousQty; + var newQty = quantity > min ? (quantity < max ? quantity : max) : min; + if (newQty !== previousQty) { + $input.val(newQty).trigger("change"); + } + }, + /** + * Reward card click circuitry + * + * @param {InputEvent} ev + */ + _onclick_choose_reward: function (ev) { + ev.preventDefault(); + var $input = $(ev.currentTarget).find("input[name='reward']"); + var $input_siblings = $(ev.currentTarget.closest(".row")).find( + "input[name='reward']" + ); + _.each($input_siblings, function ($sibling) { + $($sibling) + .closest(".csw_optional_reward") + .not(ev.currentTarget) + .find(".bg-info") + .removeClass("bg-info"); + $($sibling).closest(".csw_optional_reward").removeClass("bg-success"); + }); + $input.prop("checked", true); + $(ev.currentTarget).addClass("bg-success"); + this._choose_default_products($(ev.currentTarget)); + }, + + _choose_default_products: async function ($target) { + const defaults = await this._rpc({ + route: "/website_sale_loyalty_suggestion_wizard/get_defaults", + }); + for (var def of defaults) { + const $input = $target.find( + "input.reward_product_input[value='" + def + "']" + ); + var group = $input.attr("name"); + var $input_siblings = $target.find( + "input[name='" + group + "']:checked" + ); + if (!$input_siblings.length) { + $input.prop("checked", true); + $input.closest(".csw_optional_product").addClass("bg-info"); + } + } + console.log(defaults); + }, + /** + * Reward product card click circuitry + * + * @param {InputEvent} ev + */ + _onclick_choose_product: function (ev) { + ev.preventDefault(); + var $input = $(ev.currentTarget).find("input.reward_product_input"); + var group = $input.attr("name"); + var $input_siblings = $(ev.currentTarget.closest(".card-body")).find( + "input[name='" + group + "']" + ); + _.each($input_siblings, function ($sibling) { + $($sibling).closest(".card").removeClass("bg-info"); + }); + $input.prop("checked", true); + $(ev.currentTarget).addClass("bg-info"); + }, + }; + return CouponSelectionMixin; +}); diff --git a/website_sale_loyalty_suggestion_wizard/static/src/scss/website_sale_coupon_selection.scss b/website_sale_loyalty_suggestion_wizard/static/src/scss/website_sale_loyalty_suggestion_wizard.scss similarity index 79% rename from website_sale_loyalty_suggestion_wizard/static/src/scss/website_sale_coupon_selection.scss rename to website_sale_loyalty_suggestion_wizard/static/src/scss/website_sale_loyalty_suggestion_wizard.scss index 0d171dd82..7750d2607 100644 --- a/website_sale_loyalty_suggestion_wizard/static/src/scss/website_sale_coupon_selection.scss +++ b/website_sale_loyalty_suggestion_wizard/static/src/scss/website_sale_loyalty_suggestion_wizard.scss @@ -1,15 +1,6 @@ -.oe_promotion_wizard_item_img { - object-fit: contain; - max-height: 5rem; - width: 5rem; -} .oe_promotion_wizard_item_infos { font-size: 0.9rem; } -.card-horizontal { - display: flex; - flex: 1 1 auto; -} .oe_scw_criteria_condition, .oe_scw_reward_retribution { font-weight: bold; diff --git a/website_sale_loyalty_suggestion_wizard/templates/promotion_templates.xml b/website_sale_loyalty_suggestion_wizard/templates/promotion_templates.xml index 3f53f2438..1197268ff 100644 --- a/website_sale_loyalty_suggestion_wizard/templates/promotion_templates.xml +++ b/website_sale_loyalty_suggestion_wizard/templates/promotion_templates.xml @@ -1,9 +1,10 @@ + + +