# mp/admin /quote 接口补单房差遗漏

> **服务**: hl-product-service-v2(8093)
> **PR**: #1905 (Refs #1900)
> **日期**: 2026-05-09
> **影响范围**: 管理端 + 小程序订单确认页报价接口

---

## ⚠️ 关键变化

PR #1901 加单房差时只改了 `simpleQuote` / `getGroupQuote` 两条算价路径,**漏掉第三条** `ProductPricingService.calculateQuote`,导致以下两个接口不展示单房差:

- `POST /admin/product/item/{id}/quote`(管理端报价)
- `POST /mp/product/{id}/quote`(C 端报价)

本 PR 补齐:响应 +2 字段 `singleRoomDiff` + `singleRoomSurcharge`,`adultCount==1` 时 `grandTotal` 含单房差,**比例定金按 baseTotal 算(D2 不变)**。

---

## 一、变更接口清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 管理端报价 | POST | `/admin/product/item/{id}/quote` | 响应 +2 字段 | `singleRoomDiff` + `singleRoomSurcharge`;`adultCount==1` 时 `grandTotal` 含单房差 |
| 2 | C 端报价 | POST | `/mp/product/{id}/quote` | 响应 +2 字段 + 行为变更 | 同 #1 + 比例定金按 baseTotal 算 |
| 3 | 内部 mp 报价 | POST | `/internal/mp/product/{id}/quote` | 响应 +2 字段 | 同 #1 |

> **PR #1901 已支持的接口**(本 PR 不动):`/internal/product/{id}/simple-quote` / `/internal/product/{id}/group-quote`

## 二、响应示例

**`POST /mp/product/{productId}/quote` 请求**:

```json
{
  "departureDate": "2026-07-01",
  "adultCount": 1,
  "childCount": 0,
  "toddlerCount": 0,
  "infantCount": 0,
  "tierSeq": 1
}
```

**响应**(产品配 `singleRoomDiff=200`,`depositRatio=10%`):

```json
{
  "code": 200,
  "data": {
    "adultUnitPrice": 3980.00,
    "totalAdultPrice": 3980.00,
    "singleRoomDiff": 200.00,
    "singleRoomSurcharge": 200.00,
    "grandTotal": 4180.00,
    "paymentType": "DEPOSIT",
    "depositRatio": 10,
    "depositAmount": 398.00,
    "balanceAmount": 3782.00
  }
}
```

- `grandTotal = 4180`(成人 3980 + 单房差 200)
- `depositAmount = 398`(= **baseTotal 3980** × 10%,**不是** 4180 × 10% = 418)— D2 比例定金口径自洽
- `balanceAmount = grandTotal - depositAmount = 3782`(尾款含单房差)

**`adultCount=2` 不触发**:

```json
{
  "data": {
    "singleRoomDiff": 200.00,
    "singleRoomSurcharge": 0,
    "grandTotal": 7960.00,
    "depositAmount": 796.00
  }
}
```

## 三、决策点(沿用 #1900 既有决策)

- **D1**:严格 `adultCount == 1` 触发(不看其他类型人数)
- **D2**:比例定金按 `baseTotal`(不含单房差)算
- **D3**:固定/人定金不动
- **早鸟优惠**:基于 `grandTotal`(已含单房差),从尾款扣,自洽不动

## 四、前端改动建议(mmg)

小程序订单确认页 / 管理端报价试算面板:

- 显示:`singleRoomSurcharge > 0` 时多一行 "单房差 ¥XXX"
- 总价用后端返 `grandTotal`,**前端不要自己加单房差**(防双计)
- 定金/尾款用后端返 `depositAmount` / `balanceAmount`,**前端不要自己算**

无新增错误码。

## 五、向后兼容

- 老 calendar/batch `single_room_diff DEFAULT 0` → `singleRoomSurcharge=0` → 老前端不读字段无影响
- 老前端响应多 2 个字段不报错(Jackson `fail-on-unknown-properties=false`)

## 六、测试验证

- 单测:`ProductPricingServiceTest +4` / `ProductPricingServiceMpQuoteTest +2` / `MpProductServiceTest +2` = **8 用例全过(总 138 PASS)**
- 测试服 round-trip(经 9443 网关 + 真 admin token,产品 `2043595351268519937`,`single_room_diff=200`):
  - `/mp/product/{id}/quote` adult=1 → `grandTotal=4180`,`singleRoomSurcharge=200`,`depositAmount=398` ✅
  - `/mp/product/{id}/quote` adult=2 → `singleRoomSurcharge=0`,`depositAmount=796` ✅
  - `/admin/product/item/{id}/quote` adult=1 → `grandTotal=4180`,`singleRoomDiff=200`,`singleRoomSurcharge=200` ✅
