# 修复: 上架/完成设计校验跳过最后一天酒店(返程日豁免) **类型**: 后端 BUG 修复 **关联**: 工单 #1586 / PR #1587 **日期**: 2026-04-30 **前端处理者**: mmg **影响范围**: 管理后台「完成设计」「提交审核 / 直接上架」按钮的预检逻辑 --- ## 现象 用户反馈:产品上架/完成设计预检时,如果**最后一天**没在 `product_day_hotel` 配酒店,就被「Day N 住宿安排为空」拦截无法上架。但**最后一天通常是返程日不需要住宿**,这个校验是错的。 用户原文:「最后一天行程提示也得有住宿安排,实际不需要」 ## 根因 `hl-product-service-v2` `ProductValidationService.validateItineraryCompleteness()` 对每一天循环硬要求 `product_day_hotel` 非空,**没有跳过最后一天**。 ## 修复 判定最后一天豁免酒店校验: ```java int totalDays = days.size(); for (int i = 0; i < totalDays; i++) { ProductItineraryDayDO day = days.get(i); // ... 描述/集合地/解散地/活动校验保持不变 ... // 最后一天通常是返程,不强制要求配酒店(2026-04-30 用户反馈) boolean isLastDay = (day.getDayNumber() != null) ? day.getDayNumber() == totalDays : i == totalDays - 1; if (!isLastDay) { if (dayHotels.isEmpty()) issues.add(dayLabel + " 住宿安排为空"); } } ``` 判定规则: - 优先 `day.getDayNumber() == totalDays` - `dayNumber` 为 null 时回退索引 `i == totalDays - 1` ## 行为变化 | tripDays | 最后一天 | 行为 | |---|---|---| | 1 | i=0 是唯一一天即最后一天 | 单天产品没酒店通过 | | 2 | Day1 校验 / Day2 豁免 | OK | | 3 | Day1/Day2 校验 / Day3 豁免 | OK | | dayNumber=null | 列表最后一项兜底 | 跳过 | ## 影响接口 | 方法 | 路径 | 改动 | |------|------|------| | POST | `/admin/product/item/{id}/complete-design` | 最后一天没酒店不再返 400 | | POST | `/admin/product/item/{id}/toggle-publish` (SUBMIT_PUBLISH/DIRECT_PUBLISH) | 同上 | | PUT | `/admin/product/item/{id}/supplement` | 不变(草稿允许任意) | 请求/响应签名不变,只是错误条件减少。 ## 前端要做的改动 **0 改动**。如果前端之前对「Day N 住宿安排为空」错误做过 UX 引导(比如跳到行程编排页面),保留即可,不会被误触发。 ## 测试覆盖 新增 4 单测: - `validateItinerary_lastDayNoHotel_shouldPass` — 3 天 day3 没酒店,通过 - `validateItinerary_middleDayNoHotel_shouldFail` — 3 天 day2 没酒店,报错;day3 不计入 - `validateItinerary_singleDay_noHotel_shouldPass` — 1 天产品没酒店通过 - `validateItinerary_dayNumberNull_useListIndexFallback` — dayNumber=null 兜底 `mvn test`: ProductValidationServiceTest **53/53 全绿**。 ## 部署状态 - ✅ 测试服 hl-product-service-v2 双实例部署完成(2026-04-30 23:40) - 正式环境暂未发布(等 dev → main release PR)