diff --git a/changelogs-v2/2026-09/27_8418_团期名单补子订单流程核单结算三对状态-修改接口-管理后台.md b/changelogs-v2/2026-09/27_8418_团期名单补子订单流程核单结算三对状态-修改接口-管理后台.md new file mode 100644 index 00000000..be48bfda --- /dev/null +++ b/changelogs-v2/2026-09/27_8418_团期名单补子订单流程核单结算三对状态-修改接口-管理后台.md @@ -0,0 +1,547 @@ +--- +schema: "hl-changelog/v2" +ticket: "8418" +title: "团期名单 GB-ADM-003 逐户纯增流程 / 核单 / 结算三对状态字段:flowStatus / reviewStatus / settlementStatus 及各自中文名" +consumer: "admin" +author: "jw(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "PR #8420 已合并 dev-v3(58da1df2a),已部署 TEST 并经网关验收 AC-1~AC-9 全部通过。GET /v3/admin/order/group-batch/{groupBatchId}/orders 的 records[] 每户纯增 6 个只读字段:flowStatus / flowStatusName、reviewStatus / reviewStatusName、settlementStatus / settlementStatusName;入参、判权、分页、排序与既有字段全部不变,零 DDL、零写入。前端需:名单「状态」列改用 flowStatusName(原型里的 processStatus 就是它,后端从未提供过 processStatus);需要单独展示核单 / 结算进度时用 reviewStatusName / settlementStatusName。注意 reviewStatus / settlementStatus 与团期核单 GroupSettlementRespVO(#8361)同名字段含义相反,与财务 tab 的 items[].settleStatus 也不是一回事。" +updated_at: "2026-09-27" +base: "dev-v3" +--- + +# 团期名单: GB-ADM-003 逐户补流程 / 核单 / 结算三对状态(管理后台) + +> **存放目录**: 二期(v3) → `changelogs-v2/2026-09/` +> +> **服务**: hl-order-service-v3 +> **PR**: #8420 +> **Issue**: #8418 +> **日期**: 2026-09-27 +> **影响范围**: 管理后台团期详情「子订单」tab 名单的逐户状态列 + +--- + +## ⚠️ 关键变化 + +1. **纯增 6 个响应字段,既有字段一个不动**:`records[]` 每户新增 `flowStatus` / `flowStatusName`(流程细状态)、`reviewStatus` / `reviewStatusName`(逐户核单)、`settlementStatus` / `settlementStatusName`(逐户结算,即财务复核)。 +2. **同名不同义,别拿错**:本名单的 `reviewStatus` 是**逐户核单**、`settlementStatus` 是**逐户结算**;团期核单接口 `GroupSettlementRespVO`(#8361)里同名的 `reviewStatus` 是**团级复核**、`settlementStatus` 是**团级核单**,含义正好相反,而且那边是一团一行。 +3. **不是尾款结清**:财务 tab(GB-ADM-040)的 `items[].settleStatus`(已结清 / 待收尾款 / 已退团)表示尾款收没收齐,和本名单的 `settlementStatus` 无关。 +4. **旧版接口文档里的 `processStatus` 从未实现**,接口文档 GB-ADM-003 已改为 `flowStatus` / `flowStatusName`,按原型做「状态」列请读 `flowStatusName`。 + +--- + +## 一、背景 + +团期进入核单以后,运营在团期详情「子订单」tab 里看不出每户走到了核单 / 结算的哪一步,只能逐户点进订单详情看。#8340 / #8341 已让子订单的流程、核单、结算三列跟随团期动作同步写入,本单把这三列连同中文名原样透出到名单上。本单**只读透出**,不改任何写入与流转。 + +三列由下列动作写入(前端理解状态来源用,本单不改): + +| 动作 | flowStatus | reviewStatus | settlementStatus | 来源 | +|---|---|---|---|---| +| 团期出行完毕 | `PENDING_REVIEW` 待核单 | `PENDING` 待核算 | 不写 | #8340 | +| 团期发起核单 | `REVIEWING` 核单中 | `IN_PROGRESS` 核算中 | 不写 | #8341 | +| 逐户核单提交(定稿) | `PENDING_SETTLE` 待结算 | `COMPLETED` 已完成 | `PENDING` 待财务复核 | 既有 | +| 团期结算 `/settle` | `SETTLED` 已结算 | `COMPLETED` 已完成 | `COMPLETED` 已结算 | #8341 | +| 团期反结算 `/settle/reopen` | `PENDING_SETTLE` 待结算 | `COMPLETED` 已完成 | `PENDING` 待财务复核 | #8341 | + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 团期下子订单列表(GB-ADM-003 名单) | GET | `/v3/admin/order/group-batch/{groupBatchId}/orders` | 出参新增字段 | `records[]` 每户纯增 6 个字段,入参与既有字段不变 | + +网关无改动;无新增权限码;无新增错误码;无 DB schema 变更。 + +--- + +## 三、接口详情 + +### 1. 团期下子订单列表(GB-ADM-003 名单) `GET /v3/admin/order/group-batch/{groupBatchId}/orders` + +**VO**: `PageResult` + +#### 使用场景 + +管理后台团期详情「子订单」tab 加载名单时调用,一户一行。本次起每行多带流程细状态、逐户核单、逐户结算三对「码 + 中文名」,名单「状态」列与核单 / 结算进度不必再逐户进订单详情查。 + +#### 入参 + +本单不变。 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期须存在 | 团期 ID | +| page | Query | Integer | 否 | 缺省 1;<1 归一为 1 | 页码,从 1 起 | +| pageSize | Query | Integer | 否 | 缺省 20;<1 归一为 20;>200 截断为 200 | 每页条数 | +| includeTravelers | Query | Boolean | 否 | 缺省 true | 是否附出行人明细(证件号 / 手机号一律不返回) | +| includeNeeds | Query | Boolean | 否 | 缺省 true | 是否附房数 / 房型 / 特殊需求 | +| includeCancelled | Query | Boolean | 否 | 缺省 false | 是否含已取消子订单(缺省只返在团户) | + +#### 出参 `Result>` + +分页信封: + +| 字段 | 类型 | 说明 | +|------|------|------| +| records | Array\ | 本页子订单,一户一行(字段见下表) | +| total | Integer | 符合条件的子订单总数 | +| page | Integer | 当前页码 | +| pageSize | Integer | 每页条数 | + +`records[]` 单行(**加粗为本次新增**,其余不变): + +| 字段 | 类型 | 说明 | +|------|------|------| +| orderId | String(Long) | 子订单 ID | +| orderNo | String | 订单编号 | +| teamNo | String | 团号(订金支付成功后生成;未付订金为 null) | +| customerName | String | 客户姓名 | +| participantCount | Integer | 出行人总数 | +| orderStatus | String | 订单状态码 | +| orderStatusName | String | 订单状态中文名 | +| **flowStatus** | String | **新增**。流程细状态码,`order_main.flow_status` 原值,与订单详情 `main.flowStatus` 同值;`OrderFlowStatus` 12 值,见六.5 | +| **flowStatusName** | String | **新增**。流程细状态中文名,与订单详情 `GET /v3/admin/order/{id}` 的 `main.flowStatusName` 同规则:`AWAITING_PAY` 显示「待补全信息」,其余取枚举中文名;码为 null 时为 null;未知码回落原码 | +| **reviewStatus** | String | **新增**。逐户核单状态码,`order_main.review_status`:`NONE` / `PENDING` / `IN_PROGRESS` / `COMPLETED`;出行前为 null | +| **reviewStatusName** | String | **新增**。逐户核单状态中文名,与订单详情 `main.reviewStatusName` 同规则:`NONE`、`PENDING` →「待核算」,`IN_PROGRESS` →「核算中」,`COMPLETED` →「已完成」;码为 null 时为 null(不折叠成「待核算」);未知码回落原码 | +| **settlementStatus** | String | **新增**。逐户结算状态码(财务复核),`order_main.settlement_status`:`NONE` / `PENDING` / `COMPLETED`,列默认 `NONE` | +| **settlementStatusName** | String | **新增**。逐户结算状态中文名:未结算 / 待财务复核 / 已结算;码为 null 时为 null;未知码回落原码 | +| payStatus | String | 支付状态 `UNPAID` / `DEPOSIT_PAID` / `FULLY_PAID` | +| payStatusName | String | 支付状态中文名 | +| contractStatus | String | 合同状态(无合同为 null) | +| contractStatusName | String | 合同状态中文名(无合同为 null) | +| insuranceStatus | String | 保险状态(无保险为 null) | +| insuranceStatusName | String | 保险状态中文名(无保险为 null) | +| paidAmount | String(BigDecimal) | 已支付金额 | +| balanceAmount | String(BigDecimal) | 待支付尾款金额(≥0) | +| hotelRequirementStatus | String | 房需求状态(无有效需求行为 null) | +| hotelRequirementStatusName | String | 房需求状态中文名 | +| vehicleRequirementStatus | String | 行程用车需求状态(无有效需求行为 null) | +| vehicleRequirementStatusName | String | 行程用车需求状态中文名 | +| consultantName | String | 定制师姓名 | +| totalPrice | String(BigDecimal) | 本户应收(取消单为 `"0.00"`) | +| tierCode | String | 档位码,如 `2A1C` | +| tierName | String | 档位名,如「2成人1儿童」 | +| travelerInfoComplete | Boolean | 出行人资料是否齐全 | +| roomCount | Integer | 房数(`includeNeeds=true` 时返回) | +| roomType | String | 房型原值(`includeNeeds=true` 时返回) | +| roomTypeName | String | 房型中文名 | +| specialNeeds | String | 特殊需求(`includeNeeds=true` 时返回) | +| contactPhone | String | 联系人手机号(脱敏,前 3 后 4) | +| groupChatUnreadCount | Integer | 「联系定制师」团队共享未读数(取不到时为 0) | +| travelers | Array\ | 出行人明细(`includeTravelers=true` 时返回):`name` / `type` / `age` / `birthdayInTrip` | + +#### 请求示例 + +无请求体。 + +```http +GET /v3/admin/order/group-batch/2102000000000000001/orders?page=1&pageSize=20 HTTP/1.1 +Host: api.test.1814.love +Authorization: Bearer +``` + +#### 响应示例 + +> 字段结构示意,ID、金额、姓名为示例值。三户分别处于:待结算(核单已提交)、核单中、出行前。 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "records": [ + { + "orderId": "2102000000000000101", + "orderNo": "HL20260910100000001", + "teamNo": "26-0101", + "customerName": "王先生家庭", + "participantCount": 3, + "orderStatus": "COMPLETED", + "orderStatusName": "已完成", + "flowStatus": "PENDING_SETTLE", + "flowStatusName": "待结算", + "reviewStatus": "COMPLETED", + "reviewStatusName": "已完成", + "settlementStatus": "PENDING", + "settlementStatusName": "待财务复核", + "payStatus": "FULLY_PAID", + "payStatusName": "已付全款", + "contractStatus": "SIGNED", + "contractStatusName": "已签署", + "insuranceStatus": "INSURED", + "insuranceStatusName": "已投保", + "paidAmount": "12000.00", + "balanceAmount": "0.00", + "hotelRequirementStatus": "DONE", + "hotelRequirementStatusName": "配房完成", + "vehicleRequirementStatus": "DONE", + "vehicleRequirementStatusName": "配车完成", + "consultantName": "张三", + "totalPrice": "12000.00", + "tierCode": "2A1C", + "tierName": "2成人1儿童", + "travelerInfoComplete": true, + "roomCount": 2, + "roomType": "家庭房", + "roomTypeName": "家庭房", + "specialNeeds": null, + "contactPhone": "138****8000", + "groupChatUnreadCount": 0, + "travelers": [ + { "name": "王大明", "type": "ADULT", "age": 38, "birthdayInTrip": false }, + { "name": "李小红", "type": "ADULT", "age": 36, "birthdayInTrip": false }, + { "name": "王小明", "type": "CHILD", "age": 6, "birthdayInTrip": false } + ] + }, + { + "orderId": "2102000000000000102", + "orderNo": "HL20260910100000002", + "teamNo": "26-0102", + "customerName": "刘女士", + "participantCount": 2, + "orderStatus": "COMPLETED", + "orderStatusName": "已完成", + "flowStatus": "REVIEWING", + "flowStatusName": "核单中", + "reviewStatus": "IN_PROGRESS", + "reviewStatusName": "核算中", + "settlementStatus": "NONE", + "settlementStatusName": "未结算", + "payStatus": "FULLY_PAID", + "payStatusName": "已付全款", + "contractStatus": "SIGNED", + "contractStatusName": "已签署", + "insuranceStatus": "INSURED", + "insuranceStatusName": "已投保", + "paidAmount": "8000.00", + "balanceAmount": "0.00", + "hotelRequirementStatus": "DONE", + "hotelRequirementStatusName": "配房完成", + "vehicleRequirementStatus": "DONE", + "vehicleRequirementStatusName": "配车完成", + "consultantName": "张三", + "totalPrice": "8000.00", + "tierCode": "2A", + "tierName": "2成人", + "travelerInfoComplete": true, + "roomCount": 1, + "roomType": "大床房", + "roomTypeName": "大床房", + "specialNeeds": null, + "contactPhone": "139****1234", + "groupChatUnreadCount": 0, + "travelers": [ + { "name": "刘芳", "type": "ADULT", "age": 45, "birthdayInTrip": false }, + { "name": "陈刚", "type": "ADULT", "age": 47, "birthdayInTrip": true } + ] + }, + { + "orderId": "2102000000000000103", + "orderNo": "HL20260910100000003", + "teamNo": "26-0103", + "customerName": "赵先生", + "participantCount": 1, + "orderStatus": "PENDING_DEPARTURE", + "orderStatusName": "待出行", + "flowStatus": "PENDING_DEPARTURE", + "flowStatusName": "待出行", + "reviewStatus": null, + "reviewStatusName": null, + "settlementStatus": "NONE", + "settlementStatusName": "未结算", + "payStatus": "DEPOSIT_PAID", + "payStatusName": "已付定金", + "contractStatus": "SIGNED", + "contractStatusName": "已签署", + "insuranceStatus": "INSURED", + "insuranceStatusName": "已投保", + "paidAmount": "1500.00", + "balanceAmount": "3500.00", + "hotelRequirementStatus": "DONE", + "hotelRequirementStatusName": "配房完成", + "vehicleRequirementStatus": "DONE", + "vehicleRequirementStatusName": "配车完成", + "consultantName": "李四", + "totalPrice": "5000.00", + "tierCode": "1A", + "tierName": "1成人", + "travelerInfoComplete": true, + "roomCount": 1, + "roomType": "标间", + "roomTypeName": "标间", + "specialNeeds": "需要无烟房", + "contactPhone": "137****5678", + "groupChatUnreadCount": 1, + "travelers": [ + { "name": "赵磊", "type": "ADULT", "age": 29, "birthdayInTrip": false } + ] + } + ], + "total": 3, + "page": 1, + "pageSize": 20 + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +团期下没有子订单(或页码超出末页)时 `records` 为空数组,`total` 为真实总数;本接口新增字段无远程调用,无降级分支。 + +```json +{ + "code": 200, + "message": "成功", + "data": { "records": [], "total": 0, "page": 1, "pageSize": 20 }, + "success": true +} +``` + +三列为 null 的户(如出行前的 `reviewStatus`),码与中文名都为 null: + +```json +{ "reviewStatus": null, "reviewStatusName": null } +``` + +#### 错误响应 + +团期不存在(既有,不变): + +```json +{ + "code": 589500, + "message": "团期不存在", + "success": false, + "data": null +} +``` + +当前角色未授予 `group-batch:view`,或定制师读取不在本人名下的团期(既有,不变): + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 判权不变:需 `group-batch:view`;定制师(CUSTOMIZER)另需该团下有本人名下的在团子订单(#7949),否则 589507。判定顺序为权限码 → 定制师归属 → 团期存在(589500)。 +- 分页、排序、既有字段、`includeTravelers` / `includeNeeds` / `includeCancelled` 语义全部不变;`page` 超出末页返回空 `records`,`total` 仍为真实总数。 +- 6 个新字段逐户照实读取、只读透出,本接口不写任何状态;`includeCancelled=true` 时已取消户同样照实返回其三列。 +- `*Name` 规则:码为 null 时中文名也为 null;遇到枚举外的未知码时中文名回落为原码,不报错。 +- `reviewStatus` 出行前为 null;`settlementStatus` 列默认 `NONE`。 +- 走 #8361 团核单(finalize / confirm)结算的团,**不回写**这三列,名单照实返回逐户值,可能显示「核算中 / 未结算」;两套口径的收敛归 Epic #8361。 +- #8341(2026-09-24)之前就已进入核单的存量团没有回填,这些户的三列可能仍为 null / `NONE`。 + +--- + +## 四、契约约束与正确调用方式 + +> 本接口是只读 GET,入参规则不变;本节只说明新字段该怎么取、别和哪些同名字段混用。 + +### ✅ 正确 / ❌ 错误取值对照 + +| 场景 | 取值 | +|------|------| +| ✅ 名单「状态」列(原型里的 `processStatus`) | 读 `flowStatusName`;判定逻辑用 `flowStatus` | +| ✅ 单独展示逐户核单进度 | 读 `reviewStatusName`;判定用 `reviewStatus` | +| ✅ 单独展示逐户结算(财务复核)进度 | 读 `settlementStatusName`;判定用 `settlementStatus` | +| ❌ 按旧版接口文档读 `processStatus` | 该字段从未实现,恒不存在;接口文档 GB-ADM-003 已改为 `flowStatus` / `flowStatusName` | +| ❌ 用中文名做判定 | 中文名只用于展示,判定一律用码 | +| ❌ 前端自建码 → 中文映射 | 直接显示后端下发的 `*Name`(后端与订单详情同规则) | +| ❌ 把 null 渲染成「待核算」 | `reviewStatus` 为 null 表示尚未进入核单,后端不折叠,前端也不要折叠 | + +### 同名 / 近名字段对照(易混点) + +| 出处 | 字段 | 粒度 | 含义 | 取值 | +|------|------|------|------|------| +| **本名单** GB-ADM-003 `records[]` | `reviewStatus` | 逐户 | 逐户**核单** | `NONE` / `PENDING` / `IN_PROGRESS` / `COMPLETED` | +| **本名单** GB-ADM-003 `records[]` | `settlementStatus` | 逐户 | 逐户**结算**(财务复核) | `NONE` / `PENDING` / `COMPLETED` | +| **本名单** GB-ADM-003 `records[]` | `flowStatus` | 逐户 | 订单流程细状态 | `OrderFlowStatus` 12 值 | +| 团期核单 `GroupSettlementRespVO`(#8361,`GET /v3/admin/order/group-batch/{groupBatchId}/settlement/reports/group` 等) | `reviewStatus` | 团级一行 | 团级**复核** | `PENDING` / `APPROVED` / `RETURNED` | +| 团期核单 `GroupSettlementRespVO`(#8361) | `settlementStatus` | 团级一行 | 团级**核单** | `PENDING` / `FINALIZED` / `SETTLED` | +| 团期核单 `GroupSettlementRespVO`(#8361) | `flowStatus` | 团级一行 | 团级流程快照 | `TRIP_FINISHED` / `REVIEWING` / `SETTLED` | +| 财务 tab GB-ADM-040 `GET /v3/admin/order/group-batch/{groupBatchId}/finance` | `items[].settleStatus` | 逐户 | 尾款是否收齐(实时派生) | 已结清 / 待收尾款 / 已退团 | + +结论:本名单的 `reviewStatus` / `settlementStatus` 与 #8361 同名字段**含义相反**,与 GB-ADM-040 的 `settleStatus` **不是一回事**,三处不可互相替代、不可交叉比对。 + +### 两套结算口径并存 + +- 走团期结算 `/settle`(#8341)的团:三列随团期动作同步,名单能看到「已结算」。 +- 走 #8361 团核单 confirm 结算的团:这三列**不回写**,名单照实返回逐户值(可能仍是「核算中 / 未结算」)。两套口径的收敛归 Epic #8361,本单不处理。 + +--- + +## 五、数据库行为 + +零 DDL、零写入。新字段取自订单主表 `order_main` 既有三列(`flow_status` / `review_status` / `settlement_status`),只读;名单查询本就整行读取,不新增 SQL,也不新增远程调用。 + +--- + +## 六、边界行为 + +- 未登录 → 401(网关拦截)。 +- 团期不存在 → 589500;无权限或定制师读非本人名下团期 → 589507(均不变)。 +- 团期无子订单 → `records: []`、`total: 0`。 +- 三列为 null 的户 → 码与中文名都为 null。 +- 未知码 → 中文名回落原码。 +- 存量团:#8341(2026-09-24)之前已进入核单的团未回填,三列可能为 null / `NONE`。 +- 走 #8361 团核单 confirm 结算的团:三列不回写,名单照实返回。 +- 本接口新增字段无远程调用,无降级分支。 + +--- + +## 六.5、枚举 / 数据字典 + +### flowStatus(com.hulalv.order.core.enums.OrderFlowStatus) + +**所属字段**: `GroupBatchOrderItemRespVO.flowStatus` / `flowStatusName` | **类型**: `String` + +| 值 | 中文(flowStatusName) | 说明 | +|----|------|------| +| `AWAITING_PAY` | 待补全信息 | 枚举本名「待支付」,名单与订单详情统一显示「待补全信息」 | +| `AWAITING_PROFILE` | 待补全信息 | - | +| `RESOURCE_PREPARING` | 资源准备 | - | +| `PENDING_CONFIRM` | 待确认 | - | +| `PENDING_DEPARTURE` | 待出行 | - | +| `TRAVELLING` | 出行中 | - | +| `PENDING_REVIEW` | 待核单 | 团期出行完毕时写入(#8340) | +| `REVIEWING` | 核单中 | 团期发起核单时写入(#8341) | +| `PENDING_SETTLE` | 待结算 | 逐户核单提交后;团期反结算退回此态(#8341) | +| `SETTLED` | 已结算 | 团期结算 `/settle` 时写入(#8341) | +| `COMPLETED` | 已完成 | - | +| `CANCELLED` | 已取消 | - | + +### reviewStatus(com.hulalv.order.settlement.enums.ReviewStatus,逐户核单) + +**所属字段**: `GroupBatchOrderItemRespVO.reviewStatus` / `reviewStatusName` | **类型**: `String` + +| 值 | 中文(reviewStatusName) | 说明 | +|----|------|------| +| null | null | 出行前未进入核单;不折叠成「待核算」 | +| `NONE` | 待核算 | - | +| `PENDING` | 待核算 | 团期出行完毕时写入(#8340) | +| `IN_PROGRESS` | 核算中 | 团期发起核单时写入(#8341) | +| `COMPLETED` | 已完成 | 逐户核单提交后 | + +### settlementStatus(com.hulalv.order.settlement.enums.SettlementStatusEnum,逐户结算 / 财务复核) + +**所属字段**: `GroupBatchOrderItemRespVO.settlementStatus` / `settlementStatusName` | **类型**: `String` + +| 值 | 中文(settlementStatusName) | 说明 | +|----|------|------| +| `NONE` | 未结算 | 列默认值 | +| `PENDING` | 待财务复核 | 逐户核单提交后;团期反结算退回此态(#8341) | +| `COMPLETED` | 已结算 | 团期结算 `/settle` 时写入(#8341) | + +--- + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| `records[].flowStatus` | 无此字段 | **新增**:流程细状态码 | +| `records[].flowStatusName` | 无此字段 | **新增**:流程细状态中文名(与订单详情同规则) | +| `records[].reviewStatus` | 无此字段 | **新增**:逐户核单状态码(出行前 null) | +| `records[].reviewStatusName` | 无此字段 | **新增**:逐户核单中文名(与订单详情同规则) | +| `records[].settlementStatus` | 无此字段 | **新增**:逐户结算状态码(默认 `NONE`) | +| `records[].settlementStatusName` | 无此字段 | **新增**:逐户结算中文名 | +| 其余全部字段 / 入参 / 分页信封 | - | 不变 | + +### 行为级对比 + +| 行为 | 改前 | 改后 | +|------|------|------| +| 名单看逐户核单 / 结算进度 | 名单无此信息,需逐户进订单详情 | 名单直接返回三对状态 | +| 判权、分页、排序 | - | 不变 | +| 状态写入与流转 | - | 不变(本单只读透出) | + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 否。只新增响应字段,既有字段的名称、类型、语义不变,旧客户端忽略新字段即可。 +- **前端是否必须同步上线**: 否。不接入新字段页面照常工作;接入时名单「状态」列用 `flowStatusName`。 +- **前端 workaround 清理点**: 若名单页曾为展示核单 / 结算进度逐户调订单详情 `GET /v3/admin/order/{id}` 取 `main.flowStatusName`,可改读本名单新字段;若曾按旧版接口文档预留 `processStatus`,改为 `flowStatus` / `flowStatusName`。 + +## 七、不影响范围 + +- **仅影响**: `GET /v3/admin/order/group-batch/{groupBatchId}/orders` 响应 `records[]` 新增 6 个字段。 +- **零影响**: + - 本接口的入参、判权、分页、排序与其余字段 + - 团期文档导出与打印(只取订单 ID / 订单号 / 人数 / 房数,不受影响) + - 订单详情 `GET /v3/admin/order/{id}` 与订单列表 + - #8361 团核单各接口(finalize / confirm / `settlement/reports/group`) + - 财务 tab GB-ADM-040 `GET /v3/admin/order/group-batch/{groupBatchId}/finance` + - 团期核单、结算、反结算的写入与流转(#8340 / #8341 行为不变) + - 小程序端 + +--- + +## 八、测试环境已验证 + +TEST 已部署 dev-v3@`58da1df2a`(order-v3 双实例 8086/8186 滚动完成,2026-09-27 12:30)。构建身份探针:连打 8 次名单接口,8 次都带 `flowStatus`。经真实网关 `https://api.test.1814.love` 取证,库为 `hl_order_service_v3` 只读查询。 + +| AC | 场景 | 结果 | +|---|---|---| +| AC-1 | 每户返回三对新字段,改前改后响应 diff 只多出这 6 个键 | ✅ 5 个团 12 户部署前后各取一次:逐户「改后键 − 改前键」恰为这 6 个;改前的键一个不少,取值逐键比对 0 差异;户集合、顺序、`total` / `page` / `pageSize` 都不变 | +| AC-2 | 五种组合各取至少 1 户,三个码与库一致 | ✅ SETTLED/COMPLETED/COMPLETED 4 户、PENDING_SETTLE/COMPLETED/PENDING 3 户、REVIEWING/IN_PROGRESS/NONE 2 户、PENDING_REVIEW/PENDING/NONE 1 户、PENDING_DEPARTURE/null/NONE 2 户:名单三码与 `order_main` 同一分钟内的读数逐户一致 | +| AC-3 | 同一订单名单 `flowStatusName` / `reviewStatusName` 与订单详情 `main.*` 逐字一致 | ✅ 五种组合各 1 户对照 `GET /v3/admin/order/{id}` 的 `data.main`:待出行/null、待核单/待核算、核单中/核算中、待结算/已完成、已结算/已完成,逐字一致(详情不含 settlementStatusName,不在对照范围) | +| AC-4 | `reviewStatus` 为 null 的户码与中文名都为 null,不折叠成「待核算」 | ✅ 团 2100509904627191810 两户原始响应为 `"reviewStatus":null,"reviewStatusName":null`,库里 `review_status` 为 NULL | +| AC-5 | 未知码中文名回落原码 | ✅ 单测:合并提交上 `GroupBatchConverterTest` 的 #8418 用例 48 条执行、0 失败,含三个中文名各自的 `ZZZ_UNKNOWN` 行,以及 `offEnumCodes_sameAsOrderDetail` 5 条(空串 / 空白 / 未知码 / 小写两例) | +| AC-6 | 逐户反确认 → 逐户定稿,每步名单与库一致,最终复原 | ✅ 子订单 2102091018323296257:
• 改前 PENDING_SETTLE / COMPLETED / PENDING;
• `…/settlement/final-snapshots/reopen` 后名单与库均为 REVIEWING(核单中)/ IN_PROGRESS(核算中)/ NONE(未结算);
• `…/settlement/finalize` 后均回到 PENDING_SETTLE(待结算)/ COMPLETED(已完成)/ PENDING(待财务复核);
• 快照 v1 → REOPENED,新增 v2 FINALIZED 为当前版本,核单汇总金额与改前一致 | +| AC-7 | 名单无新增 SQL / 远程调用,生产代码只改 VO 与转换器 | ✅ 本单生产代码只有 `GroupBatchOrderItemRespVO`、`GroupBatchConverter` 两个文件;`GroupBatchQueryService` / Mapper / `OrderInfoConverter` 零改动 | +| AC-8 | order-v3 相关测试不引入新失败 | ✅ 定向 278 条 0 失败(合并提交上复测同样 278/0),16 个 Arch 类 87 条 0 失败;groupbatch 整包 4 个红类在干净基底 `7c69e8227` 上逐类读数吻合,属于既有问题 | +| AC-9 | 接口文档 GB-ADM-003 与 API-SPEC §17.3 已更新,changelog 通过校验器 | ✅ 团期接口文档 v2.0、一期实施拆分详设、实施单 02、API-SPEC §17.3、order-v3 CHANGELOG v6.3.30 已随 PR #8420 合入;本条目通过 frontmatter / 文件名校验器 | + +反例:不带 Authorization 或签名被篡改的 token,网关返回 HTTP 200 + `code: 401`(「缺少有效的 Authorization 头」/「Token 无效」),与网关既有约定一致,本单未改判权。 + +--- + +## 九、相关历史 PR + +| PR | Issue | 说明 | 是否仍有效 | +|----|-------|------|------------| +| #8344 | #8340 | 团期单子订单出发 / 返团跟随团期推进(出行完毕写 `PENDING_REVIEW` / `PENDING`) | ✅ 有效,本单只读其结果 | +| #8345 | #8341 | 团期核单 / 结算 / 反结算同步子订单三列 | ✅ 有效,本单只读其结果 | +| — | #7949 | 定制师读团期名单的归属校验 | ✅ 有效,判权不变 | +| — | #8361 | 团期报销核单一团一张(`GroupSettlementRespVO` 团级同名字段) | ✅ 有效,两套口径收敛归该 Epic | +| **本 PR #8420** | **#8418** | 名单逐户补三对状态 | ✅ 最新 | + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#8418](https://git.1814.love/wx/HL/issues/8418) +- 关联 PR: [wx/HL#8420](https://git.1814.love/wx/HL/pulls/8420) +- 接口文档:HL `docs/group/团期模块接口文档-v2.0.html` GB-ADM-003(`processStatus` 已改为 `flowStatus` / `flowStatusName`) +- API 规格:HL `docs/order-v3/api/API-SPEC.html` §17.3 `GroupBatchOrderItemRespVO` +- order-v3 变更记录:HL `docs/order-v3/CHANGELOG.md` v6.3.30 +- 数据源:#8340、#8341;口径 Epic:#8361 + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8418](https://git.1814.love/wx/HL/issues/8418) +- **PR**: [#8420](https://git.1814.love/wx/HL/pulls/8420) +- **Merge commit**: [58da1df2a](https://git.1814.love/wx/HL/commit/58da1df2ac781414c104b7c49120afab5287195f) + +### 联系人 + +- **后端负责人**: @jw