From 243ec1c164f2def770d24487f2fc064899a77171 Mon Sep 17 00:00:00 2001 From: API Changelog Bot Date: Wed, 16 Sep 2026 07:30:28 +0800 Subject: [PATCH] =?UTF-8?q?docs(order-v3):=20#7781=20=E6=A0=B8=E5=8D=95?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E6=9C=AA=E7=A1=AE=E8=AE=A4=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E8=AF=AD=E8=A1=A5=E5=88=86=E7=B1=BB=E5=90=8D=20584310=20change?= =?UTF-8?q?log=EF=BC=88=E5=B7=B2=E9=83=A8=E7=BD=B2=20dev-v3=20d3d4755e9=20?= =?UTF-8?q?=E5=B9=B6=E5=AE=9E=E6=B5=8B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) --- ...œª确认提示语补分类名584310-修改接口-管理后台.md | 393 ++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 changelogs-v2/2026-09/16_7781_核单分类未确认提示语补分类名584310-修改接口-管理后台.md diff --git a/changelogs-v2/2026-09/16_7781_核单分类未确认提示语补分类名584310-修改接口-管理后台.md b/changelogs-v2/2026-09/16_7781_核单分类未确认提示语补分类名584310-修改接口-管理后台.md new file mode 100644 index 00000000..930de032 --- /dev/null +++ b/changelogs-v2/2026-09/16_7781_核单分类未确认提示语补分类名584310-修改接口-管理后台.md @@ -0,0 +1,393 @@ +--- +schema: "hl-changelog/v2" +ticket: "7781" +title: "核单分类未确认提示语补分类名(584310 文案含占位符)" +consumer: "admin" +author: "wx(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "not_required" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "已合并 dev-v3(squash 提交 d3d4755e9,PR #7781),测试服 hl-order-service-v3 已部署该提交(2026-09-16 07:10:22,deploy-status.sh 核实 commit=d3d4755e9、BEHIND=0/N)。触发点一(8 分类循环,HOTEL 命中)已用自造测试订单实测:POST /v3/admin/order/8880000000778101001/settlement/finalize 返回 code=584310、message=核单分类「住宿」明细尚未全部确认或数据已变化,占位符已正确替换为具体分类名。触发点二(SettlementVehicleFeeSnapshotWriter 车辆草稿未确认,分类恒填「车辆」)本次未取证:该分支要求先有真实车辆需求+Fleet 派车+车辆草稿快照(reconcile 需要 Fleet Feign 真实回填数据),用直接 SQL 造数无法安全绕过 draftService.loadCandidate/lockReadySnapshot 的事实一致性比对(会被判 REPORT_SOURCE_CHANGED 而非 584310),需要完整走一遍团期车务派车流程才能自然触发,超出本次取证窗口,未编造该路径证据。本次没有新增 admin 路由,gateway_status=not_required。frontend_status=pending:若 hl-ui 存在对旧文案 八个核单分类尚未全部确认或数据已变化 做精确字符串匹配的逻辑,必须改为按 code=584310 判定,新文案恒含动态分类名,旧字面量不会再出现。本单无独立 Gitea Issue,PR #7781 备注 无关联工单(顺带发现的两处问题)。" +updated_at: "2026-09-16" +base: "dev-v3" +--- + +# order-v3: 核单分类未确认提示语补分类名(584310) + +> **存放目录**: `changelogs-v2/{YYYY-MM}/`(管理后台,二期 order-v3) +> +> **服务**: hl-order-service-v3 (端口 8083) +> **PR**: #7781 +> **Issue**: 无独立 Issue(PR 备注「无关联工单(顺带发现的两处问题)」) +> **日期**: 2026-09-16 +> **影响范围**: 错误码 `584310`(`CATEGORY_CHECK_INCOMPLETE`)的 message 文本;`code`、HTTP 状态(恒 200)、`data`、请求/响应结构均未改 + +--- + +## ⚠️ 关键变化 + +🔴 **错误码 `584310` 的 message 文本变了,`code` 和 HTTP 状态都没变(HTTP 恒 200,`code=584310`)。** + +- 改前:`八个核单分类尚未全部确认或数据已变化`(固定文案,不含分类名) +- 改后:`核单分类「{0}」明细尚未全部确认或数据已变化`,`{0}` 由后端填成实际未确认的分类名(取值来自 `SettlementCategory` 枚举 label,共 8 个分类,见「六.5、枚举」) + +🟡 **前端如果之前对旧文案「八个核单分类尚未全部确认或数据已变化」做过精确字符串匹配(例如按 message 做特殊提示/埋点),该匹配会永久失效——新文案恒含动态分类名,旧字面量不会再出现。必须改为按 `code === 584310` 判定,见「四、契约约束与正确调用方式」。** + +🟢 **测试环境已验证**(2026-09-16,order-v3 dev-v3 `d3d4755e9`):触发点一(8 分类循环,HOTEL 命中)自造订单实测通过,返回 `code=584310`、`message=核单分类「住宿」明细尚未全部确认或数据已变化`;触发点二(车辆草稿未确认)因需真实 Fleet 派车数据未取证,详见「八、测试环境已验证」。 + +--- + +## 一、背景 + +`SettlementFinancialErrorCode.CATEGORY_CHECK_INCOMPLETE`(584310)原来的模板不带占位符,但两处实际抛出点早就在传分类名参数——参数被静默丢弃(模板没有 `{0}` 时不经 `MessageFormat.format`,直接原样返回模板本身)。前端只能看到笼统的「八个核单分类尚未全部确认或数据已变化」,无法定位到底是哪个分类没确认。本单只改模板加占位符,并给两处抛出点分别核实/补传参数,不改判定逻辑本身、不改触发条件。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 完成核单 | POST | `/v3/admin/order/{orderId}/settlement/finalize` | 错误码文案修正 | `584310` message 模板补分类占位符;`code`/HTTP 状态/响应结构不变 | + +--- + +## 三、接口详情 + +### 1. 完成核单 `POST /v3/admin/order/{orderId}/settlement/finalize` + +**VO**: `无请求体 → SettlementSubmitRespVO` + +#### 使用场景 + +管理后台核单页「完成核单」按钮:提交主报账、单团核算双指纹,原子冻结车辆事实并把核单标记为终态。本单不改这个端点的请求/响应结构,只改它在两种失败场景下返回的 584310 message 文本。 + +584310 只能通过这一个端点触发——全仓 `CATEGORY_CHECK_INCOMPLETE` 共 2 处生产代码抛出点,两处都在本端点的调用链上(见「四、契约约束与正确调用方式」的调用链说明),没有第三条触发路径。 + +#### 入参字段表 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| orderId | Path | Long | 是 | 大于 0 | 订单 ID;不变 | + +(无请求体,本单未改任何入参。) + +#### 出参字段表 + +| 字段 | 类型 | 说明 | +|------|------|------| +| summaryId | String(雪花 ID) | 新写入的 settlement_summary 主键 | +| finalSnapshotId | String(雪花 ID) | 核单终态快照 ID | +| finalSnapshotVersionNo | Integer | 核单终态快照版本号 | +| finalSnapshotStatus | String | 核单终态快照状态 | +| orderId | String(雪花 ID) | 订单 ID | +| settledAt | String(LocalDateTime) | 核单完成时间 | +| totalAmount | String(金额) | 订单总金额快照 | +| paidAmount | String(金额) | 已付金额快照 | +| balanceAmount | String(金额) | 尾款金额快照 | +| roomCost | String(金额) | 住宿实际成本 | +| ticketCost | String(金额) | 门票实际成本 | +| staffCost | String(金额) | 人员费用实际成本 | +| subsidyCost | String(金额) | 补助实际成本 | +| mealCost | String(金额) | 餐食实际成本 | +| vehicleCost | String(金额) | 车辆基础服务总车费 | +| otherExpenseCost | String(金额) | 其他支出实际成本 | +| insurancePremium | String(金额) | 保险实际保费 | +| totalActualCost | String(金额) | 总实际成本 | +| driverTransferAmount | String(金额) | 给司机/主报账人转回金额 | +| profitAmount | String(金额) | 公司毛利 | +| profitRate | Number(小数) | 毛利率 | +| orderStatusAfter | String | 结算后订单状态 | +| mqTriggered | Boolean | 当前版本固定 false | +| warnings | Array of WarningItemVO | 软预警列表 | + +以上字段全部来自 `SettlementSubmitRespVO` 既有定义,本单一个字段都没改;列出仅为满足模板「逐接口自包含」要求。 + +#### 请求示例 + +```http +POST /v3/admin/order/2099716954674597889/settlement/finalize HTTP/1.1 +Authorization: Bearer {token} +``` + +(无请求体,仅 Path 参数 orderId;本单未改。) + +#### 响应示例 + +成功响应结构本单未动,字段值取自源码 `@ApiModelProperty(example=...)` 声明(本单只改错误响应文案,成功响应本身未实测,见「八、测试环境已验证」): + +```json +{ + "code": 200, + "message": "成功", + "data": { + "summaryId": "9600000000001", + "finalSnapshotId": "9600000000002", + "finalSnapshotVersionNo": 1, + "finalSnapshotStatus": "FINALIZED", + "orderId": "12345678901234", + "settledAt": "2026-05-26T10:30:25", + "totalAmount": "24800.00", + "paidAmount": "24800.00", + "balanceAmount": "0.00", + "roomCost": "4280.00", + "ticketCost": "3680.00", + "staffCost": "14260.00", + "subsidyCost": "720.00", + "mealCost": "860.00", + "vehicleCost": "5200.00", + "otherExpenseCost": "1260.00", + "insurancePremium": "180.00", + "totalActualCost": "23120.00", + "driverTransferAmount": "22940.00", + "profitAmount": "1680.00", + "profitRate": 0.0677, + "orderStatusAfter": "待财务复核", + "mqTriggered": false, + "warnings": [] + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无列表/分页语义,不存在空数据形态。warnings 为空数组时代表无软预警,不阻塞提交: + +```json +{ "code": 200, "success": true, "data": { "warnings": [] } } +``` + +#### 错误响应 + +584310 可能由两个不同的判定点触发,都在本端点内,都是本单实际改动点: + +| 触发点 | 场景 | `{0}` 取值 | +|---|---|---| +| `SettlementCategoryCheckService.validateReadyForReport`(`hl-order-service-v3/src/main/java/com/hulalv/order/settlement/service/SettlementCategoryCheckService.java:85-92`) | 按 `SettlementCategory` 枚举声明顺序(住宿/门票游玩项目/餐食/车辆/导游/摄影/其他收入/其他支出)逐个检查「有明细行但未全部确认」,命中第一个就抛出并停止,不会一次性列出全部未确认分类 | 8 个分类中,第一个命中的那个 | +| `SettlementVehicleFeeSnapshotWriter.replaceAndFreezeDraftInCurrentTransaction`(`hl-order-service-v3/src/main/java/com/hulalv/order/settlement/service/SettlementVehicleFeeSnapshotWriter.java:250-256`) | 车辆草稿行存在未确认(`settlementConfirmStatus` 不等于 `CONFIRMED`);该方法只处理车辆草稿行,在整个 finalize 调用链里先于上一行的 8 分类循环执行 | 恒为「车辆」(硬编码 `SettlementCategory.VEHICLE.getLabel()`,与草稿行具体是哪一条无关) | + +示例一(车辆草稿未全部确认,命中较早的判定点): + +```json +{ + "code": 584310, + "message": "核单分类「车辆」明细尚未全部确认或数据已变化", + "data": null, + "success": false +} +``` + +示例二(8 分类循环命中「餐食」,其余分类此前已确认或为空): + +```json +{ + "code": 584310, + "message": "核单分类「餐食」明细尚未全部确认或数据已变化", + "data": null, + "success": false +} +``` + +改前(两处触发点,本单修复前的固定文案,不区分分类): + +```json +{ + "code": 584310, + "message": "八个核单分类尚未全部确认或数据已变化", + "data": null, + "success": false +} +``` + +#### 业务边界 + +- **584310 只在本端点触发**:全仓 `CATEGORY_CHECK_INCOMPLETE` 只有上表两处生产代码抛出点,且都只能通过 `POST /v3/admin/order/{orderId}/settlement/finalize` 这一条调用链到达(`SettlementController.finalizeSettlement` → `SettlementFinalizeOrchestrator` → `SettlementFinalizeLockService` → `SettlementFinalizeTxService.finalizeSettlement`,内部依次调用车辆冻结与 8 分类校验)。 +- **8 分类循环短路**:`validateReadyForReport` 按枚举声明顺序(住宿/门票游玩项目/餐食/车辆/导游/摄影/其他收入/其他支出)遍历,一旦命中未确认分类立即抛出,不会把全部未确认分类一次性列全;前端不能假设 message 里的分类名是唯一一个未确认分类,重试提交、修完这个再确认下一个可能还会拿到另一个分类名的 584310。 +- **空分类不计入判定**:某分类若没有任何明细行(`rowCount() == 0`),不需要确认,不会触发 584310,即使它看起来没被确认过。 +- **车辆草稿分类名恒为「车辆」**:即使草稿行本身归属不同需求(如接送机/包车),触发点二的占位符固定填「车辆」,不细分到具体是哪一条草稿行。 +- **`data` 恒为 `null`**:与改前一致,本单未改 `Result.error(ec, args)` 的调用方式,仍是 `code + message`,不带附加结构化载荷。 +- **不做兼容双发**:后端不会同时给出旧文案和新文案,也不新增字段承载纯分类名——分类名只存在于 message 字符串里,前端要拿分类名必须自己从 message 里按「」定界解析,或者干脆只按 `code` 判定、把 message 原样展示给用户(推荐做法,见下节)。 + +--- + +## 四、契约约束与正确调用方式 + +> 本节只写后端接受/拒绝 payload 的规则,不写 UI 渲染建议。 + +### 正确 / 错误 判定方式对照 + +| 场景 | 判定方式 | +|------|---------| +| 正确:只用 `code` 判定是否为核单分类未确认错误 | `if (resp.code === 584310) { ... }` | +| 正确:需要展示分类名时,直接展示 `message` 原文(后端已经把分类名拼好) | `showToast(resp.message)` | +| 错误:对 `message` 做精确字符串匹配 | `if (resp.message === "八个核单分类尚未全部确认或数据已变化")`,本单起该字面量永久不会再出现,匹配会一直失败 | +| 错误:假设一次 584310 只会报一个唯一未确认分类,据此更新本地已确认分类清单 | 见业务边界短路说明,可能还有其他未确认分类没被这次报出来 | + +### 调用链(说明 584310 为什么只挂在这一个端点上) + +``` +SettlementController.finalizeSettlement (POST /v3/admin/order/{orderId}/settlement/finalize) + -> SettlementFinalizeOrchestrator.finalizeSettlement + -> SettlementFinalizeLockService.finalizeSettlement + -> SettlementFinalizeTxService.finalizeSettlement + +- SettlementVehicleFreezeService.freezeForFinalizeInCurrentTransaction + | -> SettlementVehicleFeeSnapshotWriter.replaceAndFreezeDraftInCurrentTransaction (触发点二,恒「车辆」) + +- SettlementService.finalizeInCurrentTransaction + -> SettlementReportFlowService.prepareFinalizationInCurrentTransaction + -> SettlementCategoryCheckService.validateReadyForReport (触发点一,8 分类循环) +``` + +前端无需改任何请求参数——本端点入参/路径未变;判定完全由后端按订单当前核单分类确认状态计算。 + +--- + +## 五、数据库行为 + +本单不改任何数据库读写行为,属于纯文案/参数传递修正:两处判定的读取逻辑(哪个分类算未确认)本身完全不变,只是把早就存在的 `category.getLabel()` 参数真正传进消息格式化。`finalize` 端点既有的核单写入语义(写 settlement_summary/终态快照/状态流水等)不在本单改动范围内,不在此重复。 + +--- + +## 六、边界行为 + +- 未登录 → 401(网关拦截,不变) +- `orderId <= 0` → 400(`@Min` 校验,不变) +- 8 个分类全部确认(或没有明细行)→ 不触发 584310,走正常 finalize 流程(不变) +- 车辆草稿行未全部确认 → 584310,分类名填「车辆」(本单起分类名可见,改前是固定文案) +- 非车辆分类(住宿/门票游玩项目/餐食/导游/摄影/其他收入/其他支出)有明细行但未全部确认 → 584310,分类名为 8 分类循环里第一个命中的分类名(本单起分类名可见) +- 老数据兼容:本单不改任何判定条件,存量订单的确认状态数据无需回填、无需迁移,行为按新文案原样生效 + +--- + +## 六.5、枚举 / 数据字典 + +**所属字段**:错误响应 `message` 中占位符的取值来源(不是请求/响应 JSON 里的字段,`message` 整体仍是 `String`)| **枚举类**:`com.hulalv.order.settlement.enums.SettlementCategory` + +| 值(枚举名) | label(占位符实际填入的中文) | 说明 | +|----|------|------| +| `HOTEL` | 住宿 | | +| `TICKET` | 门票/游玩项目 | label 本身含斜杠,不是格式错误 | +| `MEAL` | 餐食 | | +| `VEHICLE` | 车辆 | 触发点二恒填此值;触发点一按遍历顺序命中时也可能填此值 | +| `GUIDE` | 导游 | | +| `PHOTOGRAPHER` | 摄影 | | +| `OTHER_INCOME` | 其他收入 | | +| `OTHER_EXPENSE` | 其他支出 | | + +触发点一(`validateReadyForReport`)按上表从上到下的顺序遍历并短路——`VEHICLE` 排第 4 位,只有前 3 个分类都确认完毕,才可能在这个循环里报出车辆分类;正常情况下车辆的未确认状态会先被触发点二拦截。 + +--- + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| `code`(584310) | `584310` | `584310`(不变) | +| HTTP 状态 | `200` | `200`(不变,恒 `@ResponseStatus(HttpStatus.OK)`) | +| `message` 模板(`SettlementFinancialErrorCode.CATEGORY_CHECK_INCOMPLETE`) | `八个核单分类尚未全部确认或数据已变化`(无占位符) | `核单分类「{0}」明细尚未全部确认或数据已变化`(占位符为分类 label) | +| `data` | `null` | `null`(不变) | + +### 行为级对比 + +| 场景 | 改前返回的 message | 改后返回的 message | +|------|------|------| +| 车辆草稿未全部确认 | `八个核单分类尚未全部确认或数据已变化` | `核单分类「车辆」明细尚未全部确认或数据已变化` | +| 餐食有明细行但未全部确认(其余分类已确认) | `八个核单分类尚未全部确认或数据已变化` | `核单分类「餐食」明细尚未全部确认或数据已变化` | +| 8 个分类全部确认 | 不触发 584310(不变) | 不触发 584310(不变) | + +--- + +## 六.7、影响评估 + +- **是否破坏向后兼容**:`code`/HTTP 状态/`data` 结构均未改,接口契约的机器可读部分向后兼容;但 `message` 的字面量值变了——若前端按旧文案精确字符串匹配,这类匹配会被破坏(见下)。 +- **前端是否必须同步上线**:视前端现有实现而定。若 hl-ui 对 584310 的 `message` 做过精确字符串匹配(不管是用于弹窗文案分支还是埋点),必须同步改为按 `code === 584310` 判定;若前端本就是拿到 584310 直接展示 message 原文、不做字符串匹配的口径,则零改动。本单未接触 hl-ui 代码库,无法从后端仓库判定该假设是否成立,需前端自行核实(对应 `frontend_status: pending`)。 +- **前端 workaround 清理点**:若前端此前因为旧文案笼统、不知道是哪个分类而做过额外的提示语兜底(例如统一显示请检查全部 8 个分类),现在后端已经把具体分类名带出来,这类兜底提示可以清理、直接透传 message。 + +--- + +## 七、不影响范围 + +- **仅影响**:`584310`(`CATEGORY_CHECK_INCOMPLETE`)这一个错误码的 `message` 文本。 +- **零影响**: + - `POST /v3/admin/order/{orderId}/settlement/finalize` 的成功响应结构(`SettlementSubmitRespVO` 全部 24 个字段)——本单一个字段都没碰。 + - `584310` 的 `code` 值、触发条件、HTTP 状态——判定逻辑本身完全不变,只是把已经存在的参数真正传进消息模板。 + - 该错误码段(584300-584399)内其余错误码(如 `584311` 主报账表尚未生成、`584318` 空分类必须显式确认等)——本单未动。 + - 核单页的其余接口(应收总览、报账表、单团核算表、反确认等)——本单只改了 finalize 一个端点能返回的一个错误码文案。 + - 小程序端(`consumer: mp`)——本端点为管理后台端点,小程序无影响。 + +--- + +## 八、测试环境已验证 + +**部署确认**(2026-09-16,`deploy-status.sh` 经 SSH 在测试服执行): + +``` + SERVICE BRANCH COMMIT BEHIND DEPLOYED_AT BY STATE + hl-gateway dev-v3 6a7b43a17 29/Y 2026-09-15 12:16:26 root@local(python3) ok + hl-order-service-v3 dev-v3 d3d4755e9 0/N 2026-09-16 07:10:22 root@192.168.100.168 ok +``` + +order-v3 当前跑的就是 PR #7781 的 squash 合并提交 `d3d4755e9`(BEHIND=0/N,dev-v3 之后没有再碰本服务的提交);hl-gateway 也在 dev-v3(本单未新增路由,无需网关改动)。 + +**触发点一实测(8 分类循环,HOTEL 命中,`SettlementCategoryCheckService.validateReadyForReport`)**: + +自造测试订单 `order_id=8880000000778101001`(`order_no=HL7781FIXTURE01`,`customer_remark=#7781 584310 取证`),造数:`order_main`(`review_status=PENDING`、`paid_amount=0.00`/`deposit_amount=0.00` 满足对账一致性前置)、`order_settlement_hotel` 一条 `settlement_confirm_status=UNCONFIRMED` 的住宿明细行(字段齐全,满足 `readyLine` 数据质量判据)、`order_settlement_category_check` 八个分类各一条 `source_sync_status=READY`(满足 `readyForReport` 前置,仅 HOTEL 有明细行)。 + +请求: + +```http +POST https://api.test.1814.love:9443/v3/admin/order/8880000000778101001/settlement/finalize HTTP/1.1 +Authorization: Bearer {token} +``` + +请求时刻:2026-09-16 07:27:07 + +响应: + +```json +{ + "code": 584310, + "message": "核单分类「住宿」明细尚未全部确认或数据已变化", + "data": null, + "traceId": null, + "success": false +} +``` + +`code=584310`、`message` 占位符已正确替换为「住宿」(不含 `{0}` 字面量)、`data=null`,与源码预期一致。 + +**触发点二未实测(车辆草稿未确认,`SettlementVehicleFeeSnapshotWriter.replaceAndFreezeDraftInCurrentTransaction`,分类恒填「车辆」)**: + +该分支要求先有真实车辆需求(TRAVEL/TRANSFER)+ Fleet 已完结派车数据,`finalize` 在事务外先调用 `SettlementVehicleFeeService.prepareFreezeCandidateForReport`(经 `SettlementVehicleDraftService.loadCandidate/reconcile` 读 Fleet Feign 真实回填数据生成候选),事务内再由 `SettlementVehicleFreezeService.freezeForFinalizeInCurrentTransaction` 用 `draftService.lockReadySnapshot` 重新锁定一份快照,与候选比对不一致会先报 `REPORT_SOURCE_CHANGED`(而非 584310)。直接 SQL 向草稿表插入「未确认」行绕不过这道事实一致性校验(构造的草稿数据与 Fleet 真实候选对不上),需要完整走一遍团期车务派车(建需求→派车→回填每日车费→草稿 reconcile)才能自然产生「草稿行存在但未全部确认」的状态,超出本次取证窗口,未编造该路径证据。本单代码逻辑已按源码复核(见「三、接口详情」表格与 `SettlementVehicleFeeSnapshotWriter.java:250-256`),仅缺实测响应。 + +**本地/CI 编译与单测证据**(非测试环境实测,仅作为代码正确性的辅助信息): + +- `mvn -o -pl hl-order-service-v3 -am test-compile` 通过。 +- 定向单测合计 165/0/0/0:`SettlementCategoryCheckServiceTest` 16、`SettlementPrototypeFlowContractTest` 11、`SettlementServicePr5Test` 41、`SettlementVehicleFeeSnapshotWriterTest` 54、`LayerEnforcementTest` 5、`MapperBoundaryArchTest` 26、`RedLineArchTest` 12。 +- 两处触发点各补了一条断言渲染后 message 的用例(含 `doesNotContain` 对占位符原文的断言,防止占位符原样露给前端)。 + +--- + +## 十、相关文档 + +- 关联 PR: [wx/HL#7781](https://git.1814.love:8443/wx/HL/pulls/7781) +- 关联 Issue:无独立 Issue(PR 备注「无关联工单(顺带发现的两处问题)」) +- 合并提交:`d3d4755e9331243dad0129c2da04466cafc3bca5`(已在 dev-v3 主线) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: 无独立 Issue(见上) +- **PR**: [#7781](https://git.1814.love:8443/wx/HL/pulls/7781) +- **Merge commit**: [d3d4755e9](https://git.1814.love:8443/wx/HL/commit/d3d4755e9331243dad0129c2da04466cafc3bca5)(已在 dev-v3 主线) + +### 联系人 + +- **后端负责人**: @wx