diff --git a/changelogs/2026-04/2026-04-17_product-v2_internal-detail-insurance-fields.md b/changelogs/2026-04/2026-04-17_product-v2_internal-detail-insurance-fields.md new file mode 100644 index 0000000..1a33cbe --- /dev/null +++ b/changelogs/2026-04/2026-04-17_product-v2_internal-detail-insurance-fields.md @@ -0,0 +1,93 @@ +# 补齐:产品详情内部接口增加保险字段 + +> **服务**: hl-product-service-v2 (端口 8093) +> **PR**: #768 +> **Issue**: #767 +> **日期**: 2026-04-17 +> **影响范围**: 所有调用 `/internal/product/{id}/detail` 的下游服务(典型:order-service-v2 做订单快照) + +--- + +## 现象(下游感知) + +调用 `GET /internal/product/{productId}/detail` 时,响应体中**没有保险相关字段**,下游(order-service-v2)拿不到保险方案 ID 和保险告知状态,只能额外再调 `GET /internal/product/{id}/automation-config` 才能补齐。 + +## 根因 + +`InternalProductService.getProductDetail()` 内部用 `BeanUtil.toBean(product, InternalProductDetailVO.class)` 只复制了 `ProductDO` 的字段,**没查 `ProductSupplementDO`**(与 product 1:1 关联的补充配置表,存 `insurance_scheme_id` / `insurance_notice` 等)。导致 VO 缺保险字段。 + +同 Service 的 `getAutomationConfig()` 方法本来就正确查过补充表,这次把产品详情接口对齐这套写法。 + +## 修复 + +### 1. `InternalProductDetailVO` 新增 2 个字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `insuranceSchemeId` | Long | 保险方案 ID(下游下单/快照可直接用) | +| `insuranceNotice` | String | 保险告知状态(字典 `insurance_notice`: `INCLUDED`=含保险 / `EXCLUDED`=不含 / `OPTIONAL`=可选) | + +### 2. Service 补查补充配置 + +`InternalProductService.getProductDetail()` 在 `BeanUtil.toBean` 之后追加一次 `supplementDataService.selectById(productId)`,空安全赋值两个保险字段:无补充配置(supplement=null)或字段本身为 null 时,VO 保持 null。 + +## 接口契约 + +**向后兼容,只新增字段,不改旧字段、不改路径、不改参数。** + +### `GET /internal/product/{productId}/detail` + +**请求**(无变化): + +| 参数 | 位置 | 类型 | 说明 | +|------|------|------|------| +| `productId` | path | Long | 产品 ID | +| `date` | query(可选) | LocalDate | 班期日期 | + +**响应(新增字段,其他字段不变)**: + +```json +{ + "code": 200, + "message": "success", + "data": { + "productId": 100001, + "name": "呼伦贝尔7日游", + "subtitle": "...", + "productType": "CORE", + "category": "...", + "status": "ON_SALE", + "tripDays": 7, + "tripNights": 6, + "coverImageUrl": "https://...", + "lineId": 9001, + "carouselImages": [...], + + "insuranceSchemeId": 8888, // 新增 — 可能为 null + "insuranceNotice": "INCLUDED", // 新增 — 可能为 null(字典 insurance_notice) + + "tiers": [...], + "seasons": [...], + "tags": [...], + "itinerary": [...], + "hotels": [...], + "restaurants": [...], + "staff": [...] + } +} +``` + +## 前端/下游影响 + +- **order-service-v2**:以后调 `/internal/product/{id}/detail` 直接能拿到保险字段做订单快照,可以省掉一次 `getAutomationConfig` 的 Feign 调用 +- **其他下游**:接口完全向后兼容,不读新字段不受影响;需要保险信息的场景现在可以直接用 +- **字典**:`insurance_notice` 枚举值 `INCLUDED` / `EXCLUDED` / `OPTIONAL`,下游做展示时自行映射中文 + +## 需要重启的服务 + +**hl-product-service-v2(端口 8093)**。其他服务无需重启。 + +## 测试 + +- 单元测试 9 个全绿(`InternalProductServiceDetailTest`,含保险字段 3 场景:有 supplement / 无 supplement / 字段为 null) +- 接口契约层面:只追加字段、不改旧字段,序列化由 Jackson 保证,兼容性安全