changelog-filename-gate / validate (push) Failing after 2s
两份前端交接件(consumer=admin,frontend_owner=mmg)。 订正三处事实错误: - 派车两接口的字段表曾写入源码里不存在的字段(出参 assignmentId/ createdAssignments/updatedAssignments/cancelledAssignments、入参把扁平的 dailyPlan[] 写成 dailyPlan[].assignments[] 多一层),已按 origin/dev-v3 的 CreateAssignmentReqVO / AssignmentWriteRespVO / BatchCreateAssignmentReqVO / BatchAssignmentWriteRespVO 全量重写,85 个字段逐个 grep 回源码命中 85/85; 正文保留「旧版本曾写作 X,这些字段并不存在」以接住按旧名搜索的人。 - PR 号指错:#7442 实为 PR #7862(原写 #7866,那是 finance #7396 的 PR), #7443 实为 PR #7864(原写 #7868,那根本不是 PR 号)。 - board/orders 入参表原按「完整表」形态只列了 20 个字段中的 12 个, 改为只列本次新增的 groupBatchId 并把覆盖范围写在标题与前言里。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
342 行
11 KiB
Markdown
342 行
11 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "7442"
|
||
title: "团级确认态 + 需求已发车务回写"
|
||
consumer: "admin"
|
||
author: "wx(GIT)"
|
||
change_type: "新增接口"
|
||
backend_status: "deployed"
|
||
gateway_status: "verified"
|
||
frontend_status: "pending"
|
||
frontend_owner: "mmg"
|
||
frontend_ref: ""
|
||
target_release: ""
|
||
verified_at: "2026-09-17"
|
||
status_note: "后端交付。新增 fleet 确认整团配车端点 + order-v3 内部回写端点,支持异步回写正式用车需求状态。前端需在团期配车页增加确认按钮。"
|
||
updated_at: "2026-09-17"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# fleet/order-v3: 团级确认态 + 需求已发车务回写
|
||
|
||
**存放目录**: changelogs-v2/{YYYY-MM}/(管理后台,二期 fleet + order-v3)
|
||
|
||
**服务**: hl-fleet-service (端口 8082)、hl-order-service-v3 (端口 8083)
|
||
**PR**: #7862
|
||
**Issue**: #7442 PR-B
|
||
**日期**: 2026-09-17
|
||
**影响范围**: 新增团期配车确认接口;新增需求状态异步回写链路
|
||
|
||
---
|
||
|
||
## 关键变化
|
||
|
||
1. **新增确认接口**:fleet 侧新增 `POST /admin/fleet/group-dispatch/batches/{groupBatchId}/confirm`,车务在配车计划提交并通过后,可调用本端点把整团配车定稿,转入「已确认」态。
|
||
2. **异步回写链路**:确认成功后,fleet 侧登记一条 Outbox 意图,经 Outbox 异步投递调用 order-v3 内部端点 `POST /v3/internal/group-batch/{groupBatchId}/vehicle-requirement/dispatched`,把正式用车需求从 CONFIRMED 推进到 DISPATCHED。
|
||
3. **新增错误码**:`602007`(无可确认行)/ `602008`(覆盖不完整)用于确认端点的校验失败。
|
||
4. **部署顺序**:order-v3 先部署,fleet 后部署(后端实现细节)。
|
||
|
||
---
|
||
|
||
## 二、变更接口清单
|
||
|
||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||
|---|------|------|------|----------|------|
|
||
| 1 | 确认整团配车 | POST | `/admin/fleet/group-dispatch/batches/{groupBatchId}/confirm` | 新增 | 车务确认配车方案落定 |
|
||
| 2 | 回写需求已发车务 | POST | `/v3/internal/group-batch/{groupBatchId}/vehicle-requirement/dispatched` | 新增 | [内部接口] fleet 确认后异步回写需求状态 |
|
||
|
||
---
|
||
|
||
## 三、接口详情
|
||
|
||
### 1. 确认整团配车 `POST /admin/fleet/group-dispatch/batches/{groupBatchId}/confirm`
|
||
|
||
**VO**: `GroupDispatchConfirmReqVO → GroupDispatchConfirmRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
车务在看板完成团期配车计划提交后(配车行已过验证、状态为「已派车」),调用本端点把整团配车定稿、转为「已确认」态。确认成功后会异步推进正式用车需求的状态流转(CONFIRMED → DISPATCHED);需求页需自行刷新以获取最新状态。
|
||
|
||
#### 入参字段表
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| groupBatchId | Path | Long | 是 | - | 团期主订单 ID |
|
||
| requirementId | Body | Long | 是 | - | 本次确认所依据的正式团级用车需求 ID(字符串序列化) |
|
||
| requirementVersion | Body | Integer | 是 | - | 本次确认所依据的需求版本号 |
|
||
| remark | Body | String | 否 | ≤200 字符 | 确认备注(仅留痕,不写入配车行) |
|
||
|
||
#### 出参字段表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| groupBatchId | String | 团期主订单 ID(字符串序列化) |
|
||
| confirmedCount | Integer | 本次由「已派车」转为「已确认」的配车行数 |
|
||
| alreadyConfirmedCount | Integer | 确认前已是「已确认」的配车行数 |
|
||
| requirementId | String | 本次确认所依据的正式需求 ID(字符串序列化) |
|
||
| requirementVersion | Integer | 本次确认所依据的需求版本 |
|
||
| planVersion | Long | 当前团期计划版本(确认不改计划,不递增) |
|
||
| requirementAdvanceIntent | String | 已登记的需求回写意图方向,恒为 CONFIRMED_TO_DISPATCHED |
|
||
| coverage | Object | 按乘车分组的覆盖明细 |
|
||
| legacyGroupRowCount | Integer | 无分组键的历史派车行数(不计入任何组的覆盖) |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
POST /admin/fleet/group-dispatch/batches/1934567890123456800/confirm
|
||
{
|
||
"requirementId": 5501,
|
||
"requirementVersion": 3,
|
||
"remark": "与地接确认车辆无误"
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"groupBatchId": "1934567890123456800",
|
||
"confirmedCount": 8,
|
||
"alreadyConfirmedCount": 0,
|
||
"requirementId": "5501",
|
||
"requirementVersion": 3,
|
||
"planVersion": 7,
|
||
"requirementAdvanceIntent": "CONFIRMED_TO_DISPATCHED",
|
||
"coverage": {
|
||
"totalGroups": 2,
|
||
"coveredGroups": 2,
|
||
"incompleteGroups": []
|
||
},
|
||
"legacyGroupRowCount": 0
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
N/A(团期无可确认行时返 602007 错误)。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "配车尚未覆盖完整, 不能确认: 乘车分组 A 缺失 2026-05-08",
|
||
"data": null,
|
||
"success": false,
|
||
"errorCode": 602008
|
||
}
|
||
```
|
||
|
||
可能的错误码:
|
||
- `602005` - 用车需求已更新,请刷新后重新配车
|
||
- `602006` - 正式用车需求当前状态不允许配车
|
||
- `602007` - 本团没有可确认的配车行,请先提交配车计划
|
||
- `602008` - 配车尚未覆盖完整,不能确认
|
||
- `602009` - 无法取得本团的权威乘车分组清单
|
||
- `600008` - 并发修改
|
||
- `600009` - 基线不可用
|
||
|
||
#### 业务边界
|
||
|
||
- **鉴权**: 需 `fleet:group-dispatch:write` 权限
|
||
- **幂等性**: 重复确认返 confirmedCount=0、alreadyConfirmedCount=N(属幂等成功),HTTP 200 不是错误
|
||
- **防重提交**: 本端点无防重时间窗,连点多次都是幂等成功形态
|
||
- **异步回写**: 响应成功仅代表意图已登记,需求状态的实际推进可能稍后才发生;需求列表页需自行刷新
|
||
- **并发处理**: 同团的并发调用由服务端串行化处理
|
||
|
||
---
|
||
|
||
### 2. 回写需求已发车务 `POST /v3/internal/group-batch/{groupBatchId}/vehicle-requirement/dispatched`
|
||
|
||
⚠️ **[内部接口,不对前端开放]** fleet 侧异步回写链路调用,通过 Feign 投递。
|
||
|
||
**VO**: `GroupBatchVehicleRequirementDispatchedReqDTO → GroupBatchVehicleRequirementDispatchedRespDTO`
|
||
|
||
#### 使用场景
|
||
|
||
fleet 侧确认配车后,通过 Outbox 异步机制调用本端点,把正式用车需求从 CONFIRMED 推进到 DISPATCHED 状态。该端点不对前端暴露,仅供内部服务间通信。
|
||
|
||
#### 入参字段表
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| groupBatchId | Path | Long | 是 | - | 团期主订单 ID |
|
||
| requirementId | Body | Long | 是 | - | 车务确认所依据的正式需求 ID(字符串序列化) |
|
||
| requirementVersion | Body | Integer | 是 | - | 车务确认所依据的需求版本 |
|
||
| sourceRefNo | Body | String | 否 | - | 幂等追溯号(fleet Outbox 记录 ID,用于日志对账) |
|
||
|
||
#### 出参字段表
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| applied | Boolean | 本次是否真的推进了需求状态 |
|
||
| discardReason | String | applied=false 时的原因常量 |
|
||
| requirementStatus | String | 回写后提供方当前的需求状态 |
|
||
| requirementVersion | Integer | 回写后提供方当前的需求版本 |
|
||
|
||
#### 请求示例
|
||
|
||
```json
|
||
POST /v3/internal/group-batch/1934567890123456800/vehicle-requirement/dispatched
|
||
{
|
||
"requirementId": "5501",
|
||
"requirementVersion": 3,
|
||
"sourceRefNo": "880123"
|
||
}
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"applied": true,
|
||
"discardReason": null,
|
||
"requirementStatus": "DISPATCHED",
|
||
"requirementVersion": 3
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
applied=false 时无新状态变化,仍返 200(幂等重放或需求已变版):
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": {
|
||
"applied": false,
|
||
"discardReason": "IDENTITY_MISMATCH",
|
||
"requirementStatus": "CONFIRMED",
|
||
"requirementVersion": 4
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
#### 错误响应
|
||
|
||
真正的故障(DB 不可用、CAS 并发冲突)仍以异常形式返回失败 Result,由 Outbox 退避重试:
|
||
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"message": "数据库异常",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- **一律返 200**: 本端点由 Outbox 重试链路驱动,任何判定结论都再投无用,故用 applied+discardReason 标记
|
||
- **幂等性**: 重投同一条 sourceRefNo,结果保持一致
|
||
- **丢弃原因**:
|
||
- `IDENTITY_MISMATCH` - 需求身份不一致
|
||
- `REQUIREMENT_NOT_FOUND` - 该团无活跃需求
|
||
- `ALREADY_DISPATCHED` - 需求已是完成态
|
||
- `STATUS_INVALID` - 需求状态不允许推进
|
||
|
||
---
|
||
|
||
## 四、契约约束与正确调用方式
|
||
|
||
| 场景 | 做法 |
|
||
|------|------|
|
||
| 车务确认配车 | 调 POST /admin/fleet/group-dispatch/batches/{id}/confirm,返回 confirmedCount |
|
||
| 处理重复确认 | confirmedCount=0 且 HTTP=200 为幂等成功 |
|
||
| 等待需求更新 | 需求列表页需自行刷新 |
|
||
|
||
---
|
||
|
||
## 五、数据库行为
|
||
|
||
| 操作 | 数据库影响 |
|
||
|------|----------|
|
||
| 确认配车 | fleet_group_dispatch.dispatch_status → CONFIRMED |
|
||
| Outbox 异步回写成功 | order_group_vehicle_requirement.status → DISPATCHED |
|
||
|
||
---
|
||
|
||
## 六、边界行为
|
||
|
||
- **无可确认行** → 602007(fail-closed)
|
||
- **覆盖不完整** → 602008(fail-closed)
|
||
- **需求版本不匹配** → 602005(fail-closed)
|
||
- **并发确认** → 第二个调用见 confirmedCount=0(幂等成功)
|
||
- **投递到达时需求已变** → applied=false + IDENTITY_MISMATCH
|
||
|
||
---
|
||
|
||
## 六.5 枚举
|
||
|
||
**需求回写的丢弃原因**:
|
||
- `IDENTITY_MISMATCH` - 需求 ID/版本不符
|
||
- `REQUIREMENT_NOT_FOUND` - 团无活跃需求
|
||
- `ALREADY_DISPATCHED` - 需求已是完成态
|
||
- `STATUS_INVALID` - 需求状态不允许推进
|
||
|
||
---
|
||
|
||
## 六.6 修改前后对比
|
||
|
||
| 端点 | 改前 | 改后 |
|
||
|------|------|------|
|
||
| /admin/fleet/.../confirm | 无 | 新增 POST |
|
||
| /v3/internal/group-batch/.../dispatched | 无 | 新增 POST |
|
||
|
||
---
|
||
|
||
## 六.7 影响评估
|
||
|
||
- **向后兼容**: 是(新增端点)
|
||
- **前端同步**: 是(需加确认按钮)
|
||
- **清理点**: 无
|
||
|
||
---
|
||
|
||
## 七、不影响范围
|
||
|
||
- **仅影响**: 团期配车确认流程、需求状态转移
|
||
- **零影响**: 配车提交流程、其他需求转移路径、派单列表、看板显示
|
||
|
||
---
|
||
|
||
## 八、测试环境已验证
|
||
|
||
```
|
||
POST /admin/fleet/group-dispatch/batches/xxx/confirm → 200 ✓
|
||
POST /v3/internal/group-batch/xxx/dispatched → 200 ✓
|
||
重复确认 confirmedCount=0 ✓
|
||
异步回写已发送 ✓
|
||
```
|
||
|
||
---
|
||
|
||
## 十、相关文档
|
||
|
||
- Issue: [#7442](https://git.1814.love:8443/wx/HL/issues/7442)
|
||
- PR: [#7862](https://git.1814.love:8443/wx/HL/pulls/7862)
|
||
- Merge: [a37bd669f](https://git.1814.love:8443/wx/HL/commit/a37bd669f)
|
||
|
||
## 关联 / 联系人
|
||
|
||
### 链接
|
||
|
||
- **Issue**: [#7442](https://git.1814.love:8443/wx/HL/issues/7442)
|
||
- **PR**: [#7862](https://git.1814.love:8443/wx/HL/pulls/7862)
|
||
|
||
### 联系人
|
||
|
||
- **后端**: @wx
|