15 KiB
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 | 7746 | 取消成团 R10 守卫修正——不需要导游/摄影的团期不再恒返回 589502 | admin | wx(GIT) | 修改接口 | deployed | verified | not_required | 2026-09-15 | 测试服 dev-v3(合入提交 6976f68fd)已取得网关调用与前后 SQL 快照证据,见工单 #7746 验收评论。frontend_status 为 pending:本变更放开了此前恒被拦的取消成团路径,若 hl-ui 按 guideReady/photographerReady 隐藏或禁用「取消成团」按钮,需同步放开,请 mmg 核实后回写。mmg 2026-09-15 核实结论:cancel-group 端点在 hl-admin 前端尚未接入(cancelGroup/cancel-group/取消成团/589502 全仓含测试零命中),更无基于 guideReady/photographerReady 原值的按钮显隐/禁用逻辑——本单对前端零影响,判 not_required。将来接 cancel-group 时按本域既定口径(可见即可点 + 589507/589502 由 request.js 拦截器透 message 兜底)实现即可。 | 2026-09-15 | dev-v3 |
order-v3: 取消成团 R10 守卫修正
存放目录:
changelogs-v2/{YYYY-MM}/(管理后台,二期 order-v3)服务: hl-order-service-v3 (端口 8083) PR: #7755 Issue: #7746 日期: 2026-09-15 影响范围: 既有端点
POST /v3/admin/order/group-batch/{groupBatchId}/cancel-group的 R10「已派单资源」判定逻辑;请求/响应结构、路径、判权码均未改
⚠️ 关键变化
🔴 不需要导游、不需要摄影的团期,改前一旦成团就再也无法取消成团(恒返回 589502),本次修复后可以正常取消。 根因:成团时的「免闸」逻辑会把 needs_guide=false/needs_photographer=false 的团期对应 guide_ready/photographer_ready 直接置 true(语义是「这一项不需要,闸门免检」),而取消成团的 R10 守卫把这两列的 true 一律当成「已派单资源」(语义是「已经有资源在准备/已派单」)——同一列被两种相反的语义共用,R10 读错了其中一种。
🟢 有权限的正常场景不变:需要导游/摄影、且真的已经配了人的团期,取消成团仍然会被拦(589502),这正是 R10 该拦的场景,行为逐字节不变。
🟡 响应结构、判权(group-batch:manage,见 #7608)、成功码全部不变。本单只改「已派单资源」这一项判定的口径,不改端点契约。
一、背景
R10 守卫是取消成团(把已成团团期打回招募中)前的硬性前置检查:「无已确认子订单 且 无已派单资源」,任一不满足即拦截。它读四个资源就绪标志位(住宿/车/导游/摄影)判断「是否已派单」。
但导游/摄影两个标志位还有另一个写口:成团时,若该团期不需要导游/摄影(needs_guide=false/needs_photographer=false),系统会直接把对应的 ready 位置为 true,含义是「这一项不需要,闸门免检」,用来避免「没有员工角色配置时四个 ready 位永远凑不齐」的死锁。
R10 直接读这两个标志位的原值,无法分辨它是「真的已经排了人」还是「不需要、被免闸置位」,于是把后者也当成「已派单」,把这类团期永久拦死——只剩流团(需审批、会退款关单,是破坏性动作)一条路。该缺陷此前被三次撞到(#7060/#7608/#7287)但一直没有独立单跟进,本单是收口。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 取消成团 | POST | /v3/admin/order/group-batch/{groupBatchId}/cancel-group |
判定逻辑修正 | R10「已派单资源」判定对导游/摄影两项只在「需要该资源」时才看就绪位 |
三、接口详情
1. 取消成团 POST /v3/admin/order/group-batch/{groupBatchId}/cancel-group
VO: 无请求体 → Result<Void>
使用场景
团期详情页「取消成团」按钮,把已成团(RESOURCE_PREPARING)的团期打回招募中(RECRUITING),同一事务内清零四个资源就绪位与物资确认位、登记 Fleet 配车释放。判权 group-batch:manage(灰度开关控制,见 #7608 changelog,本单未改)。本单只改 R10 守卫本身对导游/摄影两项就绪位的判定口径。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | 是 | 团期主订单 ID(不是产品侧排期 ID) | 不变 |
(无请求体,本单未改。)
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| data | null | 结构完全不变,Result<Void> |
请求示例
POST /v3/admin/order/group-batch/2099716954674597889/cancel-group HTTP/1.1
Authorization: Bearer {token}
(无请求体,仅 Path 参数 groupBatchId。)
响应示例
{
"code": 200,
"message": "成功",
"data": null,
"success": true
}
空数据 / 降级响应
无列表/分页语义,不存在空数据形态。灰度开关关闭时判权退化为旁路观察日志(见 #7608 changelog),本单未改该降级逻辑。
{ "code": 200, "success": true, "data": null }
错误响应
| 码 | 符号 | 触发 | 本单 |
|---|---|---|---|
| 589507 | GROUP_BATCH_PERMISSION_DENIED | 灰度开关开且无 group-batch:manage |
不变,见 #7608 |
| 589500 | GROUP_BATCH_NOT_FOUND | 团期不存在 | 不变 |
| 589501 | GROUP_BATCH_STATUS_INVALID | 团期不在 RESOURCE_PREPARING |
不变 |
| 589502 | GROUP_BATCH_CANCEL_GROUP_BLOCKED | 有已确认子订单,或住宿/车/导游/摄影任一被判定为「已派单」 | 触发条件收窄,见下 |
{
"code": 589502,
"message": "取消成团被阻塞(有已确认子订单或已派单资源)",
"data": null,
"success": false
}
业务边界
- R10 判定口径:「已派单资源」= 已确认子订单数 > 0,或住宿/车两项
ready=true,或(导游needs_guide=true且guide_ready=true),或(摄影needs_photographer=true且photographer_ready=true)。住宿/车两项当前没有免闸置位,仍直接看ready位,不受本单影响。 needs=false但管理员仍配置了导游/摄影位的团期,本单放行取消成团:导游/摄影配置保存时不看needs,一律置ready=true,这类团期的ready=1在数据列上与免闸置位无法区分。本单接受这一放行结果(wx 2026-09-15 拍板方案 A),取消后配置行本身保留在原表,不被清除。- 取消成团后重置:四个资源就绪位与物资确认位随取消成团清零;再次成团时按当时的
needs重新免闸置位——不存在绕过免闸的回退后再成团路径。 - 拒绝时零写入:判权与 R10 守卫均排在任何库写入之前,被拒的请求不改团期任何列(含
update_time),不写状态流水。 - 不在本单范围:住宿/车两项当前没有免闸置位问题;若未来「免车」等场景为车项引入类似免闸置位,需要同步修改本方法的判定,否则会以同一形态复现本缺陷(
#7441PR-2e 已引入车项免闸置位并同步处理,另见#7441changelog)。
四、契约约束与正确调用方式
正确 / 错误 调用结果对照
| 场景(团期形态) | 结果 |
|---|---|
| 不需要导游、不需要摄影,住宿/车未就绪,无已确认子订单(正确) | 200,落 RECRUITING |
| 只有一项不需要(如只不需要导游),其余按需就绪(正确) | 200,落 RECRUITING |
| 需要导游且已配置导游位(真实已派单,正确应拦) | 589502 |
| 有已确认子订单(正确应拦) | 589502,零写入 |
| 不需要导游但管理员仍手动配置了导游位(本单接受放行) | 200,落 RECRUITING,配置行保留 |
切换状态时的必要动作
前端无需改动任何请求参数——本端点入参/路径未变,判定完全由后端按团期当前 needs/ready 状态计算。前端唯一需要核实的是:若此前为了规避「不需要导摄的团期点了也白点」而对「取消成团」按钮做过基于 guideReady/photographerReady 原值的隐藏/禁用逻辑,需要同步放开或调整判断依据,否则会出现「后端已允许但前端仍不让点」的体验倒退。
五、数据库行为
本单无表结构变更、无 Flyway、无数据迁移。写行为本身不变:取消成团成功后仍是「团期状态回退 + 四个资源就绪位与物资确认位清零 + 登记配车释放」这一套既有动作;本单只改变判定这套动作能否执行的前置条件。
六、边界行为
- 未登录 → 401(网关拦截)
- 无权限(灰度开关开)→
589507(不变) - 团期不存在 →
589500(不变) - 团期非
RESOURCE_PREPARING→589501(不变) - 有已确认子订单 →
589502,零写入(不变) - 需要且已就绪的导游/摄影/住宿/车任一 →
589502,零写入(不变) - 不需要的导游/摄影(免闸置位)→ 本单起不计入「已派单」判定(变化点)
- 老数据兼容:
V20260616_001之前成团的存量团期,needs列按DEFAULT 0回填,同样落入「不需要」分支,按本单新口径放行
六.6、修改前后对比
字段级对比
本单不改任何请求/响应字段,仅改判定逻辑读取既有字段(needs_guide/needs_photographer/guide_ready/photographer_ready)的组合方式,无字段级增删。
行为级对比
| 团期形态 | 改前 | 改后 |
|---|---|---|
| 不需要导游、不需要摄影,其余条件满足 | 589502(恒拦) |
200,落 RECRUITING |
| 只不需要导游(其余同上) | 589502 |
200 |
| 只不需要摄影(其余同上) | 589502 |
200 |
| 需要导游且已配置(真实已派单) | 589502 |
589502(不变) |
| 有已确认子订单 | 589502 |
589502(不变) |
| 不需要导游但已手动配置导游位 | 589502 |
200(本单接受放行,见业务边界) |
六.7、影响评估
- 是否破坏向后兼容: 否(对已能取消成团的场景无影响);对此前被误拦的场景是放宽——这类团期从「恒不可取消成团」变为「可以取消成团」。
- 前端是否必须同步上线: 视前端现有实现而定。若前端存在基于
guideReady/photographerReady原值隐藏或禁用「取消成团」按钮的逻辑,需要同步放开;若前端本就是「可见即可点,后端兜底报错」的口径(不做前置隐藏),则零改动。本草稿未接触 hl-ui 代码库,无法从后端仓库判定该假设是否成立,需前端自行核实。 - 前端 workaround 清理点: 若前端此前为「点了也白点」的已知问题做过提示语/禁用态特殊处理,可以在确认后端已放开后清理;具体清理点需前端自查。
七、不影响范围
- 仅影响:
POST /v3/admin/order/group-batch/{groupBatchId}/cancel-group端点 R10 守卫对导游/摄影两项的判定口径。 - 零影响:
- 成团(
POST .../group)、流团、名额调整、预支、物料门复判等其余团期端点——判定口径不变(#7441PR-2e 另行为车项引入免闸置位联动,见另一份 changelog,与本单各自独立)。 - 住宿、车两项在 R10 中的判定——本单未改(车项的免闸联动归
#7441PR-2e,另案)。 - 判权机制(
group-batch:manage灰度开关)——未改,见#7608。 hl-common-*、hl-fleet-service、hl-gateway路由——本单只改hl-order-service-v3一个服务的判定逻辑,未新增路由配置。- 小程序端(
consumer: mp)——本端点为管理后台端点,小程序无影响。
- 成团(
八、测试环境已验证
取证环境:测试服 dev-v3(合并提交 6976f68fd,已在 dev-v3 主线 870610927 中)。
| 验收项 | 场景 | 结果 |
|---|---|---|
| AC-1 | needs_guide=0、needs_photographer=0,子订单均未确认,住宿/车未就绪,未配置任何导摄位 |
code=200,团期落 RECRUITING,四个 ready 位与 material_confirmed 均为 0,状态流水新增 1 行 BATCH_CANCEL_GROUP;附改前同一夹具返回 589502 的对照 |
| AC-2 | 只不需要导游(needs_photographer=1)与只不需要摄影(needs_guide=1)两个团期各测一次 |
均 code=200,落 RECRUITING |
| AC-3 | 对 AC-1 取消后的团期再次调用「成团」 | code=200,团期回到 RESOURCE_PREPARING 且 guide_ready=1、photographer_ready=1(免闸重新生效) |
| AC-4 | 反例对照:needs_guide=1 且已配置导游位(真实已派单),其余 ready=0,子订单未确认 |
589502;团期行取消前后逐列相同,状态流水新增 0 行。摄影同构反例同样 589502 |
| AC-5 | 反例对照:needs_guide=0、needs_photographer=0 但至少一户子订单已确认 |
589502,零写入 |
| AC-6 | needs_guide=0 但已保存含导游位的导摄配置(方案 A 放行场景) |
code=200,落 RECRUITING |
| AC-9 | 网关实测 AC-1/AC-3/AC-4,附请求/响应、取消前后 SQL 快照、deploy-status.sh 两行(hl-order-service-v3/hl-gateway) |
已完成 |
其余读就绪位的消费方(物资门推进、recheck-material-gate、预支闸门、合同可出判定、出发门、团期详情 / 看板展示)行为不变,由单测覆盖;本单全量测试结果见工单 #7746 验收评论。
十、相关文档
- 关联 Issue: wx/HL#7746
- 关联 PR: wx/HL#7755
- 相关工单:
#7608(取消成团判权改造,评论中记录的「AC-3 ready 位重置结构性不可观测」前提,本单合入后该前提不再成立,需#7608执行方重新判定,本单不改#7608正文)、#7060/#7287(本缺陷此前被撞到但未独立跟进的历史记录)、#7441PR-2e(车项在同一守卫上引入的另一处免闸联动,另案,见另一份 changelog)
关联 / 联系人
链接
联系人
- 后端负责人: @wx