文件
hl-api-changelog/changelogs-v2/2026-09/29_8530_团期用车需求换组配车迁移下界字段-修改接口-管理后台.md
T
Mimingguang 38164c6439
changelog-filename-gate / validate (push) Failing after 2s
chore(changelog): #8530 回写 implemented(hl-admin 38bcab54)
2026-09-30 22:59:32 +08:00

17 KiB
原始文件 Blame 文件历史

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 8530 团期用车需求换组时把旧版已排车行整槽平移,响应新增 migratedAssignmentCount 平移下界字段 admin wx(GIT) 修改接口 deployed verified implemented hl-admin(claude-opus-4-8) 38bcab548c5d71317d0f56c6d0051c7fe7a0d4fd 2026-09-30 PR #8563 合并 dev-v3(cb876bf780);hl-order-service-v3 + hl-fleet-service 已随该提交部署测试网关;order-v3 新增单测 6 条(RequirementServiceTest)+ fleet 新增单测 6 条(AssignmentServiceTest)+ mapper 层 2 条 + 跨服务常量 1 条,共 15 条,均为换组迁移/无配车迁移/同内容重放不迁移/非团期恒 0/订单终态不迁移等场景的定向用例。;前端已交付:FunItemAdjustModal 成功提示附换组平移基数(>0 显「旧版 N 行配车将平移至新需求」,0/统一提交路径原提示),spec 3 例,checkpoint 全绿(hl-admin 38bcab54) 2026-09-29 dev-v3

团期用车需求换组:响应新增 migratedAssignmentCount 平移下界字段

存放目录: changelogs-v2/2026-09/ 服务: hl-order-service-v3(响应端点所在服务)+ hl-fleet-service(旧版配车整槽平移的执行方,经 Outbox/Feign 异步处理,前端不直接调用它) PR: #8563 Issue: #8530 日期: 2026-09-29 影响范围: 管理后台订单详情页「提交/修改/调整用车需求」接口的响应体(仅团期子订单换组场景新增字段值有意义)


⚠️ 关键变化

  • 团期子订单在「改提/换组」用车需求时,旧版本名下已经排好的车行,此前会原地留在已失活的旧 requirementId 下,车务侧对这些行的任何后续推进都会撞错误码 605905/605913 且没有任何提示;现在后端会在换组的同一时刻把这些行整槽平移到新需求。
  • 响应 VO VehicleRequirementRespVO 新增字段 migratedAssignmentCount(Integer,恒非 null):本次换版交给车务平移的配车基数(下界),不是真实迁移行数。它在所有分支(首提/改提/完成后调整/幂等重放)都会回填,取 0 或正整数,从不为 null。

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 提交/修改/调整用车需求 PUT /v3/admin/order/{id}/vehicle-requirement 响应新增字段 data.migratedAssignmentCount

三、接口详情

1. 提交/修改/调整用车需求 PUT /v3/admin/order/{id}/vehicle-requirement

VO: VehicleRequirementReqVO → VehicleRequirementRespVO

使用场景

定制师/团期管理员在订单详情页提交、修改或调整用车需求。后端按 order_vehicle_requirement 表当前 active 行是否存在及其状态自动判三分支:无 active → INIT_SUBMIT 首提;PENDING → PENDING_EDIT 改提;DONE → DONE_ADJUST 完成后调整。同内容重放(与当前生效版本完全一致)额外命中 IDEMPOTENT_NOOP,不换版。consultantId 由后端从 JWT 解析,不接受前端传入。

团期子订单每次「改提/换组」(即 PENDING_EDIT 分支且确实发生换版)都会触发本次改动:旧版本名下已经排好的车行会被整槽平移到新需求,响应回填 migratedAssignmentCount 说明本次交给车务平移的基数。非团期(核心)订单、首次提交、同内容重放三种情况都不触发平移,字段恒为 0。

入参字段表

字段 位置 类型 必填 约束 说明
id Path Long 是 正整数 ID 订单 ID
kind Body String 否 TRAVEL/TRANSFER,不传按 TRAVEL 需求类别:TRAVEL=团期行程用车(服务日冻结为行程日),TRANSFER=接送机(服务日由大交通派生)
fleet Body List<FleetItem> 是 至少 1 项 车型组合
fleet[].vehicleType Body String 是 suv/mpv/bus/sedan 车型大类 key(只选大类,不选具体车型)
fleet[].seats Body Integer 是 需在该大类座位选项内 座位数
fleet[].count Body Integer 是 >0 辆数
specialTags Body List<String> 否 需在字典 vehicle_special_demand 内 通用特殊诉求标签,应用到全部车辆
pickupRequired Body Boolean 否 - 兼容字段,接机/接站以实时大交通批次为准
dropoffRequired Body Boolean 否 - 兼容字段,送机/送站以实时大交通批次为准
remark Body String 否 ≤500 字符 备注

本次改动未新增或修改任何入参字段,上表为该端点既有契约,供本节自包含阅读。

出参字段表

字段 类型 说明
data.id Long 需求行 ID
data.kind String 需求类别:TRAVEL/TRANSFER
data.serviceDates List<LocalDate> 本版冻结的服务日期,升序去重
data.version Integer 版本号
data.isActive Boolean 是否为当前生效版本
data.status String 需求状态(PENDING/PENDING_REVIEW/PROCESSING/DONE 等)
data.branchTaken String 实际走的分支:INIT_SUBMIT/PENDING_EDIT/DONE_ADJUST/IDEMPOTENT_NOOP
data.previousVersion Integer/null DONE_ADJUST 分支回填上一版本号;其余分支为 null
data.assignmentDeletedCount Integer/null DONE_ADJUST 分支回填软删旧配车行数;其余分支为 null
data.migratedAssignmentCount Integer 【新增】 本次换版交给车务平移的配车基数(下界),恒非 null;语义见下方业务边界
data.passengerCount Integer 订单乘车人数(成人+儿童+幼童+婴儿),结构不变
data.vehicleCount Integer 车辆总数,结构不变
data.totalSeatCount Integer 车辆座位总数(含司机座),结构不变
data.driverSeatCount Integer 司机占用座位数,结构不变
data.passengerSeatCapacity Integer 可载客座位数,结构不变
data.remainingPassengerSeats Integer 剩余可载客座位数,结构不变
data.pickupRequired / data.dropoffRequired Boolean 兼容回显字段,结构不变
data.submittedAt / data.claimerId / data.claimerName / data.claimedAt - 结构不变

请求示例

{
  "kind": "TRAVEL",
  "fleet": [
    { "vehicleType": "mpv", "seats": 7, "count": 1 }
  ],
  "specialTags": ["中文司机"],
  "remark": "客户要求中文司机"
}

响应示例

团期子订单换组,旧版名下有 3 行在途配车镜像(branchTaken=PENDING_EDIT 且触发平移):

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "id": "2810002",
    "kind": "TRAVEL",
    "serviceDates": ["2026-07-19", "2026-07-23"],
    "version": 2,
    "isActive": true,
    "status": "PENDING_REVIEW",
    "branchTaken": "PENDING_EDIT",
    "previousVersion": null,
    "assignmentDeletedCount": null,
    "migratedAssignmentCount": 3,
    "passengerCount": 2,
    "vehicleCount": 1,
    "totalSeatCount": 7,
    "driverSeatCount": 1,
    "passengerSeatCapacity": 6,
    "remainingPassengerSeats": 4,
    "pickupRequired": true,
    "dropoffRequired": true
  }
}

首次提交 / 同内容重放(IDEMPOTENT_NOOP),没有旧版可迁移:

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "id": "2812001",
    "branchTaken": "IDEMPOTENT_NOOP",
    "migratedAssignmentCount": 0
  }
}

空数据 / 降级响应

本接口不存在空数据形态:请求参数合法时恒返回单条需求行;下游依赖(车队字典等)不可用时走错误响应,不降级为空对象。

错误响应

{
  "code": 582021,
  "message": "用车需求数组不能为空",
  "success": false,
  "data": null
}
{
  "code": 582030,
  "message": "当前需求状态不可修改(处理中)",
  "success": false,
  "data": null
}

本次改动未新增任何错误码,以上两例是该端点既有校验错误码,供本节自包含阅读。

业务边界

  • migratedAssignmentCount 是「下界」不是真实迁移行数:取值 = 换组前那一版 requirement 上挂着的已排车行数(按上一版 requirementId 统计 order_vehicle_assignment);真实平移由车务侧异步幂等执行,只搬活跃非取消行,可能小于等于该下界。
  • 连续换组(A→B 再 B→C)第二次读到的恒为 0,但迁移确实发生了:A→B 那一次已经把行迁到 B 名下,B→C 这一次按「上一版」(B)统计,B 名下此时还没有新快照(新快照要等车务重新确认后才按新需求落),统计结果恒为 0。前端不能把 0 解读成"这条链路从未发生过迁移",只能解读成"本次调用没有新的迁移基数"。
  • 首次提交(INIT_SUBMIT)与同内容重放的幂等分支(IDEMPOTENT_NOOP):字段恒为 0,且不触发平移信号。
  • 非团期(核心)订单:字段恒为 0,且不额外查询配车镜像表(不新增一次 DB 往返),行为与本次改动之前完全一致。
  • 订单处于终态(COMPLETED/CANCELLED)时不触发平移信号,字段为 0——即使是经由"订单调整"入口提交(该入口本身绕过普通提交闸),终态订单同样不发平移。
  • 该字段在全部四个分支(INIT_SUBMIT/PENDING_EDIT/DONE_ADJUST/IDEMPOTENT_NOOP)都会回填,恒非 null。

四、契约约束与正确调用方式

本节只写后端字段语义与正确/错误解读,不写 UI 渲染建议。

✅ 正确 / ❌ 错误解读对照

场景 解读
✅ migratedAssignmentCount > 0 本次换版确有旧版配车行被交给车务侧平移
✅ migratedAssignmentCount = 0 且 branchTaken = INIT_SUBMIT / IDEMPOTENT_NOOP 本来就没有触发换版,字段恒为 0,属正常值
✅ migratedAssignmentCount = 0 且 branchTaken = PENDING_EDIT 旧版名下当时没有在途配车镜像,或本次读到的是连续换组链路中的中间一跳
❌ 用单次 = 0 断言"这条订单从未发生过配车平移" 连续换组 A→B→C 时,B→C 这一次恒读 0,但 A→B 时已经迁移过;单次响应不是整条历史的累计值

不需要的前置动作

该字段只出现在响应里,不改变入参契约:请求体字段零变化,无需为这个字段额外传参或做请求前置。


五、数据库行为

migratedAssignmentCount 不落库、不是新增列:它是响应组装时的即时统计结果,等价于:

SELECT COUNT(*) FROM order_vehicle_assignment
WHERE requirement_id = <换组前的旧 requirementId> AND deleted = 0

需求行本身仍按既有逻辑落库(旧版 deactivate + 新版 insert),本次未新增、未变更任何表结构或列。真实的配车行迁移(把 order_vehicle_assignment.requirement_id 从旧值改写为新值)发生在车务侧(hl-fleet-service),经异步 Outbox/Feign 通道执行,与本端点的同步响应解耦。


六、边界行为

  • 未登录 → 401(网关拦截)。
  • 入参校验失败(fleet 为空、车型非法等)→ 既有错误码,HTTP 200,data=null。
  • 非团期(核心)订单:migratedAssignmentCount 恒为 0,且不额外查询 order_vehicle_assignment,行为与本次改动之前一字不变。
  • 订单终态(COMPLETED/CANCELLED):不触发平移信号,migratedAssignmentCount=0。
  • 业务失败仍可能是 HTTP 200,需同时检查 code、success 和 message。

六.5、枚举 / 数据字典

本次未新增或变更任何枚举取值。branchTaken 沿用既有四个取值,未变化:

branchTaken(响应字段)

所属字段: data.branchTaken | 类型: String

值 中文 说明
INIT_SUBMIT 首次提交 订单无 active 需求行时的分支
PENDING_EDIT 改提/换组 当前 active 需求为 PENDING 时的分支;团期订单在此分支触发配车平移
DONE_ADJUST 完成后调整 当前 active 需求为 DONE 时的分支
IDEMPOTENT_NOOP 幂等重放 提交内容与当前生效版本完全一致,不换版、不触发平移

六.6、修改前后对比

字段级对比

字段 改前 改后
data.migratedAssignmentCount 不存在 新增,Integer,恒非 null,团期换组场景回填平移基数,其余场景为 0

行为级对比

行为 改前 改后
团期子订单改提/换组时,旧版名下已排的车行 留在已失活的旧 requirementId 下,车务对其任何后续推进都会撞 605905/605913,且没有任何信号 换组的同一时刻整槽平移到新需求,响应回填平移基数
团期换组是否发布逐日配车快照 不适用(旧版本就是孤儿状态,不发快照) 平移这一档只做整槽平移,仍不发布逐日快照(新需求停在 PENDING_REVIEW,须经管理员审核 + C2 提交车务后才放行)

六.7、影响评估

  • 是否破坏向后兼容: 否。新增响应字段,旧前端忽略它不受影响;入参契约与既有错误码零变化。
  • 前端是否必须同步上线: 否。字段是可选适配;若前端不读取该字段,端点行为(换组成功、旧配车被平移)照常生效,只是前端看不到"本次平移了几行"这个信息。
  • 前端 workaround 清理点: 无。此前该场景下前端没有任何字段可用于感知"旧配车是否被平移",因此没有需要清理的旧逻辑。

七、不影响范围

  • 仅影响: 团期子订单在订单详情页「改提/换组」用车需求后的响应体,以及旧版已排车行是否被后端平移这一行为。
  • 零影响:
    • 请求参数(VehicleRequirementReqVO 零变化)
    • 首次提交(INIT_SUBMIT)与完成后调整(DONE_ADJUST)两个分支的既有字段语义(previousVersion/assignmentDeletedCount 等)
    • 非团期(核心)订单提交用车需求的行为——该路径 migratedAssignmentCount 恒 0 且不新增 DB 查询,与改动前完全一致
    • 该端点既有错误码(零新增)
    • 派单看板、逐日配车快照发布等下游读接口的响应结构(本次不改写它们)

八、测试环境已验证

服务:hl-order-service-v3 + hl-fleet-service,合并提交 cb876bf780(PR #8563)已合入 dev-v3 并部署测试网关。

新增单测(均为源码可核实的真实用例,覆盖以下场景):

hl-order-service-v3 RequirementServiceTest(6 条):

  • upsertVehicle_groupOrderPendingEdit_migratesPreviousRequirement:团期改提换版 → 登记平移信号,migratedAssignmentCount=3(按旧需求 ID 精确统计,非按新需求 ID 误统计)
  • upsertVehicle_groupOrderPendingEditNoAssignment_migratedCountZero:旧需求名下无在途配车 → 仍登记平移信号,migratedAssignmentCount=0
  • upsertVehicle_groupOrderSameContent_idempotentNoopNoMigrate:同内容重放(IDEMPOTENT_NOOP)→ 不登记平移信号,不查询镜像表,migratedAssignmentCount=0
  • upsertVehicle_coreOrderPendingEdit_migratedCountZero:非团期订单改提 → migratedAssignmentCount 恒 0,不新增 DB 查询
  • upsertVehicleForOrderAdjustment_groupOrderCompleted_noMigrate:订单已完成(COMPLETED)→ 不发平移信号
  • upsertVehicleForOrderAdjustment_groupOrderNotTerminal_stillMigrates:同订单调整入口、订单非终态 → 照常发平移信号(上一条的阳性对照)

hl-fleet-service AssignmentServiceTest(6 条,验证可派性闸放宽范围不外溢):

  • expand_团期改提新需求待审核_放行整槽平移
  • expand_非待审核需求换版平移_仍按既有出口发布逐日快照(阳性对照)
  • expand_不可派且非待审核需求_仍然拒绝
  • expand_待审核需求但无前序需求_仍然拒绝
  • create_当前需求待审核_仍抛605906(放宽不外溢到一步派定)
  • restoreCancel_当前需求待审核_仍拒绝恢复(放宽不外溢到撤销取消)

另有 mapper 层 OrderVehicleAssignmentMapperTest 新增 2 条、跨服务状态字面量对齐 RequirementStatusTest 新增 1 条。


十、相关文档

关联 / 联系人

链接

联系人

  • 后端负责人: @wx