---
schema: "hl-changelog/v2"
ticket: "5809"
title: "完成核单去转账/签字凭据采集：finalize 改无请求体，主报账对账与报账表删除凭据字段"
consumer: "admin"
change_type: "修改接口"
author: "yaosutu(GIT)"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "implemented"
frontend_owner: "mmg"
frontend_ref: "3993f15a"
target_release: ""
verified_at: "2026-08-11"
status_note: "前端已实现(3993f15a):finalize 改无请求体(仅 Path 传 orderId)——orderV2.finalizeSettlement 改单参 body=undefined,settlementService.completeSettlement 删 remark trim/校验与 reimbursementConfirmationPayload 组装改 completeSettlement(id);ReportModal 删转账日期/预支是否已结清/流水号/签字单凭证/备注整块凭据表单与相关 script,formulaText 改注记凭据摘除;detail.vue 删 ReportModal 凭据绑定、reimbursementConfirmation ref、askComplete 改单参、删路由 watch 重置块。测试同步:orderV2.spec finalize 用例改断言 body=undefined;settlementService.spec 重写 finalize payload 断言为 toHaveBeenCalledWith(ORDER_ID)、删「净额非零必须提交日期流水」用例、各 finalize 用例去 confirmation 第二参;ReportModal.spec 删两个凭据编辑用例与 FileUpload mock/helper。前端先上、后端随后(前后端需同批,后端上线前老前端传凭据字段会 400,已按排期先前端)。核单域四 spec 34+16 全过,checkpoint 7 文件全绿(ESLint/Vitest 全量/生产构建)。"
updated_at: "2026-08-11"
base: "dev-v3"
---

# 【⚠️ 修改接口·管理后台】完成核单去转账/签字凭据采集：finalize 改无请求体，recon 入参删 4 字段，报账表出参删 4 字段（#5809）

> **PR**: [#5813](https://git.1814.love:8443/wx/HL/pulls/5813) | **服务**: hl-order-service-v3 | **更新时间**: 2026-08-10

## 1. 接口背景

核单流程此前在「完成核单」和「主报账对账保存」两个环节采集转账/签字凭据：转账日期、转账流水号、预支是否已处理、签字凭证文件（图片 + 备注）。产品上决定凭据采集不再挂在核单链路（核单只负责核算确认，凭据留档走线下或其他系统），因此本次把凭据相关字段从 3 个接口整体摘除：

- **完成核单 finalize**：整个请求体删除，改为仅 Path 传 orderId 的无 body 接口；
- **主报账对账保存 recon**：入参只保留 transferStatus，删 4 个凭据字段及其必填校验；
- **主报账人报账表 GET**：出参删同样 4 个凭据字段，报账弹窗改纯展示。

> ⚠️ 本次为**入参删字段 + 出参删字段的硬破坏契约**：相关 ReqVO 配置了 ignoreUnknown=false，前端若继续传已删字段会直接 400，**前后端必须同批上线**（详见 §11、§12）。

## 2. 变更清单

| # | 接口 | 方法 | 路径 | 变更类型 | 前端动作 |
|---|---|---|---|---|---|
| 1 | 完成核单 | POST | /v3/admin/order/{orderId}/settlement/finalize | 删除整个请求体（原 SettlementSubmitReqVO：remark + reimbursementConfirmation 凭据对象） | 请求不再带 body；清理凭据表单/校验逻辑 |
| 2 | 主报账对账保存 | PUT | /v3/admin/order/{orderId}/settlement/recon | 入参删 transferDate / transferRef / advanceSettledFlag / signedVoucher，仅保留 transferStatus | 请求体只传 transferStatus；清理凭据表单 |
| 3 | 主报账人报账表 | GET | /v3/admin/order/{orderId}/settlement/reports/reimbursement | 出参删 transferDate / transferRef / advanceSettledFlag / signedVoucher | 停读 4 字段；报账弹窗删凭据展示区 |

## 3. 接口详情

- **使用场景**：
  - finalize：管理后台核单页面对账完成后点击「完成核单」，把订单核算推进到终态（落 FINALIZED 快照）。
  - recon：主报账对账弹窗保存转账状态（待转账 / 已转账）。
  - reports/reimbursement：主报账人报账表弹窗，展示主报账人收付对账与转账结论。
- **认证**：需要管理后台登录态（Bearer Token）；房务角色（HOUSE）被 OrderViewGuard 拦截。
- **幂等性**：
  - finalize：改为纯终态校验，已有 FINALIZED 快照且终态一致时直接返回原结果，**天然幂等**，重复点击无副作用。
  - recon：同一 transferStatus 重复保存为覆盖写，幂等。
  - reports/reimbursement：只读查询，天然幂等。
- **限流**：未声明接口专属限流。

## 4. 接口入参

### 4.1 路径参数

三个接口一致：

| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| orderId | Long | 是 | 订单 ID，路径参数，必须大于 0 |

### 4.2 请求体字段

#### POST /v3/admin/order/{orderId}/settlement/finalize（完成核单）

**无请求体**。原 SettlementSubmitReqVO 整体删除，被删字段如下（前端不得再传）：

| 原字段 | 类型 | 原说明 | 现状 |
|---|---|---|---|
| remark | String | 核单整体备注 | 已删除；服务端不再写 settlement_summary.remark |
| reimbursementConfirmation | Object | 凭据对象 | 已删除 |
| reimbursementConfirmation.transferDate | String(yyyy-MM-dd) | 转账日期 | 已删除 |
| reimbursementConfirmation.transferRef | String | 转账流水号 | 已删除 |
| reimbursementConfirmation.advanceSettledFlag | Boolean | 预支是否已处理 | 已删除 |
| reimbursementConfirmation.signedVoucher | Object | 签字凭证，含 files[{name,url}] + note | 已删除 |

> 原「reporterNetAmount 非 0 时强制 transferDate / transferRef 必填」的服务端校验同步移除；原 finalize 凭据校验失败错误码 584317 在此接口不再触发。

#### PUT /v3/admin/order/{orderId}/settlement/recon（主报账对账保存）

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| transferStatus | String | 是 | 转账状态，枚举：PENDING（待转账）/ COMPLETED（已转账） |

被删字段（前端不得再传，传了会 400）：

| 原字段 | 类型 | 原说明 | 现状 |
|---|---|---|---|
| transferDate | String(yyyy-MM-dd) | 转账日期 | 已删除 |
| transferRef | String | 转账流水号 | 已删除 |
| advanceSettledFlag | Boolean | 预支是否已处理 | 已删除 |
| signedVoucher | Object | 签字凭证，含 files[{name,url}] + note | 已删除 |

> 原「transferStatus=COMPLETED 时 transferRef 必填」校验同步移除。

#### GET /v3/admin/order/{orderId}/settlement/reports/reimbursement（主报账人报账表）

无请求体、无 Query 参数，入参零变化。

## 5. 出参字段

### 5.1 POST finalize / PUT recon

统一响应 Result 包装，data 为操作结果（成功 code=200）。出参结构无变化。

### 5.2 GET /v3/admin/order/{orderId}/settlement/reports/reimbursement（主报账人报账表）

统一响应 Result 包装，data 字段如下（仅列关键字段 + 本次删除项）：

| 字段 | 类型 | 说明 |
|---|---|---|
| id | String(Long) | 报表记录 ID；未落库时可为 null |
| orderId | String(Long) | 订单 ID |
| reportStatus | String | 报表状态：GENERATED / CONFIRMED |
| primaryReporterId | String(Long) | 主报账人人员安排 ID |
| primaryReporterName | String | 主报账人姓名 |
| primaryReporterRole | String | 主报账人角色（如 DRIVER） |
| reportVersion | Integer | 报表版本号 |
| driverCollectedTailAmount | String(BigDecimal) | 司机代收尾款 |
| approvedAdvanceAmount | String(BigDecimal) | 已审批预支金额 |
| reportablePaidCostAmount | String(BigDecimal) | 可报账已付成本 |
| reporterNetAmount | String(BigDecimal) | 报账人净额 |
| primaryReporterCollectedAmount | String(BigDecimal) | 主报账人已收款 |
| publicPrepaidAmount | String(BigDecimal) | 对公预付金额 |
| primaryReporterDueAmount | String(BigDecimal) | 主报账人应结金额 |
| advanceOutstandingAmount | String(BigDecimal) | 预支未销余额 |
| reconNetAmount | String(BigDecimal) | 对账净额 |
| transferDirection | String | 转账方向 |
| transferAmount | String(BigDecimal) | 转账金额 |
| incomeLines | Array | 收款行；每项含 type / typeName / receiptId / amount / channel / channelName / payType / payTypeName / collectorStaffId / collectorName / collectorRole / collectorRoleName / receivedAt / remark |
| expenseLines | Array | 支出行；每项含 kind / category / categoryName / amount / paymentMethod / paymentMethodName / voucherUrls / remark + 类别扩展字段 |
| advanceLines | Array | 预支行 |
| vehicleLines | Array | 已确认车辆逐日费用明细；无数据固定返回空数组 |
| transferStatus | String | 转账状态（PENDING / COMPLETED），保留 |
| ~~transferDate~~ | - | **已删除**，前端不再收到此字段 |
| ~~transferRef~~ | - | **已删除** |
| ~~advanceSettledFlag~~ | - | **已删除** |
| ~~signedVoucher~~ | - | **已删除** |
| generatedBy / generatedByName / generatedAt | - | 生成人 ID / 姓名 / 时间 |
| confirmedBy / confirmedByName / confirmedAt | - | 确认人 ID / 姓名 / 时间 |

> 除删除 4 个凭据字段外，其余字段名称、类型、语义均无变化。前端不要再读取这 4 个字段，读取结果恒为 undefined。

## 6. 枚举 / 数据字典

### transferStatus（recon 入参 + 报账表出参共用）

| 值 | 含义 | 本次变化 |
|---|---|---|
| PENDING | 待转账 | 不变 |
| COMPLETED | 已转账 | 不变（原「COMPLETED 时 transferRef 必填」联动校验移除） |

其余枚举/字典（reportStatus、incomeLines[].type、channel、payType、paymentMethod、transferDirection 等）取值与语义均无变化。

## 7. 错误码

| 错误码 | 含义 | 本次变化 |
|---|---|---|
| 400（参数校验） | 请求体含未知字段 | **新增触发路径**：ReqVO ignoreUnknown=false，前端继续传已删凭据字段（recon / finalize）会直接返回 400 |
| 584317 | 原 finalize 凭据校验失败（transferDate/transferRef 缺失等） | **此接口不再触发**（凭据校验整体移除） |

其余既有错误码（订单不存在、双报告未生成保护 584311 / 584313、房务角色 403 等）行为不变。

## 8. 示例

### 8.1 典型成功（完成核单，无请求体）

```http
POST /v3/admin/order/2084000000000002978/settlement/finalize
Authorization: Bearer <token>
Content-Length: 0
```

```json
{
  "code": 200,
  "message": "success",
  "data": null,
  "success": true
}
```

> 注意：请求不带任何 body。幂等——已有 FINALIZED 快照且终态一致时重复调用直接返回原结果。

主报账对账保存（只传 transferStatus）：

```http
PUT /v3/admin/order/2084000000000002978/settlement/recon
Authorization: Bearer <token>
Content-Type: application/json

{"transferStatus": "COMPLETED"}
```

```json
{"code": 200, "message": "success", "data": null, "success": true}
```

### 8.2 边界（报账表出参已无凭据字段）

```http
GET /v3/admin/order/2084000000000002978/settlement/reports/reimbursement
Authorization: Bearer <token>
```

```json
{
  "code": 200,
  "message": "success",
  "data": {
    "id": "8802",
    "orderId": "2084000000000002978",
    "reportStatus": "GENERATED",
    "primaryReporterId": "7001",
    "primaryReporterName": "司机甲",
    "primaryReporterRole": "DRIVER",
    "reportVersion": 1,
    "driverCollectedTailAmount": "0.00",
    "approvedAdvanceAmount": "0.00",
    "reportablePaidCostAmount": "0.00",
    "reporterNetAmount": "0.00",
    "primaryReporterCollectedAmount": "0.00",
    "publicPrepaidAmount": "0.00",
    "primaryReporterDueAmount": "0.00",
    "advanceOutstandingAmount": "0.00",
    "reconNetAmount": "0.00",
    "transferDirection": null,
    "transferAmount": "0.00",
    "incomeLines": [],
    "expenseLines": [],
    "advanceLines": [],
    "vehicleLines": [],
    "transferStatus": "PENDING",
    "generatedBy": "1001",
    "generatedByName": "张三",
    "generatedAt": "2026-08-10 10:20:30",
    "confirmedBy": null,
    "confirmedByName": null,
    "confirmedAt": null
  },
  "success": true
}
```

> 响应中已无 transferDate / transferRef / advanceSettledFlag / signedVoucher 四个字段（不是返回 null，是字段不存在）。

### 8.3 业务失败（前端仍传已删字段 → 400）

```http
PUT /v3/admin/order/2084000000000002978/settlement/recon
Authorization: Bearer <token>
Content-Type: application/json

{"transferStatus": "COMPLETED", "transferRef": "202608100001"}
```

```json
{"code": 400, "message": "请求参数格式错误（含未识别字段 transferRef）", "data": null, "success": false}
```

> ReqVO ignoreUnknown=false，任何已删字段（transferDate / transferRef / advanceSettledFlag / signedVoucher / remark / reimbursementConfirmation）传入都会 400。这是本次最需要前端规避的失败路径。

## 9. 业务边界

- ✅ 完成核单只需订单处于可核单终态 + 双报告已生成（584311 / 584313 保护不变），不再要求任何凭据。
- ✅ recon 只需选择转账状态（PENDING / COMPLETED），COMPLETED 也不再要求转账流水号。
- ✅ 报账表弹窗改为纯展示核算数据 + 转账状态，无凭据上传/回填交互。
- ❌ 不要在前端保留凭据采集表单（转账日期/流水号/预支处理标记/签字凭证上传），继续提交会 400。
- ❌ 不要把本地缓存/草稿里的凭据数据回传到 finalize 或 recon。
- ❌ 订单历史凭据数据仍在库中（零 DDL，列未删），但接口不再返回；不要依赖报账表接口读取历史凭据。

## 10. 修改前后对比

### 10.1 字段级对比

| 接口 | 字段 | 原来 | 现在 |
|---|---|---|---|
| POST finalize | 请求体整体 | SettlementSubmitReqVO（remark + reimbursementConfirmation{transferDate, transferRef, advanceSettledFlag, signedVoucher{files[{name,url}], note}}） | **无请求体**，仅 Path 传 orderId |
| PUT recon | transferDate / transferRef / advanceSettledFlag / signedVoucher | 入参（transferStatus=COMPLETED 时 transferRef 必填） | **已删除**，入参仅保留 transferStatus |
| GET reports/reimbursement | transferDate / transferRef / advanceSettledFlag / signedVoucher | 出参 | **已删除**，其余出参不变 |

### 10.2 行为级对比

| 场景 | 原来 | 现在 |
|---|---|---|
| 完成核单时 reporterNetAmount 非 0 | 强制要求 transferDate / transferRef，缺失报 584317 | 无任何凭据校验，直接走终态确认 |
| 完成核单提交备注 remark | 写入 settlement_summary.remark | 不再接收、不再写入 |
| recon 保存 transferStatus=COMPLETED | transferRef 必填 | 仅保存 transferStatus |
| 报账表弹窗 | 展示并可回填凭据区 | 纯展示，无凭据字段 |
| finalize 终态快照比对 | 含凭据字段比对 | 不再比对凭据 |
| finalize 重复调用 | 凭据差异可能导致非幂等 | 纯终态校验，终态一致直接返回原结果，天然幂等 |

## 11. 影响评估 / 回滚

### 11.1 影响评估

- **是否破坏向后兼容**：**是，硬破坏**。finalize 请求体删除 + recon 入参删 4 字段 + 报账表出参删 4 字段；且 ReqVO ignoreUnknown=false，旧前端继续传凭据字段会直接 400（不是静默忽略）。
- **前端是否必须同步上线**：**必须同批**。前端需先删掉凭据表单与字段读取，再与后端同批发布。
- **上线顺序边界**：前后端同批发布；若必须分先后，**先上前端（停传/停读凭据字段），再上后端**。旧前端 + 新后端 = finalize / recon 直接 400，功能不可用。
- **数据库侧**：**零 DDL**，数据库列未动，历史凭据数据保留在库中（接口不再读写），无数据迁移成本。

### 11.2 回滚方案

- 代码回滚即恢复原请求体/入参/出参与凭据校验；数据库无变更，历史数据完整，回滚无数据修复成本。
- **回滚必须前后端同批回滚**：新前端（不传凭据）+ 旧后端（reporterNetAmount 非 0 强制凭据）会导致 finalize 报 584317 失败。

## 12. 注意事项

- **契约破坏红线**：相关 ReqVO 配置了 ignoreUnknown=false，前端**继续传任何已删字段都会 400**（不是忽略）。包括：finalize 的 remark / reimbursementConfirmation 整个对象，recon 的 transferDate / transferRef / advanceSettledFlag / signedVoucher。前后端必须同批上线。
- 本次只动凭据采集相关字段；订单金额核算逻辑、reportStatus 枚举、双报告生成/确认保护（584311 / 584313）均未变化。
- finalize 的 Swagger 描述中若残留凭据相关文案属文档残留，以本 changelog 为准。
- 小程序端（/v3/mp/*）不涉及本次变更，无需任何改动。

## 13. 关联 / 联系人

### 13.1 链接

- **Issue**: [#5809](https://git.1814.love:8443/wx/HL/issues/5809)
- **PR**: [#5813](https://git.1814.love:8443/wx/HL/pulls/5813)
- **Commit**: [0e2ee34d6d](https://git.1814.love:8443/wx/HL/commit/0e2ee34d6d)
- **相关批次**: Issue [#5739](https://git.1814.love:8443/wx/HL/issues/5739) / PR [#5764](https://git.1814.love:8443/wx/HL/pulls/5764)（核单指纹下线，changelog 见 2026-08/09_5739）

### 13.2 联系人

- **后端负责人**: @yaosutu (yst) 腰苏图
