--- schema: "hl-changelog/v2" ticket: "8767" title: "出团通知书:默认车辆信息补上团车(整团派车)的车辆与司机,releaseBlockers 新增「车辆未派司机」DRIVER 与「司机信息暂不可用」DRIVER_UNAVAILABLE" 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: "已合并 dev-v3(PR #8794,merge commit a281744c8)并部署 TEST(order-v3 与 fleet 同为 dev-v3 a281744c8),自签 token 经网关实测:团车团 defaults.bus 与车务派车逐字一致且手机全脱敏;团车有车没派司机时 releasable=false、缺项恰为 DRIVER,补派后恢复;车务服务读不到时缺项为 DRIVER_UNAVAILABLE、接口仍 200;无团车的团读数与部署前逐项一致;判权不变。纯加取值,入参与路径不变;页面按 #8746 约定用 releaseBlockers[].name 展示即可,无需新适配。" updated_at: "2026-10-04" base: "dev-v3" --- # order-v3: 出团通知书默认车辆补团车,下发缺项新增 DRIVER / DRIVER_UNAVAILABLE **服务**: hl-order-service-v3(读团车经 hl-fleet-service 内部读口,见同日 04_8767 新增接口那份) **PR**: `#8794`(已合入 `dev-v3`,合并提交 `a281744c8`) **Issue**: #8767 --- ## ⚠️ 关键变化 🔴 **`releasable` 又多一个条件**:在 #8746「阶段 + 四项资源」之上,还要求**团车(整团派车)的车辆都已派司机**。团车有车没派司机的团,`releasable` 由 `true` 变 `false`。 🟢 **`releaseBlockers` 追加两个取值**:`DRIVER`「车辆未派司机」、`DRIVER_UNAVAILABLE`「司机信息暂不可用」,排在 `PHOTOGRAPHER` 之后,二者互斥。 🟢 **默认车辆信息 `defaults.bus` 补上团车**:先列团车,再列逐户派车;格式仍是「车型 车牌 司机 姓名 脱敏手机」。 🟢 入参、路径、判权、错误码全部不变;保存仍然不卡下发门。 --- ## 一、背景 #8746 给出团通知书加了「下发门缺项」和「默认车辆带司机」,但只覆盖逐户派车。团车(整团派车)的车辆与司机只在车务服务里,通知书读不到:团车团的默认车辆信息是空的,团车「排了车没排司机」也查不出来——车务那边判团车就绪的硬门不含司机,`vehicle_ready=true` 不代表司机已派。 本单让通知书向车务读团车的活跃派车,补进默认车辆信息,并把「车辆未派司机」加进下发门。 --- ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 读出团通知书 | GET | `/v3/admin/order/group-batch/:groupBatchId/docs/notice` | 修改 | `releaseBlockers` 新增 `DRIVER` / `DRIVER_UNAVAILABLE`;`releasable` 加「团车都已派司机」;`defaults.bus`(及未保存时正文 `bus`)含团车 | | 2 | 保存出团通知书 | PUT | `/v3/admin/order/group-batch/:groupBatchId/docs/notice` | 修改 | 响应同上 | --- ## 三、接口详情 **`releasable` 规则**(两个接口相同):团期状态是 待出发 / 出行中 / 待核单 / 核单中 / 已结算 之一,**且**配房、配车、配导游、配摄影四项都已完成,**且**团车的车辆都已派司机,才为 `true`。 **`releaseBlockers[]` 取值**(按下表顺序排列,`releasable=true` 时为 `[]`,从不为 `null`): | key | name | 何时出现 | |---|---|---| | `STAGE` | 团期未到待出发 | 团期状态不在上面五个之内(不变) | | `HOTEL` | 配房未完成 | 已成团且配房未完成(不变) | | `VEHICLE` | 配车未完成 | 已成团且配车未完成(不变) | | `GUIDE` | 配导游未完成 | 已成团且配导游未完成(不变) | | `PHOTOGRAPHER` | 配摄影未完成 | 已成团且配摄影未完成(不变) | | `DRIVER` | 车辆未派司机 | 🆕 已成团,且团车有车没派司机(按车务「团期配车总览」口径,已取消的派车不算) | | `DRIVER_UNAVAILABLE` | 司机信息暂不可用 | 🆕 已成团,且这次没能从车务读到团车信息(车务服务不可用或超时);稍后重读即可 | - 未成团(招募中、已流团)仍**只列 `STAGE`**,不判资源也不判司机。 - `DRIVER` 与 `VEHICLE` 各判各的:配车已完成的团照样可能缺司机。 - `DRIVER` 与 `DRIVER_UNAVAILABLE` 不会同时出现。 - 只用逐户派车(没有团车)的团不会出现 `DRIVER`:逐户派车的车一定带司机。 - 车务读不到时按「不可下发」处理:这期间所有已成团的团都会带 `DRIVER_UNAVAILABLE`,接口本身照常返回 `code=200`。 **`bus` 默认值**:先列团车,再列逐户派车,每辆车 `车型 车牌 司机 姓名 脱敏手机`。 - 团车的车型是车辆型号名,例 `丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020`。 - 同一辆车(车型 + 车牌相同)在团车和逐户派车里都出现时只列一次,司机去重合并。 - 多日换过司机用 ` / ` 并列;车与车之间用 `、`。 - 团车全程没派司机的车只有车型车牌,例 `丰田埃尔法 蒙A-E5555`。 - 车务读不到时团车部分不出现,逐户派车部分照常。 - 手机号一律脱敏;已保存的正文不会自动刷新,只有 `defaults` 是实时值。 ### 1. 读出团通知书 `GET /v3/admin/order/group-batch/:groupBatchId/docs/notice` **VO**: `GroupBatchNoticeRespVO`(入参只有路径参数)→ `Result` #### 使用场景 团期详情「出团通知书」弹窗打开时调用。按 `releasable` 置灰「打印 / 存 PDF」,`releasable=false` 时把 `releaseBlockers[].name` 列给用户看(与 #8746 相同,新取值无需单独处理)。 #### 入参字段表 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | groupBatchId | Path | Long | ✅ | 团期 ID | **不变** | #### 出参字段表 | 字段 | 类型 | 说明 | |------|------|------| | releasable | Boolean | 🔄 再加「团车都已派司机」(规则见上) | | releaseBlockers[].key | String | 🔄 新增取值 `DRIVER` / `DRIVER_UNAVAILABLE` | | releaseBlockers[].name | String | 🔄 新增「车辆未派司机」/「司机信息暂不可用」 | | bus | String | 🔄 未保存过(`saved=false`)时等于 `defaults.bus`,含团车;已保存时为保存的原文 | | defaults.bus | String | 🔄 先团车、再逐户派车,格式见上 | | 其余字段 | — | **不变** | #### 请求示例 ```http GET /v3/admin/order/group-batch/2106331639531601921/docs/notice HTTP/1.1 Authorization: Bearer <管理员 token> ``` #### 响应示例 示例:待出发、四项资源都已完成、团车两辆车里一辆没派司机,从未保存过(草稿)——取自 TEST 验收读数。 ```json { "code": 200, "message": "成功", "data": { "title": "冻干粉发短信给 · 出团通知书", "greeting": "亲爱的团友,欢迎参加本次行程!", "meetTime": "2026-11-20 08:30", "meetPlace": "", "leader": "", "bus": "丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020、丰田埃尔法 蒙A-E5555", "contacts": "", "service": "", "bring": "", "saved": false, "releasable": false, "releaseBlockers": [ { "key": "DRIVER", "name": "车辆未派司机" } ], "version": 0, "updateTime": null, "defaults": { "title": "冻干粉发短信给 · 出团通知书", "greeting": "亲爱的团友,欢迎参加本次行程!", "meetTime": "2026-11-20 08:30", "meetPlace": "", "leader": "", "bus": "丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020、丰田埃尔法 蒙A-E5555", "contacts": "", "service": "", "bring": "" } } } ``` 给那辆车派上司机后:`releasable=true`、`releaseBlockers=[]`,`bus` 变为 `丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020、丰田埃尔法 蒙A-E5555 司机 乌力吉 135****5015`。 #### 空数据 / 降级响应 - 没有团车、也没有逐户派车:`defaults.bus` 为 `""`。 - 车务服务读不到:接口仍 `code=200`;已成团的团 `releaseBlockers` 带 `DRIVER_UNAVAILABLE`、`releasable=false`;`defaults.bus` 只含逐户派车部分。形如: ```json { "code": 200, "data": { "releasable": false, "releaseBlockers": [ { "key": "DRIVER_UNAVAILABLE", "name": "司机信息暂不可用" } ] } } ``` #### 错误响应 | code | 条件 | |---|---| | `589500` | 团期不存在或已删除(不变) | | `589507` | 当前角色没有 `group-batch:docs` 权限(不变) | ```json { "code": 589507, "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", "data": null } ``` #### 业务边界 - `releasable` 只管「能否打印 / 下发」,不影响读取与保存。 - 同一个团在不同时间读,`releaseBlockers` 可能不同(车务补派司机、或车务恢复可读后会变)。 - `DRIVER_UNAVAILABLE` 是暂时状态,不代表真缺司机;重读即可。 ### 2. 保存出团通知书 `PUT /v3/admin/order/group-batch/:groupBatchId/docs/notice` **VO**: `GroupBatchNoticeSaveReqVO` → `Result` #### 使用场景 运营编辑通知书后保存。入参不变;响应与读接口同一个结构,`releasable` / `releaseBlockers` 按上面的新规则计算。 #### 入参字段表 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | groupBatchId | Path | Long | ✅ | 团期 ID | **不变** | | bus | Body | String | ✅ | ≤256 字 | **不变**;默认值含团车后可能更长,车与司机组合很多时需删减后再存 | | title / greeting / meetTime / meetPlace / leader / contacts / service / bring | Body | String | ✅ | 同 #7532 | **不变** | | expectedVersion | Body | Integer | ✅ | ≥0 | **不变**,取读接口的 `version` | #### 出参字段表 | 字段 | 类型 | 说明 | |------|------|------| | releasable / releaseBlockers | — | 🔄 同读接口 | | version | Integer | **不变**,保存后的新版本 | | 其余字段 | — | **不变** | #### 请求示例 ```json { "title": "冻干粉发短信给 · 出团通知书", "greeting": "亲爱的团友,欢迎参加本次行程!", "meetTime": "2026-11-20 08:30", "meetPlace": "海拉尔东山国际机场 T1 到达厅 3 号门", "leader": "", "bus": "丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020、丰田埃尔法 蒙A-E5555", "contacts": "", "service": "", "bring": "", "expectedVersion": 4 } ``` #### 响应示例 示例:团车一辆车没派司机时保存——保存成功、版本 4 → 5,响应同样带 `DRIVER`(保存不卡下发门)。 ```json { "code": 200, "message": "成功", "data": { "bus": "丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020、丰田埃尔法 蒙A-E5555", "meetPlace": "海拉尔东山国际机场 T1 到达厅 3 号门", "saved": true, "releasable": false, "releaseBlockers": [ { "key": "DRIVER", "name": "车辆未派司机" } ], "version": 5 } } ``` #### 空数据 / 降级响应 - 车务服务读不到时保存照常成功,响应缺项为 `DRIVER_UNAVAILABLE`。 #### 错误响应 | code | 条件 | |---|---| | `589500` | 团期不存在(不变) | | `589507` | 当前角色没有 `group-batch:docs` 权限(不变) | | `589585` | 版本冲突,请重读后再存(不变) | | `589587` | 正文含证件号形态的数字(不变) | ```json { "code": 589585, "message": "通知书已被他人修改,请刷新后重试", "data": null } ``` #### 业务边界 - 保存**不卡**下发门:缺司机、车务读不到都能保存。 - 保存成功仍在团期时间线新增「保存出团通知书(第 N 版)」(#8746 口径不变)。 --- ## 四、契约约束与正确调用方式 - 「打印 / 存 PDF」按 `releasable` 置灰,`releasable=false` 时展示 `releaseBlockers[].name`;判断用 `key`,不要用中文名。 - 按 #8746 约定「遇到不认识的 `key` 按 `name` 展示」实现的页面,本单零适配。 - 不要自己根据车辆、司机数据推算能否打印,以 `releasable` 为准。 - 看到 `DRIVER_UNAVAILABLE` 时可以提示「稍后重试」,它不是业务缺项。 --- ## 五、数据库行为 - 零表结构变更、零数据迁移。 - 读接口零写入;保存接口行为与 #8746 相同。 - 团车数据在保存前、写事务之外读取。 --- ## 六、边界行为 - 团车派车行里车已被删除、取不到车型和车牌的,不进默认车辆信息,但仍参与「是否派了司机」的判断。 - 派过司机但司机档案已删除的,视为已派司机(不报 `DRIVER`),默认车辆信息里不显示该司机。 - 车务返回的手机号本已脱敏,通知书侧再脱敏一次,不会出现明文。 ## 六.6、修改前后对比 | 场景 | 改前(#8746) | 改后 | |---|---|---| | 团车团默认车辆信息 | `""` | `丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020` | | 待出发、四项已完成、团车有车没派司机 | `releasable=true`,`[]` | `releasable=false`,`[DRIVER]` | | 同上,补派司机后 | `releasable=true` | `releasable=true`,`[]` | | 车务服务不可用 | 无影响(读不到团车) | 已成团的团带 `[DRIVER_UNAVAILABLE]`,`releasable=false` | | 只用逐户派车的团 | — | 与改前相同 | ## 六.7、影响评估 - **是否破坏向后兼容**:`releaseBlockers` 只是多了两个取值;`releasable` 在「团车缺司机」与「车务读不到」时由 `true` 变 `false`。按 `name` 通用展示的页面无需改动。 - **前端是否必须同步上线**:不需要。 - **回滚**:revert PR #8794 后重新部署 order-v3 与 fleet。 --- ## 七、不影响范围 - 两个接口的路径、入参、判权(`group-batch:docs`)、错误码:不变。 - 只用逐户派车的团:读数与改前一致(TEST 6 个团前后逐项比对一致)。 - 已保存的通知书正文:不会被改写。 - 小程序端:无影响。 --- ## 八、测试环境已验证 **环境**:TEST(`https://api.test.1814.love`) **验证时间**:2026-10-04 17:04~17:13 **构建身份**:order-v3、fleet 均部署 `dev-v3 @ a281744c8`(本单合并提交);`releaseBlockers` 出现 `DRIVER` / `DRIVER_UNAVAILABLE` 新取值只可能来自新字节,fleet 两实例新内部读口返回 200。 **身份**:自签 token 直打网关,用 TEST 真实账号 ID 配对应角色。 ### 8.1 团车团默认车辆(只读,3 个现成团车团) | 团期 | `defaults.bus`(6 次读一致) | 与车务派车推算 | |---|---|---| | T27-5637 | `坦克300 蒙P318A 司机 P3测试司机18 139****0018、别克GL8 C0927T01 司机 测B0927司机甲 199****0001` | 一致 | | T26-3963 | `丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020` | 一致 | | T26-0352 | `丰田埃尔法 蒙A-E5555 司机 乌力吉 135****5015` | 一致 | 部署前这三个团的 `defaults.bus` 都是 `""`。 ### 8.2 车辆未派司机(自建团期,待出发、四项已完成,团车两辆、一辆没派司机) | 步骤 | `releasable` | `releaseBlockers` | `defaults.bus` | |---|---|---|---| | 一辆没派司机 | `false` | `[DRIVER]` | `丰田考斯特 蒙A-K1999 司机 巴特尔 135****5020、丰田埃尔法 蒙A-E5555` | | 补派司机后 | `true` | `[]` | `… 丰田埃尔法 蒙A-E5555 司机 乌力吉 135****5015` | | 撤回司机后保存 | `false` | `[DRIVER]`(PUT 响应) | 版本 4 → 5,时间线新增「保存出团通知书(第 5 版)」 | 每步各读 6 次,读数一致。 ### 8.3 车务服务读不到 只对通知书读团车这一条调用临时压 1ms 超时(17:02~17:08,验完还原配置并核对一致):4 个团各读 6 次全部 `code=200`;已成团的团都带 `DRIVER_UNAVAILABLE`(如资源准备中的团为 `[STAGE, HOTEL, DRIVER_UNAVAILABLE]`、核单中的团为 `[HOTEL, DRIVER_UNAVAILABLE]`),`defaults.bus` 不含团车;两个实例各记录 12 条降级告警,无系统异常。 ### 8.4 只用逐户派车的团 6 个没有团车的团(资源准备中 4 个、核单中 1 个、已结算 1 个),部署前后 `releasable`、`releaseBlockers`、`bus`、`defaults.bus` 逐项一致,均未出现 `DRIVER`。 ### 8.5 判权与日志 | 调用方 | 读 | 存 | |---|---|---| | 不带 token | 网关 `401` | 网关 `401` | | 车务、财务(无 `group-batch:docs`) | `589507` | `589507`,零写入 | | 管理员、团期管理员 | `200` | `200` | 验收时间窗内 order-v3、fleet 四个实例的日志,按 4 名司机脱敏号的前三后四检索明文手机号,零命中(同窗口内本轮请求的团期号四个实例均有命中,窗口有效)。 ### 本地证据 | 项 | 读数 | |---|---| | 定向 7 类 | 125/0/0 | | order-v3 `groupbatch` + `fleet` + `archunit` 包 + 全模块架构测试(有 Docker) | 3799/0/0 | | fleet `dispatch` 包 + 红线架构测试 | 517/0/0,跳过 2(需显式开启的容器类) | | 变基到最新 `dev-v3` 后重测(定向 + 流团相关 + 上下文 IT + 全部架构测试) | 315/0/0 | ### 未覆盖 - TEST 上没有「未删除团期 + 未取消订单 + 逐户派车快照」的现成团,逐户派车与团车同车合并只由单测覆盖。 - 团车有车没派司机用临时插入的派车行模拟,车务真实排车流程未走;验完已删除。 --- ## 十、相关文档 - Issue `#8767`;PR `#8794` - 拆单来源:Issue `#8746`(下发门缺项、逐户派车带司机) - 团车读口:同日 `04_8767` 新增接口(内部)那份 - 接口文档:`docs/group/团期模块接口文档-v2.0.html` GB-ADM-081 / 082 ## 关联 / 联系人 ### 链接 - **Issue**: [#8767](https://git.1814.love/wx/HL/issues/8767) - **PR**: [#8794](https://git.1814.love/wx/HL/pulls/8794) - **Merge commit**: [a281744c8](https://git.1814.love/wx/HL/commit/a281744c8) ### 联系人 - **后端负责人**: @jw