本次将账号、课时、开课和预约写入统一的新数据库。旧同步网关不再接受这些业务的回写。完整路径为:总部给门店入账 → 创建学员 → 门店划拨 → 分类和内容开课 → 排课预留 → 完课扣除。管理员记账不代表在线收款或现金退款。
scripts/sql/member-enrollment.sql 安装数据库事务函数。CreditTransaction 保存总部入账、双边划拨和原单退回,双方流水及 SysLog 审计同事务提交。EnrollmentCommand 保存开课、排课请求和操作记录,按帐套及幂等键防重。相同键但不同业务内容拒绝。
CourseBinding 使用 categoryKey、categoryName、enrollmentStatus;有效记录按帐套、学员、分类、内容唯一。CommonModel 使用模型 58、栏目 28、ZL_C_kcbd,内容节点写入 kcid。开课不扣减、不预留;至少一个有效授课规则的全部账户可用量必须足够。
排课、改期、取消恢复、开始上课和完课使用数据库事务。帐套事务锁统一写入顺序,账户行锁保护余额和预留。旧资料保存若会覆盖已改变的余额,触发器拒绝并提示刷新。课时退回只能返还原划拨门店,受原单未退数及当前可用量约束。
完课将预约、预留、四类课时流水及 LessonRecord 一次性提交;重试不重复扣费。App 复习计划仍沿用现有生成流程,事务失败会清理本次新建计划。教师通用内容编辑不可改写预约的课程或分类。
npm run members:migrate -- --validate 检查迁移文件;不连接服务器。XIAOSHU_MASTER_KEY 的发布环境执行 npm run members:migrate。默认只读,导出受限权限的 tmp/member-enrollment-*/before.json 和 report.json,记录 SQL 摘要。自定义环境可设置 XIAOSHU_PARSE_URL、XIAOSHU_PARSE_APP_ID。--acknowledged-deficits=/受限路径/deficits.json 单独声明:数组项包括 objectId、account、准确 balance 和 evidence。仅允许保留没有预留的既有负数;不会改写余额或放过超额预留。npm run members:migrate -- --apply。它先备份,再补 Parse schema,执行确定性修复和约束安装,最后清理临时迁移函数和临时账号。历史分类仅采用唯一、已确认的新分类映射;其他记录标记 pending,历史进度保留。错误模型栏目修为 28 / ZL_C_kcbd;缺少关联、分类冲突和重复绑定保留待核对,不删除或合并学习历史。历史预约快照不重算,无法唯一定位绑定的旧接口要求明确 bindingId。pending 记录需依据报告人工核对分类和预约后恢复有效状态。
发布前应在服务器 PostgreSQL 的独立连接下验证最后一节课竞争、充值与完课竞争、退款与预留竞争。当前本地 PGlite 测试执行真实 SQL 事务并包含竞争请求,但 PGlite 单实例会串行调度,不能替代服务器多连接锁竞争验收。
npm run test:member-enrollment:数据库事务、网关分类资格、旧接口歧义、按日期快照、账号精确查询、运营开课排课与教师完课的本地联调。npm run test:admin:ci:管理端交互,含分类切换清空选择、余额不足禁选、充值重试幂等。npm run test:mobile:ci:用户和教师课程入口、预约固定内容、学习记录及原有无预约学习流程。npm run test:review-rewards:受影响的完课与工资奖励回归。npm run cloud:validate、npm run build:云函数语法及管理端、移动端生产构建。2026-09-09 已使用受限发布凭据完成生产备份、迁移及四个网关发布;真实隔离账户验收见 上线验收记录。管理端与移动端生产构建已完成,公网静态站点发布仍需明确托管地址。
npm run members:smoke 创建隔离门店、教师和学员,在目标服务器执行真实业务、并发 HTTP 请求与对账,最终清理测试业务行、临时函数和账号,保留审计记录。需要 XIAOSHU_MASTER_KEY;切换环境可设置 XIAOSHU_SERVER_URL、XIAOSHU_PARSE_APP_ID、XIAOSHU_COMPANY_ID。隔离状态文件仅写入权限受限的 tmp 目录,清理失败时根据文件定位残留资源。不要与会比较全站人数的 ops:smoke 同时运行。