diff --git a/changelogs-v2/2026-06/54_4645_用房需求候选升级为方案_一个方案支持多房型行_选酒店选房型_前端对接-管理后台.md b/changelogs-v2/2026-06/54_4645_用房需求候选升级为方案_一个方案支持多房型行_选酒店选房型_前端对接-管理后台.md new file mode 100644 index 0000000..9a30f8c --- /dev/null +++ b/changelogs-v2/2026-06/54_4645_用房需求候选升级为方案_一个方案支持多房型行_选酒店选房型_前端对接-管理后台.md @@ -0,0 +1,66 @@ +# 用房需求「候选」升级为「方案」:一个方案=1酒店+多条房型行各自房数 + 选酒店时选房型 + +> 模块:订单 · 用房需求(调整订单 → 酒店安排)/ 订单详情行程 / 房务详情(管理后台) +> 类型:后端结构升级 + 前端对接(additive,向后兼容) +> 日期:2026-06-29 +> 关联:PR #4654(已合并 dev-v3 + 部署测试服 + API E2E 实测闭环) + +## 背景(wx 手测发现) +1. 定制师提用房需求时「**海拉尔海棠·精品标间双床×2** 或 **海拉尔嘉世豪·标准间大床×1 + 豪华大床房×2**」二选一,**选不出来**。根因:旧模型一个候选只能挂 1 个房型、房间数是「段级」单值,无法表达「一个方案=一家酒店的多个房型各自房数」。 +2. 「选择酒店」弹窗显示**酒店级**协议价/可用房 —— 协议价/库存本是**房型**属性,单值有误导。 + +## 模型升级(候选 → 方案) +「候选(candidate)」语义升级为「方案(option)」:**一个方案 = 1 家酒店 + ≥1 条房型行**,每条房型行各自房型/房数/协议价;房控仍在同段多个方案中**择一**回配。房数/房型/协议价从「段级 + 候选级」**下沉到行级**。 + +**默认一个方案**:前端每段默认建 1 个方案、方案默认 1 条房型行(与旧交互等价)。 + +## 一、提交用房需求(写):`PUT /v3/admin/order/{id}/hotel-requirement` +请求体 `days[].segments[].candidates[]` 内**新增 `rooms[]`** 房型行数组: + +```jsonc +{ + "days": [{ + "dayNumber": 1, + "segments": [{ + "remark": "段备注(选填)", + "candidates": [ + { "hotelId": 3001000000000000002, "hotelName": "海拉尔海棠酒店", "remark": "方案A", + "rooms": [ {"roomTypeId": 3002000000000000002, "roomTypeName": "精品标间", "roomCategory": "STANDARD", "roomCount": 2} ] }, + { "hotelId": 2029926129876320258, "hotelName": "海拉尔嘉世豪酒店", "remark": "方案B", + "rooms": [ + {"roomTypeId": 2029944763138936833, "roomTypeName": "标准间", "roomCategory": "STANDARD", "roomCount": 1}, + {"roomTypeId": 2029944763138936834, "roomTypeName": "豪华大床房", "roomCategory": "DELUXE", "roomCount": 2} + ] } + ] + }] + }] +} +``` + +- **`rooms[]` 每行字段**:`roomTypeId`(必填,真实房型)、`roomTypeName`、`roomCategory`(房型大类字典码)、`roomCount`(必填,>0)、`protocolPrice`(选填快照,后端按协议价反查覆盖)、`remark`。 +- 房间数现落在**每条房型行**(不再是段级单值);一个方案可含多条房型行(=同一酒店多个房型各自房数)。 +- **预算**:`segment.budget` 仍是「预算/晚」,后端按协议价反查覆盖为段内各房型行协议价的**最大值**(前端传值不作数)。 +- **校验**:每方案至少 1 条房型行;新结构每行 `roomTypeId` 必填、`roomCount` > 0(否则 582019/582020/582016)。 +- **兼容**:旧结构(段级 `roomCount`/`roomCategory` + 候选级 `roomTypeId`,无 `rooms[]`)仍被接受,后端自动合成单行;旧前端无需立即改。 + +## 二、回显(读):订单详情行程 + 房务详情 +**订单详情行程** `GET /v3/admin/order/{id}/itinerary` → `hotelGroup.requirement.days[]`: +- 逐家明细 `hotels[]` 每项、逐段候选 `segments[].candidates[]` 每项**新增 `rooms[]`**,每条房型行 7 字段:`roomTypeId / roomTypeName / roomCategory / roomCategoryLabel(中文) / roomCount / protocolPrice / remark`。 +- `totalRoomCount` / `roomTypeSummary` 口径:候选择一,按各段**首方案**的房型行汇总。 +- 候选/段级 `roomCount`/`roomCategory`/`roomTypeId` 仍保留为**代表值**(新结构由 rooms 派生),旧前端可继续读;新前端请改用 `rooms[]`(权威)。 + +**房务详情** `GET /admin/house/orders/{orderId}` → `requirement.current.days[]` 的 `hotels[]` 与 `segments[].candidates[]` 同样新增 `rooms[]`(同 7 字段,含中文 label)。 + +## 三、选酒店时选房型(解决背景②,纯前端) +`GET /v3/admin/hotel-candidates` 每家候选**已返回 `roomTypes[]`**(每个房型自带 `protocolPrice` 协议价 / `available` 可用房 / `unlimited` / `inventoryStatus`)。 +- 【前端处理】「选择酒店」弹窗请把每家**展开到房型行**,让定制师选「酒店 + 房型」,协议价/可用房**按所选房型显示**(不要再在酒店级显示单值协议价/库存,避免误导)。 +- 选好的房型即填入该方案的 `rooms[]` 一行(`roomTypeId` + `roomTypeName` + `roomCategory` + `roomCount`,可带 `protocolPrice` 快照)。 + +## 【前端必做】 +1. 调整订单「酒店安排」:每个方案支持**多条房型行**(房型 + 房间数),默认 1 方案 1 行;提交按上方 `rooms[]` 结构。 +2. 「选择酒店」弹窗:展开房型行,选「酒店+房型」,协议价/库存按房型显示。 +3. 订单详情/房务详情:按 `candidates[].rooms[]` / `hotels[].rooms[]` 逐房型行渲染(用 `roomCategoryLabel` 中文 + `roomCount` + `protocolPrice`)。 + +## 兼容性 +- **无 DB 迁移**(days 为 JSON 列);旧订单/旧请求照常工作(后端合成单行 rooms)。 +- 不影响金额/库存:房务配房扣库存仍走房务自填的配房项,与本需求模型解耦。