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