Files
one-pipe-system/openspec/changes/add-refund-approval-recovery/design.md
luo c5d7a260d0
All checks were successful
构建并部署前端到测试环境 / deploy (push) Successful in 55s
fix: 恢复退款原审批提交
2026-09-20 18:13:14 +08:00

3.3 KiB
Raw Blame History

Context

退款审批提交由后端和企业微信协同完成。网络超时或异步任务异常时,本地不能仅凭旧字段判断提交结果:已有 sp_no 需要同步,结果未知需要先确认,明确失败才允许恢复原提交事件。恢复必须绑定当前最新审批尝试,避免重复创建审批实例或覆盖历史材料。

Goals / Non-Goals

  • Goals: 为可恢复的退款提供一个安全、可追踪的恢复入口;展示提交状态和最近恢复结果;在列表和详情保持一致。
  • Goals: 将资格判断、数据范围和并发冲突交给后端,前端只消费后端返回的可恢复标记。
  • Non-Goals: 不实现审批引擎、企业微信调用、自动重试调度或新的审批流程。

Decisions

  • Decision: 新增独立的 recoverApproval API,而不是复用历史 triggerApproval。
    • Rationale: trigger-approval 面向没有审批状态的历史记录;恢复接口面向已有审批尝试的同步/结果确认/原事件恢复,两者的幂等语义和审计含义不同。
  • Decision: 以 approval_recoverable 作为按钮展示条件,后端作为最终授权和状态校验方。
    • Rationale: 前端无法可靠重建“结果未知”和“明确失败”等状态,且状态可能在页面打开后发生变化。
  • Decision: 恢复接口只接收路径中的退款 ID,响应返回完整退款详情。
    • Rationale: 防止客户端篡改审批实例、材料或单号;一次响应即可刷新列表/详情所需字段。
  • Decision: 将 submission_status、失败摘要和最近恢复时间作为普通退款响应字段展示。
    • Rationale: 列表需要快速筛选/判断,详情需要审计和排障;字段由后端脱敏并保持一致。

State and Concurrency

  1. 若最新尝试已有 sp_no,后端执行原审批单同步。
  2. 若提交结果未知,后端先确认结果;确认成功或已存在时不得再次提交。
  3. 若结果明确提交失败,后端恢复原提交事件;不得创建新的尝试或审批实例。
  4. 若资格在请求期间失效,接口返回状态冲突;前端提示固定文案并刷新详情/列表。
  5. 后端应保证重复请求幂等,前端按钮在请求期间置为 loading,避免重复点击。

Risks / Trade-offs

  • Risk: 列表数据在恢复完成前已过期。
    • Mitigation: 成功和状态冲突都强制重新请求后端;不在前端乐观修改审批状态。
  • Risk: 失败摘要包含凭证或个人信息。
    • Mitigation: 仅展示后端提供的脱敏 approval_failure_summary,前端不拼接原始异常。
  • Risk: 新入口与旧历史补发入口混淆。
    • Mitigation: 使用“恢复审批”文案和独立 API,保留两种入口各自的资格条件与说明。

Migration Plan

  1. 扩展退款响应类型与 API service。
  2. 在列表和详情接入恢复按钮、确认/加载/错误处理和刷新逻辑。
  3. 增加 API、资格显示、冲突刷新和字段展示测试。
  4. 与后端联调已有单号、未知结果、明确失败和不可恢复四类状态。

Open Questions

  • submission_status 的完整枚举值及名称由后端提供,前端是否需要筛选取决于最终列表需求。
  • 状态冲突错误是否有稳定错误码;在未确定前以前端按错误消息或统一冲突码兼容处理。