# 配房接口升级 — 按天粒度 + 房型升级差价自动计算

> 日期：2026-03-20 | 涉及服务：hl-order-service、hl-resource-service

## 功能说明

配房接口从「按家庭+日期区间」改为「按天按家庭」粒度，每天可填备注。同时新增**房型升级差价自动计算**：如果配房时选的房型与产品默认不同（CORE产品默认标间），系统自动算出差价，临时加到尾款中，等定制师确认后正式生效。

---

## 接口变更清单

### 1. 分配酒店信息（**破坏性变更**）

```
PUT /admin/order/{orderId}/hotel-assignment
```

**请求体变更**：assignments 数组结构改为按天粒度

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| assignments | Array | 是 | 酒店分配列表（按天按家庭，每天每个家庭一条） |
| assignments[].familyIndex | Integer | 是 | 家庭序号 |
| assignments[].hotelId | Long | **是（新增）** | 酒店ID |
| assignments[].hotelName | String | 是 | 酒店名称 |
| assignments[].roomTypeId | Long | **是（新增）** | 房型ID |
| assignments[].roomType | String | 是 | 房型名称 |
| assignments[].date | String | **是（新增，替代 checkInDate/checkOutDate）** | 单天日期，格式 `yyyy-MM-dd` |
| assignments[].remark | String | 否（新增） | 当天备注 |
| assignments[].upgradePrice | BigDecimal | 否（新增） | 手动覆盖升级差价（null=使用系统计算值） |

**删除的字段**：`checkInDate`、`checkOutDate`

**示例请求**：
```json
{
  "assignments": [
    {
      "familyIndex": 1,
      "hotelId": 1001,
      "hotelName": "呼伦贝尔大酒店",
      "roomTypeId": 2001,
      "roomType": "豪华大床房",
      "date": "2026-04-01",
      "remark": "需要加床"
    },
    {
      "familyIndex": 1,
      "hotelId": 1001,
      "hotelName": "呼伦贝尔大酒店",
      "roomTypeId": 2001,
      "roomType": "豪华大床房",
      "date": "2026-04-02",
      "remark": ""
    },
    {
      "familyIndex": 2,
      "hotelId": 1001,
      "hotelName": "呼伦贝尔大酒店",
      "roomTypeId": 2002,
      "roomType": "标间",
      "date": "2026-04-01",
      "remark": ""
    }
  ]
}
```

**房型升级逻辑（自动触发）**：
- 如果分配的 roomTypeId 与产品快照中该天默认房型不同 → 自动计算差价
- CORE产品（快照中 roomTypeId 为 null）→ 默认基准为该酒店的标间（STANDARD）
- 差价 = 新房型日价格 - 默认房型日价格（来自价格日历）
- `upgradePrice` 可手动覆盖系统计算的差价
- **定制师操作**：差价自动确认，直接调整订单总售价
- **其他角色操作**：差价设为「待确认」临时加到尾款，通知定制师确认

**响应**：无变化，`Result<Void>`

---

### 2. 配房升级差价预览（**新增接口**）

```
POST /admin/order/{orderId}/hotel-assignment/preview
```

**说明**：预览配房的房型升级差价（不创建任何记录），前端可在用户提交配房前展示差价信息。

**请求体**：同分配酒店信息接口

**响应**：`Result<RoomUpgradePreviewVO>`

| 字段 | 类型 | 说明 |
|------|------|------|
| details | Array | 各天差价明细（仅有差价的天） |
| details[].familyIndex | Integer | 家庭序号 |
| details[].date | String | 日期 |
| details[].defaultRoomTypeId | Long | 产品默认房型ID |
| details[].defaultRoomTypeName | String | 产品默认房型名称 |
| details[].assignedRoomTypeId | Long | 实际分配房型ID |
| details[].assignedRoomTypeName | String | 实际分配房型名称 |
| details[].defaultPrice | BigDecimal | 默认房型当天单价 |
| details[].assignedPrice | BigDecimal | 实际房型当天单价 |
| details[].dayDiff | BigDecimal | 当天差价（正=补款，负=退款） |
| details[].direction | String | UPGRADE / DOWNGRADE / SAME |
| details[].remark | String | 备注 |
| totalDiff | BigDecimal | 差价合计 |
| direction | String | UPGRADE / DOWNGRADE / SAME / MIXED |
| description | String | 差价描述 |

**示例响应**：
```json
{
  "code": 200,
  "data": {
    "details": [
      {
        "familyIndex": 1,
        "date": "2026-04-01",
        "defaultRoomTypeId": 2002,
        "defaultRoomTypeName": "标间",
        "assignedRoomTypeId": 2001,
        "assignedRoomTypeName": "豪华大床房",
        "defaultPrice": 300.00,
        "assignedPrice": 500.00,
        "dayDiff": 200.00,
        "direction": "UPGRADE",
        "remark": "需要加床"
      }
    ],
    "totalDiff": 200.00,
    "direction": "UPGRADE",
    "description": "共 1 天有差价，合计 +200.00"
  }
}
```

---

### 3. 尾款调整汇总（**字段增强**）

```
GET /admin/order/{orderId}/itinerary/balance-summary
```

**响应新增字段**：

| 字段 | 类型 | 说明 |
|------|------|------|
| confirmedAdjustment | BigDecimal | **新增** — 已确认的调整金额（已计入总售价） |
| pendingAdjustment | BigDecimal | **新增** — 待确认的调整金额（临时，待定制师确认） |
| totalAdjustment | BigDecimal | 合计（已确认 + 待确认） |
| details[].confirmStatus | String | **新增** — `CONFIRMED` 或 `PENDING_CONFIRM` |

---

## 页面影响

### 配房页面
1. **数据结构改造**：从日期区间改为按天列表，每天一条记录
2. **新增字段**：每天增加备注输入框（remark）
3. **房型选择联动**：选择房型后，调用 preview 接口展示差价
4. **差价展示**：如果有差价，在提交前展示差价明细和合计，支持手动修改 upgradePrice
5. **提交**：PUT hotel-assignment 时传入完整按天列表

### 订单详情页 — 尾款区域
1. 展示「已确认调整」和「待确认调整（临时）」两个金额
2. 待确认项标记为临时状态，提示「待定制师确认」

### 推荐交互流程
```
选择酒店+房型 → 填写每天备注 → 点击「预览差价」
  → 展示差价明细（可修改 upgradePrice）
  → 点击「确认配房」→ 调用 PUT hotel-assignment
```
