浏览代码

feat:支持定期报告解析

wangzaijun 1 月之前
父节点
当前提交
1a66921b8a
共有 28 个文件被更改,包括 824 次插入374 次删除
  1. 166 163
      mo-daq/src/main/java/com/smppw/modaq/application/components/ReportParseUtils.java
  2. 0 13
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/ReportParserConstant.java
  3. 4 49
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/pdf/AbstractPDReportParser.java
  4. 136 0
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/pdf/PDAnnuallyReportParser.java
  5. 327 0
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/pdf/PDQuarterlyReportParser.java
  6. 0 39
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/pdf/PDWeeklyReportParser.java
  7. 2 2
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/AbstractReportWriter.java
  8. 14 0
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/AnnuallyReportWriter.java
  9. 4 4
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/LetterReportWriter.java
  10. 2 2
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/MonthlyReportWriter.java
  11. 62 0
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/QuarterlyReportWriter.java
  12. 4 6
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/ReportWriterConstant.java
  13. 0 25
      mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/WeeklyReportWriter.java
  14. 6 6
      mo-daq/src/main/java/com/smppw/modaq/common/enums/ReportParseStatus.java
  15. 0 50
      mo-daq/src/main/java/com/smppw/modaq/domain/dto/QuartzBean.java
  16. 3 8
      mo-daq/src/main/java/com/smppw/modaq/domain/dto/report/WeeklyReportData.java
  17. 41 0
      mo-daq/src/main/java/com/smppw/modaq/domain/dto/report/QuarterlyReportData.java
  18. 9 0
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportAssetAllocationMapper.java
  19. 1 1
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/ReportBaseInfoMapper.java
  20. 9 0
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportFinancialIndicatorMapper.java
  21. 1 1
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/ReportFundInfoMapper.java
  22. 1 1
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/ReportFundTransactionMapper.java
  23. 9 0
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportInvestmentIndustryMapper.java
  24. 1 1
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/ReportInvestorInfoMapper.java
  25. 9 0
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportNetReportMapper.java
  26. 9 0
      mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportShareChangeMapper.java
  27. 2 1
      mo-daq/src/main/java/com/smppw/modaq/domain/service/EmailParseService.java
  28. 2 2
      mo-daq/src/test/java/com/smppw/modaq/MoDaqApplicationTests.java

+ 166 - 163
mo-daq/src/main/java/com/smppw/modaq/application/components/ReportParseUtils.java

@@ -1,6 +1,7 @@
 package com.smppw.modaq.application.components;
 
 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.enums.ReportParseStatus;
@@ -18,143 +19,145 @@ import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;
 import java.io.IOException;
 import java.util.Calendar;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 
 public final class ReportParseUtils {
-//    /**
-//     * 行业配置的表格列名称
-//     */
-//    public static final List<String> INDUSTRY_COLUMN_NAMES = ListUtil.list(false);
-//    /**
-//     * 份额变动的表格列名称
-//     */
-//    public static final List<String> SHARE_CHANGE_COLUMN_NAMES = ListUtil.list(false);
-//    /**
-//     * 主要财务指标识别列名称
-//     */
-//    public static final List<String> FINANCIAL_INDICATORS_COLUMN_NAMES = ListUtil.list(false);
-//    /**
-//     * 资产配置明细和大类关系映射
-//     */
-//    public static final Map<String, String> ASSET_ALLOCATION_TYPE_MAPPER = MapUtil.newHashMap(32, true);
-//
-//    static {
-//        // 财务指标
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末基金净资产");
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末基金资产净值");
-//
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("报告期期末单位净值");
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末基金份额净值");
-//
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("本期利润");
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("本期已实现收益");
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末可供分配利润");
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末可供分配基金份额利润");
-//        FINANCIAL_INDICATORS_COLUMN_NAMES.add("基金份额累计净值增长率");
-//
-//        // 中国证监会行业标准
-//        INDUSTRY_COLUMN_NAMES.add("农、林、牧、渔业");
-//        INDUSTRY_COLUMN_NAMES.add("采矿业");
-//        INDUSTRY_COLUMN_NAMES.add("制造业");
-//        INDUSTRY_COLUMN_NAMES.add("电力、热力、燃气及水生产和供应业");
-//        INDUSTRY_COLUMN_NAMES.add("建筑业");
-//        INDUSTRY_COLUMN_NAMES.add("批发和零售业");
-//        INDUSTRY_COLUMN_NAMES.add("交通运输、仓储和邮政业");
-//        INDUSTRY_COLUMN_NAMES.add("住宿和餐饮业");
-//        INDUSTRY_COLUMN_NAMES.add("信息传输、软件和信息技术服务业");
-//        INDUSTRY_COLUMN_NAMES.add("金融业");
-//        INDUSTRY_COLUMN_NAMES.add("房地产业");
-//        INDUSTRY_COLUMN_NAMES.add("租赁和商务服务业");
-//        INDUSTRY_COLUMN_NAMES.add("科学研究和技术服务业");
-//        INDUSTRY_COLUMN_NAMES.add("水利、环境和公共设施管理业");
-//        INDUSTRY_COLUMN_NAMES.add("居民服务、修理和其他服务业");
-//        INDUSTRY_COLUMN_NAMES.add("教育");
-//        INDUSTRY_COLUMN_NAMES.add("卫生和社会工作");
-//        INDUSTRY_COLUMN_NAMES.add("文化、体育和娱乐业");
-//        INDUSTRY_COLUMN_NAMES.add("综合");
-//
-//        INDUSTRY_COLUMN_NAMES.add("港股通");
-//
-//        // 以下为国际标准
-//        INDUSTRY_COLUMN_NAMES.add("能源");
-//        INDUSTRY_COLUMN_NAMES.add("原材料");
-//        INDUSTRY_COLUMN_NAMES.add("材料");
-//        INDUSTRY_COLUMN_NAMES.add("工业");
-//        INDUSTRY_COLUMN_NAMES.add("可选消费品");
-//        INDUSTRY_COLUMN_NAMES.add("非日常生活消费品");
-//        INDUSTRY_COLUMN_NAMES.add("必须消费品");
-//        INDUSTRY_COLUMN_NAMES.add("日常消费品");
-//        INDUSTRY_COLUMN_NAMES.add("医疗保健");
-//        INDUSTRY_COLUMN_NAMES.add("金融");
-//        INDUSTRY_COLUMN_NAMES.add("信息技术");
-//        INDUSTRY_COLUMN_NAMES.add("通讯服务");
-//        INDUSTRY_COLUMN_NAMES.add("电信服务");
-//        INDUSTRY_COLUMN_NAMES.add("公用事业");
-//        INDUSTRY_COLUMN_NAMES.add("房地产");
-//
-//        // 份额变动表格识别列
-//        SHARE_CHANGE_COLUMN_NAMES.add("报告期期初基金份额总额");
-//        SHARE_CHANGE_COLUMN_NAMES.add("减:报告期期间基金总赎回份额");
-//        SHARE_CHANGE_COLUMN_NAMES.add("期末基金总份额/期末基金实缴总额");
-//        SHARE_CHANGE_COLUMN_NAMES.add("报告期期间基金拆分变动份额");
-//        SHARE_CHANGE_COLUMN_NAMES.add("报告期期间基金总申购份额");
-//
-//        // 资产配置
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("银行存款", "现金类资产");
-//        // 境内未上市、未挂牌公司股权投资
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("股权投资", "境内未上市、未挂牌公司股权投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:优先股", "境内未上市、未挂牌公司股权投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其他股权类投资", "境内未上市、未挂牌公司股权投资");
-//        // 上市公司定向增发投资
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("上市公司定向增发股票投资", "上市公司定向增发投资");
-//        // 新三板投资
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("新三板挂牌企业投资", "新三板投资");
-//        // 境内证券投资规模
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("结算备付金", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("存出保证金", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("股票投资", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("债券投资", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:银行间市场债券", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:利率债", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:信用债", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("资产支持证券", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("基金投资(公募基金)", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:货币基金", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("期货及衍生品交易保证金", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("买入返售金融资产", "境内证券投资规模");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其他证券类标的", "境内证券投资规模");
-//        // 资管计划投资
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("商业银行理财产品投资", "资管计划投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("信托计划投资", "资管计划投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("基金公司及其子公司资产管理计划投资", "资管计划投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("保险资产管理计划投资", "资管计划投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("证券公司及其子公司资产管理计划投资", "资管计划投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("期货公司及其子公司资产管理计划投资", "资管计划投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("私募基金产品投资", "资管计划投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("未在协会备案的合伙企业份额", "资管计划投资");
-//        // 另类投资
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("另类投资", "另类投资");
-//        // 境内债权类投资
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("银行委托贷款规模", "境内债权类投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("信托贷款", "境内债权类投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("应收账款投资", "境内债权类投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("各类受(收)益权投资", "境内债权类投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("票据(承兑汇票等)投资", "境内债权类投资");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其他债权投资", "境内债权类投资");
-//        // 境外投资
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("境外投资", "境外投资");
-//        // 其他资产
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其他资产", "其他资产");
-//        // 基金负债情况
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("债券回购总额", "基金负债情况");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("融资、融券总额", "基金负债情况");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:融券总额", "基金负债情况");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("银行借款总额", "基金负债情况");
-//        ASSET_ALLOCATION_TYPE_MAPPER.put("其他融资总额", "基金负债情况");
-//    }
+    /**
+     * 行业配置的表格列名称
+     */
+    public static final List<String> INDUSTRY_COLUMN_NAMES = ListUtil.list(false);
+    /**
+     * 份额变动的表格列名称
+     */
+    public static final List<String> SHARE_CHANGE_COLUMN_NAMES = ListUtil.list(false);
+    /**
+     * 主要财务指标识别列名称
+     */
+    public static final List<String> FINANCIAL_INDICATORS_COLUMN_NAMES = ListUtil.list(false);
+    /**
+     * 资产配置明细和大类关系映射
+     */
+    public static final Map<String, String> ASSET_ALLOCATION_TYPE_MAPPER = MapUtil.newHashMap(32, true);
+
+    static {
+        // 财务指标
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末基金净资产");
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末基金资产净值");
+
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("报告期期末单位净值");
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末基金份额净值");
+
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("本期利润");
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("本期已实现收益");
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末可供分配利润");
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("期末可供分配基金份额利润");
+        FINANCIAL_INDICATORS_COLUMN_NAMES.add("基金份额累计净值增长率");
+
+        // 中国证监会行业标准
+        INDUSTRY_COLUMN_NAMES.add("农、林、牧、渔业");
+        INDUSTRY_COLUMN_NAMES.add("采矿业");
+        INDUSTRY_COLUMN_NAMES.add("制造业");
+        INDUSTRY_COLUMN_NAMES.add("电力、热力、燃气及水生产和供应业");
+        INDUSTRY_COLUMN_NAMES.add("建筑业");
+        INDUSTRY_COLUMN_NAMES.add("批发和零售业");
+        INDUSTRY_COLUMN_NAMES.add("交通运输、仓储和邮政业");
+        INDUSTRY_COLUMN_NAMES.add("住宿和餐饮业");
+        INDUSTRY_COLUMN_NAMES.add("信息传输、软件和信息技术服务业");
+        INDUSTRY_COLUMN_NAMES.add("金融业");
+        INDUSTRY_COLUMN_NAMES.add("房地产业");
+        INDUSTRY_COLUMN_NAMES.add("租赁和商务服务业");
+        INDUSTRY_COLUMN_NAMES.add("科学研究和技术服务业");
+        INDUSTRY_COLUMN_NAMES.add("水利、环境和公共设施管理业");
+        INDUSTRY_COLUMN_NAMES.add("居民服务、修理和其他服务业");
+        INDUSTRY_COLUMN_NAMES.add("教育");
+        INDUSTRY_COLUMN_NAMES.add("卫生和社会工作");
+        INDUSTRY_COLUMN_NAMES.add("文化、体育和娱乐业");
+        INDUSTRY_COLUMN_NAMES.add("综合");
+
+        INDUSTRY_COLUMN_NAMES.add("港股通");
+
+        // 以下为国际标准
+        INDUSTRY_COLUMN_NAMES.add("能源");
+        INDUSTRY_COLUMN_NAMES.add("原材料");
+        INDUSTRY_COLUMN_NAMES.add("材料");
+        INDUSTRY_COLUMN_NAMES.add("工业");
+        INDUSTRY_COLUMN_NAMES.add("可选消费品");
+        INDUSTRY_COLUMN_NAMES.add("非日常生活消费品");
+        INDUSTRY_COLUMN_NAMES.add("必须消费品");
+        INDUSTRY_COLUMN_NAMES.add("日常消费品");
+        INDUSTRY_COLUMN_NAMES.add("医疗保健");
+        INDUSTRY_COLUMN_NAMES.add("金融");
+        INDUSTRY_COLUMN_NAMES.add("信息技术");
+        INDUSTRY_COLUMN_NAMES.add("通讯服务");
+        INDUSTRY_COLUMN_NAMES.add("电信服务");
+        INDUSTRY_COLUMN_NAMES.add("公用事业");
+        INDUSTRY_COLUMN_NAMES.add("房地产");
+
+        // 份额变动表格识别列
+        SHARE_CHANGE_COLUMN_NAMES.add("报告期期初基金份额总额");
+        SHARE_CHANGE_COLUMN_NAMES.add("减:报告期期间基金总赎回份额");
+        SHARE_CHANGE_COLUMN_NAMES.add("期末基金总份额/期末基金实缴总额");
+        SHARE_CHANGE_COLUMN_NAMES.add("报告期期间基金拆分变动份额");
+        SHARE_CHANGE_COLUMN_NAMES.add("报告期期间基金总申购份额");
+
+        // 资产配置
+        ASSET_ALLOCATION_TYPE_MAPPER.put("银行存款", "现金类资产");
+        // 境内未上市、未挂牌公司股权投资
+        ASSET_ALLOCATION_TYPE_MAPPER.put("股权投资", "境内未上市、未挂牌公司股权投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:优先股", "境内未上市、未挂牌公司股权投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其他股权类投资", "境内未上市、未挂牌公司股权投资");
+        // 上市公司定向增发投资
+        ASSET_ALLOCATION_TYPE_MAPPER.put("上市公司定向增发股票投资", "上市公司定向增发投资");
+        // 新三板投资
+        ASSET_ALLOCATION_TYPE_MAPPER.put("新三板挂牌企业投资", "新三板投资");
+        // 境内证券投资规模
+        ASSET_ALLOCATION_TYPE_MAPPER.put("结算备付金", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("存出保证金", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("股票投资", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("债券投资", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:银行间市场债券", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:利率债", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:信用债", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("资产支持证券", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("基金投资(公募基金)", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:货币基金", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("期货及衍生品交易保证金", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("买入返售金融资产", "境内证券投资规模");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其他证券类标的", "境内证券投资规模");
+        // 资管计划投资
+        ASSET_ALLOCATION_TYPE_MAPPER.put("商业银行理财产品投资", "资管计划投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("信托计划投资", "资管计划投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("基金公司及其子公司资产管理计划投资", "资管计划投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("保险资产管理计划投资", "资管计划投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("证券公司及其子公司资产管理计划投资", "资管计划投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("期货公司及其子公司资产管理计划投资", "资管计划投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("私募基金产品投资", "资管计划投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("未在协会备案的合伙企业份额", "资管计划投资");
+        // 另类投资
+        ASSET_ALLOCATION_TYPE_MAPPER.put("另类投资", "另类投资");
+        // 境内债权类投资
+        ASSET_ALLOCATION_TYPE_MAPPER.put("银行委托贷款规模", "境内债权类投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("信托贷款", "境内债权类投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("应收账款投资", "境内债权类投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("各类受(收)益权投资", "境内债权类投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("票据(承兑汇票等)投资", "境内债权类投资");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其他债权投资", "境内债权类投资");
+        // 境外投资
+        ASSET_ALLOCATION_TYPE_MAPPER.put("境外投资", "境外投资");
+        // 其他资产
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其他资产", "其他资产");
+        // 基金负债情况
+        ASSET_ALLOCATION_TYPE_MAPPER.put("债券回购总额", "基金负债情况");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("融资、融券总额", "基金负债情况");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其中:融券总额", "基金负债情况");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("银行借款总额", "基金负债情况");
+        ASSET_ALLOCATION_TYPE_MAPPER.put("其他融资总额", "基金负债情况");
+    }
 
     public static String cleaningValue(Object value) {
         return cleaningValue(value, true);
@@ -202,35 +205,35 @@ public final class ReportParseUtils {
         return StrUtil.isBlank(fieldValue) ? null : fieldValue;
     }
 
-//    /**
-//     * 匹配分级基金名称(并且把母基金追加到第一行)
-//     *
-//     * @param text 文本内容
-//     * @return /
-//     */
-//    public static List<String> matchTieredFund(String text) {
-//        List<String> matches = ListUtil.list(false);
-//        if (StrUtil.isBlank(text)) {
-//            matches.add("母基金");
-//            return matches;
-//        }
-//        // 使用正则表达式查找匹配项
-//        Pattern pattern = Pattern.compile("[A-F]级|基金[A-F]");
-//        Matcher matcher = pattern.matcher(text);
-//        // 收集所有匹配项
-//        while (matcher.find()) {
-//            matches.add(matcher.group());
-//        }
-//        // 提取字母并按字母顺序排序
-//        List<String> levels = matches.stream()
-//                .map(s -> s.replaceAll("[^A-F]", ""))
-//                .distinct()
-//                .sorted()
-//                .map(letter -> letter + "级")
-//                .collect(Collectors.toList());
-//        levels.add(0, "母基金");
-//        return levels;
-//    }
+    /**
+     * 匹配分级基金名称(并且把母基金追加到第一行)
+     *
+     * @param text 文本内容
+     * @return /
+     */
+    public static List<String> matchTieredFund(String text) {
+        List<String> matches = ListUtil.list(false);
+        if (StrUtil.isBlank(text)) {
+            matches.add("母基金");
+            return matches;
+        }
+        // 使用正则表达式查找匹配项
+        Pattern pattern = Pattern.compile("[A-F]级|基金[A-F]");
+        Matcher matcher = pattern.matcher(text);
+        // 收集所有匹配项
+        while (matcher.find()) {
+            matches.add(matcher.group());
+        }
+        // 提取字母并按字母顺序排序
+        List<String> levels = matches.stream()
+                .map(s -> s.replaceAll("[^A-F]", ""))
+                .distinct()
+                .sorted()
+                .map(letter -> letter + "级")
+                .collect(Collectors.toList());
+        levels.add(0, "母基金");
+        return levels;
+    }
 
     /**
      * 匹配报告日期
@@ -299,10 +302,10 @@ public final class ReportParseUtils {
 //        } else if (StrUtil.containsAny(string, ReportType.ANNUALLY.getPatterns())) {
 //            reportType = ReportType.ANNUALLY;
 //        } else
-       if (StrUtil.containsAny(string, ReportType.MONTHLY.getPatterns())) {
+        if (StrUtil.containsAny(string, ReportType.MONTHLY.getPatterns())) {
             reportType = ReportType.MONTHLY;
-        } else if (StrUtil.containsAny(string, ReportType.WEEKLY.getPatterns())) {
-            reportType = ReportType.WEEKLY;
+//        } else if (StrUtil.containsAny(string, ReportType.WEEKLY.getPatterns())) {
+//            reportType = ReportType.WEEKLY;
         } else if (StrUtil.containsAny(string, ReportType.LETTER.getPatterns())) {
             reportType = ReportType.LETTER;
         }

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

@@ -17,11 +17,6 @@ public final class ReportParserConstant {
     // 交易流水确认函解析
     public static final String PARSER_PDF_LETTER = "report-parser:pdf:letter";
 
-    public static final String PARSER_PDF_WEEKLY = "report-parser:pdf:weekly";
-    //    public static final String PARSER_WORD_WEEKLY = "report-parser:word:weekly";
-    public static final String PARSER_EXCEL_WEEKLY = "report-parser:excel:weekly";
-//    public static final String PARSER_PYTHON_WEEKLY = "report-parser:python:weekly";
-
     public static final String PARSER_PDF_MONTHLY = "report-parser:pdf:monthly";
     //    public static final String PARSER_WORD_MONTHLY = "report-parser:word:monthly";
     public static final String PARSER_EXCEL_MONTHLY = "report-parser:excel:monthly";
@@ -49,14 +44,6 @@ public final class ReportParserConstant {
 //                        ReportParserFileType.PYTHON, PARSER_PYTHON_MONTHLY
                 ));
 
-//        REPORT_PARSER_BEAN_MAP.put(ReportType.WEEKLY,
-//                Map.of(ReportParserFileType.PDF, PARSER_PDF_WEEKLY,
-////                        ReportParserFileType.WORD, PARSER_WORD_WEEKLY,
-//                        ReportParserFileType.EXCEL, PARSER_EXCEL_WEEKLY
-//
-////                        ReportParserFileType.PYTHON, PARSER_PYTHON_WEEKLY
-//                ));
-
         REPORT_PARSER_BEAN_MAP.put(ReportType.QUARTERLY,
                 Map.of(ReportParserFileType.PDF, PARSER_PDF_QUARTERLY,
 //                        ReportParserFileType.WORD, PARSER_WORD_QUARTERLY,

+ 4 - 49
mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/pdf/AbstractPDReportParser.java

@@ -11,6 +11,7 @@ import com.smppw.modaq.application.components.CustomPDFTextStripper;
 import com.smppw.modaq.application.components.report.parser.AbstractReportParser;
 import com.smppw.modaq.common.conts.Constants;
 import com.smppw.modaq.common.enums.ReportParseStatus;
+import com.smppw.modaq.common.enums.ReportType;
 import com.smppw.modaq.common.exception.ReportParseException;
 import com.smppw.modaq.domain.dto.report.ReportBaseInfoDTO;
 import com.smppw.modaq.domain.dto.report.ReportData;
@@ -77,12 +78,12 @@ public abstract class AbstractPDReportParser<T extends ReportData> extends Abstr
             SpreadsheetExtractionAlgorithm spreadsheetExtractionAlgorithm = new SpreadsheetExtractionAlgorithm();
             // 自定义表格提取工具,去除单元格中的水印文字
             PageIterator pageIterator = new CustomObjectExtractor(document).extract();
-            // 只解析第一页
+            // 确认单只解析第一页
             int i = 0;
             while (pageIterator.hasNext()) {
                 Page page = pageIterator.next();
                 List<Table> tableList = spreadsheetExtractionAlgorithm.extract(page);
-                if (i >= 1) {
+                if (i >= 1 && params.getReportType() == ReportType.LETTER) {
                     break;
                 }
                 Integer rows = tableList.stream().map(Table::getRowCount).filter(rowCount -> rowCount >= 1).reduce(0, Integer::sum);
@@ -93,7 +94,7 @@ public abstract class AbstractPDReportParser<T extends ReportData> extends Abstr
                             tables.add(table);
                         }
                     }
-                } else {
+                } else if (params.getReportType() == ReportType.LETTER) {
                     this.aiParse = true;
                     Map<String, Object> paramsMap = MapUtil.newHashMap(4);
                     paramsMap.put("filepath", filepath);
@@ -171,50 +172,4 @@ public abstract class AbstractPDReportParser<T extends ReportData> extends Abstr
         this.aiParserContent = null;
         this.aiParse = false;
     }
-
-//    /**
-//     * 构建只有两列表格的dto数据对象,如果有分级基金时(并且一个表格可能跨页)
-//     *
-//     * @param <DTO>    泛型对象
-//     * @param fileId   文件id
-//     * @param tables   表格
-//     * @param clazz    泛型对象
-//     * @param function 表格转换的函数
-//     * @return /
-//     */
-//    protected <DTO extends BaseReportLevelDTO<?>> List<DTO> buildLevelDto(Integer fileId, List<Table> tables, Class<DTO> clazz,
-//                                                                          Function<Table, Map<String, Object>> function) {
-//        List<DTO> dtos = ListUtil.list(true);
-//        // 信息表格字段和值映射
-//        List<Map<String, Object>> infos = ListUtil.list(true);
-//        Map<String, Object> infoMap = null;
-//        for (Table table : tables) {
-//            Map<String, Object> temp = function.apply(table);
-//            for (String key : temp.keySet()) {
-//                // 如果infoMap为null,先声明然后放在infos中
-//                if (infoMap == null) {
-//                    infoMap = MapUtil.newHashMap(16);
-//                    infos.add(infoMap);
-//                }
-//                // 如果infoMap中包含了该key时,先放infos中然后重新声明新map对象
-//                if (infoMap.containsKey(key)) {
-//                    infos.add(new HashMap<>(infoMap));
-//                    infoMap = MapUtil.newHashMap(16);
-//                } else {
-//                    infoMap.put(key, temp.get(key));
-//                }
-//            }
-//        }
-//        // 分级基金匹配
-//        List<String> levels = ReportParseUtils.matchTieredFund(String.join(",", this.textList));
-//        for (int i = 0; i < infos.size(); i++) {
-//            DTO dto = this.buildDto(fileId, clazz, infos.get(i));
-//            if (dto == null) {
-//                continue;
-//            }
-//            dto.setLevel(levels.get(i));
-//            dtos.add(dto);
-//        }
-//        return dtos;
-//    }
 }

+ 136 - 0
mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/pdf/PDAnnuallyReportParser.java

@@ -0,0 +1,136 @@
+package com.smppw.modaq.application.components.report.parser.pdf;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.map.MapUtil;
+import com.smppw.modaq.application.components.ReportParseUtils;
+import com.smppw.modaq.application.components.report.parser.ReportParserConstant;
+import com.smppw.modaq.domain.dto.report.*;
+import com.smppw.modaq.domain.mapper.EmailFieldMappingMapper;
+import org.springframework.stereotype.Component;
+import technology.tabula.Table;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+
+/**
+ * @author wangzaijun
+ * @date 2024/10/10 17:34
+ * @description 年报解析逻辑:基本信息被拆分为多个表格,财务报表未解析
+ */
+@Component(ReportParserConstant.PARSER_PDF_ANNUALLY)
+public class PDAnnuallyReportParser extends PDQuarterlyReportParser<AnnuallyReportData> {
+    private List<Table> fundInfoTables;
+
+    public PDAnnuallyReportParser(EmailFieldMappingMapper fieldMappingMapper) {
+        super(fieldMappingMapper);
+    }
+
+    @Override
+    public String getParser() {
+        return ReportParserConstant.PARSER_PDF_ANNUALLY;
+    }
+
+    @Override
+    protected void init() {
+        super.init();
+        this.fundInfoTables = ListUtil.list(true);
+    }
+
+    @Override
+    protected void initTableInfo(List<Table> tables) {
+        for (int i = 0; i < tables.size(); i++) {
+            Table table = tables.get(i);
+            if (i <= 1) {
+                this.fundInfoTables.add(table);
+                continue;
+            }
+            // 用表格的第一列的数据判断是否主要财务指标数据
+            List<String> texts = this.getTableColTexts(table, 0);
+            if (CollUtil.containsAny(texts, ReportParseUtils.FINANCIAL_INDICATORS_COLUMN_NAMES)) {
+                this.financialIndicatorsTables.add(table);
+                continue;
+            }
+            int colCount = table.getColCount();
+            if (colCount == 2) {
+                // 用表格的第一列的数据判断是否份额变动记录
+                if (CollUtil.containsAny(texts, ReportParseUtils.SHARE_CHANGE_COLUMN_NAMES)) {
+                    this.shareChangeTables.add(table);
+                }
+            } else if (colCount == 4) {
+                // 用表格的第二列的数据判断是否行业配置数据(内地)
+                texts = this.getTableColTexts(table, 1);
+                if (CollUtil.containsAny(texts, ReportParseUtils.INDUSTRY_COLUMN_NAMES)) {
+                    this.investmentIndustryTables.add(table);
+                }
+            } else if (colCount == 3) {
+                // 用表格的第一列的数据判断是否行业配置数据(港股通)
+                if (CollUtil.containsAny(texts, ReportParseUtils.INDUSTRY_COLUMN_NAMES)) {
+                    this.investmentIndustryTables.add(table);
+                    continue;
+                }
+                // 资产配置表格识别(兼容跨页的表格)获取表格中第二列的所有文字,判断所有文字中包含"股权投资"等字符串
+                texts = this.getTableColTexts(table, 1);
+                Set<String> keys = ReportParseUtils.ASSET_ALLOCATION_TYPE_MAPPER.keySet();
+                if (CollUtil.containsAny(texts, keys)) {
+                    this.assetAllocationTables.add(table);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected ReportFundInfoDTO buildFundInfo(ReportParserParams params) {
+        Map<String, Object> fundInfoMap = MapUtil.newHashMap(32);
+        for (Table table : this.fundInfoTables) {
+            Map<String, Object> temp = this.parseFundInfo(table);
+            fundInfoMap.putAll(temp);
+        }
+        ReportFundInfoDTO info = new ReportFundInfoDTO(params.getFileId());
+        this.buildInfo(fundInfoMap, info);
+        return info;
+    }
+
+    @Override
+    protected AnnuallyReportData buildReportData(ReportBaseInfoDTO reportInfo, ReportFundInfoDTO fundInfo,
+                                                 List<ReportShareChangeDTO> shareChanges, List<ReportFinancialIndicatorsDTO> financialIndicators,
+                                                 List<ReportAssetAllocationDTO> assetAllocations, List<ReportInvestmentIndustryDTO> investmentIndustries) {
+        AnnuallyReportData reportData = new AnnuallyReportData(reportInfo, fundInfo);
+        reportData.setShareChange(shareChanges);
+        reportData.setFinancialIndicators(financialIndicators);
+        reportData.setAssetAllocation(assetAllocations);
+        reportData.setInvestmentIndustry(investmentIndustries);
+        return reportData;
+    }
+
+    protected List<ReportFinancialIndicatorsDTO> buildFinancialIndicatorsInfo(Integer fileId, Function<Table, Map<String, Object>> function) {
+        List<ReportFinancialIndicatorsDTO> dtos = ListUtil.list(false);
+        // 分级基金
+        List<String> levels = ReportParseUtils.matchTieredFund(String.join(",", this.textList));
+        // 假设这里可能存在分级基金,不存在表格跨页
+        for (int k = 0; k < this.financialIndicatorsTables.size(); k++) {
+            Table table = this.financialIndicatorsTables.get(k);
+            int colCount = table.getColCount();
+            for (int j = 1; j < colCount; j++) {
+                Map<String, Object> infoMap = MapUtil.newHashMap(16);
+                String year = ReportParseUtils.cleaningValue(table.getCell(0, j).getText());
+                infoMap.put("年度", year);
+                for (int i = 0; i < table.getRowCount(); i++) {
+                    String columnName = ReportParseUtils.cleaningValue(table.getCell(i, 0).getText());
+                    if (columnName == null) {
+                        continue;
+                    }
+                    String value = ReportParseUtils.cleaningValue(table.getCell(i, j).getText());
+                    infoMap.put(columnName, value);
+                }
+                ReportFinancialIndicatorsDTO dto = new ReportFinancialIndicatorsDTO(fileId);
+                this.buildInfo(infoMap, dto);
+                dto.setLevel(levels.get(k));
+                dtos.add(dto);
+            }
+        }
+        return dtos;
+    }
+}

+ 327 - 0
mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/pdf/PDQuarterlyReportParser.java

@@ -0,0 +1,327 @@
+package com.smppw.modaq.application.components.report.parser.pdf;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
+import com.smppw.modaq.application.components.ReportParseUtils;
+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.mapper.EmailFieldMappingMapper;
+import org.springframework.stereotype.Component;
+import technology.tabula.RectangularTextContainer;
+import technology.tabula.Table;
+
+import java.awt.geom.Rectangle2D;
+import java.util.*;
+import java.util.function.Function;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/29 17:53
+ * @description pdf格式的季报解析逻辑
+ */
+@Component(ReportParserConstant.PARSER_PDF_QUARTERLY)
+public class PDQuarterlyReportParser<T extends QuarterlyReportData> extends AbstractPDReportParser<T> {
+    protected Table fundInfoTable;
+    protected List<Table> financialIndicatorsTables;
+    protected List<Table> shareChangeTables;
+    protected List<Table> assetAllocationTables;
+    protected List<Table> investmentIndustryTables;
+
+    public PDQuarterlyReportParser(EmailFieldMappingMapper fieldMappingMapper) {
+        super(fieldMappingMapper);
+    }
+
+    @Override
+    public String getParser() {
+        return ReportParserConstant.PARSER_PDF_QUARTERLY;
+    }
+
+    @Override
+    protected void init() {
+        super.init();
+        this.fundInfoTable = null;
+        this.financialIndicatorsTables = ListUtil.list(true);
+        this.shareChangeTables = ListUtil.list(true);
+        this.assetAllocationTables = ListUtil.list(true);
+        this.investmentIndustryTables = ListUtil.list(true);
+    }
+
+    @Override
+    protected void initTableInfo(List<Table> tables) {
+        for (Table table : tables) {
+            int colCount = table.getColCount();
+            int rowCount = table.getRowCount();
+            if (colCount == 0 && rowCount == 0) {
+                continue;
+            }
+            if (rowCount == 13 && colCount == 2) {
+                this.fundInfoTable = table;
+            } else if (colCount == 2) {
+                // 用表格的第一列的数据判断是否份额变动记录
+                List<String> texts = this.getTableColTexts(table, 0);
+                // 主要财务指标或份额变动
+                if (CollUtil.containsAny(texts, ReportParseUtils.SHARE_CHANGE_COLUMN_NAMES)) {
+                    this.shareChangeTables.add(table);
+                } else if (CollUtil.containsAny(texts, ReportParseUtils.FINANCIAL_INDICATORS_COLUMN_NAMES)) {
+                    this.financialIndicatorsTables.add(table);
+                }
+            } else if (colCount == 4) {
+                // 行业配置
+                this.investmentIndustryTables.add(table);
+            } else if (colCount == 3) {
+                // 用表格的第一列单元格判断是否资产配置表
+                List<String> texts = this.getTableColTexts(table, 0);
+                if (CollUtil.containsAny(texts, ReportParseUtils.INDUSTRY_COLUMN_NAMES)) {
+                    this.investmentIndustryTables.add(table);
+                } else {
+                    texts = this.getTableColTexts(table, 1);
+                    Set<String> keys = ReportParseUtils.ASSET_ALLOCATION_TYPE_MAPPER.keySet();
+                    if (CollUtil.containsAny(texts, keys)) {
+                        this.assetAllocationTables.add(table);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    protected ReportFundInfoDTO buildFundInfo(ReportParserParams params) {
+        Table fundInfoTable = this.fundInfoTable;
+        if (fundInfoTable == null) {
+            throw new ReportParseException(ReportParseStatus.PARSE_FUND_INFO_FAIL, params.getFilename());
+        }
+        // 基金基本信息映射
+        Map<String, Object> extInfoMap = this.parseFundInfo(fundInfoTable);
+        return this.buildDto(params.getFileId(), ReportFundInfoDTO.class, extInfoMap);
+    }
+
+    protected Map<String, Object> parseFundInfo(Table fundInfoTable) {
+        // 季报和年报的基金基本信息是两列的表格
+        Map<String, Object> baseInfoMap = MapUtil.newHashMap(32);
+        for (int i = 0; i < fundInfoTable.getRows().size(); i++) {
+            @SuppressWarnings("all")
+            List<RectangularTextContainer> cols = fundInfoTable.getRows().get(i);
+            for (int j = 0; j < 1; j++) {
+                baseInfoMap.put(cols.get(j).getText(), cols.get(j + 1).getText());
+            }
+        }
+        return baseInfoMap;
+    }
+
+    protected T parseExtInfoAndSetData(ReportBaseInfoDTO reportInfo, ReportFundInfoDTO fundInfo) {
+        Integer fileId = reportInfo.getFileId();
+        // 表格转换数据获取函数
+        Function<Table, Map<String, Object>> function = t -> {
+            Map<String, Object> extInfoMap = MapUtil.newHashMap(16);
+            for (int i = 0; i < t.getRowCount(); i++) {
+                String key = t.getCell(i, 0).getText();
+                String value = t.getCell(i, 1).getText();
+                extInfoMap.put(key, value);
+            }
+            return extInfoMap;
+        };
+        // 份额变动
+        List<ReportShareChangeDTO> shareChanges = this.buildLevelDto(fileId, this.shareChangeTables,
+                ReportShareChangeDTO.class, function);
+        // 主要财务指标
+        List<ReportFinancialIndicatorsDTO> financialIndicators = this.buildFinancialIndicatorsInfo(fileId, function);
+        // 资产配置
+        List<ReportAssetAllocationDTO> assetAllocations = this.buildAssetAllocationInfo(fileId);
+        // 行业配置
+        List<ReportInvestmentIndustryDTO> investmentIndustries = this.buildInvestmentIndustryInfo(fileId);
+        // 返回数据构建
+        return this.buildReportData(reportInfo, fundInfo, shareChanges, financialIndicators, assetAllocations, investmentIndustries);
+    }
+
+    /**
+     * 主要财务指标数据构建(包括分级基金,并且一个表格可能跨页)
+     *
+     * @param fileId   文件id
+     * @param function 字段映射关系
+     * @return /
+     */
+    protected List<ReportFinancialIndicatorsDTO> buildFinancialIndicatorsInfo(Integer fileId, Function<Table, Map<String, Object>> function) {
+        return this.buildLevelDto(fileId, this.financialIndicatorsTables, ReportFinancialIndicatorsDTO.class, function);
+    }
+
+    /**
+     * 子类重写,放在cast异常
+     *
+     * @param reportInfo           报告基本信息
+     * @param fundInfo             基金基本信息
+     * @param shareChanges         份额变动
+     * @param financialIndicators  基本财务指标
+     * @param assetAllocations     资产配置
+     * @param investmentIndustries 行业配置
+     * @return /
+     */
+    protected T buildReportData(ReportBaseInfoDTO reportInfo, ReportFundInfoDTO fundInfo,
+                                List<ReportShareChangeDTO> shareChanges,
+                                List<ReportFinancialIndicatorsDTO> financialIndicators,
+                                List<ReportAssetAllocationDTO> assetAllocations,
+                                List<ReportInvestmentIndustryDTO> investmentIndustries) {
+        QuarterlyReportData reportData = new QuarterlyReportData(reportInfo, fundInfo);
+        reportData.setShareChange(shareChanges);
+        reportData.setFinancialIndicators(financialIndicators);
+        reportData.setAssetAllocation(assetAllocations);
+        reportData.setInvestmentIndustry(investmentIndustries);
+        @SuppressWarnings("unchecked")
+        T t = (T) reportData;
+        return t;
+    }
+
+    @Override
+    protected void cleaningReportData(T reportData) {
+        // todo 数据清洗
+    }
+
+    /**
+     * 构建基金行业配置解析数据
+     *
+     * @return /
+     */
+    private List<ReportInvestmentIndustryDTO> buildInvestmentIndustryInfo(Integer fileId) {
+        List<ReportInvestmentIndustryDTO> dtos = ListUtil.list(false);
+        for (Table table : this.investmentIndustryTables) {
+            int colCount = table.getColCount();
+            // 投资地区: 1-境内, 2-港股通
+            int investType = colCount == 4 ? 1 : 2;
+            int j = colCount == 4 ? 1 : 0;
+            // 按行遍历
+            for (int i = 0; i < table.getRowCount(); i++) {
+                String text = ReportParseUtils.cleaningValue(table.getCell(i, 0).getText());
+                if (StrUtil.containsAny(text, "序号", "行业类别")) {
+                    continue;
+                }
+                String industryName = ReportParseUtils.cleaningValue(table.getCell(i, j).getText());
+                if (StrUtil.isBlank(industryName) || !ReportParseUtils.INDUSTRY_COLUMN_NAMES.contains(industryName)) {
+                    continue;
+                }
+                ReportInvestmentIndustryDTO dto = new ReportInvestmentIndustryDTO(fileId);
+                dto.setInvestType(investType);
+                dto.setIndustryName(industryName);
+                dto.setMarketValue(ReportParseUtils.cleaningValue(table.getCell(i, j + 1).getText()));
+                dto.setRatio(ReportParseUtils.cleaningValue(table.getCell(i, j + 2).getText()));
+                dtos.add(dto);
+            }
+        }
+        return dtos;
+    }
+
+    /**
+     * 构建基金资产配置解析数据
+     *
+     * @param fileId 文件id
+     * @return /
+     */
+    private List<ReportAssetAllocationDTO> buildAssetAllocationInfo(Integer fileId) {
+        List<ReportAssetAllocationDTO> dtos = ListUtil.list(false);
+        for (Table table : this.assetAllocationTables) {
+            // 按行遍历
+            for (@SuppressWarnings("all") List<RectangularTextContainer> row : table.getRows()) {
+                // x坐标升序(防止部分行乱序问题)
+                row.sort(Comparator.comparing(Rectangle2D.Float::getX));
+                // 金额、市值,有时是 “备注#金额”的格式
+                String marketValueAndRemark = ReportParseUtils.cleaningValue(row.get(2).getText());
+                // 资产明细
+                String detail = ReportParseUtils.cleaningValue(row.get(1).getText(), false);
+                if (!ReportParseUtils.ASSET_ALLOCATION_TYPE_MAPPER.containsKey(detail)) {
+                    continue;
+                }
+                // 大类
+                String assetType = ReportParseUtils.ASSET_ALLOCATION_TYPE_MAPPER.get(detail);
+                if (StrUtil.contains(marketValueAndRemark, "#")) {
+                    // 有#表示有备注,而且可能有多个,多个用分号分隔的.
+                    List<String> marketValueAndRemarks = StrUtil.split(marketValueAndRemark, ";");
+                    for (String mr : marketValueAndRemarks) {
+                        if (StrUtil.isBlank(mr)) {
+                            continue;
+                        }
+                        List<String> mrs = StrUtil.split(mr, "#");
+                        ReportAssetAllocationDTO dto = new ReportAssetAllocationDTO(fileId);
+                        dto.setAssetType(assetType);
+                        dto.setAssetDetails(detail);
+                        dto.setMarketValue(mrs.get(1));
+                        dto.setRemark(mrs.get(0));
+                        dtos.add(dto);
+                    }
+                } else {
+                    ReportAssetAllocationDTO dto = new ReportAssetAllocationDTO(fileId);
+                    dto.setAssetType(assetType);
+                    dto.setAssetDetails(detail);
+                    dto.setMarketValue(marketValueAndRemark);
+                    dtos.add(dto);
+                }
+            }
+        }
+        return dtos;
+    }
+
+    /**
+     * 获取表格指定列的所有文字内容
+     *
+     * @param table 表格
+     * @param col   指定列
+     * @return /
+     */
+    protected List<String> getTableColTexts(Table table, Integer col) {
+        List<String> details = ListUtil.list(false);
+        for (@SuppressWarnings("all") List<RectangularTextContainer> row : table.getRows()) {
+            String detail = ReportParseUtils.cleaningValue(row.get(col).getText(), false);
+            if (StrUtil.isNotBlank(detail)) {
+                details.add(detail);
+            }
+        }
+        return details;
+    }
+
+    /**
+     * 构建只有两列表格的dto数据对象,如果有分级基金时(并且一个表格可能跨页)
+     *
+     * @param <DTO>    泛型对象
+     * @param fileId   文件id
+     * @param tables   表格
+     * @param clazz    泛型对象
+     * @param function 表格转换的函数
+     * @return /
+     */
+    protected <DTO extends BaseReportLevelDTO<?>> List<DTO> buildLevelDto(Integer fileId, List<Table> tables, Class<DTO> clazz,
+                                                                          Function<Table, Map<String, Object>> function) {
+        List<DTO> dtos = ListUtil.list(true);
+        // 信息表格字段和值映射
+        List<Map<String, Object>> infos = ListUtil.list(true);
+        Map<String, Object> infoMap = null;
+        for (Table table : tables) {
+            Map<String, Object> temp = function.apply(table);
+            for (String key : temp.keySet()) {
+                // 如果infoMap为null,先声明然后放在infos中
+                if (infoMap == null) {
+                    infoMap = MapUtil.newHashMap(16);
+                    infos.add(infoMap);
+                }
+                // 如果infoMap中包含了该key时,先放infos中然后重新声明新map对象
+                if (infoMap.containsKey(key)) {
+                    infos.add(new HashMap<>(infoMap));
+                    infoMap = MapUtil.newHashMap(16);
+                } else {
+                    infoMap.put(key, temp.get(key));
+                }
+            }
+        }
+        // 分级基金匹配
+        List<String> levels = ReportParseUtils.matchTieredFund(String.join(",", this.textList));
+        for (int i = 0; i < infos.size(); i++) {
+            DTO dto = this.buildDto(fileId, clazz, infos.get(i));
+            if (dto == null) {
+                continue;
+            }
+            dto.setLevel(levels.get(i));
+            dtos.add(dto);
+        }
+        return dtos;
+    }
+}

+ 0 - 39
mo-daq/src/main/java/com/smppw/modaq/application/components/report/parser/pdf/PDWeeklyReportParser.java

@@ -1,39 +0,0 @@
-package com.smppw.modaq.application.components.report.parser.pdf;
-
-import com.smppw.modaq.application.components.report.parser.ReportParserConstant;
-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.dto.report.WeeklyReportData;
-import com.smppw.modaq.domain.mapper.EmailFieldMappingMapper;
-import org.springframework.stereotype.Component;
-import technology.tabula.Table;
-
-import java.util.List;
-
-@Component(ReportParserConstant.PARSER_PDF_WEEKLY)
-public class PDWeeklyReportParser extends AbstractPDReportParser<WeeklyReportData>{
-    public PDWeeklyReportParser(EmailFieldMappingMapper fieldMappingMapper) {
-        super(fieldMappingMapper);
-    }
-
-    @Override
-    public String getParser() {
-        return ReportParserConstant.PARSER_PDF_WEEKLY;
-    }
-
-    @Override
-    protected void initTableInfo(List<Table> tables) {
-
-    }
-
-    @Override
-    protected ReportFundInfoDTO buildFundInfo(ReportParserParams params) {
-        return null;
-    }
-
-    @Override
-    protected WeeklyReportData parseExtInfoAndSetData(ReportBaseInfoDTO reportInfo, ReportFundInfoDTO fundInfo) {
-        return null;
-    }
-}

+ 2 - 2
mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/AbstractReportWriter.java

@@ -3,8 +3,8 @@ package com.smppw.modaq.application.components.report.writer;
 import com.smppw.modaq.domain.dto.report.ReportBaseInfoDTO;
 import com.smppw.modaq.domain.dto.report.ReportData;
 import com.smppw.modaq.domain.dto.report.ReportFundInfoDTO;
-import com.smppw.modaq.domain.mapper.ReportBaseInfoMapper;
-import com.smppw.modaq.domain.mapper.ReportFundInfoMapper;
+import com.smppw.modaq.domain.mapper.report.ReportBaseInfoMapper;
+import com.smppw.modaq.domain.mapper.report.ReportFundInfoMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.transaction.annotation.Transactional;

+ 14 - 0
mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/AnnuallyReportWriter.java

@@ -0,0 +1,14 @@
+package com.smppw.modaq.application.components.report.writer;
+
+import com.smppw.modaq.domain.dto.report.AnnuallyReportData;
+import com.smppw.modaq.domain.mapper.report.*;
+import org.springframework.stereotype.Component;
+
+@Component(ReportWriterConstant.WRITER_ANNUALLY)
+public class AnnuallyReportWriter extends QuarterlyReportWriter<AnnuallyReportData> {
+    public AnnuallyReportWriter(ReportBaseInfoMapper baseInfoMapper, ReportFundInfoMapper fundInfoMapper,
+                                ReportShareChangeMapper shareChangeMapper, ReportAssetAllocationMapper assetAllocationMapper,
+                                ReportInvestmentIndustryMapper investmentIndustryMapper, ReportFinancialIndicatorMapper financialIndicatorMapper) {
+        super(baseInfoMapper, fundInfoMapper, shareChangeMapper, assetAllocationMapper, investmentIndustryMapper, financialIndicatorMapper);
+    }
+}

+ 4 - 4
mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/LetterReportWriter.java

@@ -3,10 +3,10 @@ package com.smppw.modaq.application.components.report.writer;
 import com.smppw.modaq.domain.dto.report.LetterReportData;
 import com.smppw.modaq.domain.dto.report.ReportFundTransactionDTO;
 import com.smppw.modaq.domain.dto.report.ReportInvestorInfoDTO;
-import com.smppw.modaq.domain.mapper.ReportBaseInfoMapper;
-import com.smppw.modaq.domain.mapper.ReportFundInfoMapper;
-import com.smppw.modaq.domain.mapper.ReportFundTransactionMapper;
-import com.smppw.modaq.domain.mapper.ReportInvestorInfoMapper;
+import com.smppw.modaq.domain.mapper.report.ReportBaseInfoMapper;
+import com.smppw.modaq.domain.mapper.report.ReportFundInfoMapper;
+import com.smppw.modaq.domain.mapper.report.ReportFundTransactionMapper;
+import com.smppw.modaq.domain.mapper.report.ReportInvestorInfoMapper;
 import org.springframework.stereotype.Component;
 
 @Component(ReportWriterConstant.WRITER_LETTER)

+ 2 - 2
mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/MonthlyReportWriter.java

@@ -1,8 +1,8 @@
 package com.smppw.modaq.application.components.report.writer;
 
 import com.smppw.modaq.domain.dto.report.MonthlyReportData;
-import com.smppw.modaq.domain.mapper.ReportBaseInfoMapper;
-import com.smppw.modaq.domain.mapper.ReportFundInfoMapper;
+import com.smppw.modaq.domain.mapper.report.ReportBaseInfoMapper;
+import com.smppw.modaq.domain.mapper.report.ReportFundInfoMapper;
 import org.springframework.stereotype.Component;
 
 @Component(ReportWriterConstant.WRITER_MONTHLY)

+ 62 - 0
mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/QuarterlyReportWriter.java

@@ -0,0 +1,62 @@
+package com.smppw.modaq.application.components.report.writer;
+
+import cn.hutool.core.collection.CollUtil;
+import com.smppw.modaq.domain.dto.report.*;
+import com.smppw.modaq.domain.entity.report.ReportAssetAllocationDO;
+import com.smppw.modaq.domain.entity.report.ReportFinancialIndicatorsDO;
+import com.smppw.modaq.domain.entity.report.ReportInvestmentIndustryDO;
+import com.smppw.modaq.domain.entity.report.ReportShareChangeDO;
+import com.smppw.modaq.domain.mapper.report.*;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component(ReportWriterConstant.WRITER_QUARTERLY)
+public class QuarterlyReportWriter<T extends QuarterlyReportData> extends AbstractReportWriter<T> {
+    private final ReportShareChangeMapper shareChangeMapper;
+    private final ReportAssetAllocationMapper assetAllocationMapper;
+    private final ReportInvestmentIndustryMapper investmentIndustryMapper;
+    private final ReportFinancialIndicatorMapper financialIndicatorMapper;
+
+    public QuarterlyReportWriter(ReportBaseInfoMapper baseInfoMapper, ReportFundInfoMapper fundInfoMapper,
+                                 ReportShareChangeMapper shareChangeMapper, ReportAssetAllocationMapper assetAllocationMapper,
+                                 ReportInvestmentIndustryMapper investmentIndustryMapper, ReportFinancialIndicatorMapper financialIndicatorMapper) {
+        super(baseInfoMapper, fundInfoMapper);
+        this.shareChangeMapper = shareChangeMapper;
+        this.assetAllocationMapper = assetAllocationMapper;
+        this.investmentIndustryMapper = investmentIndustryMapper;
+        this.financialIndicatorMapper = financialIndicatorMapper;
+    }
+
+    @Override
+    protected void writeExtData(QuarterlyReportData reportData) {
+        List<ReportShareChangeDTO> shareChange = reportData.getShareChange();
+        if (CollUtil.isNotEmpty(shareChange)) {
+            List<ReportShareChangeDO> entityList = shareChange.stream()
+                    .map(ReportShareChangeDTO::toEntity).collect(Collectors.toList());
+            this.shareChangeMapper.insert(entityList);
+        }
+
+        List<ReportAssetAllocationDTO> assetAllocation = reportData.getAssetAllocation();
+        if (CollUtil.isNotEmpty(assetAllocation)) {
+            List<ReportAssetAllocationDO> entityList = assetAllocation.stream()
+                    .map(ReportAssetAllocationDTO::toEntity).collect(Collectors.toList());
+            this.assetAllocationMapper.insert(entityList);
+        }
+
+        List<ReportFinancialIndicatorsDTO> financialIndicators = reportData.getFinancialIndicators();
+        if (CollUtil.isNotEmpty(financialIndicators)) {
+            List<ReportFinancialIndicatorsDO> entityList = financialIndicators.stream()
+                    .map(ReportFinancialIndicatorsDTO::toEntity).collect(Collectors.toList());
+            this.financialIndicatorMapper.insert(entityList);
+        }
+
+        List<ReportInvestmentIndustryDTO> investmentIndustry = reportData.getInvestmentIndustry();
+        if (CollUtil.isNotEmpty(investmentIndustry)) {
+            List<ReportInvestmentIndustryDO> entityList = investmentIndustry.stream()
+                    .map(ReportInvestmentIndustryDTO::toEntity).collect(Collectors.toList());
+            this.investmentIndustryMapper.insert(entityList);
+        }
+    }
+}

+ 4 - 6
mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/ReportWriterConstant.java

@@ -9,17 +9,15 @@ public final class ReportWriterConstant {
     public static final Map<ReportType, String> REPORT_TYPE_BEAN_MAP = MapUtil.newHashMap(8);
 
     static final String WRITER_LETTER = "report-writer:letter";
-    static final String WRITER_WEEKLY = "report-writer:weekly";
     static final String WRITER_MONTHLY = "report-writer:monthly";
-//    static final String WRITER_QUARTERLY = "report-writer:quarterly";
-//    static final String WRITER_ANNUALLY = "report-writer:annually";
+    static final String WRITER_QUARTERLY = "report-writer:quarterly";
+    static final String WRITER_ANNUALLY = "report-writer:annually";
 
     static {
         REPORT_TYPE_BEAN_MAP.put(ReportType.LETTER, WRITER_LETTER);
 
-        REPORT_TYPE_BEAN_MAP.put(ReportType.WEEKLY, WRITER_WEEKLY);
         REPORT_TYPE_BEAN_MAP.put(ReportType.MONTHLY, WRITER_MONTHLY);
-//        REPORT_TYPE_BEAN_MAP.put(ReportType.QUARTERLY, WRITER_QUARTERLY);
-//        REPORT_TYPE_BEAN_MAP.put(ReportType.ANNUALLY, WRITER_ANNUALLY);
+        REPORT_TYPE_BEAN_MAP.put(ReportType.QUARTERLY, WRITER_QUARTERLY);
+        REPORT_TYPE_BEAN_MAP.put(ReportType.ANNUALLY, WRITER_ANNUALLY);
     }
 }

+ 0 - 25
mo-daq/src/main/java/com/smppw/modaq/application/components/report/writer/WeeklyReportWriter.java

@@ -1,25 +0,0 @@
-package com.smppw.modaq.application.components.report.writer;
-
-import com.smppw.modaq.domain.dto.report.WeeklyReportData;
-import com.smppw.modaq.domain.mapper.ReportBaseInfoMapper;
-import com.smppw.modaq.domain.mapper.ReportFundInfoMapper;
-import org.springframework.stereotype.Component;
-
-@Component(ReportWriterConstant.WRITER_WEEKLY)
-public class WeeklyReportWriter extends AbstractReportWriter<WeeklyReportData> {
-
-    public WeeklyReportWriter(ReportBaseInfoMapper baseInfoMapper,
-                              ReportFundInfoMapper fundInfoMapper) {
-        super(baseInfoMapper, fundInfoMapper);
-    }
-
-    @Override
-    protected void writeExtData(WeeklyReportData reportData) {
-//        List<ReportNetReportDTO> netReport = reportData.getNetReport();
-//        if (CollUtil.isNotEmpty(netReport)) {
-//            List<ReportNetReportDO> entityList = netReport.stream()
-//                    .map(ReportNetReportDTO::toEntity).collect(Collectors.toList());
-//            this.netReportMapper.insert(entityList);
-//        }
-    }
-}

+ 6 - 6
mo-daq/src/main/java/com/smppw/modaq/common/enums/ReportParseStatus.java

@@ -7,12 +7,12 @@ public enum ReportParseStatus implements StatusCode {
     NO_SUPPORT_TEMPLATE(21003, "报告[{}]是不支持的文件格式"),
     NOT_A_FIXED_FORMAT(21004, "报告[{}]不是基协统一格式"),
 
-//    PARSE_FUND_INFO_FAIL(21010, "报告[{}]没有解析到基金基本信息"),
-//    PARSE_NAV_INFO_FAIL(21011, "报告[{}]没有解析到基金净值信息"),
-//    PARSE_FINANCIAL_INFO_FAIL(21012, "报告[{}]没有解析到基金财务指标信息"),
-//    PARSE_INDUSTRY_INFO_FAIL(21013, "报告[{}]没有解析到基金行业配置信息"),
-//    PARSE_ASSET_INFO_FAIL(21014, "报告[{}]没有解析到基金资产配置信息"),
-//    PARSE_SHARE_INFO_FAIL(21015, "报告[{}]没有解析到基金份额变动信息"),
+    PARSE_FUND_INFO_FAIL(21010, "报告[{}]没有解析到基金基本信息"),
+    PARSE_NAV_INFO_FAIL(21011, "报告[{}]没有解析到基金净值信息"),
+    PARSE_FINANCIAL_INFO_FAIL(21012, "报告[{}]没有解析到基金财务指标信息"),
+    PARSE_INDUSTRY_INFO_FAIL(21013, "报告[{}]没有解析到基金行业配置信息"),
+    PARSE_ASSET_INFO_FAIL(21014, "报告[{}]没有解析到基金资产配置信息"),
+    PARSE_SHARE_INFO_FAIL(21015, "报告[{}]没有解析到基金份额变动信息"),
 
     PARSE_RULE_NO_FUND(21020, "未设置报告解析规则"),
     ;

+ 0 - 50
mo-daq/src/main/java/com/smppw/modaq/domain/dto/QuartzBean.java

@@ -1,50 +0,0 @@
-//package com.smppw.modaq.domain.dto;
-//
-///**
-// * FileName: QuartzBean
-// * Author:   chenjianhua
-// * Date:     2024/9/17 10:26
-// * Description: ${DESCRIPTION}
-// */
-//
-//import lombok.Data;
-//
-//import java.io.Serializable;
-//
-//@Data
-//public class QuartzBean implements Serializable {
-//    /**
-//     * 任务id
-//     */
-//    private String id;
-//
-//    /**
-//     * 任务名称
-//     */
-//    private String jobName;
-//
-//    /**
-//     * 任务执行类
-//     */
-//    private String jobClass;
-//
-//    /**
-//     * 组名
-//     */
-//    private String groupName;
-//
-//    /**
-//     * 任务 参数信息
-//     */
-//    private String jobParam;
-//
-//    /**
-//     * 任务状态 启动还是暂停
-//     */
-//    private Integer status;
-//
-//    /**
-//     * 任务运行时间表达式
-//     */
-//    private String cronExpression;
-//}

+ 3 - 8
mo-daq/src/main/java/com/smppw/modaq/domain/dto/report/WeeklyReportData.java

@@ -6,18 +6,13 @@ import lombok.Setter;
 
 @Setter
 @Getter
-public class WeeklyReportData extends ReportData {
-    public WeeklyReportData(ReportBaseInfoDTO baseInfo, ReportFundInfoDTO fundInfo) {
+public class AnnuallyReportData extends QuarterlyReportData {
+    public AnnuallyReportData(ReportBaseInfoDTO baseInfo, ReportFundInfoDTO fundInfo) {
         super(baseInfo, fundInfo);
     }
 
     @Override
     public ReportType getReportType() {
-        return ReportType.WEEKLY;
-    }
-
-    @Override
-    public String toString() {
-        return super.toString();
+        return ReportType.ANNUALLY;
     }
 }

+ 41 - 0
mo-daq/src/main/java/com/smppw/modaq/domain/dto/report/QuarterlyReportData.java

@@ -0,0 +1,41 @@
+package com.smppw.modaq.domain.dto.report;
+
+import com.smppw.modaq.common.enums.ReportType;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 17:24
+ * @description 季报
+ */
+@Setter
+@Getter
+public class QuarterlyReportData extends ReportData {
+    private List<ReportAssetAllocationDTO> assetAllocation;
+    private List<ReportFinancialIndicatorsDTO> financialIndicators;
+    private List<ReportInvestmentIndustryDTO> investmentIndustry;
+    private List<ReportShareChangeDTO> shareChange;
+
+    public QuarterlyReportData(ReportBaseInfoDTO baseInfo, ReportFundInfoDTO fundInfo) {
+        super(baseInfo, fundInfo);
+    }
+
+    @Override
+    public ReportType getReportType() {
+        return ReportType.QUARTERLY;
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                super.toString() +
+                ", assetAllocation=" + assetAllocation +
+                ", financialIndicators=" + financialIndicators +
+                ", investmentIndustry=" + investmentIndustry +
+                ", shareChange=" + shareChange +
+                '}';
+    }
+}

+ 9 - 0
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportAssetAllocationMapper.java

@@ -0,0 +1,9 @@
+package com.smppw.modaq.domain.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.smppw.modaq.domain.entity.report.ReportAssetAllocationDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportAssetAllocationMapper extends BaseMapper<ReportAssetAllocationDO> {
+}

+ 1 - 1
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/ReportBaseInfoMapper.java

@@ -1,4 +1,4 @@
-package com.smppw.modaq.domain.mapper;
+package com.smppw.modaq.domain.mapper.report;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.smppw.modaq.domain.entity.report.ReportBaseInfoDO;

+ 9 - 0
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportFinancialIndicatorMapper.java

@@ -0,0 +1,9 @@
+package com.smppw.modaq.domain.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.smppw.modaq.domain.entity.report.ReportFinancialIndicatorsDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportFinancialIndicatorMapper extends BaseMapper<ReportFinancialIndicatorsDO> {
+}

+ 1 - 1
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/ReportFundInfoMapper.java

@@ -1,4 +1,4 @@
-package com.smppw.modaq.domain.mapper;
+package com.smppw.modaq.domain.mapper.report;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.smppw.modaq.domain.entity.report.ReportFundInfoDO;

+ 1 - 1
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/ReportFundTransactionMapper.java

@@ -1,4 +1,4 @@
-package com.smppw.modaq.domain.mapper;
+package com.smppw.modaq.domain.mapper.report;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.smppw.modaq.domain.entity.report.ReportFundTransactionDO;

+ 9 - 0
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportInvestmentIndustryMapper.java

@@ -0,0 +1,9 @@
+package com.smppw.modaq.domain.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.smppw.modaq.domain.entity.report.ReportInvestmentIndustryDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportInvestmentIndustryMapper extends BaseMapper<ReportInvestmentIndustryDO> {
+}

+ 1 - 1
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/ReportInvestorInfoMapper.java

@@ -1,4 +1,4 @@
-package com.smppw.modaq.domain.mapper;
+package com.smppw.modaq.domain.mapper.report;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.smppw.modaq.domain.entity.report.ReportInvestorInfoDO;

+ 9 - 0
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportNetReportMapper.java

@@ -0,0 +1,9 @@
+package com.smppw.modaq.domain.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.smppw.modaq.domain.entity.report.ReportNetReportDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportNetReportMapper extends BaseMapper<ReportNetReportDO> {
+}

+ 9 - 0
mo-daq/src/main/java/com/smppw/modaq/domain/mapper/report/ReportShareChangeMapper.java

@@ -0,0 +1,9 @@
+package com.smppw.modaq.domain.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.smppw.modaq.domain.entity.report.ReportShareChangeDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportShareChangeMapper extends BaseMapper<ReportShareChangeDO> {
+}

+ 2 - 1
mo-daq/src/main/java/com/smppw/modaq/domain/service/EmailParseService.java

@@ -414,7 +414,8 @@ 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("月报", "周报", "月度报告"));
+        emailTypeMap.put(EmailTypeConst.REPORT_EMAIL_TYPE,
+                ListUtil.toList("月报", "月度报告", "年报", "年度报告"));
         emailTypeMap.put(EmailTypeConst.REPORT_LETTER_EMAIL_TYPE,
                 ListUtil.toList("确认单", "确认函", "交易确认数据", "赎回确认", "申购确认", "分红确认", "确认表"));
         return emailTypeMap;

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

@@ -34,7 +34,7 @@ public class MoDaqApplicationTests {
 
     @Test
     public void reportTest() {
-        MailboxInfoDTO emailInfoDTO = this.buildMailbox("wangzaijun157@163.com", "AMn3Trh4UTgVMaEx");
+        MailboxInfoDTO emailInfoDTO = this.buildMailbox("wangzaijun157@163.com", "***");
         Date startDate = DateUtil.parse("2025-03-27 14:40:00", DateConst.YYYY_MM_DD_HH_MM_SS);
         Date endDate = DateUtil.parse("2025-03-27 19:42:05", DateConst.YYYY_MM_DD_HH_MM_SS);
         try {
@@ -55,7 +55,7 @@ public class MoDaqApplicationTests {
         emailInfoDTO.setUserId(1);
         emailInfoDTO.setAccount(account);
         emailInfoDTO.setPassword(pwd);
-        emailInfoDTO.setHost("imap.163.com");
+        emailInfoDTO.setHost("imap.exmail.qq.com");
         emailInfoDTO.setPort("993");
         emailInfoDTO.setProtocol("imap");
         return emailInfoDTO;