docs: hand off segment confirmation contract (#5364) (#72)
所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s
所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s
这个提交包含在:
父节点
6b86db55b1
当前提交
b184a350ea
@ -0,0 +1,174 @@
|
|||||||
|
---
|
||||||
|
schema: "hl-changelog/v2"
|
||||||
|
ticket: "5364"
|
||||||
|
title: "连续执行段司机通知、回复与整组确认隔离"
|
||||||
|
consumer: "admin"
|
||||||
|
change_type: "修改接口"
|
||||||
|
backend_status: "deployed"
|
||||||
|
gateway_status: "not_required"
|
||||||
|
frontend_status: "pending"
|
||||||
|
frontend_owner: ""
|
||||||
|
frontend_ref: ""
|
||||||
|
target_release: ""
|
||||||
|
verified_at: ""
|
||||||
|
status_note: "后端 PR #5420 已 squash 合并到 dev-v3(e543a41035);最终本地 Fleet 2820 项与 Order 7261 项 reactor verify 均通过。本工单冻结范围不要求运行时部署或网关验证;前端尚未领取,保持 pending。"
|
||||||
|
updated_at: "2026-08-03"
|
||||||
|
base: "dev-v3"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 连续执行段司机通知、回复与整组确认隔离(#5364)
|
||||||
|
|
||||||
|
> **服务**:`hl-fleet-service`、`hl-order-service-v3`
|
||||||
|
>
|
||||||
|
> **后端 PR**:[#5420](https://git.1814.love:8443/wx/HL/pulls/5420)
|
||||||
|
>
|
||||||
|
> **Backend Issue**:[#5364](https://git.1814.love:8443/wx/HL/issues/5364)
|
||||||
|
>
|
||||||
|
> **Frontend tracking**:[#5366](https://git.1814.love:8443/wx/HL/issues/5366)
|
||||||
|
|
||||||
|
## 变更接口
|
||||||
|
|
||||||
|
| 接口 | 方法 | 路径 | 变更类型 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 查询车务派车订单详情 | `GET` | `/admin/fleet/board/orders/:orderId` | additive 响应字段 |
|
||||||
|
| 登记司机确认 | `POST` | `/admin/fleet/assignments/:assignmentId/driver-confirmation` | additive 请求字段与段级约束 |
|
||||||
|
| 用车需求整组原子确认 | `POST` | `/admin/fleet/assignments/requirements/:requirementId/confirm` | 新增接口 |
|
||||||
|
| 旧单派车确认 | `POST` | `/admin/fleet/assignments/:assignmentId/confirm` | multi-group 行为收紧,singleton 兼容 |
|
||||||
|
| 司机 H5 行程单 JSON | `GET` | `/app/h5/itinerary/:token` | additive/versioned 响应字段与段级裁剪 |
|
||||||
|
|
||||||
|
## 1. Board 详情字段
|
||||||
|
|
||||||
|
`GET /admin/fleet/board/orders/:orderId` 的既有字段保持不变,新增字段均为 additive/null-safe。
|
||||||
|
|
||||||
|
### 1.1 顶层需求快照
|
||||||
|
|
||||||
|
| 字段 | JSON 类型 | 可空 | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `requirementId` | `String(Long)` | 是 | 当前有效用车需求 ID |
|
||||||
|
| `requirementVersion` | `Integer` | 是 | 当前需求版本 |
|
||||||
|
| `requirementSha256` | `String` | 是 | 当前需求 canonical SHA-256;整组确认时原样回传 |
|
||||||
|
| `driverConfirmationSummary` | `Object` | 否 | 当前 generation 的服务端守恒汇总 |
|
||||||
|
|
||||||
|
`driverConfirmationSummary`:
|
||||||
|
|
||||||
|
| 字段 | JSON 类型 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `dispatchPlanGeneration` | `String(Long)` / `null` | 当前最终派车方案代际 |
|
||||||
|
| `requiredSegmentCount` | `Integer` | 当前需司机确认的 HOLD 执行段数 |
|
||||||
|
| `confirmedSegmentCount` | `Integer` | 已满足有效确认谓词的执行段数 |
|
||||||
|
| `pendingSegmentCount` | `Integer` | 待确认且非歧义段数 |
|
||||||
|
| `rejectedSegmentCount` | `Integer` | 当前拒绝且待改派段数 |
|
||||||
|
| `ambiguousSegmentCount` | `Integer` | 通知结果歧义段数 |
|
||||||
|
| `allDriverConfirmed` | `Boolean` | 所有 required 段是否均确认 |
|
||||||
|
| `allExecutionConfirmed` | `Boolean` | 全部实际用车切片是否均确认执行 |
|
||||||
|
|
||||||
|
守恒规则:`confirmedSegmentCount + pendingSegmentCount + rejectedSegmentCount + ambiguousSegmentCount = requiredSegmentCount`。消费者不得使用 `currentAssignment` 或任一代表司机自行计算整组完成。
|
||||||
|
|
||||||
|
### 1.2 `activeAssignments[]` 执行段字段
|
||||||
|
|
||||||
|
每项按独立 `assignmentGroupId` 返回;同槽多段、同司机非连续多段不得合并。
|
||||||
|
|
||||||
|
| 字段 | JSON 类型 | 可空 | 语义 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `assignmentGroupId` | `String(Long)` | 否 | 当前连续执行段身份 |
|
||||||
|
| `assignmentSlotId` | `String(Long)` | 否 | 稳定车辆槽位身份 |
|
||||||
|
| `serviceDates[]` | `String(date)[]` | 否 | 本段精确服务日,不补日期洞 |
|
||||||
|
| `holdNotificationGeneration` | `String(Long)` | 是 | 当前段通知代际 |
|
||||||
|
| `holdNotificationStatus` | `String` | 否 | `NOT_REQUIRED/PENDING/SENT/FAILED/AMBIGUOUS/INVALIDATED` |
|
||||||
|
| `holdSentAt` | `String(date-time)` | 是 | 有可信发送成功事实时才返回 |
|
||||||
|
| `driverConfirmedAt` | `String(date-time)` | 是 | 当前段司机确认时间 |
|
||||||
|
| `driverReplyNote` | `String` | 是 | 回复摘要 |
|
||||||
|
| `driverReplySource` | `String` | 是 | `NOTIFICATION/MANUAL_CONTACT`;历史未知保持 `null` |
|
||||||
|
| `driverReplyOperatorId` | `String(Long)` | 是 | 人工登记操作人;历史未知可空 |
|
||||||
|
| `driverReplyRecordedAt` | `String(date-time)` | 是 | 回复事实登记时间 |
|
||||||
|
| `driverConfirmationEvidencePresent` | `Boolean` | 否 | 是否存在确认凭证 |
|
||||||
|
| `driverConfirmationEvidenceCount` | `Integer` | 否 | 凭证数量,不新增文件元数据 |
|
||||||
|
|
||||||
|
`SENT` 只表示系统发送成功,不表示通道已提供送达回执;前端不得展示为 `DELIVERED`。
|
||||||
|
|
||||||
|
## 2. 登记司机确认
|
||||||
|
|
||||||
|
`POST /admin/fleet/assignments/:assignmentId/driver-confirmation` 请求新增:
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `driverReplySource` | `String` | 否 | 仅允许 `NOTIFICATION` 或 `MANUAL_CONTACT`;人工电话/微信确认必须显式传 `MANUAL_CONTACT` |
|
||||||
|
|
||||||
|
既有 `requestId`、`driverReplyNote`、`evidenceFileIds[]` 保持兼容。登记只更新 `assignmentId` 所属当前 group;旧 group、旧 generation、已改派/取消或资源快照漂移均 fail closed,不得跟随 slot 更新替代组。
|
||||||
|
|
||||||
|
## 3. 用车需求整组原子确认
|
||||||
|
|
||||||
|
新增 `POST /admin/fleet/assignments/requirements/:requirementId/confirm`。
|
||||||
|
|
||||||
|
请求体:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"orderId": "2080000000000000001",
|
||||||
|
"requestId": "requirement-confirm-5364-001",
|
||||||
|
"expectedRequirementVersion": 7,
|
||||||
|
"expectedRequirementSha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||||
|
"expectedPlanGeneration": "12",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"assignmentGroupId": "2080000000000000101",
|
||||||
|
"sendItinerarySms": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `groups[]` 必须是 Board 当前 generation 中全部 used execution groups 的精确集合;按 `assignmentGroupId` 去重。
|
||||||
|
- 服务端重读 exact slot×service-date topology 并一次提交;失败不产生部分状态推进、receipt 或重复 Outbox。
|
||||||
|
- `(requirementId, requestId)` 是 durable 幂等键:同 canonical 请求返回首次稳定结果;同键不同载荷返回 `605059`。
|
||||||
|
- 旧 `/:assignmentId/confirm` 在 multi-group 当前 generation 返回 `605057`;singleton 继续委托同一原子引擎。
|
||||||
|
|
||||||
|
主要业务错误:
|
||||||
|
|
||||||
|
| code | 含义 |
|
||||||
|
|---|---|
|
||||||
|
| `605055` | 派车方案 generation 已变化 |
|
||||||
|
| `605056` | 执行段精确集合已变化 |
|
||||||
|
| `605057` | multi-group 必须使用需求级整组确认 |
|
||||||
|
| `605058` | 至少一个当前执行段不满足最终确认条件 |
|
||||||
|
| `605059` | 幂等 requestId 已用于不同确认载荷 |
|
||||||
|
|
||||||
|
## 4. H5 段级最小化
|
||||||
|
|
||||||
|
`GET /app/h5/itinerary/:token` 新增/versioned 字段:
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| `contractVersion` | `String` | 当前为 `V2` |
|
||||||
|
| `segmentDays` | `Integer` | token 所绑定执行段天数 |
|
||||||
|
| `serviceDates[]` | `String(date)[]` | 本段精确服务日期 |
|
||||||
|
| `segmentRoute` | `String` / `null` | 仅由本段逐日标题生成 |
|
||||||
|
|
||||||
|
既有 `days`、`route`、`daily`、`transport` 字段不删除且原语义不静默改写。V2 token 同时绑定 group、slot、plan generation、notification generation、driver、vehicle、精确日期摘要和 audience snapshot;任一漂移都返回失效,禁止按 slot 跳转到新司机或新 group。
|
||||||
|
|
||||||
|
## 5. 前端消费动作
|
||||||
|
|
||||||
|
1. Board 按 `activeAssignments[].assignmentGroupId` 渲染独立执行段,不以 `currentAssignment`、司机 ID 或连续日期猜测合并。
|
||||||
|
2. 整组确认提交 Board 返回的 `requirementVersion/requirementSha256/dispatchPlanGeneration` 与全部 group 精确集合;收到 `605055/605056` 后刷新,不做部分重试。
|
||||||
|
3. 人工确认显式传 `driverReplySource=MANUAL_CONTACT`;展示通知状态与确认来源为两个独立事实。
|
||||||
|
4. H5 使用 `serviceDates/segmentDays/segmentRoute` 展示本段范围;保留对既有字段的兼容读取。
|
||||||
|
5. 所有 JSON Long 按字符串处理,禁止转 JavaScript `Number`。
|
||||||
|
|
||||||
|
## 6. Internal Feign / shared Java
|
||||||
|
|
||||||
|
Fleet 与 order-v3 新增内部 reservation/release 契约:
|
||||||
|
|
||||||
|
- `POST /v3/internal/order/orders/:orderId/requirement/vehicle/final-confirmation-reservations`
|
||||||
|
- `POST /v3/internal/order/orders/:orderId/requirement/vehicle/final-confirmation-reservations/release`
|
||||||
|
|
||||||
|
共享 DTO 采用 additive 字段,Fleet reservation、事务内 durable receipt、release Outbox 与 Order holder/fence 共同保证失败回滚和可重放释放。oasdiff 与 Spring Cloud Contract 均未配置,不能标记为工具 PASS;本次以 Controller JSON、producer/consumer 源码对比及两个 reactor verify 作为人工回退证据。
|
||||||
|
|
||||||
|
## 验证证据
|
||||||
|
|
||||||
|
- Fleet:`mvn -pl hl-fleet-service -am verify`,2,820 tests,0 failures,0 errors,5 skipped,BUILD SUCCESS。
|
||||||
|
- Order:`mvn -pl hl-order-service-v3 -am verify`,7,261 tests,0 failures,0 errors,36 skipped,BUILD SUCCESS。
|
||||||
|
- Fleet Spotless:BUILD SUCCESS;`git diff --check dev-v3`:PASS。
|
||||||
|
- 最终独立 P0–P2 review:GO,无可复现阻断项。
|
||||||
|
- 后端 PR #5420 已 squash 合并到 `dev-v3@e543a41035`;按 changelog 发布门禁记录 `backend_status=deployed`,本工单不包含运行时测试部署。
|
||||||
|
- 本工单冻结范围不执行部署或网关调用,`gateway_status=not_required`。
|
||||||
|
- 前端未领取,`frontend_status=pending`;changelog 发布不代表前端已实现、发布或页面验证。
|
||||||
正在加载...
x
在新工单中引用
屏蔽一个用户