版本: v1.0日期: 2026-04-08模块: gp104_escrow1. 背景与目标1.1 背景PayBy 决定退出 FAB 的 SVA（Stored Value Account）功能。退出前需将所有 SVA 卡上的余额清空（归零），确保 Pool Account 资金与卡余额一致归零后，完成业务退出。1.2 目标基于 FAB 提供的余额文件，与系统内余额进行比对核验在确认一致后，生成余额清空交易列表，逐笔报送 FAB处理因卡状态异常导致的报送失败，通过与 FAB 协调修复后重新报送最终实现所有卡余额清零，Pool Account 余额归零1.3 约束条件所有卡总余额 = Pool Account 余额（FAB 提供的文件需满足此等式）需要设定一个系统截止时间点（Cutoff Time），截止后不再接受新交易余额清空为不可逆操作，需经过 Operator 确认后方可执行2. 整体流程概览flowchart TD A[FAB 提供余额文件] --> B[Operator 通过 Counter 上传余额文件] B --> C[设定系统截止时间点 Cutoff Time] C --> D[系统生成内部余额快照] D --> E[余额比对: FAB文件 vs 系统快照] E --> F{比对结果} F -->|一致| G[生成汇总报告] F -->|不一致| H[生成差异明细报告] H --> I[Operator 审核差异] I -->|确认差异可接受| G I -->|需要调整| J[与 FAB 协调处理差异] J --> A G --> K[Operator 确认提交] K --> L[生成余额清空交易列表] L --> M[逐批报送 FAB] M --> N{报送结果} N -->|全部成功| O[余额清空完成] N -->|部分失败| P[生成失败卡列表] P --> Q[发送失败列表给 FAB 修改卡状态] Q --> R[FAB 修复卡状态] R --> M O --> S[Pool Account 余额归零确认]3. 详细流程设计3.1 阶段一：余额文件上传与截止时间设定sequenceDiagram participant FAB as FAB Bank participant OP as Operator participant CT as Counter (UI) participant SYS as Escrow System participant UFS as UFS 文件服务 FAB->>OP: 提供余额文件(CSV) OP->>CT: 上传余额文件 + 设定截止时间 CT->>UFS: 存储余额文件 UFS-->>CT: 返回 fileTag CT->>SYS: 发起余额清空请求(fileTag + cutoffTime) SYS->>SYS: 创建清空批次记录(ClearingBatch) SYS->>SYS: 设定系统截止时间 SYS-->>CT: 返回批次号(clearingBatchId)FAB 余额文件格式（CSV）：字段说明示例CardID卡ID1234567890Balance卡余额(AED)150.00文件末尾包含汇总行：字段说明Total Cards卡总数Total Balance总余额(应等于 Pool Account 余额)3.2 阶段二：系统余额快照生成sequenceDiagram participant SYS as Escrow System participant DB as Database participant QRY as Query Service SYS->>SYS: 触发余额快照(cutoffTime) SYS->>DB: 查询所有活跃卡列表(t_issue_record + t_card_detail) DB-->>SYS: 卡列表(cardId, memberId) loop 分批处理(batch_size=200) SYS->>QRY: 查询会员账户余额(BASIC + RED_PACKET_SETTLE + OUTER_TRANSFER_SETTLE) QRY-->>SYS: 各账户类型余额 SYS->>SYS: 汇总每张卡的系统总余额 SYS->>DB: 存储余额快照明细(t_clearing_balance_detail) end SYS->>DB: 更新批次状态为 SNAPSHOT_DONE3.3 阶段三：余额比对sequenceDiagram participant SYS as Escrow System participant UFS as UFS 文件服务 participant DB as Database SYS->>UFS: 下载 FAB 余额文件 UFS-->>SYS: 文件内容 SYS->>SYS: 解析 CSV 文件 SYS->>DB: 读取系统余额快照 SYS->>SYS: 逐卡比对 Note over SYS: FAB余额 vs 系统余额(BASIC+RED_PACKET+TRANSFER) alt 完全匹配 SYS->>DB: 标记明细状态为 MATCHED else 金额不一致 SYS->>DB: 标记明细状态为 MISMATCHED, 记录差异金额 else FAB文件中有但系统无 SYS->>DB: 标记为 FAB_ONLY else 系统有但FAB文件无 SYS->>DB: 标记为 SYSTEM_ONLY end SYS->>SYS: 生成汇总信息 SYS->>DB: 更新批次状态为 RECONCILED, 存储汇总比对汇总信息：总卡数(FAB): 1500 总卡数(系统): 1500 匹配成功: 1485 金额不一致: 10 仅FAB存在: 3 仅系统存在: 2 FAB总余额: 500,000.00 AED 系统总余额: 500,000.00 AED 差异总额: 150.00 AED3.4 阶段四：确认与生成清空交易sequenceDiagram participant OP as Operator participant CT as Counter (UI) participant SYS as Escrow System participant DB as Database OP->>CT: 查看比对汇总和差异明细 OP->>CT: 确认提交(clearingBatchId) CT->>SYS: 提交确认请求 SYS->>DB: 查询所有余额>0的卡 loop 每张有余额的卡 SYS->>SYS: 创建扣减交易记录 Note over SYS: amount = 卡余额direction = negativeafterBalance = 0 SYS->>DB: 插入 t_clearing_transaction end SYS->>DB: 更新批次状态为 CONFIRMED SYS->>SYS: 生成清空交易汇总 SYS-->>CT: 返回交易列表汇总3.5 阶段五：交易报送 FABsequenceDiagram participant SYS as Escrow System participant DB as Database participant WAVE as Wave/FAB Channel participant FAB as FAB Bank SYS->>DB: 查询待报送交易(status=INIT) loop 分批报送(batch) SYS->>WAVE: 报送扣减交易 WAVE->>FAB: 发送交易请求 FAB-->>WAVE: 返回处理结果 WAVE-->>SYS: 报送结果 alt 成功 SYS->>DB: 更新交易状态为 SUCCESS else 失败(卡状态异常) SYS->>DB: 更新交易状态为 FAILED, 记录失败原因 end end SYS->>DB: 更新批次进度3.6 阶段六：失败重试流程flowchart TD A[报送完成, 存在失败记录] --> B[生成失败卡列表文件] B --> C[Operator 下载失败列表] C --> D[发送给 FAB 请求修复卡状态] D --> E[FAB 修复卡状态] E --> F[FAB 确认修复完成] F --> G[Operator 通过 Counter 触发重新报送] G --> H[系统重新报送失败交易] H --> I{全部成功?} I -->|是| J[本轮清空完成] I -->|否| B J --> K{所有交易完成?} K -->|是| L[余额清空全部完成] K -->|否| AsequenceDiagram participant OP as Operator participant CT as Counter (UI) participant SYS as Escrow System participant FAB as FAB Bank SYS->>SYS: 汇总失败交易列表 SYS->>SYS: 生成失败卡列表文件(CSV) OP->>CT: 下载失败列表 OP->>FAB: 邮件发送失败卡列表, 请求修复状态 FAB->>FAB: 修复卡状态(解冻/激活等) FAB->>OP: 确认修复完成 OP->>CT: 触发重新报送(clearingBatchId) CT->>SYS: 重试报送请求 SYS->>SYS: 查询 FAILED 状态交易 SYS->>FAB: 重新报送 FAB-->>SYS: 返回结果 alt 全部成功 SYS->>SYS: 更新批次状态为 COMPLETED else 仍有失败 SYS->>SYS: 更新失败记录, 等待下轮处理 end4. 状态机设计4.1 清空批次状态（ClearingBatch）stateDiagram-v2 [*] --> INIT: 创建批次 INIT --> SNAPSHOT_DONE: 余额快照完成 SNAPSHOT_DONE --> RECONCILED: 余额比对完成 RECONCILED --> CONFIRMED: Operator确认提交 CONFIRMED --> REPORTING: 开始报送 REPORTING --> PARTIALLY_DONE: 部分成功/部分失败 REPORTING --> COMPLETED: 全部报送成功 PARTIALLY_DONE --> REPORTING: 重新报送失败交易 PARTIALLY_DONE --> COMPLETED: 重试后全部成功 COMPLETED --> [*] INIT --> CANCELLED: 取消 SNAPSHOT_DONE --> CANCELLED: 取消 RECONCILED --> CANCELLED: 取消 CANCELLED --> [*]4.2 清空交易状态（ClearingTransaction）stateDiagram-v2 [*] --> INIT: 生成交易记录 INIT --> PROCESSING: 开始报送 PROCESSING --> SUCCESS: FAB返回成功 PROCESSING --> FAILED: FAB返回失败 FAILED --> PROCESSING: 重新报送 SUCCESS --> [*]4.3 余额比对明细状态（ClearingBalanceDetail）stateDiagram-v2 [*] --> PENDING: 快照生成 PENDING --> MATCHED: 比对一致 PENDING --> MISMATCHED: 金额不一致 PENDING --> FAB_ONLY: 仅FAB存在 PENDING --> SYSTEM_ONLY: 仅系统存在 MATCHED --> [*] MISMATCHED --> [*] FAB_ONLY --> [*] SYSTEM_ONLY --> [*]5. 数据库设计5.1 新增表t_clearing_batch（清空批次表）字段类型说明clearing_batch_idBIGINT AUTO_INCREMENT主键batch_noVARCHAR(64)批次号(唯一)bank_codeVARCHAR(16)银行编码: FABcutoff_timeDATETIME系统截止时间fab_file_tagVARCHAR(256)FAB余额文件 UFS fileTagfab_total_cardsINTFAB文件卡总数fab_total_balanceDECIMAL(18,2)FAB文件总余额sys_total_cardsINT系统卡总数sys_total_balanceDECIMAL(18,2)系统总余额matched_countINT匹配成功数mismatched_countINT不匹配数fab_only_countINT仅FAB存在数sys_only_countINT仅系统存在数diff_amountDECIMAL(18,2)差异总额total_transactionsINT总交易数success_countINT报送成功数failed_countINT报送失败数statusVARCHAR(20)批次状态operatorVARCHAR(64)操作人memoVARCHAR(512)备注gmt_createDATETIME创建时间gmt_modifiedDATETIME修改时间t_clearing_balance_detail（余额比对明细表）字段类型说明detail_idBIGINT AUTO_INCREMENT主键clearing_batch_idBIGINT批次IDcard_idVARCHAR(64)卡IDmember_idVARCHAR(64)会员IDfab_balanceDECIMAL(18,2)FAB文件中余额sys_basic_balanceDECIMAL(18,2)系统BASIC账户余额sys_red_packet_balanceDECIMAL(18,2)系统RED_PACKET_SETTLE余额sys_transfer_balanceDECIMAL(18,2)系统OUTER_TRANSFER_SETTLE余额sys_total_balanceDECIMAL(18,2)系统汇总余额diff_amountDECIMAL(18,2)差异金额currencyVARCHAR(8)币种: AEDstatusVARCHAR(20)比对状态: PENDING/MATCHED/MISMATCHED/FAB_ONLY/SYSTEM_ONLYmemoVARCHAR(512)备注gmt_createDATETIME创建时间gmt_modifiedDATETIME修改时间t_clearing_transaction（清空交易表）字段类型说明transaction_idBIGINT AUTO_INCREMENT主键clearing_batch_idBIGINT批次IDcard_idVARCHAR(64)卡IDmember_idVARCHAR(64)会员IDamountDECIMAL(18,2)扣减金额currencyVARCHAR(8)币种: AEDdirectionVARCHAR(16)方向: negativebefore_balanceDECIMAL(18,2)扣减前余额after_balanceDECIMAL(18,2)扣减后余额(应为0)report_statusVARCHAR(16)报送状态: INIT/PROCESSING/SUCCESS/FAILEDfail_reasonVARCHAR(512)失败原因fail_countINT DEFAULT 0失败次数fab_response_codeVARCHAR(32)FAB响应码fab_response_msgVARCHAR(512)FAB响应信息report_timeDATETIME报送时间report_success_timeDATETIME报送成功时间memoVARCHAR(512)备注gmt_createDATETIME创建时间gmt_modifiedDATETIME修改时间5.2 索引设计-- t_clearing_batch CREATE UNIQUE INDEX uk_batch_no ON t_clearing_batch(batch_no); CREATE INDEX idx_status ON t_clearing_batch(status); -- t_clearing_balance_detail CREATE INDEX idx_batch_id ON t_clearing_balance_detail(clearing_batch_id); CREATE INDEX idx_card_id ON t_clearing_balance_detail(card_id); CREATE INDEX idx_status ON t_clearing_balance_detail(clearing_batch_id, status); -- t_clearing_transaction CREATE INDEX idx_batch_id ON t_clearing_transaction(clearing_batch_id); CREATE INDEX idx_card_id ON t_clearing_transaction(card_id); CREATE INDEX idx_report_status ON t_clearing_transaction(clearing_batch_id, report_status); CREATE INDEX idx_member_id ON t_clearing_transaction(member_id);6. 接口设计6.1 CounterFacade 新增接口/** * 余额清空 - 创建清空批次(上传文件+设定截止时间) */ CommonResponse clearingBatchCreate(ClearingBatchCreateRequest request); /** * 余额清空 - 查询批次详情 */ ClearingBatchDetailResponse clearingBatchDetail(ClearingBatchDetailRequest request); /** * 余额清空 - 查询比对明细列表(分页) */ ClearingBalanceDetailListResponse clearingBalanceDetailList(ClearingBalanceDetailListRequest request); /** * 余额清空 - 查询清空交易列表(分页) */ ClearingTransactionListResponse clearingTransactionList(ClearingTransactionListRequest request); /** * 余额清空 - Operator确认提交 */ CommonResponse clearingBatchConfirm(ClearingBatchConfirmRequest request); /** * 余额清空 - 触发报送/重新报送 */ CommonResponse clearingBatchReport(ClearingBatchReportRequest request); /** * 余额清空 - 导出失败卡列表 */ ExportFailedCardsResponse clearingExportFailedCards(ClearingExportFailedCardsRequest request);6.2 请求/响应模型// 创建清空批次请求 public class ClearingBatchCreateRequest { private String fabFileTag; // FAB余额文件 UFS fileTag private Date cutoffTime; // 系统截止时间 private String operator; // 操作人 private String memo; // 备注 } // 批次详情响应 public class ClearingBatchDetailResponse extends CommonResponse { private String batchNo; private String status; private Date cutoffTime; // 比对汇总 private Integer fabTotalCards; private BigDecimal fabTotalBalance; private Integer sysTotalCards; private BigDecimal sysTotalBalance; private Integer matchedCount; private Integer mismatchedCount; private BigDecimal diffAmount; // 报送进度 private Integer totalTransactions; private Integer successCount; private Integer failedCount; } // 确认提交请求 public class ClearingBatchConfirmRequest { private Long clearingBatchId; private String operator; } // 触发报送请求 public class ClearingBatchReportRequest { private Long clearingBatchId; private Boolean retryFailedOnly; // true=仅重试失败的, false=全量报送 private String operator; } // 导出失败卡列表响应 public class ExportFailedCardsResponse extends CommonResponse { private String fileUrl; // 失败卡列表文件下载URL private Integer failedCount; }7. 系统模块变更7.1 模块变更总览graph LR subgraph "service/facade" A1[CounterFacade+7个新接口] A2[新增 Request/Response] A3[新增 ClearingStatus 枚举] end subgraph "ext/service" B1[CounterFacadeImpl新增实现] B2[ClearingProcessor核心处理器] B3[ClearingReportTaskHandler报送任务处理] end subgraph "domainservice" C1[ClearingBatchService] C2[ClearingBalanceDetailService] C3[ClearingTransactionService] end subgraph "core/dal" D1[t_clearing_batch] D2[t_clearing_balance_detail] D3[t_clearing_transaction] D4[对应 DO/Mapper/XML] end subgraph "core/domain" E1[ClearingBatchDomain] E2[ClearingBalanceDetailDomain] E3[ClearingTransactionDomain] end subgraph "core/common" F1[ClearingBatchStatus 枚举] F2[ClearingTransactionStatus 枚举] F3[ClearingBalanceStatus 枚举] end subgraph "ext/integration" G1[复用 Wave/FAB Channel] G2[复用 QueryClient] G3[复用 UfsServiceClient] end A1 --> B1 B1 --> B2 B2 --> C1 B2 --> C2 B2 --> C3 B2 --> G1 B2 --> G2 B2 --> G3 C1 --> D1 C2 --> D2 C3 --> D37.2 各模块详细变更模块变更类型具体内容service/facade新增ClearingBatchCreateRequest, ClearingBatchDetailRequest/Response, ClearingBalanceDetailListRequest/Response, ClearingTransactionListRequest/Response, ClearingBatchConfirmRequest, ClearingBatchReportRequest, ClearingExportFailedCardsRequest/Responseservice/facade修改CounterFacade 新增 7 个接口方法service/facade新增ClearingBatchStatusEnum, ClearingTransactionStatusEnum, ClearingBalanceStatusEnumext/service修改CounterFacadeImpl 新增接口实现ext/service新增ClearingProcessor - 余额清空核心处理器ext/service新增ClearingReportTaskHandler - 报送任务异步处理ext/service新增ClearingFileParser - FAB 余额文件解析ext/service新增ClearingConvert - 对象转换器domainservice新增ClearingBatchService / ClearingBalanceDetailService / ClearingTransactionServicedomainservice新增对应 Repository 实现core/domain新增ClearingBatchDomain, ClearingBalanceDetailDomain, ClearingTransactionDomaincore/dal新增3 张表对应的 DO、Mapper 接口、MyBatis XML 映射文件core/common新增状态枚举类ext/integration复用FabWaveChannelImpl, QueryClient, UfsServiceClient8. 操作流程（SOP）8.1 完整操作流程flowchart TD subgraph "Phase 1: 准备" P1[1. 与 FAB 协调确定退出日期和截止时间] P2[2. FAB 导出全量卡余额文件] P3[3. FAB 邮件发送余额文件给 Operator] P1 --> P2 --> P3 end subgraph "Phase 2: 上传与比对" U1[4. Operator 登录 Counter 系统] U2[5. 进入'余额清空'功能页面] U3[6. 上传 FAB 余额文件] U4[7. 设定截止时间 Cutoff Time] U5[8. 点击'创建批次'按钮] U6[9. 系统自动执行:- 生成余额快照- 执行余额比对- 生成汇总报告] U7[10. Operator 查看比对汇总] U8[11. Operator 查看差异明细] U1 --> U2 --> U3 --> U4 --> U5 --> U6 --> U7 --> U8 end subgraph "Phase 3: 确认与报送" C1[12. Operator 确认比对结果, 点击'确认提交'] C2[13. 系统生成清空交易列表] C3[14. Operator 查看交易列表] C4[15. 点击'开始报送'] C5[16. 系统逐批报送至 FAB] C6[17. 查看报送进度] C1 --> C2 --> C3 --> C4 --> C5 --> C6 end subgraph "Phase 4: 失败处理" F1[18. 查看报送结果] F2{全部成功?} F3[19. 导出失败卡列表] F4[20. 邮件发送失败列表给 FAB] F5[21. FAB 修复卡状态后回复确认] F6[22. Operator 点击'重新报送'] F7[23. 完成! 确认 Pool Account 余额归零] F1 --> F2 F2 -->|否| F3 --> F4 --> F5 --> F6 --> F1 F2 -->|是| F7 end P3 --> U1 U8 --> C1 C6 --> F18.2 Counter UI 页面设计页面 1：余额清空 - 创建批次+----------------------------------------------------------+ | 余额清空管理 | +----------------------------------------------------------+ | FAB 余额文件: [选择文件...] balance_20260408.csv | | 截止时间: [2026-04-08 23:59:59] | | 备注: [SVA退出余额清空] | | | | [创建批次] | +----------------------------------------------------------+页面 2：批次详情与比对汇总+----------------------------------------------------------+ | 批次号: CLR202604080001 状态: RECONCILED | +----------------------------------------------------------+ | 比对汇总 | | ┌──────────────┬──────────┬──────────┐ | | │ │ FAB文件 │ 系统快照 │ | | ├──────────────┼──────────┼──────────┤ | | │ 卡总数 │ 1,500 │ 1,500 │ | | │ 总余额(AED) │ 500,000 │ 500,000 │ | | └──────────────┴──────────┴──────────┘ | | | | 匹配: 1,485 | 不匹配: 10 | 仅FAB: 3 | 仅系统: 2 | | | | [查看差异明细] [确认提交] [取消] | +----------------------------------------------------------+页面 3：报送进度+----------------------------------------------------------+ | 批次号: CLR202604080001 状态: REPORTING | +----------------------------------------------------------+ | 报送进度 | | ████████████████░░░░ 80% (1200/1500) | | | | 成功: 1,180 | 失败: 20 | 待处理: 300 | | | | [查看失败列表] [导出失败列表] [重新报送] | +----------------------------------------------------------+9. 核心处理器伪代码9.1 ClearingProcessor@Component public class ClearingProcessor { /** 创建清空批次 */ public String createBatch(ClearingBatchCreateRequest request) { // 1. 校验：不能有正在进行中的批次 // 2. 生成批次号 CLR + yyyyMMdd + seq // 3. 存储批次记录(状态=INIT) // 4. 异步执行：余额快照 + 比对 asyncExecuteSnapshotAndReconcile(batchId, request); return batchNo; } /** 异步执行快照和比对 */ @Async public void asyncExecuteSnapshotAndReconcile(Long batchId, ClearingBatchCreateRequest request) { // Phase 1: 生成系统余额快照 generateSystemBalanceSnapshot(batchId, request.getCutoffTime()); // Phase 2: 解析 FAB 文件并比对 reconcileBalance(batchId, request.getFabFileTag()); } /** 生成系统余额快照 */ private void generateSystemBalanceSnapshot(Long batchId, Date cutoffTime) { // 1. 查询所有活跃卡(通过 t_issue_record + t_card_detail) // 2. 分批查询 Query 服务获取各账户类型余额 // 3. 汇总每张卡余额 = BASIC + RED_PACKET_SETTLE + OUTER_TRANSFER_SETTLE // 4. 批量存入 t_clearing_balance_detail(status=PENDING) // 5. 更新批次状态为 SNAPSHOT_DONE } /** 余额比对 */ private void reconcileBalance(Long batchId, String fabFileTag) { // 1. 下载并解析 FAB 余额文件 // 2. 构建 Map<cardId, fabBalance> // 3. 读取系统快照 Map<cardId, sysBalance> // 4. 逐卡比对，更新明细状态 // 5. 统计汇总信息，更新批次 // 6. 更新批次状态为 RECONCILED } /** Operator确认后生成清空交易 */ public void confirmAndGenerateTransactions(Long batchId) { // 1. 校验批次状态 == RECONCILED // 2. 查询所有余额 > 0 的明细 // 3. 为每张卡生成扣减交易(t_clearing_transaction) // - amount = 卡余额 // - direction = negative // - after_balance = 0 // - report_status = INIT // 4. 更新批次状态为 CONFIRMED } /** 报送交易至 FAB */ @Async public void reportTransactions(Long batchId, boolean retryFailedOnly) { // 1. 更新批次状态为 REPORTING // 2. 查询待报送交易 // retryFailedOnly ? status=FAILED : status=INIT // 3. 分批报送(复用 FabWaveChannelImpl) // 4. 逐笔更新报送结果 // 5. 汇总：若全部成功 -> COMPLETED，否则 -> PARTIALLY_DONE } /** 导出失败卡列表 */ public String exportFailedCards(Long batchId) { // 1. 查询 status=FAILED 的交易 // 2. 生成 CSV 文件(cardId, amount, failReason) // 3. 上传至 UFS // 4. 返回下载 URL } }10. 异常处理与边界情况10.1 异常处理策略异常场景处理方式FAB 文件格式错误解析失败，批次标记为 INIT，提示 Operator 重新上传系统余额查询超时重试3次，仍失败则批次标记为失败，需重新创建报送过程中网络中断已报送的记录保持状态不变，未报送的保持 INIT，可续传FAB 返回未知错误码标记为 FAILED，记录原始响应，人工介入处理重复报送同一笔交易使用幂等键(batchNo+cardId)防止重复扣减截止时间后有新交易入账系统截止后应阻止新交易，通过配置开关控制10.2 幂等性保证每笔清空交易使用 batchNo + cardId 作为幂等键报送前检查交易状态，已成功的不重复报送FAB 侧通过交易流水号去重10.3 数据一致性flowchart LR A[系统截止] --> B[快照时间 = 截止时间] B --> C[FAB文件时间 = 截止时间] C --> D[三方数据时间点一致] D --> E[比对结果可信]11. 配置项# 余额清空相关配置 escrow: clearing: # 报送批次大小 report-batch-size: 50 # 快照查询批次大小 snapshot-batch-size: 200 # 报送重试最大次数 max-retry-count: 5 # 报送间隔(ms)，避免FAB限流 report-interval: 200 # 临时文件路径 temp-file-path: /tmp/escrow/clearing # 是否启用截止时间交易阻断 cutoff-block-enabled: true12. 安全与审计所有操作需记录操作人和操作时间确认提交操作需要 Operator 权限验证批次创建和确认操作需记录审计日志FAB 余额文件下载后需验证文件完整性清空交易不可回滚，确认前需二次确认弹窗13. 测试方案测试类型测试内容单元测试文件解析、余额比对逻辑、状态转换集成测试完整流程：上传->比对->确认->报送场景测试FAB文件与系统完全匹配场景测试FAB文件与系统存在差异场景测试部分卡报送失败后重试场景测试全部卡报送失败后重试场景测试空文件/格式错误文件场景测试大批量卡(>10000)性能测试回归测试现有 Counter 功能不受影响14. 上线计划gantt title 余额清空功能上线计划 dateFormat YYYY-MM-DD section 开发 数据库DDL与DAL层 :d1, 2026-04-09, 3d Domain与DomainService :d2, after d1, 3d ClearingProcessor核心逻辑 :d3, after d2, 5d CounterFacade接口实现 :d4, after d3, 3d Counter前端页面开发 :d5, after d3, 5d section 测试 单元测试 :t1, after d4, 3d 集成测试 :t2, after d5, 4d UAT测试 :t3, after t2, 5d section 上线 预发布环境验证 :r1, after t3, 2d 生产环境发布 :r2, after r1, 1d 与FAB联调 :r3, after r2, 3d 正式执行余额清空 :milestone, after r3, 0d15. 风险评估风险影响缓解措施FAB 余额文件时间与系统截止时间不一致比对结果不可信与 FAB 明确约定同一时间点，双方确认后再执行大量卡状态异常导致报送失败清空进度缓慢提前与 FAB 沟通批量修复卡状态的 SLAFAB 接口限流报送速度受限配置合理的报送间隔和批次大小截止时间后仍有交易余额不一致系统配置开关，截止后阻断新交易长时间运行导致系统异常部分交易丢失支持断点续传，已成功的不重复处理