فهرست منبع

feat:报告解析优先接入python

wangzaijun 7 ماه پیش
والد
کامیت
5139a3f15b
43فایلهای تغییر یافته به همراه1346 افزوده شده و 272 حذف شده
  1. 18 0
      service-base/src/main/java/com/simuwang/base/common/enums/ReportType.java
  2. 14 2
      service-base/src/main/java/com/simuwang/base/components/MyBatisPlusMetaObjectHandler.java
  3. 0 5
      service-base/src/main/java/com/simuwang/base/config/DaqProperties.java
  4. 3 0
      service-base/src/main/java/com/simuwang/base/mapper/FundInfoMapper.java
  5. 9 0
      service-base/src/main/java/com/simuwang/base/mapper/report/ReportAssetAllocationMapper.java
  6. 9 0
      service-base/src/main/java/com/simuwang/base/mapper/report/ReportBaseInfoMapper.java
  7. 9 0
      service-base/src/main/java/com/simuwang/base/mapper/report/ReportFinancialIndicatorMapper.java
  8. 9 0
      service-base/src/main/java/com/simuwang/base/mapper/report/ReportFundInfoMapper.java
  9. 9 0
      service-base/src/main/java/com/simuwang/base/mapper/report/ReportInvestmentIndustryMapper.java
  10. 9 0
      service-base/src/main/java/com/simuwang/base/mapper/report/ReportNetReportMapper.java
  11. 9 0
      service-base/src/main/java/com/simuwang/base/mapper/report/ReportShareChangeMapper.java
  12. 14 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/FundAndCompanyInfoDO.java
  13. 24 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/report/BaseReportDO.java
  14. 34 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportAssetAllocationDO.java
  15. 28 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportBaseInfoDO.java
  16. 22 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportFinancialIndicatorDO.java
  17. 37 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportFundInfoDO.java
  18. 42 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportInvestmentIndustryDO.java
  19. 38 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportNetReportDO.java
  20. 42 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportShareChangeDO.java
  21. 13 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/BaseReportDTO.java
  22. 18 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/MonthlyReportData.java
  23. 14 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/PythonResult.java
  24. 26 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/QuarterlyReportData.java
  25. 43 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportAssetAllocationDTO.java
  26. 37 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportBaseInfoDTO.java
  27. 17 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportData.java
  28. 36 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportFinancialIndicatorDTO.java
  29. 60 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportFundInfoDTO.java
  30. 54 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportInvestmentIndustryDTO.java
  31. 50 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportNetReportDTO.java
  32. 54 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportShareChangeDTO.java
  33. 12 0
      service-base/src/main/resources/mapper/FundInfoMapper.xml
  34. 65 0
      service-daq/src/main/java/com/simuwang/daq/components/writer/AbstractReportWriter.java
  35. 34 0
      service-daq/src/main/java/com/simuwang/daq/components/writer/MonthlyReportWriter.java
  36. 62 0
      service-daq/src/main/java/com/simuwang/daq/components/writer/QuarterlyReportWriter.java
  37. 7 0
      service-daq/src/main/java/com/simuwang/daq/components/writer/ReportWriter.java
  38. 20 0
      service-daq/src/main/java/com/simuwang/daq/components/writer/ReportWriterConstant.java
  39. 26 0
      service-daq/src/main/java/com/simuwang/daq/components/writer/ReportWriterFactory.java
  40. 46 20
      service-daq/src/main/java/com/simuwang/daq/service/EmailParseService.java
  41. 266 241
      service-daq/src/main/java/com/simuwang/daq/utils/ReportParseUtil.java
  42. 2 4
      service-deploy/src/main/resources/application.yml
  43. 5 0
      service-deploy/src/test/java/com/simuwang/ApplicationTest.java

+ 18 - 0
service-base/src/main/java/com/simuwang/base/common/enums/ReportType.java

@@ -0,0 +1,18 @@
+package com.simuwang.base.common.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum ReportType {
+    MONTHLY(0, "月报"),
+    QUARTERLY(1, "季报"),
+    ANNUALLY(2, "年报");
+
+    private final int type;
+    private final String label;
+
+    ReportType(int type, String label) {
+        this.type = type;
+        this.label = label;
+    }
+}

+ 14 - 2
service-base/src/main/java/com/simuwang/base/components/MyBatisPlusMetaObjectHandler.java

@@ -15,7 +15,7 @@ import java.util.Date;
 public class MyBatisPlusMetaObjectHandler implements MetaObjectHandler {
     @Override
     public void insertFill(MetaObject metaObject) {
-        ShiroUser loginUser = UserUtils.getLoginUser();
+        ShiroUser loginUser = this.getCurrentUser();
         this.setFieldValByName("creatorId", loginUser.getUserId(), metaObject);
         this.strictInsertFill(metaObject, "createTime", Date::new, Date.class);
         if (metaObject.hasGetter("valid")) {
@@ -31,8 +31,20 @@ public class MyBatisPlusMetaObjectHandler implements MetaObjectHandler {
 
     @Override
     public void updateFill(MetaObject metaObject) {
-        ShiroUser loginUser = UserUtils.getLoginUser();
+        ShiroUser loginUser = this.getCurrentUser();
         this.setFieldValByName("updaterId", loginUser.getUserId(), metaObject);
         this.strictUpdateFill(metaObject, "updateTime", Date::new, Date.class);
     }
+
+    private ShiroUser getCurrentUser() {
+        ShiroUser loginUser;
+        try {
+            loginUser = UserUtils.getLoginUser();
+        } catch (Exception ignored) {
+            // 主要防止任务执行的时候获取不到用户信息报错
+            loginUser = new ShiroUser();
+            loginUser.setUserId(0);
+        }
+        return loginUser;
+    }
 }

+ 0 - 5
service-base/src/main/java/com/simuwang/base/config/DaqProperties.java

@@ -15,11 +15,6 @@ import java.util.List;
 @ConfigurationProperties(prefix = DaqProperties.DAQ_CONFIG_PREFIX)
 public class DaqProperties {
     public static final String DAQ_CONFIG_PREFIX = "simuwang";
-
-    /**
-     * 是否启用quartz定时任务功能
-     */
-    private Boolean enableQuartz = Boolean.FALSE;
     /**
      * 是否启用操作日志记录功能
      */

+ 3 - 0
service-base/src/main/java/com/simuwang/base/mapper/FundInfoMapper.java

@@ -1,5 +1,6 @@
 package com.simuwang.base.mapper;
 
+import com.simuwang.base.pojo.dos.FundAndCompanyInfoDO;
 import com.simuwang.base.pojo.dos.FundInfoDO;
 import com.simuwang.base.pojo.dto.query.FundInfoPageQuery;
 import com.simuwang.base.pojo.dto.query.FundInputPageQuery;
@@ -28,6 +29,8 @@ public interface FundInfoMapper {
 
     List<FundInfoDO> queryFundByRegisterNumber(@Param("registerNumber") String registerNumber);
 
+    FundAndCompanyInfoDO queryFundAndTrustByRegisterNumber(String registerNumber);
+
     long countFundInfoByKeyword(FundInputPageQuery fundInputPageQuery);
 
     long countFundInfo(FundInfoPageQuery fundInfoPageQuery);

+ 9 - 0
service-base/src/main/java/com/simuwang/base/mapper/report/ReportAssetAllocationMapper.java

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

+ 9 - 0
service-base/src/main/java/com/simuwang/base/mapper/report/ReportBaseInfoMapper.java

@@ -0,0 +1,9 @@
+package com.simuwang.base.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.simuwang.base.pojo.dos.report.ReportBaseInfoDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportBaseInfoMapper extends BaseMapper<ReportBaseInfoDO> {
+}

+ 9 - 0
service-base/src/main/java/com/simuwang/base/mapper/report/ReportFinancialIndicatorMapper.java

@@ -0,0 +1,9 @@
+package com.simuwang.base.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.simuwang.base.pojo.dos.report.ReportFinancialIndicatorDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportFinancialIndicatorMapper extends BaseMapper<ReportFinancialIndicatorDO> {
+}

+ 9 - 0
service-base/src/main/java/com/simuwang/base/mapper/report/ReportFundInfoMapper.java

@@ -0,0 +1,9 @@
+package com.simuwang.base.mapper.report;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.simuwang.base.pojo.dos.report.ReportFundInfoDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ReportFundInfoMapper extends BaseMapper<ReportFundInfoDO> {
+}

+ 9 - 0
service-base/src/main/java/com/simuwang/base/mapper/report/ReportInvestmentIndustryMapper.java

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

+ 9 - 0
service-base/src/main/java/com/simuwang/base/mapper/report/ReportNetReportMapper.java

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

+ 9 - 0
service-base/src/main/java/com/simuwang/base/mapper/report/ReportShareChangeMapper.java

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

+ 14 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/FundAndCompanyInfoDO.java

@@ -0,0 +1,14 @@
+package com.simuwang.base.pojo.dos;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class FundAndCompanyInfoDO {
+    private String fundId;
+    private String fundName;
+    private String fundShortName;
+    private String companyId;
+    private String companyName;
+}

+ 24 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/report/BaseReportDO.java

@@ -0,0 +1,24 @@
+package com.simuwang.base.pojo.dos.report;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.simuwang.base.common.exception.APIException;
+import com.simuwang.base.common.support.dos.DataEntity;
+import com.simuwang.base.common.support.vo.BaseVO;
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public abstract class BaseReportDO extends DataEntity<BaseVO> {
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    private Integer fileId;
+
+    @Override
+    public BaseVO toVo() {
+        // 没有转换为VO对象的逻辑
+        throw new APIException("not impl");
+    }
+}

+ 34 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportAssetAllocationDO.java

@@ -0,0 +1,34 @@
+package com.simuwang.base.pojo.dos.report;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:43
+ * @description 基金资产组合情况
+ */
+@Setter
+@Getter
+@TableName("amac_report_asset_allocation")
+public class ReportAssetAllocationDO extends BaseReportDO {
+    /**
+     * 资产类别
+     */
+    private String assetType;
+    /**
+     * 资产类别
+     */
+    private String columnName;
+    /**
+     * 资产类别
+     */
+    private BigDecimal marketValue;
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 28 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportBaseInfoDO.java

@@ -0,0 +1,28 @@
+package com.simuwang.base.pojo.dos.report;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:44
+ * @description 基协报告基础信息表
+ */
+@Setter
+@Getter
+@TableName("amac_report_base_info")
+public class ReportBaseInfoDO extends BaseReportDO {
+    /**
+     * 报告日期
+     */
+    private String reportDate;
+    /**
+     * 报告名称
+     */
+    private String reportName;
+    /**
+     * 报告类型
+     */
+    private String reportType;
+}

+ 22 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportFinancialIndicatorDO.java

@@ -0,0 +1,22 @@
+package com.simuwang.base.pojo.dos.report;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+@Setter
+@Getter
+@TableName("amac_report_financial_indicators")
+public class ReportFinancialIndicatorDO extends BaseReportDO {
+    private String level;
+    /**
+     * 年度
+     */
+    private Integer endDate;
+    private BigDecimal fundAssetSize;
+    private BigDecimal nav;
+    private BigDecimal profit;
+    private BigDecimal realizedIncome;
+}

+ 37 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportFundInfoDO.java

@@ -0,0 +1,37 @@
+package com.simuwang.base.pojo.dos.report;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:47
+ * @description 报告基金基本信息
+ */
+@Setter
+@Getter
+@TableName("amac_report_fund_info")
+public class ReportFundInfoDO extends BaseReportDO {
+    private String advisorName;
+    private String custodianName;
+    private String fundManager;
+    private String fundName;
+    private String fundStrategyDescription;
+    private Date inceptionDate;
+    private String industryTrend;
+    private String investmentObjective;
+    private BigDecimal leverage;
+    private String leverageNote;
+    private String operationType;
+    private String registerNumber;
+    private String riskReturnDesc;
+    private String secondaryBenchmark;
+    private String trustName;
+
+    private String dueDate;
+    private String isReviewed;
+}

+ 42 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportInvestmentIndustryDO.java

@@ -0,0 +1,42 @@
+package com.simuwang.base.pojo.dos.report;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:49
+ * @description 按行业分类的股票投资组合
+ */
+@Setter
+@Getter
+@TableName("amac_report_invest_industry")
+public class ReportInvestmentIndustryDO extends BaseReportDO {
+    /**
+     * 行业分类编码
+     */
+    private String industryCode;
+    /**
+     * 行业分类名称
+     */
+    private String industryName;
+    /**
+     * 投资地区: 1-境内, 2-港股通
+     */
+    private Integer investType;
+    /**
+     * 行业标准编码
+     */
+    private String isbCode;
+    /**
+     * 公允价值
+     */
+    private BigDecimal marketValue;
+    /**
+     * 占基金资产净值的比例
+     */
+    private BigDecimal ratio;
+}

+ 38 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportNetReportDO.java

@@ -0,0 +1,38 @@
+package com.simuwang.base.pojo.dos.report;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:53
+ * @description 基协报告净值月报
+ */
+@Setter
+@Getter
+@TableName("amac_report_net_report")
+public class ReportNetReportDO extends BaseReportDO {
+    private String level;
+    private Date valuationDate;
+
+    /**
+     * 累计净值
+     */
+    private BigDecimal cumulativeNav;
+    /**
+     * 基金份额总额
+     */
+    private BigDecimal endTotalShares;
+    /**
+     * 基金资产净值
+     */
+    private BigDecimal fundAssetSize;
+    /**
+     * 单位净值
+     */
+    private BigDecimal nav;
+}

+ 42 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/report/ReportShareChangeDO.java

@@ -0,0 +1,42 @@
+package com.simuwang.base.pojo.dos.report;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:40
+ * @description 基金份额变动情况
+ */
+@Setter
+@Getter
+@TableName("amac_report_share_change")
+public class ReportShareChangeDO extends BaseReportDO {
+    /**
+     * 报告期期初基金份额总额
+     */
+    private BigDecimal initTotalShares;
+    /**
+     * 基金分级
+     */
+    private String level;
+    /**
+     * 减: 报告期期间基金总赎回份额
+     */
+    private BigDecimal redemption;
+    /**
+     * 期末基金总份额/期末基金实缴总额
+     */
+    private BigDecimal sharePerAsset;
+    /**
+     * 报告期期间基金拆分变动份额
+     */
+    private BigDecimal split;
+    /**
+     * 报告期期间基金总申购份额
+     */
+    private BigDecimal subscription;
+}

+ 13 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/BaseReportDTO.java

@@ -0,0 +1,13 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.pojo.dos.report.BaseReportDO;
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public abstract class BaseReportDTO<T extends BaseReportDO> {
+    private Integer fileId;
+
+    public abstract T toEntity();
+}

+ 18 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/MonthlyReportData.java

@@ -0,0 +1,18 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.common.enums.ReportType;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Setter
+@Getter
+public class MonthlyReportData extends ReportData {
+    private List<ReportNetReportDTO> netReport;
+
+    @Override
+    public ReportType getReportType() {
+        return ReportType.MONTHLY;
+    }
+}

+ 14 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/PythonResult.java

@@ -0,0 +1,14 @@
+package com.simuwang.base.pojo.dto.report;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class PythonResult<T extends ReportData> {
+    private Integer status;
+
+    private String msg;
+
+    private T data;
+}

+ 26 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/QuarterlyReportData.java

@@ -0,0 +1,26 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.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<ReportFinancialIndicatorDTO> financialIndicators;
+    private List<ReportInvestmentIndustryDTO> investmentIndustry;
+    private List<ReportShareChangeDTO> shareChange;
+
+    @Override
+    public ReportType getReportType() {
+        return ReportType.QUARTERLY;
+    }
+}

+ 43 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportAssetAllocationDTO.java

@@ -0,0 +1,43 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.pojo.dos.report.ReportAssetAllocationDO;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:43
+ * @description 基金资产组合情况
+ */
+@Setter
+@Getter
+public class ReportAssetAllocationDTO extends BaseReportDTO<ReportAssetAllocationDO> {
+    /**
+     * 资产类别
+     */
+    private String assetType;
+    /**
+     * 资产类别
+     */
+    private String columnName;
+    /**
+     * 资产类别
+     */
+    private BigDecimal marketValue;
+    /**
+     * 备注
+     */
+    private String remark;
+
+    @Override
+    public ReportAssetAllocationDO toEntity() {
+        ReportAssetAllocationDO entity = new ReportAssetAllocationDO();
+        entity.setFileId(this.getFileId());
+        entity.setAssetType(this.assetType);
+        entity.setMarketValue(this.marketValue);
+        entity.setRemark(this.remark);
+        return entity;
+    }
+}

+ 37 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportBaseInfoDTO.java

@@ -0,0 +1,37 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.pojo.dos.report.ReportBaseInfoDO;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:44
+ * @description 基协报告基础信息表
+ */
+@Setter
+@Getter
+public class ReportBaseInfoDTO extends BaseReportDTO<ReportBaseInfoDO> {
+    /**
+     * 报告日期
+     */
+    private String reportDate;
+    /**
+     * 报告名称
+     */
+    private String reportName;
+    /**
+     * 报告类型
+     */
+    private String reportType;
+
+    @Override
+    public ReportBaseInfoDO toEntity() {
+        ReportBaseInfoDO entity = new ReportBaseInfoDO();
+        entity.setFileId(this.getFileId());
+        entity.setReportDate(this.reportDate);
+        entity.setReportName(this.reportName);
+        entity.setReportType(this.reportType);
+        return entity;
+    }
+}

+ 17 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportData.java

@@ -0,0 +1,17 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.common.enums.ReportType;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Setter
+@Getter
+public abstract class ReportData {
+    public abstract ReportType getReportType();
+
+    private List<ReportBaseInfoDTO> baseInfo;
+
+    private List<ReportFundInfoDTO> fundInfo;
+}

+ 36 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportFinancialIndicatorDTO.java

@@ -0,0 +1,36 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.pojo.dos.report.ReportFinancialIndicatorDO;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+@Setter
+@Getter
+public class ReportFinancialIndicatorDTO extends BaseReportDTO<ReportFinancialIndicatorDO> {
+    private String level;
+
+    /**
+     * 年度
+     */
+    private Integer endDate;
+
+    private BigDecimal fundAssetSize;
+    private BigDecimal nav;
+    private BigDecimal profit;
+    private BigDecimal realizedIncome;
+
+    @Override
+    public ReportFinancialIndicatorDO toEntity() {
+        ReportFinancialIndicatorDO entity = new ReportFinancialIndicatorDO();
+        entity.setFileId(this.getFileId());
+        entity.setLevel(this.level);
+        entity.setEndDate(this.endDate);
+        entity.setFundAssetSize(this.fundAssetSize);
+        entity.setNav(this.nav);
+        entity.setProfit(this.profit);
+        entity.setRealizedIncome(this.realizedIncome);
+        return entity;
+    }
+}

+ 60 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportFundInfoDTO.java

@@ -0,0 +1,60 @@
+package com.simuwang.base.pojo.dto.report;
+
+import cn.hutool.core.date.DateUtil;
+import com.simuwang.base.pojo.dos.report.ReportFundInfoDO;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:47
+ * @description 报告基金基本信息
+ */
+@Setter
+@Getter
+public class ReportFundInfoDTO extends BaseReportDTO<ReportFundInfoDO> {
+    private String advisorName;
+    private String custodianName;
+    private String fundManager;
+    private String fundName;
+    private String fundStrategyDescription;
+    private String inceptionDate;
+    private String industryTrend;
+    private String investmentObjective;
+    private BigDecimal leverage;
+    private String leverageNote;
+    private String operationType;
+    private String registerNumber;
+    private String riskReturnDesc;
+    private String secondaryBenchmark;
+    private String trustName;
+
+    private String dueDate;
+    private String isReviewed;
+
+    @Override
+    public ReportFundInfoDO toEntity() {
+        ReportFundInfoDO entity = new ReportFundInfoDO();
+        entity.setFileId(this.getFileId());
+        entity.setAdvisorName(this.advisorName);
+        entity.setCustodianName(this.custodianName);
+        entity.setFundManager(this.fundManager);
+        entity.setFundName(this.fundName);
+        entity.setFundStrategyDescription(this.fundStrategyDescription);
+        entity.setInceptionDate(this.inceptionDate == null ? null : DateUtil.parseDate(this.inceptionDate));
+        entity.setIndustryTrend(this.industryTrend);
+        entity.setInvestmentObjective(this.investmentObjective);
+        entity.setLeverage(this.leverage);
+        entity.setLeverageNote(this.leverageNote);
+        entity.setOperationType(this.operationType);
+        entity.setRegisterNumber(this.registerNumber);
+        entity.setRiskReturnDesc(this.riskReturnDesc);
+        entity.setSecondaryBenchmark(this.secondaryBenchmark);
+        entity.setTrustName(this.trustName);
+        entity.setDueDate(this.dueDate);
+        entity.setIsReviewed(this.isReviewed);
+        return entity;
+    }
+}

+ 54 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportInvestmentIndustryDTO.java

@@ -0,0 +1,54 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.pojo.dos.report.ReportInvestmentIndustryDO;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:49
+ * @description 按行业分类的股票投资组合
+ */
+@Setter
+@Getter
+public class ReportInvestmentIndustryDTO extends BaseReportDTO<ReportInvestmentIndustryDO> {
+    /**
+     * 行业分类编码
+     */
+    private String industryCode;
+    /**
+     * 行业分类名称
+     */
+    private String industryName;
+    /**
+     * 投资地区: 1-境内, 2-港股通
+     */
+    private Integer investType;
+    /**
+     * 行业标准编码
+     */
+    private String isbCode;
+    /**
+     * 公允价值
+     */
+    private BigDecimal marketValue;
+    /**
+     * 占基金资产净值的比例
+     */
+    private BigDecimal ratio;
+
+    @Override
+    public ReportInvestmentIndustryDO toEntity() {
+        ReportInvestmentIndustryDO entity = new ReportInvestmentIndustryDO();
+        entity.setFileId(this.getFileId());
+        entity.setIndustryCode(this.industryCode);
+        entity.setIndustryName(this.industryName);
+        entity.setInvestType(this.investType);
+        entity.setIsbCode(this.isbCode);
+        entity.setMarketValue(this.marketValue);
+        entity.setRatio(this.ratio);
+        return entity;
+    }
+}

+ 50 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportNetReportDTO.java

@@ -0,0 +1,50 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.pojo.dos.report.ReportNetReportDO;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:53
+ * @description 基协报告净值月报
+ */
+@Setter
+@Getter
+public class ReportNetReportDTO extends BaseReportDTO<ReportNetReportDO> {
+    private String level;
+    private Date valuationDate;
+
+    /**
+     * 累计净值
+     */
+    private BigDecimal cumulativeNav;
+    /**
+     * 基金份额总额
+     */
+    private BigDecimal endTotalShares;
+    /**
+     * 基金资产净值
+     */
+    private BigDecimal fundAssetSize;
+    /**
+     * 单位净值
+     */
+    private BigDecimal nav;
+
+    @Override
+    public ReportNetReportDO toEntity() {
+        ReportNetReportDO entity = new ReportNetReportDO();
+        entity.setFileId(this.getFileId());
+        entity.setLevel(this.level);
+        entity.setValuationDate(this.valuationDate);
+        entity.setCumulativeNav(this.cumulativeNav);
+        entity.setEndTotalShares(this.endTotalShares);
+        entity.setFundAssetSize(this.fundAssetSize);
+        entity.setNav(this.nav);
+        return entity;
+    }
+}

+ 54 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/report/ReportShareChangeDTO.java

@@ -0,0 +1,54 @@
+package com.simuwang.base.pojo.dto.report;
+
+import com.simuwang.base.pojo.dos.report.ReportShareChangeDO;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wangzaijun
+ * @date 2024/9/26 16:40
+ * @description 基金份额变动情况
+ */
+@Setter
+@Getter
+public class ReportShareChangeDTO extends BaseReportDTO<ReportShareChangeDO> {
+    /**
+     * 报告期期初基金份额总额
+     */
+    private BigDecimal initTotalShares;
+    /**
+     * 基金分级
+     */
+    private String level;
+    /**
+     * 减: 报告期期间基金总赎回份额
+     */
+    private BigDecimal redemption;
+    /**
+     * 期末基金总份额/期末基金实缴总额
+     */
+    private BigDecimal sharePerAsset;
+    /**
+     * 报告期期间基金拆分变动份额
+     */
+    private BigDecimal split;
+    /**
+     * 报告期期间基金总申购份额
+     */
+    private BigDecimal subscription;
+
+    @Override
+    public ReportShareChangeDO toEntity() {
+        ReportShareChangeDO entity = new ReportShareChangeDO();
+        entity.setFileId(this.getFileId());
+        entity.setLevel(this.level);
+        entity.setRedemption(this.redemption);
+        entity.setInitTotalShares(this.initTotalShares);
+        entity.setSharePerAsset(this.sharePerAsset);
+        entity.setSplit(this.split);
+        entity.setSubscription(this.subscription);
+        return entity;
+    }
+}

+ 12 - 0
service-base/src/main/resources/mapper/FundInfoMapper.xml

@@ -169,4 +169,16 @@
         select inception_date from PPW_EMAIL.pvn_fund_info where fund_id=#{fundId} and isvalid=1
     </select>
 
+    <select id="queryFundAndTrustByRegisterNumber" resultType="com.simuwang.base.pojo.dos.FundAndCompanyInfoDO">
+        select t.fund_id         as fundId,
+               t.fund_name       as fundName,
+               t.register_number as registerNumber,
+               t1.company_id as companyId,
+               t1.company_name as companyName
+        from PPW_EMAIL.pvn_fund_info t
+            left join PPW_EMAIL.pvn_company_info t1 on t1.isvalid = 1 and t1.company_id = t.trust_id
+        where t.isvalid = 1
+          and t.register_number = #{registerNumber}
+        limit 1
+    </select>
 </mapper>

+ 65 - 0
service-daq/src/main/java/com/simuwang/daq/components/writer/AbstractReportWriter.java

@@ -0,0 +1,65 @@
+package com.simuwang.daq.components.writer;
+
+import cn.hutool.core.collection.CollUtil;
+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;
+import com.simuwang.base.pojo.dos.report.ReportFundInfoDO;
+import com.simuwang.base.pojo.dto.report.ReportBaseInfoDTO;
+import com.simuwang.base.pojo.dto.report.ReportData;
+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;
+
+import java.util.List;
+
+public abstract class AbstractReportWriter<T extends ReportData> implements ReportWriter<T> {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    private final ReportBaseInfoMapper baseInfoMapper;
+    private final ReportFundInfoMapper fundInfoMapper;
+
+    public AbstractReportWriter(ReportBaseInfoMapper baseInfoMapper, ReportFundInfoMapper fundInfoMapper) {
+        this.baseInfoMapper = baseInfoMapper;
+        this.fundInfoMapper = fundInfoMapper;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void write(T reportData) {
+        StopWatch stopWatch = new StopWatch();
+        stopWatch.start();
+        try {
+            // 基本信息+基金信息保存
+            List<ReportBaseInfoDTO> baseInfos = reportData.getBaseInfo();
+            if (CollUtil.isNotEmpty(baseInfos)) {
+                ReportBaseInfoDO entity = baseInfos.get(0).toEntity();
+                this.baseInfoMapper.insert(entity);
+            }
+            List<ReportFundInfoDTO> fundInfos = reportData.getFundInfo();
+            if (CollUtil.isNotEmpty(fundInfos)) {
+                ReportFundInfoDO entity = fundInfos.get(0).toEntity();
+                this.fundInfoMapper.insert(entity);
+            }
+            try {
+                // 其他信息保存
+                this.writeExtData(reportData);
+            } catch (Exception e) {
+                this.logger.warn("报告解析结果之类型特有数据保存报错\n{}", ExceptionUtil.stacktraceToString(e));
+            }
+        } catch (Exception e) {
+            this.logger.error("报告解析结果保存错误\n{}", ExceptionUtil.stacktraceToString(e));
+        } finally {
+            stopWatch.stop();
+            long totalTimeMillis = stopWatch.getTotalTimeMillis();
+            if (this.logger.isInfoEnabled()) {
+                this.logger.info("报告解析结果保存成功,耗时:{}ms", totalTimeMillis);
+            }
+        }
+    }
+
+    protected abstract void writeExtData(T reportData);
+}

+ 34 - 0
service-daq/src/main/java/com/simuwang/daq/components/writer/MonthlyReportWriter.java

@@ -0,0 +1,34 @@
+package com.simuwang.daq.components.writer;
+
+import cn.hutool.core.collection.CollUtil;
+import com.simuwang.base.mapper.report.ReportBaseInfoMapper;
+import com.simuwang.base.mapper.report.ReportFundInfoMapper;
+import com.simuwang.base.mapper.report.ReportNetReportMapper;
+import com.simuwang.base.pojo.dos.report.ReportNetReportDO;
+import com.simuwang.base.pojo.dto.report.MonthlyReportData;
+import com.simuwang.base.pojo.dto.report.ReportNetReportDTO;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component(ReportWriterConstant.WRITER_MONTHLY)
+public class MonthlyReportWriter extends AbstractReportWriter<MonthlyReportData> {
+    private final ReportNetReportMapper netReportMapper;
+
+    public MonthlyReportWriter(ReportBaseInfoMapper baseInfoMapper,
+                               ReportFundInfoMapper fundInfoMapper,
+                               ReportNetReportMapper netReportMapper) {
+        super(baseInfoMapper, fundInfoMapper);
+        this.netReportMapper = netReportMapper;
+    }
+
+    @Override
+    protected void writeExtData(MonthlyReportData 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);
+        }
+    }
+}

+ 62 - 0
service-daq/src/main/java/com/simuwang/daq/components/writer/QuarterlyReportWriter.java

@@ -0,0 +1,62 @@
+package com.simuwang.daq.components.writer;
+
+import cn.hutool.core.collection.CollUtil;
+import com.simuwang.base.mapper.report.*;
+import com.simuwang.base.pojo.dos.report.ReportAssetAllocationDO;
+import com.simuwang.base.pojo.dos.report.ReportFinancialIndicatorDO;
+import com.simuwang.base.pojo.dos.report.ReportInvestmentIndustryDO;
+import com.simuwang.base.pojo.dos.report.ReportShareChangeDO;
+import com.simuwang.base.pojo.dto.report.*;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component(ReportWriterConstant.WRITER_QUARTERLY)
+public class QuarterlyReportWriter extends AbstractReportWriter<QuarterlyReportData> {
+    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<ReportFinancialIndicatorDTO> financialIndicators = reportData.getFinancialIndicators();
+        if (CollUtil.isNotEmpty(financialIndicators)) {
+            List<ReportFinancialIndicatorDO> entityList = financialIndicators.stream()
+                    .map(ReportFinancialIndicatorDTO::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);
+        }
+    }
+}

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

@@ -0,0 +1,7 @@
+package com.simuwang.daq.components.writer;
+
+import com.simuwang.base.pojo.dto.report.ReportData;
+
+public interface ReportWriter<T extends ReportData> {
+    void write(T reportData);
+}

+ 20 - 0
service-daq/src/main/java/com/simuwang/daq/components/writer/ReportWriterConstant.java

@@ -0,0 +1,20 @@
+package com.simuwang.daq.components.writer;
+
+import cn.hutool.core.map.MapUtil;
+import com.simuwang.base.common.enums.ReportType;
+
+import java.util.Map;
+
+public final class ReportWriterConstant {
+    public static final Map<ReportType, String> REPORT_TYPE_BEAN_MAP = MapUtil.newHashMap(8);
+
+    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 {
+        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);
+    }
+}

+ 26 - 0
service-daq/src/main/java/com/simuwang/daq/components/writer/ReportWriterFactory.java

@@ -0,0 +1,26 @@
+package com.simuwang.daq.components.writer;
+
+import cn.hutool.core.map.MapUtil;
+import com.simuwang.base.common.enums.ReportType;
+import com.simuwang.base.pojo.dto.report.ReportData;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+@Component
+public class ReportWriterFactory {
+    private static final ReportWriter<?> DEFAULT = (ReportWriter<ReportData>) reportData -> {
+    };
+
+    private static final Map<String, ReportWriter<? extends ReportData>> REPORT_WRITER_MAP = MapUtil.newHashMap(8);
+
+    public ReportWriterFactory(Map<String, ReportWriter<? extends ReportData>> components) {
+        REPORT_WRITER_MAP.putAll(components);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T extends ReportData> ReportWriter<T> getInstance(ReportType reportType) {
+        String beanName = ReportWriterConstant.REPORT_TYPE_BEAN_MAP.get(reportType);
+        return (ReportWriter<T>) REPORT_WRITER_MAP.getOrDefault(beanName, DEFAULT);
+    }
+}

+ 46 - 20
service-daq/src/main/java/com/simuwang/daq/service/EmailParseService.java

@@ -8,12 +8,11 @@ import cn.hutool.core.exceptions.ExceptionUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
-import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.simuwang.base.common.conts.DateConst;
 import com.simuwang.base.common.conts.EmailParseStatusConst;
-import com.simuwang.base.common.conts.NavParseStatusConst;
 import com.simuwang.base.common.conts.EmailTypeConst;
+import com.simuwang.base.common.conts.NavParseStatusConst;
 import com.simuwang.base.common.util.EmailUtil;
 import com.simuwang.base.common.util.FileUtil;
 import com.simuwang.base.config.DaqProperties;
@@ -23,6 +22,9 @@ import com.simuwang.base.pojo.dos.*;
 import com.simuwang.base.pojo.dto.EmailContentInfoDTO;
 import com.simuwang.base.pojo.dto.EmailFundNavDTO;
 import com.simuwang.base.pojo.dto.MailboxInfoDTO;
+import com.simuwang.base.pojo.dto.report.PythonResult;
+import com.simuwang.base.pojo.dto.report.ReportData;
+import com.simuwang.daq.components.writer.ReportWriterFactory;
 import jakarta.mail.*;
 import jakarta.mail.internet.MimeMultipart;
 import jakarta.mail.search.ComparisonTerm;
@@ -30,6 +32,7 @@ import jakarta.mail.search.ReceivedDateTerm;
 import jakarta.mail.search.SearchTerm;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
@@ -50,9 +53,6 @@ public class EmailParseService {
 
     private static final Logger log = LoggerFactory.getLogger(EmailParseService.class);
 
-    @Value("${email.file.path}")
-    private String path;
-
     private final String pyBaseUrl;
 
     private final EmailTypeRuleMapper emailTypeRuleMapper;
@@ -68,6 +68,14 @@ public class EmailParseService {
     private final FundService fundService;
     private final FundAliasMapper fundAliasMapper;
 
+
+    @Value("${email.file.path}")
+    private String path;
+    @Autowired
+    private FundInfoMapper fundInfoMapper;
+    @Autowired
+    private ReportWriterFactory reportWriterFactory;
+
     public EmailParseService(EmailTypeRuleMapper emailTypeRuleMapper, EmailRuleConfig emailRuleConfig,
                              EmailFieldMappingMapper emailFieldMapper, EmailParserFactory emailParserFactory,
                              EmailParseInfoMapper emailParseInfoMapper, EmailFileInfoMapper emailFileInfoMapper,
@@ -152,7 +160,7 @@ public class EmailParseService {
         emailId = saveEmailParseInfo(emailParseInfoDO);
 
         // python 报告解析接口结果
-        List<PythonData> dataList = ListUtil.list(false);
+        List<ReportData> dataList = ListUtil.list(false);
         for (Map.Entry<EmailContentInfoDTO, List<EmailFundNavDTO>> fileNameNavEntry : fileNameNavMap.entrySet()) {
             // 保存邮件文件表
             EmailContentInfoDTO emailContentInfoDTO = fileNameNavEntry.getKey();
@@ -164,8 +172,10 @@ public class EmailParseService {
                 continue;
             }
             // python接口解析结果
-            PythonData data = this.requestPyAndResult(fileId, emailContentInfoDTO);
+            ReportData data = this.requestPyAndResult(fileId, emailContentInfoDTO);
             if (data != null) {
+                // 保存报告解析数据
+                this.reportWriterFactory.getInstance(data.getReportType()).write(data);
                 dataList.add(data);
             }
             for (EmailFundNavDTO fundNavDTO : fundNavDTOList) {
@@ -181,20 +191,26 @@ public class EmailParseService {
         emailParseStatus = successNavCount >= 1 ? EmailParseStatusConst.SUCCESS : EmailParseStatusConst.FAIL;
         // 报告邮件有一条成功就表示整体成功
         if (Objects.equals(EmailTypeConst.REPORT_EMAIL_TYPE, emailType) && CollUtil.isNotEmpty(dataList)) {
-            long count = dataList.stream().map(PythonData::getStatus).filter(e -> Objects.equals(1, e)).count();
+            long count = dataList.size();
             emailParseStatus = count >= 1 ? EmailParseStatusConst.SUCCESS : EmailParseStatusConst.FAIL;
         }
         emailParseInfoMapper.updateParseStatus(emailId, emailParseStatus);
     }
 
-    private PythonData requestPyAndResult(int fileId, EmailContentInfoDTO emailContentInfoDTO) {
+    private ReportData requestPyAndResult(int fileId, EmailContentInfoDTO emailContentInfoDTO) {
         String fileName = emailContentInfoDTO.getFileName();
         Integer emailType = emailContentInfoDTO.getEmailType();
-        PythonData data = null;
+        ReportData reportData = null;
         if (Objects.equals(EmailTypeConst.REPORT_EMAIL_TYPE, emailType)) {
             if (StrUtil.isBlank(fileName)) {
                 return null;
             }
+            Pattern pattern = Pattern.compile("S(?:[A-Z]{0}[0-9]{5}|[A-Z][0-9]{4}|[A-Z]{2}[0-9]{3}|[A-Z]{3}[0-9]{2})");
+            Matcher matcher = pattern.matcher(fileName);
+            String registerNumber = null;
+            if (matcher.find()) {
+                registerNumber = matcher.group();
+            }
             int type = 0;
             if (fileName.contains("季报")) {
                 type = 1;
@@ -202,23 +218,33 @@ public class EmailParseService {
                 type = 2;
             }
             String api = "/api/v1/parse/amac_report";
-            Map<String, Object> params = MapUtil.newHashMap(8);
+            Map<String, Object> params = MapUtil.newHashMap(16);
             params.put("file_id", fileId);
             params.put("file_path", emailContentInfoDTO.getFilePath());
-            params.put("file_name", fileName);
+            params.put("register_number", registerNumber);
             params.put("file_type", type);
-            try {
-                String body = HttpUtil.post(this.pyBaseUrl + api, params);
-                JSONObject obj = JSONUtil.parseObj(body);
-                if (obj.containsKey("data") && !obj.getJSONObject("data").isEmpty()) {
-                    data = JSONUtil.toBean(obj.getJSONObject("data"), PythonData.class);
-                    data.setFileId(fileId);
+            params.put("file_name", fileName);
+            if (StrUtil.isNotBlank(registerNumber)) {
+                FundAndCompanyInfoDO info = this.fundInfoMapper.queryFundAndTrustByRegisterNumber(registerNumber);
+                if (info != null) {
+                    params.put("fund_name", info.getFundName());
+                    params.put("trust_name", info.getCompanyName());
                 }
+            }
+            long millis = System.currentTimeMillis();
+            try {
+                String body = HttpUtil.post(this.pyBaseUrl + api, JSONUtil.toJsonStr(params));
+                PythonResult<?> result = JSONUtil.toBean(body, PythonResult.class);
+                reportData = result.getData();
             } catch (Exception e) {
-                e.printStackTrace();
+                log.warn("请求python的报告解析接口报错\n{}", ExceptionUtil.stacktraceToString(e));
+            } finally {
+                if (log.isInfoEnabled()) {
+                    log.info("当前报告{}解析完成,总计耗时{}ms", params, (System.currentTimeMillis() - millis));
+                }
             }
         }
-        return data;
+        return reportData;
     }
 
     private void saveNavAndAssetNet(Integer fileId, List<EmailFundNavDTO> fundNavDTOList, Date parseDate) {

+ 266 - 241
service-daq/src/main/java/com/simuwang/daq/utils/ReportParseUtil.java

@@ -1,42 +1,67 @@
-//package com.simuwang.daq.utils;
-//
-//import cn.hutool.core.collection.CollUtil;
-//import cn.hutool.core.collection.ListUtil;
-//import cn.hutool.core.map.MapUtil;
-//import cn.hutool.core.util.ReflectUtil;
-//import cn.hutool.core.util.StrUtil;
-//import com.simuwang.daq.components.CustomPDFTextStripper;
-//import com.simuwang.daq.dto.ReportFundInfo;
-//import com.smppw.common.pojo.ValueLabelVO;
-//import org.apache.pdfbox.Loader;
-//import org.apache.pdfbox.contentstream.PDFStreamEngine;
-//import org.apache.pdfbox.contentstream.operator.text.ShowText;
-//import org.apache.pdfbox.cos.COSName;
-//import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
-//import org.apache.pdfbox.pdmodel.PDDocument;
-//import org.apache.pdfbox.pdmodel.PDPage;
-//import org.apache.pdfbox.pdmodel.PDResources;
-//import org.apache.pdfbox.pdmodel.common.PDStream;
-//import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureTreeRoot;
-//import org.apache.pdfbox.pdmodel.graphics.PDXObject;
-//import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
-//import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
-//import org.apache.pdfbox.text.PDFTextStripper;
-//import org.apache.pdfbox.text.PDFTextStripperByArea;
-//import org.apache.pdfbox.text.TextPosition;
-//import org.apache.pdfbox.util.Matrix;
-//import technology.tabula.*;
-//import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;
-//
-//import java.awt.geom.Rectangle2D;
-//import java.io.IOException;
-//import java.util.*;
-//import java.util.regex.Matcher;
-//import java.util.regex.Pattern;
-//import java.util.stream.Collectors;
-//
-//public class ReportParseUtil {
-//    public static void main(String[] args) throws IOException {
+package com.simuwang.daq.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.simuwang.daq.components.CustomPDFTextStripper;
+import com.simuwang.daq.dto.ReportFundInfo;
+import com.smppw.common.pojo.ValueLabelVO;
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.contentstream.PDFStreamEngine;
+import org.apache.pdfbox.contentstream.operator.text.ShowText;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureTreeRoot;
+import org.apache.pdfbox.pdmodel.graphics.PDXObject;
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
+import org.apache.pdfbox.text.PDFTextStripper;
+import org.apache.pdfbox.text.PDFTextStripperByArea;
+import org.apache.pdfbox.text.TextPosition;
+import org.apache.pdfbox.util.Matrix;
+import technology.tabula.*;
+import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;
+
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class ReportParseUtil {
+    public static void main(String[] args) throws IOException {
+        String fileName = "SJM970_排排精选进取一号私募证券投资基金_2022年第4季度报告.pdf";
+        Pattern pattern = Pattern.compile("S(?:[A-Z]{0}[0-9]{5}|[A-Z][0-9]{4}|[A-Z]{2}[0-9]{3}|[A-Z]{3}[0-9]{2})");
+        Matcher matcher = pattern.matcher(fileName);
+        String registerNumber = null;
+        if (matcher.find()) {
+            registerNumber = matcher.group();
+        }
+
+        String baseUrl = "http://192.168.0.81:8088";
+        String api = "/api/v1/parse/amac_report";
+        Map<String, Object> params = MapUtil.newHashMap(16);
+        params.put("file_id", 111112);
+        params.put("file_path", "E:/workproject/fastparse/src/fastparse/static/reports/quarterly_report/13445.pdf");
+        params.put("register_number", registerNumber);
+        params.put("file_type", 1);
+        params.put("file_name", fileName);
+        params.put("fund_name", null);
+        params.put("trust_name", null);
+        String body = HttpUtil.post(baseUrl + api, JSONUtil.toJsonStr(params));
+        JSONObject obj = JSONUtil.parseObj(body);
+        System.out.println(obj);
+
 //        List<ValueLabelVO> fieldMapper = ListUtil.list(false);
 //        fieldMapper.add(new ValueLabelVO("fundName", "基金名称"));
 //        fieldMapper.add(new ValueLabelVO("registerNumber", "基金编码"));
@@ -129,220 +154,220 @@
 //                }
 //            }
 //        }
-//    }
-//
-//    /**
-//     * 找图片水印
-//     *
-//     * @param page
-//     * @return
-//     * @throws IOException
-//     */
-//    public static Map<COSName, PDImageXObject> findImageWatermark(PDPage page) throws IOException {
-//        Map<COSName, PDImageXObject> watermarkMap = MapUtil.newHashMap();
+    }
+
+    /**
+     * 找图片水印
+     *
+     * @param page
+     * @return
+     * @throws IOException
+     */
+    public static Map<COSName, PDImageXObject> findImageWatermark(PDPage page) throws IOException {
+        Map<COSName, PDImageXObject> watermarkMap = MapUtil.newHashMap();
+        PDResources resources = page.getResources();
+        Iterable<COSName> xObjectNames = resources.getXObjectNames();
+        for (COSName xObjectName : xObjectNames) {
+            PDXObject xObject = resources.getXObject(xObjectName);
+            PDStream stream = xObject.getStream();
+            PDImageXObject imageXObject = null;
+            try {
+                imageXObject = new PDImageXObject(stream, resources);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            if (imageXObject != null) {
+                watermarkMap.put(xObjectName, imageXObject);
+            }
+        }
+        return watermarkMap;
+    }
+
+    private static Map<String, List<String>> generateWatermarkListMap(String fundName, String trustName, String registerNumber) {
+        Map<String, List<String>> result = MapUtil.newHashMap(32);
+        // 生成水印列表
+
+        fundName = StrUtil.isNotBlank(fundName) ? fundName : "私募证券投资基金";
+        trustName = StrUtil.isNotBlank(trustName) ? trustName : "资产管理有限公司";
+        registerNumber = StrUtil.isNotBlank(registerNumber) ? registerNumber : "";
+        String text = fundName + trustName + registerNumber;
+        text = text.replaceAll("[()]", ""); // 移除括号
+        List<String> textList = new ArrayList<>(new HashSet<>(convertStringToList(text)));
+        Collections.reverse(textList);
+        StringBuilder sb = new StringBuilder(textList.size());
+        for (String ch : textList) {
+            sb.append(ch);
+        }
+        String joinedText = sb.toString();
+
+        // 基本水印列表
+        List<String> wkList = new ArrayList<>();
+        for (String ch : textList) {
+            wkList.add(ch + "\r\n");
+            wkList.add("\r\n" + ch);
+        }
+
+        // 查找数字
+        List<String> matches = findDigits(fundName);
+        if (!matches.isEmpty()) {
+            for (String match : matches) {
+                wkList.add("\r\n" + match);
+                wkList.add(match + "\r\n");
+            }
+        }
+        wkList.add("-");
+        wkList.add("【");
+        wkList.add("】");
+        wkList.add("\r");
+        wkList.add("\r\n");
+
+        String noNumberText = removeDigits(joinedText);
+
+        // 生成不同字段的水印列表
+        result.put("report_name", new ArrayList<>(wkList));
+        result.get("report_name").addAll(convertStringToList("有限公司"));
+
+        result.put("less", new ArrayList<>(wkList));
+
+        result.put("more", new ArrayList<>(wkList));
+        result.get("more").addAll(convertStringToList(noNumberText));
+
+        result.put("leverage", new ArrayList<>(wkList));
+        result.get("leverage").addAll(convertStringToList(removeKeywords(noNumberText, "基金资产")));
+
+        result.put("base_info", new ArrayList<>(wkList));
+        result.get("base_info").addAll(convertStringToList(removeKeywords(text, "基", "金", "投资", "管理", "有", "份", "融", "资", "产", "本", "号", "收益", "策略", "期")));
+
+        result.put("industry", new ArrayList<>(wkList));
+        result.get("industry").addAll(convertStringToList(removeKeywords(noNumberText, "基金融公产")));
+
+        result.put("market_value", new ArrayList<>(Collections.singletonList("\n")));
+        return result;
+    }
+
+    private static List<String> findDigits(String text) {
+        List<String> digits = new ArrayList<>();
+        Pattern pattern = Pattern.compile("\\d");
+        Matcher matcher = pattern.matcher(text);
+        while (matcher.find()) {
+            digits.add(matcher.group());
+        }
+        return digits;
+    }
+
+    private static String removeDigits(String text) {
+        return text.replaceAll("\\d", "");
+    }
+
+    private static String removeKeywords(String text, String... keywords) {
+        for (String keyword : keywords) {
+            text = text.replaceAll(keyword, "");
+        }
+        return text;
+    }
+
+    private static List<String> convertStringToList(String text) {
+        List<String> charList = new ArrayList<>();
+        for (char c : text.toCharArray()) {
+            charList.add(c + "");
+        }
+        return charList;
+    }
+
+    public static String processString(List<String> wmList, String string) {
+        // 生成正则表达式模式
+        String pat = String.join("|", wmList);
+        // 使用正则表达式移除wmList中的元素
+        string = removeMatches(string, pat);
+        // 替换中文括号为英文括号
+        string = string.replace("(", "(").replace(")", ")");
+        // 移除空格
+        string = string.replace(" ", "");
+        // 如果字符串以括号开头,则移除第一个字符
+        if (startsWithParenthesis(string)) {
+            string = string.substring(1);
+        }
+
+        return string;
+    }
+
+    private static String removeMatches(String input, String pattern) {
+        // 编译正则表达式
+        Pattern compiledPattern = Pattern.compile(pattern);
+        // 创建Matcher对象
+        Matcher matcher = compiledPattern.matcher(input);
+        // 使用replaceAll方法替换所有匹配到的字符为空字符串
+        return matcher.replaceAll("");
+    }
+
+    private static boolean startsWithParenthesis(String input) {
+        // 匹配以括号开头的字符串
+        Pattern pattern = Pattern.compile("^[()].*");
+        Matcher matcher = pattern.matcher(input);
+        return matcher.find();
+    }
+
+//    public static void removeTextWatermark(PDPage page) throws IOException {
 //        PDResources resources = page.getResources();
-//        Iterable<COSName> xObjectNames = resources.getXObjectNames();
-//        for (COSName xObjectName : xObjectNames) {
-//            PDXObject xObject = resources.getXObject(xObjectName);
-//            PDStream stream = xObject.getStream();
-//            PDImageXObject imageXObject = null;
-//            try {
-//                imageXObject = new PDImageXObject(stream, resources);
-//            } catch (Exception e) {
-//                e.printStackTrace();
-//            }
-//            if (imageXObject != null) {
-//                watermarkMap.put(xObjectName, imageXObject);
-//            }
-//        }
-//        return watermarkMap;
-//    }
+////        if (StrUtil.isAllBlank(fundName, trustName)) {
+////            return;
+////        }
+//        PDFTextStripperByArea stripper = new PDFTextStripperByArea();
+//        stripper.setSortByPosition(true);
+//        stripper.addRegion("watermark", new Rectangle2D.Float(0, 0, page.getMediaBox().getWidth(), page.getMediaBox().getHeight()));
+//        stripper.extractRegions(page);
 //
-//    private static Map<String, List<String>> generateWatermarkListMap(String fundName, String trustName, String registerNumber) {
-//        Map<String, List<String>> result = MapUtil.newHashMap(32);
-//        // 生成水印列表
+//        PDFStreamEngine engine = new PDFTextStripper();
+//        engine.addOperator(new SetMatrix(stripper));
 //
-//        fundName = StrUtil.isNotBlank(fundName) ? fundName : "私募证券投资基金";
-//        trustName = StrUtil.isNotBlank(trustName) ? trustName : "资产管理有限公司";
-//        registerNumber = StrUtil.isNotBlank(registerNumber) ? registerNumber : "";
-//        String text = fundName + trustName + registerNumber;
-//        text = text.replaceAll("[()]", ""); // 移除括号
-//        List<String> textList = new ArrayList<>(new HashSet<>(convertStringToList(text)));
-//        Collections.reverse(textList);
-//        StringBuilder sb = new StringBuilder(textList.size());
-//        for (String ch : textList) {
-//            sb.append(ch);
-//        }
-//        String joinedText = sb.toString();
+//    }
 //
-//        // 基本水印列表
-//        List<String> wkList = new ArrayList<>();
-//        for (String ch : textList) {
-//            wkList.add(ch + "\r\n");
-//            wkList.add("\r\n" + ch);
+//    private static void processResources(PDResources resources) throws IOException {
+//        for (COSName name : resources.getXObjectNames()) {
+//            PDXObject xobject = resources.getXObject(name);
+//            if (xobject instanceof PDFormXObject) {
+//                PDFormXObject formXObject = (PDFormXObject) xobject;
+//                writeTokensToStream(formXObject.getContentStream(),
+//                        createTokensWithoutText(formXObject));
+//                processResources(formXObject.getResources());
+//            }
 //        }
-//
-//        // 查找数字
-//        List<String> matches = findDigits(fundName);
-//        if (!matches.isEmpty()) {
-//            for (String match : matches) {
-//                wkList.add("\r\n" + match);
-//                wkList.add(match + "\r\n");
+//        for (COSName name : resources.getPatternNames()) {
+//            PDAbstractPattern pattern = resources.getPattern(name);
+//            if (pattern instanceof PDTilingPattern) {
+//                PDTilingPattern tilingPattern = (PDTilingPattern) pattern;
+//                writeTokensToStream(tilingPattern.getContentStream(),
+//                        createTokensWithoutText(tilingPattern));
+//                processResources(tilingPattern.getResources());
 //            }
 //        }
-//        wkList.add("-");
-//        wkList.add("【");
-//        wkList.add("】");
-//        wkList.add("\r");
-//        wkList.add("\r\n");
-//
-//        String noNumberText = removeDigits(joinedText);
-//
-//        // 生成不同字段的水印列表
-//        result.put("report_name", new ArrayList<>(wkList));
-//        result.get("report_name").addAll(convertStringToList("有限公司"));
-//
-//        result.put("less", new ArrayList<>(wkList));
-//
-//        result.put("more", new ArrayList<>(wkList));
-//        result.get("more").addAll(convertStringToList(noNumberText));
-//
-//        result.put("leverage", new ArrayList<>(wkList));
-//        result.get("leverage").addAll(convertStringToList(removeKeywords(noNumberText, "基金资产")));
-//
-//        result.put("base_info", new ArrayList<>(wkList));
-//        result.get("base_info").addAll(convertStringToList(removeKeywords(text, "基", "金", "投资", "管理", "有", "份", "融", "资", "产", "本", "号", "收益", "策略", "期")));
-//
-//        result.put("industry", new ArrayList<>(wkList));
-//        result.get("industry").addAll(convertStringToList(removeKeywords(noNumberText, "基金融公产")));
-//
-//        result.put("market_value", new ArrayList<>(Collections.singletonList("\n")));
-//        return result;
 //    }
 //
-//    private static List<String> findDigits(String text) {
-//        List<String> digits = new ArrayList<>();
-//        Pattern pattern = Pattern.compile("\\d");
-//        Matcher matcher = pattern.matcher(text);
-//        while (matcher.find()) {
-//            digits.add(matcher.group());
+//    private static void writeTokensToStream(PDStream newContents, List<Object> newTokens) throws IOException {
+//        try (OutputStream out = newContents.createOutputStream(COSName.FLATE_DECODE)) {
+//            ContentStreamWriter writer = new ContentStreamWriter(out);
+//            writer.writeTokens(newTokens);
 //        }
-//        return digits;
-//    }
-//
-//    private static String removeDigits(String text) {
-//        return text.replaceAll("\\d", "");
 //    }
 //
-//    private static String removeKeywords(String text, String... keywords) {
-//        for (String keyword : keywords) {
-//            text = text.replaceAll(keyword, "");
-//        }
-//        return text;
-//    }
+//    private static List<Object> createTokensWithoutText(PDContentStream contentStream) throws IOException {
+//        PDFStreamParser parser = new PDFStreamParser(contentStream);
+//        Object token = parser.parseNextToken();
+//        List<Object> newTokens = new ArrayList<>();
+//        while (token != null) {
+//            if (token instanceof Operator op) {
+//                String opName = op.getName();
+//                if (OperatorName.SET_MATRIX.equals(opName)) {
+//                    // remove the argument to this operator
+//                    newTokens.remove(newTokens.size() - 1);
 //
-//    private static List<String> convertStringToList(String text) {
-//        List<String> charList = new ArrayList<>();
-//        for (char c : text.toCharArray()) {
-//            charList.add(c + "");
-//        }
-//        return charList;
-//    }
-//
-//    public static String processString(List<String> wmList, String string) {
-//        // 生成正则表达式模式
-//        String pat = String.join("|", wmList);
-//        // 使用正则表达式移除wmList中的元素
-//        string = removeMatches(string, pat);
-//        // 替换中文括号为英文括号
-//        string = string.replace("(", "(").replace(")", ")");
-//        // 移除空格
-//        string = string.replace(" ", "");
-//        // 如果字符串以括号开头,则移除第一个字符
-//        if (startsWithParenthesis(string)) {
-//            string = string.substring(1);
+//                    token = parser.parseNextToken();
+//                    continue;
+//                }
+//            }
+//            newTokens.add(token);
+//            token = parser.parseNextToken();
 //        }
-//
-//        return string;
+//        return newTokens;
 //    }
-//
-//    private static String removeMatches(String input, String pattern) {
-//        // 编译正则表达式
-//        Pattern compiledPattern = Pattern.compile(pattern);
-//        // 创建Matcher对象
-//        Matcher matcher = compiledPattern.matcher(input);
-//        // 使用replaceAll方法替换所有匹配到的字符为空字符串
-//        return matcher.replaceAll("");
-//    }
-//
-//    private static boolean startsWithParenthesis(String input) {
-//        // 匹配以括号开头的字符串
-//        Pattern pattern = Pattern.compile("^[()].*");
-//        Matcher matcher = pattern.matcher(input);
-//        return matcher.find();
-//    }
-//
-////    public static void removeTextWatermark(PDPage page) throws IOException {
-////        PDResources resources = page.getResources();
-//////        if (StrUtil.isAllBlank(fundName, trustName)) {
-//////            return;
-//////        }
-////        PDFTextStripperByArea stripper = new PDFTextStripperByArea();
-////        stripper.setSortByPosition(true);
-////        stripper.addRegion("watermark", new Rectangle2D.Float(0, 0, page.getMediaBox().getWidth(), page.getMediaBox().getHeight()));
-////        stripper.extractRegions(page);
-////
-////        PDFStreamEngine engine = new PDFTextStripper();
-////        engine.addOperator(new SetMatrix(stripper));
-////
-////    }
-////
-////    private static void processResources(PDResources resources) throws IOException {
-////        for (COSName name : resources.getXObjectNames()) {
-////            PDXObject xobject = resources.getXObject(name);
-////            if (xobject instanceof PDFormXObject) {
-////                PDFormXObject formXObject = (PDFormXObject) xobject;
-////                writeTokensToStream(formXObject.getContentStream(),
-////                        createTokensWithoutText(formXObject));
-////                processResources(formXObject.getResources());
-////            }
-////        }
-////        for (COSName name : resources.getPatternNames()) {
-////            PDAbstractPattern pattern = resources.getPattern(name);
-////            if (pattern instanceof PDTilingPattern) {
-////                PDTilingPattern tilingPattern = (PDTilingPattern) pattern;
-////                writeTokensToStream(tilingPattern.getContentStream(),
-////                        createTokensWithoutText(tilingPattern));
-////                processResources(tilingPattern.getResources());
-////            }
-////        }
-////    }
-////
-////    private static void writeTokensToStream(PDStream newContents, List<Object> newTokens) throws IOException {
-////        try (OutputStream out = newContents.createOutputStream(COSName.FLATE_DECODE)) {
-////            ContentStreamWriter writer = new ContentStreamWriter(out);
-////            writer.writeTokens(newTokens);
-////        }
-////    }
-////
-////    private static List<Object> createTokensWithoutText(PDContentStream contentStream) throws IOException {
-////        PDFStreamParser parser = new PDFStreamParser(contentStream);
-////        Object token = parser.parseNextToken();
-////        List<Object> newTokens = new ArrayList<>();
-////        while (token != null) {
-////            if (token instanceof Operator op) {
-////                String opName = op.getName();
-////                if (OperatorName.SET_MATRIX.equals(opName)) {
-////                    // remove the argument to this operator
-////                    newTokens.remove(newTokens.size() - 1);
-////
-////                    token = parser.parseNextToken();
-////                    continue;
-////                }
-////            }
-////            newTokens.add(token);
-////            token = parser.parseNextToken();
-////        }
-////        return newTokens;
-////    }
-//}
+}

+ 2 - 4
service-deploy/src/main/resources/application.yml

@@ -73,8 +73,6 @@ email:
 
 # 配置
 simuwang:
-  # 是否启用quartz定时任务功能
-  enable-quartz: false
   # 操作日志功能是否启用,启用了才会记录操作日志
   enable-logging: true
   default-pwd: "QWER1234!@#$"
@@ -97,7 +95,7 @@ simuwang:
     - path: "/v1/rsa-key"
       filters: anon
     - path: "/v1/**"
-      filters: anon
+      filters: jwt
     - path: "/**"
-      filters: anon
+      filters: jwt
 

+ 5 - 0
service-deploy/src/test/java/com/simuwang/ApplicationTest.java

@@ -47,6 +47,11 @@ public class ApplicationTest {
     }
 
     @Test
+    public void pyTest() {
+
+    }
+
+    @Test
     public void testReparseEmail() {
         emailParseApiService.reparseEmail(593);
     }