Kaynağa Gözat

feat:报告解析和保存逻辑优化重构完成,开始支持季报和年报的java解析

wangzaijun 7 ay önce
ebeveyn
işleme
22c1126743
18 değiştirilmiş dosya ile 240 ekleme ve 130 silme
  1. 3 2
      service-daq/src/main/java/com/simuwang/daq/components/PythonReportConverter.java
  2. 13 1
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/ReportParser.java
  3. 1 1
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/ReportParserFactory.java
  4. 10 27
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/pdf/AbstractReportParser.java
  5. 5 0
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/pdf/PDAnnuallyReportParser.java
  6. 5 0
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/pdf/PDMonthlyReportParser.java
  7. 5 0
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/pdf/PDQuarterlyReportParser.java
  8. 43 2
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/py/AbstractPyReportParser.java
  9. 25 0
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/py/PythonAnnuallyReportParser.java
  10. 11 0
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/py/PythonMonthlyReportParser.java
  11. 25 0
      service-daq/src/main/java/com/simuwang/daq/components/report/parser/py/PythonQuarterlyReportParser.java
  12. 14 31
      service-daq/src/main/java/com/simuwang/daq/components/report/writer/AbstractReportWriter.java
  13. 5 0
      service-daq/src/main/java/com/simuwang/daq/components/report/writer/ReportWriter.java
  14. 51 15
      service-daq/src/main/java/com/simuwang/daq/service/EmailParseService.java
  15. 3 2
      service-daq/src/main/java/com/simuwang/daq/service/ReportEmailParser.java
  16. 0 19
      service-daq/src/main/java/com/simuwang/daq/service/ReportParseService.java
  17. 21 9
      service-deploy/src/test/java/com/simuwang/ApplicationTest.java
  18. 0 21
      service-manage/src/main/java/com/simuwang/manage/api/test/ReportParseTestApi.java

+ 3 - 2
service-daq/src/main/java/com/simuwang/daq/components/PythonReportConverter.java

@@ -7,6 +7,7 @@ import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.simuwang.base.common.enums.ReportType;
 import com.simuwang.base.pojo.dos.report.BaseReportDO;
 import com.simuwang.base.pojo.dto.report.*;
 
@@ -21,7 +22,7 @@ import java.util.Set;
  */
 public class PythonReportConverter {
     @SuppressWarnings("unchecked")
-    public static <T extends ReportData> PythonResult<T> convert(JSONObject jsonObject, Integer type) {
+    public static <T extends ReportData> PythonResult<T> convert(JSONObject jsonObject, ReportType type) {
         PythonResult<T> result = new PythonResult<>();
         if (jsonObject == null) {
             return result;
@@ -34,7 +35,7 @@ public class PythonReportConverter {
         }
 
         T reportData;
-        if (Objects.equals(2, type) || Objects.equals(1, type)) {
+        if (Objects.equals(ReportType.ANNUALLY, type) || Objects.equals(ReportType.QUARTERLY, type)) {
             reportData = (T) convertQuarterly(data);
         } else {
             reportData = (T) convertMonthly(data);

+ 13 - 1
service-daq/src/main/java/com/simuwang/daq/components/report/parser/ReportParser.java

@@ -3,6 +3,8 @@ package com.simuwang.daq.components.report.parser;
 import com.simuwang.base.pojo.dto.report.ReportData;
 import com.simuwang.base.pojo.dto.report.ReportParserParams;
 
+import java.io.IOException;
+
 /**
  * @author wangzaijun
  * @date 2024/9/9 19:18
@@ -10,11 +12,21 @@ import com.simuwang.base.pojo.dto.report.ReportParserParams;
  */
 public interface ReportParser<T extends ReportData> {
     /**
+     * 获取当前解析器名称
+     *
+     * @return /
+     */
+    default String getParser() {
+        return this.getClass().getSimpleName();
+    }
+
+    /**
      * 报告模板解析接口
      * 扩展支持月报、季报和年报,解析文件格式支持pdf、word和excel
      *
      * @param params 解析请求参数
      * @return 解析结果
+     * @throws IOException 文件io异常
      */
-    T parse(ReportParserParams params);
+    T parse(ReportParserParams params) throws IOException;
 }

+ 1 - 1
service-daq/src/main/java/com/simuwang/daq/components/report/parser/ReportParserFactory.java

@@ -12,7 +12,7 @@ import java.util.Map;
 public class ReportParserFactory {
     private static final ReportParser<? extends ReportData> DEFAULT = (ReportParser<ReportData>) params -> null;
 
-    private static final Map<String, ReportParser<? extends ReportData>> REPORT_WRITER_MAP = MapUtil.newHashMap(8);
+    private static final Map<String, ReportParser<? extends ReportData>> REPORT_WRITER_MAP = MapUtil.newHashMap(32);
 
     public ReportParserFactory(Map<String, ReportParser<? extends ReportData>> components) {
         REPORT_WRITER_MAP.putAll(components);

+ 10 - 27
service-daq/src/main/java/com/simuwang/daq/components/report/parser/pdf/AbstractReportParser.java

@@ -1,7 +1,6 @@
 package com.simuwang.daq.components.report.parser.pdf;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.exceptions.ExceptionUtil;
 import com.simuwang.base.mapper.EmailFieldMappingMapper;
 import com.simuwang.base.pojo.dos.EmailFieldMappingDO;
 import com.simuwang.base.pojo.dto.report.ReportBaseInfoDTO;
@@ -12,12 +11,10 @@ import com.simuwang.daq.components.report.parser.ReportParser;
 import com.smppw.common.pojo.ValueLabelVO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.util.StopWatch;
 
 import java.io.IOException;
 import java.util.Calendar;
 import java.util.List;
-import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -36,31 +33,17 @@ public abstract class AbstractReportParser<T extends ReportData> implements Repo
     }
 
     @Override
-    public T parse(ReportParserParams params) {
-        StopWatch watch = new StopWatch();
-        watch.start();
-        String filepath = params.getFilepath();
-        try {
-            if (this.logger.isInfoEnabled()) {
-                this.logger.info("报告{} 开始解析!", filepath);
-            }
-            List<EmailFieldMappingDO> emailFieldMapping = this.fieldMappingMapper.getEmailFieldMapping();
-            if (CollUtil.isNotEmpty(emailFieldMapping)) {
-                this.fieldMapper = emailFieldMapping.stream().map(e -> new ValueLabelVO(e.getCode(), e.getName())).collect(Collectors.toList());
-            }
-            String reportName = this.initAndGetReportName(params);
-            ReportBaseInfoDTO reportInfo = this.buildReportInfo(params, reportName);
-            ReportFundInfoDTO reportFundInfo = this.parseBaseInfo(params);
-            return this.parseExtInfoAndSetData(reportInfo, reportFundInfo, params);
-        } catch (Exception e) {
-            this.logger.error("报告{} 解析错误\n{}", filepath, ExceptionUtil.stacktraceToString(e));
-        } finally {
-            watch.stop();
-            if (this.logger.isInfoEnabled()) {
-                this.logger.info("报告{} 解析结束!耗时:{}s", filepath, watch.getTotalTime(TimeUnit.SECONDS));
-            }
+    public T parse(ReportParserParams params) throws IOException {
+        List<EmailFieldMappingDO> emailFieldMapping = this.fieldMappingMapper.getEmailFieldMapping();
+        if (CollUtil.isEmpty(emailFieldMapping)) {
+            this.logger.error("未设置报告解析规则!");
+            return null;
         }
-        return null;
+        this.fieldMapper = emailFieldMapping.stream().map(e -> new ValueLabelVO(e.getCode(), e.getName())).collect(Collectors.toList());
+        String reportName = this.initAndGetReportName(params);
+        ReportBaseInfoDTO reportInfo = this.buildReportInfo(params, reportName);
+        ReportFundInfoDTO reportFundInfo = this.parseBaseInfo(params);
+        return this.parseExtInfoAndSetData(reportInfo, reportFundInfo, params);
     }
 
     protected abstract String initAndGetReportName(ReportParserParams params) throws IOException;

+ 5 - 0
service-daq/src/main/java/com/simuwang/daq/components/report/parser/pdf/PDAnnuallyReportParser.java

@@ -30,4 +30,9 @@ public class PDAnnuallyReportParser extends AbstractReportParser<AnnuallyReportD
     protected AnnuallyReportData parseExtInfoAndSetData(ReportBaseInfoDTO baseInfo, ReportFundInfoDTO fundInfo, ReportParserParams params) {
         return null;
     }
+
+    @Override
+    public String getParser() {
+        return ReportParserConstant.PARSER_PDF_ANNUALLY;
+    }
 }

+ 5 - 0
service-daq/src/main/java/com/simuwang/daq/components/report/parser/pdf/PDMonthlyReportParser.java

@@ -40,6 +40,11 @@ public class PDMonthlyReportParser extends AbstractReportParser<MonthlyReportDat
     }
 
     @Override
+    public String getParser() {
+        return ReportParserConstant.PARSER_PDF_MONTHLY;
+    }
+
+    @Override
     protected String initAndGetReportName(ReportParserParams params) throws IOException {
         String reportName = null;
         try (PDDocument document = Loader.loadPDF(new RandomAccessReadBufferedFile(params.getFilepath()))) {

+ 5 - 0
service-daq/src/main/java/com/simuwang/daq/components/report/parser/pdf/PDQuarterlyReportParser.java

@@ -17,6 +17,11 @@ public class PDQuarterlyReportParser extends AbstractReportParser<QuarterlyRepor
     }
 
     @Override
+    public String getParser() {
+        return ReportParserConstant.PARSER_PDF_QUARTERLY;
+    }
+
+    @Override
     protected String initAndGetReportName(ReportParserParams params) throws IOException {
         return null;
     }

+ 43 - 2
service-daq/src/main/java/com/simuwang/daq/components/report/parser/py/AbstractPyReportParser.java

@@ -1,12 +1,27 @@
 package com.simuwang.daq.components.report.parser.py;
 
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import com.simuwang.base.common.enums.ReportType;
 import com.simuwang.base.config.DaqProperties;
 import com.simuwang.base.mapper.FundInfoMapper;
+import com.simuwang.base.pojo.dos.FundAndCompanyInfoDO;
+import com.simuwang.base.pojo.dto.report.PythonResult;
 import com.simuwang.base.pojo.dto.report.ReportData;
 import com.simuwang.base.pojo.dto.report.ReportParserParams;
+import com.simuwang.daq.components.PythonReportConverter;
 import com.simuwang.daq.components.report.parser.ReportParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Map;
 
 public abstract class AbstractPyReportParser<T extends ReportData> implements ReportParser<T> {
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
     private final DaqProperties properties;
     private final FundInfoMapper fundInfoMapper;
 
@@ -16,7 +31,33 @@ public abstract class AbstractPyReportParser<T extends ReportData> implements Re
     }
 
     @Override
-    public T parse(ReportParserParams params) {
-        return null;
+    public T parse(ReportParserParams params) throws IOException {
+        Boolean enablePyParser = this.properties.getEnablePyParser();
+        if (!enablePyParser) {
+            this.logger.error("The python report parser is unavailable!");
+            return null;
+        }
+        String pyBaseUrl = this.properties.getPyBaseUrl();
+        ReportType reportType = this.getReportType();
+        String registerNumber = params.getRegisterNumber();
+        String api = "/api/v1/parse/amac_report";
+        Map<String, Object> param = MapUtil.newHashMap(16);
+        param.put("file_id", params.getFileId());
+        param.put("file_path", params.getFilepath());
+        param.put("register_number", registerNumber);
+        param.put("file_type", reportType.getType());
+        param.put("file_name", params.getFilename());
+        if (StrUtil.isNotBlank(registerNumber)) {
+            FundAndCompanyInfoDO info = this.fundInfoMapper.queryFundAndTrustByRegisterNumber(registerNumber);
+            if (info != null) {
+                param.put("fund_name", info.getFundName());
+                param.put("trust_name", info.getCompanyName());
+            }
+        }
+        String body = HttpUtil.post(pyBaseUrl + api, JSONUtil.toJsonStr(params));
+        PythonResult<T> result = PythonReportConverter.convert(JSONUtil.parseObj(body), reportType);
+        return result.getData();
     }
+
+    protected abstract ReportType getReportType();
 }

+ 25 - 0
service-daq/src/main/java/com/simuwang/daq/components/report/parser/py/PythonAnnuallyReportParser.java

@@ -0,0 +1,25 @@
+package com.simuwang.daq.components.report.parser.py;
+
+import com.simuwang.base.common.enums.ReportType;
+import com.simuwang.base.config.DaqProperties;
+import com.simuwang.base.mapper.FundInfoMapper;
+import com.simuwang.base.pojo.dto.report.AnnuallyReportData;
+import com.simuwang.daq.components.report.parser.ReportParserConstant;
+import org.springframework.stereotype.Component;
+
+@Component(ReportParserConstant.PARSER_PYTHON_ANNUALLY)
+public class PythonAnnuallyReportParser extends AbstractPyReportParser<AnnuallyReportData> {
+    public PythonAnnuallyReportParser(DaqProperties properties, FundInfoMapper fundInfoMapper) {
+        super(properties, fundInfoMapper);
+    }
+
+    @Override
+    protected ReportType getReportType() {
+        return ReportType.ANNUALLY;
+    }
+
+    @Override
+    public String getParser() {
+        return ReportParserConstant.PARSER_PYTHON_ANNUALLY;
+    }
+}

+ 11 - 0
service-daq/src/main/java/com/simuwang/daq/components/report/parser/py/PythonMonthlyReportParser.java

@@ -1,5 +1,6 @@
 package com.simuwang.daq.components.report.parser.py;
 
+import com.simuwang.base.common.enums.ReportType;
 import com.simuwang.base.config.DaqProperties;
 import com.simuwang.base.mapper.FundInfoMapper;
 import com.simuwang.base.pojo.dto.report.MonthlyReportData;
@@ -11,4 +12,14 @@ public class PythonMonthlyReportParser extends AbstractPyReportParser<MonthlyRep
     public PythonMonthlyReportParser(DaqProperties properties, FundInfoMapper fundInfoMapper) {
         super(properties, fundInfoMapper);
     }
+
+    @Override
+    protected ReportType getReportType() {
+        return ReportType.MONTHLY;
+    }
+
+    @Override
+    public String getParser() {
+        return ReportParserConstant.PARSER_PYTHON_MONTHLY;
+    }
 }

+ 25 - 0
service-daq/src/main/java/com/simuwang/daq/components/report/parser/py/PythonQuarterlyReportParser.java

@@ -0,0 +1,25 @@
+package com.simuwang.daq.components.report.parser.py;
+
+import com.simuwang.base.common.enums.ReportType;
+import com.simuwang.base.config.DaqProperties;
+import com.simuwang.base.mapper.FundInfoMapper;
+import com.simuwang.base.pojo.dto.report.QuarterlyReportData;
+import com.simuwang.daq.components.report.parser.ReportParserConstant;
+import org.springframework.stereotype.Component;
+
+@Component(ReportParserConstant.PARSER_PYTHON_QUARTERLY)
+public class PythonQuarterlyReportParser extends AbstractPyReportParser<QuarterlyReportData> {
+    public PythonQuarterlyReportParser(DaqProperties properties, FundInfoMapper fundInfoMapper) {
+        super(properties, fundInfoMapper);
+    }
+
+    @Override
+    protected ReportType getReportType() {
+        return ReportType.QUARTERLY;
+    }
+
+    @Override
+    public String getParser() {
+        return ReportParserConstant.PARSER_PYTHON_QUARTERLY;
+    }
+}

+ 14 - 31
service-daq/src/main/java/com/simuwang/daq/components/report/writer/AbstractReportWriter.java

@@ -1,6 +1,5 @@
 package com.simuwang.daq.components.report.writer;
 
-import cn.hutool.core.exceptions.ExceptionUtil;
 import com.simuwang.base.mapper.report.ReportBaseInfoMapper;
 import com.simuwang.base.mapper.report.ReportFundInfoMapper;
 import com.simuwang.base.pojo.dos.report.ReportBaseInfoDO;
@@ -11,7 +10,6 @@ import com.simuwang.base.pojo.dto.report.ReportFundInfoDTO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.StopWatch;
 
 public abstract class AbstractReportWriter<T extends ReportData> implements ReportWriter<T> {
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -27,45 +25,30 @@ public abstract class AbstractReportWriter<T extends ReportData> implements Repo
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void write(T reportData) {
-        StopWatch stopWatch = new StopWatch();
-        stopWatch.start();
+        if (reportData == null) {
+            this.logger.error("The report no result!");
+            return;
+        }
         // 基本信息+基金信息保存
         this.saveBaseInfo(reportData);
         this.saveFundInfo(reportData);
-        try {
-            // 其他信息保存
-            this.writeExtData(reportData);
-        } catch (Exception e) {
-            this.logger.error("报告解析结果之类型特有数据保存报错\n{}", ExceptionUtil.stacktraceToString(e));
-        }
-        stopWatch.stop();
-        long totalTimeMillis = stopWatch.getTotalTimeMillis();
-        if (this.logger.isInfoEnabled()) {
-            this.logger.info("报告解析结果保存成功,耗时:{}ms", totalTimeMillis);
-        }
+        // 其他信息保存
+        this.writeExtData(reportData);
     }
 
     private void saveBaseInfo(T reportData) {
-        try {
-            ReportBaseInfoDTO baseInfo = reportData.getBaseInfo();
-            if (baseInfo != null) {
-                ReportBaseInfoDO entity = baseInfo.toEntity();
-                this.baseInfoMapper.insert(entity);
-            }
-        } catch (Exception e) {
-            this.logger.error("报告解析结果之报告基本信息保存报错\n{}", ExceptionUtil.stacktraceToString(e));
+        ReportBaseInfoDTO baseInfo = reportData.getBaseInfo();
+        if (baseInfo != null) {
+            ReportBaseInfoDO entity = baseInfo.toEntity();
+            this.baseInfoMapper.insert(entity);
         }
     }
 
     private void saveFundInfo(T reportData) {
-        try {
-            ReportFundInfoDTO fundInfo = reportData.getFundInfo();
-            if (fundInfo != null) {
-                ReportFundInfoDO entity = fundInfo.toEntity();
-                this.fundInfoMapper.insert(entity);
-            }
-        } catch (Exception e) {
-            this.logger.error("报告解析结果之基金信息保存报错\n{}", ExceptionUtil.stacktraceToString(e));
+        ReportFundInfoDTO fundInfo = reportData.getFundInfo();
+        if (fundInfo != null) {
+            ReportFundInfoDO entity = fundInfo.toEntity();
+            this.fundInfoMapper.insert(entity);
         }
     }
 

+ 5 - 0
service-daq/src/main/java/com/simuwang/daq/components/report/writer/ReportWriter.java

@@ -2,6 +2,11 @@ package com.simuwang.daq.components.report.writer;
 
 import com.simuwang.base.pojo.dto.report.ReportData;
 
+/**
+ * @author wangzaijun
+ * @date 2024/9/29 14:06
+ * @description 报告存储保存的服务业务(可以扩展支持保存到本地缓存或文件)
+ */
 public interface ReportWriter<T extends ReportData> {
     void write(T reportData);
 }

+ 51 - 15
service-daq/src/main/java/com/simuwang/daq/service/EmailParseService.java

@@ -25,6 +25,7 @@ import com.simuwang.base.pojo.dto.report.ReportParserParams;
 import com.simuwang.base.pojo.valuation.CmValuationTableAttribute;
 import com.simuwang.daq.components.report.parser.ReportParser;
 import com.simuwang.daq.components.report.parser.ReportParserFactory;
+import com.simuwang.daq.components.report.writer.ReportWriter;
 import com.simuwang.daq.components.report.writer.ReportWriterFactory;
 import jakarta.mail.*;
 import jakarta.mail.internet.MimeMultipart;
@@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.util.StopWatch;
 
 import java.io.File;
 import java.math.BigDecimal;
@@ -87,7 +89,7 @@ public class EmailParseService {
                              EmailParseInfoMapper emailParseInfoMapper, EmailFileInfoMapper emailFileInfoMapper,
                              EmailFundNavMapper emailFundNavMapper, EmailFundAssetMapper emailFundAssetMapper,
                              AssetMapper assetMapper, NavMapper navMapper, FundService fundService,
-                             FundAliasMapper fundAliasMapper, DaqProperties properties,
+                             FundAliasMapper fundAliasMapper,
                              ValuationTableMapper valuationTableMapper, ValuationTableAttributeMapper valuationTableAttributeMapper,
                              FundPositionDetailMapper fundPositionDetailMapper) {
         this.emailTypeRuleMapper = emailTypeRuleMapper;
@@ -103,7 +105,6 @@ public class EmailParseService {
         this.fundService = fundService;
         this.fundAliasMapper = fundAliasMapper;
 
-        this.properties = properties;
         this.valuationTableMapper = valuationTableMapper;
         this.valuationTableAttributeMapper = valuationTableAttributeMapper;
         this.fundPositionDetailMapper = fundPositionDetailMapper;
@@ -185,12 +186,12 @@ public class EmailParseService {
             if (CollUtil.isEmpty(fundNavDTOList) && !Objects.equals(EmailTypeConst.REPORT_EMAIL_TYPE, emailType)) {
                 continue;
             }
-            // 解析结果(可以从python获取或者自行解析)
-            ReportData data = this.parseReportAndHandleResult(fileId, emailContentInfoDTO);
-            if (data != null) {
-                // 保存报告解析数据
-                this.reportWriterFactory.getInstance(data.getReportType()).write(data);
-                dataList.add(data);
+            if (Objects.equals(EmailTypeConst.REPORT_EMAIL_TYPE, emailType)) {
+                // 解析结果(可以从python获取或者自行解析)并保存报告
+                ReportData data = this.parseReportAndHandleResult(fileId, emailContentInfoDTO);
+                if (data != null) {
+                    dataList.add(data);
+                }
             }
             for (EmailFundNavDTO fundNavDTO : fundNavDTOList) {
                 // 设置净值数据的解析状态
@@ -354,11 +355,11 @@ public class EmailParseService {
         if (matcher.find()) {
             registerNumber = matcher.group();
         }
-        ReportType type = ReportType.MONTHLY;
+        ReportType reportType = ReportType.MONTHLY;
         if (fileName.contains(ReportType.QUARTERLY.getLabel())) {
-            type = ReportType.QUARTERLY;
+            reportType = ReportType.QUARTERLY;
         } else if (fileName.contains(ReportType.ANNUALLY.getLabel())) {
-            type = ReportType.ANNUALLY;
+            reportType = ReportType.ANNUALLY;
         }
         ReportParserFileType fileType;
         if (Objects.equals(Boolean.TRUE, this.properties.getEnablePyParser())) {
@@ -367,10 +368,45 @@ public class EmailParseService {
             String fileSuffix = StrUtil.subAfter(fileName, ".", true);
             fileType = ReportParserFileType.getBySuffix(fileSuffix);
         }
-        ReportParser<ReportData> instance = this.reportParserFactory.getInstance(type, fileType);
-        ReportParserParams params = ReportParserParams.builder().fileId(fileId).filename(fileName)
-                .filepath(emailContentInfoDTO.getFilePath()).registerNumber(registerNumber).build();
-        return instance.parse(params);
+        // 解析报告
+        ReportParserParams params = null;
+        ReportData reportData = null;
+        StopWatch parserWatch = new StopWatch();
+        parserWatch.start();
+        try {
+            params = ReportParserParams.builder().fileId(fileId).filename(fileName)
+                    .filepath(emailContentInfoDTO.getFilePath()).registerNumber(registerNumber).build();
+            ReportParser<ReportData> instance = this.reportParserFactory.getInstance(reportType, fileType);
+            reportData = instance.parse(params);
+            if (log.isInfoEnabled()) {
+                log.info("报告{}解析器{}的解析结果为:{}", params, instance.getParser(), reportData);
+            }
+        } catch (Exception e) {
+            log.error("报告{}解析失败\n{}", params, ExceptionUtil.stacktraceToString(e));
+        } finally {
+            parserWatch.stop();
+            if (log.isInfoEnabled()) {
+                log.info("报告{}解析完成,耗时{}ms", params, parserWatch.getTotalTimeMillis());
+            }
+        }
+        // 保存报告解析结果
+        StopWatch writeWatch = new StopWatch();
+        writeWatch.start();
+        try {
+            ReportWriter<ReportData> instance = this.reportWriterFactory.getInstance(reportType);
+            instance.write(reportData);
+            if (log.isInfoEnabled()) {
+                log.info("报告{}结果保存成功", params);
+            }
+        } catch (Exception e) {
+            log.error("报告{}结果保存失败\n{}", params, ExceptionUtil.stacktraceToString(e));
+        } finally {
+            writeWatch.stop();
+            if (log.isInfoEnabled()) {
+                log.info("报告{}解析结果保存完成,耗时{}ms", params, writeWatch.getTotalTimeMillis());
+            }
+        }
+        return reportData;
     }
 
     private void saveNavAndAssetNet(Integer fileId, List<EmailFundNavDTO> fundNavDTOList, Date parseDate) {

+ 3 - 2
service-daq/src/main/java/com/simuwang/daq/service/ReportEmailParser.java

@@ -12,7 +12,8 @@ import java.util.Map;
 /**
  * @author wangzaijun
  * @date 2024/9/25 14:52
- * @description 报告的解析逻辑,目前先调用python接口
+ * @description 报告的解析逻辑
+ * @see com.simuwang.daq.components.report.parser.ReportParser,com.simuwang.daq.components.report.parser.py.AbstractPyReportParser,com.simuwang.daq.components.report.parser.pdf.AbstractReportParser
  */
 @Component
 public class ReportEmailParser extends AbstractEmailParser {
@@ -24,7 +25,7 @@ public class ReportEmailParser extends AbstractEmailParser {
 
     @Override
     public List<EmailFundNavDTO> parse(EmailContentInfoDTO emailContentInfoDTO, Map<String, List<String>> emailFieldMap) {
-        // 目前啥也不做,调用python的逻辑在EmailParseService里写死,等java的逻辑完成后注释掉python逻辑
+        // 目前啥也不做,但是要返回空集合并且支持报告解析
         return ListUtil.empty();
     }
 }

+ 0 - 19
service-daq/src/main/java/com/simuwang/daq/service/ReportParseService.java

@@ -1,19 +0,0 @@
-package com.simuwang.daq.service;
-
-import com.simuwang.daq.components.report.parser.ReportParser;
-import org.springframework.stereotype.Service;
-
-@Service
-public class ReportParseService {
-    private final ReportParser parser;
-
-    public ReportParseService(ReportParser parser) {
-        this.parser = parser;
-    }
-
-    public void parse() {
-//        this.parser.parse(1, "D:\\Documents\\workspace\\idea\\smppw\\data-daq\\service-daq\\src\\main\\java\\com\\simuwang\\daq\\utils\\12931.pdf", "幻方量化1000指数专享1号5期私募证券投资基金宁波幻方量化投资管理合伙企业(有限合伙)");
-//        this.parser.parse(1, ,
-//                "D:\\Documents\\workspace\\idea\\smppw\\data-daq\\service-daq\\src\\main\\java\\com\\simuwang\\daq\\utils\\12931.pdf");
-    }
-}

+ 21 - 9
service-deploy/src/test/java/com/simuwang/ApplicationTest.java

@@ -25,13 +25,7 @@ public class ApplicationTest {
 
     @Test
     public void test() {
-        MailboxInfoDTO emailInfoDTO = new MailboxInfoDTO();
-        emailInfoDTO.setUserId(2395446);
-        emailInfoDTO.setAccount("mozuwen@simuwang.com");
-        emailInfoDTO.setPassword("Mzw@0306");
-        emailInfoDTO.setHost("imap.exmail.qq.com");
-        emailInfoDTO.setPort("993");
-        emailInfoDTO.setProtocol("imap");
+        MailboxInfoDTO emailInfoDTO = this.buildMailbox();
 //
 //        emailInfoDTO.setAccount("jjpj_test");
 //        emailInfoDTO.setPassword("shzq#919");
@@ -49,8 +43,15 @@ public class ApplicationTest {
     }
 
     @Test
-    public void pyTest() {
-
+    public void reportTest() {
+        MailboxInfoDTO emailInfoDTO = this.buildMailbox();
+        Date startDate = DateUtil.parse("2024-09-26 10:25:00", DateConst.YYYY_MM_DD_HH_MM_SS);
+        Date endDate = DateUtil.parse("2024-09-26 19:40:00", DateConst.YYYY_MM_DD_HH_MM_SS);
+        try {
+            emailParseService.parseEmail(emailInfoDTO, startDate, endDate);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
@@ -72,4 +73,15 @@ public class ApplicationTest {
             System.out.println(dateString + ": -> " + date);
         }
     }
+
+    private MailboxInfoDTO buildMailbox() {
+        MailboxInfoDTO emailInfoDTO = new MailboxInfoDTO();
+        emailInfoDTO.setUserId(2395446);
+        emailInfoDTO.setAccount("mozuwen@simuwang.com");
+        emailInfoDTO.setPassword("Mzw@0306");
+        emailInfoDTO.setHost("imap.exmail.qq.com");
+        emailInfoDTO.setPort("993");
+        emailInfoDTO.setProtocol("imap");
+        return emailInfoDTO;
+    }
 }

+ 0 - 21
service-manage/src/main/java/com/simuwang/manage/api/test/ReportParseTestApi.java

@@ -1,21 +0,0 @@
-package com.simuwang.manage.api.test;
-
-import com.simuwang.daq.service.ReportParseService;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-@RequestMapping("/v1/test/parse")
-public class ReportParseTestApi {
-    private final ReportParseService service;
-
-    public ReportParseTestApi(ReportParseService service) {
-        this.service = service;
-    }
-
-    @GetMapping("monthly")
-    public void monthly() {
-        this.service.parse();
-    }
-}