changes
This commit is contained in:
133
fusion_clock/models/clock_activity_log.py
Normal file
133
fusion_clock/models/clock_activity_log.py
Normal file
@@ -0,0 +1,133 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class FusionClockActivityLog(models.Model):
|
||||
_name = 'fusion.clock.activity.log'
|
||||
_description = 'Clock Activity Log'
|
||||
_order = 'log_date desc, id desc'
|
||||
_rec_name = 'display_name'
|
||||
|
||||
employee_id = fields.Many2one(
|
||||
'hr.employee',
|
||||
string='Employee',
|
||||
required=True,
|
||||
index=True,
|
||||
ondelete='cascade',
|
||||
)
|
||||
log_type = fields.Selection(
|
||||
[
|
||||
('clock_in', 'Clock In'),
|
||||
('clock_out', 'Clock Out'),
|
||||
('late_clock_in', 'Late Clock-In'),
|
||||
('early_clock_out', 'Early Clock-Out'),
|
||||
('outside_geofence', 'Outside Geofence'),
|
||||
('auto_clock_out', 'Auto Clock-Out'),
|
||||
('missed_clock_out', 'Missed Clock-Out'),
|
||||
('absent', 'Absent'),
|
||||
('leave_request', 'Leave Request'),
|
||||
('reason_provided', 'Reason Provided'),
|
||||
('overtime', 'Overtime'),
|
||||
('correction_request', 'Correction Request'),
|
||||
('ip_fallback', 'IP Fallback Used'),
|
||||
('streak_milestone', 'Streak Milestone'),
|
||||
],
|
||||
string='Log Type',
|
||||
required=True,
|
||||
index=True,
|
||||
)
|
||||
log_date = fields.Datetime(
|
||||
string='Date/Time',
|
||||
required=True,
|
||||
default=fields.Datetime.now,
|
||||
index=True,
|
||||
)
|
||||
description = fields.Text(string='Description')
|
||||
attendance_id = fields.Many2one(
|
||||
'hr.attendance',
|
||||
string='Attendance',
|
||||
ondelete='set null',
|
||||
index=True,
|
||||
)
|
||||
location_id = fields.Many2one(
|
||||
'fusion.clock.location',
|
||||
string='Location',
|
||||
ondelete='set null',
|
||||
)
|
||||
latitude = fields.Float(string='Latitude', digits=(10, 7))
|
||||
longitude = fields.Float(string='Longitude', digits=(10, 7))
|
||||
distance = fields.Float(
|
||||
string='Distance (m)',
|
||||
digits=(10, 2),
|
||||
help="Distance from location center in meters.",
|
||||
)
|
||||
source = fields.Selection(
|
||||
[
|
||||
('portal', 'Portal'),
|
||||
('portal_fab', 'Portal FAB'),
|
||||
('systray', 'Systray'),
|
||||
('backend_fab', 'Backend FAB'),
|
||||
('kiosk', 'Kiosk'),
|
||||
('system', 'System (Cron)'),
|
||||
],
|
||||
string='Source',
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
'res.company',
|
||||
string='Company',
|
||||
related='employee_id.company_id',
|
||||
store=True,
|
||||
)
|
||||
attempt_map_url = fields.Char(
|
||||
string='Map Preview',
|
||||
compute='_compute_attempt_map_url',
|
||||
)
|
||||
display_name = fields.Char(
|
||||
compute='_compute_display_name',
|
||||
store=True,
|
||||
)
|
||||
|
||||
LOG_TYPE_LABELS = {
|
||||
'clock_in': 'Clock In',
|
||||
'clock_out': 'Clock Out',
|
||||
'late_clock_in': 'Late Clock-In',
|
||||
'early_clock_out': 'Early Clock-Out',
|
||||
'outside_geofence': 'Outside Geofence',
|
||||
'auto_clock_out': 'Auto Clock-Out',
|
||||
'missed_clock_out': 'Missed Clock-Out',
|
||||
'absent': 'Absent',
|
||||
'leave_request': 'Leave Request',
|
||||
'reason_provided': 'Reason Provided',
|
||||
'overtime': 'Overtime',
|
||||
'correction_request': 'Correction Request',
|
||||
'ip_fallback': 'IP Fallback Used',
|
||||
'streak_milestone': 'Streak Milestone',
|
||||
}
|
||||
|
||||
@api.depends('latitude', 'longitude')
|
||||
def _compute_attempt_map_url(self):
|
||||
api_key = self.env['ir.config_parameter'].sudo().get_param(
|
||||
'fusion_clock.google_maps_api_key', ''
|
||||
)
|
||||
for rec in self:
|
||||
if rec.latitude and rec.longitude and api_key:
|
||||
lat, lng = rec.latitude, rec.longitude
|
||||
rec.attempt_map_url = (
|
||||
f"https://maps.googleapis.com/maps/api/staticmap?"
|
||||
f"center={lat},{lng}&zoom=16&size=600x250&maptype=roadmap"
|
||||
f"&markers=color:red%7C{lat},{lng}"
|
||||
f"&key={api_key}"
|
||||
)
|
||||
else:
|
||||
rec.attempt_map_url = False
|
||||
|
||||
@api.depends('employee_id', 'log_type', 'log_date')
|
||||
def _compute_display_name(self):
|
||||
for rec in self:
|
||||
emp = rec.employee_id.name or ''
|
||||
ltype = self.LOG_TYPE_LABELS.get(rec.log_type, rec.log_type or '')
|
||||
date_str = rec.log_date.strftime('%Y-%m-%d %H:%M') if rec.log_date else ''
|
||||
rec.display_name = f"{emp} - {ltype} ({date_str})"
|
||||
Reference in New Issue
Block a user