# 实施计划:审批退回结果通知缺失治理 ## 实施顺序 1. 在通知类型常量中新增 `leave.returned`、`purchase_request.returned`、`travel_request.returned`,加入 IM 支持表和领域映射。 2. 扩展 workflow returned outcome 映射;不改 return 路由事务、状态、释放、allowedActions 或其他 outcome。 3. 补齐纯函数测试:逐个断言三个新类型在类型对象、IM 支持清单、领域映射三处注册完整,并覆盖五类 returned 矩阵及四类“可修改后重新提交”文案/摘要/deeplink。 4. 补齐 route/side-effect 测试:三类站内通知、收件人去重、email task、IM dispatch task、失败不回滚;若现有 harness 不足,只提取最小可测试编排 helper,不改变运行时职责。 5. 补齐 IM routing 和通知渠道 schema 测试:三种新类型的允许/拒绝矩阵,既有类型不漂移。 6. 回归报销 returned、所有 approved/rejected、请假额度释放、采购/差旅预算释放、补卡无 return 和通知失败容错。 7. 更新 `docs/领域事件清单.md`、`docs/集成边界.md` 与 `.trellis/spec/hyb-oa/approval-workflow.md`,只沉淀稳定 notification type 和副作用合同。 8. 完成本地质量门禁与只读 review。此任务涉及 workflow 和生产路由,reviewer 不得改代码。 9. 分别取得 commit、push、部署授权后发布代码候选;部署前不修改生产 routing。 10. 代码生产验收通过后,另行请求生产配置写入授权;按脱敏快照、有效矩阵 diff、管理 API PATCH、读回、审计顺序放行 routing。 11. 只有出现自然 return 或取得受控生产数据写入授权后才做真实两渠道验收;否则明确记录 `BLOCKED`。 ## 风险文件 - `server/src/constants/notificationTypes.js`:共享通知枚举与路由白名单,任何遗漏都会造成站内有通知但 IM 被静默跳过。 - `server/src/routes/workflow.js`:五类审批共用,必须只扩展 returned 类型映射。 - `server/src/routes/notifications.js`:管理 API schema 由支持清单生成,需证明新 routing 可写且旧配置兼容。 - `server/src/services/notifications/imRouting.js`:原则上不改;测试需证明三维过滤仍是 AND 关系。 - `docs/领域事件清单.md` 与 `docs/集成边界.md`:必须区分运行时 notification type 与领域 Outbox 事件,不能误写成新增消息总线事件。 ## 预期验证命令 ```bash cd server && npm run prisma:validate cd server && node --check src/constants/notificationTypes.js cd server && node --check src/routes/workflow.js cd server && npm test -- tests/unit/constants/notificationTypes.test.js tests/unit/routes/workflow.travel.test.js cd server && npm test -- tests/unit/services/imRouting.test.js tests/unit/services/imEnqueue.test.js tests/unit/services/notificationDispatcher.test.js cd server && npm test -- tests/unit/routes/notifications.test.js cd server && npm test -- tests/unit/routes/workflow.permissions.test.js tests/unit/routes/workflow.batch.test.js node scripts/qa/check-process-contract.mjs --baseline --json node scripts/qa/audit-docs.mjs --check-registry node scripts/qa/check-trellis-governance.mjs python3 ./.trellis/scripts/task.py validate 09-04-approval-return-notification-gap git diff --check ``` 实施时若新增聚焦 route test 文件,将其追加到命令,不用扩大为无关全仓测试来掩盖缺口。 ## Review 清单 1. 三种新类型是否在 `NOTIFICATION_TYPES`、`IM_SUPPORTED_NOTIFICATION_TYPES`、领域映射三处注册齐全,且三种渠道全部由 `resolveWorkflowOutcomeNotificationType` 的同一返回值驱动。 2. 三类收件人与 deeplink 是否复用现有实体元数据且正确去重。 3. 通知异常是否仍不回滚状态、history、假期或预算释放。 4. 报销 returned、其他 outcome、补卡和 allowedActions 是否零变化。 5. 生产 routing 变更是否被留在部署后独立授权阶段,代码或脚本中没有静默改生产配置。 6. 日志、测试 fixture、task 与证据中是否无真实人员、单据、通知正文、外部 ID、Secret 或原始 payload。 7. 退回通知是否明确“可修改后重新提交”,且没有复用驳回措辞。 ## 提交与部署边界 - commit message 使用中文并引用 `09-04-approval-return-notification-gap`。 - 实施完成后先交 diff 与只读 review 结果;用户批准后才能提交。 - commit、push、应用部署、生产 routing 写入、受控生产单据创建/退回分别授权,不合并推定。 - 代码阶段无 migration、schema、seed、flag 或生产数据改动。 ## 生产验收清单 ### 代码候选 1. provenance、工作区与候选 SHA 一致;部署前现有 routing 只读快照未变化。 2. `/ready` 返回候选短 SHA;服务端日志无新类型/领域解析错误。 3. 报销 returned、approved/rejected、待办及五类审批 smoke 正常。 4. 生产渠道配置在独立授权前仍不放行三种新类型。 ### routing 配置 1. 变更前保存脱敏 routing 快照和有效允许矩阵。 2. 管理 API PATCH 只增加三个 type 与所需 domain;其他配置不变。 3. 变更后读回值、有效矩阵与审计记录一致,新增有效能力严格等于目标三种 returned。 4. 回滚演练至少完成静态命令与快照核对;不得为了演练反复写生产。 ### 真实事件 1. 目标用户站内只收到一份“已退回”通知,意见、目标类型和目标 ID 正确。 2. 企业微信 delivery 成功,真机收到消息并可点击回到有权限的 OA 页面。 3. 通知结果与业务对象 draft、workflow returned/history 以及假期/预算释放一致。 4. 无真实样本或授权时记录 `BLOCKED`,不标记 PASS。 ## 本地实施结果(2026-09-04) - 已完成三个 returned 通知类型、IM 支持清单和领域映射的同步注册;管理 API schema 测试保留既有 `workflow.task_assigned` 覆盖并新增三个 returned 值。 - 已由统一 workflow outcome 投影生成三类站内通知、email task 与 IM dispatch task;退回正文统一明确“已退回,可修改后重新提交”。 - 已增加 route 级容错回归:站内通知创建抛错时,接口仍成功,task 为 `completed/returned`、业务对象回 `draft`、return history 保留。 - 产品状态机、allowedActions、假期/预算释放分支、Prisma schema、前端和生产 routing 均未修改。 - 聚焦通知测试 53/53、全部 workflow route 测试 49/49、假期/预算服务测试 14/14 通过;Prisma validate、Node syntax、process contract、Trellis governance、task validate、docs registry 检查和 `git diff --check` 通过。 - 全量后端测试为 1384/1387 通过;三条失败均来自当前环境缺少受控 BIFF8 生成依赖 `xlwt`,集中在付款指令导出测试,与本任务改动文件和通知/workflow 路径无关。聚焦重跑全部通过,未修改或弱化这三条断言。 - AC9–AC11 尚未执行:未 commit、未 push、未部署、未写生产 routing,也未创建或退回生产测试单。真实企业微信送达继续保持未验证。