390 行
13 KiB
Markdown
390 行
13 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "7245"
|
||
title: "团期看板 batchName 去空格 + 不限容量 remain 统一为 null + board 库存同源"
|
||
consumer: "admin"
|
||
author: "jw(GIT)"
|
||
change_type: "修改接口"
|
||
backend_status: "deployed"
|
||
gateway_status: "verified"
|
||
frontend_status: "not_required"
|
||
frontend_owner: ""
|
||
frontend_ref: ""
|
||
target_release: ""
|
||
verified_at: ""
|
||
status_note: "PR #7256 已合入 dev-v3(732889527);2026-09-07 测试环境网关实测 AC-1/2/4/4b/5/6 全部通过。前端 mmg 已实查为 not_required:无任一读取点用后端 remainRooms/remainParticipants 判满员(PeriodRow 用 enrolledRooms>=maxRooms 自算,maxRooms=0/null 不显满团,与 null=不限一致);remainParticipants 读取点全按 !=null;前端无 batchName.trim();board enrolledRooms 仅显示。结构零变化,显示自动改善,无需改码。"
|
||
updated_at: "2026-09-07"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# 团期看板: 三处响应值口径修正(结构不变)
|
||
|
||
> **服务**: hl-order-service-v3 | **PR**: #7256 | **Issue**: #7245 | **合并提交**: `732889527`
|
||
> **影响范围**: 管理后台团期看板分页 / board / 详情三个读端点的响应值
|
||
|
||
---
|
||
|
||
## ⚠️ 关键变化
|
||
|
||
**`remainRooms` 与 `remainParticipants` 为 `null` 表示「不限」,前端不要按 `=== 0` 判满员。**
|
||
|
||
改前:容量字段为 `0` 时这两个值返 `0`,而同一列表里未建团行返 `null`,两类行语义打架,运营看到「剩余 0 人」会误判满员。
|
||
改后:容量为 `null` 或 `0` 一律返 `null`;容量大于 0 时才返 `max(0, 容量 − 已用)`。
|
||
|
||
另有两处修正:班期名去除前后空格;board 未建团行的已用房数改与分页、产品侧同源。
|
||
|
||
**接口路径、入参、响应结构均未变**,前端无需改码。
|
||
|
||
---
|
||
|
||
## 一、背景
|
||
|
||
1. 产品侧存量脏值(如 `" 没,那你"`,前导空格)经合并层实时透出成看板行标题。product 侧只在保存路径 trim、order 侧只在建团与刷新快照时 trim,**存量列不会自愈**。
|
||
2. `remainParticipants` 两路不一致:未建团行走 `normalizeRemainingSlots`(不限返 null),命中行走 `calcRemain`(max=0 返 0)。
|
||
3. board 未建团行的已用房数取订单侧计数器(**不含线下占位** `manual_order_count`),而合并分页与产品侧取 `occupiedRooms`(含占位)——**同一个班期两个剩余数**。实测容量 8 / 占位 3 / 线上 0 时,产品侧与分页回「剩 5」,board 回「剩 8」。
|
||
|
||
---
|
||
|
||
## 二、变更接口清单
|
||
|
||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||
|---|------|------|------|----------|------|
|
||
| 1 | 团期看板分页 | GET | `/v3/admin/order/group-batch` | **响应值修正** | `batchName` 去空格;不限容量 remain 返 null |
|
||
| 2 | 团期合并看板 | GET | `/v3/admin/order/group-batch/board` | **响应值修正** | 同上,另:未建团行已用房数改与分页同源 |
|
||
| 3 | 团期详情 | GET | `/v3/admin/order/group-batch/:groupBatchId` | **响应值修正** | 同 1 |
|
||
|
||
---
|
||
|
||
## 三、接口详情
|
||
|
||
### 1. 团期看板分页 `GET /v3/admin/order/group-batch`
|
||
|
||
**VO**: `GroupBatchPageItemRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
管理后台「团期订单」看板列表。传 `productId` 走合并基底(命中 / 未建团 / 孤儿三类行),不传走订单侧老路径。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| `productId` | Query | Long | ❌ | 字符串传参 | 有值走合并基底 |
|
||
| `scope` | Query | String | ❌ | `ONGOING`/`FINISHED`/`ALL` | 缺省:有 productId 时 ONGOING,否则 ALL |
|
||
| `opsStage` | Query | String | ❌ | 八桶之一 | 运营阶段筛选 |
|
||
| `batchStatus` | Query | String | ❌ | 团期九态 | 状态筛选 |
|
||
| `month` | Query | String | ❌ | `yyyy-MM` | 出发月 |
|
||
| `keyword` | Query | String | ❌ | — | 编号或名称模糊 |
|
||
| `pageNo` / `pageSize` | Query | Integer | ❌ | 默认 1 / 20,上限 100 | 分页 |
|
||
|
||
#### 出参 `Result<PageResult<GroupBatchPageItemRespVO>>`
|
||
|
||
本次仅三个字段取值变化,结构不变:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `batchName` | String | 班期名,**已去除前后空白**;null 仍为 null |
|
||
| `remainRooms` | Integer | 剩余房数。**`maxRooms` 为 null 或 0 时返 null(不限)**,否则 `max(0, maxRooms − enrolledRooms)` |
|
||
| `remainParticipants` | Integer | 剩余人数。口径同上,基于 `maxParticipants` 与 `enrolledPeople` |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/group-batch?productId=2044306857534636034&scope=ALL&pageSize=50
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"success": true,
|
||
"data": {
|
||
"total": 8,
|
||
"records": [
|
||
{
|
||
"productBatchId": "2052935476557328386",
|
||
"batchName": "没,那你",
|
||
"maxRooms": 80,
|
||
"enrolledRooms": 55,
|
||
"remainRooms": 25,
|
||
"maxParticipants": 0,
|
||
"remainParticipants": null
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
无匹配班期时 `records` 为空数组、`total` 为 0,不报错。
|
||
|
||
#### 错误响应
|
||
|
||
无权限:
|
||
|
||
```json
|
||
{
|
||
"code": 589507,
|
||
"message": "无权限操作该团期",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 只读接口,不产生任何写入
|
||
- `remainRooms` / `remainParticipants` 为 **null 表示不限**,不是「剩 0」
|
||
- 命中行容量读订单侧快照,未建团行读产品侧实时值——改产品容量不会立刻影响命中行
|
||
- 行集、排序、分页与其余字段值均不变
|
||
|
||
---
|
||
|
||
### 2. 团期合并看板 `GET /v3/admin/order/group-batch/board`
|
||
|
||
**VO**: `GroupBatchBoardItemRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
按产品维度展示全部班期(含未建团班期)的合并看板。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| `productId` | Query | Long | ✅ | 字符串传参 | 产品 ID |
|
||
| `scope` | Query | String | ❌ | 缺省 `ALL` | 范围筛选 |
|
||
|
||
#### 出参 `Result<List<GroupBatchBoardItemRespVO>>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `batchName` | String | 已去除前后空白 |
|
||
| `remainRooms` / `remainParticipants` | Integer | 不限时返 null,口径同接口 1 |
|
||
| `enrolledRooms` | Integer | **未建团行改取产品侧 `occupiedRooms`(含线下占位)**,与分页及产品侧同源;命中行与孤儿行仍为订单侧计数 |
|
||
| `enrolledPeople` | Integer | 未建团行改取产品侧 `enrolledCount`,同上 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/group-batch/board?productId=2044306857534636034
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"success": true,
|
||
"data": [
|
||
{
|
||
"productBatchId": "2045498872326717443",
|
||
"groupBatchId": null,
|
||
"batchName": "冻干粉发短信给",
|
||
"maxRooms": 11,
|
||
"enrolledRooms": 9,
|
||
"remainRooms": 2
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
产品下无班期时返回空数组。
|
||
|
||
#### 错误响应
|
||
|
||
产品域不可用:
|
||
|
||
```json
|
||
{
|
||
"code": 589515,
|
||
"message": "拉取产品信息失败",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 只读接口
|
||
- **未建团行的已用量含线下占位**,与产品侧 `schedule/list` 剩余库存一致
|
||
- 命中行的权威源仍是订单侧计数器,不受产品侧占位影响
|
||
|
||
---
|
||
|
||
### 3. 团期详情 `GET /v3/admin/order/group-batch/:groupBatchId`
|
||
|
||
**VO**: `GroupBatchDetailRespVO`
|
||
|
||
#### 使用场景
|
||
|
||
团期详情页头部信息。
|
||
|
||
#### 入参
|
||
|
||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||
|------|------|------|------|------|------|
|
||
| `groupBatchId` | Path | Long | ✅ | — | 团期主订单 ID(**不是** productBatchId) |
|
||
|
||
#### 出参 `Result<GroupBatchDetailRespVO>`
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `batchName` | String | 快照值,已去除前后空白 |
|
||
| `remainRooms` / `remainParticipants` | Integer | 不限时返 null,口径同接口 1 |
|
||
|
||
#### 请求示例
|
||
|
||
```http
|
||
GET /v3/admin/order/group-batch/2096779382436651009
|
||
```
|
||
|
||
#### 响应示例
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "成功",
|
||
"success": true,
|
||
"data": {
|
||
"batchName": "#7196复验班期",
|
||
"maxRooms": 9,
|
||
"remainRooms": 9,
|
||
"maxParticipants": 0,
|
||
"remainParticipants": null
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 空数据 / 降级响应
|
||
|
||
无空数据形态;团期不存在返 589500。
|
||
|
||
#### 错误响应
|
||
|
||
```json
|
||
{
|
||
"code": 589500,
|
||
"message": "团期不存在",
|
||
"success": false,
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
#### 业务边界
|
||
|
||
- 只读接口
|
||
- 容量读订单侧快照,产品侧改容量需等下次该班期下单刷新才反映
|
||
|
||
---
|
||
|
||
## 四、契约约束与正确调用方式
|
||
|
||
- **`remainRooms` / `remainParticipants` 为 null 一律解释为「不限」**,不要按 `=== 0` 或 `!= null` 判满员;判满员应看 `maxXxx > 0 && remainXxx === 0`。
|
||
- **`batchName` 已由服务端去空格**,前端不必再 trim;null 仍为 null(未转空串)。
|
||
- **board 与分页的剩余数现已同源**,两处显示不一致即为缺陷,可直接报。
|
||
- 命中行与未建团行的容量来源不同(订单侧快照 vs 产品侧实时),验证时不要混用样本。
|
||
|
||
---
|
||
|
||
## 五、数据库行为
|
||
|
||
三个接口均为**只读**,不产生任何写入。本次**无表变更、无 Flyway、无 H2 schema 变更,不回填存量数据**。
|
||
|
||
产品侧 `group_tour_batch.batch_name` 的存量脏值**未回填**,由读端 trim 兜住。
|
||
|
||
---
|
||
|
||
## 六、边界行为
|
||
|
||
- 容量为 null 或 0 → remain 返 null
|
||
- 容量大于 0 且已用超额 → remain 返 0(不返负数)
|
||
- `batchName` 为 null → 保持 null
|
||
- `batchName` 为纯空白 → 转空串
|
||
- 未建团行含线下占位 → 已用量计入
|
||
- 无权限 → 589507;产品域不可用 → 589515;团期不存在 → 589500
|
||
|
||
---
|
||
|
||
## 六.5、枚举 / 数据字典
|
||
|
||
本次无新增枚举。
|
||
|
||
---
|
||
|
||
## 六.6、修改前后对比
|
||
|
||
| 项 | 变更前 | 变更后 |
|
||
|---|---|---|
|
||
| `batchName` | 原样透出,可带前后空格 | **trim 后**输出,null 仍 null |
|
||
| 容量为 0 时 `remainRooms` | 返 `0`(前端显示「剩余 0」误判满员) | 返 **null**(不限) |
|
||
| 容量为 0 时 `remainParticipants` | 命中行返 `0`、未建团行返 `null`(两路打架) | 三类行统一返 **null** |
|
||
| board 未建团行 `enrolledRooms` | 订单侧计数,**不含线下占位** | 产品侧 `occupiedRooms`,**含线下占位** |
|
||
| board 与分页剩余数 | 同班期可能不同(实测 8 vs 5) | **一致** |
|
||
| 路径 / 入参 / 响应结构 | — | **均未变** |
|
||
|
||
## 六.7、影响评估
|
||
|
||
| 维度 | 评估 |
|
||
|---|---|
|
||
| 兼容性 | 结构零变化,仅三个字段取值修正;前端无需改码 |
|
||
| 前端 | 行标题与「剩余」列显示自动改善;若曾用 `remainXxx === 0` 判满员,不限行不再误判 |
|
||
| 数据 | 无 DDL、无迁移、无回填;纯读端派生 |
|
||
| 性能 | 无额外查询,未建团行改用入参里已有的产品侧字段,零新增 IO |
|
||
| 回滚 | 还原 Converter 即可,无数据侧残留 |
|
||
| 风险 | 低。改动集中在单个静态 Converter,13 例单测 + 6 组网关用例覆盖 |
|
||
|
||
---
|
||
|
||
## 七、不影响范围
|
||
|
||
- **零影响**:三个接口的路径、入参、响应结构、行集、排序、分页
|
||
- **零影响**:导出 CSV(GB-ADM-008,读订单快照)
|
||
- **零影响**:建团与刷新时的快照写入路径
|
||
- **零影响**:product-v2、`normalizeRemainingSlots`、Feign 契约的 `remainingSlots` MAX_VALUE 语义
|
||
- **零影响**:`GroupBatchMergedRowsService`(含 `matchesKeyword`,用 contains,带空格不影响搜索)
|
||
|
||
---
|
||
|
||
## 八、测试环境已验证
|
||
|
||
✅ 2026-09-07 于测试环境网关实测,真实鉴权(管理端 admin),部署本单特性分支后验收再合入 dev-v3。
|
||
|
||
| # | 用例 | 结果 |
|
||
|---|---|---|
|
||
| AC-1 | 分页 `batchName` 无前后空白 | ✅ 8 行全通过;目标脏值行 `2052935476557328386` → `"没,那你"` |
|
||
| AC-2 | 容量 0/null 的行 remain 均为 null | ✅ 违例 0(其中容量 0/null 的行 1 行构成有效样本) |
|
||
| AC-4 | board 同样成立 | ✅ 8 行,带空白 0、违例 0 |
|
||
| **AC-4b** | **board 与分页库存同源** | ✅ **8 行 `remainRooms` 全部一致**。样本:未建团行 `2045498872326717443` 已用 9 / 剩 2(含线下占位),改前 board 会回 `0/11` |
|
||
| AC-5 | 详情端点 | ✅ `batchName` 无空白;同一行 `maxRooms=9→remainRooms=9`(有限容量正常算)、`maxParticipants=0→remainParticipants=null`(不限) |
|
||
| AC-6 | 缺省 productId 老路径回归 | ✅ 22 行,容量 0/null 的 21 行 remain 均为 null,batchName 无空白 |
|
||
|
||
**本地单测**:`GroupBatchConverterTest` 新增 13 例(trim 四组、max=0 三组、未建团行含线下占位取 `occupiedRooms`、命中行仍用订单侧计数);全量 **8728 例 0 failures**(余 7 个 error 为 Testcontainers 依赖 Docker,纯 dev-v3 同样失败)。
|
||
|
||
---
|
||
|
||
## 九、相关历史 PR
|
||
|
||
- #7256 本次变更
|
||
- 前序:#7188(batchLabel 与保存路径 trim)、#7189(合并基底引入,暴露两路 remain 不一致)
|
||
|
||
---
|
||
|
||
## 十、相关文档
|
||
|
||
- 团期需求文档:`docs/group/`(dev-v3 分支)
|
||
|
||
---
|
||
|
||
## 关联 / 联系人
|
||
|
||
- **Issue**: #7245 | **PR**: #7256(合并提交 `732889527`)
|
||
- **服务**: hl-order-service-v3
|
||
- **后端**: jw | **前端**: 无需改码,仅需知悉「null = 不限」
|