7445 团期用车结算闸(584131+VEHICLE 软预警)与 7446 住宿结算闸判团口径 (584130 判据修正),经 grep 实证 hl-admin 前端均零改动: - 前端无按码分支,request.js 通用 bizError 兜底透传后端 message 原文, 584131/584130 文案已含订单号+需求状态+操作指引,透传即达标。 - detail.vue warnings 渲染只取 item.message 且兼容过渡期字符串,从不读 settlementId/dayNumber 定位明细行,category=VEHICLE 项(恒 null)正常展示。 - 7446 契约一字未变仅触发人群变化,前端对 584130 无专属处理不受影响。 frontmatter 翻 frontend_status=not_required + owner=mmg + status_note 追加, 无业务 commit,ref 留空。
18 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 | 7446 | 住宿结算闸归团判据改走统一门面,修正已降级的 productBatchId 误用(584130 触发人群变更) | admin | wx(GIT) | 修改接口 | deployed | verified | not_required | mmg | 2026-09-11 | gateway_status=verified:2026-09-11 17:38 批次网关实测已完成(详见“八、测试环境已验证”),经 hl-gateway 网关调用 POST /v3/admin/order/{orderId}/settlement/finalize 验证四组场景(含 584130 硬阻断与放行分支)。所有前置条件均为 SQL 直更需求表状态构造,非真实业务链路(配房)产生;另绕过与本单无关的 584310/584082/车费草稿冻结确认三道通用前置闸,其正确性未验证;本单“团期已软删放行”这一唯一取舍点未在本次网关实测中单独覆盖。前端 2026-09-11 闭环 not_required:本单只改住宿闸归团判据(productBatchId 误用→统一门面 isGroupSubOrder),584130 错误码值/符号/message 文案/响应结构一字未变,仅触发人群变化;前端对 584130 本就无专属处理走兜底透传后端 message,人群变化不影响识别/展示逻辑。零业务代码改动。 | 2026-09-11 | dev-v3 |
order-v3: 住宿结算闸归团判据改走统一门面
服务: hl-order-service-v3 PR: #7504 Issue: #7446 日期: 2026-09-11 影响范围: 既有端点
POST /v3/admin/order/{orderId}/settlement/finalize(完成核单)中住宿结算闸(584130)的归团判据修正;签名、错误码值/符号/message 文案、响应结构均未改,仅 584130 的触发人群变化。
⚠️ 关键变化
本次只改判据,不改契约:POST /v3/admin/order/{orderId}/settlement/finalize 的住宿结算闸(错误码 584130)判断"这单是不是团期子订单"的依据,从 order.getProductBatchId() == null 改为统一判团门面 OrderService.resolveGroupBatchLinks(经新增私有方法 isGroupSubOrder 转发;#7445 已在同一方法体建立该方法,本单复用)。
之前的 changelog(#7347,见十节链接)说"闸门只对 productBatchId 非空的订单生效"——这句话现在不再准确,判团依据已改为统一门面。签名、错误码值/符号、message 文案与两个占位参数、响应体结构均未改变,但 584130 实际覆盖的订单范围变了:
- 一部分此前被静默漏判为非团期从而放行的订单(
group_batch_id非空但product_batch_id为空,即"脱离产品排期独立建团"的团单),现在会被 584130 正确拦截。 - 一部分此前因裸列判断误判为团期从而阻断的订单(
product_batch_id非空、group_batch_id为空、且所属团期已被软删),现在会被判定为非团期,改为放行——这是本单唯一一处放松结算闸的已知取舍(详见"六.6")。
前端无需修改任何代码:错误码、message 文案、响应结构一字未变,只是该错误码出现的订单范围变了。
一、背景
SettlementService.assertGroupHotelReadyForFinalize(#7347/PR #7433 引入的住宿户级闸门,方法体内新增于本单之前)原判团短路条件是 order.getProductBatchId() == null。但 product_batch_id 自 Issue #7083 起已被显式降级为"产品侧排期溯源 + 迁移期两跳回退通路"、不再作归团判别——order_main 表的列 COMMENT 与 OrderInfo.java 的字段 javadoc 均明确记载归团判别唯一依据是 group_batch_id。用错判据会让闸门在"建团脱离产品排期"的一部分团单上静默不生效,#7347 想堵的洞在这批订单上依然成立。
本单不是简单地把 getProductBatchId 换成 getGroupBatchId——单列直换会在另一个方向开新洞:group_batch_id 是 #7083 后加列,存量靠回填脚本、增量靠创单同事务回写、漏网靠对账 Job 兜底,三者都不是瞬时完成的,回填窗口期内团期仍存活但 group_batch_id 尚未回填的老单,裸判会把它们误判成普通单直接放行。本单改调仓内已有的统一判团口径 OrderService.resolveGroupBatchLinks(一跳 group_batch_id、为空再两跳回退 product_batch_id),两个方向都不漏。与 #7445(同一方法体新增的用车闸)已协调统一使用同一私有方法 isGroupSubOrder,避免同一方法体内相邻两道闸对同一订单给出相反的"是不是团单"结论。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 完成核单 | POST | /v3/admin/order/{orderId}/settlement/finalize |
判据修正(584130 触发人群变更) | 住宿结算闸归团判据由已降级的 productBatchId 改走统一判团门面 |
三、接口详情
1. 完成核单 POST /v3/admin/order/{orderId}/settlement/finalize
VO: Long(Path 参数 orderId,无请求体) → Result<SettlementSubmitRespVO>
使用场景
管理后台核单页点击「完成核单」按钮时调用,原子完成结算并推订单进终态。本单不改调用方式、不改请求/响应结构,只改住宿闸内部的归团判据,因此本节按模板要求自包含列出请求/响应契约(与 #7445 changelog 重复列出属正常,两单各自独立可读)。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| orderId | Path | Long | 是 | 大于等于1 | 订单 ID;本单未改 |
(finalize 本身无请求体,本单未新增/删除任何入参。)
出参字段表
Result<SettlementSubmitRespVO>,字段集合本单未增删任何字段(本单只改内部判据,不改响应结构),为保证本节自包含仍列出关键字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| orderId | Long | 订单 ID |
| finalSnapshotStatus | String | 核单终态快照状态 |
| totalAmount | BigDecimal | 订单总金额快照 |
| paidAmount | BigDecimal | 已付金额快照 |
| roomCost | BigDecimal | 住宿实际成本 |
| totalActualCost | BigDecimal | 总实际成本 |
| orderStatusAfter | String | 结算后订单状态 |
| warnings | List | 软预警列表;本单不改其结构与产出逻辑 |
(完整字段清单共 24 个,见 SettlementSubmitRespVO;本单未增删任何字段,故不重复列出全部,只摘录关键项用于自包含理解。)
请求示例
POST /v3/admin/order/1934567890123456789/settlement/finalize
Authorization: Bearer {token}
(无请求体,仅 Path 参数 orderId;本单未改请求形态)
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"orderId": "1934567890123456789",
"finalSnapshotStatus": "FINALIZED",
"totalAmount": "24800.00",
"paidAmount": "24800.00",
"roomCost": "4280.00",
"totalActualCost": "23120.00",
"orderStatusAfter": "待财务复核",
"warnings": []
}
}
空数据 / 降级响应
本闸不产生独立的空态/降级响应;判团查询是既有门面的纯本地只读查询(同库同服务,非 Feign/MQ),不发生外部降级。warnings 为空时返回空数组:
{ "code": 200, "success": true, "data": { "warnings": [] } }
错误响应
584130 错误码本身未变,仅摘录触发该码的一个示例(判团结果来自统一门面而非旧的 productBatchId 判据):
{
"code": 584130,
"message": "团期子订单 GB202609120007 的住宿尚未安排完成(住宿需求当前状态:PROCESSING),请等房务配房完成后再提交核单",
"success": false,
"data": null
}
message 模板(SettlementErrorCode.SETTLEMENT_GROUP_HOTEL_NOT_READY,584130,本单未改):团期子订单 {0} 的住宿尚未安排完成(住宿需求当前状态:{1}),请等房务配房完成后再提交核单。{0} = 订单号 orderNo;{1} = 住宿需求当前 status 字面量,需求缺失时固定文案"未提交住宿需求"。
业务边界
- 判团口径统一为
OrderService.resolveGroupBatchLinks(经私有方法 isGroupSubOrder 转发),不再使用已降级的 productBatchId;该方法同时被 #7445 新增的用车闸复用,是全类唯一的判团落点。 - needsHotel 半条件判断依旧前置:短路顺序为"先 needsHotel、后判团",needs_hotel=0/null 时直接放行、不发判团查询(与改动前一致,未变)。
- 已知取舍:所属团期已被软删的订单(product_batch_id 非空、group_batch_id 为空、团期已软删)此前会因 productBatchId 非空而进闸判定住宿状态,改判后判定为非团期、跳闸放行——这是本单唯一一处放松结算闸的行为变更,详见"六.6"。
- 待回填窗口内的老单(product_batch_id 非空、group_batch_id 为空、团期存活)判团口径经统一门面的两跳回退仍判定为团单,闸门继续生效,不受影响。
- 判定语义本身完全未变:仍只读户级住宿需求 status,仍只认 DONE 放行,不读住宿派生行,不解析行程日自行判断"是否自助订房"。
四、契约约束与正确调用方式
正确 / 错误 调用结果对照(本单不改请求 payload,用订单形态代替)
| 场景(订单形态) | 结果 |
|---|---|
| group_batch_id 非空 + product_batch_id 非空(常规团单),住宿需求非 DONE | 584130(不变) |
| group_batch_id 非空 + product_batch_id 为空(脱离产品排期建团),住宿需求非 DONE | 584130(改前静默漏判放行,本单修正为阻断) |
| product_batch_id 非空 + group_batch_id 为空 + 团期存活(回填窗口老单),住宿需求非 DONE | 584130(不变,两跳回退保住) |
| product_batch_id 非空 + group_batch_id 为空 + 团期已软删,住宿需求非 DONE | 放行(改前 584130,改后判定为非团单,已知取舍) |
| 两列皆空(核心散客单) | 放行(不变) |
| needs_hotel=0/null | 放行(不变,且改后连判团查询都不发) |
切换状态时的必要动作
无需前端做任何动作。本单不改请求 payload、不改错误码、不改响应结构,仅内部判据修正;前端现有对 584130 的处理逻辑无需调整,唯一影响是该错误码出现的订单范围变了(不改变前端识别/展示逻辑)。
五、数据库行为
本单不写数据库。判团查询是既有门面 OrderService.resolveGroupBatchLinks 的纯只读查询(同库同服务本地查询,非 Feign/MQ),不新增表、不新增列、不新增索引、不写 Flyway。判定不通过时 finalize 在写入结算数据之前即中止、整个事务回滚,不产生部分写入。
六、边界行为
- 未登录 → 401(网关拦截)
- needs_hotel=0/null → 直接放行,不发判团查询(短路顺序:先 needsHotel、后判团,未变)
- 判团查询本身若异常,走既有全局异常处理,本单不新增降级分支
- 团期已软删的订单 → 判定为非团期,放行(已知取舍,见"六.6")
- 待回填窗口老单(团期存活但 group_batch_id 未回填)→ 判定为团期,闸门继续生效(不受回填进度影响)
六.5、枚举
本单不新增、不改变任何响应字段的枚举取值。584130 的两个 message 占位符沿用既有定义,未变:
584130 message 占位符 {1}(com.hulalv.order.requirement.enums.RequirementStatus)
所属字段: 错误响应 message 文本内嵌值(非独立 JSON 字段) | 类型: String
| 值 | 中文 | 是否放行本闸 |
|---|---|---|
| PENDING | 待房务配 | 否 |
| PROCESSING | 配房中 | 否 |
| DONE | 配房完成 | 是(唯一放行值) |
| PENDING_REVIEW | 待审核 | 否 |
| REJECTED_TO_CONSULTANT | 驳回 | 否 |
| REJECTED_TO_ADMIN | 驳回 | 否 |
warnings[].category(com.hulalv.order.settlement.enums.SettlementCategory,本单未改动,供自包含参照)
所属字段: warnings[].category | 类型: String
| 值 | 中文 | 说明 |
|---|---|---|
| HOTEL | 住宿 | 既有取值,本单未改 |
| TICKET | 门票/游玩项目 | 既有取值,本单未改 |
| VEHICLE | 车辆 | 既有取值(由 #7445 同批引入,本单未涉及) |
六.6、修改前后对比
字段级对比
无字段级变化。请求 payload(无)、响应体 SettlementSubmitRespVO 的字段集合均未改动;584130 的错误码值、符号、message 文案、两个占位参数均未改;仅错误响应触发人群变化。
行为级对比
| 订单形态 | 改前 | 改后 |
|---|---|---|
| group_batch_id 非空、product_batch_id 非空(绝大多数团单) | 进闸 | 进闸(不变) |
| group_batch_id 非空、product_batch_id 为空(脱离产品排期建团) | 跳闸(漏判) | 进闸(本单修正) |
| product_batch_id 非空、group_batch_id 为空、团期存活(回填窗口老单) | 进闸 | 进闸(不变,靠门面两跳回退保住) |
| product_batch_id 非空、group_batch_id 为空、团期已软删 | 进闸 | 跳闸(行为变更,已知取舍,见下方说明) |
| 两列皆空(核心散客单) | 跳闸 | 跳闸(不变) |
| needs_hotel 为 0/null | 跳闸 | 跳闸(不变,且改后连判团查询都不发) |
关于"团期已软删"这一行的取舍说明:门面对团期已软删的订单返回"不归团"(反查通道被软删过滤),于是这批订单从"今天进闸"变为"跳闸"。这仍是行为变更。之所以可接受:软删团期不再提供子订单视图是 #7083 已确立的系统级口径,团都解散了还卡住结算不符合业务预期;工单要求先量化受影响订单数再合并(工单 AC-1 的方向乙 SQL),量化结果见工单本身,本 changelog 不重复贴库查数据。
六.7、影响评估
- 是否破坏向后兼容: 是(覆盖人群变化——一部分订单从放行变阻断,一部分从阻断变放行;签名、错误码值/符号、响应结构本身不变)。
- 前端是否必须同步上线: 否。前端无需改代码;错误码、message 文案、响应结构一字未变,前端现有对 584130 的处理逻辑无需调整。
- 前端 workaround 清理点: 无。
七、不影响范围
- 仅影响:
POST /v3/admin/order/{orderId}/settlement/finalize中住宿结算闸(assertGroupHotelReadyForFinalize)的归团判据。 - 零影响:
- 584130 的错误码值/符号/message 文案/两个占位参数——完全不变。
- 响应结构 SettlementSubmitRespVO 的任何字段——不增删。
- 住宿闸的判定语义本身(只读户级需求 status/只认 DONE 放行/不看派生行/不解析行程日)——逐字节未变。
- #7445 新增的用车闸(同一方法体内相邻代码,但两者是独立判定,互不影响各自触发条件)。
POST /v3/admin/order/{orderId}/settlement/submit及分步保存/草稿接口。- 核心(非团期)订单的 finalize 行为。
- fleet 侧、hl-common-*、网关路由、权限点——均未改动。
八、测试环境已验证
取证环境(2026-09-11 17:38 批次,hl-gateway、hl-order-service-v3 当时一致停在 dev-v3 f035b85be):
hl-gateway dev-v3 f035b85be 0/N 2026-09-11 17:25:31 ok
hl-order-service-v3 dev-v3 f035b85be 0/N 2026-09-11 17:24:23 ok
端点:POST /v3/admin/order/{orderId}/settlement/finalize,角色 ADMIN,经 hl-gateway 网关实调。
四组请求/响应:
| 场景 | 前置 | code | message 原文 |
|---|---|---|---|
| 方向甲(group_batch_id 非空 + product_batch_id 为空)+ 住宿 PENDING | 订单 HL20260819230221927;SQL 直更住宿需求为 PENDING | 584130 | 团期子订单 HL20260819230221927 的住宿尚未安排完成(住宿需求当前状态:PENDING),请等房务配房完成后再提交核单 |
| 同订单住宿推 DONE | SQL 直更回 DONE | 200 | 成功(finalSnapshotStatus=FINALIZED) |
| 待回填老单(product_batch_id 非空 + group_batch_id 为空 + 团期存活) | 订单 HL20260819224314154;团期 deleted_at IS NULL 已实测 | 584130 | 团期子订单 HL20260819224314154 的住宿尚未安排完成(住宿需求当前状态:PENDING),请等房务配房完成后再提交核单 |
| 核心散客单 | 订单 HL20260819223840144,两列均 NULL | 200 | 成功 |
取证边界(如实说明,不得省略):
- 以上所有前置条件均为 SQL 直更需求表 status 构造,不是配房链路真实产生的业务状态;配房链路本身未在本次取证中被验证。本单唯一的放松取舍点——"团期已被软删的订单改为放行"(见"六.6")——未在本次网关实测中单独覆盖。
- 取证过程中用 SQL 绕过了与本单无关的三道通用前置闸:584310(八个核单分类未全部确认)、584082(待收尾款)、车费草稿冻结确认——手段是把明细行标记 CONFIRMED、把应收金额清零对齐已付。这三道闸自身的正确性未在本次取证中验证。
backend_status: "deployed" 代表代码已合并 dev-v3 并随服务部署(合并提交 da3bd7854,2026-09-11 10:42:41,PR #7504);gateway_status 现更新为 verified,依据即上述 2026-09-11 17:38 网关实测。存量影响量化(工单 AC-1 的方向甲/方向乙/方向丙三条 SQL 结果)由工单正文本身承载,本节不重复贴库查数据。
十、相关文档
- 关联 Issue: wx/HL#7446
- 关联 PR: wx/HL#7504
- 前置/关联依赖:
#7347(原始需求单,PR #7433 引入了本单要修正的判据缺陷,本单是其判据订正件而非同一工单的延续)、#7445(同一方法体内新增的用车闸,与本单共用私有方法 isGroupSubOrder,#7445 先合、#7446 随后统一判团口径)、#7449(判团口径统一,收口全仓其余 23 处同类 productBatchId 误用,本单不处理,另建单处理)
关联 / 联系人
链接
联系人
- 后端负责人: @wx