旧排课在教师端无法开始的修复验收
2026-10-12,北京时间。生产环境 server.xiaoshu.pro,应用 7pIbDBJmKx_main。
原因
预约主附表已导入,不等于新系统的开课、分类、课时预留链路已成立。截图预约的既有开课记录仍处于 pending,预约缺少 bindingId、creditCostsSnapshot 等字段,因此单元接口拒绝访问,详情不提供 start 权限。原历史预留预览和提交还按预约的具体钟点判断过期,漏掉当天已过预约钟点、但仍应可开始的课次。
另发现一名学员的新系统档案完全缺少四个课时余额字段,形成“没有余额”的误判。不是将旧余额覆盖到已有余额的场景。
修复行为
- App 详情在预约当天对缺凭据的旧预约进行原子核对;开始入口也会核对,不能依赖一次旧详情的结果。
- SQL 再验帐套、实际操作者与预约师生关系;仅处理未开始、未取消、未交给新教学流程管理的历史预约。
- 仅使用同学员、同课程、唯一的已有开课记录。重复、回收、缺内容、未确认分类、课程编号冲突保持阻塞,不新增或猜测开课。
- 旧开课 pending/null 仅在分类已有可靠确认、课程内容有效且余额足够时恢复。空分类可从唯一已确认的非写作分类补齐;全局写作分类不替代逐人确认。
- 复用管理端默认规则,正式保存的版本覆盖默认版本。按课程日期匹配;已有工资快照保留。
- 开课状态、快照、预留、审计在同一事务中完成。补建预留不扣余额、不启动课程、不生成上课记录。失败整体回滚,重试不重复预留或审计。
- 历史预留预览/提交统一按北京时间预约日判断有效期。
生产验收
- 当天有老师、未开始的旧预约共 10 节,修复后 10 节均具备绑定、有效快照及唯一预留,状态保持未开始。
- 截图预约以真实教师现有会话调用 e_order_detail,返回 allowedActions=[start]、validToday=true、blockedReason 为空。node_list 返回 1 个单元、3,087 个词条。
- 使用生产开始事务做回滚验证,事务中可到达学习中,回滚后仍未开始;未替老师实际开始或结课。
- 缺余额档案经旧 user_list 两次实时核对,且新库无该学员课时交易、四类流水或新流程完课;只恢复原本缺失的字段:30分钟课时40、60分钟课时0、体验课时0、陪练时长20。保留其余档案字段,审计入库,重复恢复返回 alreadyRestored。
- 其余学员余额未改动。10条预约凭据修复审计、1条缺余额恢复审计。
- 小赵(858566)、花花(858626)的“2025高考卷考点”原被归为体验课,与旧预约普通60分钟课冲突。用户明确确认“普通单词课,使用60分钟课时及陪练时长”后,仅修正两人的既有开课分类及对应预约;全局课程分类保留。版本核对、分类确认审计、预约快照及预留在同一事务完成。
- 两节预约生产回读均为普通单词课、60分钟、线上,每节预留 SilverCoin 1、UserPoint 1,教师工资快照30元。余额、学习进度与未开始状态保持不变;重复确认返回 alreadyConfirmed,无重复预留。
- 使用所属真实教师的现有会话分别调用两节预约的 e_order_detail,均返回 allowedActions=[start]、validToday=true、blockedReason 为空;两次 node_list 均返回1个单元、214个词条。不是替老师实际开始或完成课程。
- App、运营主网关、运营V3均已部署,并逐字核对线上代码与本地打包代码一致。migration_status版本为
2026-10-12-legacy-appointment-v3。
验证与发布
70项相关Node/PGlite测试通过,涵盖当天过钟点、权限和空教师ID、跨帐套、取消、过期、重复开课、课时不足、快照保留、详情权限、审计失败回滚、缺失非写作分类等。11个云函数定义语法校验通过。
窄迁移入口:node scripts/migrate-legacy-appointment-preparation.mjs --apply。仅安装受影响的两个SQL例程;使用已有帐套管理员会话,备份部署前后的定义,清理临时函数,不创建测试用户、不执行历史全量回填。凭据从执行环境提供,备份目录使用 XIAOSHU_LEGACY_PREPARE_REPORT_DIR。
私有证据与备份:/Users/mac/.local/state/xiaoshu/appointment-repair/2026-10-12/。含回滚验收、实际教师接口、生产数据回读、旧系统证据、函数部署前后代码等,均不提交Git。未以伪造检查点或成功日志放行工资结算,也未改变夜间同步的验收状态。