from odoo import models, fields, api from odoo.exceptions import UserError class LaundryCommission(models.Model): """Staff commission tracking (PART 3). States: pending — auto-created when order progresses; awaiting manager review confirmed — manager has verified and approved the commission paid — commission has been settled/paid to the staff member The commission_account_id (from settings) is informational for now. Managers can bulk-confirm and bulk-mark-paid from the list view. """ _name = 'laundry.commission' _description = 'Laundry Staff Commission' _inherit = ['mail.thread'] _order = 'date desc, id desc' name = fields.Char( string='Reference', compute='_compute_name', store=True, readonly=True, ) order_id = fields.Many2one( 'sale.order', string='Order', required=True, ondelete='cascade', index=True, ) company_id = fields.Many2one( 'res.company', related='order_id.company_id', store=True, index=True, ) employee_id = fields.Many2one( 'res.users', string='Staff Member', required=True, domain=[('share', '=', False)], tracking=True, ) role = fields.Selection([ ('reception', 'Reception / Intake'), ('processing', 'Processing / Cleaning'), ('delivery', 'Delivery / Handover'), ], string='Role', required=True, tracking=True) commission_type = fields.Selection([ ('percentage', 'Percentage (%)'), ('fixed', 'Fixed Amount'), ], string='Type', required=True, default='percentage') rate = fields.Float(string='Rate / Amount', digits=(10, 2)) base_amount = fields.Float(string='Order Total', digits=(10, 2)) commission_amount = fields.Float( string='Commission', compute='_compute_commission_amount', store=True, digits=(10, 2), ) date = fields.Date(string='Date', required=True, default=fields.Date.today) state = fields.Selection([ ('pending', 'Pending'), ('confirmed', 'Confirmed'), ('paid', 'Paid'), ], default='pending', required=True, tracking=True, copy=False, index=True) notes = fields.Text(string='Notes') _ROLE_LABELS = { 'reception': 'Reception', 'processing': 'Processing', 'delivery': 'Delivery', } @api.depends('order_id', 'order_id.name', 'role') def _compute_name(self): for rec in self: order = rec.order_id.name or 'NEW' role = self._ROLE_LABELS.get(rec.role, rec.role or '') rec.name = f'COM/{order}/{role}' @api.depends('commission_type', 'rate', 'base_amount') def _compute_commission_amount(self): for rec in self: if rec.commission_type == 'percentage': rec.commission_amount = rec.base_amount * rec.rate / 100.0 else: rec.commission_amount = rec.rate # ── State transitions ───────────────────────────────────────────── def action_confirm(self): """Manager confirms commission is valid and approved.""" for rec in self: if rec.state != 'pending': raise UserError( f'"{rec.name}" cannot be confirmed — current state: {rec.state}.' ) rec.write({'state': 'confirmed'}) rec.message_post( body=f'Commission confirmed by {self.env.user.name}. ' f'Amount: {rec.commission_amount:.2f}' ) def action_mark_paid(self): """Mark commission as settled/paid to staff.""" for rec in self: if rec.state == 'paid': raise UserError(f'"{rec.name}" is already paid.') if rec.state == 'pending': # Allow paying directly from pending (manager shortcut) rec.write({'state': 'paid'}) else: rec.write({'state': 'paid'}) rec.message_post( body=f'Marked as paid by {self.env.user.name}.' ) def action_reset_pending(self): """Reset commission back to pending (manager only).""" for rec in self: if rec.state == 'paid': raise UserError( f'Cannot reset "{rec.name}" — it has already been paid.' ) rec.write({'state': 'pending'}) rec.message_post( body=f'Reset to pending by {self.env.user.name}.' )