---
date: 2026-05-12
type: backend-fix
service: hl-product-service-v2
priority: medium
notify: ["@mmg"]
status: verified
---

# 班期创建: 儿童价=0 时跳过订金校验 (与价格日历对齐)

> **PR**: [#2117](https://git.1814.love:8443/wx/HL/pulls/2117) — 已合并 dev + 部署测试服
> **Issue**: [#2116](https://git.1814.love:8443/wx/HL/issues/2116)
> **接口**: `POST /admin/product/item/{id}/schedule` (POST 新增 / PUT 修改, 同一 Service 方法)
> **状态**: ✅ **测试服已验证** — 3 case curl 真测

---

## 背景

价格日历 `validatePriceCalendarReq` 早已加 child=0 视为儿童免费 → 跳过订金校验的逻辑。**班期 `doSaveSchedule` 路径漏改**, 同一固定订金产品下:

- 价格日历批量保存 child=0: ✓ 通过
- 班期创建 child=0: ❌ 报 `儿童售价（0元）必须大于产品订金`

两路径校验不一致, 用户感知为 BUG。

## 修复

`ProductPricingService.doSaveSchedule` 加 `> 0` 守卫:

```java
if (req.getChildPrice() != null
        && req.getChildPrice().compareTo(BigDecimal.ZERO) > 0   // ← 新增
        && req.getChildPrice().compareTo(fixedDeposit) <= 0) {
    throw new BusinessException(PRICE_CHILD_BELOW_DEPOSIT, ...);
}
```

**成人价校验保持不变** (成人不允许免费 / 必须大于订金, 该规则与价格日历一致)。

## 测试服真测 (硬性凭证)

产品 2053059685258309633 (DEPOSIT mode, deposit_amount=500)

```
Scenario 1: child=0 + adult=600
  → 200 OK, batchId=2054124392056590337 ✓ (修复前 410106)

Scenario 2: child=300 + adult=600 (300 < 500 deposit)
  → 410106 "儿童售价（300元）必须大于产品订金（500.00元/人）" ✓ (回归 child<deposit 仍拦截)

Scenario 3: adult=400 + child=0 (400 < 500 deposit)
  → 410105 "成人售价（400元）必须大于产品订金（500.00元/人）" ✓ (adult 校验不变)
```

## 前端 @mmg 无需改动

仅是后端校验放宽, 接口/字段/响应结构无变化。班期编辑页面**已经允许** child=0 输入(原前端无禁用), 之前是被后端拦截。本 changelog 备案即可。

## 风险

极小。校验放宽方向: child=0 从拦截改为允许, 不破坏既有数据/调用。
