diff --git a/changelogs-v2/2026-07/59_4935_车务需求级派单完成回调与滚动发布契约-管理后台.md b/changelogs-v2/2026-07/59_4935_车务需求级派单完成回调与滚动发布契约-管理后台.md new file mode 100644 index 0000000..64f62da --- /dev/null +++ b/changelogs-v2/2026-07/59_4935_车务需求级派单完成回调与滚动发布契约-管理后台.md @@ -0,0 +1,219 @@ +# 【前端对接·管理后台】车务需求级派单完成回调与滚动发布契约 + +> Issue: [wx/HL#4935](https://git.1814.love:8443/wx/HL/issues/4935) +> +> PR: [wx/HL#4994](https://git.1814.love:8443/wx/HL/pulls/4994) +> +> 服务: `hl-fleet-service` / `hl-order-service-v3` +> +> 日期: 2026-07-15 +> +> 影响范围: 车务派单完成、用车需求驳回、订单资源状态、看板刷新与部署兼容 + +## 一、关键纠正 + +此前链路可能在单个日期或单辆车派定后提前把整个用车需求写成 `DONE`。本次改为: + +- 一个用车需求只做一次最终完成回调。 +- 只有全部服务日期、全部车型项均已生成有效派单,并且每条逐日配置同时绑定车辆和司机,后端才允许整个需求完成。 +- 前端不得根据“某一天已派”“某一辆车已派”自行把需求或订单资源节点标成完成。 +- 前端继续直接使用看板/详情接口返回的状态、文案和能力字段,不维护独立状态映射。 + +## 二、前端接口结论 + +本次不新增前端调用接口,管理后台继续使用: + +| 接口 | 方法 | 路径 | 前端用途 | +|---|---|---|---| +| 派单看板汇总 | GET | `/admin/fleet/board/summary` | 状态选项、文案、数量 | +| 派单看板列表 | GET | `/admin/fleet/board/orders` | 分页卡片、状态与能力字段 | +| 派单看板详情 | GET | `/admin/fleet/board/orders/{orderId}` | 当前需求、逐日行程、当前派单 | +| 派单时间线 | GET | `/admin/fleet/board/orders/{orderId}/timeline` | 已发生操作记录 | + +前端处理规则: + +1. 状态筛选使用 `summary.statusOptions`,卡片文案使用 `assignmentStatusLabel`。 +2. 派车入口只看 `canAssign`,驳回入口只看 `canRejectRequirement`。 +3. 派单、驳回或重试成功后重新请求汇总、列表和当前详情,不能只在本地改一张卡片。 +4. 同一需求仍有未完成日期或其他车辆项时,后端保持进行中;前端不得提前展示“已完成”。 +5. 后端部署开关关闭期间,需求级完成/驳回事件会保留待重放;前端不需要轮询内部 Outbox,也不得调用内部回调。 + +## 三、管理后台响应示例 + +### 3.1 仍有未完成配置 + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "assignmentStatus": "holding", + "assignmentStatusLabel": "排车中", + "canAssign": true, + "canRejectRequirement": false, + "currentAssignment": { + "requirementId": "2075001000000000001" + } + } +} +``` + +该响应只表示需求仍在处理,不能因 `currentAssignment` 非空推断整个需求已完成。 + +### 3.2 整个需求完成后 + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "assignmentStatus": "assigned", + "assignmentStatusLabel": "已派车", + "canAssign": false, + "canRejectRequirement": false + } +} +``` + +实际字段以看板接口当前 OpenAPI 为准;状态中文和能力判断均由后端返回。 + +## 四、内部回调契约 + +> 本节供后端与 QA 验收。以下 `/v3/internal/**` 接口不经过管理后台,不配置公网网关路由,前端禁止调用。 + +### 4.1 最终完成回调 + +```http +POST /v3/internal/order/vehicle-assignment/callback +Content-Type: application/json +``` + +请求示例: + +```json +{ + "orderId": "2074746808742928386", + "requirementId": "2075001000000000001", + "vehicleId": "2076001000000000001", + "vehicleType": "suv", + "vehicleCount": 1, + "licensePlate": "蒙A12345", + "brand": "丰田汉兰达", + "seats": 7, + "plannedDailyFee": "1300.00", + "dailyFeeSource": "PRICE_CALENDAR", + "driverStaffId": "2077001000000000001", + "driverName": "测试司机", + "driverPhone": "13800000000", + "remark": "需求级最终派单快照" +} +``` + +成功响应: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": null +} +``` + +必填字段:`orderId`、`requirementId`、`vehicleId`、`vehicleType`、`vehicleCount`。其余快照字段允许为空,后端不得伪造车牌、品牌、座位、价格或司机信息。 + +### 4.2 轻量进度回写 + +```http +POST /v3/internal/order/orders/{orderId}/requirement/vehicle/status?requirementId={requirementId}&status=PROCESSING +``` + +该接口只允许 `PROCESSING`。`DONE` 必须走最终完成回调并冻结快照。 + +### 4.3 驳回回写 + +```http +POST /v3/internal/order/orders/{orderId}/requirement/vehicle/reject +Content-Type: application/json +``` + +请求示例: + +```json +{ + "requirementId": "2075001000000000001", + "returnRemark": "车型需求不完整,请定制师补充", + "operatorId": "2078001000000000001" +} +``` + +只有当前需求不存在 `holding/assigned` 有效派单时才允许驳回。 + +## 五、状态、幂等和错误分支 + +| 场景 | 结果 | 副作用 | +|---|---|---| +| `PENDING/PROCESSING` 且无快照 | 原子写快照并完成需求 | 同事务写需求 `DONE`、订单车辆状态 `DONE`、待办/日志并尝试推进订单 | +| `DONE` 且已有快照 | 幂等成功 | 不重复插入快照,不重复推进 | +| `DONE` 但无快照 | 返回 `582081` | 禁止补造快照,禁止继续副作用 | +| active 状态已有快照 | 返回 `582082` | 禁止重复回写 | +| 需求不存在或失效 | 返回 `582080` | 无写入 | +| 非法状态流转 | 返回 `582083` | 无写入 | +| 订单/需求已取消 | 跳过 | 不写完成快照,不推进订单 | + +错误响应示例: + +```json +{ + "code": 582081, + "message": "用车需求状态不允许回写配车", + "success": false, + "data": null +} +``` + +## 六、滚动发布与回滚 + +1. 先部署全部 `hl-order-service-v3` 实例并确认 Flyway 成功。 +2. 保持 `FLEET_REQUIREMENT_LIFECYCLE_ENABLED=false`,再部署全部 `hl-fleet-service` 实例。 +3. 确认 Fleet Flyway、健康与普通 Outbox 消费正常后,再启用开关。 +4. 开关关闭时,需求级 Outbox 事件不会占用普通事件扫描窗口,也不会被丢弃;开启后继续重放。 +5. 异常时先关闭开关,再回滚服务制品;兼容字段和历史 Outbox 不做破坏性回滚。 + +## 七、前端必须处理 + +1. 不新增内部回调请求,不把内部错误码做成独立前端流程。 +2. 不按每日派单行数或单车派定结果推导需求完成。 +3. 继续使用后端返回的 `statusOptions`、`assignmentStatusLabel`、`canAssign`、`canRejectRequirement`。 +4. 操作成功后刷新服务端状态;并发处理中若能力字段变化,以最新接口响应为准。 +5. 不修改既有分页、团号、联系人、定制师、逐日行程和大交通字段接法;这些仍以 `57_4882` 文档为准。 + +## 八、不影响范围 + +- 不修改 `hl-ui`,本文件仅做后端契约告知。 +- 不新增管理后台分页或不分页接口。 +- 不改变车型大类、司机占一座、司机险只计车队成本等既有口径。 +- 不处理团期配车。 + +## 九、验证状态 + +合并前代码验证: + +```text +hl-order-service-v3 verify: 5574 tests,0 failures,0 errors,15 skipped +hl-fleet-service clean verify: 1693 tests,0 failures,0 errors,0 skipped +Feign 集成测试隔离定向回归: 63 tests,全部通过 +Fleet Spotless: 472 files clean +gate_check.py --dataflow --assert-base dev-v3: PASS +``` + +部署任务、测试环境网关/API、MySQL/Flyway 和服务日志证据将在 PR 合并后回填;在这些证据完成前,Issue #4935 保持 OPEN。 + +## 十、相关文档 + +- 当前看板字段、分页、统计、行程与保险:`57_4882_车务派单看板当前订单字段统计行程与保险事务收口-管理后台.md` +- 车务提需求与派单看板:`53_4871_车务提需求派单看板闭环契约-管理后台.md` +- 团号与定制师筛选:`54_4876_派单看板团号与定制师下拉筛选-管理后台.md` +- 后端最终回调契约:`hl-backend-changelog/changelogs/2026-07/14_1022_order-v3_vehicle-assignment-callback-contract.md`