文件
hl-api-changelog/changelogs-v2/2026-09/15_7441_结算核单车侧闸门升级硬阻断-修改接口-管理后台.md
T
API Changelog Bot和Claude Opus 5 51d838baf8
changelog-filename-gate / validate (push) Failing after 1s
docs(order-v3): #7441 changelog 订正——取证出处改指工单评论、补验收口径边界与收件人
- 6 份 #7441 changelog:正文与 status_note 里的内部取证目录引用(20 处)改为「见工单 #7441 验收评论」,时间戳与部署提交号保留
- 5 份管理后台分册补「验收口径边界:页面完成状态单独跟踪(前端归 mmg),不计入 #7441 验收」;3 份补「前端负责人(收件人)@mmg」
- 15_确认行程清单 / 15_结算核单:frontend_status=not_required 时 verified_at 按校验器 E_FRONTEND_STATE 规则置空(mmg 核实结论保留在 status_note)

Refs #7441

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 03:33:40 +08:00

16 KiB
原始文件 Blame 文件历史

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
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
hl-changelog/v2 7441 完成核单车侧闸门升级为硬阻断——缺行改抛 584131,warnings[].category=VEHICLE 取值退场,免车团整户跳过 admin wx(GIT) 修改接口 deployed verified not_required 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。 2026-09-15 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<SettlementSubmitRespVO>

使用场景

管理后台核单页点击"完成核单"按钮时调用,原子完成结算并推订单进终态。调用方式、路径、入参完全不变。团期子订单(经统一判团门面判定)车侧户级闸门本单起行为变化,见下。完整响应字段(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

请求示例

POST /v3/admin/order/2099716821748715521/settlement/finalize HTTP/1.1
Authorization: Bearer {token}

(无请求体,仅 Path 参数 orderId;本单未改请求形态。)

响应示例

团车完成路径、免车团整户跳过:均能成功。以下为团车完成路径成功响应(测试服真实响应,2026-09-15,见工单 #7441 验收评论,warnings 未出现 VEHICLE 相关项):

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "orderId": "2099716821748715521",
    "orderStatusAfter": "待财务复核",
    "warnings": []
  }
}

空数据 / 降级响应

本闸不产生独立的空态/降级响应:warnings 在没有任何软预警时为空数组,判定不可达时按错误响应处理,不发生静默降级(不变)。

{ "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 逐户完成行(非团车、非快照来源)过车侧闸后在车费链路被拦 未改,本单不动 有(测试服真实触发,见第八节)
{
  "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
  • 关联 PR: #7763
  • 前置/关联依赖:#7445(11_7445_团期用车结算闸-修改接口-管理后台.md,本单改造的正是它交付的软预警分支,完整响应字段定义见该文)、#7439(团车来源在逐户费用链路里的正向标识判据,本单不改此逻辑)
  • 相关分册:#7441 正式用车需求声明四端点(本单免车判据的唯一生产者)、内部接口分册(团车完成回写,本单"用车需求已完成"判据的数据来源)
  • 验收口径边界:页面完成状态单独跟踪(前端归 mmg),不计入 #7441 验收;#7441 验收范围 = API 契约 + 状态流转 + 占用账本 + changelog 交接件。

关联 / 联系人

链接

联系人

  • 后端负责人: @wx
  • 前端负责人(收件人): @mmg