这个提交包含在:
父节点
4ad3a92f66
当前提交
601e272457
@ -0,0 +1,894 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "5342"
|
||||
title: "核单报表取消中间确认并由 finalize 固化"
|
||||
consumer: "admin"
|
||||
change_type: "修改接口"
|
||||
backend_status: "deployed"
|
||||
gateway_status: "verified"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: ""
|
||||
status_note: "后端 PR #5345 已合并并部署;网关已验证旧确认路由 404、finalize 新校验与实时查询链路"
|
||||
updated_at: "2026-07-29"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# 【修改接口·管理后台】核单报表取消中间确认并由 finalize 固化 (#5342)
|
||||
|
||||
> **PR**: #5345 | **服务**: hl-order-service-v3 | **更新时间**: 2026-07-29 13:28
|
||||
|
||||
## 1. 接口背景
|
||||
|
||||
核单流程不再要求用户分别确认“主报账人报账表”和“单团核算表”。核单未完成时,两张报表查询接口按当前业务数据实时返回;点击完成核单时,前端一次性提交转账、垫资结清和签字凭证信息,服务端按提交时的当前数据重新计算并固化终态。核单完成后,两张报表查询接口只返回该次完成核单时固化的内容,后续来源数据变化不会改写该终态结果。
|
||||
|
||||
## 变更接口(2. 变更清单)
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---|------|------|------|----------|------|
|
||||
| 1 | 查询主报账人报账表 | GET | `/v3/admin/order/:orderId/settlement/reports/reimbursement` | 行为修改 | 未完成核单时实时计算;完成核单后读取终态结果 |
|
||||
| 2 | 查询单团核算表 | GET | `/v3/admin/order/:orderId/settlement/reports/group` | 行为修改 | 未完成核单时实时计算;完成核单后读取终态结果 |
|
||||
| 3 | 确认主报账人报账表 | POST | `/v3/admin/order/:orderId/settlement/reports/reimbursement/confirm` | 删除 | 接口下线,调用返回业务码 `404` |
|
||||
| 4 | 确认单团核算表 | POST | `/v3/admin/order/:orderId/settlement/reports/group/confirm` | 删除 | 接口下线,调用返回业务码 `404` |
|
||||
| 5 | 完成核单 | POST | `/v3/admin/order/:orderId/settlement/finalize` | 请求与行为修改 | 请求体改为必填;删除两个客户端指纹;新增转账、垫资和签字凭证字段;提交时实时重算并固化终态 |
|
||||
|
||||
## 3. 接口详情
|
||||
|
||||
### 3.1 查询主报账人报账表
|
||||
|
||||
- **方法 + 路径**: `GET /v3/admin/order/:orderId/settlement/reports/reimbursement`
|
||||
- **使用场景**: 打开核单报账表或刷新核单数据
|
||||
- **认证**: 管理后台 JWT;房务角色不可访问
|
||||
- **幂等性**: 幂等,只读
|
||||
- **请求体**: 无
|
||||
|
||||
**路径参数**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `orderId` | String/Long | 是 | 订单 ID,必须大于 `0` |
|
||||
|
||||
**响应字段**
|
||||
|
||||
| 字段 | 类型 | 可空 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | String | 是 | 报账表记录 ID;实时报表和终态快照中可为 `null` |
|
||||
| `orderId` | String | 否 | 订单 ID |
|
||||
| `reportStatus` | String | 否 | 报表状态,见 §6.1 |
|
||||
| `sourceFingerprint` | String | 否 | 当前报表来源指纹,仅用于识别数据版本;前端不再回传 |
|
||||
| `primaryReporterId` | String | 是 | 主报账人 ID |
|
||||
| `primaryReporterName` | String | 是 | 主报账人姓名 |
|
||||
| `primaryReporterRole` | String | 是 | 主报账人角色 |
|
||||
| `reportVersion` | Integer | 否 | 报账表结构版本 |
|
||||
| `driverCollectedTailAmount` | Decimal | 否 | 主报账人代收尾款 |
|
||||
| `approvedAdvanceAmount` | Decimal | 否 | 已审批垫资金额 |
|
||||
| `reportablePaidCostAmount` | Decimal | 否 | 可报账的已付成本 |
|
||||
| `reporterNetAmount` | Decimal | 否 | 报账人净额;大于 0 表示报账人应转给公司,小于 0 表示公司应转给报账人 |
|
||||
| `primaryReporterCollectedAmount` | Decimal | 否 | 主报账人代收金额 |
|
||||
| `publicPrepaidAmount` | Decimal | 否 | 公共预支金额 |
|
||||
| `primaryReporterDueAmount` | Decimal | 否 | 主报账人应报账金额 |
|
||||
| `advanceOutstandingAmount` | Decimal | 否 | 未结清垫资金额 |
|
||||
| `reconNetAmount` | Decimal | 否 | 报账净额 |
|
||||
| `transferDirection` | String | 否 | 转账方向,见 §6.2 |
|
||||
| `transferAmount` | Decimal | 否 | 应转账金额的绝对值 |
|
||||
| `incomeLines` | Array\<Object> | 否 | 主报账人代收明细,字段见下表 |
|
||||
| `expenseLines` | Array\<Object> | 否 | 现金已付成本明细,字段随费用分类变化,字段见下表 |
|
||||
| `advanceLines` | Array\<Object> | 否 | 已审批垫资明细,字段见下表 |
|
||||
| `vehicleLines` | Array\<Object> | 否 | 车辆独立明细;当前返回空数组,车辆金额已进入费用分类和汇总金额 |
|
||||
| `transferStatus` | String | 是 | 未完成核单时为 `null`;终态为 `COMPLETED` |
|
||||
| `transferDate` | String/date | 是 | 转账日期,格式 `YYYY-MM-DD` |
|
||||
| `transferRef` | String | 是 | 转账流水号 |
|
||||
| `advanceSettledFlag` | Boolean | 是 | 垫资是否结清 |
|
||||
| `signedVoucher` | Object | 是 | 签字凭证;结构同 finalize 请求的 `signedVoucher` |
|
||||
| `generatedBy` | String | 是 | 历史生成操作人 ID;实时/终态模式下可为 `null` |
|
||||
| `generatedByName` | String | 是 | 历史生成操作人姓名;实时/终态模式下可为 `null` |
|
||||
| `generatedAt` | String/date-time | 是 | 历史生成时间;实时/终态模式下可为 `null` |
|
||||
| `confirmedBy` | String | 是 | 完成核单操作人 ID;未完成核单时为 `null` |
|
||||
| `confirmedByName` | String | 是 | 完成核单操作人姓名;未完成核单时为 `null` |
|
||||
| `confirmedAt` | String/date-time | 是 | 完成核单时间;未完成核单时为 `null` |
|
||||
|
||||
**`incomeLines[]` 字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `type` | String | 固定为 `DRIVER_CASH_RECEIPT` |
|
||||
| `receiptId` | String | 收款记录 ID |
|
||||
| `amount` | Decimal | 收款金额 |
|
||||
| `channel` | String | 收款渠道;当前参与报账的值为 `DRIVER_CASH` |
|
||||
| `payType` | String/null | 支付类型 |
|
||||
| `collectorStaffId` | String/null | 收款人员 ID |
|
||||
| `collectorName` | String/null | 收款人员姓名 |
|
||||
| `collectorRole` | String/null | 收款人员角色 |
|
||||
| `receivedAt` | String/date-time/null | 收款时间 |
|
||||
| `remark` | String/null | 备注 |
|
||||
|
||||
**`advanceLines[]` 字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `type` | String | 固定为 `APPROVED_ADVANCE` |
|
||||
| `advanceId` | String | 垫资记录 ID |
|
||||
| `payeeStaffId` | String/null | 收款人员 ID |
|
||||
| `payeeName` | String/null | 收款人员姓名 |
|
||||
| `payeeRole` | String/null | 收款人员角色 |
|
||||
| `advanceType` | String/null | 垫资类型 |
|
||||
| `amount` | Decimal | 已审批金额 |
|
||||
| `purpose` | String/null | 用途 |
|
||||
| `voucherUrl` | String/null | 垫资凭证地址 |
|
||||
| `status` | String | 垫资状态 |
|
||||
| `submittedAt` | String/date-time/null | 提交时间 |
|
||||
| `approvedAt` | String/date-time/null | 审批时间 |
|
||||
| `approvedBy` | String/null | 审批人 ID |
|
||||
|
||||
**`expenseLines[]` 公共字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `category` | String | 费用分类,见 §6.3 |
|
||||
| `kind` | String | 明细类型,例如 `HOTEL`、`TICKET`、`MEAL`、`VEHICLE_FEE`、`STAFF:DRIVER` |
|
||||
| `amount` | Decimal | 当前行实际成本 |
|
||||
| `paymentMethod` | String | 当前仅包含 `CASH_PAID` 行 |
|
||||
|
||||
`expenseLines[]` 会按 `kind` 追加以下分类字段:
|
||||
|
||||
- `HOTEL`: `hotelAssignmentId`、`hotelId`、`roomTypeId`、`dayNumber`、`stayDate`、`hotelName`、`roomType`、`roomTypeName`、`roomCount`、`unitPrice`、`plannedCost`、`sourceType`、`sourceId`、`voucherUrls`、`remark`。
|
||||
- `TICKET`: `sourceType`、`scenicAssignmentId`、`dayNumber`、`dayDate`、`scenicName`、`specName`、`ticketCount`、`ticketUnitPrice`、`sellPrice`、`totalAmount`、`plannedCost`、`voucherUrls`、`remark`。
|
||||
- `MEAL`: `mealType`、`mealDate`、`mealName`、`quantity`、`unitPrice`、`voucherUrls`、`remark`。
|
||||
- `VEHICLE_FEE`: `sourceRecordType`、`sourceDetailId`、`serviceDate`、`vehicleId`、`vehiclePlate`、`vehicleModelId`、`vehicleModelName`、`driverId`、`driverName`、`startDate`、`endDate`、`dailyPrice`、`paymentTypeCode`、`paymentTypeName`。
|
||||
- `STAFF:*`: `staffRole`、`staffId`、`staffName`、`totalPlannedCost`、`voucherUrls`、`reimburse`、`settleStatus`、`settledDate`、`transferRef`、`detail`、`remark`。
|
||||
- `EXPENSE:*`: `expenseType`、`projectName`、`expenseDate`、`voucherUrls`、`remark`。
|
||||
- `SUBSIDY:*`: `subsidyType`、`projectName`、`expenseDate`、`voucherUrls`、`remark`。
|
||||
|
||||
**行为**
|
||||
|
||||
- 订单不存在当前终态快照时,每次请求均按当前核单数据计算,`reportStatus=GENERATED`。
|
||||
- 订单存在当前终态快照时,返回完成核单时固化的报账表,`reportStatus=CONFIRMED`。
|
||||
- `sourceFingerprint` 继续返回,但不再作为任何前端确认或 finalize 入参。
|
||||
|
||||
### 3.2 查询单团核算表
|
||||
|
||||
- **方法 + 路径**: `GET /v3/admin/order/:orderId/settlement/reports/group`
|
||||
- **使用场景**: 打开单团核算表或刷新核算结果
|
||||
- **认证**: 管理后台 JWT;房务角色不可访问
|
||||
- **幂等性**: 幂等,只读
|
||||
- **请求体**: 无
|
||||
|
||||
**路径参数**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `orderId` | String/Long | 是 | 订单 ID,必须大于 `0` |
|
||||
|
||||
**响应字段**
|
||||
|
||||
| 字段 | 类型 | 可空 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `id` | String | 是 | 单团核算表记录 ID;实时报表和终态快照中可为 `null` |
|
||||
| `orderId` | String | 否 | 订单 ID |
|
||||
| `reportStatus` | String | 否 | 报表状态,见 §6.1 |
|
||||
| `sourceFingerprint` | String | 否 | 当前报表来源指纹,仅用于识别数据版本;前端不再回传 |
|
||||
| `baseOrderAmount` | Decimal | 否 | 订单基础金额 |
|
||||
| `otherIncomeAmount` | Decimal | 否 | 其他收入金额 |
|
||||
| `discountAmount` | Decimal | 否 | 优惠金额 |
|
||||
| `adjustedReceivableAmount` | Decimal | 否 | 调整后应收金额 |
|
||||
| `paidAmount` | Decimal | 否 | 已收金额 |
|
||||
| `actualRefundedAmount` | Decimal | 否 | 实际退款金额 |
|
||||
| `netRevenueAmount` | Decimal | 否 | 净收入 |
|
||||
| `netReceivedAmount` | Decimal | 否 | 净已收 |
|
||||
| `outstandingAmount` | Decimal | 否 | 待收金额 |
|
||||
| `hotelCost` | Decimal | 否 | 住宿成本 |
|
||||
| `ticketCost` | Decimal | 否 | 门票/游玩项目成本 |
|
||||
| `mealCost` | Decimal | 否 | 餐食成本 |
|
||||
| `vehicleCost` | Decimal | 否 | 车辆成本 |
|
||||
| `guideCost` | Decimal | 否 | 导游/领队成本 |
|
||||
| `photographerCost` | Decimal | 否 | 摄影成本 |
|
||||
| `otherExpenseCost` | Decimal | 否 | 其他支出成本 |
|
||||
| `insurancePremium` | Decimal | 否 | 保险保费 |
|
||||
| `totalCost` | Decimal | 否 | 总成本 |
|
||||
| `paidCost` | Decimal | 否 | 已付成本 |
|
||||
| `unpaidCost` | Decimal | 否 | 未付成本 |
|
||||
| `grossProfit` | Decimal | 否 | 毛利 |
|
||||
| `grossProfitRate` | Decimal | 否 | 毛利率,小数形式 |
|
||||
| `travelerCount` | Integer | 否 | 出行人数 |
|
||||
| `perCapitaRevenue` | Decimal | 否 | 人均收入 |
|
||||
| `perCapitaCost` | Decimal | 否 | 人均成本 |
|
||||
| `perCapitaProfit` | Decimal | 否 | 人均利润 |
|
||||
| `incomeLines` | Array\<Object> | 否 | 收入汇总行,固定结构见下表 |
|
||||
| `costCategories` | Array\<Object> | 否 | 成本分类汇总,固定结构见下表 |
|
||||
| `generatedBy` | String | 是 | 历史生成操作人 ID;实时/终态模式下可为 `null` |
|
||||
| `generatedByName` | String | 是 | 历史生成操作人姓名;实时/终态模式下可为 `null` |
|
||||
| `generatedAt` | String/date-time | 是 | 历史生成时间;实时/终态模式下可为 `null` |
|
||||
| `confirmedBy` | String | 是 | 完成核单操作人 ID;未完成核单时为 `null` |
|
||||
| `confirmedByName` | String | 是 | 完成核单操作人姓名;未完成核单时为 `null` |
|
||||
| `confirmedAt` | String/date-time | 是 | 完成核单时间;未完成核单时为 `null` |
|
||||
|
||||
**`incomeLines[]` 字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `type` | String | `BASE_ORDER`、`OTHER_INCOME`、`DISCOUNT` 或 `ACTUAL_REFUND` |
|
||||
| `amount` | Decimal | 金额;优惠和实际退款以负数返回 |
|
||||
|
||||
**`costCategories[]` 字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `category` | String | `HOTEL`、`TICKET`、`MEAL`、`VEHICLE`、`GUIDE`、`PHOTOGRAPHER`、`OTHER_EXPENSE` 或 `INSURANCE` |
|
||||
| `amount` | Decimal | 分类成本 |
|
||||
|
||||
**行为**
|
||||
|
||||
- 订单不存在当前终态快照时,每次请求均按当前核单数据计算,`reportStatus=GENERATED`。
|
||||
- 订单存在当前终态快照时,返回完成核单时固化的单团核算表,`reportStatus=CONFIRMED`。
|
||||
- `sourceFingerprint` 继续返回,但不再作为任何前端确认或 finalize 入参。
|
||||
|
||||
### 3.3 完成核单
|
||||
|
||||
- **方法 + 路径**: `POST /v3/admin/order/:orderId/settlement/finalize`
|
||||
- **使用场景**: 用户检查实时主报账表和单团核算表后,点击完成核单
|
||||
- **认证**: 管理后台 JWT;需要核单资金写权限;房务角色不可访问
|
||||
- **幂等性**: 已存在当前终态快照时,重复请求返回已有终态结果,不重新生成新终态
|
||||
- **限流**: 无接口级特殊限流
|
||||
|
||||
**路径参数**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `orderId` | String/Long | 是 | 订单 ID,必须大于 `0` |
|
||||
|
||||
**请求体字段**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|
||||
|------|------|------|------|----------|
|
||||
| `remark` | String | 否 | 核单整体备注 | 最多 `500` 字符 |
|
||||
| `transferDate` | String/date | 条件必填 | 转账日期 | `reporterNetAmount != 0` 时必填;格式 `YYYY-MM-DD` |
|
||||
| `transferRef` | String | 条件必填 | 转账流水号 | `reporterNetAmount != 0` 时必须为非空字符串;最多 `128` 字符 |
|
||||
| `advanceSettledFlag` | Boolean | 是 | 垫资是否结清;必须明确传 `true` 或 `false` | 不可为 `null` |
|
||||
| `signedVoucher` | Object | 是 | 签字凭证 | 不可为 `null` |
|
||||
| `signedVoucher.files` | Array\<Object> | 是 | 签字凭证文件 | `1`~`9` 项;重复 URL 按规范化后的 URL 去重并保留首项 |
|
||||
| `signedVoucher.files[].name` | String | 否 | 文件名 | 最多 `255` 字符 |
|
||||
| `signedVoucher.files[].url` | String | 是 | 文件地址 | 非空;最多 `1024` 字符;必须是带有效主机名的绝对 `http/https` URL |
|
||||
| `signedVoucher.note` | String | 否 | 签字凭证备注 | 最多 `500` 字符 |
|
||||
|
||||
以下字段已经删除,前端不得继续发送:
|
||||
|
||||
| 删除字段 | 原类型 | 迁移方式 |
|
||||
|----------|--------|----------|
|
||||
| `reimbursementExpectedSourceFingerprint` | String | 删除本地缓存和提交逻辑;完成核单时不再回传报账表指纹 |
|
||||
| `groupExpectedSourceFingerprint` | String | 删除本地缓存和提交逻辑;完成核单时不再回传单团核算表指纹 |
|
||||
|
||||
**响应字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `summaryId` | String | 核单汇总 ID |
|
||||
| `finalSnapshotId` | String | 核单终态快照 ID |
|
||||
| `finalSnapshotVersionNo` | Integer | 终态快照版本号,从 `1` 开始 |
|
||||
| `finalSnapshotStatus` | String | 当前终态固定为 `FINALIZED` |
|
||||
| `orderId` | String | 订单 ID |
|
||||
| `settledAt` | String/date-time | 核单完成时间 |
|
||||
| `totalAmount` | String/Decimal | 订单总金额快照 |
|
||||
| `paidAmount` | String/Decimal | 已付金额快照 |
|
||||
| `balanceAmount` | String/Decimal | 尾款金额快照 |
|
||||
| `roomCost` | String/Decimal | 住宿实际成本 |
|
||||
| `ticketCost` | String/Decimal | 门票实际成本 |
|
||||
| `staffCost` | String/Decimal | 人员费用实际成本 |
|
||||
| `subsidyCost` | String/Decimal | 补助实际成本 |
|
||||
| `mealCost` | String/Decimal | 餐食实际成本 |
|
||||
| `vehicleCost` | String/Decimal | 车辆基础服务总车费 |
|
||||
| `otherExpenseCost` | String/Decimal | 其他支出实际成本 |
|
||||
| `insurancePremium` | String/Decimal | 保险实际保费 |
|
||||
| `totalActualCost` | String/Decimal | 总实际成本 |
|
||||
| `driverTransferAmount` | String/Decimal | 给司机/主报账人转回金额 |
|
||||
| `profitAmount` | String/Decimal | 公司毛利 |
|
||||
| `profitRate` | Decimal | 毛利率;订单总金额为 `0` 时返回 `0` |
|
||||
| `orderStatusAfter` | String | 当前返回 `待财务复核` |
|
||||
| `mqTriggered` | Boolean | 当前固定返回 `false`;完成核单不发布结算 MQ |
|
||||
| `warnings` | Array\<String> | 软预警列表;不阻塞完成核单 |
|
||||
|
||||
**提交行为**
|
||||
|
||||
1. 前端不再先调用任何报表“确认”接口。
|
||||
2. 服务端按提交时的当前核单数据重新计算两张报表和所有汇总金额,不采信前端缓存的金额或指纹。
|
||||
3. `transferDate`、`transferRef`、`advanceSettledFlag` 和 `signedVoucher` 与本次完成核单结果一并固化。
|
||||
4. 成功后,两张 GET 报表接口返回本次固化结果。
|
||||
|
||||
### 3.4 已删除的报表确认接口
|
||||
|
||||
以下接口不再有可用请求契约:
|
||||
|
||||
| 原接口 | 原请求字段 | 当前结果 |
|
||||
|--------|------------|----------|
|
||||
| `POST /v3/admin/order/:orderId/settlement/reports/reimbursement/confirm` | `expectedSourceFingerprint`、`transferStatus`、`transferDate`、`transferRef`、`advanceSettledFlag`、`signedVoucher` | 业务码 `404` |
|
||||
| `POST /v3/admin/order/:orderId/settlement/reports/group/confirm` | `expectedSourceFingerprint` | 业务码 `404` |
|
||||
|
||||
前端必须删除这两个请求,不要用忽略 `404`、重试或降级继续调用的方式兼容。
|
||||
|
||||
## 4. 接口入参
|
||||
|
||||
### 4.1 通用路径参数
|
||||
|
||||
| 接口 | 字段 | 类型 | 必填 | 规则 |
|
||||
|------|------|------|------|------|
|
||||
| 两张 GET 报表、finalize | `orderId` | String/Long | 是 | 必须大于 `0` |
|
||||
|
||||
### 4.2 请求体变化总览
|
||||
|
||||
| 接口 | 修改前 | 修改后 |
|
||||
|------|--------|--------|
|
||||
| 主报账表确认 | 独立 POST 提交报账表指纹及凭证 | 接口删除 |
|
||||
| 单团核算表确认 | 独立 POST 提交单团核算表指纹 | 接口删除 |
|
||||
| finalize | 请求体可缺省;主要提交两个报告指纹和可选 `remark` | 请求体必填;提交 `remark`、`transferDate`、`transferRef`、`advanceSettledFlag`、`signedVoucher`;不再提交任何指纹 |
|
||||
|
||||
## 5. 出参
|
||||
|
||||
### 5.1 报表查询
|
||||
|
||||
- 两张 GET 接口的字段结构保持不变。
|
||||
- 未完成核单时返回最新实时计算结果。
|
||||
- 完成核单后返回完成核单时固化的结果。
|
||||
- 报表 `sourceFingerprint` 仍存在于出参,但只表示数据版本,前端不得再将其用于确认或 finalize。
|
||||
|
||||
### 5.2 完成核单
|
||||
|
||||
- finalize 响应字段结构保持 `SettlementSubmitRespVO`。
|
||||
- `finalSnapshotId`、`finalSnapshotVersionNo`、`finalSnapshotStatus` 标识本次固化结果。
|
||||
- `mqTriggered` 的当前契约为固定 `false`,前端不得用该字段判断是否需要等待 MQ。
|
||||
|
||||
## 6. 枚举 / 数据字典
|
||||
|
||||
### 6.1 `reportStatus`
|
||||
|
||||
**所属字段**: 两张报表响应 `reportStatus` | **类型**: String
|
||||
|
||||
| 值 | 中文 | 当前语义 |
|
||||
|----|------|----------|
|
||||
| `GENERATED` | 实时结果 | 订单未完成核单,响应按当前数据实时计算 |
|
||||
| `CONFIRMED` | 已固化 | 订单已完成核单,响应来自终态结果 |
|
||||
| `STALE` | 历史过期状态 | 仅兼容历史报表数据;新实时查询流程不要求前端据此重新生成或确认 |
|
||||
|
||||
### 6.2 `transferDirection`
|
||||
|
||||
**所属字段**: 主报账人报账表 `transferDirection` | **类型**: String
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|----|------|------|
|
||||
| `REPORTER_TO_COMPANY` | 报账人转给公司 | `reporterNetAmount > 0` |
|
||||
| `COMPANY_TO_REPORTER` | 公司转给报账人 | `reporterNetAmount < 0` |
|
||||
| `BALANCED` | 已平衡 | `reporterNetAmount = 0` |
|
||||
|
||||
### 6.3 报账费用分类
|
||||
|
||||
**所属字段**: `expenseLines[].category`、`costCategories[].category` | **类型**: String
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|----|------|------|
|
||||
| `HOTEL` | 住宿 | 住宿成本 |
|
||||
| `TICKET` | 门票/游玩项目 | 门票及游玩项目成本 |
|
||||
| `MEAL` | 餐食 | 餐食成本 |
|
||||
| `VEHICLE` | 车辆 | 车辆成本 |
|
||||
| `GUIDE` | 导游/领队 | 导游及领队成本 |
|
||||
| `PHOTOGRAPHER` | 摄影 | 摄影成本 |
|
||||
| `OTHER_EXPENSE` | 其他支出 | 其他支出成本 |
|
||||
| `INSURANCE` | 保险 | 保险保费;仅用于单团核算表成本分类 |
|
||||
|
||||
### 6.4 `finalSnapshotStatus`
|
||||
|
||||
**所属字段**: finalize 响应 `finalSnapshotStatus` | **类型**: String
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|----|------|------|
|
||||
| `FINALIZED` | 已固化 | 当前核单终态有效 |
|
||||
|
||||
### 6.5 `transferStatus`
|
||||
|
||||
**所属字段**: 主报账人报账表 `transferStatus` | **类型**: String/null
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|----|------|------|
|
||||
| `COMPLETED` | 已完成 | finalize 成功后固化到终态报账表 |
|
||||
| `null` | 未固化 | 尚未完成核单的实时报表 |
|
||||
|
||||
## 7. 错误码
|
||||
|
||||
| code | 含义 | 触发场景 |
|
||||
|------|------|----------|
|
||||
| `400` | 请求参数校验失败 | `orderId <= 0`、finalize 缺请求体/必填字段、字段超长、凭证文件数量不在 1~9 |
|
||||
| `403` | 无访问权限 | 房务角色或无权访问当前订单 |
|
||||
| `404` | 接口不存在 | 继续调用两个已删除的 `/confirm` 接口 |
|
||||
| `584051` | 当前核单状态不允许提交结算 | review 状态不是待核单或核单中 |
|
||||
| `584056` | 订单已结算,不能重复提交 | 已存在结算汇总但缺少可返回的当前终态 |
|
||||
| `584071` | 无权访问该订单(公司隔离) | 当前管理员不能查看该订单 |
|
||||
| `584077` | 存在未确认的其他收入 | finalize 前其他收入未确认 |
|
||||
| `584078` | 其他收入关联附加费已失效或金额不一致 | finalize 前其他收入与当前附加费不一致 |
|
||||
| `584079` | 存在未纳入核单分类的有效附加费 | finalize 前还有有效附加费未进入核单 |
|
||||
| `584081` | 对账数据不一致 | 已付金额与有效支付、线下收款合计不一致 |
|
||||
| `584082` | 存在待收尾款 | 单团核算 `outstandingAmount != 0` |
|
||||
| `584085` | 存在辅助人员结算未完成 | 辅助人员未全部完成结算或缺转账流水 |
|
||||
| `584092` | 存在未确认的人员费用 | 人员费用确认状态未全部完成 |
|
||||
| `584097` | 凭证 URL 格式或数量不合法 | URL 不是有效绝对 `http/https` 地址、为空、过长或数量超限 |
|
||||
| `584100` | 车辆总车费暂时不可用 | 报表查询或 finalize 暂时无法取得车辆费用 |
|
||||
| `584101` | 存在未完结派车或未确认车辆总车费 | 当前车辆数据尚不能用于核单 |
|
||||
| `584102` | 当前用车需求没有可核单的车辆总车费 | 有用车需求但没有可用车辆费用 |
|
||||
| `584315` | 核单来源数据已变化,请刷新后重新确认 | finalize 提交期间当前用车需求发生变化 |
|
||||
| `584316` | 核单报告发生并发变化,请刷新后重试 | 同一订单并发完成核单发生冲突 |
|
||||
| `584317` | 当前报告状态不允许执行该操作 | 报账人净额非 0 但缺转账日期/流水,或签字凭证不可用 |
|
||||
| `584320` | 核单分类明细尚未保存完整 | 当前分类数据不能用于报账和 finalize |
|
||||
|
||||
## 验证证据(8. 示例)
|
||||
|
||||
### 8.1 典型成功:查询实时主报账人报账表
|
||||
|
||||
**请求**
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/1914050000000001/settlement/reports/reimbursement
|
||||
Authorization: Bearer <admin-jwt>
|
||||
```
|
||||
|
||||
无请求体。
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"id": null,
|
||||
"orderId": "1914050000000001",
|
||||
"reportStatus": "GENERATED",
|
||||
"sourceFingerprint": "7a0e84a9f9d0cb411f9cff8d6a0d1c047726bb05b68c8e23af5629afdbdd67c1",
|
||||
"primaryReporterId": "3001",
|
||||
"primaryReporterName": "示例报账人",
|
||||
"primaryReporterRole": "DRIVER",
|
||||
"reportVersion": 1,
|
||||
"driverCollectedTailAmount": 2000.00,
|
||||
"approvedAdvanceAmount": 500.00,
|
||||
"reportablePaidCostAmount": 1200.00,
|
||||
"reporterNetAmount": 1300.00,
|
||||
"primaryReporterCollectedAmount": 2000.00,
|
||||
"publicPrepaidAmount": 1200.00,
|
||||
"primaryReporterDueAmount": 800.00,
|
||||
"advanceOutstandingAmount": 500.00,
|
||||
"reconNetAmount": 1300.00,
|
||||
"transferDirection": "REPORTER_TO_COMPANY",
|
||||
"transferAmount": 1300.00,
|
||||
"incomeLines": [
|
||||
{
|
||||
"type": "DRIVER_CASH_RECEIPT",
|
||||
"receiptId": "9100000000001",
|
||||
"amount": 2000.00,
|
||||
"channel": "DRIVER_CASH",
|
||||
"payType": "CASH",
|
||||
"collectorStaffId": "3001",
|
||||
"collectorName": "示例报账人",
|
||||
"collectorRole": "DRIVER",
|
||||
"receivedAt": "2026-07-28T15:30:00",
|
||||
"remark": "示例代收尾款"
|
||||
}
|
||||
],
|
||||
"expenseLines": [
|
||||
{
|
||||
"category": "HOTEL",
|
||||
"kind": "HOTEL",
|
||||
"hotelAssignmentId": "9200000000001",
|
||||
"hotelId": "1001",
|
||||
"roomTypeId": "2001",
|
||||
"dayNumber": 1,
|
||||
"stayDate": "2026-07-20",
|
||||
"hotelName": "示例酒店",
|
||||
"roomType": "STANDARD",
|
||||
"roomTypeName": "标准间",
|
||||
"roomCount": 2,
|
||||
"unitPrice": 300.00,
|
||||
"plannedCost": 600.00,
|
||||
"amount": 600.00,
|
||||
"paymentMethod": "CASH_PAID",
|
||||
"sourceType": "HOUSE_ASSIGNMENT",
|
||||
"sourceId": "9200000000001",
|
||||
"voucherUrls": ["https://oss.example.com/vouchers/hotel-1.pdf"],
|
||||
"remark": null
|
||||
}
|
||||
],
|
||||
"advanceLines": [
|
||||
{
|
||||
"type": "APPROVED_ADVANCE",
|
||||
"advanceId": "9300000000001",
|
||||
"payeeStaffId": "3001",
|
||||
"payeeName": "示例报账人",
|
||||
"payeeRole": "DRIVER",
|
||||
"advanceType": "PUBLIC",
|
||||
"amount": 500.00,
|
||||
"purpose": "行程公共支出",
|
||||
"voucherUrl": "https://oss.example.com/vouchers/advance-1.pdf",
|
||||
"status": "APPROVED",
|
||||
"submittedAt": "2026-07-19T10:00:00",
|
||||
"approvedAt": "2026-07-19T11:00:00",
|
||||
"approvedBy": "10001"
|
||||
}
|
||||
],
|
||||
"vehicleLines": [],
|
||||
"transferStatus": null,
|
||||
"transferDate": null,
|
||||
"transferRef": null,
|
||||
"advanceSettledFlag": null,
|
||||
"signedVoucher": null,
|
||||
"generatedBy": null,
|
||||
"generatedByName": null,
|
||||
"generatedAt": null,
|
||||
"confirmedBy": null,
|
||||
"confirmedByName": null,
|
||||
"confirmedAt": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 典型成功:查询实时单团核算表
|
||||
|
||||
**请求**
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/1914050000000001/settlement/reports/group
|
||||
Authorization: Bearer <admin-jwt>
|
||||
```
|
||||
|
||||
无请求体。
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"id": null,
|
||||
"orderId": "1914050000000001",
|
||||
"reportStatus": "GENERATED",
|
||||
"sourceFingerprint": "651cb6708a49f169e2ccb1b455267def9cc1a69d06935f9d9eeb41919897e0fb",
|
||||
"baseOrderAmount": 24800.00,
|
||||
"otherIncomeAmount": 500.00,
|
||||
"discountAmount": 300.00,
|
||||
"adjustedReceivableAmount": 25000.00,
|
||||
"paidAmount": 25000.00,
|
||||
"actualRefundedAmount": 0.00,
|
||||
"netRevenueAmount": 25000.00,
|
||||
"netReceivedAmount": 25000.00,
|
||||
"outstandingAmount": 0.00,
|
||||
"hotelCost": 4280.00,
|
||||
"ticketCost": 3680.00,
|
||||
"mealCost": 860.00,
|
||||
"vehicleCost": 1260.00,
|
||||
"guideCost": 800.00,
|
||||
"photographerCost": 600.00,
|
||||
"otherExpenseCost": 300.00,
|
||||
"insurancePremium": 180.00,
|
||||
"totalCost": 11960.00,
|
||||
"paidCost": 11960.00,
|
||||
"unpaidCost": 0.00,
|
||||
"grossProfit": 13040.00,
|
||||
"grossProfitRate": 0.521600,
|
||||
"travelerCount": 5,
|
||||
"perCapitaRevenue": 5000.00,
|
||||
"perCapitaCost": 2392.00,
|
||||
"perCapitaProfit": 2608.00,
|
||||
"incomeLines": [
|
||||
{
|
||||
"type": "BASE_ORDER",
|
||||
"amount": 24800.00
|
||||
},
|
||||
{
|
||||
"type": "OTHER_INCOME",
|
||||
"amount": 500.00
|
||||
},
|
||||
{
|
||||
"type": "DISCOUNT",
|
||||
"amount": -300.00
|
||||
},
|
||||
{
|
||||
"type": "ACTUAL_REFUND",
|
||||
"amount": 0.00
|
||||
}
|
||||
],
|
||||
"costCategories": [
|
||||
{
|
||||
"category": "HOTEL",
|
||||
"amount": 4280.00
|
||||
},
|
||||
{
|
||||
"category": "TICKET",
|
||||
"amount": 3680.00
|
||||
},
|
||||
{
|
||||
"category": "MEAL",
|
||||
"amount": 860.00
|
||||
},
|
||||
{
|
||||
"category": "VEHICLE",
|
||||
"amount": 1260.00
|
||||
},
|
||||
{
|
||||
"category": "GUIDE",
|
||||
"amount": 800.00
|
||||
},
|
||||
{
|
||||
"category": "PHOTOGRAPHER",
|
||||
"amount": 600.00
|
||||
},
|
||||
{
|
||||
"category": "OTHER_EXPENSE",
|
||||
"amount": 300.00
|
||||
},
|
||||
{
|
||||
"category": "INSURANCE",
|
||||
"amount": 180.00
|
||||
}
|
||||
],
|
||||
"generatedBy": null,
|
||||
"generatedByName": null,
|
||||
"generatedAt": null,
|
||||
"confirmedBy": null,
|
||||
"confirmedByName": null,
|
||||
"confirmedAt": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 典型成功:完成核单并固化
|
||||
|
||||
**请求**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000001/settlement/finalize
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"remark": "核单完成",
|
||||
"transferDate": "2026-07-29",
|
||||
"transferRef": "BANK-20260729-001",
|
||||
"advanceSettledFlag": true,
|
||||
"signedVoucher": {
|
||||
"files": [
|
||||
{
|
||||
"name": "签字单.pdf",
|
||||
"url": "https://oss.example.com/vouchers/signed-20260729.pdf"
|
||||
}
|
||||
],
|
||||
"note": "签字凭证已回收"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"summaryId": "9400000000001",
|
||||
"finalSnapshotId": "9400000000002",
|
||||
"finalSnapshotVersionNo": 1,
|
||||
"finalSnapshotStatus": "FINALIZED",
|
||||
"orderId": "1914050000000001",
|
||||
"settledAt": "2026-07-29T13:28:22",
|
||||
"totalAmount": "25000.00",
|
||||
"paidAmount": "25000.00",
|
||||
"balanceAmount": "0.00",
|
||||
"roomCost": "4280.00",
|
||||
"ticketCost": "3680.00",
|
||||
"staffCost": "1400.00",
|
||||
"subsidyCost": "0.00",
|
||||
"mealCost": "860.00",
|
||||
"vehicleCost": "1260.00",
|
||||
"otherExpenseCost": "300.00",
|
||||
"insurancePremium": "180.00",
|
||||
"totalActualCost": "11960.00",
|
||||
"driverTransferAmount": "11780.00",
|
||||
"profitAmount": "13040.00",
|
||||
"profitRate": 0.5216,
|
||||
"orderStatusAfter": "待财务复核",
|
||||
"mqTriggered": false,
|
||||
"warnings": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.4 边界:报账人净额为 0
|
||||
|
||||
当最新 `reporterNetAmount=0` 时,`transferDate` 和 `transferRef` 可以省略;`advanceSettledFlag` 和 `signedVoucher` 仍必须提交。
|
||||
|
||||
**请求**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000002/settlement/finalize
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"remark": "收支已平衡",
|
||||
"advanceSettledFlag": false,
|
||||
"signedVoucher": {
|
||||
"files": [
|
||||
{
|
||||
"name": "签字单.jpg",
|
||||
"url": "https://oss.example.com/vouchers/signed-balanced.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"summaryId": "9400000000011",
|
||||
"finalSnapshotId": "9400000000012",
|
||||
"finalSnapshotVersionNo": 1,
|
||||
"finalSnapshotStatus": "FINALIZED",
|
||||
"orderId": "1914050000000002",
|
||||
"settledAt": "2026-07-29T13:40:00",
|
||||
"totalAmount": "0.00",
|
||||
"paidAmount": "0.00",
|
||||
"balanceAmount": "0.00",
|
||||
"roomCost": "0.00",
|
||||
"ticketCost": "0.00",
|
||||
"staffCost": "0.00",
|
||||
"subsidyCost": "0.00",
|
||||
"mealCost": "0.00",
|
||||
"vehicleCost": "0.00",
|
||||
"otherExpenseCost": "0.00",
|
||||
"insurancePremium": "0.00",
|
||||
"totalActualCost": "0.00",
|
||||
"driverTransferAmount": "0.00",
|
||||
"profitAmount": "0.00",
|
||||
"profitRate": 0,
|
||||
"orderStatusAfter": "待财务复核",
|
||||
"mqTriggered": false,
|
||||
"warnings": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.5 异常:仍调用已删除的确认接口
|
||||
|
||||
**请求**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000001/settlement/reports/group/confirm
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"expectedSourceFingerprint": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
}
|
||||
```
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 404,
|
||||
"msg": "请求地址不存在",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
### 8.6 异常:车辆费用尚未可核单
|
||||
|
||||
**请求**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000001/settlement/finalize
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"transferDate": "2026-07-29",
|
||||
"transferRef": "BANK-20260729-001",
|
||||
"advanceSettledFlag": true,
|
||||
"signedVoucher": {
|
||||
"files": [
|
||||
{
|
||||
"name": "签字单.pdf",
|
||||
"url": "https://oss.example.com/vouchers/signed-20260729.pdf"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 584101,
|
||||
"msg": "存在未完结派车或未确认车辆总车费,暂不能核单",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 业务边界
|
||||
|
||||
- 报表 GET 的“实时”以每次请求时可用于核单的当前数据为准,前端不要把上一次响应当作提交凭据。
|
||||
- 完成核单前,前端可以重复查询两张报表;无需执行任何“生成”或“确认”步骤。
|
||||
- finalize 不接收前端金额。页面展示金额与提交时权威数据发生变化时,以提交时重新计算结果为准。
|
||||
- 报账人净额不为 `0` 时,必须同时提交 `transferDate` 和非空 `transferRef`。
|
||||
- `signedVoucher.files` 原始数组必须为 `1`~`9` 项;URL 会去除首尾空格、规范化并按 URL 去重。
|
||||
- 完成核单成功后,两张报表进入终态读取;只有业务上的核单反确认使当前终态失效后,查询才重新进入实时模式。
|
||||
- finalize 成功响应中的 `warnings` 是软预警,不表示提交失败。
|
||||
- 已有当前终态时重复调用 finalize 返回已有终态,不会依据本次请求改写已固化的转账或凭证信息。
|
||||
|
||||
## 10. 修改前后对比
|
||||
|
||||
### 10.1 字段级对比
|
||||
|
||||
| 接口/字段 | 修改前 | 修改后 |
|
||||
|-----------|--------|--------|
|
||||
| finalize 请求体 | 可缺省 | 必填 |
|
||||
| `remark` | 可选,最多 500 字符 | 保持不变 |
|
||||
| `reimbursementExpectedSourceFingerprint` | finalize 必填 | 删除 |
|
||||
| `groupExpectedSourceFingerprint` | finalize 必填 | 删除 |
|
||||
| `transferDate` | 在主报账表确认接口提交 | 移至 finalize;报账人净额非 0 时必填 |
|
||||
| `transferRef` | 在主报账表确认接口提交 | 移至 finalize;报账人净额非 0 时必填,最多 128 字符 |
|
||||
| `advanceSettledFlag` | 在主报账表确认接口提交 | 移至 finalize,必填 |
|
||||
| `signedVoucher` | 在主报账表确认接口提交 | 移至 finalize,必填 |
|
||||
| `signedVoucher.files` | 原确认接口字段 | finalize 中要求 1~9 项 |
|
||||
| `signedVoucher.files[].name` | 原确认接口未明确长度 | 最多 255 字符 |
|
||||
| `signedVoucher.files[].url` | 原确认接口未明确长度 | 必填;最多 1024 字符;绝对 http/https URL |
|
||||
| `signedVoucher.note` | 原确认接口未明确长度 | 最多 500 字符 |
|
||||
| `mqTriggered` | 示例和历史说明可能按 `true` 理解 | 当前固定 `false` |
|
||||
|
||||
### 10.2 行为级对比
|
||||
|
||||
| 行为 | 修改前 | 修改后 |
|
||||
|------|--------|--------|
|
||||
| 主报账表 | 先读取,再调用独立 confirm | GET 实时读取;不再确认 |
|
||||
| 单团核算表 | 主报账表确认后再读取并 confirm | GET 实时读取;不再确认 |
|
||||
| 数据变化处理 | 前端携带两张报表指纹,指纹过期时刷新重试 | 前端不携带指纹;finalize 按提交时数据重算 |
|
||||
| 转账/垫资/签字信息 | 主报账表 confirm 时提交 | finalize 时一次提交 |
|
||||
| 完成核单后查询 | 依赖已确认报表记录 | 返回完成核单时固化的终态结果 |
|
||||
| 重复 finalize | 依赖旧报告确认门禁 | 已有当前终态时返回已有结果 |
|
||||
|
||||
## 11. 影响评估 / 回滚
|
||||
|
||||
### 11.1 影响评估
|
||||
|
||||
- **是否破坏向后兼容**: 是。两个 POST 确认接口删除,finalize 请求字段和必填规则改变。
|
||||
- **前端是否必须同步调整**: 是。旧页面继续调用 `/confirm` 会收到业务码 `404`;旧 finalize 请求缺少新必填字段会收到业务码 `400`。
|
||||
- **查询字段兼容性**: 两张 GET 报表的顶层字段结构保持不变,但数据时效语义变为“未终态实时、终态固定”。
|
||||
|
||||
### 11.2 回滚说明
|
||||
|
||||
- 如果接口契约回滚,前端需要同步恢复两次确认请求和两个指纹字段。
|
||||
- 前后端不能混用新旧流程:新版前端不再保留报表确认指纹,旧版后端仍会要求指纹和独立确认。
|
||||
|
||||
## 12. 注意事项
|
||||
|
||||
- 删除“确认主报账表”“确认单团核算表”按钮、请求封装、loading 状态、重试逻辑和指纹缓存。
|
||||
- 页面展示仍调用两个 GET 接口;无需在详情加载时调用任何写接口。
|
||||
- “完成核单”按钮直接提交 finalize 新请求体。
|
||||
- 不要把 GET 返回的 `sourceFingerprint` 填回 finalize。
|
||||
- 不要继续发送已删除字段;即使服务端当前可能忽略未知 JSON 字段,前端类型和请求对象也应删除。
|
||||
- `signedVoucher` 不是可选附件:至少需要一个有效 URL。
|
||||
- `mqTriggered=false` 是当前固定契约,不要显示“MQ 触发失败”或据此轮询。
|
||||
|
||||
## 13. 关联 / 联系人
|
||||
|
||||
### 13.1 链接
|
||||
|
||||
- **Issue**: [#5342](https://git.1814.love:8443/wx/HL/issues/5342)
|
||||
- **PR**: [#5345](https://git.1814.love:8443/wx/HL/pulls/5345)
|
||||
- **Merge commit**: [eb9ecfafad](https://git.1814.love:8443/wx/HL/commit/eb9ecfafadde4cb9e2dbe5be8193abcf569ca44c)
|
||||
|
||||
### 13.2 联系人
|
||||
|
||||
- **后端负责人**: @yst
|
||||
- **消费端**: v3 管理后台
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户