- 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>
16 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
| 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(完成核单),团期子订单车侧户级闸门由软预警升级为硬阻断,方法、路径、入参、响应结构均未改
⚠️ 关键变化
- 团期子订单"用车需求缺失"从软预警升级为硬阻断——
#7445交付时,该场景只在成功响应的warnings[]里追加一条category=VEHICLE的提示,finalize仍会成功;本单起改为直接抛业务错误码584131,finalize不再成功。 warnings[].category="VEHICLE"这一取值从此不再出现——#7445changelog 曾让前端为它做过渲染容错,本单起该取值退场,不要因为看不到它而报错,也不要把584131当系统异常展示。- 整团声明"本团无需用车"(
waive)的团,该户整户跳过车侧闸门——finalize照常成功,不判用车需求状态。 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 交接件。