From d2bce9b9c8fef9934eddf907030f44a463b7c004 Mon Sep 17 00:00:00 2001 From: API Changelog Bot Date: Sun, 13 Sep 2026 22:26:38 +0800 Subject: [PATCH] =?UTF-8?q?docs(changelog):=20#7439=20dayNumber=20?= =?UTF-8?q?=E5=8F=96=E5=80=BC=E5=9F=9F=E6=94=BE=E5=AE=BD=EF=BC=8C=E7=94=A8?= =?UTF-8?q?=E8=BD=A6=E8=A1=8C=E5=8F=AF=E8=90=BD=E5=9C=A8=E8=A1=8C=E7=A8=8B?= =?UTF-8?q?=E7=AA=97=E5=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #7439 / PR #7639 (8c699658a) - TerminateRefundItemVO.dayNumber 不再保证落在 [1, tripDays]:接送机服务日常在行程窗外, 该值是服务日的无损编码,后端不再截断;原先这类订单被 581048 拒掉,现在正常返回。 - 前端凡是拿 dayNumber 直接当下标 / 做 1..N 循环的地方必须先做边界判断。 - 第八节为测试服实测:order-v3 @ dev-v3/8c699658a,经网关调 refund-preview, 同一响应实测到 dayNumber=0(接机,出发前一天)与 dayNumber=5(送机,>tripDays=3), 保险行仍 null,581048 未出现;取证前后 deploy-status 的 commit 一致。 --- ...”¾宽-不再截断接送机服务日-修改接口-管理后台.md | 278 ++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 changelogs-v2/2026-09/13_7439_dayNumber取值域放宽-不再截断接送机服务日-修改接口-管理后台.md diff --git a/changelogs-v2/2026-09/13_7439_dayNumber取值域放宽-不再截断接送机服务日-修改接口-管理后台.md b/changelogs-v2/2026-09/13_7439_dayNumber取值域放宽-不再截断接送机服务日-修改接口-管理后台.md new file mode 100644 index 00000000..0acb9d80 --- /dev/null +++ b/changelogs-v2/2026-09/13_7439_dayNumber取值域放宽-不再截断接送机服务日-修改接口-管理后台.md @@ -0,0 +1,278 @@ +--- +schema: "hl-changelog/v2" +ticket: "7439" +title: "终止退款·dayNumber 字段取值域放宽,不再截断接送机窗外服务日" +consumer: "admin" +author: "wx(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "2026-09-13T22:23:57+08:00" +status_note: "后端已部署 8c699658a,接收端应对 dayNumber ≤0 或 > 行程天数的情况做边界处理,避免越界或错误渲染" +updated_at: "2026-09-13" +base: "dev-v3" +generated: "2026-09-13T22:26:36+08:00" +--- + +# 终止退款·dayNumber 字段取值域放宽 + +> **服务**: hl-order-service-v3 +> **PR**: #7639 +> **Issue**: #7439 +> **日期**: 2026-09-13 +> **影响范围**: 管理后台终止行程退款预览接口,用车行的天序号编码 + +## ⚠️ 关键变化 + +**接送机服务日现已正常返回,不再被截断丢弃**。 + +1. 终止退款预览接口出参中,用车行的 `dayNumber` **不再保证落在 `[1, 行程天数]` 内** +2. **接送机场景**(提前一天接机 → `dayNumber ≤ 0`;返程后一天送机 → `dayNumber > 行程天数`)现已正常返回真实值 +3. 原先这类订单因服务日越界会被 **581048 拒掉**,现在正常预览返回 +4. **前端需对 dayNumber 做边界处理**,避免用它直接索引"第几天"数组而越界;保险行 `dayNumber` **仍为 null**(无变化) + +## 一、背景 + +接送机服务是订单行程的边界服务:出发前接机服务日早于出发日,返程后送机服务日晚于行程结束日。 +原先后端按 `[1, 行程天数]` 硬截断这类服务日,致使真实服务日信息丢失。 + +现改为:`dayNumber` 是服务日相对出发日的 **1-based 编码**,其逆运算 `serviceDate = departDate + (dayNumber - 1)` 可精确还原服务日。 +前端回传释放行时会用这个值,所以后端**不再截断、不置空**,由前端按业务场景判断是否显示/处理。 + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|---|---|---|---|---| +| 1 | 终止行程·退款预览 | POST | `/{id}/terminate/refund-preview` | 响应字段取值域放宽 | 用车行 `dayNumber` 不再截断 | + +## 三、接口详情 + +### 1. 终止行程·退款预览 `POST /{id}/terminate/refund-preview` + +**VO**: `没有请求体 → OrderTerminateRefundPreviewRespVO` + +#### 使用场景 + +管理后台出行中订单详情页,用户点击「终止行程」时调用,预览该订单所有资源(住宿/门票/用车/保险/备品等)的退款金额,供用户和管理员确认。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|:---:|---|---| +| id | Path | Long | ✅ | Snowflake ID | 订单 ID | + +#### 出参 `Result` + +| 字段 | 类型 | 说明 | +|---|---|---| +| data.orderNo | String | 订单号 | +| data.tripDays | Integer | 行程天数 | +| data.departDate | LocalDate | 出发日(ISO 8601) | +| data.days | List | 按天分组的退款资源(含已用/未用统计) | +| data.days[].dayNumber | Integer | 第几天(1-based,接送机可能 ≤0 或 > tripDays) | +| data.days[].items | List | 该天的资源列表 | +| data.days[].items[].dayNumber | Integer | 资源对应的天序号 ⚠️ **本次变更重点** | +| data.days[].items[].categoryCode | String | 资源分类(ROOM/TICKET/SERVICE/VEHICLE/INSURANCE/SUPPLIES) | +| data.days[].items[].name | String | 资源名称(酒店名/车型/景点等) | +| data.days[].items[].dealPrice | BigDecimal | 单位价格(住宿=元/间·晚;用车=日费) | +| data.days[].items[].quantity | Integer | 数量(住宿=间数;用车=车辆数) | +| data.days[].items[].totalAmount | BigDecimal | 行合计 = dealPrice × quantity | +| data.days[].items[].locked | Boolean | 是否锁定不退(保险等 = true) | + +#### 请求示例 + +```http +POST /v3/admin/order/123456789/terminate/refund-preview +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "orderNo": "ORD-2026090100001", + "tripDays": 3, + "departDate": "2026-09-15", + "days": [ + { + "dayNumber": 0, + "items": [ + { + "lineKey": "VEHICLE_ASSIGNMENT:666:1", + "categoryCode": "VEHICLE", + "categoryName": "用车", + "sourceType": "VEHICLE_ASSIGNMENT", + "sourceId": "666", + "name": "丰田 RAV4", + "dayNumber": 0, + "dealPrice": "380.00", + "quantity": 1, + "totalAmount": "380.00", + "defaultUsed": false, + "locked": false + } + ] + } + ] + } +} +``` + +#### 空数据 / 降级响应 + +```json +{ + "code": 404, + "message": "订单不存在或不在出行中状态", + "success": false, + "data": null +} +``` + +#### 错误响应 + +```json +{ + "code": 581048, + "message": "终止行程:本地车辆费用服务日与订单行程不一致", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- **鉴权**: OrderViewGuard 排除房务角色;其他所有角色(产品/运营/财务等)均可调用 +- **车辆已用状态**: 按 Order 当前 DAILY_V3 的 serviceDate 与实际终止日对比,前端显示仅供参考,提交时后端权威重算 +- **服务日合法性**: 原先 dayNumber < 1 或 > tripDays 时会抛 581048;现已移到 OrderVehicleDailyFeeSnapshotProvider 按车型分流验证 +- **保险**: 始终 locked=true,dayNumber=null,不可退 + +--- + +## 四、契约约束与正确调用方式 + +此接口返回的 `dayNumber` **仅是原始编码,不保证在行程窗内**。消费方必须按以下流程处理: + +| dayNumber 情况 | 含义 | 前端处理建议 | +|---|---|---| +| ≤ 0 | 接送机:出发前服务 | 标记为"接机";不索引"第几天"数组 | +| 1 ~ tripDays | 行程内 | 正常按"第 dayNumber 天"渲染 | +| > tripDays | 接送机:返程后服务 | 标记为"送机";不索引"第几天"数组 | + +--- + +## 五、数据库行为 + +此接口为**读接口**,无数据库写操作。返回的是现存订单快照中的车辆事实编码。 + +--- + +## 六、边界行为 + +- **未登录** → 401(网关拦截) +- **无权限(房务角色)** → 403(OrderViewGuard 拦截) +- **订单不存在** → 404 +- **订单非出行中** → 404 +- **下游数据缺失** → 返 `[]` 对应项,不 500(降级处理) +- **老数据兼容** → 旧字段为 null,不异常 + +--- + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| dayNumber(用车) | 强制落在 `[1, tripDays]`;越界时异常拒绝(581048) | 无约束;可以 ≤0 或 > tripDays;精确编码服务日 | + +### 行为级对比 + +| 行为 | 改前 | 改后 | +|------|------|------| +| 接送机订单预览 | 被 581048 拒绝 | 正常返回,dayNumber 准确反映接送日期 | + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 是 +- **前端是否必须同步上线**: 是 +- **前端 workaround 清理点**: 原先对接送机订单做的排除逻辑可撤销;dayNumber 直接索引改为先检查边界 + +## 七、不影响范围 + +- **仅影响**: 管理后台终止行程退款预览接口中用车行 +- **零影响**: + - 订单详情/订单列表接口 + - 住宿/门票/保险/备品的 dayNumber + - 订单创建/修改接口 + +## 八、测试环境已验证 + +**部署**:`hl-order-service-v3` @ `dev-v3 / 8c699658a`(PR #7639 的 merge commit), +两实例 8086 / 8186 滚动完成并 UP,Nacos(`namespaceId=test`)两实例 `healthy:true`。 +取证**前后各查一次** `deploy-status.sh`,commit 均为 `8c699658a`、`BEHIND=0/N` ⇒ 取证期间无人换分支。 + +**实测请求**(路径取自源码 `OrderController.java:203`,不是照文档猜的): + +``` +POST https://api.test.1814.love:9443/v3/admin/order/8880000000000000001/terminate/refund-preview +Authorization: Bearer +``` + +**实测响应**:`HTTP 200`,`code=200`,`success=true`。订单 `tripDays=3`、`departDate=2026-10-01`。 +`refundLines` 里六行的 `dayNumber` 实测值: + +| 行 | 类别 | 服务日 | `dayNumber` 实测 | 说明 | +|---|---|---|---|---| +| ceB00001 | 用车(接机) | 2026-09-30(出发**前**1 天) | **`0`** | 🔴 **≤0,改动前会被 581048 拒掉** | +| ceA00001 | 用车 | 2026-10-01 | `1` | 行程内 | +| ceA00002 | 用车 | 2026-10-02 | `2` | 行程内 | +| ceA00003 | 用车 | 2026-10-03 | `3` | 行程内 | +| ceB00002 | 用车(送机) | 2026-10-05(返程**后**2 天) | **`5`** | 🔴 **> tripDays=3,改动前会被 581048 拒掉** | +| 旅行险 | 保险 | — | **`null`** | 保险行仍为 null,此条未变 | + +⇒ **本次改动实际放行的行为已被真实触发并观测到**:同一响应里同时出现 `0` 与 `5`, +不是全部落在 `[1, 3]` 内;**`581048` 未出现**。 + +**取证用数据说明(供排查时识别,勿动)**:该订单为本次验证**专门新建**的独占单 +(`order_id=8880000000000000001` / `order_no=HL88800000000001`),未改动任何既有订单; +`order_main` / `order_vehicle_requirement` / `order_vehicle_assignment` / `insurance_order` +的备注字段均带 `#7439 AC-27` 标记,可直接检索。 + +**本节的已知边界(不外推)**: +- 未做前端页面联调——本节只验到接口层。 +- 未调用有副作用的终止提交接口(`processTermination`),只验了只读的 `refund-preview`。 +- 该测试单由 SQL 直插创建(DAILY_V3 派车快照涉十余项耦合 CHECK,走真实抢单/派车链路超出本次范围), + **未经"定制→支付→出发"业务流程产出**。 + +## 九、相关历史 PR + +| PR | Issue | 说明 | 是否仍有效 | +|----|-------|------|-----------| +| **本 PR #7639** | **#7439** | 放宽 dayNumber 取值域 | ✅ 最新 | + +## 十、相关文档 + +- 端点定义: `hl-order-service-v3/.../controller/admin/OrderController.java:203` +- 改动点: `hl-order-service-v3/.../settlement/service/TerminateRefundService.java` 的 `vehicleDayNumber` +- 字段定义: `hl-order-service-v3/.../controller/admin/vo/TerminateRefundItemVO.java` 的 `dayNumber` +- 鉴权: `com.hulalv.order.core.guard.OrderViewGuard#assertNotHouseRole`(房务/组长 → 581045) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#7439](https://git.1814.love:8443/wx/HL/issues/7439) +- **PR**: [#7639](https://git.1814.love:8443/wx/HL/pulls/7639) +- **Merge commit**: [8c699658a](https://git.1814.love:8443/wx/HL/commit/8c699658a) + +### 联系人 + +- **后端负责人**: @wx