65 lines
2.0 KiB
Python
65 lines
2.0 KiB
Python
from datetime import datetime, time, timedelta
|
|
from django.utils import timezone
|
|
from .models import AttendanceLog, DailyAttendance, Employee, Shift
|
|
|
|
def calculate_daily_attendance(employee, date):
|
|
"""
|
|
Calculate summary for a specific employee on a specific date.
|
|
"""
|
|
logs = AttendanceLog.objects.filter(
|
|
employee=employee,
|
|
timestamp__date=date
|
|
).order_by('timestamp')
|
|
|
|
if not logs.exists():
|
|
# Check if they are on leave (simplified for now)
|
|
# In a real app, we'd check LeaveRequest for this date
|
|
return None
|
|
|
|
check_in = logs.first().timestamp.time()
|
|
check_out = logs.last().timestamp.time()
|
|
|
|
# Calculate worked hours
|
|
first_log = logs.first().timestamp
|
|
last_log = logs.last().timestamp
|
|
duration = last_log - first_log
|
|
worked_hours = duration.total_seconds() / 3600
|
|
|
|
# Determine status based on shift
|
|
status = 'present'
|
|
is_late = False
|
|
|
|
if employee.shift:
|
|
# If check-in is 15 mins later than shift start, mark as late
|
|
shift_start_datetime = datetime.combine(date, employee.shift.start_time)
|
|
check_in_datetime = datetime.combine(date, check_in)
|
|
|
|
if check_in_datetime > (shift_start_datetime + timedelta(minutes=15)):
|
|
status = 'late'
|
|
is_late = True
|
|
|
|
# Update or create summary
|
|
summary, created = DailyAttendance.objects.update_or_create(
|
|
employee=employee,
|
|
date=date,
|
|
defaults={
|
|
'check_in': check_in,
|
|
'check_out': check_out,
|
|
'status': status,
|
|
'is_late': is_late,
|
|
'worked_hours': round(worked_hours, 2)
|
|
}
|
|
)
|
|
return summary
|
|
|
|
def sync_all_daily_summaries(date=None):
|
|
"""
|
|
Utility to refresh summaries for all employees.
|
|
"""
|
|
if not date:
|
|
date = timezone.now().date()
|
|
|
|
employees = Employee.objects.filter(is_active=True)
|
|
for emp in employees:
|
|
calculate_daily_attendance(emp, date)
|