13 KiB
schema, ticket, title, consumer, change_type, author, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
| schema | ticket | title | consumer | change_type | author | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 5824 | 换版后看板缺口消失 / 订单车控误标 DONE 修复:assignmentProgress 新增 staleFinalizedPlan,finalizedByFleet 语义收窄为「已对当前用车需求定稿」 | admin | 修改接口 | wx(GIT) | deployed | not_required | implemented | mmg | aa9c087b | 2026-08-11 | 后端 PR #5843 已合并 dev-v3 并部署测试服,26-5067 双出口实测通过。前端已实现(aa9c087b):BoardSlotSummary 在 assignmentProgress.staleFinalizedPlan===true 时头部挂「需求已换版 · 请核对车型与数量」warning 轻提示(严格 === true,旧契约缺省不误亮,不做按钮禁用)。其余 checklist 实证零改动——finalizedByFleet 前端零消费;「已派几台车」boardSummary 已走 assignmentProgress.assignedSlots/totalSlots 不数 assignmentSlots;CANCELED 槽位渲染层已按 assignmentStatus 区分(display.js canceled 态样式 + OrderDrawer 着色与短信/费用编辑排除);待派车 tab 记录级状态由后端驱动。测试:board-slot-summary 10/10(新增 3 分支用例),fleet 全域 66 文件 619 用例全绿,checkpoint light 全过。 | 2026-08-11 | dev-v3 |
车务看板:换版后缺口重新露出 + 订单车控不再误标完成(#5824)
服务: hl-fleet-service 日期: 2026-08-11 含 Flyway:
20260811.005(fleet_assignment新增plan_finalized_requirement_id定稿归属列) 无新增端点 · 无字段删除 · 无请求参数变化 · 无需改网关路由
背景(一句话)
#5810 换版整槽平移只改派单行的 requirement_id,「已定稿」标记原样保留,于是上一版需求的定稿被当成当前版需求的定稿:
看板把缺口整体抹平(多要的车看不见),订单侧还会据此回发最终方案把车控标成已完成(实测 26-5067 少 1 台车仍 DONE)。
本次给定稿加上「归属哪一版需求」的证据,读侧据此区分「当代定稿」与「换版平移来的陈旧定稿」,修两个出口:
①看板缺口重新露出(下文「变更接口」);②订单车控不再误标完成(下文「订单车控状态(order-v3 侧)」)。
变更接口
GET /admin/fleet/board/orders —— assignmentProgress 结构变化
1. 新增字段 staleFinalizedPlan(Boolean,恒非 null)
| 取值 | 含义 |
|---|---|
true |
该需求名下存在任一非终态派单行携带「上一版需求的定稿」:换版后旧派单被整槽平移过来,车务尚未对这些行按当前需求重新定稿。判据是析取——当代定稿行与陈旧定稿行并存(例如部分槽已按新需求重新确认、部分槽仍是平移过来的旧定稿)时同样为 true,不要求「只剩」旧定稿 |
false |
全部定稿行都归属当前需求(当代定稿)/ 未定稿 / 历史存量行无归属证据(新列上线前的行,按兼容口径视同当代)/ 携带陈旧归属的行已是终态(canceled、completed 一律豁免,不判 true) |
终态豁免的原因:改派与按天改派只把行置为
canceled、不清定稿标记,完结行同理不会再被刷进新方案; 不豁免就会让这些永远动不了的历史行把需求永久钉成「陈旧」(看板永久缺口提示、订单车控永久卡处理中)。
它只是提示,不一定改判:只有 staleFinalizedPlan=true 且确有缺口(suggestedSlots > 现有槽位数)时才撤销定稿权威。
换版只改车型或人数、车数没变时(例:V1 商务车×1 → V2 SUV×1),本字段仍为 true,但计数与卡片状态一律不动——
车型/数量不符按 #5810 已定口径只做提示、不做门禁。
前端建议:staleFinalizedPlan=true 时在卡片上挂一个「需求已换版,请核对车型与数量」的轻提示,配合已有的
requirementFleetText(当前需求车队组成语句)让车管一眼比对。不要用它做任何按钮禁用。
2. finalizedByFleet 语义收窄
| 旧语义 | 新语义 | |
|---|---|---|
finalizedByFleet=true |
车务已提交最终实派方案(不区分是哪一版需求的方案) | 车务已对当前用车需求提交最终实派方案 |
只有当「陈旧定稿 + 确有缺口」同时成立时,finalizedByFleet 才由旧口径的 true 变成 false。
其余场景取值不变(含少派:车务对当前需求定稿后少派也仍是 true,缺口按实派守恒不再报)。
3. staleFinalizedPlan=true 且有缺口时的具体变化
以「V1 商务车×1 已定稿并派车 → 换版为 V2 SUV×2」为例(suggestedSlots=2,现有 1 个槽位):
| 字段 | 修复前 | 修复后 |
|---|---|---|
finalizedByFleet |
true(按上一版定稿) |
false |
staleFinalizedPlan |
无此字段 | true |
totalSlots |
1(按实派守恒) |
2(按当前需求估算) |
unassignedSlots |
0(缺口被抹平) |
1(缺口露出) |
canceledSlots |
0(定稿分支恒 0) |
按实际取消槽位数返回(可 > 0) |
记录级 assignmentStatus |
assigned |
unassigned(当天/临近出发则 unassigned_urgent) |
卡片会换 tab:这类订单从「已派车」跳到「待派车」(临近出发进急单组)。这是本次修复的目的—— 车管必须在待派车里看到它,否则新需求多要的那台车永远没人补。
statusCounts 与列表条数同源一致:summary.statusCounts、statusOptions 与 /orders 列表用的是同一份记录级派生态,
「tab 上有 N 条 → 点进去就是 N 条」这一保证在本次改动后仍然成立(已加回归用例锁定)。
4. ⚠️ 破坏性提醒:assignmentSlots 会包含 CANCELED 槽位
assignmentSlots 原本在 finalizedByFleet=true 时会过滤掉已取消的槽位。
由于本次「陈旧定稿 + 有缺口」会把 finalizedByFleet 置为 false,这类卡片的 assignmentSlots 里会重新出现
baseAssignmentStatus=canceled / assignmentStatus=canceled 的槽位(该需求下整槽被取消的历史槽位;
该需求没有整槽取消历史时列表内容不变)。
前端必须按槽位状态区分渲染:不要假设 assignmentSlots 只含活跃槽位;已取消槽位应置灰或折叠,
不要计入「已派几台车」的展示口径(改用 assignmentProgress 的 assignedSlots/totalSlots)。
这类槽位的 availableActionCodes 为空、canAssign=false,点不动,但会占版面。
GET /admin/fleet/board/summary —— 口径变化(字段结构不变)
| 字段 | 变化 |
|---|---|
todayDepartCount |
「今日出团」只数「今天出发 且记录级已派车」。陈旧定稿且缺口的卡片记录级已被改判为待派车,不再计入本数 |
pendingCount / pendingUrgentCount |
上述卡片改由这两个数体现(今天出发必然落在 unassigned_urgent) |
statusCounts.unassigned / .assigned |
随记录级派生态同步变化,与 /orders 列表同源 |
口径理由:车还没配齐,算作「已派车出团」会让当天出团数虚高、车管漏配车。
订单车控状态(order-v3 侧,定制师页面可见)
本工单修的是两个出口,上面是看板(出口①),这里是订单车控(出口②)。无接口结构变化:
fleet 不新增/修改端点,变的是 order-v3 既有字段 vehicle_control_status 的推进时机。
触发条件(两个条件必须同时成立,与看板同一份「陈旧」行级判据):
- 该需求下存在任一非终态派单行携带上一版需求的定稿(终态行同样豁免);
- 当前需求车数 > 现有非取消槽位数(订单侧刻意排除已取消槽位——取消掉的槽位不是交付出去的车, 与看板按槽位视图计数略有差异,这里统一取更保守的一侧,宁可判未完成也不误报完成)。
结果对比:
| 修复前 | 修复后 | |
|---|---|---|
| 车务确认后的满派判定 | 按「上一版定稿即权威」判已满派(该分支刻意不比对需求车数) | 退回常规拓扑校验,按当前需求的车数 × 服务日核对,缺车即未满派 |
是否回发 DAILY_V3 最终方案 |
回发 | 不回发 |
订单 vehicle_control_status |
被标 DONE(定制师页面显示派车已完成,实际少一台车,实测 26-5067) |
停在处理中(PROCESSING),定制师页面继续显示派车进行中 |
恢复方式:车务在看板对当前需求重新提交/确认最终方案即可自动恢复——确认时定稿归属会被盖章成当前需求 ID,
陈旧判据随即失效,满派后照常回发最终方案、车控回到 DONE。无需人工改库,也不需要运维介入。
只陈旧不缺车不改判:车数没变的换版(只改车型/人数)仍按定稿权威判已满派,车控照常推进到 DONE,
与看板「只提示不改判」保持同一口径。
详情端点说明(无变化)
GET /admin/fleet/board/orders/{orderId} 不返回 assignmentProgress,因此也没有 staleFinalizedPlan。
详情页已有等价且更可操作的信息:requirementFleetText(当前需求车队组成)+ suggestedVehicleCount(需求车数)
actualVehicleCount(实派槽位数)。由于本次改判只在「确有缺口」时发生,凡列表把卡片挪进待派车的订单, 详情页必然满足suggestedVehicleCount > actualVehicleCount,两处不会互相矛盾。
验证证据
测试服(hl-fleet-service 部署于 2026-08-11 14:44,含 PR #5843 合并提交 6789811ea),实测订单 26-5067(HL20260809095538772)。
该单需求 V1 mpv×1(已派 1 台并定稿)→ V2 suv×2,属于典型「换版后车数变多」场景。
存量回填
Flyway 20260811.005 执行后,该单派单行 plan_finalized_requirement_id 精确回填为 V1 的 requirement_id,与行上当前 requirement_id 不等 → 判定为陈旧定稿。真库统计:17 行活跃定稿中 12 行可由确认回执精确反查,其中仅 1 行为真陈旧(即本单),其余存量归属 = 当前需求或留 NULL(兼容档),状态无跳变。
出口①:看板缺口重新露出
GET /admin/fleet/board/orders?keyword=26-5067 实际返回:
"assignmentProgress": {
"totalSlots": 2, "suggestedSlots": 2,
"finalizedByFleet": false, "staleFinalizedPlan": true,
"unassignedSlots": 1, "holdingSlots": 0, "assignedSlots": 1,
"completedSlots": 0, "canceledSlots": 0
}
- 记录级状态
unassigned/ 「待派车」(修复前为assigned「已派车」) - tab 计数与列表条数一致:
statuses=unassigned→ 1 条;statuses=assigned→ 0 条 - 与订单侧「部分回配 (1/2)」口径对齐
出口②:订单车控不再误标完成
在测试服对该单再提交一次换版(V3 suv×2,车数不变仍缺 1 台)实测:
| 项 | 修复前(V2 换版时) | 修复后(V3 换版时) |
|---|---|---|
fleet 行 requirement_id |
平移到新需求 | 平移到新需求(一致) |
plan_finalized_requirement_id |
无此列 | 仍为 V1 → 陈旧 |
| 是否回发 DAILY_V3 最终方案 | 是 | 否 |
order_main.vehicle_control_status |
DONE(缺 1 台车却判完成) | PENDING ✅ |
门禁与测试
- 受影响 6 个测试类 666/666 全绿;
FleetRedLineArchTest12/12;spotless:check通过 - 全量 3505 用例,剩余失败均为环境相关且已在干净
origin/dev-v3基线复现(Testcontainers 并发起容器失败、ReleaseE缺-Dfleet.mysql.releaseE.finalMigrationSha256系统属性),低负载单独重跑 32/32 通过
已知取舍
带 statuses=[unassigned](含 unassigned_urgent)筛选时,后端为了不漏掉「落库态是 assigned/holding、
但记录级会被改判成待派车」的卡片,会把 DB 候选集扩到 unassigned + holding + assigned 再在内存精筛。
副作用:该筛选条件下扫描量变大,更容易触发 5000 条安全上限(触发后走游标扫描,或提示「请增加日期或关键词条件」)。
不带状态筛选的默认首屏不受影响(本来就查全状态)。
前端 checklist
assignmentProgress.staleFinalizedPlan=true时展示换版核对提示(不做按钮禁用)- 不再假设
finalizedByFleet=true等于「有过最终方案」,语义已收窄为「对当前需求定稿」 assignmentSlots按assignmentStatus区分渲染,容忍canceled槽位出现- 「已派几台车」一律取
assignmentProgress,不要自己数assignmentSlots长度 - 待派车 tab 会新增这类换版订单,确认列表/角标/急单分组渲染正常