Files
hfb_sys/docs/结算后订单利润调整方案.md

167 lines
6.9 KiB
Markdown
Raw Permalink 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.
# 结算后订单利润调整方案
## 1. 背景与目标
订单完成结算后,用户可能继续发生售后补偿、部分退款、号主收入修正等情况。需要在不破坏正式结算快照和历史资金流水的前提下,记录每次调整,并展示订单的最终实际收入和平台利润。
本方案针对正常租赁订单,提号订单已有类似实现,可复用其“追加调整流水”的思路。
## 2. 当前系统结算口径
- 正式结算基准使用最终结算记录 `order_checkouts` 的正式金额,不能使用发布价格、预计价格或订单初始价格。
- 号主正式收入为 `order_checkouts.owner_income_amount_cent`
- 普通订单结算时通过 `wallet_ledger` 给号主入账。
- 平台代管订单结算时把待付号主金额记录在 `rental_orders.offline_settlement_amount_cent`
- 订单过程留痕使用 `process_events`,管理员操作审计使用 `audit_logs`
- 财务明细目前通过结算记录、号主钱包入账和平台代管线下结算金额计算平台净额。
相关代码:
- `backend/internal/modules/order/checkout_finalize.go`
- `backend/internal/modules/order/queries.go`
- `backend/internal/modules/adminfinance/detail.go`
- `backend/internal/model/order_checkout.go`
- `backend/internal/modules/pickup/repository.go`
## 3. 核心设计
不要修改原始结算记录、订单线下结算金额或已有钱包流水。新增不可变的订单财务调整流水:
```text
admin_order_financial_adjustments
```
建议字段:
```text
id
order_id
adjustment_no 唯一调整单号,用于幂等
settlement_mode owner_wallet / platform_managed
owner_income_delta_cent 号主收入调整,可正可负
renter_compensation_cent 本次租客补偿金额
compensation_bearer platform / owner
platform_profit_delta_cent 系统计算的利润变化,不允许前端直接填写
owner_settlement_status settled / pending / recovery_pending
renter_refund_status none / pending / refunded / failed
reason
reference_no 售后单号或外部凭证号
created_by
processed_by
processed_at
remark
created_at
```
最终结果按流水累计:
```text
最终号主收入 = 正式结算号主收入 + 所有有效 owner_income_delta_cent
最终租客退款 = 正式结算退款 + 所有已完成 renter_compensation_cent
最终平台利润 = 正式结算利润 + 所有 platform_profit_delta_cent
```
`platform_profit_delta_cent` 由服务端根据补偿承担方和号主收入变化自动计算,避免出现“号主收入、租客退款、平台利润”三者不一致。
## 4. 后台操作口径
后台输入“目标最终金额”,系统自动计算差额,不建议让客服手工输入差额:
1. 展示正式结算号主收入和当前实际号主收入。
2. 输入调整后的号主最终收入(可不调整)。
3. 输入本次售后补偿金额。
4. 选择补偿承担方:平台或号主。
5. 填写售后单号、原因和备注。
6. 提交前预览本次差额、最终号主收入、最终平台利润和待处理资金状态。
示例:正式号主收入 100 元,平台利润 20 元,售后补偿 3 元:
- 平台承担:号主仍为 100 元,平台利润减少 3 元。
- 号主承担:号主最终收入减少 3 元,并产生 3 元退款;平台利润原则上不变。
## 5. 资金处理
### 普通号主钱包订单
- 增加号主收入:在同一数据库事务中追加钱包入账流水。
- 减少号主收入:余额足够时追加钱包扣款流水。
- 余额不足:记录 `recovery_pending`,不能把钱包扣成负数,后续由财务处理追回。
- 平台承担租客补偿:提交支付退款任务,退款完成后再将调整标记为已处理。
### 平台代管订单
- 原线下款尚未支付:调整金额并入待打款任务,原始结算金额保持不变。
- 原线下款已支付:增加新的待补款或待追回任务。
- 不直接覆盖 `offline_settlement_amount_cent`,否则会丢失首次结算记录。
### 退款幂等
当前退款逻辑按订单和 `biz_type` 查找已有退款单。多次售后不能共用同一个退款业务键,应使用 `adjustment_no` 作为每次退款的唯一幂等键,并补充退款重试和失败状态。
## 6. API、权限与页面
建议接口:
```text
GET /admin/orders/:id/financial-adjustments
POST /admin/orders/:id/financial-adjustments
POST /admin/order-financial-adjustments/:id/settle
```
新增权限:
```text
order:financial_adjust
```
不建议复用订单关闭或标记异常权限。
订单详情的结算区域增加:
- 正式结算号主收入
- 售后调整合计
- 当前实际号主收入
- 正式退款与售后补偿
- 当前实际平台利润
- 调整流水、退款状态、补款/追回状态
- “新增售后补偿/修改利润”按钮
需要同步修改订单详情、财务明细、财务仪表盘和线下出款待办的聚合查询。
## 7. 状态与审计
号主资金和租客退款可能分别处于不同状态,因此不能只使用一个总状态。建议分别保存号主结算状态和租客退款状态,再由接口计算调整单的整体状态。
创建调整、钱包入账/扣款、退款任务创建、退款完成/失败、线下补款/追回确认,都要写入 `process_events``audit_logs`,并记录调整前后金额、操作人、原因和凭证号。
## 8. 测试范围
- 普通订单增加或减少号主收入。
- 钱包余额不足进入待追回。
- 平台代管未打款时调整。
- 平台代管已打款后补款或追回。
- 平台承担补偿与号主承担补偿。
- 退款失败、重试和重复请求幂等。
- 同一订单多次售后调整的累计结果。
- 正式结算记录和原始钱包流水不可被修改。
- 财务明细、仪表盘和出款待办金额一致。
## 9. 分支核查(2026-08-30
- 当前 `main``98f6ee9`,包含最近的客服上传账号统计。
- 本地 `dev``85332df`
- 远端 `gitea/dev``85332df`,与本地 `dev` 一致。
- `dev` 包含 `80e55ba 支持提号完成后财务调整`,相关实现位于 `admin_pickup_financial_adjustments`、提号仓库/服务和提号管理页面。
- `dev` 尚未包含正常租赁订单的结算后利润调整。
- `dev``main` 的共同基点为 `f48da14``dev` 有 1 个独有提交,`main` 有 49 个后续提交。不能直接整体合并 `dev`,如需保留其中的接口最小化和私有文件加固,应单独评审后再移植 `85332df`
## 10. 实施顺序
1. 增加迁移和 `AdminOrderFinancialAdjustment` 模型。
2. 增加订单调整仓库、服务、接口、权限和审计。
3. 接入钱包、退款幂等键、平台代管补款/追回。
4. 修改订单详情和财务聚合查询。
5. 补齐普通订单、平台代管、余额不足、退款失败和重复调整测试。
实施前需要确认:补偿承担方规则、退款是否全部原路退回、以及是否统一采用“目标最终金额”输入。推荐采用本文方案。