--- schema: "hl-changelog/v2" ticket: "8528" title: "团期配车重排新增资源态硬校验,响应回填被 clearAll 忽略的行程日" consumer: "admin" author: "wx(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "not_required" frontend_owner: "" frontend_ref: "" target_release: "" verified_at: "" status_note: "PR #8553 合并 dev-v3(7b702f5c3f);hl-fleet-service dev-v3 分支部署测试网关 @ e2982739e8(含 7b702f5c3f)并实测:排入 rest 司机返 605038、排入 DISABLED 车辆返 605037(均一行未落库);正常 ACTIVE 车辆 7 天全排返 addedCount=7;clearAll=true 场景返 ignoredDemandDays 回填生效。" updated_at: "2026-09-30" base: "dev-v3" --- # 团期配车重排:新增资源态硬校验,响应回填被 clearAll 忽略的行程日 > **存放目录**: `changelogs-v2/2026-09/` > **服务**: hl-fleet-service (端口 8087) > **PR**: #8553 > **Issue**: #8528 #8529 > **日期**: 2026-09-29 > **影响范围**: 管理后台团期配车页「整团逐日配车提交」 --- ## ⚠️ 关键变化 - 团期配车重排提交时,本次新增或就地改动的配车行,其车辆与司机的当前状态(是否维保/停用/休假/待激活/黑名单/非在册赛季)现在会被硬校验,不可派即整批提交回滚(工单 #8528)。 - 响应新增字段 `ignoredDemandDays`:`clearAll=true` 时把未被写入的行程日回填给前端(工单 #8529)。此前 `clearAll=true` 提交后无法区分「清完并按新计划重排」与「只清空」,两者响应里 `addedCount` 都是 0。 --- ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 整团逐日配车提交 | POST | `/admin/fleet/group-dispatch/batches/{groupBatchId}/reconfigure` | 新增错误码 + 新增响应字段 | 605037/605038 新增;605006/605013 文案带占位符;响应新增 `ignoredDemandDays` | --- ## 三、接口详情 ### 1. 整团逐日配车提交 `POST /admin/fleet/group-dispatch/batches/{groupBatchId}/reconfigure` **VO**: `GroupDispatchReconfigureReqVO` → `GroupDispatchReconfigureRespVO` #### 使用场景 车务在团期配车页提交/重排整团逐日配车计划:服务端按乘车分组与现状差量比对,多删少补,旧记录软删留痕。本次改动新增两类内容:①提交时对新增/就地改的配车行做车辆与司机的当前可派性硬校验;②`clearAll=true` 时把未写入的行程日回填进响应。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | groupBatchId | Path | Long | ✅ | - | 团期主订单 ID | | requirementId | Body | Long | ✅ | - | 正式团级用车需求 ID;与基线不一致抛 602005 | | requirementVersion | Body | Integer | ✅ | - | 需求版本;落后于基线当前版本抛 602005 | | clearAll | Body | Boolean | 否 | 默认 false | true=整团清零,`demands` 仅当待清日用,不写入任何配车行 | | survivorPolicy | Body | String | 条件必填 | `KEEP_LEGAL`/`REASSIGN`/`RELEASE` | 仅 `clearAll=true` 且该团存在 active 共用关系时必填,缺失抛 602110 | | demands | Body | List<GroupDispatchDayDemandReqVO> | 条件必填 | - | `clearAll=false` 时必填且非空;每项含 `tripDate` + `assignments`(车辆/司机/分组),本次不变 | | reconfigureWindowToken | Body | String | 条件必填 | - | 团期过资源准备阶段后必填,本次不变 | #### 出参 `Result` | 字段 | 类型 | 说明 | |------|------|------| | ignoredDemandDays | List<LocalDate> | **新增(#8529)**:因 `clearAll=true` 未被写入的行程日清单,格式 `yyyy-MM-dd`;`clearAll=false` 时恒为空列表,不会是 null | | addedCount / removedCount / keptCount / updatedCount / aliveCount | Integer | 结构不变 | | coverage | GroupDispatchCoverageRespVO | 结构不变,含 `wholeBatchSatisfied`(全团行程日整体覆盖是否成立)等字段 | | 其余字段 | - | 结构不变,与既有契约一致(本次不变) | #### 请求示例 正常提交(7 天全排 ACTIVE 车辆场景,节选一天): ```json { "requirementId": "5501", "requirementVersion": 3, "clearAll": false, "demands": [ { "tripDate": "2026-09-12", "assignments": [ { "groupId": "BUS", "vehicleId": "1001", "driverId": "2001" } ] } ] } ``` clearAll 场景: ```json { "requirementId": "5501", "requirementVersion": 3, "clearAll": true, "survivorPolicy": "RELEASE", "demands": [ { "tripDate": "2026-11-10", "assignments": [] } ] } ``` #### 响应示例 7 天全排成功: ```json { "code": 200, "message": "成功", "data": { "addedCount": 7, "coverage": { "wholeBatchSatisfied": true } }, "success": true } ``` clearAll 场景(行程日被回填进 `ignoredDemandDays`): ```json { "code": 200, "message": "成功", "data": { "addedCount": 0, "ignoredDemandDays": ["2026-11-10"] }, "success": true } ``` #### 空数据 / 降级响应 无空数据形态;命中资源态硬校验或既有校验失败时 `data=null`,见错误响应。 #### 错误响应 ```json { "code": 605038, "message": "司机处于休假或待激活状态,不能派车:苏和巴特尔", "data": null, "success": false } ``` ```json { "code": 605037, "message": "车辆处于维保或停用状态,不能派车:蒙C02E02", "data": null, "success": false } ``` #### 业务边界 - 605037/605038/605006/605013 四个码新增的占位符文案同样出现在逐户派单写路径(`POST /admin/fleet/assignments` 及改派端点),二者共用同一个资源态校验组件;前端若对这 4 个码有硬编码文案匹配,两条路径都要一起改。 - 资源态校验是整批拒绝:任意一天新增/就地改的车辆或司机不可派,会回滚本次整团提交,不是部分成功。 - 本次未改动的存量配车行不重判——车辆/司机事后状态变化不会把整团重配卡死,只挡本次新增/就地改的行。 - 车辆/司机已被删除时,占位符退回请求里携带的主键(`ID=车辆ID` / `ID=司机ID`),不是报 500。 - `ignoredDemandDays` 在 `clearAll=false` 时恒为空列表(不是 null),前端可无条件取其长度判断有无回填项。 --- ## 四、契约约束与正确调用方式(接口类必写) > 本节只写**后端接受/拒绝 payload 的规则**,不写 UI 渲染建议。 ### ✅ 正确 / ❌ 错误 payload 对照 | 场景 | payload | |------|---------| | ✅ 排入正常 ACTIVE 车辆/司机 | 正常提交,返回 `code=200` | | ❌ 排入 DISABLED/维保车辆 | 任意排车项使用该车辆 → `605037` | | ❌ 排入休假/待激活司机 | 任意排车项使用该司机 → `605038` | ### 切换状态时的必要动作 收到 605037/605038/605006/605013 直接把 `message` 展示给车务,引导其在该排车项上更换车辆或司机后重新提交;本端点无独立幂等键字段,防重仅靠既有 10 秒窗口,修正后正常重提即可。 --- ## 五、数据库行为(涉及写操作时必写) 本次未新增表、未新增列。资源态硬校验发生在写入前(校验车辆/司机当前状态),校验不通过时整批回滚、不产生任何 `fleet_group_dispatch` 写入;`ignoredDemandDays` 是内存计算结果、不落库。 --- ## 六、边界行为 - 未登录 → 401(网关拦截) - 车辆/司机已被删除 → 错误码占位符退回请求里携带的主键(`ID=车辆ID`/`ID=司机ID`),不是 500 - 本次未改动的存量配车行不参与资源态重判 - `clearAll=false` 时 `ignoredDemandDays` 恒为空列表,不是 null --- ## 六.5、枚举 / 数据字典(接口出现枚举时必写) 本次未新增或变更任何枚举取值;`survivorPolicy`(`KEEP_LEGAL`/`REASSIGN`/`RELEASE`)沿用既有契约,未变化。 ## 六.6、修改前后对比(修改/删除类接口必写,新增跳过) ### 字段级对比 | 字段 | 改前 | 改后 | |------|------|------| | `data.ignoredDemandDays` | 不存在 | 新增,`clearAll=true` 时回填未被写入的行程日 | | 605006 `message` | `司机已黑名单,不能派车` | `司机已黑名单,不能派车:{司机姓名}`(缺姓名退回 `ID=司机ID`) | | 605013 `message` | `司机非在册赛季不可派单` | `司机非在册赛季不可派单:{司机姓名}`(缺姓名退回 `ID=司机ID`) | ### 行为级对比 | 行为 | 改前 | 改后 | |------|------|------| | 排入维保/停用车辆 | 无该项硬校验,可能带着不可派车辆落库 | 605037 拒绝,整批回滚 | | 排入休假/待激活司机 | 无该项硬校验,可能带着不可派司机落库 | 605038 拒绝,整批回滚 | | `clearAll=true` 提交 | 响应无法区分「清完重排」与「只清空」 | `ignoredDemandDays` 回填未写入日期 | ## 六.7、影响评估(修改/删除类必写) - **是否破坏向后兼容**: 否——605037/605038 是新增错误码,605006/605013 只在文案末尾追加占位符文本(前端如做精确字符串匹配需要更新);`ignoredDemandDays` 是新增字段,旧前端忽略它不受影响。 - **前端是否必须同步上线**: 否——新增字段/错误码是可选适配,未处理时行为退化为"看不到具体车牌/司机名,只看到通用错误码提示",不影响提交本身的成败判定。 - **前端 workaround 清理点**: 若此前靠 `addedCount===0` 猜测「clearAll 是否清空后又重排」,可以换成直接读 `ignoredDemandDays`。 --- ## 七、不影响范围(显式声明, 帮前端/QA 缩小排查面) - **仅影响**: 管理后台团期配车页「整团逐日配车提交」(`POST reconfigure`) - **零影响**: - 确认整团配车端点(`POST confirm`)本次未改动响应结构(其资源态硬校验为工单 #8528 同批改动,但不在本 changelog 覆盖范围内) - 团期配车四个读口(总览/就绪/共用关系/共用候选,见另一份 changelog) - 既有错误码(600003-600011、602005-602012 等)语义与格式不变 --- ## 八、测试环境已验证 服务:`hl-fleet-service`,dev-v3 分支部署测试网关 @ `e2982739e8`(含 #8528/#8529 所在提交 `7b702f5c3f`),测试网关 `https://api.test.1814.love`: ``` ✓ 排入 driverStatus=rest 的司机 → code=605038, message="司机处于休假或待激活状态,不能派车:苏和巴特尔",一行未落库 ✓ 排入 DISABLED 车辆(车牌 蒙C02E02)→ code=605037, message="车辆处于维保或停用状态,不能派车:蒙C02E02",一行未落库 ✓ 正常 ACTIVE 车辆 7 天全排 → code=200, addedCount=7, coverage.wholeBatchSatisfied=true(回归未破坏) ✓ clearAll=true 场景 → code=200, data.addedCount=0, data.ignoredDemandDays=["2026-11-10"] ``` --- ## 十、相关文档 - 关联 Issue: [wx/HL#8528](https://git.1814.love/wx/HL/issues/8528)、[wx/HL#8529](https://git.1814.love/wx/HL/issues/8529) - 关联 PR: [wx/HL#8553](https://git.1814.love/wx/HL/pulls/8553) ## 关联 / 联系人 ### 链接 - **Issue**: [#8528](https://git.1814.love/wx/HL/issues/8528)、[#8529](https://git.1814.love/wx/HL/issues/8529) - **PR**: [#8553](https://git.1814.love/wx/HL/pulls/8553) - **Merge commit**: [7b702f5c3f](https://git.1814.love/wx/HL/commit/7b702f5c3f) ### 联系人 - **后端负责人**: @wx