122 行
7.7 KiB
Markdown
122 行
7.7 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "8003"
|
||
title: "团期车辆共用关系:跨维度确认后成员行跟随最新派单行 + 新增每日悬挂核对任务 1045(无接口契约变更)"
|
||
consumer: "admin"
|
||
author: "jw(GIT)"
|
||
change_type: "修复"
|
||
backend_status: "deployed"
|
||
gateway_status: "verified"
|
||
frontend_status: "not_required"
|
||
frontend_owner: ""
|
||
frontend_ref: ""
|
||
target_release: ""
|
||
verified_at: ""
|
||
status_note: "本单没有新增、修改、删除任何 admin/mp 端点,请求参数与响应字段全部不变,change_type 取「修复」是按 20_7539 先例(校验器只允许 新增接口/修改接口/删除接口/修复/前端* 几类,接口三类要求逐端点模板而本单无 admin 端点可列)。唯一新增的是 Quartz 桥接用的内部端点 POST /internal/fleet/jobs/share-member-dangling-reconcile/run,只由 hl-user-service 的定时任务经 X-Internal-Token 调用,不经网关、前端不可达,故不单列后端 changelog 条目。gateway_status=verified 指共用关系确认端点 POST /admin/fleet/group-dispatch/batches/{groupBatchId}/share-groups 经测试网关实测通过(2026-09-20 在团期 2101174125761265666 上连建车、司机两个维度的关系,库内复核两组成员行均指向同一张最新派单行)。frontend_status=not_required:响应字段与结构不变,前端无需改调用;但 members[].sourceId 的取值行为变了(见第二节),任何把它缓存/固化的前端逻辑需要复核。 前端实证维持 not_required(mmg 2026-09-20):share-groups/shareGroups 全仓零命中,共用关系功能前端未接入(#7444 交接件未到件),members[].sourceId 取值行为变化零消费面;无缓存/固化该值的逻辑。"
|
||
updated_at: "2026-09-20"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# fleet: 团期车辆共用关系跨维度确认后成员行跟随最新派单行 + 每日悬挂核对任务 1045
|
||
|
||
> **服务**: hl-fleet-service(改绑与核对逻辑)/ hl-user-service(任务注册 1045)
|
||
> **PR**: [#8029](https://git.1814.love:8443/wx/HL/pulls/8029)
|
||
> **Issue**: [#8003](https://git.1814.love:8443/wx/HL/issues/8003)
|
||
> **日期**: 2026-09-20
|
||
> **影响范围**: 无对外接口变化;共用关系详情里 `members[].sourceId` 在跨维度确认后会指向最新那张派单行
|
||
|
||
---
|
||
|
||
## ⚠️ 关键变化
|
||
|
||
- **本单没有任何可调用的新接口**:admin 侧没有新增、修改、删除端点,请求参数、响应字段、枚举、路径全部不变。
|
||
- **同一批成员先后建「车维度」和「司机维度」两个共用关系时,两个关系的成员身份现在指向同一张派单行**。
|
||
此前第二次确认只更新它自己那个维度,先建的那个维度会一直指着一张已经作废的派单。
|
||
- **新增每日定时任务 1045「共用关系成员悬挂核对」**(每天 `04:10`),只巡检、只记日志,**不改任何业务数据**。
|
||
- **前端不需要改任何调用**,但要知道:`GET /admin/fleet/group-dispatch/batches/{groupBatchId}/share-groups`
|
||
返回的 `members[].sourceId` 会在成员被重新派车后换成新值,**不能把它当成稳定标识长期缓存**。
|
||
|
||
---
|
||
|
||
## 一、原先的现象
|
||
|
||
确认共用关系时,如果某个成员当前还没占着这辆共用车(或这名共用司机),后端会替它走一次改派
|
||
把它派进来。**改派是「作废旧的派车记录、生成一张新的」**,派车记录的 ID 必然换新。
|
||
|
||
一户成员可以同时在两个关系里:一个是「共用这辆车」,另一个是「共用这名司机」。
|
||
过去第二次确认只把**它自己那个维度**的成员身份更新成新的派车记录,先建的那个维度仍记着旧的那张
|
||
——而旧的那张此刻已经作废。结果是:
|
||
|
||
- 关系的成员名单里挂着一个**已经不存在的派车记录**;
|
||
- 这户真正在跑的那张派车记录,反而不在那个关系的成员名单里。
|
||
|
||
对使用者当时不可见(冲突校验会跳过已作废的记录,所以不会误判、不会报错),
|
||
但凡是按「这个关系有几个成员」计数的地方都会多算一个。
|
||
|
||
## 二、现在的行为
|
||
|
||
| 场景 | 原来 | 现在 |
|
||
|------|------|------|
|
||
| 先建车维度关系,再建司机维度关系 | 车维度成员仍指向被作废的派车记录 | 两个维度的成员都指向同一张、当前在跑的派车记录 |
|
||
| 关系详情里的 `members[].sourceId` | 可能是一个已作废的派车记录 ID | 始终是当前在跑的那张 |
|
||
| 关系的活跃成员数 | 可能把同一户算两次(旧 ID 一次、新 ID 一次) | 与真实成员数一致 |
|
||
|
||
**响应结构没有任何变化**,变的是 `members[].sourceId` 的取值:
|
||
|
||
```jsonc
|
||
// GET /admin/fleet/group-dispatch/batches/2101174125761265666/share-groups?serviceDate=2027-01-06
|
||
// 车维度关系(359966491308855296)——下面这个 sourceId 就是修复后的取值
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"data": [
|
||
{
|
||
"shareGroupId": "359966491308855296",
|
||
"resourceType": "VEHICLE",
|
||
"resourceId": "2065329519232720897",
|
||
"status": "ACTIVE",
|
||
"members": [
|
||
{ "sourceType": "GROUP_DISPATCH", "sourceId": "2101174278589190146", "requirementId": null, "orderId": null },
|
||
{ "sourceType": "ASSIGNMENT", "sourceId": "359966520803201024", "requirementId": "7330996163649609", "orderId": "2101174125723516929" }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
修复前这一格会停在 `359966492122550272`(已作废的那张),修复后是 `359966520803201024`(当前在跑的那张),
|
||
与司机维度关系里那一格完全相同。
|
||
|
||
**给前端的一句话**:`sourceId` 是「这户当前挂的那张派车记录」,会随改派变化;
|
||
要长期标识一户成员请用 `requirementId`(用车需求 ID,跨改派不变)或 `orderId`。
|
||
|
||
## 三、新增定时任务 1045「共用关系成员悬挂核对」
|
||
|
||
| 任务 | 时间 | 做什么 | 会不会改数据 |
|
||
|------|------|--------|--------------|
|
||
| 1045 共用关系成员悬挂核对 | 每天 `04:10` | 巡检全部在关系里的成员,找出那些指向**已作废/已不存在**派车记录的 | **不会**,只记日志并返回条数 |
|
||
|
||
- **只发现、不处置**:一条这样的记录,可能该改绑到新的派车记录、也可能该退出关系,
|
||
从记录本身分辨不出,自动猜错方向会把车务人工确认过的关系悄悄改掉。所以任务只把它们报出来,由人处置。
|
||
- 任务的结果在 fleet 服务日志里按关系汇总(`共用关系存在悬挂成员行: shareGroupId=... 悬挂行数=...`),
|
||
并作为返回值回给调度侧的执行日志。
|
||
- 任务不对前端暴露任何接口,前端无需感知。
|
||
|
||
## 四、测试服实测(2026-09-20)
|
||
|
||
| 项 | 实测 |
|
||
|---|---|
|
||
| 连建车、司机两个维度的关系(团期 `2101174125761265666` / `2027-01-06`) | 两次确认均 `code=200`;库内复核两个关系的成员行 `source_id` 同为 `359966520803201024`,被作废的 `359966492122550272` 上无任何在关系中的成员 |
|
||
| 定时任务 1045 | `sys_job` 已注册且 `ACTIVE`,cron `0 10 4 * * ?`;两个 fleet 实例各触发一次均 `code=200` |
|
||
| 核对结果与库读数对账 | 存量处置前 **4** → 处置 2 条后 **2** → 新建两个关系后仍 **2**(新关系零悬挂),每一次都与同口径 SQL 读数相同 |
|
||
|
||
存量:测试服清查出的历史遗留记录共 4 条,已处置 2 条(改绑到当前在跑的派车记录),
|
||
另 2 条因对应需求当日已无在途派车记录而保留待人工判断,任务会继续把它们报出来。
|
||
|
||
---
|
||
|
||
## 五、前端要不要动
|
||
|
||
**不需要**。响应结构、字段名、枚举、路径、错误码全部不变。唯一需要知悉的是第二节末尾那句:
|
||
`members[].sourceId` 不是稳定标识,不要缓存或用它做跨请求的比对,要稳定标识用 `requirementId` / `orderId`。
|