# 【管理后台 + 小程序】小蒙马满团叠加「人数维度」+ 单房差改为「仅奇数成人收取」

> **类型**: 后端行为增强(满团判定口径 + 单房差计费规则)
> **服务**: hl-product-service-v2, hl-order-service-v2
> **日期**: 2026-05-30
> **影响范围**: 班期满团展示 / 下单库存校验 / 全产品类型报价单房差
> **归属**: 后端已改(PR #3280 → dev,已同步 dev-v3)
> **状态**: 已部署测试服并验证通过
> **关联工单**: #3279

---

## 一、小蒙马满团叠加「人数维度」(原仅房间数)

此前(PR #3267)满团只看房间数(1单=1房)。现在**房间或人数任一达上限即满团**(OR):

- 新增/启用「剩余名额」`remainParticipants = 最大参与人数 - 已报名人数`。
  - 班期「最大参与人数」为 0/null = 人数不限,此维度不卡(**未设人数上限的存量班期行为不变**)。
  - 线下占位仅占房间、不占人数名额(口径如此)。
- `batchStatus` 满团判定:房间耗尽 **或** 人数耗尽 → `FULL`。

### 新增响应字段

| 接口 | VO | 新字段 |
|------|-----|--------|
| `GET /admin/product/item/{id}/schedule/list` | ScheduleRespVO | `remainParticipants` 剩余名额(不限时 null) |
| `GET /admin/product/item/{id}/pricing-calendar` | UnifiedPricingCalendarItemVO | `remainParticipants` |
| `GET /mp/product/{id}/schedules` | MpScheduleRespVO | `remainParticipants`(原恒为 null,现回传真实值);`batchStatus` 现会因人数耗尽也变 `FULL` |

> 前端:仍按 `batchStatus` 判断能否报名即可(只 `ENROLLING` 放开)。如需展示「还剩 N 个名额」可用新 `remainParticipants`(与房间维度 `remainStock`/`remainFamilies` 并列)。

## 二、下单库存校验新增「人数维度」+ 新错误码

GROUP 下单时,除房间校验外新增人数名额校验(软校验 + 锁内硬守卫双道):

- **新错误码 `503109` 「剩余名额不足」**(人数超出剩余名额时返回)。
- 房间不足仍为 `503106` 「剩余房间不足」。

> 前端:下单失败时请按 code 区分提示(503109=名额不足 / 503106=房间不足)。

## 三、单房差改为「仅奇数成人收取」(所有产品类型)

报价 `singleRoomSurcharge` 计费规则调整(CORE/CUSTOM/ROUTE/GROUP 全部生效):

- **成人数为奇数(1/3/5…)** 且配置了单房差 → 收一份单房差。
- **成人数为偶数(含 0,2/4/6…)** → 不收。
- `singleRoomDiff`(配置值)字段含义不变,仅实际加价 `singleRoomSurcharge` 的触发条件由「严格 1 人」改为「奇数人」。

> 前端:报价/订单详情的「单房差」行仍读 `singleRoomSurcharge`,无需改字段,仅金额随上述规则变化。

## 四、测试服实测

- 单房差(配置 500,成人价 2925):1人→+500(3425)、2人→+0(5850)、3人→+500(9275)、4人→+0(11700)。✓
- 满团人数维度:admin schedule/list 正确回传 `remainParticipants`(=最大人数−已报名)。✓
- 下单防超卖:班期 maxPart=2,请求 3 人/1 房 → `503109 剩余名额不足`;请求 1 人/2 房 → `503106 剩余房间不足`。✓
