Browse Source

feat:输出基金净值缺失明细表格数据

mozuwen 5 months ago
parent
commit
dbcc450081

+ 2 - 0
service-base/src/main/java/com/simuwang/base/mapper/DeletionInfoMapper.java

@@ -52,4 +52,6 @@ public interface DeletionInfoMapper {
     void deleteDeletion(@Param("fundId")String fundId, @Param("deletionType")Integer deletionType);
 
     void updateDeletionInfoDO(DeletionInfoDO oldDeletionDO);
+
+    List<FundDeletionInfoDO> getFundNavDeletion(@Param("deletionType") Integer deletionType);
 }

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

@@ -53,4 +53,6 @@ public interface FundInfoMapper {
     Long countFundTotal();
 
     List<FundInfoDO> queryFundInfoByFundId(@Param("fundIdList") List<String> fundIdList);
+
+    List<FundAndCompanyInfoDO> queryFundAndTrustByFundId(@Param("fundIdList")List<String> fundIdList);
 }

+ 2 - 0
service-base/src/main/java/com/simuwang/base/mapper/TradeDateMapper.java

@@ -15,4 +15,6 @@ import java.util.List;
 @Mapper
 public interface TradeDateMapper {
     List<TradeDateDO> selectTradeDate(@Param("startDate") String inceptionDate,@Param("endDate")  String today);
+
+    List<TradeDateDO> queryByDate(@Param("dateList") List<String> dateList);
 }

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

@@ -9,6 +9,7 @@ public class FundAndCompanyInfoDO {
     private String fundId;
     private String fundName;
     private String fundShortName;
+    private String registerNumber;
     private String companyId;
     private String companyName;
 }

+ 53 - 0
service-base/src/main/java/com/simuwang/base/pojo/dto/FundNavDeletionDTO.java

@@ -0,0 +1,53 @@
+package com.simuwang.base.pojo.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.HeadFontStyle;
+import lombok.Data;
+
+@Data
+public class FundNavDeletionDTO {
+
+    /**
+     * 管理人名称
+     */
+    @HeadFontStyle(fontHeightInPoints = 10)
+    @ColumnWidth(25)
+    @ExcelProperty("管理人名称")
+    private String trustName;
+
+    /**
+     * 基金名称
+     */
+    @ColumnWidth(25)
+    @ExcelProperty("基金名称")
+    private String fundName;
+
+    /**
+     * 备案编码
+     */
+    @ColumnWidth(15)
+    @ExcelProperty("备案编码")
+    private String registerNumber;
+
+    /**
+     * 缺失年份
+     */
+    @ColumnWidth(15)
+    @ExcelProperty("缺失年份")
+    private String year;
+
+    /**
+     * 缺失周数
+     */
+    @ColumnWidth(15)
+    @ExcelProperty("缺失周数")
+    private String week;
+
+    /**
+     * 缺失日期
+     */
+    @ColumnWidth(15)
+    @ExcelProperty("缺失日期")
+    private String date;
+}

+ 6 - 0
service-base/src/main/resources/mapper/DeletionInfoMapper.xml

@@ -288,4 +288,10 @@
         update deletion_info d set isvalid=1,updatetime=now() where id=#{id}
     </update>
 
+    <select id="getFundNavDeletion" resultMap="BaseMap">
+        select fund_id, deletion_date
+        from deletion_info
+        where isvalid = 1
+          and deletion_type = #{deletionType}
+    </select>
 </mapper>

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

@@ -230,4 +230,20 @@
             #{fundId}
         </foreach>
     </select>
+
+    <select id="queryFundAndTrustByFundId" 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 pvn_fund_info t
+                 left join pvn_company_info t1 on t1.isvalid = 1 and t1.company_id = t.trust_id
+        where t.isvalid = 1
+              and t.fund_id in
+              <foreach collection="fundIdList" item="fundId" index="index" open="(" separator="," close=")">
+                 #{fundId}
+              </foreach>
+    </select>
+
 </mapper>

+ 10 - 0
service-base/src/main/resources/mapper/TradeDateMapper.xml

@@ -19,5 +19,15 @@
         from pvn_trade_date where isvalid=1 and isholiday=0 and trade_date>=#{startDate} and trade_date <![CDATA[ <= ]]> #{endDate}
     </select>
 
+    <select id="queryByDate" resultMap="BaseResultMap">
+        select trade_date, end_year, week_of_year, year_week
+        from pvn_trade_date
+        where isvalid = 1
+        and isholiday = 0
+        and trade_date in
+        <foreach collection="dateList" index="index" item="date" open="(" separator="," close=")">
+            #{date}
+        </foreach>
+    </select>
 
 </mapper>

+ 8 - 0
service-manage/src/main/java/com/simuwang/manage/service/FundNavService.java

@@ -1,6 +1,7 @@
 package com.simuwang.manage.service;
 
 import com.simuwang.base.pojo.dto.FundNavDataDTO;
+import com.simuwang.base.pojo.dto.FundNavDeletionDTO;
 
 import java.util.List;
 
@@ -8,8 +9,15 @@ public interface FundNavService {
 
     /**
      * 获取基金净值数据
+     *
      * @return 基金净值数据
      */
     List<FundNavDataDTO> getFungNavData();
 
+    /**
+     * 获取基金净值缺失明细数据
+     *
+     * @return 基金净值缺失明细数据
+     */
+    List<FundNavDeletionDTO> getFundNavDeletion();
 }

+ 74 - 11
service-manage/src/main/java/com/simuwang/manage/service/impl/FundNavServiceImpl.java

@@ -1,16 +1,14 @@
 package com.simuwang.manage.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.map.MapUtil;
 import com.simuwang.base.common.conts.DateConst;
-import com.simuwang.base.mapper.AssetMapper;
-import com.simuwang.base.mapper.FundInfoMapper;
-import com.simuwang.base.mapper.NavMapper;
-import com.simuwang.base.pojo.dos.AssetDO;
-import com.simuwang.base.pojo.dos.FundInfoDO;
-import com.simuwang.base.pojo.dos.NavDO;
+import com.simuwang.base.mapper.*;
+import com.simuwang.base.pojo.dos.*;
 import com.simuwang.base.pojo.dto.FundNavDataDTO;
+import com.simuwang.base.pojo.dto.FundNavDeletionDTO;
 import com.simuwang.manage.service.FundNavService;
 import org.springframework.stereotype.Service;
 
@@ -27,11 +25,16 @@ public class FundNavServiceImpl implements FundNavService {
     private final NavMapper navMapper;
     private final FundInfoMapper fundInfoMapper;
     private final AssetMapper assetMapper;
+    private final DeletionInfoMapper deletionInfoMapper;
+    private final TradeDateMapper tradeDateMapper;
 
-    public FundNavServiceImpl(NavMapper navMapper, FundInfoMapper fundInfoMapper, AssetMapper assetMapper) {
+    public FundNavServiceImpl(NavMapper navMapper, FundInfoMapper fundInfoMapper,
+                              AssetMapper assetMapper, DeletionInfoMapper deletionInfoMapper, TradeDateMapper tradeDateMapper) {
         this.navMapper = navMapper;
         this.fundInfoMapper = fundInfoMapper;
         this.assetMapper = assetMapper;
+        this.deletionInfoMapper = deletionInfoMapper;
+        this.tradeDateMapper = tradeDateMapper;
     }
 
     @Override
@@ -63,11 +66,58 @@ public class FundNavServiceImpl implements FundNavService {
         return navDataDTOList;
     }
 
+    @Override
+    public List<FundNavDeletionDTO> getFundNavDeletion() {
+        List<FundNavDeletionDTO> navDeletionDTOList = CollUtil.newArrayList();
+        // 缺失类型-1对应全部,1-净值缺失,2-对应规模缺失,3-对应分红缺失,5-估值缺失
+        List<FundDeletionInfoDO> deletionInfoDOList = deletionInfoMapper.getFundNavDeletion(1);
+        if (CollUtil.isEmpty(deletionInfoDOList)) {
+            return navDeletionDTOList;
+        }
+        List<String> fundIdList = deletionInfoDOList.stream().map(FundDeletionInfoDO::getFundId).distinct().toList();
+        List<FundAndCompanyInfoDO> fundInfoCompanyNameList = fundInfoMapper.queryFundAndTrustByFundId(fundIdList);
+        Map<String, FundAndCompanyInfoDO> fundIdCompanyNameMap = fundInfoCompanyNameList.stream().collect(Collectors.toMap(FundAndCompanyInfoDO::getFundId, v -> v));
+
+        // 获取净值日期所在年和所在周
+        List<String> dateList = deletionInfoDOList.stream().map(FundDeletionInfoDO::getDeletionDate).distinct().toList();
+        Map<String, TradeDateDO> tradeDateDoMap = getYearAndWeekOfDate(dateList);
+
+        Map<String, List<FundDeletionInfoDO>> fundIdDeletionInfoMap = deletionInfoDOList.stream().collect(Collectors.groupingBy(FundDeletionInfoDO::getFundId));
+        for (Map.Entry<String, List<FundDeletionInfoDO>> fundIdDeletionInfoEntry : fundIdDeletionInfoMap.entrySet()) {
+            String fundId = fundIdDeletionInfoEntry.getKey();
+            List<FundDeletionInfoDO> fundDeletionInfoDOList = fundIdDeletionInfoEntry.getValue();
+            FundAndCompanyInfoDO fundAndCompanyInfoDO = fundIdCompanyNameMap.get(fundId);
+            List<FundNavDeletionDTO> fundNavDataDTOList = buildFundNavDeletionDTO(fundAndCompanyInfoDO, fundDeletionInfoDOList, tradeDateDoMap);
+            navDeletionDTOList.addAll(fundNavDataDTOList);
+        }
+        return navDeletionDTOList;
+    }
+
+    private List<FundNavDeletionDTO> buildFundNavDeletionDTO(FundAndCompanyInfoDO fundAndCompanyInfoDO, List<FundDeletionInfoDO> fundDeletionInfoDOList, Map<String, TradeDateDO> tradeDateDoMap) {
+        String fundName = fundAndCompanyInfoDO.getFundName();
+        String trustName = fundAndCompanyInfoDO.getCompanyName();
+        String registerNumber = fundAndCompanyInfoDO.getRegisterNumber();
+        return fundDeletionInfoDOList.stream().map(e -> {
+            FundNavDeletionDTO fundNavDeletionDTO = new FundNavDeletionDTO();
+            fundNavDeletionDTO.setTrustName(trustName);
+            fundNavDeletionDTO.setFundName(fundName);
+            fundNavDeletionDTO.setRegisterNumber(registerNumber);
+            TradeDateDO tradeDateDO = tradeDateDoMap.get(e.getDeletionDate());
+            fundNavDeletionDTO.setYear(tradeDateDO != null ? tradeDateDO.getEndYear() : null);
+            fundNavDeletionDTO.setWeek(tradeDateDO != null ? String.valueOf(tradeDateDO.getWeekOfYear()) : null);
+            fundNavDeletionDTO.setDate(e.getDeletionDate());
+            return fundNavDeletionDTO;
+        }).sorted(Comparator.comparing(FundNavDeletionDTO::getFundName).thenComparing(FundNavDeletionDTO::getDate)).toList();
+    }
+
     private List<FundNavDataDTO> buildFundNavDataDTO(FundInfoDO fundInfoDO, List<NavDO> fundNavDoList, List<AssetDO> fundAssetDoList) {
         String fundName = fundInfoDO.getFundName();
         String registerNumber = fundInfoDO.getRegisterNumber();
-        Map<String, BigDecimal> priceDateAssetMap = fundAssetDoList.stream()
-                .collect(Collectors.toMap(k -> DateUtil.format(k.getPriceDate(), DateConst.YYYY_MM_DD), AssetDO::getAssetNet));
+        Map<String, BigDecimal> priceDateAssetMap = MapUtil.newHashMap();
+        if (CollUtil.isNotEmpty(fundAssetDoList)) {
+            priceDateAssetMap = fundAssetDoList.stream().collect(Collectors.toMap(k -> DateUtil.format(k.getPriceDate(), DateConst.YYYY_MM_DD), AssetDO::getAssetNet));
+        }
+        Map<String, BigDecimal> finalPriceDateAssetMap = priceDateAssetMap;
         return fundNavDoList.stream().map(e -> {
             FundNavDataDTO fundNavDataDTO = new FundNavDataDTO();
             fundNavDataDTO.setFundName(fundName);
@@ -76,10 +126,23 @@ public class FundNavServiceImpl implements FundNavService {
             fundNavDataDTO.setPriceDate(priceDate);
             fundNavDataDTO.setNav(e.getNav() != null ? String.valueOf(e.getNav()) : null);
             fundNavDataDTO.setCumulativeNavWithdrawal(e.getCumulativeNavWithdrawal() != null ? String.valueOf(e.getCumulativeNavWithdrawal()) : null);
-            BigDecimal asset = priceDateAssetMap.get(priceDate) != null ? priceDateAssetMap.get(priceDate).setScale(2, RoundingMode.HALF_UP) : null;
+            BigDecimal asset = finalPriceDateAssetMap.get(priceDate) != null ? finalPriceDateAssetMap.get(priceDate).setScale(2, RoundingMode.HALF_UP) : null;
             fundNavDataDTO.setAsset(asset != null ? String.valueOf(asset) : null);
             return fundNavDataDTO;
-        }).sorted(Comparator.comparing(FundNavDataDTO::getPriceDate)).toList();
+        }).sorted(Comparator.comparing(FundNavDataDTO::getFundName).thenComparing(FundNavDataDTO::getPriceDate)).toList();
     }
 
+    private Map<String, TradeDateDO> getYearAndWeekOfDate(List<String> dateList) {
+        Map<String, TradeDateDO> tradeDateDoMap = MapUtil.newHashMap();
+        if (CollUtil.isEmpty(dateList)) {
+            return tradeDateDoMap;
+        }
+        List<TradeDateDO> tradeDateDOList = CollUtil.newArrayList();
+        List<List<String>> partition = ListUtil.partition(dateList, 500);
+        partition.forEach(e -> tradeDateDOList.addAll(tradeDateMapper.queryByDate(dateList)));
+        if (CollUtil.isNotEmpty(tradeDateDOList)) {
+            tradeDateDoMap = tradeDateDOList.stream().collect(Collectors.toMap(k -> DateUtil.format(k.getTradeDate(), DateConst.YYYY_MM_DD), v -> v));
+        }
+        return tradeDateDoMap;
+    }
 }

+ 35 - 5
service-manage/src/main/java/com/simuwang/manage/task/GenerateNavDataTask.java

@@ -8,6 +8,7 @@ import com.simuwang.base.common.conts.DateConst;
 import com.simuwang.base.common.util.EmailUtil;
 import com.simuwang.base.config.CompetitionConfig;
 import com.simuwang.base.pojo.dto.FundNavDataDTO;
+import com.simuwang.base.pojo.dto.FundNavDeletionDTO;
 import com.simuwang.base.pojo.dto.MailboxInfoDTO;
 import com.simuwang.manage.service.EmailSystemConfigService;
 import com.simuwang.manage.service.FundNavService;
@@ -21,26 +22,27 @@ import java.util.Date;
 import java.util.List;
 
 @Component
-public class GenerateNavDataTask {
+public class CompetitionTask {
 
-    private static final Logger log = LoggerFactory.getLogger(GenerateNavDataTask.class);
+    private static final Logger log = LoggerFactory.getLogger(CompetitionTask.class);
 
     private final FundNavService fundNavService;
     private final CompetitionConfig competitionConfig;
 
     private final EmailSystemConfigService emailSystemConfigService;
 
-    public GenerateNavDataTask(FundNavService fundNavService, CompetitionConfig competitionConfig, EmailSystemConfigService emailSystemConfigService) {
+    public CompetitionTask(FundNavService fundNavService, CompetitionConfig competitionConfig, EmailSystemConfigService emailSystemConfigService) {
         this.fundNavService = fundNavService;
         this.competitionConfig = competitionConfig;
         this.emailSystemConfigService = emailSystemConfigService;
     }
 
     /**
+     * 输出基金净值采集结果明细任务
      * 每周五 18:00 执行
      */
-     @Scheduled(cron = "0 0 18 ? * 5")
-    public void runTask() {
+    @Scheduled(cron = "0 0 18 ? * 5")
+    public void fundNavDataTask() {
         List<FundNavDataDTO> navDataDTOList = fundNavService.getFungNavData();
         if (CollUtil.isEmpty(navDataDTOList)) {
             return;
@@ -64,4 +66,32 @@ public class GenerateNavDataTask {
             }
         }
     }
+
+    /**
+     * 输出基金净值缺失明细任务
+     * 每周五 18:00 执行
+     */
+    @Scheduled(cron = "0 0 18 ? * 5")
+    public void NavDeletionTask() {
+        List<FundNavDeletionDTO> navDeletionDTOList = fundNavService.getFundNavDeletion();
+        String filePath = competitionConfig.getDirectory() + "基金净值缺失明细_" + DateUtil.format(new Date(), DateConst.YYYYMMDD) + ".xlsx";
+        EasyExcel.write(filePath, FundNavDeletionDTO.class)
+                .sheet("基金净值缺失明细")
+                .doWrite(navDeletionDTOList);
+        log.info("基金净值缺失明细表格已输出 -> 文件:{}", filePath);
+
+        Integer method = competitionConfig.getMethod();
+        // 通过邮件发送"基金净值采集结果明细表格"
+        if (method == 1) {
+            MailboxInfoDTO mailboxInfoDTO = emailSystemConfigService.getFromEmailInfo();
+            String ReceivingMailbox = emailSystemConfigService.getRecipientEmail();
+            try {
+                EmailUtil.senEmail(mailboxInfoDTO, ReceivingMailbox, new File(filePath), "基金净值缺失明细", "", "基金净值缺失明细");
+                log.info("基金净值缺失明细表 -> 邮件已发送");
+            } catch (Exception e) {
+                log.error("邮件发送基金净值缺失明细表异常 -> 堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
+            }
+        }
+    }
+
 }