--- schema: "hl-changelog/v2" ticket: "7441" title: "完成核单车侧闸门升级为硬阻断——缺行改抛 584131,warnings[].category=VEHICLE 取值退场,免车团整户跳过" consumer: "admin" author: "wx(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "not_required" frontend_owner: "" frontend_ref: "" target_release: "" verified_at: "" status_note: "finalize 成功路径(含免车团整户跳过车侧、团车完成路径正常结算)与 584100 对照均有测试服真实网关调用记录(第八节,见工单 #7441 验收评论)。584131 的两个实际触发分支(户级需求缺失/未完成)在本轮测试服取证中未见网关调用记录,只有源码走查,已在第八节与错误响应表中如实标注;#7445 changelog(11_7445)记录的是本单改造前的旧版软预警取证,不能作为本次硬阻断分支的证据。被测服务:order-v3 = dev-v3 7d8cecb3e,2026-09-15 15:38 部署。mmg 2026-09-15 核实:detail.vue finalize warnings 渲染只取 item.message 从不读 category,VEHICLE 取值退场无影响;584131 全仓零引用,按本项目惯例走 request.js 拦截器透后端 message(含团号与需求状态),detail.vue 有 error?.message 回落。前端零改动,判 not_required。" updated_at: "2026-09-15" base: "dev-v3" --- # order-v3: 完成核单车侧闸门升级为硬阻断 > **存放目录**: `changelogs-v2/{YYYY-MM}/`(管理后台,二期 order-v3) > > **服务**: hl-order-service-v3 (端口 8083) > **PR**: #7763(PR-3) > **Issue**: #7441 > **日期**: 2026-09-15 > **影响范围**: 既有端点 `POST /v3/admin/order/{orderId}/settlement/finalize`(完成核单),团期子订单车侧户级闸门由软预警升级为硬阻断,方法、路径、入参、响应结构均未改 --- ## ⚠️ 关键变化 1. **团期子订单"用车需求缺失"从软预警升级为硬阻断**——`#7445` 交付时,该场景只在成功响应的 `warnings[]` 里追加一条 `category=VEHICLE` 的提示,`finalize` 仍会成功;本单起改为直接抛业务错误码 `584131`,`finalize` 不再成功。 2. **`warnings[].category="VEHICLE"` 这一取值从此不再出现**——`#7445` changelog 曾让前端为它做过渲染容错,本单起该取值退场,不要因为看不到它而报错,也不要把 `584131` 当系统异常展示。 3. **整团声明"本团无需用车"(`waive`)的团,该户整户跳过车侧闸门**——`finalize` 照常成功,不判用车需求状态。 4. **`waive` 声明的可用阶段放宽到核单中**:出团前忘了点免车的团,在核单阶段(`TRIP_FINISHED`/`REVIEWING`)仍可补点免车(见另一份 PR-1 changelog 的「三、4」)。 --- ## 一、背景 `#7445` 交付了团期子订单车侧户级闸门:用车需求存在但未完成时硬阻断(`584131`),需求缺失时因为当时没有任何运营可达的"这个团不要车"的表达,只能降级为软预警,代价是"车根本没提需求"的户照样把钱结掉。`#7441` PR-1 交付了团级免车声明(`waive` 端点)后,"不要车"有了显式、留痕的表达,本单据此把缺行分支也升级为硬阻断,并让免车团整户跳过本闸。 --- ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 完成核单 | POST | `/v3/admin/order/{orderId}/settlement/finalize` | 车侧闸门升级 | 缺行改硬阻断 584131;免车团整户跳过;warnings VEHICLE 取值退场 | --- ## 三、接口详情 ### 1. 完成核单 `POST /v3/admin/order/{orderId}/settlement/finalize` **VO**: `Long(Path 参数 orderId,无请求体) → Result` #### 使用场景 管理后台核单页点击"完成核单"按钮时调用,原子完成结算并推订单进终态。调用方式、路径、入参完全不变。团期子订单(经统一判团门面判定)车侧户级闸门本单起行为变化,见下。完整响应字段(`totalAmount`/`roomCost`/`profitAmount` 等结算金额字段)已在 `11_7445_团期用车结算闸-修改接口-管理后台.md` 完整列出,本单不重复,仅列出本次实际变化的部分。 #### 入参字段表 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | orderId | Path | Long | 是 | 大于等于 1 | 订单 ID(不变) | (finalize 本身无请求体,本单未改。) #### 出参字段表 | 字段 | 类型 | 说明 | |------|------|------| | warnings | List | 软预警列表;**`category="VEHICLE"` 这一取值本单起不再出现**(缺行改抛硬错误码,不再走软预警) | | warnings[].category | String | 仍可能出现 `HOTEL`/`TICKET`(既有取值,未改) | | (其余字段:summaryId/finalSnapshotId/totalAmount/roomCost/vehicleCost/profitAmount 等) | - | 结构与语义均未改,完整定义见 `11_7445` | #### 请求示例 ```http POST /v3/admin/order/2099716821748715521/settlement/finalize HTTP/1.1 Authorization: Bearer {token} ``` (无请求体,仅 Path 参数 orderId;本单未改请求形态。) #### 响应示例 团车完成路径、免车团整户跳过:均能成功。以下为团车完成路径成功响应(测试服真实响应,2026-09-15,见工单 #7441 验收评论,`warnings` 未出现 VEHICLE 相关项): ```json { "code": 200, "message": "成功", "success": true, "data": { "orderId": "2099716821748715521", "orderStatusAfter": "待财务复核", "warnings": [] } } ``` #### 空数据 / 降级响应 本闸不产生独立的空态/降级响应:`warnings` 在没有任何软预警时为空数组,判定不可达时按错误响应处理,不发生静默降级(不变)。 ```json { "code": 200, "success": true, "data": { "warnings": [] } } ``` #### 错误响应 | 码 | 符号 | 触发 | 本单 | 网关取证 | |----|------|------|------|------| | 584130 | SETTLEMENT_GROUP_HOTEL_NOT_READY | 住宿闸未过(排在车侧闸之前,未改) | 不变 | 见 11_7445 | | 584131 | SETTLEMENT_GROUP_VEHICLE_NOT_READY | 团期子订单用车未安排完成,或需求缺失且未免车 | **本单起:缺行分支改为硬阻断(改前软预警)** | 源码走查,本轮测试服取证未覆盖实际触发 | | 584100 | FLEET_VEHICLE_FEE_UNAVAILABLE | 历史 legacy 逐户完成行(非团车、非快照来源)过车侧闸后在车费链路被拦 | 未改,本单不动 | 有(测试服真实触发,见第八节) | ```json { "code": 584131, "message": "团期子订单 GB202609200007 的用车尚未安排完成(用车需求当前状态:未提交用车需求),请等车务配车完成后再提交核单", "success": false, "data": null } ``` (该条示例按源码报文模板拼出(`{1}` 占位符在需求缺失分支固定取值"未提交用车需求",见另一份 PR-1 changelog 的「六.5」枚举),非测试服实测原文——本轮取证未覆盖该分支的实际触发。) #### 业务边界 - **闸序不变**:住宿闸(584130)→ 用车闸(584131)→ CASH_PAID 软预警。两闸同时未就绪仍只返回先触发的住宿闸错误码。 - **免车判断排在判团之后、查户级需求之前**:免车是团级结论,优先于户级需求状态——免车团的户即便残留一份非"已完成"的需求也照常放行。免车判断使用的 `groupBatchId` 取判团门面解析值,不读订单自身冗余列(`#7083` 回填窗口期该列可能为空)。 - **缺行分支升级为硬阻断的前提**:团期处于可免车阶段、且免车未被"车务已开工"守卫拦下时,缺行不再有"只能这样"的合法解释。该前提不成立时(例如团期已结算/已取消,免车阶段守卫拒绝;或车务已开工,免车被拒),缺行仍会把该户卡在本闸,需人工处置——这是已知例外,不是本单的缺陷。 - **只判 TRAVEL(行程用车),不判 TRANSFER(接送机)**:结算车费日快照固定按 TRAVEL 取,闸门与账对齐;接送机需求未完成不会拦住本次结算(未改)。 - **判定只读户级当前 active 需求的状态,不读车费派生行、不读实配行、不读团级镜像列**——删除派生行、清空实配行都不能绕过闸门(未改)。 - **并发与幂等**:判定与后续结算写入在同一 finalize 事务、同一把锁内,不存在 TOCTOU 窗口;本闸是只读判定,不加 `@Idempotent`(未改)。 --- ## 四、契约约束与正确调用方式 ### 正确 / 错误 调用结果对照 | 场景(订单形态) | 结果 | |------|------| | 团期子订单,用车需求"已完成"(正确) | 200 成功,warnings 无车侧项 | | 团期子订单,用车需求存在但未完成(错误) | 584131(改前后行为一致) | | 团期子订单,无 active 用车需求行,团未免车(本单变化点) | 改前:200 成功 + warnings 追加 VEHICLE 软预警;改后:**584131 硬阻断** | | 团期子订单,所在团已声明整团免车(正确) | 200 成功,整户跳过车侧闸,不判需求状态 | | 非团期订单(正确) | 200 成功,本闸不进(未改) | ### 切换状态时的必要动作 前端无需改动请求参数——finalize 无请求体,本闸完全由后端按订单/团期当前状态判定。前端需要改的是响应解析与提示:不再需要处理 `warnings[].category="VEHICLE"` 这一取值(该分支已改走错误响应,不再出现在成功响应里);`584131` 建议直接展示后端 `message`(已含团号与需求状态或"未提交用车需求"字样)。 --- ## 五、数据库行为 本单不新增任何数据库写操作。闸门仍是纯只读判定,随 finalize 既有事务执行;若判定不通过(`584131`),finalize 在写入结算数据之前即中止、整个事务回滚,不产生部分写入(未改)。不新增表、不新增列、不写 Flyway、不改索引。 --- ## 六、边界行为 - 未登录 → 401(网关拦截) - 订单不存在/状态不允许核单 → 沿用 finalize 既有前置校验(未改) - 团期子订单但 `needs_vehicle=0/null` → 直接放行,不查用车需求(未改) - 非团期订单 → 直接放行,不查用车需求(未改) - 用车需求行缺失,团已免车 → 直接放行,不判需求状态(本单新增分支) - 用车需求行缺失,团未免车 → **584131 硬阻断**(本单变化:改前是软预警放行) - 用车需求存在但未完成 → 584131(未改) - 老数据兼容:存量老响应结构不受影响,`warnings[]` 少了一种可能取值属于"取值集合收窄",未识别 `VEHICLE` 的前端旧代码本就不会崩溃,只是从此永远不会再看到它 --- ## 六.6、修改前后对比 ### 字段级对比 | 字段 | 改前 | 改后 | |------|------|------| | `warnings[].category` 可能取值 | HOTEL / TICKET / VEHICLE | HOTEL / TICKET(VEHICLE 退场) | | 错误码集合 | 584130/584131(仅需求未完成分支)/584100 | 584130/584131(需求未完成 **或** 需求缺失且未免车两个分支)/584100 | | 其余响应字段 | 无变化 | 无变化 | ### 行为级对比 | 行为 | 改前(#7445 交付后) | 改后(本单) | |------|------|------| | 团期子订单 + needs_vehicle=1 + 无 active 用车需求,未免车 | 200 成功,warnings 追加 category=VEHICLE 软预警 | **584131 硬阻断** | | 团期子订单 + 该团已整团免车 | 按上一行处置(软预警或阻断,取决于是否有需求行) | **整户跳过本闸,warnings 无车侧项,结算照常成功** | | 团期子订单 + 用车需求非"已完成" | 584131 | 不变,仍 584131 | | 团期子订单 + 用车需求"已完成" | 200 成功 | 不变 | | 非团期订单 / needs_vehicle=0 | 200 成功 | 不变,本闸不进 | --- ## 六.7、影响评估 - **是否破坏向后兼容**: 是。团期子订单在"用车需求缺失且未免车"这一状态下,由"可结算(软预警提示)"变为"584131 阻断"——这正是本单的设计目的,用于堵住"车根本没提需求也能结算"的洞。 - **前端是否必须同步上线**: 是。需要新增对 `584131`(若之前只处理需求未完成分支,现在还需处理缺失分支,文案已由后端一并给出)的错误提示;`warnings[]` 渲染逻辑不再需要兼容 `category=VEHICLE`(可保留兼容代码不强制删除,但新场景不会再触发)。 - **前端 workaround 清理点**: 若前端此前专门为 `category=VEHICLE` 软预警写过展示逻辑,可以保留(向前兼容,不会报错)也可以清理(该取值不会再出现)。 --- ## 七、不影响范围 - **仅影响**: `POST /v3/admin/order/{orderId}/settlement/finalize` 在团期子订单"用车需求缺失"这一状态下的错误码与 `warnings[]` 取值集合。 - **零影响**: - 核心(非团期)订单的 finalize 行为——完全不变。 - `needs_vehicle=0/null` 的存量团期订单——完全不变。 - finalize 内其余既有检查(住宿闸 584130、CASH_PAID 软预警、金额汇总写入)——未改动。 - `POST /v3/admin/order/{orderId}/settlement/submit` 及分步保存/草稿接口——本闸只挂在 finalize。 - `hl-fleet-service`、`hl-common-*`、`hl-gateway` 路由——本单只改 `hl-order-service-v3`,未新增路由配置。 --- ## 八、测试环境已验证 **取证环境**:order-v3 = dev-v3 `7d8cecb3e`(2026-09-15 15:38:56 部署)。 **已有网关取证的场景**: - 团车完成路径子订单 finalize 成功,未出现 `584131`/`584100`/`REPORT_SOURCE_CHANGED`,`order_settlement_vehicle_fee` 该单零行——见工单 #7441 验收评论。 - 团车/接送机混存子订单 finalize 成功,逐户车费只保留接送机一条——同上 AC-27(乙)。 - 历史 legacy 完成行子订单 finalize 抛 `584100`(车费链路拦截,未改行为,作为"团车路径与历史路径待遇不同"的对照)——见工单 #7441 验收评论。 **本轮未覆盖的分支(如实列出)**: - `584131` 的两个实际触发分支(户级需求缺失、需求存在但未完成)本轮测试服取证均未实际触发——已有证据均为"未出现该错误码"的成功路径对照,不是错误响应本身的网关实测。`#7445` 旧版软预警的取证(`11_7445`)覆盖的是改造前的行为,不能替代本次硬阻断分支的证据。 - `waive` 声明放宽到 `TRIP_FINISHED`/`REVIEWING` 阶段这一变化,本轮未实测在这两个新增阶段调用 `waive` 补点免车、随后 finalize 放行的完整链路。 --- ## 十、相关文档 - 关联 Issue: [wx/HL#7441](https://git.1814.love:8443/wx/HL/issues/7441) - 关联 PR: [#7763](https://git.1814.love:8443/wx/HL/pulls/7763) - 前置/关联依赖:`#7445`(`11_7445_团期用车结算闸-修改接口-管理后台.md`,本单改造的正是它交付的软预警分支,完整响应字段定义见该文)、`#7439`(团车来源在逐户费用链路里的正向标识判据,本单不改此逻辑) - 相关分册:`#7441` 正式用车需求声明四端点(本单免车判据的唯一生产者)、内部接口分册(团车完成回写,本单"用车需求已完成"判据的数据来源) - **验收口径边界**:页面完成状态单独跟踪(前端归 mmg),不计入 #7441 验收;#7441 验收范围 = API 契约 + 状态流转 + 占用账本 + changelog 交接件。 ## 关联 / 联系人 ### 链接 - **Issue**: [#7441](https://git.1814.love:8443/wx/HL/issues/7441) - **PR**: [#7763](https://git.1814.love:8443/wx/HL/pulls/7763) ### 联系人 - **后端负责人**: @wx - **前端负责人(收件人)**: @mmg