文件
hl-api-changelog/changelogs-v2/2026-09/18_7949_定制师可读名下团期详情与子订单名单-修改接口-管理后台.md
T

14 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 7949 定制师可读名下团期的详情与子订单名单(调整订单弹窗恢复可用) admin jw(GIT) 修改接口 deployed verified not_required 团期详情与子订单名单两个读接口:CUSTOMIZER 由「一律 589507」改为「可读本人名下团期」,其余团期仍 589507;ADMIN / FINANCE / SUPER_ADMIN 行为逐字不变。589507 文案同步订正。响应结构、字段、HTTP 状态均不变,前端无需改代码——定制师的调整订单弹窗自动恢复可用。前端实证维持 not_required(hl-ui v2.1,2026-09-20):判权放宽为后端网关层放行,前端对 group-batch 无权限显隐接线(按钮码从未下发,可见即可点、589507 由拦截器兜底),详情/名单接口原样调用即可受益,零改动。 2026-09-18 dev-v3

order-v3:定制师可读名下团期的详情与子订单名单

服务: hl-order-service-v3 (端口 8086)、hl-user-service (端口 8081,权限种子) PR: #7951 Issue: #7949 日期: 2026-09-18 影响范围: 管理后台团期详情、团期子订单名单,以及团期子订单的「调整订单」弹窗


⚠️ 关键变化

  1. 定制师现在能打开团期子订单的「调整订单」弹窗了。弹窗打开时会读团期详情,该接口要求 group-batch:view,而这个权限码此前从未授予 CUSTOMIZER,于是弹窗一开就弹 589507,酒店 / 用车需求提交不了。
  2. 定制师只能读「本人名下」的团期:判据是该团期下存在 consultant_id = 当前 adminId 的在团子订单;读别人的团期仍然 589507。只授权限不加这层校验,等于让任一定制师读到全公司所有团期的详情与逐户名单。
  3. ADMIN / FINANCE / SUPER_ADMIN 行为逐字不变,连多余的查询都没有。
  4. 589507 文案订正:由「无操作权限(非团期管理员 / 非本定制师名下)」改为「无操作权限(当前角色未授予团期权限,或该团期不在您名下)」——旧文案承诺的「本定制师名下」这个判定维度当时并不存在,现在两个分支才都真实存在。
  5. 响应结构与字段零变化,前端无需改代码。

一、背景

团期子订单的住宿与用车需求由定制师提交,再由团期管理员汇总、房务 / 车务接单。定制师提不了需求,整条团期资源准备链路的起点就是断的——订单流程状态会永远停在「配房待提交需求 / 配车待提交需求」。

wx 2026-09-18 在测试环境以定制师身份操作订单时撞到,口径定案:「团期订单定制师不能改出行日期、行程,但出行人、酒店需求、用车需求还是能改的」。

根因不在调整链路上:调整订单的提交接口本来就没有权限守卫,定制师是被挡在弹窗打开这一步——GET /v3/admin/order/group-batch/{groupBatchId} 需要 group-batch:view,而 V20260831_002 的授权名单只有 ADMIN / FINANCE / SUPER_ADMIN。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 团期详情 GET /v3/admin/order/group-batch/{groupBatchId} 修改 定制师可读本人名下团期;其余团期仍 589507;文案订正
2 团期子订单名单 GET /v3/admin/order/group-batch/{groupBatchId}/orders 修改 同上,同一层归属校验

三、接口详情

1. 团期详情 GET /v3/admin/order/group-batch/{groupBatchId}

VO: Result<GroupBatchDetailRespVO>(结构与字段零变化)

使用场景

管理后台团期详情页;以及团期子订单的「调整订单」弹窗打开时的第一跳。定制师此前在这一跳被 589507 挡住,弹窗内的酒店 / 用车需求页签渲染不出来。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 雪花 ID 团期 ID(order_group_batch.group_batch_id)
Authorization Header String ✅ Bearer token 管理端登录令牌
X-Admin-Id Header Long ✅ 网关注入 受信操作人 ID,客户端传值一律忽略
X-Admin-Role Header String ✅ 网关注入 当前角色 key,判权与归属校验都按它走,不按库角色

出参

字段 类型 说明
(全部字段) — 与改动前逐字一致,本次只改判权,不改响应结构

请求示例

GET /v3/admin/order/group-batch/2100856430494973953
Authorization: Bearer <定制师 token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "groupBatchId": "2100856430494973953",
    "teamNo": "26-7060",
    "batchStatus": "RECRUITING"
  },
  "success": true
}

空数据 / 降级响应

本接口无空数据形态:团期不存在返回 589500;权限或归属不满足返回 589507。归属判定依赖在团子订单查询,查询为空即判为「不在名下」,按 589507 拒绝(失败关闭),不会降级放行。

错误响应

{
  "code": 589507,
  "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
  "data": null,
  "success": false
}
码 触发
589507 当前角色未获授 group-batch:view;或(本次新增)定制师读的团期下没有本人名下的在团子订单
589500 团期不存在

业务边界

  • 归属判据是「该团期下存在 consultant_id = 当前 adminId 的在团子订单」,在团口径 = 仅排除 CANCELLED(含 COMPLETED),软删自动过滤
  • 名下子订单退团 / 取消后,该定制师对这个团期的可见性随之消失
  • 一个团期下有多个定制师的子订单时,各自都可见
  • ADMIN / FINANCE / SUPER_ADMIN 不走归属校验,行为逐字不变
  • 判权顺序:先角色级权限码,再数据级归属;被拒时不读团期实体,不产生任何副作用
  • 非请求上下文(定时任务 / 内部调用)按系统态放行

2. 团期子订单名单 GET /v3/admin/order/group-batch/{groupBatchId}/orders

VO: Result<PageResult<GroupBatchOrderItemRespVO>>(结构与字段零变化)

使用场景

团期详情页的子订单名单(含联系人、人数、房 / 车需求摘要)。与详情同挂 group-batch:view,因此必须与详情同一层归属校验——只挡详情不挡名单,等于把同一批数据从另一个门放出去。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ 雪花 ID 团期 ID
page Query Integer ❌ ≥1,缺省 1 页码
pageSize Query Integer ❌ 缺省 20,上限 200 每页条数
includeTravelers Query Boolean ❌ 缺省 true 是否附出行人明细
includeNeeds Query Boolean ❌ 缺省 true 是否附房数 / 房型 / 特殊需求
includeCancelled Query Boolean ❌ 缺省 false 是否含已取消子订单

出参

字段 类型 说明
(全部字段) — 与改动前逐字一致

请求示例

GET /v3/admin/order/group-batch/2100856430494973953/orders?page=1&pageSize=20
Authorization: Bearer <定制师 token>

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "records": [
      {
        "orderId": "2100856430239121409",
        "orderNo": "HL20260918155619496",
        "customerName": "王有亿"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 20
  },
  "success": true
}

空数据 / 降级响应

团期下无子订单时返回 records: []、total: 0,不报错。归属校验不满足时按 589507 拒绝,不返回空列表——「看不到」与「没有」必须区分开。

错误响应

{
  "code": 589507,
  "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
  "data": null,
  "success": false
}
码 触发
589507 同接口 1
589500 团期不存在

业务边界

  • 与接口 1 同一份归属判据,同一套角色豁免
  • includeCancelled=true 只影响返回的子订单集合,不影响归属判定——归属判定恒按在团口径(已取消的单不能用来「借」可见性)

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

  • 前端无需改动:定制师登录后照常打开团期详情与调整订单弹窗即可,响应结构没有任何变化。
  • 收到 589507 时不要再按旧文案提示「非团期管理员 / 非本定制师名下」,新文案已覆盖两种成因(角色无权限 / 团期不在名下)。
  • 定制师不能通过本接口拿到别人的团期,遍历 groupBatchId 只会得到 589507。
  • 定制师仍然没有团期看板列表(GET /v3/admin/order/group-batch)与导出(.../export)权限,本次只授 group-batch:view 一个码。

五、数据库行为

  • 表结构 / 索引:零变更。
  • 数据变更:新增 hl-user-service 迁移 V20260918_005__grant_group_batch_view_to_customizer.sql,向 admin_role_permission 插入 CUSTOMIZER × group-batch:view 一行;INSERT IGNORE + 唯一键 uk_role_permission(role_id, permission_id) 保证幂等,可重复执行;按 role_key 子查询取 role_id,适配各环境角色 ID 差异。
  • 读侧:归属校验复用既有的在团子订单查询,未新增 Mapper;归团投影(一跳与回退两条通道)多带出 order_main.consultant_id 一列,未改变行过滤口径。
  • 本次两个接口仍是纯读,无任何写入。

六、边界行为

  • 权限码走 Redis 缓存(admin_permissions:v2:role:{roleKey},TTL 10 分钟):种子落库后非超管角色可能先继续收到 589507,属正常窗口期。
  • hl-user-service 与 hl-order-service-v3 必须同批部署:只滚前者则权限是纯角色级(任一定制师可读全部团期,横向越权);只滚后者则定制师仍不可用。
  • 团期不存在时,无权限的调用者收到的是 589507 而不是 589500——判权在存在性校验之前,不暴露团期是否存在。
  • 网关未注入 X-Admin-Id 时(非网关来源的请求)一律 589507,失败关闭。

六.6、修改前后对比

调用者 改前 改后
CUSTOMIZER,读本人名下团期 589507 200
CUSTOMIZER,读他人团期 589507 589507(不变)
ADMIN / FINANCE / SUPER_ADMIN 200 200(逐字不变)
589507 文案 无操作权限(非团期管理员 / 非本定制师名下) 无操作权限(当前角色未授予团期权限,或该团期不在您名下)
CUSTOMIZER 调团期看板列表 / 导出 589507 589507(不变)

六.7、影响评估

  • 前端:无需改动;定制师侧由「弹窗打不开」恢复为可用。文案变化仅影响提示文本,无需适配。
  • 权限面:新增授权仅 1 个只读码,且叠加了数据级归属校验,净暴露面是「定制师可见自己名下团期的详情与子订单名单」。
  • 回归风险:管理员 / 财务 / 超管路径未新增任何查询与判定;非请求上下文(定时任务)不受影响。
  • 已知遗留:同样挂 group-batch:view 的六芯片逐户明细等端点,在授权后对定制师一并可见,本次只对详情与子订单名单加了归属校验,后续评估是否统一收口(见工单 #7949「后续工单」第 2 条)。

七、不影响范围

  • 调整订单的提交链路(POST /v3/admin/order/{id}/adjustment/submit):一行未改,它本来就没有权限守卫。
  • 出行日期与行程的既有约束(587039 / 587041 / 587042):未削弱,实测定制师改出发日仍返回 587039。
  • 团期子订单出行人增删拦截(587036):不变。
  • group-batch:list 与 group-batch:export 的授权名单:不变。
  • 所有写接口、所有非团期域接口:不受影响。

八、测试环境已验证

部署:PR #7951 合入 dev-v3(73333427d)后,hl-order-service-v3 与 hl-user-service 一起滚到测试环境;Flyway 20260918.005 执行 success=1,执行后 CUSTOMIZER 持有的 group-batch 码恰为 group-batch:view 一个。

用例 角色 请求 改前 改后
本人名下团期详情 CUSTOMIZER(本团期定制师) GET /v3/admin/order/group-batch/2100856430494973953 589507 200
本人名下子订单名单 同上 GET .../orders 589507 200
他人团期详情 CUSTOMIZER(本团期无单) GET .../group-batch/{id} 589507 589507
他人团期子订单名单 同上 GET .../orders 589507 589507
管理员 / 财务 / 超管 ADMIN / FINANCE / SUPER_ADMIN GET .../group-batch/{id} 200 200
团期看板列表 / 导出 CUSTOMIZER GET /v3/admin/order/group-batch、.../export 589507 589507
提交酒店 + 用车需求 CUSTOMIZER POST /v3/admin/order/{id}/adjustment/submit 弹窗打不开 200,两条需求落 PENDING_REVIEW,团期配房 / 配车芯片由「待提交」变「待审核」
改出发日仍被拒 CUSTOMIZER 同上,传 schedule.departDate 587039 587039

单测:GroupBatchQueryServiceTest 69 → 77(新增 8 条覆盖归属校验四类分支);新增 CustomizerGroupBatchViewMigrationMysqlTest 6 条(真 MySQL,含幂等与「只授 view」阴性对照);OrderInfoMapperIT 28/28(断言投影真的带出 consultant_id)。全量:hl-user-service 4006 例全绿;hl-order-service-v3 11198 例,唯一失败 MapperBoundaryArchTest#non_refund_not_depend_on_refund_mapper 在干净 dev-v3 @ 701898e2f 上逐字复现,属既有问题。


十、相关文档


关联 / 联系人

  • 后端:jw
  • 前端:mmg(无需改动,仅周知 589507 文案变化)
  • 口径定案:wx(2026-09-18)