---
date: 2026-05-08
type: backend-fix
module: hl-product-service-v2/pricing
priority: high
notify: ["@mmg"]
status: tested-passed
restart_service: hl-product-service-v2
gitea_pr: 1876
gitea_issue: [1870]
---

# 小童价格计算方向错误修复(add → subtract)

## 现象

产品价格配置:儿童=3000、小童(优惠差价)=1000,小程序应显示 toddlerPrice=2000(=3000-1000),实际显示 4000(=3000+1000),方向反了。

## 根因

字段 `toddler_discount` 历史 schema COMMENT 标「负数」,但实际业务/前端传的是正数差价。后端 4 处用 `childPrice.add(toddlerDiscount)` 拼接,正数相加结果反向。

## 修复

1. 4 处计算 `add → subtract`(传入参数 toddlerDiscount 仍为正数,语义自然):
   - `ProductPricingService.java:704`(核心报价)
   - `GroupTourBatchService.java:276`(admin 团报价)
   - `InternalProductService.java:281` / `:383`(mp 报价 / mp 班期报价)
2. `ProductPricingService.java:322` 校验去掉 `.abs()`,正数语义直接 compareTo
3. schema.sql 两表(`product_price_calendar`、`group_tour_batch`)`toddler_discount` COMMENT 改为「正数,小童比儿童便宜多少元」
4. 新建 Flyway `V20260508_001__fix_toddler_discount_comment_and_normalize_negative.sql`:改 COMMENT + 历史负数 ABS 兜底
5. 单测 7 处期望同步:`setToddlerDiscount(-X)` → `setToddlerDiscount(X)`,数学等价

## 前端可见变化

**API 字段名/路径/响应结构无变化**,前端无需改代码。但 toddlerPrice **数值会变化**:

- 改前:小童价 = 儿童价 + 差价(显示偏高)
- 改后:小童价 = 儿童价 − 差价(符合产品语义)

涉及接口:
- mp 报价(`InternalProductService.quote*`)
- mp 班期报价
- admin 团产品报价
- admin 核心报价

如果前端 UI 上有写死的小童价格预期(如测试用例硬编码、截图对比),请同步 review。

## 兜底保留

- `max(BigDecimal.ZERO)` 兜底逻辑保留(防 toddlerDiscount > childPrice 时变负数)
- Flyway 历史数据兜底:`UPDATE ... SET toddler_discount = ABS(toddler_discount) WHERE toddler_discount < 0`

## 测试

- 本地 `mvn -pl hl-product-service-v2 test`:1128 全过(0 failure / 0 error)
- 4 处计算路径 + Flyway + schema COMMENT 全部一致

## 重启服务

测试服需重启:`hl-product-service-v2`(PR #1876 合 dev → deploy panel)。

## 关联

- Closes wx/HL #1870
