Skip to content

Commit 42acd0c

Browse files
committed
[IMP] Product Kit : Added a new product type
In this commit we have introduced following changes: - Updated unlink method to delete all subproducts if main product is deleted. - Updated both sales and invoice reports to print subproducts or not based on a boolean field 'print_kit'.
1 parent e41522d commit 42acd0c

12 files changed

+109
-30
lines changed

Diff for: product_kit/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from . import models
1+
from . import models

Diff for: product_kit/__manifest__.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
'depends': [
1010
'base',
1111
'stock',
12-
'sale_management'
12+
'sale_management',
13+
'account'
1314
],
14-
'data' : [
15+
'data': [
1516
'views/product_template_views.xml',
1617
'views/sale_order_views.xml',
1718
'views/kit_products_wizard_views.xml',
1819
'security/ir.model.access.csv',
20+
'views/sale_order_report.xml',
21+
'views/account_move_views.xml',
1922
]
20-
}
23+
}

Diff for: product_kit/models/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from . import product_template
22
from . import sale_order_line
33
from . import kit_products_wizard_line
4-
from . import kit_products_wizard
4+
from . import kit_products_wizard
5+
from . import sale_order
6+
from . import account_move

Diff for: product_kit/models/account_move.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from odoo import models, fields
2+
3+
4+
class AccountMove(models.Model):
5+
_inherit = "account.move"
6+
7+
sale_id = fields.Many2one('sale.order', string="Sale Order", compute='_compute_sale_id', store=True, readonly=True)
8+
print_kit = fields.Boolean(related="sale_id.print_kit", readonly=True)
9+
from_wizard = fields.Boolean(related="line_ids.sale_line_ids.from_wizard", store=True, readonly=True)
10+
11+
def _compute_sale_id(self):
12+
for move in self:
13+
sale_orders = move.line_ids.mapped("sale_line_ids.order_id")
14+
move.sale_id = sale_orders and sale_orders[0] or False

Diff for: product_kit/models/kit_products_wizard.py

+32-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from odoo import models, fields, api
22

3+
34
class KitProductsWizard(models.TransientModel):
45
_name = "kit.products.wizard"
56
_description = "Kit Products Wizard"
@@ -33,13 +34,13 @@ def default_get(self, fields_list):
3334
kit_product_vals.append((0, 0, {
3435
"product_id": line.product_id.id,
3536
"product_qty": line.product_uom_qty,
36-
"price_unit": line.product_id.list_price,
37+
"price_unit": line.product_id.list_price,
3738
}))
3839
else:
3940
for kit_product in product_template.kit_product_ids:
4041
kit_product_vals.append((0, 0, {
4142
"product_id": kit_product.id,
42-
"product_qty": 1,
43+
"product_qty": 1,
4344
"price_unit": kit_product.list_price,
4445
}))
4546

@@ -48,40 +49,52 @@ def default_get(self, fields_list):
4849
return res
4950

5051
def action_generate_order_lines(self):
51-
"""Creates sale order lines for each kit product in the wizard"""
52+
"""Updates or creates sale order lines for each kit product in the wizard"""
5253
self.ensure_one()
5354

5455
main_product_line = self.env["sale.order.line"].search([
5556
("order_id", "=", self.sale_order_id.id),
56-
("product_id", "in", self.product_template_id.product_variant_ids.ids),
57+
("product_id", "in", self.product_template_id.product_variant_ids.ids),
5758
], limit=1)
58-
# breakpoint()
59-
original_price = main_product_line.price_unit if main_product_line else self.product_template_id.list_price
6059

61-
total_price = original_price
60+
original_price = self.product_template_id.list_price
61+
total_price = original_price
6262

6363
for kit_product in self.kit_product_ids:
64+
existing_line = self.env["sale.order.line"].search([
65+
("order_id", "=", self.sale_order_id.id),
66+
("product_id", "=", kit_product.product_id.id),
67+
("from_wizard", "=", True),
68+
], limit=1)
6469

65-
sub_total = kit_product.product_qty * kit_product.price_unit
70+
sub_total = kit_product.product_qty * kit_product.product_id.list_price
6671
total_price += sub_total
67-
self.env["sale.order.line"].create({
68-
"name": kit_product.product_id.name,
69-
"order_id": self.sale_order_id.id,
70-
"product_id": kit_product.product_id.id,
71-
"product_uom_qty": kit_product.product_qty,
72-
"price_unit": 0.00,
73-
"from_wizard": True,
74-
})
72+
73+
if existing_line:
74+
existing_line.write({
75+
"product_uom_qty": kit_product.product_qty,
76+
"price_unit": 0.00, # Ensure sub-products remain zero-priced
77+
})
78+
else:
79+
self.env["sale.order.line"].create({
80+
"name": kit_product.product_id.name,
81+
"order_id": self.sale_order_id.id,
82+
"product_id": kit_product.product_id.id,
83+
"product_uom_qty": kit_product.product_qty,
84+
"price_unit": 0.00,
85+
"from_wizard": True,
86+
})
7587

7688
if main_product_line:
7789
main_product_line.price_unit = total_price * main_product_line.product_uom_qty
7890
else:
7991
self.env["sale.order.line"].create({
8092
"order_id": self.sale_order_id.id,
8193
"product_id": self.product_template_id.product_variant_id.id,
82-
"product_uom_qty": 1,
83-
"price_unit": total_price,
94+
"product_uom_qty": 1,
95+
"price_unit": total_price,
8496
"name": self.product_template_id.name,
85-
})
97+
})
8698

8799
return {"type": "ir.actions.act_window_close"}
100+

Diff for: product_kit/models/kit_products_wizard_line.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from odoo import models, fields
22

3+
34
class KitProductsWizardLine(models.TransientModel):
45
_name = "kit.products.wizard.line"
56
_description = "Kit Products Wizard Line"
@@ -8,5 +9,3 @@ class KitProductsWizardLine(models.TransientModel):
89
product_id = fields.Many2one("product.product", string="Product")
910
product_qty = fields.Float(string="Quantity")
1011
price_unit = fields.Float(string="Price")
11-
12-

Diff for: product_kit/models/product_template.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from odoo import models, fields
22

3+
34
class ProductTemplate(models.Model):
45
_inherit = 'product.template'
56

67
is_kit = fields.Boolean(string="Is Kit")
78
kit_product_ids = fields.Many2many(
8-
'product.product',
9+
'product.product',
910
string="Sub Products"
10-
)
11+
)

Diff for: product_kit/models/sale_order.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from odoo import models, fields
2+
3+
4+
class SaleOrder(models.Model):
5+
_inherit = "sale.order"
6+
7+
print_kit = fields.Boolean(string="Print in report", default=True)

Diff for: product_kit/models/sale_order_line.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ class SaleOrderLine(models.Model):
77
is_kit = fields.Boolean(related="product_template_id.is_kit", store=True)
88
from_wizard = fields.Boolean(string="Created from Wizard", default=False)
99

10-
1110
def action_open_kit_wizard(self):
1211
"""Opens the wizard with Sale Order ID in context"""
1312
return {
@@ -17,7 +16,21 @@ def action_open_kit_wizard(self):
1716
"view_mode": "form",
1817
"target": "new",
1918
"context": {
20-
"default_sale_order_id": self.order_id.id,
19+
"default_sale_order_id": self.order_id.id,
2120
"default_product_template_id": self.product_template_id.id,
2221
}
2322
}
23+
24+
def unlink(self):
25+
"""Delete only the related wizard-generated sale order lines when a main product line is deleted."""
26+
main_product_lines = self.filtered(lambda line: not line.from_wizard)
27+
28+
for main_line in main_product_lines:
29+
kit_lines = self.search([
30+
("order_id", "=", main_line.order_id.id),
31+
("from_wizard", "=", True),
32+
("product_id", "in", main_line.product_id.kit_product_ids.ids),
33+
])
34+
kit_lines.unlink()
35+
36+
return super().unlink()

Diff for: product_kit/views/account_move_views.xml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<odoo>
3+
<template id="report_invoice_document" inherit_id="account.report_invoice_document">
4+
<xpath expr="//tbody/t[@t-foreach='lines']" position="attributes">
5+
<attribute name="t-if">line.move_id.sale_id.print_kit or not line.sale_line_ids.from_wizard</attribute>
6+
</xpath>
7+
</template>
8+
</odoo>
9+
<!-- //table[@name='invoice_line_table']//tbody[@hasclass('invoice_tbody')] -->

Diff for: product_kit/views/sale_order_report.xml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<odoo>
3+
<template id="report_saleorder_document_inherit" inherit_id="sale.sale_order_portal_content">
4+
<xpath expr="//table[@id='sales_order_table']//tbody[@class='sale_tbody']//t[@t-foreach='lines_to_report']" position="attributes">
5+
<attribute name="t-if">
6+
(sale_order.print_kit and line.from_wizard) or (not line.from_wizard)
7+
</attribute>
8+
</xpath>
9+
</template>
10+
<template id="report_saleorder_document" inherit_id="sale.report_saleorder_document">
11+
<xpath expr="//tbody/t[@t-foreach='lines_to_report']" position="attributes">
12+
<attribute name="t-if">doc.print_kit or not line.from_wizard</attribute>
13+
</xpath>
14+
</template>
15+
</odoo>

Diff for: product_kit/views/sale_order_views.xml

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
<field name="model">sale.order</field>
66
<field name="inherit_id" ref="sale.view_order_form"/>
77
<field name="arch" type="xml">
8+
<xpath expr="//field[@name='payment_term_id']" position="after">
9+
<field name="print_kit"/>
10+
</xpath>
811
<xpath expr="//field[@name='order_line']/list//field[@name='product_template_id']" position="after">
912
<button name="action_open_kit_wizard" type="object" string="+" class="oe_highlight"
1013
invisible = "not is_kit or state in ['sale']"/>

0 commit comments

Comments
 (0)