changelog(7189): 团期看板以产品全班期为基底 + scope 班期范围筛选 + 页签期数 product 侧计数(PR #7219),已部署 dev-v3 网关复测 23/23 + AC-14
这个提交包含在:
@@ -0,0 +1,669 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "7189"
|
||||
title: "团期看板基底改为产品全班期(含未建团行)+ 新增班期范围 scope 筛选默认未结束 + 产品页签期数改 product 侧计数"
|
||||
consumer: "admin"
|
||||
author: "wx(GIT)"
|
||||
change_type: "修改接口"
|
||||
backend_status: "deployed"
|
||||
gateway_status: "verified"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: "2026-09-07"
|
||||
updated_at: "2026-09-07"
|
||||
base: "dev-v3"
|
||||
status_note: "后端已合并(PR #7219,合并提交 ac0ffb02dfc3aa6d1edbba2788ba2542a9cb686b)并于 2026-09-07 00:47-00:49 部署测试服 dev-v3(product-v2 + order-v3),网关复测 23/23 + AC-14 改期一致性 通过;前端需:范围下拉默认「未结束」、点后段桶自动切「全部」、未建团行(groupBatchId=null)只放「新增子订单」、summary/export 与列表同传 scope、行标题「第{batchLabel}期 {batchName}」、页签期数直接用 batchCount。"
|
||||
---
|
||||
|
||||
# 团期模块:看板以产品全班期为基底 + 班期范围 scope 筛选 + 页签期数
|
||||
|
||||
## ⚠️ 关键变化
|
||||
|
||||
- **列表基底变了(传 `productId` 时)**:GB-ADM-001 分页与 GB-ADM-009 统计条改以「产品侧全部班期 ∪ 订单侧团期」为基底,返回三类行:**命中行**(有团期)、**未建团行**(`groupBatchId=null`,产品建了班期但还没人下单)、**孤儿行**(`productBatchRemoved=true`,产品侧班期已删但团期还有活跃子订单)。改前只查 `order_group_batch`,产品建了 8 期看板只显 1 期,运营点不到「新增子订单」。
|
||||
- **新增筛选 `scope`**(四端点同名同义):`ONGOING` 未结束(返团日 ≥ 今天或未填)/ `FINISHED` 已结束 / `ALL` 全部。**缺省值按 `productId` 定**:有 `productId` → `ONGOING`;无 `productId` → `ALL`(老调用行集不变);board 恒默认 `ALL`。前端范围下拉默认「未结束」,**summary / export 必须与列表同传 scope**,否则统计条与列表对不上账。
|
||||
- **范围 ∩ 桶是严格交集**:默认 `ONGOING` 下点后段桶 `TRIP_FINISHED` / `AUDITING` / `CHECKED`(返团日必已过)会得到空列表;前端点这三个页签时**自动把范围切成「全部」**(或提示)。
|
||||
- **传 `productId` 时排序改为出发日升序**(改前 create_time 倒序),分页在内存完成,`pageSize` 仍 ≤ 100。
|
||||
- 未建团行:`batchStatus=RECRUITING`(落 `RECRUIT` 桶)、`orderCount=0`、金额 0、`chips` 六项 `TODO`;`enrolledRooms` = 产品侧占房数(**含线下占位**)、`remainRooms` = `maxRooms - 占房`(不限房 → null);新增 `productBatchStatus / productBatchStatusLabel`(产品侧售卖状态:报名中 / 即将满额 / 已满额 / 已结束 / 取消中 / 已取消,与团期九态是两套口径)。前端对 `groupBatchId=null` 的行只放「新增子订单」,不展开子订单、不做任何团期操作。
|
||||
- 命中行 `batchNo / batchName / batchLabel / departDate / endDate / enrollDeadline` 改取 product 实时值(改名改期即时生效),孤儿行回落订单快照。
|
||||
- **子订单为 0 的行 `chips` 六项固定 `TODO`,不再为 null**(含 productId 缺省路径)。
|
||||
- GB-ADM-000 产品页签 `batchCount` 改为 product 侧未删班期数(与传该 `productId` + `scope=ALL` 的列表行数一致),改前是订单侧团期数。
|
||||
|
||||
---
|
||||
|
||||
## 一、背景
|
||||
|
||||
### 现象
|
||||
|
||||
wx 2026-09-06 看测试服「团期订单」看板:产品「冻干粉发短信给」建了 8 期,看板只显 1 期(10-01,唯一有团期的班期),其余班期没有入口下单;且没有「未结束 / 已结束」筛选,历史班期与在售班期混在一起。
|
||||
|
||||
### 调用链
|
||||
|
||||
1. hl-ui `src/stores/orderV2Batch.js` `getGroupBatchPage()` → `GET /v3/admin/order/group-batch`(GB-ADM-001)→ order-v3 `GroupBatchQueryService.listPage`:`productId` 有值 → `GroupBatchMergedRowsService.listMergedRows`(Feign `GET /internal/product/group/{productId}/detail` 取产品全班期 + `order_group_batch` 该产品团期 → 合并三类行 → 内存筛选 / 出发日升序 / 内存分页);`productId` 缺省 → 原 DB 分页 + `end_date` 条件
|
||||
2. 统计条 `GET /v3/admin/order/group-batch/summary`(GB-ADM-009)→ `GroupBatchBoardStatsService.summary` 同一合并基底分桶
|
||||
3. 导出 `GET /v3/admin/order/group-batch/export`(GB-ADM-008)→ 仍以 `order_group_batch` 为基底(不含未建团行),`scope` 按 product 实时返团日过滤
|
||||
4. 产品页签 `GET /v3/admin/order/group-batch/products`(GB-ADM-000)→ Feign `GET /internal/product/group/all` 的 `batchCount`(product 侧 `countByProductIds` 一次 in 投影)
|
||||
|
||||
### 地面真相(测试服 dev-v3 ac0ffb02dfc3aa6d1edbba2788ba2542a9cb686b,2026-09-07 00:47-00:49,产品 2044306857534636034「冻干粉发短信给」,product 侧 8 期:06-04 / 07-03 / 07-10 / 07-17 / 07-24 / 07-31 已返团,10-01 有团期,12-01 未建团)
|
||||
|
||||
| 接口 | 结果 |
|
||||
|---|---|
|
||||
| 分页 `scope=ALL` | 8 行出发日升序;10-01 行 `groupBatchId` 非空 `batchLabel="7"`;其余 7 行 `groupBatchId=null` `batchStatus=RECRUITING` `chips` 六项 TODO |
|
||||
| 分页默认(=ONGOING) | 2 行(10-01、12-01);`scope=FINISHED` 6 行 |
|
||||
| summary 默认 | `RECRUIT=1 FORMED=1 其余 0 total=2`;`scope=ALL` → `total=8 RECRUIT=7 FORMED=1` |
|
||||
| products | 该产品 `batchCount=8` |
|
||||
| board | 8 行(默认 ALL),`scope=ONGOING` 2 行;改前/改后 JSON 逐字段 diff:键集合无增减(`batchLabel` 已由 #7188 先行加入),仅 10-01 行 orderCount/enrolledRooms/enrolledPeople/remainRooms 因期间新增 4 单变化 |
|
||||
| 06-04 期(线下占位 9 房 / 限 11 房,未建团) | `enrolledRooms=9 remainRooms=2` |
|
||||
|
||||
---
|
||||
|
||||
## 二、变更接口清单
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---|------|------|------|----------|------|
|
||||
| 1 | 团期看板分页(GB-ADM-001) | GET | `/v3/admin/order/group-batch` | 入参新增 + 响应新增字段 + 基底/排序变化 | 新增 `scope`;`productId` 有值时基底改合并三类行、出发日升序;`records[]` 新增 `productBatchStatus / productBatchStatusLabel / productBatchRemoved` |
|
||||
| 2 | 团期看板统计条(GB-ADM-009) | GET | `/v3/admin/order/group-batch/summary` | 入参新增 + 基底变化 | 新增 `scope`;与 GB-ADM-001 同基底,未建团行计入 `RECRUIT` |
|
||||
| 3 | 团期看板导出(GB-ADM-008) | GET | `/v3/admin/order/group-batch/export` | 入参新增 | 新增 `scope`;基底不变(不含未建团行);`productId` 场景新增 589515 |
|
||||
| 4 | 团期看板合并层列表 | GET | `/v3/admin/order/group-batch/board` | 入参新增(可选) | 新增 `scope`,缺省 `ALL`;产品班期全删时不再返回空(孤儿行照常输出) |
|
||||
| 5 | 团期产品页签(GB-ADM-000) | GET | `/v3/admin/order/group-batch/products` | 响应字段语义变化 | `batchCount` 由订单侧团期数改为 product 侧未删班期数 |
|
||||
|
||||
---
|
||||
|
||||
## 三、接口详情
|
||||
|
||||
### 1. 团期看板分页 `GET /v3/admin/order/group-batch`
|
||||
|
||||
**VO**: `GroupBatchListReqVO → Result<PageResult<GroupBatchPageItemRespVO>>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
团期看板列表;传 `productId` 时显示该产品全部班期(含未建团行),范围下拉默认「未结束」。
|
||||
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| productId | query | Long(字符串) | 否 | 雪花 ID | 有值 → 基底 = 产品全班期 ∪ 订单团期;缺省 → 只查订单侧团期(行集与改前一致) |
|
||||
| scope | query | String | 否 | ONGOING / FINISHED / ALL;非法值按缺省处理 | **新增**。班期范围。缺省:`productId` 有值 → ONGOING,缺省 → ALL |
|
||||
| opsStage | query | String | 否 | RECRUIT / FORMED / PENDING_TRIP / TRAVELLING / TRIP_FINISHED / AUDITING / CHECKED / DISBANDED | 桶筛选;与 scope 取交集;未建团行按 RECRUITING 落 RECRUIT |
|
||||
| batchStatus | query | String | 否 | 团期九态 | 未建团行按 RECRUITING 匹配 |
|
||||
| month | query | String | 否 | yyyy-MM | 出发月份(未建团行按 product 侧出发日) |
|
||||
| keyword | query | String | 否 | 已转义 | 班期编号 / 名称模糊(命中行 / 未建团行按 product 实时名) |
|
||||
| deadlineFrom / deadlineTo | query | String | 否 | yyyy-MM-dd | 报名截止日区间 |
|
||||
| page | query | Integer | 否 | 默认 1 | 页码 |
|
||||
| pageSize | query | Integer | 否 | 默认 20,最大 100 | 每页条数 |
|
||||
|
||||
#### 出参 `Result<PageResult<GroupBatchPageItemRespVO>>`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| data.records[] | Array | 团期行(`records / total / page / pageSize`);传 `productId` 时按出发日升序 |
|
||||
| data.records[].groupBatchId | String(Long) | **未建团行为 null**,前端据此只放「新增子订单」 |
|
||||
| data.records[].productBatchId / productId | String | 三类行都有值 |
|
||||
| data.records[].batchNo / batchName / batchLabel | String | 命中行 / 未建团行取 product 实时值;孤儿行取订单快照 |
|
||||
| data.records[].batchStatus / batchStatusName | String | 团期九态;未建团行固定 `RECRUITING` / 招募中 |
|
||||
| data.records[].productBatchStatus | String | **新增**。product 侧售卖状态 code:ENROLLING / NEARLY_FULL / FULL / FINISHED / CANCELLING / CANCELLED;孤儿行 null |
|
||||
| data.records[].productBatchStatusLabel | String | **新增**。上项中文:报名中 / 即将满额 / 已满额 / 已结束 / 取消中 / 已取消 |
|
||||
| data.records[].productBatchRemoved | Boolean | **新增**。孤儿行 true(product 侧班期已删) |
|
||||
| data.records[].departDate / endDate / enrollDeadline | String(yyyy-MM-dd) | 命中行 / 未建团行 product 实时;孤儿行快照 |
|
||||
| data.records[].maxRooms / enrolledRooms / remainRooms | Integer | 未建团行:`enrolledRooms` = product 占房数(含线下占位),`remainRooms` = maxRooms − 占房(不限房 null) |
|
||||
| data.records[].orderCount / receivableAmount / receivedAmount | Integer / String | 未建团行 0 / "0.00" / "0.00" |
|
||||
| data.records[].chips | Object | hotel / vehicle / guide / photographer / insurance / contract 六项;**子订单为 0 的行六项固定 TODO(不再为 null)** |
|
||||
| 其余字段 | — | 不变 |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/group-batch?productId=2044306857534636034&scope=ALL&pageSize=50 HTTP/1.1
|
||||
Host: api.test.1814.love:9443
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
实测(2026-09-07,只列本单相关字段;8 行中取命中行 10-01 与未建团行 12-01):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"records": [
|
||||
{
|
||||
"groupBatchId": "2096412454643802114",
|
||||
"productBatchId": "2052935476557328386",
|
||||
"productId": "2044306857534636034",
|
||||
"batchNo": "Q202610012052935476548939777",
|
||||
"batchName": " 没,那你",
|
||||
"batchLabel": "7",
|
||||
"batchStatus": "RESOURCE_PREPARING",
|
||||
"batchStatusName": "资源准备中",
|
||||
"productBatchStatus": "ENROLLING",
|
||||
"productBatchStatusLabel": "报名中",
|
||||
"productBatchRemoved": false,
|
||||
"departDate": "2026-10-01",
|
||||
"endDate": "2026-10-03",
|
||||
"enrollDeadline": "2026-09-30",
|
||||
"maxRooms": 8,
|
||||
"enrolledRooms": 4,
|
||||
"remainRooms": 4,
|
||||
"orderCount": 4,
|
||||
"receivableAmount": "23400.00",
|
||||
"receivedAmount": "4000.00",
|
||||
"chips": {
|
||||
"hotel": "DOING",
|
||||
"vehicle": "TODO",
|
||||
"guide": "TODO",
|
||||
"photo": "TODO",
|
||||
"contract": "TODO",
|
||||
"insurance": "TODO"
|
||||
}
|
||||
},
|
||||
{
|
||||
"groupBatchId": null,
|
||||
"productBatchId": "2096631555760807938",
|
||||
"productId": "2044306857534636034",
|
||||
"batchNo": "Q202612012096631555752419329",
|
||||
"batchName": "QA-7189-1201",
|
||||
"batchLabel": "8",
|
||||
"batchStatus": "RECRUITING",
|
||||
"batchStatusName": "招募中",
|
||||
"productBatchStatus": "ENROLLING",
|
||||
"productBatchStatusLabel": "报名中",
|
||||
"productBatchRemoved": false,
|
||||
"departDate": "2026-12-01",
|
||||
"endDate": "2026-12-03",
|
||||
"enrollDeadline": "2026-11-30",
|
||||
"maxRooms": 4,
|
||||
"enrolledRooms": 0,
|
||||
"remainRooms": 4,
|
||||
"orderCount": 0,
|
||||
"receivableAmount": "0",
|
||||
"receivedAmount": "0",
|
||||
"chips": {
|
||||
"hotel": "TODO",
|
||||
"vehicle": "TODO",
|
||||
"guide": "TODO",
|
||||
"photo": "TODO",
|
||||
"contract": "TODO",
|
||||
"insurance": "TODO"
|
||||
}
|
||||
}
|
||||
],
|
||||
"total": 8,
|
||||
"page": 1,
|
||||
"pageSize": 50
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
传 `productId` 且 product 侧无班期、订单侧也无团期 → `records=[]`;默认 `ONGOING` 下点后段桶(TRIP_FINISHED / AUDITING / CHECKED)交集为空也返回 `records=[]`,前端应自动切 `scope=ALL`。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": { "records": [], "total": 0, "page": 1, "pageSize": 20 },
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 错误响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 589515,
|
||||
"message": "获取团期产品列表失败,请稍后重试",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
`productId` 有值时依赖产品域(Feign 取全班期),产品域不可用返回 589515;`productId` 缺省不依赖产品域。另:`589507` 无操作权限。HTTP 始终 200,按 `code` 判断。
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 权限 `group-batch:view`
|
||||
- `scope` 判定用 product 实时返团日(命中 / 未建团行);孤儿行用快照;返团日未填视为未结束
|
||||
- 传 `productId` 时排序固定出发日升序(无出发日排最后),分页在内存完成
|
||||
- 未建团行 `groupBatchId=null`:不能展开子订单、不能做任何团期操作,只能「新增子订单」(深链预填 `productId` + `productBatchId`)
|
||||
|
||||
### 2. 团期看板统计条 `GET /v3/admin/order/group-batch/summary`
|
||||
|
||||
**VO**: `Result<GroupBatchSummaryVO>`(查询参数 productId / scope / month / keyword,无请求 VO)
|
||||
|
||||
#### 使用场景
|
||||
|
||||
看板顶部桶计数;**必须与列表同传 `productId / scope / month / keyword`**。
|
||||
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| productId | query | Long(字符串) | 否 | 雪花 ID | 同 GB-ADM-001 |
|
||||
| scope | query | String | 否 | ONGOING / FINISHED / ALL | **新增**。缺省规则同 GB-ADM-001 |
|
||||
| month / keyword | query | String | 否 | 同 GB-ADM-001 | 逐字同义 |
|
||||
|
||||
#### 出参 `Result<GroupBatchSummaryVO>`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| data.buckets | Object | 固定 8 键(RECRUIT / FORMED / PENDING_TRIP / TRAVELLING / TRIP_FINISHED / AUDITING / CHECKED / DISBANDED);传 `productId` 时未建团行计入 RECRUIT |
|
||||
| data.total | Integer | 8 桶之和 = 同筛选下 GB-ADM-001 的 total |
|
||||
| data.subOrderCount | Integer | 有效子订单合计(未建团行贡献 0) |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/group-batch/summary?productId=2044306857534636034 HTTP/1.1
|
||||
Host: api.test.1814.love:9443
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
实测(默认 ONGOING):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"total": 2,
|
||||
"buckets": {
|
||||
"RECRUIT": 1,
|
||||
"FORMED": 1,
|
||||
"PENDING_TRIP": 0,
|
||||
"TRAVELLING": 0,
|
||||
"TRIP_FINISHED": 0,
|
||||
"AUDITING": 0,
|
||||
"CHECKED": 0,
|
||||
"DISBANDED": 0
|
||||
},
|
||||
"subOrderCount": 4
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无命中时 8 键全 0、`total=0`,不省略键。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": { "buckets": { "RECRUIT": 0, "FORMED": 0, "PENDING_TRIP": 0, "TRAVELLING": 0, "TRIP_FINISHED": 0, "AUDITING": 0, "CHECKED": 0, "DISBANDED": 0 }, "total": 0, "subOrderCount": 0 },
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 错误响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 589515,
|
||||
"message": "获取团期产品列表失败,请稍后重试",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 桶计数不受 opsStage 影响(本接口不接受 opsStage)
|
||||
- 传 `productId` 时与 GB-ADM-001 共用同一合并基底与筛选,逐桶 = 列表按该桶筛选的 total
|
||||
|
||||
### 3. 团期看板导出 `GET /v3/admin/order/group-batch/export`
|
||||
|
||||
**VO**: CSV 附件(查询参数 productId / scope / month / keyword / opsStage,无请求 VO)
|
||||
|
||||
#### 使用场景
|
||||
|
||||
导出当前列表;与列表同传 `scope`。
|
||||
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| scope | query | String | 否 | ONGOING / FINISHED / ALL | **新增**。缺省规则同 GB-ADM-001;按 product 实时返团日过滤 |
|
||||
| productId / month / keyword / opsStage | query | — | 否 | 不变 | 不变 |
|
||||
|
||||
#### 出参
|
||||
|
||||
CSV 字节流(BOM + 表头),**不含未建团行**(只导有团期的行);行数 = 同 scope 下 GB-ADM-001 中 `groupBatchId` 非空的行数(例外:产品侧班期已删且 0 活跃单的残留团期会出现在导出、不出现在列表)。
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/group-batch/export?productId=2044306857534636034&scope=ALL HTTP/1.1
|
||||
Host: api.test.1814.love:9443
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
实测:`scope=ALL` 表头 + 1 行(10-01 团期);默认 ONGOING 1 行;`scope=FINISHED` 0 行。
|
||||
|
||||
```text
|
||||
团期号,期号,日期,出团日,满团名额,已售,剩余,状态,子订单数,整团应收
|
||||
Q202610012052935476548939777,没,那你,2026-10-01~2026-10-03,2026-10-01,8,4,4,已成团,4,23400.00
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无命中只返回表头一行。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
`productId` 有值且 `scope≠ALL` 时会调产品域取实时返团日,产品域不可用返回 589515(改前导出不依赖产品域);超过 2000 行 589517。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 589515,
|
||||
"message": "获取团期产品列表失败,请稍后重试",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 权限 `group-batch:export`
|
||||
- 导出基底与列表基底不同(不含未建团行),前端导出按钮旁如需提示请用「仅导出已建团期」
|
||||
|
||||
### 4. 团期看板合并层列表 `GET /v3/admin/order/group-batch/board`
|
||||
|
||||
**VO**: `Result<List<GroupBatchBoardItemRespVO>>`(查询参数 productId 必填、scope 可选)
|
||||
|
||||
#### 使用场景
|
||||
|
||||
以产品全部班期为基底的看板(hl-ui 当前未调用);本单只加可选 `scope`,响应结构不变。
|
||||
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| productId | query | Long(字符串) | 是 | 雪花 ID | 不变 |
|
||||
| scope | query | String | 否 | ONGOING / FINISHED / ALL | **新增**。缺省 `ALL`(保持既有行集) |
|
||||
|
||||
#### 出参 `Result<List<GroupBatchBoardItemRespVO>>`
|
||||
|
||||
字段不变;行为变化:产品班期全部删除时不再提前返回空,仍有活跃子订单的孤儿行照常输出(`productBatchRemoved=true`)。
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/group-batch/board?productId=2044306857534636034&scope=ONGOING HTTP/1.1
|
||||
Host: api.test.1814.love:9443
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
实测默认(ALL)8 行、`scope=ONGOING` 2 行;改前/改后逐字段 diff 见「地面真相」。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": [
|
||||
{
|
||||
"productBatchId": "2052935476557328386",
|
||||
"groupBatchId": "2096412454643802114",
|
||||
"departureDate": "2026-10-01",
|
||||
"endDate": "2026-10-03",
|
||||
"batchName": " 没,那你",
|
||||
"batchLabel": "7",
|
||||
"batchStatus": "RESOURCE_PREPARING",
|
||||
"productBatchRemoved": false,
|
||||
"orderCount": 4,
|
||||
"enrolledRooms": 4,
|
||||
"remainRooms": 4
|
||||
},
|
||||
{
|
||||
"productBatchId": "2096631555760807938",
|
||||
"groupBatchId": null,
|
||||
"departureDate": "2026-12-01",
|
||||
"endDate": "2026-12-03",
|
||||
"batchName": "QA-7189-1201",
|
||||
"batchLabel": "8",
|
||||
"batchStatus": "RECRUITING",
|
||||
"productBatchRemoved": false,
|
||||
"orderCount": 0,
|
||||
"enrolledRooms": 0,
|
||||
"remainRooms": 4
|
||||
}
|
||||
],
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
产品无班期且无团期 → `data=[]`。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
`589515` 产品域不可用;`589507` 无权限。
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 与 GB-ADM-001 共用 `GroupBatchMergedRowsService` 合并逻辑,三类行判定一致
|
||||
|
||||
### 5. 团期产品页签 `GET /v3/admin/order/group-batch/products`
|
||||
|
||||
**VO**: `Result<List<GroupBatchProductItemRespVO>>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
看板左侧产品页签「N 期」徽标。
|
||||
|
||||
#### 入参
|
||||
|
||||
无。
|
||||
|
||||
#### 出参 `Result<List<GroupBatchProductItemRespVO>>`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| data[].batchCount | Integer | **语义变化**:改前 = 订单侧团期数(只有下过单的班期才算),改后 = product 侧未删班期数,与传该 `productId` + `scope=ALL` 的列表行数一致 |
|
||||
| 其余字段 | — | 不变 |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/group-batch/products HTTP/1.1
|
||||
Host: api.test.1814.love:9443
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
实测(只列该产品):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": [
|
||||
{
|
||||
"productId": "2044306857534636034",
|
||||
"productName": "冻干粉发短信给",
|
||||
"productNo": "G260415004",
|
||||
"category": "family",
|
||||
"subtitle": "发短信给对方搞定",
|
||||
"coverImageUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/material/2026/03/07/ed278d1da74c3827cb06b7f0cf6091fe.jpg",
|
||||
"lineId": "2044248925572919297",
|
||||
"lineName": "阿斯蒂芬撒点",
|
||||
"tripDays": 3,
|
||||
"tripNights": 2,
|
||||
"status": "PUBLISHED",
|
||||
"sortOrder": 0,
|
||||
"batchCount": 8,
|
||||
"regionText": null
|
||||
}
|
||||
],
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无团期产品 → `data=[]`;产品无班期 → `batchCount=0`。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
`589515` 产品域不可用。
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 徽标直接显示 `batchCount`,不要用列表 total 反推(列表默认 ONGOING 只含未结束)
|
||||
|
||||
---
|
||||
|
||||
## 四、契约约束与正确调用方式
|
||||
|
||||
> 四个 GET 接口均只读;本节写**前端消费规则**。
|
||||
|
||||
### ✅ 正确 / ❌ 错误 payload 对照
|
||||
|
||||
| 场景 | payload / 处理 |
|
||||
|------|---------|
|
||||
| ✅ 看板默认加载 | 列表 `?productId=X`(不传 scope = ONGOING)+ 统计条 `?productId=X` 同样不传 |
|
||||
| ✅ 用户切范围 | 列表 / 统计条 / 导出三处**同时**带 `scope=FINISHED` 或 `ALL` |
|
||||
| ✅ 点后段桶 | `opsStage=TRIP_FINISHED / AUDITING / CHECKED` 时把范围切成 `scope=ALL` 再请求 |
|
||||
| ✅ 未建团行 | `groupBatchId == null` → 只渲染「新增子订单」(深链带 `productId` + `productBatchId`),隐藏展开 / 操作列 |
|
||||
| ✅ 孤儿行 | `productBatchRemoved == true` → 标「班期已删」,仍可看子订单 |
|
||||
| ✅ 状态展示 | 团期态用 `batchStatus`;售卖态用 `productBatchStatusLabel`(两套口径,不要互相推导) |
|
||||
| ❌ 只给列表传 scope、统计条不传 | 统计条会按默认 ONGOING,与列表对不上账 |
|
||||
| ❌ 用列表 total 当页签期数 | 默认 ONGOING 不含已结束期;徽标用 `batchCount` |
|
||||
| ❌ 对 `groupBatchId=null` 的行调详情 / 子订单 / 团期操作 | 后端 589500 团期不存在 |
|
||||
| ❌ 把 `chips` 为 TODO 的未建团行当「待办」 | 未建团行没有子订单,六项 TODO 只是零户占位 |
|
||||
|
||||
### 切换状态时的必要动作
|
||||
|
||||
无写接口。范围切换 / 页签切换后**同时**刷新列表与统计条(同一组参数)。
|
||||
|
||||
---
|
||||
|
||||
## 五、数据库行为
|
||||
|
||||
无表变更、无 Flyway。读路径变化:
|
||||
|
||||
| 时点 | 读取 |
|
||||
|------|------|
|
||||
| GB-ADM-001 / 009 传 `productId` | Feign `GET /internal/product/group/{productId}/detail`(product 全班期,含 `occupiedRooms / manualOrderCount`)+ `order_group_batch` 该产品团期 → 内存合并 |
|
||||
| GB-ADM-001 / 009 / 008 缺省 `productId` | `order_group_batch` 单表;`scope` 落 `end_date >= 今天 OR end_date IS NULL` / `end_date < 今天` |
|
||||
| GB-ADM-000 | Feign `GET /internal/product/group/all` 的 `batchCount`(product 侧 `group_tour_batch` 按 productId 一次 in 投影计数,软删不计) |
|
||||
|
||||
写路径不变(建团 / 下单刷新快照见 #7188)。
|
||||
|
||||
---
|
||||
|
||||
## 六、边界行为
|
||||
|
||||
- 未登录 → 网关 401;无权限 → `589507`
|
||||
- 传 `productId` 时产品域不可用 → `589515`(列表 / 统计条 / 导出三处;缺省 `productId` 不依赖产品域)
|
||||
- `scope` 非法值(如 `scope=xxx`)→ 按缺省规则处理,不报错
|
||||
- 返团日未填的班期 / 团期 → 视为未结束(ONGOING 含、FINISHED 不含)
|
||||
- 默认 ONGOING 下 `opsStage` 取后段桶 → 空列表(交集),不报错
|
||||
- 产品班期全删但团期仍有活跃子订单 → 列表 / board 都输出孤儿行;0 活跃单的残留团期不输出(导出仍会导出它)
|
||||
- 合并行超过 500 记 WARN(护栏,不截断)
|
||||
|
||||
## 六.5、枚举 / 数据字典
|
||||
|
||||
| 枚举 | 值 | 说明 |
|
||||
|------|----|------|
|
||||
| scope | ONGOING / FINISHED / ALL | 未结束(返团日 ≥ 今天或未填)/ 已结束(返团日 < 今天)/ 全部 |
|
||||
| productBatchStatus | ENROLLING / NEARLY_FULL / FULL / FINISHED / CANCELLING / CANCELLED | 报名中 / 即将满额 / 已满额 / 已结束 / 取消中 / 已取消(product 侧售卖态) |
|
||||
| batchStatus(未建团行) | RECRUITING | 固定值,落 RECRUIT 桶 |
|
||||
|
||||
## 六.6、修改前后对比
|
||||
|
||||
### 字段级对比
|
||||
|
||||
| 字段 | 修改前 | 修改后 |
|
||||
|------|--------|--------|
|
||||
| GB-ADM-001 / 009 / 008 / board `scope` | 无 | 新增(缺省按 productId:有 → ONGOING,无 → ALL;board → ALL) |
|
||||
| GB-ADM-001 `records[].productBatchStatus / productBatchStatusLabel / productBatchRemoved` | 无 | 新增 |
|
||||
| GB-ADM-001 `records[].groupBatchId` | 恒非空 | 未建团行 null |
|
||||
| GB-ADM-001 `records[].chips`(0 子订单行) | null | 六项 TODO |
|
||||
| GB-ADM-001 `records[].batchNo / batchName / 日期`(命中行) | 订单快照 | product 实时 |
|
||||
| GB-ADM-000 `data[].batchCount` | 订单侧团期数 | product 侧未删班期数 |
|
||||
| product `GET /internal/product/group/all` `batchCount`、`/group/{productId}/detail` `batches[].occupiedRooms / manualOrderCount` | 无 | 新增(内部接口,前端不直接调) |
|
||||
|
||||
### 行为级对比
|
||||
|
||||
| 场景 | 修改前 | 修改后 |
|
||||
|------|--------|--------|
|
||||
| 传 productId 的列表 | 只显有团期的班期(8 期显 1 期) | 显全部班期(8 行),未建团行可「新增子订单」 |
|
||||
| 传 productId 的排序 | create_time 倒序 | 出发日升序 |
|
||||
| 默认范围 | 无范围概念,全部 | 传 productId 默认只显未结束;缺省 productId 仍全部 |
|
||||
| 统计条 | 只统计有团期的 | 与列表同基底,未建团行计入 RECRUIT |
|
||||
| 产品班期全删 | board 返回空(有客人的团期被藏) | 孤儿行照常输出 |
|
||||
| 页签期数 | 下过单的班期数 | 产品班期数 |
|
||||
|
||||
## 六.7、影响评估
|
||||
|
||||
- 向后兼容:缺省 `productId` 的调用行集与排序不变;传 `productId` 的老调用**行数与排序会变**(多出未建团行、按出发日升序、默认只含未结束),hl-ui 看板必须按第四节处理 `groupBatchId=null`
|
||||
- 前端是否必须同步上线:**是**(否则看板会出现不可操作的未建团行、点后段桶得空列表)
|
||||
- 数据:无表变更;依赖产品域可用性(589515)
|
||||
|
||||
---
|
||||
|
||||
## 七、不影响范围
|
||||
|
||||
- **仅影响**: 团期看板列表 / 统计条 / 导出 / board / 产品页签
|
||||
- **零影响**:
|
||||
- 团期详情 GB-ADM-002、子订单 GB-ADM-003、芯片明细 GB-ADM-092/093(仍按 groupBatchId 查)
|
||||
- 创单 / 报价 / 状态机 / 按日推进 job(#7190,仍 PAUSED)
|
||||
- 小程序、product 管理端班期列表
|
||||
|
||||
---
|
||||
|
||||
## 八、测试环境已验证
|
||||
|
||||
真实接口输出(测试服 api.test.1814.love,2026-09-07 00:47-00:49,登录后切 ADMIN 角色):
|
||||
|
||||
```
|
||||
GET /v3/admin/order/group-batch?productId=2044306857534636034&scope=ALL&pageSize=50 → 200, total=8,出发日升序 06-04..12-01;10-01 行 groupBatchId=2096412454643802114 batchLabel="7";其余 7 行 groupBatchId=null batchStatus=RECRUITING orderCount=0 receivableAmount="0" chips 六项 TODO productBatchStatus 有值 ✓
|
||||
GET /v3/admin/order/group-batch?productId=2044306857534636034&pageSize=50 → 200, 默认 ONGOING total=2(10-01、12-01)✓;scope=FINISHED total=6 ✓
|
||||
GET /v3/admin/order/group-batch/summary?productId=2044306857534636034 → RECRUIT=1 FORMED=1 其余 0 total=2 subOrderCount=4 ✓;scope=ALL → total=8 RECRUIT=7 FORMED=1 ✓
|
||||
GET /v3/admin/order/group-batch?productId=…&scope=ALL&opsStage=RECRUIT → total=7 = summary(ALL).RECRUIT ✓;默认范围 opsStage=RECRUIT → total=1(12-01)= summary.RECRUIT ✓
|
||||
GET /v3/admin/order/group-batch?productId=…&scope=ALL&month=2026-10 → total=1(10-01)✓;keyword=没 → total=1(10-01)✓
|
||||
GET /v3/admin/order/group-batch/products → 该产品 batchCount=8 ✓
|
||||
GET /v3/admin/order/group-batch?pageSize=100(缺省 productId) → 改前/改后 20 行 groupBatchId 集合与顺序完全一致 ✓;scope=ONGOING 全部 endDate ≥ 今天 ✓;行内差异仅 chips(0 单行 null→六项 TODO,16 行)与 10-01 行计数(期间他人新下 4 单)
|
||||
GET /v3/admin/order/group-batch/board?productId=2044306857534636034 → 8 行,改前/改后逐字段 diff:键集合无增减,仅 10-01 行 orderCount/enrolledRooms/enrolledPeople/remainRooms 因新增 4 单变化 ✓;scope=ONGOING → 2 行 ✓
|
||||
GET /v3/admin/order/group-batch/export?productId=…&scope=ALL|默认|FINISHED → 数据行 1 / 1 / 0 = 列表同 scope 下 groupBatchId 非空行数 ✓
|
||||
GET /v3/admin/order/group-batch?productId=2061640294608134146&scope=ALL → 造数 maxRooms=0+manual=3 期 enrolledRooms=3 remainRooms=null ✓;maxRooms=5+manual=2 期 enrolledRooms=2 remainRooms=3 ✓;P1 06-04 期(线下 9/11)enrolledRooms=9 remainRooms=2 ✓
|
||||
AC-14:PUT /admin/product/item/2056944943066132481/schedule 把班期 2089667211995115522 出发日 09-05→09-13(返团日昨天→下周),不下单:分页默认 total 8→9 且含团期 2089667627927437313(departDate=2026-09-13 endDate=2026-09-14)✓、summary FORMED 5→6 ✓、export 数据行 6→7 含该班期号 ✓;随后改回 09-05,三处恢复 8 / 5 / 6 ✓
|
||||
```
|
||||
|
||||
验证产品:`productId=2044306857534636034`(冻干粉发短信给,8 期)、AC-13 载体 `2061640294608134146`(副本,造 maxRooms=0/manual=3 与 maxRooms=5/manual=2 两期)、AC-14 载体 `2056944943066132481` 班期 `2089667211995115522`(返团日昨天 → 改出发日到下周 → 三处出现 → 改回)。单测:order-v3 全量 `JAVA_TOOL_OPTIONS=-Xmx3g mvn -pl hl-order-service-v3 test` 8658/0/0(Skipped 7,ArchTest 六道门禁全绿)、product-v2 全量 1556/0/0;触点定向 ConverterTest 49 / QueryServiceTest 37 / ConsoleQueryServiceTest 27 / BoardStatsServiceTest 21 / MergedRowsServiceTest 18 / MapperIT 17(Testcontainers)/ ScopeResolverTest 9 / QueryControllerTest 8 / BoardStatsControllerTest 7 = 234/0/0。部署:Deploy Panel 00:47-00:49 product-v2 与 order-v3 滚动完成,分支 dev-v3。
|
||||
|
||||
---
|
||||
|
||||
## 十、相关文档
|
||||
|
||||
- 关联 Issue: [wx/HL#7189](https://git.1814.love:8443/wx/HL/issues/7189)
|
||||
- 关联 PR: [wx/HL#7219](https://git.1814.love:8443/wx/HL/pulls/7219)
|
||||
- 同现场: #7188(batchLabel「第N期」)、#7190(TRIP_FINISHED 九态 / 八桶)、#7204(导/摄芯片零指派口径)
|
||||
- 前端缺陷 changelog: `06_frontend_团期看板展开行子订单列表恒空-前端缺陷-管理后台.md`
|
||||
|
||||
## 关联 / 联系人
|
||||
|
||||
### 链接
|
||||
|
||||
- **Issue**: [#7189](https://git.1814.love:8443/wx/HL/issues/7189)
|
||||
- **PR**: [#7219](https://git.1814.love:8443/wx/HL/pulls/7219)
|
||||
- **Merge commit**: [ac0ffb02](https://git.1814.love:8443/wx/HL/commit/ac0ffb02dfc3aa6d1edbba2788ba2542a9cb686b)
|
||||
|
||||
### 联系人
|
||||
|
||||
- **后端负责人**: @wx
|
||||
在新工单中引用
屏蔽一个用户