# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) from datetime import datetime, timedelta from odoo import models, fields, api class HrEmployee(models.Model): _inherit = 'hr.employee' x_fclk_default_location_id = fields.Many2one( 'fusion.clock.location', string='Default Clock Location', help="The default location shown on this employee's clock page.", ) x_fclk_enable_clock = fields.Boolean( string='Enable Fusion Clock', default=True, help="If unchecked, this employee cannot use the Fusion Clock portal/systray.", ) x_fclk_break_minutes = fields.Float( string='Custom Break (min)', default=0.0, help="Override default break duration for this employee. 0 = use company default.", ) x_fclk_period_hours = fields.Float( string='Period Hours', compute='_compute_fclk_period_hours', help="Net hours worked in the current pay period.", ) x_fclk_period_label = fields.Char( string='Current Period', compute='_compute_fclk_period_hours', help="Label for the current pay period.", ) def _get_fclk_break_minutes(self): """Return effective break minutes for this employee.""" self.ensure_one() if self.x_fclk_break_minutes > 0: return self.x_fclk_break_minutes return float( self.env['ir.config_parameter'].sudo().get_param( 'fusion_clock.default_break_minutes', '30' ) ) def action_fclk_open_attendance(self): """Open attendance list for this employee, grouped by pay period.""" self.ensure_one() list_view = self.env.ref('fusion_clock.view_hr_attendance_list_by_period') search_view = self.env.ref('fusion_clock.view_hr_attendance_search_by_period') return { 'type': 'ir.actions.act_window', 'name': f'{self.name} - Attendance', 'res_model': 'hr.attendance', 'view_mode': 'list,form', 'views': [(list_view.id, 'list'), (False, 'form')], 'search_view_id': (search_view.id, search_view.name), 'domain': [('employee_id', '=', self.id)], 'context': { 'search_default_group_pay_period': 1, 'default_employee_id': self.id, }, } def _compute_fclk_period_hours(self): ICP = self.env['ir.config_parameter'].sudo() schedule_type = ICP.get_param('fusion_clock.pay_period_type', 'biweekly') anchor_str = ICP.get_param('fusion_clock.pay_period_start', '') anchor = None if anchor_str: try: anchor = fields.Date.from_string(anchor_str) except Exception: pass today = fields.Date.today() Attendance = self.env['hr.attendance'] period_start, period_end = Attendance._calc_period(schedule_type, anchor, today) period_label = ( f"{period_start.strftime('%b %d')} - " f"{period_end.strftime('%b %d, %Y')}" ) start_dt = datetime.combine(period_start, datetime.min.time()) end_dt = datetime.combine(period_end + timedelta(days=1), datetime.min.time()) for emp in self: atts = Attendance.sudo().search([ ('employee_id', '=', emp.id), ('check_in', '>=', start_dt), ('check_in', '<', end_dt), ('check_out', '!=', False), ]) emp.x_fclk_period_hours = round( sum(a.x_fclk_net_hours or 0 for a in atts), 1 ) emp.x_fclk_period_label = period_label