Updated overtime calculations (GOOD STATE)
This commit is contained in:
@@ -5516,7 +5516,7 @@ def get_miss_punch_details(employee_id):
|
|||||||
converted_records.append(converted_record)
|
converted_records.append(converted_record)
|
||||||
|
|
||||||
# Calculate working hours using the same calculator as the dashboard
|
# Calculate working hours using the same calculator as the dashboard
|
||||||
from single_checkin_calculator import SingleCheckInCalculator
|
# from single_checkin_calculator import SingleCheckInCalculator
|
||||||
calculator = SingleCheckInCalculator()
|
calculator = SingleCheckInCalculator()
|
||||||
|
|
||||||
# Calculate hours for this employee
|
# Calculate hours for this employee
|
||||||
|
|||||||
+42
-30
@@ -700,9 +700,9 @@ class PayrollExcelExporter:
|
|||||||
return current_row
|
return current_row
|
||||||
|
|
||||||
def _write_employee_section(self, worksheet, employee_id: str, employee_name: str,
|
def _write_employee_section(self, worksheet, employee_id: str, employee_name: str,
|
||||||
emp_data: Dict, start_date: datetime, end_date: datetime,
|
emp_data: Dict, start_date: datetime, end_date: datetime,
|
||||||
attendance_records: List[Dict], start_row: int) -> int:
|
attendance_records: List[Dict], start_row: int) -> int:
|
||||||
"""Write individual employee section with multiple pairs per day, daily totals, weekly totals, and grand total"""
|
"""Write individual employee section with FIXED WEEKLY OVERTIME CALCULATION"""
|
||||||
current_row = start_row
|
current_row = start_row
|
||||||
|
|
||||||
# Employee info header (merged across columns A-O)
|
# Employee info header (merged across columns A-O)
|
||||||
@@ -746,12 +746,10 @@ class PayrollExcelExporter:
|
|||||||
day_info['location'] = sorted_records[0].qr_code.location or ''
|
day_info['location'] = sorted_records[0].qr_code.location or ''
|
||||||
day_info['building_address'] = sorted_records[0].qr_code.location_address or ''
|
day_info['building_address'] = sorted_records[0].qr_code.location_address or ''
|
||||||
|
|
||||||
# Initialize weekly totals tracking
|
# FIXED: Initialize ALL weekly totals tracking variables
|
||||||
weekly_regular_hours = 0
|
|
||||||
weekly_ot_hours = 0
|
|
||||||
weekly_total_hours = 0
|
weekly_total_hours = 0
|
||||||
|
|
||||||
# Track overall totals for grand total
|
# Track overall totals for grand total
|
||||||
grand_regular_hours = 0
|
grand_regular_hours = 0
|
||||||
grand_ot_hours = 0
|
grand_ot_hours = 0
|
||||||
grand_total_hours = 0
|
grand_total_hours = 0
|
||||||
@@ -760,6 +758,9 @@ class PayrollExcelExporter:
|
|||||||
# Track week boundaries (assuming payroll period starts on Monday)
|
# Track week boundaries (assuming payroll period starts on Monday)
|
||||||
current_week_start = None
|
current_week_start = None
|
||||||
|
|
||||||
|
# Log the overtime calculation change
|
||||||
|
print(f"🔧 FIXED: Using weekly overtime calculation (40 hrs/week) for employee {employee_id}")
|
||||||
|
|
||||||
# Write data rows using the calculated daily hours from emp_data
|
# Write data rows using the calculated daily hours from emp_data
|
||||||
for date_str in sorted(emp_data['daily_hours'].keys()):
|
for date_str in sorted(emp_data['daily_hours'].keys()):
|
||||||
date_obj = datetime.strptime(date_str, '%Y-%m-%d')
|
date_obj = datetime.strptime(date_str, '%Y-%m-%d')
|
||||||
@@ -780,30 +781,33 @@ class PayrollExcelExporter:
|
|||||||
# Calculate week boundaries
|
# Calculate week boundaries
|
||||||
week_start = date_obj - timedelta(days=date_obj.weekday()) # Monday of the week
|
week_start = date_obj - timedelta(days=date_obj.weekday()) # Monday of the week
|
||||||
|
|
||||||
# Check if we've moved to a new week and need to write weekly total
|
# FIXED: Check if we've moved to a new week and need to write weekly total
|
||||||
if current_week_start is not None and week_start != current_week_start:
|
if current_week_start is not None and week_start != current_week_start:
|
||||||
|
# Calculate weekly overtime using 40-hour threshold
|
||||||
|
week_regular = min(weekly_total_hours, 40.0)
|
||||||
|
week_overtime = max(0, weekly_total_hours - 40.0)
|
||||||
|
|
||||||
# Write weekly total row for previous week
|
# Write weekly total row for previous week
|
||||||
current_row = self._write_weekly_total_row(worksheet, current_row,
|
current_row = self._write_weekly_total_row(worksheet, current_row,
|
||||||
weekly_regular_hours, weekly_ot_hours, weekly_total_hours)
|
week_regular, week_overtime, weekly_total_hours)
|
||||||
|
|
||||||
|
# Add to grand totals
|
||||||
|
grand_regular_hours += week_regular
|
||||||
|
grand_ot_hours += week_overtime
|
||||||
|
|
||||||
# Reset weekly counters
|
# Reset weekly counters
|
||||||
weekly_regular_hours = 0
|
|
||||||
weekly_ot_hours = 0
|
|
||||||
weekly_total_hours = 0
|
weekly_total_hours = 0
|
||||||
|
|
||||||
current_week_start = week_start
|
current_week_start = week_start
|
||||||
|
|
||||||
total_hours = day_hours_data.get('total_hours', 0)
|
total_hours = day_hours_data.get('total_hours', 0)
|
||||||
regular_hours = min(total_hours, 8.0) # Max 8 regular hours per day
|
|
||||||
ot_hours = max(0, total_hours - 8.0)
|
|
||||||
|
|
||||||
# Add to weekly and grand totals
|
# FIXED: Remove daily overtime calculation - now calculated weekly only
|
||||||
weekly_regular_hours += regular_hours
|
# OLD CODE: regular_hours = min(total_hours, 8.0) # Max 8 regular hours per day
|
||||||
weekly_ot_hours += ot_hours
|
# OLD CODE: ot_hours = max(0, total_hours - 8.0)
|
||||||
|
|
||||||
|
# Add to weekly totals (no daily overtime calculation)
|
||||||
weekly_total_hours += total_hours
|
weekly_total_hours += total_hours
|
||||||
|
|
||||||
grand_regular_hours += regular_hours
|
|
||||||
grand_ot_hours += ot_hours
|
|
||||||
grand_total_hours += total_hours
|
grand_total_hours += total_hours
|
||||||
|
|
||||||
# Get location info for this date
|
# Get location info for this date
|
||||||
@@ -829,10 +833,11 @@ class PayrollExcelExporter:
|
|||||||
start_record = day_records[i]
|
start_record = day_records[i]
|
||||||
end_record = day_records[i + 1]
|
end_record = day_records[i + 1]
|
||||||
|
|
||||||
|
# FIXED: Pass total_hours without daily overtime split
|
||||||
current_row = self._write_record_pair_row(
|
current_row = self._write_record_pair_row(
|
||||||
worksheet, current_row, date_obj, start_record, end_record,
|
worksheet, current_row, date_obj, start_record, end_record,
|
||||||
location, building_address, total_hours, regular_hours, ot_hours,
|
location, building_address, total_hours, 0, 0, # No daily regular/ot split
|
||||||
pairs_written, total_hours, total_pairs_for_day # Add total_pairs parameter
|
pairs_written, total_hours, total_pairs_for_day
|
||||||
)
|
)
|
||||||
pairs_written += 1
|
pairs_written += 1
|
||||||
total_pairs_written += 1 # Track total pairs
|
total_pairs_written += 1 # Track total pairs
|
||||||
@@ -841,13 +846,19 @@ class PayrollExcelExporter:
|
|||||||
start_record = day_records[0] if day_records else None
|
start_record = day_records[0] if day_records else None
|
||||||
current_row = self._write_single_record_row(
|
current_row = self._write_single_record_row(
|
||||||
worksheet, current_row, date_obj, start_record,
|
worksheet, current_row, date_obj, start_record,
|
||||||
location, building_address, total_hours, regular_hours, ot_hours
|
location, building_address, total_hours, 0, 0 # No daily regular/ot split
|
||||||
)
|
)
|
||||||
|
|
||||||
# Write final weekly total if we have data
|
# FIXED: Write final weekly total with proper weekly overtime calculation
|
||||||
if weekly_total_hours > 0:
|
if weekly_total_hours > 0:
|
||||||
|
week_regular = min(weekly_total_hours, 40.0)
|
||||||
|
week_overtime = max(0, weekly_total_hours - 40.0)
|
||||||
current_row = self._write_weekly_total_row(worksheet, current_row,
|
current_row = self._write_weekly_total_row(worksheet, current_row,
|
||||||
weekly_regular_hours, weekly_ot_hours, weekly_total_hours)
|
week_regular, week_overtime, weekly_total_hours)
|
||||||
|
|
||||||
|
# Add final week to grand totals
|
||||||
|
grand_regular_hours += week_regular
|
||||||
|
grand_ot_hours += week_overtime
|
||||||
|
|
||||||
# Write grand total row
|
# Write grand total row
|
||||||
current_row = self._write_grand_total_row(worksheet, current_row,
|
current_row = self._write_grand_total_row(worksheet, current_row,
|
||||||
@@ -856,8 +867,9 @@ class PayrollExcelExporter:
|
|||||||
# Add space between employees
|
# Add space between employees
|
||||||
current_row += 2
|
current_row += 2
|
||||||
|
|
||||||
# Log the export action (use print for now since logger_handler import is complex)
|
# Log the export action with fixed overtime calculation
|
||||||
print(f"✅ Template format export: Employee {employee_id} ({employee_name}) data written with {total_pairs_written} record pairs, weekly totals, and grand total")
|
print(f"✅ FIXED Template format export: Employee {employee_id} ({employee_name}) data written with weekly overtime calculation (40 hrs/week)")
|
||||||
|
print(f"📊 Total: {grand_total_hours:.2f} hrs, Regular: {grand_regular_hours:.2f} hrs, Overtime: {grand_ot_hours:.2f} hrs")
|
||||||
|
|
||||||
return current_row
|
return current_row
|
||||||
|
|
||||||
@@ -936,8 +948,8 @@ class PayrollExcelExporter:
|
|||||||
"", # F - Zone (empty)
|
"", # F - Zone (empty)
|
||||||
pair_hours, # G - Hours/Building
|
pair_hours, # G - Hours/Building
|
||||||
daily_total_display, # H - Daily Total (only on last pair)
|
daily_total_display, # H - Daily Total (only on last pair)
|
||||||
regular_hours if is_last_pair else "", # I - Regular Hours (only on last pair)
|
"", # I - Regular Hours (only on last pair)
|
||||||
ot_hours if is_last_pair else "", # J - OT Hours (only on last pair)
|
"", # J - OT Hours (only on last pair)
|
||||||
building_address_display, # K - Building Address
|
building_address_display, # K - Building Address
|
||||||
recorded_location_display, # L - Recorded Location
|
recorded_location_display, # L - Recorded Location
|
||||||
distance_value, # M - Distance
|
distance_value, # M - Distance
|
||||||
@@ -1002,8 +1014,8 @@ class PayrollExcelExporter:
|
|||||||
"", # F - Zone
|
"", # F - Zone
|
||||||
total_hours, # G - Hours/Building
|
total_hours, # G - Hours/Building
|
||||||
total_hours, # H - Daily Total
|
total_hours, # H - Daily Total
|
||||||
regular_hours, # I - Regular Hours
|
"", # I - Regular Hours
|
||||||
ot_hours, # J - OT Hours
|
"", # J - OT Hours
|
||||||
building_address, # K - Building Address
|
building_address, # K - Building Address
|
||||||
recorded_location, # L - Recorded Location
|
recorded_location, # L - Recorded Location
|
||||||
distance_value, # M - Distance
|
distance_value, # M - Distance
|
||||||
|
|||||||
Reference in New Issue
Block a user