---
schema: "hl-changelog/v2"
ticket: "5480"
title: "金额序列化规范化（#5480 候选金额 String；#5482 finance 零值 scale=2）"
consumer: "admin"
change_type: "修改接口"
author: "wx(GIT)"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "not_required"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "后端完成：PR #5487 已合并 dev-v3 并部署 TEST；网关实测 finance 零值 balancePaidAmount/fullPaidAmount/depositPaidAmount 已为 \"0.00\"（部署前 \"0\"）；candidates 当前 TEST 无候选车辆数据，协议价 String 化由序列化单测+代码证据覆盖（AssignmentCandidateRespVOAmountSerializationTest）。金额口径收敛到全站 String+scale=2 契约。"
updated_at: "2026-08-04"
base: "dev-v3"
---

# 金额序列化规范化（#5480/#5482）

> **服务**: hl-fleet-service + hl-order-service-v3
> **PR**: #5487
> **Issue**: #5480（P3）、#5482（P2）
> **联系人**: @wx
> **日期**: 2026-08-04
> **影响范围**: 管理后台车务候选列表金额字段、订单财务 Tab 零值金额字段

---

## ⚠️ 关键变化

金额 BigDecimal 序列化口径收敛：**金额字段一律 JSON String，且两位小数**（对齐平台「金额=String」铁律 #3978）。

1. **#5480（fleet）**：`POST /admin/fleet/assignments/candidates` 车辆候选的 `protocolPrice` / `autoVehicleFeeTotal` 此前输出 **JSON number 浮点**（`860.0` / `2580.0`），与同接口 `dailyVehicleFees[].calendarPrice/assignmentPrice`（String `"860.00"`）及全站金额 String 契约不一致。现补 `@JsonSerialize(ToStringSerializer)`，输出 String `"860.00"` / `"2580.00"`。
2. **#5482（order-v3）**：`GET /v3/admin/order/{id}/finance` 零值金额 `depositPaidAmount` / `balancePaidAmount` / `fullPaidAmount` 此前输出 `"0"`（scale=0），同响应 `totalAmount`/`paidAmount` 等为 `"0.00"`（scale=2）。现统一 scale=2，全部输出 `"0.00"`。

**数值不变**（仅序列化形态收敛）：前端金额按 String 处理（`>` `<` `-` `*` `/` 自动转数字）不受影响；仅 `a + b` 字符串拼接、`.toFixed()`、`=== "0.00"` 严格比较三类场景需按既有金额口径处理。

## 变更接口清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 派单候选查询 | POST | `/admin/fleet/assignments/candidates` | 序列化口径 | `protocolPrice`/`autoVehicleFeeTotal` number → String（"860.00"） |
| 2 | 订单财务 Tab | GET | `/v3/admin/order/{id}/finance` | 序列化口径 | 零值 `depositPaidAmount`/`balancePaidAmount`/`fullPaidAmount` "0" → "0.00" |

## 接口详情

### 1. 派单候选查询 `POST /admin/fleet/assignments/candidates`

**响应 `data.vehicleCandidates[]`（VehicleCandidateVO）**：

| 字段 | 类型 | 变化 | 说明 |
|------|------|------|------|
| `protocolPrice` | String | number → String | 用车开始日价格日历参考价（兼容字段）；例 `"860.00"` |
| `autoVehicleFeeTotal` | String | number → String | 价格日历自动总车费参考；例 `"2580.00"` |
| `dailyVehicleFees[].calendarPrice/assignmentPrice` | String | 无变化 | 保持 String 回归 |

```json
{
  "vehicleId": "2064998142394183681",
  "protocolPrice": "860.00",
  "autoVehicleFeeTotal": "2580.00",
  "dailyVehicleFees": [
    {"serviceDate": "2026-07-29", "calendarPrice": "860.00", "assignmentPrice": "860.00", "source": "CALENDAR"}
  ]
}
```

### 2. 订单财务 Tab `GET /v3/admin/order/{id}/finance`

**响应 `data`（FinanceVO）**：

| 字段 | 变化 | 说明 |
|------|------|------|
| `depositPaidAmount` | "0" → "0.00" | 无订金支付时零值统一两位小数 |
| `balancePaidAmount` | "0" → "0.00" | 无尾款支付时零值统一两位小数 |
| `fullPaidAmount` | "0" → "0.00" | 无全款支付时零值统一两位小数 |
| `totalAmount`/`paidAmount`/`balanceAmount`/`discountAmount`/`surchargeAmount`/`refundAmount` | 无变化 | 保持 "0.00" 形态 |

```json
{
  "totalAmount": "1000.00",
  "paidAmount": "100.00",
  "depositPaidAmount": "100.00",
  "balancePaidAmount": "0.00",
  "fullPaidAmount": "0.00",
  "balanceAmount": "900.00"
}
```

## 验证证据

- fleet：`AssignmentCandidateRespVOAmountSerializationTest`（2 例：正常值 String 化 + 零值类型保真），fleet verify 3080 例（1 例 Docker 基线环境失败与改动无关，stash 复现）。
- order-v3：`OrderDetailConverterTest` 新增零值 scale=2 + 序列化断言（41/41），order-v3 verify 7443 例全过。
- 网关 TEST 实测（#5482）：finance 零值 `balancePaidAmount="0.00"`/`fullPaidAmount="0.00"` 与 `totalAmount="1000.00"` 同形态（部署前 `"0"`）。
- 网关 TEST（#5480）：当前环境无候选车辆需求数据（全需求 vehicles=0），端到端候选金额验证暂不可行；由序列化单测（protocolPrice="860.00" String 断言）+ 同 VO dailyVehicleFees String 回归 + 代码注解证据覆盖。

## 关联/联系人

### 链接

- [后端工单 #5480](https://git.1814.love:8443/wx/HL/issues/5480)
- [后端 PR #5487](https://git.1814.love:8443/wx/HL/pulls/5487)
- Merge commit: `cbf08a4c02`

### 联系人

- **后端负责人**: @wx
