# -*- coding: utf-8 -*- # Copyright 2024-2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) """Emergency / rush service rate card. The pissed-off-grumpy-client scenario: stairlift dead at 5 PM Friday, needs service yesterday. Office bumps them into today's route OR books them priority for tomorrow OR (if after-hours / weekend) charges an emergency surcharge. Sometimes more than one technician is needed (e.g. lifting an adjustable bed back onto its frame) - per_tech_multiplier handles that. Pricing logic on repair.order: surcharge = base_amount + base_amount * per_tech_multiplier * (techs_required - 1) Example: same-day stairlift, 1 tech, base $250, multiplier 0.5 -> $250 surcharge Example: same-day stairlift, 2 techs (one to hold, one to wrench) -> $250 + $250 * 0.5 * 1 = $375 surcharge """ from odoo import _, api, fields, models class FusionRepairEmergencyCharge(models.Model): _name = 'fusion.repair.emergency.charge' _description = 'Rush / Emergency Service Surcharge Rate' _order = 'category_id, tier' name = fields.Char( compute='_compute_name', store=True, ) category_id = fields.Many2one( 'fusion.repair.product.category', string='Equipment Category', required=True, ondelete='cascade', index=True, ) tier = fields.Selection( [ ('same_day', 'Same Day (during business hours)'), ('next_day', 'Next Day Priority'), ('after_hours', 'After Hours (5pm-9pm weekday)'), ('weekend', 'Weekend'), ('holiday', 'Statutory Holiday'), ], string='Tier', required=True, ) base_amount = fields.Monetary( string='Base Surcharge', currency_field='currency_id', required=True, default=0.0, help='Surcharge for ONE technician on top of the normal labour / parts cost.', ) per_tech_multiplier = fields.Float( string='Additional Tech Multiplier', default=0.5, help='Each additional technician adds base_amount * this multiplier ' 'to the surcharge. Default 0.5 means tech #2 costs half the base.', ) currency_id = fields.Many2one( 'res.currency', default=lambda self: self.env.company.currency_id, ) company_id = fields.Many2one( 'res.company', default=lambda self: self.env.company, ) active = fields.Boolean(default=True) description = fields.Text( help='Internal note - shown to CS when they pick this tier in the wizard.', ) _cat_tier_unique = models.Constraint( 'unique(category_id, tier, company_id)', 'Only one emergency-charge row per (category, tier, company).', ) @api.depends('category_id', 'tier', 'base_amount') def _compute_name(self): for r in self: tier_label = dict(self._fields['tier'].selection).get(r.tier) or '?' cat = r.category_id.name or '?' r.name = f'{cat} - {tier_label} (${r.base_amount:.0f})' @api.model def calculate(self, category, tier, techs_required=1): """Return the surcharge for the given category + tier + tech count, or 0.0 if no rate is configured.""" if not category or not tier or techs_required < 1: return 0.0 rate = self.sudo().search([ ('category_id', '=', category.id), ('tier', '=', tier), ('active', '=', True), ('company_id', 'in', self.env.companies.ids), ], limit=1) if not rate: return 0.0 extra = max(techs_required - 1, 0) return rate.base_amount + (rate.base_amount * rate.per_tech_multiplier * extra)