--- 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` 只列本次新增或取值有变化的字段。 | 字段 | 类型 | 说明 | |------|------|------| | 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\ | **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 ``` 无请求体。 #### 响应示例 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>` | 字段 | 类型 | 说明 | |------|------|------| | 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 ``` 无请求体。 #### 响应示例 传旧值 `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` | 字段 | 类型 | 说明 | |------|------|------| | 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 ``` 无请求体。 #### 响应示例 传旧值返回房务-赵丽娟整团认领的待核单团期(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>` | 字段 | 类型 | 说明 | |------|------|------| | 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 ``` 无请求体。 #### 响应示例 传旧值返回待核单团期,没有退回默认筛选(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>` | 字段 | 类型 | 说明 | |------|------|------| | 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 ``` 无请求体。 #### 响应示例 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