Simplify Attendance export status groups to 6 categories: 正常|遲到|早退|加班|異常/缺勤|假期/請假

This commit is contained in:
IT狗
2026-07-21 13:38:58 +08:00
parent c1b1d6f35b
commit 6f2df815f5
+36 -22
View File
@@ -3407,31 +3407,45 @@ async def export_excel(
earliest = min((r.date for r in rows if r.date), default=None) earliest = min((r.date for r in rows if r.date), default=None)
overview.merge_range("F7:G7", earliest.isoformat() if earliest else "-", kpi_value_fmt) overview.merge_range("F7:G7", earliest.isoformat() if earliest else "-", kpi_value_fmt)
# Status distribution table (B10:D) # Status distribution table — simplified 6-group (B10:D)
overview.write("B10", "出勤狀態分佈", section_fmt) overview.write("B10", "出勤狀態分佈", section_fmt)
overview.write("B11", "Status", header_fmt_ov) overview.write("B11", "Status", header_fmt_ov)
overview.write("C11", "數量", header_fmt_ov) overview.write("C11", "數量", header_fmt_ov)
overview.write("D11", "百分比", header_fmt_ov) overview.write("D11", "百分比", header_fmt_ov)
status_codes_order = ["normal", "late", "late_early", "late_ot", "early", "early_ot", "ot", "abnormal", "missing", # Simplified 6-group status
"holiday", "al", "sl", "cl", "mixed_leave"] _grp_status = {
status_labels = { "正常": 0, "遲到": 0, "早退": 0, "加班": 0, "異常/缺勤": 0, "假期/請假": 0, "(空)": 0,
"normal": "正常", "late": "遲到", "late_early": "遲到+早走",
"late_ot": "遲到+加班", "early": "早走", "early_ot": "早走+加班",
"ot": "加班", "abnormal": "異常", "missing": "缺勤",
"holiday": "🏖️公假", "al": "年假 AL", "sl": "病假 SL", "cl": "補鐘 CL",
"mixed_leave": "混合假",
} }
for i, code in enumerate(status_codes_order): for r in rows:
count = sum(1 for r in rows if (r.status_code or "").lower() == code) c = (r.status_code or "").lower()
overview.write(11 + i, 1, status_labels.get(code, code), cell_fmt_ov) if not c.strip():
_grp_status["(空)"] += 1
elif c == "normal":
_grp_status["正常"] += 1
elif "late" in c and "early" in c:
_grp_status["遲到"] += 1
elif "late" in c:
_grp_status["遲到"] += 1
elif "early" in c:
_grp_status["早退"] += 1
elif "ot" in c:
_grp_status["加班"] += 1
elif c in ("abnormal", "missing", "", " "):
_grp_status["異常/缺勤"] += 1
else:
_grp_status["假期/請假"] += 1
_total = len(rows)
for i, (label, count) in enumerate(_grp_status.items()):
overview.write(11 + i, 1, label, cell_fmt_ov)
overview.write(11 + i, 2, count, cell_fmt_ov) overview.write(11 + i, 2, count, cell_fmt_ov)
pct = (count / len(rows) * 100) if rows else 0 pct = (count / _total * 100) if _total else 0
overview.write(11 + i, 3, f"{pct:.1f}%", cell_fmt_ov) overview.write(11 + i, 3, f"{pct:.1f}%", cell_fmt_ov)
unk = sum(1 for r in rows if not (r.status_code or "").strip()) _n_status_groups = len(_grp_status)
overview.write(11 + len(status_codes_order), 1, "(空)", cell_fmt_ov) # Also update KPI counters to match simplified grouping
overview.write(11 + len(status_codes_order), 2, unk, cell_fmt_ov) n_late_grp = _grp_status["遲到"]
pct_unk = (unk / len(rows) * 100) if rows else 0 n_early_grp = _grp_status["早退"]
overview.write(11 + len(status_codes_order), 3, f"{pct_unk:.1f}%", cell_fmt_ov) n_ot_grp = _grp_status["加班"]
n_abn_grp = _grp_status["異常/缺勤"]
# Department TOP 10 table (F10:G) # Department TOP 10 table (F10:G)
overview.write("F10", "部門記錄數 (TOP 10)", section_fmt) overview.write("F10", "部門記錄數 (TOP 10)", section_fmt)
@@ -3449,8 +3463,8 @@ async def export_excel(
status_pie = wb.add_chart({"type": "pie"}) status_pie = wb.add_chart({"type": "pie"})
status_pie.add_series({ status_pie.add_series({
"name": "出勤狀態分佈", "name": "出勤狀態分佈",
"categories": ["總覽", 11, 1, 11 + len(status_codes_order), 1], "categories": ["總覽", 11, 1, 11 + _n_status_groups, 1],
"values": ["總覽", 11, 2, 11 + len(status_codes_order), 2], "values": ["總覽", 11, 2, 11 + _n_status_groups, 2],
"data_labels": {"percentage": True, "category": False, "position": "outside_end"}, "data_labels": {"percentage": True, "category": False, "position": "outside_end"},
}) })
status_pie.set_title({"name": "出勤狀態分佈 (Pie)"}) status_pie.set_title({"name": "出勤狀態分佈 (Pie)"})
@@ -3480,8 +3494,8 @@ async def export_excel(
status_col_chart = wb.add_chart({"type": "column"}) status_col_chart = wb.add_chart({"type": "column"})
status_col_chart.add_series({ status_col_chart.add_series({
"name": "出勤狀態 數量", "name": "出勤狀態 數量",
"categories": ["總覽", 11, 1, 11 + len(status_codes_order) - 1, 1], "categories": ["總覽", 11, 1, 11 + _n_status_groups - 1, 1],
"values": ["總覽", 11, 2, 11 + len(status_codes_order) - 1, 2], "values": ["總覽", 11, 2, 11 + _n_status_groups - 1, 2],
"fill": {"color": "#10B981"}, "fill": {"color": "#10B981"},
"border": {"color": "#065F46"}, "border": {"color": "#065F46"},
"data_labels": {"value": True}, "data_labels": {"value": True},