文件
hl-api-changelog/changelogs-v2/2026-09/24_8331_接送机需求窗不跟随新增大交通方向时整团确认可预检与605062报文点名-修改接口-管理后台.md
T
Mimingguang 020a3959a4
changelog-filename-gate / validate (push) Failing after 1s
docs(changelog): #8331 前端已交付 verified(ref=c88fd794)
2026-09-24 14:44:30 +08:00

428 行
21 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "8331"
title: "接送机需求窗不跟随新增大交通方向:整团确认预检新增 TRANSFER_WINDOW_INCOMPLETE(809126),605062 报文改为点名版本、越窗日期与处置方"
consumer: "admin"
author: "wx(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "verified"
frontend_owner: "mmg"
frontend_ref: "c88fd79478246ec68d7ca86267d90a9839f04fee"
target_release: "v2.1"
verified_at: "2026-09-24"
status_note: "PR #8335 squash 合并 dev-v3(2b4656424)。部署:hl-order-service-v3 + hl-fleet-service dev-v3 @ 2b4656424,2026-09-24 14:02—14:03 滚动部署(order-v3 两实例 8086/8186 均 UP,fleet 两实例滚动完成)。测试服网关实测(groupBatchId=2102981652823302146;甲 2102981652680695809 的接送机需求 2102989264394563586 窗内只有 2027-02-03,之后补录了 2027-02-05 返程大交通):① GET requirement/confirm-check → ready=false,vehicleMissing 新增 reason=TRANSFER_WINDOW_INCOMPLETE、tripDate=2027-02-05、detail=该户接送机需求窗仅含 2027-02-03,大交通送机 2027-02-05 未进窗,请定制师重新提交接送机需求后再派车(改前该位置 vehicleMissing=[]);② POST /admin/fleet/assignments 派 2027-02-05 送机车 → code=605062,报文已改为:派车日期 2027-02-05 越出当前接送机需求日期窗(版本 v1,窗内服务日 2027-02-03):请先调整或取消这些越窗槽位,或让定制师重新提交接送机需求换版后再派车(改前为「存在派车日期与当前用车需求不符的槽位,请先调整或取消后再继续」)。定向单测:order-v3 157 绿、fleet AssignmentServiceTest 565 绿,fleet spotless:check 901 files clean。只对「提交得了的户」报(与 809122 同一份豁免判据取交集),避免对没有提交入口的户把整团确认永久卡死。 | 2026-09-24 mmg 交付:confirm-check 侧实证开箱即用(detail 直显),JSDoc 补 809126 口径+spec 回归锁;useAssignFlow 605062 一码两业务注释订正+缺省回退文案中性化,新报文直接透;spec 32+34+47 例全绿(新增 2 例,2 例改中性断言)"
updated_at: "2026-09-24"
base: "dev-v3"
---
# order-v3 + fleet 接送机: 需求窗缺方向预检(809126)与 605062 可执行报文
> **存放目录**: 二期(v3) → `changelogs-v2/2026-09/`
>
> **服务**: hl-order-service-v3(团期需求域 + requirement 域)· hl-fleet-service(assignment 域)
> **PR**: https://git.1814.love/wx/HL/pulls/8335
> **Issue**: #8331
> **日期**: 2026-09-24
> **影响范围**: 管理后台「团期详情 → 查看需求」Tab 的整团确认预检与整团确认;车务「派车」写入口的 605062 报文
---
## ⚠️ 关键变化(非必须,本版与上版行为不同 / 纠错 / 撤销时必写)
- **新增车侧缺失原因 `TRANSFER_WINDOW_INCOMPLETE` 与错误码 809126**:某户的大交通派生出了新的方向日期(典型:先报到达、后补返程),而该户接送机需求的 `service_dates` 里没有这一天时,整团确认预检点名该户并 `ready=false`。
- **605062 报文重写(码值与判据不变)**:由「存在派车日期与当前用车需求不符的槽位,请先调整或取消后再继续」改为点名**哪一版需求、哪一天越窗、窗内有哪些服务日、谁该做什么**。**这是一个既有错误码的报文变更,前端/QA 的文案断言需要同步更新。**
- **只对「提交得了的户」报**:候选户与 809122 那份豁免判据取交集(订单在定制中且团期阶段开放提交,或该户最新需求被打回)。提交不了的户此刻在系统里没有提交入口,报出来只会把整团确认**永久卡死**(户补不了、团也确认不了)。
- **不自动改需求数据、不自动换版**:换版要重走提交链(服务日重新派生、状态回待审核、记录换版原因),由定制师发起才是这个事实的属主该做的事。方案①(新方向大交通落库即自动换版)与 `requirementVersion` 身份校验、已派车行 superseded 处置耦合,留待产品决策。
- **成功路径仍要求定制师重新提交**:本次只保证「不一致在整团确认前被看见 + 车务拿到的 605062 可执行」。
---
## 一、背景(选填)
大交通天然是分次录入的(先定去程、回程后补)。接送机的服务日只在**提交那一刻**由大交通派生一次、随后冻结在需求行上;补录一个**此前完全不存在方向**的大交通与「把已有航班改签」是两件事——前者是新增缺口,不是对已冻结窗口的修改。此前的现场是:车务看板按大交通报出「有送机缺口」,车务去派送机车却被 605062 拦死,报文既不点名越窗日期也不指出处置方,车务在派车侧怎么调整都推不动。本单落**方案②**(零 DDL、只做可见性与报文)。
---
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 整团确认预检 | GET | `/v3/admin/order/group-batch/{groupBatchId}/requirement/confirm-check` | 响应新增枚举值 | `vehicleMissing[].reason` 新增 `TRANSFER_WINDOW_INCOMPLETE`,对应 809126 |
| 2 | 整团确认 | POST | `/v3/admin/order/group-batch/{groupBatchId}/requirement/confirm` | 行为变更(同一判据) | 存在该缺失时整团确认被拒 |
| 3 | 创建派车(单槽位占位) | POST | `/admin/fleet/assignments` | 报文变更(码值与判据不变) | 605062 报文改为点名版本、越窗日期、窗内服务日与处置方 |
---
## 三、接口详情
### 1. 整团确认预检 `GET /v3/admin/order/group-batch/{groupBatchId}/requirement/confirm-check`
**VO**: `GroupBatchRequirementCheckRespVO`
#### 使用场景
团期详情「查看需求」Tab 打开或点「整团确认」前的只读预检。权限 `group-batch:demand:confirm`。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| groupBatchId | Path | Long | ✅ | - | 团期聚合主键(不是产品班期 ID) |
#### 出参 `Result<GroupBatchRequirementCheckRespVO>`
| 字段 | 类型 | 说明 |
|------|------|------|
| ready | Boolean | 是否可整体确认;本次起在「接送机需求窗缺方向」时为 false |
| vehicleMissing[] | Array | 车侧缺失项;本次新增 `TRANSFER_WINDOW_INCOMPLETE` |
| vehicleMissing[].reason | String | 原因码,取值见「六.5」 |
| vehicleMissing[].tripDate | LocalDate | 本原因下为**首个越窗日期**(大交通派生出来、却不在需求窗内的那天) |
| vehicleMissing[].orderId / orderNo | String / String | 涉及的子订单 |
| vehicleMissing[].groupCode | String | 本原因恒为 null(接送机需求没有乘车分组维度) |
| vehicleMissing[].detail | String | 人话描述,与整团确认抛出的报文逐字相同,已含「请定制师重新提交接送机需求后再派车」 |
#### 请求示例
```http
GET /v3/admin/order/group-batch/2102981652823302146/requirement/confirm-check
Authorization: Bearer <admin token>
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": {
"groupBatchId": "2102981652823302146",
"ready": false,
"vehicleMissing": [
{
"reason": "TRANSFER_WINDOW_INCOMPLETE",
"groupCode": null,
"tripDate": "2027-02-05",
"orderId": "2102981652680695809",
"orderNo": "HL20260924124112051",
"detail": "该户接送机需求窗仅含 2027-02-03,大交通送机 2027-02-05 未进窗,请定制师重新提交接送机需求后再派车"
}
],
"groupVehicleRequirementId": "2102982327141556225",
"groupVehicleRequirementStatus": "CONFIRMED",
"groupVehicleRequirementVersion": 4
},
"success": true
}
```
#### 空数据 / 降级响应
- 全部一致时 `vehicleMissing: []`、`ready: true`。
- 该户**提交不了**(订单不在定制中,或团期阶段已关提交且最新需求未被打回)时**跳过**本判据,不报 809126。
- 该户没有活跃接送机需求、或大交通没有派生任何方向日期时不报。
- 接送机需求窗与派生日期完全一致时不报。
```json
{ "code": 200, "message": "成功", "data": { "ready": true, "vehicleMissing": [] }, "success": true }
```
#### 错误响应
本端点只读,业务结果包在 HTTP 200 内。
```json
{ "code": 200, "message": "成功", "data": { "ready": false, "vehicleMissing": [{ "reason": "TRANSFER_WINDOW_INCOMPLETE" }] }, "success": true }
```
#### 业务边界
- 判据 =「当前大交通按方向派生的日期集合」−「需求行冻结的 `service_dates`」非空;只取**首个**越窗日期进 `tripDate`,多条时 `detail` 里顿号分隔。
- 判据取「在团户」而不是「放行集合」:接送机需求是户级自己报的,与团级 `needs_vehicle` 无关。
- 与 809007(待放行接送机需求未回填服务日)互斥且不重叠:809007 管「一行服务日都没有」,809126 管「有窗但窗比大交通旧」。
- **同方向改签不报**:判据落在「缺的方向/日期」上,不是「大交通变了」。
---
### 2. 整团确认 `POST /v3/admin/order/group-batch/{groupBatchId}/requirement/confirm`
**VO**: `GroupBatchRequirementCheckRespVO`(确认口无请求体,与预检同源判据)
#### 使用场景
团期管理员点「整团确认」,把各户需求汇总成正式需求并放行给车务。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| groupBatchId | Path | Long | ✅ | - | 团期聚合主键 |
#### 出参 `Result<...>`
| 字段 | 类型 | 说明 |
|------|------|------|
| requirementConfirmed | Boolean | 本次是否完成整体确认;被拒时不返回该结构 |
| vehicleDispatchedOrderIds | Array&lt;String&gt; | 本次被放行的户 |
#### 请求示例
```http
POST /v3/admin/order/group-batch/2102981652823302146/requirement/confirm
Authorization: Bearer <admin token>
```
#### 响应示例
```json
{ "code": 200, "message": "成功", "data": { "requirementConfirmed": true }, "success": true }
```
#### 空数据 / 降级响应
与预检读同一份快照;预检不报 809126 时确认也不会报。
```json
{ "code": 200, "message": "成功", "data": { "requirementConfirmed": false }, "success": true }
```
#### 错误响应
```json
{
"code": 809126,
"message": "该户接送机需求窗仅含 2027-02-03,大交通送机 2027-02-05 未进窗,请定制师重新提交接送机需求后再派车",
"success": false,
"data": null
}
```
#### 业务边界
- 异常顺序:团级六条 → 户级未提交(809122)→ 接送机未回填(809007)→ **接送机窗不完整(809126)** → 车型不符(809125)。
- 「车型不符(809125)」排在 809126 之后:前者的处置是管理员**重新汇总**,而户级还在改(定制师要重提接送机需求)时先汇总,改完还得再汇总一次。
---
### 3. 创建派车(单槽位占位) `POST /admin/fleet/assignments`
**VO**: `AssignmentCreateReqVO`(沿用既有请求体,本单未改结构)
#### 使用场景
车务按看板缺口派车。本单只改**被拒时的报文**,不改编排、判据与码值。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| orderId | Body | Long | ✅ | 在团户 | 子订单 |
| requirementId | Body | Long | ✅ | 该户当前活跃需求 | 与 `requirementVersion` 共同构成需求身份 |
| startDate / endDate | Body | LocalDate | ✅ | `yyyy-MM-dd` | 本次派车的服务日段(逐日行) |
| headcount | Body | Integer | ✅ | ≥1 | 用车人数 |
| requestId | Body | String | ✅ | 幂等标识 | 重复提交同值即幂等 |
#### 出参 `Result<...>`
| 字段 | 类型 | 说明 |
|------|------|------|
| (结构未变) | — | 本单只改业务失败时的 605062 报文 |
#### 请求示例
```json
{
"orderId": "2102981652680695809",
"requirementId": "2102989264394563586",
"vehicleId": "2085284111341023234",
"driverId": "2089691308707733506",
"startDate": "2027-02-05",
"endDate": "2027-02-05",
"headcount": 2,
"sendItinerarySms": false,
"confirmCrossResident": true,
"requestId": "GRE2E-win-0205"
}
```
#### 响应示例
```json
{ "code": 200, "message": "成功", "data": { "assignmentId": "2103003339824435202" }, "success": true }
```
#### 空数据 / 降级响应
- 需求窗内派车:正常 200,报文未变。
- 该户当天已有在途槽位:仍走既有 605003 / 605004 等码,本单未改。
```json
{ "code": 200, "message": "成功", "data": { "addedCount": 1 }, "success": true }
```
#### 错误响应
```json
{
"code": 605062,
"message": "派车日期 2027-02-05 越出当前接送机需求日期窗(版本 v1,窗内服务日 2027-02-03):请先调整或取消这些越窗槽位,或让定制师重新提交接送机需求换版后再派车",
"success": false,
"data": null
}
```
#### 业务边界
- **四个实参**:{0}=越窗派车日期(升序、顿号分隔)、{1}=需求类别的人话名(接送机需求 / 行程用车需求)、{2}=需求版本号、{3}=当前需求窗内的服务日。全部由抛点拼成**字符串**传入——数字与日期直接交给 `MessageFormat` 会被本地化或插入千分位(版本号会变成 1,234)。
- **两个入口共用同一份报文**:「在途槽位行越窗」与「请求日期段越窗」现在从同一个构造点出来,不会出现同一次越窗、两个入口不同指引。
- **判据与码值不变**:仍然只按日期窗拦截,车型 / 数量 / 人数不符一律不拦。
---
## 四、契约约束与正确调用方式(接口类必写)
- `reason` 是稳定的机器可判值;`detail` 直接展示,**不要解析**。
- 605062 是「车务侧无解」的码:**不要**在页面引导车务反复调整槽位,正确下一步是让定制师重新提交接送机需求(换版)后再派车。新报文已把这句话写进 message。
- 需求版本会随换版 +1,换版后车务必须按新版本重新配车确认(既有语义)。
### ✅ 正确 / ❌ 错误处置对照
```text
✅ 预检 ready=false 含 TRANSFER_WINDOW_INCOMPLETE → 通知该户定制师重新提交接送机需求 → 团期管理员重新整团确认 → 车务再派车
❌ 车务反复改派车日期:需求窗没变,改到哪一天都还是 605062
❌ 把需求窗当成可以手工改的字段:需求服务日由大交通派生,只能通过重新提交换版
```
### 切换状态时的必要动作
- 定制师换版后,该户需求进入 PENDING_REVIEW,团期管理员需重新整团确认放行;届时 `requirementVersion` 变化,车务侧旧版本身份校验会失败(既有 602005 语义)。
---
## 五、数据库行为(涉及写操作时必写)
- 无表结构变更、无 Flyway。
- 809126 在**写库之前**抛出:整团确认被拒时零写入(正式需求版本与状态不变,可回读确认)。
- 605062 在**写库之前**抛出:没有任何派车行落库。
---
## 六、边界行为
- 判据按「当前大交通派生的日期 − 需求窗」求差,同方向改签(日期变了但方向仍齐)不报——这是刻意保留「冻结不覆盖」的既有定案。
- 只对「提交得了的户」报;提交不了的户不报,避免整团确认被永久卡死。
- 多条越窗日期时 `tripDate` 取首个,`detail` / 805062 报文列出全部。
---
## 六.5、枚举 / 数据字典(接口出现枚举时必写)
| reason / 错误码 | 触发 | 报文 |
|---|---|---|
| `TRANSFER_WINDOW_INCOMPLETE` / 809126 | 该户大交通派生出的日期不在活跃接送机需求窗内,且该户此刻提交得了 | 该户接送机需求窗仅含 {0},大交通{1} 未进窗,请定制师重新提交接送机需求后再派车 |
| 605062(报文变更,码值不变) | 派车日期越出当前需求窗 | 派车日期 {0} 越出当前{1}日期窗(版本 v{2},窗内服务日 {3}):请先调整或取消这些越窗槽位,或让定制师重新提交{1}换版后再派车 |
| `TRANSFER_SERVICE_DATES_NOT_BACKFILLED`(不变) / 809007 | 待放行接送机需求一行服务日都没有 | 既有报文 |
---
## 六.6、修改前后对比(修改/删除类接口必写,新增跳过)
### 字段级对比
| 字段 | 改前 | 改后 |
|------|------|------|
| `confirm-check` 请求/响应字段 | — | 无新增、无删除;`vehicleMissing[].reason` 多一个取值 |
| 605062 `message` | 存在派车日期与当前用车需求不符的槽位,请先调整或取消后再继续 | 派车日期 {0} 越出当前{1}日期窗(版本 v{2},窗内服务日 {3}):请先调整或取消这些越窗槽位,或让定制师重新提交{1}换版后再派车 |
### 行为级对比
| 行为 | 改前 | 改后 |
|------|------|------|
| 先提接送机需求、后补录新方向大交通 | 预检 `ready=true`;车务按看板缺口派车被 605062 拦死且报文无出路 | 预检 `ready=false` 点名该户;605062 报文点名版本、越窗日期与处置方 |
| 同方向改签 | 不换版、需求窗不变 | 不变(判据落在「缺的方向/日期」) |
| 提交不了的户窗不完整 | 无提示 | 仍无提示(刻意 fail-open,避免永久卡死) |
---
## 六.7、影响评估(修改/删除类必写)
- **是否破坏向后兼容**:`confirm-check` 响应结构不变但**同一场景 `ready` 可能由 true 变 false**;605062 **报文文本变更**,凡断言旧文案的自动化脚本需同步。
- **前端是否必须同步上线**:**建议同批**。新 reason 未适配时仍可由 `ready=false` 正确禁用确认按钮;605062 报文是纯文案替换,页面直接透传即可。
- **存量数据影响**:不批量重算、不改数据;只有下一次预检 / 确认 / 派车才会暴露。
- **上线风险**:对「窗比大交通旧且该户提交得了」的团期会在整团确认时被拦,需要定制师换版一次;提交不了的户不受影响。
---
## 七、不影响范围(显式声明, 帮前端/QA 缩小排查面)
- **仅影响**:`GET .../requirement/confirm-check` 的 `ready` / `vehicleMissing`;`POST .../requirement/confirm` 的拒绝条件;605062 的报文文本。
- **零影响**:
- 605062 的**判据与码值**(仍只拦日期越窗;车型 / 数量 / 人数不拦)。
- 派车 / 排车 / 看板的缺口计算与 `overview` 字段。
- 需求数据本身:不自动换版、不写 `service_dates`。
- 团级六条既有校验与 809116 / 809118 / 809119 / 809120 / 809121 / 809122 / 809007 等其余判据与报文。
- 数据库、网关路由。
---
## 八、测试环境已验证
**部署读数**:`hl-order-service-v3` 与 `hl-fleet-service` 均 dev-v3 @ `2b4656424`,2026-09-24 14:02—14:03 滚动部署完成。
**网关真实请求与响应**(`https://api.test.1814.love`,`groupBatchId=2102981652823302146`;甲 `2102981652680695809` 的接送机需求 `2102989264394563586` 窗内只有 `2027-02-03`,之后补录了 `2027-02-05` 返程大交通):
```text
① GET .../requirement/confirm-check
→ http 200, code=200, ready=false
vehicleMissing 含一条:
reason=TRANSFER_WINDOW_INCOMPLETE, tripDate=2027-02-05,
orderId=2102981652680695809, orderNo=HL20260924124112051
detail=该户接送机需求窗仅含 2027-02-03,大交通送机 2027-02-05 未进窗,请定制师重新提交接送机需求后再派车 ✓
② POST /admin/fleet/assignments(派 2027-02-05 送机车)
→ http 200, code=605062
message=派车日期 2027-02-05 越出当前接送机需求日期窗(版本 v1,窗内服务日 2027-02-03):
请先调整或取消这些越窗槽位,或让定制师重新提交接送机需求换版后再派车 ✓
改前读数(2026-09-24 13:1x,同一团期同一数据):
confirm-check → ready=true、vehicleMissing=[]
assignments → code=605062,message=存在派车日期与当前用车需求不符的槽位,请先调整或取消后再继续 ✓
```
**定向测试逐类读数**:
| 模块 / 测试类 | Tests run |
|---|---|
| hl-order-service-v3(5 个类合计) | 157 |
| ├ GroupBatchRequirementServiceTest | 73 |
| ├ GroupVehicleRequirementConfirmCheckTest | 30 |
| ├ GroupBatchRequirementServiceCheckVehicleTest | 27 |
| ├ GroupBatchRequirementServiceConfirmVehicleTest | 19 |
| └ TransferServiceDatesResolverTest | 8 |
| hl-fleet-service / AssignmentServiceTest | 565 |
fleet `spotless:check`:901 files clean、0 needs changes。
---
## 十、相关文档
- 户级未提交(809122)先例:#8249 → `changelogs-v2/2026-09/`
- 车型与分组不符(809125,同日并入):#8330 → `changelogs-v2/2026-09/24_8330_团期整团确认预检新增车型与分组不符原因MEMBER_GROUP_MISMATCH与809125-修改接口-管理后台.md`
- 605062 越窗门禁来源:#5810 / #8235
- 接送机需求提交与 `transfer/batch-confirm`:#8202 / #8152
---
## 关联 / 联系人
### 链接
- Issue: https://git.1814.love/wx/HL/issues/8331
- 后端 PR: https://git.1814.love/wx/HL/pulls/8335
### 联系人
- 后端: wx