forked from wangziqi/gongxue-base
feat: settle course attendance automatically
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# 课程二态考勤与截止自动结算设计
|
||||
|
||||
## 目标
|
||||
|
||||
课程考勤仅向教师展示“已打卡 / 未打卡”。迟到属于已打卡。每节课程到达截止时间后,系统自动从钉钉做最后一次拉取并将最终结果写入课程考勤记录;截止仍无实际打卡的学生记为缺勤。
|
||||
|
||||
## 范围
|
||||
|
||||
- 仅调整排课关联的课程考勤。
|
||||
- 不迁移历史记录。
|
||||
- 不改变后台其他考勤来源、迟到统计或钉钉原始数据。
|
||||
- 不引入队列或新依赖,复用 NestJS Schedule 与现有导入、匹配、课程考勤服务。
|
||||
|
||||
## 状态规则
|
||||
|
||||
### 教师当前课程页面
|
||||
|
||||
- 存在课程时间窗口内的实际打卡时间:显示“已打卡”。
|
||||
- 不存在实际打卡时间:显示“未打卡”。
|
||||
- `Late`、`SeriousLate` 和 `Normal` 均显示为“已打卡”。
|
||||
- 页面汇总仅显示已打卡数、未打卡数和总人数。
|
||||
|
||||
### 最终记录
|
||||
|
||||
- 截止时存在实际打卡时间:`present`。
|
||||
- 截止时不存在实际打卡时间:`absent`。
|
||||
- 钉钉原始记录继续保留 `timeResult`,因此不会丢失迟到信息。
|
||||
- 自动结算完成后,课程考勤场次状态改为 `completed`,不再被后续拉取覆盖。
|
||||
|
||||
## 自动结算
|
||||
|
||||
后台任务每分钟扫描:
|
||||
|
||||
1. 当天有效的内部课程;
|
||||
2. 当前时间已经达到课程 `endTime`;
|
||||
3. 对应日期的课程考勤场次尚未完成或尚未创建。
|
||||
|
||||
对每节符合条件的课程:
|
||||
|
||||
1. 获取该班在读学生的钉钉用户 ID;
|
||||
2. 拉取当天最终钉钉考勤并自动匹配;
|
||||
3. 创建或刷新课程考勤记录;
|
||||
4. 将有实际打卡的记录归为 `present`,其余归为 `absent`;
|
||||
5. 将场次标记为 `completed`。
|
||||
|
||||
任务按课程独立处理。单节课拉取失败只记录错误,其他课程继续;下一分钟继续补偿失败课程。现有 `(scheduleId, lessonDate)` 唯一约束和完成状态保证重复扫描幂等。
|
||||
|
||||
跨午夜课程以结束时间不晚于开始时间判断为次日截止;扫描同时覆盖昨日跨午夜课程。
|
||||
|
||||
## 手动查看
|
||||
|
||||
课程开始后,教师点击“查看当前考勤”仍会拉取最新数据。课程截止前结果是临时二态视图;课程截止后读取自动结算的最终记录。若自动任务尚未成功,手动查看可继续拉取,但只有自动结算或明确完成操作会冻结最终结果。
|
||||
|
||||
## 测试
|
||||
|
||||
- 迟到且存在实际打卡时间时,当前课程视图为“已打卡”。
|
||||
- 无实际打卡时间时,当前课程视图为“未打卡”。
|
||||
- 截止结算把迟到和正常打卡写为 `present`。
|
||||
- 截止结算把无打卡写为 `absent` 并完成场次。
|
||||
- 未截止课程不结算。
|
||||
- 重复扫描已完成课程不重复拉取或写入。
|
||||
- 单节课程失败不阻断其他课程,后续扫描可补偿。
|
||||
- 跨午夜课程在次日截止后结算。
|
||||
Reference in New Issue
Block a user