|
|
@@ -0,0 +1,159 @@
|
|
|
+# ETC/加油充值申请 · 撤回 — 设计文档
|
|
|
+
|
|
|
+> **日期**: 2026-09-29
|
|
|
+> **状态**: 已确认待实现
|
|
|
+> **仓库**: shanxia2.0(`backend/` + `web-admin/` + `miniprogram/`)
|
|
|
+> **对齐**: 报销申请撤回(`ReimburseService.withdraw`:审批中 → 草稿,记录保留)
|
|
|
+> **前置**:
|
|
|
+> - `docs/superpowers/specs/2026-06-29-pl-vehicle-recharge-design.md`
|
|
|
+> - `docs/superpowers/specs/2026-09-26-pl-vehicle-recharge-workflow-design.md`
|
|
|
+> - `docs/superpowers/specs/2026-09-27-mini-pl-vehicle-recharge-apply-design.md`
|
|
|
+
|
|
|
+## 背景与问题
|
|
|
+
|
|
|
+【报销申请】在审批中支持申请人**撤回** → 变为待提交/草稿,可修改后再提交。
|
|
|
+
|
|
|
+【ETC/加油充值申请】现状:
|
|
|
+
|
|
|
+| 能力 | 状态 |
|
|
|
+|------|------|
|
|
|
+| 草稿 / 已驳回:编辑、提交、作废 | 已有 |
|
|
|
+| 审批中 `in_approval`:编辑 | 无 |
|
|
|
+| 审批中:撤回 → 草稿 | **缺失** |
|
|
|
+| 作废 `cancel` | 仅草稿/已驳回 → `cancelled`(与撤回不同) |
|
|
|
+
|
|
|
+申请人发现写错内容时,只能等驳回或让审批人处理,无法主动撤回修改。
|
|
|
+
|
|
|
+## 已确认决策
|
|
|
+
|
|
|
+| # | 决策 | 说明 |
|
|
|
+|---|------|------|
|
|
|
+| D1 | 撤回结果 | 审批中 → **草稿 `draft`**,可再编辑后重新提交(与报销一致) |
|
|
|
+| D2 | 端范围 | **Web 管理端 + 小程序** |
|
|
|
+| D3 | 审批记录 | **保留**,不强制切轮次、不写「撤回」分界(与报销撤回现状对齐) |
|
|
|
+| D4 | 可撤回状态 | 仅 **`in_approval`(审批中)**;不含待发放 `pending`、已发放、已作废、草稿、已驳回 |
|
|
|
+| D5 | 操作人 | 仅 **申请人本人**(`applicant_id === 当前用户`) |
|
|
|
+| D6 | 实现方案 | 新增独立 `withdraw` API,与 `cancel`(作废)分离 |
|
|
|
+
|
|
|
+## 1. 目标与范围
|
|
|
+
|
|
|
+### 目标
|
|
|
+
|
|
|
+1. 申请人可在审批中撤回充值申请,单据回到草稿。
|
|
|
+2. Web 与小程序均可操作,规则一致。
|
|
|
+3. 撤回后沿用现有草稿编辑 / 提交能力。
|
|
|
+
|
|
|
+### 范围内
|
|
|
+
|
|
|
+- 后端:`withdraw_apply` + `POST /transport/vehicle-recharge-apply/{id}/withdraw`
|
|
|
+- Web:`views/pl/vehicle-recharge-apply/index.vue` 列表工具栏 + 查看弹窗
|
|
|
+- 小程序:`pages/pl/vehicle-recharge-apply/list.vue`(及详情/表单页若有操作区则对齐)
|
|
|
+- API 封装:`web-admin/src/api/pl/index.ts`、`miniprogram/api/pl.js`
|
|
|
+
|
|
|
+### 范围外(明确不做)
|
|
|
+
|
|
|
+- 审批轮次过滤改造、写入 `withdrawn` 审批记录
|
|
|
+- 待发放 `pending` 撤回
|
|
|
+- 改作废语义或合并 cancel/withdraw
|
|
|
+- 备用金、维修、尿素等其它业务的撤回
|
|
|
+- 同步改造报销撤回的轮次逻辑
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 2. 后端行为
|
|
|
+
|
|
|
+### 2.1 接口
|
|
|
+
|
|
|
+`POST /api/transport/vehicle-recharge-apply/{id}/withdraw`
|
|
|
+
|
|
|
+Query(与现有 apply 写接口一致):
|
|
|
+
|
|
|
+- `mineVehicles`(可选,小程序列表作用域时传 `true`)
|
|
|
+
|
|
|
+成功:返回更新后的 `VehicleRechargeApplyRead`。
|
|
|
+
|
|
|
+### 2.2 前置校验
|
|
|
+
|
|
|
+1. 申请存在且未删除、租户匹配、数据权限可读。
|
|
|
+2. `applicant_id` 必须等于当前用户,否则 403。
|
|
|
+3. `status == "in_approval"`,否则 400(文案如:仅审批中的申请可撤回)。
|
|
|
+4. `mineVehicles=true` 时继续沿用现有本人车辆/本人写校验。
|
|
|
+
|
|
|
+### 2.3 成功副作用
|
|
|
+
|
|
|
+| 字段 | 处理 |
|
|
|
+|------|------|
|
|
|
+| `status` | → `draft` |
|
|
|
+| `current_node` | → `null` / 清空 |
|
|
|
+| `approval_round` | **保持不变**(下次 `submit` 仍会 `+1`,当前进度按新轮展示) |
|
|
|
+| `wf_id` | 保持不变 |
|
|
|
+| `pl_vehicle_recharge_approval` 行 | **不删、不改** |
|
|
|
+| 其它业务字段 | 不变 |
|
|
|
+
|
|
|
+无发票额度等资源需退回(与报销不同)。
|
|
|
+
|
|
|
+### 2.4 与重新提交的关系
|
|
|
+
|
|
|
+现有 `submit_apply` 已执行 `approval_round = (approval_round or 0) + 1` 并重置 `current_node` 为首节点。
|
|
|
+因此:撤回 → 改稿 → 再提交后,**当前审批进度**自然只看新轮;旧轮记录仍可通过既有 **审批历史** 接口/UI 查看。
|
|
|
+这与「不强制切轮次」决策兼容:不新增撤回分界记录,依赖已有 `approval_round`。
|
|
|
+
|
|
|
+### 2.5 错误语义(建议)
|
|
|
+
|
|
|
+| 情况 | HTTP | detail |
|
|
|
+|------|------|--------|
|
|
|
+| 非申请人 | 403 | 仅申请人可撤回 |
|
|
|
+| 非审批中 | 400 | 仅审批中的申请可撤回 |
|
|
|
+| 不存在 | 404 | 申请单不存在 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 3. 前端行为
|
|
|
+
|
|
|
+### 3.1 公共规则
|
|
|
+
|
|
|
+`canWithdraw(row)`:
|
|
|
+
|
|
|
+- `row.status === 'in_approval'`
|
|
|
+- `String(row.applicantId) === 当前用户 id`
|
|
|
+
|
|
|
+确认文案建议:
|
|
|
+
|
|
|
+> 确定撤回该充值申请?撤回后变为草稿,可修改后再提交。
|
|
|
+
|
|
|
+成功 Toast:`已撤回`。
|
|
|
+
|
|
|
+### 3.2 Web 管理端
|
|
|
+
|
|
|
+对齐报销申请页交互:
|
|
|
+
|
|
|
+- 列表工具栏:在「作废」附近增加「撤回」按钮;单选且 `canWithdraw` 时可用。
|
|
|
+- 查看弹窗 `#hero-actions`:审批中且本人时展示「撤回」(替代或并列于仅查看态;**不**开放编辑/作废)。
|
|
|
+- 图标:与报销一致优先 `RefreshLeft`(或项目已有等价图标)。
|
|
|
+
|
|
|
+编辑 / 提交 / 作废条件不变:仍仅 `draft` / `rejected`。
|
|
|
+
|
|
|
+### 3.3 小程序
|
|
|
+
|
|
|
+- 列表卡片:当 `canWithdraw(item)` 时展示「撤回」;审批中他人单据仅「查看」+「复制发群」等现有能力。
|
|
|
+- 若表单页以只读打开审批中本人单,可在底部增加「撤回」(可选,与列表能力二选一即可;**至少列表具备**)。
|
|
|
+- 调用 `vehicleRechargeApplyApi.withdraw(id)`,小程序请求带现有 `mineVehicles` 约定。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 4. 验收要点
|
|
|
+
|
|
|
+1. 本人 + 审批中:两端均可撤回 → 状态变草稿 → 可编辑 → 可再提交进入新一轮审批。
|
|
|
+2. 非本人 / 非审批中:无撤回入口;直调 API 被拒绝。
|
|
|
+3. 作废仍仅草稿/已驳回;撤回不会变成 `cancelled`。
|
|
|
+4. 撤回后审批历史中仍可见撤回前已产生的审批动作;再提交后当前进度为新轮。
|
|
|
+5. 待发放、已发放、已作废不可撤回。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 5. 实现备注
|
|
|
+
|
|
|
+- Service 放在 `pl_vehicle_recharge_service.py`(与 `submit_apply` / `cancel_apply` 同层)。
|
|
|
+- 路由挂在 `vehicle_recharge.py` 的 `apply_router`,放在 `submit` / `cancel` 附近。
|
|
|
+- 无需改表结构 / SQL。
|
|
|
+- 建议补一条后端单测:`in_approval` 本人撤回成功;非本人 / 错误状态失败。
|