docs(changelog): publish order kind filters (#7635)
changelog-filename-gate / validate (push) Failing after 2s

这个提交包含在:
API Changelog Bot
2026-09-13 20:18:39 +08:00
父节点 0686db9ad5
当前提交 e3700420a2
@@ -0,0 +1,303 @@
---
schema: "hl-changelog/v2"
ticket: "7635"
title: "订单列表补 orderKind/groupBatchId 筛选并将缺省改为散客"
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-13T20:11:00+08:00"
status_note: "后端测试服 ca252347e 已部署并经网关 35 请求验证;破坏性缺省行为变更,前端筛选控件仍 pending,生产必须同批上线"
updated_at: "2026-09-13"
base: "dev-v3"
generated: "2026-09-13T16:41:30+08:00"
---
# 订单列表补 orderKind/groupBatchId 筛选并将缺省改为散客
> **服务**: hl-order-service-v3
> **PR**: #7650
> **Issue**: #7635
> **日期**: 2026-09-13
> **影响范围**: 管理后台订单列表与顶部 Tab 计数
## ⚠️ 关键变化
### 破坏性:缺省行为变更
1. 不传 `orderKind`(或传空串)后,订单列表与 Tab 计数只返回散客单,不再包含团期子订单。
2. 要获取改动前的全集,必须显式传 `orderKind=ALL`。
3. 因缺省集合变小,顶部 Tab 计数会同步变小;**这不是丢单**,显式 `ALL` 可取回原全集。
4. 管理后台必须提供 `NORMAL / GROUP / ALL` 筛选控件,并与本后端版本**同批上生产**,否则管理员无法从普通订单列表切换查看团单;团期订单页仍可访问团单。
## 一、背景
管理端订单列表原来无法按团期子订单/散客区分,也不能按运营团期精确筛选。本次以 `order_main.group_batch_id` 为唯一判团依据补齐筛选;为保护共享 Mapper 的定制师待办,缺省 NORMAL 只在管理端 OrderService 入口归一化。
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 管理端订单列表 | GET | `/v3/admin/order` | 修改接口 | 新增 `orderKind` / `groupBatchId`,缺省改为 NORMAL |
| 2 | 订单列表 Tab 分组计数 | GET | `/v3/admin/order/status-group-counts` | 修改接口 | 复用团属性筛选;缺省计数与列表一致,显式 ALL 保留改前数字 |
## 三、接口详情
### 1. 管理端订单列表 `GET /v3/admin/order`
**VO**: `OrderListReqVO → PageResult<OrderListItemRespVO>`
#### 使用场景
管理后台按散客、团期子订单、全部订单或指定运营团期查看订单。兼容路径 `/v3/admin/order/list` 具有完全相同的筛选语义。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|:---:|---|---|
| orderKind | Query | String | 否 | ALL / GROUP / NORMAL;空串按缺省 | NORMAL 仅散客;GROUP 仅团单;ALL 全部;缺省 NORMAL |
| groupBatchId | Query | Long | 否 | Snowflake ID;非数字返回 100001 | 精确筛选运营团期;非空时强制 GROUP |
| cancelled | Query | Boolean | 否 | true / false | 保持既有列表语义;缺省排除已取消 |
| page / pageSize | Query | Integer | 否 | 既有分页约束 | 分页参数,行为不变 |
#### 出参 `Result<PageResult<OrderListItemRespVO>>`
| 字段 | 类型 | 说明 |
|---|---|---|
| data.records | List | 当前筛选页;已有 groupBatchId / groupOrder 可判团 |
| data.total | Long | 当前全部筛选条件下的订单总数 |
| code / message / success | Integer / String / Boolean | 统一业务响应字段,结构不变 |
#### 请求示例
```http
GET /v3/admin/order?page=1&pageSize=20&orderKind=GROUP
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"records": [
{"orderNo": "masked-example", "groupBatchId": "2099078774497681409", "groupOrder": true}
],
"total": 1
}
}
```
#### 空数据 / 降级响应
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {"records": [], "total": 0}
}
```
- 不存在的 `groupBatchId` 返回成功空分页,不降级成全部订单。
- `orderKind=` 与省略参数都降级到 NORMAL,而不是 ALL。
#### 错误响应
```json
{
"code": 100001,
"message": "orderKind 非法,可选值: ALL, GROUP, NORMAL",
"success": false,
"data": null
}
```
#### 业务边界
- 判团唯一依据是 `order_main.group_batch_id` 是否为空;禁止用 `productBatchId`、`productType` 或 `teamNo` 推断。
- `groupBatchId` 非空优先于 `orderKind`;即使同传 NORMAL 也按指定团期的 GROUP 口径返回。
- 同一组其它筛选下,`NORMAL.total + GROUP.total = ALL.total`。
### 2. 订单列表 Tab 分组计数 `GET /v3/admin/order/status-group-counts`
**VO**: `OrderListReqVO → List<StatusGroupCountVO>`
#### 使用场景
管理后台订单列表顶部“全部/出行前/出行中/核单/异常取消/售后”Tab 随当前团属性视角刷新数量。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|:---:|---|---|
| orderKind | Query | String | 否 | ALL / GROUP / NORMAL;空串按缺省 | 与列表一致,缺省 NORMAL |
| groupBatchId | Query | Long | 否 | Snowflake ID;非数字返回 100001 | 精确团期,非空时强制 GROUP |
| cancelled | Query | Boolean | 否 | true / false | NORMAL/GROUP 与列表对齐;显式 ALL 为 AC-6 保留改前含取消计数 |
| 其它公共筛选 | Query | 多种 | 否 | 既有约束 | keyword、出发日期、顾问、来源和标签等继续 AND |
#### 出参 `Result<List<StatusGroupCountVO>>`
| 字段 | 类型 | 说明 |
|---|---|---|
| data[].group | String | ALL / BEFORE_TRIP / ON_TRIP / SETTLEMENT / ABNORMAL / AFTERSALE |
| data[].orderCount | Long | 当前团属性与公共筛选下的分组数量 |
| code / message / success | Integer / String / Boolean | 统一业务响应字段,结构不变 |
#### 请求示例
```http
GET /v3/admin/order/status-group-counts?orderKind=ALL
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": [
{"group": "ALL", "orderCount": 323},
{"group": "BEFORE_TRIP", "orderCount": 228},
{"group": "ON_TRIP", "orderCount": 0},
{"group": "SETTLEMENT", "orderCount": 27},
{"group": "ABNORMAL", "orderCount": 68},
{"group": "AFTERSALE", "orderCount": 0}
]
}
```
#### 空数据 / 降级响应
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": [
{"group": "ALL", "orderCount": 0},
{"group": "BEFORE_TRIP", "orderCount": 0},
{"group": "ON_TRIP", "orderCount": 0},
{"group": "SETTLEMENT", "orderCount": 0},
{"group": "ABNORMAL", "orderCount": 0},
{"group": "AFTERSALE", "orderCount": 0}
]
}
```
- 无匹配时仍稳定返回六个分组,每个数量为 0。
- 不存在的团期 ID 不降级为其它团期或全部订单。
#### 错误响应
```json
{
"code": 100001,
"message": "参数【groupBatchId】格式不正确",
"success": false,
"data": null
}
```
#### 业务边界
- 不传团属性参数时,ALL Tab 等于缺省散客列表 total,并缺省排除已取消。
- GROUP/指定团期按列表 cancelled 口径;显式 `orderKind=ALL` 的六个 Tab 严格保持改动前含取消口径。
- `orderStatus` / `flowStatus` / `statusGroup` 仍按既有 Tab 语义不缩窄计数基数。
## 四、契约约束与正确调用方式(接口类必写)
### ✅ 正确 / ❌ 错误 payload 对照
- ✅ 默认只看散客:省略 `orderKind` 或传 `orderKind=`。
- ✅ 查看团单:传 `orderKind=GROUP`;查看改动前全集:传 `orderKind=ALL`。
- ✅ 指定团期:传 `groupBatchId=<ID>`,可省略 `orderKind`。
- ❌ 不要把“省略 orderKind”继续理解为全部订单。
- ❌ 不要传中文值、SQL 片段、XXX,或根据 teamNo 判断团单。
### 切换状态时的必要动作
前端切换 `orderKind` 或 `groupBatchId` 后,必须用同一组参数同时刷新列表与 status-group-counts;清空筛选时按 NORMAL 展示。显式 ALL 的 Tab 数字沿用既有含取消口径。后端与前端筛选控件必须同批生产发布。
## 五、数据库行为(涉及写操作时必写)
- 本次只有查询条件变化,无数据库写入、无 Flyway、无数据迁移。
- 使用已有 `group_batch_id` 索引;不新增动态 SQL 字符串或客户端排序字段。
## 六、边界行为
- `orderKind=null` / 空串:仅管理端列表与计数入口归一为 NORMAL。
- `OrderListQuery.orderKind=null`:Mapper 不增加团属性过滤,Designer 待办保持原全集行为。
- 仅 `group_batch_id` 判团;`product_batch_id` 非空但 `group_batch_id` 为空仍是 NORMAL。
- 非法 orderKind 和非数字 groupBatchId 在列表与计数接口均返回 HTTP 200、业务 code=100001、中文字段消息。
## 六.5、前端开发任务拆分
1. 在管理后台订单列表增加 NORMAL / GROUP / ALL 控件,初始值 NORMAL。
2. 切换团属性后同时刷新列表和 Tab;选择团期时传 groupBatchId。
3. 查看旧全集时显式传 ALL;不要依赖省略参数。
4. 与后端同批上生产;本 changelog 的 frontend_status 在前端完成前保持 pending。
## 六.6、修改前后对比
### 字段级对比
| 对象 | 修改前 | 修改后 |
|---|---|---|
| OrderListReqVO | 无团属性筛选参数 | 新增可选 orderKind 与 groupBatchId |
| OrderListQuery | 无团属性字段 | 新增 nullable 团属性字段;null 仍表示不过滤 |
| 响应 DTO | 已有 groupBatchId / groupOrder | 不变 |
### 行为级对比
| 行为 | 修改前 | 修改后 |
|---|---|---|
| 不传团属性参数 | 普通单与团单混合 | 仅散客 NORMAL |
| 查看旧全集 | 省略参数 | 显式 orderKind=ALL |
| 精确团期筛选 | 不支持 | 传 groupBatchId,且优先强制 GROUP |
| Tab 数字 | 不支持团属性视角 | 缺省 NORMAL 与列表一致;显式 ALL 保持改前数字 |
## 六.7、影响评估(修改/删除类必写)
- **高影响**:所有依赖“省略团属性参数=全集”的管理端调用方必须显式改传 ALL。
- 前端未同步控件时,管理员无法从普通订单列表切换团单,因此必须同批发布。
- 缺省 Tab 数字变小是视角切换,不代表订单丢失。
## 七、不影响范围(显式声明, 帮前端/QA 缩小排查面)
- 定制师待办保持普通单与团单全集;改前后 total、顺序散列与团单数量已实测一致。
- 团期订单页与团期子订单入口不变,团单仍可达。
- 订单写入、归团、状态、权限、排序和响应结构均不变。
## 八、测试环境已验证
- 定向测试:focused reactor 351 tests,0 failures/errors/skips,含 Docker OrderInfoMapperIT 与 ArchTest。
- 网关验证:测试服提交 ca252347e;35 个 GET 请求、17 项断言全绿。缺省/NORMAL=171、GROUP=84、ALL=255;显式 ALL 各 Tab 保持改前 323/228/0/27/68/0;cancelled=true 三档 list/count 为 208/208、115/115、323/323。
- 回归:Designer total=17、首页 orderNo SHA-256 与 2 个团单的改前基线完全一致;团期页与团期订单入口均可达。
- 部署状态:hl-order-service-v3 为 ca252347e、0/N、ok;hl-gateway 为 a82367e15、25/N、ok。
## 十、相关文档
- 后端规范:`docs/order-v3/api/API-SPEC.html` §1.2、§1.11。
- 团期冻结口径:`docs/group/团期模块接口文档-v2.0.html` §0A.2、已落地清单及订单列表筛选卡片。
- 脱敏证据:任务 #7635 的 gateway-verification-after.json、gateway-baseline-before.json、display-matrix.md。
## 关联 / 联系人
### 链接
- **Issue**: [#7635](https://git.1814.love:8443/wx/HL/issues/7635)
- **PR**: [#7650](https://git.1814.love:8443/wx/HL/pulls/7650)
- **Merge commit**: 尚未产生
### 联系人
- **后端负责人**: @wx