文件
hl-api-changelog/changelogs-v2/2026-09/30_8516_团期新增核单结算状态字段且出行完毕改名待核单-修改接口-管理后台.md
T
Mimingguang和Claude Opus 4.8 eb2dc899f2
changelog-filename-gate / validate (push) Failing after 2s
chore(changelog): #8516 回写 implemented(hl-admin d8de94a8)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-10-01 09:36:34 +08:00

1061 行
53 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "8516"
title: "团期状态「出行完毕」TRIP_FINISHED 改名「待核单」PENDING_REVIEW(破坏性,前端须同批发布);团期详情 / 分页新增整团核单、结算状态四个字段;进度条核单 / 结算节点新增分支;三处入参旧值兼容"
consumer: "admin"
author: "jw(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "implemented"
frontend_owner: "hl-admin(claude-opus-4-8)"
frontend_ref: "d8de94a894680f3b3e62985f03fce235ccb0f3f8"
target_release: "v2.1"
verified_at: "2026-10-01"
status_note: "① 团期主状态取值 TRIP_FINISHED「出行完毕」改为 PENDING_REVIEW「待核单」,存量数据与时间线历史行已随迁移改写,所有返回团期主状态的接口只输出新值;出行子状态 tripSubStatus 同步由 TRIP_FINISHED「已返团」改为 PENDING_REVIEW「待核单」。② A2 团期详情、A1 团期分页新增 reviewStatus / reviewStatusName / settlementStatus / settlementStatusName。③ 详情进度条 REVIEW、SETTLE 节点各新增一条分支,文案如「核单·已核单」「结算·结算中」,字段为 NONE 时「待开始」;当前节点仍按主状态分桶。④ 团期分页 batchStatus、房务配房列表(含 scope=mine)batchStatus、房务团期看板 batchStatus 传旧值 TRIP_FINISHED 时按 PENDING_REVIEW 处理;opsStage=TRIP_FINISHED 旧桶名保留。⑤ 团期时间线新增「核单状态变更」「结算状态变更」两类事件。⑥ 发起核单、首笔共享成本、/settle、/settle/reopen 四个既有写入口请求与响应不变,/settle 不再逐户推 ORDER 报账单。hl-ui 必须同批改:按 TRIP_FINISHED 判断的 7 处与显示映射 3 处,不改则「发起核单」按钮消失、财务面板「完成核单」点不了。TEST 已于 2026-09-30 部署(dev-v3 dd0452916,合并提交 54e64c50f)并实测;jw 09-30 定 TEST 先行,正式环境前后端同批发布,故 frontend_status 记 pending。财务回写用的两个内部接口见同日 30_8516 新增接口那份。2026-10-01 hl-admin 交付:判断 7 处改 [TRIP_FINISHED, PENDING_REVIEW] 并集兼容(batchLifecycle/orderDetailActions/requirementFreeze/canStartReview/canWaive/FinanceTab ADVANCE_STAGES/finalizeNodeOk),显示映射 3 处加新键保留旧键(FLOW_STATUS_TEXT/boardLabels/GroupBatchTable),BatchHero 页头新增「核单·X」「结算·X」标签(NONE 不显示,直显后端 *Name,与进度条分支文案一致),api JSDoc 3 文件钉新口径;定向 4 spec 66 例全绿,ref d8de94a8。"
updated_at: "2026-09-30"
base: "dev-v3"
---
# 团期:「出行完毕」改名「待核单」,新增整团核单 / 结算状态字段(管理后台)
> **服务**: hl-order-service-v3(端口 8086 / 8186)
> **PR**: #8650(merge commit `54e64c50f`)
> **Issue**: #8516
> **日期**: 2026-09-30
> **影响范围**: 团期详情 / 分页 / 进度条 / 时间线的核单、结算展示;团期状态筛选入参;所有按团期状态值做判断的前端代码
---
## ⚠️ 关键变化
**破坏性变更,前端必须与后端同批发布。**
| 变了什么 | 以前 | 现在 |
|---|---|---|
| 团期主状态 `batchStatus` 的一个取值 | `TRIP_FINISHED`「出行完毕」 | `PENDING_REVIEW`「待核单」。存量团期、时间线历史行已统一改写,**任何接口的返回值里都不再出现 `TRIP_FINISHED`** |
| 出行子状态 `tripSubStatus` 的一个取值 | `TRIP_FINISHED`「已返团」 | `PENDING_REVIEW`「待核单」;进度条出行节点 label 同步变为「待核单」 |
| 团期详情、分页 | 没有整团核单 / 结算状态 | 新增 `reviewStatus` / `reviewStatusName` / `settlementStatus` / `settlementStatusName` |
| 详情进度条核单、结算节点 | `subFlows=null` | 各带一条分支,如「核单·已核单」「结算·结算中」 |
| `/settle` 整团结算 | 逐户做财务复核并推 ORDER 报账单(#8341) | 只把子订单状态置为已结算,**不推报账单**;请求 / 响应不变 |
前端代码里凡是写死 `'TRIP_FINISHED'` 当状态值判断的地方,不改就会静默失效——最明显的是团期详情「发起核单」按钮会消失、财务面板「完成核单」点不了(清单见六.7)。
---
## 一、背景
jw 09-29 定口径:团期上加核单、结算两个独立状态(写法参照配房、配车),出行结束后团期自动进入「待核单」,此后核单中、已核单、待结算、结算中、已结算都由财务从外部更新,团期主状态由这两个状态推导,子订单跟着同步。
「出行完毕」描述的是出行结束这件事,事件之后团期所处的状态是「待核单」,所以主状态改名;时间线里的事件「出行完毕」`BATCH_TRIP_FINISH` 不改名。财务回写这两个状态用的内部接口见同日 `30_8516_团期核单与结算状态财务内部回写接口-新增接口-管理后台.md`(前端无需对接)。
---
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | A2 团期详情 | GET | `/v3/admin/order/group-batch/:groupBatchId` | 修改接口 | 新增 4 个字段;`batchStatus` / `tripSubStatus` 取值改名;进度条核单、结算节点新增分支 |
| 2 | A1 团期分页 | GET | `/v3/admin/order/group-batch` | 修改接口 | 新增 4 个字段;取值改名;入参 `batchStatus` 旧值兼容;`opsStage=TRIP_FINISHED` 桶名保留 |
| 3 | 房务配房列表(团期) | GET | `/v3/admin/order/house-allocation/group-batches` | 修改接口 | 入参 `batchStatus` 旧值兼容(含 `scope=mine`,改前返回 400);`batchStatus` / `batchStatusLabel` 取值改名 |
| 4 | 房务团期看板列表 | GET | `/v3/admin/house/group-batches` | 修改接口 | 入参 `batchStatus` 旧值兼容(改前退回默认筛选);`batchStatus` / `batchStatusText` 取值改名 |
| 5 | 团期状态流水(时间线) | GET | `/v3/admin/order/group-batch/:groupBatchId/status-logs` | 修改接口 | 新增「核单状态变更」「结算状态变更」两类事件;`fromStatus` / `toStatus` 取值改名(含历史行) |
---
## 三、接口详情
### 1. A2 团期详情 `GET /v3/admin/order/group-batch/:groupBatchId`
**VO**: `GroupBatchDetailRespVO`(进度条节点 `GroupBatchProgressNodeVO`,分支 `GroupBatchProgressSubFlowVO`)
#### 使用场景
团期详情页页头状态、进度条、核单 / 结算信息。本次新增整团核单 / 结算状态四个字段,进度条核单、结算节点新增分支,主状态与出行子状态的「出行完毕 / 已返团」改为「待核单」。其余出参不变。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| groupBatchId | Path | Long | 是 | 团期 ID | 不存在返回 589500;未变 |
#### 出参 `Result<GroupBatchDetailRespVO>`
只列本次新增或取值有变化的字段。
| 字段 | 类型 | 说明 |
|------|------|------|
| reviewStatus | String | **新增**。整团核单状态:`NONE` 未核单(还没出行完毕)/ `PENDING` 待核单 / `IN_PROGRESS` 核单中 / `COMPLETED` 已核单。与子订单核单状态同名同值。恒非 null |
| reviewStatusName | String | **新增**。未核单 / 待核单 / 核单中 / 已核单 |
| settlementStatus | String | **新增**。整团结算状态:`NONE` 未结算(核单还没完成)/ `PENDING` 待结算 / `IN_PROGRESS` 结算中 / `COMPLETED` 已结算。恒非 null。与财务 tab 逐户付款结清的 `settleStatus` 无关 |
| settlementStatusName | String | **新增**。未结算 / 待结算 / 结算中 / 已结算 |
| batchStatus | String | 取值 `TRIP_FINISHED` 改为 `PENDING_REVIEW`,其余八个取值不变 |
| batchStatusName | String | 「出行完毕」改为「待核单」 |
| tripSubStatus | String | 仅 `stage=TRIP` 时有值:`PENDING_DEPARTURE` 待出发 / `TRAVELLING` 出行中 / `PENDING_REVIEW` 待核单(原 `TRIP_FINISHED` 已返团) |
| tripSubStatusName | String | 「已返团」改为「待核单」 |
| progressStepper[].label | String | 出行节点为当前节点且团期待核单时,由「已返团」改为「待核单」 |
| progressStepper[].subFlows | List\<GroupBatchProgressSubFlowVO\> | **REVIEW、SETTLE 两个节点由 `null` 改为各 1 条分支**;CONFIGURE 仍是 5 条;RECRUIT / CONFIRM / TRIP 仍为 `null` |
| progressStepper[].subFlows[].code | String | 核单节点 `REVIEW`,结算节点 `SETTLE` |
| progressStepper[].subFlows[].name | String | 核单 / 结算 |
| progressStepper[].subFlows[].status | String | 直接取 `reviewStatus` / `settlementStatus` 的值:`PENDING` / `IN_PROGRESS` / `COMPLETED`;字段为 `NONE` 时为 `WAITING` |
| progressStepper[].subFlows[].statusName | String | 核单节点:待核单 / 核单中 / 已核单;结算节点:待结算 / 结算中 / 已结算;字段为 `NONE` 时「待开始」 |
| progressStepper[].subFlows[].displayText | String | `name·statusName`,如「核单·已核单」「结算·结算中」「结算·待开始」 |
#### 请求示例
```http
GET /v3/admin/order/group-batch/2105223438312652802 HTTP/1.1
Host: api.test.1814.love
Authorization: Bearer <admin token>
```
无请求体。
#### 响应示例
T26-5936(核单已完成、结算中):注意核单节点 label 仍是「核单中」(按主状态分桶),分支是「核单·已核单」(TEST 2026-09-30 实测,只列与本次相关的字段):
```json
{
"code": 200,
"message": "成功",
"data": {
"groupBatchId": "2105223438312652802",
"batchNo": "T26-5936",
"batchName": "呼伦贝尔草原3日游·9月26日团",
"batchStatus": "REVIEWING",
"batchStatusName": "核单中",
"reviewStatus": "COMPLETED",
"reviewStatusName": "已核单",
"settlementStatus": "IN_PROGRESS",
"settlementStatusName": "结算中",
"stage": "REVIEW",
"stageName": "核单",
"tripSubStatus": null,
"tripSubStatusName": null,
"progressStepper": [
{"step": 1, "code": "RECRUIT", "name": "招募", "status": "DONE", "label": null, "isCurrent": false, "subFlows": null },
{"step": 2, "code": "CONFIGURE", "name": "配置", "status": "DONE", "label": null, "isCurrent": false, "subFlows": [
{"code": "HOTEL", "name": "配房", "status": "UNMET", "statusName": "未配齐", "displayText": "配房·未配齐"},
{"code": "VEHICLE", "name": "配车", "status": "UNMET", "statusName": "未配齐", "displayText": "配车·未配齐"},
{"code": "GUIDE", "name": "配导游", "status": "WAIVED", "statusName": "无需", "displayText": "配导游·无需"},
{"code": "PHOTOGRAPHER", "name": "配摄影", "status": "WAIVED", "statusName": "无需", "displayText": "配摄影·无需"},
{"code": "MATERIAL", "name": "配物资", "status": "UNMET", "statusName": "未确认", "displayText": "配物资·未确认"}
] },
{"step": 3, "code": "CONFIRM", "name": "确认", "status": "DONE", "label": null, "isCurrent": false, "subFlows": null },
{"step": 4, "code": "TRIP", "name": "出行", "status": "DONE", "label": null, "isCurrent": false, "subFlows": null },
{"step": 5, "code": "REVIEW", "name": "核单", "status": "PROCESSING", "label": "核单中", "isCurrent": true, "subFlows": [
{"code": "REVIEW", "name": "核单", "status": "COMPLETED", "statusName": "已核单", "displayText": "核单·已核单"}
] },
{"step": 6, "code": "SETTLE", "name": "结算", "status": "WAITING", "label": null, "isCurrent": false, "subFlows": [
{"code": "SETTLE", "name": "结算", "status": "IN_PROGRESS", "statusName": "结算中", "displayText": "结算·结算中"}
] }
]
},
"traceId": null,
"success": true
}
```
T26-2325(待核单):主状态、出行子状态、出行节点 label 都是「待核单」,核单分支「核单·待核单」:
```json
{
"code": 200,
"message": "成功",
"data": {
"groupBatchId": "2105223439872933889",
"batchNo": "T26-2325",
"batchName": "呼伦贝尔草原3日游·9月25日团",
"batchStatus": "PENDING_REVIEW",
"batchStatusName": "待核单",
"reviewStatus": "PENDING",
"reviewStatusName": "待核单",
"settlementStatus": "NONE",
"settlementStatusName": "未结算",
"stage": "TRIP",
"stageName": "出行",
"tripSubStatus": "PENDING_REVIEW",
"tripSubStatusName": "待核单",
"progressStepper": [
{"step": 1, "code": "RECRUIT", "name": "招募", "status": "DONE", "label": null, "isCurrent": false, "subFlows": null },
{"step": 2, "code": "CONFIGURE", "name": "配置", "status": "DONE", "label": null, "isCurrent": false, "subFlows": [
{"code": "HOTEL", "name": "配房", "status": "UNMET", "statusName": "未配齐", "displayText": "配房·未配齐"},
{"code": "VEHICLE", "name": "配车", "status": "WAIVED", "statusName": "整团免车", "displayText": "配车·整团免车"},
{"code": "GUIDE", "name": "配导游", "status": "WAIVED", "statusName": "无需", "displayText": "配导游·无需"},
{"code": "PHOTOGRAPHER", "name": "配摄影", "status": "WAIVED", "statusName": "无需", "displayText": "配摄影·无需"},
{"code": "MATERIAL", "name": "配物资", "status": "UNMET", "statusName": "未确认", "displayText": "配物资·未确认"}
] },
{"step": 3, "code": "CONFIRM", "name": "确认", "status": "DONE", "label": null, "isCurrent": false, "subFlows": null },
{"step": 4, "code": "TRIP", "name": "出行", "status": "PROCESSING", "label": "待核单", "isCurrent": true, "subFlows": null },
{"step": 5, "code": "REVIEW", "name": "核单", "status": "WAITING", "label": null, "isCurrent": false, "subFlows": [
{"code": "REVIEW", "name": "核单", "status": "PENDING", "statusName": "待核单", "displayText": "核单·待核单"}
] },
{"step": 6, "code": "SETTLE", "name": "结算", "status": "WAITING", "label": null, "isCurrent": false, "subFlows": [
{"code": "SETTLE", "name": "结算", "status": "WAITING", "statusName": "待开始", "displayText": "结算·待开始"}
] }
]
},
"traceId": null,
"success": true
}
```
#### 空数据 / 降级响应
- 出行完毕之前(招募中 ~ 出行中):`reviewStatus` / `settlementStatus` 恒为 `NONE`(不会是 null),核单、结算分支都是「待开始」。
- 已流团、`batchStatus` 为 null 或不在九态内:`progressStepper` 仍为空列表 `[]`(与 #8478 相同,未改);四个新字段照常输出(已流团团期为 `NONE`)。
- 库里是枚举外的脏值时:`reviewStatus` / `settlementStatus` 原样输出、中文名回原值;进度条分支按 `NONE` 处理(`WAITING`「待开始」),不报错。
T26-5936 招募中时(17:18 实测,只列相关字段):
```json
{
"code": 200,
"message": "成功",
"data": {
"groupBatchId": "2105223438312652802",
"batchStatus": "RECRUITING",
"batchStatusName": "招募中",
"reviewStatus": "NONE",
"reviewStatusName": "未核单",
"settlementStatus": "NONE",
"settlementStatusName": "未结算",
"progressStepper": [
{"step": 1, "code": "RECRUIT", "name": "招募", "status": "PROCESSING", "label": "招募中", "isCurrent": true, "subFlows": null },
{"step": 2, "code": "CONFIGURE", "name": "配置", "status": "WAITING", "label": null, "isCurrent": false, "subFlows": [
{"code": "HOTEL", "name": "配房", "status": "WAITING", "statusName": "待开始", "displayText": "配房·待开始"},
{"code": "VEHICLE", "name": "配车", "status": "WAITING", "statusName": "待开始", "displayText": "配车·待开始"},
{"code": "GUIDE", "name": "配导游", "status": "WAITING", "statusName": "待开始", "displayText": "配导游·待开始"},
{"code": "PHOTOGRAPHER", "name": "配摄影", "status": "WAITING", "statusName": "待开始", "displayText": "配摄影·待开始"},
{"code": "MATERIAL", "name": "配物资", "status": "WAITING", "statusName": "待开始", "displayText": "配物资·待开始"}
] },
{"step": 3, "code": "CONFIRM", "name": "确认", "status": "WAITING", "label": null, "isCurrent": false, "subFlows": null },
{"step": 4, "code": "TRIP", "name": "出行", "status": "WAITING", "label": null, "isCurrent": false, "subFlows": null },
{"step": 5, "code": "REVIEW", "name": "核单", "status": "WAITING", "label": null, "isCurrent": false, "subFlows": [
{"code": "REVIEW", "name": "核单", "status": "WAITING", "statusName": "待开始", "displayText": "核单·待开始"}
] },
{"step": 6, "code": "SETTLE", "name": "结算", "status": "WAITING", "label": null, "isCurrent": false, "subFlows": [
{"code": "SETTLE", "name": "结算", "status": "WAITING", "statusName": "待开始", "displayText": "结算·待开始"}
] }
]
},
"traceId": null,
"success": true
}
```
#### 错误响应
```json
{
"code": 589500,
"message": "团期不存在",
"data": null,
"traceId": null,
"success": false
}
```
| 错误码 | 触发条件 |
|--------|----------|
| 589500 | 团期不存在(未变) |
| 589507 | 缺 `group-batch:view` 权限码(未变) |
#### 业务边界
- 当前节点(`isCurrent` / 节点 `status` / `label`)**仍按主状态分桶**,不看这两个新字段;两个新字段只决定核单、结算分支的文案。
- 因此「核单已完成、结算未完成」时:核单节点 label 仍是「核单中」,分支是「核单·已核单」;结算节点仍是 `WAITING`,分支显示「结算·待结算 / 结算中」。前端要表达「核单已完成」,请展示分支 `displayText`,不要只看节点 label。
- 进度条只供展示;业务判断仍读 `batchStatus`。
- TEST 实测到的分支组合:
| 团期所处 | 出行节点 label | 核单节点 label | 核单分支 | 结算分支 |
|---|---|---|---|---|
| 招募中 / 出行中 | —(出行中时为「出行中」) | — | 核单·待开始 | 结算·待开始 |
| 待核单 | 待核单 | — | 核单·待核单 | 结算·待开始 |
| 核单中 | — | 核单中 | 核单·核单中 | 结算·待开始 |
| 已核单 + 待结算 | — | 核单中 | 核单·已核单 | 结算·待结算 |
| 已核单 + 结算中 | — | 核单中 | 核单·已核单 | 结算·结算中 |
| 已结算 | — | —(结算节点 DONE + 当前,label「已结算」) | 核单·已核单 | 结算·已结算 |
### 2. A1 团期分页 `GET /v3/admin/order/group-batch`
**VO**: `GroupBatchPageItemRespVO`(入参 `GroupBatchListReqVO`)
#### 使用场景
团期列表页。本次每行新增整团核单 / 结算状态四个字段;`batchStatus` 筛选传旧值 `TRIP_FINISHED` 时按 `PENDING_REVIEW` 查询(改前静默返回空);看板桶筛选 `opsStage=TRIP_FINISHED` 照常可用。
#### 入参
只列本次有变化的入参,其余(productId、keyword、deadlineFrom / To、departFrom / To、month、scope、sortBy、sortOrder 等)不变。
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| batchStatus | Query | String | 否 | 九态之一 | 新值传 `PENDING_REVIEW`;旧值 `TRIP_FINISHED` 按 `PENDING_REVIEW` 处理(兼容用,新代码请传新值)。其他取值规则不变 |
| opsStage | Query | String | 否 | 七桶或旧八桶别名 | `TRIP` 桶展开为 待出发 + 出行中 + 待核单;旧桶名 `TRIP_FINISHED` **保留**,展开为 `PENDING_REVIEW`(它是桶名,不是状态值) |
| pageNo | Query | Integer | 否 | 默认 1 | 未变 |
| pageSize | Query | Integer | 否 | 默认 20 | 未变 |
#### 出参 `Result<PageResult<GroupBatchPageItemRespVO>>`
| 字段 | 类型 | 说明 |
|------|------|------|
| records[].reviewStatus | String | **新增**,同 A2:`NONE` / `PENDING` / `IN_PROGRESS` / `COMPLETED` |
| records[].reviewStatusName | String | **新增**,未核单 / 待核单 / 核单中 / 已核单 |
| records[].settlementStatus | String | **新增**,同 A2:`NONE` / `PENDING` / `IN_PROGRESS` / `COMPLETED` |
| records[].settlementStatusName | String | **新增**,未结算 / 待结算 / 结算中 / 已结算 |
| records[].batchStatus | String | 取值 `TRIP_FINISHED` 改为 `PENDING_REVIEW` |
| records[].batchStatusName | String | 「出行完毕」改为「待核单」 |
| records[].tripSubStatus | String | `TRIP_FINISHED` 改为 `PENDING_REVIEW` |
| records[].tripSubStatusName | String | 「已返团」改为「待核单」 |
| total / page / pageSize | Long / Integer / Integer | 未变 |
#### 请求示例
```http
GET /v3/admin/order/group-batch?batchStatus=TRIP_FINISHED&pageNo=1&pageSize=50 HTTP/1.1
Host: api.test.1814.love
Authorization: Bearer <admin token>
```
无请求体。
#### 响应示例
传旧值 `TRIP_FINISHED`,返回的是两个待核单团期,与传 `PENDING_REVIEW` 结果一致(TEST 实测,只列与本次相关的字段):
```json
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"groupBatchId": "2105223438312652802",
"batchNo": "T26-5936",
"batchName": "呼伦贝尔草原3日游·9月26日团",
"batchStatus": "PENDING_REVIEW",
"batchStatusName": "待核单",
"reviewStatus": "PENDING",
"reviewStatusName": "待核单",
"settlementStatus": "NONE",
"settlementStatusName": "未结算",
"stage": "TRIP",
"stageName": "出行",
"tripSubStatus": "PENDING_REVIEW",
"tripSubStatusName": "待核单",
"opsStage": "TRIP",
"opsStageName": "出行",
"departDate": "2026-09-26",
"endDate": "2026-09-28"
},
{
"groupBatchId": "2105223439872933889",
"batchNo": "T26-2325",
"batchName": "呼伦贝尔草原3日游·9月25日团",
"batchStatus": "PENDING_REVIEW",
"batchStatusName": "待核单",
"reviewStatus": "PENDING",
"reviewStatusName": "待核单",
"settlementStatus": "NONE",
"settlementStatusName": "未结算",
"stage": "TRIP",
"stageName": "出行",
"tripSubStatus": "PENDING_REVIEW",
"tripSubStatusName": "待核单",
"opsStage": "TRIP",
"opsStageName": "出行",
"departDate": "2026-09-25",
"endDate": "2026-09-27"
}
],
"total": 2,
"page": 1,
"pageSize": 50
},
"traceId": null,
"success": true
}
```
#### 空数据 / 降级响应
无匹配时 `records=[]`、`total=0`(未变,下例为结构示意)。已流团团期照常返回,四个新字段为 `NONE` / 未核单 / `NONE` / 未结算(TEST 上 T27-2584 实测):
```json
{
"code": 200,
"message": "成功",
"data": {
"records": [],
"total": 0,
"page": 1,
"pageSize": 20
},
"traceId": null,
"success": true
}
```
#### 错误响应
```json
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"traceId": null,
"success": false
}
```
| 错误码 | 触发条件 |
|--------|----------|
| 589507 | 缺 `group-batch:list` 权限码(未变) |
#### 业务边界
- 入参只兼容旧值,返回值一律输出新值。
- `opsStage` 旧八桶别名(FORMED / PENDING_TRIP / TRAVELLING / TRIP_FINISHED / AUDITING / CHECKED)照常接受;`TRIP_FINISHED` 桶现在就是「待核单」团期。
- 本次**没有**做按 `reviewStatus` / `settlementStatus` 筛选(jw 09-29 定不做),列表只输出这两个字段。
- 团期统计条 `GET /v3/admin/order/group-batch/summary` 的旧桶统计键 `TRIP_FINISHED` 同样保留,计数对象是待核单团期。
### 3. 房务配房列表(团期) `GET /v3/admin/order/house-allocation/group-batches`
**VO**: `HouseAllocationGroupPageRespVO`(入参 `HouseAllocationGroupPageReqVO`,列表项 `HouseAllocationGroupRespVO`)
#### 使用场景
房务配房列表(一行一团),同时承接原房务「我的团」(`scope=mine`,原「我的团」接口已随 #8491 下线)。本次 `batchStatus` 筛选传旧值 `TRIP_FINISHED` 时按 `PENDING_REVIEW` 查询(改前直接返回 400)。
#### 入参
只列本次有变化的入参,其余不变。
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| scope | Query | String | 否 | `all` / `mine`,默认 `all` | 未变;两种范围都享受旧值兼容 |
| batchStatus | Query | String | 否 | 九态之一或空串 | 合法值中 `TRIP_FINISHED` 换成 `PENDING_REVIEW`;传旧值 `TRIP_FINISHED` 先按 `PENDING_REVIEW` 处理再校验,不再 400;其他非法值仍 400 |
#### 出参 `Result<HouseAllocationGroupPageRespVO>`
| 字段 | 类型 | 说明 |
|------|------|------|
| list[].batchStatus | String | 取值 `TRIP_FINISHED` 改为 `PENDING_REVIEW` |
| list[].batchStatusLabel | String | 「出行完毕」改为「待核单」 |
| total / stats | Long / Object | 未变 |
#### 请求示例
```http
GET /v3/admin/order/house-allocation/group-batches?scope=mine&batchStatus=TRIP_FINISHED HTTP/1.1
Host: api.test.1814.love
Authorization: Bearer <admin token>
```
无请求体。
#### 响应示例
传旧值返回房务-赵丽娟整团认领的待核单团期(TEST 实测,只列与本次相关的字段):
```json
{
"code": 200,
"message": "成功",
"data": {
"list": [
{
"groupBatchId": "2105223439872933889",
"batchNo": "T26-2325",
"batchName": "呼伦贝尔草原3日游·9月25日团",
"batchStatus": "PENDING_REVIEW",
"batchStatusLabel": "待核单",
"departDate": "2026-09-25",
"endDate": "2026-09-27",
"houseClaimerName": "房务-赵丽娟",
"isMine": true
}
],
"total": 1,
"stats": { "pendingClaim": 0, "claimed": 1, "all": 1 }
},
"traceId": null,
"success": true
}
```
#### 空数据 / 降级响应
无匹配时 `list=[]`、`total=0`;`stats` 按同一筛选条件计数(未变,下例为结构示意):
```json
{
"code": 200,
"message": "成功",
"data": {
"list": [],
"total": 0,
"stats": { "pendingClaim": 0, "claimed": 0, "all": 0 }
},
"traceId": null,
"success": true
}
```
#### 错误响应
非法状态值仍被拒(TEST 实测):
```json
{
"code": 400,
"message": "batchStatus 不是合法的团期阶段",
"data": null,
"traceId": null,
"success": false
}
```
#### 业务边界
- 只兼容 `TRIP_FINISHED` 这一个旧值;返回值一律输出新值。
- `scope=mine` 与 `scope=all` 的兼容行为一致(均已实测)。
### 4. 房务团期看板列表 `GET /v3/admin/house/group-batches`
**VO**: `HouseGroupBatchBoardSimpleRespVO`(入参 `HouseGroupBatchBoardPageReqVO`)
#### 使用场景
房务团期看板(只显示已认领的团)。本次 `batchStatus` 多选筛选里的旧值 `TRIP_FINISHED` 按 `PENDING_REVIEW` 处理(改前被当成非法值丢弃,整页退回默认筛选)。
#### 入参
只列本次有变化的入参,其余不变。
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| scope | Query | String | 否 | `MINE` / `ALL`,默认 `MINE` | 未变 |
| batchStatus | Query | String | 否 | 逗号分隔多选,最长 200 | 旧值 `TRIP_FINISHED` 按 `PENDING_REVIEW` 处理;`CANCELLED` 与非法值仍忽略;不传时默认四态(资源准备中 / 物料准备中 / 待出发 / 出行中,不含待核单,未变) |
| pageSize | Query | Long | 否 | 1~50,默认 20 | 未变 |
#### 出参 `Result<PageResult<HouseGroupBatchBoardSimpleRespVO>>`
| 字段 | 类型 | 说明 |
|------|------|------|
| records[].batchStatus | String | 取值 `TRIP_FINISHED` 改为 `PENDING_REVIEW` |
| records[].batchStatusText | String | 「出行完毕」改为「待核单」 |
| total / page / pageSize | Long | 未变 |
#### 请求示例
```http
GET /v3/admin/house/group-batches?batchStatus=TRIP_FINISHED HTTP/1.1
Host: api.test.1814.love
Authorization: Bearer <admin token>
```
无请求体。
#### 响应示例
传旧值返回待核单团期,没有退回默认筛选(TEST 实测,只列与本次相关的字段):
```json
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"groupBatchId": "2105223439872933889",
"batchNo": "T26-2325",
"batchName": "呼伦贝尔草原3日游·9月25日团",
"batchStatus": "PENDING_REVIEW",
"batchStatusText": "待核单",
"departDate": "2026-09-25",
"endDate": "2026-09-27",
"claimerName": "房务-赵丽娟",
"boardStatus": "NOT_STARTED"
}
],
"total": 1,
"page": 1,
"pageSize": 20
},
"traceId": null,
"success": true
}
```
#### 空数据 / 降级响应
不传 `batchStatus` 走默认四态,待核单团期不在其中;同一账号此时为空(TEST 实测):
```json
{
"code": 200,
"message": "成功",
"data": {
"records": [],
"total": 0,
"page": 1,
"pageSize": 20
},
"traceId": null,
"success": true
}
```
#### 错误响应
```json
{
"code": 400,
"message": "pageSize 最大 50",
"data": null,
"traceId": null,
"success": false
}
```
#### 业务边界
- 只兼容 `TRIP_FINISHED` 这一个旧值;返回值一律输出新值。
- `scope=ALL` 同样兼容(已实测)。
### 5. 团期状态流水(时间线) `GET /v3/admin/order/group-batch/:groupBatchId/status-logs`
**VO**: `GroupBatchStatusLogItemVO`
#### 使用场景
团期详情页时间线。本次新增两类事件:财务或管理后台入口改动整团核单 / 结算状态时各记一条;主状态值 `TRIP_FINISHED` 改名后,历史行的 `fromStatus` / `toStatus` 也已统一改写。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| groupBatchId | Path | Long | 是 | 团期 ID | 未变;按时间升序返回全部流水,不分页 |
#### 出参 `Result<List<GroupBatchStatusLogItemVO>>`
| 字段 | 类型 | 说明 |
|------|------|------|
| eventType | String | **新增两个取值**:`BATCH_REVIEW_STATUS_CHANGE`「核单状态变更」、`BATCH_SETTLE_STATUS_CHANGE`「结算状态变更」。事件 `BATCH_TRIP_FINISH`「出行完毕」不改名 |
| eventTypeName | String | 核单状态变更 / 结算状态变更 |
| changeType | String | 新事件一般为 `DATA`;核单从核单中退回待核单(主状态 核单中 → 待核单)那一条为 `STATUS` |
| fromStatus / toStatus | String | 取值 `TRIP_FINISHED` 改为 `PENDING_REVIEW`(含历史行) |
| fromStatusName / toStatusName | String | 「出行完毕」改为「待核单」 |
| content | String | 如「核单状态:核单中 → 已核单」「结算状态:已结算 → 结算中」;核单从已核单退回时追加「;结算状态随之置回:结算中 → 未结算」 |
| reason | String | 调用方传入的原因;管理后台入口为验团意见或 null |
| operatorType / operatorId / operatorName | String / Long / String | 财务内部接口写入的行:`SYSTEM`、`null`、财务传入的姓名(如「财务-王丽华」);管理后台入口写入的行为登录管理员 |
| extra | Object | 新事件带 `field` / `from` / `to` / `fromName` / `toName` / `source`,有操作人时带 `operatorName`;核单退回时带 `settlementFrom` / `settlementTo`;有子订单同步时带 `subOrderSyncedCount` / `subOrderSkippedOrderIds`;结算离开已结算、核团被退回时带 `auditReverted: true` |
#### 请求示例
```http
GET /v3/admin/order/group-batch/2105223438312652802/status-logs HTTP/1.1
Host: api.test.1814.love
Authorization: Bearer <admin token>
```
无请求体。
#### 响应示例
T26-5936 时间线中的四条(TEST 实测,节选):
```json
{
"code": 200,
"message": "成功",
"data": [
{
"logId": "2105228170246713346",
"groupBatchId": "2105223438312652802",
"changeType": "STATUS",
"eventType": "BATCH_TRIP_FINISH",
"eventTypeName": "出行完毕",
"fromStatus": "TRAVELLING",
"fromStatusName": "出行中",
"toStatus": "PENDING_REVIEW",
"toStatusName": "待核单",
"content": "系统自动出行完毕",
"reason": null,
"operatorType": "SYSTEM",
"operatorId": null,
"operatorName": "系统",
"extra": null,
"changedAt": "2026-09-30 17:28:04"
},
{
"logId": "2105231057186156546",
"groupBatchId": "2105223438312652802",
"changeType": "STATUS",
"eventType": "BATCH_REVIEW_STATUS_CHANGE",
"eventTypeName": "核单状态变更",
"fromStatus": "REVIEWING",
"fromStatusName": "核单中",
"toStatus": "PENDING_REVIEW",
"toStatusName": "待核单",
"content": "核单状态:核单中 → 待核单",
"reason": "大巴费用票据未到,退回待核单",
"operatorType": "SYSTEM",
"operatorId": null,
"operatorName": "财务-王丽华",
"extra": {
"field": "reviewStatus",
"from": "IN_PROGRESS",
"to": "PENDING",
"fromName": "核单中",
"toName": "待核单",
"operatorName": "财务-王丽华",
"source": "GroupBatchReviewSettleService",
"subOrderSyncedCount": 2,
"subOrderSkippedOrderIds": []
},
"changedAt": "2026-09-30 17:39:32"
},
{
"logId": "2105239217246531585",
"groupBatchId": "2105223438312652802",
"changeType": "DATA",
"eventType": "BATCH_SETTLE_STATUS_CHANGE",
"eventTypeName": "结算状态变更",
"fromStatus": "SETTLED",
"fromStatusName": "已结算",
"toStatus": "SETTLED",
"toStatusName": "已结算",
"content": "结算状态:未结算 → 已结算",
"reason": "报账款已付清,整团结算完成",
"operatorType": "SYSTEM",
"operatorId": null,
"operatorName": "财务-王丽华",
"extra": {
"field": "settlementStatus",
"from": "NONE",
"to": "COMPLETED",
"fromName": "未结算",
"toName": "已结算",
"operatorName": "财务-王丽华",
"source": "GroupBatchReviewSettleService",
"subOrderSyncedCount": 1,
"subOrderSkippedOrderIds": ["2105223438178435074"]
},
"changedAt": "2026-09-30 18:11:58"
},
{
"logId": "2105241608285024259",
"groupBatchId": "2105223438312652802",
"changeType": "DATA",
"eventType": "BATCH_SETTLE_STATUS_CHANGE",
"eventTypeName": "结算状态变更",
"fromStatus": "REVIEWING",
"fromStatusName": "核单中",
"toStatus": "REVIEWING",
"toStatusName": "核单中",
"content": "结算状态:已结算 → 结算中",
"reason": "出纳付款失败需重付,结算改回结算中",
"operatorType": "SYSTEM",
"operatorId": null,
"operatorName": "财务-王丽华",
"extra": {
"field": "settlementStatus",
"from": "COMPLETED",
"to": "IN_PROGRESS",
"fromName": "已结算",
"toName": "结算中",
"operatorName": "财务-王丽华",
"source": "GroupBatchReviewSettleService",
"auditReverted": true,
"subOrderSyncedCount": 2,
"subOrderSkippedOrderIds": []
},
"changedAt": "2026-09-30 18:21:28"
}
],
"traceId": null,
"success": true
}
```
#### 空数据 / 降级响应
团期没有流水时返回空数组(未变):
```json
{
"code": 200,
"message": "成功",
"data": [],
"traceId": null,
"success": true
}
```
#### 错误响应
```json
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"traceId": null,
"success": false
}
```
| 错误码 | 触发条件 |
|--------|----------|
| 589507 | 缺 `group-batch:view` 权限码(未变) |
#### 业务边界
- 主状态随核单 / 结算变化时,除新事件这一行外,另有一条既有事件的主状态流转行:进入核单中记 `BATCH_TRIP_END`「发起核单」,进出已结算记 `BATCH_SETTLE`「结算」;只有「核单中 → 待核单」没有既有事件可用,由新事件那一行直接以 `STATUS` 记录。
- 因此进入核单中时,新事件那一行是 `DATA` 行,`fromStatus` / `toStatus` 都是变化后的主状态(如 `REVIEWING` → `REVIEWING`),前端不要据此判断主状态有没有变。
- 同值重复回写不记流水。
---
## 四、契约约束与正确调用方式
> 本节只写后端接受 / 拒绝的规则,以及字段该怎么读。
### ✅ 正确 / ❌ 错误用法对照
| 场景 | 用法 |
|------|------|
| ✅ 判断团期是否待核单(如「发起核单」按钮) | `batchStatus === 'PENDING_REVIEW'`(与 `reviewStatus === 'PENDING'` 等价) |
| ❌ 仍按旧值判断 | `batchStatus === 'TRIP_FINISHED'` → 永远为 false,按钮消失 |
| ✅ 按待核单筛选列表 | `?batchStatus=PENDING_REVIEW` |
| ⚠️ 旧书签 / 旧代码传 `?batchStatus=TRIP_FINISHED` | 三处入参按 `PENDING_REVIEW` 处理,能查出数据;新代码请改传新值 |
| ✅ 看板页签按旧桶筛选 | `?opsStage=TRIP_FINISHED`(桶名保留)或七桶 `?opsStage=TRIP` |
| ✅ 展示「核单已完成」 | 读 `reviewStatus === 'COMPLETED'` 或进度条核单分支 `displayText` |
| ❌ 用核单节点 label 判断核单是否完成 | 核单已完成、结算未完成时 label 仍是「核单中」 |
| ❌ 用 `settlementStatus` 当逐户付款结清 | 那是财务 tab `items[].settleStatus`,与整团结算状态无关 |
### 切换状态时的必要动作
- 管理后台没有直接改 `reviewStatus` / `settlementStatus` 的入口。整团核单 / 结算状态由财务通过内部接口回写;管理后台既有的「发起核单」「首笔共享成本」「整团结算 `/settle`」「反结算 `/settle/reopen`」会按固定规则改这两个状态(见六)。
- 前端操作后如需刷新状态,重新拉 A2 详情即可,不要在前端自行推导主状态。
---
## 五、数据库行为
- 本文五个接口都是只读接口,不写数据。
- 存量数据已由迁移一次性改写(TEST 迁移 `20260929.8516` 已执行):
- 主状态「出行完毕」统一改为「待核单」,团期时间线历史行、团级核单快照里的流程状态一并改名;
- 两个新状态按主状态回填:待核单 → 核单=待核单;核单中 → 核单=核单中;已结算 → 核单=已核单、结算=已结算;其余团期两者都是 `NONE`。回填可重跑,重跑不产生变化。
- 管理后台写入口的数据变化见六「既有写入口」。
---
## 六、边界行为
- 未登录 → 401(网关拦截,未变);缺权限码 → 589507(未变)。
- 团期不存在 → 589500(未变)。
- 入参传旧值 `TRIP_FINISHED`:A1 分页、房务配房列表、房务团期看板按 `PENDING_REVIEW` 处理;其他任何接口的返回值都不会再出现 `TRIP_FINISHED`。
- 新字段 `reviewStatus` / `settlementStatus` 恒非 null;出行完毕前为 `NONE`。
### 既有写入口:请求 / 响应契约不变,行为变化
以下四个管理后台入口的路径、入参、出参结构、成功返回值**都没有变**,变的是它们对团期核单 / 结算状态与子订单的写入。子订单同步与团期改动同一事务,**任何一步都不推报账单**。
| 入口 | 请求 / 响应 | 行为变化 | TEST 实测 |
|------|-------------|----------|-----------|
| 发起核单 `POST /v3/admin/order/group-batch/:groupBatchId/review/start` | 不变:无请求体,返回 `groupBatchId` / `batchStatus` / `batchStatusDesc` / `alreadyStarted` | 核单改为核单中,团期推导为核单中,核单为待核单的在团户同事务进核单中(替代 #8341 的「整团带入核单中」);核单已是核单中或已核单时返回 `alreadyStarted=true`、零写入,不会把已核单退回;错误码 589564 文案由「须为「出行完毕」」改为「须为「待核单」」,589565 / 589566 不变 | 首次 `alreadyStarted=false`;重复调用、已核单时调用均 `alreadyStarted=true` |
| 首笔共享成本 `POST /v3/admin/order/group-batch/:groupBatchId/settlement/cost` | 不变:返回成本明细 ID | 核单为待核单时改为核单中并同步子订单;第二笔起不再改状态;状态不符仍 589501 | 待核单 → 核单中,两户同步进核单中 |
| 整团结算 `POST /v3/admin/order/group-batch/:groupBatchId/settle` | 不变:请求体 `checkNote` 可空,`data=null` | 核单置已核单(已是则跳过)、结算置已结算 → 团期已结算;待结算的在团户**只改状态**为已结算,**不再逐户推 ORDER 报账单**(停掉 #8341 的逐户财务复核推单);有在团户逐户核单未提交时仍整团 589568 并列出订单号、零写入;589555 / 589567 / 589573 不变 | 从已核单、从核单中两种起点都成功,核团 → 已结算(CHECKED),报账单行数不变;未提交户 589568 |
| 反结算 `POST /v3/admin/order/group-batch/:groupBatchId/settle/reopen` | 不变:无请求体,`data=null` | 结算改为待结算 → 团期核单中;核团从已结算退回已核算;已结算的在团户退回待结算,已推的报账单不撤;非已结算仍 589501 | 结算 → 待结算,两户退回待结算,之后重新核算、再结算均可用 |
- 四个入口在极端并发下可能多出一个兜底码 589703「团期核单或结算状态已被他人修改,请刷新后重试」(内部已先加团期行锁,正常操作不会出现),前端透传 message 即可。
- 团级核单定稿 `POST /v3/admin/order/group-batch/:groupBatchId/settlement/finalize` 的 584138 文案「需出行完毕或核单中」改为「需待核单或核单中」,码与触发条件不变。
## 六.5、枚举 / 数据字典
### batchStatus(`com.hulalv.order.groupbatch.enums.GroupBatchStatus`)
**所属字段**: `GroupBatchDetailRespVO.batchStatus`、`GroupBatchPageItemRespVO.batchStatus` 等所有团期主状态字段 | **类型**: `String`
| 值 | 中文 | 说明 |
|----|------|------|
| `RECRUITING` | 招募中 | 未变 |
| `RESOURCE_PREPARING` | 资源准备中 | 未变 |
| `MATERIAL_PREPARING` | 物料准备中 | 未变 |
| `PENDING_DEPARTURE` | 待出发 | 未变 |
| `TRAVELLING` | 出行中 | 未变 |
| `PENDING_REVIEW` | 待核单 | **原 `TRIP_FINISHED`「出行完毕」**。返团日已过、尚未开始核单;等价于 `reviewStatus=PENDING` |
| `REVIEWING` | 核单中 | 未变;`reviewStatus` 为核单中,或已核单但结算未到已结算 |
| `SETTLED` | 已结算 | 未变;`reviewStatus` 与 `settlementStatus` 都已完成 |
| `CANCELLED` | 已取消 | 未变(已流团) |
### tripSubStatus(`GroupBatchStageBuckets.TripSubStatus`)
**所属字段**: `GroupBatchDetailRespVO.tripSubStatus`、`GroupBatchPageItemRespVO.tripSubStatus` | **类型**: `String`
| 值 | 中文 | 说明 |
|----|------|------|
| `PENDING_DEPARTURE` | 待出发 | 未变 |
| `TRAVELLING` | 出行中 | 未变 |
| `PENDING_REVIEW` | 待核单 | **原 `TRIP_FINISHED`「已返团」** |
### reviewStatus(`com.hulalv.order.settlement.enums.ReviewStatus`,与子订单核单状态同一枚举)
**所属字段**: `GroupBatchDetailRespVO.reviewStatus`、`GroupBatchPageItemRespVO.reviewStatus` | **类型**: `String`
| 值 | 中文 | 说明 |
|----|------|------|
| `NONE` | 未核单 | 还没出行完毕 |
| `PENDING` | 待核单 | 出行完毕后自动进入 |
| `IN_PROGRESS` | 核单中 | 财务开始核单,或管理后台发起核单 / 首笔共享成本 |
| `COMPLETED` | 已核单 | 财务完成核单,或管理后台整团结算 |
### settlementStatus(`com.hulalv.order.groupbatch.enums.GroupBatchSettlementStatus`)
**所属字段**: `GroupBatchDetailRespVO.settlementStatus`、`GroupBatchPageItemRespVO.settlementStatus` | **类型**: `String`
| 值 | 中文 | 说明 |
|----|------|------|
| `NONE` | 未结算 | 核单完成之前恒为此值 |
| `PENDING` | 待结算 | 核单已完成、尚未开始结算。同一个值在子订单上叫「待财务复核」 |
| `IN_PROGRESS` | 结算中 | 团期独有,子订单没有这一态;含义由财务定义 |
| `COMPLETED` | 已结算 | 团期主状态随之为已结算 |
### 进度条核单 / 结算分支 status(`GroupBatchProgressSubFlowVO.status`)
**所属字段**: `progressStepper[].subFlows[].status`(仅 code 为 `REVIEW` / `SETTLE` 的分支) | **类型**: `String`
| 值 | 中文(statusName) | 说明 |
|----|------|------|
| `WAITING` | 待开始 | 对应字段为 `NONE`(或脏值) |
| `PENDING` | 待核单 / 待结算 | 对应字段为 `PENDING` |
| `IN_PROGRESS` | 核单中 / 结算中 | 对应字段为 `IN_PROGRESS` |
| `COMPLETED` | 已核单 / 已结算 | 对应字段为 `COMPLETED` |
### 时间线新增 eventType(`com.hulalv.order.groupbatch.enums.GroupBatchLogEventType`)
**所属字段**: `GroupBatchStatusLogItemVO.eventType` | **类型**: `String`
| 值 | 中文 | 说明 |
|----|------|------|
| `BATCH_REVIEW_STATUS_CHANGE` | 核单状态变更 | 整团核单状态每次真的变化记一条 |
| `BATCH_SETTLE_STATUS_CHANGE` | 结算状态变更 | 整团结算状态每次真的变化记一条 |
## 六.6、修改前后对比
### 字段级对比
| 字段 | 改前 | 改后 |
|------|------|------|
| `batchStatus`(所有返回团期主状态的接口) | 可能为 `TRIP_FINISHED`「出行完毕」 | 该值改为 `PENDING_REVIEW`「待核单」,`TRIP_FINISHED` 不再出现 |
| `tripSubStatus` / `tripSubStatusName` | `TRIP_FINISHED` / 已返团 | `PENDING_REVIEW` / 待核单 |
| `progressStepper` 出行节点 label(待核单团期) | 已返团 | 待核单 |
| A2 / A1 `reviewStatus` / `reviewStatusName` | 无 | 新增 |
| A2 / A1 `settlementStatus` / `settlementStatusName` | 无 | 新增 |
| A2 `progressStepper` REVIEW / SETTLE 节点 `subFlows` | `null` | 各 1 条分支 |
| 时间线 `eventType` | 无核单 / 结算状态事件 | 新增 `BATCH_REVIEW_STATUS_CHANGE` / `BATCH_SETTLE_STATUS_CHANGE` |
| 时间线历史行 `fromStatus` / `toStatus` | 可能为 `TRIP_FINISHED` | 已改写为 `PENDING_REVIEW` |
### 行为级对比
| 行为 | 改前 | 改后 |
|------|------|------|
| A1 分页 `?batchStatus=TRIP_FINISHED` | 静默返回空 | 返回待核单团期 |
| 房务配房列表 `?batchStatus=TRIP_FINISHED`(含 `scope=mine`) | 400「batchStatus 不是合法的团期阶段」 | 返回待核单团期 |
| 房务团期看板 `?batchStatus=TRIP_FINISHED` | 当非法值丢弃,退回默认四态 | 返回待核单团期 |
| `?opsStage=TRIP_FINISHED` | 出行完毕团期 | 待核单团期(桶名保留) |
| 团期主状态「待核单 / 核单中 / 已结算」 | 各入口直接推进主状态 | 由整团核单、结算两个状态推导 |
| `/settle` | 逐户财务复核并推 ORDER 报账单 | 子订单只改状态为已结算,不推报账单 |
| `/settle/reopen` | 本入口自己退核团 | 核团退回收进统一写口,本入口与财务内部接口行为一致 |
| 发起核单 589564 文案 | 须为「出行完毕」 | 须为「待核单」 |
## 六.7、影响评估
- **是否破坏向后兼容**: 是。`batchStatus` / `tripSubStatus` 的 `TRIP_FINISHED` 取值改名,按旧值判断的前端代码会静默失效。
- **前端是否必须同步发布**: 是。jw 09-30 定:TEST 先行(后端 09-30 16:31 已部署到 TEST,hl-ui 本次未改),正式环境前后端同批发布。
- **前端必须改:按状态值做判断的代码**(hl-ui `origin/v2.1` 只读核对,行号以核对时为准):
- `order-v2/batch/detail/index.vue:832` `canStartReview`:改为判 `'PENDING_REVIEW'`,不改「发起核单」按钮会消失;
- `finance/settlement/components/GroupSettlementPanel.vue:281`:「完成核单」可点条件;
- `order-v2/batch/detail/components/FinanceTab.vue:309`:预支可发起的阶段;
- `order-v2/batch/detail/components/GroupVehicleRequirementSection.vue:399`:免车声明可用的阶段;
- `order-v2/detail/_shared/orderDetailActions.js:24`、`requirementFreeze.js:16`:状态集合;
- `order-v2/batch/_shared/batchLifecycle.js:53`:状态到节点的映射。
- **前端必须改:显示用的映射表**:`GroupSettlementPanel.vue:260`、`housekeeper/orders/GroupBatchTable.vue:49`、`housekeeper/room-board/components/boardLabels.js:50`(`PENDING_REVIEW` → 待核单)。
- **前端建议改**:团期详情 / 列表展示 `reviewStatusName` / `settlementStatusName`;进度条核单、结算节点渲染新分支(写法与配置节点五条分支相同)。
- **前端不用改**:`opsStage=TRIP_FINISHED`(旧桶名,后端保留);`NO_VEHICLE_TRIP_FINISHED_CODE`(车队错误码常量,与团期状态无关)。
- **其他返回团期主状态的接口**(团期看板 `/board`、团期统计 `/summary`、房务看板详情、车务派单相关读口、核团详情 `return-detail` 的 `flowStatus` 等):字段名与结构不变,取值同样由 `TRIP_FINISHED` 变为 `PENDING_REVIEW`、中文名变为「待核单」;统计键 `TRIP_FINISHED` 保留。
- **BI / 报表 / 外部取数**:如按 `'TRIP_FINISHED'` 取数会取不到,需要改为 `PENDING_REVIEW`(代码仓 grep 不到这类依赖,无法替使用方确认)。
- **前端 workaround 清理点**: 无。
- **回滚**:先执行后端回滚 SQL 把存量值改回,再回退代码;前端须一起回退。
## 七、不影响范围
- **仅影响**:团期主状态「出行完毕」这一个取值的名称与中文名;团期详情 / 分页的四个新字段;详情进度条核单、结算分支;时间线两类新事件;三处入参旧值兼容;四个既有写入口对状态与子订单的写入方式。
- **零影响**:
- 其余八个团期主状态取值、六节点 `stage` 取值、`opsStage` 七桶与旧桶名;
- 进度条配置节点五条分支、六个主节点的当前节点判定规则;
- 团期状态筛选以外的所有入参;
- 团级核单定稿 / 确认、逐户核单提交、逐户财务复核确认、逐户反确认的接口与行为(对团期子订单不加限制);
- 时间线事件「出行完毕」`BATCH_TRIP_FINISH` 的名称;
- 网关:路径未变,无新增路由与权限码。
---
## 八、测试环境已验证
2026-09-30 TEST(`api.test.1814.love`):合并提交 `54e64c50f`,部署构建 dev-v3 `dd0452916`(order-v3 双实例 8086 / 8186),迁移 `20260929.8516` 于 16:32:13 执行成功。验收团期为本次新建:T26-5936 呼伦贝尔草原3日游·9月26日团、T26-2325 呼伦贝尔草原3日游·9月25日团。证据目录 `HL/.evidence/8516/`。
```text
AC-03 迁移:两列存在;三处存量 TRIP_FINISHED 均为 0 行,时间线 38 行改名为 PENDING_REVIEW;回填重跑零变化 ✓
AC-09 发起核单首次 alreadyStarted=false、重复与已核单时 true;首笔成本 待核单→核单中并同步;/settle 两种起点均 SETTLED、报账单行数不变;未提交户 589568;/settle/reopen 结算→待结算、户退回 ✓
AC-10 GET /v3/admin/order/group-batch/:groupBatchId 与分页返回四个新字段;核单分支实测 待开始/待核单/核单中/已核单,结算分支实测 待开始/待结算/结算中/已结算;出行节点 label 与 tripSubStatusName 为「待核单」 ✓
AC-11 分页 batchStatus=TRIP_FINISHED 与 PENDING_REVIEW 结果一致(2 条,不筛选 27 条);房务配房列表 scope=mine/all 只返回待核单团、非法值仍 400;房务看板传旧值返回待核单团、未退回默认筛选;opsStage=TRIP_FINISHED 返回 2 条 ✓
AC-12 GET /v3/admin/order/group-batch/:groupBatchId/status-logs 可见「核单状态变更」「结算状态变更」,操作人与原因正确 ✓
```
| AC | 证据 |
|----|------|
| AC-09 | `HL/.evidence/8516/AC-09/` |
| AC-10 | `HL/.evidence/8516/AC-10/` |
| AC-11 | `HL/.evidence/8516/AC-11/01-legacy-TRIP_FINISHED.json`、`02-discriminators.json` |
| AC-12 | `HL/.evidence/8516/AC-12/01-status-logs.json` |
单元测试:进度条 `GroupBatchProgressStepperTest`、分桶 `GroupBatchStageBucketsTest`、转换 `GroupBatchConverterTest`、看板入参 `HouseGroupBatchBoardManagerTest`、迁移 `GroupBatchReviewSettlementStatusMysqlMigrationTest` 等;order-v3 全量两半对照干净 dev-v3 基线,本单新增失败 0。
---
## 九、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|----|-------|------|------------|
| — | #7190 | 团期状态新增出行完毕 `TRIP_FINISHED`、看板八桶 | ⚠️ 状态值已改名 `PENDING_REVIEW`,旧桶名保留 |
| — | #7527 | 团期发起核单端点 | ✅ 有效,改为写整团核单状态 |
| — | #8341 | 团期核单 / 结算 / 反结算同步子订单,结算即整团财务复核并推报账单 | ⚠️ 部分被本单取代:同步规则按本单,`/settle` 不再推报账单;589568 门禁保留 |
| — | #8478 | 团期详情分叉进度条 | ✅ 有效,本单为核单、结算节点加分支 |
| **#8650** | **#8516** | 整团核单 / 结算独立状态,「出行完毕」改名「待核单」 | ✅ 最新 |
---
## 十、相关文档
- 关联 Issue: [wx/HL#8516](https://git.1814.love/wx/HL/issues/8516)
- 关联 PR: [wx/HL#8650](https://git.1814.love/wx/HL/pulls/8650)(正文含前端影响说明)
- 状态机文档:`docs/group/实施单/16-团期生命周期与状态机.html`(随 PR #8650 同步,提交 `30ed15777`);接口文档 `docs/group/团期模块接口文档-v2.0.html`
- 财务内部回写接口:`changelogs-v2/2026-09/30_8516_团期核单与结算状态财务内部回写接口-新增接口-管理后台.md`
## 关联 / 联系人
### 链接
- **Issue**: [#8516](https://git.1814.love/wx/HL/issues/8516)
- **PR**: [#8650](https://git.1814.love/wx/HL/pulls/8650)
- **Merge commit**: [54e64c50f](https://git.1814.love/wx/HL/commit/54e64c50f)
### 联系人
- **后端负责人**: @jw