PR #2067 (commit d30bd995): - #2064 行程编排日里程手动改后保存被高德自动计算覆盖 - #2066 价格日历批量设置允许儿童售价等于 0(儿童免费) 测试服 admin token round-trip 4 case 全过(2026-05-12 10:14-10:15)。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.2 KiB
后端 fix 通知 — 产品 V2 编辑两项修复(里程被覆盖 + 儿童售价=0)
日期: 2026-05-12
类型: 后端修复 (PR #2067, merge commit d30bd995)
模块: 产品 V2 编辑 → 行程编排 / 价格日历批量
通知: @mmg
前端是否需改动: 可选(后端兼容现有前端行为, 修复后即生效; 若要支持"取消手动锁回到自动计算"则需小调整, 见下)
严重性: P1(行程里程) + P2(儿童售价=0)
修复 1: 行程编排「当日里程」手动改后保存被高德覆盖 (Closes #2064)
现象
产品 V2 编辑页 → 第 2 步「行程编排」→ DAY N → 修改「里程」输入框为某个值(如 180 km)→ 保存 → 刷新页面 → 里程又变回了高德自动计算的数字。
根因
后端有 mileageManualOverride 开关字段标记是否人工覆盖。前端编辑 dailyMileage 时只传数值未带 override=true, 后端 MP updateById NOT_NULL 策略跳过 null 字段, DB 中 override 保持 0, 事务提交后 ItineraryAutoCalculator 调高德 API 重新覆盖用户输入。
修复
后端 ProductItineraryService.convertDay 兜底: 当前端传了 dailyMileage 但未显式传 mileageManualOverride 时, 自动视为手动覆盖(置为 TRUE), 阻断 autocalc 覆盖。
前端 mmg 完全无需改动
前端继续按当前逻辑只提交 dailyMileage 即可, 后端兜底已覆盖。
如果要支持「重置回自动计算」(可选, 不是必做)
若想加一个"刷新/重置"按钮让用户撤销手动锁、回到高德自动值, 需:
- 该天 SaveReqVO 显式传
dailyMileage: null且mileageManualOverride: false - 保存后等 1-2 秒, 后端 autocalc 会重算并填入
截图里看到里程字段旁有圆形刷新图标和 × 按钮, 如果这两个图标已绑此语义, 检查一下提交时是否真的清空 dailyMileage + 显式 override=false。
修复 2: 价格日历批量设置允许儿童售价 = 0 (Closes #2066)
现象
价格日历批量设置中, 儿童售价填 0 报「儿童售价必须大于0」无法保存。业务上 0 表示儿童免费应允许。
修复
后端 4 处放宽:
PriceCalendarBatchReqVO.childSellPrice@DecimalMin0.01 → 0.00, 文案改"儿童售价不能为负数"ProductPricingService第一道校验拆分: null → 原 REQUIRED 错误码; <0 → 新错误码PRICE_CHILD_SELL_PRICE_NEGATIVE(410112)ProductPricingService固定订金模式:childSellPrice=0时跳过"必须>订金"校验ProductBasicService反向校验对称处理: 调订金时若现存价格日历/班期childPrice=0视为免费跳过, 避免"正向能设 0、反向改订金又被卡"
成人售价校验维持 >0 不变, 不允许成人售价 0。
前端 mmg 行为变化
- 儿童售价输入框: 现在允许填
0(免费) - 儿童售价 = 负数: 仍报错, 文案变成「儿童售价不能为负数」(原"必须大于0")
- 成人售价: 维持
>0, 不可填 0
如果前端有"儿童售价 ≥ 0.01"的本地校验, 请放宽到 ≥ 0(允许 0.00, 不允许负数)。
✅ 测试服真测(2026-05-12 10:04 部署, 10:14-10:15 真测)
测试服 admin token (test_admin) 经网关 api.test.1814.love:9443 真测, 用产品 2053662735618506754:
Case 1: BUG #2064 修复验证
| 步骤 | 操作 | 结果 |
|---|---|---|
| baseline | DAY 2 (dayId=2053662735677227011) daily_mileage=140.0 override=1 |
— |
| 改动 | PUT /admin/product/item/{id}/itinerary DAY 2 dailyMileage=888.0, 不传 override |
HTTP 200, code=200, msg="行程保存成功" |
| 等 8s | autocalc 在 10:14:11 跑完 自动计算每日里程完成, 天数=7 |
— |
| 验证 | SQL daily_mileage=888.0 mileage_manual_override=1 |
✅ 888 未被高德覆盖 |
Case 2: BUG #2066 修复验证
| 步骤 | 操作 | 结果 |
|---|---|---|
| 改动 | POST /admin/product/item/{id}/price-calendar/batch, childSellPrice=0, adultSellPrice=1999, date=2026-12-15, tier=1, NORMAL |
HTTP 200, code=200, msg="价格日历设置成功" |
| 验证 | SQL child_sell_price=0.00, adult_sell_price=1999.00, price_type=NORMAL |
✅ child=0 落库 |
Case 3: 边界 — 儿童售价 = -1 仍拦
- POST 同上
childSellPrice=-1→ HTTP 200, code=400 msg="儿童售价不能为负数" success=false ✅
Case 4: 旁证 — autocalc 在 override=false 时正常生效
- DAY 3 显式传
mileageManualOverride=false且不传dailyMileage→ 8s 后 SQLdaily_mileage=0.0 override=0, 日志 10:15:36自动计算每日里程完成— autocalc 正常生效(该天集散坐标相同高德返 0km, 是预期结果)
影响面 / 兼容性
- 接口签名零变化 — 任何前端代码不改也能直接用
- 已部署: 测试服 product-v2 双实例(8083 + 8183) 已是含修复的版本
- 历史已被高德覆盖的天: 下次用户手动改并保存即可锁住, 无需脏数据修复
- 已有
mileage_manual_override=1的天不受影响 - 历史已有
childSellPrice数据不受影响, 仅前向允许 0 入库
关联
- PR: wx/HL#2067
- Issue #2064: wx/HL#2064
- Issue #2066: wx/HL#2066