# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) import logging from odoo import models, fields, api, _ from odoo.exceptions import ValidationError _logger = logging.getLogger(__name__) class FusionClockLeaveRequest(models.Model): _name = 'fusion.clock.leave.request' _description = 'Clock Leave Request' _order = 'leave_date desc, id desc' _rec_name = 'display_name' _inherit = ['mail.thread'] employee_id = fields.Many2one( 'hr.employee', string='Employee', required=True, index=True, ondelete='cascade', ) leave_date = fields.Date( string='From Date', required=True, index=True, ) date_to = fields.Date( string='To Date', index=True, help="Last day of the leave (inclusive); equals the start date for a " "single-day request.", ) reason = fields.Text( string='Reason', required=True, ) state = fields.Selection( [ ('auto_approved', 'Auto-Approved'), ('reviewed', 'Reviewed'), ], string='Status', default='auto_approved', tracking=True, ) created_from = fields.Selection( [ ('portal', 'Portal'), ('backend', 'Backend'), ], string='Created From', default='portal', ) company_id = fields.Many2one( 'res.company', string='Company', related='employee_id.company_id', store=True, ) display_name = fields.Char( compute='_compute_display_name', store=True, ) @api.depends('employee_id', 'leave_date', 'date_to') def _compute_display_name(self): for rec in self: emp = rec.employee_id.name or '' rec.display_name = f"{emp} - Leave ({rec._fclk_date_label()})" def _fclk_date_label(self): """Human label for the leave period: a single date, or 'from to to'.""" self.ensure_one() if not self.leave_date: return '' if self.date_to and self.date_to != self.leave_date: return f"{self.leave_date} to {self.date_to}" return str(self.leave_date) @api.constrains('leave_date', 'date_to') def _check_leave_dates(self): for rec in self: if rec.date_to and rec.leave_date and rec.date_to < rec.leave_date: raise ValidationError(_("The end date cannot be before the start date.")) @api.model_create_multi def create(self, vals_list): for vals in vals_list: if not vals.get('date_to') and vals.get('leave_date'): vals['date_to'] = vals['leave_date'] records = super().create(vals_list) for rec in records: rec._notify_office_user() rec._create_activity_log() return records def _notify_office_user(self): """Schedule a mail.activity for the office user.""" ICP = self.env['ir.config_parameter'].sudo() office_user_id = int(ICP.get_param('fusion_clock.office_user_id', '0')) if not office_user_id: return office_user = self.env['res.users'].sudo().browse(office_user_id) if not office_user.exists(): return try: self.env['mail.activity'].sudo().create({ 'activity_type_id': self.env.ref('mail.mail_activity_data_todo').id, 'summary': f"Leave Request: {self.employee_id.name} ({self._fclk_date_label()})", 'note': f"Reason: {self.reason}", 'user_id': office_user.id, 'res_model_id': self.env['ir.model']._get_id('fusion.clock.leave.request'), 'res_id': self.id, 'date_deadline': self.leave_date, }) except Exception as e: _logger.error("Fusion Clock: Failed to create leave activity: %s", e) def _create_activity_log(self): """Log the leave request in the activity log.""" try: self.env['fusion.clock.activity.log'].sudo().create({ 'employee_id': self.employee_id.id, 'log_type': 'leave_request', 'description': f"Leave requested for {self._fclk_date_label()}: {self.reason}", 'source': 'portal' if self.created_from == 'portal' else 'system', }) except Exception as e: _logger.error("Fusion Clock: Failed to create leave activity log: %s", e) def action_mark_reviewed(self): """Mark the leave request as reviewed by the office user.""" self.write({'state': 'reviewed'})