docs(changelog): #8410 团期「配置 → 确认」新增只读预检 confirm-check(新增接口-管理后台)
changelog-filename-gate / validate (push) Failing after 1s

GET /v3/admin/order/group-batch/{groupBatchId}/confirm-check:前端据 ready 提前置灰「确认」按钮,
团期级五项与逐户未满足项可见,gateMessage 与 589556 message 逐字相同;零写入。
TEST 已部署(dev-v3 @ ecc92b95c)并经网关验收,工单 #8410 已关。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
这个提交包含在:
jw
2026-09-27 10:56:55 +08:00
共同撰写人 Claude Opus 5.5
父节点 013493d614
当前提交 17210578cb
@@ -0,0 +1,309 @@
---
schema: "hl-changelog/v2"
ticket: "8410"
title: "团期「配置 → 确认」新增只读预检 confirm-check:前端据 ready 提前置灰「确认」按钮,团期级五项与逐户未满足项可见"
consumer: "admin"
author: "jw(GIT)"
change_type: "新增接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "pending"
frontend_owner: ""
frontend_ref: ""
target_release: "v2.1"
verified_at: "2026-09-27"
status_note: "新增 GET /v3/admin/order/group-batch/{groupBatchId}/confirm-check(权限码 group-batch:confirm,与确认写口同码)。返回此刻点「确认」能不能过(ready)、状态是否允许确认(statusConfirmable)、团期级五项(房 / 车 / 导游领队 / 摄影 / 物资,每项 passed + 未通过文案)、逐户未满足项(待支付 / 定制中的在团户,每户 orderNo + items[code, text])与 gateMessage(与此刻点确认拿到的 589556 message 逐字相同)。判据与写口同源;主报账人按「确认时会先补齐人员副本」投影;零写入。状态不是 RESOURCE_PREPARING 时不做逐户预检,checkedHouseholdCount 为 null。前端需在团期详情「配置」节点进入时与点「确认」前调用,据 ready 置灰按钮、据 batchItems / unmetHouseholds 列缺项。"
updated_at: "2026-09-27"
base: "dev-v3"
---
# 团期确认: 新增只读预检 confirm-check,按钮可提前置灰(管理后台)
> **服务**: hl-order-service-v3(端口 8086/8186)
> **PR**: #8411
> **Issue**: #8410
> **日期**: 2026-09-27
> **影响范围**: 管理后台团期详情「配置」节点的「确认」按钮(置灰与缺项提示);确认写口本身契约不变
---
## ⚠️ 关键变化
1. **新增只读端点** `GET .../{groupBatchId}/confirm-check`:点「确认」之前就能知道能不能过、差什么。
2. **逐户未满足项第一次对前端可见**。#8339 起确认门含逐户预检(订金、出行人、户级房车、合同模板、主报账人),但团期详情只有团期级五个标记位,前端据此置灰会漏掉逐户这一半;以后以本端点的 `ready` 为准。
3. `gateMessage` 与点确认拿到的 589556 `message` 逐字相同,可直接展示。
---
## 一、背景
团期「配置 → 确认」(#8268,`POST .../confirm`)的门 = 房 / 车 / 导游领队 / 摄影四项配齐 + 物资已确认,#8339 又加了逐户预检。不满足时整单返回 589556,`message` 里列出未满足项,但**没有结构化数据**,团期详情也只透出团期级五个标记位。于是出现「五项全绿、某户没付订金时按钮是亮的,点下去才报错」。需求确认与订房确认早就各有配对的只读预检(`requirement/confirm-check`、`room-plans/confirm-check`),团期确认补齐同一形态。
---
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 团期确认预检 | GET | `/v3/admin/order/group-batch/{groupBatchId}/confirm-check` | 新增接口 | 只读;与 `POST .../confirm` 同门、同报文、同权限码 |
网关无改动(在既有 `/v3/admin/order/group-batch` 前缀下)。
---
## 三、接口详情
### 1. 团期确认预检 `GET /v3/admin/order/group-batch/{groupBatchId}/confirm-check`
**VO**: `GroupBatchConfirmCheckRespVO`
#### 使用场景
团期详情「配置」节点:进入页面时与点「确认」前调用。`ready=false` 时置灰「确认」按钮,用 `batchItems` 展示团期级五项的勾叉,用 `unmetHouseholds` 逐户列出还差什么,或直接展示 `gateMessage`。`statusConfirmable=false`(不在配置节点)时按钮应隐藏或置灰,不要提示缺项。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| groupBatchId | Path | Long | ✅ | 团期主键 | 不存在返 589500 |
#### 出参
| 字段 | 类型 | 说明 |
|------|------|------|
| groupBatchId | String | 团期主键(雪花 id,按字符串返回) |
| batchStatus | String | 团期状态码 |
| batchStatusName | String | 团期状态中文名 |
| ready | Boolean | 此刻点「确认」能否通过:`statusConfirmable=true` 且五项全过且 `unmetHouseholds` 为空 |
| statusConfirmable | Boolean | 状态是否允许确认(仅 `RESOURCE_PREPARING`);false 时点确认会是 589501 |
| batchItems | Array | 团期级五项,固定顺序、全量返回(含已通过项),任何状态下都有值 |
| batchItems[].code | String | `HOTEL_READY` / `VEHICLE_READY` / `GUIDE_READY` / `PHOTOGRAPHER_READY` / `MATERIAL_CONFIRMED`,与团期详情同名布尔字段对应 |
| batchItems[].name | String | 房 / 车 / 导游领队 / 摄影 / 物资 |
| batchItems[].passed | Boolean | 是否通过 |
| batchItems[].unmetText | String | 未通过时的文案(与 589556 里的逐字相同),通过时 null |
| checkedHouseholdCount | Integer | 参与逐户预检的户数(待支付 + 定制中的在团户);`statusConfirmable=false` 时不做逐户预检,为 null(null = 没查,0 = 查了没有需确认的户) |
| unmetHouseholds | Array | 不满足的户,按 orderId 升序;全满足或未做逐户预检时为空数组 |
| unmetHouseholds[].orderId | String | 子订单 id(字符串) |
| unmetHouseholds[].orderNo | String | 子订单号 |
| unmetHouseholds[].orderStatus | String | `PENDING_PAY` / `CUSTOMIZING` |
| unmetHouseholds[].items | Array | 该户未满足项,顺序同 589556 |
| unmetHouseholds[].items[].code | String | 见「六.5、枚举」 |
| unmetHouseholds[].items[].text | String | 文案,与 589556 里的逐字相同 |
| gateMessage | String | 此刻点确认会拿到的 589556 `message`(逐字相同);`ready=true` 或 `statusConfirmable=false` 时为 null |
#### 请求示例
```http
GET /v3/admin/order/group-batch/2097250563497385985/confirm-check HTTP/1.1
Host: api.test.1814.love
Authorization: Bearer <admin token>
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"groupBatchId": "2097250563497385985",
"batchStatus": "RESOURCE_PREPARING",
"batchStatusName": "资源准备中",
"ready": false,
"statusConfirmable": true,
"batchItems": [
{ "code": "HOTEL_READY", "name": "房", "passed": true, "unmetText": null },
{ "code": "VEHICLE_READY", "name": "车", "passed": true, "unmetText": null },
{ "code": "GUIDE_READY", "name": "导游领队", "passed": true, "unmetText": null },
{ "code": "PHOTOGRAPHER_READY", "name": "摄影", "passed": true, "unmetText": null },
{ "code": "MATERIAL_CONFIRMED", "name": "物资", "passed": false, "unmetText": "物资未确认" }
],
"checkedHouseholdCount": 3,
"unmetHouseholds": [
{
"orderId": "2097260000000000001",
"orderNo": "GT-26-0085",
"orderStatus": "CUSTOMIZING",
"items": [
{ "code": "PAYMENT_OK", "text": "未付订金" },
{ "code": "PRIMARY_REPORTER_MISSING", "text": "未指定主报账人" }
]
}
],
"gateMessage": "团期尚不满足确认条件:物资未确认;订单 GT-26-0085:未付订金、未指定主报账人"
}
}
```
#### 空数据 / 降级响应
全部满足:`ready=true`,`unmetHouseholds=[]`,`gateMessage=null`。不在配置节点(如招募中、已确认):`statusConfirmable=false`、`ready=false`、`checkedHouseholdCount=null`、`unmetHouseholds=[]`、`gateMessage=null`,`batchItems` 照常返回五项。
```json
{
"code": 200,
"success": true,
"data": {
"groupBatchId": "2097250563497385985",
"batchStatus": "MATERIAL_PREPARING",
"batchStatusName": "物料准备中",
"ready": false,
"statusConfirmable": false,
"batchItems": [
{ "code": "HOTEL_READY", "name": "房", "passed": true, "unmetText": null },
{ "code": "VEHICLE_READY", "name": "车", "passed": true, "unmetText": null },
{ "code": "GUIDE_READY", "name": "导游领队", "passed": true, "unmetText": null },
{ "code": "PHOTOGRAPHER_READY", "name": "摄影", "passed": true, "unmetText": null },
{ "code": "MATERIAL_CONFIRMED", "name": "物资", "passed": true, "unmetText": null }
],
"checkedHouseholdCount": null,
"unmetHouseholds": [],
"gateMessage": null
}
}
```
#### 错误响应
团期不存在:
```json
{ "code": 589500, "message": "团期不存在", "success": false, "data": null }
```
无权限(角色未授 `group-batch:confirm`):
```json
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"success": false,
"data": null
}
```
#### 业务边界
- 权限码 `group-batch:confirm`,与确认写口同码(授 `GROUP_BATCH_MANAGER` / `ADMIN`);看不到「确认」按钮的角色不需要调本端点。
- 判据与 `POST .../confirm` 同源:同一阶段判断、同一张五项表、同一套逐户判据、同一个 589556 构造;`gateMessage` 就是那条异常的 message。
- 预检只是预检:点确认时写口按当时数据重判一遍,两次调用之间数据变了以写口为准。
- 主报账人按「确认时会先补齐团期人员副本」投影:团期层已设主报账人、订单层副本滞后的户,预检不报「未指定主报账人」(点确认时写口会先补齐再判)。
- 零写入:不补齐副本、不写时间线、不改状态、不发事件。
- 逐户预检的开销与点一次确认相当(每户读一次确认清单),不要轮询调用。
---
## 四、契约约束与正确调用方式
### ✅ 正确 / ❌ 错误调用顺序
| 场景 | 调用 |
|------|------|
| ✅ 置灰「确认」按钮 | 进入配置节点 → `GET confirm-check` → 按 `ready` 置灰 |
| ✅ 点「确认」 | `GET confirm-check`(`ready=true`)→ `POST confirm` |
| ❌ 只用详情的五个标记位判断能否确认 | 漏掉逐户预检,点下去仍可能 589556 |
| ❌ 自己拼 589556 文案 | 直接用 `gateMessage` 或 `batchItems[].unmetText` / `items[].text` |
### ready 与 statusConfirmable
`statusConfirmable=false` 表示「不在能确认的节点」(按钮不该出现或应置灰且不提示缺项);`statusConfirmable=true` 且 `ready=false` 表示「在配置节点但还有缺项」(置灰并展示缺项)。
---
## 六、边界行为
- 未登录 → 401(网关拦截)。
- 团期不存在 → 589500;无权限 → 589507(不进业务逻辑)。
- 在团户里已是待出行 / 出行中 / 已完成的户不参与逐户预检(与写口一致);已取消户不在「在团」口径内。
- 库里若出现认不出的团期状态值,预检返回 `statusConfirmable=false`;确认写口同步改为返回 589501(此前是 500)。正常数据不可达。
---
## 六.5、枚举 / 数据字典
### 团期级五项(batchItems[].code)
**所属字段**: `batchItems[].code` | **类型**: `String`
| 值 | 中文 | 未通过文案 |
|----|------|------------|
| `HOTEL_READY` | 房 | 房未配齐 |
| `VEHICLE_READY` | 车 | 车未配齐 |
| `GUIDE_READY` | 导游领队 | 导游领队未配齐 |
| `PHOTOGRAPHER_READY` | 摄影 | 摄影未配齐 |
| `MATERIAL_CONFIRMED` | 物资 | 物资未确认 |
### 逐户未满足项(unmetHouseholds[].items[].code)
**所属字段**: `unmetHouseholds[].items[].code` | **类型**: `String`
| 值 | 中文 | 说明 |
|----|------|------|
| `PENDING_PAY` | 待支付(须先付订金或取消) | 订单仍是待支付;此时不再重复列 `PAYMENT_OK` |
| `PAYMENT_OK` | 未付订金 | 团期口径付订金即可(沿用单户确认清单编码) |
| `TRAVELER_COMPLETE` | 出行人信息 | 文案取单户确认清单的失败原因 |
| `HOTEL_DONE` | 房型安排 | 同上 |
| `VEHICLE_DONE` | 用车安排 | 同上 |
| `CONTRACT_TEMPLATE_OK` | 合同方案配置 | 同上 |
| `PRIMARY_REPORTER_MISSING` | 未指定主报账人 | 按「确认时先补齐副本」投影后仍无主报账人 |
---
## 七、不影响范围
- **仅影响**: 新增一个只读端点。
- **零影响**:
- `POST .../confirm` 的入参、出参、错误码与门条件(内部改为与预检共用判据;唯一可观察差异是库里出现非法状态值时由 500 改 589501,正常数据不可达)
- 团期详情、需求确认预检、订房确认预检
- 小程序端
- 零数据库变更、零配置变更、零权限种子变更(复用 #8268 的 `group-batch:confirm`)。
---
## 八、测试环境已验证
部署:hl-order-service-v3 = dev-v3 @ ecc92b95c(2026-09-27 10:22);取证时 TEST 检出为 dev-v3 @ 57199b539(含 ecc92b95c),经网关 `https://api.test.1814.love` 真实鉴权实测(2026-09-27 10:45–10:56),order-v3 取证期间未被重部署;工单 #8410 已验收关单。
| # | 场景 | 结果 |
|---|---|---|
| 1 | ADMIN / GROUP_BATCH_MANAGER / SUPER_ADMIN 调 confirm-check | 200 |
| 2 | CUSTOMIZER 调 confirm-check | 589507,前后三表无写入 |
| 3 | 不存在的团期 / 不带 token | 589500 / 401 |
| 4 | RESOURCE_PREPARING 团期(房 / 车 / 物资未过,12 户定制中) | `batchItems` 五项顺序正确,与详情五个布尔、库值三方一致;`checkedHouseholdCount=12`,12 户逐户列出(TRAVELER_COMPLETE / HOTEL_DONE / VEHICLE_DONE / PRIMARY_REPORTER_MISSING) |
| 5 | 同一团期调 `POST .../confirm` 对照 | 589556,`message` 与预检 `gateMessage` 逐字相同(914 字);确认被拒无写入 |
| 6 | 团期层临时设主报账人、订单层副本滞后(NONE) | 预检不再报「未指定主报账人」(按确认时先补齐副本投影),预检不补齐副本;还原后恢复原状 |
| 7 | 订单层副本是 PRIMARY 但团期层为 NONE(将被补齐降级) | 预检仍报「未指定主报账人」,预检不改该行;还原后恢复原状 |
| 8 | 连续四次调预检 | `order_group_batch` / `group_batch_status_log` / `order_staff_assignment` / 子订单状态逐字段无变化 |
| 9 | RECRUITING / MATERIAL_PREPARING / CANCELLED 团期 | `statusConfirmable=false`、`ready=false`、`checkedHouseholdCount=null`、`unmetHouseholds=[]`、`gateMessage=null`,五项照返 |
---
## 九、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|----|-------|------|------------|
| #8302 | #8268 | 团期人工确认写口(五项门、589556) | ✅ |
| #8346 / #8349 | #8339 | 确认门逐户预检、确认前补齐人员副本 | ✅(本端点投影的就是这次补齐) |
| — | #7210 | 需求确认预检 `requirement/confirm-check`(同形先例) | ✅ |
| **本 PR #8411** | **#8410** | 团期确认只读预检 | ✅ 最新 |
---
## 十、相关文档
- 关联 Issue: [wx/HL#8410](https://git.1814.love/wx/HL/issues/8410)
- 关联 PR: [wx/HL#8411](https://git.1814.love/wx/HL/pulls/8411)
- 写口条目:`24_8268_团期人工确认端点与确认后才出合同保险-新增接口-管理后台.md`
## 关联 / 联系人
### 链接
- **Issue**: [#8410](https://git.1814.love/wx/HL/issues/8410)
- **PR**: [#8411](https://git.1814.love/wx/HL/pulls/8411)
- **Merge commit**: [ecc92b95c](https://git.1814.love/wx/HL/commit/ecc92b95ca2cc9c5801f2cfab5f29456f0419875)
### 联系人
- **后端负责人**: @jw