# -*- coding: utf-8 -*- # Copyright 2024-2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) from odoo import api, fields, models class ProductTemplate(models.Model): _inherit = 'product.template' x_fc_can_be_loaned = fields.Boolean( string='Can be Loaned', default=False, help='If checked, this product can be loaned out to clients', ) x_fc_loaner_period_days = fields.Integer( string='Loaner Period (Days)', default=7, help='Default number of free loaner days before rental conversion', ) x_fc_rental_price_weekly = fields.Float( string='Weekly Rental Price', digits='Product Price', help='Rental price per week if loaner converts to rental', ) x_fc_rental_price_monthly = fields.Float( string='Monthly Rental Price', digits='Product Price', help='Rental price per month if loaner converts to rental', ) x_fc_equipment_type = fields.Selection([ ('type_1_walker', 'Type 1 Walker'), ('type_2_mw', 'Type 2 MW'), ('type_2_pw', 'Type 2 PW'), ('type_2_walker', 'Type 2 Walker'), ('type_3_mw', 'Type 3 MW'), ('type_3_pw', 'Type 3 PW'), ('type_3_walker', 'Type 3 Walker'), ('type_4_mw', 'Type 4 MW'), ('type_5_mw', 'Type 5 MW'), ('ceiling_lift', 'Ceiling Lift'), ('mobility_scooter', 'Mobility Scooter'), ('patient_lift', 'Patient Lift'), ('transport_wheelchair', 'Transport Wheelchair'), ('standard_wheelchair', 'Standard Wheelchair'), ('power_wheelchair', 'Power Wheelchair'), ('cushion', 'Cushion'), ('backrest', 'Backrest'), ('stairlift', 'Stairlift'), ('others', 'Others'), ], string='Equipment Type') x_fc_wheelchair_category = fields.Selection([ ('type_1', 'Type 1'), ('type_2', 'Type 2'), ('type_3', 'Type 3'), ('type_4', 'Type 4'), ('type_5', 'Type 5'), ], string='Wheelchair Category') x_fc_seat_width = fields.Char(string='Seat Width') x_fc_seat_depth = fields.Char(string='Seat Depth') x_fc_seat_height = fields.Char(string='Seat Height') x_fc_storage_location = fields.Selection([ ('warehouse', 'Warehouse'), ('westin_brampton', 'Westin Brampton'), ('mobility_etobicoke', 'Mobility Etobicoke'), ('scarborough_storage', 'Scarborough Storage'), ('client_loaned', 'Client/Loaned'), ('rented_out', 'Rented Out'), ], string='Storage Location') x_fc_listing_type = fields.Selection([ ('owned', 'Owned'), ('borrowed', 'Borrowed'), ], string='Listing Type') x_fc_asset_number = fields.Char(string='Asset Number') x_fc_package_info = fields.Text(string='Package Information') x_fc_security_deposit_type = fields.Selection( [ ('fixed', 'Fixed Amount'), ('percentage', 'Percentage of Rental Price'), ], string='Security Deposit Type', ) x_fc_security_deposit_amount = fields.Float( string='Security Deposit Amount', digits='Product Price', ) x_fc_security_deposit_percent = fields.Float( string='Security Deposit (%)', ) x_flm_current_location = fields.Char( string='Current Location', compute='_compute_current_location', help='Current stock location of this loaner product based on inventory quants', ) x_flm_serial_count = fields.Integer( string='Serial Numbers', compute='_compute_serial_count', ) @api.depends('product_variant_ids') def _compute_serial_count(self): for tmpl in self: tmpl.x_flm_serial_count = self.env['stock.lot'].sudo().search_count([ ('product_id', 'in', tmpl.product_variant_ids.ids), ]) def action_view_serial_numbers(self): self.ensure_one() return { 'type': 'ir.actions.act_window', 'name': 'Serial Numbers', 'res_model': 'stock.lot', 'view_mode': 'list,form', 'domain': [('product_id', 'in', self.product_variant_ids.ids)], 'context': {'default_product_id': self.product_variant_ids[:1].id}, } @api.depends('product_variant_ids') def _compute_current_location(self): for tmpl in self: if not tmpl.x_fc_can_be_loaned: tmpl.x_flm_current_location = False continue quants = self.env['stock.quant'].sudo().search([ ('product_id', 'in', tmpl.product_variant_ids.ids), ('quantity', '>', 0), ('location_id.usage', '=', 'internal'), ], limit=5) if quants: locations = quants.mapped('location_id.complete_name') tmpl.x_flm_current_location = ', '.join(set(locations)) else: tmpl.x_flm_current_location = False