文件
hl-api-changelog/changelogs-v2/2026-10/03_8746_出团通知书下发门缺项与车辆带司机-修改接口-管理后台.md
T
Mimingguang和Claude Opus 4.8 86da96e23e
changelog-filename-gate / validate (push) Failing after 2s
chore(#8746): 前端交付回写 implemented(缺项展示随 #8767 同提交 130a49ebf 落地,补漏回写)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-10-05 10:57:58 +08:00

19 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 8746 出团通知书:可下发改为「阶段 + 四项资源」并新增缺项清单 releaseBlockers,默认车辆信息带司机,保存留痕 admin jw(GIT) 修改接口 deployed verified implemented mmg 130a49ebfd326cbf083622819b036918be2a00a6 v2.1 2026-10-04 已合并 dev-v3(b90969493)并部署 TEST,自签 token 经网关实测:招募中 / 待出发 / 资源准备中 / 已流团 / 脏值逐态缺项、配房配车回落与恢复、缺资源仍可保存、默认车辆带司机且手机全脱敏、一户派车数据异常时跳过该户接口仍 200、保存留痕与撞版本不留痕、无权限角色 589507 零写入。前端待改:通知书弹窗按 releasable 置灰「打印 / 存 PDF」并展示 releaseBlockers[].name。前端已交付(2026-10-04):随 #8767 同一提交落地(该单顺手补齐本单缺项展示缺口,详见 #8767 status_note),GroupBatchNoticeModal 存 releaseBlockers+printBlockTip 按 name 列示缺项,提交 130a49ebf。 2026-10-03 dev-v3

order-v3: 出团通知书可下发判定补四项资源,新增 releaseBlockers

服务: hl-order-service-v3 PR: #8770(已合入 dev-v3,合并提交 b90969493) Issue: #8746


⚠️ 关键变化

🔴 releasable 口径变了:原来团期到「待出发」及之后就是 true;现在还要求房 / 车 / 导 / 摄四项资源全部就绪。待出发后房务或车务回落的团,releasable 会变成 false。

🟢 新增出参 releaseBlockers(GET / PUT 响应都有):不可下发时列出缺哪几项,可下发时为空数组。

🟢 默认车辆信息 defaults.bus 带上司机:每辆车「车型 车牌 司机 姓名 脱敏手机」。

🟢 入参、路径、判权、错误码全部不变;保存仍然不卡下发门。


一、背景

出团通知书「打印 / 存 PDF」按钮靠 releasable 置灰。原口径只看团期阶段:团期进入待出发前要先过「四项资源配齐」,但进入之后房务、车务回落不会把团期退回去,于是资源已经缺了的团照样能打印,页面也不知道缺什么。另外默认车辆信息只有车型和车牌,没有司机。

本单把「四项资源就绪」加进 releasable,并新增 releaseBlockers 告诉页面缺哪一项;默认车辆信息补上司机。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 读出团通知书 GET /v3/admin/order/group-batch/:groupBatchId/docs/notice 修改 releasable 新口径;新增 releaseBlockers;defaults.bus(及未保存时正文 bus)带司机
2 保存出团通知书 PUT /v3/admin/order/group-batch/:groupBatchId/docs/notice 修改 响应同上;保存成功在团期时间线新增「保存出团通知书」一条

三、接口详情

releasable 规则(两个接口相同):团期状态是 待出发 PENDING_DEPARTURE / 出行中 TRAVELLING / 待核单 PENDING_REVIEW / 核单中 REVIEWING / 已结算 SETTLED 之一,且配房、配车、配导游、配摄影四项都已完成,才为 true。

releaseBlockers[] 取值(按下表顺序排列,releasable=true 时为 [],从不为 null):

key name 何时出现
STAGE 团期未到待出发 团期状态不在上面五个之内
HOTEL 配房未完成 已成团且配房未完成
VEHICLE 配车未完成 已成团且配车未完成(整团免车算已完成)
GUIDE 配导游未完成 已成团且配导游未完成(不需要导游的团算已完成)
PHOTOGRAPHER 配摄影未完成 已成团且配摄影未完成(不需要摄影的团算已完成)
  • 未成团(招募中 RECRUITING、已流团 CANCELLED)只列 STAGE,不列资源项。
  • 已成团但未到待出发(资源准备中、物料准备中):STAGE + 缺的资源项。
  • 以后可能追加取值(团车司机,#8767)。遇到不认识的 key,按 name 展示即可。

bus 默认值格式:每辆车 车型 车牌 司机 姓名 脱敏手机,例 33 座大巴 蒙A·88888 司机 王师傅 138****8888。

  • 同一辆车多日换过司机,司机之间用 / 分隔:33 座大巴 蒙A·88888 司机 王师傅 138****1234 / 赵师傅 136****9999。
  • 车与车之间仍用 、。
  • 司机没有手机号时只有姓名;手机号一律脱敏。
  • 整团派车(团车)的团,车辆信息暂不出现在默认值里(#8767 补)。
  • 已保存的正文不会自动刷新,只有 defaults 是实时值。

1. 读出团通知书 GET /v3/admin/order/group-batch/:groupBatchId/docs/notice

VO: GroupBatchNoticeRespVO(入参只有路径参数)→ Result<GroupBatchNoticeRespVO>

使用场景

团期详情「出团通知书」弹窗打开时调用。按 releasable 置灰「打印 / 存 PDF」,releasable=false 时把 releaseBlockers[].name 列给用户看。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期 ID 不变

出参字段表

字段 类型 说明
releasable Boolean 🔄 是否允许打印 / 下发:阶段在可下发集合内且四项资源都已完成(规则见上)
releaseBlockers Object[] 🆕 不可下发的缺项,可下发时为 []
releaseBlockers[].key String 🆕 缺项编码:STAGE / HOTEL / VEHICLE / GUIDE / PHOTOGRAPHER
releaseBlockers[].name String 🆕 缺项中文名,见上表
bus String 🔄 未保存过(saved=false)时等于 defaults.bus,格式见上;已保存时为保存的原文
defaults.bus String 🔄 实时默认车辆信息,每辆车带司机,格式见上
title / greeting / meetTime / meetPlace / leader / contacts / service / bring String 不变
saved / version / updateTime / defaults 其余字段 — 不变

请求示例

GET /v3/admin/order/group-batch/2106331639531601921/docs/notice HTTP/1.1
Authorization: Bearer <管理员 token>

响应示例

示例:待出发团期配房回落、从未保存过(草稿)——releasable=false,缺项只有 HOTEL,bus 默认值带司机(缺项与车辆串取自 TEST 验收读数,两步读数拼成一个示例)。

{
  "code": 200,
  "message": "成功",
  "data": {
    "title": "冻干粉发短信给 · 出团通知书",
    "greeting": "亲爱的团友,欢迎参加本次行程!",
    "meetTime": "2026-11-20 08:30",
    "meetPlace": "",
    "leader": "",
    "bus": "mpv 蒙A-G8888 司机 阿拉坦 135****5019、suv 蒙A-E2E01 司机 宝音德力格尔 135****5009、suv 蒙P301A 司机 P3测试司机01 139****0001 / P3测试司机21 139****0021",
    "contacts": "",
    "service": "",
    "bring": "",
    "saved": false,
    "releasable": false,
    "releaseBlockers": [
      {
        "key": "HOTEL",
        "name": "配房未完成"
      }
    ],
    "version": 0,
    "updateTime": null,
    "defaults": {
      "title": "冻干粉发短信给 · 出团通知书",
      "greeting": "亲爱的团友,欢迎参加本次行程!",
      "meetTime": "2026-11-20 08:30",
      "meetPlace": "",
      "leader": "",
      "bus": "mpv 蒙A-G8888 司机 阿拉坦 135****5019、suv 蒙A-E2E01 司机 宝音德力格尔 135****5009、suv 蒙P301A 司机 P3测试司机01 139****0001 / P3测试司机21 139****0021",
      "contacts": "",
      "service": "",
      "bring": ""
    }
  }
}

四项都已完成时 releasable=true、releaseBlockers=[]。

空数据 / 降级响应

  • 团内没有逐户派车、或由团车承担:defaults.bus 为 ""。
  • 某一户的派车数据异常:跳过该户,其余户照常拼出车辆信息,接口仍返回 code=200。
  • 司机手机号取不到:该司机只显示姓名。

错误响应

code 条件
589500 团期不存在或已删除
589507 当前角色没有 group-batch:docs 权限(不变)
{
  "code": 589500,
  "message": "团期不存在",
  "data": null
}

业务边界

  • releasable 只管「能否打印 / 下发」,不影响读取与保存。
  • 招募中的团只返回 STAGE 一项,即使资源都没配。
  • 同一个团在不同时间读,releasable 与 releaseBlockers 可能不同(房务、车务回落或补齐后会变)。

2. 保存出团通知书 PUT /v3/admin/order/group-batch/:groupBatchId/docs/notice

VO: GroupBatchNoticeSaveReqVO → Result<GroupBatchNoticeRespVO>

使用场景

运营编辑通知书后保存。入参不变;响应与读接口同一个结构,同样带 releasable 与 releaseBlockers。

入参字段表

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 团期 ID 不变
title Body String ✅ ≤128 字 不变
greeting Body String ✅ ≤512 字 不变
meetTime Body String ✅ ≤64 字 不变
meetPlace Body String ✅ ≤256 字 不变
leader Body String ✅ ≤256 字 不变
bus Body String ✅ ≤256 字 不变;默认值带司机后变长,车与司机组合很多时原样保存可能超长,需删减后再存
contacts Body String ✅ ≤256 字 不变
service Body String ✅ ≤1024 字 不变
bring Body String ✅ ≤1024 字 不变
expectedVersion Body Integer ✅ ≥0 不变,取读接口的 version

出参字段表

字段 类型 说明
releasable / releaseBlockers — 🔄 / 🆕 同读接口
version Integer 不变,保存后的新版本
其余字段 — 不变

请求示例

{
  "title": "呼伦贝尔亲子研学 6 日 · 出团通知书",
  "greeting": "亲爱的团友,欢迎参加本次行程!",
  "meetTime": "2026-11-20 08:30",
  "meetPlace": "海拉尔东山国际机场 T1 到达厅 3 号门",
  "leader": "李雪梅",
  "bus": "33 座大巴 蒙A·88888 司机 王师傅 138****8888",
  "contacts": "李雪梅 139****2756",
  "service": "含 3 早 6 正餐、全程用车、景区门票",
  "bring": "防晒霜、驱蚊液、厚外套",
  "expectedVersion": 0
}

响应示例

示例:招募中团期首次保存(expectedVersion=0)——保存成功、version=1,缺项只有 STAGE(保存不卡下发门)。

{
  "code": 200,
  "message": "成功",
  "data": {
    "title": "呼伦贝尔亲子研学 6 日 · 出团通知书",
    "greeting": "亲爱的团友,欢迎参加本次行程!",
    "meetTime": "2026-11-20 08:30",
    "meetPlace": "海拉尔东山国际机场 T1 到达厅 3 号门",
    "leader": "李雪梅",
    "bus": "33 座大巴 蒙A·88888 司机 王师傅 138****8888",
    "contacts": "李雪梅 139****2756",
    "service": "含 3 早 6 正餐、全程用车、景区门票",
    "bring": "防晒霜、驱蚊液、厚外套",
    "saved": true,
    "releasable": false,
    "releaseBlockers": [
      {
        "key": "STAGE",
        "name": "团期未到待出发"
      }
    ],
    "version": 1,
    "updateTime": "2026-10-03T18:33:10",
    "defaults": {
      "title": "冻干粉发短信给 · 出团通知书",
      "greeting": "亲爱的团友,欢迎参加本次行程!",
      "meetTime": "2026-11-20 08:30",
      "meetPlace": "",
      "leader": "",
      "bus": "",
      "contacts": "",
      "service": "",
      "bring": ""
    }
  }
}

空数据 / 降级响应

  • 不涉及;保存成功即返回保存后的全量。

错误响应

code 条件
589500 团期不存在
589507 当前角色没有 group-batch:docs 权限(不变)
589585 版本冲突(别人先保存了),请重读后再存(不变)
589587 正文含证件号形态的数字(不变)
参数校验失败 字段超长或缺失(不变)
{
  "code": 589585,
  "message": "通知书已被他人修改,请刷新后重试",
  "data": null
}

业务边界

  • 保存不卡下发门:招募中、资源未齐都能保存,响应里照样带缺项。
  • 保存成功后,团期时间线(GET /v3/admin/order/group-batch/:groupBatchId/status-logs)新增一条「保存出团通知书」,内容如「保存出团通知书(第 3 版)」。保存失败(版本冲突、证件号拦截、参数校验)不新增。
  • 打印不经后端,不留痕。

四、契约约束与正确调用方式

  • 「打印 / 存 PDF」按 releasable 置灰;releasable=false 时展示 releaseBlockers[].name。判断用 key,不要用中文名。
  • 不要自己根据团期状态推算能否打印,以 releasable 为准。
  • 遇到不认识的 key(以后会加团车司机),按 name 展示。
  • 车辆信息里的司机拼在 bus 字符串里,不需要新输入框。

五、数据库行为

  • 零表结构变更、零数据迁移。
  • 读接口零写入。
  • 保存接口:正文写入不变;成功后额外在团期时间线新增一条「保存出团通知书」记录。

六、边界行为

  • 团期状态是历史脏值(不在已知状态内):releasable=false,只列 STAGE,不报错。
  • 四项资源中任何一项为空值(历史数据)按「未完成」处理。
  • 时间线记录写失败不影响保存结果。

六.6、修改前后对比

场景 改前 改后
待出发,四项都已完成 releasable=true releasable=true,releaseBlockers=[]
待出发,配房回落未完成 releasable=true(照样能打印) releasable=false,[HOTEL]
招募中 releasable=false releasable=false,[STAGE]
资源准备中,配车未完成 releasable=false releasable=false,[STAGE, VEHICLE]
默认车辆信息 33 座大巴 蒙A·88888 33 座大巴 蒙A·88888 司机 王师傅 138****8888
保存成功 时间线无记录 时间线新增「保存出团通知书(第 N 版)」

六.7、影响评估

  • 是否破坏向后兼容:releaseBlockers 是纯新增字段;releasable 在「待出发后资源回落」时由 true 变 false,旧页面会置灰按钮但看不到原因。
  • 前端是否必须同步上线:建议同步展示 releaseBlockers;不改也不会报错。
  • 回滚:revert PR #8770 后重新部署 order-v3。

七、不影响范围

  • 两个接口的路径、入参、判权(group-batch:docs)、错误码:不变。
  • 已保存的通知书正文:不会被改写。
  • 团期时间线读接口的结构:不变,只是多了一种事件「保存出团通知书」。
  • 小程序端:无影响。

八、测试环境已验证

环境:TEST(https://api.test.1814.love) 验证时间:2026-10-03 18:14~18:46 构建身份:order-v3 部署 dev-v3 @ b90969493(本单合并提交),18:08:56 完成;部署状态表 order-v3 行为 dev-v3 b90969493 ok。零写入判据:部署后连查 8 次读接口,每次响应都带 releaseBlockers 键(旧字节没有)。 身份:自签 token 直打网关,用 TEST 真实账号 ID 配对应角色。

8.1 造数

载体产品「冻干粉发短信给」上新建班期「11月20日海拉尔-额尔古纳4日团」(出发 2026-11-20),下两单(各 2 成人)进同一团期 2106331639531601921。待出发 / 资源回落用 SQL 改团期状态与四项资源完成标记模拟(与房务、车务回落的落库效果相同),每步后恢复。

8.2 下发门与缺项

团期状态 未完成项 releasable releaseBlockers
招募中 四项全未完成 false [STAGE]
待出发 无 true [](4 次读一致)
待出发 配房 false [HOTEL],恢复后回到 true / []
待出发 配车 false [VEHICLE]
资源准备中 配摄影 false [STAGE, PHOTOGRAPHER]
已流团 配房、配车 false [STAGE]
历史脏值 PENDING_TRIP — false [STAGE],接口 200

缺资源时保存照常成功(version 2 → 3,响应带 [HOTEL])。

8.3 默认车辆带司机

把真实派车数据复制到两户名下(手机号按新订单重新加密):defaults.bus 出 3 辆车、4 名司机,8 次读一致;4 个手机号均为 ddd****dddd 形态,前三后四与独立解密结果一致;同一辆车两天两名司机用「 / 」并列。两个实例在时间窗内的日志明文手机号零命中。

8.4 一户派车数据异常

两户中一户的派车数据改为不自洽:8 次读全部 code=200,bus 只含正常户的车;两个实例各记 4 条「已跳过该户」告警,无事务回滚异常。清理后 bus 回到空。

8.5 保存留痕

操作 结果
首次保存 version=1;时间线新增「保存出团通知书(第 1 版)」,操作人 jw
用旧版本号再存 589585,时间线条数与版本号不变
用新版本号再存 version=2;新增「第 2 版」

8.6 判权

调用方 读 存
不带 token 网关 401 网关 401
车务、财务(无 group-batch:docs) 589507 589507,零写入
管理员、团期管理员 200 200,版本 +1

本地证据

项 读数
定向 3 类(含 5 个内嵌类) 63/0/0
合并提交复跑 6 类 97/0/0
团期包 + archunit 包 + 全模块架构测试(有 Docker) 3851 例 5 失败 2 错误,全部在基底 d778c9a71 干净工作区逐条复现,本单零新增

未覆盖

  • TEST 上没有「待出发、逐户派车、在团户未取消」的现成团,默认车辆带司机用复制的真实派车数据验证。
  • 房务、车务回落用 SQL 模拟落库效果,真实回落业务路径未走。
  • 团车(整团派车)的车辆与司机不在本单(#8767)。

十、相关文档

  • Issue #8746;PR #8770
  • 拆出:Issue #8767(团车车辆与司机进通知书、DRIVER 缺项)
  • 前置:Issue #7532(出团通知书首版)

关联 / 联系人

链接

联系人

  • 后端负责人: @jw