hl-api-changelog/changelogs/2026-04/2026-04-23_admin-unified-pricing-calendar.md

4.4 KiB

统一价格日历接口 /admin/product/item/{id}/pricing-calendar

日期: 2026-04-23 PR: #1290 (Closes #1286) 服务: hl-product-service-v2 类型: feat新增接口,零破坏性


背景

之前 admin 查价格日历需要分场景调两个不同接口:

  • CORE/CUSTOM → GET /admin/product/item/{id}/price-calendar
  • GROUP小蒙马GET /admin/product/item/{id}/schedule/list

根因GROUP 定价真相源是 group_tour_batch.adult_price(班期表),不走 product_price_calendar。前端要按 productType 分流调用。

本次新增统一入口,后端按 productType 聚合两种数据源,前端一个接口搞定。


新接口

GET /admin/product/item/{id}/pricing-calendar

Query 参数

  • month(可选):yyyy-MM,过滤月份。不传返全部
  • tierSeq(可选):档位序号,仅 CORE/CUSTOM 生效,GROUP 忽略

响应

{
  "code": 200,
  "data": {
    "productType": "CORE | GROUP | CUSTOM",
    "items": [
      { ... 统一条目 VO ... }
    ]
  }
}

统一条目 VO 字段表

字段 类型 CORE/CUSTOM GROUP
通用
date LocalDate 每日价格日 出发日departureDate
adultPrice BigDecimal adultSellPrice adultPrice
childPrice BigDecimal childSellPrice childPrice
toddlerDiscount BigDecimal
infantPrice BigDecimal
stock Integer dailyStock productStockLimit无则 maxParticipants
sold Integer sold enrolledCount
sellable Boolean dailyStock 空或 sold<stock batchStatus∈{ENROLLING,NEARLY_FULL}
CORE/CUSTOM 专属
id Long 日历记录主键 null
tierSeq Integer 档位序号 null
priceType String NORMAL/PEAK/HOLIDAY/SPECIAL null
rangeId Long 批量区间标识 null
GROUP 专属
batchId Long null 班期ID
batchNo String null 班期编号
batchName String null 班期名称
batchStatus String null ENROLLING/NEARLY_FULL/FULL/FINISHED/CANCELLING/CANCELLED
endDate LocalDate null 班期结束日
enrollmentDeadline LocalDate null 报名截止日
maxRooms Integer null 总房间数
bookedRooms Integer null 已预订房间数

前端渲染建议

const resp = await api.getUnifiedPricingCalendar(productId, { month, tierSeq });
switch (resp.data.productType) {
  case 'CORE':
  case 'CUSTOM':
    // 矩阵日历: 按 tierSeq × date 渲染档位 × 日期表格
    renderMatrixCalendar(resp.data.items);
    break;
  case 'GROUP':
    // 列表日历: 按出发日渲染班期卡片,显示 batchName/batchStatus/endDate
    renderBatchCalendar(resp.data.items);
    break;
}

示例

CORE 响应

{
  "productType": "CORE",
  "items": [
    {
      "date": "2026-05-01",
      "adultPrice": 1999.00,
      "childPrice": 999.00,
      "id": 1780000000000000001,
      "tierSeq": 1,
      "priceType": "NORMAL",
      "stock": 50,
      "sold": 10,
      "sellable": true,
      "batchId": null
    }
  ]
}

GROUP 响应

{
  "productType": "GROUP",
  "items": [
    {
      "date": "2026-07-06",
      "adultPrice": 4580.00,
      "childPrice": 2290.00,
      "batchId": 2043697199761584129,
      "batchNo": "Q202607062043697199757389826",
      "batchName": "7月暑期团",
      "batchStatus": "ENROLLING",
      "endDate": "2026-07-10",
      "stock": 25,
      "sold": 0,
      "sellable": true,
      "tierSeq": null,
      "priceType": null
    }
  ]
}

向后兼容

老接口保持不变

  • GET /admin/product/item/{id}/price-calendar — 不动
  • GET /admin/product/item/{id}/schedule/list — 不动

前端可逐步迁移到新接口,无需一次性全量改造。


验证

测试服网关 7 场景全过:

  • CORE 全量 → 92 条 tierSeq/priceType 齐
  • GROUP 全量 → 4 条班期 batchId/batchStatus/endDate 齐
  • CUSTOM → 62 条走 CORE 分支
  • CORE/GROUP ?month=2026-05 → 正确过滤
  • CORE ?tierSeq=1 → 从 92 条过滤到 79 条
  • 老接口 /price-calendar → 92 条不变零回归

部署

测试服已部署: task a1ca3b50 success。 正式环境上线前无需任何 DDL,纯接口聚合。