123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- package com.simuwang.manage.service.competition;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.map.MapUtil;
- import com.simuwang.base.common.conts.DateConst;
- import com.simuwang.base.common.util.NavDataUtil;
- 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.base.pojo.dto.TradeDateDTO;
- import com.simuwang.base.pojo.dto.competition.CompetitionBaseResultDTO;
- import org.springframework.stereotype.Service;
- import java.math.BigDecimal;
- import java.math.RoundingMode;
- import java.util.Comparator;
- import java.util.Date;
- import java.util.List;
- import java.util.Map;
- import java.util.stream.Collectors;
- @Service
- public class FundNavService {
- private final NavMapper navMapper;
- private final FundInfoMapper fundInfoMapper;
- private final AssetMapper assetMapper;
- private final DeletionInfoMapper deletionInfoMapper;
- private final TradeDateMapper tradeDateMapper;
- private final CompetitionFactory competitionFactory;
- public FundNavService(NavMapper navMapper, FundInfoMapper fundInfoMapper,
- AssetMapper assetMapper, DeletionInfoMapper deletionInfoMapper,
- TradeDateMapper tradeDateMapper, CompetitionFactory competitionFactory) {
- this.navMapper = navMapper;
- this.fundInfoMapper = fundInfoMapper;
- this.assetMapper = assetMapper;
- this.deletionInfoMapper = deletionInfoMapper;
- this.tradeDateMapper = tradeDateMapper;
- this.competitionFactory = competitionFactory;
- }
- public List<FundNavDataDTO> getFungNavData(Integer competitionId) {
- List<FundNavDataDTO> navDataDTOList = CollUtil.newArrayList();
- List<NavDO> navDOList = navMapper.queryAllNav(competitionId);
- if (CollUtil.isEmpty(navDOList)) {
- return navDataDTOList;
- }
- // 过滤出周频的净值点
- String toDay = DateUtil.format(new Date(), DateConst.YYYY_MM_DD);
- List<TradeDateDO> tradeDateDOList = tradeDateMapper.listAllTradeDate(toDay);
- navDOList = NavDataUtil.filterWeekFrequencyNav(navDOList, tradeDateDOList);
- List<String> fundIdList = navDOList.stream().map(NavDO::getFundId).distinct().toList();
- List<FundAndCompanyInfoDO> fundInfoCompanyNameList = fundInfoMapper.queryFundAndTrustByFundId(competitionId);
- Map<String, FundAndCompanyInfoDO> fundIdCompanyNameMap = fundInfoCompanyNameList.stream().collect(Collectors.toMap(FundAndCompanyInfoDO::getFundId, v -> v));
- List<AssetDO> assetDOList = assetMapper.queryAssetByFundId(fundIdList);
- Map<String, List<AssetDO>> fundIdAssetMap = MapUtil.newHashMap();
- if (CollUtil.isNotEmpty(assetDOList)) {
- fundIdAssetMap = assetDOList.stream().collect(Collectors.groupingBy(AssetDO::getFundId));
- }
- Map<String, List<NavDO>> fundIdNavMap = navDOList.stream().collect(Collectors.groupingBy(NavDO::getFundId));
- for (Map.Entry<String, List<NavDO>> fundIdNavEntry : fundIdNavMap.entrySet()) {
- String fundId = fundIdNavEntry.getKey();
- List<NavDO> fundNavDoList = fundIdNavEntry.getValue();
- List<AssetDO> fundAssetDoList = fundIdAssetMap.get(fundId);
- FundAndCompanyInfoDO fundInfoDO = fundIdCompanyNameMap.get(fundId);
- List<FundNavDataDTO> fundNavDataDTOList = buildFundNavDataDTO(fundInfoDO, fundNavDoList, fundAssetDoList);
- navDataDTOList.addAll(fundNavDataDTOList);
- }
- return navDataDTOList;
- }
- public List<FundNavDeletionDTO> getFundNavDeletion(Integer competitionId, String endDate) {
- List<FundNavDeletionDTO> navDeletionDTOList = CollUtil.newArrayList();
- // 缺失类型-1对应全部,1-净值缺失,2-对应规模缺失,3-对应分红缺失,5-估值缺失
- List<FundDeletionInfoDO> deletionInfoDOList = deletionInfoMapper.getFundNavDeletionNew(1, competitionId, endDate);
- if (CollUtil.isEmpty(deletionInfoDOList)) {
- return navDeletionDTOList;
- }
- Map<String, List<FundDeletionInfoDO>> fundIdDeletionInfoMap = deletionInfoDOList.stream().collect(Collectors.groupingBy(FundDeletionInfoDO::getFundId));
- // 基金信息和对应的管理人信息
- List<FundAndCompanyInfoDO> fundInfoCompanyNameList = fundInfoMapper.queryFundAndTrustByFundId(competitionId);
- if (CollUtil.isEmpty(fundInfoCompanyNameList)) {
- return navDeletionDTOList;
- }
- // 得到存在基金完整的基金id
- List<String> allFundIdList = navMapper.getAllFundId();
- // 得到基金净值缺失的基金Id
- List<String> deletionFundIdList = getDeletionFundId(fundInfoCompanyNameList, fundIdDeletionInfoMap);
- List<String> notDeletionFundIdList = allFundIdList.stream().filter(e -> !deletionFundIdList.contains(e)).toList();
- // 过滤掉净值没有缺失的基金Id
- fundInfoCompanyNameList = fundInfoCompanyNameList.stream().filter(e -> !notDeletionFundIdList.contains(e.getFundId())).toList();
- for (FundAndCompanyInfoDO fundAndCompanyInfoDO : fundInfoCompanyNameList) {
- String fundId = fundAndCompanyInfoDO.getFundId();
- String entryDate = DateUtil.format(fundAndCompanyInfoDO.getEntryDate(), DateConst.YYYY_MM_DD);
- // 获取净值日期所在年和所在周
- Map<String, TradeDateDTO> tradeDateDoMap = getYearAndWeekOfDate(entryDate, endDate);
- List<FundDeletionInfoDO> fundDeletionInfoDOList = fundIdDeletionInfoMap.get(fundId);
- if (CollUtil.isNotEmpty(fundDeletionInfoDOList)) {
- fundDeletionInfoDOList = fundDeletionInfoDOList.stream().filter(e -> e.getDeletionDate().compareTo(entryDate) >= 0).toList();
- }
- List<FundNavDeletionDTO> fundNavDataDTOList = buildFundNavDeletionDTO(fundAndCompanyInfoDO, fundDeletionInfoDOList, tradeDateDoMap);
- navDeletionDTOList.addAll(fundNavDataDTOList);
- }
- return navDeletionDTOList;
- }
- private List<String> getDeletionFundId(List<FundAndCompanyInfoDO> fundInfoCompanyNameList, Map<String, List<FundDeletionInfoDO>> fundIdDeletionInfoMap) {
- List<String> deletionFundIdList = CollUtil.newArrayList();
- for (FundAndCompanyInfoDO fundAndCompanyInfoDO : fundInfoCompanyNameList) {
- String fundId = fundAndCompanyInfoDO.getFundId();
- String entryDate = DateUtil.format(fundAndCompanyInfoDO.getEntryDate(), DateConst.YYYY_MM_DD);
- List<FundDeletionInfoDO> fundDeletionInfoDOList = fundIdDeletionInfoMap.get(fundId);
- if (CollUtil.isEmpty(fundDeletionInfoDOList)) {
- continue;
- }
- long count = fundDeletionInfoDOList.stream().filter(e -> e.getDeletionDate().compareTo(entryDate) >= 0).count();
- if (count != 0) {
- deletionFundIdList.add(fundId);
- }
- }
- return deletionFundIdList;
- }
- public List<? extends CompetitionBaseResultDTO> getCompetitionResult(Integer competitionId, String period) {
- List<? extends CompetitionBaseResultDTO> dataList = CollUtil.newArrayList();
- AbstractCompetitionResultService competitionResult = competitionFactory.getInstance(competitionId);
- if (competitionResult == null) {
- return dataList;
- }
- return competitionResult.getCompetitionResult(competitionId, period);
- }
- private List<FundNavDeletionDTO> buildFundNavDeletionDTO(FundAndCompanyInfoDO fundAndCompanyInfoDO, List<FundDeletionInfoDO> fundDeletionInfoDOList, Map<String, TradeDateDTO> tradeDateDoMap) {
- String fundName = fundAndCompanyInfoDO.getFundName();
- String trustName = fundAndCompanyInfoDO.getCompanyName();
- String trustRegisterNumber = fundAndCompanyInfoDO.getCompanyRegisterNumber();
- String registerNumber = fundAndCompanyInfoDO.getRegisterNumber();
- String fundId = fundAndCompanyInfoDO.getFundId();
- // 净值缺失表中无该基金的数据 -> 该基金为缺失全部净值
- if (CollUtil.isEmpty(fundDeletionInfoDOList)) {
- List<FundNavDeletionDTO> navDeletionDTOList = CollUtil.newArrayList();
- tradeDateDoMap.forEach((k, v) -> {
- FundNavDeletionDTO fundNavDeletionDTO = new FundNavDeletionDTO();
- fundNavDeletionDTO.setTrustName(trustName);
- fundNavDeletionDTO.setTrustRegisterNumber(trustRegisterNumber);
- fundNavDeletionDTO.setFundId(fundId);
- fundNavDeletionDTO.setFundName(fundName);
- fundNavDeletionDTO.setRegisterNumber(registerNumber);
- fundNavDeletionDTO.setYear(v != null ? v.getYear() + v.getWeek() : null);
- fundNavDeletionDTO.setWeek(v != null ? String.valueOf(v.getWeek()) : null);
- // 第1周(2022-12-26至2022-12-30)
- String date = v != null ? v.getFirstDate() + "至" + v.getLastDate() : null;
- fundNavDeletionDTO.setCompetitionDate(date);
- fundNavDeletionDTO.setDate(k);
- navDeletionDTOList.add(fundNavDeletionDTO);
- });
- navDeletionDTOList.sort(Comparator.comparing(FundNavDeletionDTO::getFundName).thenComparing(FundNavDeletionDTO::getWeek));
- return navDeletionDTOList;
- }
- return fundDeletionInfoDOList.stream().map(e -> {
- FundNavDeletionDTO fundNavDeletionDTO = new FundNavDeletionDTO();
- fundNavDeletionDTO.setTrustName(trustName);
- fundNavDeletionDTO.setTrustRegisterNumber(trustRegisterNumber);
- fundNavDeletionDTO.setFundId(fundId);
- fundNavDeletionDTO.setFundName(fundName);
- fundNavDeletionDTO.setRegisterNumber(registerNumber);
- TradeDateDTO tradeDateDTO = tradeDateDoMap.get(e.getDeletionDate());
- fundNavDeletionDTO.setYear(tradeDateDTO != null ? tradeDateDTO.getYear() + tradeDateDTO.getWeek() : null);
- fundNavDeletionDTO.setWeek(tradeDateDTO != null ? String.valueOf(tradeDateDTO.getWeek()) : null);
- // 第1周(2022-12-26至2022-12-30)
- String date = tradeDateDTO != null ? tradeDateDTO.getFirstDate() + "至" + tradeDateDTO.getLastDate() : null;
- fundNavDeletionDTO.setCompetitionDate(date);
- fundNavDeletionDTO.setDate(e.getDeletionDate());
- return fundNavDeletionDTO;
- }).sorted(Comparator.comparing(FundNavDeletionDTO::getFundName).thenComparing(FundNavDeletionDTO::getWeek)).toList();
- }
- private List<FundNavDataDTO> buildFundNavDataDTO(FundAndCompanyInfoDO fundInfoDO, List<NavDO> fundNavDoList, List<AssetDO> fundAssetDoList) {
- String fundName = fundInfoDO.getFundName();
- String registerNumber = fundInfoDO.getRegisterNumber();
- String trustName = fundInfoDO.getCompanyName();
- String trustRegisterNumber = fundInfoDO.getCompanyRegisterNumber();
- 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.setTrustName(trustName);
- fundNavDataDTO.setTrustRegisterNumber(trustRegisterNumber);
- fundNavDataDTO.setFundId(e.getFundId());
- fundNavDataDTO.setFundName(fundName);
- fundNavDataDTO.setRegisterNumber(registerNumber);
- String priceDate = e.getPriceDate() != null ? DateUtil.format(e.getPriceDate(), DateConst.YYYY_MM_DD) : null;
- 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 = 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::getFundName).thenComparing(FundNavDataDTO::getPriceDate)).toList();
- }
- private Map<String, TradeDateDTO> getYearAndWeekOfDate(String startDate, String endDate) {
- Map<String, TradeDateDTO> tradeDateDoMap = MapUtil.newHashMap();
- List<TradeDateDO> tradeDateDOList = tradeDateMapper.selectTradeDate(startDate, endDate);
- if (CollUtil.isEmpty(tradeDateDOList)) {
- return tradeDateDoMap;
- }
- List<Integer> yearWeekList = tradeDateDOList.stream().map(TradeDateDO::getYearWeek).distinct().toList();
- Map<String, TradeDateDO> dateMap = tradeDateDOList.stream().collect(Collectors.toMap(k -> DateUtil.format(k.getTradeDate(), DateConst.YYYY_MM_DD), v -> v));
- Map<Integer, List<TradeDateDO>> yearWeekDateMap = tradeDateDOList.stream().collect(Collectors.groupingBy(TradeDateDO::getYearWeek));
- // 得到startDate~endDate的最后一个交易日
- List<String> dateList = CollUtil.newArrayList();
- yearWeekDateMap.forEach((k, v) -> {
- String date = v.stream().max(Comparator.comparing(TradeDateDO::getTradeDate)).map(e -> DateUtil.format(e.getTradeDate(), DateConst.YYYY_MM_DD)).orElse(null);
- dateList.add(date);
- });
- for (String date : dateList) {
- TradeDateDO tradeDateDO = dateMap.get(date);
- Integer yearWeek = tradeDateDO.getYearWeek();
- TradeDateDTO tradeDateDTO = new TradeDateDTO();
- tradeDateDTO.setWeek(tradeDateDO.getWeekOfYear());
- tradeDateDTO.setYear(tradeDateDO.getEndYear());
- String firstDate = yearWeekDateMap.get(yearWeek).stream()
- .min(Comparator.comparing(TradeDateDO::getTradeDate)).map(e -> DateUtil.format(e.getTradeDate(), DateConst.YYYY_MM_DD)).orElse(null);
- tradeDateDTO.setFirstDate(firstDate);
- tradeDateDTO.setLastDate(date);
- int competitionWeek = (int) yearWeekList.stream().filter(e -> e.compareTo(yearWeek) < 0).count() + 1;
- tradeDateDTO.setCompetitionWeek(competitionWeek);
- tradeDateDoMap.put(date, tradeDateDTO);
- }
- return tradeDateDoMap;
- }
- }
|