fujian_water_biz_doc/docs/evidence/rev004-split-adjust-execution-design-draft-2026-04-14.md

247 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` 升级成独立正式业务对象来建设。