11 KiB
schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base, generated
| schema | ticket | title | consumer | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base | generated |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 7439 | 终止退款·dayNumber 字段取值域放宽,不再截断接送机窗外服务日 | admin | wx(GIT) | 修改接口 | deployed | verified | verified | mmg | e03170eaf52e44858ec04cfa5a41fa252a34ba50 | 2026-09-14 | 后端已部署 8c699658a,接收端应对 dayNumber ≤0 或 > 行程天数的情况做边界处理,避免越界或错误渲染【前端 2026-09-14 交付 verified】MidTripRefundModal 接送机窗外服务日边界处理:≤0 标「接」、>tripDays 标「送」并按 departDate+(dayNumber-1) 还原真实日期,行程内恒 Day;day 格判断改 != null(0 接机不落图标分支);车辆组「含接送机日」提示;terminateRefund.js 适配器零改动(本就透传不截断不索引);保险行 null 不变。spec 13/13+terminateRefund 14/14,checkpoint 7 项全绿。ref=e03170ea。 | 2026-09-13 | dev-v3 | 2026-09-13T22:26:36+08:00 |
终止退款·dayNumber 字段取值域放宽
服务: hl-order-service-v3 PR: #7639 Issue: #7439 日期: 2026-09-13 影响范围: 管理后台终止行程退款预览接口,用车行的天序号编码
⚠️ 关键变化
接送机服务日现已正常返回,不再被截断丢弃。
- 终止退款预览接口出参中,用车行的
dayNumber不再保证落在[1, 行程天数]内 - 接送机场景(提前一天接机 →
dayNumber ≤ 0;返程后一天送机 →dayNumber > 行程天数)现已正常返回真实值 - 原先这类订单因服务日越界会被 581048 拒掉,现在正常预览返回
- 前端需对 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<OrderTerminateRefundPreviewRespVO>
| 字段 | 类型 | 说明 |
|---|---|---|
| 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) |
请求示例
POST /v3/admin/order/123456789/terminate/refund-preview
响应示例
{
"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
}
]
}
]
}
}
空数据 / 降级响应
{
"code": 404,
"message": "订单不存在或不在出行中状态",
"success": false,
"data": null
}
错误响应
{
"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 <token>
实测响应: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)
关联 / 联系人
链接
联系人
- 后端负责人: @wx