7.6 KiB
7.6 KiB
07. 考勤统计语义与指标口径规范 (Attendance Analytics Semantics)
版本:V1.0 (Package C 闭环基线)
更新日期:2026-09-21
适用模块:管理驾驶舱 (Dashboard)、考勤专题分析 (Attendance Analytics)、学员 360 画像 (Student360)、考勤异常 Top 10
核心原则:统一底层 Expected Attendance Universe 聚合语义,严格隔离未来课次,严格区分缺勤与未签到,技术语义守恒闭环。
1. 冻结技术语义 (Frozen Technical Semantics)
| 技术语义项 | 规范定义 | 技术落地点 | 解决问题 |
|---|---|---|---|
| 已开始课次 (Started Lesson) | lesson.start_time <= CURRENT_TIMESTAMP未来课次打卡记录严格隔离,不得进入任何当前历史统计。 |
TrainAnalysisMapper.xml 所有考勤聚合统一条件 l.start_time <= CURRENT_TIMESTAMP |
C07 关闭:消除 Dashboard 状态分布泄漏 46 条未来课次打卡记录缺陷。 |
| 应到基准集 (Expected Attendance Universe) | STARTED_LESSONS × PLAN_COURSES × ELIGIBLE_ENROLLMENTS LEFT JOIN CHECKIN由计划已开课次与计划参训学员关系形成应到基准,不得由打卡流水作为驱动表。 |
共享查询基准 expectedAttendanceBase / filteredAttendanceConditions |
C08 关闭:消除异常 Top 10 仅从打卡流水统计导致未打卡学员不可见缺陷。 |
| 显式缺勤 vs 未签到 | - 显式缺勤 (Explicit Absence):打卡流水存在且 attendance_status = 0。- 未签到 (No Checkin):无打卡流水行( checkin_id IS NULL)。两者在状态分布、Top 10、学员画像中严格互斥,不得隐式混淆。 |
状态派生:CASE WHEN c.checkin_id IS NULL THEN 'NO_CHECKIN' ELSE CAST(c.attendance_status AS VARCHAR) END |
杜绝将无流水学员擅自改写为 status=0,客观反映教务未核验状态。 |
| 趋势时间轴 (Trend Time Axis) | 每日考勤打卡走势时间轴必须锚定 lesson.start_time,严禁锚定 sign_in_time。确保正常、迟到、早退、请假、明确缺勤、未签到均落入课次排课日期。 |
TO_CHAR(l.start_time, 'YYYY-MM-DD') AS stat_date 统一分组 |
C06 关闭:消除因 sign_in_time IS NULL 导致缺勤/请假/未签到无法进入走势的缺陷。 |
| 状态分布守恒律 | EXPECTED_PERSON_TIMES = NORMAL + LATE + EARLY + LEAVE + EXPLICIT_ABSENCE + NO_CHECKIN |
Dashboard 与 Attendance 共享 buildStatusDistribution |
全局与专题分析在无筛选或相同筛选条件下统计口径严格 1:1 相等。 |
| 走势守恒律 | 筛选范围内各日期走势累加 SUM(normal_count + abnormal_count) 严格等于该范围内的 EXPECTED_PERSON_TIMES。 |
selectFilteredDailyTrend |
走势无漏项、无未来虚假漂移。 |
2. 待确认业务定义清单 (Business Definitions Pending Confirmation)
以下规则由于缺乏业务需求权威定论或底层数据表时序字段支撑,代码中均以策略开关或明确常量集中隔离,严禁作为已定案的最终甲方规则:
2.1 PENDING-01: 待报到参训学员的应到基准 (WAITING_ENROLLMENT_EXPECTED_POLICY)
- 状态:
BUSINESS_DEFINITION_REQUIRED - 问题说明:学员参训记录为
status=0(待报到)且无报到核验流水时,是否从该培训班开班的第一节课起就计入应到基准分母。 - 当前处理:V1 默认不以
EXISTS(train_class_report)过滤应到集合,确保未到场报到人员可进入缺勤/未签到统计;待甲方确认是否仅针对开班前已完成报名审核的名单起算。
2.2 PENDING-02: 考勤请假是否计入出勤率分母 (LEAVE_DENOMINATOR_POLICY)
- 状态:
BUSINESS_DEFINITION_REQUIRED - 问题说明:学员在某课次拥有
attendance_status=4(请假)流水时,该人次是否从出勤率分母(应到人次)中扣除,还是保留在分母但计为非正常出勤。 - 当前处理:当前系统出勤率公式为
正常出勤人次 / 应到总人次(请假保留在分母,但非正常)。页面与 API 返回均携带metricDefinitionNotice = BUSINESS_METRIC_DEFINITION_PENDING_CONFIRMATION声明。
2.3 PENDING-03: 放弃参训学员的历史课次有效性 (ABANDON_HISTORICAL_POLICY)
- 状态:
BUSINESS_DEFINITION_REQUIRED - 问题说明:学员参训状态为
status=3(放弃)时,由于train_enrollment表无状态变更生效时间区间(HISTORICAL_ENROLLMENT_ELIGIBILITY_EXACT = NO),无法精准切分放弃前与放弃后的课次。 - 当前处理:当前统计按所属计划完整名单统计,不利用当前最终状态逆向重写历史;待建立学员流转审计历史表后重构精确时间切片。
2.4 PENDING-04: 请假是否计入考勤异常排行 (LEAVE_COUNTS_AS_ABNORMAL)
- 状态:
BUSINESS_DEFINITION_PENDING_CONFIRMATION - 问题说明:请假属于审批合规事项,部分管理制度认为请假不属于“违规异常考勤”,不应计入 Top 10 预警排行榜。
- 当前处理:集中在
TrainAnalysisServiceImpl.LEAVE_COUNTS_AS_ABNORMAL_DEFAULT = true(当前预览保持系统现有计入异常口径),并通过AttendanceFilterDto.includeLeaveAsAbnormal支持单点无缝切换,未散落硬编码。
3. 跨模块考勤统计语义对齐矩阵
| 功能界面 / API | 基础驱动集 | 正常出勤 | 异常考勤构成 | 未签到 (无打卡) | 未来课次防护 |
|---|---|---|---|---|---|
管理驾驶舱 状态分布/train/analysis/dashboard/charts |
已开始课次 × 班级学员 | 正常出勤 (1) |
迟到(2)、早退(3)、请假(4)、缺勤(0) |
未签到 (NO_CHECKIN) |
隔离(0 泄漏) |
管理驾驶舱 30天走势/train/analysis/dashboard/charts |
已开始课次 × 班级学员 | 正常人次 (1) |
异常人次 (0,2,3,4,NO_CHECKIN) |
计入异常人次 | 隔离(0 泄漏) |
考勤专题 状态构成/train/analysis/attendance/charts |
已开始课次 × 班级学员 | 正常出勤 (1) |
迟到(2)、早退(3)、请假(4)、缺勤(0) |
未签到 (NO_CHECKIN) |
隔离(0 泄漏) |
考勤专题 每日趋势/train/analysis/attendance/charts |
已开始课次 × 班级学员 | 正常人次 (1) |
异常人次 (0,2,3,4,NO_CHECKIN) |
计入异常人次 | 隔离(0 泄漏) |
考勤异常 Top 10/train/analysis/attendance/charts |
已开始课次 × 班级学员 | 不参与排行 | 缺勤(absentCount)、迟到(lateCount)、早退(earlyLeaveCount)、请假(leaveCount) |
未签到 (noCheckinCount) |
隔离(0 泄漏) |
学员 360 画像 考勤卡片/train/analysis/portrait/student-360/{id} |
该学员所属计划已开始课次 | 正常出勤 (normalCount) |
迟到、早退、请假、明确缺勤 | 未签到 (noCheckinCount) |
隔离(0 泄漏) |
4. 数据库只读验证事实 (Kingbase QA Live Snapshot)
在 railwaysystem_integrated_qa_20260916 数据库实例上的只读验证结果:
- 课次总数:118,其中已开始课次:1(Lesson 90),未来课次:117。
- 考勤打卡记录总数:77,其中已开始课次打卡:31,未来课次打卡:46。
- 已开始课次应到人次:31,打卡匹配人次:31,未签到人次:0。
- 31 人次考勤分布:正常 31,迟到 0,早退 0,请假 0,缺勤 0,未签到 0。
- 守恒断言:
EXPECTED_PERSON_TIMES (31) = NORMAL (31) + ABNORMAL (0),PASS。 - 未来打卡泄漏:
FUTURE_LESSON_ANALYTICS_LEAK_COUNT = 0,PASS。 DUPLICATE_CHECKIN_KEY_COUNT = 0,无重复打卡键。