13 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 | 7245 | 团期看板 batchName 去空格 + 不限容量 remain 统一为 null + board 库存同源 | admin | jw(GIT) | 修改接口 | deployed | verified | not_required | 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 仅显示。结构零变化,显示自动改善,无需改码。 | 2026-09-07 | 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 未建团行的已用房数改与分页、产品侧同源。
接口路径、入参、响应结构均未变,前端无需改码。
一、背景
- 产品侧存量脏值(如
" 没,那你",前导空格)经合并层实时透出成看板行标题。product 侧只在保存路径 trim、order 侧只在建团与刷新快照时 trim,存量列不会自愈。 remainParticipants两路不一致:未建团行走normalizeRemainingSlots(不限返 null),命中行走calcRemain(max=0 返 0)。- 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 |
请求示例
GET /v3/admin/order/group-batch?productId=2044306857534636034&scope=ALL&pageSize=50
响应示例
{
"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,不报错。
错误响应
无权限:
{
"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,同上 |
请求示例
GET /v3/admin/order/group-batch/board?productId=2044306857534636034
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": [
{
"productBatchId": "2045498872326717443",
"groupBatchId": null,
"batchName": "冻干粉发短信给",
"maxRooms": 11,
"enrolledRooms": 9,
"remainRooms": 2
}
]
}
空数据 / 降级响应
产品下无班期时返回空数组。
错误响应
产品域不可用:
{
"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 |
请求示例
GET /v3/admin/order/group-batch/2096779382436651009
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"batchName": "#7196复验班期",
"maxRooms": 9,
"remainRooms": 9,
"maxParticipants": 0,
"remainParticipants": null
}
}
空数据 / 降级响应
无空数据形态;团期不存在返 589500。
错误响应
{
"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 → 保持 nullbatchName为纯空白 → 转空串- 未建团行含线下占位 → 已用量计入
- 无权限 → 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 契约的remainingSlotsMAX_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 = 不限」