docs(changelog): #7443 AC-26 TRANSFER 派车行四端点网关实测收尾,gateway_status 回填 verified
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
四个既有端点(candidates/change/confirm(assignmentId)/confirm(requirementId))经网关
逐一实测通过;此前缺失的 confirm(requirementId) 借新上线的
GET /admin/fleet/board/orders/{orderId} requirementIdentities 字段取得
expectedRequirementVersion/Sha256/expectedPlanGeneration 真值补齐验证。
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
这个提交包含在:
@@ -0,0 +1,985 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "7443"
|
||||
title: "TRANSFER 派车行确认/改派基线复核修复(605905/605041 不再误判)"
|
||||
consumer: "admin"
|
||||
author: "wx(GIT)"
|
||||
change_type: "修改接口"
|
||||
backend_status: "deployed"
|
||||
gateway_status: "verified"
|
||||
frontend_status: "not_required"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: ""
|
||||
status_note: "【2026-09-20 AC-26 收尾】gateway_status 回填 verified,四个端点(「二、变更接口清单」全部条目)均经网关实测(cw_test_7443 账号,dev-v3 测试服,fleet 部署 dev-v3@311dc92ee,2026-09-20 17:46:56,含 PR #7952/c527e48c3 + #8048 + #8042;取证前后各跑一次 deploy-status.sh,两次 fleet/order-v3 commit 一致,证据有效):(1) POST /admin/fleet/assignments/candidates(requirementId=2101219393722634242):canonicalSnapshot 非 null;(2) POST /admin/fleet/assignments/{id}/change(TRANSFER 派车行 2101174428044824578):code=200;(3) POST /admin/fleet/assignments/{id}/confirm(TRANSFER 派车行 2101174428711686146):code=200/confirmed=true/assignmentStatus=assigned(此前记录的 582093 已由 #8037 修复);(4) POST /admin/fleet/assignments/requirements/{requirementId}/confirm(TRANSFER 需求 2101567456596365313,订单 2101566624467419137):借新上线的 GET /admin/fleet/board/orders/{orderId} 返回的 requirementIdentities(#7990/#8048 一并带来的新字段,含 requirementVersion/requirementSha256/dispatchPlanGeneration 三个本端点必需的真值,此前全仓无接口能给出)取得 expectedRequirementVersion=1/expectedRequirementSha256=814e3f85.../expectedPlanGeneration=359984828583645184,groups[] 取自 candidates 返回的 retainedGroupIds 两个 assignmentGroupId,实测 code=200/confirmed=true/finalPlanPublished=true。四项证据补全,判据满足,回填 verified。"
|
||||
updated_at: "2026-09-20"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# fleet/order-v3: TRANSFER 派车行确认/改派基线复核修复(605905/605041 不再误判)
|
||||
|
||||
> **存放目录**: changelogs-v2/{YYYY-MM}/
|
||||
>
|
||||
> **服务**: hl-fleet-service、hl-order-service-v3(共享 hl-common-core 的 Feign DTO)
|
||||
> **PR**: 尚未创建(三个提交 `abd435c15`/`694e405fd`/`15c7cdd0c`,本地分支 `feature/7443-rest-ac`,尚未合入 `dev-v3`)
|
||||
> **Issue**: #7443 AC-24
|
||||
> **日期**: 2026-09-18
|
||||
> **影响范围**: 管理后台车务派单弹窗——按需求原子确认、车务确认执行、修改派单、查询派单候选资源(Step2 canonical 快照)四个既有端点,仅当对象(派车行/需求/候选查询)属于 `kind=TRANSFER`(接送机)时行为发生变化;另有一处内部作业端点(重发最终方案快照)不面向 admin 前端
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 关键变化
|
||||
|
||||
**一句话**:`kind=TRANSFER` 建出来的派车行,以前建得出来但操作不动——现在通了。三个既有端点
|
||||
(按需求原子确认、车务确认执行、修改派单)的入参、出参**零变化**,变的只是内部"拿哪条需求当
|
||||
基线比对"的逻辑。
|
||||
|
||||
**根因**(写给前端知道以前为什么会失败):fleet 侧这三个端点的最终基线复核,原来一律拿
|
||||
`OrderFleetDetailContextDTO.vehicleRequirement` 当基线;而 order-v3 提供这个字段时**恒为
|
||||
TRAVEL**(`OrderFleetProviderService.java:1027-1029` 写死取 `kind=TRAVEL` 那条需求)。于是一条
|
||||
`requirement_id` 指向 TRANSFER 需求的派车行,在第一道 `requirementId` 比对上必然不等,从而被
|
||||
判定为"需求已过期/已变化"而拒绝——**接送机的车派得出来,却一步都确认/改派不了**。
|
||||
|
||||
**修法**:`OrderFleetDetailContextDTO`(`hl-common-core`)新增**可空**字段
|
||||
`transferVehicleRequirement`;order-v3 一并把订单当前生效的 TRANSFER 需求带回(服务日未回填时
|
||||
降级为 `null`,不让整个车务详情上下文报错)。fleet 侧新增私有方法
|
||||
`baselineRequirementFor(requirementId, context)`:传入的 `requirementId` 命中
|
||||
`transferVehicleRequirement` 就用那条,否则原样回退 `vehicleRequirement`(TRAVEL)——
|
||||
**TRAVEL 派车行的比对结果与改动前逐字相同**。
|
||||
|
||||
> ⚠️ **订正 2026-09-18 早些时候的说法**(本目录 `17_7443_*.md`、`18_7443_接送机用车需求分叉…`
|
||||
> 两份文档的「六、边界行为」都写"确认、改派、基线变更复验三处内部调用……对 TRANSFER 派车行
|
||||
> 一律 605041"):这句话对 `POST /{assignmentId}/confirm` 与 `POST /{assignmentId}/change`
|
||||
> 准确,但对 `POST /requirements/{requirementId}/confirm` **不准确**——经 2026-09-18 源码复核
|
||||
> (`AssignmentService.java:3567-3583` 的 `assertRequirementPreflightVersion`),该端点有一道
|
||||
> **更早**触发的版本预检门禁,直接读 `context.getVehicleRequirement()`(恒 TRAVEL)与请求体里的
|
||||
> `requirementId`(TRANSFER)比对,必不等 ⇒ **实际可观测的报错是 605905(需求版本过期),
|
||||
> 不是 605041**;请求根本走不到后面真正会抛 605041 的 `assertFinalConfirmationBaseline`
|
||||
> (`:3974`)。两处的根因完全相同(都是"拿 `context.getVehicleRequirement()` 当基线"),
|
||||
> 本次修复对两处一并修,但**前端排查历史工单日志时请按实际报错码 605905 去找**,不要按
|
||||
> 605041 去找。
|
||||
|
||||
**不影响范围(前端最关心的一句)**:TRAVEL 派车行的确认/改派/复核行为**逐字未变**;上游
|
||||
`PUT /v3/admin/order/{id}/vehicle-requirement` 传 `kind=TRANSFER` 的写口目前仍然关着
|
||||
(809009,见 `18_7443_接送机用车需求分叉…` 一文),本次修复**不改变这一点**——没有那个开关,
|
||||
生产环境仍然造不出真实的 TRANSFER 需求;本次修复解决的是"已经有一条 TRANSFER 需求/派车行时,
|
||||
这三个端点能不能正常操作它"。
|
||||
|
||||
> **前端行动项**:无。本次三个端点的请求体、响应体结构一个字段都没有变,不需要改任何代码。
|
||||
> 如果贵方之前按 `18_7443_接送机用车需求分叉…` 文档的提示"前端本版暂缓接入 TRANSFER 派车行的
|
||||
> 确认/改派"搁置了相关联调,这条限制在**这三个端点自身**的维度已经解除;但由于上游写口
|
||||
> (809009)仍未开放,测试环境目前仍无法通过正常业务流程产出可供联调的 TRANSFER 数据。
|
||||
|
||||
> 🆕 **2026-09-18 当日追加两个提交,同一根因的另外两处落点**(分支已 rebase 到最新 `dev-v3`,
|
||||
> 现为三个提交):
|
||||
>
|
||||
> **① `refinalizeFinalSnapshot`**(`AssignmentService.java:13092`,提交 `694e405fd`)——一个
|
||||
> **内部作业端点**(`POST /internal/fleet/jobs/vehicle-assignment-snapshot/refinalize`,
|
||||
> `FleetJobInternalController`),不面向 admin 前端,供运维/作业系统补发存量订单的最终方案
|
||||
> 快照。坏法与前三处同形:读 `context.getVehicleRequirement()`(恒 TRAVEL),入参
|
||||
> `requirementId` 指向 TRANSFER 需求时必判"身份错位"而拒绝。⚠️ **源码注释与提交信息把这里的
|
||||
> 错误码写成了"605036",经核实是笔误**:该方法唯一的身份不一致分支
|
||||
> (`AssignmentService.java:13096-13098`)实际 `throw new BusinessException(
|
||||
> AssignmentErrorCode.REQUIREMENT_VERSION_EXPIRED)`,即 **605905**("需求版本过期"),
|
||||
> 605036 是另一个不相关的码(`CROSS_RESIDENT_CONFIRMATION_REQUIRED`,"司机与车辆不是常驻组合")。
|
||||
> 本文档按实测的 605905 记录,不采信注释里的 605036。这一处**不进本文档「二/三」的接口清单**
|
||||
> (非 admin 端点),详见下方「六、边界行为」。
|
||||
>
|
||||
> **② Step2 canonical 快照**(`Step2CanonicalSnapshotService.java:100`,提交
|
||||
> `15c7cdd0c`)——**这一处前端可见,是本次追加里最重要的一处**。四步向导第②步选车/选司机页
|
||||
> 用的 `POST /admin/fleet/assignments/candidates` 端点(`AssignmentCandidateRespVO
|
||||
> .canonicalSnapshot` 字段)此前同样恒读 `context.getVehicleRequirement()`(TRAVEL)。
|
||||
> **坏法是静默的**:身份比对(`identityConsistent`)不等时**不抛任何错误码**,只有一条
|
||||
> `log.warn("Step2 快照身份不一致,拒绝建快照/更新")`,方法直接 `return null`——调用方拿到的是
|
||||
> **一个空字段,不是一次失败**。运营端表现为"四步向导第②步网格出不来",且**没有任何错误码指向
|
||||
> 成因**,排查只能靠日志。已收录为本文档新增的「三、接口详情」第 4 条,详见该节与「六、边界
|
||||
> 行为」。
|
||||
|
||||
---
|
||||
|
||||
## 二、变更接口清单
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---|------|------|------|----------|------|
|
||||
| 1 | 按需求原子确认 | POST | `/admin/fleet/assignments/requirements/{requirementId}/confirm` | 行为修复(入参/出参契约不变) | `kind=TRANSFER` 需求不再在预检门禁上必现 605905 |
|
||||
| 2 | 车务确认执行 | POST | `/admin/fleet/assignments/{assignmentId}/confirm` | 行为修复(入参/出参契约不变) | `kind=TRANSFER` 派车行的 holding 收尾与 ASSIGNED 复核两条内部分支不再必现 605041 |
|
||||
| 3 | 修改派单 | POST | `/admin/fleet/assignments/{assignmentId}/change` | 行为修复(入参/出参契约不变) | `kind=TRANSFER` 派车行改派不再必现 605041 |
|
||||
| 4 | 查询派单候选资源 | POST | `/admin/fleet/assignments/candidates` | 行为修复(入参/出参契约不变) | `kind=TRANSFER` 需求的 Step2 canonical 快照(`canonicalSnapshot` 字段)不再静默返回 `null` |
|
||||
|
||||
> 另有一处**内部作业端点**(不进本表)同根因修复:`POST /internal/fleet/jobs/vehicle-assignment-snapshot/refinalize`,
|
||||
> 详见「⚠️ 关键变化」①与「六、边界行为」。
|
||||
|
||||
---
|
||||
|
||||
## 三、接口详情
|
||||
|
||||
### 1. 按当前派车方案代际原子确认全部执行段 `POST /admin/fleet/assignments/requirements/{requirementId}/confirm`
|
||||
|
||||
**VO**: `ConfirmRequirementReqVO → ConfirmRequirementRespVO`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
车务在派单弹窗对某条用车需求下**当前有效的全部执行段**做原子最终确认(#5827 起新派车提交即
|
||||
派定,本端点服务"已派定组的复核"与"存量 holding 组的收尾确认")。本次修复前,若
|
||||
`requirementId` 指向一条 `kind=TRANSFER`(接送机)需求,请求会在最早一道版本预检门禁
|
||||
(`assertRequirementPreflightVersion`)上必然判定"需求已过期"而拒绝,即使前端刚从看板拉取的
|
||||
`expectedRequirementVersion`/`expectedRequirementSha256` 完全正确也一样;修复后该门禁按
|
||||
`requirementId` 正确择取 TRANSFER 需求做比对,version/sha256 匹配时可正常通过。
|
||||
|
||||
#### 入参(本次零新增/零变化,全量 7 个字段逐一核对源码)
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| requirementId | Path | Long | 是 | - | 当前用车需求 ID;本次修复后,传一条 `kind=TRANSFER` 需求的 ID 时不再必然被判定为版本过期 |
|
||||
| orderId | Body | Long | 是 | - | 订单 ID |
|
||||
| requestId | Body | String | 是 | ≤64 | 幂等请求标识 |
|
||||
| expectedRequirementVersion | Body | Integer | 是 | - | 预期当前有效用车需求版本 |
|
||||
| expectedRequirementSha256 | Body | String | 是 | 64 位小写十六进制 | Board 返回的当前用车需求 canonical SHA-256 |
|
||||
| expectedPlanGeneration | Body | Long | 是 | - | 预期当前最终派车方案代际 |
|
||||
| groups[] | Body | Array | 是 | ≤50 项 | 当前有效执行段精确集合及各段行程短信选择 |
|
||||
| groups[].assignmentGroupId | Body | Long | 是 | - | 当前有效派车组 ID |
|
||||
| groups[].sendItinerarySms | Body | Boolean | 是 | - | 是否向本执行段司机发送行程短信 |
|
||||
|
||||
#### 出参(本次零新增/零变化,全量字段)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| requirementId | String(雪花 ID,Long 转字符串序列化) | 用车需求 ID |
|
||||
| dispatchPlanGeneration | String(雪花 ID) | 已确认的最终派车方案代际 |
|
||||
| confirmed | Boolean | 整组是否原子确认成功 |
|
||||
| finalPlanPublished | Boolean | 本次是否发布了最终方案快照;false 表示确认已成功但订单车控仍为处理中 |
|
||||
| groups[] | Array | 各执行段确认结果 |
|
||||
| groups[].assignmentId | String(雪花 ID) | 代表派单 ID |
|
||||
| groups[].assignmentGroupId | String(雪花 ID) | 派车组 ID |
|
||||
| groups[].assignmentStatus | String | 派单状态 |
|
||||
| groups[].confirmedAt | LocalDateTime | 车务最终确认时间 |
|
||||
| groups[].sendItinerarySms | Boolean | 是否选择发送本段行程短信 |
|
||||
| groups[].itinerarySmsEventId | String(雪花 ID,未发送为 null) | 行程短信 Outbox 事件 ID |
|
||||
| groups[].itinerarySmsStatus | String | 行程短信状态 |
|
||||
| groups[].itineraryUrl | String | 本段电子行程单 H5 链接;签发不可用时为 null |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```json
|
||||
POST /admin/fleet/assignments/requirements/1934567890123457001/confirm
|
||||
{
|
||||
"orderId": 1934567890123456789,
|
||||
"requestId": "confirm-req-20260918-0001",
|
||||
"expectedRequirementVersion": 3,
|
||||
"expectedRequirementSha256": "a1b2c3d4e5f60718293a4b5c6d7e8f90112233445566778899aabbccddeeff",
|
||||
"expectedPlanGeneration": 5,
|
||||
"groups": [
|
||||
{"assignmentGroupId": 1934567890123457100, "sendItinerarySms": true}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
上例 `requirementId=1934567890123457001` 是一条 `kind=TRANSFER` 需求;本次修复前该请求必返
|
||||
605905,version/sha256 是否匹配无关紧要。
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"requirementId": "1934567890123457001",
|
||||
"dispatchPlanGeneration": "5",
|
||||
"confirmed": true,
|
||||
"finalPlanPublished": true,
|
||||
"groups": [
|
||||
{
|
||||
"assignmentId": "1934567890123457100",
|
||||
"assignmentGroupId": "1934567890123457100",
|
||||
"assignmentStatus": "assigned",
|
||||
"confirmedAt": "2026-09-18 15:00:00",
|
||||
"sendItinerarySms": true,
|
||||
"itinerarySmsEventId": "1934567890123457200",
|
||||
"itinerarySmsStatus": "PENDING",
|
||||
"itineraryUrl": "https://h5.example.com/#/itinerary/eyJvcmRlcklkIjoi..."
|
||||
}
|
||||
]
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
N/A。本端点是需求级原子确认动作,要么全部执行段确认成功并返回完整 `groups[]`,要么整体失败
|
||||
关闭返回错误响应;不存在"部分成功"或 `data` 为空数组/null 的成功响应形态。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 605905,
|
||||
"message": "需求版本过期",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ **响应信封订正**:`Result` 只有 `code`/`message`/`data`/`traceId` 四个字段,业务失败时
|
||||
> `code` 本身就是业务错误码,HTTP 状态码固定 200,**不存在独立的 `errorCode` 字段**;
|
||||
> `success` 是 `Result.isSuccess()`(`code==200`)序列化出的真实字段。此端点未被
|
||||
> Controller 专门 catch,异常经 `GlobalExceptionHandler.handleBusiness` 兜底,`data`
|
||||
> 固定为 `null`(不含 `dailyDifferences`,与下面两个端点不同)。
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 本次修复前,仅因 `requirementId` 指向 `kind=TRANSFER` 需求就必然命中上面这条 605905,即便
|
||||
`expectedRequirementVersion`/`expectedRequirementSha256` 与前端刚拉取的完全一致;修复后只在
|
||||
需求确实已发生变化(如被他人换版/改派)时才会命中
|
||||
- 若通过预检门禁后,在需求级原子确认循环内部(`assertFinalConfirmationBaseline`,
|
||||
`AssignmentService.java:3974`)仍检出基线不一致,同样按 605041
|
||||
(`FINAL_CONFIRMATION_BASELINE_MISMATCH`,"订单行程或用车派单已变化,请按逐日差异处理后
|
||||
重试")拒绝;但该调用点不经 Controller 的专门 catch,响应 `data` 固定为 `null`,**不返回
|
||||
`dailyDifferences`**(与「2. 车务确认执行」「3. 修改派单」两个端点不同,那两处会返回结构化
|
||||
差异)
|
||||
- `kind=TRAVEL` 需求的确认流程、错误码语义与本次改动前逐字一致
|
||||
|
||||
---
|
||||
|
||||
### 2. 车务确认执行(holding→assigned) `POST /admin/fleet/assignments/{assignmentId}/confirm`
|
||||
|
||||
**VO**: `ConfirmReqVO → ConfirmRespVO`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
两类入口共用本端点:①存量 holding 组的收尾确认;②已派定组的复核——重跑最终确认基线 + 行程
|
||||
短信决策一致性校验 + 接送机门禁,通过后重发最终方案快照。本次修复覆盖这两条内部分支
|
||||
(holding 收尾在 `AssignmentService.java:4246/4279`,ASSIGNED 复核经
|
||||
`revalidateAssignedAfterBaselineChange` 于 `:4462`)对 `kind=TRANSFER` 派车行的基线选取——
|
||||
两处修复前都直接读 `context.getVehicleRequirement()`(恒 TRAVEL),派车行的
|
||||
`assignmentId` 无论对应哪条需求,基线比对都必然落到 TRAVEL 上。
|
||||
|
||||
#### 入参(本次零新增/零变化,全量 5 个字段)
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| assignmentId | Path | Long | 是 | - | 派单 ID;本次修复后,若该行属于 `kind=TRANSFER` 需求,不再必然 605041 |
|
||||
| sendItinerarySms | Body | Boolean | 是 | - | 是否在最终确认后向该车师傅发送行程短信 |
|
||||
| requestId | Body | String | 是 | ≤64 | 幂等请求标识 |
|
||||
| vehicleFeeTotal | Body | BigDecimal | 否 | 已废弃,传值即被拒绝 | 历史字段,最终总车费已改为逐日车费只读合计 |
|
||||
| vehicleFeeAdjustmentReason | Body | String | 否 | ≤256,已废弃,传值即被拒绝 | 历史字段,逐日车费调整原因应在派车保存时提交 |
|
||||
|
||||
#### 出参(本次零新增/零变化,全量字段,含 `sideEffects`/`dailyDifferences` 展开)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| confirmed | Boolean | 是否已完成最终确认 |
|
||||
| assignmentStatus | String | 派单状态(assigned=已派定) |
|
||||
| stageCode | String | 生命周期阶段码 |
|
||||
| stageLabel | String | 生命周期阶段文案 |
|
||||
| currentStep | Integer | 当前三阶段步骤(订单详情/排车/确认执行) |
|
||||
| assignmentGroupId | String(雪花 ID) | 派车组 ID(同一辆车连续每日切片共用) |
|
||||
| vehicleFeeTotal | String(BigDecimal 转字符串) | 最终确认后的该车本派车段总车费 |
|
||||
| vehicleFeeSource | String | 最终总车费来源:AUTO、MANUAL |
|
||||
| vehicleFeeAdjustmentReason | String | 手工总车费调整原因 |
|
||||
| confirmedAt | LocalDateTime | 车务确认派车时间 |
|
||||
| sendItinerarySms | Boolean | 车务是否选择向该车师傅发送行程短信 |
|
||||
| itinerarySmsEventId | String(雪花 ID) | 行程短信可靠事件 ID;不发送为空 |
|
||||
| itinerarySmsStatus | String | 确认响应中的初始短信状态(PENDING,NOT_SENT) |
|
||||
| itineraryUrl | String | 电子行程单 H5 签名链接 |
|
||||
| sideEffects | Object | 副作用执行结果,见下方展开 |
|
||||
| sideEffects.vehicleStatusUpdated | String | 车辆状态更新结果(idle,busy,maint;不涉及车为 null) |
|
||||
| sideEffects.driverStatusUpdated | String | 司机状态更新结果(busy,idle;不涉及司机为 null) |
|
||||
| sideEffects.reconPrepRowsCreated | Integer | 对账预备单创建条数(M1 降级恒返 0) |
|
||||
| sideEffects.reconPrepMarkedCanceled | Integer | 对账预备单标记取消条数(M1 降级恒返 0) |
|
||||
| dailyDifferences | Array | 确认失败时的逐日基线差异;成功时为空 |
|
||||
| dailyDifferences[].serviceDate | LocalDate | 服务日 |
|
||||
| dailyDifferences[].differenceType | String | 差异类型枚举,见「六.5」 |
|
||||
| dailyDifferences[].differenceLabel | String | 差异中文名称 |
|
||||
| dailyDifferences[].assignmentId | String(雪花 ID) | 派单 ID |
|
||||
| dailyDifferences[].assignmentSlotId | String(雪花 ID) | 稳定车辆槽位 ID |
|
||||
| dailyDifferences[].passengerCount | Integer | 订单乘客人数(不含司机) |
|
||||
| dailyDifferences[].message | String | 差异说明 |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```json
|
||||
POST /admin/fleet/assignments/1934567890123457100/confirm
|
||||
{
|
||||
"sendItinerarySms": true,
|
||||
"requestId": "fleet-final-confirm-20260918-0001"
|
||||
}
|
||||
```
|
||||
|
||||
上例 `assignmentId=1934567890123457100` 是一条挂在 `kind=TRANSFER` 需求下的派车行;本次修复前
|
||||
该请求必返 605041。
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"confirmed": true,
|
||||
"assignmentStatus": "assigned",
|
||||
"stageCode": "assigned",
|
||||
"stageLabel": "已派车",
|
||||
"currentStep": 3,
|
||||
"assignmentGroupId": "1934567890123457100",
|
||||
"vehicleFeeTotal": "700.00",
|
||||
"vehicleFeeSource": "AUTO",
|
||||
"vehicleFeeAdjustmentReason": null,
|
||||
"confirmedAt": "2026-09-18 15:05:00",
|
||||
"sendItinerarySms": true,
|
||||
"itinerarySmsEventId": "1934567890123457200",
|
||||
"itinerarySmsStatus": "PENDING",
|
||||
"itineraryUrl": "https://h5.example.com/#/itinerary/eyJvcmRlcklkIjoi...",
|
||||
"sideEffects": {
|
||||
"vehicleStatusUpdated": "busy",
|
||||
"driverStatusUpdated": "busy",
|
||||
"reconPrepRowsCreated": 0,
|
||||
"reconPrepMarkedCanceled": 0
|
||||
},
|
||||
"dailyDifferences": null
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
N/A。本端点确认成功时恒返回完整对象(`sideEffects` 各字段可能为 null,但不是"空数据"形态);
|
||||
失败时按下方错误响应返回,不存在中间态。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 605041,
|
||||
"message": "订单行程或用车派单已变化,请按逐日差异处理后重试",
|
||||
"data": {
|
||||
"confirmed": false,
|
||||
"dailyDifferences": [
|
||||
{
|
||||
"serviceDate": null,
|
||||
"differenceType": "REQUIREMENT_VERSION_MISMATCH",
|
||||
"differenceLabel": "用车需求已更新",
|
||||
"assignmentId": "1934567890123457100",
|
||||
"assignmentSlotId": "1934567890123457099",
|
||||
"passengerCount": null,
|
||||
"message": "用车需求已更新,请刷新后按最新需求重新派车"
|
||||
}
|
||||
]
|
||||
},
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 本次修复前,`kind=TRANSFER` 派车行走 holding 收尾确认或 ASSIGNED 复核任一分支都**必现**
|
||||
605041,与请求体字段是否正确无关(两条分支都不接受调用方传 `requirementId`,只能按
|
||||
`assignmentId` 反查行、再拿上下文里恒为 TRAVEL 的需求比对);修复后按该行自己的
|
||||
`requirementId` 正确匹配 TRANSFER 需求
|
||||
- 若基线确实发生变化(如换版、需求被取消),仍会返回 605041 及 `data.dailyDifferences`,与本次
|
||||
改动前逐字一致;前端展示优先用 `differenceLabel`/`message`,`differenceType` 仅供逻辑判断
|
||||
- `kind=TRAVEL` 派车行的确认流程、`sideEffects`/`dailyDifferences` 语义与本次改动前逐字一致
|
||||
- 旧 HOLD 通知结果仍在确认中的场景(605042 等)不在本次修复范围内,行为未变
|
||||
|
||||
---
|
||||
|
||||
### 3. 修改派单(按槽位和生效日) `POST /admin/fleet/assignments/{assignmentId}/change`
|
||||
|
||||
**VO**: `ChangeAssignmentReqVO → ChangeAssignmentRespVO`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
按稳定车辆槽位和生效日原子换车、换司机或同时替换;改派恒执行最终基线复核。本次修复覆盖
|
||||
`doChangeInLock` 内部对 `kind=TRANSFER` 派车行的基线选取(`AssignmentService.java:5848` 附近,
|
||||
修复前 `assertFinalConfirmationBaseline` 的 `requirementOverride` 显式传 `null`,回退读
|
||||
`context.getVehicleRequirement()` 恒为 TRAVEL)。
|
||||
|
||||
#### 入参(本次零新增/零变化,全量 14 个字段,含嵌套 `dailyVehicleFees[]`)
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| assignmentId | Path | Long | 是 | - | 当前车辆槽位任一派单 ID;本次修复后,若该行属于 `kind=TRANSFER` 需求,不再必然 605041 |
|
||||
| effectiveDate | Body | LocalDate | 是 | - | 改派生效日(含当日) |
|
||||
| serviceDates | Body | Array\<LocalDate\> | 否 | - | 按天改派限定的服务日期集;空=生效日起连续后缀整体改派 |
|
||||
| newVehicleId | Body | Long | 否 | - | 新车辆 ID;不换车可空 |
|
||||
| newDriverId | Body | Long | 否 | - | 新司机 ID;不换司机可空 |
|
||||
| sendItinerarySms | Body | Boolean | 否 | 不传按 false | 是否向改派后的师傅发送行程短信 |
|
||||
| holdMode | Body | Integer | 否 | 已废弃,服务端忽略 | #5827 起一律一步派定,勿再传 |
|
||||
| messageTemplateId | Body | Long | 否 | 已废弃 | 不再消费 |
|
||||
| customBody | Body | String | 否 | ≤4000,已废弃 | 不再消费 |
|
||||
| protocolPrice | Body | BigDecimal | 否 | ≥0.00,整数最多10位/小数最多2位 | 新协议价日单价;可空按价格日历计算 |
|
||||
| vehicleFeeTotal | Body | BigDecimal | 否 | 已废弃,传值即被拒绝 | 历史字段 |
|
||||
| vehicleFeeAdjustmentReason | Body | String | 否 | ≤256 | 新派车段单日车费与价格日历不一致时的调整原因 |
|
||||
| dailyVehicleFees[] | Body | Array | 否 | - | 新派车段逐日车费;未提交的收费日按价格日历取价 |
|
||||
| dailyVehicleFees[].serviceDate | Body | LocalDate | 是(数组项内) | - | 车费服务日期 |
|
||||
| dailyVehicleFees[].price | Body | BigDecimal | 是(数组项内) | ≥0.00 | 本次派车单日车费;只覆盖本次派车,不回写价格日历 |
|
||||
| retainedVehicleFeeTotal | Body | BigDecimal | 否 | 已废弃,传值即被拒绝 | 历史字段 |
|
||||
| retainedVehicleFeeAdjustmentReason | Body | String | 否 | ≤256,已废弃 | 历史字段 |
|
||||
| chargeableServiceDates | Body | Array\<LocalDate\> | 否 | - | 生效日起收取车费的服务日期;不传沿用原值 |
|
||||
| vehicleFeeWaiverReason | Body | String | 否 | ≤256 | 免费服务日原因;全部免费时必填 |
|
||||
| confirmAllServiceDatesFree | Body | Boolean | 否 | - | 目标日期全部免费二次确认 |
|
||||
| confirmCrossResident | Body | Boolean | 否 | - | 跨常驻车显式确认 |
|
||||
| reason | Body | String | 是 | ≤256 | 修改原因 |
|
||||
| requestId | Body | String | 是 | ≤64 | 请求幂等 ID |
|
||||
|
||||
#### 出参(本次零新增/零变化,全量字段,含 `otherVehicles[]`/`dailyVehicleFees[]`/`dailyDifferences[]` 展开)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| assignmentId | String(雪花 ID) | 新派单锚点 ID |
|
||||
| assignmentSlotId | String(雪花 ID) | 稳定车辆槽位 ID;改派前后保持不变 |
|
||||
| previousAssignmentGroupId | String(雪花 ID) | 被替换的旧派车组 ID |
|
||||
| newAssignmentGroupId | String(雪花 ID) | 新派车组 ID |
|
||||
| assignmentStatus | String | 新派车组状态 |
|
||||
| effectiveDate | LocalDate | 改派实际生效日(含当日) |
|
||||
| affectedDays | Integer | 本次原子替换的逐日切片数量 |
|
||||
| protocolPrice | String(BigDecimal 转字符串) | 新协议价日单价快照(元/车天) |
|
||||
| vehicleFeeAutoTotal | String(BigDecimal) | 改派后价格日历自动合计参考 |
|
||||
| vehicleFeeAutoComplete | Boolean | 改派后自动合计是否覆盖全部计费服务日 |
|
||||
| vehicleFeeTotal | String(BigDecimal) | 改派后新派车段逐日车费只读合计 |
|
||||
| vehicleFeeSource | String | 改派后总车费来源:AUTO、MANUAL、INCOMPLETE |
|
||||
| vehicleFeeAdjustmentReason | String | 改派后单日车费调整原因 |
|
||||
| dailyVehicleFees[] | Array | 改派后逐日价格日历参考价和本次派车价 |
|
||||
| dailyVehicleFees[].serviceDate | LocalDate | 服务日期 |
|
||||
| dailyVehicleFees[].chargeable | Boolean | 是否收取车费 |
|
||||
| dailyVehicleFees[].calendarPrice | String(BigDecimal) | 车型价格日历参考价;缺价为空 |
|
||||
| dailyVehicleFees[].assignmentPrice | String(BigDecimal) | 本次派车单日车费;收费日必有值 |
|
||||
| dailyVehicleFees[].source | String | 价格来源:CALENDAR、OVERRIDE、FREE、MISSING |
|
||||
| dailyVehicleFees[].calendarPriceMissing | Boolean | 价格日历是否缺价 |
|
||||
| otherVehicleCount | Integer | 同订单其它有效车辆槽位数 |
|
||||
| warningCode | String | 强提示代码;无其它车辆时为空 |
|
||||
| warningMessage | String | 强提示文案;无其它车辆时为空 |
|
||||
| otherVehicles[] | Array | 同订单其它有效车辆摘要 |
|
||||
| otherVehicles[].assignmentSlotId | String(雪花 ID) | 其它稳定车辆槽位 ID |
|
||||
| otherVehicles[].vehiclePlate | String | 当前车牌号 |
|
||||
| otherVehicles[].driverName | String | 当前司机名称 |
|
||||
| otherVehicles[].startDate | LocalDate | 当前有效服务日起 |
|
||||
| otherVehicles[].endDate | LocalDate | 当前有效服务日止 |
|
||||
| sendItinerarySms | Boolean | 车务本次是否选择向改派后的师傅发送行程短信 |
|
||||
| itinerarySmsEventId | String(雪花 ID) | 行程短信可靠事件 ID;未勾选发送为空 |
|
||||
| itinerarySmsStatus | String | 本次改派的初始短信状态(PENDING,NOT_SENT) |
|
||||
| dailyDifferences[] | Array | 改派最终派定失败时的逐日基线差异(结构同「2. 车务确认执行」的 `dailyDifferences`) |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```json
|
||||
POST /admin/fleet/assignments/1934567890123457100/change
|
||||
{
|
||||
"effectiveDate": "2026-10-11",
|
||||
"newVehicleId": 1934567890123456701,
|
||||
"newDriverId": 1934567890123456702,
|
||||
"sendItinerarySms": false,
|
||||
"reason": "司机临时无法执行,替换车辆和司机",
|
||||
"requestId": "change-20260918-0001"
|
||||
}
|
||||
```
|
||||
|
||||
上例 `assignmentId=1934567890123457100` 是一条挂在 `kind=TRANSFER` 需求下的派车行;本次修复前
|
||||
该请求必返 605041。
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"assignmentId": "1934567890123457300",
|
||||
"assignmentSlotId": "1934567890123457099",
|
||||
"previousAssignmentGroupId": "1934567890123457100",
|
||||
"newAssignmentGroupId": "1934567890123457300",
|
||||
"assignmentStatus": "assigned",
|
||||
"effectiveDate": "2026-10-11",
|
||||
"affectedDays": 1,
|
||||
"protocolPrice": "1688.00",
|
||||
"vehicleFeeAutoTotal": "1688.00",
|
||||
"vehicleFeeAutoComplete": true,
|
||||
"vehicleFeeTotal": "1688.00",
|
||||
"vehicleFeeSource": "AUTO",
|
||||
"vehicleFeeAdjustmentReason": null,
|
||||
"dailyVehicleFees": [
|
||||
{
|
||||
"serviceDate": "2026-10-11",
|
||||
"chargeable": true,
|
||||
"calendarPrice": "1688.00",
|
||||
"assignmentPrice": "1688.00",
|
||||
"source": "CALENDAR",
|
||||
"calendarPriceMissing": false
|
||||
}
|
||||
],
|
||||
"otherVehicleCount": 0,
|
||||
"warningCode": null,
|
||||
"warningMessage": null,
|
||||
"otherVehicles": [],
|
||||
"sendItinerarySms": false,
|
||||
"itinerarySmsEventId": null,
|
||||
"itinerarySmsStatus": "NOT_SENT",
|
||||
"dailyDifferences": null
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
N/A。本端点改派成功时恒返回完整对象(`otherVehicles` 无其它车辆时为空数组而非缺失字段);
|
||||
失败时按下方错误响应返回。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 605041,
|
||||
"message": "订单行程或用车派单已变化,请按逐日差异处理后重试",
|
||||
"data": {
|
||||
"dailyDifferences": [
|
||||
{
|
||||
"serviceDate": null,
|
||||
"differenceType": "REQUIREMENT_VERSION_MISMATCH",
|
||||
"differenceLabel": "用车需求已更新",
|
||||
"assignmentId": "1934567890123457100",
|
||||
"assignmentSlotId": "1934567890123457099",
|
||||
"passengerCount": null,
|
||||
"message": "用车需求已更新,请刷新后按最新需求重新派车"
|
||||
}
|
||||
]
|
||||
},
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 本次修复前,`kind=TRANSFER` 派车行改派**必现** 605041,与请求体字段是否正确无关(`change`
|
||||
端点不接受调用方传 `requirementId`,只能按 `assignmentId` 反查所属行,再拿上下文里恒为 TRAVEL
|
||||
的需求比对);修复后按该行自己的 `requirementId` 正确匹配 TRANSFER 需求
|
||||
- 若基线确实发生变化,仍会返回 605041 及 `data.dailyDifferences`,与本次改动前逐字一致
|
||||
- 同订单存在其它车辆槽位时仍返回 `warningCode=ORDER_HAS_OTHER_VEHICLES` 及摘要,前端仍须强提示
|
||||
(行为未变)
|
||||
- `kind=TRAVEL` 派车行的改派流程、错误码语义与本次改动前逐字一致
|
||||
|
||||
---
|
||||
|
||||
### 4. 查询派单候选资源 `POST /admin/fleet/assignments/candidates`
|
||||
|
||||
**VO**: `AssignmentCandidateReqVO → AssignmentCandidateRespVO`
|
||||
|
||||
> ⚠️ **本节范围声明**:本端点是派单弹窗车辆/司机候选查询的既有端点,入参 24 个字段、出参
|
||||
> 涵盖车辆候选、司机候选、常驻关系、动态筛选项等一整套与本次修复无关的结构。**本次修复只影响
|
||||
> 出参里的 `canonicalSnapshot` 一个字段**(及其内部 `resolveCanonicalSnapshot` 的基线选取逻辑),
|
||||
> 下方入参/出参表**只列与本次修复直接相关的字段**,其余约 20 个入参字段与 `vehicles[]`/
|
||||
> `drivers[]`/`fleetTeamFacets[]`/`vehicleTypeFacets[]`/`selectedDriverResidentVehicle` 等
|
||||
> 出参结构本次**零改动**,未逐一列出。
|
||||
|
||||
#### 使用场景
|
||||
|
||||
四步向导第②步(选车/选司机)加载页面时调用。本次修复前,若 `requirementId` 指向一条
|
||||
`kind=TRANSFER`(接送机)需求,响应里 `vehicles[]`/`drivers[]` 等候选数据正常返回,但
|
||||
**`canonicalSnapshot` 字段恒为 `null`**——`Step2CanonicalSnapshotService.resolveCanonicalSnapshot`
|
||||
内部的 `identityConsistent` 身份比对拿 `context.getVehicleRequirement()`(恒 TRAVEL)与请求的
|
||||
`requirementId`(TRANSFER)比对,必不等,**不抛错误码,只打一条 `log.warn` 后直接返回 `null`**。
|
||||
运营端表现为"网格出不来",没有任何错误提示能指向成因。修复后 `Step2CanonicalSnapshotService`
|
||||
与 `AssignmentService` 共用新抽出的 `BaselineRequirementSelector.select(requirementId, context)`
|
||||
按请求自己的 `requirementId` 正确择取 TRANSFER 需求。
|
||||
|
||||
**可验证的效果句**(工单 #7443 AC-24 给定判据):对一条 `kind=TRANSFER` 的活跃需求调
|
||||
`resolveCanonicalSnapshot`(该 `requirementId`),返回非 `null`,且 `editableServiceDates`
|
||||
恰为该需求的两条航班日、`cells` 覆盖这两日、其中已派车那一日的 cell `used = "USED"` 且
|
||||
`assignmentId` 指向该派车行。
|
||||
|
||||
#### 入参(本节只列与本次修复相关的字段;其余约 20 个字段本次零改动,未列出)
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| orderId | Body | Long | 改派排除自身时必填 | - | 当前订单 ID |
|
||||
| requirementId | Body | Long | 改派排除自身时必填 | - | 当前用车需求 ID;本次修复后,传一条 `kind=TRANSFER` 需求的 ID 时 `canonicalSnapshot` 不再必然为 `null` |
|
||||
|
||||
#### 出参(本节只列 `canonicalSnapshot` 极其内部结构;`vehicles[]`/`drivers[]`/其余顶层字段本次零改动,未列出)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| canonicalSnapshot | Object | Step2 canonical full snapshot;无 `requirementId` 或需求上下文不可用时为 `null`(本次修复前,`kind=TRANSFER` 需求也会落入这个 `null`,是本次修复的对象) |
|
||||
| canonicalSnapshot.planGeneration | String(雪花 ID,`required=true`) | 当前计划代际(不透明令牌) |
|
||||
| canonicalSnapshot.snapshotVersion | String(雪花 ID,`required=true`) | 当前快照版本;同代内容修订递增 |
|
||||
| canonicalSnapshot.retainedGroupIds | Array\<String\>(`required=true`) | 有序 RetainedGroupSet:稳定派车组 ID |
|
||||
| canonicalSnapshot.editableServiceDates | Array\<LocalDate\>(`required=true`) | 完整有序可编辑服务日集合 |
|
||||
| canonicalSnapshot.cells | Array(`required=true`) | 每个派车组×服务日笛卡尔积位置唯一 cell |
|
||||
| canonicalSnapshot.cells[].groupId | String(雪花 ID) | 稳定派车组 ID |
|
||||
| canonicalSnapshot.cells[].serviceDate | LocalDate | 服务日期 |
|
||||
| canonicalSnapshot.cells[].assignmentId | String(雪花 ID) | 当天逐日派车行 ID;无行为 null |
|
||||
| canonicalSnapshot.cells[].used | String | `USED`=实际用车/`UNUSED`=显式不用车/`null`=无切片行 |
|
||||
| canonicalSnapshot.cells[].readOnly | Boolean | 该 cell 是否只读 |
|
||||
| canonicalSnapshot.cells[].vehicleId | String(雪花 ID) | 当天车辆 ID |
|
||||
| canonicalSnapshot.cells[].driverId | String(雪花 ID) | 当天司机 ID |
|
||||
| canonicalSnapshot.selectedVehicle | Object | 已选车辆最小脱敏展示快照;未选为 null(结构未动) |
|
||||
| canonicalSnapshot.selectedDriver | Object | 已选司机最小脱敏展示快照;未选为 null(结构未动) |
|
||||
|
||||
> `CanonicalSnapshotVO` 五个 `required=true` 字段(`planGeneration`/`snapshotVersion`/
|
||||
> `retainedGroupIds`/`editableServiceDates`/`cells`)是 **Swagger 注解表达的契约意图,不是
|
||||
> 运行时观测**——它们只在 `canonicalSnapshot` 本身非 `null` 时必然存在;`canonicalSnapshot`
|
||||
> 整体为 `null` 时这五个字段自然也拿不到。`Swagger required` 描述的是"存在时必填",不是
|
||||
> "恒存在"。
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```json
|
||||
POST /admin/fleet/assignments/candidates
|
||||
{
|
||||
"orderId": 1934567890123456789,
|
||||
"requirementId": 1934567890123457001,
|
||||
"startDate": "2026-10-11",
|
||||
"endDate": "2026-10-17",
|
||||
"vehiclePage": 1,
|
||||
"vehiclePageSize": 20,
|
||||
"driverPage": 1,
|
||||
"driverPageSize": 20
|
||||
}
|
||||
```
|
||||
|
||||
上例 `requirementId=1934567890123457001` 是一条 `kind=TRANSFER` 需求;本次修复前
|
||||
`data.canonicalSnapshot` 必为 `null`(`vehicles`/`drivers` 等其余字段不受影响,正常返回)。
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"canonicalSnapshot": {
|
||||
"planGeneration": "1934567890123457500",
|
||||
"snapshotVersion": "1",
|
||||
"retainedGroupIds": ["1934567890123457100"],
|
||||
"editableServiceDates": ["2026-10-11", "2026-10-17"],
|
||||
"cells": [
|
||||
{
|
||||
"groupId": "1934567890123457100",
|
||||
"serviceDate": "2026-10-11",
|
||||
"assignmentId": "1934567890123457100",
|
||||
"used": "USED",
|
||||
"readOnly": false,
|
||||
"vehicleId": "2064998142394183681",
|
||||
"driverId": "2065272150960357378"
|
||||
},
|
||||
{
|
||||
"groupId": "1934567890123457100",
|
||||
"serviceDate": "2026-10-17",
|
||||
"assignmentId": null,
|
||||
"used": null,
|
||||
"readOnly": false,
|
||||
"vehicleId": null,
|
||||
"driverId": null
|
||||
}
|
||||
],
|
||||
"selectedVehicle": null,
|
||||
"selectedDriver": null
|
||||
}
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
(省略号:本响应实际还含 `vehicles`/`drivers`/`fleetTeamFacets` 等与本次修复无关的字段,
|
||||
上例只展示 `canonicalSnapshot`。)
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
`canonicalSnapshot` 为 `null` 是本端点**合法的既有降级形态**,不是本次修复要消灭的东西——
|
||||
未传 `requirementId`、或需求上下文确实不可达(如 809007 服务日未回填导致
|
||||
`transferVehicleRequirement` 也取不到)时,`canonicalSnapshot` 仍然合法为 `null`。本次修复只
|
||||
消灭了"`requirementId` 合法指向一条**存在**的 TRANSFER 需求,却因基线选错而被误判身份不一致"
|
||||
这一种 `null` 成因;其余合法 `null` 成因不受影响。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"canonicalSnapshot": null
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 错误响应
|
||||
|
||||
本端点的 `canonicalSnapshot` 解析路径**不抛错误码**(这正是「使用场景」里描述的"坏法是静默的");
|
||||
`resolveCanonicalSnapshot` 内部锁获取失败时会抛 `CommonErrorCode.RESOURCE_LOCKED`
|
||||
(`hl-common-core/.../CommonErrorCode.java:67-68`),但这是既有的锁竞争兜底,与本次修复的身份
|
||||
比对分支无关,本次未改动:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 100503,
|
||||
"message": "资源被占用,请稍后重试",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 🔴 **本条【假设】未验证,请 mmg 自验**:`canonicalSnapshot` 为 `null` 时四步向导第②步前端
|
||||
会表现出什么效果(空白网格/报错提示/直接不可操作),本单**没有测试前端行为**,不替前端下
|
||||
结论。上文"运营看到网格出不来"是问题背景陈述,不是对当前前端代码行为的实测断言
|
||||
- `canonicalSnapshot` 为 `null` 与"请求本身失败"是两回事:响应 `code` 仍是 200、`success`
|
||||
仍是 `true`,`vehicles[]`/`drivers[]` 等其余候选数据不受影响,只有这一个字段拿不到
|
||||
- `kind=TRAVEL` 需求的 `canonicalSnapshot` 解析行为逐字不变
|
||||
- 本条修复与本文档前三条同根因、同修法(`BaselineRequirementSelector`),但触发路径不同
|
||||
(前三条走 HTTP 错误响应,这一条走静默降级字段),前端排查时不能用同一套"看错误码"的思路
|
||||
|
||||
---
|
||||
|
||||
## 四、契约约束与正确调用方式
|
||||
|
||||
> 本节只写后端接受/拒绝 payload 的规则,不写 UI 渲染建议。
|
||||
|
||||
| 场景 | 做法 |
|
||||
|------|------|
|
||||
| `requirementId`/`assignmentId` 指向一条 `kind=TRANSFER` 需求/派车行 | 三个端点的请求体格式**不需要任何调整**——与 `kind=TRAVEL` 完全一样传参即可,fleet 内部会自动按行/需求自己的 ID 择基线 |
|
||||
| `POST /requirements/{id}/confirm` 拿到 605905 | 与本次修复前不同:现在**只**代表需求版本确实过期(被他人换版/改派),需要重新拉取最新的 `expectedRequirementVersion`/`expectedRequirementSha256` 后重试,**不再**是"TRANSFER 需求天生用不了这个端点"的信号 |
|
||||
| `POST /{assignmentId}/confirm`、`POST /{assignmentId}/change` 拿到 605041 | 同上,现在只代表基线确实变化,按 `data.dailyDifferences[].differenceLabel`/`message` 提示用户刷新重试 |
|
||||
| 需要创建/查询一条真实的 `kind=TRANSFER` 需求用于联调 | 目前仍需 SQL 直接构造(上游写口 809009 未开放),不在本次修复范围内 |
|
||||
|
||||
---
|
||||
|
||||
## 五、数据库行为
|
||||
|
||||
| 操作 | 影响 |
|
||||
|------|------|
|
||||
| `kind=TRANSFER` 派车行调用上述三接口,基线校验通过 | 与 `kind=TRAVEL` 完全相同的既有落库逻辑(`fleet_assignment` 状态流转、`confirmed_at`/`assignment_status` 等列更新),不因 `kind` 不同而有任何额外列或额外写入 |
|
||||
| `kind=TRANSFER` 派车行调用上述三接口,基线校验未通过(需求确实已变化) | 与 `kind=TRAVEL` 相同:整体拒绝,不落库,不改变已有行状态 |
|
||||
| `kind=TRAVEL` 派车行调用上述三接口 | 落库行为与本次改动前逐字一致 |
|
||||
| `OrderFleetDetailContextDTO` 新增字段 `transferVehicleRequirement` | 纯内存态 Feign 响应字段,不对应任何新增数据库列 |
|
||||
|
||||
---
|
||||
|
||||
## 六、边界行为
|
||||
|
||||
- `transferVehicleRequirement` 为 `null` 的三种合法情形(源码 javadoc 逐字,
|
||||
`OrderFleetProviderService.java:336-354`):①该订单没有接送机需求(绝大多数订单);
|
||||
②接送机需求存在但服务日尚未回填(809007 降级为 `null`,不让整个订单车务详情报错);
|
||||
③订单已终态。三种情形下 `baselineRequirementFor` 都会回退到 `vehicleRequirement`(TRAVEL),
|
||||
行为与改动前一致
|
||||
- 服务日尚未回填的 `kind=TRANSFER` 需求:本次修复**不改变**这类需求仍无法被正常操作的事实
|
||||
(`transferVehicleRequirement` 取不到即为 `null`,三端点仍按原口径拒绝);服务日回填属
|
||||
#7443 AC-6~9 范畴,已于今天早些时候的 PR #7911/#7912/#7913 交付(见
|
||||
`18_7443_接送机用车需求分叉…` 文档)
|
||||
- `POST /requirements/{requirementId}/confirm` 对 `kind=TRANSFER` 的实际可观测报错是
|
||||
**605905**(`assertRequirementPreflightVersion` 更早触发的预检门禁),不是 605041——本条
|
||||
订正了 2026-09-18 早些时候 `17_7443_*.md`/`18_7443_接送机用车需求分叉…` 两份文档"三处均
|
||||
605041"的表述,理由与出处见上方「⚠️ 关键变化」
|
||||
- `POST /{assignmentId}/confirm`、`POST /{assignmentId}/change` 对 `kind=TRANSFER` 的实际可
|
||||
观测报错才是 605041
|
||||
- 本次修复还覆盖了一处**非 HTTP 端点**的内部判据:`isRequirementEligibleForReopen`
|
||||
(`AssignmentService.java:9135`,commit 内注释标注"第 4 个落点")。它被两条异步补偿链路调用
|
||||
(`AssignmentLifecycleOutboxEffectService.java:136` 撤销"整段不用车"声明后的需求重开、`:264`
|
||||
取消派车后的补偿重开),修复前对 `kind=TRANSFER` 需求恒返回 `false`,两条补偿链路对接送机
|
||||
需求整条失效(需求会卡在 `DONE`/`PROCESSING` 不自愈,且不报任何错误)。前端**无法直接感知**
|
||||
这一点——它不产生任何同步 HTTP 响应,只在"撤销不用车声明"或"取消已派车后需求应否被重开"的
|
||||
排查场景可能相关,记录于此供后续问题定位参考
|
||||
- **`refinalizeFinalSnapshot`(内部作业端点,提交 `694e405fd`,`AssignmentService.java:13092`)**:
|
||||
与 `isRequirementEligibleForReopen` 同形,入参 `requirementId` 由
|
||||
`FleetJobInternalController`(`POST /internal/fleet/jobs/vehicle-assignment-snapshot/refinalize`)
|
||||
原样传入、不带 `kind`,修复前恒读 `context.getVehicleRequirement()`(TRAVEL),TRANSFER 需求
|
||||
进来在 `:13096-13098` 的身份比对上必然不等,**整条重发最终方案快照的补偿链路对 TRANSFER
|
||||
不可用**。抛出的错误码是 **605905**(`REQUIREMENT_VERSION_EXPIRED`,"需求版本过期")——
|
||||
⚠️ 该方法的源码注释与提交信息把这里写成"报 605036",经对照 `:13097-13098` 的实际
|
||||
`throw` 语句核实为**笔误**(605036 是 `CROSS_RESIDENT_CONFIRMATION_REQUIRED`,"司机与车辆
|
||||
不是常驻组合",与本方法无关),本文档按源码实测的 605905 记录。本端点不面向 admin 前端,
|
||||
不进「二、变更接口清单」
|
||||
- **Step2 canonical 快照(提交 `15c7cdd0c`,`Step2CanonicalSnapshotService.java:100`)**:
|
||||
详见「三、接口详情」第 4 条。补充一点边界行为——`identityConsistent` 的身份比对**除
|
||||
`requirementId` 外还比对 `orderId`**(`Step2CanonicalSnapshotService.java:136-154`),本次
|
||||
修复只解决了 `requirementId` 因恒读 TRAVEL 而误判的那部分;若 `orderId` 本身传错,
|
||||
修复前后同样会被判定"身份不一致"并静默返回 `null`,这不是本次修复要处理的场景
|
||||
- **`BaselineRequirementSelector`(提交 `15c7cdd0c`,`assignment/support/` 新增类)**:原来
|
||||
fleet 内部只有 `AssignmentService` 私有方法 `baselineRequirementFor` 一份择基线逻辑,本次
|
||||
抽成独立静态工具类 `BaselineRequirementSelector.select(requirementId, context)`,
|
||||
`AssignmentService`(确认/改派/复验/重开/重发快照五处)与 `Step2CanonicalSnapshotService`
|
||||
(候选查询一处)共用同一份实现(CODE_RULES §15.7 对称子域禁镜像重复)。这是**内部重构,不
|
||||
改变任何对外行为或字段**,此处只作记录,不影响上面任何一条边界行为
|
||||
- `kind=TRAVEL` 派车行三个端点、`isRequirementEligibleForReopen`、`refinalizeFinalSnapshot`、
|
||||
Step2 canonical 快照的全部行为逐字不变(`baselineRequirementFor`/`BaselineRequirementSelector`
|
||||
对非 TRANSFER 命中的 `requirementId` 一律回退到原 `context.getVehicleRequirement()`)
|
||||
- 本次修复零 DB 迁移,不改变 `fleet_assignment`/`vehicle_requirement` 任一张表结构
|
||||
- 上游 `PUT /v3/admin/order/{id}/vehicle-requirement` 传 `kind=TRANSFER` 的写口仍然关着
|
||||
(809009,`transfer-kind-submit-enabled` 默认 `false`),本次修复**不改变这一点**——没有这个
|
||||
开关,生产环境依然造不出真实的 TRANSFER 需求;本次修复只在"已经存在一条 TRANSFER 需求/
|
||||
派车行(如通过 SQL 构造,或未来开关打开后)"的前提下起作用
|
||||
|
||||
---
|
||||
|
||||
## 六.5 枚举(本次不新增错误码,以下为本次行为直接相关的既有错误码)
|
||||
|
||||
| 错误码 | 常量名 | 文案 | 触发位置 |
|
||||
|--------|--------|------|----------|
|
||||
| 605905 | `REQUIREMENT_VERSION_EXPIRED` | 需求版本过期 | `assertRequirementPreflightVersion`(`AssignmentService.java:3567-3583`),`POST /requirements/{id}/confirm` 专属预检门禁;同码也是内部作业端点 `refinalizeFinalSnapshot`(`:13096-13098`)的身份不一致分支,见「六、边界行为」 |
|
||||
| 605041 | `FINAL_CONFIRMATION_BASELINE_MISMATCH` | 订单行程或用车派单已变化,请按逐日差异处理后重试 | `assertFinalConfirmationBaseline`(`AssignmentService.java:4644` 起),`POST /{assignmentId}/confirm`、`POST /{assignmentId}/change` 及 `POST /requirements/{id}/confirm` 内部循环共用 |
|
||||
|
||||
> ⚠️ **Step2 canonical 快照(`POST /admin/fleet/assignments/candidates` 的 `canonicalSnapshot`
|
||||
> 字段)没有对应错误码**——它的身份不一致分支(`identityConsistent` 判 false)走的是
|
||||
> `return null` + `log.warn`,不抛任何 `IErrorCode`。上表只覆盖会抛错误码的场景,`canonicalSnapshot`
|
||||
> 为 `null` 的排查请走「三、接口详情」第 4 条,不要在这张表里找它的错误码——它没有。
|
||||
|
||||
**`dailyDifferences[].differenceType` 允许值**(既有枚举,本次未新增,仅在 605041 场景可能
|
||||
出现):`REQUIREMENT_VERSION_MISMATCH` / `ORDER_DATE_MISMATCH` / `ITINERARY_DATE_MISMATCH` /
|
||||
`ASSIGNMENT_DATE_MISSING` / `ASSIGNMENT_DATE_EXTRA` / `HEADCOUNT_BASELINE_MISMATCH`。
|
||||
|
||||
---
|
||||
|
||||
## 六.6、修改前后对比
|
||||
|
||||
### 字段级对比
|
||||
|
||||
| 字段 | 改前 | 改后 |
|
||||
|------|------|------|
|
||||
| `OrderFleetDetailContextDTO.transferVehicleRequirement`(`hl-common-core`,fleet↔order-v3 内部 Feign 契约,前端不可见) | 不存在 | 新增可空字段,携带订单当前生效的 `kind=TRANSFER` 需求 |
|
||||
| 四个端点(confirmRequirement/confirm/change/candidates)的请求体、响应体字段 | — | **零变化**,本次不涉及任何 ReqVO/RespVO 字段增删(`canonicalSnapshot` 及其内部字段结构不变,只是不再必然为 `null`) |
|
||||
| `AssignmentService.baselineRequirementFor` 的实现 | 内联逻辑 | 委托给新抽出的 `BaselineRequirementSelector.select`(内部重构,行为等价) |
|
||||
|
||||
### 行为级对比
|
||||
|
||||
| 行为 | 改前 | 改后 |
|
||||
|------|------|------|
|
||||
| `POST /requirements/{id}/confirm` 对 `kind=TRANSFER` 需求 | 必现 605905(`assertRequirementPreflightVersion` 恒判需求已过期) | version/sha256 匹配时正常通过 |
|
||||
| `POST /{assignmentId}/confirm` 对 `kind=TRANSFER` 派车行(holding 收尾 + ASSIGNED 复核两条分支) | 必现 605041 | 基线一致时正常确认为 `assigned` |
|
||||
| `POST /{assignmentId}/change` 对 `kind=TRANSFER` 派车行 | 必现 605041 | 基线一致时正常改派 |
|
||||
| `isRequirementEligibleForReopen`(内部,两条异步补偿链路) | 对 `kind=TRANSFER` 需求恒返 `false`,重开补偿失效且无报错 | 按该需求自己的 `requirementId` 正确判定 |
|
||||
| `refinalizeFinalSnapshot`(内部作业端点) | 对 `kind=TRANSFER` 需求必现 605905,重发快照补偿失效 | 按入参 `requirementId` 正确判定 |
|
||||
| `POST /admin/fleet/assignments/candidates` 的 `canonicalSnapshot` 字段(对 `kind=TRANSFER` 需求) | **静默**恒为 `null`,不抛任何错误码 | `requirementId`/`orderId` 身份一致时返回正常快照 |
|
||||
| `kind=TRAVEL` 上述全部行为 | — | 逐字不变 |
|
||||
|
||||
---
|
||||
|
||||
## 六.7、影响评估
|
||||
|
||||
- **是否破坏向后兼容**: 否。三个端点入参/出参零变化,`OrderFleetDetailContextDTO` 只新增
|
||||
可空字段(纯增量),TRAVEL 行为逐字不变
|
||||
- **前端是否必须同步上线**: 否。本次不涉及任何前端可见的请求/响应契约变更,不需要改代码。
|
||||
仅供知悉:`18_7443_接送机用车需求分叉…` 文档里"前端本版暂缓接入 TRANSFER 派车行确认/改派"
|
||||
的限制,在这三个端点自身维度已解除;但上游 809009 写口未开放,测试环境目前仍无法通过正常
|
||||
业务流程产出可联调的 TRANSFER 数据(见「七、不影响范围」)
|
||||
- **前端 workaround 清理点**: 无(此前未要求前端做任何 workaround,只是要求暂缓接入)
|
||||
- **数据**: 无需迁移,本次零 DB 迁移
|
||||
|
||||
---
|
||||
|
||||
## 七、不影响范围
|
||||
|
||||
- **仅影响**: 管理后台车务派单弹窗——`POST /requirements/{id}/confirm`、
|
||||
`POST /{assignmentId}/confirm`、`POST /{assignmentId}/change`、
|
||||
`POST /admin/fleet/assignments/candidates` 四个既有端点对 `kind=TRANSFER`
|
||||
对象(派车行/需求/候选查询)的内部基线选取逻辑;以及一处不面向 admin 前端的内部作业端点
|
||||
`POST /internal/fleet/jobs/vehicle-assignment-snapshot/refinalize`
|
||||
- **零影响**:
|
||||
- 四个端点自身的请求体、响应体字段结构(零新增/零删除/零改名)
|
||||
- `kind=TRAVEL` 派车行/需求在这四个端点的全部行为
|
||||
- `POST /admin/fleet/assignments/batch`(批量创建)、`PUT /pickup-dropoff-config`
|
||||
(接送机配置)——两者的 `kind=TRANSFER` 基线复核缺口已由今天早些时候的 PR #7913
|
||||
单独修复(见 `18_7443_接送机用车需求分叉…` 文档),与本次修复是同一根因的两个不同修复点
|
||||
- 单笔创建派单 `POST /admin/fleet/assignments`(该端点无本次改动涉及的基线复核缺口)
|
||||
- 取消派单 `DELETE /{assignmentId}`、司机拒接 `POST /{assignmentId}/driver-reject`、软清
|
||||
`POST /{assignmentId}/soft-clear-assignment`、撤销取消 `POST /{assignmentId}/restore-cancel`、
|
||||
提前完结 `POST /{assignmentId}/early-complete`、行程短信查询/重发、一键重派推荐等其余端点
|
||||
- `fleet_assignment`/`vehicle_requirement` 数据库表结构(零迁移)
|
||||
- 上游 `PUT /v3/admin/order/{id}/vehicle-requirement` 传 `kind=TRANSFER` 的写口现状
|
||||
(809009 仍未开放,不受本次修复影响)
|
||||
- 看板列表、矩阵日订单等只读查询接口
|
||||
|
||||
---
|
||||
|
||||
## 部署清单(本单改了 hl-common-core,CODE_RULES §16.6)
|
||||
|
||||
本单在 `hl-common-core` 新增了字段(`OrderFleetDetailContextDTO.transferVehicleRequirement`)。
|
||||
按 CODE_RULES §16.6,**共享 jar 变了行为就变了,部署时全部消费方必须一起滚**,不能只滚
|
||||
`hl-fleet-service`/`hl-order-service-v3` 这两个直接改代码的服务。
|
||||
|
||||
⚠️ **消费方清单不能按 `pom.xml` 直接依赖关系查**(2026-09-18 实测教训):
|
||||
`grep -rl 'hl-common-core' */pom.xml` 的结果里 **order-v3、fleet、user、resource、
|
||||
product-v2、mp 一个都没有**——它们全部经 `hl-common-web`(本身声明 `hl-common-core` 依赖)
|
||||
传递引入,直接查 `pom.xml` 会把本单真正改动、也真正需要重启的这两个服务漏掉。
|
||||
|
||||
| 部署单位 | 与 `hl-common-core` 的依赖关系 | 是否需要本次一起滚 |
|
||||
|---|---|---|
|
||||
| hl-gateway | 直接依赖(`pom.xml` 实测命中) | 是(§16.6 全消费方一起滚) |
|
||||
| hl-user-service | 经 `hl-common-web` 传递依赖 | 是 |
|
||||
| hl-resource-service | 经 `hl-common-web` 传递依赖 | 是 |
|
||||
| hl-product-service-v2 | 经 `hl-common-web` 传递依赖 | 是 |
|
||||
| hl-order-service-v3 | 经 `hl-common-web` 传递依赖 | **是(本单直接改了这个服务的生产代码)** |
|
||||
| hl-mp-service | 经 `hl-common-web` 传递依赖 | 是 |
|
||||
| hl-fleet-service | 经 `hl-common-web` 传递依赖 | **是(本单直接改了这个服务的生产代码)** |
|
||||
| hl-finance | 直接依赖(`pom.xml` 实测命中) | 不独立部署——`packaging=jar`,无 `spring-boot-maven-plugin`,是 order-v3 的库依赖,随 order-v3 一起滚即可,不是第 8 个部署单位 |
|
||||
|
||||
⇒ **实际部署单位共 7 个**:gateway / user / resource / product-v2 / order-v3 / mp / fleet。
|
||||
部署顺序、回滚预案等具体操作步骤本文档不展开(属发布流程,不是本 changelog 的职责范围);
|
||||
这里只交付"漏了会出什么问题"的判据——`hl-common-core` 里的类是所有 7 个服务共享的同一份
|
||||
class 定义,只滚一部分服务会导致该部分服务与其余服务对 `OrderFleetDetailContextDTO` 的
|
||||
序列化/反序列化预期不一致(新滚的服务发出/接收带 `transferVehicleRequirement` 字段的
|
||||
JSON,未滚的服务用旧版本类反序列化——**Jackson 对未知字段默认静默丢弃,不会报错**,但会让
|
||||
这次修复在未滚的服务视角里"看起来没生效")。
|
||||
|
||||
---
|
||||
|
||||
## 八、测试环境已验证
|
||||
|
||||
> ⚠️ **本节如实说明:本次修复尚未通过网关/端到端验证。**
|
||||
|
||||
- 三个提交 `abd435c15`/`694e405fd`/`15c7cdd0c` 位于本地分支 `feature/7443-rest-ac`(已 rebase
|
||||
到最新 `dev-v3`),**尚未合入 `origin/dev-v3`**(2026-09-18 复核:分支落在
|
||||
`origin/dev-v3@701898e2f` 之上 3 个提交,`git log origin/dev-v3..HEAD --oneline` 精确列出
|
||||
这三个;`origin/dev-v3:hl-common/hl-common-core/.../OrderFleetDetailContextDTO.java` 实测
|
||||
确认无 `transferVehicleRequirement` 字段)
|
||||
- 2026-09-18 现场 `deploy-status.sh` 复测(合入前最后一次核对):测试环境 `hl-fleet-service`
|
||||
跑在 `dev-v3` 分支的 `cdf763de6`、`hl-order-service-v3` 跑在 `dev-v3` 分支的
|
||||
`701898e2f`(0 behind,即当前 `origin/dev-v3` 的真实 HEAD)——均**不含**本次三个提交
|
||||
- 因此本节**没有**网关请求/响应实测数据;上方「三、接口详情」的请求/响应示例是依据源码 VO
|
||||
字段结构构造的示意,不是网关捕获的原始报文,取值仅供理解结构,不代表真实业务数据
|
||||
- 代码层佐证(随三个提交一并提交,本次撰写过程中**未在本会话重新执行**,通过与否以合并前的
|
||||
CI/单测结果为准,行数据/测试数字均取自各提交的 `git show --stat` 与提交信息实测):
|
||||
- `abd435c15`(第一批,前三个端点):`AssignmentServiceTest.java` +471 行、
|
||||
`AssignmentServiceNoVehicleDeclarationTest.java` +25 行、
|
||||
`OrderFleetProviderServiceTest.java` +81 行、`RequirementServiceTest.java` +73 行
|
||||
- `694e405fd`(`refinalizeFinalSnapshot`):`AssignmentServiceTest.java` +119 行;提交信息称
|
||||
fleet 定向 626/0/0/0
|
||||
- `15c7cdd0c`(Step2 canonical 快照 + `BaselineRequirementSelector`):
|
||||
`Step2CanonicalSnapshotServiceTest.java` +59 行(新增 `BaselineRequirementSelector.java`
|
||||
+62 行为非测试代码);提交信息称 `Step2CanonicalSnapshotServiceTest` 23/0/0/0(+1),
|
||||
fleet 定向合计 714/0/0/0
|
||||
- **发布前置条件**:需先将 `feature/7443-rest-ac` 合入 `dev-v3` 并部署到测试环境(含
|
||||
`hl-common-core` 触及的全部 7 个部署单位,见上方「部署清单」),完成四个端点对
|
||||
`kind=TRANSFER` 的网关实测后,方可将本文档 `backend_status` 改为 `deployed`、
|
||||
`gateway_status` 改为 `verified` 并推送
|
||||
|
||||
---
|
||||
|
||||
## 十、相关文档
|
||||
|
||||
- Issue: [#7443](https://git.1814.love:8443/wx/HL/issues/7443) AC-24
|
||||
- PR: 尚未创建(代码见本地分支 `feature/7443-rest-ac`,三个提交
|
||||
[abd435c15](https://git.1814.love:8443/wx/HL/commit/abd435c15)(前三个端点,rebase 后哈希;
|
||||
原 `09e9d7e50` 内容相同,rebase 到 `dev-v3@701898e2f` 后哈希改变)、
|
||||
[694e405fd](https://git.1814.love:8443/wx/HL/commit/694e405fd)(`refinalizeFinalSnapshot`)、
|
||||
[15c7cdd0c](https://git.1814.love:8443/wx/HL/commit/15c7cdd0c)(Step2 canonical 快照 +
|
||||
`BaselineRequirementSelector`)——这些链接在 PR 合入前可能 404,仅作提交号留档)
|
||||
- 前序文档(本文订正其中一处表述,详见「⚠️ 关键变化」):
|
||||
`changelogs-v2/2026-09/17_7443_团期身份失败关闭与看板矩阵按团筛选-修改接口-管理后台.md`、
|
||||
`changelogs-v2/2026-09/18_7443_接送机用车需求分叉PR1派车入参新增需求类别kind-修改接口-管理后台.md`
|
||||
|
||||
## 关联 / 联系人
|
||||
|
||||
### 链接
|
||||
|
||||
- **Issue**: [#7443](https://git.1814.love:8443/wx/HL/issues/7443) AC-24
|
||||
- **PR**: 尚未创建;三个提交
|
||||
[abd435c15](https://git.1814.love:8443/wx/HL/commit/abd435c15)/
|
||||
[694e405fd](https://git.1814.love:8443/wx/HL/commit/694e405fd)/
|
||||
[15c7cdd0c](https://git.1814.love:8443/wx/HL/commit/15c7cdd0c)(本地分支
|
||||
`feature/7443-rest-ac`,已 rebase 到 `dev-v3@701898e2f`,尚未合入)
|
||||
|
||||
### 联系人
|
||||
|
||||
- **后端**: @wx
|
||||
在新工单中引用
屏蔽一个用户