hl-api-changelog/changelogs/2026-04/30_fix_product_itinerary-validate-on-publish.md

4.2 KiB

修复:产品行程必填校验改到「完成设计」「上架审批」时,草稿允许空

类型: 后端 BUG 修复(翻盘 PR #1558 任务B 方向) 关联: 工单 #1557 / PR #1558(误) / PR #1560(修正) 日期: 2026-04-30 前端处理者: mmg 影响范围: 管理后台产品编辑页 Step 2 行程编排 + 完成设计按钮 + 提交上架审批按钮


翻盘说明

PR #1558 任务B 错误方向(已 revert)

PR #1558 在 ProductItinerarySaveReqVO 三处加 @NotBlank/@NotEmpty,等于"保存即必填" — 把草稿态的中间保存也拦下了。

用户反馈(2026-04-30)

"上架和完成实际时候得校验不能有空数据"

正确业务规则

操作 路径 校验
保存草稿 PUT /admin/product/item/{id}/itinerary 不校验(允许空,方便分阶段保存)
完成设计(仅 CUSTOM) POST /admin/product/item/{id}/complete 必填校验
提交上架审批 POST /admin/product/item/{id}/toggle-publish(SUBMIT_PUBLISH 方向) 必填校验
超管直接上架 同上(DIRECT_PUBLISH 方向) 必填校验
下架/撤回/驳回回退 同上(其他方向) 不校验(避免阻塞补救路径)

后端改动

1. 回滚 ReqVO 注解

ProductItinerarySaveReqVO.java 撤销 PR #1558 三处:

  • L53 description 移除 @NotBlank
  • L84 nodes 移除 @NotEmpty
  • L87 hotels 移除 @NotEmpty

(gatherPlace/dismissalPlace@NotNull 不动 — PR #1558 之前就有。)

2. ProductValidationService 新增两 public 方法

// 返回错误清单(空列表=可上架)
public List<String> validateItineraryCompleteness(Long productId)

// 硬校验,失败抛 BusinessException(批量错误一次抛)
public void assertItineraryCompleteForPublish(Long productId)

实现要点:

  • DB 3 次读(行程天 + 全部活动节点 + 全部酒店),按 dayId 分组避免 N+1
  • 一次扫所有 day,缺哪些字段累加到 issues 列表,调用方一次抛出
  • 错误码 ProductCoreErrorCode.PRODUCT_ITINERARY_INCOMPLETE (400404)

3. 挂载点

  • ProductStatusService.completeDesign 入口直接调
  • ProductStatusService.togglePublishpreAction == SUBMIT_PUBLISH || DIRECT_PUBLISH 触发

错误响应示例

完成设计 / 提交上架时,行程不完整返回:

HTTP 200 (走业务错误码,非协议错误)
{
  "code": 400404,
  "message": "行程未完整填写,请补全后再操作:\nDay 1 行程描述未填写\nDay 1 活动安排为空\nDay 1 住宿安排为空\nDay 3 集合地未填写",
  "data": null
}

测试服 round-trip 结果(用户截图原产品 2049468625294708737)

Case 操作 实际结果
草稿 PUT itinerary 全空 PUT /itinerary body 含空 description+nodes=[]+hotels=[] 200 code=200 msg="行程保存成功"
完成设计 POST /complete code=400404 含批量错误清单
提交上架审批 POST /toggle-publish 同上批量错误

前端要做的改动 ⚠️

1. 草稿保存路径 — 无须改动

保存草稿现在允许 description / nodes / hotels 为空,前端可以取消保存按钮的"必填校验提示",让用户中间状态自由保存。

2. 完成设计 / 提交上架 按钮

点击后如果后端返回 code=400404:

  • message 字段是多行文本,保留 \n 换行直接展示(如 <pre> 或 white-space: pre-wrap)
  • 内容形如:
    行程未完整填写,请补全后再操作:
    Day 1 行程描述未填写
    Day 1 活动安排为空
    Day 3 集合地未填写
    
  • 用户根据清单逐条补齐再点完成设计/上架即可

3. 错误码字典

业务码 含义 触发
400404 行程未完整 完成设计/提交上架前预检

部署状态

  • PR #1560 合并到 dev (sha 040d2ccb)
  • Deploy Panel 任务 success,hl-product-service-v2:8083+8183 双实例 1/1 Up
  • 测试服 3 笔 round-trip 全通过
  • Release dev → main 暂缓(用户指示"不用立即合 main")

单测

mvn test -pl hl-product-service-v2: 1019 全绿 (-8 旧 +7 新)

不动

  • 任务A 最低价接口完全不动
  • gatherPlace/dismissalPlace @NotNull 不动
  • NodeItem/HotelItem 子字段不动(原工单未要求,防回归)