# 【修改接口·管理后台】费用明细已收款拆分 (#5022)

> **PR**: #5025 | **服务**: hl-order-service-v3 | **更新时间**: 2026-07-18 00:00

## 1. 接口背景

管理后台订单费用明细需要区分展示已收订金、已收尾款、已收全款。原接口只返回 `paidAmount` 已收总额，无法直接区分不同收款类型。本次在订单费用接口响应 `data` 内新增 3 个拆分金额字段，`paidAmount` 仍表示已收总额。

## 2. 变更清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 订单费用信息 | GET | `/v3/admin/order/{id}/finance` | 修改接口 | 响应 `data` 新增 `depositPaidAmount`、`balancePaidAmount`、`fullPaidAmount` |

## 3. 接口详情

### 3.1 订单费用信息

- **使用场景**: 查询单个订单的费用汇总、优惠、加价、退款、线上支付交易明细。
- **认证**: 需要管理后台登录态 JWT。
- **幂等性**: 查询接口，幂等。
- **限流**: 无新增限流规则。

## 4. 接口入参

### 4.1 路径参数 / Query 参数

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `id` | String | 是 | 订单 ID，路径参数。示例：`2077233785174179841` |

### 4.2 请求体字段

GET 请求，无请求体。

## 5. 出参字段

### 5.1 顶层响应字段

| 字段 | 类型 | 说明 |
|------|------|------|
| `code` | Integer | 业务状态码，`200` 表示成功 |
| `message` | String | 响应消息 |
| `data` | Object | 订单费用信息 |
| `traceId` | String / null | 链路追踪 ID，可能为 `null` |
| `success` | Boolean | 请求是否成功 |

### 5.2 data 字段

| 字段 | 类型 | 说明 |
|------|------|------|
| `totalAmount` | String | 订单总金额，金额字符串，单位元 |
| `payableAmount` | String | 应付金额，金额字符串，单位元 |
| `paidAmount` | String | 已收总额，包含成功线上收款和未撤销线下收款 |
| `depositPaidAmount` | String | 新增。实际已收订金金额，成功线上订金 + 未撤销线下订金 |
| `balancePaidAmount` | String | 新增。实际已收尾款金额，成功线上尾款 + 未撤销线下尾款 |
| `fullPaidAmount` | String | 新增。实际已收全款金额，成功线上全款 + 未撤销线下全款 |
| `balanceAmount` | String | 待收余额，金额字符串，单位元 |
| `discountAmount` | String | 优惠总额，金额字符串，单位元 |
| `surchargeAmount` | String | 加价总额，金额字符串，单位元 |
| `refundAmount` | String | 已退金额，金额字符串，单位元 |
| `payments` | Array | 线上支付交易明细；仍只表示线上交易，不包含线下收款明细 |
| `discounts` | Array | 优惠明细 |
| `surcharges` | Array | 加价明细 |

### 5.3 payments 字段项

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String | 支付交易 ID |
| `paymentNo` | String | 支付流水号 |
| `amount` | String | 支付金额，单位元 |
| `paymentType` | String | 支付类型 |
| `status` | String | 支付状态 |
| `paidAt` | String / null | 支付成功时间，格式 `yyyy-MM-dd HH:mm:ss` |

> 本次未改变 `payments` 语义：它仍只表示线上支付交易明细。线下收款明细仍通过 `GET /v3/admin/order/{orderId}/payment/manual-receipt` 获取；线下金额已聚合进 `depositPaidAmount`、`balancePaidAmount`、`fullPaidAmount` 和 `paidAmount`。

### 5.4 discounts 字段项

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String | 优惠明细 ID |
| `name` | String | 优惠名称 |
| `amount` | String | 优惠金额，单位元 |
| `type` | String | 优惠类型 |
| `source` | String | 优惠来源 |
| `createdAt` | String | 创建时间，格式 `yyyy-MM-dd HH:mm:ss` |

### 5.5 surcharges 字段项

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String | 加价明细 ID |
| `name` | String | 加价名称 |
| `amount` | String | 加价金额，单位元 |
| `type` | String | 加价类型 |
| `createdAt` | String | 创建时间，格式 `yyyy-MM-dd HH:mm:ss` |

## 6. 枚举 / 数据字典

### 6.1 paymentType

**所属字段**: `payments[].paymentType` | **类型**: String

| 值 | 中文 | 说明 |
|----|------|------|
| `DEPOSIT` | 订金 | 订金支付 |
| `BALANCE` | 尾款 | 尾款支付 |
| `FULL` | 全款 | 全款支付 |

### 6.2 status

**所属字段**: `payments[].status` | **类型**: String

| 值 | 中文 | 说明 |
|----|------|------|
| `SUCCESS` | 支付成功 | 计入对应已收金额 |
| `PENDING` | 待支付 | 不计入对应已收金额 |
| `CLOSED` | 已关闭 | 不计入对应已收金额 |
| `FAILED` | 支付失败 | 不计入对应已收金额 |

### 6.3 type

**所属字段**: `discounts[].type`、`surcharges[].type` | **类型**: String

| 值 | 中文 | 说明 |
|----|------|------|
| `EARLY_BIRD` | 早鸟优惠 | 早鸟规则产生的优惠 |
| `MANUAL` | 手工调整 | 人工录入的优惠或加价 |
| `OTHER` | 其他 | 其他类型 |

### 6.4 source

**所属字段**: `discounts[].source` | **类型**: String

| 值 | 中文 | 说明 |
|----|------|------|
| `EARLY_BIRD_PLAN` | 早鸟方案 | 来源于早鸟优惠方案 |
| `MANUAL` | 手工录入 | 来源于人工录入 |

## 7. 错误码

| code | 含义 | 触发场景 |
|------|------|----------|
| `200` | 成功 | 订单费用信息查询成功 |
| `401` | 未登录或登录失效 | 未携带有效管理后台 JWT |
| `403` | 无权限 | 当前账号无权访问该订单费用信息 |
| `404` | 订单不存在 | 路径参数 `id` 对应订单不存在 |
| `500` | 系统异常 | 服务端处理异常 |

## 8. 示例

### 8.1 典型成功

**请求**:

```http
GET /v3/admin/order/2077233785174179841/finance HTTP/1.1
Authorization: Bearer <token>
```

无请求体。

**响应**:

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "totalAmount": "3105.00",
    "payableAmount": "2955.00",
    "paidAmount": "2500.00",
    "depositPaidAmount": "2000.00",
    "balancePaidAmount": "500.00",
    "fullPaidAmount": "0",
    "balanceAmount": "455.00",
    "discountAmount": "150.00",
    "surchargeAmount": "0.00",
    "refundAmount": "0.00",
    "payments": [],
    "discounts": [
      {
        "id": "2077233785199345666",
        "name": "早鸟优惠:早鸟-小团减150(适用人群:成人/儿童/小童)",
        "amount": "150.00",
        "type": "EARLY_BIRD",
        "source": "EARLY_BIRD_PLAN",
        "createdAt": "2026-07-15 11:28:22"
      }
    ],
    "surcharges": []
  },
  "traceId": null,
  "success": true
}
```

### 8.2 边界情况

**场景说明**: 订单暂无任何成功线上收款和未撤销线下收款时，所有已收拆分金额均返回 0 金额；明细数组可为空数组。

**请求**:

```http
GET /v3/admin/order/2077233785174179841/finance HTTP/1.1
Authorization: Bearer <token>
```

无请求体。

**响应**:

```json
{
  "code": 200,
  "message": "成功",
  "data": {
    "totalAmount": "3105.00",
    "payableAmount": "2955.00",
    "paidAmount": "0",
    "depositPaidAmount": "0",
    "balancePaidAmount": "0",
    "fullPaidAmount": "0",
    "balanceAmount": "2955.00",
    "discountAmount": "150.00",
    "surchargeAmount": "0.00",
    "refundAmount": "0.00",
    "payments": [],
    "discounts": [],
    "surcharges": []
  },
  "traceId": null,
  "success": true
}
```

### 8.3 业务失败

**场景说明**: 订单 ID 不存在。

**请求**:

```http
GET /v3/admin/order/9999999999999999999/finance HTTP/1.1
Authorization: Bearer <token>
```

无请求体。

**响应**:

```json
{
  "code": 404,
  "message": "订单不存在",
  "data": null,
  "traceId": null,
  "success": false
}
```

## 9. 业务边界

- **适用场景**: 管理后台查询订单费用明细时调用，订单存在且当前账号有访问权限。
- **不适用场景**: 用该接口获取线下收款明细列表；线下收款明细仍由 `GET /v3/admin/order/{orderId}/payment/manual-receipt` 返回。
- **特殊边界**: `payments` 为空不代表订单没有已收金额；可能存在未撤销线下收款，已聚合到本次新增的拆分金额和 `paidAmount`。
- **金额口径**: `paidAmount` 为已收总额；`depositPaidAmount`、`balancePaidAmount`、`fullPaidAmount` 为按收款类型拆分后的已收金额。

## 10. 修改前后对比

### 10.1 字段级对比

| 字段 | 改前 | 改后 |
|------|------|------|
| `data.depositPaidAmount` | 不返回 | 返回实际已收订金金额 |
| `data.balancePaidAmount` | 不返回 | 返回实际已收尾款金额 |
| `data.fullPaidAmount` | 不返回 | 返回实际已收全款金额 |
| `data.paidAmount` | 返回已收总额 | 继续返回已收总额，语义不变 |
| `data.payments` | 返回线上支付交易明细 | 继续只返回线上支付交易明细，语义不变 |

### 10.2 行为级对比

| 行为 | 改前 | 改后 |
|------|------|------|
| 已收金额拆分 | 只能读取 `paidAmount` 总额 | 可读取订金、尾款、全款 3 类已收金额 |
| 线下收款聚合 | `paidAmount` 中包含线下收款，无法按类型拆分 | 线下收款按类型聚合进新增拆分字段和 `paidAmount` |
| 线上支付明细 | `payments` 表示线上支付交易明细 | 保持不变，仍不包含线下收款明细 |

## 11. 影响评估 / 回滚

### 11.1 影响评估

- **是否破坏向后兼容**: 否。本次只新增响应字段，未删除或改名已有字段。
- **前端是否必须同步上线**: 否。旧前端继续读取 `paidAmount` 不受影响；需要区分已收订金、已收尾款、已收全款时读取新增字段。
- **影响已有数据**: 否。历史订单按成功线上收款和未撤销线下收款聚合返回。

### 11.2 回滚方案

- **回滚方式**: 回滚 PR #5025 后，接口不再返回 3 个新增字段。
- **回滚后兼容**: 只依赖 `paidAmount` 的旧逻辑不受影响；依赖新增字段的消费方需要兼容字段缺失。
- **回滚后清理**: 无需清理前端侧数据。

## 12. 注意事项

- `depositPaidAmount`、`balancePaidAmount`、`fullPaidAmount` 是金额字符串，单位元。
- 金额为 0 时可能返回 `"0"` 或 `"0.00"`，消费方不要依赖固定小数位判断金额语义。
- `payments` 为空时仍可能存在已收金额，因为线下收款不进入 `payments`。
- 线下收款明细列表仍由 `GET /v3/admin/order/{orderId}/payment/manual-receipt` 获取。

## 13. 关联 / 联系人

### 13.1 链接

- **Issue**: [#5022](https://git.1814.love:8443/wx/HL/issues/5022)
- **PR**: [#5025](https://git.1814.love:8443/wx/HL/pulls/5025)
- **Merge commit**: [aeb2d6d24](https://git.1814.love:8443/wx/HL/commit/aeb2d6d248fcc0fe49a540bfb3b864f06bc00123)

### 13.2 联系人

- **后端负责人**: 腰苏图
