39 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 | 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。
四、契约约束与正确调用方式
- 前端不需要改任何请求代码。 入参、出参、既有错误码一律未变,只是多了一种失败可能。
- 要处理
589507。 这十五个口现在可能返589507,按「无权限」提示即可,别当业务失败重试。 - 更好的做法是按钮级 / 菜单级预判:能登录后台不等于能进团期。建议按当前角色是否持有
group-batch:list决定团期菜单可见性,group-batch:view决定详情页可进,group-batch:manage决定物资与人员配置的编辑按钮可见 / 置灰。 - 三个码是分层的,不要混用:
list(列表 / 看板 / 产品选择器)→view(详情 / 名单 / 物资读 / 人员读) →manage(物资写 / 人员写)。这个划分取自权限种子V20260831_002的注册描述,不是本单新拍。 - 雪花 ID 一律按字符串处理。
- ⚠️ 别把
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。
三条判断依据:
group-batch:manage早已在「成团」端点上跑通(#7158),list/view也早已在统计条、导出、 六芯片、合同面板上跑通。这几个码覆盖的就是真实操作人群,本次只是把漏网的十五个口接上同一套码。- 定制师本来就不该有: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,与种子完全一致。 - 房务 / 车务走自己的域:房务在
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