diff --git a/changelogs/2026-04/2026-04-20_mp-earliest-available-date-and-full-tier.md b/changelogs/2026-04/2026-04-20_mp-earliest-available-date-and-full-tier.md new file mode 100644 index 0000000..9cf4946 --- /dev/null +++ b/changelogs/2026-04/2026-04-20_mp-earliest-available-date-and-full-tier.md @@ -0,0 +1,65 @@ +# 小程序新增"最近可售日期"接口 + 全档位可售判定 + +**日期**: 2026-04-20 +**服务**: hl-product-service-v2 +**PR**: #991 +**类型**: 新增接口 + 后端字段语义收紧 + +## 新增接口 + +### `GET /mp/product/{id}/earliest-available-date` +返回该产品从今天起的最近**全档位可售**日期(多档位产品要求该日所有档位都已配置成人价)。 + +**请求**: +- Path: `id` (Long) 产品ID +- 需要 mp token + +**响应**: +```json +{ + "code": 200, + "message": "成功", + "data": { + "date": "2026-04-20", + "available": true, + "daysFromToday": 0 + }, + "success": true +} +``` + +**字段说明**: +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `date` | `LocalDate` | 最近全档位可售日期(无可售时 null) | +| `available` | `Boolean` | `date != null` | +| `daysFromToday` | `Integer` | 距今天数(无可售时 null) | + +**判定规则**: +```sql +SELECT date FROM product_price_calendar +WHERE product_id = ? AND date >= today AND adult_sell_price > 0 +GROUP BY date +HAVING COUNT(DISTINCT tier_seq) >= tierCount(productId) +ORDER BY date ASC LIMIT 1 +``` +- `tierCount` = `product.tiers` JSON 数组长度 +- 单档产品 `tierCount<=1` 退化为"任一未来日有成人价" + +## 后端字段语义调整 + +### `MpProductDetailRespVO.isBooking` 判定收紧 +**之前**: `isBooking = (status == PUBLISHED)` +**现在**: `isBooking = (status == PUBLISHED) && (最近全档位可售日期 != null)` + +> 背景:isBooking 原意为"是否预约产品(订金可不填出行人)",今天已复用为"是否可订"。若多档产品未配齐所有档位价格,则认为该产品不可订,按钮应置灰。 + +## 前端建议接入方式 + +1. 进入产品详情页时调 `/mp/product/{id}/earliest-available-date`,`available=true` 才点亮"预订"按钮。 +2. 选日历时可将 `date` 作为最小可选日期。 +3. 判断按钮状态**不要**用 `status` 字段(mp 详情响应体里没有)。 + +## 已部署 +- 测试环境已部署,hl-product-service-v2 双实例(8083/8183)均生效。 +- 验证产品 `2045345825172639746` 返 `isBooking:true, startPrice:4105`,全档位最近可售日 `2026-04-20`。