15 KiB
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 | 8329 | 团期配车确认重复调用不再返 602005:需求版本校验下沉到幂等分支之后,回写推进版本不再让重复确认变成错误 | admin | wx(GIT) | 修改接口 | deployed | verified | pending | mmg | v2.1 | PR #8332 squash 合并 dev-v3(8675e1ff0)。部署:hl-fleet-service dev-v3 @ 2b4656424(2026-09-24 14:03 滚动部署完成;同批 order-v3 亦为 2b4656424)。测试服网关从零实测(自造团期 groupBatchId=2103003304906936322,正式需求 2103003334258675714 v2,3 条配车行):① reconfigure(requirementVersion=2)→ 200;② confirm 第一次(requirementVersion=2)→ 200,confirmedCount=3、alreadyConfirmedCount=0、requirementAdvanceIntent=CONFIRMED_TO_DISPATCHED,回写把正式需求推到 status=DONE、version=3;③ 用提交时的旧版本再 confirm 一次(requirementVersion=2)→ http 200、code=200、message=成功,confirmedCount=0、alreadyConfirmedCount=3。改前同一形态返 602005「用车需求已更新, 请刷新后重新配车(提交 …/v2, 当前 …/v3)」。定向单测 81 绿(GroupDispatchConfirmTest 23 / GroupDispatchServiceTest 58),fleet spotless:check 901 files clean。闸门按「基线需求状态已是 DISPATCHED/DONE(即本端点回写已落地)」放行,状态停在 CONFIRMED/PENDING_RECONFIRM 时仍 fail-closed 抛 602005。 | 2026-09-24 | dev-v3 |
fleet 团期配车: 确认重复调用不再返 602005(版本校验下沉)
存放目录: 二期(v3) →
changelogs-v2/2026-09/服务: hl-fleet-service(dispatch 域) PR: wx/HL#8332 Issue: #8329 日期: 2026-09-24 影响范围: 车务「团期配车 → 确认配车」按钮的重复点击 / 刷新后重试
⚠️ 关键变化(非必须,本版与上版行为不同 / 纠错 / 撤销时必写)
- 重复确认不再返 602005:整团配车确认成功后,本次确认会推进正式用车需求版本(回写);此前这个自己造成的版本前进会让「再点一次确认」被判成「需求已更新」,返回 602005 要求刷新重配——而刷新后拿到的还是同一个已完成的团。现在这一档返回 200,并以
confirmedCount=0/alreadyConfirmedCount=N表达「本来就是已确认状态」。 - 602005 仍然存在,且判据更精确:只有当「本次端点的回写尚未落地」而版本/状态又对不上时才抛(fail-closed),即真正的「业务侧改了需求,你拿的是旧版本」。
- 602007 的触发面变化:本团一行配车行都没有(
assignedCount=0且alreadyConfirmedCount=0)时抛 602007「本团没有可确认的配车行」,不再被版本校验抢先报成 602005。 - 602005 报文的两个占位符统一成
id=…/v…形态:前端只应按错误码 602005 处置,不要解析 {0} / {1}。
一、背景(选填)
确认配车是定稿动作,它认下的是「这一版需求对应的这套车」,因此入参带了 requirementId + requirementVersion 作为需求身份。问题是这个端点自己有副作用:确认成功会把正式需求从 CONFIRMED 回写成 DISPATCHED,版本因此前进。改前版本校验排在幂等分支之前、且在事务外先跑,于是「重复确认」这条正常操作被自己造成的版本前进判成了错误。实测:POST .../confirm {requirementId:2102982327141556225, requirementVersion:2} → code=602005「用车需求已更新, 请刷新后重新配车(提交 2102982327141556225/v2, 当前 2102982327141556225/v3)」,而同刻回读需求已是 v3——前进正是首次确认自己的回写。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 确认整团配车 | POST | /admin/fleet/group-dispatch/batches/{groupBatchId}/confirm |
行为变更(校验时机 + 报文占位符口径) | 重复确认返 200;602005 只在「本端点回写未落地」时抛 |
三、接口详情
1. 确认整团配车 POST /admin/fleet/group-dispatch/batches/{groupBatchId}/confirm
VO: GroupDispatchConfirmReqVO → GroupDispatchConfirmRespVO
使用场景
车务在团期配车页点「确认配车」,把本团已排的车一次定稿。没有防重提交时间窗:连点多少次都是同一个形态,不会出现「请稍后重试」。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期聚合主键 |
| requirementId | Body | Long | ✅ | 须等于本团当前正式需求 | 不等于抛 602005(不受本次改动放宽) |
| requirementVersion | Body | Integer | ✅ | 本次确认所依据的版本 | 语义细化(本单):版本不一致时——本团仍有「已派车」行待确认,或基线需求状态还停在 CONFIRMED / PENDING_RECONFIRM ⇒ 602005;基线需求状态已是 DISPATCHED / DONE(本端点回写已落地)⇒ 不抛,按 confirmedCount=0 返 200 |
| remark | Body | String | ❌ | ≤200 | 仅日志留痕,不写进配车行(配车行 remark 参与 planDigest,刷进去会让下次重配误判「计划有变更」) |
出参 Result<GroupDispatchConfirmRespVO>
| 字段 | 类型 | 说明 |
|---|---|---|
| confirmedCount | Integer | 本次真正由 ASSIGNED 转 CONFIRMED 的行数;重复确认时为 0 |
| alreadyConfirmedCount | Integer | 本次之前就已是 CONFIRMED 的行数 |
| requirementId / requirementVersion | String / Integer | 本次提交的需求身份(照原样回显) |
| planVersion | Integer | 配车计划版本 |
| requirementAdvanceIntent | String | 回写意图,如 CONFIRMED_TO_DISPATCHED |
| coverage | Object | 按组覆盖读数(groups / missingGroupCodes / satisfied) |
请求示例
{
"requirementId": "2103003334258675714",
"requirementVersion": 2,
"remark": "与地接确认车辆无误"
}
响应示例
{
"code": 200,
"message": "成功",
"data": {
"groupBatchId": "2103003304906936322",
"confirmedCount": 0,
"alreadyConfirmedCount": 3,
"requirementId": "2103003334258675714",
"requirementVersion": 2,
"planVersion": 2,
"requirementAdvanceIntent": "CONFIRMED_TO_DISPATCHED",
"coverage": { "satisfied": true, "missingGroupCodes": [] }
},
"success": true
}
空数据 / 降级响应
- 本团没有任何配车行时不是空成功,而是 602007(见「错误响应」)。
- 本团有配车行但已全部 CONFIRMED:200 +
confirmedCount=0、alreadyConfirmedCount=N。
{ "code": 200, "message": "成功", "data": { "confirmedCount": 0, "alreadyConfirmedCount": 3 }, "success": true }
错误响应
{
"code": 602005,
"message": "用车需求已更新, 请刷新后重新配车(提交 id=2103003334258675714/v2, 当前 id=2103003334258675714/v4)",
"success": false,
"data": null
}
{
"code": 602007,
"message": "本团没有可确认的配车行, 请先提交配车计划",
"success": false,
"data": null
}
业务边界
- 真实的判定顺序(改后):事务外只做需求 ID 校验(602005 的一种形态);进事务、取团锁、锁内重读配车行后依次判 —— 行数都为 0 ⇒ 602007;本端点回写是否已落地(基线需求状态 ∈ DISPATCHED / DONE)⇒ 落地则跳过版本/状态校验(幂等重放),未落地则照旧 fail-closed 抛 602005 / 602006;随后做按组覆盖校验(602008),再 CAS 确认。
- 跳过的条件不是「没有待确认行」,而是「本端点的回写已经落地」:状态停在 CONFIRMED / PENDING_RECONFIRM 而版本不等 ⇒ 推进版本的不是我们,是业务侧改了需求,必须照旧 602005。不要按 assignedCount==0 一刀切。
- 需求被整份换过(
requirementId都变了)时拿不到「提交版本」,报文只有 ID 那一半;两支统一拼id=…前缀。 - 重配端点(
reconfigure)未变:仍整份调用身份校验。
四、契约约束与正确调用方式(接口类必写)
- 前端按码处置,不解析报文:602005 = 需求被业务侧改过,刷新重配;200 且
confirmedCount=0= 本来就是已确认,无需任何动作。 - 不要把「重复确认」当成需要防抖的操作:本端点没有防重提交时间窗,按钮可以做防抖,但服务端保证重复调用不报错。
- 确认成功后若要改车,走重配端点(
reconfigure)而不是再点确认。
✅ 正确 / ❌ 错误处置对照
✅ 200 + confirmedCount=0 → 已是确认态,直接展示「已确认」,不要提示失败
✅ 602005 → 提示「需求已更新,请刷新后重新配车」
❌ 把 200 + confirmedCount=0 渲染成错误或重复提交警告
❌ 发现 602005 后原地重试同一个 requirementVersion(版本不会自己回来)
切换状态时的必要动作
- 重配(
reconfigure)成功后配车行回到 ASSIGNED/待确认,需要再点一次确认;本单未改这条链路。
五、数据库行为(涉及写操作时必写)
- 无表结构变更、无 Flyway。
- 确认成功的写入是「把本团存活配车行由 ASSIGNED 置 CONFIRMED」+「事务内意图记录回写需求状态」;重复确认时 CAS 命中 0 行,零写入。
- 602005 / 602006 / 602007 / 602008 都在写库之前抛出,可回读需求版本与配车行状态确认未变。
六、边界行为
- 并发下的保护未变:确认前取团级变更锁并在锁内重读配车行,命中行数与 assignedCount 不符即判并发。
- 受控重开窗口(602012 / 602013)语义未变。
- 需求被整份换过仍抛 602005,不受本次放宽影响。
六.5、枚举 / 数据字典(接口出现枚举时必写)
| 码 | 触发(改后) | 报文 |
|---|---|---|
| 602005 | requirementId 不等于基线;或本端点回写未落地(需求状态非 DISPATCHED/DONE)而 requirementVersion 不等于基线当前版本 | 用车需求已更新, 请刷新后重新配车(提交 {0}, 当前 {1}),两个占位符均为 id=需求ID/v版本 |
| 602006(不变) | 需求状态不允许配车(回写未落地时的状态判据) | 正式用车需求当前状态不允许配车: {0} |
| 602007(触发面变更) | 本团 assignedCount=0 且 alreadyConfirmedCount=0 | 本团没有可确认的配车行, 请先提交配车计划 |
| 602008(不变) | 库里现存计划仍不满足按组覆盖 | 配车尚未覆盖完整, 不能确认: {0} |
六.6、修改前后对比(修改/删除类接口必写,新增跳过)
字段级对比
| 字段 | 改前 | 改后 |
|---|---|---|
| 请求 / 响应字段 | — | 无新增、无删除,结构不变 |
| 602005 的 {0} | 「换版」支不带前缀词 | 两支统一为 id=…/v… |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 首次确认成功 | 200,confirmedCount=N | 200,confirmedCount=N(不变) |
| 需求版本已被本端点回写推进后再确认(旧版本) | 602005(要求刷新重配) | 200,confirmedCount=0、alreadyConfirmedCount=N |
| 业务侧改了需求、本团仍有待确认行 | 602005 | 602005(不变,fail-closed) |
| 业务侧改了需求、本团早已确认完(回写已落地) | 602005 | 200(幂等重放) |
| 本团一行配车行都没有 | 可能先被版本校验报成 602005 | 602007 |
六.7、影响评估(修改/删除类必写)
- 是否破坏向后兼容:不破坏——只把「自己造成的版本前进」这一档从错误放宽成幂等成功;报文占位符口径变化不影响按码处置的前端。
- 前端是否必须同步上线:不必须。建议把 confirmedCount=0 渲染成「已确认」而不是失败。
- 存量数据影响:无迁移、无重算。
- 上线风险:放宽的闸门以「基线需求状态已是 DISPATCHED / DONE」为唯一理由,状态未落地时判据与改前完全一致,因此不会掩盖「业务侧改需求」这一真实冲突。
七、不影响范围(显式声明, 帮前端/QA 缩小排查面)
- 仅影响:
POST /admin/fleet/group-dispatch/batches/{groupBatchId}/confirm的版本/状态校验时机与 602005 报文占位符形态。 - 零影响:
- 重配端点
POST .../reconfigure(仍整份校验身份)。 - 602006 / 602008 / 602012 / 602013 的判据与报文。
- 按组覆盖校验、并发锁、受控重开窗口。
- order-v3 侧对回写意图的幂等消费口径。
- readiness / overview / 配车行数据结构、数据库、网关路由。
- 重配端点
八、测试环境已验证
部署读数:hl-fleet-service dev-v3 @ 2b4656424,2026-09-24 14:03 滚动部署完成。
网关真实请求与响应(https://api.test.1814.love,自造团期 groupBatchId=2103003304906936322,正式需求 2103003334258675714,3 条配车行):
① POST /admin/fleet/group-dispatch/batches/2103003304906936322/reconfigure
{requirementId:2103003334258675714, requirementVersion:2, demands:[3 天 × BUS × 1 辆]}
→ http 200, code=200;addedCount=3、aliveCount=3 ✓
② POST .../confirm {requirementId:2103003334258675714, requirementVersion:2}
→ http 200, code=200, confirmedCount=3, alreadyConfirmedCount=0,
requirementAdvanceIntent=CONFIRMED_TO_DISPATCHED ✓
回读 GET /v3/admin/order/group-batch/2103003304906936322/vehicle-requirement
→ status=DONE, version=3(版本被本次回写推进)✓
③ POST .../confirm {requirementId:2103003334258675714, requirementVersion:2} ← 用提交时的旧版本重复确认
→ http 200, code=200, message=成功, confirmedCount=0, alreadyConfirmedCount=3 ✓(改前此处为 602005)
定向测试逐类读数(mvn -o -pl hl-fleet-service -am test -Dtest='GroupDispatchConfirmTest,GroupDispatchServiceTest' -DfailIfNoTests=false -Dhl.surefire.failIfNoTests=false,81 绿):
| 测试类 | Tests run |
|---|---|
| GroupDispatchServiceTest | 58 |
| GroupDispatchConfirmTest | 23 |
fleet spotless:check:901 files clean、0 needs changes。
十、相关文档
- 确认配车端点与
GroupDispatchConfirmReqVO原始设计:#7442 - 受控重开窗口(602012 / 602013):#8308 系列 →
changelogs-v2/2026-09/ - 团期配车就绪检查:#8294 →
changelogs-v2/2026-09/24_8294_团期配车就绪检查座位不足黄牌扣司机座,新增-passengerSeatTotal-修改接口-管理后台.md
关联 / 联系人
链接
- Issue: wx/HL#8329
- 后端 PR: wx/HL#8332
联系人
- 后端: wx