From e9d5bc3c4221f6e143b0ffd0b07993bc64ccb710 Mon Sep 17 00:00:00 2001 From: abkus-odoo Date: Wed, 16 Sep 2026 17:46:51 +0530 Subject: [PATCH] [ADD] new_product_type: allow configurable kit products Standard Odoo requires the Manufacturing (MRP) and Bill of Materials (BoM) modules to handle kit products. Users who only do trading or pure sales without manufacturing need a lightweight way to sell product bundles, manage their pricing dynamically, and control their visibility on invoices without overhead. WHAT: -Added a new product type for kits without requiring MRP dependencies. -Created a configuration wizard on sale order lines to manage kit items, quantities, and pricing before order confirmation. -Implemented parent-child relationships between sale order lines to link kit products with their sub-products. -Made sub-product lines readonly and protected them from direct deletion to maintain data integrity. -Updated sale order, portal, and invoice reports with a dedicated option to show or hide kit sub-products. --- new_product_type/__init__.py | 2 + new_product_type/__manifest__.py | 14 +++++ new_product_type/models/__init__.py | 2 + new_product_type/models/product_template.py | 8 +++ new_product_type/models/sale_order_line.py | 32 ++++++++++ new_product_type/security/ir.model.access.csv | 3 + .../views/product_kit_wizard_views.xml | 25 ++++++++ new_product_type/views/product_views.xml | 17 ++++++ .../views/sale_order_line_views.xml | 20 +++++++ new_product_type/wizard/__init__.py | 2 + new_product_type/wizard/product_kit_wizard.py | 59 +++++++++++++++++++ .../wizard/product_kit_wizard_line.py | 24 ++++++++ 12 files changed, 208 insertions(+) create mode 100644 new_product_type/__init__.py create mode 100644 new_product_type/__manifest__.py create mode 100644 new_product_type/models/__init__.py create mode 100644 new_product_type/models/product_template.py create mode 100644 new_product_type/models/sale_order_line.py create mode 100644 new_product_type/security/ir.model.access.csv create mode 100644 new_product_type/views/product_kit_wizard_views.xml create mode 100644 new_product_type/views/product_views.xml create mode 100644 new_product_type/views/sale_order_line_views.xml create mode 100644 new_product_type/wizard/__init__.py create mode 100644 new_product_type/wizard/product_kit_wizard.py create mode 100644 new_product_type/wizard/product_kit_wizard_line.py diff --git a/new_product_type/__init__.py b/new_product_type/__init__.py new file mode 100644 index 00000000000..9b4296142f4 --- /dev/null +++ b/new_product_type/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/new_product_type/__manifest__.py b/new_product_type/__manifest__.py new file mode 100644 index 00000000000..5ae68a935bf --- /dev/null +++ b/new_product_type/__manifest__.py @@ -0,0 +1,14 @@ +{ + "name": "New Product Type", + "version": "1.0", + 'author': "abkus", + "depends": ["sale", "product"], + "data": [ + "security/ir.model.access.csv", + "views/product_kit_wizard_views.xml", + "views/product_views.xml", + "views/sale_order_line_views.xml", + ], + "installable": True, + 'license': 'LGPL-3', +} diff --git a/new_product_type/models/__init__.py b/new_product_type/models/__init__.py new file mode 100644 index 00000000000..83527162d00 --- /dev/null +++ b/new_product_type/models/__init__.py @@ -0,0 +1,2 @@ +from . import product_template +from . import sale_order_line diff --git a/new_product_type/models/product_template.py b/new_product_type/models/product_template.py new file mode 100644 index 00000000000..aea78ba4aad --- /dev/null +++ b/new_product_type/models/product_template.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + is_kit = fields.Boolean() + sub_product_ids = fields.Many2many('product.product') diff --git a/new_product_type/models/sale_order_line.py b/new_product_type/models/sale_order_line.py new file mode 100644 index 00000000000..19ff7754b83 --- /dev/null +++ b/new_product_type/models/sale_order_line.py @@ -0,0 +1,32 @@ +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + + is_kit = fields.Boolean( + related="product_id.product_tmpl_id.is_kit", + store=True + ) + is_kit_product = fields.Boolean() + kit_parent_line_id = fields.Many2one('sale.order.line', ondelete='cascade') + extra_price = fields.Float(default=0.0) + + @api.ondelete(at_uninstall=False) + def _check_kit_product_restriction(self): + for line in self: + if line.is_kit_product: + raise UserError(_("You can't direclty delete the sub product")) + + def action_open_kit_wizard(self): + return { + "type": "ir.actions.act_window", + "name": "Configure Kit", + "res_model": "product.kit.wizard", + "view_mode": "form", + "target": "new", + "context": { + "active_id": self.id + }, + } diff --git a/new_product_type/security/ir.model.access.csv b/new_product_type/security/ir.model.access.csv new file mode 100644 index 00000000000..7219eb233fb --- /dev/null +++ b/new_product_type/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_create,perm_write,perm_unlink +access_product_wizard_kit_line,access_product_wizard_kit_line,model_product_wizard_kit_line,base.group_user,1,1,1,1 +access_product_kit_wizard,access_product_kit_wizard,model_product_kit_wizard,base.group_user,1,1,1,1 diff --git a/new_product_type/views/product_kit_wizard_views.xml b/new_product_type/views/product_kit_wizard_views.xml new file mode 100644 index 00000000000..4f3f826f16a --- /dev/null +++ b/new_product_type/views/product_kit_wizard_views.xml @@ -0,0 +1,25 @@ + + + + product.kit.wizard.form + product.kit.wizard + +
+ + + + + + + + + + + + + + +
+
+
+
diff --git a/new_product_type/views/product_views.xml b/new_product_type/views/product_views.xml new file mode 100644 index 00000000000..c69ce243fb9 --- /dev/null +++ b/new_product_type/views/product_views.xml @@ -0,0 +1,17 @@ + + + + product.template.view_form + product.template + + + + + + + + + + + diff --git a/new_product_type/views/sale_order_line_views.xml b/new_product_type/views/sale_order_line_views.xml new file mode 100644 index 00000000000..2a5288d5afe --- /dev/null +++ b/new_product_type/views/sale_order_line_views.xml @@ -0,0 +1,20 @@ + + + + sale.order.line.form.view + sale.order + + + + is_kit_product + + +