docs(changelog): 主报账表baseInfo尾款口径三新字段透出+outstandingAmount下线(#5955 / PR #5958)管理后台
所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s
所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s
这个提交包含在:
父节点
094146d793
当前提交
983c274860
@ -0,0 +1,326 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "5955"
|
||||
title: "主报账表baseInfo尾款口径透出三新字段+outstandingAmount下线"
|
||||
consumer: "admin"
|
||||
change_type: "修改接口"
|
||||
author: "yst"
|
||||
backend_status: "deployed"
|
||||
gateway_status: "verified"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: ""
|
||||
status_note: "PR #5958 已合并 dev-v3(commit cb40e197cb)。破坏性契约变化:baseInfo 删除 outstandingAmount(整单未收尾款),新增 receivableBalanceAmount(应收尾款)/ paidBalanceAmount(实收尾款)/ reporterPaidBalanceAmount(报账人实收尾款);reporterNetAmount 保留为唯一带正负净额字段。仅出参变化,无入参/枚举/DDL 变化。"
|
||||
updated_at: "2026-08-14"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# 【修改接口·管理后台】主报账表 baseInfo 尾款口径透出三新字段 + outstandingAmount 下线(#5955)
|
||||
|
||||
## 1. 接口背景
|
||||
|
||||
主报账人报账表(reimbursement)是管理后台订单核单页查看主报账人(通常是司机)代收、垫付支出、预支与净额结算情况的只读报表,`baseInfo` 块承载全部汇总金额。
|
||||
|
||||
此前 baseInfo 用 `outstandingAmount`(整单未收尾款,口径同核单应收财务总览)一个字段表达尾款情况,前端无法区分「应收多少尾款」「实际已收多少尾款」「其中主报账人线下代收了多少尾款」,做尾款对账展示时信息不够。
|
||||
|
||||
本次变更把尾款口径拆成三个权威字段直接透出,同时**删除 outstandingAmount**:未收尾款改由前端以「应收尾款 − 实收尾款」自算。报账人净额 `reporterNetAmount` 保留为**唯一**带正负的净额字段(正=报账人应转回公司,负=公司应补报账人),不再单出绝对值字段。
|
||||
|
||||
## 2. 变更清单
|
||||
|
||||
| # | 位置 | 变更 | 类型 |
|
||||
|---|------|------|------|
|
||||
| 1 | baseInfo.outstandingAmount | **字段删除**:整单未收尾款不再透出,前端读到 undefined/键不存在 | ⚠️ 破坏性删除 |
|
||||
| 2 | baseInfo.receivableBalanceAmount | **新增**:应收尾款(调整后应收合计 − 已退 − 订金实收,负截 0) | ✨ 新增字段 |
|
||||
| 3 | baseInfo.paidBalanceAmount | **新增**:实收尾款(payType∈{BALANCE,FULL} 已收:线上 SUCCESS 流水 + 线下手工收款) | ✨ 新增字段 |
|
||||
| 4 | baseInfo.reporterPaidBalanceAmount | **新增**:报账人实收尾款(主报账人 channel=DRIVER_CASH 且 payType∈{BALANCE,FULL} 的线下收款合计) | ✨ 新增字段 |
|
||||
| 5 | baseInfo.reporterNetAmount | **保留**,口径不变;强调其为唯一带正负净额字段,绝对值展示(如「公司应补报账人」)由前端按符号渲染 | 📝 口径声明(数值零漂移) |
|
||||
| 6 | baseInfo.primaryReporterCollectedAmount | **保留**,口径不变(所有 channel=DRIVER_CASH 收款行合计);与 reporterPaidBalanceAmount(仅其 BALANCE/FULL 尾款子集)语义不同 | 📝 口径声明(数值零漂移) |
|
||||
|
||||
无入参变化、无新接口、无枚举/字典变化、无 DDL。组报 / finalize 门禁内部的 outstandingAmount 计算口径**不受影响**(仅本接口出参不再透出)。
|
||||
|
||||
## 3. 接口详情
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 方法 + 路径 | GET /v3/admin/order/{orderId}/settlement/reports/reimbursement |
|
||||
| 接口名 | 查询主报账人报账表 |
|
||||
| 使用场景 | 管理后台订单核单页,查看主报账人代收/垫付/预支/净额结算报表(含尾款三口径) |
|
||||
| 认证 | 管理后台 JWT(/v3/admin/* 走网关鉴权) |
|
||||
| 角色限制 | 房务角色(HOUSE)不可访问,调了会被 403 拦截 |
|
||||
| 幂等性 | 只读查询,幂等 |
|
||||
| 限流 | 走网关默认限流,无接口级特殊限流 |
|
||||
|
||||
## 4. 接口入参
|
||||
|
||||
### 4.1 路径参数
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| orderId | Long | 是 | 订单 ID,必须大于 0(否则 400「订单 ID 必须大于 0」) |
|
||||
|
||||
### 4.2 请求体 / Query
|
||||
|
||||
无请求体、无 Query 参数。
|
||||
|
||||
## 5. 出参字段
|
||||
|
||||
返回 `Result<SettlementReimbursementReportRespVO>`。顶层 4 个字段不变:baseInfo / incomeLines / expenseLines / advanceLines。本次**仅 baseInfo 金额区变化**,incomeLines / expenseLines / advanceLines 结构零变化。
|
||||
|
||||
### 5.1 baseInfo 全量字段表(变化字段加粗)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Long(String) | 核单记录 ID(settlement_recon.recon_id);未生成时不输出该键 |
|
||||
| orderId | Long(String) | 订单 ID |
|
||||
| orderNo | String | 订单号 |
|
||||
| teamNo | String | 团号(订金未支付为 null,不输出该键) |
|
||||
| productName | String | 产品名 |
|
||||
| productType | String | 产品类型枚举(如 CORE) |
|
||||
| productTypeName | String | 产品类型中文名(字典 product_type 回填) |
|
||||
| customerName | String | 客户姓名 |
|
||||
| departDate | String | 出团日期,格式 yyyy-MM-dd |
|
||||
| returnDate | String | 返回日期,格式 yyyy-MM-dd |
|
||||
| consultantName | String | 定制师姓名 |
|
||||
| travelerCount | Integer | 出行人总数(成人+儿童+幼童+婴儿,空档按 0 计) |
|
||||
| travelerComposition | String | 出行人构成(数量为 0 的档不显示,全空为 null),如「2大 1儿童 1幼童」 |
|
||||
| primaryReporterId | Long(String) | 主报账人人员安排 ID |
|
||||
| primaryReporterName | String | 主报账人姓名 |
|
||||
| primaryReporterRole | String | 主报账人角色(如 DRIVER) |
|
||||
| primaryReporterCollectedAmount | BigDecimal | 主报账人代收金额:所有 channel=DRIVER_CASH 收款行合计(**含订金性质现金**,不含 OTHER_INCOME 其他收入展示行),保留两位小数 |
|
||||
| approvedAdvanceAmount | BigDecimal | 已审批预支金额(预支行合计),保留两位小数 |
|
||||
| reportablePaidCostAmount | BigDecimal | 可报账已付成本(仅 CASH_PAID 现金垫付支出行合计,含 OTHER_EXPENSE 分类中的 CASH_PAID 行),保留两位小数 |
|
||||
| reporterNetAmount | BigDecimal | 报账人净额 = 代收 + 预支 − 支出,保留两位小数;**正=报账人应转回公司,负=公司应补报账人,0=两清**。唯一净额字段,带正负 |
|
||||
| ~~outstandingAmount~~ | — | **已删除**:整单未收尾款不再透出(见 §10) |
|
||||
| **receivableBalanceAmount** | BigDecimal | **新增**·应收尾款 = 调整后应收合计 − 已退 − 订金实收,负值截 0,保留两位小数。其中:订金实收 = 线上 SUCCESS 支付流水 + 线下手工收款中 payType=DEPOSIT 部分;调整后应收合计/已退口径同核单应收财务总览 adjustedReceivableAmount / actualRefundedAmount |
|
||||
| **paidBalanceAmount** | BigDecimal | **新增**·实收尾款 = 已收且 payType∈{BALANCE, FULL} 的合计(线上 SUCCESS 支付流水 + 线下手工收款),保留两位小数。**FULL 全款单无订金概念,首笔即全收,计入实收尾款** |
|
||||
| **reporterPaidBalanceAmount** | BigDecimal | **新增**·报账人实收尾款 = 主报账人 channel=DRIVER_CASH 且 payType∈{BALANCE, FULL} 且 collectorStaffId=主报账人的线下收款合计;无主报账人时为 0,保留两位小数 |
|
||||
|
||||
### 5.2 三新字段的派生关系(前端对账用)
|
||||
|
||||
```
|
||||
receivableBalanceAmount(应收尾款)= 调整后应收合计 − 已退 − 订金实收(DEPOSIT 已收),负截 0
|
||||
paidBalanceAmount(实收尾款) = Σ 已收且 payType∈{BALANCE,FULL}(线上 SUCCESS + 线下手工)
|
||||
reporterPaidBalanceAmount = paidBalanceAmount 中「主报账人 DRIVER_CASH 线下代收」的子集
|
||||
未收尾款(前端自算) = max(0, receivableBalanceAmount − paidBalanceAmount)
|
||||
```
|
||||
|
||||
**与 primaryReporterCollectedAmount 的区别**:代收(collected)含主报账人所有 DRIVER_CASH 收款(含 payType=DEPOSIT 的订金现金);reporterPaidBalanceAmount 只算其中 BALANCE/FULL 尾款部分。订单存在「主报账人代收订金现金」时两者会分叉,属预期。
|
||||
|
||||
## 6. 枚举 / 数据字典
|
||||
|
||||
本次无新增枚举/字典。涉及的既有枚举(仅用于理解口径,不在 baseInfo 出参里):
|
||||
|
||||
| 枚举 | 取值 | 说明 |
|
||||
|------|------|------|
|
||||
| PayType(款项类型) | DEPOSIT(订金)/ FULL(全款)/ BALANCE(尾款) | 实收尾款口径 = BALANCE + FULL;订金实收口径 = DEPOSIT |
|
||||
| 收款渠道 | DRIVER_CASH(报账人现金)/ BANK_TRANSFER / CONSULTANT_COLLECTION | reporterPaidBalanceAmount 只算 DRIVER_CASH 且收款人=主报账人 |
|
||||
|
||||
## 7. 错误码
|
||||
|
||||
本次无新增错误码,沿用既有:
|
||||
|
||||
| code | message | 触发场景 |
|
||||
|------|---------|----------|
|
||||
| 400 | 订单 ID 必须大于 0 | orderId 路径参数校验失败 |
|
||||
| 403 | 无权限访问 | 房务角色(HOUSE)JWT 调用 |
|
||||
| 581007 | 订单不存在 | orderId 查不到订单 |
|
||||
|
||||
## 8. 示例
|
||||
|
||||
### 8.1 典型成功(订金单部分付尾款,含主报账人 DRIVER_CASH 尾款代收)
|
||||
|
||||
场景:调整后应收 10000,已退 0,订金实收 2000(线上 SUCCESS)→ 应收尾款 8000;尾款已收 2200(线上 1700 + 主报账人现金代收 500)。
|
||||
|
||||
GET /v3/admin/order/2087088947225038849/settlement/reports/reimbursement
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"baseInfo": {
|
||||
"id": "6001",
|
||||
"orderId": "2087088947225038849",
|
||||
"orderNo": "HL20260730001",
|
||||
"teamNo": "T20260730001",
|
||||
"productName": "呼伦贝尔草原 5 日游",
|
||||
"productType": "CORE",
|
||||
"productTypeName": "核心产品",
|
||||
"customerName": "张三",
|
||||
"departDate": "2026-07-30",
|
||||
"returnDate": "2026-08-03",
|
||||
"consultantName": "李四",
|
||||
"travelerCount": 4,
|
||||
"travelerComposition": "2大 2儿童",
|
||||
"primaryReporterId": "7001",
|
||||
"primaryReporterName": "司机甲",
|
||||
"primaryReporterRole": "DRIVER",
|
||||
"primaryReporterCollectedAmount": 500.00,
|
||||
"approvedAdvanceAmount": 300.00,
|
||||
"reportablePaidCostAmount": 100.00,
|
||||
"reporterNetAmount": 700.00,
|
||||
"receivableBalanceAmount": 8000.00,
|
||||
"paidBalanceAmount": 2200.00,
|
||||
"reporterPaidBalanceAmount": 500.00
|
||||
},
|
||||
"incomeLines": [
|
||||
{
|
||||
"type": "DRIVER_CASH_RECEIPT",
|
||||
"typeName": "司机现金收款",
|
||||
"receiptId": "8001",
|
||||
"amount": 500.00,
|
||||
"channel": "DRIVER_CASH",
|
||||
"channelName": "报账人收款",
|
||||
"payType": "BALANCE",
|
||||
"payTypeName": "尾款",
|
||||
"collectorStaffId": "7001",
|
||||
"collectorName": "司机甲",
|
||||
"collectorRole": "DRIVER",
|
||||
"collectorRoleName": "司机",
|
||||
"receivedAt": "2026-07-30 18:20:30",
|
||||
"remark": "尾款现金"
|
||||
}
|
||||
],
|
||||
"expenseLines": [],
|
||||
"advanceLines": []
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
前端展示:未收尾款 = max(0, 8000 − 2200) = **5800.00**(自算);reporterNetAmount=700.00>0 → 「报账人应转回公司 700.00」。
|
||||
|
||||
### 8.2 边界情况(FULL 全款单,首笔即全收 + 全额已付后再部分退款)
|
||||
|
||||
场景:FULL 全款单 5000 线上一次付清,无订金概念。应收尾款 = 5000 − 0 − 0(无 DEPOSIT 实收)= 5000;实收尾款 = 5000(FULL 计入);未收尾款自算 = 0。若此后部分退款 1000,应收尾款冲减为 4000、实收仍 5000,自算未收尾款为负 → **前端必须 max(0, ·) 截 0 展示**:
|
||||
|
||||
```json
|
||||
{
|
||||
"baseInfo": {
|
||||
"orderId": "2087088947225038849",
|
||||
"orderNo": "HL20260801002",
|
||||
"primaryReporterName": "司机乙",
|
||||
"primaryReporterRole": "DRIVER",
|
||||
"primaryReporterCollectedAmount": 0.00,
|
||||
"approvedAdvanceAmount": 0.00,
|
||||
"reportablePaidCostAmount": 0.00,
|
||||
"reporterNetAmount": 0.00,
|
||||
"receivableBalanceAmount": 4000.00,
|
||||
"paidBalanceAmount": 5000.00,
|
||||
"reporterPaidBalanceAmount": 0.00
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
边界要点:reporterNetAmount=0 → 两清;reporterPaidBalanceAmount=0(主报账人没有线下代收尾款);未收尾款展示 0.00(负值截 0)。
|
||||
|
||||
### 8.3 业务失败(字段已删——历史代码读 outstandingAmount 拿到 undefined)
|
||||
|
||||
修改后 baseInfo **不再包含 outstandingAmount 键**(不是 null,是键不存在)。前端旧代码 `baseInfo.outstandingAmount` 读到 undefined,若直接参与渲染/计算会出现「undefined元」或 NaN——**必须改为三新字段**:
|
||||
|
||||
```json
|
||||
{
|
||||
"baseInfo": {
|
||||
"orderId": "2087088947225038849",
|
||||
"reporterNetAmount": 700.00,
|
||||
"receivableBalanceAmount": 8000.00,
|
||||
"paidBalanceAmount": 2200.00,
|
||||
"reporterPaidBalanceAmount": 500.00
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
另附通用业务失败响应(与修改前一致):
|
||||
|
||||
```json
|
||||
{ "code": 403, "message": "无权限访问", "success": false }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "code": 581007, "message": "订单不存在", "success": false }
|
||||
```
|
||||
|
||||
## 9. 业务边界
|
||||
|
||||
**适用**:
|
||||
|
||||
- 核单页查看主报账人结算全貌 + 尾款三口径(应收/实收/报账人实收),未收尾款由前端自算展示。
|
||||
|
||||
**不适用**:
|
||||
|
||||
- 组报 / finalize 门禁判断 —— 内部仍用 outstandingAmount 口径,但那是服务端逻辑,前端无需关心,也不要再试图从本接口读它。
|
||||
|
||||
**特殊边界(前端必知)**:
|
||||
|
||||
1. **outstandingAmount 已删,不是 null 是键不存在**:VO 带 @JsonInclude(NON_NULL),删除后该键彻底不下发。旧代码读到 undefined,必须改。
|
||||
2. **历史 finalize 快照无新三字段**:查看本次上线前生成的旧结算快照时,receivableBalanceAmount / paidBalanceAmount / reporterPaidBalanceAmount 三键为 null(不下发),前端需容忍空态展示(如「--」)。
|
||||
3. **前端自算未收尾款可为负**:「全额已付后再部分退款」场景下 应收尾款−实收尾款 为负,展示时必须 max(0, ·)。
|
||||
4. **净额方向**:reporterNetAmount > 0 → 报账人欠公司(应转回);< 0 → 公司欠报账人(应补);= 0 → 两清。界面「公司应补报账人」等绝对值文案由前端按符号渲染,后端不再单出绝对值字段。
|
||||
5. **代收 ≠ 报账人实收尾款**:primaryReporterCollectedAmount 含订金性质现金(DEPOSIT);reporterPaidBalanceAmount 只含 BALANCE/FULL。两者在「主报账人代收过订金现金」时分叉,属预期,不要互相校验相等。
|
||||
|
||||
## 10. 修改前后对比
|
||||
|
||||
### 10.1 字段级对比
|
||||
|
||||
| 位置 | 字段 | 修改前 | 修改后 |
|
||||
|------|------|--------|--------|
|
||||
| baseInfo | outstandingAmount | 整单未收尾款(口径同财务总览) | **已删除**(键不再下发) |
|
||||
| baseInfo | receivableBalanceAmount | 无 | **新增**:应收尾款(调整后应收 − 已退 − 订金实收,负截 0) |
|
||||
| baseInfo | paidBalanceAmount | 无 | **新增**:实收尾款(BALANCE/FULL 已收,线上 SUCCESS + 线下手工) |
|
||||
| baseInfo | reporterPaidBalanceAmount | 无 | **新增**:报账人实收尾款(主报账人 DRIVER_CASH 的 BALANCE/FULL 子集) |
|
||||
| baseInfo | reporterNetAmount | 报账人净额(带正负) | **口径不变**,明确为唯一净额字段 |
|
||||
| baseInfo | primaryReporterCollectedAmount | 主报账人代收 | **口径不变** |
|
||||
| baseInfo | 其余字段 | 原样 | **零变化** |
|
||||
|
||||
### 10.2 行为级对比
|
||||
|
||||
| 场景 | 修改前 | 修改后 |
|
||||
|------|--------|--------|
|
||||
| 未收尾款展示 | 直接读 baseInfo.outstandingAmount | **前端自算** max(0, receivableBalanceAmount − paidBalanceAmount) |
|
||||
| FULL 全款单尾款口径 | outstandingAmount 一个数,无细分 | 应收=调整后应收(无订金可减),实收含 FULL 首笔全额,自算未收=0 |
|
||||
| 主报账人代收了多少尾款 | 无法区分(代收含订金现金混在一起) | reporterPaidBalanceAmount 直接给出 BALANCE/FULL 子集 |
|
||||
| 历史 finalize 快照 | 含 outstandingAmount | 旧快照无新三字段(键为 null 不下发),前端空态容忍 |
|
||||
|
||||
## 11. 影响评估 / 回滚
|
||||
|
||||
### 11.1 影响评估
|
||||
|
||||
- **破坏兼容性**:⚠️ **破坏性变更**。baseInfo 删除 outstandingAmount 字段,凡读取该字段的前端代码必须改造;新增三字段对不读旧字段的页面无影响。
|
||||
- **前端是否必须同步上线**:**是(针对 outstandingAmount 消费点)**。后端上线后 outstandingAmount 立即消失,读它的界面会显示 undefined/空白,前端三新字段改造需与后端同窗口上线。
|
||||
- **改造点清单**:
|
||||
1. 删 baseInfo.outstandingAmount 的所有读取,未收尾款改自算 max(0, receivableBalanceAmount − paidBalanceAmount);
|
||||
2. 新增应收尾款 / 实收尾款 / 报账人实收尾款三处展示(按产品 UI 需要);
|
||||
3. 「公司应补报账人」等绝对值展示按 reporterNetAmount 符号渲染;
|
||||
4. 历史快照空态容忍(三新字段键可能不存在)。
|
||||
- **无 DDL、无枚举、无字典变更**,无其他服务依赖。
|
||||
|
||||
### 11.2 回滚方案
|
||||
|
||||
- 后端回滚 = revert PR #5958 的 commit(cb40e197cb),重启 hl-order-service-v3,outstandingAmount 恢复透出、三新字段消失。
|
||||
- 前端若已按新字段上线而后端回滚,三新字段读到 undefined → 前端回滚需同步;建议前后端同窗口切换。
|
||||
- 零 DDL / 零数据迁移,回滚无数据残留风险。
|
||||
|
||||
## 12. 注意事项
|
||||
|
||||
1. **NON_NULL 省略**:baseInfo 带 @JsonInclude(NON_NULL),null 字段不下发该键(不是下 null);旧快照的三新字段、未生成核单的 id、未付订金的 teamNo 都是「键不存在」,前端读取必须兜底。
|
||||
2. **Long 主键序列化为字符串**(id / orderId / primaryReporterId 等),前端按 string 处理,不要 Number() 转换。
|
||||
3. **金额保留两位小数**,BigDecimal JSON 输出为 number(如 8000.00),前端展示格式化自行处理。
|
||||
4. **汇总只读 baseInfo**:三新字段与 reporterNetAmount 都是后端算好的权威值,前端不要拿 incomeLines 数组自算尾款(收款行还含 DEPOSIT,口径不同必然对不上)。
|
||||
5. 组报 / finalize 门禁内部 outstandingAmount 口径不受本变更影响,无需前端配合。
|
||||
6. 本变更只影响 reimbursement 报账表的 baseInfo;incomeLines / expenseLines / advanceLines 结构零变化,单团核算表(reports/group)不受影响。
|
||||
|
||||
## 13. 关联 / 联系人
|
||||
|
||||
- Issue #5955:https://git.1814.love:8443/wx/HL/issues/5955
|
||||
- PR #5958:https://git.1814.love:8443/wx/HL/pulls/5958
|
||||
- Commit:https://git.1814.love:8443/wx/HL/commit/cb40e197cb
|
||||
- 服务:hl-order-service-v3(端口 8086)
|
||||
- 后端负责人:yst(腰苏图)
|
||||
|
||||
## 14. 验证证据
|
||||
|
||||
- 后端单测:SettlementReportFlowServiceTest / SettlementControllerTest 补 FULL 全款单、部分退款、混合拆分类边界用例(实收尾款含 FULL、应收尾款负截 0、报账人 DRIVER_CASH+BALANCE/FULL 子集口径),PR #5958 已合并 dev-v3(commit cb40e197cb)。
|
||||
- 代码已合并 dev-v3 并部署测试服。
|
||||
- 前端联调验证点:旧 outstandingAmount 消费点全部改造;§8.1 典型场景未收尾款自算 = 5800.00;§8.2 FULL 单部分退款后自算负值截 0 展示;历史快照三新字段空态不报错。
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户