E_API_TEMPLATE 要求接口类正文必须有 二/三/四/六/七/八/十/关联 八个章节。
内容零丢失,只重组结构并补齐模板要求的缺失章节。
三处不能丢的都逐字保留:
- 覆盖边界(本文只验到「提交」为止;TRANSFER 同步车务 outbox 恒 605905)
在「六、边界行为」子节原样保留,文首「关键变化」只做导读不做替代
- 阳性对照注脚(两字段 fleet 恰好相同不能证明按 kind 取数生效,真正证明
它的是全 null 对照与 id 不同)在「八」原样保留
- 809002/809009 分开处置(去补大交通 / 找后端开开关)新建对照表,两码
各自一行,不混提示
代理顺带查实并订正三处:
- 路径参数按源码 AdjustmentAdminController 实为 {id} 而非 {orderId}
- status 枚举以 RequirementStatus 为准共 6 个;RespVO 注释里的 CLAIMED
在源码里根本不存在,已显式点出分歧而非悄悄抹平
- 文件实际行尾是 LF 不是 CRLF,按现状保持
29 KiB
schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
| schema | ticket | title | consumer | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 7443 | 调整订单「车辆安排」页同页提交 行程用车(TRAVEL) + 接送机用车(TRANSFER) 两类需求 | admin | wx(GIT) | 修改接口 | deployed | verified | pending | mmg | 2026-09-20 | 后端已合入 dev-v3(PR #8024,squash 提交 920f29d76)并部署测试服:deploy-status.sh 回读 hl-order-service-v3 = dev-v3 @ 920f29d76、BEHIND=0/N、STATE=ok,两实例滚动重启均 UP,判据 git merge-base --is-ancestor 920f29d76 920f29d76 = true。gateway_status=verified 的依据是四条真实网关调用而非源码推断:①读口双槽(含阳性对照:未提交需求的订单两个字段都是 null,证明不是恒有值)②一次 submit 同时提交两份 → HTTP 200,落库两条 active 行,fleet 分别为 bus/19座/1台 与 mpv/7座/2台 ③调整记录两条 label 原文不同 ④无大交通时 809002。🔴 一条必须连着读的限定:本文只验证了「提交」这一段。同一次实测观测到 TRANSFER 需求同步给车务的 outbox 命令持续失败(order_fleet_command_outbox command_type=RECONCILE,TRAVEL=SUCCEEDED 而 TRANSFER=PENDING/retry_count=2,last_error_message='Fleet 用车需求换版失败: code=605905, message=需求版本过期'),根因是 hl-fleet-service AssignmentService:11492 requireCurrentVehicleRequirementForMutation 取当前需求时不带 kind、恒取 TRAVEL,与 TRANSFER 的 requirementId 比对必然不等。即:前端按本文接完即可正常提交并回显,但提交出去的接送机需求在修复该缺陷之前到不了车务侧,端到端业务尚未打通。该缺陷已在修(属 #7990 那一族),修好后另发交接件,不影响本文的前端契约。 | 2026-09-20 | dev-v3 |
order-v3: 调整订单「车辆安排」页同页提交 行程用车 + 接送机用车 两类需求
服务: hl-order-service-v3(adjustment 层,唯一变化点) PR: #8024 | Issue: #7443 | 合并提交:
920f29d76日期: 2026-09-20 影响范围: 管理后台「调整订单 → 车辆安排」页。此前该页结构上只能提交行程用车,本次补上接送机用车的读口与写口。
⚠️ 关键变化
接口契约本身已闭环(可正常提交、可双槽回显),但接送机(TRANSFER)需求同步给车务的链路目前恒失败,业务尚未端到端打通。 前端可以按本文正常开工,但不要把"提交成功"等同于"车务已收到派车任务"。完整证据与根因见「六、边界行为」§「本文的覆盖边界」。
一、背景
「车辆安排」页此前只有一个用车需求槽。页面上那张接送机卡片(航班号、抵离时间、接送备注)来自 vehicleTransportSummary,它是只读的大交通摘要——没有车型、座位数、数量输入,也没有对应的提交字段。于是业务上「接机用什么车、用几辆」没有任何录入通道。
后端的用车需求模型本身早就支持两类并存:表 order_vehicle_requirement 的 requirement_kind 取 TRAVEL(行程用车,服务日=行程日)/ TRANSFER(接送机,服务日=航班日),唯一键 (order_id, active_kind) ⇒ 同一订单两类 active 需求合法并存,各有自己的 fleet 与 service_dates。缺口只在 adjustment 这一层把 kind 焊死成了 TRAVEL。本次把它透出来。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 调整订单预填快照查询 | GET | /v3/admin/order/{id}/adjustment/snapshot |
修改接口 | 新增响应字段 transferRequirement(结构与既有 vehicleRequirement 完全相同) |
| 2 | 调整订单统一提交 | POST | /v3/admin/order/{id}/adjustment/submit |
修改接口 | updates 新增 transferRequirement,支持一次提交同时落 TRAVEL + TRANSFER 两类用车需求 |
三、接口详情
1. 调整订单预填快照查询 GET /v3/admin/order/{id}/adjustment/snapshot
VO: AdjustmentSnapshotRespVO(无独立 ReqVO;入参为 path 变量 id + query 参数 scope)
使用场景
「车辆安排」弹窗打开时调用,一次性拉取行程用车(TRAVEL)与接送机用车(TRANSFER)两类需求的当前 active 版本、以及大交通摘要,用于双卡片回显。scope 传 VEHICLE_REQ(或不传,不传返全部子领域)时本组字段有值;basic 恒返回不受 scope 限制。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
id |
Path | Long | ✅ | 订单雪花 ID | 订单 ID |
scope |
Query | String | ❌ | 逗号分隔枚举:BASIC/PEOPLE/SCHEDULE/ITINERARY/HOTEL_REQ/VEHICLE_REQ;任一 token 非法返 587003 |
限定返回子领域;不传返全部。scope 传了但不含 VEHICLE_REQ 时,vehicleRequirement/transferRequirement/vehicleTransportSummary 三个字段均不返回 |
出参 Result<AdjustmentSnapshotRespVO>
| 字段 | 类型 | 说明 |
|---|---|---|
vehicleRequirement |
VehicleRequirementVO | 行程用车需求(requirement_kind=TRAVEL)。字段名/类型均未变动;该类别无活跃需求时为 null |
transferRequirement |
VehicleRequirementVO | 新增。接送机用车需求(requirement_kind=TRANSFER)。该类别无活跃需求时为 null |
vehicleTransportSummary |
VehicleTransportSummaryVO | 大交通接送时间摘要,结构与行为原样不变,仍是只读展示 |
basic/travelers/schedule/itinerary/hotelRequirement/hotelDayDefaults/lockedDays/editableTabLocksHint |
- | 其余子领域字段,本次未改动,按各自既有 scope 规则返回 |
VehicleRequirementVO 结构(vehicleRequirement 与 transferRequirement 复用同一 VO):
| 字段 | 类型 | 说明 |
|---|---|---|
id |
String | 需求 ID(雪花,序列化为字符串) |
version |
Integer | 版本号 |
status |
String | 需求状态,枚举见「六.5、枚举 / 数据字典」 |
fleet |
Array | 车辆组合,元素 {vehicleType, seats, count} —— 即「用什么车、几座、几辆」 |
specialTags |
Array<String> | 特殊诉求标签(字典 vehicle_special_demand) |
pickupRequired |
Boolean | 兼容回显字段;接机/接站以大交通摘要为准 |
dropoffRequired |
Boolean | 兼容回显字段;送机/送站以大交通摘要为准 |
remark |
String | 备注 |
claimerId / claimerName / claimedAt |
- | 车控人信息(已认领时有值) |
vehicleType / requiredSeats |
- | ⚠️ 旧兼容字段,恒为 null。车型与座位已迁入 fleet,不要再读这两个 |
VehicleTransportSummaryVO 结构(本次未改动,供接送机门控逻辑参考):
| 字段 | 类型 | 说明 |
|---|---|---|
hasPickupTime |
Boolean | 是否有可展示的接送机/站时间——前端据此判断能否提交接送机需求 |
displayText |
String | 汇总展示文案;无时间时为 null |
emptyText |
String | 空态提示;hasPickupTime=false 时返回,当前文案「暂无接送机时间」 |
arrivals / departures |
Array | 到达/离开接送时间明细 |
请求示例
GET /v3/admin/order/2101219133700952066/adjustment/snapshot?scope=VEHICLE_REQ
响应示例
实测节选(订单 2101219133700952066,摘自「八、测试环境已验证」①第二行,仅保留 data 内 vehicleRequirement/transferRequirement 两字段用于结构对照):
{
"vehicleRequirement": {
"id": "2101219223517659138",
"fleet": [{"vehicleType": "mpv", "seats": 7, "count": 1}]
},
"transferRequirement": {
"id": "2101219393722634242",
"fleet": [{"vehicleType": "mpv", "seats": 7, "count": 1}]
}
}
⚠️ 以上两者 fleet 恰好相同是该样本单本身如此,不能拿来证明按 kind 取数生效;真正证明它的是下面「空数据 / 降级响应」的阳性对照,以及两者 id 不同。
空数据 / 降级响应
该订单没有接送机需求时 transferRequirement 为 null(不是空对象,也不是省略字段)。实测阳性对照:订单 2101566624467419137(提交前)两个字段均为 null——用于证明 transferRequirement 不是恒有值、按 kind 派生是真实生效的(若恒有值就无法与 vehicleRequirement 区分开)。
{ "code": 200, "data": { "vehicleRequirement": null, "transferRequirement": null }, "success": true }
错误响应
{ "code": 581007, "message": "订单不存在", "success": false, "data": null }
{ "code": 587003, "message": "调整范围取值非法", "success": false, "data": null }
业务边界
- 未登录/网关未透传
X-Admin-Role→ 401(网关拦截),不进入本接口逻辑 - 订单不存在 →
581007 scope含非法枚举值 →587003,不会静默只返basicvehicleRequirement/transferRequirement为null是正常态(该类别当前无活跃需求),前端不应把null当异常处理- 两个字段结构完全对称,读取代码不应区分对待,唯一差异是各自的
id/fleet/version等业务数据 vehicleType/requiredSeats两个旧兼容字段恒为null,车型信息一律读fleet
2. 调整订单统一提交 POST /v3/admin/order/{id}/adjustment/submit
VO: AdjustmentSubmitReqVO → AdjustmentSubmitRespVO
使用场景
「车辆安排」弹窗点击保存时调用。前端在内存中收集本次改动的 vehicleRequirement(行程用车)与/或 transferRequirement(接送机用车),一次性提交;后端在单一事务内原子应用,任一子域校验失败则整体回滚(含已提交的另一半)。这是「调整订单」弹窗统一提交入口的一部分,本次只新增 updates.transferRequirement 这一个子字段,其余子域(people/schedule/itinerary/hotelRequirement)行为不变。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
id |
Path | Long | ✅ | 订单雪花 ID | 订单 ID |
updates |
Body | Object | ✅ | 至少一个子字段非 null,否则 587012 |
各子域修改内容容器 |
updates.vehicleRequirement |
Body | VehicleRequirementBodyVO |
❌ | 未改子领域置 null |
行程用车需求完整新版本;只传它时行为与改动前逐字节一致 |
updates.vehicleRequirement.fleet |
Body | Array | 提交该需求时必填 | 元素 {vehicleType, seats, count};vehicleType 取值见「六.5、枚举 / 数据字典」 |
车型组合 |
updates.vehicleRequirement.specialTags |
Body | Array<String> | ❌ | 字典 vehicle_special_demand |
通用特殊诉求标签 |
updates.vehicleRequirement.pickupRequired / .dropoffRequired |
Body | Boolean | ❌ | - | 兼容字段 |
updates.vehicleRequirement.remark |
Body | String | ❌ | - | 备注 |
updates.transferRequirement |
Body | VehicleRequirementBodyVO |
❌ | 新增;子字段与 updates.vehicleRequirement 完全相同(fleet/specialTags/pickupRequired/dropoffRequired/remark) |
接送机用车需求完整新版本;🔴 不含 serviceDates——服务日由后端从大交通派生;该订单没有大交通时返 809002;开关未开时返 809009 |
出参 Result<AdjustmentSubmitRespVO>
| 字段 | 类型 | 说明 |
|---|---|---|
success |
Boolean | 提交是否成功。响应体极简,不含业务数据;失败统一由全局异常处理器返回 Result{code, message} |
请求示例
与「八、测试环境已验证」②实测一致,补上 updates 外层包裹以符合 AdjustmentSubmitReqVO 结构:
{
"updates": {
"vehicleRequirement": {
"fleet": [{"vehicleType": "bus", "seats": 19, "count": 1}]
},
"transferRequirement": {
"fleet": [{"vehicleType": "mpv", "seats": 7, "count": 2}]
}
}
}
响应示例
实测原文(HTTP 200,未展开顶层 message/success 字段):
{"code":200,"data":{"success":true}}
空数据 / 降级响应
若 updates 整体所有子字段均为 null(既未改行程用车也未改接送机,也未改其它子域),后端判定为无实际修改,返回 587012(不落库、不产生调整记录)。只传 vehicleRequirement 或只传 transferRequirement 都是合法的部分提交,另一半保持不变——不是"全有全无"。
错误响应
实测原文(订单无大交通时提交 transferRequirement):
{"code":809002,"message":"接送机需求缺少服务日期,请先补齐大交通信息"}
源码定义、未在本次实测中主动触发(测试服开关已开),按 VehicleRequirementKindErrorCode/AdjustmentErrorCode 源码消息模板给出:
{ "code": 809009, "message": "接送机用车需求尚未开放提交,请联系管理员确认开放时间(订单 2101566624467419137)", "success": false, "data": null }
{ "code": 587012, "message": "变更内容为空,无实际修改", "success": false, "data": null }
{ "code": 587002, "message": "订单已是终态,不可调整", "success": false, "data": null }
业务边界
- 事务边界:
updates.vehicleRequirement与updates.transferRequirement在同一个@Transactional事务内应用;任一半失败(如接送机因缺大交通抛809002)整笔回滚,已提交的另一半也不落库 serviceDates前端不传;服务日由后端派生:TRAVEL取行程日,TRANSFER取大交通航班/车次日期(详见「四、契约约束与正确调用方式」)- 开关
hl.order.requirement.transfer-kind-submit-enabled关闭时提交transferRequirement返809009;开关无@RefreshScope,Nacos 热推不生效,需重启实例 - 只传
vehicleRequirement→ 行为与改动前逐字节一致;改动前的请求体不含transferRequirement字段,旧前端请求不受影响(向后兼容) fleet[].vehicleType只接受suv/mpv/bus/sedan四个大类 key,后端兼容历史别名并归一- 调整记录
adjustment-record会为两类需求各产出一条可区分的VEHICLE_REQ条目(行程用车需求已调整/接送机用车需求已调整),见「八、测试环境已验证」③ - 🔴 提交成功仅代表订单侧需求已落库;同步给车务的 outbox 命令目前对
TRANSFER恒失败,详见「六、边界行为」的覆盖边界说明——业务尚未端到端打通
四、契约约束与正确调用方式
本节只写后端接受/拒绝 payload 的规则,不写 UI 渲染建议。
serviceDates 由后端派生,前端禁止传
TRANSFER 的服务日来自大交通,空集合不会兜底成行程日(那样会把航班日写错,派车日期落到需求单声明范围之外):
TRAVEL:服务日 = 行程日(order_itinerary_day派生)TRANSFER:服务日 = 大交通的航班/车次日期(客人可能提前一天到、返程后一天走,所以允许落在行程日窗口之外)
✅ 正确 / ❌ 错误 payload 对照
| 场景 | payload | 结果 |
|---|---|---|
| ✅ 只提交行程用车 | {"updates":{"vehicleRequirement":{"fleet":[...]}}} |
200,行为与改动前一致 |
| ✅ 只提交接送机用车(订单已录大交通) | {"updates":{"transferRequirement":{"fleet":[...]}}} |
200,落 1 条 TRANSFER 需求 |
| ✅ 同页两类都提交 | {"updates":{"vehicleRequirement":{...},"transferRequirement":{...}}} |
200,落 2 条 active 需求(见「八」②实测) |
| ❌ 提交接送机用车但订单未录大交通 | {"updates":{"transferRequirement":{"fleet":[...]}}} |
809002,整笔回滚(见「八」④实测) |
| ❌ 提交接送机用车但开关未开(生产默认) | 同上 | 809009 |
❌ 期望通过入参指定 serviceDates |
{"updates":{"transferRequirement":{"serviceDates":[...]}}} |
无效——该字段不在 VehicleRequirementBodyVO 定义内,传了也会被忽略,服务日仍按后端派生规则计算 |
前端必须处理的前置:没有大交通时提交接送机需求会失败
因此该订单没有录入大交通行程时,提交 transferRequirement 会返回 809002。
⇒ 建议前端在没有大交通时把接送机那一段的输入置灰,并提示「请先录入大交通行程」,不要让用户填完再吃一个错误码。判断依据用同一份快照里的 vehicleTransportSummary.hasPickupTime(为 false 时它还会给出 emptyText,当前文案是「暂无接送机时间」)。
⚠️ 两份同时提交而接送机这半抛 809002 时,整笔调整回滚(一次 submit = 一笔原子调整),行程用车那半也不会落库。所以置灰比事后补救重要。
错误码处置对照(🔴 两码分开处理,别混)
| 错误码 | 触发条件 | 前端应做的下一步 |
|---|---|---|
809002 |
该订单尚未录入大交通行程,却提交了 transferRequirement |
去补大交通——引导用户先在大交通模块录入行程,而不是重试提交 |
809009 |
hl.order.requirement.transfer-kind-submit-enabled 开关未开(生产环境默认关闭) |
找后端开开关——这不是数据问题,重试/补数据都无效,需要后端改配置并重启实例 |
环境开关
hl.order.requirement.transfer-kind-submit-enabled
- 代码默认
false;生产环境未开,提交kind=TRANSFER返809009 - 测试服已置
true(2026-09-19 15:33:32 发布,随 order-v3 重启生效) - ⚠️ 该配置无
@RefreshScope(源码RequirementService注释确认),改完必须重启服务才生效,Nacos 热推不生效
五、数据库行为
写接口 POST .../adjustment/submit 落库表 order_vehicle_requirement(INSERT-only 版本化模型,唯一键 (order_id, active_kind),同订单同 kind 仅 1 行 is_active=1)。
实测②落库结果(订单 2101566624467419137):
active_kind |
fleet |
service_dates |
|---|---|---|
TRAVEL |
[{"count":1,"seats":19,"vehicleType":"bus"}] |
["2026-10-20","2026-10-21","2026-10-22"](行程三天) |
TRANSFER |
[{"count":2,"seats":7,"vehicleType":"mpv"}] |
["2026-10-20","2026-10-23"](接机日 + 送机日) |
🔴 两个 service_dates 一个都不是前端传的,全部由后端按 kind 派生——这是「前端不传日期」这条约定的硬证据。
同订单两类需求各占一行、互不覆盖:TRAVEL 与 TRANSFER 各自维护自己的 version/fleet/service_dates,提交一类不影响另一类已落库的行(除非同次 submit 一起提交)。
写入原子性:updates.vehicleRequirement 与 updates.transferRequirement 在同一个 @Transactional 事务内落库;任一半失败(如 809002)整笔回滚,DB 层零写入(不是"先落一半再补")。
六、边界行为
- 未登录/网关未透传角色 → 401(网关拦截)
- 订单不存在 →
581007 scope非法枚举值 →587003- 订单已是终态(已结算/已取消)→ 提交返
587002,拒绝任何调整(含车辆需求) updates全部子字段为空 →587012- 老数据兼容:改动前落库的旧行仍被正确识别为
requirement_kind=TRAVEL并映射进vehicleRequirement,不会因为响应新增字段而出现兼容异常
🔴 本文的覆盖边界:只验到「提交」为止
同一次实测里观测到:TRANSFER 需求同步给车务的 outbox 命令持续失败
(order_fleet_command_outbox,command_type=RECONCILE:TRAVEL SUCCEEDED,
TRANSFER PENDING / retry_count=2 / last_error_message="Fleet 用车需求换版失败: code=605905, message=需求版本过期")。
⇒ 前端按本文接完即可正常提交并回显,但提交出去的接送机需求目前到不了车务侧。
该缺陷在 fleet(AssignmentService:11492 取当前需求不带 kind、恒取 TRAVEL),已在修,
修好后另发交接件。它不改变本文的前端契约,可以并行开工。
⚠️ 写下这段是因为「四条实测全达成」这个汇总句丢掉边界之后会变强—— 会被读成「接送机用车已经端到端可用」,而那句话今天还不成立。
六.5、枚举 / 数据字典
status(VehicleRequirementVO.status,源码 RequirementStatus 枚举,房/车需求共用单源)
所属字段: vehicleRequirement.status / transferRequirement.status | 类型: String
| 值 | 中文 label | 说明 |
|---|---|---|
PENDING |
待房务配 | 已提交,等待车控接单(核心+团期共用,进入抢单池) |
PROCESSING |
配房中 | 已接单,处理中 |
DONE |
配房完成 | 配车完成 |
PENDING_REVIEW |
待审核 | 仅团期:定制师提交后等团期管理员审核 |
REJECTED_TO_CONSULTANT |
驳回 | 已驳回定制师 |
REJECTED_TO_ADMIN |
驳回 | 已驳回团期管理员(仅团期) |
⚠️ label 是房务侧视角措辞(该枚举被房、车两域共用),车需求场景下前端应另行映射展示文案,不要直接渲染 label 原文。AdjustmentSnapshotRespVO 内嵌 VehicleRequirementVO 的 Swagger 注释写的是「PENDING / CLAIMED / DONE」——该注释与源码枚举 RequirementStatus 不一致,CLAIMED 不是合法取值,请以本表(源码枚举)为准。
fleet[].vehicleType(FleetItem.vehicleType)
所属字段: vehicleRequirement.fleet[].vehicleType / transferRequirement.fleet[].vehicleType / 提交体同路径 | 类型: String
| 值 | 说明 |
|---|---|
suv |
SUV |
mpv |
MPV(本文实测样本使用值) |
bus |
大巴/中巴(本文实测样本使用值) |
sedan |
轿车 |
只选大类,不选具体车型;后端兼容历史别名并归一。
requirement_kind(DB 列 order_vehicle_requirement.requirement_kind;不直接出现在 JSON 字段名中,通过 vehicleRequirement/transferRequirement 两个槽位体现)
| 值 | 对应响应/提交字段 | 服务日口径 |
|---|---|---|
TRAVEL |
vehicleRequirement |
行程日(order_itinerary_day 派生) |
TRANSFER |
transferRequirement |
大交通航班/车次日期(允许落在行程日窗口之外) |
六.6、修改前后对比
字段级对比
| 字段 | 改前 | 改后 |
|---|---|---|
GET .../snapshot 响应 vehicleRequirement |
唯一的用车需求槽 | 语义收窄为「行程用车」,字段名/类型/取值规则不变 |
GET .../snapshot 响应 transferRequirement |
不存在 | 新增,接送机用车需求,无该需求时为 null |
POST .../submit 请求体 updates.vehicleRequirement |
唯一的用车需求提交槽 | 字段名/类型/校验规则不变 |
POST .../submit 请求体 updates.transferRequirement |
不存在 | 新增,接送机用车需求提交槽 |
adjustment-record 车辆需求变更项 label |
恒为「车辆需求已调整」 | 按类别区分为「行程用车需求已调整」/「接送机用车需求已调整」 |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 接送机用车的录入通道 | 无——vehicleTransportSummary 只读展示,没有对应提交字段 |
有——updates.transferRequirement 可提交车型/座位/数量 |
| 一次提交能覆盖的用车类别 | 仅 TRAVEL |
TRAVEL、TRANSFER,或两者同页一次提交(同一原子事务) |
| 调整记录中车辆需求变更的可辨识度 | 无法区分改的是哪一类 | 两条独立可辨识条目 |
TRANSFER 服务日来源 |
N/A(无此提交路径) | 后端从大交通派生,前端不传;无大交通时拒绝(809002) |
六.7、影响评估
- 是否破坏向后兼容: 否——
vehicleRequirement字段名/类型/语义零变更,旧前端请求体(不含transferRequirement)行为与改动前逐字节一致 - 前端是否必须同步上线: 否,本次是纯新增字段/新增可选提交槽,前端可延后接入;接入前不会影响现网「行程用车」链路
- 前端 workaround 清理点: 无——此前接送机用车没有任何前端录入通道,不存在需要撤下的旧 workaround
- 🔴 业务闭环限制:接口契约本身已闭环(提交 + 回显),但 TRANSFER 需求同步给车务的链路当前恒失败(见「六、边界行为」覆盖边界),前端接入后用户能成功提交,但接送机需求实际派不出车,直到 fleet 侧缺陷修复为止
七、不影响范围
- 仅影响: 管理后台「调整订单 → 车辆安排」弹窗的读口(
GET .../adjustment/snapshot)与写口(POST .../adjustment/submit) - 零影响:
vehicleRequirement字段名/类型/语义零变更,现网只读行程用车那部分代码无需调整vehicleTransportSummary(大交通摘要)结构与语义原样不变,仍只读展示- 用车需求生命周期写口
VehicleRequirementAdminController(dispatch/reject/supplier-reject/submit/urgent/urgent/cancel/candidates/assign)均未改动——本次 PR 只动了AdjustmentSnapshotRespVO/AdjustmentSubmitReqVO/AdjustmentService三个源文件(git show --stat 920f29d76核实) - Fleet 侧确认/重开内部写口(
OrderInternalForFleetController的.../vehicle/final-confirmation-reservations、.../release、.../vehicle/reopen-after-assignment-cancel)响应结构未动 - 团期用车需求 reopen(
GroupBatchRequirementController的.../vehicle-requirement/reopen)未动 - 「调整订单」弹窗其余子域(出行人/改期/行程/房需求)的接口与行为完全不受影响
- C 端接口、订单创建/详情读取接口零影响
- 历史数据无需迁移:存量订单的
TRAVEL需求行结构不变;本次不产生任何TRANSFER迁移行
八、测试环境已验证
真实网关调用(2026-09-20,测试服),后端版本 hl-order-service-v3 @ 920f29d76(PR #8024 squash 合入 dev-v3):
① 读口双槽 —— 带阳性对照
| 订单 | vehicleRequirement |
transferRequirement |
|---|---|---|
2101566624467419137(提交前) |
null |
null |
2101219133700952066(两类都有) |
{id:2101219223517659138, fleet:[{mpv,7,1}]} |
{id:2101219393722634242, fleet:[{mpv,7,1}]} |
⚠️ 第二行两者的 fleet 恰好相同(样本单本身如此),所以"两个字段不同"这件事不能拿来证明按 kind 取数生效;真正证明它的是第一行那个全 null 的阳性对照,以及两者 requirementId 不同。 ✓
② 同页提交(本文的核心)
POST /v3/admin/order/2101566624467419137/adjustment/submit
updates.vehicleRequirement = {fleet:[{vehicleType:"bus", seats:19, count:1}]}
updates.transferRequirement = {fleet:[{vehicleType:"mpv", seats:7, count:2}]}
→ HTTP 200 {"code":200,"data":{"success":true}}
落库 order_vehicle_requirement 两条 active 行:
active_kind |
fleet |
service_dates |
|---|---|---|
TRAVEL |
[{"count":1,"seats":19,"vehicleType":"bus"}] |
["2026-10-20","2026-10-21","2026-10-22"](行程三天) |
TRANSFER |
[{"count":2,"seats":7,"vehicleType":"mpv"}] |
["2026-10-20","2026-10-23"](接机日 + 送机日) |
🔴 两个 service_dates 一个都不是前端传的,全部由后端按 kind 派生——这是「前端不传日期」这条约定的硬证据。 ✓
③ 调整记录可区分
GET /v3/admin/order/{id}/adjustment-record → 本次 changeCount:2,两条 type=VEHICLE_REQ,
label 分别是 行程用车需求已调整 / 接送机用车需求已调整。改动前两条 label 完全相同、事后分不出改的是哪一份。 ✓
④ 无大交通的失败形态
订单 2101567681155207169(同产品、已付款、无大交通),只提交 transferRequirement:
→ HTTP 200 + {"code":809002,"message":"接送机需求缺少服务日期,请先补齐大交通信息"}
(提交前已确认测试服 Nacos hl.order.requirement.transfer-kind-submit-enabled: true,
所以这个 809002 不是被开关挡住的假象。) ✓
联调样本:订单 2101219133700952066(订单号 HL20260919155734730,散客单),已录大交通 2 条,TRAVEL 与 TRANSFER 两类需求均已存在,可直接用来验双槽回显。
十、相关文档
- 关联 Issue: wx/HL#7443
- 关联 PR: wx/HL#8024(squash 合并至 dev-v3 @
920f29d76) - fleet 侧 outbox 换版失败(
code=605905)已在修,属#7990那一族,修好后另发交接件——不影响本文描述的前端契约
关联 / 联系人
链接
联系人
- 后端负责人: wx(GIT)
- 前端负责人: mmg