Pārlūkot izejas kodu

feat: 退款队列系统 - 待退款自动重试

- 新增 pending_refund 表及迁移(迁移77)
- WithdrawalService.audit() 审核通过时余额不足自动创建待退款记录
- RefundScheduledTasks 每5分钟执行,FIFO处理待退款队列,指数退避重试
- 新增 Admin API: /api/admin/commission/refunds/pending (列表+状态过滤+分页)
- 新增 Admin API: /api/admin/commission/refunds/summary (待退款总金额统计)
- 修复 TianpanDashboardVO 缺失 import
Xiaogang Liao 2 mēneši atpakaļ
vecāks
revīzija
da01bf1307

+ 28 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -5081,5 +5081,33 @@ try {
 
         // 迁移76: DanAssessmentResult添加structured_analysis字段(G3)
         ensureColumn("dan_assessment_results", "structured_analysis", "TEXT COMMENT '结构化分析JSON'");
+
+
+        // 迁移77: 创建 pending_refund 表(待退款记录)
+        try {
+            jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS pending_refund (" +
+                "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+                "user_id BIGINT NOT NULL COMMENT '用户ID', " +
+                "withdrawal_request_id BIGINT COMMENT '提现申请ID', " +
+                "amount INT NOT NULL COMMENT '退款金额(分)', " +
+                "attempt_count INT DEFAULT 0 COMMENT '当前尝试次数', " +
+                "max_attempts INT DEFAULT 10 COMMENT '最大重试次数', " +
+                "next_retry_time DATETIME COMMENT '下次重试时间', " +
+                "status VARCHAR(20) DEFAULT 'pending' COMMENT '状态: pending/processing/success/failed', " +
+                "failure_reason VARCHAR(500) COMMENT '失败原因', " +
+                "refunded_amount INT COMMENT '实际退款金额(分)', " +
+                "refunded_at DATETIME COMMENT '退款时间', " +
+                "remark VARCHAR(500) COMMENT '备注', " +
+                "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+                "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
+                "INDEX idx_user_id (user_id), " +
+                "INDEX idx_status (status), " +
+                "INDEX idx_next_retry (next_retry_time), " +
+                "INDEX idx_withdrawal_request (withdrawal_request_id)" +
+            ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='待退款记录表'");
+            log.info("已创建pending_refund表");
+        } catch (Exception e) {
+            log.warn("创建pending_refund表失败: {}", e.getMessage());
+        }
         }
 }

+ 21 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminCommissionController.java

@@ -2,13 +2,16 @@ package com.etotem.cfc.controller.admin;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.etotem.cfc.common.Result;
+import com.etotem.cfc.entity.PendingRefund;
 import com.etotem.cfc.entity.Product;
 import com.etotem.cfc.entity.WithdrawalRequest;
 import com.etotem.cfc.mapper.ProductMapper;
+import com.etotem.cfc.service.PendingRefundService;
 import com.etotem.cfc.service.WithdrawalService;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import java.util.HashMap;
 import java.util.Map;
 
 @RestController
@@ -18,6 +21,9 @@ public class AdminCommissionController {
     @Resource
     private WithdrawalService withdrawalService;
 
+    @Resource
+    private PendingRefundService pendingRefundService;
+
     @Resource
     private ProductMapper productMapper;
 
@@ -71,4 +77,19 @@ public class AdminCommissionController {
         productMapper.updateById(product);
         return Result.success("设置成功");
     }
+
+    @PostMapping("/refunds/pending")
+    public Result<Page<PendingRefund>> pendingRefunds(@RequestBody Map<String, Object> params) {
+        String status = (String) params.get("status");
+        int page = params.get("page") != null ? ((Number) params.get("page")).intValue() : 1;
+        int size = params.get("size") != null ? ((Number) params.get("size")).intValue() : 20;
+        return Result.success(pendingRefundService.getAllPendingRefunds(status, page, size));
+    }
+
+    @PostMapping("/refunds/summary")
+    public Result<Map<String, Object>> refundSummary() {
+        Map<String, Object> summary = new HashMap<>();
+        summary.put("totalPendingAmount", pendingRefundService.getTotalPendingAmount());
+        return Result.success(summary);
+    }
 }

+ 1 - 0
cfc-backend/src/main/resources/schema.sql

@@ -2602,6 +2602,7 @@ CREATE TABLE IF NOT EXISTS schema_versions (
     applied_by VARCHAR(100)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='迁移版本追踪表';
 
+
 -- 待退款记录表
 CREATE TABLE IF NOT EXISTS pending_refund (
     id BIGINT AUTO_INCREMENT PRIMARY KEY,