文件
hl-api-changelog/changelogs-v2/2026-09/10_7455_团期十五个端点补判权-修改接口-管理后台.md
T
Mimingguang 6fee8114b8
changelog-filename-gate / validate (push) Failing after 2s
chore(changelog): #7455 前端 no-op 回写 not_required
2026-09-10 18:01:41 +08:00

39 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 7455 团期十五个 admin 端点补判权:写口 group-batch:manage / 详情名单 view / 列表看板 list admin jw(GIT) 修改接口 deployed verified not_required mmg 2026-09-10 ⚠️ 对外行为变更。团期域十五个 admin 端点此前零判权——任意能登录后台的账号都能调,其中六个是写口(物资增改删、确认物资会推进团期阶段、保存人员配置会扇出到团内全部活跃订单、设主次报账人),读口里子订单还带逐户出行人明细。现按三层收口:物资写与人员写要 group-batch:manage,详情/子订单/物资读/人员读要 group-batch:view,列表/看板/产品选择器要 group-batch:list。三个码取自权限种子 V20260831_002 的注册描述,不是新拍的,也不新增授权种子。管理员/超管完全不受影响;财务能看不能改;定制师全部被挡(他的入口在订单侧提需求,不碰团期域端点)。前端两条必看:① 入参出参既有错误码一律未变,不需要改请求代码,只需处理新出现的 589507;② 建议按码做菜单级/按钮级预判——list 决定团期菜单可见、view 决定详情可进、manage 决定编辑按钮可点。判权在进入业务逻辑之前,被拒时零写入、不写时间线、不触发扇出(已用 TEST SQL 佐证)。TEST 上十五个端点×三种角色 45 次调用逐条取证。前端实证 no-op:15 端点请求/响应/错误码未变,唯一新增 589507 由拦截器透 message;本仓从不按权限码前端显隐(grep 零 hasPermission/v-if 按 group-batch 码),可见即可点+589507 兜底,不采纳后端「按码显隐」建议。 2026-09-10 dev-v3

团期十五个 admin 端点补判权

一、给前端的一句话

团期的列表 / 看板 / 详情 / 子订单名单 / 物资 / 人员配置这十五个端点,以前任何能登录后台的账号都能调 (一个权限都不判),现在按三层收口:看列表要 group-batch:list,看详情和名单要 group-batch:view, 改物资和人员配置要 group-batch:manage。管理员 / 超级管理员不受影响,财务能看不能改,其余角色返 589507。

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 管理员新增团期备品行 POST /v3/admin/order/group-batch/:groupBatchId/supplies 修改 补判权 group-batch:manage,其余不变
2 调整团期备品数量 PUT /v3/admin/order/group-batch/supplies/:batchSuppliesId/quantity 修改 补判权 group-batch:manage,其余不变
3 软删团期备品行 DELETE /v3/admin/order/group-batch/supplies/:batchSuppliesId 修改 补判权 group-batch:manage,其余不变
4 确认团期物资 POST /v3/admin/order/group-batch/:groupBatchId/confirm-material 修改 补判权 group-batch:manage,其余不变
5 全量保存团期人员配置 PUT /v3/admin/group-batch/:productBatchId/staff 修改 补判权 group-batch:manage,其余不变
6 设置团期报账人等级 PUT /v3/admin/group-batch/:productBatchId/staff/:staffId/reporter-rank 修改 补判权 group-batch:manage,其余不变
7 团期详情 GET /v3/admin/order/group-batch/:groupBatchId 修改 补判权 group-batch:view,其余不变
8 团期下子订单列表 GET /v3/admin/order/group-batch/:groupBatchId/orders 修改 补判权 group-batch:view,其余不变
9 查询团期备品列表 GET /v3/admin/order/group-batch/:groupBatchId/supplies 修改 补判权 group-batch:view,其余不变
10 查询备品候选 GET /v3/admin/order/group-batch/:groupBatchId/supplies/candidates 修改 补判权 group-batch:view,其余不变
11 查询团期人员配置列表 GET /v3/admin/group-batch/:productBatchId/staff 修改 补判权 group-batch:view,其余不变
12 查询团期人员候选 GET /v3/admin/group-batch/:productBatchId/staff/candidates 修改 补判权 group-batch:view,其余不变
13 团期分页列表 GET /v3/admin/order/group-batch 修改 补判权 group-batch:list,其余不变
14 团期看板列表 GET /v3/admin/order/group-batch/board 修改 补判权 group-batch:list,其余不变
15 团期控制台产品选择器 GET /v3/admin/order/group-batch/products 修改 补判权 group-batch:list,其余不变

三、接口详情

十五个端点的入参、出参、业务语义、既有错误码一律未变,唯一变化是请求进入业务逻辑前多一道权限校验。

1. 管理员新增团期备品行 POST /v3/admin/order/group-batch/:groupBatchId/supplies

VO: AddSuppliesReqVO

使用场景

团期详情「物资清单」页手工加一行备品。可从备品库选(带 suppliesResourceId),也可纯手填。

入参

字段 位置 类型 必填 约束 说明
groupBatchId path Long 是 雪花 ID,按字符串传 团期 ID
suppliesName body String 否 — 备品名称;从库选时可由服务端回填
suppliesResourceId body Long 否 — 备品库资源 ID;传了就按库里口径取计费方式与单价
unitPrice body BigDecimal 否 — 单价;不传取库价
quantity body Integer 是 非空 数量

出参

字段 类型 说明
data String 新建的备品行 ID(雪花,按字符串下发)

请求示例

POST /v3/admin/order/group-batch/2097498512387104770/supplies
Authorization: Bearer <admin token>
Content-Type: application/json

{"suppliesName":"矿泉水","quantity":20,"unitPrice":2.00}

响应示例

{ "code": 200, "message": "成功", "data": "2097963098638876675", "success": true }

空数据 / 降级响应

写口无空数据形态。备品库不可用仍报 589522,所选备品不存在或已下架仍报 589519——与本次变更无关,行为未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:manage:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时一行都不落库(已用 TEST SQL 佐证:被拒后表里查不到该行)。
  • 既有的阶段门、备品重复校验(589523)全部保留,顺序在判权之后。
  • 权限码 group-batch:manage。

2. 调整团期备品数量 PUT /v3/admin/order/group-batch/supplies/:batchSuppliesId/quantity

VO: AdjustSuppliesQuantityReqVO

使用场景

物资清单里改某一行的数量。

入参

字段 位置 类型 必填 约束 说明
batchSuppliesId path Long 是 雪花 ID 备品行 ID
quantity body Integer 是 — 新数量

出参

字段 类型 说明
data null 无返回体

请求示例

PUT /v3/admin/order/group-batch/supplies/8801/quantity
Authorization: Bearer <admin token>
Content-Type: application/json

{"quantity":30}

响应示例

{ "code": 200, "message": "成功", "data": null, "success": true }

空数据 / 降级响应

写口无空数据形态。备品行不存在仍报 589521,行为未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:manage:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时数量不被改写。
  • 行存在性校验与阶段门保留,顺序在判权之后。
  • 权限码 group-batch:manage。

3. 软删团期备品行 DELETE /v3/admin/order/group-batch/supplies/:batchSuppliesId

VO: 无请求体

使用场景

物资清单里删掉一行。软删,不物理删除。

入参

字段 位置 类型 必填 约束 说明
batchSuppliesId path Long 是 雪花 ID 备品行 ID

出参

字段 类型 说明
data null 无返回体

请求示例

DELETE /v3/admin/order/group-batch/supplies/8801
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": null, "success": true }

空数据 / 降级响应

写口无空数据形态。行不存在仍报 589521,行为未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:manage:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不软删任何行。
  • 软删语义与阶段门保留,顺序在判权之后。
  • 权限码 group-batch:manage。

4. 确认团期物资 POST /v3/admin/order/group-batch/:groupBatchId/confirm-material

VO: 无请求体

使用场景

物资备齐后点「确认物资清单」。这个动作会把团期从「物料准备中」推向「待出发」(需同时满足子订单全确认的双门)。六个写口里它的破坏力最大——它推的是团期阶段。

入参

字段 位置 类型 必填 约束 说明
groupBatchId path Long 是 雪花 ID,按字符串传 团期 ID

出参

字段 类型 说明
data null 无返回体

请求示例

POST /v3/admin/order/group-batch/2097498512387104770/confirm-material
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": null, "success": true }

空数据 / 降级响应

写口无空数据形态。双门未同时满足时状态停在「物料准备中」并照常返回成功,这是既有语义,行为未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:manage:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时团期阶段不被推进,material_confirmed 不置位,时间线不写。
  • 团期不存在仍 589500、状态不符仍 589501;顺序:先判权,再判状态。
  • 权限码 group-batch:manage。

5. 全量保存团期人员配置 PUT /v3/admin/group-batch/:productBatchId/staff

VO: BatchStaffConfigReqVO

使用场景

团期「导游 / 摄影」页整批保存人员配置。传入列表即最终状态(全量覆盖),保存成功后异步扇出到团内全部活跃订单。⚠️ 路径前缀是 /v3/admin/group-batch(不在 /order/ 下),路径变量是产品侧排期 ID。

入参

字段 位置 类型 必填 约束 说明
productBatchId path Long 是 雪花 ID;产品侧排期 ID,不是团期主键 产品侧排期 ID
staffList body Array 是 非空字段(#7377 起字段缺失一律 400;要清空请显式传 []) 人员配置列表,全量覆盖
staffList[].staffId body Long 是 — 员工 ID
staffList[].staffRole body String 是 取值域 + 资源域实际 staffType 双校验(582114) 角色位

出参

字段 类型 说明
data Object 保存后的配置快照(结构未变)

请求示例

PUT /v3/admin/group-batch/2097498511120478210/staff
Authorization: Bearer <admin token>
Content-Type: application/json

{"staffList":[{"staffId":3301,"staffRole":"GUIDE"}]}

响应示例

{ "code": 200, "message": "成功", "data": { "staffList": [] }, "success": true }

空数据 / 降级响应

显式传 staffList: [] 表示清空配置,仍是合法请求(#7377 定的语义,未改);字段缺失一律 400,也未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:manage:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时既不覆盖配置,也不触发向团内订单的扇出。
  • #7377 的 @NotNull、582114 类型校验保留,顺序在判权之后。
  • 权限码 group-batch:manage。

6. 设置团期报账人等级 PUT /v3/admin/group-batch/:productBatchId/staff/:staffId/reporter-rank

VO: SetReporterRankReqVO

使用场景

指定团期的主 / 次报账人。报账人决定核团阶段谁来记账、成本记在谁头上,不是无关紧要的标记。

入参

字段 位置 类型 必填 约束 说明
productBatchId path Long 是 雪花 ID;产品侧排期 ID,不是团期主键 产品侧排期 ID
staffId path Long 是 必须是该团期已配置的 staff 员工 ID
reporterRank body String(枚举) 是 PRIMARY / SECONDARY / NONE 报账人等级

出参

字段 类型 说明
data null 无返回体

请求示例

PUT /v3/admin/group-batch/2097498511120478210/staff/3301/reporter-rank
Authorization: Bearer <admin token>
Content-Type: application/json

{"reporterRank":"PRIMARY"}

响应示例

{ "code": 200, "message": "成功", "data": null, "success": true }

空数据 / 降级响应

写口无空数据形态。团期尚未成团仍报 589552,行为未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:manage:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时报账人一个字段都不被改动(含「设新主报账人时原主自动降级」这条连带效果)。
  • 团期内 PRIMARY / SECONDARY 各唯一的既有语义保留。
  • 权限码 group-batch:manage。

7. 团期详情 GET /v3/admin/order/group-batch/:groupBatchId

VO: GroupBatchDetailRespVO

使用场景

团期详情页主接口。出参含整团应收 / 已收 / 已预支金额、四项资源就绪位、成团门槛与报账人——比 chips/* 更该判权,而 chips/* 早就判了。

入参

字段 位置 类型 必填 约束 说明
groupBatchId path Long 是 雪花 ID,按字符串传 团期 ID

出参

字段 类型 说明
data Object 团期详情(字段结构未变)
data.totalReceivable / totalReceived Number 整团应收 / 已收(实时聚合)
data.minToForm Integer 成团门槛(户)

请求示例

GET /v3/admin/order/group-batch/2097498512387104770
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": { "groupBatchId": "2097498512387104770", "batchStatus": "RESOURCE_PREPARING" }, "success": true }

空数据 / 降级响应

读口。团期不存在仍报 589500(不是空对象),行为未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:view:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不查团期、不返回任何金额字段。
  • 团期不存在的 589500 排在判权之后。
  • ⚠️ #7376 的旁路探针 GB_DETAIL_ACL_PROBE 随本次判权落地已删除——判权之后它只会记录必然 hasView=true 的调用。
  • 权限码 group-batch:view。

8. 团期下子订单列表 GET /v3/admin/order/group-batch/:groupBatchId/orders

VO: GroupBatchOrderItemRespVO

使用场景

团期详情「子订单」页。includeTravelers=true 时带出逐户出行人明细(证件号不返回),是本批里最敏感的读口。

入参

字段 位置 类型 必填 约束 说明
groupBatchId path Long 是 雪花 ID,按字符串传 团期 ID
includeTravelers query Boolean 否 缺省 false 是否附出行人明细
includeNeeds query Boolean 否 缺省 false 是否附房数 / 房型 / 特殊需求
includeCancelled query Boolean 否 缺省 false 是否含已取消子订单

出参

字段 类型 说明
data Array 子订单列表(字段结构未变)
data[].travelers Array 出行人明细;仅 includeTravelers=true 时出现

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/orders?includeTravelers=true
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": [], "success": true }

空数据 / 降级响应

团期无活跃子订单时返回空数组,不报错——既有语义,未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:view:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时出行人明细一条都不返回。
  • 活跃集口径(缺省排除已取消)未变。
  • 权限码 group-batch:view。

9. 查询团期备品列表 GET /v3/admin/order/group-batch/:groupBatchId/supplies

VO: GroupBatchSuppliesRespVO

使用场景

团期详情「物资清单」页的列表。

入参

字段 位置 类型 必填 约束 说明
groupBatchId path Long 是 雪花 ID,按字符串传 团期 ID

出参

字段 类型 说明
data Array 备品行列表(字段结构未变)

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/supplies
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": [], "success": true }

空数据 / 降级响应

无备品行时返回空数组,不报错——既有语义,未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:view:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不查任何备品行。
  • 与写口同在一个页面,但读走 view、写走 manage:能看不等于能改。
  • 权限码 group-batch:view。

10. 查询备品候选 GET /v3/admin/order/group-batch/:groupBatchId/supplies/candidates

VO: SuppliesCandidateRespVO

使用场景

加备品行时的备品库下拉候选,支持按分类与关键字过滤。

入参

字段 位置 类型 必填 约束 说明
groupBatchId path Long 是 雪花 ID,按字符串传 团期 ID
categoryCode query String 否 — 分类过滤
keyword query String 否 #7377 起 LIKE 通配符已转义 名称关键字

出参

字段 类型 说明
data Array 候选备品列表(字段结构未变)

请求示例

GET /v3/admin/order/group-batch/2097498512387104770/supplies/candidates?keyword=水
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": [], "success": true }

空数据 / 降级响应

无匹配候选时返回空数组。搜 % 或 _ 从 #7377 起是零结果而非全库,行为本次未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:view:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不查备品库。
  • #7377 的关键字转义保留。
  • 权限码 group-batch:view。

11. 查询团期人员配置列表 GET /v3/admin/group-batch/:productBatchId/staff

VO: BatchStaffConfigRespVO

使用场景

团期「导游 / 摄影」页的配置列表,手机号脱敏(前 3 后 4)后返回。⚠️ 路径变量是产品侧排期 ID。

入参

字段 位置 类型 必填 约束 说明
productBatchId path Long 是 雪花 ID;产品侧排期 ID,不是团期主键 产品侧排期 ID

出参

字段 类型 说明
data Object 人员配置(字段结构未变,手机号脱敏)

请求示例

GET /v3/admin/group-batch/2097498511120478210/staff
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": { "staffList": [] }, "success": true }

空数据 / 降级响应

未配置人员时返回空列表,不报错——既有语义,未改。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:view:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不查人员配置。
  • 手机号脱敏规则未变。
  • 权限码 group-batch:view。

12. 查询团期人员候选 GET /v3/admin/group-batch/:productBatchId/staff/candidates

VO: StaffCandidateRespVO

使用场景

配人员时按角色位拉候选人。#7028 起勾选态按配置位收敛,assignedRole 仍带真实角色。

入参

字段 位置 类型 必填 约束 说明
productBatchId path Long 是 雪花 ID;产品侧排期 ID,不是团期主键 产品侧排期 ID
role query String 是 角色位 按角色位过滤候选人

出参

字段 类型 说明
data Array 候选人列表(字段结构未变)

请求示例

GET /v3/admin/group-batch/2097498511120478210/staff/candidates?role=GUIDE
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": [], "success": true }

空数据 / 降级响应

无候选人时返回空数组。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:view:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不查资源域候选人。
  • #7028 的勾选态收敛口径未变。
  • 权限码 group-batch:view。

13. 团期分页列表 GET /v3/admin/order/group-batch

VO: GroupBatchPageItemRespVO

使用场景

团期列表页。出参含整团已收合计(实时聚合)。

入参

字段 位置 类型 必填 约束 说明
pageNum / pageSize query Integer 否 — 分页参数
batchStatus 等筛选项 query String 否 — 既有筛选项,未变

出参

字段 类型 说明
data.records Array 团期行(字段结构未变)
data.total Number 总条数

请求示例

GET /v3/admin/order/group-batch?pageNum=1&pageSize=20
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": { "records": [], "total": 0 }, "success": true }

空数据 / 降级响应

无数据时 records 为空数组、total 为 0,不报错。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:list:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不查列表。
  • ⚠️ 走 group-batch:list 不是 view——权限种子把 GB-ADM-001 划给了 list。
  • 权限码 group-batch:list。

14. 团期看板列表 GET /v3/admin/order/group-batch/board

VO: GroupBatchBoardItemRespVO

使用场景

团期看板。以产品全班期为基底左连订单侧团期记录,返回命中 / 未命中 / 孤儿三类行。

入参

字段 位置 类型 必填 约束 说明
productId query Long 是 雪花 ID 产品 ID
scope query String 否 ONGOING / FINISHED / ALL,缺省 ALL 班期范围

出参

字段 类型 说明
data Array 看板行(字段结构未变)

请求示例

GET /v3/admin/order/group-batch/board?productId=2097498511120478210
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": [], "success": true }

空数据 / 降级响应

产品无班期时返回空数组,不报错。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:list:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不查看板。
  • scope 缺省行集与改前逐字一致(#7189),本次未动。
  • 权限码 group-batch:list。

15. 团期控制台产品选择器 GET /v3/admin/order/group-batch/products

VO: GroupBatchProductItemRespVO

使用场景

看板上游的产品下拉。返回 PUBLISHED 产品 + 有活跃订单的非 PUBLISHED 产品。

入参

字段 位置 类型 必填 约束 说明
productType query String 否 缺省不限 产品类型
keyword query String 否 — 产品名称关键词

出参

字段 类型 说明
data Array 产品列表(字段结构未变)

请求示例

GET /v3/admin/order/group-batch/products
Authorization: Bearer <admin token>

响应示例

{ "code": 200, "message": "成功", "data": [], "success": true }

空数据 / 降级响应

无匹配产品时返回空数组。

错误响应

本次新增的拒绝形态——当前角色没有 group-batch:list:

{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }

缺少或无效的 token 由网关拦截返 401。本端点不新增其它业务错误码。

业务边界

  • 判权发生在进入业务逻辑之前;权限源不可用时失败关闭按拒绝处理。
  • 拒绝时不查产品。
  • 与看板同性质,同走 list。
  • 权限码 group-batch:list。

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

  1. 前端不需要改任何请求代码。 入参、出参、既有错误码一律未变,只是多了一种失败可能。
  2. 要处理 589507。 这十五个口现在可能返 589507,按「无权限」提示即可,别当业务失败重试。
  3. 更好的做法是按钮级 / 菜单级预判:能登录后台不等于能进团期。建议按当前角色是否持有 group-batch:list 决定团期菜单可见性,group-batch:view 决定详情页可进, group-batch:manage 决定物资与人员配置的编辑按钮可见 / 置灰。
  4. 三个码是分层的,不要混用:list(列表 / 看板 / 产品选择器)→ view(详情 / 名单 / 物资读 / 人员读) → manage(物资写 / 人员写)。这个划分取自权限种子 V20260831_002 的注册描述,不是本单新拍。
  5. 雪花 ID 一律按字符串处理。
  6. ⚠️ 别把 productBatchId 当成 groupBatchId:人员配置那四个口的路径变量是产品侧排期 ID, 前缀也不在 /order/ 下。这是既有形态,本次未改。

五、数据库行为

  • 无表变更、无 Flyway、无数据迁移。
  • 三个权限码 group-batch:list / view / manage 早已存在(V20260831_002 #6902、V20260906_002 #7158), 本次不新增授权种子。
  • 拒绝路径零写入:判权在进入 Service 事务之前,被拒的请求不产生任何行变更、不写时间线、不触发扇出。 已用 TEST SQL 佐证(CUSTOMIZER 调「新增备品行」被拒后,表里查不到该行)。

六、边界行为

场景 行为
角色持有对应权限码 与改前完全一致
角色没有对应码 589507,且零副作用
缺少 / 无效 token 网关拦截返 401(未到业务层)
权限源(user-service)不可用 失败关闭 → 按无权限拒绝,不放行
团期不存在 / 状态不对 / 备品行不存在 既有错误码不变,但判权在前——无权限时先返 589507
confirm-material 被拒 团期阶段不推进、material_confirmed 不置位、时间线不写
saveConfig 被拒 配置不覆盖、扇出不触发
reporter-rank 被拒 报账人不改动,原主 / 次不降级
子订单列表被拒 出行人明细一条都不返回

六.6、修改前后对比

端点组 改前 改后
物资 3 写 + confirm-material + 人员 2 写 零判权:任意能登录后台的账号都可调 group-batch:manage
详情 / 子订单 / 物资读 2 / 人员读 2 零判权 group-batch:view
分页列表 / 看板 / 产品选择器 零判权 group-batch:list
判权位置 无 Controller 方法体第一行(进 Service 事务之前)
权限源不可用时 无判权,直接放行 失败关闭,按无权限拒绝

改前的实测证据(origin/dev-v3,用 role=CUSTOMIZER 打真实网关):这十五个口一律 200; 而同团期的 chips/*、finance、settlement/*、contracts、requirement/*、status-logs、itinerary 一律 589507。同一个 controller 包里有的加了有的没加,是漏加不是设计如此。

六.7、影响评估

TEST 库实测的授予关系:

权限码 授予角色
group-batch:list SUPER_ADMIN、ADMIN、FINANCE
group-batch:view SUPER_ADMIN、ADMIN、FINANCE
group-batch:manage SUPER_ADMIN、ADMIN

系统里没有独立的「团期管理员」角色(sys_role 共 11 个),原型所说的团期管理员就是 ADMIN。

完全不受影响:SUPER_ADMIN、ADMIN。 读得到、改不了:FINANCE——能看团期列表、详情、物资、人员配置,但不能改物资与人员配置。这是修正而非损失:改物资清单、改人员配置本来就不是财务的职责。 全部被挡:CUSTOMIZER、ROOM_MANAGER、VEHICLE_MANAGER、OPERATOR、CUSTOMER_SERVICE、MATERIAL_ADMIN、house_keeper_lead、order_console。

三条判断依据:

  1. group-batch:manage 早已在「成团」端点上跑通(#7158),list / view 也早已在统计条、导出、 六芯片、合同面板上跑通。这几个码覆盖的就是真实操作人群,本次只是把漏网的十五个口接上同一套码。
  2. 定制师本来就不该有:jw 2026-09-10 口径——定制师负责提需求,走订单侧 POST /v3/admin/order/:id/adjustment/submit;团期管理员确认后再流转到房务 / 车务。 定制师不碰团期域端点。TEST 探针日志实测印证:GB_DETAIL_ACL_PROBE 采到 roleKey=CUSTOMIZER hasView=false、SUPER_ADMIN hasView=true、FINANCE hasView=true,与种子完全一致。
  3. 房务 / 车务走自己的域:房务在 com.hulalv.house(#7322#7327),车务在 fleet(#7439#7444), 都有各自的权限体系,不依赖团期域这十五个口。

如果上线后发现某个角色确实需要:在 user-service 给该角色补对应码即可,不需要改代码。

⚠️ order_console(测试用角色)会被挡,TEST 上若有自动化脚本用它调这些口需改角色或补授权。

七、不影响范围

  • 不改任何端点的路径、入参、出参、既有错误码。
  • 不改任何业务逻辑:阶段门、双门推进、重复校验、扇出、时间线、活跃集口径全部原样保留,只是排在判权之后。
  • 无表变更、无 Flyway、无新增错误码(复用 589507)、无网关路由变更、无新增授权种子。
  • 只滚 hl-order-service-v3 一个服务。

八、测试环境已验证

TEST(api.test.1814.love)真实网关,十五个端点 × 三种角色 = 45 次调用逐条取证(2026-09-10)。 角色 token 用 dev 默认 JWT 密钥自签,打的是真实网关与真实权限源。

# 端点 权限码 CUSTOMIZER FINANCE SUPER_ADMIN
1 物资 新增行 manage 589507 589507 越过判权(589520 业务前置)
2 物资 改数量 manage 589507 589507 越过判权(589521 行不存在)
3 物资 删行 manage 589507 589507 越过判权(589521 行不存在)
4 确认物资 manage 589507 589507 越过判权(589501 状态不符)
5 人员配置 保存 manage 589507 589507 越过判权(589552 尚未成团)
6 设报账人 manage 589507 589507 越过判权(589552 尚未成团)
7 团期详情 view 589507 200 200
8 子订单(带出行人明细) view 589507 200 200
9 物资列表 view 589507 200 200
10 备品候选 view 589507 200 200
11 人员配置列表 view 589507 200 200
12 人员候选 view 589507 200 200
13 分页列表 list 589507 200 200
14 看板 list 589507 200(17 行) 200(17 行)
15 产品选择器 list 589507 200 200

放行侧怎么证明的:manage 组是写口,不能真跑(会造脏数据),改用「必然失败的业务前置」—— SUPER_ADMIN 拿到的是各自的业务错误码而不是 589507,说明请求已经越过判权层进入业务逻辑。

零写入的 SQL 佐证:CUSTOMIZER 调「新增备品行」被拒后, SELECT count(*) FROM order_batch_supplies WHERE supplies_name LIKE '#7455探针%' → 0。两轮验收各查一次,均为 0。

分层判权生效:FINANCE 在 view / list 组全部 200、在 manage 组全部 589507—— 这正是「能看不能改」的设计意图,不是巧合。

探针日志聚合(AC-1,删除探针前采集):GB_DETAIL_ACL_PROBE 采到 roleKey=CUSTOMIZER hasView=false、SUPER_ADMIN hasView=true、FINANCE hasView=true, 与权限种子 V20260831_002 的角色集完全一致。 ⚠️ 如实标注:样本是自造流量(TEST 无真实运营流量),只能证明探针工作正常与判定口径正确, 不能代表生产调用方分布;收口决策的主依据是职责链路论证(见「六.7 影响评估」第 2 条)。

回归取证(AC-11):以 SUPER_ADMIN 走完看板 → 列表 → 详情 → 子订单 → 物资 → 人员配置 一条完整路径,全部 200,团期页面主链路未被打断。

本机全量:mvn -pl hl-order-service-v3 test → Tests run: 9657, Failures: 0, Errors: 0, Skipped: 7, BUILD SUCCESS (含 MapperBoundaryArchTest 26 例、LayerEnforcementTest 5 例——跨域引用 guard 未破边界)。

十、相关文档

  • 工单:#7455(本单),前序 #7376(旁路探针,本单是它的收口)
  • 同类先例:#7316(全团需求汇总补 view)、#7411(核单共享成本补判权,本单的单测范式来自它)
  • 权限种子:V20260831_002(list / view / export,#6902)、V20260906_002(manage,#7158)
  • 契约:《团期模块接口文档 v2.0》GB-ADM-000/001/002/003/014/024/029/035/036/037

关联 / 联系人