Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
36 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 | 8717 | 团期读端点定制师归属校验:21 个端点新增定制师非本人团期返回 589507 | admin | wx(GIT) | 修改接口 | deployed | not_required | not_required | 2026-10-02 | dev-v3 |
团期读端点定制师归属校验:21 个端点新增 589507 拒绝码
存放目录: 二期 →
changelogs-v2/2026-10/服务: hl-order-service-v3 Issue: #8717 日期: 2026-10-02 影响范围: 管理后台团期详情页及相关弹窗的 21 个数据读端点
⚠️ 关键变化
CUSTOMIZER(定制师)角色对非本人团期的 21 个读端点,新增返回业务码 589507 的场景。 该团期属于定制师本人(存在一笔在团且非 CANCELLED 的子订单其顾问 ID 等于本人)时,返回 200 与完整数据。不属于本人时返回 HTTP 200 + code: 589507 + data: null。其他角色(管理员、超管、团期主管等)对这些端点无变化。
一、背景
#7949 授予 CUSTOMIZER 权限码 group-batch:view 用于打开自己团期的订单调整弹窗,但当时仅在 GET /{id} 与 GET /{id}/orders 两个端点补了数据级归属校验。同一团期的其余 21 个读视图端点(逐户名单、配房、行程、签单凭证等)仍缺少该校验,导致任一定制师可读全公司所有团期的客户名、联系人、已付金额等敏感信息。本次补齐这 21 个端点的归属校验,与既有两个端点采用同一口径:团期「属于」定制师当且仅当该团期存在在团(非 CANCELLED)子订单其顾问 ID 等于当前登录用户。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 需求汇总 | GET | /v3/admin/order/group-batch/{groupBatchId}/requirement-summary |
修改 | 新增 589507(定制师非本人团期) |
| 2 | 逐户订房记录 | GET | /v3/admin/order/group-batch/{groupBatchId}/requirement/hotel-households |
修改 | 新增 589507(定制师非本人团期) |
| 3 | 逐户用车记录 | GET | /v3/admin/order/group-batch/{groupBatchId}/requirement/vehicle-households |
修改 | 新增 589507(定制师非本人团期) |
| 4 | 配房方案 | GET | /v3/admin/order/group-batch/{groupBatchId}/room-plans |
修改 | 新增 589507(定制师非本人团期) |
| 5 | 酒店芯片详情 | GET | /v3/admin/order/group-batch/{groupBatchId}/chips/hotel |
修改 | 新增 589507(定制师非本人团期) |
| 6 | 用车芯片详情 | GET | /v3/admin/order/group-batch/{groupBatchId}/chips/vehicle |
修改 | 新增 589507(定制师非本人团期) |
| 7 | 导游芯片详情 | GET | /v3/admin/order/group-batch/{groupBatchId}/chips/guide |
修改 | 新增 589507(定制师非本人团期) |
| 8 | 摄影芯片详情 | GET | /v3/admin/order/group-batch/{groupBatchId}/chips/photo |
修改 | 新增 589507(定制师非本人团期) |
| 9 | 合同芯片详情 | GET | /v3/admin/order/group-batch/{groupBatchId}/chips/contract |
修改 | 新增 589507(定制师非本人团期) |
| 10 | 保险芯片详情 | GET | /v3/admin/order/group-batch/{groupBatchId}/chips/insurance |
修改 | 新增 589507(定制师非本人团期) |
| 11 | 合同看板 | GET | /v3/admin/order/group-batch/{groupBatchId}/contracts |
修改 | 新增 589507(定制师非本人团期) |
| 12 | 团级行程单打印 | GET | /v3/admin/order/group-batch/{groupBatchId}/print-itinerary |
修改 | 新增 589507(定制师非本人团期) |
| 13 | 签单凭证 | GET | /v3/admin/order/group-batch/{groupBatchId}/sign-voucher |
修改 | 新增 589507(定制师非本人团期) |
| 14 | 行程汇总 | GET | /v3/admin/order/group-batch/{groupBatchId}/itinerary |
修改 | 新增 589507(定制师非本人团期) |
| 15 | 行程节点明细 | GET | /v3/admin/order/group-batch/{groupBatchId}/itinerary/nodes/{nodeKey} |
修改 | 新增 589507(定制师非本人团期) |
| 16 | 状态流水 | GET | /v3/admin/order/group-batch/{groupBatchId}/status-logs |
修改 | 新增 589507(定制师非本人团期) |
| 17 | 物资清单 | GET | /v3/admin/order/group-batch/{groupBatchId}/supplies |
修改 | 新增 589507(定制师非本人团期) |
| 18 | 物资候选 | GET | /v3/admin/order/group-batch/{groupBatchId}/supplies/candidates |
修改 | 新增 589507(定制师非本人团期) |
| 19 | 撤团候选 | GET | /v3/admin/order/group-batch/{groupBatchId}/withdraw-candidates |
修改 | 新增 589507(定制师非本人团期) |
| 20 | 撤团预览 | GET | /v3/admin/order/group-batch/{groupBatchId}/sub-order/{orderId}/withdraw-preview |
修改 | 新增 589507(定制师非本人团期) |
| 21 | 转团候选 | GET | /v3/admin/order/group-batch/{groupBatchId}/transfer-candidates |
修改 | 新增 589507(定制师非本人团期) |
三、接口详情
公共说明:所有 21 个接口的行为变化相同。改前 CUSTOMIZER 对任意团期 ID 均返回 200。改后仅本人团期返回 200,其余返回 HTTP 200 + code: 589507 + data: null。非 CUSTOMIZER 角色(ADMIN / SUPER_ADMIN / GROUP_BATCH_MANAGER / FINANCE 等)无变化。
1. 需求汇总 GET /v3/admin/order/group-batch/{groupBatchId}/requirement-summary
VO: GroupRequirementSummaryRespVO
使用场景
团期详情页"需求"Tab 的汇总数据(酒店间数、用车数量等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 详见改前契约;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/requirement-summary
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "hotelCount": 8, "vehicleCount": 3, "totalGuests": 24 },
"success": true
}
空数据 / 降级响应
- 团期不存在:返回 589500「团期不存在」(顺序:角色码 → 归属 → 存在性)。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:CUSTOMIZER 对非本人团期(无在团子订单或顾问 ID 不匹配)请求时返回。
- 定制师本人团期:该团期下存在一笔在团(非 CANCELLED 状态)的子订单其
consultantId等于当前登录用户。 - 系统上下文:以 system 用户(无登录态)请求时放行,不返回 589507。
2. 逐户订房记录 GET /v3/admin/order/group-batch/{groupBatchId}/requirement/hotel-households
VO: GroupHotelHouseholdsRespVO
使用场景
团期详情页"需求"Tab 的逐户订房明细(客户名、订房房型、金额等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含 customerName / consultantName / remark 等;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/requirement/hotel-households
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "households": [ { "customerName": "张三", "roomType": "大床房", "nights": 3 } ] },
"success": true
}
空数据 / 降级响应
- 团期无订房需求:返回空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
- 列表可能为空:即使 CUSTOMIZER 本人团期,若无订房需求也返回空数组而非 589507。
3. 逐户用车记录 GET /v3/admin/order/group-batch/{groupBatchId}/requirement/vehicle-households
VO: GroupVehicleHouseholdsRespVO
使用场景
团期详情页"需求"Tab 的逐户用车明细(客户名、车型、备注等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含 customerName / specialTags / remark 等;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/requirement/vehicle-households
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "households": [ { "customerName": "李四", "vehicleType": "中巴", "remark": "轮椅可达" } ] },
"success": true
}
空数据 / 降级响应
- 团期无用车需求:返回空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
4. 配房方案 GET /v3/admin/order/group-batch/{groupBatchId}/room-plans
VO: GroupBatchRoomPlanDetailRespVO
使用场景
团期详情页"配房"Tab 的配房方案(酒店、房型、间数、价格等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含 hotelName / roomTypeName / travelerCount 等;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/room-plans
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "hotelName": "如家酒店", "roomType": "标准间", "travelerCount": 8 },
"success": true
}
空数据 / 降级响应
- 团期无配房数据:返回空数据或空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
5. 酒店芯片详情 GET /v3/admin/order/group-batch/{groupBatchId}/chips/hotel
VO: GroupBatchChipDetailVO
使用场景
团期详情页"芯片"弹窗中酒店芯片的详细信息(人数、供应商列表、备注等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 芯片聚合数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/chips/hotel
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "count": 3, "staffList": [], "items": [] },
"success": true
}
空数据 / 降级响应
- 团期无酒店芯片:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
6. 用车芯片详情 GET /v3/admin/order/group-batch/{groupBatchId}/chips/vehicle
VO: GroupBatchChipDetailVO
使用场景
团期详情页"芯片"弹窗中用车芯片的详细信息。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 芯片聚合数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/chips/vehicle
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "count": 1, "staffList": [], "items": [] },
"success": true
}
空数据 / 降级响应
- 团期无用车芯片:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
7. 导游芯片详情 GET /v3/admin/order/group-batch/{groupBatchId}/chips/guide
VO: GroupBatchChipDetailVO
使用场景
团期详情页"芯片"弹窗中导游芯片的详细信息。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 芯片聚合数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/chips/guide
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "count": 2, "staffList": [], "items": [] },
"success": true
}
空数据 / 降级响应
- 团期无导游芯片:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
8. 摄影芯片详情 GET /v3/admin/order/group-batch/{groupBatchId}/chips/photo
VO: GroupBatchChipDetailVO
使用场景
团期详情页"芯片"弹窗中摄影芯片的详细信息。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 芯片聚合数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/chips/photo
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "count": 1, "staffList": [], "items": [] },
"success": true
}
空数据 / 降级响应
- 团期无摄影芯片:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
9. 合同芯片详情 GET /v3/admin/order/group-batch/{groupBatchId}/chips/contract
VO: GroupBatchChipDetailVO
使用场景
团期详情页"芯片"弹窗中合同芯片的详细信息。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 芯片聚合数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/chips/contract
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "count": 1, "staffList": [], "items": [] },
"success": true
}
空数据 / 降级响应
- 团期无合同芯片:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
10. 保险芯片详情 GET /v3/admin/order/group-batch/{groupBatchId}/chips/insurance
VO: GroupBatchChipDetailVO
使用场景
团期详情页"芯片"弹窗中保险芯片的详细信息。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 芯片聚合数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/chips/insurance
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "count": 1, "staffList": [], "items": [] },
"success": true
}
空数据 / 降级响应
- 团期无保险芯片:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
11. 合同看板 GET /v3/admin/order/group-batch/{groupBatchId}/contracts
VO: GroupBatchContractBoardVO
使用场景
团期详情页"合同"Tab 的合同签署看板(签署状态、进度等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 合同看板数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/contracts
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "items": [] },
"success": true
}
空数据 / 降级响应
- 团期无合同数据:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
12. 团级行程单打印 GET /v3/admin/order/group-batch/{groupBatchId}/print-itinerary
VO: GroupPrintItineraryRespVO
使用场景
团期详情页"文档"弹窗中团级行程单的打印数据(日期、酒店、金额等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含 contactName / dayTotalAmount / totalAmount 等;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/print-itinerary
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "contactName": "王五", "totalAmount": "15000.00" },
"success": true
}
空数据 / 降级响应
- 团期无行程数据:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
13. 签单凭证 GET /v3/admin/order/group-batch/{groupBatchId}/sign-voucher
VO: GroupSignVoucherRespVO
使用场景
团期详情页"文档"弹窗中签单凭证的打印数据(联系人、电话、金额等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
| showAmount | Query | Boolean | ❌ | - | 是否显示金额 |
| scope | Query | String | ❌ | - | 凭证范围 |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含 contactPerson / contactPhone / totalAmount 等;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/sign-voucher?showAmount=true
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "contactPerson": "张三", "contactPhone": "13800138000", "totalAmount": "15000.00" },
"success": true
}
空数据 / 降级响应
- 团期无凭证数据:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
- 查询参数不变:
showAmount与scope的默认值、约束保持不变。
14. 行程汇总 GET /v3/admin/order/group-batch/{groupBatchId}/itinerary
VO: GroupBatchItineraryRespVO
使用场景
团期详情页"行程"Tab 的逐日汇总(日期、酒店、景点、金额等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含 contactName / dayTotalAmount / totalAmount 等;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/itinerary
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "days": [ { "dayNumber": 1, "hotel": "如家酒店", "dayTotalAmount": "2000.00" } ] },
"success": true
}
空数据 / 降级响应
- 团期无行程数据:返回空数据或空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
15. 行程节点明细 GET /v3/admin/order/group-batch/{groupBatchId}/itinerary/nodes/{nodeKey}
VO: GroupBatchItineraryNodeDetailVO
使用场景
团期详情页"行程"Tab 中行程节点(某天的具体景点、酒店、出发地点等)的明细信息。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
| nodeKey | Path | String | ✅ | - | 行程节点键 |
| dayNumber | Query | Integer | ❌ | - | 第几天(可选) |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 节点级行程数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/itinerary/nodes/node_001?dayNumber=1
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "nodeKey": "node_001", "location": "颐和园", "dayNumber": 1 },
"success": true
}
空数据 / 降级响应
- 节点不存在:返回空数据。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
- 路径参数:
nodeKey必填,dayNumber为可选查询参数。
16. 状态流水 GET /v3/admin/order/group-batch/{groupBatchId}/status-logs
VO: 无请求体 → List<GroupBatchStatusLogVO>
使用场景
团期详情页"概览"等区域的操作历史(谁在什么时间做了什么操作)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 状态流水数组;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/status-logs
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": [ { "operator": "李四", "operationTime": "2026-10-02 14:30", "action": "确认配房" } ],
"success": true
}
空数据 / 降级响应
- 团期无操作历史:返回空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
17. 物资清单 GET /v3/admin/order/group-batch/{groupBatchId}/supplies
VO: GroupBatchSuppliesRespVO
使用场景
团期详情页"物资"区域的清单数据(物资名称、单价、数量等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含单价等信息;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/supplies
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "supplies": [ { "name": "导游讲解", "unitPrice": "100.00" } ] },
"success": true
}
空数据 / 降级响应
- 团期无物资数据:返回空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
18. 物资候选 GET /v3/admin/order/group-batch/{groupBatchId}/supplies/candidates
VO: 无请求体 → List<SupplyCandidateVO>
使用场景
团期详情页"物资"区域添加物资时的候选物资下拉/搜索数据。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 物资候选数据;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/supplies/candidates
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": [ { "id": "2105...", "name": "导游讲解", "unitPrice": "100.00" } ],
"success": true
}
空数据 / 降级响应
- 无可选物资:返回空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
19. 撤团候选 GET /v3/admin/order/group-batch/{groupBatchId}/withdraw-candidates
VO: WithdrawCandidateVO 列表
使用场景
团期详情页"撤团"弹窗中可撤团的子订单候选列表(客户名、已付金额等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含 customerName / paidAmount 等;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/withdraw-candidates
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": [ { "orderId": "2105...", "customerName": "张三", "paidAmount": "5000.00" } ],
"success": true
}
空数据 / 降级响应
- 团期无可撤订单:返回空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
20. 撤团预览 GET /v3/admin/order/group-batch/{groupBatchId}/sub-order/{orderId}/withdraw-preview
VO: 无请求体 → WithdrawPreviewVO
使用场景
团期详情页"撤团"弹窗中选中某个子订单后,展示该订单的撤团预览数据(退款金额、涉及的应收应付等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
| orderId | Path | Long | ✅ | - | 子订单 ID |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 撤团预览数据(金额等);定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/sub-order/2105709698592440322/withdraw-preview
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": { "refundAmount": "5000.00", "hasPaymentRecord": true },
"success": true
}
空数据 / 降级响应
- 订单不存在或不属于该团期:返回空数据或错误。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。
21. 转团候选 GET /v3/admin/order/group-batch/{groupBatchId}/transfer-candidates
VO: TransferCandidateVO 列表
使用场景
团期详情页"转团"弹窗中可转入的候选团期/订单列表,支持按手机号跨团期搜索(客户名、已付金额等)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Path | Long | ✅ | - | 团期 ID |
| keyword | Query | String | ❌ | - | 搜索关键字(手机号/姓名) |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| 出参结构不变 | - | 含 customerName / paidAmount 等;定制师本人团期返回完整数据 |
请求示例
GET /v3/admin/order/group-batch/2105709698592440321/transfer-candidates?keyword=13800138000
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "成功",
"data": [ { "orderId": "2105...", "customerName": "李四", "paidAmount": "3000.00" } ],
"success": true
}
空数据 / 降级响应
- 搜索无结果或无可转订单:返回空数组。
错误响应
{
"code": 589507,
"message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)",
"data": null,
"success": false
}
业务边界
- 触发 589507:同上(#1)。本端点搜索支持跨团期,但归属校验作用在
{groupBatchId}参数上,仅限定制师本人团期可查该团期的候选。
四、契约约束与正确调用方式
- 共同变化:所有 21 个接口的请求参数、响应结构无变化,仅新增 589507 错误场景。
- CUSTOMIZER 对非本人团期:返回 HTTP 200 +
code: 589507+data: null,与其他业务错误码(如 589500)走同一套错误处理流程。 - hl-ui 现有处理:v2.1 通用请求拦截器(
src/utils/request.js的业务错误分支)对非成功业务码一律弹出后端message,没有 589507 专属分支。团期详情页头部GET /{id}对非本人团期早已返回 589507(#7949),本次补的是同页兄弟端点。 - 前端无需新增代码:现有拦截器即可覆盖。如果希望定制师打开非本人团期时只提示一次、不按区块各弹一次,可以在页头
GET /{id}返回 589507 后不再拉取各区块,这属于体验优化,不影响正确性。
五、数据库行为
- 无表结构变更、无 Flyway 迁移。
- 归属校验基于已有子订单投影(
OrderService.listInGroupOrdersByGroupBatchId),仅在读路径内存查询,不涉及写入。
六、边界行为
- 系统上下文:无登录态(system user)时放行,不返回 589507。
- 其他角色:ADMIN / SUPER_ADMIN / GROUP_BATCH_MANAGER / FINANCE 等对这些端点无变化,仍返回 200。
- 团期不存在:顺序 — 角色码 → 归属 → 存在性;CUSTOMIZER 查不存在的团期返回 589507(因无在团子订单),不区分「不存在」与「不是你的」。
- 子订单全部取消 / 团期已无在团子订单:定制师名下在该团期的子订单全部变为 CANCELLED(或已移出团期)后,同一定制师再调这 21 个端点同样返回 589507;取消前是 200。测试服已实测这一翻转。
- 判据只看子订单顾问:「本人团期」= 该团期存在一笔在团、非 CANCELLED 的子订单,其
consultantId等于当前登录用户;团期本身的创建人不参与判定。 - 转团候选
transfer-candidates:校验接在该端点的判权分支内,测试服当前对定制师非本人团期返回 589507。本人团期没有可转团候选时返回200 + [],这是业务空结果,不是权限拒绝。 - 灰度与开关:除上一条外,没有灰度开关,所有环境均生效。
六.5 枚举
不新增枚举值。
六.6、修改前后对比
| 项 | 改前 | 改后 |
|---|---|---|
| CUSTOMIZER 对任意团期 ID | 返回 200 + 完整数据 | 仅本人团期 200,其余 589507 + null |
| 非 CUSTOMIZER 角色 | 返回 200 + 完整数据 | 返回 200 + 完整数据(无变化) |
| 系统上下文 | 返回 200 + 完整数据 | 返回 200 + 完整数据(无变化) |
| 定制师本人团期判据 | 仅 2 个端点检查 | 21 个端点统一检查 |
六.7、影响评估
- 是否破坏向后兼容:否。仅对 CUSTOMIZER 非本人团期新增拒绝,正常调用链路无影响。
- 前端是否必须同步上线:否。hl-ui v2.1 现有的通用业务错误拦截器会把后端返回的
message原样呈现,无需新增前端代码。 - 前端 workaround 清理点:无。定制师在团期详情页的所有操作链路已依赖
GET /{id}的 589507 拒绝(该接口已在 #7949 加过校验),本次只是补全兄弟端点的一致性。
七、不影响范围
- 仅影响:CUSTOMIZER 角色对非本人团期的这 21 个读端点。
- 零影响:其他角色、写操作端点、一期 HL(无 order-v3 标签)、其他权限码(如 LIST / FINANCE_VIEW / AUDIT_VIEW)。
- 按审批单 ID(
{approvalId})或产品批次 ID({productBatchId})取数的团期相关端点(如流团审批详情):本次没有加这道校验,对定制师不会返回 589507;行为与改前相同。 - staff/meal-info:跨前缀且数据类别不同(员工档案 vs 客户信息),本次未动。
八、测试环境已验证
测试服 order-v3 1f8b1dacd(2026-10-02)经网关实测:21 个端点,加上 GET /{id} 与 GET /{id}/orders 两个既有对照端点,共 23 个端点 × 3 种身份 = 69 组调用,全部符合预期。
- 定制师 → 非本人团期:均为
HTTP 200 + code 589507 + data null,message 为「无操作权限(当前角色未授予团期权限,或该团期不在您名下)」。 - 定制师 → 本人团期:均为
code 200。 - 管理员 → 同一非本人团期:均为
code 200。 - 定制师本人团期的子订单全部取消后复测:由 200 转为 589507。
十、相关文档
- 工单 #7949(授权 CUSTOMIZER 查看本人团期)。
- 源码
GroupBatchOwnershipGuard(新公共守卫)。
关联 / 联系人
联系人
- 后端负责人: @wx