文件
hyb-oa/.trellis/tasks/07-27-yang-jun-reimbursement-readiness/design.md
T

5.7 KiB
原始文件 Blame 文件历史

杨俊报销就绪:技术设计

1. 设计目标

以最小生产变更打通“杨俊企微登录 → 杨俊提交真实报销 → 马建勇审批 → 王芝玲财务处理”。本任务不新增产品能力,复用现有通讯录导入、用户主管写入、报销工作流和异机备份能力。

2. 已确认边界

  • 企业微信成员与 OA 员工是两个独立事实:杨俊已在企微通讯录,但生产尚无 OA 员工记录和企微绑定。
  • 单人通讯录输入可唯一筛出杨俊;手机号为空符合现有 nullable 合同,企业邮箱存在,incomplete=0。
  • 生产已有 37 个 active 费用类型和 1 个 active 报销工作流定义。
  • active 法体为 0,但当前报销创建、提交和费用控制不以法体为硬门禁,本任务不创建法体。
  • 杨俊的真实直属主管由用户确认是马建勇。
  • 自动备份 daily/watchdog/drill-reminder 与 WARCH3 service 的 BUILD_SHA 均已漂移,必须先修复。

3. 数据流与执行门禁

现场只读复核活动构建与 4 个 unit
  → 重装 automatic-backup 三项 timer/service 与 WARCH3 timer
  → 验证 unit BUILD_SHA、enabled、active
  → 手工触发一份真实自动异机备份
  → 验证源端成功与 ARM 恢复点完整/新鲜
  → 从管理员导出通讯录在内存中仅筛选杨俊
  → production dry-run(create=1、conflict/skip/fail=0)
  → production apply(初始角色仅 employee)
  → 验证 OA 员工 active、企微绑定唯一、其他成员未导入
  → 通过现有用户管理接口设置 direct_manager_id=马建勇
  → 验证主管 active、不同人、具备 expense.approve,并核对审计
  → 杨俊本人企微登录并提交真实报销
  → 马建勇审批,随后进入王芝玲财务处理链路

任一门禁失败即停止后续步骤,不用后续成功掩盖前序失败。

4. 复用合同

4.1 通讯录导入

  • 复用 server/src/scripts/import-wecom-directory-export.js 的 stdin 输入,不把筛选后的 XLSX 或成员原始 payload 写入磁盘、日志、Trellis 或聊天。
  • dry-run 只记录人数与结果计数。
  • apply 必须同时满足脚本 --apply 参数和容器内 WECOM_DIRECTORY_EXPORT_APPLY=1。当前 Compose v1 调用必须显式使用 docker-compose exec -T -e WECOM_DIRECTORY_EXPORT_APPLY ...,不能只在宿主 shell export。
  • 输入严格只有杨俊一人;成功创建后的初始角色集合严格为 employee,不导入其他通讯录成员。
  • 此路径是“管理员导出企微通讯录 → OA 员工/身份绑定”的单向导入。OA 侧主管字段仅服务 OA 工作流;不调用企微成员 create/update/disable,也不把 OA 主管、姓名、部门、手机或邮箱写回企微。
  • 企微成员资料如需变化,由成员本人在企微允许的入口修改,或由企微管理员在管理后台修改;OA 后续只通过重新导出/受控同步读取变化。

4.2 直属主管

  • 复用 POST /api/users/batch/set-manager,不直写数据库。
  • 写入目标仅杨俊,主管仅马建勇;接口负责 active、自指等现有校验。
  • 写后核对 SYSTEM_USERS_BATCH_SET_MANAGER 审计增量,不记录完整账号或原始请求体。
  • 马建勇必须是 active、与杨俊不同且按有效角色解析出 expense.approve。

4.3 报销业务

  • 杨俊无需先存在差旅申请;linked_travel_request_id 可空。
  • 提交仍须满足既有硬门禁:至少一条费用明细、至少一张已绑定且状态为 bound 的真实票据、可匹配工作流并能解析审批人。
  • 第一笔真实报销必须由杨俊本人操作;Codex 不代建生产报销、发票、付款或测试业务数据。

4.4 timer 与备份

  • 使用现有 install-automatic-backup-timer.sh 和 install-warch3-ops-timer.sh,从活动部署现场解析并显式传入合同参数;不在任务文档中固化 Secret、宿主路径或完整账号。
  • 重装后核对 4 个 service 的 BUILD_SHA 与活动 server 一致,并确认对应 timers 为 enabled/active。
  • 随后手工触发 daily 自动备份路径,验证源端 service 成功、ARM 批次完成且 dead-man/新鲜度检查通过。
  • 新鲜异机恢复点是人员数据写入的前置条件,但不会用于回滚单个人员变更。

5. 失败与回退

  • timer 重装或异机备份失败:不写杨俊数据,保留本地诊断并走既有脱敏群告警。
  • dry-run 不满足 target=1 / active=1 / incomplete=0 / planned create=1 / conflicts=0 / skipped=0 / failed=0:不 apply,重新核对输入或生产现状。
  • apply 失败:停止;按脚本结果诊断,不手工拼接残缺账号。
  • apply 成功但主管写入失败:保留已创建的 OA 员工和企微绑定,不删除、不恢复整库;主管仍为空时不能提交报销,可安全重试同一主管接口。
  • 主管写错:通过同一接口恢复写入前的 direct_manager_id,不恢复整库。
  • 真实报销提交失败:保留草稿和真实票据状态,按返回的业务错误定位;不得通过扩权、代批或伪造数据绕过。

6. 隐私与审计

  • 终端与任务证据只保留布尔值、计数、角色 slug、审计 action 和脱敏状态。
  • 不输出手机号、企业邮箱、企微 userid、完整账号、通讯录原始行、票据内容、银行资料、Secret 或完整宿主路径。
  • 账号导入与主管写入分别保留现有系统审计,确保每一步可独立追踪和撤销。

7. 不做的设计扩展

  • 不新增导入 API、主管兜底规则、CEO 自审批能力或报销状态。
  • 不启用 OA → 企微通讯录写回,不修改任何企微成员资料。
  • 不创建法体、不补银行账号、不导入其余成员。
  • 不把首次真实业务扩成管理员代办的生产自动化测试。