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 getFungNavData(Integer competitionId) { List navDataDTOList = CollUtil.newArrayList(); List navDOList = navMapper.queryAllNav(competitionId); if (CollUtil.isEmpty(navDOList)) { return navDataDTOList; } // 过滤出周频的净值点 String toDay = DateUtil.format(new Date(), DateConst.YYYY_MM_DD); List tradeDateDOList = tradeDateMapper.listAllTradeDate(toDay); navDOList = NavDataUtil.filterWeekFrequencyNav(navDOList, tradeDateDOList); List fundIdList = navDOList.stream().map(NavDO::getFundId).distinct().toList(); List fundInfoCompanyNameList = fundInfoMapper.queryFundAndTrustByFundId(competitionId); Map fundIdCompanyNameMap = fundInfoCompanyNameList.stream().collect(Collectors.toMap(FundAndCompanyInfoDO::getFundId, v -> v)); List assetDOList = assetMapper.queryAssetByFundId(fundIdList); Map> fundIdAssetMap = MapUtil.newHashMap(); if (CollUtil.isNotEmpty(assetDOList)) { fundIdAssetMap = assetDOList.stream().collect(Collectors.groupingBy(AssetDO::getFundId)); } Map> fundIdNavMap = navDOList.stream().collect(Collectors.groupingBy(NavDO::getFundId)); for (Map.Entry> fundIdNavEntry : fundIdNavMap.entrySet()) { String fundId = fundIdNavEntry.getKey(); List fundNavDoList = fundIdNavEntry.getValue(); List fundAssetDoList = fundIdAssetMap.get(fundId); FundAndCompanyInfoDO fundInfoDO = fundIdCompanyNameMap.get(fundId); List fundNavDataDTOList = buildFundNavDataDTO(fundInfoDO, fundNavDoList, fundAssetDoList); navDataDTOList.addAll(fundNavDataDTOList); } return navDataDTOList; } public List getFundNavDeletion(Integer competitionId, String startDate, String endDate) { List navDeletionDTOList = CollUtil.newArrayList(); // 缺失类型-1对应全部,1-净值缺失,2-对应规模缺失,3-对应分红缺失,5-估值缺失 List deletionInfoDOList = deletionInfoMapper.getFundNavDeletion(1, competitionId, startDate, endDate); if (CollUtil.isEmpty(deletionInfoDOList)) { return navDeletionDTOList; } List fundInfoCompanyNameList = fundInfoMapper.queryFundAndTrustByFundId(competitionId); Map fundIdCompanyNameMap = fundInfoCompanyNameList.stream().collect(Collectors.toMap(FundAndCompanyInfoDO::getFundId, v -> v)); // 获取净值日期所在年和所在周 List dateList = deletionInfoDOList.stream().map(FundDeletionInfoDO::getDeletionDate).distinct().toList(); Map tradeDateDoMap = getYearAndWeekOfDate(startDate, endDate, dateList); Map> fundIdDeletionInfoMap = deletionInfoDOList.stream().collect(Collectors.groupingBy(FundDeletionInfoDO::getFundId)); for (Map.Entry> fundIdDeletionInfoEntry : fundIdDeletionInfoMap.entrySet()) { String fundId = fundIdDeletionInfoEntry.getKey(); List fundDeletionInfoDOList = fundIdDeletionInfoEntry.getValue(); FundAndCompanyInfoDO fundAndCompanyInfoDO = fundIdCompanyNameMap.get(fundId); List fundNavDataDTOList = buildFundNavDeletionDTO(fundAndCompanyInfoDO, fundDeletionInfoDOList, tradeDateDoMap); navDeletionDTOList.addAll(fundNavDataDTOList); } return navDeletionDTOList; } public List getCompetitionResult(Integer competitionId, String period) { List dataList = CollUtil.newArrayList(); AbstractCompetitionResultService competitionResult = competitionFactory.getInstance(competitionId); if (competitionResult == null) { return dataList; } return competitionResult.getCompetitionResult(competitionId, period); } private List buildFundNavDeletionDTO(FundAndCompanyInfoDO fundAndCompanyInfoDO, List fundDeletionInfoDOList, Map tradeDateDoMap) { String fundName = fundAndCompanyInfoDO.getFundName(); String trustName = fundAndCompanyInfoDO.getCompanyName(); String trustRegisterNumber = fundAndCompanyInfoDO.getCompanyRegisterNumber(); String registerNumber = fundAndCompanyInfoDO.getRegisterNumber(); return fundDeletionInfoDOList.stream().map(e -> { FundNavDeletionDTO fundNavDeletionDTO = new FundNavDeletionDTO(); fundNavDeletionDTO.setTrustName(trustName); fundNavDeletionDTO.setTrustRegisterNumber(trustRegisterNumber); fundNavDeletionDTO.setFundId(e.getFundId()); 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.getCompetitionWeek() + "周(" + tradeDateDTO.getFirstDate() + "至" + tradeDateDTO.getLastDate() + ")"; fundNavDeletionDTO.setCompetitionDate(date); fundNavDeletionDTO.setDate(e.getDeletionDate()); return fundNavDeletionDTO; }).sorted(Comparator.comparing(FundNavDeletionDTO::getFundName).thenComparing(FundNavDeletionDTO::getWeek)).toList(); } private List buildFundNavDataDTO(FundAndCompanyInfoDO fundInfoDO, List fundNavDoList, List fundAssetDoList) { String fundName = fundInfoDO.getFundName(); String registerNumber = fundInfoDO.getRegisterNumber(); String trustName = fundInfoDO.getCompanyName(); String trustRegisterNumber = fundInfoDO.getCompanyRegisterNumber(); Map 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 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 getYearAndWeekOfDate(String startDate, String endDate, List dateList) { Map tradeDateDoMap = MapUtil.newHashMap(); List tradeDateDOList = tradeDateMapper.selectTradeDate(startDate, endDate); if (CollUtil.isEmpty(tradeDateDOList)) { return tradeDateDoMap; } List yearWeekList = tradeDateDOList.stream().map(e -> e.getYearWeek()).distinct().toList(); Map dateMap = tradeDateDOList.stream().collect(Collectors.toMap(k -> DateUtil.format(k.getTradeDate(), DateConst.YYYY_MM_DD), v -> v)); Map> yearWeekDateMap = tradeDateDOList.stream().collect(Collectors.groupingBy(TradeDateDO::getYearWeek)); 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; } }