changelog-filename-gate / validate (push) Failing after 2s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
645 行
27 KiB
Markdown
645 行
27 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "7154"
|
||
title: "团期财务总览与预支复用订单预支:财务 Tab 三个只读端点 + 预支创建语义改造"
|
||
consumer: "admin"
|
||
author: "jw(GIT)"
|
||
change_type: "新增接口"
|
||
backend_status: "deployed"
|
||
gateway_status: "verified"
|
||
frontend_status: "verified"
|
||
frontend_owner: "mmg"
|
||
frontend_ref: "af7cc62b"
|
||
target_release: "hl-ui@af7cc62b"
|
||
verified_at: "2026-09-08"
|
||
status_note: "后端 PR #7170 已合 dev-v3 并部署测试服(网关 finance/advances/payee-candidates 实测 200),原 backend_status/gateway_status=pending 系 09-06 陈旧快照已修正为 deployed/verified。前端团期财务 Tab 与预支接真已交付:groupBatchFinance.js 五端点+FinanceTab(四金额卡/逐户付款表/预支记录/整团核算口径行)+GroupAdvanceModal+detail 挂财务 Tab+store 键缓存+AdvanceApprovalList scope 筛选;金额全后端权威值零反算。ref af7cc62b,checkpoint 全绿含 Vitest 全量+生产构建。"
|
||
updated_at: "2026-09-24"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# 团期: 财务总览与预支复用订单预支
|
||
|
||
> **服务**: hl-order-service-v3
|
||
> **PR**: #7170
|
||
> **Issue**: #7154
|
||
> **日期**: 2026-09-06
|
||
> **影响范围**: 管理后台团期详情「财务」Tab、底部操作条「预支」弹窗、财务管理→预支审批列表
|
||
|
||
---
|
||
|
||
## ⚠️ 关键变化
|
||
|
||
团期财务 Tab 与团期预支弹窗此前**在 hl-ui 里完全不存在**(全仓零调用点),本次补齐后端。
|
||
|
||
四条前端必读:
|
||
|
||
1. **`POST .../group-batch/{id}/advance` 入参整体更换**。旧契约 `{amount, remark}` 是后端造了、前端从没接过的端点(已核 hl-ui v2.1 全仓无调用点),故**不是破坏性变更**;新契约与订单级预支**逐字一致**,预支弹窗组件可整体复用。
|
||
2. **「已预支」拆成三个数,旧 `advanceTotal` 已废**。旧语义是「提交即计入」(无审批),与新口径不等价:展示用 `advanceApproved`(只计已通过),额度用 `advanceAvailable`。**不要再用一个数**。
|
||
3. **预支上限一律读后端 `advanceAvailable`,不要前端自算**。订单级弹窗现在是本地 `balanceAmount − Σ记录` 算的,依赖记录列表已拉全;团期场景该算法不可靠。
|
||
4. **「设置报账人」传的是产品侧 `productBatchId`**,从团期详情接口取,**不是**财务 Tab 路径上的 `groupBatchId`,两者不同值。该端点后端零改动。
|
||
|
||
---
|
||
|
||
## 二、变更接口清单
|
||
|
||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| 1 | 团期财务总览 | GET | `/v3/admin/order/group-batch/:id/finance` | 新增 | 四张金额卡 + 逐户付款 + 整团合计 |
|
||
| 2 | 团期预支记录 | GET | `/v3/admin/order/group-batch/:id/advances` | 新增 | 团期级 + 各子订单级逐笔,不分页 |
|
||
| 3 | 领款人候选 | GET | `/v3/admin/order/group-batch/:id/advance/payee-candidates` | 新增 | 预支弹窗「借款对象」下拉 |
|
||
| 4 | 发起团期预支 | POST | `/v3/admin/order/group-batch/:id/advance` | 修改 | 路径不变,入参与返回体更换;创建即进待审批 |
|
||
| 5 | 预支审批列表 | GET | `/v3/admin/order/advance-approvals/page` | 修改 | 容忍团期级行 + `scope` 筛选 + keyword 六路 |
|
||
| 6 | 整团核算汇总 | GET | `/v3/admin/order/group-batch/:id/settlement/summary` | 修改 | 出参新增两个整团预支只读字段 |
|
||
|
||
**零改动复用**(同一套审批流程,前端无需改):`PUT /v3/admin/order/advance/:id/approve`、
|
||
`PUT /v3/admin/order/advance/:id/reject`、`DELETE /v3/admin/order/advance/:id`、
|
||
`PUT /v3/admin/group-batch/:id/staff/:id/reporter-rank`。
|
||
|
||
---
|
||
|
||
## 三、接口详情
|
||
|
||
### 1. 团期财务总览 `GET /v3/admin/order/group-batch/:id/finance`
|
||
|
||
**VO**: `GroupBatchFinanceRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
团期详情切到「财务」Tab 时加载。一次返回顶部四张金额卡、逐户付款表与整团合计、已退团户数、主/次报账人,Tab 全部内容一个请求搞定。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| `id` | path | Long | ✓ | 正整数 | 团期 ID(订单侧 `order_group_batch.group_batch_id`) |
|
||
|
||
无 query 参数,无请求体。需 `group-batch:finance:view` 权限码(比 `group-batch:view` 更严)。
|
||
|
||
#### 出参
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `receivableAmount` | BigDecimal | 整团应收 = Σ 活跃子订单(订单金额 + 附加费 − 优惠) |
|
||
| `receivedAmount` | BigDecimal | 整团已收 = Σ 已付(累计毛额,不冲抵退款) |
|
||
| `unpaidAmount` | BigDecimal | 整团待收 = 应收 − 已收,下限 0,即本期总尾款 |
|
||
| `advanceApproved` | BigDecimal | 已预支(只计已通过)。**第四张卡取此值,不是三个数之和** |
|
||
| `advancePending` | BigDecimal | 待审批预支,占额度但未出账,不计入「已预支」卡 |
|
||
| `advanceAvailable` | BigDecimal | 可支取余额 = 尾款池 − (已通过 + 待审批),下限 0,即预支上限 |
|
||
| `withdrawnCount` | Integer | 已退团户数(前端只拉活跃集,算不出这个数) |
|
||
| `primaryPayeeName` | String | 主报账人姓名,未设置为 `null`(后端不兜底默认导游) |
|
||
| `secondaryPayeeName` | String | 次报账人姓名,未设置为 `null` |
|
||
| `totals.totalPrice` / `.paidAmount` / `.unpaidAmount` | BigDecimal | 逐户表末行「整团合计」,**服务端算**,与顶部卡同源 |
|
||
| `items[].orderId` | String | 子订单 ID(字符串回传防精度丢失) |
|
||
| `items[].orderNo` | String | 子订单号 |
|
||
| `items[].customerName` | String | 客户姓名(不返回手机号与证件号) |
|
||
| `items[].consultantName` | String | 定制师姓名 |
|
||
| `items[].totalPrice` | BigDecimal | 本户应收 |
|
||
| `items[].paidAmount` | BigDecimal | 本户已付。⚠️ 是**全额已付**,不是真定金拆分 |
|
||
| `items[].unpaidAmount` | BigDecimal | 本户待收尾款 |
|
||
| `items[].payStatus` | String | 仅 `UNPAID` / `DEPOSIT_PAID` / `FULLY_PAID` **三值** |
|
||
| `items[].settleStatus` | String | `SETTLED` / `PENDING_BALANCE` / `WITHDRAWN`,**状态胶囊取此值** |
|
||
| `items[].settleStatusText` | String | 结清状态中文,可直接渲染 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/group-batch/90211/finance
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "success",
|
||
"data": {
|
||
"receivableAmount": 40200.00,
|
||
"receivedAmount": 32900.00,
|
||
"unpaidAmount": 7300.00,
|
||
"advanceApproved": 0.00,
|
||
"advancePending": 0.00,
|
||
"advanceAvailable": 7300.00,
|
||
"withdrawnCount": 0,
|
||
"primaryPayeeName": "张领队",
|
||
"secondaryPayeeName": null,
|
||
"totals": { "totalPrice": 40200.00, "paidAmount": 32900.00, "unpaidAmount": 7300.00 },
|
||
"items": [
|
||
{ "orderId": "770145", "orderNo": "GT-26-0081", "customerName": "罗敏", "consultantName": "李雯",
|
||
"totalPrice": 12300.00, "paidAmount": 12300.00, "unpaidAmount": 0.00,
|
||
"payStatus": "FULLY_PAID", "settleStatus": "SETTLED", "settleStatusText": "已结清" },
|
||
{ "orderId": "770147", "orderNo": "GT-26-0083", "customerName": "汪洋", "consultantName": "陈璐",
|
||
"totalPrice": 12300.00, "paidAmount": 5000.00, "unpaidAmount": 7300.00,
|
||
"payStatus": "DEPOSIT_PAID", "settleStatus": "PENDING_BALANCE", "settleStatusText": "待收尾款" }
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
无活跃子订单时,六个金额字段均为 `0.00`(**不是 null**),`items` 为空数组,`withdrawnCount` 为 `0`,两个报账人为 `null`。
|
||
|
||
#### 错误响应
|
||
|
||
| 码 | 含义 |
|
||
|---|---|
|
||
| `589500` | 团期不存在或已软删 |
|
||
| `589507` | 缺 `group-batch:finance:view` 权限 |
|
||
|
||
```json
|
||
{ "code": 589500, "msg": "团期不存在", "data": null }
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 已取消与已软删子订单**不进任何金额、不进 `items`**,只贡献 `withdrawnCount`。
|
||
- 隐式团(`IMPLICIT_SINGLE`)按一单退化开放,字段结构不变,**前端不得因团类型走两套渲染分支**。
|
||
- 顶部「已收(定金)」卡与逐户「已付定金」列,语义都是**全额已付**,不区分定金/尾款;已结清户该列等于应收。
|
||
- 整团应收与团期详情 `totalReceivable`、看板列表该行应收**三处同源**,数值必然一致。
|
||
|
||
---
|
||
|
||
### 2. 团期预支记录 `GET /v3/admin/order/group-batch/:id/advances`
|
||
|
||
**VO**: `List<GroupBatchAdvanceItemVO>`
|
||
|
||
#### 使用场景
|
||
|
||
财务 Tab 下半部「预支记录」区块,以及预支弹窗内的记录列表。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| `id` | path | Long | ✓ | 正整数 | 团期 ID |
|
||
|
||
无 query 参数,**不分页**,一次返回本期全部。
|
||
|
||
#### 出参
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `id` | String | 预支单 ID |
|
||
| `payeeStaffId` | String | 领款人主键快照 |
|
||
| `payeeName` / `payeeRole` / `payeeRoleText` | String | 领款人姓名 / 角色码 / 角色中文 |
|
||
| `advanceType` | String | 借款类型 |
|
||
| `amount` | BigDecimal | 预支金额 |
|
||
| `purpose` / `voucherUrl` | String | 用途说明 / 凭证 URL |
|
||
| `status` / `statusText` | String | `SUBMITTED` / `APPROVED` / `REJECTED` 及其中文 |
|
||
| `rejectReason` | String | 驳回原因 |
|
||
| `createdByName` | String | 申请人姓名 |
|
||
| `createTime` / `submittedAt` / `approvedAt` | String | 创建 / 提交 / 审批时间 |
|
||
| `approvedBy` | String | 审批人姓名 |
|
||
| `scope` | String | `ORDER` 订单级 / `GROUP_BATCH` 团期级(**本次新增**) |
|
||
| `scopeName` | String | 归属维度中文,可直接渲染标签(**本次新增**) |
|
||
| `orderNo` | String | 子订单号,`scope=ORDER` 时非空;团期级为 `null`(**本次新增**) |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/group-batch/90211/advances
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "success",
|
||
"data": [
|
||
{ "id": "31005", "scope": "GROUP_BATCH", "scopeName": "团期预支", "orderNo": null,
|
||
"payeeName": "朝鲁门", "payeeRole": "DRIVER", "payeeRoleText": "司机",
|
||
"advanceType": "住宿押金", "amount": 5000.00, "purpose": "沿途住宿押金",
|
||
"status": "APPROVED", "statusText": "已通过", "createdByName": "李雯",
|
||
"submittedAt": "2026-08-18 22:58:26", "approvedAt": "2026-08-19 09:12:03" }
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
无预支时返回空数组 `[]`,前端显示空态文案「暂无预支 · 在底部「预支」发起,记录将在此显示」(文案由前端提供,后端不返回)。
|
||
|
||
#### 错误响应
|
||
|
||
| 码 | 含义 |
|
||
|---|---|
|
||
| `589500` | 团期不存在 |
|
||
| `589507` | 缺 `group-batch:finance:view` 权限 |
|
||
|
||
```json
|
||
{ "code": 589500, "msg": "团期不存在", "data": null }
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 返回**团期级 + 各子订单级**全部预支,按创建时间倒序。
|
||
- **本接口不返回累计金额**,累计取接口 1 的 `advanceApproved` / `advancePending` / `advanceAvailable`。
|
||
|
||
---
|
||
|
||
### 3. 领款人候选 `GET /v3/admin/order/group-batch/:id/advance/payee-candidates`
|
||
|
||
**VO**: `List<AdvancePayeeCandidateVO>`
|
||
|
||
#### 使用场景
|
||
|
||
预支弹窗「借款对象」下拉。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| `id` | path | Long | ✓ | 正整数 | 团期 ID(订单侧),服务端内部换算成产品侧,前端不感知 |
|
||
|
||
#### 出参
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `id` | Long | 候选 ID,即创建预支的 `payeeStaffId`(资源域 `staff.staff_id`) |
|
||
| `staffName` | String | 姓名 |
|
||
| `staffRole` | String | 角色代码 |
|
||
| `staffRoleText` | String | 角色中文 |
|
||
| `reporterRank` | String | `PRIMARY` / `SECONDARY` / `NONE` |
|
||
| `isDefault` | Boolean | 主报账人为 `true`,前端默认选中 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/group-batch/90211/advance/payee-candidates
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0, "msg": "success",
|
||
"data": [
|
||
{ "id": 88101, "staffName": "张领队", "staffRole": "GUIDE", "staffRoleText": "导游",
|
||
"reporterRank": "PRIMARY", "isDefault": true },
|
||
{ "id": 88102, "staffName": "朝鲁门", "staffRole": "DRIVER", "staffRoleText": "司机",
|
||
"reporterRank": "NONE", "isDefault": false }
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
团期未配人员时返回空数组 `[]`;此时预支无法提交(借款对象必填)。
|
||
|
||
#### 错误响应
|
||
|
||
| 码 | 含义 |
|
||
|---|---|
|
||
| `589500` | 团期不存在 |
|
||
| `589507` | 缺 `group-batch:finance:view` 权限 |
|
||
|
||
```json
|
||
{ "code": 589500, "msg": "团期不存在", "data": null }
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 候选 = 本团**全部**人员(与订单级「可选本单任一人员」口径一致),排序:主报账人 → 次报账人 → 其余。
|
||
- **不返回手机号**,与订单级候选保持一致。
|
||
|
||
---
|
||
|
||
### 4. 发起团期预支 `POST /v3/admin/order/group-batch/:id/advance`
|
||
|
||
**VO**: `OrderAdvanceRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
财务 Tab 底部操作条「预支」→ 弹窗填写 → 「申请预支」。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| `id` | path | Long | ✓ | 正整数 | 团期 ID |
|
||
| `payeeStaffId` | body | Long | ✓ | 须属本团人员 | 借款对象,取候选下拉项的 `id` |
|
||
| `advanceType` | body | String | ✓ | 字典 `advance_type` 的 `dictValue` | 借款类型 |
|
||
| `amount` | body | BigDecimal | ✓ | > 0 且 ≤ `advanceAvailable` | 预支金额 |
|
||
| `purpose` | body | String | — | ≤ 255 | 用途说明 |
|
||
| `voucherUrl` | body | String | — | ≤ 512 | 凭证 URL |
|
||
|
||
> ⚠️ 旧入参 `{amount, remark}` **已废除**。`remark` 无对应字段,改用 `purpose`。
|
||
|
||
#### 出参
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `id` | String | 新建的预支单 ID(旧实现返回 `Void`,**现在回传**) |
|
||
| `payeeStaffId` | String | 领款人主键快照(团期级存资源域 `staff.staff_id`) |
|
||
| `payeeName` / `payeeRole` / `payeeRoleText` | String | 领款人姓名 / 角色码 / 角色中文 |
|
||
| `advanceType` | String | 借款类型 |
|
||
| `amount` | BigDecimal | 预支金额 |
|
||
| `purpose` / `voucherUrl` | String | 用途说明 / 凭证 URL |
|
||
| `status` / `statusText` | String | 创建后恒为 `SUBMITTED` / 「待审批」 |
|
||
| `createdByName` | String | 申请人姓名 |
|
||
| `createTime` / `submittedAt` | String | 创建 / 提交时间 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
POST /v3/admin/order/group-batch/90211/advance
|
||
{
|
||
"payeeStaffId": 88102,
|
||
"advanceType": "住宿押金",
|
||
"amount": "3000.00",
|
||
"purpose": "沿途住宿押金",
|
||
"voucherUrl": null
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0, "msg": "success",
|
||
"data": {
|
||
"id": "31006", "payeeStaffId": "88102", "payeeName": "朝鲁门",
|
||
"payeeRole": "DRIVER", "payeeRoleText": "司机",
|
||
"advanceType": "住宿押金", "amount": 3000.00, "purpose": "沿途住宿押金",
|
||
"status": "SUBMITTED", "statusText": "待审批",
|
||
"createdByName": "李雯", "submittedAt": "2026-09-06 15:20:11"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
数据字典服务不可用时,借款类型校验降级为服务端内置集合,**不影响正常类型提交**。
|
||
|
||
#### 错误响应
|
||
|
||
| 码 | 含义 |
|
||
|---|---|
|
||
| `589500` | 团期不存在 |
|
||
| `589507` | 缺 `group-batch:finance:advance` 权限 |
|
||
| `589541` | 团期状态不可发起预支。⚠️ 2026-09-24 订正:原文误写为 `589538`(号段顺延后实际落 589541);允许状态已两次放宽,现为「进入核单前都可以」(#8270 / #8322) |
|
||
| `589542` | 房 / 车 / 导 / 摄四项未配齐。⚠️ 2026-09-24 订正:原文误写为 `589539`(该号实为 #7178「名额调整量不能为 0」);**#8270 起本码不再返回** |
|
||
| `585003` | 预支金额必须大于 0 |
|
||
| `585004` | 预支金额超过可用余额上限 |
|
||
| `585006` | 借款类型非法 |
|
||
| `585007` | 借款对象不属于本团期人员 |
|
||
|
||
```json
|
||
{ "code": 585004, "msg": "预支金额超过可用余额上限", "data": null }
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- **双前置闸门**:团期状态 + 四项资源全就绪,缺一即拒(此前服务端两道都没有,只有前端做了置灰)。⚠️ 已变更:#8270 删除四项配齐门,#8322 起进入核单前都可发起,且领款人限定为本团主报账人(589557),见 `24_8322_…` 条目。
|
||
- **上限走团期统一池**:团期级与各子订单级**共扣一池**。团期把整团尾款预支满后,该团任一子订单再发起订单级预支同样会被 `585004` 拒——这是本次修复的超支漏洞。
|
||
- 创建后进入**站内财务审批**,走既有 `advance-approvals` 列表与 approve / reject / 撤回三端点,与订单级完全一致。
|
||
- 一期仍**只记账不出款**,实际出款走财务既有付款流程。
|
||
- 同一团期 + 同一金额 5 秒内重复提交只成功一次(幂等)。
|
||
|
||
---
|
||
|
||
### 5. 预支审批列表 `GET /v3/admin/order/advance-approvals/page`
|
||
|
||
**VO**: `PageResult<AdvanceApprovalPageItemRespVO>`
|
||
|
||
#### 使用场景
|
||
|
||
财务管理 → 预支审批。团期级预支与订单级预支**混排在同一列表、走同一审批流程**。
|
||
|
||
#### 入参
|
||
|
||
新增一个可选 query 参数,其余入参不变:
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| `scope` | query | String | — | `ALL` / `ORDER` / `GROUP_BATCH` | 归属维度筛选,缺省 `ALL`(两类混排,与改造前行为一致) |
|
||
|
||
`keyword` 语义扩展:由「订单号 / 团号 / 产品名」三路扩为**六路**,另加「团期号 / 团期名 / 团期产品名」。改造前搜索框标着「团号 / 产品」却搜不出团期级预支。
|
||
|
||
#### 出参
|
||
|
||
每行新增四个字段,其余不变:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `scope` | String | `ORDER` / `GROUP_BATCH` |
|
||
| `scopeName` | String | 归属维度中文 |
|
||
| `batchStatus` | String | 团期状态编码,仅 `scope=GROUP_BATCH` 时非空 |
|
||
| `batchStatusName` | String | 团期状态中文 |
|
||
|
||
**既有字段按 `scope` 择一填充,前端零改动即可显示**:
|
||
|
||
| 字段 | `scope=ORDER` | `scope=GROUP_BATCH` |
|
||
|---|---|---|
|
||
| `teamNo`(团号列) | 订单团号 | **团期号** |
|
||
| `productName` | 订单产品名 | 团期产品名 |
|
||
| `departDate` / `returnDate`(行程列) | 订单出行日期 | 团期出团 / 返程日 |
|
||
| `orderAmount` / `paidAmount` | 本单应收 / 已收 | **整团应收 / 已收** |
|
||
| `orderNo` / `consultantName` | 有值 | `null`(前端显「—」) |
|
||
| `orderStatus` / `flowStatus` / `payStatus` / `settlementStatus` | 有值 | `null`,改看 `batchStatus` |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/advance-approvals/page?status=SUBMITTED&scope=GROUP_BATCH&page=1&pageSize=20
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0, "msg": "success",
|
||
"data": {
|
||
"records": [
|
||
{ "id": "31006", "scope": "GROUP_BATCH", "scopeName": "团期预支",
|
||
"orderNo": null, "teamNo": "GT-26-05", "productName": "呼伦贝尔草原 5 日游",
|
||
"departDate": "2026-09-20", "returnDate": "2026-09-24", "consultantName": null,
|
||
"orderStatus": null, "batchStatus": "PENDING_DEPARTURE", "batchStatusName": "待出发",
|
||
"orderAmount": 40200.00, "paidAmount": 32900.00,
|
||
"payeeName": "朝鲁门", "advanceType": "住宿押金", "amount": 3000.00,
|
||
"status": "SUBMITTED", "statusText": "待审批" }
|
||
],
|
||
"total": 1, "page": 1, "pageSize": 20
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
无匹配记录时 `records` 为空数组,`total` 为 `0`。
|
||
|
||
#### 错误响应
|
||
|
||
沿用改造前,本次未新增错误码。
|
||
|
||
```json
|
||
{ "code": 589507, "msg": "无操作权限", "data": null }
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- **前端必须容忍 `orderId` / `orderNo` 为 `null`**(团期级行不挂订单)。
|
||
- 审批通过 / 驳回 / 撤回三个端点**零改动**,对团期级行行为与订单级完全一致。
|
||
- 团期级预支走**站内财务审批(资金审批)**,与流团 / 退单户的企微 OA **业务审批**是两条线,不合并。
|
||
|
||
---
|
||
|
||
### 6. 整团核算汇总 `GET /v3/admin/order/group-batch/:id/settlement/summary`
|
||
|
||
**VO**: `GroupBatchSettlementSummaryRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
整团核算页。本次新增两个只读字段,用于**核单时把整团预支从主报账人代收的尾款中扣回**。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| `id` | path | Long | ✓ | 正整数 | 团期 ID。入参未变 |
|
||
|
||
#### 出参
|
||
|
||
新增两个字段,其余不变:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `groupAdvanceApproved` | BigDecimal | 整团已拨付预支(**只含团期级**),核算时单独成一行扣回 |
|
||
| `groupAdvancePending` | BigDecimal | 整团待审批预支,占额度未出账,仅提示 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/group-batch/90211/settlement/summary
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 0, "msg": "success",
|
||
"data": {
|
||
"settledOrderCount": 3, "totalActiveOrderCount": 3,
|
||
"subOrderTotalActualCost": 21000.00, "sharedCostTotal": 6000.00,
|
||
"grandTotalCost": 27000.00,
|
||
"groupAdvanceApproved": 5000.00,
|
||
"groupAdvancePending": 0.00
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
无团期级预支时两个字段均为 `0.00`(不是 null)。
|
||
|
||
#### 错误响应
|
||
|
||
沿用改造前。
|
||
|
||
```json
|
||
{ "code": 589500, "msg": "团期不存在", "data": null }
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 🚫 **只含团期级预支,不含子订单级**。子订单级预支已进各户的核单报销单与对账,整团层再算一次会**同一笔钱扣两遍**。
|
||
- 🚫 **不计入 `grandTotalCost`**。预支是**资金拨付**不是成本,计入会与核销后的真实成本科目重复计成本。前端渲染为「整团成本 X / 其中已拨付预支 Y」的独立一行,**不参与任何成本或毛利公式**。
|
||
- 逐户报销单与逐户对账**一个字未改**。
|
||
|
||
---
|
||
|
||
## 四、契约约束与正确调用方式
|
||
|
||
1. **财务 Tab 一次请求拿全**:接口 1 已含四张卡、逐户表、整团合计、退团户数、报账人,不要再拼 `/orders`。
|
||
2. **金额一律用服务端给的值**。整团合计由服务端算并与四张卡同源;前端自行 sum 会与卡片对不上。
|
||
3. **预支上限读 `advanceAvailable`**,不要用「待收尾款 − 记录之和」本地推算。
|
||
4. **状态胶囊读 `settleStatus`**,不要用 `payStatus` 推——后者只有三值,表达的是支付事件不是结清与否,已退团户用它渲染会显示成「已付定金」。
|
||
5. **设置报账人用产品侧 `productBatchId`**(团期详情接口取),不是财务 Tab 路径上的 `groupBatchId`。
|
||
|
||
---
|
||
|
||
## 五、数据库行为
|
||
|
||
> 只写外部可观察行为。
|
||
|
||
| 动作 | 可观察结果 |
|
||
|---|---|
|
||
| 发起团期预支 | 新增一条待审批预支记录,立即出现在本团期预支记录列表与预支审批列表;团期与订单的任何金额字段**均不变动**(预支不改应收/已收/待收) |
|
||
| 审批通过 | 该记录转为「已通过」,财务 Tab 的「已预支」增加、「待审批预支」减少、「可支取余额」不变(原本就已占额度) |
|
||
| 审批驳回 / 撤回 | 该记录转为「已驳回」或从列表消失,占用的额度**当场释放**,「可支取余额」回升 |
|
||
| 上线迁移(一次性) | 存量团期原有的累计预支金额,会转成一条「已通过」的**期初结转**记录出现在预支记录列表,金额与迁移前的累计值相等;该记录无领款人与凭证,按借款类型「期初结转」可识别 |
|
||
|
||
**幂等**:同一团期 + 同一金额 5 秒内重复提交只成功一次。
|
||
|
||
**并发**:同一团期的预支申请串行处理,两个管理员同时提交不会双双突破可支取余额。
|
||
|
||
---
|
||
|
||
## 六、边界行为
|
||
|
||
| 场景 | 行为 |
|
||
|---|---|
|
||
| 团期无活跃子订单 | 六个金额字段 `0.00`,`items` 空数组 |
|
||
| 子订单已取消 | 不进金额、不进 `items`,只计入 `withdrawnCount` |
|
||
| 未设置报账人 | `primaryPayeeName` 为 `null`,后端不兜底默认导游 |
|
||
| 团期状态为招募中 / 核单中 | 发起预支返回 `589541`(2026-09-24 订正码值;#8322 起招募中已可发起,仅核单中及之后返回) |
|
||
| 四项资源缺任一 | 原返回 `589542`(2026-09-24 订正码值);#8270 起不再拦截 |
|
||
| 团期尾款池已被预支占满 | 团期级与该团任一子订单级预支**均**返回 `585004` |
|
||
| 数据字典服务不可用 | 借款类型降级到内置集合校验,正常类型仍可提交 |
|
||
| 审批列表出现团期级行 | `orderId` / `orderNo` / `consultantName` / 订单四态均为 `null` |
|
||
|
||
---
|
||
|
||
## 七、不影响范围
|
||
|
||
- **订单级预支全链路行为零变化**:创建 / 审批 / 驳回 / 撤回 / 本单列表五个端点与改造前逐字一致(底表 `order_id` 由非空放宽为可空,但既有查询全是等值匹配,空值行天然不命中)。
|
||
- **逐户核单报销单与逐户对账未改**:仍只含本户预支。
|
||
- **审批通过 / 驳回 / 撤回三端点未改**。
|
||
- **设置报账人端点未改**。
|
||
- 前端页面、打印导出、发票区、预支实际出款均不在本次范围。
|
||
|
||
---
|
||
|
||
## 八、测试环境已验证
|
||
|
||
> ⏳ **尚未验证**。本文档随 PR #7170 提交,待合并并部署测试服后过网关实测,届时更新
|
||
> `backend_status` / `gateway_status` / `verified_at` 并补本节实测结果。
|
||
|
||
计划实测要点:
|
||
|
||
1. 财务 Tab 四张卡与逐户表末行合计一致,且与团期详情、看板列表三处应收同源。
|
||
2. **超支被堵死**:团期级把整团尾款预支满 → 该团任一子订单再发起订单级预支被 `585004` 拒。
|
||
3. **核单零重复扣**:团期级预支 5,000 通过 + 某户订单级预支 2,000 通过 → 该户报销单含 2,000,整团 `groupAdvanceApproved` 仍是 5,000;`grandTotalCost` 不变。
|
||
4. 两道闸门各拒一次(`589541` / `589542`,2026-09-24 订正码值)。
|
||
5. 团期级预支出现在预支审批列表,「团号 / 产品」「行程」两列有值,按团期号搜得到,就地通过 / 驳回 / 撤回正常。
|
||
6. 订单级预支五端点回归无变化。
|
||
|
||
---
|
||
|
||
## 十、相关文档
|
||
|
||
- 团期模块接口文档 v2.0 §0B(预支权威契约)、§0A.3(金额口径)、卡片 GB-ADM-040 / 041 / 042 / 043
|
||
- 团期模块数据模型 §A.11(预支复用订单预支)、§A.11.10(团期层单独对账)
|
||
- 团期模块表结构 v1.2 §4-5(`order_advance` 改造 DDL)
|
||
|
||
**待回写正式稿**(本次实现与文档不一致处):
|
||
|
||
| 处 | 文档现状 | 实际 |
|
||
|---|---|---|
|
||
| §0B.9 错误码 | 「统一用 `AdvanceErrorCode`(585 段)」 | 改落 `589541` / `589542`(原拟 589538 / 589539,被 #7158 / #7178 先占后顺延,2026-09-24 订正);585 段被 v2/v3 整段重叠声明且 585001-585010 已被 order-v2 实占 |
|
||
| GB-ADM-040 出参 | `payStatus` 写五值含 `REFUNDING` / `REFUNDED` | 代码只有三值;结清状态另出 `settleStatus` 字段 |
|
||
| GB-ADM-040 出参 | 含 `advanceTotal` | 已废,改三个数 |
|
||
| GB-ADM-042 | 返回 `GroupBatchWriteResultVO`、不回传 `advanceId` | 改返 `OrderAdvanceRespVO` 并回传 `advanceId` |
|
||
| §0A.3 | 「金额缺口是本期 P0,详情恒返回 0.00」 | 已被 #6905 / #6902 实时聚合关闭 |
|
||
| §0B.6 | 「查询键列名骗人,必须进 CR checklist」 | `V20260904_001` 改名后该坑消失 |
|
||
|
||
---
|
||
|
||
## 关联 / 联系人
|
||
|
||
- **Issue**: #7154
|
||
- **PR**: #7170(base `dev-v3`)
|
||
- **后端**: jw
|
||
- **前端**: 待认领(三个新端点 + 预支弹窗入参更换 + 审批列表 `scope` 标签)
|