From bbfeb70e54ba322b970af2c4f4e264c6dc713de0 Mon Sep 17 00:00:00 2001 From: hapt-odoo Date: Wed, 25 Jun 2025 19:32:26 +0530 Subject: [PATCH 1/2] [ADD] rental: added deposit for particular product In the rental module, a field deposit_product, was added, in which the product is selected to apply a deposit. and in product form added a field amount_deposit to apply the deposit amount in sale.order.line --- rental/__init__.py | 1 + rental/__manifest__.py | 13 ++++++++++++ rental/models/__init__.py | 4 ++++ rental/models/product_template.py | 8 ++++++++ rental/models/res_company.py | 8 ++++++++ rental/models/res_config_settings.py | 9 ++++++++ rental/models/sale_order_line.py | 24 ++++++++++++++++++++++ rental/views/product_template_views.xml | 14 +++++++++++++ rental/views/res_config_settings_views.xml | 16 +++++++++++++++ 9 files changed, 97 insertions(+) create mode 100644 rental/__init__.py create mode 100644 rental/__manifest__.py create mode 100644 rental/models/__init__.py create mode 100644 rental/models/product_template.py create mode 100644 rental/models/res_company.py create mode 100644 rental/models/res_config_settings.py create mode 100644 rental/models/sale_order_line.py create mode 100644 rental/views/product_template_views.xml create mode 100644 rental/views/res_config_settings_views.xml diff --git a/rental/__init__.py b/rental/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/rental/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/rental/__manifest__.py b/rental/__manifest__.py new file mode 100644 index 00000000000..5e5a6e66e03 --- /dev/null +++ b/rental/__manifest__.py @@ -0,0 +1,13 @@ +{ + 'name': 'Rental App', + 'category': '', + 'description': """This module is rental app module""", + 'depends': ['base', 'sale_renting'], + 'data': [ + "views/res_config_settings_views.xml", + "views/product_template_views.xml", + ], + 'application': True, + 'license': 'OEEL-1', + "sequence": 1, +} diff --git a/rental/models/__init__.py b/rental/models/__init__.py new file mode 100644 index 00000000000..8cceeeb6df9 --- /dev/null +++ b/rental/models/__init__.py @@ -0,0 +1,4 @@ +from . import res_config_settings +from . import res_company +from . import product_template +from . import sale_order_line diff --git a/rental/models/product_template.py b/rental/models/product_template.py new file mode 100644 index 00000000000..e40b03c8b7e --- /dev/null +++ b/rental/models/product_template.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + required_deposit = fields.Boolean(default=False) + amount_deposit = fields.Float(string="Deposit Amount") diff --git a/rental/models/res_company.py b/rental/models/res_company.py new file mode 100644 index 00000000000..0bd9263ed75 --- /dev/null +++ b/rental/models/res_company.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + product_deposit = fields.Many2one('product.product', string="Product", + domain=[("rent_ok", "=", True)]) diff --git a/rental/models/res_config_settings.py b/rental/models/res_config_settings.py new file mode 100644 index 00000000000..c81326fbcce --- /dev/null +++ b/rental/models/res_config_settings.py @@ -0,0 +1,9 @@ +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + product_deposit = fields.Many2one('product.product', string="Deposit", + related="company_id.product_deposit", + readonly=False, domain=[("rent_ok", "=", True)]) diff --git a/rental/models/sale_order_line.py b/rental/models/sale_order_line.py new file mode 100644 index 00000000000..19d9421d744 --- /dev/null +++ b/rental/models/sale_order_line.py @@ -0,0 +1,24 @@ +from odoo import models, api + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + @api.model_create_multi + def create(self, vals_list): + rec = super().create(vals_list) + for vals in vals_list: + if vals.get('is_rental'): + deposite_product = self.env.company.product_deposit + product_template = self.env['product.template'].browse(vals.get('product_template_id')) + if product_template.required_deposit and deposite_product: + deposite_number = vals.get('product_uom_qty') + if deposite_product.id == vals.get('product_id'): + self.create({ + 'order_id': vals['order_id'], + 'product_id': deposite_product.id, + 'product_uom_qty': deposite_number, + 'price_unit': product_template.amount_deposit * deposite_number, + 'name': 'Deposit Amount', + }) + return rec diff --git a/rental/views/product_template_views.xml b/rental/views/product_template_views.xml new file mode 100644 index 00000000000..e32cefae362 --- /dev/null +++ b/rental/views/product_template_views.xml @@ -0,0 +1,14 @@ + + + + product.template.form.view.rental.inherit + product.template + + + + + + + + + diff --git a/rental/views/res_config_settings_views.xml b/rental/views/res_config_settings_views.xml new file mode 100644 index 00000000000..ac8cb1a8440 --- /dev/null +++ b/rental/views/res_config_settings_views.xml @@ -0,0 +1,16 @@ + + + + res.config.settings.inherit.view.form + res.config.settings + + + +
+
+
+
+
+
From 3c5f0f5f10e56dca9a3dd5a1d75d662848f3e0f8 Mon Sep 17 00:00:00 2001 From: hapt-odoo Date: Thu, 26 Jun 2025 15:37:21 +0530 Subject: [PATCH 2/2] [IMP] rental: In website part added Required deposit In rental module a 'required deposit' is added in the product description in the website part, and in cart section, the total deposit amount is calculated as per the product quantity and final deposit amount will be displayed --- rental/__manifest__.py | 8 +++- rental/models/sale_order_line.py | 54 ++++++++++++++++++-------- rental/static/srs/js/rental_deposit.js | 26 +++++++++++++ rental/views/templates.xml | 38 ++++++++++++++++++ 4 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 rental/static/srs/js/rental_deposit.js create mode 100644 rental/views/templates.xml diff --git a/rental/__manifest__.py b/rental/__manifest__.py index 5e5a6e66e03..031035d7af3 100644 --- a/rental/__manifest__.py +++ b/rental/__manifest__.py @@ -2,11 +2,17 @@ 'name': 'Rental App', 'category': '', 'description': """This module is rental app module""", - 'depends': ['base', 'sale_renting'], + 'depends': ['sale_renting', 'website_sale_renting'], 'data': [ "views/res_config_settings_views.xml", "views/product_template_views.xml", + "views/templates.xml", ], + 'assets': { + 'web.assets_frontend': [ + 'rental_deposit/static/src/js/rental_deposit.js', + ], + }, 'application': True, 'license': 'OEEL-1', "sequence": 1, diff --git a/rental/models/sale_order_line.py b/rental/models/sale_order_line.py index 19d9421d744..ce55dd7dec2 100644 --- a/rental/models/sale_order_line.py +++ b/rental/models/sale_order_line.py @@ -1,24 +1,46 @@ -from odoo import models, api +from odoo import fields, models, api class SaleOrderLine(models.Model): _inherit = 'sale.order.line' + is_deposit_line = fields.Boolean(default=False) + deposit_link_id = fields.Many2one("sale.order.line", ondelete="cascade") + @api.model_create_multi def create(self, vals_list): - rec = super().create(vals_list) - for vals in vals_list: - if vals.get('is_rental'): - deposite_product = self.env.company.product_deposit - product_template = self.env['product.template'].browse(vals.get('product_template_id')) - if product_template.required_deposit and deposite_product: - deposite_number = vals.get('product_uom_qty') - if deposite_product.id == vals.get('product_id'): - self.create({ - 'order_id': vals['order_id'], - 'product_id': deposite_product.id, - 'product_uom_qty': deposite_number, - 'price_unit': product_template.amount_deposit * deposite_number, - 'name': 'Deposit Amount', + lines = super().create(vals_list) + + deposit_product = self.env.company.product_deposit + deposit_lines = [] + for line in lines: + if (line.product_id == deposit_product) and line.product_id.product_tmpl_id.required_deposit: + deposit_price = line.product_id.product_tmpl_id.amount_deposit * line.product_uom_qty + deposit_lines.append({ + "is_deposit_line": True, + "order_id": line.order_id.id, + "product_id": deposit_product.id, + "name": f"Deposit for {line.product_id.name}", + "product_uom_qty": line.product_uom_qty, + "price_unit": deposit_price, + "deposit_link_id": line.id, + }) + if deposit_lines: + super().create(deposit_lines) + return lines + + def write(self, vals): + res = super().write(vals) + if "product_uom_qty" in vals: + for line in self: + if not line.is_deposit_line: + deposit_line = self.search([ + ("order_id", "=", line.order_id.id), + ("deposit_link_id", "=", line.id), + ]) + if deposit_line: + deposit_line.write({ + "product_uom_qty": vals["product_uom_qty"], + "price_unit": line.product_template_id.amount_deposit, }) - return rec + return res diff --git a/rental/static/srs/js/rental_deposit.js b/rental/static/srs/js/rental_deposit.js new file mode 100644 index 00000000000..e0641ce980f --- /dev/null +++ b/rental/static/srs/js/rental_deposit.js @@ -0,0 +1,26 @@ +import publicWidget from "@web/legacy/js/public/public_widget"; + +publicWidget.registry.WebsiteSale.include({ + start: function () { + this._super.apply(this, arguments); + this.changeDepositAmount({ target: document.querySelector('input[name="add_qty"]') }); + }, + + _onChangeAddQuantity: function (ev) { + this._super.apply(this, arguments); + this.changeDepositAmount(ev); + }, + + changeDepositAmount: function(ev){ + const input = ev.target || document.querySelector('input[name="add_qty"]'); + if (!input) return; + const qty = parseFloat(input.value || 1); + const depositSpan = document.getElementById('product_amount_deposit'); + if (!depositSpan) return; + + const baseDeposit = parseFloat(depositSpan.dataset.baseAmount || 0); + const currencySymbol = depositSpan.dataset.currencySymbol || ''; + const totalDeposit = (baseDeposit * qty).toFixed(2); + depositSpan.textContent = `${currencySymbol} ${totalDeposit}`; + } +}); diff --git a/rental/views/templates.xml b/rental/views/templates.xml new file mode 100644 index 00000000000..4f34bef1f39 --- /dev/null +++ b/rental/views/templates.xml @@ -0,0 +1,38 @@ + + + + + + +