Skip to content

Commit f630036

Browse files
committed
[ADD] Rental Deposit: Configure and Display Deposit for Rental Products
In this commit: - Added option to set a deposit product from configuration - Introduced checkbox to enable deposit for rental products - Added a field to specify the deposit amount - Inherited sale order line to auto-add deposit line when rental product added - Synced deposit quantity with rental product quantity - Displayed deposit amount on the product page in the website - Shown deposit details with amount in the shopping cart
1 parent 4c650f3 commit f630036

12 files changed

+218
-0
lines changed

deposit_in_rental_app/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import models
2+
from . import tests

deposit_in_rental_app/__manifest__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
'name': 'Rental Deposit',
3+
'installable': True,
4+
'license': 'LGPL-3',
5+
'depends': ['sale_renting', 'website_sale_renting'],
6+
'data': [
7+
'views/res_config_settings_views.xml',
8+
'views/product_template_views.xml',
9+
'views/templates.xml',
10+
],
11+
12+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from . import res_config_settings
2+
from . import product_template
3+
from . import sale_order_line
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from odoo import fields, models
2+
3+
4+
class ProductTemplate(models.Model):
5+
_inherit = 'product.template'
6+
7+
require_deposit = fields.Boolean(string='Require Deposit', default=False)
8+
deposit_amount = fields.Float(string='Amount')
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from odoo import fields, models
2+
3+
4+
class ResConfigSettings(models.TransientModel):
5+
_inherit = 'res.config.settings'
6+
7+
deposit_product_id = fields.Many2one('product.product', string='Deposit', config_parameter='deposit_in_rental_app.deposit_product_id')
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from odoo import api, fields, models
2+
from odoo.exceptions import UserError
3+
4+
5+
class SaleOrderLine(models.Model):
6+
_inherit = 'sale.order.line'
7+
8+
is_deposit_line = fields.Boolean(default=False)
9+
parent_id = fields.Many2one(comodel_name="sale.order.line", ondelete='cascade', copy=False)
10+
child_ids = fields.One2many(comodel_name="sale.order.line", inverse_name="parent_id", copy=False)
11+
12+
@api.model_create_multi
13+
def create(self, vals_list):
14+
res = super().create(vals_list)
15+
# fetch deposit product name from ip.config.setting
16+
deposit_product_id = self.env["ir.config_parameter"].sudo().get_param("deposit_in_rental_app.deposit_product_id")
17+
18+
if not deposit_product_id:
19+
raise UserError("Set deposit product from setting")
20+
21+
for line in res:
22+
# If product line product is deposit enable create new deposit line
23+
if line.product_id.require_deposit and line.product_id.deposit_amount:
24+
deposit_order_line = self.env['sale.order.line'].create({
25+
"order_id": line.order_id.id,
26+
"product_id": int(deposit_product_id),
27+
"name": f"Deposit for {line.product_id.name}",
28+
"product_uom_qty": line.product_uom_qty,
29+
"price_unit": line.product_template_id.deposit_amount,
30+
"parent_id": line.id,
31+
"sequence": line.sequence + 1,
32+
"is_deposit_line": True,
33+
})
34+
35+
if not deposit_order_line:
36+
raise UserError("Something went wrong!!")
37+
38+
return res
39+
40+
def write(self, vals):
41+
res = super().write(vals)
42+
# Update quantity if deposit order line is already created
43+
if 'product_uom_qty' in vals:
44+
for line in self:
45+
if line.child_ids:
46+
line.child_ids.write({
47+
"product_uom_qty": vals['product_uom_qty'],
48+
"price_unit": line.child_ids.price_unit
49+
})
50+
return res
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import test_deposit_rental
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
from odoo.tests import tagged
2+
from odoo.tests.common import TransactionCase
3+
from odoo.fields import Command
4+
from odoo.exceptions import UserError
5+
6+
@tagged('post_install', '-at_install')
7+
class RentalDepositTestCase(TransactionCase):
8+
def setUp(self):
9+
super(RentalDepositTestCase, self).setUp()
10+
11+
self.partner = self.env['res.partner'].create({
12+
'name': 'Test Partner',
13+
})
14+
15+
self.deposit_product = self.env['product.product'].create({
16+
'name': 'Deposit Product',
17+
'rent_ok': True
18+
})
19+
20+
self.rental_product = self.env['product.product'].create({
21+
'name': 'Music System',
22+
'type': 'consu',
23+
'require_deposit': True,
24+
'deposit_amount': 100.0
25+
})
26+
27+
self.sale_order = self.env['sale.order'].create({'partner_id': self.partner.id})
28+
29+
def test_configure_deposit_product(self):
30+
31+
with self.assertRaises(UserError, msg="Should raise error if deposit product is not configured"):
32+
self.sale_order.write({
33+
"order_line": [
34+
Command.create({'product_id': self.rental_product.id, 'product_uom_qty': 2}),
35+
]
36+
})
37+
38+
def test_deposit_line(self):
39+
40+
self.env['ir.config_parameter'].sudo().set_param('deposit_in_rental_app.deposit_product_id', self.deposit_product.id)
41+
42+
self.sale_order.write({
43+
"order_line": [
44+
Command.create({'product_id': self.rental_product.id, 'product_uom_qty': 2}),
45+
]
46+
})
47+
48+
main_line = self.sale_order.order_line.filtered(lambda l: not l.is_deposit_line)
49+
deposit_line = self.sale_order.order_line.filtered(lambda l: l.is_deposit_line)
50+
51+
# Check deposit line is created or not
52+
self.assertTrue(deposit_line, "Deposit line was not created.")
53+
54+
# Check deposit line is correctly linked
55+
self.assertIn(deposit_line[0], main_line.child_ids, "Deposit line is not in child_ids of main line.")
56+
self.assertEqual(deposit_line[0].parent_id, main_line[0], "Deposit line's parent_id does not point to the main line.")
57+
58+
main_line.write({'product_uom_qty': 5})
59+
60+
# Check deposit line quantity is also updated
61+
self.assertEqual(
62+
deposit_line.product_uom_qty, 5,
63+
"Deposit line quantity should update when main line quantity changes"
64+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0"?>
2+
<odoo>
3+
4+
<record id="product_template_form_view" model="ir.ui.view">
5+
<field name="name">product.template.form.view.inherit.deposit.in.rental.app</field>
6+
<field name="model">product.template</field>
7+
<field name="inherit_id" ref="product.product_template_form_view" />
8+
<field name="arch" type="xml">
9+
<xpath expr="//group[@name='extra_rental']" position="inside">
10+
<field name="require_deposit" />
11+
<field name="deposit_amount" invisible="not require_deposit" widget="monetary" />
12+
</xpath>
13+
</field>
14+
</record>
15+
16+
</odoo>

0 commit comments

Comments
 (0)