247 lines
7.1 KiB
Markdown
247 lines
7.1 KiB
Markdown
# REV004 / 分账执行态后端设计草案(2026-04-14)
|
||
|
||
## 1. 目标
|
||
在当前“分账申请态”基础上,补齐“审批通过后真正执行拆账”的后端能力,使系统可以:
|
||
- 将一笔原始未收费账单拆成多笔目标账单
|
||
- 支持两类分账策略:
|
||
- 按水量分账
|
||
- 按费用组成分账
|
||
- 保证金额/水量守恒、状态可追踪、失败可回滚
|
||
- 被后续收费、开票、日志、查询完整承接
|
||
|
||
---
|
||
|
||
## 2. 当前现状
|
||
### 已有
|
||
- 统一对象类型:`SPLIT_ADJUST`
|
||
- 统一提交入口:`unsold-split-submit`
|
||
- 当前结果:`PENDING_APPROVAL`
|
||
- 已有原因、审批、日志、查询承接能力
|
||
|
||
### 缺失
|
||
- 审批通过后的执行器
|
||
- 分账主表/明细表落库
|
||
- 目标账单生成
|
||
- 原账单与目标账单关系链
|
||
- 按水量/按费用组成的规则明细
|
||
- 执行态查询回看
|
||
|
||
---
|
||
|
||
## 3. 设计原则
|
||
1. **先审批、后执行**:分账执行必须挂在审批通过之后,不在申请提交时直接拆账。
|
||
2. **守恒原则**:
|
||
- 按水量分账:子账单水量之和 = 原账单水量
|
||
- 按费用组成分账:子账单金额之和 = 原账单金额
|
||
3. **原账单可追溯**:必须保留原账单与所有目标账单关系。
|
||
4. **执行幂等**:同一分账单不得重复执行。
|
||
5. **失败可回滚**:执行中任一步失败,必须整体回滚。
|
||
6. **查询可回看**:日志页/分账页必须能看到申请、审批、执行结果、目标账单明细。
|
||
|
||
---
|
||
|
||
## 4. 结果对象建议
|
||
### 最终业务真值
|
||
建议以:
|
||
- **多张目标子账单**
|
||
为正式业务真值;
|
||
- “多笔待收费结果”只是前台呈现视角。
|
||
|
||
### 原因
|
||
- 文档原始语义就是“由一笔账单分成两笔独立账单信息”
|
||
- 后续还要支持分别收费、分别开票、分别承担
|
||
- 若没有目标账单实体,后续业务承接会变得模糊
|
||
|
||
---
|
||
|
||
## 5. 数据模型草案
|
||
|
||
### 5.1 主表:`biz_split_adjust`
|
||
建议字段:
|
||
- `id`
|
||
- `split_adjust_no`:分账单号
|
||
- `source_charge_id`:原账单 ID
|
||
- `split_rule_type`:分账规则类型(`BY_WATER` / `BY_COMPONENT`)
|
||
- `reason_code`
|
||
- `remark`
|
||
- `approval_status`
|
||
- `execute_status`:`PENDING / PROCESSING / SUCCESS / FAIL`
|
||
- `execute_message`
|
||
- `executed_at`
|
||
- `accounting_case_id`(如继续挂统一骨架)
|
||
- 通用审计字段
|
||
|
||
### 5.2 明细表:`biz_split_adjust_detail`
|
||
建议字段:
|
||
- `id`
|
||
- `split_adjust_id`
|
||
- `seq_no`
|
||
- `target_cust_id` / `target_cust_code`(若允许拆给不同客户)
|
||
- `target_charge_id`(执行后生成)
|
||
- `split_basis`:拆分依据描述
|
||
- `split_ratio`
|
||
- `split_water`
|
||
- `split_amount`
|
||
- `component_code`(按费用组成分账时必填)
|
||
- `component_amount`
|
||
- `status`
|
||
- 通用审计字段
|
||
|
||
### 5.3 与现有 `biz_charge` 的关系
|
||
- 原账单:`source_charge_id`
|
||
- 子账单:执行后在 `biz_charge` 新增多条记录
|
||
- 子账单增加来源追踪字段(建议二选一):
|
||
- `source_charge_id`
|
||
- 或 `split_adjust_id`
|
||
|
||
建议至少有一个能让后续查询直接知道:
|
||
> 这张账单是由哪次分账生成的。
|
||
|
||
---
|
||
|
||
## 6. 执行流程草案
|
||
|
||
### Phase 1:申请提交
|
||
接口:`POST /unsold-split-submit`
|
||
- 校验未收费、`splitCount`、原因等
|
||
- 保存申请主单/明细草稿(如果前端已能提供拆分明细)
|
||
- 状态置为 `PENDING_APPROVAL`
|
||
|
||
> 若当前前端还没有真正提交拆分明细,只是申请头信息,则需在后续补充“审批前明细维护”或“审批时确认明细”能力。
|
||
|
||
### Phase 2:审批通过
|
||
触发点:审批系统回调/人工审批通过
|
||
- 校验该分账单仍未执行
|
||
- 锁定原账单
|
||
- 进入执行事务
|
||
|
||
### Phase 3:执行拆账
|
||
#### 3.1 按水量分账
|
||
- 读取原账单水量、单价/模板/费用构成
|
||
- 根据各子项 `split_water` 重新计算子账单金额
|
||
- 生成 N 条目标账单
|
||
- 校验:
|
||
- `sum(split_water) = source.bill_water`
|
||
- `sum(target.bill_amount)` 与可接受计算误差范围内守恒
|
||
|
||
#### 3.2 按费用组成分账
|
||
- 读取原账单明细 `biz_charge_detail`
|
||
- 按费用项将金额拆入不同子账单
|
||
- 汇总生成 N 条目标账单及其明细
|
||
- 校验:
|
||
- 各费用项总额守恒
|
||
- 原账单总金额守恒
|
||
|
||
### Phase 4:收尾
|
||
- 原账单标记为:
|
||
- 已拆分 / 已失效 / 不可继续收费(建议新增状态或来源标识)
|
||
- 分账主单置为 `SUCCESS`
|
||
- 明细回填 `target_charge_id`
|
||
- 写 operat_log / 业务日志 / 查询投影
|
||
|
||
### Phase 5:失败回滚
|
||
- 任一步失败:回滚事务
|
||
- 主单置 `FAIL`
|
||
- 保留失败原因
|
||
- 不产生部分子账单残留
|
||
|
||
---
|
||
|
||
## 7. 接口草案
|
||
|
||
### 7.1 申请接口(保留)
|
||
- `POST /unsold-split-submit`
|
||
|
||
### 7.2 明细查询接口(建议新增)
|
||
- `GET /split-adjust-detail?adjustmentNo=...`
|
||
- 返回:
|
||
- 原账单摘要
|
||
- 分账规则类型
|
||
- 子项明细
|
||
- 目标账单(若已执行)
|
||
|
||
### 7.3 明细维护接口(建议新增,若前端需要)
|
||
- `POST /split-adjust-draft-save`
|
||
- 在审批前保存:
|
||
- 按水量拆分行
|
||
- 按费用组成拆分行
|
||
|
||
### 7.4 审批通过执行接口(内部)
|
||
- `POST /internal/split-adjust/execute`
|
||
- 由审批流或业务服务调用,不暴露给前端
|
||
|
||
### 7.5 查询接口增强(建议)
|
||
- `log-detail` / `log-process`
|
||
- 增加目标账单摘要
|
||
- `unsold-page`
|
||
- 原账单若已提交分账且审批中/已执行,要有能力位变化提示
|
||
|
||
---
|
||
|
||
## 8. 状态机建议
|
||
### 申请主单状态
|
||
- `PENDING_APPROVAL`
|
||
- `APPROVED_PENDING_EXECUTE`
|
||
- `PROCESSING`
|
||
- `SUCCESS`
|
||
- `FAIL`
|
||
- `REVOKED`(如审批前允许撤销)
|
||
|
||
### 原账单状态建议
|
||
原账单不建议简单删除,建议新增可追溯状态:
|
||
- `UNPAID`
|
||
- `SPLIT_PENDING`
|
||
- `SPLIT_DONE`
|
||
- `SPLIT_INVALIDATED`
|
||
|
||
若不想改老字段,可用额外来源标记字段表达。
|
||
|
||
---
|
||
|
||
## 9. 与前端配合建议
|
||
### 前端最少补充信息
|
||
若要真正进入执行态,前端弹窗至少要能提交:
|
||
- 分账方式:按水量 / 按费用组成
|
||
- 子项列表
|
||
- 按水量:每笔 `split_water`
|
||
- 按费用组成:每笔目标费用项/金额归属
|
||
- 申请人 / 联系电话 / 原因 / 备注
|
||
|
||
### 前端结果回看
|
||
执行态落地后,前端需要新增:
|
||
- 原账单 -> 目标账单列表
|
||
- 子账单金额/水量/费用项明细
|
||
- 分账执行结果与失败原因
|
||
|
||
---
|
||
|
||
## 10. 分阶段落地建议
|
||
### 第一阶段(最小闭环)
|
||
目标:审批通过后真正生成子账单,但先只支持**按水量分账**
|
||
- 优先原因:
|
||
- 规则相对更直观
|
||
- 守恒约束明确
|
||
- 更容易先做闭环
|
||
|
||
### 第二阶段
|
||
扩展支持:**按费用组成分账**
|
||
- 需要补足 `biz_charge_detail` 级别重分摊能力
|
||
|
||
### 第三阶段
|
||
增强:
|
||
- 目标客户维度分账
|
||
- 更复杂的规则模板
|
||
- 开票/收费联动优化查询
|
||
|
||
---
|
||
|
||
## 11. 最终建议
|
||
若项目要正式推进“分账执行态”,建议:
|
||
1. 先把 **按水量分账** 做成最小执行闭环
|
||
2. 明确 `biz_split_adjust` / `biz_split_adjust_detail` 模型
|
||
3. 把审批通过后的执行器作为独立服务落地
|
||
4. 再补按费用组成的二阶段能力
|
||
|
||
一句话:
|
||
> 不建议继续在当前“统一 adjustAccounting 申请态”里硬塞执行逻辑,而应把 `SplitAdjust` 升级成独立正式业务对象来建设。
|