Skip to content

Commit 09860e4

Browse files
committed
[ADD] rental_deposit: adding deposit to rental products.
- Added and fields on to allow per-product deposit configuration - Added on , exposed via config settings - Auto-add/update/delete deposit line on sale order via CRUD overrides - Blocked direct editing or deletion of deposit lines using context guards - Added deposit display on webshop product page with dynamic qty update
1 parent 781b590 commit 09860e4

11 files changed

Lines changed: 190 additions & 0 deletions

rental_deposit/__init__.py

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

rental_deposit/__manifest__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
'author': 'Aditi (adpaw)',
3+
'name': 'Deposit Rental App',
4+
'license': 'LGPL-3',
5+
'depends': ['sale_renting', 'website_sale'],
6+
'data': [
7+
'views/res_config_settings_view.xml',
8+
'views/product_template_view.xml',
9+
'views/template_view.xml'
10+
],
11+
'assets': {
12+
'web.assets_frontend': [
13+
'rental_deposit/static/src/deposit_amount.js',
14+
],
15+
},
16+
'installable': True,
17+
'auto_install': True,
18+
}

rental_deposit/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from . import res_config_settings
2+
from . import product_template
3+
from . import sale_order_line
4+
from . import res_company
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+
requires_deposit = fields.Boolean(string="Requires Deposit")
8+
deposit_amount = fields.Float()
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 ResCompany(models.Model):
5+
_inherit = "res.company"
6+
7+
deposit_product = fields.Many2one("product.product")
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from odoo import fields, models
2+
3+
4+
class ResConfigSettings(models.TransientModel):
5+
_inherit = 'res.config.settings'
6+
7+
deposit_product = fields.Many2one(
8+
"product.product",
9+
related="company_id.deposit_product",
10+
string="Deposit",
11+
readonly=False
12+
)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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+
10+
parent_rental_line_id = fields.Many2one(
11+
'sale.order.line',
12+
string="Parent Rental Line",
13+
ondelete="cascade",
14+
index=True
15+
)
16+
17+
@api.model_create_multi
18+
def create(self, vals_list):
19+
lines = super().create(vals_list)
20+
rental_lines = lines.filtered(
21+
lambda l: l.product_id.rent_ok
22+
and l.product_id.requires_deposit
23+
and l.product_id.deposit_amount > 0
24+
and not l.is_deposit_line
25+
)
26+
if not rental_lines:
27+
return lines
28+
company_map = {}
29+
for line in rental_lines:
30+
company = line.company_id
31+
if company not in company_map:
32+
if not company.deposit_product:
33+
raise UserError("Please set deposit product in settings.")
34+
company_map[company] = company.deposit_product
35+
deposit_vals = []
36+
for line in rental_lines:
37+
deposit_product = company_map[line.company_id]
38+
deposit_vals.append({
39+
'order_id': line.order_id.id,
40+
'product_id': deposit_product.id,
41+
'product_uom_qty': line.product_uom_qty,
42+
'price_unit': line.product_id.deposit_amount,
43+
'name': f"Deposit fee for product: {line.product_id.name}",
44+
'is_deposit_line': True,
45+
'parent_rental_line_id': line.id,
46+
})
47+
self.create(deposit_vals)
48+
return lines
49+
50+
@api.ondelete(at_uninstall=False)
51+
def _unlink_deposit_fee(self):
52+
if not self.env.context.get("bypass_deposit_protection_for_delete"):
53+
for record in self:
54+
if record.is_deposit_line:
55+
raise UserError("You can't delete a Deposit Product line directly.")
56+
57+
def write(self, vals):
58+
if not self.env.context.get("bypass_deposit_protection_for_write"):
59+
for record in self:
60+
if record.is_deposit_line:
61+
raise UserError("You can't edit Deposit Product line directly.")
62+
res = super().write(vals)
63+
if 'product_uom_qty' not in vals:
64+
return res
65+
rental_lines = self.filtered(
66+
lambda l: l.product_id.rent_ok
67+
and l.product_id.requires_deposit
68+
and l.product_id.deposit_amount > 0
69+
and not l.is_deposit_line
70+
)
71+
for line in rental_lines:
72+
deposit_line = self.search([('parent_rental_line_id', '=', line.id)], limit=1)
73+
if deposit_line:
74+
deposit_line.with_context(bypass_deposit_protection_for_write=True).write({
75+
'product_uom_qty': line.product_uom_qty,
76+
'price_unit': line.product_id.deposit_amount,
77+
})
78+
return res
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import publicWidget from "@web/legacy/js/public/public_widget";
2+
3+
publicWidget.registry.DepositRental = publicWidget.Widget.extend({
4+
selector: "#product_detail",
5+
events: {
6+
'change input[name="add_qty"]': '_updateDepositAmount',
7+
},
8+
9+
start: function () {
10+
this._super.apply(this, arguments);
11+
if ($("#deposit_amount").length) {
12+
this._updateDepositAmount();
13+
} else {
14+
this.$el.off('change input[name="add_qty"]');
15+
}
16+
},
17+
18+
_updateDepositAmount: function () {
19+
const qty = parseFloat($("#o_wsale_cta_wrapper").find("input[name='add_qty']").val());
20+
const depositAmount = parseFloat($("#deposit_amount").attr("data-base-amount")) || 0;
21+
const currencySymbol = $("#deposit_amount").attr("data-currency-symbol") || "";
22+
$("#deposit_amount").text(currencySymbol + (depositAmount * qty).toFixed(2));
23+
},
24+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<odoo>
2+
<record id="product_template_form_view_rental_deposit" model="ir.ui.view">
3+
<field name="name">product.template.view.form.inherit.rental.deposit</field>
4+
<field name="model">product.template</field>
5+
<field name="inherit_id" ref="product.product_template_only_form_view"/>
6+
<field name="arch" type="xml">
7+
<xpath expr="//group[@name='extra_rental']" position="inside">
8+
<field name="requires_deposit"/>
9+
<field name="deposit_amount" invisible="not requires_deposit" widget="monetary"/>
10+
</xpath>
11+
</field>
12+
</record>
13+
</odoo>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<odoo>
2+
<record id="res_config_settings_view_form_deposit_inherit" model="ir.ui.view">
3+
<field name="name">res.config.settings.view.form.inherit.deposit</field>
4+
<field name="model">res.config.settings</field>
5+
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
6+
<field name="arch" type="xml">
7+
<xpath expr="//field[@name='extra_product']" position="after">
8+
<label for="deposit_product"/>
9+
<field name="deposit_product"/>
10+
</xpath>
11+
</field>
12+
</record>
13+
</odoo>

0 commit comments

Comments
 (0)