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
1 change: 1 addition & 0 deletions rental_deposit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
18 changes: 18 additions & 0 deletions rental_deposit/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
'author': 'Aditi (adpaw)',
'name': 'Deposit Rental App',
'license': 'LGPL-3',
'depends': ['sale_renting', 'website_sale'],
'data': [
'views/res_config_settings_view.xml',
'views/product_template_view.xml',
'views/template_view.xml'
],
'assets': {
'web.assets_frontend': [
'rental_deposit/static/src/deposit_amount.js',
],
},
'installable': True,
'auto_install': True,
}
4 changes: 4 additions & 0 deletions rental_deposit/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import res_config_settings
from . import product_template
from . import sale_order_line
from . import res_company
8 changes: 8 additions & 0 deletions rental_deposit/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from odoo import fields, models


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

requires_deposit = fields.Boolean(string="Requires Deposit")
deposit_amount = fields.Float()
7 changes: 7 additions & 0 deletions rental_deposit/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from odoo import fields, models


class ResCompany(models.Model):
_inherit = "res.company"

deposit_product = fields.Many2one("product.product")
12 changes: 12 additions & 0 deletions rental_deposit/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'

deposit_product = fields.Many2one(
"product.product",
related="company_id.deposit_product",
string="Deposit",
readonly=False
)
94 changes: 94 additions & 0 deletions rental_deposit/models/sale_order_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from odoo import api, fields, models
from odoo.exceptions import UserError


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

is_deposit_line = fields.Boolean(default=False)
parent_rental_line_id = fields.Many2one(
'sale.order.line',
string="Parent Rental Line",
ondelete="cascade",
index=True
)

@api.model_create_multi
def create(self, vals_list):
lines = super().create(vals_list)
rental_lines = lines.filtered(
lambda l: l.product_id.rent_ok
and l.product_id.requires_deposit
and l.product_id.deposit_amount > 0
and not l.is_deposit_line
)
if not rental_lines:
return lines
company_map = {}
for line in rental_lines:
company = line.company_id
if company not in company_map:
if not company.deposit_product:
raise UserError("Please set deposit product in settings.")
company_map[company] = company.deposit_product
deposit_vals = []
for line in rental_lines:
deposit_product = company_map[line.company_id]
deposit_vals.append({
'order_id': line.order_id.id,
'product_id': deposit_product.id,
'product_uom_qty': line.product_uom_qty,
'price_unit': line.product_id.deposit_amount,
'name': f"Deposit fee for product: {line.product_id.name}",
'is_deposit_line': True,
'parent_rental_line_id': line.id,
})
self.create(deposit_vals)
return lines

# deposit_vals = []
# for line in rental_lines:
# deposit_product = line.company_id.deposit_product
# if not deposit_product:
# raise UserError("Please set deposit product in settings.")
# deposit_vals.append({
# 'order_id': line.order_id.id,
# 'product_id': deposit_product.id,
# 'product_uom_qty': line.product_uom_qty,
# 'price_unit': line.product_id.deposit_amount,
# 'name': f"Deposit fee for product: {line.product_id.name}",
# 'is_deposit_line': True,
# 'parent_rental_line_id': line.id,
# })
# self.create(deposit_vals)
# return lines

@api.ondelete(at_uninstall=False)
def _unlink_deposit_fee(self):
if not self.env.context.get("bypass_deposit_protection_for_delete"):
for record in self:
if record.is_deposit_line:
raise UserError("You can't delete a Deposit Product line directly.")

def write(self, vals):
if not self.env.context.get("bypass_deposit_protection_for_write"):
for record in self:
if record.is_deposit_line:
raise UserError("You can't edit Deposit Product line directly.")
res = super().write(vals)
if 'product_uom_qty' not in vals:
return res
rental_lines = self.filtered(
lambda l: l.product_id.rent_ok
and l.product_id.requires_deposit
and l.product_id.deposit_amount > 0
and not l.is_deposit_line
)
for line in rental_lines:
deposit_line = self.search([('parent_rental_line_id', '=', line.id)], limit=1)
if deposit_line:
deposit_line.with_context(bypass_deposit_protection_for_write=True).write({
'product_uom_qty': line.product_uom_qty,
'price_unit': line.product_id.deposit_amount,
})
return res
27 changes: 27 additions & 0 deletions rental_deposit/static/src/deposit_amount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Component, onMounted } from "@odoo/owl";
import { registry } from "@web/core/registry";

export class DepositAmount extends Component {
setup() {
onMounted(() => {
const depositEl = document.querySelector('#deposit_amount_val');
const qtyInput = document.querySelector('input[name="add_qty"]');

if (!depositEl || !qtyInput) return;

const baseAmount = parseFloat(depositEl.dataset.baseAmount) || 0;

const calculateTotal = () => {
const quantity = parseFloat(qtyInput.value) || 1;
depositEl.textContent = (baseAmount * quantity).toFixed(2);
};

qtyInput.addEventListener('input', calculateTotal);
qtyInput.addEventListener('change', calculateTotal);

calculateTotal();
});
}
}

registry.category("public_components").add("deposit_amount", DepositAmount);
2 changes: 2 additions & 0 deletions rental_deposit/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import common
from . import test_sale_order_line
57 changes: 57 additions & 0 deletions rental_deposit/tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from odoo.tests.common import TransactionCase


class RentalDepositCommon(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()

cls.deposit_product = cls.env['product.product'].create({
'name': 'Deposit Fee',
'type': 'service',
})
cls.env.company.deposit_product = cls.deposit_product

cls.rental_product_a = cls.env['product.product'].create({
'name': 'Test Projector',
'rent_ok': True,
'requires_deposit': True,
'deposit_amount': 50.0,
})

cls.rental_product_b = cls.env['product.product'].create({
'name': 'Test Bike',
'rent_ok': True,
'requires_deposit': True,
'deposit_amount': 30.0,
})

cls.rental_product_c = cls.env['product.product'].create({
'name': 'Test Camera',
'rent_ok': True,
'requires_deposit': True,
'deposit_amount': 20.0,
})

cls.rental_no_deposit = cls.env['product.product'].create({
'name': 'Test Chair',
'rent_ok': True,
'requires_deposit': False,
})

cls.partner = cls.env['res.partner'].create({'name': 'Test Customer'})

def _make_order(self):
"""Creates a fresh sale order each time."""
return self.env['sale.order'].create({
'partner_id': self.partner.id,
})

def _add_line(self, order, product, qty=1, price=10.0):
"""Helper — adds a single order line and returns it."""
return self.env['sale.order.line'].create({
'order_id': order.id,
'product_id': product.id,
'product_uom_qty': qty,
'price_unit': price,
})
Loading