changelog(9209): 单团排车项上限 4000->500(修改接口/管理后台)
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
这个提交包含在:
@@ -0,0 +1,201 @@
|
||||
---
|
||||
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<BatchAssignmentWriteRespVO>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
管理后台在团期 / 订单的车务配车页点「提交最终方案」时调用:一次提交该需求在完整日期窗内的逐日配车清单(服务日期 × 车辆 × 司机),服务端原子落库并回写订单。
|
||||
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| 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<BatchAssignmentWriteRespVO>`
|
||||
|
||||
结构与字段名均未变:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| 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
|
||||
在新工单中引用
屏蔽一个用户