Skip to content
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 add_product_warranty/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizard
15 changes: 15 additions & 0 deletions add_product_warranty/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "Product Warranty",
"description": "Adds functionality to manage product warranties in sales orders and linking warranties to products",
"depends": ["sale_management"],
"data": [
"security/ir.model.access.csv",
"wizard/sale_order_add_warranty_views.xml",
"views/product_template_views.xml",
"views/sale_order_views.xml",
"views/warranty_configuration_views.xml",
"views/warranty_configuration_menus.xml",
],
"installable": True,
"license": "LGPL-3",
}
4 changes: 4 additions & 0 deletions add_product_warranty/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import warranty_configuration
from . import product_template
from . import sale_order_line
from . import sale_order
9 changes: 9 additions & 0 deletions add_product_warranty/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from odoo import fields, models


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

is_warranty_available = fields.Boolean(
help="Indicates if the product has an associated warranty option.",
)
50 changes: 50 additions & 0 deletions add_product_warranty/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from odoo import api, fields, models


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

show_warranty_button = fields.Boolean(
string="Show Warranty Button",
compute="_compute_show_warranty_button",
store=True
)

@api.depends("order_line")
def _compute_show_warranty_button(self):
for order in self:
show_button = False
for line in order.order_line:
# Check if this product has warranty available
if line.product_template_id.is_warranty_available:
# And there is no other line that links to this line as warranty
linked_as_warranty = any(
l.warranty_line_linked_with_so_line == line
for l in order.order_line
)
if not linked_as_warranty:
show_button = True
break # We can stop early if condition is satisfied

order.show_warranty_button = show_button

@api.onchange("order_line")
def _onchange_order_line(self):
original_line_ids = self._origin.order_line.ids

current_line_ids = self.order_line.ids

deleted_line_ids = list(set(original_line_ids) - set(current_line_ids))

if deleted_line_ids:
# Remove warranty lines linked to deleted lines
self.order_line = [
(
6,
0,
self.order_line.filtered(
lambda line: line.warranty_line_linked_with_so_line.id
not in deleted_line_ids
).ids,
)
]
9 changes: 9 additions & 0 deletions add_product_warranty/models/sale_order_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from odoo import fields, models


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

warranty_line_linked_with_so_line = fields.Many2one(
"sale.order.line", ondelete="cascade"
)
23 changes: 23 additions & 0 deletions add_product_warranty/models/warranty_configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from odoo import fields, models


class WarrantyConfiguration(models.Model):
_name = "warranty.configuration"
_description = "Warranty configuration for all products"

name = fields.Char(required=True)
period = fields.Integer(
string="Warranty Period (years)",
default=1,
help="Duration of the warranty period in year.",
)
percentage = fields.Float(
required=True,
help="Percentage of the product price to be charged for the warranty.",
)
product_id = fields.Many2one(
comodel_name="product.product",
string="Product",
required=True,
help="Product used to represent the warranty service.",
)
4 changes: 4 additions & 0 deletions add_product_warranty/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_warranty_configuration,warranty.configuration,model_warranty_configuration,base.group_user,1,1,1,1
access_sale_order_add_warranty,sale.order.add.warranty,model_sale_order_add_warranty,base.group_user,1,1,1,1
access_sale_order_add_warranty_line,sale.order.add.warranty.line,model_sale_order_add_warranty_line,base.group_user,1,1,1,1
15 changes: 15 additions & 0 deletions add_product_warranty/views/product_template_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="product_template_form_view" model="ir.ui.view">
<field name="name">product.template.form.view.inherit.add.prodcut.warranty</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[@name='sales']" position="inside">
<group>
<field name="is_warranty_available"/>
</group>
</xpath>
</field>
</record>
</odoo>
14 changes: 14 additions & 0 deletions add_product_warranty/views/sale_order_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="view_order_form" model="ir.ui.view">
<field name="name">view.order.form.inherit.add.product.warranty</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='order_lines']//button[@name='action_open_discount_wizard']" position="before">
<button name="add_product_warranty.action_open_warranty_wizard" string="Add Warranty"
class="btn btn-secondary" type="action" invisible="not show_warranty_button"/>
</xpath>
</field>
</record>
</odoo>
8 changes: 8 additions & 0 deletions add_product_warranty/views/warranty_configuration_menus.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<menuitem id="warranty_configuration_menu"
name="Warranty Configuration"
sequence="25"
parent="sale.menu_sale_config"
action="warranty_configuration_action"/>
</odoo>
29 changes: 29 additions & 0 deletions add_product_warranty/views/warranty_configuration_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="warranty_configuration_action" model="ir.actions.act_window">
<field name="name">Warranty Configuration</field>
<field name="res_model">warranty.configuration</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a warranty
</p>
<p>
Create warranty configurations to manage product warranties effectively.
</p>
</field>
</record>

<record id="warranty_configuration_view_list" model="ir.ui.view">
<field name="name">warranty.configuration.view.list</field>
<field name="model">warranty.configuration</field>
<field name="arch" type="xml">
<list string="Warranty Configurations" editable="bottom">
<field name="name"/>
<field name="product_id"/>
<field name="percentage"/>
<field name="period"/>
</list>
</field>
</record>
</odoo>
2 changes: 2 additions & 0 deletions add_product_warranty/wizard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import sale_order_add_warranty_line
from . import sale_order_add_warranty
72 changes: 72 additions & 0 deletions add_product_warranty/wizard/sale_order_add_warranty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from odoo import api, Command, fields, models


class SaleOrderAddWarranty(models.TransientModel):
_name = "sale.order.add.warranty"
_description = "Wizard to add warranty to sale order"

warranty_line_ids = fields.One2many(
comodel_name="sale.order.add.warranty.line",
inverse_name="wizard_id",
string="Warranty Lines",
help="Lines representing the warranties to be added to the sale order.",
)
sale_order_id = fields.Many2one(
comodel_name="sale.order",
string="Sale Order",
required=True,
)

@api.model
def default_get(self, fields):
res = super().default_get(fields)
sale_order = self.env["sale.order"].browse(self.env.context.get("active_id"))

warranty_lines = []
for line in sale_order.order_line:
has_warranty = (
self.env["sale.order.line"].search_count(
[("warranty_line_linked_with_so_line", "=", line.id)]
)
> 0
)
if line.product_template_id.is_warranty_available and not has_warranty:
warranty_lines.append(
{
"sale_order_line_id": line.id,
"product_id": line.product_id.id,
}
)

res.update(
{
"sale_order_id": sale_order.id,
"warranty_line_ids": [Command.clear()]
+ [Command.create(vals) for vals in warranty_lines],
}
)
return res

def action_add_warranty(self):
sale_order_lines = []
warranty_lines = self.warranty_line_ids.filtered(lambda l: l.warranty_id)

for line in warranty_lines:
sale_order_lines.append(
{
"order_id": self.sale_order_id.id,
"product_id": line.warranty_id.product_id.id,
"name": f" Extended Warranty, \n End Date: {line.end_date}",
"warranty_line_linked_with_so_line": line.sale_order_line_id.id,
"price_unit": (
line.sale_order_line_id.price_unit
* line.warranty_id.percentage
/ 100
),
"product_uom_qty": line.sale_order_line_id.product_uom_qty,
"sequence": line.sale_order_line_id.sequence,
}
)
if sale_order_lines:
self.env["sale.order.line"].create(sale_order_lines)
return
41 changes: 41 additions & 0 deletions add_product_warranty/wizard/sale_order_add_warranty_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from datetime import timedelta

from odoo import api, fields, models


class SaleOrderAddWarrantyLine(models.TransientModel):
_name = "sale.order.add.warranty.line"
_description = "Line representing a warranty to be added to the sale order"

wizard_id = fields.Many2one(
comodel_name="sale.order.add.warranty",
required=True,
ondelete="cascade",
)
sale_order_line_id = fields.Many2one(
comodel_name="sale.order.line",
required=True,
ondelete="cascade",
)
product_id = fields.Many2one(
comodel_name="product.product",
string="Product",
)
warranty_id = fields.Many2one(
comodel_name="warranty.configuration",
string="Warranty Configuration",
)
end_date = fields.Date(
string="End Date",
compute="_compute_end_date",
)

@api.depends("warranty_id")
def _compute_end_date(self):
for record in self:
if record.warranty_id:
record.end_date = fields.Date.context_today(record) + timedelta(
days=record.warranty_id.period * 365
)
else:
record.end_date = False
32 changes: 32 additions & 0 deletions add_product_warranty/wizard/sale_order_add_warranty_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="action_open_warranty_wizard" model="ir.actions.act_window">
<field name="name">Add Warranty</field>
<field name="res_model">sale.order.add.warranty</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>

<record id="sale_order_add_warranty_view_form" model="ir.ui.view">
<field name="name">sale.order.add.warranty.view.form</field>
<field name="model">sale.order.add.warranty</field>
<field name="arch" type="xml">
<form string="Add Warranty">
<group>
<field name="warranty_line_ids" nolabel="1">
<list editable="bottom" create="0">
<field name="sale_order_line_id" column_invisible="1"/>
<field name="product_id" readonly="1"/>
<field name="warranty_id" required="1"/>
<field name="end_date" readonly="1"/>
</list>
</field>
</group>
<footer>
<button string="Add" type="object" name="action_add_warranty" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>