diff --git a/changelogs-v2/2026-09/24_8268_团期人工确认端点与确认后才出合同保险-新增接口-管理后台.md b/changelogs-v2/2026-09/24_8268_团期人工确认端点与确认后才出合同保险-新增接口-管理后台.md new file mode 100644 index 00000000..3d47ebe8 --- /dev/null +++ b/changelogs-v2/2026-09/24_8268_团期人工确认端点与确认后才出合同保险-新增接口-管理后台.md @@ -0,0 +1,677 @@ +--- +schema: "hl-changelog/v2" +ticket: "8268" +title: "团期人工「确认」:新增确认端点(配置 → 确认),确认后才出合同保险并全团逐户补发;确认物资前移到配置节点;物料门复判端点下线" +consumer: "admin" +author: "jw(GIT)" +change_type: "新增接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "2026-09-24" +status_note: "六节点定案(SRS §0.27.3 / §0.27.5 #2~#5):「配置 → 确认」由系统自动推进改为人工点「确认」。新增 POST /v3/admin/order/group-batch/{groupBatchId}/confirm(权限码 group-batch:confirm,授 GROUP_BATCH_MANAGER / ADMIN),门 = 房 / 车 / 导游领队 / 摄影四项 ready 全 true 且物资已确认,不满足返新码 589556 并逐项列出未满足项,状态不是 RESOURCE_PREPARING(含重复确认)返 589501;成功后团期进入 MATERIAL_PREPARING、时间线记 BATCH_CONFIRM(确认),事务提交后系统对全团已确认行程的户逐户补发合同与保险。四项 ready 翻真 / 成团 / 免车不再自动推进状态。连带改动:confirm-material 只在 RESOURCE_PREPARING 可调且不再顺带准入待出发(其它状态 589501);合同保险出具门改为团期已确认(MATERIAL_PREPARING 及之后),确认前手动出具返 589548,文案改为「团期确认后才能出具合同与保险」,合同保险面板 issuable 同口径;POST .../recheck-material-gate 下线(589561 不再抛出)。前端需新增「确认」按钮与 589556 逐项提示、把确认物资按钮挪到配置节点、移除物料门复判入口。" +updated_at: "2026-09-24" +base: "dev-v3" +--- + +# 团期状态流转: 人工「确认」取代自动推进,确认后才出合同保险(管理后台) + +> **服务**: hl-order-service-v3(端口 8086/8186);权限种子在 hl-user-service +> **PR**: #8302 +> **Issue**: #8268 +> **日期**: 2026-09-24 +> **影响范围**: 管理后台团期详情页的「确认」按钮(新增)、「确认物资」按钮、「合同保险」页签的出具按钮与可出具提示;原「复判物料门」入口下线 + +--- + +## ⚠️ 关键变化 + +1. **团期不会再自己从「资源准备中」走到「物料准备中」**。改前四项 ready 齐 + 合同保险出齐时系统自动推进;现在必须由团期管理员点「确认」(新端点)。 +2. **合同 / 保险在确认前一律不出**。改前资源准备中四项配齐即可出具;现在确认前手动出具被 589548 拒,面板 `issuable=false`。确认后系统自动给全团已确认行程的户逐户补发。 +3. **确认物资挪到确认之前**。`confirm-material` 以前只在物料准备中可调、还会顺带尝试进入待出发;现在只在资源准备中可调,且只置物资已确认,不改团期状态。 +4. **`recheck-material-gate` 端点已删除**,调用会得到 404。 + +--- + +## 一、背景 + +六节点定案里「配置 → 确认」是一个**不可撤销的人工动作**:确认之后四项配置与物资锁定(锁定写口见 #8269 条目),系统随即对客出合同与保险。因此它不能再由系统在 ready 位翻真时悄悄推进,也需要独立于 `group-batch:manage` 的授权。 + +| 节点 | 持久态 | 本单之后怎么进入 | +|---|---|---| +| 配置 | `RESOURCE_PREPARING` | 成团(不变) | +| 确认 | `MATERIAL_PREPARING` | **仅**人工调用确认端点 | +| 出行·待出发 | `PENDING_DEPARTURE` | 七项硬门(不变) | + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 团期确认 | POST | `/v3/admin/order/group-batch/{groupBatchId}/confirm` | 新增接口 | 配置 → 确认;门不满足 589556 逐项回执 | +| 2 | 确认团期物资 | POST | `/v3/admin/order/group-batch/{groupBatchId}/confirm-material` | 修改(可调状态 + 行为) | 只在 `RESOURCE_PREPARING` 可调;不再顺带准入待出发 | +| 3 | 手工复判物料门 | POST | `/v3/admin/order/group-batch/{groupBatchId}/recheck-material-gate` | 删除接口 | 自动推进已删,复判入口随之下线 | +| 4 | 手动开合同 / 保险(GB-ADM-031) | POST | `/v3/admin/order/group-batch/{groupBatchId}/contracts/issue` | 修改(前置门 + 文案) | 确认前 589548,文案改 | +| 5 | 作废重开合同 / 保险(GB-ADM-031) | POST | `/v3/admin/order/group-batch/{groupBatchId}/contracts/reissue` | 修改(前置门 + 文案) | 同上 | +| 6 | 合同保险面板(GB-ADM-030) | GET | `/v3/admin/order/group-batch/{groupBatchId}/contracts` | 修改(出参语义) | `issuable` 改为「团期已确认」 | + +网关无改动(均在既有 `/v3/admin/order/group-batch` 前缀下)。 + +--- + +## 三、接口详情 + +### 1. 团期确认 `POST /v3/admin/order/group-batch/{groupBatchId}/confirm` + +**VO**: `Result`(无请求体) + +#### 使用场景 + +团期详情页「配置」节点的「确认」按钮。房、车、导游领队、摄影四项配齐且物资已确认后,团期管理员点确认,团期进入「确认」节点,配置锁定,系统开始逐户出合同与保险。**没有撤销确认。** + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | 不存在返 589500 | + +无请求体。 + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Void | 成功返回 null;团期状态已是 `MATERIAL_PREPARING`,重新拉详情即可看到 `stage=CONFIRM` | + +#### 请求示例 + +```http +POST /v3/admin/order/group-batch/2097250563497385985/confirm HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": null, + "success": true +} +``` + +#### 空数据 / 降级响应 + +本接口无列表出参。确认成功后的逐户补发合同保险是**异步**的:确认接口立即返回 200,补发结果在「合同保险」页签逐户可见;单户出具失败不影响确认结果,也不影响其余户,可在该页签手动开(GB-ADM-031)补出。 + +```json +{ "code": 200, "data": null, "success": true } +``` + +#### 错误响应 + +确认门不满足(逐项列出,顺序固定为 房、车、导游领队、摄影、物资): + +```json +{ + "code": 589556, + "message": "团期尚不满足确认条件:车未配齐、物资未确认", + "success": false, + "data": null +} +``` + +状态不是「配置」(含已确认后再点一次): + +```json +{ + "code": 589501, + "message": "团期状态不允许当前操作", + "success": false, + "data": null +} +``` + +无权限(角色未授 `group-batch:confirm`): + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 权限码 `group-batch:confirm`,授给 `GROUP_BATCH_MANAGER` 与 `ADMIN`;其余角色 589507。与 `group-batch:manage` 分开授权。 +- 判定顺序:团期存在(589500)→ 状态为 `RESOURCE_PREPARING`(589501)→ 确认门(589556)→ CAS 推进。任一步拒绝**零写入**。 +- 589556 的未满足项取值只有五种:`房未配齐`、`车未配齐`、`导游领队未配齐`、`摄影未配齐`、`物资未确认`,以「、」连接。 +- 不需要导游 / 摄影的团、整团免车的团,其 ready 位已由成团免闸 / 免车写口置真,确认时不会被这几项挡住。 +- 并发确认只有一个成功,其余 589501;重复确认不会重复推进。 +- 成功后时间线新增一条 `eventType=BATCH_CONFIRM`、`eventTypeName=确认`,带操作人。 +- 补发只处理子订单状态为待出发 / 出行中(已确认行程)的户;尚未确认行程的户跳过,等其确认行程时由既有自动出具链路出;已出具的户逐项跳过;已取消户不出。 + +--- + +### 2. 确认团期物资 `POST /v3/admin/order/group-batch/{groupBatchId}/confirm-material` + +**VO**: `Result`(无请求体) + +#### 使用场景 + +「物资」页签的「确认物资」按钮。本次起它是团期确认的前置条件之一,在「配置」节点点。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | 不存在返 589500 | + +无请求体。 + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Void | 成功返回 null;团期状态**不变**,物资已确认标记置真 | + +#### 请求示例 + +```http +POST /v3/admin/order/group-batch/2097250563497385985/confirm-material HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": null, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无列表出参。确认前物资可反复增删改、反复确认,每次确认都在时间线记一条「确认物资」流水(内容「确认物资清单」)。 + +```json +{ "code": 200, "data": null, "success": true } +``` + +#### 错误响应 + +团期不在 `RESOURCE_PREPARING`(含招募中、已确认及之后): + +```json +{ + "code": 589501, + "message": "团期状态不允许当前操作", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 权限码 `group-batch:manage`(不变)。 +- **只在 `RESOURCE_PREPARING` 可调**;改前只在 `MATERIAL_PREPARING` 可调,两者正好相反。 +- **不再推进团期状态**:改前确认物资后会顺带尝试进入待出发;现在进入待出发改由子订单确认、定时扫描与「复判待出发硬门」端点负责,七项硬门本身不变。 +- 取消成团会把物资已确认标记重置(不变)。 + +--- + +### 3. 手工复判物料门 `POST /v3/admin/order/group-batch/{groupBatchId}/recheck-material-gate` + +**VO**: `GroupBatchMaterialGateRespVO`(已删除) + +#### 使用场景 + +**已下线。** 该端点原用于在「资源准备中 → 物料准备中」自动推进卡住时手工复判。自动推进已删除,这一跳只剩人工确认一条路,复判入口不再有意义。请改用新端点 `POST .../confirm`。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 端点已删除 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| advanced | Boolean | 已删除(原:是否推进了团期) | +| currentStatus / currentStatusName | String | 已删除 | +| blockedGate / blockedOrderId / blockedReason | String / Long / String | 已删除 | + +#### 请求示例 + +```http +POST /v3/admin/order/group-batch/2097250563497385985/recheck-material-gate HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +路由已不存在,经网关调用返回业务信封 `code=404`(TEST 2026-09-24 实测): + +```json +{ "code": 404, "msg": "接口不存在: POST /v3/admin/order/group-batch/2102932276390383618/recheck-material-gate" } +``` + +#### 空数据 / 降级响应 + +无。端点不存在,不会返回任何业务数据。 + +#### 错误响应 + +任何调用都返回 `code=404`「接口不存在」(同上): + +```json +{ "code": 404, "msg": "接口不存在: POST /v3/admin/order/group-batch/2102932276390383618/recheck-material-gate" } +``` + +#### 业务边界 + +- 原错误码 589561「团期当前状态为「{0}」,不在「资源准备中」,无需复判物料门」不再抛出,仅保留占位防号段复用。 +- 前端所有调用点与按钮需移除;替代动作是「确认」。 + +--- + +### 4. 手动开合同 / 保险 `POST /v3/admin/order/group-batch/{groupBatchId}/contracts/issue` + +**VO**: `GroupBatchContractIssueReqVO` → `GroupBatchIssueResultVO` + +#### 使用场景 + +「合同保险」页签逐户开合同 / 保险。本次只改前置门与拒绝文案,入参出参结构不变。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | - | +| orderIds | Body | List<Long> | 否 | - | 为空 = 本期全部尚未出具的户 | +| target | Body | String | ✅ | `CONTRACT` / `INSURANCE` / `BOTH` | 出具目标 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| totalCount | Integer | 本次处理户数 | +| successCount | Integer | 成功户数 | +| failCount | Integer | 失败户数 | +| skipCount | Integer | 跳过户数(已出具 / 已签等) | +| results[].orderId | String | 子订单 ID | +| results[].target | String | `CONTRACT` / `INSURANCE` | +| results[].outcome | String | `SUCCESS` / `SKIPPED` / `FAILED` | +| results[].message | String | 失败或跳过原因 | + +#### 请求示例 + +```json +{ "orderIds": ["770145"], "target": "CONTRACT" } +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "totalCount": 1, + "successCount": 1, + "failCount": 0, + "skipCount": 0, + "results": [ + { "orderId": "770145", "target": "CONTRACT", "outcome": "SUCCESS", "message": null } + ] + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +已出具的户逐项 `SKIPPED`,不算失败;单户失败只记在 `results` 里,不影响其余户(不变)。 + +```json +{ "code": 200, "data": { "totalCount": 1, "successCount": 0, "failCount": 0, "skipCount": 1, "results": [ { "orderId": "770145", "target": "CONTRACT", "outcome": "SKIPPED", "message": "该户合同已出具,自动跳过" } ] }, "success": true } +``` + +#### 错误响应 + +团期尚未确认(`RECRUITING` / `RESOURCE_PREPARING`,即便四项已配齐): + +```json +{ + "code": 589548, + "message": "团期确认后才能出具合同与保险", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 权限码 `group-batch:contract:issue`(不变)。 +- 可出具的团期状态:`MATERIAL_PREPARING` / `PENDING_DEPARTURE` / `TRAVELLING` / `REVIEWING` / `SETTLED`;其余一律 589548,整单拒绝、零写入。 +- 改前 `RESOURCE_PREPARING` 且四项 ready 全真时可出具,本次起不可。 + +--- + +### 5. 作废重开合同 / 保险 `POST /v3/admin/order/group-batch/{groupBatchId}/contracts/reissue` + +**VO**: `GroupBatchContractIssueReqVO` → `GroupBatchIssueResultVO` + +#### 使用场景 + +「开错」态的补救通路:先作废该户现有单据再重开。前置门与手动开完全一致。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | - | +| orderIds | Body | List<Long> | 否 | - | 为空 = 本期全部户 | +| target | Body | String | ✅ | `CONTRACT` / `INSURANCE` / `BOTH` | 重开目标 | +| reason | Body | String | 否 | - | 作废原因 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| totalCount / successCount / failCount / skipCount | Integer | 同手动开 | +| results[] | List | 逐户结果,同手动开 | + +#### 请求示例 + +```json +{ "orderIds": ["770145"], "target": "CONTRACT", "reason": "方案选错" } +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "totalCount": 1, + "successCount": 1, + "failCount": 0, + "skipCount": 0, + "results": [ + { "orderId": "770145", "target": "CONTRACT", "outcome": "SUCCESS", "message": null } + ] + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +作废失败的户直接记 `FAILED`,不进重开,不影响其他户(不变)。 + +```json +{ "code": 200, "data": { "totalCount": 1, "successCount": 0, "failCount": 1, "skipCount": 0, "results": [ { "orderId": "770145", "target": "CONTRACT", "outcome": "FAILED", "message": "作废失败" } ] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589548, + "message": "团期确认后才能出具合同与保险", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 与手动开共用同一出具门与同一文案。 +- 确认前没有任何已出具的单据可重开,调用即 589548。 + +--- + +### 6. 合同保险面板 `GET /v3/admin/order/group-batch/{groupBatchId}/contracts` + +**VO**: `GroupBatchContractBoardVO` + +#### 使用场景 + +「合同保险」页签首屏:顶部三格统计 + 逐户卡片;`issuable` 决定出具按钮是否可点。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | - | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| issuable | Boolean | **语义改变**:= 团期已人工确认(`MATERIAL_PREPARING` 及之后的可出具状态);改前 = 四项配齐 | +| batchStatus | String | 团期状态存储值,`issuable=false` 时可据此提示(不变) | +| totalCount / contractIssuedCount / contractSignedCount / insuranceIssuedCount | Integer | 不变 | +| items | List | 逐户明细(不变) | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2097250563497385985/contracts HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "groupBatchId": "2097250563497385985", + "issuable": false, + "batchStatus": "RESOURCE_PREPARING", + "totalCount": 3, + "contractIssuedCount": 0, + "contractSignedCount": 0, + "insuranceIssuedCount": 0, + "items": [] + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无活跃子订单时 `totalCount=0`、`items` 为空数组(不变): + +```json +{ "code": 200, "data": { "issuable": false, "batchStatus": "RESOURCE_PREPARING", "totalCount": 0, "items": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589500, + "message": "团期不存在", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- `RESOURCE_PREPARING` 且四项已配齐时,改前 `issuable=true`,现在 `false`;提示文案建议为「团期确认后才能出具合同与保险」。 +- 其余字段口径不变。 + +--- + +## 四、契约约束与正确调用方式 + +### ✅ 正确 / ❌ 错误调用顺序 + +| 场景 | 调用 | +|------|------| +| ✅ 配置节点收尾 | 配房 / 车 / 导摄 → `confirm-material` → `confirm` | +| ❌ 先确认团期再确认物资 | `confirm` → 589556「…物资未确认」;确认后再调 `confirm-material` → 589501 | +| ❌ 确认前出具合同 | `contracts/issue`(`RESOURCE_PREPARING`)→ 589548 | +| ❌ 继续调复判物料门 | `recheck-material-gate` → 404 | + +### 589556 的处理 + +message 的冒号之后就是未满足项清单,可直接展示给操作人;不要再去调已下线的复判端点找原因。 + +--- + +## 五、数据库行为 + +| 前端动作 | 外部可观察的写入 | +|----------|------------------| +| `confirm` 成功 | 团期状态 `RESOURCE_PREPARING → MATERIAL_PREPARING`(CAS,一次)+ 时间线一条「确认」(含操作人);提交后异步逐户生成合同 / 保单 | +| `confirm` 被拒(589501 / 589556 / 589507) | 零写入 | +| `confirm-material` 成功 | 物资已确认标记置真 + 时间线一条「确认物资」;团期状态不变 | +| `confirm-material` 被拒 | 零写入 | +| `contracts/issue` / `reissue` 被 589548 拒 | 零写入 | + +--- + +## 六、边界行为 + +- 未登录 → 401(网关拦截)。 +- 团期不存在 → 589500。 +- 四项 ready 翻真、成团、整团免车**都不会再推进团期状态**;团期会停在「配置」直到有人点确认。 +- 确认后补发是异步的,确认接口不等补发完成;补发整轮失败(如团期被并发流团)只影响出具,不回滚确认,可在「合同保险」页签手动补出。 +- 进入待出发的七项硬门不变。 + +--- + +## 六.5、枚举 / 数据字典 + +### 589556 未满足项(GroupBatchService.unmetConfirmConditions) + +**所属字段**: 错误 `message` 冒号后的清单 | **类型**: `String`(「、」分隔) + +| 值 | 中文 | 说明 | +|----|------|------| +| `房未配齐` | 房 | 团期配房完成标志为假 | +| `车未配齐` | 车 | 团期配车完成标志为假(整团免车时为真) | +| `导游领队未配齐` | 导游领队 | 不需要导游的团成团时已置真 | +| `摄影未配齐` | 摄影 | 不需要摄影的团成团时已置真 | +| `物资未确认` | 物资 | 未调用 `confirm-material` | + +### 时间线事件(GroupBatchLogEventType,新增一值) + +**所属字段**: 团期状态流水 `eventType` / `eventTypeName` | **类型**: `String` + +| 值 | 中文 | 说明 | +|----|------|------| +| `BATCH_CONFIRM` | 确认 | 本次新增;人工确认时写入,`fromStatus=RESOURCE_PREPARING`、`toStatus=MATERIAL_PREPARING` | +| `BATCH_RESOURCE_READY` | 资源就绪·进物资准备 | 原自动推进事件,本次起不再写入;历史行照常显示 | + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| 合同保险面板 `issuable` | 四项配齐(或已进物料准备中)即 true | 团期已确认(物料准备中及之后)才 true | +| 589548 message | 房/车/导/摄四项配齐后才能出具合同与保险 | 团期确认后才能出具合同与保险 | +| 589556 | 无 | 新增:团期尚不满足确认条件:{0} | + +### 行为级对比 + +| 行为 | 改前 | 改后 | +|------|------|------| +| 资源准备中 → 物料准备中 | 四项 ready + 逐户合同已签、保险已出 → 系统自动推进 | 只能人工 `confirm`,门 = 四项 ready + 物资已确认 | +| 确认物资可调状态 | `MATERIAL_PREPARING` | `RESOURCE_PREPARING` | +| 确认物资的副作用 | 顺带尝试进入待出发 | 不改团期状态 | +| 合同保险出具时机 | 资源准备中四项配齐即可 | 确认后;确认时对已确认行程的户自动补发 | +| 复判物料门端点 | 可用 | 删除(404) | + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 是。复判端点删除;确认物资的可调状态翻转;确认前不能出合同保险。 +- **前端是否必须同步上线**: 是。缺少「确认」按钮时,新成团的团期会一直停在「配置」节点。 +- **前端 workaround 清理点**: 移除「复判物料门」入口及其结果弹窗;「确认物资」按钮的显示条件由物料准备中改为资源准备中;合同保险页签按 `issuable` 置灰的提示文案改为「团期确认后才能出具合同与保险」。 + +--- + +## 七、不影响范围 + +- **仅影响**: 团期「配置 → 确认」这一跳、确认物资、合同保险出具门。 +- **零影响**: + - 成团、取消成团、流团的入参与出参 + - 进入待出发的七项硬门与「复判待出发硬门」端点 + - 子订单确认行程后的逐户自动出具链路(团期已确认时照常出) + - 小程序端 +- 另:内部定时任务端点 `/v3/internal/jobs/group-batch-material-gate/run` 与其定时任务同批下线,属服务间内部接口,管理后台不调用。 + +--- + +## 八、测试环境已验证 + +部署:hl-user-service + hl-order-service-v3 = dev-v3 @ d9fdd7fe0(2026-09-24 09:18 / 09:20),经网关 `https://api.test.1814.love` 真实鉴权实测(2026-09-24 09:22–09:45);工单 #8268 已验收关单。 + +| # | 场景 | 结果 | +|---|---|---| +| 1 | 四项 ready + 物资已确认,GROUP_BATCH_MANAGER 调 `POST /confirm` | 200,RESOURCE_PREPARING → MATERIAL_PREPARING,时间线 `BATCH_CONFIRM`(含操作人) | +| 2 | 门不满足调 confirm | 589556「团期尚不满足确认条件:房未配齐、车未配齐、摄影未配齐、物资未确认」,状态不变 | +| 3 | 招募中 / 已确认后重复调 confirm | 589501,不推进 | +| 4 | ROOM_MANAGER / VEHICLE_MANAGER / CUSTOMIZER / FINANCE 调 confirm | 589507;Flyway `20260923.268` 已执行,仅授 ADMIN 与 GROUP_BATCH_MANAGER | +| 5 | 成团及四项依次翻真 | 不再自动推进,停在 RESOURCE_PREPARING 直到人工确认 | +| 6 | 确认前户确认行程 / 手动出具 | 不自动出具;`GET /contracts` 的 `issuable=false`;手动出具 589548「团期确认后才能出具合同与保险」 | +| 7 | 确认后全团补发 | `total=6 success=4 skipped=2 failed=0`:已确认行程两户合同 GENERATED + 保险 INSURED;已取消户、未确认行程户不出;再次出具返回 SKIPPED | +| 8 | 配置阶段 / 确认后调 `confirm-material` | 200(`material_confirmed=1`)/ 589501 | +| 9 | 旧 `recheck-material-gate` 与内部 job 端点 | `code=404`「接口不存在」;sys_job 与 QRTZ 均无 1044 | +| 10 | 合同签齐 + 七门满足后复检 | 进入 PENDING_DEPARTURE(签署以 SQL 模拟) | + +--- + +## 九、相关历史 PR + +| PR | Issue | 说明 | 是否仍有效 | +|----|-------|------|------------| +| — | #7105 | 合同保险出具门(四项配齐,589548) | ❌ 门条件被本单替换,码值保留 | +| — | #7526 | 物料门兜底复判(端点 + 定时任务) | ❌ 本单下线 | +| — | #7528 | 确认物资后顺带准入待出发 | ❌ 本单删除该顺带准入 | +| **本 PR #8302** | **#8268** | 人工确认 + 确认后出合同保险 | ✅ 最新 | + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#8268](https://git.1814.love/wx/HL/issues/8268) +- 关联 PR: [wx/HL#8302](https://git.1814.love/wx/HL/pulls/8302) +- 同批六节点条目:确认后锁定配置(#8269)、六节点展示与看板七桶(#8271) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8268](https://git.1814.love/wx/HL/issues/8268) +- **PR**: [#8302](https://git.1814.love/wx/HL/pulls/8302) +- **Merge commit**: [d9fdd7fe0](https://git.1814.love/wx/HL/commit/d9fdd7fe038952ac3ffdd31913dfcc4a2fc40574) + +### 联系人 + +- **后端负责人**: @jw diff --git a/changelogs-v2/2026-09/24_8269_团期确认后锁定配置各写口收紧到配置阶段-修改接口-管理后台.md b/changelogs-v2/2026-09/24_8269_团期确认后锁定配置各写口收紧到配置阶段-修改接口-管理后台.md new file mode 100644 index 00000000..82091072 --- /dev/null +++ b/changelogs-v2/2026-09/24_8269_团期确认后锁定配置各写口收紧到配置阶段-修改接口-管理后台.md @@ -0,0 +1,1732 @@ +--- +schema: "hl-changelog/v2" +ticket: "8269" +title: "团期确认后锁定配置:导游 / 摄影 / 物资、订房计划与分房、需求整体确认 / 打回、正式用车需求保存 / 受控重开 / 免车、房务整团抢单的阶段门收紧到确认之前;抢单池 batchStatus 只接受 RESOURCE_PREPARING" +consumer: "admin" +author: "jw(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "2026-09-24" +status_note: "六节点定案(SRS §0.27.3 / §0.27.5 #6~#9):团期人工「确认」(进入 MATERIAL_PREPARING,见 #8268)之后四项配置与物资一律不可修改,没有撤销确认。本单把各写口的允许阶段收紧:导游 / 摄影 / 物资由出行前四态(#8231)收回到招募、配置两态,拒绝码仍为 589598,文案改为「团期已确认,配置不可修改」;订房计划新增 / 修改 / 删除 / 按日确认 / 整团确认与分房微调 / 重算只在 RESOURCE_PREPARING 可用(删除另放行已流团),拒绝码 808600 文案补「订房计划仅在配置阶段可改,团期已确认,配置不可修改」;需求整体确认与整团打回、逐单打回两边同步收紧到 RESOURCE_PREPARING(589501);正式用车需求保存收紧到 RESOURCE_PREPARING(589501),受控重开只在 RESOURCE_PREPARING 可用(809111,文案补同一句),免车在 RESOURCE_PREPARING 及出行完毕 / 核单中可用;房务整团抢单池只收 RESOURCE_PREPARING 的团,分页参数 batchStatus 只接受 RESOURCE_PREPARING,其它值 400,整团认领与超管团级接管对确认后的团返 808651。码值、路径、入参出参结构均不变。子订单退单 / 转团 / 加人、满团名额调整、流团不受本单影响。本条取代 23_8231 中「出行前四态可配」的窗口描述。前端需:确认后隐藏或置灰上述写操作入口、按新文案提示、抢单池筛选下拉只保留资源准备中。" +updated_at: "2026-09-24" +base: "dev-v3" +--- + +# 团期资源配置: 团期确认后配置锁定,各写口收紧到确认之前(管理后台) + +> **服务**: hl-order-service-v3(端口 8086/8186) +> **PR**: #8280 +> **Issue**: #8269 +> **日期**: 2026-09-24 +> **影响范围**: 管理后台团期详情页的配导游 / 配摄影、物资、订房计划与分房、查看需求(整体确认 / 打回)、正式用车需求(保存 / 受控重开 / 免车);房务端整团抢单池 + +--- + +## ⚠️ 关键变化 + +1. **团期「确认」之后,下面所有写口一律拒绝**(没有撤销确认)。确认之前(招募 / 配置)可反复改。 +2. **#8231 刚放开的「出行前四态都能配导摄物资」被收回**:现在只有招募、配置两态能配,`MATERIAL_PREPARING` / `PENDING_DEPARTURE` 也被拒。589598 码值不变,**文案由「出行后不可再配置导游 / 摄影 / 物资」改为「团期已确认,配置不可修改」**,按原文案做过匹配的要改。 +3. **订房计划不再允许返团后按实际入住修正**:改前可写到核单中,现在只剩配置阶段;差异改在核单按成本 / 冲正处理。 +4. **需求打回也收紧了**:改前整团打回除已流团外全程可用、逐单打回不看团期阶段;现在两者都只在配置阶段可用。 +5. **房务抢单池分页参数 `batchStatus` 只接受 `RESOURCE_PREPARING`**,传 `MATERIAL_PREPARING` / `PENDING_DEPARTURE` / `TRAVELLING` 返 400。 + +--- + +## 一、背景 + +| 节点 | 持久态 | 本单后可写 | +|---|---|---| +| 招募 | `RECRUITING` | 仅导游 / 摄影 / 物资(提前配) | +| 配置 | `RESOURCE_PREPARING` | 本条全部写口 | +| 确认及之后 | `MATERIAL_PREPARING` / `PENDING_DEPARTURE` / `TRAVELLING` / `TRIP_FINISHED` / `REVIEWING` / `SETTLED` | 一律拒绝(免车在出行完毕 / 核单中例外,见接口 21) | +| 已流团 | `CANCELLED` | 一律拒绝(订房计划删除例外,用于释放库存) | + +不受本单影响:子订单退单 / 转团 / 加人、满团名额调整、流团、订房计划整团批量释放(仅已流团可用,不变)。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 保存团期人员配置 | PUT | `/v3/admin/group-batch/{productBatchId}/staff` | 阶段门收紧 + 文案 | 四态 → 招募 / 配置;589598 文案改 | +| 2 | 设置报账人等级 | PUT | `/v3/admin/group-batch/{productBatchId}/staff/{staffId}/reporter-rank` | 阶段门收紧 + 文案 | 同上 | +| 3 | 新增团期备品行 | POST | `/v3/admin/order/group-batch/{groupBatchId}/supplies` | 阶段门收紧 + 文案 | 同上 | +| 4 | 调整团期备品数量 | PUT | `/v3/admin/order/group-batch/supplies/{batchSuppliesId}/quantity` | 阶段门收紧 + 文案 | 同上 | +| 5 | 软删团期备品行 | DELETE | `/v3/admin/order/group-batch/supplies/{batchSuppliesId}` | 阶段门收紧 + 文案 | 同上 | +| 6 | 整团按日提交订房计划 | POST | `/v3/admin/house/group-batches/{groupBatchId}/room-plans` | 阶段门收紧 + 文案 | 六态 → 仅配置;808600 文案改 | +| 7 | 修改单条订房计划 | PUT | `/v3/admin/house/group-batches/{groupBatchId}/room-plans/{planId}` | 阶段门收紧 + 文案 | 同上 | +| 8 | 删除单条订房计划 | DELETE | `/v3/admin/house/group-batches/{groupBatchId}/room-plans/{planId}` | 阶段门收紧 + 文案 | 仅配置 + 已流团 | +| 9 | 按日确认订房 | POST | `/v3/admin/house/group-batches/{groupBatchId}/room-plans/days/{stayDate}/confirm` | 阶段门收紧 + 文案 | 仅配置 | +| 10 | 整团确认订房 | POST | `/v3/admin/house/group-batches/{groupBatchId}/room-plans/confirm` | 阶段门收紧 + 文案 | 仅配置 | +| 11 | 订房确认预检 | GET | `/v3/admin/house/group-batches/{groupBatchId}/room-plans/confirm-check` | 出参取值变化 | `stageAllowed` 仅配置为 true | +| 12 | 人工微调分房 | POST | `/v3/admin/house/group-batches/{groupBatchId}/allocations` | 阶段门收紧 + 文案 | 仅配置 | +| 13 | 重算分房 | POST | `/v3/admin/house/group-batches/{groupBatchId}/allocations/rebuild` | 阶段门收紧 + 文案 | 仅配置 | +| 14 | 整体确认需求缺失预检 | GET | `/v3/admin/order/group-batch/{groupBatchId}/requirement/confirm-check` | 出参取值变化 | `ready` 仅配置可能为 true | +| 15 | 整体确认需求 | POST | `/v3/admin/order/group-batch/{groupBatchId}/requirement/confirm` | 阶段门收紧 | 四态 → 仅配置(589501) | +| 16 | 按户打回需求(整团入口) | POST | `/v3/admin/order/group-batch/{groupBatchId}/requirement/reject` | 阶段门收紧 | 除已流团外全程 → 仅配置(589501) | +| 17 | 团期管理员打回住宿需求(逐单) | POST | `/v3/admin/order/{id}/hotel-requirement/reject` | 新增阶段门 | 仅配置(589501) | +| 18 | 团期管理员打回用车需求(逐单) | POST | `/v3/admin/order/{id}/vehicle-requirement/reject` | 新增阶段门 | 仅配置(589501) | +| 19 | 保存团期正式用车需求 | PUT | `/v3/admin/order/group-batch/{groupBatchId}/vehicle-requirement` | 阶段门收紧 | 四态 → 仅配置(589501) | +| 20 | 受控重开正式用车需求 | POST | `/v3/admin/order/group-batch/{groupBatchId}/vehicle-requirement/reopen` | 阶段门收紧 + 文案 | 三态 → 仅配置;809111 文案改 | +| 21 | 声明整团无需用车 | POST | `/v3/admin/order/group-batch/{groupBatchId}/vehicle-requirement/waive` | 阶段门收紧 | 去掉物料准备中 / 待出发 / 出行中 | +| 22 | 团期抢单池列表 | GET | `/v3/admin/order/grab-pool/group-batches` | 入参取值收窄 + 出参行集合变化 | `batchStatus` 只接受 `RESOURCE_PREPARING`;池内只剩配置阶段的团 | +| 23 | 整团认领 | POST | `/v3/admin/order/grab-pool/group-batches/{groupBatchId}/claim` | 阶段门收紧 | 确认后的团 808651 | +| 24 | 团级接管(超管) | POST | `/v3/admin/order/grab-pool/group-batches/{groupBatchId}/takeover` | 阶段门收紧 | 确认后的团 808651 | + +路径、HTTP 方法、权限码、入参结构、成功响应结构均不变;网关无改动。 + +--- + +## 三、接口详情 + +### 1. 保存团期人员配置 `PUT /v3/admin/group-batch/{productBatchId}/staff` + +**VO**: `BatchStaffConfigReqVO` → `BatchStaffConfigRespVO` + +#### 使用场景 + +团期详情页「配导游 / 配摄影」弹窗保存(整期全量覆盖,可按 `scopeRoles` 限定角色范围)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| productBatchId | Path | Long | ✅ | 产品侧排期 ID | 未建团返 589553(不变) | +| scopeRoles | Body | List<String> | 否 | 元素非空 | 限定覆盖的角色范围(不变) | +| staffList | Body | List | 否 | null 按空列表 | 传空列表 = 清空覆盖范围内配置(不变) | +| staffList[].staffId | Body | Long | ✅ | 须命中候选人员 | 不变 | +| staffList[].staffRole | Body | String | ✅ | 须与人员类型相符 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| productBatchId | Long | 不变 | +| groupBatchId | Long | 不变 | +| staffList | List | 保存后的整期最终状态(不变) | +| affectedOrderCount | Integer | 不变 | + +#### 请求示例 + +```json +{ "staffList": [ { "staffId": 1002, "staffRole": "GUIDE", "sortOrder": 0 } ] } +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { "productBatchId": "2097250420299530242", "groupBatchId": "2097250563497385985", "affectedOrderCount": 0, "staffList": [ { "staffId": 1002, "staffRole": "GUIDE" } ] }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +`staffList` 传空列表即清空,返回 200、`staffList` 为空数组(不变)。 + +```json +{ "code": 200, "data": { "staffList": [], "affectedOrderCount": 0 }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589598, + "message": "团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 允许:`RECRUITING`、`RESOURCE_PREPARING`;其余(含 `MATERIAL_PREPARING`、`PENDING_DEPARTURE`、`CANCELLED`)589598,被拒时零写入。 +- 未建团仍返 589553,与 589598 不可合并。 + +--- + +### 2. 设置报账人等级 `PUT /v3/admin/group-batch/{productBatchId}/staff/{staffId}/reporter-rank` + +**VO**: `ReporterRank`(枚举入参)→ `Result` + +#### 使用场景 + +团期人员名单里标主报账人 / 协助报账人,与保存口同窗口。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| productBatchId | Path | Long | ✅ | - | 不变 | +| staffId | Path | Long | ✅ | 须命中已配人员 | 不变 | +| rank | Body | String | ✅ | `PRIMARY` / `ASSIST` / `NONE` | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Void | 成功返回 null | + +#### 请求示例 + +```json +{ "rank": "PRIMARY" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": null, "success": true } +``` + +#### 空数据 / 降级响应 + +无列表出参,无空数据形态。 + +```json +{ "code": 200, "data": null, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589598, + "message": "团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 窗口与保存口完全一致:招募、配置两态。 +- 被拒时零写入。 + +--- + +### 3. 新增团期备品行 `POST /v3/admin/order/group-batch/{groupBatchId}/supplies` + +**VO**: `AddSuppliesReqVO` → `Result` + +#### 使用场景 + +「物资」页签手工录入一行备品。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | 不变 | +| suppliesName | Body | String | 否 | 纯手填时必填 | 不变 | +| suppliesResourceId | Body | Long | 否 | - | 不变 | +| quantity | Body | Integer | ✅ | ≥ 1 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Long | 新建备品行 ID(不变) | + +#### 请求示例 + +```json +{ "suppliesName": "雨衣", "quantity": 1, "sortOrder": 999 } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": "2102611411027066881", "success": true } +``` + +#### 空数据 / 降级响应 + +写接口,无空数据形态;创单时系统固化产品备品的路径不过本门(不变)。 + +```json +{ "code": 200, "data": "2102611411027066881", "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589598, + "message": "团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 允许:`RECRUITING`、`RESOURCE_PREPARING`;其余 589598,不落库。 +- 确认物资之后、团期确认之前仍可增删改(确认物资不锁物资清单,团期确认才锁)。 + +--- + +### 4. 调整团期备品数量 `PUT /v3/admin/order/group-batch/supplies/{batchSuppliesId}/quantity` + +**VO**: `AdjustSuppliesQuantityReqVO` → `Result` + +#### 使用场景 + +「物资」页签行内改数量。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| batchSuppliesId | Path | Long | ✅ | 须命中活跃备品行 | 不变 | +| quantity | Body | Integer | ✅ | ≥ 1 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Void | 成功返回 null | + +#### 请求示例 + +```json +{ "quantity": 5 } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": null, "success": true } +``` + +#### 空数据 / 降级响应 + +无列表出参;备品行已软删返 589521(不变)。 + +```json +{ "code": 200, "data": null, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589598, + "message": "团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 阶段门按备品行所属团期判定,窗口同新增口。 +- 被拒时数量不变。 + +--- + +### 5. 软删团期备品行 `DELETE /v3/admin/order/group-batch/supplies/{batchSuppliesId}` + +**VO**: `Result`(无请求体) + +#### 使用场景 + +「物资」页签删除一行备品。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| batchSuppliesId | Path | Long | ✅ | 须命中活跃备品行 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Void | 成功返回 null | + +#### 请求示例 + +```http +DELETE /v3/admin/order/group-batch/supplies/2102611411027066881 HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": null, "success": true } +``` + +#### 空数据 / 降级响应 + +对已软删的行再调返 589521(不变)。 + +```json +{ "code": 200, "data": null, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589598, + "message": "团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 窗口同新增口;被拒时该行不被软删。 + +--- + +### 6. 整团按日提交订房计划 `POST /v3/admin/house/group-batches/{groupBatchId}/room-plans` + +**VO**: `GroupBatchRoomPlanSaveReqVO` → `List` + +#### 使用场景 + +房务在团期订房页按日录入订房行(追加式)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | 不变 | +| items | Body | List | ✅ | 1~200 行 | 订房行(不变) | +| items[].stayDate | Body | LocalDate | ✅ | 落在团期区间内 | 不变 | +| items[].hotelId | Body | Long | ✅ | - | 不变 | +| items[].roomTypeId | Body | Long | ✅ | - | 不变 | +| items[].roomCount | Body | Integer | ✅ | ≥ 1 | 不变 | + +其余行字段(`roomCategory` / `protoPrice` / `settlementPrice` / `settleType` / `deductInventory` / `remark`)不变。 + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| [].planId | Long | 计划行 ID(不变) | +| [].planStatus | String | `PENDING` / `CONFIRMED`(不变) | +| [].version | Integer | 乐观锁版本(不变) | + +其余字段不变。 + +#### 请求示例 + +```json +{ "items": [ { "stayDate": "2026-10-01", "hotelId": 200001, "roomTypeId": 300001, "roomCount": 3 } ] } +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ { "planId": "2103000000000000001", "stayDate": "2026-10-01", "roomCount": 3, "planStatus": "PENDING", "version": 0 } ], + "success": true +} +``` + +#### 空数据 / 降级响应 + +`items` 不能为空(400,不变);成功时返回本次新建的行。 + +```json +{ "code": 200, "data": [], "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808600, + "message": "团期当前阶段(MATERIAL_PREPARING)不允许修改订房计划:订房计划仅在配置阶段可改,团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 允许:仅 `RESOURCE_PREPARING`。改前 `RESOURCE_PREPARING` ~ `REVIEWING` 六态可写。 +- 808600 的 `{0}` 是团期当前状态码。 + +--- + +### 7. 修改单条订房计划 `PUT /v3/admin/house/group-batches/{groupBatchId}/room-plans/{planId}` + +**VO**: `GroupBatchRoomPlanItemReqVO` → `GroupBatchRoomPlanRespVO` + +#### 使用场景 + +房务修改一条订房行(关键字段变化即删旧建新)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| planId | Path | Long | ✅ | - | 不变 | +| version | Body | Integer | ✅ | 乐观锁 | 不变 | +| roomCount | Body | Integer | 否 | ≥ 1 | 不变 | +| replaceReason | Body | String | 否 | ≤ 256 | 原「核单中团期必填」,本次起核单中已不可改,该约束不再触发 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| planId | Long | 不变 | +| planStatus | String | 不变 | +| version | Integer | 不变 | +| warnings | List<String> | 不变 | + +#### 请求示例 + +```json +{ "version": 0, "roomCount": 4 } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "planId": "2103000000000000001", "roomCount": 4, "planStatus": "PENDING", "version": 1, "warnings": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +无列表出参;`warnings` 无告警时为空数组(不变)。 + +```json +{ "code": 200, "data": { "warnings": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808600, + "message": "团期当前阶段(PENDING_DEPARTURE)不允许修改订房计划:订房计划仅在配置阶段可改,团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`;返团后按实际入住修正计划不再允许,差异走核单成本 / 冲正。 +- 「已发生的间夜冻结」808690 在修改路径上已不可达(出行后阶段门先拦)。 + +--- + +### 8. 删除单条订房计划 `DELETE /v3/admin/house/group-batches/{groupBatchId}/room-plans/{planId}` + +**VO**: `GroupBatchRoomPlanDeleteReqVO` → `GroupBatchRoomPlanDeleteRespVO` + +#### 使用场景 + +房务删除一条订房行(软删,归还库存);已流团的团也用它释放库存。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| planId | Path | Long | ✅ | - | 不变 | +| reason | Body | String | 否 | ≤ 256 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| planId | Long | 不变 | +| releasedLogId | Long | 不变 | +| warnings | List<String> | 不变 | + +#### 请求示例 + +```json +{ "reason": "客人退团,该晚不再需要" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "planId": "2103000000000000001", "releasedLogId": null, "warnings": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +从未扣过库存的行 `releasedLogId` 为 null(不变)。 + +```json +{ "code": 200, "data": { "releasedLogId": null, "warnings": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808600, + "message": "团期当前阶段(MATERIAL_PREPARING)不允许修改订房计划:订房计划仅在配置阶段可改,团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 允许:`RESOURCE_PREPARING` 与 `CANCELLED`(已流团释放库存,不变);确认后到核单中均被拒。 + +--- + +### 9. 按日确认订房 `POST /v3/admin/house/group-batches/{groupBatchId}/room-plans/days/{stayDate}/confirm` + +**VO**: `GroupBatchRoomDayConfirmRespVO` + +#### 使用场景 + +房务逐日确认订房(扣库存、分房、回填配房完成标志)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| stayDate | Path | String | ✅ | `yyyy-MM-dd` | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| confirmedPlanIds | List<Long> | 不变 | +| skippedPlanIds | List<Long> | 不变 | +| hotelReady | Boolean | 不变 | +| warnings | List | 不变 | + +#### 请求示例 + +```http +POST /v3/admin/house/group-batches/2097250563497385985/room-plans/days/2026-10-01/confirm HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "stayDate": "2026-10-01", "confirmedPlanIds": ["2103000000000000001"], "skippedPlanIds": [], "hotelReady": false, "warnings": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +该日已全部确认时幂等返回,`confirmedPlanIds` 为空、`skippedPlanIds` 列出已确认行(不变)。 + +```json +{ "code": 200, "data": { "confirmedPlanIds": [], "skippedPlanIds": ["2103000000000000001"] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808600, + "message": "团期当前阶段(MATERIAL_PREPARING)不允许修改订房计划:订房计划仅在配置阶段可改,团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`;与「可写」同一集合,不会出现「能改却确认不了」。 + +--- + +### 10. 整团确认订房 `POST /v3/admin/house/group-batches/{groupBatchId}/room-plans/confirm` + +**VO**: `GroupBatchRoomConfirmAllRespVO` + +#### 使用场景 + +房务一键整团确认订房(先整团预检,再逐日确认)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| confirmedDates | List<String> | 不变 | +| skippedDates | List<String> | 不变 | +| emptyDemand | Boolean | 不变 | +| hotelReady | Boolean | 不变 | + +#### 请求示例 + +```http +POST /v3/admin/house/group-batches/2097250563497385985/room-plans/confirm HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "confirmedDates": ["2026-10-01", "2026-10-02"], "skippedDates": [], "emptyDemand": false, "hotelReady": true, "warnings": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +全团无需订房时直接置配房完成并返回 `emptyDemand=true`(不变)。 + +```json +{ "code": 200, "data": { "confirmedDates": [], "emptyDemand": true, "hotelReady": true }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808600, + "message": "团期当前阶段(MATERIAL_PREPARING)不允许修改订房计划:订房计划仅在配置阶段可改,团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`;阶段门在整团预检第一步,被拒时零写入。 + +--- + +### 11. 订房确认预检 `GET /v3/admin/house/group-batches/{groupBatchId}/room-plans/confirm-check` + +**VO**: `GroupBatchRoomConfirmCheckReqVO` → `GroupBatchRoomConfirmCheckRespVO` + +#### 使用场景 + +订房页「确认」按钮前的只读预检。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| stayDate | Query | LocalDate | 否 | - | 不传返回全部相关日(不变) | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| stageAllowed | Boolean | **取值改变**:仅 `RESOURCE_PREPARING` 为 true(改前资源准备中 ~ 核单中为 true) | +| ready | Boolean | 整团是否可确认(含 `stageAllowed`,随之变化) | +| batchStatus | String | 不变 | +| days | List | 不变 | + +#### 请求示例 + +```http +GET /v3/admin/house/group-batches/2097250563497385985/room-plans/confirm-check HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "batchStatus": "MATERIAL_PREPARING", "stageAllowed": false, "ready": false, "days": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +无计划行时 `days` 为空数组(不变)。 + +```json +{ "code": 200, "data": { "stageAllowed": true, "ready": false, "days": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589500, + "message": "团期不存在", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 只读零副作用;确认后打开订房页,`stageAllowed=false` 可直接用来置灰确认按钮。 + +--- + +### 12. 人工微调分房 `POST /v3/admin/house/group-batches/{groupBatchId}/allocations` + +**VO**: `GroupBatchRoomAllocationSaveReqVO` → `GroupBatchRoomAllocationRebuildRespVO` + +#### 使用场景 + +房务在分房页手工调整某户落在哪条计划行。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| items | Body | List | 否 | ≤ 500 行;与 `clearPlanIds` 至少一个非空 | 不变 | +| clearPlanIds | Body | List<Long> | 否 | ≤ 200 条 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| balanced | Boolean | 不变 | +| hotelReady | Boolean | 不变 | +| days | List | 不变 | +| warnings | List | 不变 | + +#### 请求示例 + +```json +{ "items": [], "clearPlanIds": ["2103000000000000001"] } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "force": false, "balanced": true, "hotelReady": true, "days": [], "warnings": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +`days` / `warnings` 无内容时为空数组(不变)。 + +```json +{ "code": 200, "data": { "days": [], "warnings": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808600, + "message": "团期当前阶段(MATERIAL_PREPARING)不允许修改订房计划:订房计划仅在配置阶段可改,团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`;改前资源准备中 ~ 核单中可用。 + +--- + +### 13. 重算分房 `POST /v3/admin/house/group-batches/{groupBatchId}/allocations/rebuild` + +**VO**: `GroupBatchRoomAllocationRebuildReqVO` → `GroupBatchRoomAllocationRebuildRespVO` + +#### 使用场景 + +房务按当前需求基线重算分房。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| force | Body | Boolean | 否 | 默认 false | 不变 | +| stayDate | Body | LocalDate | 否 | - | 不传 = 全部已确认日(不变) | +| reason | Body | String | 否 | `force=true` 时必填 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| balanced | Boolean | 不变 | +| hotelReady | Boolean | 不变 | +| days / skippedDays | List | 不变 | + +#### 请求示例 + +```json +{ "force": false, "stayDate": "2026-10-01" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "force": false, "balanced": true, "hotelReady": true, "days": [], "skippedDays": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +未确认的日进 `skippedDays`(不变)。 + +```json +{ "code": 200, "data": { "days": [], "skippedDays": [ { "stayDate": "2026-10-02", "reason": "PLAN_NOT_CONFIRMED" } ] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808600, + "message": "团期当前阶段(MATERIAL_PREPARING)不允许修改订房计划:订房计划仅在配置阶段可改,团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`。 + +--- + +### 14. 整体确认需求缺失预检 `GET /v3/admin/order/group-batch/{groupBatchId}/requirement/confirm-check` + +**VO**: `GroupBatchRequirementCheckRespVO` + +#### 使用场景 + +「查看需求」页整体确认按钮前的只读预检。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| ready | Boolean | **取值改变**:阶段条件由「资源准备中 / 物料准备中 / 待出发 / 出行中」收紧为仅 `RESOURCE_PREPARING` | +| batchStatus / batchStatusName | String | 不变 | +| missing / vehicleMissing | List | 不变 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2097250563497385985/requirement/confirm-check HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "batchStatus": "MATERIAL_PREPARING", "batchStatusName": "物料准备中", "ready": false, "missing": [], "vehicleMissing": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +无缺失时两个缺失清单为空数组(不变)。 + +```json +{ "code": 200, "data": { "ready": true, "missing": [], "vehicleMissing": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589500, + "message": "团期不存在", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 缺失清单为空但 `ready=false`,说明卡在团期阶段;确认后打开该页恒为 false。 + +--- + +### 15. 整体确认需求 `POST /v3/admin/order/group-batch/{groupBatchId}/requirement/confirm` + +**VO**: `GroupBatchRequirementConfirmRespVO` + +#### 使用场景 + +团期管理员整体确认需求、放行房务 / 车务。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| requirementConfirmed | Boolean | 不变 | +| dispatchedOrderIds / skippedOrderIds | List<Long> | 不变 | +| groupVehicleRequirementStatus | String | 不变 | + +#### 请求示例 + +```http +POST /v3/admin/order/group-batch/2097250563497385985/requirement/confirm HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "requirementConfirmed": true, "dispatchedOrderIds": ["60123456789001"], "skippedOrderIds": [], "dispatchedCount": 1 }, "success": true } +``` + +#### 空数据 / 降级响应 + +无可放行户时 `dispatchedOrderIds` 为空数组(不变)。 + +```json +{ "code": 200, "data": { "requirementConfirmed": true, "dispatchedOrderIds": [], "dispatchedCount": 0 }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589501, + "message": "团期状态不允许当前操作", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`;改前物料准备中 / 待出发 / 出行中也可重新确认,现在一律 589501。 +- 与打回(接口 16~18)同步收紧,不会出现「能打回却确认不了」。 + +--- + +### 16. 按户打回需求(整团入口) `POST /v3/admin/order/group-batch/{groupBatchId}/requirement/reject` + +**VO**: `RejectRequirementReqVO` → `GroupBatchRequirementRejectRespVO` + +#### 使用场景 + +「查看需求」页勾选多户打回给定制师重提。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| orderIds | Body | List<Long> | ✅ | 1~200 户 | 不变 | +| reason | Body | String | ✅ | ≤ 500 字 | 不变 | +| resourceType | Body | String | 否 | `HOTEL` / `VEHICLE` / `ALL`,默认 `ALL` | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| requirementConfirmed | Boolean | 成功后恒 false(不变) | +| rejected[] | List | 每户每资源类型一条(不变) | + +#### 请求示例 + +```json +{ "orderIds": ["60123456789001"], "reason": "房型数量与人数不符,请重报", "resourceType": "HOTEL" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "requirementConfirmed": false, "rejected": [ { "orderId": "60123456789001", "resourceType": "HOTEL", "requirementId": "90011223344", "sourceStatus": "PENDING_REVIEW" } ] }, "success": true } +``` + +#### 空数据 / 降级响应 + +所选户均无可打回的需求时 `rejected` 为空数组(不变)。 + +```json +{ "code": 200, "data": { "requirementConfirmed": false, "rejected": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589501, + "message": "团期状态不允许当前操作", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`。改前除已流团外全程可用(含招募中),**招募中现在也被拒**。 + +--- + +### 17. 团期管理员打回住宿需求(逐单) `POST /v3/admin/order/{id}/hotel-requirement/reject` + +**VO**: `RejectReqVO` → `Result` + +#### 使用场景 + +逐户需求详情里单独打回住宿需求。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| id | Path | Long | ✅ | 子订单 ID | 不变 | +| returnRemark | Body | String | ✅ | ≤ 500 字 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Void | 成功返回 null | + +#### 请求示例 + +```json +{ "returnRemark": "第二晚缺房型,请补充" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": null, "success": true } +``` + +#### 空数据 / 降级响应 + +无列表出参。 + +```json +{ "code": 200, "data": null, "success": true } +``` + +#### 错误响应 + +所属团期不在 `RESOURCE_PREPARING`: + +```json +{ + "code": 589501, + "message": "团期状态不允许当前操作", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- **新增阶段门**:改前逐单打回不看团期阶段;现在仅 `RESOURCE_PREPARING`。 +- 非团期订单仍返 582083(不变)。 + +--- + +### 18. 团期管理员打回用车需求(逐单) `POST /v3/admin/order/{id}/vehicle-requirement/reject` + +**VO**: `RejectReqVO` → `Result` + +#### 使用场景 + +逐户需求详情里单独打回行程用车或接送机需求。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| id | Path | Long | ✅ | 子订单 ID | 不变 | +| kind | Query | String | 否 | `TRAVEL` / `TRANSFER`,默认 `TRAVEL` | 不变 | +| returnRemark | Body | String | ✅ | ≤ 500 字 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Void | 成功返回 null | + +#### 请求示例 + +```json +{ "returnRemark": "用车人数与报名人数不符" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": null, "success": true } +``` + +#### 空数据 / 降级响应 + +无列表出参。 + +```json +{ "code": 200, "data": null, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589501, + "message": "团期状态不允许当前操作", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- **新增阶段门**:仅 `RESOURCE_PREPARING`;非团期订单仍返 582083。 + +--- + +### 19. 保存团期正式用车需求 `PUT /v3/admin/order/group-batch/{groupBatchId}/vehicle-requirement` + +**VO**: `GroupVehicleRequirementSaveReqVO` → `GroupVehicleRequirementRespVO` + +#### 使用场景 + +团期管理员编辑整团乘车分组(全量替换)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| version | Body | Integer | 否 | 首次保存传 null | 不变 | +| remark | Body | String | 否 | ≤ 500 字 | 不变 | +| groups | Body | List | ✅ | 不能为 null | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| requirementId | Long | 不变 | +| status | String | 不变 | +| version | Integer | 不变 | +| groups | List | 不变 | + +#### 请求示例 + +```json +{ "version": 3, "groups": [ { "groupCode": "BUS", "vehicleType": "BUS", "serviceStartDate": "2026-10-01", "serviceEndDate": "2026-10-03", "seats": 35, "count": 1, "days": [ { "tripDate": "2026-10-01", "headcount": 30, "memberOrderIds": ["60123456789001"] } ] } ] } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "requirementId": "1867000000101", "groupBatchId": "2097250563497385985", "status": "DRAFT", "version": 4, "groups": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +整团免车请走 `waive`,本接口 `groups` 为 null 返 400(不变)。 + +```json +{ "code": 200, "data": { "status": "DRAFT", "groups": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589501, + "message": "团期状态不允许当前操作", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`;改前资源准备中 / 物料准备中 / 待出发 / 出行中可用。 + +--- + +### 20. 受控重开正式用车需求 `POST /v3/admin/order/group-batch/{groupBatchId}/vehicle-requirement/reopen` + +**VO**: `GroupVehicleRequirementReopenReqVO` → `GroupVehicleReopenRespVO` + +#### 使用场景 + +把已被车务执行的正式用车需求退回可改(带令牌、范围、有效期的窗口)。本次起只在配置阶段可用,是配置阶段内把已完成的用车需求改回的唯一出口。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| reason | Body | String | ✅ | ≤ 200 | 不变 | +| scopeGroupCodes | Body | List<String> | ✅ | 1~20 个 | 不变 | +| scopeDates | Body | List<LocalDate> | ✅ | 1~60 天 | 不变 | +| windowMinutes | Body | Integer | 否 | 10~1440,默认 120 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| requirementId | Long | 不变 | +| requirementStatus | String | 不变 | +| windowToken | String | 不变 | +| expiresAt | LocalDateTime | 不变 | +| blockedStage | String | 本次起恒为 `RESOURCE_PREPARING` | + +#### 请求示例 + +```json +{ "reason": "客户临时增加 2 人,需要加一辆车", "scopeGroupCodes": ["BUS"], "scopeDates": ["2026-10-01"], "windowMinutes": 120 } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "requirementId": "1934567890123456789", "requirementVersion": 3, "requirementStatus": "PENDING_RECONFIRM", "windowToken": "窗口令牌示例", "expiresAt": "2026-09-24 12:00:00", "blockedStage": "RESOURCE_PREPARING", "batchStatus": "RESOURCE_PREPARING" }, "success": true } +``` + +#### 空数据 / 降级响应 + +同一操作人重复开窗幂等返回既有令牌(不变)。 + +```json +{ "code": 200, "data": { "requirementStatus": "PENDING_RECONFIRM", "windowToken": "窗口令牌示例" }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 809111, + "message": "团期当前状态 MATERIAL_PREPARING 不允许编辑、确认或重开正式用车需求:仅配置阶段可改,团期已确认,配置不可修改", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 仅 `RESOURCE_PREPARING`;改前物料准备中 / 待出发也可重开(#7442 窗口),本次起下线。 +- 809101 / 809203 / 809209 等其余拒绝条件不变。 + +--- + +### 21. 声明整团无需用车 `POST /v3/admin/order/group-batch/{groupBatchId}/vehicle-requirement/waive` + +**VO**: `GroupVehicleRequirementWaiveReqVO` → `GroupVehicleRequirementRespVO` + +#### 使用场景 + +纯自驾等整团不用车的团声明免车。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 不变 | +| reason | Body | String | ✅ | ≤ 200 字 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| status | String | 不变 | +| groups | List | 免车态为空数组(不变) | + +#### 请求示例 + +```json +{ "reason": "纯自驾团,客户自理交通" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "requirementId": "1867000000101", "status": "CONFIRMED", "groups": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +已是免车态时幂等返回(不变)。 + +```json +{ "code": 200, "data": { "status": "CONFIRMED", "groups": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589501, + "message": "团期状态不允许当前操作", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 允许:`RESOURCE_PREPARING`、`TRIP_FINISHED`、`REVIEWING`。改前另含 `MATERIAL_PREPARING` / `PENDING_DEPARTURE` / `TRAVELLING`,本次去掉。 +- 出行完毕 / 核单中仍可补点免车(结算闸需要),不属于「确认后改配置」。 +- 809114 等其余拒绝条件不变。 + +--- + +### 22. 团期抢单池列表 `GET /v3/admin/order/grab-pool/group-batches` + +**VO**: `HouseGroupGrabPoolPageReqVO` → `PageResult` + +#### 使用场景 + +房务端整团抢单池(一团一条)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| batchStatus | Query | String | 否 | **只接受 `RESOURCE_PREPARING`** | **本次收窄**:改前接受 `RESOURCE_PREPARING` / `MATERIAL_PREPARING` / `PENDING_DEPARTURE` / `TRAVELLING` | +| keyword | Query | String | 否 | ≤ 32 字 | 不变 | +| productId | Query | Long | 否 | - | 不变 | +| departDateFrom / departDateTo | Query | LocalDate | 否 | - | 不变 | +| page | Query | Integer | 否 | ≥ 1,默认 1 | 不变 | +| pageSize | Query | Integer | 否 | 1~100,默认 20 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| records[].groupBatchId | Long | 不变 | +| records[].batchStatus | String | **行集合改变**:本次起恒为 `RESOURCE_PREPARING` | +| records[].batchStatusLabel | String | 恒为「资源准备中」 | +| records[].hotelReady | Boolean | 不变 | +| total | Long | 不变 | + +#### 请求示例 + +```http +GET /v3/admin/order/grab-pool/group-batches?batchStatus=RESOURCE_PREPARING&page=1&pageSize=20 HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "total": 1, "records": [ { "groupBatchId": "2097250563497385985", "batchNo": "GB26100101", "batchStatus": "RESOURCE_PREPARING", "batchStatusLabel": "资源准备中", "hotelReady": false, "urgencyLevel": "NORMAL" } ] }, "success": true } +``` + +#### 空数据 / 降级响应 + +无可认领团期时空页(不变)。 + +```json +{ "code": 200, "data": { "total": 0, "records": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ "code": 400, "message": "batchStatus 只接受 RESOURCE_PREPARING", "success": false, "data": null } +``` + +#### 业务边界 + +- 入池条件:未被认领 + 需求已整体确认 + 团期在 `RESOURCE_PREPARING`;确认后的团不再出现在池里。 +- 不传 `batchStatus` 即可,前端筛选下拉若保留其它三个值会得到 400。 + +--- + +### 23. 整团认领 `POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/claim` + +**VO**: `Result`(无请求体) + +#### 使用场景 + +房务在抢单池点「认领」整团。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| data | Void | 成功返回 null | + +#### 请求示例 + +```http +POST /v3/admin/order/grab-pool/group-batches/2097250563497385985/claim HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": null, "success": true } +``` + +#### 空数据 / 降级响应 + +无列表出参。 + +```json +{ "code": 200, "data": null, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808651, + "message": "该团期当前不可认领(需求未整体确认或团期阶段不允许)", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 团期阶段须为 `RESOURCE_PREPARING`;改前物料准备中 / 待出发 / 出行中也可认领。 +- 已被他人认领 / 自己已认领的码不变。 + +--- + +### 24. 团级接管(超管) `POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/takeover` + +**VO**: `HouseGroupTakeoverReqVO` → `HouseGroupTakeoverRespVO` + +#### 使用场景 + +超管把某团的房务认领人改派给另一位房务(如原认领人离职)。与整团认领共用同一阶段集合。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | 不变 | +| toUserId | Body | Long | ✅ | 须为在职房务 | 不变 | +| reason | Body | String | ✅ | trim 后 10~200 字 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| groupBatchId | Long | 不变 | +| fromClaimerId / toClaimerId | Long | 不变 | +| toClaimerName | String | 不变 | +| clearedOrderIds / legacyFinalizedOrderIds / skippedOrderIds | List<String> | 不变 | + +#### 请求示例 + +```json +{ "toUserId": 30002, "reason": "原认领房务离职,指派新房务接管该团" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "fromClaimerId": "30001", "toClaimerId": "30002", "toClaimerName": "李四", "clearedOrderIds": [], "legacyFinalizedOrderIds": [], "skippedOrderIds": [] }, "success": true } +``` + +#### 空数据 / 降级响应 + +没有需要清理的户级归属时三个列表为空数组(不变)。 + +```json +{ "code": 200, "data": { "clearedOrderIds": [], "legacyFinalizedOrderIds": [], "skippedOrderIds": [] }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 808651, + "message": "该团期当前不可认领(需求未整体确认或团期阶段不允许)", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 团期阶段须为 `RESOURCE_PREPARING`;改前物料准备中 / 待出发 / 出行中也可接管。确认后的团要换房务负责人,本接口不再可用。 +- 非超管、原因过短等其余拒绝码不变。 + +--- + +## 四、契约约束与正确调用方式 + +### ✅ 正确 / ❌ 错误调用对照 + +| 场景 | 结果 | +|------|------| +| ✅ 招募中配导游 / 摄影 / 物资 | 200 | +| ✅ 配置中改订房、改用车、打回需求、重开用车 | 200 | +| ❌ 确认后(`MATERIAL_PREPARING`)保存导摄或改物资 | 589598「团期已确认,配置不可修改」 | +| ❌ 确认后改订房 / 确认订房 / 分房 | 808600 | +| ❌ 确认后整体确认需求、打回需求、保存用车需求 | 589501 | +| ❌ 确认后受控重开用车 | 809111 | +| ❌ 抢单池 `batchStatus=MATERIAL_PREPARING` | 400 | + +### 文案变化(码值不变) + +| code | 改前 message | 改后 message | +|---|---|---| +| 589598 | 出行后不可再配置导游 / 摄影 / 物资 | 团期已确认,配置不可修改 | +| 808600 | 团期当前阶段({0})不允许修改订房计划 | 团期当前阶段({0})不允许修改订房计划:订房计划仅在配置阶段可改,团期已确认,配置不可修改 | +| 809111 | 团期当前状态 {0} 不允许编辑、确认或重开正式用车需求 | 团期当前状态 {0} 不允许编辑、确认或重开正式用车需求:仅配置阶段可改,团期已确认,配置不可修改 | + +前端按码值分支即可;按原文案做过匹配的需改。 + +--- + +## 五、数据库行为 + +- 所有接口在阶段门被拒时**零写入**:阶段门位于任何写库动作之前。 +- 放行时的写入行为与改前完全一致(本单只改允许的阶段集合与拒绝文案),不新增、不删除任何写入。 +- 抢单池与两个预检接口只读。 + +--- + +## 六、边界行为 + +- 未登录 → 401(网关拦截)。 +- 团期不存在 → 589500 / 各域既有「不存在」码(不变)。 +- 已流团:导摄物资 589598、订房计划只允许删除 / 整团释放、需求与用车一律 589501 / 809111。 +- 子订单退单、转团、加人不受本单影响(只锁团期配置,不锁子订单)。 +- 满团名额调整(招募、配置)、流团(招募 ~ 待出发)窗口不变。 +- 核单中订房修改的 808617、出行中的 808690 两道守卫在修改路径上已不可达。 + +--- + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| 抢单池入参 `batchStatus` 可选值 | `RESOURCE_PREPARING` / `MATERIAL_PREPARING` / `PENDING_DEPARTURE` / `TRAVELLING` | 仅 `RESOURCE_PREPARING` | +| 订房预检 `stageAllowed` | 资源准备中 ~ 核单中为 true | 仅资源准备中为 true | +| 需求预检 `ready` 的阶段条件 | 资源准备中 / 物料准备中 / 待出发 / 出行中 | 仅资源准备中 | +| 589598 / 808600 / 809111 message | 见「四」改前列 | 见「四」改后列 | + +### 行为级对比 + +| 写口 | 改前允许 | 改后允许 | +|------|----------|----------| +| 导游 / 摄影 / 物资(接口 1~5) | 招募 / 配置 / 物料准备中 / 待出发 | 招募 / 配置 | +| 订房计划新增 / 修改 / 按日确认 / 整团确认 / 分房微调 / 重算(接口 6、7、9、10、12、13) | 资源准备中 ~ 核单中 | 资源准备中 | +| 订房计划删除(接口 8) | 资源准备中 ~ 核单中 + 已流团 | 资源准备中 + 已流团 | +| 需求整体确认(接口 15) | 资源准备中 / 物料准备中 / 待出发 / 出行中 | 资源准备中 | +| 整团打回(接口 16) | 除已流团外全程 | 资源准备中 | +| 逐单打回(接口 17、18) | 不看团期阶段 | 资源准备中 | +| 保存正式用车需求(接口 19) | 资源准备中 / 物料准备中 / 待出发 / 出行中 | 资源准备中 | +| 受控重开(接口 20) | 资源准备中 / 物料准备中 / 待出发 | 资源准备中 | +| 免车(接口 21) | 资源准备中 / 物料准备中 / 待出发 / 出行中 / 出行完毕 / 核单中 | 资源准备中 / 出行完毕 / 核单中 | +| 整团认领 / 团级接管(接口 23、24) | 资源准备中 / 物料准备中 / 待出发 / 出行中 | 资源准备中 | + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 是。确认后的写操作全部被拒;抢单池 `batchStatus` 旧可选值返 400;589598 文案变化。 +- **前端是否必须同步上线**: 否(后端拒绝即安全),但建议同步:确认后隐藏或置灰上述入口,否则用户点了才看到报错;抢单池筛选下拉若保留旧选项会触发 400。 +- **前端 workaround 清理点**: #8231 交接时物资页签「出行前四态放行」的显隐判据需收回到招募 / 配置两态;按 589598 原文案做匹配的地方改为按码值。 + +--- + +## 七、不影响范围 + +- **仅影响**: 上述 24 个接口的允许阶段与 3 个错误码的文案。 +- **零影响**: + - 子订单退单 / 转团 / 加人 + - 满团名额调整、流团、取消成团 + - 订房计划整团批量释放(仅已流团,不变) + - 各接口的路径、权限码、入参结构、成功响应结构 + - 小程序端 + +--- + +## 八、测试环境已验证 + +部署:hl-order-service-v3 = dev-v3 @ d9fdd7fe0 / ade8ac292,经网关 `https://api.test.1814.love` 真实鉴权实测(2026-09-24 09:28–09:58);工单 #8269 已验收关单。 + +| # | 场景 | 结果 | +|---|---|---| +| 1 | 招募 / 配置阶段 staff 保存、物资增改删 | 均 200 | +| 2 | 确认后 staff 修改 / 清空、物资增改删 | 589598「团期已确认,配置不可修改」,数据回读不变;待出发抽查同样拒绝 | +| 3 | 确认后车务受控重开 / 改正式用车需求 / 免车 | 809111 / 589501 / 589501,需求读回不变 | +| 4 | 订房计划:配置阶段增改删、整团确认 | 可用;确认后新增 / 修改 / 删除 / 按日确认 / 整团确认 / 微调均 808600;流团后 release-all 过阶段门 | +| 5 | 需求整体确认 / 批量打回 / 逐单打回 | 配置阶段可用;确认后均 589501 | +| 6 | 房务抢单池 `batchStatus` | `MATERIAL_PREPARING` → 400;`RESOURCE_PREPARING` → 200 | +| 7 | 确认后子订单取消、同班期新下子订单 | 均 200,团期状态不变 | + +--- + +## 九、相关历史 PR + +| PR | Issue | 说明 | 是否仍有效 | +|----|-------|------|------------| +| #8234 / #8237 | #8231 | 导游 / 摄影 / 物资放开到出行前四态 | ❌ 窗口被本单收回到招募 / 配置 | +| — | #7442 | 车务受控重开(物料准备中 / 待出发窗口) | ❌ 窗口被本单收回到配置 | +| — | #7210 | 需求整体确认与打回 | ⚠️ 阶段集合被本单收紧 | +| — | #7324 | 订房计划可写到核单中(返团后修正) | ❌ 本单收回 | +| **本 PR #8280** | **#8269** | 确认后锁定配置 | ✅ 最新 | + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#8269](https://git.1814.love/wx/HL/issues/8269) +- 关联 PR: [wx/HL#8280](https://git.1814.love/wx/HL/pulls/8280) +- 被本条取代的窗口描述:`changelogs-v2/2026-09/23_8231_配导游配摄影物资放开到出行前四态-修改接口-管理后台.md` +- 同批六节点条目:团期人工确认(#8268)、六节点展示与看板七桶(#8271) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8269](https://git.1814.love/wx/HL/issues/8269) +- **PR**: [#8280](https://git.1814.love/wx/HL/pulls/8280) +- **Merge commit**: [7111a8cae](https://git.1814.love/wx/HL/commit/7111a8caef4aedda7ec73d4bb94972ae31dbc4b9) + +### 联系人 + +- **后端负责人**: @jw diff --git a/changelogs-v2/2026-09/24_8271_团期看板与详情按六节点展示看板改七桶-修改接口-管理后台.md b/changelogs-v2/2026-09/24_8271_团期看板与详情按六节点展示看板改七桶-修改接口-管理后台.md new file mode 100644 index 00000000..8d8b3eec --- /dev/null +++ b/changelogs-v2/2026-09/24_8271_团期看板与详情按六节点展示看板改七桶-修改接口-管理后台.md @@ -0,0 +1,800 @@ +--- +schema: "hl-changelog/v2" +ticket: "8271" +title: "团期看板与详情按六节点展示:分页 / 详情 / 看板行新增 stage 与出行子状态,统计条与 opsStage 改七桶(旧八桶过渡期兼容),核团 / 验团用语统一为核单 / 结算" +consumer: "admin" +author: "jw(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "2026-09-24" +status_note: "六节点定案(SRS §0.27.1 / §0.27.4):持久九态 batchStatus 不动,服务端派生节点 stage(RECRUIT 招募 / CONFIGURE 配置 / CONFIRM 确认 / TRIP 出行 / REVIEW 核单 / SETTLE 结算 / DISBANDED 已流团)与出行子状态 tripSubStatus(待出发 / 出行中 / 已返团),只供展示。团期分页、详情、看板行新增 stage / stageName / tripSubStatus / tripSubStatusName 四字段;既有字段 opsStage 的取值由八桶改为七桶(与 stage 逐字同值);统计条 buckets 固定 13 键 = 七桶 + 6 个旧八桶别名键(别名键不计入 total);opsStage 筛选接受七桶,旧八桶 code 过渡期按原口径兼容;导出 CSV「状态」列改为节点名。PR #8303 补充:面向用户的核团 / 验团用语统一为核单 / 结算(6 个错误码文案、时间线事件中文标签、核单状态 CHECKED 中文名),码值与存储值不变。前端需把看板页签与统计条切到七桶、详情页按 stage / tripSubStatus 展示节点;旧八桶别名在前端切换完成前保留。" +updated_at: "2026-09-24" +base: "dev-v3" +--- + +# 团期看板: 按六节点展示,统计条与筛选改七桶(管理后台) + +> **服务**: hl-order-service-v3(端口 8086/8186) +> **PR**: #8276(代码)、#8279(文档)、#8303(核单 / 结算用语) +> **Issue**: #8271 +> **日期**: 2026-09-24 +> **影响范围**: 管理后台团期看板(页签、统计条、列表行、导出)、团期详情头部节点展示、团期时间线与核单 / 结算相关报错文案 + +--- + +## ⚠️ 关键变化 + +1. **`opsStage` 响应取值变了**:以前是八桶(`FORMED` / `PENDING_TRIP` / `TRAVELLING` / `TRIP_FINISHED` / `AUDITING` / `CHECKED` …),现在只输出七桶(`CONFIGURE` / `CONFIRM` / `TRIP` / `REVIEW` / `SETTLE` …),且与新字段 `stage` 逐字同值。按旧值做过 `switch` 的前端代码会落到默认分支。 +2. **原「已成团」一桶拆成两桶**:`RESOURCE_PREPARING` → 配置(`CONFIGURE`),`MATERIAL_PREPARING` → 确认(`CONFIRM`);原「待出行 / 出行中 / 出行完毕」三桶合成一个「出行」(`TRIP`),细分看 `tripSubStatus`。 +3. **统计条 `buckets` 从 8 键变 13 键**:七桶在前、6 个旧别名键在后。`total` 只等于七桶之和,**不要再对 `buckets` 整体求和**(会重复计数)。 +4. **旧入参仍然能用**:页签继续传旧八桶 code 给 `opsStage` 筛选,结果与改前逐条一致(按原口径展开);统计条的旧键名计数也照旧给。 +5. **用语**:「核团中 / 已验团」改为「核单 / 结算」,涉及 6 个错误码文案、时间线事件中文名、核单状态 `CHECKED` 的中文名;码值与存储值一律不变。 + +--- + +## 一、背景 + +团期六节点定案:看板与详情按「招募 → 配置 → 确认 → 出行 → 核单 → 结算」展示,另有分叉终态「已流团」。持久九态 `batchStatus` 不动、不新增持久列,节点与出行子状态由服务端唯一派生,**只供展示,不承担业务判断**——按钮可用性、权限仍以 `batchStatus` 与各就绪位为准。 + +| 节点 `stage` | `stageName` | 覆盖的 `batchStatus` | 说明 | +|---|---|---|---| +| `RECRUIT` | 招募 | `RECRUITING` | 未建团行(产品侧有班期、订单侧尚无团期)也恒为 `RECRUIT` | +| `CONFIGURE` | 配置 | `RESOURCE_PREPARING` | 配房 / 车 / 导游领队 / 摄影与物资,确认前可改 | +| `CONFIRM` | 确认 | `MATERIAL_PREPARING` | 人工确认后配置锁定,逐户出合同与保险 | +| `TRIP` | 出行 | `PENDING_DEPARTURE`、`TRAVELLING`、`TRIP_FINISHED` | 复合节点,细分见 `tripSubStatus` | +| `REVIEW` | 核单 | `REVIEWING` | 原「核团中」 | +| `SETTLE` | 结算 | `SETTLED` | 原「已验团」 | +| `DISBANDED` | 已流团 | `CANCELLED` | 分叉终态 | + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 团期分页列表(GB-ADM-001) | GET | `/v3/admin/order/group-batch` | 出参新增字段 + 出参取值变化 + 入参取值扩展 | 新增四字段;`opsStage` 出参改七桶;`opsStage` 筛选接受七桶并兼容旧八桶 | +| 2 | 团期详情(GB-ADM-002) | GET | `/v3/admin/order/group-batch/{groupBatchId}` | 出参新增字段 + 出参取值变化 | 新增四字段;`opsStage` 改七桶 | +| 3 | 团期看板列表 | GET | `/v3/admin/order/group-batch/board` | 出参新增字段 + 出参取值变化 | 命中 / 未命中 / 孤儿三类行均带四字段;`opsStage` 改七桶 | +| 4 | 团期看板统计条(GB-ADM-009) | GET | `/v3/admin/order/group-batch/summary` | 出参取值变化 | `buckets` 13 键;`total` = 七桶之和 | +| 5 | 导出团期列表 CSV(GB-ADM-008) | GET | `/v3/admin/order/group-batch/export` | 入参取值扩展 + 导出内容变化 | `opsStage` 同分页口径;「状态」列改为节点名 | +| 6 | 团期状态流水(GB-ADM-096) | GET | `/v3/admin/order/group-batch/{groupBatchId}/status-logs` | 出参取值变化(文案) | 5 个核团 / 验团事件的 `eventTypeName` 改为核单 / 结算用语 | + +路径、HTTP 方法、权限码、信封结构均不变;网关无改动。 + +--- + +## 三、接口详情 + +### 1. 团期分页列表 `GET /v3/admin/order/group-batch` + +**VO**: `GroupBatchListReqVO` → `PageResult` + +#### 使用场景 + +团期看板主列表(按页签筛选)。页签既可以传七桶 code,也可以继续传旧八桶 code。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| opsStage | Query | String | 否 | 七桶或旧八桶 code;空白 / 非法值忽略 | **本次改取值**:七桶 `RECRUIT` / `CONFIGURE` / `CONFIRM` / `TRIP` / `REVIEW` / `SETTLE` / `DISBANDED`;旧八桶 `FORMED` / `PENDING_TRIP` / `TRAVELLING` / `TRIP_FINISHED` / `AUDITING` / `CHECKED` 过渡期仍按原口径展开 | +| scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL` | 班期范围;与 `opsStage` 取交集(不变) | +| productId | Query | Long | 否 | - | 按产品筛选(不变) | +| batchStatus | Query | String | 否 | 九态 code | 精确九态筛选(不变) | +| month | Query | String | 否 | `yyyy-MM` | 出发月份(不变) | +| keyword | Query | String | 否 | - | 班期编号 / 名称模糊(不变) | +| pageNo | Query | Integer | 否 | 默认 1 | 页码(不变) | +| pageSize | Query | Integer | 否 | 默认 20,最大 100 | 每页条数(不变) | + +其余既有筛选参数(`deadlineFrom` / `deadlineTo` / `departFrom` / `departTo` / `sortBy` / `sortOrder`)不变。 + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| records[].batchStatus | String | 持久九态,**业务判断用这个**(不变) | +| records[].batchStatusName | String | 九态中文名(不变,如「资源准备中」「出行完毕」) | +| records[].stage | String | **新增**。节点 code,取值见「一、背景」七个 | +| records[].stageName | String | **新增**。节点中文名,与 `stage` 同生同灭 | +| records[].tripSubStatus | String | **新增**。出行子状态 `PENDING_DEPARTURE` / `TRAVELLING` / `TRIP_FINISHED`;仅 `stage = TRIP` 时有值,其余为 null | +| records[].tripSubStatusName | String | **新增**。待出发 / 出行中 / 已返团;与 `tripSubStatus` 同生同灭 | +| records[].opsStage | String | **取值改变**:与 `stage` 逐字同值(七桶),旧八桶值不再输出 | +| records[].opsStageName | String | **取值改变**:与 `stageName` 同值 | +| total | Long | 命中总数(不变) | + +其余分页项字段不变。 + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch?opsStage=TRIP&scope=ALL&pageNo=1&pageSize=20 HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "total": 1, + "records": [ + { + "groupBatchId": "2099750660965584898", + "batchNo": "GB26100101", + "batchStatus": "PENDING_DEPARTURE", + "batchStatusName": "待出发", + "stage": "TRIP", + "stageName": "出行", + "tripSubStatus": "PENDING_DEPARTURE", + "tripSubStatusName": "待出发", + "opsStage": "TRIP", + "opsStageName": "出行" + } + ] + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无命中返回空页;`batchStatus` 为 null 或不在九态内的历史脏数据行,四个新字段与 `opsStage` / `opsStageName` 同为 null,不抛错: + +```json +{ "code": 200, "data": { "total": 0, "records": [] }, "success": true } +``` + +#### 错误响应 + +`opsStage` 传非法值不报错(忽略该筛选并记 warn);本接口错误形态沿用既有,如无列表权限: + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 七桶与旧别名 code 不相交,先按七桶解析、未命中再按别名解析。 +- 旧别名按**原口径**展开,不放大为新节点:`PENDING_TRIP` 仍只筛待出发,`FORMED` = 配置 + 确认。 +- 服务端严格取 `scope ∩ opsStage`:`REVIEW` / `SETTLE` 及 `TRIP` 里已返团的那部分返团日必然已过,默认 `ONGOING` 会过滤掉,点这些页签需把 `scope` 切到 `ALL`。 +- 四个新字段是纯内存映射,整页无额外查询。 + +--- + +### 2. 团期详情 `GET /v3/admin/order/group-batch/{groupBatchId}` + +**VO**: `GroupBatchDetailRespVO` + +#### 使用场景 + +团期详情页头部展示当前节点(如「出行 · 待出发」)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| batchStatus | String | 持久九态(不变) | +| batchStatusName | String | 九态中文名(不变) | +| stage | String | **新增**。节点 code | +| stageName | String | **新增**。节点中文名 | +| tripSubStatus | String | **新增**。仅 `stage = TRIP` 时有值 | +| tripSubStatusName | String | **新增**。与 `tripSubStatus` 同生同灭 | +| opsStage | String | **取值改变**:七桶,与 `stage` 同值 | +| opsStageName | String | **取值改变**:与 `stageName` 同值 | + +其余详情字段不变。 + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2097250563497385985 HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "groupBatchId": "2097250563497385985", + "batchStatus": "MATERIAL_PREPARING", + "batchStatusName": "物料准备中", + "stage": "CONFIRM", + "stageName": "确认", + "tripSubStatus": null, + "tripSubStatusName": null, + "opsStage": "CONFIRM", + "opsStageName": "确认" + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +非出行节点 `tripSubStatus` / `tripSubStatusName` 为 null;脏数据行四字段同为 null: + +```json +{ "code": 200, "data": { "batchStatus": null, "stage": null, "stageName": null, "tripSubStatus": null, "tripSubStatusName": null, "opsStage": null, "opsStageName": null }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589500, + "message": "团期不存在", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 子状态中文名「已返团」与九态 `batchStatusName`「出行完毕」不同名,两套文案各自展示,不要互相替换。 +- 前端不得用 `stage` / `tripSubStatus` 判断按钮可用性或权限。 + +--- + +### 3. 团期看板列表 `GET /v3/admin/order/group-batch/board` + +**VO**: `List` + +#### 使用场景 + +按产品展示全部班期(含未建团行与孤儿行)的看板卡片列表。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| productId | Query | Long | ✅ | - | 产品 ID(不变) | +| scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL`,缺省 `ALL` | 班期范围(不变) | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| [].batchStatus | String | 持久九态(不变);未建团行按 `RECRUITING` | +| [].stage | String | **新增**。节点 code;未建团行恒 `RECRUIT` | +| [].stageName | String | **新增**。节点中文名 | +| [].tripSubStatus | String | **新增**。仅 `stage = TRIP` 时有值 | +| [].tripSubStatusName | String | **新增** | +| [].opsStage | String | **取值改变**:七桶,与 `stage` 同值 | +| [].opsStageName | String | **取值改变**:与 `stageName` 同值 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/board?productId=100001&scope=ALL HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "groupBatchId": "2097250563497385985", + "batchStatus": "TRAVELLING", + "stage": "TRIP", + "stageName": "出行", + "tripSubStatus": "TRAVELLING", + "tripSubStatusName": "出行中", + "opsStage": "TRIP", + "opsStageName": "出行" + }, + { + "productBatchId": "2097250420299530242", + "batchStatus": "RECRUITING", + "stage": "RECRUIT", + "stageName": "招募", + "tripSubStatus": null, + "tripSubStatusName": null, + "opsStage": "RECRUIT", + "opsStageName": "招募" + } + ], + "success": true +} +``` + +#### 空数据 / 降级响应 + +产品无班期时返回空数组: + +```json +{ "code": 200, "data": [], "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 命中 / 未命中 / 孤儿三类行统一带四个新字段。 +- 行集合、排序、其余字段均不变。 + +--- + +### 4. 团期看板统计条 `GET /v3/admin/order/group-batch/summary` + +**VO**: `GroupBatchSummaryVO` + +#### 使用场景 + +看板顶部各页签的计数。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| productId | Query | Long | 否 | - | 不变 | +| month | Query | String | 否 | `yyyy-MM` | 不变 | +| keyword | Query | String | 否 | - | 不变 | +| scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL` | 不变 | + +本接口不接受 `opsStage`(它的作用正是给出各桶数量)。 + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| total | Integer | **口径改变**:= 七桶之和(旧别名键不计入) | +| buckets | Map<String, Integer> | **键集合改变**:固定 13 键,无命中为 0;前 7 键为七桶,后 6 键为旧八桶别名 | +| subOrderCount | Integer | 命中团期的活跃子订单合计(不变) | +| effectiveScope | String | 实际生效的班期范围(不变) | +| filteredOutCount | Integer | 被范围过滤掉的团期数(不变) | + +`buckets` 13 键口径: + +| 键 | 计数口径 | 计入 `total` | +|---|---|---| +| `RECRUIT` / `CONFIGURE` / `CONFIRM` / `TRIP` / `REVIEW` / `SETTLE` / `DISBANDED` | 七桶;`TRIP` = 待出发 + 出行中 + 已返团 | ✅ | +| `FORMED` | 旧别名 = `RESOURCE_PREPARING` + `MATERIAL_PREPARING` | ❌ | +| `PENDING_TRIP` | 旧别名 = `PENDING_DEPARTURE` | ❌ | +| `TRAVELLING` | 旧别名 = `TRAVELLING` | ❌ | +| `TRIP_FINISHED` | 旧别名 = `TRIP_FINISHED` | ❌ | +| `AUDITING` | 旧别名 = `REVIEWING` | ❌ | +| `CHECKED` | 旧别名 = `SETTLED` | ❌ | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/summary?scope=ALL HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "total": 12, + "buckets": { + "RECRUIT": 3, + "CONFIGURE": 2, + "CONFIRM": 1, + "TRIP": 4, + "REVIEW": 1, + "SETTLE": 0, + "DISBANDED": 1, + "FORMED": 3, + "PENDING_TRIP": 2, + "TRAVELLING": 1, + "TRIP_FINISHED": 1, + "AUDITING": 1, + "CHECKED": 0 + }, + "subOrderCount": 57, + "effectiveScope": "ALL", + "filteredOutCount": 0 + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无命中时 13 键全部为 0: + +```json +{ "code": 200, "data": { "total": 0, "buckets": { "RECRUIT": 0, "CONFIGURE": 0, "CONFIRM": 0, "TRIP": 0, "REVIEW": 0, "SETTLE": 0, "DISBANDED": 0, "FORMED": 0, "PENDING_TRIP": 0, "TRAVELLING": 0, "TRIP_FINISHED": 0, "AUDITING": 0, "CHECKED": 0 }, "subOrderCount": 0 }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 按键名读取,不要依赖 Map 下标;也不要对 `buckets` 整体求和。 +- `RECRUIT` / `DISBANDED` 新旧同名同义,不重复出现。 +- 状态不在九态内的行被排除,不计入任何桶。 + +--- + +### 5. 导出团期列表 CSV `GET /v3/admin/order/group-batch/export` + +**VO**: `text/csv` 附件(非 `Result` 信封) + +#### 使用场景 + +看板「导出」按钮,按当前筛选导出 CSV。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| opsStage | Query | String | 否 | 同分页口径 | **本次改取值**:七桶或旧八桶 code | +| productId | Query | Long | 否 | - | 不变 | +| month | Query | String | 否 | `yyyy-MM` | 不变 | +| keyword | Query | String | 否 | - | 不变 | +| scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL` | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| 状态(CSV 第 8 列) | String | **内容改变**:由旧八桶中文名改为节点名;出行节点拼子状态,如「出行·待出发」「出行·出行中」「出行·已返团」 | + +列名、列序(固定 10 列)与单次 2000 行上限不变。 + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/export?opsStage=CONFIGURE&scope=ALL HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +响应为 CSV 附件;「状态」列示例: + +```json +{ + "Content-Type": "text/csv; charset=utf-8", + "header": "团期号,期号,日期,出团日,满团名额,已售,剩余,状态,子订单数,整团应收", + "状态列取值示例": ["招募", "配置", "确认", "出行·待出发", "出行·出行中", "出行·已返团", "核单", "结算", "已流团"] +} +``` + +#### 空数据 / 降级响应 + +无命中时只输出表头一行(不变): + +```json +{ "header": "团期号,期号,日期,出团日,满团名额,已售,剩余,状态,子订单数,整团应收", "rows": 0 } +``` + +#### 错误响应 + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 按「状态」列中文做过解析的下游需同步:旧值「已成团 / 待出行 / 核团中 / 已验团」不再出现。 +- 筛选口径与分页接口共用同一展开逻辑。 + +--- + +### 6. 团期状态流水 `GET /v3/admin/order/group-batch/{groupBatchId}/status-logs` + +**VO**: `List` + +#### 使用场景 + +团期详情「操作记录 / 时间线」。本次只改 5 个事件的中文标签(PR #8303)。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | 团期主键 | 不变 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|------|------|------| +| [].eventType | String | 事件类型值(**不变**) | +| [].eventTypeName | String | **取值改变**:见下表;标签在读取时渲染,存量行一并显示新标签 | +| [].content | String | 展示文本;本次之后新写入的核单 / 结算相关流水改用新用语,存量行原样 | + +| eventType | 改前 eventTypeName | 改后 eventTypeName | +|---|---|---| +| `BATCH_TRIP_END` | 返团核团 | 发起核单 | +| `BATCH_SETTLE` | 验团结算 | 结算 | +| `BATCH_AUDIT_ALLOCATE` | 核团提交核算 | 核单提交核算 | +| `BATCH_AUDIT_REALLOCATE` | 核团重新核算 | 核单重新核算 | +| `BATCH_AUDIT_PRICE_OVERRIDE` | 核团改价 | 核单改价 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2097250563497385985/status-logs HTTP/1.1 +Host: api.test.1814.love:9443 +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "eventType": "BATCH_SETTLE", + "eventTypeName": "结算", + "fromStatus": "REVIEWING", + "fromStatusName": "核单中", + "toStatus": "SETTLED", + "toStatusName": "已结算", + "content": "结算归档,团期结束", + "operatorType": "ADMIN" + } + ], + "success": true +} +``` + +#### 空数据 / 降级响应 + +无流水返回空数组;库里是枚举外历史值时 `eventTypeName` 为 null(不变): + +```json +{ "code": 200, "data": [], "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 589500, + "message": "团期不存在", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 按 `eventType` 做分支的前端不受影响;按中文标签匹配的需改。 +- `fromStatusName` / `toStatusName`(九态中文名「核单中」「已结算」)不变。 + +--- + +## 四、契约约束与正确调用方式 + +### ✅ 正确 / ❌ 错误用法对照 + +| 场景 | 用法 | +|------|------| +| ✅ 看板页签筛选(新) | `opsStage=CONFIGURE` / `opsStage=TRIP` | +| ✅ 看板页签筛选(过渡期旧值) | `opsStage=FORMED`,结果 = 配置 + 确认,与改前一致 | +| ✅ 页签计数 | 读 `buckets.CONFIGURE`、`buckets.TRIP` 等七桶键;总数读 `total` | +| ❌ 总数自己求和 | `Object.values(buckets).reduce(...)` → 七桶与别名重复,结果偏大 | +| ❌ 用节点判按钮 | `if (stage === 'CONFIGURE') showConfirmButton()` → 应读 `batchStatus` 与就绪位 | +| ❌ 按旧 `opsStage` 值分支 | `case 'FORMED':` → 响应已不再输出旧值 | + +### 核单 / 结算用语:错误码文案变化(PR #8303,码值不变) + +| code | 改前 message | 改后 message | +|---|---|---| +| 589555 | 该团期已验团归档,不可重复验团 | 该团期已结算归档,不可重复结算 | +| 589565 | 团期已验团归档,如需重新核单请先做验团反确认 | 团期已结算归档,如需重新核单请先做结算反确认 | +| 589567 | 该团期尚未进入核团:{0} | 该团期尚未进入整团核单:{0} | +| 589568 | 核团当前状态不允许该操作:{0} | 整团核单当前状态不允许该操作:{0} | +| 589572 | 所选订单不属于本团期的核团范围 | 所选订单不属于本团期的整团核单范围 | +| 589573 | 核团数据已被他人修改(当前版本 {0},提交版本 {1}),请刷新后重试 | 整团核单数据已被他人修改(当前版本 {0},提交版本 {1}),请刷新后重试 | + +核单状态枚举 `CHECKED` 的中文名由「已验团」改为「已结算」(存储值不变);前端按 code 判断即可,按中文匹配的需改。 + +--- + +## 六、边界行为 + +- 未登录 → 401(网关拦截)。 +- `batchStatus` 为 null 或不在九态内的脏数据行:四个新字段与 `opsStage` / `opsStageName` 同为 null,不抛错。 +- `opsStage` 空白或非法值:忽略该筛选并记 warn,不报错。 +- 未建团行恒为 `RECRUIT` / 招募。 +- 旧八桶别名(筛选入参 + 统计条 6 键)在前端切到七桶之前保留,删除时另发契约变更。 + +--- + +## 六.5、枚举 / 数据字典 + +### stage / opsStage(GroupBatchStageBuckets.Bucket) + +**所属字段**: `stage`、`opsStage`(响应)、`opsStage`(筛选入参)、`buckets` 前 7 键 | **类型**: `String` + +| 值 | 中文 | 说明 | +|----|------|------| +| `RECRUIT` | 招募 | ← `RECRUITING` | +| `CONFIGURE` | 配置 | ← `RESOURCE_PREPARING` | +| `CONFIRM` | 确认 | ← `MATERIAL_PREPARING` | +| `TRIP` | 出行 | ← `PENDING_DEPARTURE` / `TRAVELLING` / `TRIP_FINISHED` | +| `REVIEW` | 核单 | ← `REVIEWING` | +| `SETTLE` | 结算 | ← `SETTLED` | +| `DISBANDED` | 已流团 | ← `CANCELLED` | + +### tripSubStatus(GroupBatchStageBuckets.TripSubStatus) + +**所属字段**: `tripSubStatus` | **类型**: `String` + +| 值 | 中文 | 说明 | +|----|------|------| +| `PENDING_DEPARTURE` | 待出发 | 仍可发起流团 | +| `TRAVELLING` | 出行中 | 出发日起 | +| `TRIP_FINISHED` | 已返团 | 返团日次日起;首次录共享成本即进入核单 | + +### 旧八桶别名(GroupBatchStageBuckets.LegacyBucket,过渡期) + +**所属字段**: `opsStage`(筛选入参)、`buckets` 后 6 键 | **类型**: `String` + +| 值 | 中文 | 说明 | +|----|------|------| +| `FORMED` | 已成团 | = `RESOURCE_PREPARING` + `MATERIAL_PREPARING` | +| `PENDING_TRIP` | 待出行 | = `PENDING_DEPARTURE` | +| `TRAVELLING` | 出行中 | = `TRAVELLING` | +| `TRIP_FINISHED` | 出行完毕 | = `TRIP_FINISHED` | +| `AUDITING` | 核团中 | = `REVIEWING` | +| `CHECKED` | 已验团 | = `SETTLED` | + +--- + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| `stage` / `stageName` | 无 | 新增,七个节点 | +| `tripSubStatus` / `tripSubStatusName` | 无 | 新增,仅出行节点有值 | +| `opsStage`(响应) | 八桶:`RECRUIT` / `FORMED` / `PENDING_TRIP` / `TRAVELLING` / `TRIP_FINISHED` / `AUDITING` / `CHECKED` / `DISBANDED` | 七桶,与 `stage` 同值 | +| `opsStageName`(响应) | 招募中 / 已成团 / 待出行 / 出行中 / 出行完毕 / 核团中 / 已验团 / 已流团 | 招募 / 配置 / 确认 / 出行 / 核单 / 结算 / 已流团 | +| `buckets`(统计条) | 8 键,`total` = 8 桶之和 | 13 键(七桶 + 6 别名),`total` = 七桶之和 | +| 导出「状态」列 | 旧八桶中文名 | 节点名,出行节点拼子状态 | +| `eventTypeName`(5 个核单 / 结算事件) | 核团 / 验团用语 | 核单 / 结算用语 | +| 6 个错误码 message | 核团 / 验团用语 | 核单 / 结算用语(见「四」) | + +### 行为级对比 + +| 行为 | 改前 | 改后 | +|------|------|------| +| `opsStage=FORMED` 筛选 | 配置 + 确认 | 不变(别名按原口径) | +| `opsStage=TRIP` 筛选 | 非旧八桶 code,按非法值忽略(不筛) | 筛待出发 + 出行中 + 已返团 | +| `opsStage=CONFIGURE` / `CONFIRM` / `REVIEW` / `SETTLE` | 非法值被忽略 | 按新节点筛选 | + +⚠️ 注意 `TRIP` 与旧 `TRIP_FINISHED` 的区别:旧八桶里「出行完毕」的 code 是 `TRIP_FINISHED`,不是 `TRIP`;页签若传的是 `TRIP_FINISHED`,行为不变。 + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 部分。筛选入参与统计条旧键完全兼容;响应字段 `opsStage` / `opsStageName` 的取值改变,读这两个字段做分支或展示的代码会受影响。 +- **前端是否必须同步上线**: 否。旧页签传旧 code、读旧键仍然工作;要展示六节点需改读 `stage` / `tripSubStatus` 与七桶键。 +- **前端 workaround 清理点**: 若前端曾自己把九态折叠成阶段,可改为直接读 `stage`;切到七桶后告知后端删除旧八桶别名。 + +--- + +## 七、不影响范围 + +- **仅影响**: 上述 6 个查询 / 导出接口的节点相关字段与文案,及 6 个核单 / 结算错误码的 message。 +- **零影响**: + - 持久九态 `batchStatus` 及其中文名 `batchStatusName`(「核单中」「已结算」原本就是这两个字) + - 所有写接口的状态流转与业务闸(节点只供展示) + - 错误码 code 值、枚举存储值、时间线 `eventType` 值 + - 权限码、路径、信封结构、网关配置 + - 小程序端 + +--- + +## 八、测试环境已验证 + +部署 `dev-v3` @ `b212cb708`,2026-09-23 17:44–17:48,`api.test.1814.love:9443`。 + +| 验证项 | 结果 | +|---|---| +| 分页(`pageSize=100`)与看板行(187 行)字段 | 均带 `stage` / `stageName` / `tripSubStatus` / `tripSubStatusName` 四个新字段,且 `opsStage == stage` ✓ | +| 九态 → 节点映射 | 全映射实测 ✓ | +| 统计条 `summary`(`scope=ALL`) | 13 键逐键与 DB 一致;`total = 267` = 七桶之和(13 键合计 492) ✓ | +| `opsStage` 筛选 15 个取值 | `total` 全部等于 DB 计数;`PENDING_TRIP` 只筛待出发 3 条,`FORMED = 215`,未知值忽略 ✓ | +| 低权限角色 | `ROOM_MANAGER` / `VEHICLE_MANAGER` → 589507 ✓ | + +核单 / 结算用语(PR #8303:6 个错误码文案、时间线标签): + +补充(PR #8303,dev-v3 @ ade8ac292,2026-09-24 09:52–09:58):api-docs 中「已验团 / 团期核团 / 验团归档 / 验团反确认 / 核团面板」旧文案 0 次;589555「该团期已结算归档,不可重复结算」、589565「团期已结算归档,如需重新核单请先做结算反确认」实测触发;`status-logs` 对 09-18 旧记录返回新标签「发起核单 / 核单改价 / 核单提交核算 / 核单重新核算 / 结算」(`content` 为写入时原文,不随之变化)。工单 #8271 已验收关单。 + +--- + +## 九、相关历史 PR + +| PR | Issue | 说明 | 是否仍有效 | +|----|-------|------|------------| +| #6917 / #6926 | #6904 | 统计条与导出、`opsStage` 筛选首版 | ⚠️ 桶取值被本次替换,旧 code 以别名保留 | +| — | #7190 | 加「出行完毕」`TRIP_FINISHED` 成八桶 | ⚠️ 同上 | +| — | #7535 | 详情 / 分页透出 `opsStage` | ⚠️ 字段保留,取值改七桶 | +| **本 PR #8276 / #8279 / #8303** | **#8271** | 六节点派生 + 七桶 + 核单 / 结算用语 | ✅ 最新 | + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#8271](https://git.1814.love/wx/HL/issues/8271) +- 关联 PR: [wx/HL#8276](https://git.1814.love/wx/HL/pulls/8276)、[wx/HL#8279](https://git.1814.love/wx/HL/pulls/8279)、[wx/HL#8303](https://git.1814.love/wx/HL/pulls/8303) +- 同批六节点条目:团期人工确认(#8268)、确认后锁定配置(#8269) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8271](https://git.1814.love/wx/HL/issues/8271) +- **PR**: [#8276](https://git.1814.love/wx/HL/pulls/8276)、[#8279](https://git.1814.love/wx/HL/pulls/8279)、[#8303](https://git.1814.love/wx/HL/pulls/8303) +- **Merge commit**: [678d47b58](https://git.1814.love/wx/HL/commit/678d47b584ac0237784c0bf728e86dfe6cbacb1d)、[bfbc0d337](https://git.1814.love/wx/HL/commit/bfbc0d337a92f3e2dec8b84aa54cbf1042f08698)、[ade8ac292](https://git.1814.love/wx/HL/commit/ade8ac292388354649c3e367e1171e6e55836280) + +### 联系人 + +- **后端负责人**: @jw