From f11eb1dccaaeff434804721015eca65454cccf57 Mon Sep 17 00:00:00 2001 From: "Jacky (trj)" Date: Tue, 25 May 2021 08:46:00 +0000 Subject: [PATCH] [ADD] pos_sale_product_configurator: add optional products in the product info popup With the module sale_product_configurator, you can add optionnal products on your product to suggest them during the sale process. We are now displaying them of the info popup of a product to easily find them in the POS, and we also allow to automatically open this popup for products having such optionnal products. closes odoo/odoo#71203 Task-id: 2518884 Signed-off-by: pimodoo --- .../point_of_sale/views/pos_config_view.xml | 2 +- .../pos_sale_product_configurator/__init__.py | 4 +++ .../__manifest__.py | 29 +++++++++++++++++ .../models/__init__.py | 5 +++ .../models/pos_config.py | 7 +++++ .../models/product.py | 26 ++++++++++++++++ .../src/css/popups/product_info_popup.css | 16 ++++++++++ .../static/src/js/models.js | 31 +++++++++++++++++++ .../src/xml/Popups/ProductInfoPopup.xml | 25 +++++++++++++++ .../views/pos_config_views.xml | 23 ++++++++++++++ 10 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 addons/pos_sale_product_configurator/__init__.py create mode 100644 addons/pos_sale_product_configurator/__manifest__.py create mode 100644 addons/pos_sale_product_configurator/models/__init__.py create mode 100644 addons/pos_sale_product_configurator/models/pos_config.py create mode 100644 addons/pos_sale_product_configurator/models/product.py create mode 100644 addons/pos_sale_product_configurator/static/src/css/popups/product_info_popup.css create mode 100644 addons/pos_sale_product_configurator/static/src/js/models.js create mode 100644 addons/pos_sale_product_configurator/static/src/xml/Popups/ProductInfoPopup.xml create mode 100644 addons/pos_sale_product_configurator/views/pos_config_views.xml diff --git a/addons/point_of_sale/views/pos_config_view.xml b/addons/point_of_sale/views/pos_config_view.xml index bf059dc2bcc..aef2b1ebde2 100644 --- a/addons/point_of_sale/views/pos_config_view.xml +++ b/addons/point_of_sale/views/pos_config_view.xml @@ -172,7 +172,7 @@ -
+
diff --git a/addons/pos_sale_product_configurator/__init__.py b/addons/pos_sale_product_configurator/__init__.py new file mode 100644 index 00000000000..dc5e6b693d1 --- /dev/null +++ b/addons/pos_sale_product_configurator/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import models diff --git a/addons/pos_sale_product_configurator/__manifest__.py b/addons/pos_sale_product_configurator/__manifest__.py new file mode 100644 index 00000000000..d17197c0593 --- /dev/null +++ b/addons/pos_sale_product_configurator/__manifest__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + + +{ + 'name': 'pos_sale_product_configurator', + 'version': '1.0', + 'category': 'Hidden', + 'summary': 'Link module between point_of_sale and sale_product_configurator', + 'description': """ +This module adds features depending on both modules. +""", + 'depends': ['point_of_sale', 'sale_product_configurator'], + 'installable': True, + 'auto_install': True, + 'data': [ + 'views/pos_config_views.xml', + ], + 'assets': { + 'point_of_sale.assets': [ + 'pos_sale_product_configurator/static/src/js/models.js', + 'pos_sale_product_configurator/static/src/css/popups/product_info_popup.css', + ], + 'web.assets_qweb': [ + 'pos_sale_product_configurator/static/src/xml/**/*' + ] + }, + 'license': 'LGPL-3', +} diff --git a/addons/pos_sale_product_configurator/models/__init__.py b/addons/pos_sale_product_configurator/models/__init__.py new file mode 100644 index 00000000000..8c7aba25471 --- /dev/null +++ b/addons/pos_sale_product_configurator/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import pos_config +from . import product diff --git a/addons/pos_sale_product_configurator/models/pos_config.py b/addons/pos_sale_product_configurator/models/pos_config.py new file mode 100644 index 00000000000..a5ffc90637a --- /dev/null +++ b/addons/pos_sale_product_configurator/models/pos_config.py @@ -0,0 +1,7 @@ +from odoo import models, fields + + +class PosConfig(models.Model): + _inherit = 'pos.config' + + iface_open_product_info = fields.Boolean(string="Open Product Info", help="Display the 'Product Info' page when a product with optional products are added in the customer cart") diff --git a/addons/pos_sale_product_configurator/models/product.py b/addons/pos_sale_product_configurator/models/product.py new file mode 100644 index 00000000000..c810fcf92cd --- /dev/null +++ b/addons/pos_sale_product_configurator/models/product.py @@ -0,0 +1,26 @@ +from odoo import models + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + def get_product_info_pos(self, price, quantity, pos_config_id): + res = super().get_product_info_pos(price, quantity, pos_config_id) + + # Optional products + res['optional_products'] = [ + {'name': p.name, 'price': min(p.product_variant_ids.mapped('lst_price'))} + for p in self.optional_product_ids.filtered_domain(self._optional_product_pos_domain()) + ] + + return res + + def has_optional_product_in_pos(self): + self.ensure_one() + return bool(self.optional_product_ids.filtered_domain(self._optional_product_pos_domain())) + + def _optional_product_pos_domain(self): + return [ + '&', '&', ['sale_ok', '=', True], ['available_in_pos', '=', True], + '|', ['company_id', '=', self.env.company], ['company_id', '=', False] + ] diff --git a/addons/pos_sale_product_configurator/static/src/css/popups/product_info_popup.css b/addons/pos_sale_product_configurator/static/src/css/popups/product_info_popup.css new file mode 100644 index 00000000000..c59e17c8a0b --- /dev/null +++ b/addons/pos_sale_product_configurator/static/src/css/popups/product_info_popup.css @@ -0,0 +1,16 @@ +.product-info-popup .extra { + display: flex; +} + +.product-info-popup .extra div { + width: 100%; +} + +@media screen and (max-width: 768px) { + .product-info-popup .extra{ + flex-direction: column; + } + .product-info-popup .section-optional-product-body td { + width: 50%; + } +} diff --git a/addons/pos_sale_product_configurator/static/src/js/models.js b/addons/pos_sale_product_configurator/static/src/js/models.js new file mode 100644 index 00000000000..05cc5855406 --- /dev/null +++ b/addons/pos_sale_product_configurator/static/src/js/models.js @@ -0,0 +1,31 @@ +odoo.define('pos_sale_product_configurator.models', function (require) { + "use strict"; + + const { Gui } = require('point_of_sale.Gui'); + var models = require('point_of_sale.models'); + + models.load_fields("product.product", ["optional_product_ids"]); + models.load_fields("pos.config", ["iface_open_product_info"]); + + const super_order_model = models.Order.prototype; + models.Order = models.Order.extend({ + async add_product(product, options) { + super_order_model.add_product.apply(this, arguments); + if (this.pos.config.iface_open_product_info && product.optional_product_ids.length) { + // The `optional_product_ids` only contains ids of the product templates and not the product itself + // We don't load all the product template in the pos, so it'll be hard to know if the id comes from + // a product available in POS. We send a quick cal to the back end to verify. + const isProductLoaded = await this.pos.rpc( + { + model: 'product.product', + method: 'has_optional_product_in_pos', + args: [[product.id]] + } + ); + if (isProductLoaded) { + Gui.showPopup('ProductInfoPopup', {product, quantity: this.get_selected_orderline().get_quantity()}); + } + } + } + }) +}) diff --git a/addons/pos_sale_product_configurator/static/src/xml/Popups/ProductInfoPopup.xml b/addons/pos_sale_product_configurator/static/src/xml/Popups/ProductInfoPopup.xml new file mode 100644 index 00000000000..e6b7ab3f419 --- /dev/null +++ b/addons/pos_sale_product_configurator/static/src/xml/Popups/ProductInfoPopup.xml @@ -0,0 +1,25 @@ + + + + +
+
+ Optional Products +
+
+
+ + + + + + + +
+ from +
+
+
+ + + diff --git a/addons/pos_sale_product_configurator/views/pos_config_views.xml b/addons/pos_sale_product_configurator/views/pos_config_views.xml new file mode 100644 index 00000000000..e69fc8765c9 --- /dev/null +++ b/addons/pos_sale_product_configurator/views/pos_config_views.xml @@ -0,0 +1,23 @@ + + + + pos.config.form.view.inherit.pos.sale.product.configuration + pos.config + + +
+
+
+ +
+
+
+
+
+
+
+