--- schema: "hl-changelog/v2" ticket: "9209" title: "单团排车项上限由 4000 收紧到 500:超过 500 项在提交阶段即被拒,文案改为「请减少配车项后重新提交」" consumer: "admin" author: "chewu5(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "not_required" frontend_owner: "" frontend_ref: "" target_release: "" verified_at: "" status_note: "已合并 dev-v3(PR #9218,squash 5f1d456c4),已部署测试服(deploy-backend hl-fleet-service --branch dev-v3,11:47:04):deploy-status 显示 dev-v3 / 5f1d456c4 / 0/N / ok;双实例 8087、8187 health 均 200,部署日志 Started 之后 ERROR 0。契约变化只有一处上限:POST /admin/fleet/assignments/batch 的 dailyPlan 由最多 4000 项收紧到 500 项(@Size(max=500)),501 项起返回 400 + 可执行文案;入参字段名/类型、出参结构、其余错误码均未变。确认侧上限 500 与 #9193 的计数守卫原样保留,常量统一到 FleetLimits.MAX_DISPATCH_ITEMS_PER_GROUP。hl-ui 不改也不会错;若前端曾按 4000 做本地上限,建议同步到 500,免得用户填到 501~4000 项才在提交时被拒。" updated_at: "2026-10-23" base: "dev-v3" --- # hl-fleet-service: 单团排车项上限由 4000 收紧到 500 > **服务**: hl-fleet-service(管理后台) > **PR**: #9218(已合入 dev-v3,合并提交 5f1d456c4) > **Issue**: #9209 > **日期**: 2026-10-23 > **影响范围**: 管理后台「车务最终实派方案」批量提交(`dailyPlan` 项数上限) --- ## ⚠️ 关键变化 🟢 `POST /admin/fleet/assignments/batch` 的 `dailyPlan` 上限:**4000 项 → 500 项**。 🟢 超过上限的拒绝文案改为可执行提示: ```text 单次逐日派车配置不能超过500项,请减少配车项后重新提交 ``` 🔴 请求体字段名/类型、响应结构、错误码集合都没变;500 项整仍然成功提交,501 项起才被拒。 --- ## 一、背景 确认侧(`POST /admin/fleet/group-dispatch/batches/{groupBatchId}/confirm`)自 #9179 起单团只允许 500 行存活配车行,而提交侧 `batchCreate` 的 `dailyPlan` 一直允许 4000 项(该数值来自 #5292,无容量依据)。两者不一致的结果是:**501~4000 项的团能建得成、却永远确认不了**——25 天 × 21 车的常规团就是 525 项,直接命中。 wx 2026-10-23 拍板:500 够用,提交侧收紧到 500。本单同时把「500」这个数字收敛到唯一出处 `FleetLimits.MAX_DISPATCH_ITEMS_PER_GROUP`:提交侧的 Bean Validation 注解与确认侧的行数守卫引用同一个常量,避免将来改一处漏一处。 ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 车务最终实派方案原子提交 | POST | `/admin/fleet/assignments/batch` | 入参上限收紧 + 文案 | `dailyPlan` 最多 500 项(原 4000);其余字段与出参不变 | ## 三、接口详情 ### 1. 车务最终实派方案原子提交 `POST /admin/fleet/assignments/batch` **VO**: `BatchCreateAssignmentReqVO` / `Result` #### 使用场景 管理后台在团期 / 订单的车务配车页点「提交最终方案」时调用:一次提交该需求在完整日期窗内的逐日配车清单(服务日期 × 车辆 × 司机),服务端原子落库并回写订单。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | orderId | Body | Long | ✅ | - | 订单 ID | | requirementId | Body | Long | ✅ | - | 当前生效用车需求 ID | | kind | Body | String | 否 | TRAVEL / TRANSFER | 需求类别,不传按 TRAVEL | | startDate / endDate | Body | Date | ✅ | - | 用车起止日期 | | requestId | Body | String | ✅ | ≤ 64 字符 | 批次级幂等标识 | | **dailyPlan** | Body | Array | ✅ | **≤ 500 项(原 4000)** | 按行程日的完整配车列表,逐项为 服务日期×车辆×司机;同一服务日允许多条 | | 其余字段 | Body | - | 否 | - | 与改动前一致(headcount / pickupAt / dropoffAt / sendItinerarySms 等) | #### 出参 `Result` 结构与字段名均未变: | 字段 | 类型 | 说明 | |------|------|------| | assignments | Array | 本次提交落库的配车行列表 | | finalPlanPublished | Boolean | 最终方案是否已发布 | | finalPlanNotPublishedReason | String | 未发布时的第一个原因;发布时为 null | | pickupDropoffGate | Object | 接送机第③步门禁信息 | | failedFleetItemIndex | Integer | 失败的配车项下标(仅失败时) | | dailyDifferences | Array | 整批 diff 明细(按日) | | fleetItemIndex | Integer | 当前处理到的配车项下标 | | assignment | Object | 单行写入结果(`AssignmentWriteRespVO`) | #### 请求示例 ```json { "orderId": "2112275846201069569", "requirementId": "2112275846201070000", "startDate": "2026-10-25", "endDate": "2026-10-30", "requestId": "batch-20261023-0001", "dailyPlan": [ { "serviceDate": "2026-10-25", "vehicleId": "2112275846201088001", "driverId": "2112275846201099001" } ] } ``` #### 响应示例 ```json { "code": 200, "message": "成功", "data": { "finalPlanPublished": true, "finalPlanNotPublishedReason": null }, "success": true } ``` #### 空数据 / 降级响应 `dailyPlan` 为空或缺失不属于降级场景:`@NotNull` 直接拒绝,返回 400「逐日派车计划不能为空」。 #### 错误响应 超过 500 项时(HTTP 200 + 业务码,网关统一语义): ```json { "code": 400, "message": "单次逐日派车配置不能超过500项,请减少配车项后重新提交", "data": null, "success": false } ``` 其余错误码(605062 服务日期越窗、605912 派车快照缺车型等)语义与文案均未变。 #### 业务边界 - `dailyPlan` 恰好 500 项:**成功**,与改动前一样走完整提交流程。 - `dailyPlan` 501 项起:`@Size` 拒绝,**零写入**,不产生配车行、不触发订单回写。 - 确认侧上限仍是 500 行存活配车行(#9179 / #9193),且 #9193 的「先计数拒绝、不读明细」守卫原样保留;提交侧与确认侧现在共用同一常量。 - 本单不动读取路径、不动表结构、不订正存量数据。 ## 四、契约约束与正确调用方式 | 场景 | 调用 | |------|------| | ✅ 单团 ≤ 500 项 | 正常提交 | | ❌ 501~4000 项 | 会被 400 拒绝;应按提示减少配车项后重新提交,不要重试同一请求 | | ❌ 把 400 当成可重试的并发错误 | 不是并发错误,重试不会改变项数 | 前端若做提交前校验,上限请用 **500**;已经按 4000 做本地上限的页面在 501~4000 项时会拿到上述 400 与文案(功能不会错,只是提示出现在提交时刻)。 ## 五、数据库行为 无表结构变更、无 Flyway、无数据订正。仅提交侧入参校验收紧。 ## 六、边界行为 - 边界严格按 `> 500`:500 成功、501 拒绝,两侧都有单元用例(`BatchCreateAssignmentReqVOTest#validate_dailyPlanAtLimit_passes` / `#validate_dailyPlanOverLimit_violatesSize`)。 - 校验发生在 Controller 入参绑定阶段(`@Valid`),早于任何业务写入与锁获取。 - 确认侧文案:「拆团」措辞已清理,现为「请减少配车项后重试」(该动作没有接口,不该出现在提示里)。 ## 六.6、修改前后对比 ### 行为级对比 | 场景 | 改前 | 改后 | |------|------|------| | dailyPlan = 500 项 | 成功 | 成功(不变) | | dailyPlan = 501 项 | 成功提交(随后永远确认不了) | 400 拒绝,零写入 | | dailyPlan = 1000 / 4000 项 | 成功提交(死团) | 400 拒绝 | | 确认侧 > 500 存活行 | 602010(#9193:先计数拒绝) | 不变 | ### 字段级对比 无字段变化:字段名、类型、必填性、枚举、错误码数值均未改;只有 `dailyPlan` 的 `@Size(max)` 由 4000 变为 500,以及超限文案改为可执行提示。 ## 六.7、影响评估 - **是否破坏向后兼容**: 是「收紧」而非「破坏」——合法调用(≤ 500 项)行为与出参完全不变;原本能提交的 501~4000 项现在被提前拒绝,而这批数据原本也无法确认(确认侧上限 500)。 - **前端是否必须同步上线**: 否。前端不做任何改动也能正常提交 ≤ 500 项;若前端自己按 4000 做本地上限,建议同步到 500(只是把提示提前到用户编辑时)。 - **前端 workaround 清理点**: 若有页面按 4000 做客户端条数校验,把常量改为 500。 - **存量数据**: 测试服 > 500 行的团 0 个,无需订正;生产如有存量死团,应另单处置(本单不做数据订正)。 ## 七、不影响范围 - 其它 `hl-fleet-service` 接口:`PickupDropoffConfigReqVO` 的 4000 上限属接送机配置,写的是另一张表、不参与 `fleet_group_dispatch`,本单未改。 - 确认侧守卫逻辑(#9193)零改动。 - `hl-mini` / `about-h5` 不消费 `/admin/fleet/**`。 ## 八、测试环境已验证 | 项 | 读数 | |---|---| | 部署 | `deploy-backend hl-fleet-service --branch dev-v3` 11:47:04;deploy-status:dev-v3 / 5f1d456c4 / 0/N / ok | | 双实例 | 8087、8187 `is UP`,`/actuator/health` 均 200 | | 部署日志 | 两实例 `Started` 之后 ` ERROR ` 计数均 0 | | 定向测试 | `BatchCreateAssignmentReqVOTest` 13 / `AssignmentControllerTest` 49 / `GroupDispatchConfirmTest` 32 / `FleetRedLineArchTest` 31+2,SUM tests=127 failures=0 errors=0 skipped=0 | | 编译 | 清 classes 后重新编译:Compiling 1195 main + 532 test,EXIT=0 | | 存量数据只读核对 | 测试服 `fleet_group_dispatch` 存活行:>500 行的团 0 个(最多 7 行,4 团共 23 行)⇒ 无死团需要处置 | ## 十、相关文档 - `docs/fleet-workbench/1-2接口文档.md`(提交接口的 dailyPlan 上限说明如与本条不一致,以本条为准) - 上游单:#9179(确认侧 500 行上限)、#9193(先计数再拒绝)、#5292(4000 的来源,已判定无依据) ## 关联 / 联系人 - 后端:车务5(本单实现与验证) - 工单:wx/HL#9209;PR:wx/HL#9218