import logging from odoo import api, fields, models _logger = logging.getLogger(__name__) class SaleOrderLine(models.Model): _inherit = 'sale.order.line' is_security_deposit = fields.Boolean( string="Is Security Deposit", default=False, help="Marks this line as a security deposit for a rental product.", ) rental_deposit_source_line_id = fields.Many2one( 'sale.order.line', string="Deposit For", ondelete='cascade', help="The rental product line this deposit is associated with.", ) def _ensure_deposit_lines(self): """Check rental lines and create missing security deposit lines.""" deposit_vals = [] for line in self: if not line.is_rental or line.is_security_deposit: continue if not line.order_id.is_rental_order: continue deposit_amount = line.order_id._compute_deposit_amount_for_line(line) if deposit_amount <= 0: continue existing = line.order_id.order_line.filtered( lambda l, src=line: ( l.is_security_deposit and l.rental_deposit_source_line_id == src ) ) if existing: continue deposit_product = line.order_id._get_deposit_product() deposit_vals.append({ 'order_id': line.order_id.id, 'product_id': deposit_product.id, 'product_uom_id': deposit_product.uom_id.id, 'name': ( "SECURITY DEPOSIT - REFUNDABLE UPON RETURN IN " f"GOOD & CLEAN CONDITION - {line.product_id.display_name}" ), 'product_uom_qty': 1, 'price_unit': deposit_amount, 'is_security_deposit': True, 'rental_deposit_source_line_id': line.id, }) if deposit_vals: self.env['sale.order.line'].with_context( skip_deposit_check=True, ).create(deposit_vals) return bool(deposit_vals) @api.model_create_multi def create(self, vals_list): lines = super().create(vals_list) if not self.env.context.get('skip_deposit_check'): lines._ensure_deposit_lines() return lines def write(self, vals): res = super().write(vals) if self.env.context.get('skip_deposit_check'): return res if 'is_rental' in vals or 'product_id' in vals: self._ensure_deposit_lines() return res def unlink(self): deposit_lines = self.env['sale.order.line'] for line in self: if not line.exists(): continue if line.is_rental and not line.is_security_deposit: deps = line.order_id.order_line.filtered( lambda l: ( l.exists() and l.rental_deposit_source_line_id == line ) ) deposit_lines |= deps deposit_lines = deposit_lines.exists() - self if deposit_lines: deposit_lines.unlink() return super().unlink()