1
0
Преглед на файлове

feat:邮件解析-保存保存相关信息->邮件信息表,邮件文件表,邮件净值表,邮件规模表,基金净值表

mozuwen преди 7 месеца
родител
ревизия
399608c4bd
променени са 25 файла, в които са добавени 718 реда и са изтрити 18 реда
  1. 15 0
      service-base/src/main/java/com/simuwang/base/common/conts/EmailParseStatusConst.java
  2. 30 0
      service-base/src/main/java/com/simuwang/base/common/conts/NavParseStatusConst.java
  3. 2 2
      service-base/src/main/java/com/simuwang/base/common/util/EmailUtil.java
  4. 8 1
      service-base/src/main/java/com/simuwang/base/common/util/StringUtil.java
  5. 12 0
      service-base/src/main/java/com/simuwang/base/mapper/EmailFileInfoMapper.java
  6. 14 0
      service-base/src/main/java/com/simuwang/base/mapper/EmailFundAssetMapper.java
  7. 14 0
      service-base/src/main/java/com/simuwang/base/mapper/EmailFundNavMapper.java
  8. 13 0
      service-base/src/main/java/com/simuwang/base/mapper/EmailParseInfoMapper.java
  9. 16 0
      service-base/src/main/java/com/simuwang/base/mapper/FundAliasMapper.java
  10. 6 0
      service-base/src/main/java/com/simuwang/base/mapper/FundInfomationMapper.java
  11. 5 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/EmailFileInfoDO.java
  12. 5 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/EmailFundAssetDO.java
  13. 9 4
      service-base/src/main/java/com/simuwang/base/pojo/dos/EmailFundNavDO.java
  14. 2 2
      service-base/src/main/java/com/simuwang/base/pojo/dos/EmailParseInfoDO.java
  15. 68 0
      service-base/src/main/java/com/simuwang/base/pojo/dos/FundAliasDO.java
  16. 10 0
      service-base/src/main/java/com/simuwang/base/pojo/dto/EmailFundNavDTO.java
  17. 25 0
      service-base/src/main/resources/mapper/EmailFileInfoMapper.xml
  18. 32 0
      service-base/src/main/resources/mapper/EmailFundAssetMapper.xml
  19. 36 0
      service-base/src/main/resources/mapper/EmailFundNavMapper.xml
  20. 33 0
      service-base/src/main/resources/mapper/EmailParseInfoMapper.xml
  21. 41 0
      service-base/src/main/resources/mapper/FundAliasMapper.xml
  22. 22 0
      service-base/src/main/resources/mapper/FundInformationMapper.xml
  23. 25 0
      service-daq/src/main/java/com/simuwang/daq/service/AbstractEmailParser.java
  24. 270 9
      service-daq/src/main/java/com/simuwang/daq/service/EmailParseService.java
  25. 5 0
      service-daq/src/main/java/com/simuwang/daq/service/NavEmailParser.java

+ 15 - 0
service-base/src/main/java/com/simuwang/base/common/conts/EmailParseStatusConst.java

@@ -0,0 +1,15 @@
+package com.simuwang.base.common.conts;
+
+public class EmailParseStatusConst {
+
+    /**
+     * 成功
+     */
+    public final static Integer SUCCESS = 1;
+
+    /**
+     * 失败
+     */
+    public final static Integer FAIL = 2;
+
+}

+ 30 - 0
service-base/src/main/java/com/simuwang/base/common/conts/NavParseStatusConst.java

@@ -0,0 +1,30 @@
+package com.simuwang.base.common.conts;
+
+public class NavParseStatusConst {
+
+    /**
+     * 成功
+     */
+    public final static Integer SUCCESS = 1;
+
+    /**
+     * 净值缺失
+     */
+    public final static Integer NAV_DEFICIENCY = 2;
+
+    /**
+     * 未匹配基金
+     */
+    public final static Integer NOT_MATCH = 3;
+
+    /**
+     * 净值不大于0
+     */
+    public final static Integer NAV_NEGATIVE = 4;
+
+    /**
+     * 资产净值不大于0
+     */
+    public final static Integer ASSET_NET_NEGATIVE = 5;
+
+}

+ 2 - 2
service-base/src/main/java/com/simuwang/base/common/util/EmailUtil.java

@@ -67,7 +67,7 @@ public class EmailUtil {
                 emailContentInfoDTO = collectTextPart(part, partContent, filePath, fileName);
             } else if ("BASE64DecoderStream".equals(contentClass)) {
                 if (StrUtil.isNotBlank(part.getFileName())) {
-                    String fileName = emailDate + MimeUtility.decodeText(part.getFileName());
+                    String fileName = MimeUtility.decodeText(part.getFileName());
                     emailContentInfoDTO.setFileName(fileName);
 
                     File savefile = new File(filePath + fileName);
@@ -101,7 +101,7 @@ public class EmailUtil {
             }
             emailContentInfoDTO.setEmailAddress(emailAddress);
             emailContentInfoDTO.setEmailTitle(emailTitle);
-            emailContentInfoDTO.setEmailDate((emailDate));
+            emailContentInfoDTO.setEmailDate(DateUtil.format(message.getSentDate(), DateConst.YYYY_MM_DD_HH_MM_SS));
             emailContentInfoDTOList.add(emailContentInfoDTO);
         }
 

+ 8 - 1
service-base/src/main/java/com/simuwang/base/common/util/StringUtil.java

@@ -48,12 +48,19 @@ public class StringUtil {
                 sdf.parse(dateString);
                 return true;
             } catch (Exception e) {
-                e.printStackTrace();
+                return false;
             }
         }
         return false;
     }
 
+    public static boolean isNumeric(String value) {
+        if (StrUtil.isBlank(value)) {
+            return false;
+        }
+        return value.matches("^[-+]?[0-9]*\\.?[0-9]+$");
+    }
+
 
     /**
      * 获取参数不为空值

+ 12 - 0
service-base/src/main/java/com/simuwang/base/mapper/EmailFileInfoMapper.java

@@ -0,0 +1,12 @@
+package com.simuwang.base.mapper;
+
+import com.simuwang.base.pojo.dos.EmailFileInfoDO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface EmailFileInfoMapper {
+
+    Integer insert(@Param("itemDo") EmailFileInfoDO emailFileInfoDO);
+
+}

+ 14 - 0
service-base/src/main/java/com/simuwang/base/mapper/EmailFundAssetMapper.java

@@ -0,0 +1,14 @@
+package com.simuwang.base.mapper;
+
+import com.simuwang.base.pojo.dos.EmailFundAssetDO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface EmailFundAssetMapper {
+
+    void batchInsert(@Param("itemDoList") List<EmailFundAssetDO> emailFundAssetDOList);
+
+}

+ 14 - 0
service-base/src/main/java/com/simuwang/base/mapper/EmailFundNavMapper.java

@@ -0,0 +1,14 @@
+package com.simuwang.base.mapper;
+
+import com.simuwang.base.pojo.dos.EmailFundNavDO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface EmailFundNavMapper {
+
+    void batchInsert(@Param("itemDoList") List<EmailFundNavDO> emailFundNavDOList);
+
+}

+ 13 - 0
service-base/src/main/java/com/simuwang/base/mapper/EmailParseInfoMapper.java

@@ -0,0 +1,13 @@
+package com.simuwang.base.mapper;
+
+import com.simuwang.base.pojo.dos.EmailParseInfoDO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface EmailParseInfoMapper {
+
+    Integer insert(@Param("itemDo") EmailParseInfoDO emailParseInfoDO);
+
+    void updateParseStatus(@Param("id") Integer id, @Param("parseStatus") int parseStatus);
+}

+ 16 - 0
service-base/src/main/java/com/simuwang/base/mapper/FundAliasMapper.java

@@ -0,0 +1,16 @@
+package com.simuwang.base.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface FundAliasMapper {
+
+    List<String> queryFundByNameAndRegisterNumber(@Param("fundName") String fundName, @Param("registerNumber") String registerNumber);
+
+    List<String> queryFundByName(@Param("fundName") String fundName);
+
+    List<String> queryFundByRegisterNumber(@Param("registerNumber") String registerNumber);
+}

+ 6 - 0
service-base/src/main/java/com/simuwang/base/mapper/FundInfomationMapper.java

@@ -21,4 +21,10 @@ public interface FundInfomationMapper {
                                                @Param("companyName") String companyName, @Param("navFrequency") Integer navFrequency,
                                                @Param("assetFrequency") Integer assetFrequency,@Param("startDate") Integer startDate,
                                                @Param("endDate")Integer endDate);
+
+    List<String> queryFundByNameAndRegisterNumber(@Param("fundName")String fundName, @Param("registerNumber")String registerNumber);
+
+    List<String> queryFundByName(@Param("fundName") String fundName);
+
+    List<String> queryFundByRegisterNumber(@Param("registerNumber") String registerNumber);
 }

+ 5 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/EmailFileInfoDO.java

@@ -21,6 +21,11 @@ public class EmailFileInfoDO {
     @TableField(value = "email_id")
     private Integer emailId;
     /**
+     * 基金id
+     */
+    @TableField(value = "fund_id")
+    private Integer fundId;
+    /**
      * 附件名称
      */
     @TableField(value = "file_name")

+ 5 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/EmailFundAssetDO.java

@@ -17,6 +17,11 @@ public class EmailFundAssetDO {
     @TableId(value = "id")
     private Integer id;
     /**
+     * 文件id(email_file_info.id)
+     */
+    @TableField(value = "file_id")
+    private Integer fileId;
+    /**
      * 基金id
      */
     @TableField(value = "fund_id")

+ 9 - 4
service-base/src/main/java/com/simuwang/base/pojo/dos/EmailFundNavDO.java

@@ -17,10 +17,15 @@ public class EmailFundNavDO {
     @TableId(value = "id")
     private Integer id;
     /**
-     * 邮件id(email_parse_info.id)
+     * 邮件id(email_file_info.id)
      */
-    @TableField(value = "email_id")
-    private Integer emailId;
+    @TableField(value = "file_id")
+    private Integer fileId;
+    /**
+     * 基金id
+     */
+    @TableField(value = "fund_id")
+    private String fundId;
     /**
      * 邮件解析的基金名称
      */
@@ -45,7 +50,7 @@ public class EmailFundNavDO {
      * 累计单位净值
      */
     @TableField(value = "cumulative_nav")
-    private BigDecimal cumulativeNav;
+    private BigDecimal cumulativeNavWithdrawal;
     /**
      * 是否入库 0-没有,1-有
      */

+ 2 - 2
service-base/src/main/java/com/simuwang/base/pojo/dos/EmailParseInfoDO.java

@@ -24,12 +24,12 @@ public class EmailParseInfoDO {
      * 邮箱日期
      */
     @TableField(value = "email_date")
-    private String emailDate;
+    private Date emailDate;
     /**
      * 解析日期
      */
     @TableField(value = "parse_date")
-    private String parseDate;
+    private Date parseDate;
     /**
      * 邮件主题
      */

+ 68 - 0
service-base/src/main/java/com/simuwang/base/pojo/dos/FundAliasDO.java

@@ -0,0 +1,68 @@
+package com.simuwang.base.pojo.dos;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@TableName("fund_alias")
+public class FundAliasDO {
+    /**
+     * 主键Id
+     */
+    @TableId(value = "id")
+    private Integer id;
+    /**
+     * 邮件解析基金名称
+     */
+    @TableField(value = "source_fund_name")
+    private String sourceFundName;
+    /**
+     * 邮件解析基金的备案编码
+     */
+    @TableField(value = "source_register_number")
+    private String sourceRegisterNumber;
+    /**
+     * 匹配的源数据基金名称
+     */
+    @TableField(value = "target_fund_name")
+    private String targetFundName;
+    /**
+     * 匹配的源基金ID
+     */
+    @TableField(value = "target_fund_id")
+    private String targetFundId;
+    /**
+     * 匹配的源备案编码
+     */
+    @TableField(value = "target_register_number")
+    private String targetRegisterNumber;
+    /**
+     * 记录的有效性;1-有效;0-无效;
+     */
+    @TableField(value = "isvalid")
+    private Integer isvalid;
+    /**
+     * 创建者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "creatorid")
+    private Integer creatorId;
+    /**
+     * 修改者Id;第一次创建时与Creator值相同,修改时与修改人值相同
+     */
+    @TableField(value = "updaterid")
+    private Integer updaterId;
+    /**
+     * 创建时间,默认第一次创建的getdate()时间
+     */
+    @TableField(value = "createtime")
+    private Date createTime;
+    /**
+     * 修改时间;第一次创建时与CreatTime值相同,修改时与修改时间相同
+     */
+    @TableField(value = "updatetime")
+    private Date updateTime;
+}

+ 10 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/EmailFundNavDTO.java

@@ -2,6 +2,8 @@ package com.simuwang.base.pojo.dto;
 
 import lombok.Data;
 
+import java.util.List;
+
 @Data
 public class EmailFundNavDTO {
     /**
@@ -36,4 +38,12 @@ public class EmailFundNavDTO {
      * 资产净值(基金规模)
      */
     private String assetNet;
+    /**
+     * 匹配上的基金id
+     */
+    private List<String> fundIdList;
+    /**
+     * 解析状态:1-成功,2-净值缺失,3-未匹配基金,4-净值<=0,5-资产净值<=0
+     */
+    private Integer parseStatus;
 }

+ 25 - 0
service-base/src/main/resources/mapper/EmailFileInfoMapper.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.simuwang.base.mapper.EmailFileInfoMapper">
+    <resultMap id="BaseResultMap" type="com.simuwang.base.pojo.dos.EmailFileInfoDO">
+        <id column="id" property="id"/>
+        <result column="email_id" property="emailId"/>
+        <result column="file_name" property="fileName"/>
+        <result column="file_path" property="filePath"/>
+        <result column="isvalid" property="isvalid"/>
+        <result column="creatorid" property="creatorId"/>
+        <result column="createtime" property="createTime"/>
+        <result column="updaterid" property="updaterId"/>
+        <result column="updatetime" property="updateTime"/>
+    </resultMap>
+
+    <insert id="insert" parameterType="com.simuwang.base.pojo.dos.EmailFileInfoDO" useGeneratedKeys="true"
+            keyProperty="id" keyColumn="id">
+        insert into PPW_EMAIL.email_file_info(email_id, file_name, file_path,
+                                              isvalid, creatorid, createtime, updaterid, updatetime)
+        values (#{itemDo.emailId}, #{itemDo.fileName}, #{itemDo.filePath},
+                #{itemDo.isvalid}, #{itemDo.creatorId}, #{itemDo.createTime}, #{itemDo.updaterId}, #{itemDo.updateTime})
+    </insert>
+
+
+</mapper>

+ 32 - 0
service-base/src/main/resources/mapper/EmailFundAssetMapper.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.simuwang.base.mapper.EmailFundAssetMapper">
+    <resultMap id="BaseResultMap" type="com.simuwang.base.pojo.dos.EmailFundAssetDO">
+        <id column="id" property="id"/>
+        <result column="file_id" property="fileId"/>
+        <result column="fund_id" property="fundId"/>
+        <result column="fund_name" property="fundName"/>
+        <result column="register_number" property="registerNumber"/>
+        <result column="price_date" property="priceDate"/>
+        <result column="asset_net" property="assetNet"/>
+        <result column="asset_share" property="assetShare"/>
+        <result column="isvalid" property="isvalid"/>
+        <result column="creatorid" property="creatorId"/>
+        <result column="createtime" property="createTime"/>
+        <result column="updaterid" property="updaterId"/>
+        <result column="updatetime" property="updateTime"/>
+    </resultMap>
+
+    <insert id="batchInsert" parameterType="com.simuwang.base.pojo.dos.EmailFundAssetDO">
+        insert into PPW_EMAIL.email_fund_asset(file_id, fund_id, fund_name,register_number,price_date,asset_net,asset_share,
+                                              isvalid, creatorid, createtime, updaterid, updatetime)
+        values
+        <foreach collection="itemDoList" item="itemDo" index="index" separator=",">
+            (#{itemDo.fileId},#{itemDo.fundId},#{itemDo.fundName},#{itemDo.registerNumber},#{itemDo.priceDate},#{itemDo.assetNet},#{itemDo.assetShare},
+            #{itemDo.isvalid}, #{itemDo.creatorId}, #{itemDo.createTime}, #{itemDo.updaterId}, #{itemDo.updateTime})
+        </foreach>
+
+    </insert>
+
+
+</mapper>

+ 36 - 0
service-base/src/main/resources/mapper/EmailFundNavMapper.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.simuwang.base.mapper.EmailFundNavMapper">
+    <resultMap id="BaseResultMap" type="com.simuwang.base.pojo.dos.EmailFundNavDO">
+        <id column="id" property="id"/>
+        <result column="file_id" property="fileId"/>
+        <result column="fund_id" property="fundId"/>
+        <result column="fund_name" property="fundName"/>
+        <result column="register_number" property="registerNumber"/>
+        <result column="price_date" property="priceDate"/>
+        <result column="nav" property="nav"/>
+        <result column="cumulative_nav_withdrawal" property="cumulativeNavWithdrawal"/>
+        <result column="is_stored" property="isStored"/>
+        <result column="exception_status" property="exceptionStatus"/>
+        <result column="isvalid" property="isvalid"/>
+        <result column="creatorid" property="creatorId"/>
+        <result column="createtime" property="createTime"/>
+        <result column="updaterid" property="updaterId"/>
+        <result column="updatetime" property="updateTime"/>
+    </resultMap>
+
+    <insert id="batchInsert" parameterType="com.simuwang.base.pojo.dos.EmailFundNavDO">
+        insert into PPW_EMAIL.email_fund_nav(file_id, fund_id, fund_name,register_number,price_date,
+                                              nav,cumulative_nav_withdrawal,is_stored,exception_status,
+                                              isvalid, creatorid, createtime, updaterid, updatetime)
+        values
+        <foreach collection="itemDoList" item="itemDo" index="index" separator=",">
+            (#{itemDo.fileId},#{itemDo.fundId},#{itemDo.fundName},#{itemDo.registerNumber},#{itemDo.priceDate},
+             #{itemDo.nav},#{itemDo.cumulativeNavWithdrawal},#{itemDo.isStored},#{itemDo.exceptionStatus},
+            #{itemDo.isvalid}, #{itemDo.creatorId}, #{itemDo.createTime}, #{itemDo.updaterId}, #{itemDo.updateTime})
+        </foreach>
+
+    </insert>
+
+
+</mapper>

+ 33 - 0
service-base/src/main/resources/mapper/EmailParseInfoMapper.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.simuwang.base.mapper.EmailParseInfoMapper">
+    <resultMap id="BaseResultMap" type="com.simuwang.base.pojo.dos.EmailParseInfoDO">
+        <id column="id" property="id"/>
+        <result column="email" property="email"/>
+        <result column="email_date" property="emailDate" />
+        <result column="parse_date" property="parseDate" />
+        <result column="email_title" property="emailTitle"/>
+        <result column="email_type" property="emailType"/>
+        <result column="parse_status" property="parseStatus"/>
+        <result column="isvalid" property="isvalid"/>
+        <result column="creatorid" property="creatorId"/>
+        <result column="createtime" property="createTime"/>
+        <result column="updaterid" property="updaterId"/>
+        <result column="updatetime" property="updateTime"/>
+    </resultMap>
+
+    <insert id="insert" parameterType="com.simuwang.base.pojo.dos.EmailParseInfoDO" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
+        insert into PPW_EMAIL.email_parse_info(email, email_date, parse_date, email_title, email_type, parse_status,
+                                     isvalid, creatorid, createtime, updaterid, updatetime)
+        values (#{itemDo.email}, #{itemDo.emailDate}, #{itemDo.parseDate}, #{itemDo.emailTitle}, #{itemDo.emailType}, #{itemDo.parseStatus},
+                #{itemDo.isvalid}, #{itemDo.creatorId}, #{itemDo.createTime}, #{itemDo.updaterId}, #{itemDo.updateTime})
+    </insert>
+
+    <update id="updateParseStatus">
+        update PPW_EMAIL.email_parse_info
+        set parse_status = #{parseStatus}
+        where isvalid = 1
+          and id = #{id}
+    </update>
+
+</mapper>

+ 41 - 0
service-base/src/main/resources/mapper/FundAliasMapper.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.simuwang.base.mapper.FundAliasMapper">
+    <resultMap id="BaseResultMap" type="com.simuwang.base.pojo.dos.FundAliasDO">
+        <id column="id" property="id"/>
+        <result column="source_fund_name" property="sourceFundName"/>
+        <result column="source_register_number" property="sourceRegisterNumber"/>
+        <result column="target_fund_id" property="targetFundId"/>
+        <result column="target_fund_name" property="targetFundName"/>
+        <result column="target_register_number" property="targetRegisterNumber"/>
+        <result column="isvalid" property="isvalid"/>
+        <result column="creatorid" property="creatorId"/>
+        <result column="createtime" property="createTime"/>
+        <result column="updaterid" property="updaterId"/>
+        <result column="updatetime" property="updateTime"/>
+    </resultMap>
+
+
+    <select id="queryFundByNameAndRegisterNumber" resultType="java.lang.String">
+        select target_fund_id
+        from PPW_EMAIL.fund_alias
+        where isvalid = 1
+          and source_fund_name = #{fundName}
+          and source_register_number = #{registerNumber}
+    </select>
+
+    <select id="queryFundByName" resultType="java.lang.String">
+        select target_fund_id
+        from PPW_EMAIL.fund_alias
+        where isvalid = 1
+          and source_fund_name = #{fundName}
+    </select>
+
+    <select id="queryFundByRegisterNumber" resultType="java.lang.String">
+        select target_fund_id
+        from PPW_EMAIL.fund_alias
+        where isvalid = 1
+          and source_register_number = #{registerNumber}
+    </select>
+
+</mapper>

+ 22 - 0
service-base/src/main/resources/mapper/FundInformationMapper.xml

@@ -74,4 +74,26 @@
         </if>
     </select>
 
+    <select id="queryFundByNameAndRegisterNumber" resultType="java.lang.String">
+        select fund_id
+        from PPW_EMAIL.fund_information
+        where isvalid = 1
+          and fund_name = #{fundName}
+          and register_number = #{registerNumber}
+    </select>
+
+    <select id="queryFundByName" resultType="java.lang.String">
+        select fund_id
+        from PPW_EMAIL.fund_information
+        where isvalid = 1
+          and fund_name = #{fundName}
+    </select>
+
+    <select id="queryFundByRegisterNumber" resultType="java.lang.String">
+        select fund_id
+        from PPW_EMAIL.fund_information
+        where isvalid = 1
+          and register_number = #{registerNumber}
+    </select>
+
 </mapper>

+ 25 - 0
service-daq/src/main/java/com/simuwang/daq/service/AbstractEmailParser.java

@@ -1,17 +1,42 @@
 package com.simuwang.daq.service;
 
+import cn.hutool.core.util.StrUtil;
+import com.simuwang.base.common.util.StringUtil;
 import com.simuwang.base.pojo.dto.EmailContentInfoDTO;
 import com.simuwang.base.pojo.dto.EmailFundNavDTO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.List;
 import java.util.Map;
 
 public abstract class AbstractEmailParser {
 
+    private static final Logger log = LoggerFactory.getLogger(AbstractEmailParser.class);
+
     public boolean isSupport(Integer emailType) {
         return false;
     }
 
     public abstract List<EmailFundNavDTO> parse(EmailContentInfoDTO emailContentInfoDTO, Map<String, List<String>> emailFieldMap);
 
+    public boolean dataFormat(EmailFundNavDTO fundNavDTO) {
+        // 净值日期格式校验
+        boolean isvalidDate = StringUtil.isValidDate(fundNavDTO.getPriceDate());
+        if (!isvalidDate) {
+            log.warn("净值日期格式不正确 -> 解析到的数据:{}", fundNavDTO);
+            return false;
+        }
+        // 单位净值,累计单位净值,资产净值,资产份额数字格式校验
+        boolean isvalidNumericFormat = (StrUtil.isBlank(fundNavDTO.getNav()) || StringUtil.isNumeric(fundNavDTO.getNav()))
+                && (StrUtil.isBlank(fundNavDTO.getCumulativeNavWithdrawal()) || StringUtil.isNumeric(fundNavDTO.getCumulativeNavWithdrawal()))
+                && (StrUtil.isBlank(fundNavDTO.getAssetNet()) || StringUtil.isNumeric(fundNavDTO.getAssetNet()))
+                && (StrUtil.isBlank(fundNavDTO.getAssetShare()) || StringUtil.isNumeric(fundNavDTO.getAssetShare()));
+        if (!isvalidNumericFormat) {
+            log.warn("单位净值或累计净值或资产净值或资产份额格式不正确 -> 解析到的数据:{}", fundNavDTO);
+            return false;
+        }
+        log.info("数据格式验证通过...");
+        return true;
+    }
 }

+ 270 - 9
service-daq/src/main/java/com/simuwang/daq/service/EmailParseService.java

@@ -6,14 +6,14 @@ import cn.hutool.core.exceptions.ExceptionUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
 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.util.EmailUtil;
 import com.simuwang.base.common.util.FileUtil;
 import com.simuwang.base.config.EmailRuleConfig;
-import com.simuwang.base.mapper.EmailFieldMappingMapper;
-import com.simuwang.base.mapper.EmailTypeRuleMapper;
-import com.simuwang.base.pojo.dos.EmailFieldMappingDO;
-import com.simuwang.base.pojo.dos.EmailTypeRuleDO;
+import com.simuwang.base.mapper.*;
+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;
@@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
+import java.math.BigDecimal;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -46,13 +47,28 @@ public class EmailParseService {
     private final EmailRuleConfig emailRuleConfig;
     private final EmailFieldMappingMapper emailFieldMapper;
     private final EmailParserFactory emailParserFactory;
+    private final EmailParseInfoMapper emailParseInfoMapper;
+    private final FundInfomationMapper fundInfomationMapper;
+    private final EmailFileInfoMapper emailFileInfoMapper;
+    private final EmailFundNavMapper emailFundNavMapper;
+    private final EmailFundAssetMapper emailFundAssetMapper;
+    private final FundAliasMapper fundAliasMapper;
 
     public EmailParseService(EmailTypeRuleMapper emailTypeRuleMapper, EmailRuleConfig emailRuleConfig,
-                             EmailFieldMappingMapper emailFieldMapper, EmailParserFactory emailParserFactory) {
+                             EmailFieldMappingMapper emailFieldMapper, EmailParserFactory emailParserFactory,
+                             EmailParseInfoMapper emailParseInfoMapper, FundInfomationMapper fundInfomationMapper,
+                             EmailFileInfoMapper emailFileInfoMapper, EmailFundNavMapper emailFundNavMapper,
+                             EmailFundAssetMapper emailFundAssetMapper, FundAliasMapper fundAliasMapper) {
         this.emailTypeRuleMapper = emailTypeRuleMapper;
         this.emailRuleConfig = emailRuleConfig;
         this.emailFieldMapper = emailFieldMapper;
         this.emailParserFactory = emailParserFactory;
+        this.emailParseInfoMapper = emailParseInfoMapper;
+        this.fundInfomationMapper = fundInfomationMapper;
+        this.emailFileInfoMapper = emailFileInfoMapper;
+        this.emailFundNavMapper = emailFundNavMapper;
+        this.emailFundAssetMapper = emailFundAssetMapper;
+        this.fundAliasMapper = fundAliasMapper;
     }
 
     /**
@@ -78,23 +94,251 @@ public class EmailParseService {
             List<EmailContentInfoDTO> emailContentInfoDTOList = emailEntry.getValue();
             if (CollUtil.isEmpty(emailContentInfoDTOList)) {
                 log.warn("未采集到正文或附件");
+                continue;
             }
             List<EmailFundNavDTO> emailFundNavDTOList = CollUtil.newArrayList();
+            Map<EmailContentInfoDTO, List<EmailFundNavDTO>> fileNameNavMap = MapUtil.newHashMap();
             for (EmailContentInfoDTO emailContentInfoDTO : emailContentInfoDTOList) {
                 try {
                     List<EmailFundNavDTO> fundNavDTOList = parseEmail(emailContentInfoDTO, emailFieldMap);
+                    fileNameNavMap.put(emailContentInfoDTO, fundNavDTOList);
                     emailFundNavDTOList.addAll(fundNavDTOList);
                 } catch (Exception e) {
                     log.error("堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
                 }
             }
-            if (CollUtil.isEmpty(emailFundNavDTOList)) {
-                log.warn("未解析到净值 -> 邮件主题:{},邮件日期:{}", emailContentInfoDTOList.get(0).getEmailTitle(), emailContentInfoDTOList.get(0).getEmailDate());
+            // 保存相关信息 -> 邮件信息表,邮件文件表,邮件净值表,邮件规模表,基金净值表
+            saveRelatedTable(mailboxInfoDTO.getAccount(), emailContentInfoDTOList, fileNameNavMap);
+        }
+    }
+
+    private void saveRelatedTable(String emailAddress, List<EmailContentInfoDTO> emailContentInfoDTOList, Map<EmailContentInfoDTO, List<EmailFundNavDTO>> fileNameNavMap) {
+        String emailTitle = CollUtil.isNotEmpty(emailContentInfoDTOList) ? emailContentInfoDTOList.get(0).getEmailTitle() : null;
+        String emailDate = CollUtil.isNotEmpty(emailContentInfoDTOList) ? emailContentInfoDTOList.get(0).getEmailDate() : null;
+        Integer emailType = CollUtil.isNotEmpty(emailContentInfoDTOList) ? emailContentInfoDTOList.get(0).getEmailType() : null;
+
+        Date parseDate = new Date();
+        int emailParseStatus = EmailParseStatusConst.SUCCESS;
+        EmailParseInfoDO emailParseInfoDO = buildEmailParseInfo(emailAddress, emailDate, emailTitle, emailType, emailParseStatus, parseDate);
+        Integer emailId = saveEmailParseInfo(emailParseInfoDO);
+
+        for (Map.Entry<EmailContentInfoDTO, List<EmailFundNavDTO>> fileNameNavEntry : fileNameNavMap.entrySet()) {
+            // 保存邮件文件表
+            EmailContentInfoDTO emailContentInfoDTO = fileNameNavEntry.getKey();
+            Integer fileId = saveEmailFileInfo(emailId, emailContentInfoDTO.getFileName(), emailContentInfoDTO.getFilePath(), parseDate);
+
+            List<EmailFundNavDTO> fundNavDTOList = fileNameNavEntry.getValue();
+            if (CollUtil.isEmpty(fundNavDTOList)) {
                 continue;
             }
-            // todo 邮件信息表,邮件文件表,邮件净值表,邮件规模表,基金净值表
+            for (EmailFundNavDTO fundNavDTO : fundNavDTOList) {
+                // 设置净值数据的解析状态
+                setNavParseStatus(fundNavDTO, emailTitle, emailDate);
+            }
+            // 保存净值表和规模表
+            saveNavAndAssetNet(fileId, fundNavDTOList, parseDate);
+        }
+
+        // 更新邮件解析结果 -> 存在一条成功解析的净值数据就认为解析成功
+        long successNavCount = fileNameNavMap.values().stream().flatMap(List::stream).filter(e -> e.getParseStatus().equals(NavParseStatusConst.SUCCESS)).count();
+        emailParseStatus = successNavCount >= 1 ? EmailParseStatusConst.SUCCESS : EmailParseStatusConst.FAIL;
+        emailParseInfoMapper.updateParseStatus(emailId, emailParseStatus);
+    }
+
+    private void saveNavAndAssetNet(Integer fileId, List<EmailFundNavDTO> fundNavDTOList, Date parseDate) {
+        if (CollUtil.isEmpty(fundNavDTOList)) {
+            return;
+        }
+        // 净值数据
+        List<EmailFundNavDO> emailFundNavDOList = fundNavDTOList.stream()
+                .map(e -> buildEmailFundNavDo(fileId, e, parseDate)).flatMap(List::stream).collect(Collectors.toList());
+        if (CollUtil.isNotEmpty(emailFundNavDOList)) {
+            emailFundNavMapper.batchInsert(emailFundNavDOList);
+        }
+        // 保存规模数据
+        List<EmailFundAssetDO> emailFundAssetDOList = fundNavDTOList.stream()
+                .map(e -> buildEmailFundAssetDo(fileId, e, parseDate)).flatMap(List::stream).collect(Collectors.toList());
+        if (CollUtil.isNotEmpty(emailFundAssetDOList)) {
+            emailFundAssetMapper.batchInsert(emailFundAssetDOList);
+        }
+    }
+
+    private List<EmailFundAssetDO> buildEmailFundAssetDo(Integer fileId, EmailFundNavDTO fundNavDTO, Date parseDate) {
+        List<EmailFundAssetDO> fundAssetDOList = CollUtil.newArrayList();
+        BigDecimal assetNet = StrUtil.isNotBlank(fundNavDTO.getAssetNet()) ? new BigDecimal(fundNavDTO.getAssetNet()) : null;
+        BigDecimal assetShare = StrUtil.isNotBlank(fundNavDTO.getAssetShare()) ? new BigDecimal(fundNavDTO.getAssetShare()) : null;
+        if (assetNet == null) {
+            return fundAssetDOList;
+        }
+        Date priceDate = DateUtil.parse(fundNavDTO.getPriceDate(), DateConst.YYYY_MM_DD);
+        if (CollUtil.isNotEmpty(fundNavDTO.getFundIdList())) {
+            for (String fundId : fundNavDTO.getFundIdList()) {
+                EmailFundAssetDO emailFundAssetDO = new EmailFundAssetDO();
+                emailFundAssetDO.setFileId(fileId);
+                emailFundAssetDO.setPriceDate(priceDate);
+                emailFundAssetDO.setFundId(fundId);
+                emailFundAssetDO.setFundName(fundNavDTO.getFundName());
+                emailFundAssetDO.setRegisterNumber(fundNavDTO.getRegisterNumber());
+                emailFundAssetDO.setAssetNet(assetNet);
+                emailFundAssetDO.setAssetShare(assetShare);
+                emailFundAssetDO.setIsvalid(1);
+                emailFundAssetDO.setCreatorId(0);
+                emailFundAssetDO.setCreateTime(parseDate);
+                emailFundAssetDO.setUpdaterId(0);
+                emailFundAssetDO.setUpdateTime(parseDate);
+                fundAssetDOList.add(emailFundAssetDO);
+            }
+        } else {
+            EmailFundAssetDO emailFundAssetDO = new EmailFundAssetDO();
+            emailFundAssetDO.setFileId(fileId);
+            emailFundAssetDO.setPriceDate(priceDate);
+            emailFundAssetDO.setFundName(fundNavDTO.getFundName());
+            emailFundAssetDO.setRegisterNumber(fundNavDTO.getRegisterNumber());
+            emailFundAssetDO.setAssetNet(assetNet);
+            emailFundAssetDO.setAssetShare(assetShare);
+            emailFundAssetDO.setIsvalid(1);
+            emailFundAssetDO.setCreatorId(0);
+            emailFundAssetDO.setCreateTime(parseDate);
+            emailFundAssetDO.setUpdaterId(0);
+            emailFundAssetDO.setUpdateTime(parseDate);
+            fundAssetDOList.add(emailFundAssetDO);
+        }
+        return fundAssetDOList;
+    }
+
+    private List<EmailFundNavDO> buildEmailFundNavDo(Integer fileId, EmailFundNavDTO fundNavDTO, Date parseDate) {
+        List<EmailFundNavDO> fundNavDOList = CollUtil.newArrayList();
+        Date priceDate = DateUtil.parse(fundNavDTO.getPriceDate(), DateConst.YYYY_MM_DD);
+        BigDecimal nav = StrUtil.isNotBlank(fundNavDTO.getNav()) ? new BigDecimal(fundNavDTO.getNav()) : null;
+        BigDecimal cumulativeNavWithdrawal = StrUtil.isNotBlank(fundNavDTO.getCumulativeNavWithdrawal()) ? new BigDecimal(fundNavDTO.getCumulativeNavWithdrawal()) : null;
+        Integer isStored = fundNavDTO.getParseStatus() != null && !fundNavDTO.getParseStatus().equals(NavParseStatusConst.NAV_DEFICIENCY)
+                && !fundNavDTO.getParseStatus().equals(NavParseStatusConst.NOT_MATCH) ? 1 : 0;
+        if (CollUtil.isNotEmpty(fundNavDTO.getFundIdList())) {
+            for (String fundId : fundNavDTO.getFundIdList()) {
+                EmailFundNavDO emailFundNavDO = new EmailFundNavDO();
+                emailFundNavDO.setFileId(fileId);
+                emailFundNavDO.setIsStored(isStored);
+                emailFundNavDO.setPriceDate(priceDate);
+                emailFundNavDO.setNav(nav);
+                emailFundNavDO.setFundId(fundId);
+                emailFundNavDO.setCumulativeNavWithdrawal(cumulativeNavWithdrawal);
+                emailFundNavDO.setFundName(fundNavDTO.getFundName());
+                emailFundNavDO.setRegisterNumber(fundNavDTO.getRegisterNumber());
+                emailFundNavDO.setExceptionStatus(fundNavDTO.getParseStatus());
+                emailFundNavDO.setIsvalid(1);
+                emailFundNavDO.setCreatorId(0);
+                emailFundNavDO.setCreateTime(parseDate);
+                emailFundNavDO.setUpdaterId(0);
+                emailFundNavDO.setUpdateTime(parseDate);
+                fundNavDOList.add(emailFundNavDO);
+            }
+        } else {
+            EmailFundNavDO emailFundNavDO = new EmailFundNavDO();
+            emailFundNavDO.setFileId(fileId);
+            emailFundNavDO.setPriceDate(priceDate);
+            emailFundNavDO.setNav(nav);
+            emailFundNavDO.setCumulativeNavWithdrawal(cumulativeNavWithdrawal);
+            emailFundNavDO.setFundName(fundNavDTO.getFundName());
+            emailFundNavDO.setRegisterNumber(fundNavDTO.getRegisterNumber());
+            emailFundNavDO.setExceptionStatus(fundNavDTO.getParseStatus());
+            emailFundNavDO.setIsvalid(1);
+            emailFundNavDO.setCreatorId(0);
+            emailFundNavDO.setCreateTime(parseDate);
+            emailFundNavDO.setUpdaterId(0);
+            emailFundNavDO.setUpdateTime(parseDate);
+            fundNavDOList.add(emailFundNavDO);
+        }
+        return fundNavDOList;
+    }
+
+    private Integer saveEmailFileInfo(Integer emailId, String fileName, String filePath, Date parseDate) {
+        EmailFileInfoDO emailFileInfoDO = buildEmailFileInfoDO(emailId, fileName, filePath, parseDate);
+        return emailFileInfoMapper.insert(emailFileInfoDO);
+    }
+
+    private EmailFileInfoDO buildEmailFileInfoDO(Integer emailId, String fileName, String filePath, Date parseDate) {
+        EmailFileInfoDO emailFileInfoDO = new EmailFileInfoDO();
+        emailFileInfoDO.setEmailId(emailId);
+        emailFileInfoDO.setFileName(fileName);
+        emailFileInfoDO.setFilePath(filePath);
+        emailFileInfoDO.setIsvalid(1);
+        emailFileInfoDO.setCreatorId(0);
+        emailFileInfoDO.setCreateTime(parseDate);
+        emailFileInfoDO.setUpdaterId(0);
+        emailFileInfoDO.setUpdateTime(parseDate);
+        return emailFileInfoDO;
+    }
+
+    private void setNavParseStatus(EmailFundNavDTO fundNavDTO, String emailTitle, String emailDate) {
+        Integer navParseStatus = getDataParseStatus(fundNavDTO, emailTitle, emailDate);
+        fundNavDTO.setParseStatus(navParseStatus);
+        if (navParseStatus.equals(NavParseStatusConst.NAV_DEFICIENCY)) {
+            return;
+        }
+        // 2.匹配基金
+        List<String> fundIdList = matchFund(fundNavDTO.getFundName(), fundNavDTO.getRegisterNumber());
+        if (CollUtil.isEmpty(fundIdList)) {
+            fundNavDTO.setParseStatus(NavParseStatusConst.NOT_MATCH);
+        }
+        fundNavDTO.setFundIdList(fundIdList);
+    }
+
+    private List<String> matchFund(String fundName, String registerNumber) {
+        // 1.基金名称 + 备案编码 一起进行匹配
+        List<String> fundIdList = fundInfomationMapper.queryFundByNameAndRegisterNumber(fundName, registerNumber);
+        if (CollUtil.isNotEmpty(fundIdList)) {
+            return fundIdList;
+        }
+        fundIdList = fundAliasMapper.queryFundByNameAndRegisterNumber(fundName, registerNumber);
+        if (CollUtil.isNotEmpty(fundIdList)) {
+            return fundIdList;
+        }
+        // 2.基金名称匹配
+        if(StrUtil.isNotBlank(fundName)){
+            List<String> fundIds = fundInfomationMapper.queryFundByName(fundName);
+            if (CollUtil.isNotEmpty(fundIds)) {
+                return fundIdList;
+            }
+            fundIds = fundAliasMapper.queryFundByName(fundName);
+            if (CollUtil.isNotEmpty(fundIds)) {
+                return fundIds;
+            }
+        }
+        // 3.备案编码匹配
+        if(StrUtil.isNotBlank(fundName)){
+            List<String> fundIds = fundInfomationMapper.queryFundByRegisterNumber(registerNumber);
+            if (CollUtil.isNotEmpty(fundIds)) {
+                return fundIds;
+            }
+            fundIds = fundAliasMapper.queryFundByRegisterNumber(registerNumber);
+            if (CollUtil.isNotEmpty(fundIds)) {
+                return fundIds;
+            }
+        }
+        return CollUtil.newArrayList();
+    }
 
+    private Integer saveEmailParseInfo(EmailParseInfoDO emailParseInfoDO) {
+        if (emailParseInfoDO == null) {
+            return null;
         }
+        return emailParseInfoMapper.insert(emailParseInfoDO);
+    }
+
+    private EmailParseInfoDO buildEmailParseInfo(String emailAddress, String emailDate, String emailTitle, Integer emailType, Integer parseStatus, Date parseDate) {
+        EmailParseInfoDO emailParseInfoDO = new EmailParseInfoDO();
+        emailParseInfoDO.setEmail(emailAddress);
+        emailParseInfoDO.setEmailDate(DateUtil.parse(emailDate, DateConst.YYYY_MM_DD_HH_MM_SS));
+        emailParseInfoDO.setParseDate(parseDate);
+        emailParseInfoDO.setEmailTitle(emailTitle);
+        emailParseInfoDO.setEmailType(emailType);
+        emailParseInfoDO.setParseStatus(parseStatus);
+        emailParseInfoDO.setIsvalid(1);
+        emailParseInfoDO.setCreatorId(0);
+        emailParseInfoDO.setCreateTime(parseDate);
+        emailParseInfoDO.setUpdaterId(0);
+        emailParseInfoDO.setUpdateTime(parseDate);
+        return emailParseInfoDO;
     }
 
     private List<EmailFundNavDTO> parseEmail(EmailContentInfoDTO emailContentInfoDTO, Map<String, List<String>> emailFieldMap) {
@@ -103,6 +347,23 @@ public class EmailParseService {
         return emailParser.parse(emailContentInfoDTO, emailFieldMap);
     }
 
+    private Integer getDataParseStatus(EmailFundNavDTO fundNavDTO, String emailTitle, String emailDate) {
+        log.info("判断数据的解析状态 -> 邮件主题:{},邮件日期:{},净值数据:{}", emailTitle, emailDate, fundNavDTO);
+        // 1.单位净值或累计净值缺失
+        if (StrUtil.isBlank(fundNavDTO.getNav()) || StrUtil.isBlank(fundNavDTO.getCumulativeNavWithdrawal())) {
+            return NavParseStatusConst.NAV_DEFICIENCY;
+        }
+        // 3.单位净值或累计净值不大于0
+        if (fundNavDTO.getNav().compareTo("0") <= 0 || fundNavDTO.getCumulativeNavWithdrawal().compareTo("0") <= 0) {
+            return NavParseStatusConst.NAV_NEGATIVE;
+        }
+        // 4.资产净值不大于0
+        if (StrUtil.isNotBlank(fundNavDTO.getAssetNet()) && fundNavDTO.getAssetNet().compareTo("0") <= 0) {
+            return NavParseStatusConst.ASSET_NET_NEGATIVE;
+        }
+        return NavParseStatusConst.SUCCESS;
+    }
+
     public Map<String, List<String>> getEmailFieldMapping() {
         List<EmailFieldMappingDO> emailFieldMappingDOList = emailFieldMapper.getEmailFieldMapping();
         return emailFieldMappingDOList.stream()
@@ -142,7 +403,7 @@ public class EmailParseService {
         // 获取邮件日期大于等于startDate的邮件(搜索条件只支持按天)
         SearchTerm startDateTerm = new ReceivedDateTerm(ComparisonTerm.GE, startDate);
         Message[] messages = folder.search(startDateTerm);
-        String path = "/data/file/";
+        String path = "/data/file";
         Map<String, List<EmailContentInfoDTO>> emailMessageMap = MapUtil.newHashMap();
         for (Message message : messages) {
             List<EmailContentInfoDTO> emailContentInfoDTOList = CollUtil.newArrayList();

+ 5 - 0
service-daq/src/main/java/com/simuwang/daq/service/NavEmailParser.java

@@ -27,6 +27,7 @@ import java.io.File;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * @author mozuwen
@@ -61,6 +62,10 @@ public class NavEmailParser extends AbstractEmailParser {
             List<EmailFundNavDTO> fundNavDTOList = parseExcelFile(emailContentInfoDTO.getFilePath(), emailFieldMap);
             emailFundNavDTOList.addAll(fundNavDTOList);
         }
+        // 校验净值数据格式
+        if (CollUtil.isNotEmpty(emailFundNavDTOList)) {
+            emailFundNavDTOList = emailFundNavDTOList.stream().filter(super::dataFormat).collect(Collectors.toList());
+        }
         return emailFundNavDTOList;
     }