diff --git a/changelogs-v2/2026-06/42_4548_终止行程退款弹窗预览补字段与提交下界校验-修改接口-管理后台.md b/changelogs-v2/2026-06/42_4548_终止行程退款弹窗预览补字段与提交下界校验-修改接口-管理后台.md new file mode 100644 index 0000000..a90e17e --- /dev/null +++ b/changelogs-v2/2026-06/42_4548_终止行程退款弹窗预览补字段与提交下界校验-修改接口-管理后台.md @@ -0,0 +1,191 @@ +# 【修改接口·管理后台】终止行程·退款计算弹窗:预览补字段 + 提交下界校验 (#4548 #4563) + +> **PR**: #4551 #4564 | **服务**: hl-order-service-v3 | **更新时间**: 2026-06-28 + +## 1. 接口背景 + +「终止行程·退款计算」弹窗(出行中订单点终止时打开)涉及两个接口:预览(拉资源清单 + 选结束日)、提交(确认终止 + 算退款)。本次两点优化: + +1. **预览接口**:弹窗需要渲染「客户在哪天结束行程」的日期按钮排(第 1 天 / 第 2 天 …),以及头部展示订单基本信息(订单号 / 客户 / 产品 / 团号 / 定制师)。原先这些都要前端自己拼,现在后端直接给。 +2. **提交接口**:原先后端不校验「结束日之前的资源是否标记已用」,可能把已经发生的天数算成可退款。现在加了下界校验兜底。 + +## 2. 变更清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 终止退款预览 | POST | `/v3/admin/order/{id}/terminate/refund-preview` | 修改接口 | 出参新增 `days` 数组 + 5 个订单基本信息字段 | +| 2 | 终止行程提交 | POST | `/v3/admin/order/{id}/terminate` | 修改接口 | 新增错误码 581044 + 入参约束「结束日前的资源必须标记已用」 | + +> 两接口入参主体结构不变,均为出参/校验增量,向后兼容。 + +--- + +## 3. 接口详情 + +### 3.1 终止退款预览(POST `/v3/admin/order/{id}/terminate/refund-preview`) + +- **使用场景**:出行中订单点「终止行程」打开弹窗时调用,拉取资源清单、结束日选项、订单基本信息。 +- **认证**:需要管理后台 JWT。 +- **前置**:订单状态必须为「出行中(TRAVELLING)」,否则返回错误。 +- **本次变更**:纯出参新增,无破坏性。 + +**入参**(不变) + +| 位置 | 字段 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| path | `id` | Long | ✅ | 订单 ID | + +无请求体。 + +**出参新增字段** + +| 字段 | 类型 | 说明 | +|------|------|------| +| `orderNo` | String | 订单号 | +| `customerName` | String | 客户名 | +| `productName` | String | 产品名称 | +| `batchNo` | String | 团号(团期订单有值;**核心订单为 `null`**) | +| `consultantName` | String | 定制师 | +| `days` | Array | 结束日期选项(见下表),范围 `1..tripCurrentDay`,**不含「未出行」** | + +`days[]` 元素字段 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `dayNumber` | Integer | 第几天(从 1 开始) | +| `label` | String | 中文展示名,如「第 1 天」 | +| `date` | String(日期) | 该天日期(= 出发日期 + dayNumber - 1) | +| `isCurrent` | Boolean | 是否当前天(= tripCurrentDay),前端默认选中此项 | + +> 原有字段 `paidAmount` / `tripDays` / `departDate` / `tripCurrentDay` / `rooms` / `tickets` / `vehicles` / `insurance` 全部保留不变。 + +**响应示例**(典型成功,团期订单 6 天行程、当前到第 3 天) + +```json +{ + "code": 200, + "message": "success", + "data": { + "orderNo": "HL202605120001", + "customerName": "张三", + "productName": "西藏拉林环线 6 日定制", + "batchNo": "GB20260512-008", + "consultantName": "李顾问", + "paidAmount": "6000.00", + "tripDays": 6, + "departDate": "2026-05-12", + "tripCurrentDay": 3, + "days": [ + { "dayNumber": 1, "label": "第 1 天", "date": "2026-05-12", "isCurrent": false }, + { "dayNumber": 2, "label": "第 2 天", "date": "2026-05-13", "isCurrent": false }, + { "dayNumber": 3, "label": "第 3 天", "date": "2026-05-14", "isCurrent": true } + ], + "rooms": [], + "tickets": [], + "vehicles": [], + "insurance": [] + }, + "success": true +} +``` + +> 核心订单(非团期)`batchNo` 为 `null`,其余结构一致。 + +**业务边界** + +- ✅ 订单状态 = 出行中(TRAVELLING)时可调。 +- ❌ 非出行中订单调用 → 返回「出行中取消仅适用于出行中订单」错误。 +- ⚠️ `days` 不含「未出行(第 0 天)」:未出行属于「取消订单」链路,不在终止行程范围内。 + +--- + +### 3.2 终止行程提交(POST `/v3/admin/order/{id}/terminate`) + +- **使用场景**:弹窗内确认终止,提交各资源「是否已用」+ 结束天,后端算退款并终止订单。 +- **认证**:需要管理后台 JWT。 +- **本次变更**:新增一条下界校验 + 对应错误码;入参字段结构不变。 + +**入参约束变更(重点)** + +新增校验:**结束日之前(`dayNumber < endDayNumber`)的资源行,`used` 必须为 `true`**;否则返回错误码 **581044**。 + +- `dayNumber < endDayNumber`(结束日之前已发生的天)→ `used` 必须 `true`(不可退)。 +- `dayNumber >= endDayNumber`(结束当天及之后)→ `used` 自由(默认 `false`,也可手动标 `true`,如当天酒店已入住)。 + +> 与现有前端交互一致:前端选定结束天后「自动标记前 N 天资源为已用」,天然满足此约束,正常不会触发 581044。仅当传入与结束天矛盾的 `used` 时才会被拒。 + +**入参字段表**(结构不变,列出供对照) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `cancelReason` | String | ✅ | 终止原因 + 调整说明 | +| `endDayNumber` | Integer | ✅ | 停在第几天(≥ 1) | +| `rooms` | Array | ✅ | 住宿已用判定 `[{refId, used}]` | +| `tickets` | Array | ✅ | 门票已用判定 `[{refId, used}]` | +| `vehicles` | Array | ✅ | 用车每天已用判定 `[{refId, dayNumber, used}]` | +| `adjustAmount` | Decimal | ❌ | 人工调整额(默认 0,允许负) | + +**错误码** + +| code | 含义 | 触发场景 | +|------|------|----------| +| 581044 | 终止行程:结束日之前的资源必须标记为已使用 | 提交时存在 `dayNumber < endDayNumber` 的资源行被标 `used=false` | + +**示例** + +8.1 业务失败(异常)——触发 581044 + +**请求**(结束天=2,但第 1 天住宿被标未用): + +```json +{ + "cancelReason": "QA测试", + "endDayNumber": 2, + "rooms": [ { "refId": "96011", "used": false } ], + "tickets": [], + "vehicles": [] +} +``` + +**响应**: + +```json +{ + "code": 581044, + "message": "终止行程:结束日之前的资源必须标记为已使用", + "success": false +} +``` + +> 触发 581044 时订单不会被终止、不产生退款(校验在落库前拦截)。 + +**业务边界** + +- ✅ 结束当天及之后的资源可自由标记已用 / 未用。 +- ❌ 结束日之前的资源标记未用 → 581044。 +- ⚠️ 保险行不参与此校验(保险整单不可退,由后端固定处理,无需前端传入)。 + +--- + +## 11. 影响评估 + +- **是否破坏向后兼容**:否。预览为出参增量;提交为新增校验,与现有「前 N 天自动标已用」前端交互一致,正常流程不受影响。 +- **前端是否必须同步上线**:否(预览新字段不消费则忽略;提交保持现有标记逻辑即可)。建议前端接入 `days` 后撤掉自行用 `tripDays + departDate` 构造日期按钮的逻辑。 + +## 12. 注意事项 + +- 前端可清理 workaround:原先用 `tripDays + departDate` 循环构造结束日按钮、自行算每天日期的逻辑,可改为直接渲染后端返回的 `days` 数组。 +- `batchNo` 在核心订单为 `null`,前端头部展示需做空值兜底。 + +## 13. 关联 / 联系人 + +### 13.1 链接 + +- **Issue**: [#4548](https://git.1814.love:8443/wx/HL/issues/4548) / [#4563](https://git.1814.love:8443/wx/HL/issues/4563) +- **PR**: [#4551](https://git.1814.love:8443/wx/HL/pulls/4551) / [#4564](https://git.1814.love:8443/wx/HL/pulls/4564) +- **Merge commit**: [a66e78143](https://git.1814.love:8443/wx/HL/commit/a66e78143) / [37e52315d](https://git.1814.love:8443/wx/HL/commit/37e52315d) + +### 13.2 联系人 + +- **后端负责人**: @yst +- **前端对接(管理后台)**: 终止行程·退款计算弹窗