---
schema: "hl-changelog/v2"
ticket: "5610"
title: "核单完毕车辆费用写入fleet对账（实际结算取消手动录入）"
consumer: "admin"
author: "wx"
change_type: "新增接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "implemented"
frontend_owner: "mmg"
frontend_ref: "hl-admin@d4ac54f5c0b756fc49ce7efa907d81912a7cfd58"
target_release: ""
verified_at: "2026-08-06"
status_note: ""
updated_at: "2026-08-07"
base: "origin/dev-v3"
generated: "2026-08-06T19:42:24+08:00"
---

# 🚗 核单完毕车辆费用写入 fleet 对账（实际结算取消手动录入）

- **日期**: 2026-08-06
- **服务**: `hl-order-service-v3`（核单）→ `hl-fleet-service`（车队对账）
- **PR**: [#5622](https://git.1814.love:8443/wx/HL/pulls/5622) + 补丁 [#5624](https://git.1814.love:8443/wx/HL/pulls/5624)
- **Issue**: [#5610](https://git.1814.love:8443/wx/HL/issues/5610)
- **Merge commit**: [fd67c16a7](https://git.1814.love:8443/wx/HL/commit/fd67c16a74aedaac9f4869c089a03d30ab3d5466) + [973953481](https://git.1814.love:8443/wx/HL/commit/97395348127b766cfa9957664dff853546a38e28)
- **作者**: wx
- **设计**: hl-backend-changelog [06_5597 写模式数据流设计](./06_5597_hl-order-service-v3_hl-fleet-service_核单完毕车辆费用车队对账数据流设计.md)
- **影响范围**: 车队对账页（admin）「实际结算」列数据供给与录入方式变更；`PUT /admin/fleet/reconciliation/actual` 删除

## 变更接口

| 方法 | 路径 | 来源 |
|---|---|---|
| POST | /internal/fleet/reconciliation/vehicle-fee | 新增（fleet internal，Feign 直连） |
| PUT | /admin/fleet/reconciliation/actual | 删除（实际结算改读核单写入） |
| GET | /admin/fleet/reconciliation/cars | 修改（actualTotal 数据源变更 + 新增退款列） |

### 新增 internal 接口 `POST /internal/fleet/reconciliation/vehicle-fee` 的前置说明

### 1. 变更内容

写模式：核单完毕 → order 调 fleet 写入接口 → fleet 对账本地读。

| 接口 | 位置 | 改前 | 改后 |
|---|---|---|---|
| `POST /internal/fleet/reconciliation/vehicle-fee`（新增） | fleet internal，Feign 直连 | 不存在 | 核单完毕写入该订单车辆实际费用（逐车逐日） |
| `PUT /admin/fleet/reconciliation/actual`（删除） | fleet admin | 车管手工录入实际结算 | **已删除**（404），实际结算改读核单写入数据 |
| `GET /admin/fleet/reconciliation/cars` | fleet admin | `fleets[].actualTotal` = 手工录入值 | `fleets[].actualTotal` = SUM(vehicle_fee.actual_amount)，新增 `fleets[].refundTotal`、`vehicles[].actualAmount/refundAmount`、`grandTotal.refundTotal` |

### 新增 internal 接口 `POST /internal/fleet/reconciliation/vehicle-fee`

- 调用方：hl-order-service-v3（核单完毕 finalize 事务内登记 Fleet 命令 Outbox `SETTLEMENT_VEHICLE_FEE_WRITE`，提交后重放调用；不在核单事务内同步 Feign，可重放补偿）。
- 幂等：`orderId + assignmentId + serviceDate` 唯一键，重核覆盖写（金额/退款/核单时间全量覆盖）。
- 服务日所在对账期已关账（period CLOSED）拒绝（605600），与 prep 冻结口径一致；须超管 reopen 后重核。
- `items[]` 为空（无车订单）直接成功不落行。

**请求体 `SettlementVehicleFeeWriteDTO`（Feign 契约，hl-common）**：

| 字段 | 类型 | 说明 |
|---|---|---|
| `orderId` / `orderNo` | Long / String | 订单标识（必填） |
| `settledAt` | LocalDateTime | 核单完成时间（必填） |
| `items[]` | Array | 逐车逐日明细（必填，可空数组） |

item：

| 字段 | 类型 | 说明 |
|---|---|---|
| `assignmentId` | Long | 派单 ID（fleet_assignment.assignment_id，必填；order 侧取核单冻结行 sourceDetailId） |
| `vehicleId` / `vehiclePlate` / `vehicleModelName` / `seats` / `driverName` | — | 车辆/司机展示快照（order 核单冻结快照） |
| `serviceDate` | LocalDate | 服务日期（必填） |
| `actualAmount` | BigDecimal | 核单实际车费（必填，≥0，605611） |
| `refundAmount` / `refundedAt` | BigDecimal / LocalDateTime | 终止退款金额/完成时间（可空；仅订单首行携带防对账重复计数） |

**响应**：`Result<Void>`（200 成功；605600 已关账 / 605610 参数非法 / 605611 金额为负）。

### 删除 `PUT /admin/fleet/reconciliation/actual`

- 车队对账「实际结算」不再手工录入：`fleet_reconciliation_actual` 表停止写入（历史数据保留，遗留待定另行处理）。
- 关账前置 605603「对账期实际金额未录入」改为校验对账车辆费用表该期至少一行。

## 2. Feign 接口变更

| 调用方向 | Controller | 方法与路径 | 请求类型 | 响应类型 | 变更类型 |
|---|---|---|---|---|---|
| order-v3 → fleet | `ReconciliationVehicleFeeInternalController` | `POST /internal/fleet/reconciliation/vehicle-fee` | `SettlementVehicleFeeWriteDTO` | `Result<Void>` | 新增 |
| 前端 → fleet | `ReconciliationController` | `PUT /admin/fleet/reconciliation/actual` | `ReconActualSaveReqVO` | `ReconActualSaveRespVO` | **删除** |

internal 接口为内网 Feign LB 直连，不经 Gateway；调用方由公共 Feign 拦截器注入 `X-Internal-Token`。order-v3 侧 Feign 方法 `FleetAssignmentExpandFeignClient#writeSettlementVehicleFee`（contextId `fleetAssignmentExpand`）。

## 3. 统一响应包络与错误

正常和参数错误响应使用 `Result<T>`（code/message/data/traceId/success）。新增/复用错误码：

| code | 说明 |
|---|---|
| 605600 | 服务日所在对账期已关账，重核须先重开账 |
| 605610 | 核单车辆费用写入参数非法（幂等键缺失） |
| 605611 | 核单实际车费不能为负 |

## 4. 前端/调用方动作（车队对账页）

- ❌ **删除**「实际结算」手动录入入口（PUT /actual 已 404）；实际结算列改展示核单写入值（只读）。
- 保留展示：`actualTotal`（车队级）、`diff`（= actualTotal − payableTotal）；新增可空展示：`fleets[].refundTotal`、`vehicles[].actualAmount`、`vehicles[].refundAmount`、`grandTotal.refundTotal`。
- 金额为字符串（BigDecimal @JsonSerialize ToStringSerializer），前端按既有金额处理。

## 验证证据

- 定向测试：`ReconciliationVehicleFeeServiceTest` 9 例（幂等/重核覆盖/已关账拒绝/负数/参数非法/teamNo 取车辆车队归属）、`ReconciliationQueryServiceTest` 11 例（actual 读对账车辆费用表）、`ReconciliationPeriodServiceTest` 17 例（close 前置改造）、`SettlementVehicleFeeReconciliationPublisherTest` 4 例、`SettlementFinalizeTxServiceTest` 5 例（核单完毕登记 outbox）、`OrderFleetCommandOutboxProcessorTest` 26 例（SETTLEMENT_VEHICLE_FEE_WRITE 分发）、`MapperBoundaryArchTest` 25 例（settlement 域经 RequirementService 契约）。
- fleet verify：3196 tests 0 失败 + spotless:check 通过（含 Release E 门禁参数）。
- 网关验证（TEST）：internal 写入 200 ×3（首写/幂等/重核覆盖），DB 复查 `fleet_reconciliation_vehicle_fee` 3 行金额随覆盖更新；`PUT /actual` 404；对账页 `GET /admin/fleet/reconciliation/cars` 200 显示核单写入实际结算。
- order 全量 verify 失败集合（8F+95E）与干净 dev-v3 基线完全一致（#5599 H2 schema 未同步 / #5603 架构违规 / MySQL 集成环境），非本变更引入。
- 兼容性结论：`fleet_reconciliation_actual` 历史数据保留未迁移（遗留待定）；`GET /admin/fleet/reconciliation/cars` 响应新增字段向后兼容；删除 PUT /actual 为破坏性变更，前端须同步移除录入入口。
