# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) from odoo import models, fields, api class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' # -- Work Schedule -- fclk_default_clock_in_time = fields.Float( string='Default Clock-In Time', config_parameter='fusion_clock.default_clock_in_time', default=9.0, help="Default scheduled clock-in time (24h format, e.g. 9.0 = 9:00 AM).", ) fclk_default_clock_out_time = fields.Float( string='Default Clock-Out Time', config_parameter='fusion_clock.default_clock_out_time', default=17.0, help="Default scheduled clock-out time (24h format, e.g. 17.0 = 5:00 PM).", ) # -- Break -- fclk_default_break_minutes = fields.Float( string='Default Break Duration (min)', config_parameter='fusion_clock.default_break_minutes', default=30.0, help="Default unpaid break duration in minutes.", ) fclk_auto_deduct_break = fields.Boolean( string='Auto-Deduct Break', config_parameter='fusion_clock.auto_deduct_break', default=True, help="Automatically deduct break from worked hours on clock-out.", ) fclk_break_threshold_hours = fields.Float( string='Break Threshold (hours)', config_parameter='fusion_clock.break_threshold_hours', default=4.0, help="Only deduct break if shift is longer than this many hours.", ) # -- Grace Period & Auto Clock-Out -- fclk_grace_period_minutes = fields.Float( string='Grace Period (min)', config_parameter='fusion_clock.grace_period_minutes', default=15.0, help="Minutes allowed after scheduled end before auto clock-out.", ) fclk_enable_auto_clockout = fields.Boolean( string='Enable Auto Clock-Out', config_parameter='fusion_clock.enable_auto_clockout', default=True, ) fclk_max_shift_hours = fields.Float( string='Max Shift Length (hours)', config_parameter='fusion_clock.max_shift_hours', default=12.0, help="Maximum shift length before auto clock-out (safety net).", ) # -- Penalties -- fclk_enable_penalties = fields.Boolean( string='Enable Penalty Tracking', config_parameter='fusion_clock.enable_penalties', default=True, ) fclk_penalty_grace_minutes = fields.Float( string='Penalty Grace (min)', config_parameter='fusion_clock.penalty_grace_minutes', default=5.0, help="Minutes of grace before a late/early penalty is recorded.", ) fclk_penalty_deduction_minutes = fields.Float( string='Penalty Deduction (min)', config_parameter='fusion_clock.penalty_deduction_minutes', default=15.0, help="Minutes deducted from worked hours per penalty occurrence.", ) # -- Office User & Notifications -- fclk_office_user_id = fields.Many2one( 'res.users', string='Office User', help="User who receives activity notifications for attendance issues.", ) fclk_very_late_threshold_minutes = fields.Float( string='Very Late Threshold (min)', config_parameter='fusion_clock.very_late_threshold_minutes', default=15.0, help="Minutes late before an activity is scheduled for the office user.", ) fclk_max_monthly_absences = fields.Integer( string='Max Monthly Absences', config_parameter='fusion_clock.max_monthly_absences', default=3, help="Alert office user when an employee reaches this many absences in a month.", ) fclk_enable_employee_notifications = fields.Boolean( string='Enable Employee Notifications', config_parameter='fusion_clock.enable_employee_notifications', default=True, help="Send clock-in/out reminders to employees.", ) fclk_reminder_before_shift_minutes = fields.Float( string='Remind After Shift Start (min)', config_parameter='fusion_clock.reminder_before_shift_minutes', default=30.0, help="Send reminder if employee hasn't clocked in this many minutes after shift start.", ) fclk_reminder_before_end_minutes = fields.Float( string='Remind Before Shift End (min)', config_parameter='fusion_clock.reminder_before_end_minutes', default=15.0, help="Send clock-out reminder this many minutes before shift end.", ) fclk_send_weekly_summary = fields.Boolean( string='Send Weekly Summary', config_parameter='fusion_clock.send_weekly_summary', default=True, help="Send weekly attendance summary to each employee on Monday.", ) # -- Overtime -- fclk_enable_overtime = fields.Boolean( string='Enable Overtime Tracking', config_parameter='fusion_clock.enable_overtime', default=True, ) fclk_daily_overtime_threshold = fields.Float( string='Daily OT Threshold (hours)', config_parameter='fusion_clock.daily_overtime_threshold', default=8.0, help="Net hours beyond this threshold count as daily overtime.", ) fclk_weekly_overtime_threshold = fields.Float( string='Weekly OT Threshold (hours)', config_parameter='fusion_clock.weekly_overtime_threshold', default=40.0, help="Net hours beyond this threshold count as weekly overtime.", ) # -- Location -- fclk_enable_ip_fallback = fields.Boolean( string='Enable IP Fallback', config_parameter='fusion_clock.enable_ip_fallback', default=False, help="Allow IP-based location verification when GPS is unavailable.", ) fclk_enable_photo_verification = fields.Boolean( string='Enable Photo Verification', config_parameter='fusion_clock.enable_photo_verification', default=False, help="Global toggle for selfie verification on clock-in (per-location control).", ) # -- Kiosk -- fclk_enable_kiosk = fields.Boolean( string='Enable Kiosk Mode', config_parameter='fusion_clock.enable_kiosk', default=False, ) fclk_kiosk_pin_required = fields.Boolean( string='Require PIN for Kiosk', config_parameter='fusion_clock.kiosk_pin_required', default=True, help="Require employees to enter a PIN when using kiosk mode.", ) # -- Corrections -- fclk_enable_correction_requests = fields.Boolean( string='Enable Correction Requests', config_parameter='fusion_clock.enable_correction_requests', default=True, help="Allow employees to request timesheet corrections from the portal.", ) # -- CSV Export -- fclk_csv_column_mapping = fields.Char( string='CSV Column Mapping', config_parameter='fusion_clock.csv_column_mapping', help="Custom column names for CSV export (JSON format). Leave blank for defaults.", ) # -- Pay Period -- fclk_pay_period_type = fields.Selection( [ ('weekly', 'Weekly'), ('biweekly', 'Bi-Weekly'), ('semi_monthly', 'Semi-Monthly'), ('monthly', 'Monthly'), ], string='Pay Period', config_parameter='fusion_clock.pay_period_type', default='biweekly', ) fclk_pay_period_start = fields.Char( string='Pay Period Anchor Date', config_parameter='fusion_clock.pay_period_start', help="Start date for pay period calculations (YYYY-MM-DD format).", ) # -- Reports -- fclk_auto_generate_reports = fields.Boolean( string='Auto-Generate Reports', config_parameter='fusion_clock.auto_generate_reports', default=True, ) fclk_report_recipient_emails = fields.Char( string='Report Recipient Emails', config_parameter='fusion_clock.report_recipient_emails', help="Comma-separated email addresses for batch report delivery.", ) fclk_send_employee_reports = fields.Boolean( string='Send Employee Copies', config_parameter='fusion_clock.send_employee_reports', default=True, help="Send individual report copies to each employee's work email.", ) # -- Google Maps -- fclk_google_maps_api_key = fields.Char( string='Google Maps API Key', config_parameter='fusion_clock.google_maps_api_key', ) # -- Sounds -- fclk_enable_sounds = fields.Boolean( string='Enable Clock Sounds', config_parameter='fusion_clock.enable_sounds', default=True, ) def set_values(self): super().set_values() ICP = self.env['ir.config_parameter'].sudo() if self.fclk_office_user_id: ICP.set_param('fusion_clock.office_user_id', str(self.fclk_office_user_id.id)) else: ICP.set_param('fusion_clock.office_user_id', '0') @api.model def get_values(self): res = super().get_values() ICP = self.env['ir.config_parameter'].sudo() office_user_id = int(ICP.get_param('fusion_clock.office_user_id', '0')) if office_user_id: res['fclk_office_user_id'] = office_user_id return res