18 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 | 7142 | 订单详情/列表/创单响应透出 groupBatchId·productBatchId·groupOrder 判团字段 | admin | wx(GIT) | 修改接口 | deployed | verified | not_required | 2026-09-06 | dev-v3 |
订单模块:判团字段透出(详情·列表·创单)
三个订单读接口响应透出判团字段 groupBatchId / productBatchId / groupOrder,供前端判断订单是否为团订单。关键口径:判团只读 groupBatchId(非空=团订单)或 groupOrder;productBatchId 仅供溯源,不参与判团。
⚠️ 关键变化
- 判团唯一口径
groupBatchId非空或groupOrder = true→ 团订单;为空/false → 普通订单。 - 不要拿
productBatchId反推团单,该字段仅供产品侧班期溯源展示,产品侧可能有多个班期映射同一团期。 - 前一版 #7083 仅涉及订单主表冻结,本次全量透出给前端消费,与主表字段同源。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 订单详情 - 主单数据 | GET | /v3/admin/order/{id} |
响应新增字段 | data.main 新增 4 字段 |
| 2 | 订单分页列表 | GET | /v3/admin/order |
响应新增字段 | data.list[] 新增 2 字段 |
| 3 | 创建订单 | POST | /v3/admin/order |
响应新增字段 | data 新增 3 字段 |
三、接口详情
1. 订单详情 - 主单数据 GET /v3/admin/order/{id}
VO: OrderMainVO(响应位置:data.main)
使用场景
打开订单详情页面时,读取订单主单数据及其判团标记,供前端决定显示团期相关内容(如「团期编号」、「团期名称」等)。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
id |
Path | String | 是 | 正整数 ID | 订单 ID |
出参 Result<OrderDetailRespVO>
| 字段 | 类型 | 说明 |
|---|---|---|
data.main.groupBatchId |
String/null | 运营团期主键(order_group_batch.group_batch_id);非空=团订单,为空=普通订单 |
data.main.productBatchId |
String/null | 产品侧班期 ID(product_v2.group_tour_batch.batch_id);仅供溯源,不参与判团 |
data.main.groupOrder |
Boolean | 派生值,= groupBatchId != null;直接用于前端判团 |
data.main.batchNo |
String/null | 团期编号(order_group_batch.batch_no);普通单为 null,团期软删也为 null |
data.main.batchName |
String/null | 团期名称(order_group_batch.batch_name);普通单为 null,团期软删也为 null |
请求示例
GET /v3/admin/order/2096414445365338113
Authorization: Bearer <token>
无请求体。
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"main": {
"id": "2096414445365338113",
"orderNo": "HL20260906094527867",
"orderStatus": "PENDING_PAY",
"orderStatusName": "待支付",
"flowStatus": "AWAITING_PAY",
"flowStatusName": "待补全信息",
"flowStep": 0,
"flowStepTotal": 6,
"totalAmount": "5850.00",
"depositAmount": "1000.00",
"departureDate": "2026-10-01",
"returnDate": "2026-10-03",
"groupBatchId": "2096412454643802114",
"productBatchId": "2052935476557328386",
"groupOrder": true,
"batchNo": "Q202610012052935476548939777",
"batchName": "10月1日长白山亲子团",
"progressStepper": []
},
"profile": {},
"resource": {},
"contract": {},
"insurance": {},
"refund": {},
"aftersale": {},
"financial": {}
}
}
空数据 / 降级响应
普通订单时,groupBatchId、productBatchId、batchNo、batchName 均为 null;groupOrder 为 false。
错误响应
{
"code": 581007,
"message": "订单不存在",
"success": false,
"data": null
}
示例错误码:
- 581007:订单不存在
- 581045:房务角色无权查看订单详情(HTTP 200 code)
业务边界
- 沿用订单详情权限校验;业务失败仍为 HTTP 200,需检查 code。
- 普通订单与团单在出参结构上无区别,仅字段值不同(null vs 有值)。
- 团期已软删时,
groupBatchId存在但对应记录不可查,batchNo/batchName回退为 null。 productBatchId与groupBatchId无必然对应,前端不做交叉校验。
2. 订单分页列表 GET /v3/admin/order
别名接口:GET /v3/admin/order/list
VO: OrderListItemRespVO(响应位置:data.list[])
使用场景
订单列表页加载数据时,带上新增的判团标记,供前端快速判断每行是否为团订单,可用于条件展示「团期信息」列或其他团期特化功能。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
orderStatus |
Query | String | 否 | 枚举多值(逗号分隔) | 粗状态过滤(PENDING_PAY、CUSTOMIZING 等) |
flowStatus |
Query | String | 否 | 枚举多值(逗号分隔) | 细状态过滤(AWAITING_PAY、RESOURCE_PREPARING 等) |
tagNames |
Query | Array | 否 | - | 按标签过滤(多标签 OR 关系) |
keyword |
Query | String | 否 | - | 搜索关键字(团号/客户姓名/产品名/订单号 LIKE) |
departureDateFrom |
Query | String | 否 | yyyy-MM-dd | 出发日期范围起始 |
departureDateTo |
Query | String | 否 | yyyy-MM-dd | 出发日期范围结束 |
createSource |
Query | String | 否 | - | 来源过滤(CONSULTANT/MP/...) |
cancelled |
Query | Boolean | 否 | - | 是否含已取消订单(默认 false) |
consultantName |
Query | String | 否 | - | 定制师姓名 LIKE 模糊匹配 |
statusGroup |
Query | String | 否 | 枚举单值 | 按 Tab 分组(ALL/BEFORE_TRIP/ON_TRIP/SETTLEMENT/ABNORMAL/AFTERSALE) |
page |
Query | Integer | 是 | ≥1 | 页码 |
pageSize |
Query | Integer | 是 | ≤100 | 每页条数 |
出参 Result<Page<OrderListItemRespVO>>
| 字段 | 类型 | 说明 |
|---|---|---|
data.list[].groupBatchId |
String/null | 运营团期主键(order_group_batch.group_batch_id);非空=团订单 |
data.list[].groupOrder |
Boolean | 派生值,= groupBatchId != null;直接用于前端判团 |
其他字段详见现有订单列表接口文档。
请求示例
GET /v3/admin/order?page=1&pageSize=20
Authorization: Bearer <token>
无请求体。
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"total": 150,
"list": [
{
"id": "2096414445365338113",
"orderNo": "HL20260906094527867",
"productName": "冻干粉发短信给",
"customerName": "张三",
"departureDate": "2026-10-01",
"orderStatus": "PENDING_PAY",
"flowStatus": "AWAITING_PAY",
"totalAmount": "5850.00",
"groupBatchId": "2096412454643802114",
"groupOrder": true
},
{
"id": "2096414445365338114",
"orderNo": "HL20260906094527868",
"productName": "其他产品",
"customerName": "李四",
"departureDate": "2026-10-02",
"orderStatus": "PENDING_DEPARTURE",
"flowStatus": "PENDING_DEPARTURE",
"totalAmount": "8000.00",
"groupBatchId": null,
"groupOrder": false
}
]
}
}
空数据 / 降级响应
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"total": 0,
"list": []
}
}
错误响应
{
"code": 401,
"message": "未登录或登录已过期",
"success": false,
"data": null
}
业务边界
- 分页字段
page/pageSize沿用现有约束。 - 列表返回最新 50 条或 100 条时,两个新增字段保证同时返回,不存在部分返回的情况。
groupOrder是groupBatchId != null的派生布尔值,前端可二选一使用。- 普通订单与团单混合返回,字段值直接对标订单属性。
3. 创建订单 POST /v3/admin/order
VO: OrderCreateRespVO(响应位置:data)
使用场景
创建订单后,管理端「订单已创建」弹窗或后续流程需判断该单是否为团单,及时显示团期相关信息(如「团期编号」、「出发日期」等)。
入参
沿用现有 OrderCreateReqVO,请求体不变(本单只改响应)。字段表:
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
productId |
Body | String(Long) | ✅ | 正整数 | 产品 ID |
tierSeq |
Body | Integer | ✅ | ≥1 | 档位序号 |
departureDate |
Body | String(yyyy-MM-dd) | ✅ | 不早于今天 | 出发日期 |
adultCount |
Body | Integer | ✅ | ≥1 | 成人数 |
childCount |
Body | Integer | 否 | ≥0,默认 0 | 儿童数 |
youngChildCount |
Body | Integer | 否 | ≥0,默认 0 | 小童数 |
babyCount |
Body | Integer | 否 | ≥0,默认 0 | 婴儿数 |
customerName |
Body | String | ✅ | @NotBlank | 客户姓名 |
customerPhone |
Body | String | ✅ | ^1[3-9]\d{9}$ | 客户手机号 |
customerRemark |
Body | String | 否 | ≤500 | 备注 |
createSource |
Body | String | 否 | 默认 CONSULTANT | 创建来源 |
productBatchId |
Body | String(Long) | 否 | GROUP 必传、非 GROUP 禁传 | 团期 ID(见 #7135) |
roomCount |
Body | Integer | 否 | ≥1 | 房间数 |
tags |
Body | Array<String> | 否 | — | 订单标签 |
出参 Result<OrderCreateRespVO>
| 字段 | 类型 | 说明 |
|---|---|---|
data.id |
String | 订单主键 |
data.orderNo |
String | 订单号 |
data.orderStatus |
String | 粗状态(创单后为 PENDING_PAY) |
data.flowStatus |
String | 细状态(创单后为 AWAITING_PAY) |
data.flowStep |
Integer | 线性步序(创单初态为 0) |
data.flowStepTotal |
Integer | 总步数(固定 6) |
data.productName |
String | 产品名 |
data.tierName |
String | 档位名 |
data.departureDate |
String | 出发日期 |
data.returnDate |
String | 返团日期 |
data.totalAmount |
String | 订单总价 |
data.depositAmount |
String | 建议定金金额 |
data.depositRatio |
Integer/null | 定金比例百分比 |
data.depositMode |
String | 定金计算模式(FIXED/RATIO/FULL) |
data.paymentMode |
String | 支付模式(DEPOSIT/FULL) |
data.groupBatchId |
String/null | 运营团期 ID(创单同事务回写);非空=团订单 |
data.productBatchId |
String/null | 产品侧班期 ID(创单入参原样固化);仅供溯源 |
data.groupOrder |
Boolean | 派生值,= groupBatchId != null;直接用于判团 |
请求示例
{
"productId": 2044306857534636034,
"tierSeq": 1,
"departureDate": "2026-10-01",
"adultCount": 2,
"childCount": 1,
"customerName": "张三",
"customerPhone": "13800138000",
"productBatchId": 2052935476557328386,
"createSource": "CONSULTANT"
}
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"id": "2096414445365338113",
"orderNo": "HL20260906094527867",
"orderStatus": "PENDING_PAY",
"orderStatusName": "待支付",
"flowStatus": "AWAITING_PAY",
"flowStatusName": "待补全信息",
"flowStep": 0,
"flowStepTotal": 6,
"flowStepName": "待支付",
"productName": "冻干粉发短信给",
"tierName": "经典档",
"departureDate": "2026-10-01",
"returnDate": "2026-10-03",
"totalAmount": "5850.00",
"depositAmount": "1000.00",
"depositRatio": null,
"depositMode": "FIXED",
"paymentMode": "DEPOSIT",
"expiryMinutes": 1440,
"payUrl": "https://pay.hulalv.com/pay/HL20260906094527867",
"customerName": "张三",
"groupBatchId": "2096412454643802114",
"productBatchId": "2052935476557328386",
"groupOrder": true
}
}
实测数据示例(2026-09-06 测试服):
- 产品「冻干粉发短信给」productId=2044306857534636034
- 班期 2026-10-01 productBatchId=2052935476557328386
- 团期主键 groupBatchId=2096412454643802114
- 团期编号 batchNo=Q202610012052935476548939777
空数据 / 降级响应
创建订单成功后无空数据响应。
错误响应
{
"code": 400,
"message": "产品 ID 非法或产品已下架",
"success": false,
"data": null
}
业务边界
- 创建普通订单时,
groupBatchId/productBatchId为 null,groupOrder为 false。 - 创建 GROUP 产品订单时(必须提交
productBatchId),后端在同事务内懒创建或命中已有团期,回写groupBatchId。 groupBatchName字段当前恒为 null(仅为兼容既有前端契约),前端不要读它。- 响应中
groupBatchId/productBatchId为字符串(JSON 序列化后,避免 JS 精度丢失);前端若需数值运算应转换为字符串存储。
四、契约约束与正确调用方式
| 场景 | 正确做法 |
|---|---|
| 判断订单是否团单 | 读 groupBatchId 非空 或 groupOrder == true,两者等价 |
| 不要用 productBatchId 判团 | productBatchId 仅供溯源,可能 null(普通单)或有值(团单/非团单均可能) |
| 团单需显示团期名 | groupBatchName 恒为 null,读 batchName;团期软删时也为 null |
| 普通单与团单混合渲染 | 按 groupOrder 条件渲染,普通单该字段为 false;两类订单出参结构一致,仅值不同 |
五、数据库行为
| 订单类型 | groupBatchId | productBatchId | groupOrder | batchNo | batchName |
|---|---|---|---|---|---|
| 普通订单 | null | null | false | null | null |
| 团单(命中或懒建) | 非空 | 非空 | true | 有值 | 有值 |
| 团期已软删 | 非空 | 非空 | true | null | null |
六、边界行为
- 业务失败可能仍为 HTTP 200,必须同时检查
code、success和message。 - 详情接口 404/权限 403 时直接返回对应 HTTP 状态码;业务类失败(如订单状态不符)返回 HTTP 200 + code。
- 列表空结果返回
total=0, list=[],分页参数超界时返回空列表(无 5XX)。 - 创单失败不落库,响应 HTTP 200 + code,data 为 null。
- 新增判团字段与现有字段同源、同时刷新,无时间差。
六.6、修改前后对比
字段级对比
| 字段 | 改前 | 改后 |
|---|---|---|
groupBatchId |
无此字段 | 新增;运营团期主键 |
productBatchId |
无此字段 | 新增;产品班期 ID(仅溯源) |
groupOrder |
无此字段 | 新增;派生布尔,= groupBatchId != null |
batchNo |
无此字段 | 新增;团期编号(详情/列表) |
batchName |
无此字段 | 新增;团期名称(详情/列表) |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 前端判团依据 | 无判团字段,无法直接判别 | 读 groupBatchId 非空 或 groupOrder = true |
| 团单信息展示 | 依赖联查或额外接口 | 直接在订单响应中获得 |
| 产品班期溯源 | 不支持 | 新增 productBatchId(仅溯源展示) |
六.7、影响评估
- 是否破坏向后兼容: 否。新增字段对旧客户端透明,非必需字段缺失时前端框架可靠 null 处理。
- 前端是否必须同步上线: 是。前端需接入新增四个字段至详情/列表/创建成功弹窗模板,判团逻辑改用 groupBatchId 或 groupOrder。
- 前端 workaround 清理点:
- 删除旧的"通过产品 ID 推断团单"逻辑,改用 groupBatchId 判别
- 不要硬编码团期编号/名称,改用响应中的 batchNo / batchName
- groupBatchName 恒为 null,勿读之;用 batchName 替代
七、不影响范围
- 仅影响: 管理后台订单详情、列表和创建流程的前端渲染
- 零影响:
- 订单创建/编辑/取消接口
- 小程序端(MpOrderDetailVO 不变)
- 数据库结构(新字段冻结在 order_main 表,无表改动)
- 订单写操作和业务流程
八、测试环境已验证
- 单测: 559 条测试用例绿✓(新增判团字段相关的 UT 已覆盖普通单/团单双路径)
- ArchTest: 45 条架构测试绿✓
- 测试服网关实测: 单测 + CR 通过;测试服网关实测见管理者补充
实测产品: productId=2044306857534636034(冻干粉发短信给),班期 2026-10-01(productBatchId=2052935476557328386),团期主键 groupBatchId=2096412454643802114,批号 batchNo=Q202610012052935476548939777。
九、相关历史 PR(功能演进)
| PR | Issue | 说明 | 是否仍有效 |
|---|---|---|---|
| #7083 | - | order_group_batch 一跳直连,订单主表冻结 groupBatchId/productBatchId | ✅ 有效 |
| #7135 | - | GROUP 产品创单校验与重整 | ✅ 有效 |
| #7143 | - | 团期看板 VO 补 productId(配合本 PR) | ✅ 有效 |
| 本 PR #7155 | #7142 | 订单详情/列表/创单响应透出判团字段 | ✅ 最新 |
十、相关文档
- 关联 Issue: wx/HL#7142
- 关联 PR: wx/HL#7155
- 团期接口文档:
docs/ARCHITECTURE.md§0A.2.2(团单冻结口径) - 团单业务规范: 见 #7135 changelog 中的团期创建规则
关联 / 联系人
链接
联系人
- 后端负责人: @wx