Răsfoiți Sursa

feat: 定时任务增加卡包补插逻辑

- 第二阶段查找已开票但 cardInformation 为空的 InvoiceDetail
- 对其补调 insertToCardPackage,解决重启/失败后未重试的问题

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline 2 zile în urmă
părinte
comite
db03b7d56b

+ 51 - 4
admin/src/main/java/com/kym/admin/jobs/InvoiceStatusJob.java

@@ -1,10 +1,12 @@
 package com.kym.admin.jobs;
 
 import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import com.kym.entity.admin.InvoiceDetail;
 import com.kym.entity.miniapp.ChargeOrder;
 import com.kym.entity.miniapp.Invoice;
 import com.kym.entity.wechat.InvoiceOrderDetail;
 import com.kym.huapiaoer.enums.InvoiceQueryType;
+import com.kym.service.admin.InvoiceDetailService;
 import com.kym.service.miniapp.ChargeOrderService;
 import com.kym.service.miniapp.HuapiaoerInvoiceService;
 import com.kym.service.miniapp.InvoiceService;
@@ -22,21 +24,25 @@ public class InvoiceStatusJob {
     private final InvoiceService invoiceService;
     private final ChargeOrderService chargeOrderService;
     private final HuapiaoerInvoiceService huapiaoerInvoiceService;
+    private final InvoiceDetailService invoiceDetailService;
 
     public InvoiceStatusJob(InvoiceService invoiceService, ChargeOrderService chargeOrderService,
-                            HuapiaoerInvoiceService huapiaoerInvoiceService) {
+                            HuapiaoerInvoiceService huapiaoerInvoiceService,
+                            InvoiceDetailService invoiceDetailService) {
         this.invoiceService = invoiceService;
         this.chargeOrderService = chargeOrderService;
         this.huapiaoerInvoiceService = huapiaoerInvoiceService;
+        this.invoiceDetailService = invoiceDetailService;
     }
 
     /**
-     * 每5分钟轮询航信查询开票结果,处理开票中的发票
+     * 每5分钟轮询航信查询开票结果,处理开票中的发票,并对已开票但未插卡包的发票补插
      */
     @Scheduled(cron = "0 */5 * * * ?")
     public void execute() {
         log.info("执行发票状态轮询任务...开始");
 
+        // 第一阶段:处理开票中的发票
         List<Invoice> invoiceList;
         try {
             DynamicDataSourceContextHolder.push("db-miniapp");
@@ -62,12 +68,10 @@ public class InvoiceStatusJob {
                     DynamicDataSourceContextHolder.poll();
                 }
 
-                // 如果开票时填写了邮箱,自动发送邮件
                 if (invoice.getEmail() != null && !invoice.getEmail().isBlank()) {
                     huapiaoerInvoiceService.sendInvoiceEmail(invoice.getApplyId(), InvoiceQueryType.BLUE.getCode(), invoice.getEmail());
                 }
 
-                // 插入微信卡包
                 huapiaoerInvoiceService.insertToCardPackage(invoice, result);
 
                 log.info("发票轮询处理成功, applyId:{}, invoiceCode:{}, invoiceNumber:{}",
@@ -76,7 +80,50 @@ public class InvoiceStatusJob {
                 log.error("发票轮询处理失败, applyId:{}", invoice.getApplyId(), e);
             }
         }
+
+        // 第二阶段:对已开票但 cardInformation 为空的发票补插卡包
+        retryCardInsertion();
+
         log.info("执行发票状态轮询任务...结束");
     }
 
+    private void retryCardInsertion() {
+        List<String> applyIds;
+        try {
+            DynamicDataSourceContextHolder.push("db-admin");
+            applyIds = invoiceDetailService.lambdaQuery()
+                    .eq(InvoiceDetail::getStatus, "ISSUED")
+                    .isNull(InvoiceDetail::getCardInformation)
+                    .select(InvoiceDetail::getApplyId)
+                    .list().stream().map(InvoiceDetail::getApplyId).toList();
+        } finally {
+            DynamicDataSourceContextHolder.poll();
+        }
+
+        if (applyIds.isEmpty()) {
+            return;
+        }
+
+        log.info("发现 {} 条已开票但未插卡包的发票,开始补插", applyIds.size());
+
+        for (String applyId : applyIds) {
+            try {
+                DynamicDataSourceContextHolder.push("db-miniapp");
+                var invoice = invoiceService.lambdaQuery().eq(Invoice::getApplyId, applyId).one();
+                DynamicDataSourceContextHolder.poll();
+
+                if (invoice == null) {
+                    log.warn("补插卡包: 找不到发票记录, applyId:{}", applyId);
+                    continue;
+                }
+
+                var result = huapiaoerInvoiceService.queryInvoiceResult(applyId, InvoiceQueryType.BLUE.getCode());
+                huapiaoerInvoiceService.insertToCardPackage(invoice, result);
+            } catch (Exception e) {
+                log.error("补插卡包失败, applyId:{}", applyId, e);
+                DynamicDataSourceContextHolder.poll();
+            }
+        }
+    }
+
 }