Selaa lähdekoodia

fix:修复一系列bug

wangzaijun 1 kuukausi sitten
vanhempi
commit
496f6cf127

+ 2 - 1
mo-daq/src/main/java/com/smppw/modaq/application/components/CustomTabulaTextStripper.java

@@ -78,8 +78,9 @@ public class CustomTabulaTextStripper extends TextStripper {
 
             float h = textPosition.getHeightDir();
 
+            // 必须是一个空格,否则SpreadsheetExtractionAlgorithm类的73行报错字符串chat获取时越界
             if (c.equals(NBSP)) { // replace non-breaking space for space
-                c = "";
+                c = " ";
             }
 
             // 文字没有旋转角度,并且水印字体大小没有包含当前文字时说明是正常文字

+ 49 - 20
mo-daq/src/main/java/com/smppw/modaq/application/components/ReportParseUtils.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
 import com.smppw.modaq.common.conts.Constants;
+import com.smppw.modaq.common.conts.EmailTypeConst;
 import com.smppw.modaq.common.enums.ReportParseStatus;
 import com.smppw.modaq.common.enums.ReportType;
 import com.smppw.modaq.common.exception.ReportParseException;
@@ -335,16 +336,18 @@ public final class ReportParseUtils {
         Pattern pat1 = Pattern.compile("(2\\d{3}).*([一二三四1234])季");  // 2023年XXX3季(度\报)
         Pattern pat2 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");  // 2023-12-31
         Pattern pat3 = Pattern.compile("(2\\d{3})年年度");  // 2023年年度
+        Pattern pat6 = Pattern.compile("(2\\d{3})年度");  // 2023年度
         Pattern pat4 = Pattern.compile("(\\d{4})年(\\d{1,2})月");  // 2023年12月
+        Pattern pat7 = Pattern.compile("(\\d{4})年_(\\d{1,2})月");  // 2023年_12月
         Pattern pat5 = Pattern.compile("(?<!\\d)\\d{4}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])(?!\\d)");  // 20231231
-        Pattern pat6 = Pattern.compile("(2\\d{3})年度");  // 2023年度
         // 创建Matcher对象
         Matcher matcher1 = pat1.matcher(string);
         Matcher matcher2 = pat2.matcher(string);
         Matcher matcher3 = pat3.matcher(string);
+        Matcher matcher6 = pat6.matcher(string);
         Matcher matcher4 = pat4.matcher(string);
+        Matcher matcher7 = pat7.matcher(string);
         Matcher matcher5 = pat5.matcher(string);
-        Matcher matcher6 = pat6.matcher(string);
         // 尝试匹配
         if (matcher1.find()) {
             String year = matcher1.group(1);
@@ -362,34 +365,60 @@ public final class ReportParseUtils {
             return matcher3.group(1) + "-12-31";
         } else if (matcher6.find()) {
             return matcher6.group(1) + "-12-31";
-        } else if (matcher4.find()) {
-            String year = matcher4.group(1);
-            String month = matcher4.group(2);
-            int lastDayOfMonth = getLastDayOfMonth(Integer.parseInt(year), Integer.parseInt(month));
-            return year + "-" + padZero(month) + "-" + padZero(lastDayOfMonth + "");
-        } else if (matcher5.find()) {
-            return matcher5.group();
         } else {
-            return null;
+            // 格式4和格式7优先,不满足时才用格式5,都不满足返回null
+            boolean m4 = matcher4.find();
+            boolean m7 = matcher7.find();
+            if (m4 || m7) {
+                String year;
+                String month;
+                if (m4) {
+                    year = matcher4.group(1);
+                    month = matcher4.group(2);
+                } else {
+                    year = matcher7.group(1);
+                    month = matcher7.group(2);
+                }
+                int lastDayOfMonth = getLastDayOfMonth(Integer.parseInt(year), Integer.parseInt(month));
+                return year + "-" + padZero(month) + "-" + padZero(lastDayOfMonth + "");
+            } else if (matcher5.find()) {
+                return matcher5.group();
+            } else {
+                return null;
+            }
         }
     }
 
     /**
      * 匹配报告类型,如“季度”、“年度”
      *
-     * @param string 输入字符串
+     * @param emailTYpe 邮件类型
+     * @param string    输入字符串
      * @return 匹配到的报告类型子字符串,如果没有匹配到则返回null
      */
-    public static ReportType matchReportType(String string) {
-        // 类型识别---先识别季度报告,没有季度再识别年度报告,最后识别月报
+    public static ReportType matchReportType(Integer emailTYpe, String string) {
+        if (emailTYpe == null) {
+            return null;
+        }
         ReportType reportType = null;
-        if (StrUtil.containsAny(string, ReportType.QUARTERLY.getPatterns())) {
-            reportType = ReportType.QUARTERLY;
-        } else if (StrUtil.containsAny(string, ReportType.ANNUALLY.getPatterns())) {
-            reportType = ReportType.ANNUALLY;
-        } else if (StrUtil.containsAny(string, ReportType.MONTHLY.getPatterns())) {
-            reportType = ReportType.MONTHLY;
-        } else if (StrUtil.containsAny(string, ReportType.LETTER.getPatterns())) {
+        if (Objects.equals(EmailTypeConst.REPORT_EMAIL_TYPE, emailTYpe)) {
+            // 类型识别---先识别季度报告,没有季度再识别年度报告,最后识别月报
+            Pattern pattern = Pattern.compile("(\\d{1,2})月");  // xxxx_xx月
+            Matcher matcher = pattern.matcher(string);
+            if (StrUtil.containsAny(string, ReportType.QUARTERLY.getPatterns())) {
+                reportType = ReportType.QUARTERLY;
+            } else if (StrUtil.containsAny(string, ReportType.ANNUALLY.getPatterns())) {
+                reportType = ReportType.ANNUALLY;
+            } else if (StrUtil.containsAny(string, ReportType.MONTHLY.getPatterns())) {
+                reportType = ReportType.MONTHLY;
+            } else if (matcher.find()) {
+                // 特殊的月报(当季度->年度->月度报告无法识别时,如果包含“\\d{1,2}月”就说明也是月报)
+                reportType = ReportType.MONTHLY;
+            }
+            return reportType;
+        }
+        //
+        if (StrUtil.containsAny(string, ReportType.LETTER.getPatterns())) {
             reportType = ReportType.LETTER;
         } else if (StrUtil.containsAny(string, ReportType.WEEKLY.getPatterns())) {
             reportType = ReportType.WEEKLY;

+ 2 - 0
mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/AbstractReportParser.java

@@ -2,6 +2,7 @@ package com.smppw.modaq.application.components.report.parser;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.exceptions.ExceptionUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ReflectUtil;
 import cn.hutool.core.util.StrUtil;
@@ -102,6 +103,7 @@ public abstract class AbstractReportParser<T extends ReportData> implements Repo
         } catch (ReportParseException e) {
             throw e;
         } catch (Exception e) {
+            this.logger.warn("报告{} 解析时有异常:{}", filename, ExceptionUtil.stacktraceToString(e));
             throw new ReportParseException(ReportParseStatus.NOT_A_FIXED_FORMAT, filename);
         }
     }

+ 30 - 21
mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/ai/AIMonthlyReportParser.java

@@ -1,15 +1,16 @@
 package com.smppw.modaq.application.components.report.parser.ai;
 
-import cn.hutool.core.collection.ListUtil;
-import com.smppw.modaq.application.components.ReportParseUtils;
+import cn.hutool.core.util.ObjUtil;
 import com.smppw.modaq.application.components.report.parser.ReportParserConstant;
 import com.smppw.modaq.common.enums.ReportParseStatus;
 import com.smppw.modaq.common.exception.ReportParseException;
-import com.smppw.modaq.domain.dto.report.*;
+import com.smppw.modaq.domain.dto.report.MonthlyReportData;
+import com.smppw.modaq.domain.dto.report.ReportBaseInfoDTO;
+import com.smppw.modaq.domain.dto.report.ReportFundInfoDTO;
+import com.smppw.modaq.domain.dto.report.ReportParserParams;
 import com.smppw.modaq.domain.mapper.EmailFieldMappingMapper;
 import org.springframework.stereotype.Component;
 
-import java.util.List;
 import java.util.Map;
 
 @Component(ReportParserConstant.PARSER_AI_MONTHLY)
@@ -25,29 +26,37 @@ public class AIMonthlyReportParser extends AbstractAIReportParser<MonthlyReportD
 
     @Override
     protected String prompt() {
-        return "识别文件中的基金概况、净值信息表格数据,要求准确识别金额等小数的位数,去掉金额单位、英文和多余的空格,结果用json返回";
+        return """
+                识别文件中的基金概况,并且解析文件中的联系人等信息,
+                要求准确识别金额等小数的位数,去掉金额单位、英文和多余的空格,结果用json返回
+                """;
     }
 
     @Override
-    @SuppressWarnings("unchecked")
     protected MonthlyReportData parseExtInfoAndSetData(ReportBaseInfoDTO reportInfo,
                                                        ReportFundInfoDTO fundInfo) throws ReportParseException {
-        List<ReportNetReportDTO> dtos = ListUtil.list(true);
-        for (Map.Entry<String, Object> entry : this.allInfoMap.entrySet()) {
-            Object netInfo = entry.getValue();
-            if (netInfo == null) {
-                continue;
-            }
-            Map<String, Object> netInfoMap = (Map<String, Object>) netInfo;
-            ReportNetReportDTO dto = this.buildDto(reportInfo.getFileId(), ReportNetReportDTO.class, netInfoMap);
-            if (dto == null) {
-                continue;
-            }
-            dto.setLevel(ReportParseUtils.matchFundLevel(entry.getKey()));
-            dtos.add(dto);
-        }
         MonthlyReportData reportData = new MonthlyReportData(reportInfo, fundInfo);
-        reportData.setNetReport(dtos);
+        Object contact = this.allInfoMap.get("联系人信息");
+        if (ObjUtil.isNotEmpty(contact)) {
+            // 有联系人就不要净值数据了
+            reportInfo.setWithContacts(true);
+        }
+        // AI 就不解析净值数据了
+//        List<ReportNetReportDTO> dtos = ListUtil.list(true);
+//        for (Map.Entry<String, Object> entry : this.allInfoMap.entrySet()) {
+//            Object netInfo = entry.getValue();
+//            if (netInfo == null) {
+//                continue;
+//            }
+//            Map<String, Object> netInfoMap = (Map<String, Object>) netInfo;
+//            ReportNetReportDTO dto = this.buildDto(reportInfo.getFileId(), ReportNetReportDTO.class, netInfoMap);
+//            if (dto == null) {
+//                continue;
+//            }
+//            dto.setLevel(ReportParseUtils.matchFundLevel(entry.getKey()));
+//            dtos.add(dto);
+//        }
+//        reportData.setNetReport(dtos);
         return reportData;
     }
 

+ 6 - 0
mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/ai/AIWeeklyReportParser.java

@@ -1,5 +1,6 @@
 package com.smppw.modaq.application.components.report.parser.ai;
 
+import cn.hutool.core.util.ObjUtil;
 import com.smppw.modaq.application.components.report.parser.ReportParserConstant;
 import com.smppw.modaq.common.exception.ReportParseException;
 import com.smppw.modaq.domain.dto.report.ReportBaseInfoDTO;
@@ -22,6 +23,7 @@ public class AIWeeklyReportParser extends AbstractAIReportParser<WeeklyReportDat
     protected String prompt() {
         return """
                 识别文件中的基金名称、基金编码、基金管理人和报告日期,
+                并且解析文件中的联系人等信息,
                 基金编码的正则表达式是`S[A-Z0-9]{5}`,
                 如果日期是区间段则取截止日期,如果无法识别就返回空字符串,结果用json返回
                 """;
@@ -35,6 +37,10 @@ public class AIWeeklyReportParser extends AbstractAIReportParser<WeeklyReportDat
     @Override
     protected WeeklyReportData parseExtInfoAndSetData(ReportBaseInfoDTO reportInfo,
                                                       ReportFundInfoDTO fundInfo) throws ReportParseException {
+        Object contact = this.allInfoMap.get("联系人信息");
+        if (ObjUtil.isNotEmpty(contact)) {
+            reportInfo.setWithContacts(true);
+        }
         return new WeeklyReportData(reportInfo, fundInfo);
     }
 

+ 9 - 9
mo-daq/src/main/java/com/smppw/modaq/application/task/ParseSchedulerTask.java

@@ -31,15 +31,15 @@ public class ParseSchedulerTask {
 
     @PostConstruct
     public void executeOnStartup() {
-//        try {
-//            // 定期报告从 我的文件夹.报告公告 文件夹获取邮件
-//            this.emailParseApiService.parseEmail(
-//                    DateUtil.parseDateTime("2025-04-30 10:02:00"),
-//                    DateUtil.parseDateTime("2025-04-30 10:35:00"),
-//                    ListUtil.of("其他文件夹/报告公告"), EmailTypeConst.REPORT_EMAIL_TYPES);
-//        } catch (Exception e) {
-//            logger.error(ExceptionUtil.getMessage(e));
-//        }
+        try {
+            // 定期报告从 我的文件夹.报告公告 文件夹获取邮件
+            this.emailParseApiService.parseEmail(
+                    DateUtil.parseDateTime("2025-05-09 19:21:00"),
+                    DateUtil.parseDateTime("2025-05-09 19:23:00"),
+                    ListUtil.of("其他文件夹/报告公告"), EmailTypeConst.REPORT_EMAIL_TYPES);
+        } catch (Exception e) {
+            logger.error(ExceptionUtil.getMessage(e));
+        }
     }
 
     /**

+ 10 - 4
mo-daq/src/main/java/com/smppw/modaq/application/util/EmailUtil.java

@@ -12,10 +12,9 @@ import jakarta.mail.Store;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @author mozuwen
@@ -241,6 +240,13 @@ public class EmailUtil {
                     return emailTypeEntry.getKey();
                 }
             }
+            if (Objects.equals(EmailTypeConst.REPORT_EMAIL_TYPE, emailTypeEntry.getKey())) {
+                Pattern pattern = Pattern.compile("(\\d{1,2})月");  // xxxx_xx月
+                Matcher matcher = pattern.matcher(subject);
+                if (matcher.find()) {
+                    return EmailTypeConst.REPORT_EMAIL_TYPE;
+                }
+            }
         }
         return EmailTypeConst.NAV_EMAIL_TYPE;
     }

+ 7 - 4
mo-daq/src/main/java/com/smppw/modaq/common/enums/ReportType.java

@@ -6,16 +6,19 @@ import lombok.Getter;
 public enum ReportType {
     // 最后识别的类型
     OTHER(-2, "其他报告", new String[]{"公告", "通知", "告知函", "意见征询函", "说明函",
-            "清算报告", "邀请函", "观点", "预警", "复核函", "提醒", "投研报告", "公示", "回顾"}),
+            "清算报告", "邀请函", "观点", "预警", "提醒", "投研报告", "公示", "回顾"}),
 
     LETTER(-1, "交易流水确认函", new String[]{"确认单", "确认函", "交易确认数据",
             "赎回确认", "申购确认", "分红确认", "确认表", "交易确认", "确认"}),
 
-    MONTHLY(0, "月", new String[]{"月", "月度报告", "月报"}),
+    /**
+     * 月报识别规则(单独的“月”字不绑定到月度报告中,防止影响其他报告)
+     */
+    MONTHLY(0, "月", new String[]{"月度报告", "月报", "月度"}),
 
-    QUARTERLY(1, "季", new String[]{"季", "季度报告", "季报", "季度"}),
+    QUARTERLY(1, "季", new String[]{"季度报告", "季报", "季度"}),
 
-    ANNUALLY(2, "年", new String[]{"年度", "年报"}),
+    ANNUALLY(2, "年", new String[]{"年度", "年报", "年度报告"}),
 
     WEEKLY(3, "周", new String[]{"周报", "周度报告", "周度", "周"}),
     ;

+ 52 - 28
mo-daq/src/main/java/com/smppw/modaq/domain/service/EmailParseService.java

@@ -100,13 +100,13 @@ public class EmailParseService {
         if (CollUtil.isEmpty(emailTypes)) {
             emailTypes = ListUtil.of(EmailTypeConst.REPORT_LETTER_EMAIL_TYPE);
         }
-        log.info("开始邮件解析 -> 邮箱信息:{},开始时间:{},结束时间:{}", mailboxInfoDTO, DateUtil.format(startDate,
-                DateConst.YYYY_MM_DD_HH_MM_SS), DateUtil.format(endDate, DateConst.YYYY_MM_DD_HH_MM_SS));
-        // 邮件类型配置
-        Map<Integer, List<String>> emailTypeMap = getEmailType();
+        if (log.isInfoEnabled()) {
+            log.info("开始邮件解析 -> 邮箱信息:{},开始时间:{},结束时间:{}", mailboxInfoDTO, DateUtil.format(startDate,
+                    DateConst.YYYY_MM_DD_HH_MM_SS), DateUtil.format(endDate, DateConst.YYYY_MM_DD_HH_MM_SS));
+        }
         Map<String, List<EmailContentInfoDTO>> emailContentMap;
         try {
-            emailContentMap = realEmail(mailboxInfoDTO, emailTypeMap, startDate, endDate, folderNames);
+            emailContentMap = realEmail(mailboxInfoDTO, startDate, endDate, folderNames);
         } catch (Exception e) {
             log.error("采集邮件失败 -> 邮箱配置信息:{},堆栈信息:{}", mailboxInfoDTO, ExceptionUtil.stacktraceToString(e));
             return;
@@ -149,13 +149,23 @@ public class EmailParseService {
             while (entryIterator.hasNext()) {
                 Map.Entry<EmailContentInfoDTO, List<EmailZipFileDTO>> entry = entryIterator.next();
                 EmailContentInfoDTO key = entry.getKey();
+                String emailTitle = key.getEmailTitle();
                 List<EmailZipFileDTO> dtos = entry.getValue();
 
                 List<Integer> types = ListUtil.list(false);
                 types.add(key.getEmailType());
                 if (CollUtil.isNotEmpty(dtos)) {
+                    Iterator<EmailZipFileDTO> iterator = dtos.iterator();
+                    while (iterator.hasNext()) {
+                        EmailZipFileDTO dto = iterator.next();
+                        String filename = dto.getFilename();
+                        if (filename != null && filename.contains("复核函")) {
+                            log.warn("邮件{} 附件中的压缩文件{} 是复核函,不用解析上传。", emailTitle, filename);
+                            iterator.remove();
+                        }
+                    }
                     List<Integer> list = dtos.stream().map(EmailZipFileDTO::getEmailType).distinct().toList();
-                    types.addAll(list);
+                    CollUtil.addAllIfNotContains(types, list);
                 }
 
                 boolean flag = false;
@@ -310,8 +320,7 @@ public class EmailParseService {
             for (EmailZipFileDTO zipFile : dtos) {
                 EmailFileInfoDO emailFile = saveEmailFileInfo(emailId, zipFile.getFilename(), zipFile.getFilepath());
                 // 解析并保存报告
-                ParseResult<ReportData> parseResult = this.parseReportAndHandleResult(emailFile.getId(), zipFile.getFilename(),
-                        zipFile.getFilepath(), zipFile.getEmailType(), emailFile.getAiFileId());
+                ParseResult<ReportData> parseResult = this.parseReportAndHandleResult(emailTitle, emailFile, zipFile);
                 dataList.add(parseResult);
             }
 
@@ -337,26 +346,31 @@ public class EmailParseService {
         }
     }
 
-    private ParseResult<ReportData> parseReportAndHandleResult(int fileId, String fileName,
-                                                               String filepath, Integer emailType, String aiFileId) {
+    private ParseResult<ReportData> parseReportAndHandleResult(String emailTitle, EmailFileInfoDO emailFileInfo, EmailZipFileDTO zipFile) {
+        Integer emailType = zipFile.getEmailType();
+        String fileName = zipFile.getFilename();
+        String filepath = zipFile.getFilepath();
         ParseResult<ReportData> result = new ParseResult<>();
         boolean reportFlag = emailType == null || !EmailTypeConst.SUPPORT_EMAIL_TYPES.contains(emailType);
         if (reportFlag || StrUtil.isBlank(fileName) || fileName.endsWith(".html")) {
             result.setStatus(ReportParseStatus.NOT_A_REPORT.getCode());
             result.setMsg(StrUtil.format(ReportParseStatus.NOT_A_REPORT.getMsg(), fileName));
+            log.error(result.getMsg());
             return result;
         }
-        Pattern pattern = Pattern.compile("[A-Z0-9]{6}");
-        Matcher matcher = pattern.matcher(fileName);
-        String registerNumber = null;
-        if (matcher.find()) {
-            registerNumber = matcher.group();
-        }
+        // 基金代码、备案编码
+        String registerNumber = ReportParseUtils.matchFundCode(fileName);
         // 类型识别---先识别季度报告,没有季度再识别年度报告,最后识别月报
-        ReportType reportType = ReportParseUtils.matchReportType(fileName);
+        ReportType reportType = ReportParseUtils.matchReportType(emailType, fileName);
         if (Objects.equals(EmailTypeConst.REPORT_LETTER_EMAIL_TYPE, emailType)) {
             reportType = ReportType.LETTER;
         }
+        if (reportType == null) {
+            reportType = ReportParseUtils.matchReportType(emailType, emailTitle);
+            if (log.isDebugEnabled()) {
+                log.debug("报告{} 根据邮件主题{} 重新识别的类型是:{}", fileName, emailTitle, reportType);
+            }
+        }
         // 解析器--根据文件后缀获取对应解析器,解析不了就用AI来解析
         ReportParserFileType fileType;
         String fileSuffix = StrUtil.subAfter(fileName, ".", true);
@@ -365,14 +379,18 @@ public class EmailParseService {
         if (fileType == null) {
             result.setStatus(ReportParseStatus.NO_SUPPORT_TEMPLATE.getCode());
             result.setMsg(StrUtil.format(ReportParseStatus.NO_SUPPORT_TEMPLATE.getMsg(), fileName));
+            log.error(result.getMsg());
             return result;
         }
         // 不是定期报告的判断逻辑放在不支持的格式下面
         if (reportType == null) {
             result.setStatus(ReportParseStatus.NOT_A_REPORT.getCode());
             result.setMsg(StrUtil.format(ReportParseStatus.NOT_A_REPORT.getMsg(), fileName));
+            log.error(result.getMsg());
             return result;
         }
+        Integer fileId = emailFileInfo.getId();
+        String aiFileId = emailFileInfo.getAiFileId();
         // 不支持解析的格式文件
         boolean notSupportFile = false;
         // 解析报告
@@ -395,7 +413,7 @@ public class EmailParseService {
                     }
                 } else {
                     if (log.isInfoEnabled()) {
-                        log.info("报告{} 是已经存在ai解析记录,上传过文件{},直接跳转到AI解析器进行解析", fileName, fileId);
+                        log.info("报告{} 是已经存在ai解析记录,上传过文件{},直接跳转到AI解析器进行解析", fileName, aiFileId);
                     }
                 }
             }
@@ -525,14 +543,21 @@ public class EmailParseService {
 
     public Map<Integer, List<String>> getEmailType() {
         Map<Integer, List<String>> emailTypeMap = MapUtil.newHashMap(3, true);
-        emailTypeMap.put(EmailTypeConst.REPORT_EMAIL_TYPE,
-                ListUtil.toList("月报", "月度报告", "季报", "季度报告", "年报", "年度报告"));
+        // 定期报告的类型判断
+        List<String> types = ListUtil.list(true);
+        CollUtil.addAll(types, ReportType.QUARTERLY.getPatterns());
+        CollUtil.addAll(types, ReportType.ANNUALLY.getPatterns());
+        CollUtil.addAll(types, ReportType.MONTHLY.getPatterns());
+        emailTypeMap.put(EmailTypeConst.REPORT_EMAIL_TYPE, types);
+        // 确认函
         emailTypeMap.put(EmailTypeConst.REPORT_LETTER_EMAIL_TYPE,
                 ListUtil.toList(ReportType.LETTER.getPatterns()));
-        emailTypeMap.put(EmailTypeConst.REPORT_OTHER_TYPE,
-                ListUtil.toList(ReportType.OTHER.getPatterns()));
+        // 周报
         emailTypeMap.put(EmailTypeConst.REPORT_WEEKLY_TYPE,
                 ListUtil.toList(ReportType.WEEKLY.getPatterns()));
+        // 其他
+        emailTypeMap.put(EmailTypeConst.REPORT_OTHER_TYPE,
+                ListUtil.toList(ReportType.OTHER.getPatterns()));
         return emailTypeMap;
     }
 
@@ -540,14 +565,12 @@ public class EmailParseService {
      * 读取邮件
      *
      * @param mailboxInfoDTO 邮箱配置信息
-     * @param emailTypeMap   邮件类型识别规则映射表
      * @param startDate      邮件起始日期
      * @param endDate        邮件截止日期(为null,将解析邮件日期小于等于startDate的当天邮件)
      * @return 读取到的邮件信息
      * @throws Exception 异常信息
      */
     private Map<String, List<EmailContentInfoDTO>> realEmail(MailboxInfoDTO mailboxInfoDTO,
-                                                             Map<Integer, List<String>> emailTypeMap,
                                                              Date startDate, Date endDate,
                                                              List<String> folderNames) throws Exception {
         if (CollUtil.isEmpty(folderNames)) {
@@ -568,7 +591,7 @@ public class EmailParseService {
 
             for (String folderName : folderNames) {
                 try {
-                    Map<String, List<EmailContentInfoDTO>> temp = this.getFolderEmail(mailboxInfoDTO, emailTypeMap,
+                    Map<String, List<EmailContentInfoDTO>> temp = this.getFolderEmail(mailboxInfoDTO,
                             startDate, endDate, store, folderName);
                     if (MapUtil.isNotEmpty(temp)) {
                         result.putAll(temp);
@@ -587,7 +610,6 @@ public class EmailParseService {
     }
 
     private Map<String, List<EmailContentInfoDTO>> getFolderEmail(MailboxInfoDTO mailboxInfoDTO,
-                                                                  Map<Integer, List<String>> emailTypeMap,
                                                                   Date startDate, Date endDate,
                                                                   Store store, String folderName) throws MessagingException {
         // 默认读取收件箱的邮件
@@ -622,12 +644,14 @@ public class EmailParseService {
                     continue;
                 }
                 senderEmail = getSenderEmail(message);
-                emailType = EmailUtil.getEmailTypeBySubject(emailTitle, emailTypeMap);
+                emailType = EmailUtil.getEmailTypeBySubject(emailTitle, this.getEmailType());
                 if (emailType == null) {
                     log.warn("{} 邮件不满足解析条件 -> 邮件主题:{},邮件日期:{}", folderName, emailTitle, emailDateStr);
                     continue;
                 }
-                log.info("{} 邮件{} 基本信息获取完成,开始下载附件!邮件日期:{}", folderName, emailTitle, emailDateStr);
+                if (log.isInfoEnabled()) {
+                    log.info("{} 邮件{} 基本信息获取完成,开始下载附件!邮件日期:{}", folderName, emailTitle, emailDateStr);
+                }
                 Object content = message.getContent();
 
                 if (content instanceof Multipart multipart) {

+ 4 - 4
mo-daq/src/main/resources/mapper/EmailFileInfoMapper.xml

@@ -241,7 +241,7 @@
                  join mo_report_base_info b on b.file_id = a.id and b.report_type = 'LETTER'
                  join mo_report_fund_transaction c on a.id = c.file_id and c.fund_name is not null
                  join mo_report_investor_info d on a.id = d.file_id and d.investor_name is not null
-        where a.file_name = #{filename}
+        where a.file_name = #{filename} and a.isvalid = 1
     </select>
 
     <select id="getAmacFilenameSuccessCount" resultType="int">
@@ -249,7 +249,7 @@
         from mo_email_file_info a
                  join mo_report_base_info b on b.file_id = a.id and b.report_type in ('MONTHLY', 'QUARTERLY', 'ANNUALLY')
                  join mo_report_fund_info c on a.id = c.file_id and (c.fund_name is not null or c.fund_code is not null)
-        where a.file_name = #{filename}
+        where a.file_name = #{filename} and a.isvalid = 1
     </select>
 
     <select id="getWeeklyFilenameSuccessCount" resultType="int">
@@ -257,13 +257,13 @@
         from mo_email_file_info a
                  join mo_report_base_info b on b.file_id = a.id and b.report_type = 'WEEKLY'
                  join mo_report_fund_info c on a.id = c.file_id and (c.fund_name is not null or c.fund_code is not null)
-        where a.file_name = #{filename}
+        where a.file_name = #{filename} and a.isvalid = 1
     </select>
 
     <select id="getOtherFilenameSuccessCount" resultType="int">
         select count(1)
         from mo_email_file_info a
                  join mo_report_base_info b on b.file_id = a.id and b.report_type = 'OTHER'
-        where a.file_name = #{filename}
+        where a.file_name = #{filename} and a.isvalid = 1
     </select>
 </mapper>

+ 3 - 3
mo-daq/src/test/java/com/smppw/modaq/MoDaqApplicationTests.java

@@ -37,9 +37,9 @@ public class MoDaqApplicationTests {
 
     @Test
     public void reportTest() {
-        MailboxInfoDTO emailInfoDTO = this.buildMailbox("*@simuwang.com", "**");
-        Date startDate = DateUtil.parse("2025-05-09 10:55:00", DateConst.YYYY_MM_DD_HH_MM_SS);
-        Date endDate = DateUtil.parse("2025-05-09 19:55:05", DateConst.YYYY_MM_DD_HH_MM_SS);
+        MailboxInfoDTO emailInfoDTO = this.buildMailbox("**@simuwang.com", "**");
+        Date startDate = DateUtil.parse("2025-05-10 15:40:00", DateConst.YYYY_MM_DD_HH_MM_SS);
+        Date endDate = DateUtil.parse("2025-05-10 17:59:00", DateConst.YYYY_MM_DD_HH_MM_SS);
         try {
             List<String> folderNames = ListUtil.list(false);
 //            folderNames.add("其他文件夹/报告公告");