这张图的核心是帮你理解:调账不是直接把 `settle_balance` 改一下,而是先生成调账单,再走审核、复核,最后通过 settlement 生成一笔 `adjustment` 类型账务流水。也就是说,调账本质上仍然是“账本驱动余额”,只是来源不是交易成功,而是人工修复。
01
创建调账单
- 后台通过 `AdminAdjustController.save` 创建调账单。
- 先校验商户、`paymentId`、币种、金额、描述和调账方向。
- 保存到 `settle_adjust`,状态先是 `waiting_audit`。
关键点:这一步只是在建单,不影响余额,也不会立刻生成 `settle_transaction`。
02
审核与复核
- 审核通过后进入 `waiting_re_audit`,审核拒绝进入 `audit_failed`。
- 复核通过才真正入账,复核拒绝进入 `re_audited_failed`。
- 失败状态允许修改后重提,重新回到待审核。
关键点:调账一定要有双人审批味道,不然就是高风险“手工改账”。
03
两种调账方向
- `charge` 表示扣款,录入正数,入账时转成负数。
- `back` 表示返还,录入正数,入账时保持正数。
- 两者最后都会生成 `type = adjustment` 的账务流水。
关键点:调账方向决定的是 `net` 正负,不是简单改一个状态字段。
04
进入结算引擎
- 复核通过后才组装 `SettleProcessorDTO`。
- 如果关联原交易,`parentBusinessNo = paymentId`;否则挂自己。
- 再调用 `settleService.doSettle` 走 `CommonProcessor`。
关键点:调账不是绕开 settlement,而是复用同一套账务引擎。
05
账本与余额
- 结算层生成 `settle_transaction(type = adjustment)`。
- 状态直接是 `available`,一般不进 `pending`。
- `charge` 会把金额转成负数,直接扣减 `settle_balance.available_amount`。
- `back` 会保留正数,直接回补 `settle_balance.available_amount`。
关键点:最终改余额的仍然是账务流水,不是后台直接 UPDATE 余额表。