瀏覽代碼

docs: allow negative invoice wallet balance on reimburse submit

Record the approved design to drop the hard balance gate while keeping full debit_reimburse occupancy.

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu 2 月之前
父節點
當前提交
12e8cdaaf9
共有 1 個文件被更改,包括 131 次插入 和 0 次删除
  1. 131 0
      docs/superpowers/specs/2026-08-12-reimburse-allow-negative-invoice-balance-design.md

+ 131 - 0
docs/superpowers/specs/2026-08-12-reimburse-allow-negative-invoice-balance-design.md

@@ -0,0 +1,131 @@
+# 报销提交允许发票夹余额为负 — 设计文档
+
+> **日期**: 2026-08-12  
+> **状态**: 待实现  
+> **仓库**: shanxia2.0(`backend/` + `web-admin/` + `bx-mobile/`)  
+> **前置 / 修订**:
+> - `docs/superpowers/specs/2026-07-25-invoice-wallet-reimburse-design.md`(原规则:余额不足不可提交)
+> - `docs/business-inventory/03-报销业务明细.md`
+
+## 背景与问题
+
+发票夹上线后,报销「提交审批」要求申请人发票夹余额 ≥ 报销合计;不足则前后端均拦截。业务方希望:额度不足也可提交,因为申请人会**后续独立在发票夹补票**。
+
+## 已确认决策
+
+| # | 决策 | 说明 |
+|---|------|------|
+| D1 | **仍全额占用** | 提交时照常写 `debit_reimburse`;允许 `balance` 变为负 |
+| D2 | **全端一致** | 后端 + Web 报销申请 + `bx-mobile` 统一放开;小程序当前无此校验,本期不改 |
+| D3 | **弱提示、不拦截** | 保留「当前余额 / 本次合计」;不足时提示「余额不足,提交后余额将为负,请后续补发票」 |
+| D4 | **删票保护不变** | 删票冲减后余额不得为负(`assert_can_delete_invoice`) |
+| D5 | **不做** | 审批/发放页负余额二次提醒;提交部分占用;延后扣账;关联发票金额覆盖校验 |
+
+相对 `2026-07-25-invoice-wallet-reimburse-design`:**硬门槛「余额 ≥ 申请金额」废止**;扣/退时机与流水类型不变。冲突时以本文为准。
+
+---
+
+## 一、目标与范围
+
+### 目标
+
+报销提交审批不再因发票夹余额不足失败。提交仍按合计全额占用;申请人后续补票使余额回升。
+
+### 范围内
+
+- 后端:`InvoiceLedgerService.debit_reimburse` 去掉余额不足拦截
+- Web:`web-admin/src/views/bx/reimburse/apply/index.vue` 去掉提交拦截与强警告文案
+- 移动:`bx-mobile/src/views/reimburse/ReimburseApplyPage.vue` 同上
+- 文档:业务清单与相关表述同步
+
+### 范围外
+
+- 不改扣账时机(仍在 submit)
+- 不改驳回/撤回释放、submit 幂等
+- 不加审批/发放提醒
+- 不改 miniprogram
+- 不做补票后差额自动核销等新能力
+
+---
+
+## 二、行为规则
+
+### 2.1 提交占用
+
+1. 业务校验通过后,按报销合计写全额 `debit_reimburse`。
+2. **不再**因 `balance < amount` 抛错或前端拦截。
+3. 驳回 / 撤回仍写 `credit_release`(现有逻辑)。
+4. 同一单已有有效占用则跳过再扣(现有幂等)。
+
+### 2.2 余额语义
+
+```
+balance = Σ(credit_upload) − Σ(debit_delete) − Σ(debit_reimburse) + Σ(credit_release)
+```
+
+- 允许 `balance < 0`。
+- 负余额含义:已提交占用超过已上传发票总额;补票(`credit_upload`)后回升。
+- 删票:若冲减后余额将 &lt; 0,仍拒绝(防止用删票抵消占用)。
+
+### 2.3 关联发票
+
+仍为可选;不要求关联票面金额覆盖报销合计。
+
+### 2.4 并发
+
+仍对 `BxInvoiceWalletSummary` 使用 `with_for_update()`;仅取消「余额不足拒绝」条件。
+
+---
+
+## 三、改动点
+
+### 3.1 后端
+
+| 位置 | 改动 |
+|------|------|
+| `backend/app/services/bx/invoice_ledger.py` → `debit_reimburse` | 删除 `if balance < amt: raise HTTPException(...)` |
+| `release_reimburse` / `assert_can_delete_invoice` / `calc_summary` | 不改 |
+
+### 3.2 Web(`web-admin`)
+
+| 位置 | 改动 |
+|------|------|
+| 申请弹窗余额区 | 保留余额与合计;不足时弱提示改为「余额不足,提交后余额将为负,请后续补发票」;删除「提交时将被拦截」 |
+| `handleToolbarSubmit` / `handleSubmit` | 删除提交前余额不足 `return` |
+| `submitAdd`(存草稿) | 本就不拦,无需改逻辑 |
+
+### 3.3 bx-mobile
+
+| 位置 | 改动 |
+|------|------|
+| 申请页余额提示 | 去掉「无法提交」类文案;改为与 Web 一致的弱提示 |
+| 保存成功对话框 | 去掉「请先充值发票夹后再提交」;不足时仍可点「提交审批」 |
+| 确认提交分支 | 删除 `balanceInsufficient` 时 toast「余额不足,无法提交」并 return |
+
+---
+
+## 四、验收标准
+
+1. 余额 &lt; 报销合计时,Web 与 bx-mobile 均可成功提交审批。
+2. 提交后余额减少(可为负);流水存在对应 `debit_reimburse`。
+3. 申请页仍展示余额与合计;不足仅弱提示,无拦截文案。
+4. 余额充足时行为与现网一致。
+5. 驳回 / 撤回后占用释放,余额回升。
+6. 删票在冲减后余额将 &lt; 0 时仍拒绝。
+7. 后续补票可使负余额回到 ≥ 0。
+
+---
+
+## 五、文档同步(实现时)
+
+- 更新 `docs/business-inventory/03-报销业务明细.md` 额度规则:「提交全额占用,余额可为负;不足不拦截」。
+- 实现计划另见 `docs/superpowers/plans/`(实现前由 writing-plans 产出)。
+
+---
+
+## 六、非目标
+
+- 审批/发放页负余额提醒  
+- 部分占用或延后扣账  
+- 关联发票必填 / 金额覆盖硬校验  
+- miniprogram 改造