父节点
2ce66df423
当前提交
cf97a39075
@ -0,0 +1,874 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "5343"
|
||||
title: "核单确认收口到完成核单"
|
||||
consumer: "admin"
|
||||
change_type: "修改接口"
|
||||
backend_status: "merged"
|
||||
gateway_status: "pending"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: ""
|
||||
status_note: "后端 PR #5347 已合并;等待测试服部署与网关验证,前端待按本文纠正 finalize 请求契约"
|
||||
updated_at: "2026-07-29"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# ⚠️【修改接口·管理后台】核单确认收口到完成核单 (#5343)
|
||||
|
||||
> **PR**: #5347 | **服务**: hl-order-service-v3 | **更新时间**: 2026-07-29
|
||||
|
||||
## 1. 接口背景
|
||||
|
||||
主报账表和单团核算表不再各自提供“确认”写操作。页面先通过两张 GET 报表取得同一轮核单事实对应的两个 `sourceFingerprint`,再由“完成核单”一次提交双指纹、转账信息、预支处理标志和签字凭证。
|
||||
|
||||
本文纠正并取代 `29_5342_核单报表取消中间确认并由finalize固化-修改接口-管理后台.md` 中关于 finalize 请求的说明:**双指纹没有删除,仍是 finalize 必填字段;转账与凭证字段必须放在必填的 `reimbursementConfirmation` 对象内。**
|
||||
|
||||
## 2. 变更清单
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---|------|------|------|----------|------|
|
||||
| 1 | 查询主报账表 | GET | `/v3/admin/order/{orderId}/settlement/reports/reimbursement` | 行为明确 | 返回主报账数据及 `sourceFingerprint`,该指纹必须回传给 finalize |
|
||||
| 2 | 查询单团核算表 | GET | `/v3/admin/order/{orderId}/settlement/reports/group` | 行为明确 | 返回单团核算数据及 `sourceFingerprint`,该指纹必须回传给 finalize |
|
||||
| 3 | 完成核单 | POST | `/v3/admin/order/{orderId}/settlement/finalize` | 请求与行为修改 | 必填双指纹和嵌套 `reimbursementConfirmation`;成功后一次完成核单 |
|
||||
| 4 | 确认主报账表 | POST | `/v3/admin/order/{orderId}/settlement/reports/reimbursement/confirm` | 删除接口 | 路由继续保持删除,不得调用 |
|
||||
| 5 | 确认单团核算表 | POST | `/v3/admin/order/{orderId}/settlement/reports/group/confirm` | 删除接口 | 路由继续保持删除,不得调用 |
|
||||
|
||||
## 3. 接口详情
|
||||
|
||||
### 3.1 查询主报账表
|
||||
|
||||
- **方法与路径**:`GET /v3/admin/order/{orderId}/settlement/reports/reimbursement`
|
||||
- **使用场景**:展示主报账表,并在调用 finalize 前取得最新主报账指纹
|
||||
- **认证**:管理后台 JWT;房务角色不可访问
|
||||
- **幂等性**:幂等,只读
|
||||
- **限流**:无接口级特殊限流
|
||||
|
||||
**路径参数**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `orderId` | String/Long | 是 | 订单 ID,必须大于 `0` |
|
||||
|
||||
**请求体**
|
||||
|
||||
无。
|
||||
|
||||
**响应字段**
|
||||
|
||||
| `data` 字段 | JSON 类型 | 可空 | 说明 |
|
||||
|-------------|-----------|:---:|------|
|
||||
| `id` | string | 是 | 报账表记录 ID |
|
||||
| `orderId` | string | 否 | 订单 ID |
|
||||
| `reportStatus` | string | 否 | 报表状态,见 §6.1 |
|
||||
| `sourceFingerprint` | string | 否 | 64 位小写十六进制 SHA-256;传给 finalize 的 `reimbursementExpectedSourceFingerprint` |
|
||||
| `primaryReporterId` | string | 是 | 主报账人 ID |
|
||||
| `primaryReporterName` | string | 是 | 主报账人姓名 |
|
||||
| `primaryReporterRole` | string | 是 | 主报账人角色 |
|
||||
| `reportVersion` | integer | 否 | 报账表结构版本 |
|
||||
| `driverCollectedTailAmount` | number | 否 | 主报账人代收尾款 |
|
||||
| `approvedAdvanceAmount` | number | 否 | 已审批预支金额 |
|
||||
| `reportablePaidCostAmount` | number | 否 | 可报账的已付成本 |
|
||||
| `reporterNetAmount` | number | 否 | 主报账人净额;决定转账日期和流水是否必填 |
|
||||
| `primaryReporterCollectedAmount` | number | 否 | 主报账人代收金额 |
|
||||
| `publicPrepaidAmount` | number | 否 | 公共预支金额 |
|
||||
| `primaryReporterDueAmount` | number | 否 | 主报账人应报账金额 |
|
||||
| `advanceOutstandingAmount` | number | 否 | 未结清预支金额 |
|
||||
| `reconNetAmount` | number | 否 | 报账净额 |
|
||||
| `transferDirection` | string | 否 | 转账方向,见 §6.2 |
|
||||
| `transferAmount` | number | 否 | 应转账金额的绝对值 |
|
||||
| `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 的凭证一致 |
|
||||
| `generatedBy` | string | 是 | 历史生成操作人 ID |
|
||||
| `generatedByName` | string | 是 | 历史生成操作人姓名 |
|
||||
| `generatedAt` | string(date-time) | 是 | 历史生成时间 |
|
||||
| `confirmedBy` | string | 是 | 完成核单操作人 ID |
|
||||
| `confirmedByName` | string | 是 | 完成核单操作人姓名 |
|
||||
| `confirmedAt` | string(date-time) | 是 | 完成核单时间 |
|
||||
|
||||
**`incomeLines[]` 字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `type` | string | 当前为 `DRIVER_CASH_RECEIPT` |
|
||||
| `receiptId` | string | 收款记录 ID |
|
||||
| `amount` | number | 收款金额 |
|
||||
| `channel` | string | 收款渠道 |
|
||||
| `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` | number | 已审批金额 |
|
||||
| `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` | number | 当前行实际成本 |
|
||||
| `paymentMethod` | string | 当前报账明细使用 `CASH_PAID` |
|
||||
|
||||
不同 `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`。
|
||||
|
||||
**错误与业务边界**
|
||||
|
||||
- `orderId <= 0` 返回 `400`。
|
||||
- 房务角色或无订单访问权限返回 `403`/对应订单访问错误。
|
||||
- 未完成核单时返回当前核单事实的实时视图和当前指纹。
|
||||
- 已完成核单时返回当前有效终态版本中的报账表和该版本指纹。
|
||||
- 管理员反确认后再次 GET 会回到实时视图;前端必须重新取得指纹。
|
||||
|
||||
**典型请求**
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/1914050000000001/settlement/reports/reimbursement
|
||||
Authorization: Bearer <admin-jwt>
|
||||
```
|
||||
|
||||
无请求体。
|
||||
|
||||
**典型响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"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": [],
|
||||
"expenseLines": [],
|
||||
"advanceLines": [],
|
||||
"vehicleLines": [],
|
||||
"transferStatus": null,
|
||||
"transferDate": null,
|
||||
"transferRef": null,
|
||||
"advanceSettledFlag": null,
|
||||
"signedVoucher": null,
|
||||
"generatedBy": null,
|
||||
"generatedByName": null,
|
||||
"generatedAt": null,
|
||||
"confirmedBy": null,
|
||||
"confirmedByName": null,
|
||||
"confirmedAt": null
|
||||
},
|
||||
"traceId": "a1b2c3d4-e5f6-7890",
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 查询单团核算表
|
||||
|
||||
- **方法与路径**:`GET /v3/admin/order/{orderId}/settlement/reports/group`
|
||||
- **使用场景**:展示单团核算表,并在调用 finalize 前取得最新单团指纹
|
||||
- **认证**:管理后台 JWT;房务角色不可访问
|
||||
- **幂等性**:幂等,只读
|
||||
- **限流**:无接口级特殊限流
|
||||
|
||||
**路径参数**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `orderId` | String/Long | 是 | 订单 ID,必须大于 `0` |
|
||||
|
||||
**请求体**
|
||||
|
||||
无。
|
||||
|
||||
**响应字段**
|
||||
|
||||
| `data` 字段 | JSON 类型 | 可空 | 说明 |
|
||||
|-------------|-----------|:---:|------|
|
||||
| `id` | string | 是 | 单团核算表记录 ID |
|
||||
| `orderId` | string | 否 | 订单 ID |
|
||||
| `reportStatus` | string | 否 | 报表状态,见 §6.1 |
|
||||
| `sourceFingerprint` | string | 否 | 64 位小写十六进制 SHA-256;传给 finalize 的 `groupExpectedSourceFingerprint` |
|
||||
| `baseOrderAmount` | number | 否 | 订单基础金额 |
|
||||
| `otherIncomeAmount` | number | 否 | 其他收入金额 |
|
||||
| `discountAmount` | number | 否 | 优惠金额 |
|
||||
| `adjustedReceivableAmount` | number | 否 | 调整后应收金额 |
|
||||
| `paidAmount` | number | 否 | 已收金额 |
|
||||
| `actualRefundedAmount` | number | 否 | 实际退款金额 |
|
||||
| `netRevenueAmount` | number | 否 | 净收入 |
|
||||
| `netReceivedAmount` | number | 否 | 净已收 |
|
||||
| `outstandingAmount` | number | 否 | 待收金额;不为 `0` 时不能 finalize |
|
||||
| `hotelCost` | number | 否 | 住宿成本 |
|
||||
| `ticketCost` | number | 否 | 门票/游玩项目成本 |
|
||||
| `mealCost` | number | 否 | 餐食成本 |
|
||||
| `vehicleCost` | number | 否 | 车辆成本 |
|
||||
| `guideCost` | number | 否 | 导游/领队成本 |
|
||||
| `photographerCost` | number | 否 | 摄影成本 |
|
||||
| `otherExpenseCost` | number | 否 | 其他支出成本 |
|
||||
| `insurancePremium` | number | 否 | 保险保费 |
|
||||
| `totalCost` | number | 否 | 总成本 |
|
||||
| `paidCost` | number | 否 | 已付成本 |
|
||||
| `unpaidCost` | number | 否 | 未付成本 |
|
||||
| `grossProfit` | number | 否 | 毛利 |
|
||||
| `grossProfitRate` | number | 否 | 毛利率,小数形式 |
|
||||
| `travelerCount` | integer | 否 | 出行人数 |
|
||||
| `perCapitaRevenue` | number | 否 | 人均收入 |
|
||||
| `perCapitaCost` | number | 否 | 人均成本 |
|
||||
| `perCapitaProfit` | number | 否 | 人均利润 |
|
||||
| `incomeLines` | array<object> | 否 | 收入汇总行 |
|
||||
| `costCategories` | array<object> | 否 | 成本分类汇总 |
|
||||
| `generatedBy` | string | 是 | 历史生成操作人 ID |
|
||||
| `generatedByName` | string | 是 | 历史生成操作人姓名 |
|
||||
| `generatedAt` | string(date-time) | 是 | 历史生成时间 |
|
||||
| `confirmedBy` | string | 是 | 完成核单操作人 ID |
|
||||
| `confirmedByName` | string | 是 | 完成核单操作人姓名 |
|
||||
| `confirmedAt` | string(date-time) | 是 | 完成核单时间 |
|
||||
|
||||
**`incomeLines[]` 字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `type` | string | `BASE_ORDER`、`OTHER_INCOME`、`DISCOUNT` 或 `ACTUAL_REFUND` |
|
||||
| `amount` | number | 金额;优惠和实际退款以负数返回 |
|
||||
|
||||
**`costCategories[]` 字段**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `category` | string | `HOTEL`、`TICKET`、`MEAL`、`VEHICLE`、`GUIDE`、`PHOTOGRAPHER`、`OTHER_EXPENSE` 或 `INSURANCE` |
|
||||
| `amount` | number | 分类成本 |
|
||||
|
||||
**错误与业务边界**
|
||||
|
||||
- `orderId <= 0` 返回 `400`。
|
||||
- 房务角色或无订单访问权限返回 `403`/对应订单访问错误。
|
||||
- 未完成核单时返回实时视图;已完成核单时返回当前有效终态版本。
|
||||
- 管理员反确认后,下一次 GET 会生成新的实时结果和指纹。
|
||||
|
||||
**典型请求**
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/1914050000000001/settlement/reports/group
|
||||
Authorization: Bearer <admin-jwt>
|
||||
```
|
||||
|
||||
无请求体。
|
||||
|
||||
**典型响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"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": 5200.00,
|
||||
"guideCost": 800.00,
|
||||
"photographerCost": 600.00,
|
||||
"otherExpenseCost": 1200.00,
|
||||
"insurancePremium": 180.00,
|
||||
"totalCost": 16800.00,
|
||||
"paidCost": 16800.00,
|
||||
"unpaidCost": 0.00,
|
||||
"grossProfit": 8200.00,
|
||||
"grossProfitRate": 0.328,
|
||||
"travelerCount": 5,
|
||||
"perCapitaRevenue": 5000.00,
|
||||
"perCapitaCost": 3360.00,
|
||||
"perCapitaProfit": 1640.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": 5200.00},
|
||||
{"category": "GUIDE", "amount": 800.00},
|
||||
{"category": "PHOTOGRAPHER", "amount": 600.00},
|
||||
{"category": "OTHER_EXPENSE", "amount": 1200.00},
|
||||
{"category": "INSURANCE", "amount": 180.00}
|
||||
],
|
||||
"generatedBy": null,
|
||||
"generatedByName": null,
|
||||
"generatedAt": null,
|
||||
"confirmedBy": null,
|
||||
"confirmedByName": null,
|
||||
"confirmedAt": null
|
||||
},
|
||||
"traceId": "a1b2c3d4-e5f6-7890",
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 完成核单
|
||||
|
||||
- **方法与路径**:`POST /v3/admin/order/{orderId}/settlement/finalize`
|
||||
- **使用场景**:两张报表核对完成后,一次提交双指纹和主报账凭据
|
||||
- **认证**:管理后台 JWT;房务角色不可访问
|
||||
- **幂等性**:严格幂等,比较双指纹、规范化后的凭据和 `remark`
|
||||
- **限流**:无接口级特殊限流
|
||||
|
||||
**路径参数**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `orderId` | String/Long | 是 | 订单 ID,必须大于 `0` |
|
||||
|
||||
**请求体字段**
|
||||
|
||||
| 字段 | JSON 类型 | 必填 | 校验与规范化 |
|
||||
|------|-----------|:---:|--------------|
|
||||
| `remark` | string/null | 否 | 最长 500;去除首尾空格,空串按 `null` 比较 |
|
||||
| `reimbursementExpectedSourceFingerprint` | string | 是 | 必须等于主报账 GET 返回的 64 位小写十六进制 `sourceFingerprint` |
|
||||
| `groupExpectedSourceFingerprint` | string | 是 | 必须等于单团 GET 返回的 64 位小写十六进制 `sourceFingerprint` |
|
||||
| `reimbursementConfirmation` | object | 是 | 主报账转账、预支和签字凭据 |
|
||||
| `reimbursementConfirmation.transferDate` | string(date)/null | 条件必填 | `reporterNetAmount != 0` 时必填;净额为 `0` 时可为 `null` |
|
||||
| `reimbursementConfirmation.transferRef` | string/null | 条件必填 | 去除首尾空格后最长 128;净额非 `0` 时长度必须为 1~128 |
|
||||
| `reimbursementConfirmation.advanceSettledFlag` | boolean | 是 | 必须明确传值,`false` 合法 |
|
||||
| `reimbursementConfirmation.signedVoucher` | object | 是 | 缺失返回 `400` |
|
||||
| `reimbursementConfirmation.signedVoucher.files` | array<object> | 业务必填 | 1~9 项;为 `null`、空数组、超过 9 项或含 `null` 项返回 `584317` |
|
||||
| `reimbursementConfirmation.signedVoucher.files[].url` | string | 业务必填 | 去除首尾空格后长度 1~1024;不符合返回 `584317` |
|
||||
| `reimbursementConfirmation.signedVoucher.files[].name` | string/null | 否 | 去除首尾空格;空串归一化为 `null`;非空最长 255 |
|
||||
| `reimbursementConfirmation.signedVoucher.note` | string/null | 否 | 去除首尾空格;空串归一化为 `null`;非空最长 500 |
|
||||
|
||||
`transferStatus` **不得提交**。finalize 成功后,报账终态中的 `transferStatus` 固定为 `COMPLETED`。
|
||||
|
||||
签字凭证文件按规范化后的 `url`、`name` 升序稳定保存。不得依赖请求数组原顺序进行严格幂等判断。
|
||||
|
||||
**响应字段**
|
||||
|
||||
| `data` 字段 | JSON 类型 | 说明 |
|
||||
|-------------|-----------|------|
|
||||
| `summaryId` | string | 核单汇总 ID |
|
||||
| `finalSnapshotId` | string | 核单终态快照 ID |
|
||||
| `finalSnapshotVersionNo` | integer | 终态版本号;首次为 1,反确认后再次 finalize 为上一版本 + 1 |
|
||||
| `finalSnapshotStatus` | string | 成功固定为 `FINALIZED` |
|
||||
| `orderId` | string | 订单 ID |
|
||||
| `settledAt` | string(date-time) | ISO-8601 核单完成时间 |
|
||||
| `totalAmount` | string | 订单总金额快照 |
|
||||
| `paidAmount` | string | 已付金额快照 |
|
||||
| `balanceAmount` | string | 尾款金额快照 |
|
||||
| `roomCost` | string | 住宿实际成本 |
|
||||
| `ticketCost` | string | 门票实际成本 |
|
||||
| `staffCost` | string | 人员费用实际成本 |
|
||||
| `subsidyCost` | string | 补助实际成本 |
|
||||
| `mealCost` | string | 餐食实际成本 |
|
||||
| `vehicleCost` | string | 车辆成本 |
|
||||
| `otherExpenseCost` | string | 其他支出实际成本 |
|
||||
| `insurancePremium` | string | 保险实际保费 |
|
||||
| `totalActualCost` | string | 总实际成本 |
|
||||
| `driverTransferAmount` | string | 给司机/主报账人转回金额 |
|
||||
| `profitAmount` | string | 公司毛利 |
|
||||
| `profitRate` | number | 毛利率;订单总金额为 0 时为 0 |
|
||||
| `orderStatusAfter` | string | 成功后为 `待财务复核` |
|
||||
| `mqTriggered` | boolean | 当前固定为 `false` |
|
||||
| `warnings` | array<string> | 软预警列表;无预警为 `[]` |
|
||||
|
||||
**错误与业务边界**
|
||||
|
||||
- 缺 body、非法 JSON、`remark` 超长、双指纹格式错误,或缺少 `reimbursementConfirmation`、`advanceSettledFlag`、`signedVoucher`:返回 `400`。
|
||||
- 双指纹任一与当前冻结事实不一致:返回 `584315`,须重新 GET 两张报表。
|
||||
- `transferRef` 条件不满足或超过 128,凭证 `files`/文件项/`url` 无效,或 `name`/`note` 超长:返回 `584317`。
|
||||
- 单团核算的 `outstandingAmount != 0`:返回 `584082`,不能完成核单。
|
||||
- 完全相同的终态请求重试返回原 `summaryId`、`finalSnapshotId` 和版本号,不产生新版本。
|
||||
- 已有当前终态时,双指纹、规范化凭据或 `remark` 任一不同:返回 `584316`。
|
||||
- 任一失败不留下部分完成结果。
|
||||
|
||||
**典型请求:净报账金额非 0**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000001/settlement/finalize
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"remark": "主报账人与单团核算均已核对",
|
||||
"reimbursementExpectedSourceFingerprint": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
"groupExpectedSourceFingerprint": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"reimbursementConfirmation": {
|
||||
"transferDate": "2026-07-29",
|
||||
"transferRef": "FT202607290001",
|
||||
"advanceSettledFlag": false,
|
||||
"signedVoucher": {
|
||||
"files": [
|
||||
{
|
||||
"name": "司机签字报账单.pdf",
|
||||
"url": "https://oss.example.com/settlement/driver-signed-20260729.pdf"
|
||||
}
|
||||
],
|
||||
"note": "司机现场签字后上传"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**典型响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"summaryId": "9600000000001",
|
||||
"finalSnapshotId": "9600000000002",
|
||||
"finalSnapshotVersionNo": 1,
|
||||
"finalSnapshotStatus": "FINALIZED",
|
||||
"orderId": "1914050000000001",
|
||||
"settledAt": "2026-07-29T10:30:25",
|
||||
"totalAmount": "24800.00",
|
||||
"paidAmount": "24800.00",
|
||||
"balanceAmount": "0.00",
|
||||
"roomCost": "4280.00",
|
||||
"ticketCost": "3680.00",
|
||||
"staffCost": "7000.00",
|
||||
"subsidyCost": "720.00",
|
||||
"mealCost": "860.00",
|
||||
"vehicleCost": "5200.00",
|
||||
"otherExpenseCost": "1200.00",
|
||||
"insurancePremium": "180.00",
|
||||
"totalActualCost": "23120.00",
|
||||
"driverTransferAmount": "22940.00",
|
||||
"profitAmount": "1680.00",
|
||||
"profitRate": 0.0677,
|
||||
"orderStatusAfter": "待财务复核",
|
||||
"mqTriggered": false,
|
||||
"warnings": []
|
||||
},
|
||||
"traceId": "a1b2c3d4-e5f6-7890",
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**边界请求:`reporterNetAmount = 0`**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000002/settlement/finalize
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"remark": null,
|
||||
"reimbursementExpectedSourceFingerprint": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
"groupExpectedSourceFingerprint": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"reimbursementConfirmation": {
|
||||
"transferDate": null,
|
||||
"transferRef": null,
|
||||
"advanceSettledFlag": false,
|
||||
"signedVoucher": {
|
||||
"files": [
|
||||
{
|
||||
"name": null,
|
||||
"url": "https://oss.example.com/settlement/zero-net-signed.jpg"
|
||||
}
|
||||
],
|
||||
"note": null
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**边界响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"summaryId": "9600000000011",
|
||||
"finalSnapshotId": "9600000000012",
|
||||
"finalSnapshotVersionNo": 1,
|
||||
"finalSnapshotStatus": "FINALIZED",
|
||||
"orderId": "1914050000000002",
|
||||
"settledAt": "2026-07-29T10:35: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": []
|
||||
},
|
||||
"traceId": "a1b2c3d4-e5f6-7890",
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**异常请求:凭证包含空 URL**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000001/settlement/finalize
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"reimbursementExpectedSourceFingerprint": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
"groupExpectedSourceFingerprint": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"reimbursementConfirmation": {
|
||||
"transferDate": "2026-07-29",
|
||||
"transferRef": "FT202607290001",
|
||||
"advanceSettledFlag": true,
|
||||
"signedVoucher": {
|
||||
"files": [
|
||||
{"name": "签字单.pdf", "url": " "}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**异常响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 584317,
|
||||
"message": "当前报告状态不允许执行该操作",
|
||||
"data": null,
|
||||
"traceId": "a1b2c3d4-e5f6-7890",
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
**异常请求:缺少 `signedVoucher`**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000001/settlement/finalize
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"reimbursementExpectedSourceFingerprint": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
"groupExpectedSourceFingerprint": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"reimbursementConfirmation": {
|
||||
"transferDate": "2026-07-29",
|
||||
"transferRef": "FT202607290001",
|
||||
"advanceSettledFlag": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**异常响应**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 400,
|
||||
"message": "参数校验失败",
|
||||
"data": null,
|
||||
"traceId": "a1b2c3d4-e5f6-7890",
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 已删除:确认主报账表
|
||||
|
||||
- **原方法与路径**:`POST /v3/admin/order/{orderId}/settlement/reports/reimbursement/confirm`
|
||||
- **当前契约**:接口已删除,无有效请求体或成功响应。
|
||||
- **前端动作**:删除请求封装、按钮、loading、重试和错误忽略逻辑。
|
||||
|
||||
**请求示例**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000001/settlement/reports/reimbursement/confirm
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{}
|
||||
```
|
||||
|
||||
**响应示例**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 404,
|
||||
"message": "请求地址不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
### 3.5 已删除:确认单团核算表
|
||||
|
||||
- **原方法与路径**:`POST /v3/admin/order/{orderId}/settlement/reports/group/confirm`
|
||||
- **当前契约**:接口已删除,无有效请求体或成功响应。
|
||||
- **前端动作**:删除请求封装、按钮、loading、重试和错误忽略逻辑。
|
||||
|
||||
**请求示例**
|
||||
|
||||
```http
|
||||
POST /v3/admin/order/1914050000000001/settlement/reports/group/confirm
|
||||
Authorization: Bearer <admin-jwt>
|
||||
Content-Type: application/json
|
||||
|
||||
{}
|
||||
```
|
||||
|
||||
**响应示例**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 404,
|
||||
"message": "请求地址不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 接口入参汇总
|
||||
|
||||
| 接口 | 入参 |
|
||||
|------|------|
|
||||
| 主报账 GET | 路径参数 `orderId`;无请求体 |
|
||||
| 单团 GET | 路径参数 `orderId`;无请求体 |
|
||||
| finalize | 路径参数 `orderId`;请求体必须包含两个指纹及 `reimbursementConfirmation` |
|
||||
| 两个旧 confirm | 已删除,无有效入参 |
|
||||
|
||||
双指纹映射必须严格如下:
|
||||
|
||||
| 来源 | finalize 字段 |
|
||||
|------|---------------|
|
||||
| 主报账 GET 的 `data.sourceFingerprint` | `reimbursementExpectedSourceFingerprint` |
|
||||
| 单团 GET 的 `data.sourceFingerprint` | `groupExpectedSourceFingerprint` |
|
||||
|
||||
## 5. 出参汇总
|
||||
|
||||
- 两张 GET 均返回 `Result<报表对象>`,其中 `sourceFingerprint` 是 finalize 的提交凭据。
|
||||
- finalize 返回 `Result<SettlementSubmitRespVO>`,完整字段见 §3.3。
|
||||
- 两个旧 confirm 不再返回业务成功响应,只会命中不存在的路由。
|
||||
- 金额序列化以各字段表和示例为准:finalize 的金额字段为字符串,两张 GET 的金额字段为 JSON number。
|
||||
|
||||
## 6. 枚举 / 数据字典
|
||||
|
||||
### 6.1 `reportStatus`
|
||||
|
||||
**所属字段**:两张报表响应 `reportStatus` | **类型**:string
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|----|------|------|
|
||||
| `GENERATED` | 实时结果 | 当前不存在有效终态,按当前核单事实计算 |
|
||||
| `CONFIRMED` | 已固化 | 返回当前有效终态版本中的报表 |
|
||||
| `STALE` | 历史过期 | 兼容历史报表状态,不用于当前 finalize |
|
||||
|
||||
### 6.2 `transferDirection`
|
||||
|
||||
**所属字段**:主报账响应 `transferDirection` | **类型**:string
|
||||
|
||||
| 值 | 中文 | 说明 |
|
||||
|----|------|------|
|
||||
| `REPORTER_TO_COMPANY` | 报账人转公司 | `reporterNetAmount > 0` |
|
||||
| `COMPANY_TO_REPORTER` | 公司转报账人 | `reporterNetAmount < 0` |
|
||||
| `BALANCED` | 已平衡 | `reporterNetAmount = 0` |
|
||||
|
||||
### 6.3 `category`
|
||||
|
||||
**所属字段**:`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` | 尚未固化 | 实时报表可为空 |
|
||||
|
||||
`transferStatus` 只出现在响应中,不是 finalize 入参。
|
||||
|
||||
## 7. 错误码
|
||||
|
||||
| code | 含义 | 触发场景 |
|
||||
|------|------|----------|
|
||||
| `400` | 请求/参数校验失败 | `orderId <= 0`、缺请求体、非法 JSON、双指纹格式错误、缺 `reimbursementConfirmation`/`advanceSettledFlag`/`signedVoucher`、`remark` 超长 |
|
||||
| `403` | 无访问权限 | 房务角色或无权访问当前订单 |
|
||||
| `404` | 路由不存在 | 调用两个已删除的报表 confirm 接口 |
|
||||
| `584082` | 存在待收尾款 | 单团核算 `outstandingAmount != 0` |
|
||||
| `584100` | 车辆费用暂时不可用 | 报表查询或 finalize 当前无法取得可核单车辆费用 |
|
||||
| `584101` | 车辆事实未完成 | 存在未完结派车或未确认车辆费用 |
|
||||
| `584102` | 缺少车辆费用 | 有用车需求但没有可核单车辆费用 |
|
||||
| `584315` | 核单来源数据已变化 | 车辆候选与冻结事实不一致,或任一双指纹过期 |
|
||||
| `584316` | 并发或严格幂等冲突 | 终态重试请求不同、并发完成/反确认冲突 |
|
||||
| `584317` | 转账条件或签字凭证不合法 | 净额非 0 缺日期/流水、流水超长、files/文件项/url 无效、name/note 超长 |
|
||||
| `584320` | 核单明细未准备好 | 当前分类数据不能用于报账或 finalize |
|
||||
| `584321` | 缺少当前终态 | 后续财务复核缺少 current `FINALIZED` 终态 |
|
||||
| `584325` | 双指纹兜底校验失败 | finalize 发现双指纹不完整或不合法 |
|
||||
| `584326` | 终态组合不一致 | 当前终态、关联汇总或订单终态不匹配 |
|
||||
|
||||
## 8. 示例索引
|
||||
|
||||
| 场景 | 位置 |
|
||||
|------|------|
|
||||
| 主报账 GET 典型请求与响应 | §3.1 |
|
||||
| 单团 GET 典型请求与响应 | §3.2 |
|
||||
| finalize 净额非 0 典型成功 | §3.3 |
|
||||
| finalize 净额为 0 合法边界 | §3.3 |
|
||||
| finalize 凭证 URL 非法返回 584317 | §3.3 |
|
||||
| finalize 缺 `signedVoucher` 返回 400 | §3.3 |
|
||||
| 两个旧 confirm 返回 404 | §3.4、§3.5 |
|
||||
|
||||
## 9. 业务边界
|
||||
|
||||
- 必须先分别 GET 两张报表,再把两个 `sourceFingerprint` 一一映射到 finalize;不能复用旧指纹、互换字段或只传一个。
|
||||
- 任一核单事实变化后,旧双指纹都会失效;收到 `584315` 后必须重新 GET 两张表。
|
||||
- `outstandingAmount` 必须为 `0` 才能 finalize。
|
||||
- `reporterNetAmount != 0` 时,`transferDate` 和非空 `transferRef` 同时必填;净额为 `0` 时二者可为 `null`。
|
||||
- `advanceSettledFlag=false` 是有效业务值,不等同于缺失。
|
||||
- `signedVoucher` 始终必填,且 `files` 必须有 1~9 个合法文件项。
|
||||
- 完全相同请求重试严格幂等;任何双指纹、规范化凭据或 `remark` 差异均返回 `584316`。
|
||||
- 管理员反确认使当前终态失效后,两张 GET 重新返回实时结果;再次 finalize 必须使用新双指纹,成功响应的 `finalSnapshotVersionNo` 为上一版本 + 1。
|
||||
- finalize 成功后订单进入“待财务复核”。既有财务复核接口 `POST /v3/admin/order/{orderId}/settlement/confirm` 的请求/响应结构未在本次变更:请求仅含可选 `confirmRemark`;当前没有独立财务角色校验;成功 `data` 为 `orderId`、`settlementStatus=COMPLETED`、`settledAt`、`flowStatus=SETTLED`。其复核前提为当前有效 `FINALIZED` 终态及其关联汇总,旧报表 confirm 状态不参与判断。
|
||||
|
||||
## 10. 修改前后对比
|
||||
|
||||
### 10.1 字段级对比
|
||||
|
||||
| 接口/字段 | 修改前或错误说明 | 当前正确契约 |
|
||||
|-----------|------------------|--------------|
|
||||
| finalize 双指纹 | #5342 通知误写为删除 | 两个字段均必填 |
|
||||
| `reimbursementExpectedSourceFingerprint` | 误写为不再回传 | 来自主报账 GET 的 `sourceFingerprint` |
|
||||
| `groupExpectedSourceFingerprint` | 误写为不再回传 | 来自单团 GET 的 `sourceFingerprint` |
|
||||
| `reimbursementConfirmation` | #5342 把内部字段错误提升到 finalize 顶层 | 必填嵌套对象 |
|
||||
| `transferDate` | 误写为 finalize 顶层 | 位于 `reimbursementConfirmation` |
|
||||
| `transferRef` | 误写为 finalize 顶层 | 位于 `reimbursementConfirmation`,trim 后最长 128 |
|
||||
| `advanceSettledFlag` | 误写为 finalize 顶层 | 位于 `reimbursementConfirmation`,必填 boolean |
|
||||
| `signedVoucher` | 误写为 finalize 顶层 | 位于 `reimbursementConfirmation`,必填 object |
|
||||
| `transferStatus` | 可能沿用旧 confirm 传值 | finalize 不接收,成功后固定为 `COMPLETED` |
|
||||
|
||||
### 10.2 行为级对比
|
||||
|
||||
| 行为 | 修改前 | 当前 |
|
||||
|------|--------|------|
|
||||
| 主报账确认 | 独立 POST confirm | 接口删除,由 finalize 一次完成 |
|
||||
| 单团确认 | 独立 POST confirm | 接口删除,由 finalize 一次完成 |
|
||||
| finalize 前的数据校验 | 分散在两个 confirm | 两张 GET 取双指纹,finalize 一次校验 |
|
||||
| 重复 finalize | 旧流程语义不明确 | 完全相同返回原结果,任一差异返回 `584316` |
|
||||
| 反确认后再次核单 | 可能沿用旧报表结果 | 重新 GET 新指纹,再 finalize 生成版本号 + 1 |
|
||||
|
||||
## 11. 影响评估 / 回滚
|
||||
|
||||
### 11.1 影响评估
|
||||
|
||||
- **是否破坏向后兼容**:是。两个 POST confirm 已删除,finalize 的双指纹及嵌套凭据均为必填。
|
||||
- **前端是否必须同步上线**:是。按 #5342 错误契约提交会因缺双指纹或缺 `reimbursementConfirmation` 返回 `400`/业务错误。
|
||||
- **查询兼容性**:两张 GET 的字段结构保持,`sourceFingerprint` 的用途明确为 finalize 必填凭据。
|
||||
|
||||
### 11.2 回滚说明
|
||||
|
||||
- 前后端必须使用同一版核单流程;不能混用“独立 confirm”和“finalize 双指纹”两套调用顺序。
|
||||
- 若后端契约回滚,前端也需同步恢复对应请求模型与调用链,不能只单独回滚一端。
|
||||
|
||||
## 12. 注意事项
|
||||
|
||||
- 删除两个报表确认按钮及对应请求、loading、重试、错误忽略代码。
|
||||
- 保留两个 GET 返回的 `sourceFingerprint`,并在点击完成核单前保存当前两份值。
|
||||
- finalize 请求模型必须新增必填 `reimbursementConfirmation`,其余凭据字段不得放在顶层。
|
||||
- 不要发送 `transferStatus`;页面在 finalize 成功后按响应/重新 GET 展示终态。
|
||||
- 不要继续沿用 #5342 通知中的“删除双指纹”“finalize 顶层凭据字段”实现。
|
||||
- 对 `584315` 进行刷新两张报表后重试;对 `584316` 不要静默覆盖终态。
|
||||
|
||||
## 13. 关联 / 联系人
|
||||
|
||||
### 13.1 链接
|
||||
|
||||
- **Issue**: [#5343](https://git.1814.love:8443/wx/HL/issues/5343)
|
||||
- **PR**: [#5347](https://git.1814.love:8443/wx/HL/pulls/5347)
|
||||
- **Merge commit**: [a892a6b56a](https://git.1814.love:8443/wx/HL/commit/a892a6b56a2c3c0c2e4e345156096ac1ac5750c0)
|
||||
|
||||
### 13.2 联系人
|
||||
|
||||
- **后端负责人**: @yst
|
||||
- **消费端**: v3 管理后台
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户