From 669b9fcc2fb82bb410e2b36e8bfa638ffd66cc2c Mon Sep 17 00:00:00 2001 From: vlst Date: Wed, 5 Jul 2023 09:13:46 +0000 Subject: [PATCH] [IMP] point_of_sale: add product combos In this PR we introduce the ability to create product combos. Now any product can be turned into a combo meal by defining the different combo choices it contains. In this PR, we add the backend logic and the backoffice views needed for this feature. Afterwards, different modules will be able to use the platform provided by this PR in order to integrate `product combos` in their flows. Such modules are the `point_of_sale` and `pos_self_order`. closes odoo/odoo#128857 Task: 3430635 Signed-off-by: Joseph Caburnay (jcb) --- addons/point_of_sale/__manifest__.py | 1 + addons/point_of_sale/models/__init__.py | 2 + addons/point_of_sale/models/pos_combo.py | 25 +++++++++++ addons/point_of_sale/models/pos_combo_line.py | 11 +++++ addons/point_of_sale/models/product.py | 1 + .../security/ir.model.access.csv | 4 ++ addons/point_of_sale/views/pos_combo_view.xml | 41 +++++++++++++++++++ addons/point_of_sale/views/product_view.xml | 6 +++ 8 files changed, 91 insertions(+) create mode 100644 addons/point_of_sale/models/pos_combo.py create mode 100644 addons/point_of_sale/models/pos_combo_line.py create mode 100644 addons/point_of_sale/views/pos_combo_view.xml diff --git a/addons/point_of_sale/__manifest__.py b/addons/point_of_sale/__manifest__.py index 351ca106e87..c275471a0c9 100644 --- a/addons/point_of_sale/__manifest__.py +++ b/addons/point_of_sale/__manifest__.py @@ -23,6 +23,7 @@ 'views/point_of_sale_view.xml', 'views/pos_order_view.xml', 'views/pos_category_view.xml', + 'views/pos_combo_view.xml', 'views/product_view.xml', 'views/account_journal_view.xml', 'views/pos_payment_method_views.xml', diff --git a/addons/point_of_sale/models/__init__.py b/addons/point_of_sale/models/__init__.py index c71d05f2c84..676f237afe6 100644 --- a/addons/point_of_sale/models/__init__.py +++ b/addons/point_of_sale/models/__init__.py @@ -13,6 +13,8 @@ from . import pos_category from . import pos_config from . import pos_order from . import pos_session +from . import pos_combo +from . import pos_combo_line from . import product from . import res_partner from . import res_company diff --git a/addons/point_of_sale/models/pos_combo.py b/addons/point_of_sale/models/pos_combo.py new file mode 100644 index 00000000000..74e627c4e24 --- /dev/null +++ b/addons/point_of_sale/models/pos_combo.py @@ -0,0 +1,25 @@ +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError + +class PosCombo(models.Model): + """ + This model is used to allow the pos user to create menus. + This means that products can be grouped together and sold as a combo. + """ + _name = "pos.combo" + _description = "Product combo choices" + + name = fields.Char(string="Name", required=True) + combo_line_ids = fields.One2many("pos.combo.line", "combo_id", string="Products in Combo") + num_of_products = fields.Integer("No of Products", compute="_compute_num_of_products") + + @api.depends("combo_line_ids") + def _compute_num_of_products(self): + # optimization trick to count the number of products in each combo + for rec, num_of_products in self.env["pos.combo.line"]._read_group([("combo_id", "in", self.ids)], groupby=["combo_id"], aggregates=["__count"]): + rec.num_of_products = num_of_products + + @api.constrains("combo_line_ids") + def _check_combo_line_ids_is_not_null(self): + if any(not rec.combo_line_ids for rec in self): + raise ValidationError(_("Please add products in combo.")) diff --git a/addons/point_of_sale/models/pos_combo_line.py b/addons/point_of_sale/models/pos_combo_line.py new file mode 100644 index 00000000000..6293b2a427a --- /dev/null +++ b/addons/point_of_sale/models/pos_combo_line.py @@ -0,0 +1,11 @@ +from odoo import fields, models + + +class PosComboLine(models.Model): + _name = "pos.combo.line" + _description = "Product Combo Items" + + product_id = fields.Many2one("product.product", string="Product") + price = fields.Float("Price Extra", default=0.0) + lst_price = fields.Float("Original Price", related="product_id.lst_price") + combo_id = fields.Many2one("pos.combo") diff --git a/addons/point_of_sale/models/product.py b/addons/point_of_sale/models/product.py index 99f3b0e3869..d694bec80f2 100644 --- a/addons/point_of_sale/models/product.py +++ b/addons/point_of_sale/models/product.py @@ -15,6 +15,7 @@ class ProductTemplate(models.Model): pos_categ_ids = fields.Many2many( 'pos.category', string='Point of Sale Category', help="Category used in the Point of Sale.") + combo_ids = fields.Many2many('pos.combo', string='Combinations') @api.ondelete(at_uninstall=False) def _unlink_except_open_session(self): diff --git a/addons/point_of_sale/security/ir.model.access.csv b/addons/point_of_sale/security/ir.model.access.csv index 41b5594da75..9dbd50ab155 100644 --- a/addons/point_of_sale/security/ir.model.access.csv +++ b/addons/point_of_sale/security/ir.model.access.csv @@ -47,6 +47,10 @@ access_decimal_precision_user,decimal.precision,base.model_decimal_precision,gro access_pos_payment_user,pos.payment user,model_pos_payment,group_pos_user,1,1,1,1 access_pos_payment_method_user,pos.payment.method user,model_pos_payment_method,group_pos_user,1,0,0,0 access_pos_payment_method_manager,pos.payment.method manager,model_pos_payment_method,group_pos_manager,1,1,1,1 +access_pos_combo_manager,pos.combo manager,model_pos_combo,group_pos_manager,1,1,1,1 +access_pos_combo_user,pos.combo user,model_pos_combo,group_pos_user,1,0,0,0 +access_pos_combo_line_manager,pos.combo.line manager,model_pos_combo_line,group_pos_manager,1,1,1,1 +access_pos_combo_line_user,pos.combo.line user,model_pos_combo_line,group_pos_user,1,0,0,0 access_pos_details_wizard,access.pos.details.wizard,model_pos_details_wizard,point_of_sale.group_pos_manager,1,1,1,0 access_pos_make_payment,access.pos.make.payment,model_pos_make_payment,point_of_sale.group_pos_manager,1,1,1,0 access_pos_close_session_wizard,access.pos.close.session.wizard,model_pos_close_session_wizard,point_of_sale.group_pos_user,1,1,1,0 diff --git a/addons/point_of_sale/views/pos_combo_view.xml b/addons/point_of_sale/views/pos_combo_view.xml new file mode 100644 index 00000000000..386e3325b42 --- /dev/null +++ b/addons/point_of_sale/views/pos_combo_view.xml @@ -0,0 +1,41 @@ + + + + pos.combo.form + pos.combo + +
+
+
+ + + + + + + +
+
+
+ + + pos.combo.tree + pos.combo + + + + + + + + + + Combo Choices + pos.combo + tree,form + +
diff --git a/addons/point_of_sale/views/product_view.xml b/addons/point_of_sale/views/product_view.xml index 66003b96b5a..e63cd4bea57 100644 --- a/addons/point_of_sale/views/product_view.xml +++ b/addons/point_of_sale/views/product_view.xml @@ -69,6 +69,7 @@ + @@ -88,6 +89,11 @@ action="product_product_action" groups="product.group_product_variant" sequence="10"/> +