# 配房统一换酒店写口 — 去「换酒店」按钮 + 回显已配酒店 + 根治配房重提超卖

> 变更类型：♻️ 重构（后端，**房务管家前端需配合：去换酒店按钮 + 候选回显**）
> 端类型：管理后台（房务管家·配房/换酒店）
> 日期：2026-06-25 ｜ 工单：#4401 ｜ PR：#4407（在 #4402 基础上重写）｜ 服务：hl-order-service-v3（双实例已部署 health UP，**测试服 API+DB 实测全通过**）

---

## 背景
「配房」与「换酒店」本质同一功能（同城同日选酒店+房型）。原两个按钮/两条后端路径，且换酒店候选漏传 roomTypeId 导致提交报 `808403 新酒店库存扣减失败`。本单把换酒店**并入配房保存唯一写口**，去换酒店按钮，并根治「配房重提同天换酒店→新店不扣(超卖)/旧店不释放(泄漏)」潜伏 P0。

---

## 前端必改（房务管家，mmg）

### 1. 去掉「换酒店」按钮，改房统一走「配房」
- **换酒店 3 个端点已删除**，前端停止调用：
  - `GET /v3/admin/order/swap-hotel/candidates`（删）
  - `POST /v3/admin/order/swap-hotel/preview`（删）
  - `POST /v3/admin/order/swap-hotel/commit`（删）
- **改房统一走配房保存**：`POST /v3/admin/order/hotel-requirements/{requirementId}/assignments`（§2.2，原配房保存接口）。给某天提交一个新的酒店/房型 item 即完成「换酒店」——后端自动识别：同酒店同房型同间数=幂等不动；酒店/房型/间数变=替换（释放旧店库存+扣新店+软删旧行+保留 swap 血缘+发换店通知）。**一个 item 一个 (天,酒店,房型)，同天同三元组不要重复提交**（后端 808117 拒，请合并间数）。

### 2. 配房候选回显「本天当前已配酒店」（用户要求）
`GET /v3/admin/hotel-candidates?orderId=&dayNumber=` 候选项 `candidates[]` **新增 2 字段**：
- `isCurrentlyAssigned`（Boolean）：该候选是否=本天当前已配酒店。前端据此**高亮/默认选中**原酒店。
- `assignedRoomTypeId`（String 雪花）：本天已配的房型 ID，供**预填原房型下拉**。
- 已配酒店**保证出现在候选结果中**（即使排序靠后也强制保留，不被 limit 截断）。
- 候选项本就含 `tags`（运营标签）、`roomTypes[]`（roomTypeId/房型/协议价/可用数）——换酒店选房直接复用配房候选这套，标签照常展示。

### 3. 订单详情 currentAssignment 补 roomTypeId
`GET /admin/house/orders/{orderId}` → `itinerary[].currentAssignment` **新增 `roomTypeId`**（String 雪花），供详情侧精确回显/预填原房型。

---

## 后端行为（前端知悉即可）
- 配房保存按天对账：某天换酒店时先释放旧酒店库存、再用隔离幂等键扣新酒店（根治同天多房型/换店复用键短路不扣的超卖），软删旧行后新行 `swap_from_id` 指向旧行。
- 换酒店（hotelId 真变）仍发 3 条通知（旧店/新店/客户，走通知中心）+ 写 SWAP_SUCCESS 审计 + 自动归档 SWAP_HOTEL 待办。
- 原 `808403` 不再复现（配房候选自带 roomTypeId）。

---

## 测试服实测（已通过）
- 回显：候选 day2 正确标已配酒店 `isCurrentlyAssigned=true`+`assignedRoomTypeId`；详情 currentAssignment 返 roomTypeId。
- 换酒店：配房保存换某天酒店 → 旧行软删+库存释放、新行 swap 血缘、每天仅 1 active、新旧幂等键隔离真扣。
- 多房型同天：一次提交 2 房型 → 各自独立扣减（键不同、不短路）。
