Fix: use roster public_holiday column to determine if employee works on holidays, instead of checking clock-in

This commit is contained in:
IT狗
2026-07-21 12:26:27 +08:00
parent adc9e6451b
commit cca088261b
+24 -8
View File
@@ -128,8 +128,19 @@ def enrich_attendance_with_leave(records, db):
if r.date in holidays_by_date:
h = holidays_by_date[r.date]
# Only mark as holiday if no clock-in record
# (employee who worked on holiday should keep attendance status)
# Check roster: if shift's public_holiday == 'Yes', employee works on holidays
# Don't override with holiday status in that case
shift_holiday = '休息' # default: assume rest on holiday
if r.shift_code:
shift_info = get_shift_schedule_full(r.shift_code, r.weekday or '')
if shift_info and len(shift_info) >= 3:
shift_holiday = shift_info[2]
if shift_holiday == 'Yes':
# Employee works on public holidays - keep attendance status, append holiday note
base = r.status_text or "正常"
r.status_text = f"{base} (🎉{h.name})"
continue
# Employee rests on public holidays - mark as holiday unless already has clock-in
has_clock_in = (
(r.check_in is not None) or
(r.actual_in and r.actual_in not in ("", "-"))
@@ -138,9 +149,10 @@ def enrich_attendance_with_leave(records, db):
r.status_code = "holiday"
r.status_text = f"\U0001F3D6\uFE0F{h.name}"
continue
# Has clock-in on holiday: keep computed attendance status but append holiday flag
base = r.status_text or "正常"
r.status_text = f"{base} (🎉{h.name})"
# Has clock-in but roster says rest on holiday - still show holiday
r.status_code = "holiday"
r.status_text = f"\U0001F3D6\uFE0F{h.name}"
continue
emp_leaves = leave_by_emp_date.get(r.employee_name, {}).get(r.date, [])
if not emp_leaves:
@@ -504,7 +516,8 @@ async def _import_attendance_to_db(db: Session, headers, rows, user_id: int) ->
# ============ Attendance Calculation ============
def get_shift_schedule_full(shift_code: str, weekday: str) -> Optional[tuple]:
"""Get the expected start and end time for a shift on a given weekday.
Returns (start_time, end_time) tuple.
Returns (start_time, end_time, public_holiday) tuple.
public_holiday is 'Yes' if the shift requires working on public holidays, '休息' otherwise.
"""
roster_path = get_excel_path("roster")
if not os.path.exists(roster_path):
@@ -518,10 +531,12 @@ def get_shift_schedule_full(shift_code: str, weekday: str) -> Optional[tuple]:
# Find column indices
shift_col = None
ph_col = None
for i, h in enumerate(headers):
if h == '班次':
shift_col = i
break
elif h == 'public holiday':
ph_col = i
if shift_col is None:
return None
@@ -549,6 +564,7 @@ def get_shift_schedule_full(shift_code: str, weekday: str) -> Optional[tuple]:
# Find the shift row
for row in ws.iter_rows(min_row=2, values_only=True):
if row[shift_col] == shift_code:
public_holiday = str(row[ph_col]).strip() if ph_col is not None else '休息'
day_col = day_col_map.get(target_day)
if day_col is not None:
schedule = row[day_col]
@@ -561,7 +577,7 @@ def get_shift_schedule_full(shift_code: str, weekday: str) -> Optional[tuple]:
end_str = parts[1].strip()
start_time = datetime.strptime(start_str, '%H:%M').time()
end_time = datetime.strptime(end_str, '%H:%M').time()
return (start_time, end_time)
return (start_time, end_time, public_holiday)
except:
pass