Skip to content

[ADD] new_product_type: Added sub-products to a particular product #833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: 18.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions new_producttype/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizard
18 changes: 18 additions & 0 deletions new_producttype/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
'name': "New Product Type",
'category': '',
'version': '0.1',
'depends': ['sale'],
'sequence': 1,
'application': True,
'installable': True,
'data': [
"security/ir.model.access.csv",
"report/sub_product_report.xml",
"wizard/sub_product_kit_wizard_view.xml",
"views/product_views.xml",
"views/sale_order_view.xml",
"views/sub_product_customer_preview.xml",
],
'license': 'AGPL-3'
}
3 changes: 3 additions & 0 deletions new_producttype/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import product_template
from . import sale_order_line
from . import sale_order
25 changes: 25 additions & 0 deletions new_producttype/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from odoo import fields, models, api
from odoo.exceptions import ValidationError


class ProductTemplate(models.Model):
_inherit = 'product.template'

is_kit = fields.Boolean(default=False, string='Is kit')
sub_products_ids = fields.Many2many('product.product', string='Sub products')

@api.constrains("sub_products_ids")
def check_sub_product_not_itself(self):
for record in self:
if record.id in record.sub_products_ids.mapped("product_tmpl_id.id"):
raise ValidationError(
"A product cannot be added as its own sub-product"
)

@api.constrains("sub_products_ids", "is_kit")
def check_sub_product(self):
for record in self:
if record.is_kit and not record.sub_products_ids:
raise ValidationError(
"A kit product must have at least one sub-product"
)
7 changes: 7 additions & 0 deletions new_producttype/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from odoo import models, fields


class SaleOrder(models.Model):
_inherit = 'sale.order'

print_report = fields.Boolean(string="Print in Report")
23 changes: 23 additions & 0 deletions new_producttype/models/sale_order_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from odoo import fields, models


class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'

is_kit = fields.Boolean(string='Is kit', related='product_id.is_kit')
main_product_line_id = fields.Many2one("sale.order.line", ondelete="cascade")
sub_products_ids = fields.Many2many(
"product.product",
related="product_template_id.sub_products_ids",
string="Sub Products",
)
last_price = fields.Float()

def action_open_kit_wizard(self):
return {
'type': 'ir.actions.act_window',
'name': 'sub.product.kit.wizard.view',
'res_model': 'sub.product.kit.wizard',
'view_mode': 'form',
'target': 'new',
}
8 changes: 8 additions & 0 deletions new_producttype/report/sub_product_report.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="report_sub_product_template" inherit_id="sale.report_saleorder_document">
<xpath expr="//tbody[@class='sale_tbody']/t/tr" position="attributes">
<attribute name="t-if">(doc.print_report) or (not line.main_product_line_id)</attribute>
</xpath>
</template>
</odoo>
3 changes: 3 additions & 0 deletions new_producttype/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sub_product_kit_wizard,access_sub_product_kit_wizard,model_sub_product_kit_wizard,base.group_user,1,1,1,1
access_sub_product_line_kit_wizard,access_sub_product_line_kit_wizard,model_sub_product_line_kit_wizard,base.group_user,1,1,1,1
14 changes: 14 additions & 0 deletions new_producttype/views/product_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="product_template_form_view_inherit" model="ir.ui.view">
<field name="name">product.template.form.view.inherit</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page//group[@name='group_general']" position="inside">
<field name="is_kit"/>
<field name="sub_products_ids" widget="many2many_tags" invisible="is_kit == False"/>
</xpath>
</field>
</record>
</odoo>
35 changes: 35 additions & 0 deletions new_producttype/views/sale_order_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_order_form_inherit_sub_product" model="ir.ui.view">
<field name="name">view.order.form.inherit.sub.product</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//list//field[@name='product_template_id']" position="after">
<button name="action_open_kit_wizard"
type="object"
string="Add Sub-Products"
invisible="not is_kit or state=='sale' or main_product_line_id"
/>
</xpath>
<xpath expr="//field[@name='order_line']/list" position="attributes">
<attribute name="decoration-warning">main_product_line_id</attribute>
</xpath>
<xpath expr="//list//field[@name='product_template_id']" position="attributes">
<attribute name="readonly">main_product_line_id</attribute>
</xpath>
<xpath expr="//list//field[@name='product_uom_qty']" position="attributes">
<attribute name="readonly">main_product_line_id</attribute>
</xpath>
<xpath expr="//list//field[@name='price_unit']" position="attributes">
<attribute name="readonly">main_product_line_id</attribute>
</xpath>
<xpath expr="//list//field[@name='tax_id']" position="attributes">
<attribute name="readonly">main_product_line_id</attribute>
</xpath>
<xpath expr="//group//field[@name='payment_term_id']" position="after">
<field name="print_report"/>
</xpath>
</field>
</record>
</odoo>
8 changes: 8 additions & 0 deletions new_producttype/views/sub_product_customer_preview.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="sale_portal_templates_report_inherited" inherit_id="sale.sale_order_portal_content">
<xpath expr="//table[@id='sales_order_table']/tbody/t/tr" position="attributes">
<attribute name="t-if">(sale_order.print_report) or (not line.main_product_line_id)</attribute>
</xpath>
</template>
</odoo>
2 changes: 2 additions & 0 deletions new_producttype/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import sub_product_kit_wizard
from . import sub_product_line_kit_wizard
76 changes: 76 additions & 0 deletions new_producttype/wizard/sub_product_kit_wizard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from odoo import fields, models, api, Command


class SubProductKitWizard(models.TransientModel):
_name = 'sub.product.kit.wizard'

sale_order_line_id = fields.Many2one('sale.order.line', required=True)
sub_products_ids = fields.One2many('sub.product.line.kit.wizard', 'sub_products_line_id')

@api.model
def default_get(self, fields_list):
res = super().default_get(fields_list)
sale_order_line_id = self._context.get("active_id")
if sale_order_line_id:
sale_order_line = self.env["sale.order.line"].browse(sale_order_line_id)
existing_lines = self.env["sale.order.line"].search(
[("main_product_line_id", "=", sale_order_line_id)]
)
line_values = []
if existing_lines:
for sub_product in existing_lines:
curr_product = self.env["sub.product.line.kit.wizard"].create(
{
"product_id": sub_product.product_id.id,
"price": sub_product.price_unit,
"quantity": sub_product.product_uom_qty,
}
)
line_values.append(Command.link(curr_product.id))
else:
for sub_product in sale_order_line.product_id.sub_products_ids:
curr_product = self.env["sub.product.line.kit.wizard"].create(
{
"product_id": sub_product.id,
"price": sub_product.list_price,
"quantity": 1,
}
)
line_values.append(Command.link(curr_product.id))
res["sub_products_ids"] = line_values
res["sale_order_line_id"] = sale_order_line_id
return res

def action_confirm(self):
total_of_sub_product_price = 0
for rec in self.sub_products_ids:
existing_lines = self.env["sale.order.line"].search(
[
("main_product_line_id", "=", self.sale_order_line_id.id),
("product_id", "=", rec.product_id.id),
("order_id", "=", self.sale_order_line_id.order_id.id)
],
limit=1,
)
if existing_lines:
existing_lines.product_uom_qty = rec.quantity
existing_lines.last_price = rec.price
existing_lines.price_unit = 0
else:
self.env["sale.order.line"].create(
{
"order_id": self.sale_order_line_id.order_id.id,
"product_id": rec.product_id.id,
"product_uom_qty": rec.quantity,
"last_price": rec.price,
"price_unit": 0,
"main_product_line_id": self.sale_order_line_id.id,
}
)
total_of_sub_product_price += (rec.quantity * rec.price)
total_of_sub_product_price += (
self.sale_order_line_id.product_uom_qty
* self.sale_order_line_id.product_template_id.list_price
)
self.sale_order_line_id.price_unit = total_of_sub_product_price
return True
24 changes: 24 additions & 0 deletions new_producttype/wizard/sub_product_kit_wizard_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="sub_product_kit_wizard_view" model="ir.ui.view">
<field name="name">sub.product.kit.wizard.view</field>
<field name="model">sub.product.kit.wizard</field>
<field name="arch" type="xml">
<form string="Sub-Products">
<sheet>
<field name="sub_products_ids">
<list create="false" editable="bottom">
<field name="product_id" readonly="1"/>
<field name="quantity"/>
<field name="price"/>
</list>
</field>
<footer>
<button name="action_confirm" class="btn btn-primary" type="object" string="Confirm"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
</odoo>
10 changes: 10 additions & 0 deletions new_producttype/wizard/sub_product_line_kit_wizard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from odoo import fields, models


class SubProductLineKitWizard(models.TransientModel):
_name = 'sub.product.line.kit.wizard'

sub_products_line_id = fields.Many2one('sub.product.kit.wizard')
product_id = fields.Many2one('product.product', required=True)
quantity = fields.Float(default=0.0)
price = fields.Float(default=0)