docs(changelog): order-v3 全团需求汇总逐日房间补酒店维度与住宿日期(#8030)
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
这个提交包含在:
@@ -0,0 +1,248 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "8030"
|
||||
title: "全团需求汇总逐日房间补酒店维度与住宿日期"
|
||||
consumer: "admin"
|
||||
author: "jw(GIT)"
|
||||
change_type: "修改接口"
|
||||
backend_status: "deployed"
|
||||
gateway_status: "not_required"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: "mmg"
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: "2026-09-20"
|
||||
status_note: "全团需求汇总 GET /v3/admin/order/group-batch/{groupBatchId}/requirement-summary 的 dailyRoomBreakdown 纯增两项:stayDate(该晚住宿日期 = 团期出发日 + dayNumber - 1,团期无出发日时为 null)与 hotels[](该晚按酒店分组的用房,含 hotelId / hotelName / totalRoomCount / rooms[])。原有 rooms[](不分酒店的全天合计)与其余字段一个没动。这样团期「查看需求」页的「用房 · 汇总」表(Day N | 酒店 | 房型 | 所需间数)一个接口就能画完,不必逐户调订单调整快照去拼酒店,也不必等房务建完订房计划——后者在成团前根本没有数据。口径:与 rooms 同一次遍历的两个视角,任一天 Σhotels[].totalRoomCount == Σrooms[].totalRoomCount;每段只取首方案候选(候选是房控择一,累加全部会翻倍);取不到酒店的段归 hotelId=null 一条且恒排末位,间数不丢;酒店名优先取需求里落库的快照,缺失的按 ID 一次批量补,资源服务不可用时名称为 null、间数照常。"
|
||||
updated_at: "2026-09-20"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# order-v3: 全团需求汇总逐日房间补酒店维度与住宿日期
|
||||
|
||||
> **服务**: hl-order-service-v3 (端口 8086)
|
||||
> **PR**: [#8040](https://git.1814.love:8443/wx/HL/pulls/8040)(主体)、[#8041](https://git.1814.love:8443/wx/HL/pulls/8041)(验收补丁:按酒店分组那份补房型中文名)
|
||||
> **Issue**: [#8030](https://git.1814.love:8443/wx/HL/issues/8030)
|
||||
> **日期**: 2026-09-20
|
||||
> **影响范围**: 管理后台「团期订单 → 查看需求」页的「用房 · 汇总」表
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 关键变化
|
||||
|
||||
- **纯增两项**:`dailyRoomBreakdown[].stayDate`、`dailyRoomBreakdown[].hotels[]`。既有字段一个没删没改,入参与路径不变。
|
||||
- **一个接口画完整张表**:此前「酒店」这一列只能逐户调 `GET /v3/admin/order/{orderId}/adjustment/snapshot` 去拼,或等房务建完订房计划(`room-plans`,成团前为空)。
|
||||
- **两个视角、同一批间数**:`hotels[]` 与 `rooms[]` 是同一次遍历的两个视角,任一天间数总和必然相等。
|
||||
- **不改任何口径**:计入哪些户、哪些需求算数,全部沿用 #7925 / #8023 的既有判定。
|
||||
|
||||
---
|
||||
|
||||
## 一、背景
|
||||
|
||||
原型「用房 · 汇总」要的是「Day N | 酒店 | 房型 | 所需间数」,而汇总此前只给房型与间数,酒店这一列没有数据源:
|
||||
|
||||
| 想要的列 | 改前只能这么拿 | 问题 |
|
||||
|---|---|---|
|
||||
| 间数 + 房型 | `requirement-summary` | ✅ 有 |
|
||||
| 酒店 | 逐户 `adjustment/snapshot` | N 户调 N 次,且那是为「订单调整」设计的重接口 |
|
||||
| 酒店(房务实际订房) | `room-plans` | **要房务认领并建计划之后才有数据**,成团前为空 |
|
||||
| 住宿日期 | 无 | 只有 `dayNumber` |
|
||||
|
||||
TEST 实证(团期 `jw测试1期`,招募中):`room-plans` 返回 `days: []`、`progress: NOT_STARTED` —— 运营恰恰要在成团前按这张表向酒店报数。
|
||||
|
||||
---
|
||||
|
||||
## 二、变更接口清单
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---|------|------|------|----------|------|
|
||||
| 1 | 全团需求汇总 | GET | `/v3/admin/order/group-batch/{groupBatchId}/requirement-summary` | 修改 | `dailyRoomBreakdown[]` 纯增 `stayDate` 与 `hotels[]` |
|
||||
|
||||
---
|
||||
|
||||
## 三、接口详情
|
||||
|
||||
### 1. 全团需求汇总 `GET /v3/admin/order/group-batch/{groupBatchId}/requirement-summary`
|
||||
|
||||
**VO**: `Result<GroupRequirementSummaryRespVO>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
团期详情「查看需求」页的「用房 · 汇总」表:逐日列出住哪家酒店、什么房型、要几间,运营据此向酒店报数。
|
||||
|
||||
#### 入参
|
||||
|
||||
本次入参**不变**。
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| groupBatchId | Path | Long | ✅ | 团期 ID | 团期不存在返回 589500 |
|
||||
|
||||
#### 出参
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| dailyRoomBreakdown[].dayNumber | Integer | 第几天(不变) |
|
||||
| dailyRoomBreakdown[].stayDate | String(yyyy-MM-dd) | **新增**。该晚住宿日期 = 团期出发日 + dayNumber − 1;团期无出发日时为 `null`(不推算) |
|
||||
| dailyRoomBreakdown[].rooms[] | List | 该天各房型合计,**不分酒店**(不变) |
|
||||
| dailyRoomBreakdown[].hotels[] | List | **新增**。该天按酒店分组的用房 |
|
||||
| dailyRoomBreakdown[].hotels[].hotelId | String | 酒店 ID(字符串序列化防 JS 精度丢失);取不到酒店时为 `null` |
|
||||
| dailyRoomBreakdown[].hotels[].hotelName | String | 酒店名;资源服务不可用时为 `null` |
|
||||
| dailyRoomBreakdown[].hotels[].totalRoomCount | Integer | 该天该酒店合计间数 |
|
||||
| dailyRoomBreakdown[].hotels[].rooms[] | List | 该天该酒店各房型合计(结构同上面的 `rooms[]`) |
|
||||
| 其余既有字段 | — | 不变(无删除、无改名、无类型变化) |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/group-batch/2101506167098511362/requirement-summary
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"activeOrderCount": 3,
|
||||
"hotelNeededOrderCount": 2,
|
||||
"hotelSubmittedOrderCount": 2,
|
||||
"hotelFlagMismatchOrderCount": 1,
|
||||
"dailyRoomBreakdown": [
|
||||
{
|
||||
"dayNumber": 1,
|
||||
"stayDate": "2026-09-27",
|
||||
"rooms": [{"roomCategory": "KING", "roomCategoryName": "豪华大床", "totalRoomCount": 3}],
|
||||
"hotels": [
|
||||
{
|
||||
"hotelId": "2023714929877450753",
|
||||
"hotelName": "呼伦贝尔香格里拉大酒店",
|
||||
"totalRoomCount": 3,
|
||||
"rooms": [{"roomCategory": "KING", "roomCategoryName": "豪华大床", "totalRoomCount": 3}]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"vehicleSeatSummary": [],
|
||||
"orderSpecialTags": []
|
||||
},
|
||||
"traceId": null,
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
- 全团无计入需求时 `dailyRoomBreakdown` 为 `[]`(不是 null),不调房型字典、不调资源服务。
|
||||
- 某天全部段都取不到酒店时,`hotels[]` 只有一条 `hotelId: null` 的记录,间数照常。
|
||||
- 资源服务不可用时只有 `hotelName` 为 `null`,`hotelId`、间数与分组照常返回,接口不报错。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
```json
|
||||
{ "code": 589507, "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", "data": null, "success": false }
|
||||
```
|
||||
|
||||
| code | 触发条件 |
|
||||
|------|----------|
|
||||
| 589507 | 当前角色没有 `group-batch:view`(本次不变) |
|
||||
| 589500 | 团期不存在(本次不变) |
|
||||
| 401 | 未登录(网关拦截) |
|
||||
|
||||
本次新增内部错误码 589574(资源服务住宿名称补全降级),**只在服务端降级日志里出现,不会传播给前端**。
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- **间数不变量**:任一天 `Σ hotels[].totalRoomCount == Σ rooms[].totalRoomCount`。两者是同一次遍历的两个视角,不是两套统计。
|
||||
- **只取首方案**:一段有多个候选酒店时只计 `candidates[0]`。候选是房控择一、不是都要,累加全部会让采购分母翻倍。
|
||||
- **取不到酒店的段**(没有候选、或候选未填酒店)归到 `hotelId: null` 一条,**不丢间数**;该条恒排在**最后**,即使它间数最多。
|
||||
- **排序**:其余酒店按间数降序,同数按 hotelId 升序(稳定)。
|
||||
- **酒店名来源**:优先取需求里落库的快照;快照缺的按 ID 一次批量补(不逐个查)。酒店改名后快照会旧,以补齐结果为准。
|
||||
- **计入口径不变**:哪些户、哪些需求算数完全沿用 #7925 / #8023;客户自订晚仍整晚跳过。
|
||||
|
||||
---
|
||||
|
||||
## 四、契约约束与正确调用方式
|
||||
|
||||
- 画「用房 · 汇总」表用 `hotels[]`;要「这一天一共几间」用 `rooms[]`。**不要**把 `hotels[]` 里的间数再跨酒店累加去当全天合计——直接读 `rooms[]` 即可,两者本就相等。
|
||||
- `hotelId` 是**字符串**,不要用 JS 的 Number 解析。
|
||||
- `hotelName` 可能为 `null`(资源服务降级 / 该酒店已删),前端按「未知酒店」展示即可,**不要**因此隐藏整行——间数仍然有效。
|
||||
- `stayDate` 可能为 `null`(团期未排出发日),此时按 `Day N` 展示。
|
||||
|
||||
---
|
||||
|
||||
## 六、边界行为
|
||||
|
||||
| 场景 | 行为 |
|
||||
|------|------|
|
||||
| 多户订同一家酒店 | 合并为一条,间数相加 |
|
||||
| 同一晚多户订不同酒店 | `hotels[]` 出多条,按间数降序 |
|
||||
| 一段有多个候选酒店 | 只计首方案,不重复计数 |
|
||||
| 段未填酒店 / hotelId 脏值 | 归 `hotelId: null` 一条并排末位,间数不丢 |
|
||||
| 客户自订晚 | 整晚跳过(不变) |
|
||||
| 团期无出发日 | `stayDate` 为 null,不推算 |
|
||||
| 资源服务不可用 | `hotelName` 为 null,其余照常 |
|
||||
|
||||
---
|
||||
|
||||
## 六.6、修改前后对比
|
||||
|
||||
### 字段级对比
|
||||
|
||||
| 字段 | 改前 | 改后 |
|
||||
|------|------|------|
|
||||
| `dailyRoomBreakdown[].stayDate` | 无 | 新增,String(yyyy-MM-dd),可为 null |
|
||||
| `dailyRoomBreakdown[].hotels[]` | 无 | 新增,List |
|
||||
| `dailyRoomBreakdown[].rooms[]` | — | 不变 |
|
||||
| 其余既有字段 / 入参 / 路径 / 错误码 | — | 不变 |
|
||||
|
||||
### 行为级对比
|
||||
|
||||
| 场景 | 改前 | 改后 |
|
||||
|------|------|------|
|
||||
| 画「用房 · 汇总」表 | 逐户调 `adjustment/snapshot` 拼酒店,或等房务建订房计划 | 一个接口出数 |
|
||||
| 成团前查逐日酒店 | 无数据源(`room-plans` 为空) | 直接从各户已提交需求汇总 |
|
||||
| 逐日间数与房型 | 已有 | 逐字不变 |
|
||||
|
||||
## 六.7、影响评估
|
||||
|
||||
- **是否破坏向后兼容**: 是纯增字段,完全兼容;既有 `rooms[]` 数值逐字不变。
|
||||
- **前端是否必须同步上线**: 否。不接入则页面保持现状。
|
||||
- **回滚**: 回滚本 PR 即可,只读接口、无数据变更。
|
||||
|
||||
---
|
||||
|
||||
## 七、不影响范围
|
||||
|
||||
- **仅影响**: 本接口 `dailyRoomBreakdown[]` 的两个新增字段。
|
||||
- **零影响**: 计入户口径与三个户数、用车座位合计、各户特殊需求标签、整体确认预检、房务侧订房与分房、`room-plans`、`adjustment/snapshot`、数据库结构(只读接口,无表变更、无 Flyway)。
|
||||
|
||||
---
|
||||
|
||||
## 八、测试环境已验证
|
||||
|
||||
```
|
||||
待部署 TEST 后回填实测结果(工单 #8030 AC-1~AC-11)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、相关文档
|
||||
|
||||
- 工单 [#8030](https://git.1814.love:8443/wx/HL/issues/8030)
|
||||
- 计入口径前置:[#7925](https://git.1814.love:8443/wx/HL/issues/7925)、[#8023](https://git.1814.love:8443/wx/HL/issues/8023)
|
||||
|
||||
---
|
||||
|
||||
## 关联 / 联系人
|
||||
|
||||
### 链接
|
||||
|
||||
- **Issue**: [#8030](https://git.1814.love:8443/wx/HL/issues/8030)
|
||||
- **PR**: [#8040](https://git.1814.love:8443/wx/HL/pulls/8040)、[#8041](https://git.1814.love:8443/wx/HL/pulls/8041)
|
||||
|
||||
### 联系人
|
||||
|
||||
- **后端负责人**: @jw
|
||||
- **前端负责人**: @mmg
|
||||
在新工单中引用
屏蔽一个用户