14 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 | 8030 | 全团需求汇总逐日房间补酒店维度与住宿日期 | admin | jw(GIT) | 修改接口 | deployed | not_required | verified | mmg | 9a14ad866b3ef6ac9acb0ca9ab9e9f0fe98f6559 | 2026-09-20 | 全团需求汇总 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、间数照常。 前端实证维持 not_required(mmg 2026-09-20):requirement-summary/dailyRoomBreakdown/stayDate(本端点义)/hotels 全仓零命中(同 #7925/#7937/#8023 第四次实证,汇总端点未接入);「用房·汇总」表属新功能排期,届时 stayDate null 按 Day N 展示、hotelName null 显「未知酒店」不隐藏行、全天合计直读 rooms[] 不跨酒店累加、hotelId 字符串。 2026-09-20 前端接入(mmg):「用房 · 汇总」建页随 hl-admin v2.1 交付——requirement-summary 经 getGroupRequirementSummary 接入「查看需求」页 RoomSummarySection:户数条(在团/需订房/已提交)+不一致只提示不扣减+Day N|酒店|房型|所需间数扁平表;stayDate null 按 Day N、hotelName null 显「未知酒店」不隐藏行、roomCategoryName null 回落编码、全天合计直读 rooms[] 禁跨酒店累加、hotelId null 组间数不丢;整团确认/按户打回后自动重拉。定向 Vitest 17/17,checkpoint 全绿。 2026-09-20 后端回填订正(mmg 复核):降级错误码 589574→589596(589574 是 #7932 保留位冲突),该码只在服务端降级日志产生、从不传播前端,前端零影响;TEST AC-1~11 回填全✓。frontmatter 维持 verified 不动。 | 2026-09-20 | dev-v3 |
order-v3: 全团需求汇总逐日房间补酒店维度与住宿日期
服务: hl-order-service-v3 (端口 8086) PR: #8040(主体)、#8041(验收补丁:按酒店分组那份补房型中文名) Issue: #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[]) |
| 其余既有字段 | — | 不变(无删除、无改名、无类型变化) |
请求示例
GET /v3/admin/order/group-batch/2101506167098511362/requirement-summary
Authorization: Bearer <token>
响应示例
{
"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、间数与分组照常返回,接口不报错。
错误响应
{ "code": 589507, "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", "data": null, "success": false }
| code | 触发条件 |
|---|---|
| 589507 | 当前角色没有 group-batch:view(本次不变) |
| 589500 | 团期不存在(本次不变) |
| 401 | 未登录(网关拦截) |
本次新增内部错误码 589596(资源服务住宿名称补全降级),只在服务端降级日志里出现,不会传播给前端。(初版误取 589574,该号是 #7932 的保留位,已于 2026-09-20 随 #8046 订正为 589596。)
业务边界
- 间数不变量:任一天
Σ 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 环境(hl-order-service-v3,dev-v3,2026-09-20),团期 jw测试1期(2101506167098511362,出发 2026-09-27,6 晚)。
AC-1 单户 6 晚逐晚不同酒店,hotels[] 与 hotelName 正确 ✓
AC-2 同天多户不同酒店 → 出多条并按间数降序;同一酒店合并且间数相加 ✓
AC-3 间数不变量 Σhotels == Σrooms:单测 + TEST 六天逐日实测 ✓
AC-4 stayDate = 出发日 + dayNumber − 1,跨月 09-30 → 10-01 正确 ✓
AC-5 字符串形态 hotelId 的存量 days JSON 正确解析(TEST 数据本就是字符串)✓
AC-6 候选缺失 / hotelId 为空 → 归「未指定」一条恒排末位,间数不丢 ✓
AC-7 酒店名:快照优先;快照置空后按 ID 批量补,实测补出正确名称 ✓
AC-8 既有字段零变化:三个户数 / rooms[] / vehicleSeatSummary /
orderSpecialTags 与改前逐字一致 ✓
AC-9 客户自订晚仍不计入(该日由 3 间降为 2 间) ✓
AC-10 判权:低权限角色 1002/user → 589507;超管 200 ✓
AC-11 changelog 按「修改接口」推送(提交 af00e6f) ✓
订正(2026-09-20,#8046 回归发现):本单新增的降级错误码原取 589574,该号被 #7932 登记为保留位且有测试断言它必须空闲,#8030 当轮回归范围未覆盖该测试类故漏网。 现已改为 589596(见下方「五、错误码」与 PR #8055 第一个提交)。 该码只在服务端降级路径产生,从不传播给前端,对前端无影响。