|
@@ -1,13 +1,14 @@
|
|
|
package com.simuwang.manage.service.impl;
|
|
|
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
import com.simuwang.base.common.enums.DeletionType;
|
|
|
+import com.simuwang.base.common.enums.DistributeType;
|
|
|
+import com.simuwang.base.common.enums.Frequency;
|
|
|
import com.simuwang.base.common.support.MybatisPage;
|
|
|
import com.simuwang.base.common.util.DateUtils;
|
|
|
import com.simuwang.base.common.util.StringUtil;
|
|
|
-import com.simuwang.base.mapper.DeletionInfoMapper;
|
|
|
-import com.simuwang.base.mapper.FundInfoMapper;
|
|
|
-import com.simuwang.base.pojo.dos.DeletionInfoDO;
|
|
|
-import com.simuwang.base.pojo.dos.FundDeletionInfoDO;
|
|
|
+import com.simuwang.base.mapper.*;
|
|
|
+import com.simuwang.base.pojo.dos.*;
|
|
|
import com.simuwang.base.pojo.dto.DeletionDownParam;
|
|
|
import com.simuwang.base.pojo.dto.ExcelDeletionInfoDTO;
|
|
|
import com.simuwang.base.pojo.dto.query.DeletionPageQuery;
|
|
@@ -18,8 +19,11 @@ import com.simuwang.shiro.utils.UserUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.TreeMap;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
@@ -36,6 +40,21 @@ public class DeletionServiceImpl implements DeletionService {
|
|
|
|
|
|
@Autowired
|
|
|
private FundInfoMapper fundInfoMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AssetMapper assetMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FundReportFrequencyMapper fundReportFrequencyMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TradeDateMapper tradeDateMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DistributionMapper distributionMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private NavMapper navMapper;
|
|
|
@Override
|
|
|
public MybatisPage<DeletionInfoVO> searchDeletionList(DeletionPageQuery deletionPageQuery) {
|
|
|
List<DeletionInfoDO> deletionInfoDOList = deletionInfoMapper.searchDeletionList(deletionPageQuery);
|
|
@@ -106,4 +125,269 @@ public class DeletionServiceImpl implements DeletionService {
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void computeDeletion(DeletionDownParam deletionDownParam) {
|
|
|
+ String fundId = deletionDownParam.getFundId();
|
|
|
+ String liquidateDate = fundInfoMapper.getLiquidateDateByFundId(fundId);
|
|
|
+ if(StringUtil.isNotEmpty(liquidateDate)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String inceptionDate = fundInfoMapper.getInceptionDateByFundId(fundId);
|
|
|
+ if(StringUtil.isEmpty(inceptionDate)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String today = DateUtils.getAroundToday(0);
|
|
|
+ //获取基金对应的净值报送频率
|
|
|
+ FundReportFrequencyDO fundReportFrequencyDO = fundReportFrequencyMapper.getFrequencyByFundId(fundId);
|
|
|
+ if(StringUtil.isNull(fundReportFrequencyDO)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<NavDO> navDOList = navMapper.selectNavByFundId(fundId);
|
|
|
+ List<AssetDO> assetDOList = assetMapper.selectAssetByFundId(fundId);
|
|
|
+ //查询成立日到今天为止的交易日集合
|
|
|
+ List<TradeDateDO> tradeDateDOList = tradeDateMapper.selectTradeDate(inceptionDate,today);
|
|
|
+ //延迟天数为3天
|
|
|
+ tradeDateDOList = tradeDateDOList.subList(0,tradeDateDOList.size()-3);
|
|
|
+ if(deletionDownParam.getDeletionType() != null && deletionDownParam.getDeletionType().equals(DeletionType.NAV_DELETION.getCode())){
|
|
|
+ navDeletion(fundId,navDOList,tradeDateDOList,fundReportFrequencyDO);
|
|
|
+ }else if(deletionDownParam.getDeletionType() != null && deletionDownParam.getDeletionType().equals(DeletionType.ASSET_DELETION.getCode())){
|
|
|
+ assetDeletion(fundId,assetDOList,tradeDateDOList,fundReportFrequencyDO);
|
|
|
+ }else if(deletionDownParam.getDeletionType() != null && deletionDownParam.getDeletionType().equals(DeletionType.DISTRIBUTION_DELETION.getCode())){
|
|
|
+ distributionDeletion(fundId,navDOList);
|
|
|
+ }else{
|
|
|
+ navDeletion(fundId,navDOList,tradeDateDOList,fundReportFrequencyDO);
|
|
|
+ assetDeletion(fundId,assetDOList,tradeDateDOList,fundReportFrequencyDO);
|
|
|
+ distributionDeletion(fundId,navDOList);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void distributionDeletion(String fundId, List<NavDO> navDOList) {
|
|
|
+ if(navDOList.size() < 1){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //查询是否存在拆分
|
|
|
+ List<DistributionDO> distributionDOS = distributionMapper.getDistributionByFundId(fundId, DistributeType.DIVIDENDS_SPLIT);
|
|
|
+ if(distributionDOS.size() > 0){
|
|
|
+ //存在拆分,不做分红缺失计算,同时把以往的数据添加备注
|
|
|
+ deletionInfoMapper.updateRemark(fundId,DeletionType.ASSET_DELETION.getCode(),null,DeletionType.EXIST_SPLIT.getInfo(),null);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ BigDecimal threshold = new BigDecimal(0.0035);
|
|
|
+ BigDecimal preDifference = new BigDecimal(0);
|
|
|
+ for(int navIdx=0;navIdx < navDOList.size() ;navIdx++){
|
|
|
+ NavDO navDO = navDOList.get(navIdx);
|
|
|
+ //获取当前净值日期下的分红总和
|
|
|
+ BigDecimal sumDistribute = distributionMapper.getSumDistributeByFundId(navDO.getFundId(),DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD));
|
|
|
+ BigDecimal nav = navDO.getNav();
|
|
|
+ BigDecimal cumulativeNavWithdrawal = navDO.getCumulativeNavWithdrawal();
|
|
|
+ if(sumDistribute == null){
|
|
|
+ sumDistribute = new BigDecimal(0);
|
|
|
+ }
|
|
|
+ //不存在分红的时候,判断当前的差值是否符合要求
|
|
|
+ BigDecimal difference = cumulativeNavWithdrawal.subtract(nav.add(sumDistribute));
|
|
|
+ if(difference.compareTo(threshold) > 0){
|
|
|
+ //存在缺失
|
|
|
+ String tradeDate = null;
|
|
|
+ if(navIdx == 0 || navDOList.size() ==1){
|
|
|
+ //有且仅有一条数据
|
|
|
+ tradeDate = DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD)+"~"+DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ }else{
|
|
|
+ //判断前一条的差值与当前是否一致,一致就不处理
|
|
|
+ if(difference.compareTo(preDifference) == 0){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ tradeDate = DateUtils.format(navDOList.get(navIdx-1).getPriceDate(),DateUtils.YYYY_MM_DD)+"~"+DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ }
|
|
|
+ saveDeletionInfoDO(fundId,tradeDate,DeletionType.DISTRIBUTION_DELETION.getCode());
|
|
|
+ }
|
|
|
+ preDifference = difference;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assetDeletion(String fundId, List<AssetDO> assetDOList, List<TradeDateDO> tradeDateDOList, FundReportFrequencyDO fundReportFrequencyDO) {
|
|
|
+ if(Frequency.DAY == Frequency.getFrequencyByCode(fundReportFrequencyDO.getAssetFrequency())){
|
|
|
+ Map<String,List<AssetDO>> navListMap = assetDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
|
|
|
+ Map<String,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getTradeDate(),DateUtils.YYYY_MM_DD)));
|
|
|
+ for(String tradeDate : tradeListMap.keySet()){
|
|
|
+ if(navListMap.containsKey(tradeDate)){
|
|
|
+ deletionInfoMapper.updateRemark(fundId,DeletionType.ASSET_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //写入缺失信息表
|
|
|
+ saveDeletionInfoDO(fundId,tradeDate,DeletionType.ASSET_DELETION.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Frequency.WEEK == Frequency.getFrequencyByCode(fundReportFrequencyDO.getAssetFrequency())){
|
|
|
+ Map<String,List<AssetDO>> navListMap = assetDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
|
|
|
+ TreeMap<Integer,List<AssetDO>> weekNavListMap = new TreeMap<>();
|
|
|
+ //按周数整合
|
|
|
+ for(String priceDate : navListMap.keySet()){
|
|
|
+ Integer weekOfYear = DateUtil.weekOfYear(DateUtils.parse(priceDate,DateUtils.YYYY_MM_DD));
|
|
|
+ if(weekNavListMap.containsKey(weekOfYear)){
|
|
|
+ List<AssetDO> assetDOS = weekNavListMap.get(weekOfYear);
|
|
|
+ assetDOS.addAll(navListMap.get(priceDate));
|
|
|
+ weekNavListMap.put(weekOfYear,assetDOS);
|
|
|
+ }else{
|
|
|
+ List<AssetDO> navDOS = new ArrayList<>();
|
|
|
+ navDOS.addAll(navListMap.get(priceDate));
|
|
|
+ weekNavListMap.put(weekOfYear,navDOS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Map<Integer,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> e.getWeekOfYear()));
|
|
|
+ for(Integer weekOfYear : tradeListMap.keySet()){
|
|
|
+ if(weekNavListMap.containsKey(weekOfYear)){
|
|
|
+ List<AssetDO> assetDOS = weekNavListMap.get(weekOfYear);
|
|
|
+ String tradeDate = DateUtils.format(assetDOS.get(assetDOS.size()-1).getPriceDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ deletionInfoMapper.updateRemark(fundId,DeletionType.ASSET_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //不包含的话,默认取每周的最后一个交易日作为周净值日期
|
|
|
+ List<TradeDateDO> tradeDateDOS = tradeListMap.get(weekOfYear);
|
|
|
+ String tradeDate = null;
|
|
|
+ if(tradeDateDOS.size() > 0){
|
|
|
+ tradeDate = DateUtils.format(tradeDateDOS.get(tradeDateDOS.size()-1).getTradeDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ }
|
|
|
+ //写入缺失信息表
|
|
|
+ saveDeletionInfoDO(fundId,tradeDate,DeletionType.ASSET_DELETION.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Frequency.MONTH == Frequency.getFrequencyByCode(fundReportFrequencyDO.getAssetFrequency())){
|
|
|
+ Map<String,List<AssetDO>> navListMap = assetDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
|
|
|
+ TreeMap<String,List<AssetDO>> monthNavListMap = new TreeMap<>();
|
|
|
+ //按周数整合
|
|
|
+ for(String priceDate : navListMap.keySet()){
|
|
|
+ String yearMonth = priceDate.substring(0,7);
|
|
|
+ if(monthNavListMap.containsKey(yearMonth)){
|
|
|
+ List<AssetDO> navDOS = monthNavListMap.get(yearMonth);
|
|
|
+ navDOS.addAll(navListMap.get(priceDate));
|
|
|
+ monthNavListMap.put(yearMonth,navDOS);
|
|
|
+ }else{
|
|
|
+ List<AssetDO> navDOS = new ArrayList<>();
|
|
|
+ navDOS.addAll(navListMap.get(priceDate));
|
|
|
+ monthNavListMap.put(yearMonth,navDOS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Map<String,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> e.getYearmonth()));
|
|
|
+ for(String yearMonth : tradeListMap.keySet()){
|
|
|
+ if(monthNavListMap.containsKey(yearMonth)){
|
|
|
+ List<AssetDO> assetDOS = monthNavListMap.get(yearMonth);
|
|
|
+ String tradeDate = DateUtils.format(assetDOS.get(assetDOS.size()-1).getPriceDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ deletionInfoMapper.updateRemark(fundId,DeletionType.ASSET_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //不包含的话,默认取每周的最后一个交易日作为周净值日期
|
|
|
+ List<TradeDateDO> tradeDateDOS = tradeListMap.get(yearMonth);
|
|
|
+ String tradeDate = null;
|
|
|
+ if(tradeDateDOS.size() > 0){
|
|
|
+ tradeDate = DateUtils.format(tradeDateDOS.get(tradeDateDOS.size()-1).getTradeDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ }
|
|
|
+ //写入缺失信息表
|
|
|
+ saveDeletionInfoDO(fundId,tradeDate,DeletionType.ASSET_DELETION.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void navDeletion(String fundId,List<NavDO> navDOList, List<TradeDateDO> tradeDateDOList,FundReportFrequencyDO fundReportFrequencyDO) {
|
|
|
+ //只处理日月季频率
|
|
|
+ if(Frequency.DAY == Frequency.getFrequencyByCode(fundReportFrequencyDO.getNavFrequency())){
|
|
|
+ Map<String,List<NavDO>> navListMap = navDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
|
|
|
+ Map<String,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getTradeDate(),DateUtils.YYYY_MM_DD)));
|
|
|
+ for(String tradeDate : tradeListMap.keySet()){
|
|
|
+ if(navListMap.containsKey(tradeDate)){
|
|
|
+ deletionInfoMapper.updateRemark(fundId,DeletionType.NAV_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //写入缺失信息表
|
|
|
+ saveDeletionInfoDO(fundId,tradeDate,DeletionType.NAV_DELETION.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Frequency.WEEK == Frequency.getFrequencyByCode(fundReportFrequencyDO.getNavFrequency())){
|
|
|
+ Map<String,List<NavDO>> navListMap = navDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
|
|
|
+ TreeMap<Integer,List<NavDO>> weekNavListMap = new TreeMap<>();
|
|
|
+ //按周数整合
|
|
|
+ for(String priceDate : navListMap.keySet()){
|
|
|
+ Integer weekOfYear = DateUtil.weekOfYear(DateUtils.parse(priceDate,DateUtils.YYYY_MM_DD));
|
|
|
+ if(weekNavListMap.containsKey(weekOfYear)){
|
|
|
+ List<NavDO> navDOS = weekNavListMap.get(weekOfYear);
|
|
|
+ navDOS.addAll(navListMap.get(priceDate));
|
|
|
+ weekNavListMap.put(weekOfYear,navDOS);
|
|
|
+ }else{
|
|
|
+ List<NavDO> navDOS = new ArrayList<>();
|
|
|
+ navDOS.addAll(navListMap.get(priceDate));
|
|
|
+ weekNavListMap.put(weekOfYear,navDOS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Map<Integer,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> e.getWeekOfYear()));
|
|
|
+ for(Integer weekOfYear : tradeListMap.keySet()){
|
|
|
+ if(weekNavListMap.containsKey(weekOfYear)){
|
|
|
+ List<NavDO> navDOS = weekNavListMap.get(weekOfYear);
|
|
|
+ String tradeDate = DateUtils.format(navDOS.get(navDOS.size()-1).getPriceDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ deletionInfoMapper.updateRemark(fundId,DeletionType.NAV_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //不包含的话,默认取每周的最后一个交易日作为周净值日期
|
|
|
+ List<TradeDateDO> tradeDateDOS = tradeListMap.get(weekOfYear);
|
|
|
+ String tradeDate = null;
|
|
|
+ if(tradeDateDOS.size() > 0){
|
|
|
+ tradeDate = DateUtils.format(tradeDateDOS.get(tradeDateDOS.size()-1).getTradeDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ }
|
|
|
+ //写入缺失信息表
|
|
|
+ saveDeletionInfoDO(fundId,tradeDate,DeletionType.NAV_DELETION.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Frequency.MONTH == Frequency.getFrequencyByCode(fundReportFrequencyDO.getNavFrequency())){
|
|
|
+ Map<String,List<NavDO>> navListMap = navDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
|
|
|
+ TreeMap<String,List<NavDO>> monthNavListMap = new TreeMap<>();
|
|
|
+ //按周数整合
|
|
|
+ for(String priceDate : navListMap.keySet()){
|
|
|
+ String yearMonth = priceDate.substring(0,7);
|
|
|
+ if(monthNavListMap.containsKey(yearMonth)){
|
|
|
+ List<NavDO> navDOS = monthNavListMap.get(yearMonth);
|
|
|
+ navDOS.addAll(navListMap.get(priceDate));
|
|
|
+ monthNavListMap.put(yearMonth,navDOS);
|
|
|
+ }else{
|
|
|
+ List<NavDO> navDOS = new ArrayList<>();
|
|
|
+ navDOS.addAll(navListMap.get(priceDate));
|
|
|
+ monthNavListMap.put(yearMonth,navDOS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Map<String,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> e.getYearmonth()));
|
|
|
+ for(String yearMonth : tradeListMap.keySet()){
|
|
|
+ if(monthNavListMap.containsKey(yearMonth)){
|
|
|
+ List<NavDO> navDOS = monthNavListMap.get(yearMonth);
|
|
|
+ String tradeDate = DateUtils.format(navDOS.get(navDOS.size()-1).getPriceDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ deletionInfoMapper.updateRemark(fundId,DeletionType.NAV_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //不包含的话,默认取每周的最后一个交易日作为周净值日期
|
|
|
+ List<TradeDateDO> tradeDateDOS = tradeListMap.get(yearMonth);
|
|
|
+ String tradeDate = null;
|
|
|
+ if(tradeDateDOS.size() > 0){
|
|
|
+ tradeDate = DateUtils.format(tradeDateDOS.get(tradeDateDOS.size()-1).getTradeDate(),DateUtils.YYYY_MM_DD);
|
|
|
+ }
|
|
|
+ //写入缺失信息表
|
|
|
+ saveDeletionInfoDO(fundId,tradeDate,DeletionType.NAV_DELETION.getCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveDeletionInfoDO(String fundId, String tradeDate, Integer code) {
|
|
|
+ if(tradeDate == null){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ DeletionInfoDO deletionInfoDO = new DeletionInfoDO();
|
|
|
+ deletionInfoDO.setFundId(fundId);
|
|
|
+ deletionInfoDO.setDeletionDate(tradeDate);
|
|
|
+ deletionInfoDO.setDeletionType(code);
|
|
|
+ DeletionInfoDO oldDeletionDO = deletionInfoMapper.getDeletionInfoDO(deletionInfoDO);
|
|
|
+ if(StringUtil.isNull(oldDeletionDO)){
|
|
|
+ deletionInfoDO.setIsvalid(1);
|
|
|
+ deletionInfoDO.setIsSend(0);
|
|
|
+ deletionInfoDO.setUpdateTime(DateUtils.getNowDate());
|
|
|
+ deletionInfoDO.setCreateTime(DateUtils.getNowDate());
|
|
|
+ deletionInfoMapper.saveDeletionInfoDO(deletionInfoDO);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|