CompetitionTask.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package com.simuwang.manage.task;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.collection.ListUtil;
  4. import cn.hutool.core.date.DateUtil;
  5. import cn.hutool.core.exceptions.ExceptionUtil;
  6. import cn.hutool.core.util.StrUtil;
  7. import com.alibaba.excel.EasyExcel;
  8. import com.simuwang.base.common.conts.DateConst;
  9. import com.simuwang.base.common.util.EmailUtil;
  10. import com.simuwang.base.config.CompetitionConfig;
  11. import com.simuwang.base.mapper.RcCompetitionCalcDateMapper;
  12. import com.simuwang.base.mapper.RcCompetitionTaskDateMapper;
  13. import com.simuwang.base.pojo.dos.RcCompetitionCalcDateDO;
  14. import com.simuwang.base.pojo.dos.RcCompetitionTaskDateDO;
  15. import com.simuwang.base.pojo.dto.FundNavDataDTO;
  16. import com.simuwang.base.pojo.dto.FundNavDeletionDTO;
  17. import com.simuwang.base.pojo.dto.MailboxInfoDTO;
  18. import com.simuwang.base.pojo.dto.competition.CompetitionBaseResultDTO;
  19. import com.simuwang.manage.service.EmailSystemConfigService;
  20. import com.simuwang.manage.service.competition.FundNavService;
  21. import com.simuwang.task.CompetitionIndicatorCalcTask;
  22. import org.slf4j.Logger;
  23. import org.slf4j.LoggerFactory;
  24. import org.springframework.beans.factory.annotation.Qualifier;
  25. import org.springframework.scheduling.annotation.Scheduled;
  26. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  27. import org.springframework.stereotype.Component;
  28. import java.io.File;
  29. import java.util.Date;
  30. import java.util.List;
  31. import java.util.Map;
  32. import java.util.stream.Collectors;
  33. @Component
  34. public class CompetitionTask {
  35. private static final Logger log = LoggerFactory.getLogger(CompetitionTask.class);
  36. private final FundNavService fundNavService;
  37. private final CompetitionConfig competitionConfig;
  38. private final EmailSystemConfigService emailSystemConfigService;
  39. private final RcCompetitionTaskDateMapper competitionTaskDateMapper;
  40. private final RcCompetitionCalcDateMapper competitionCalcDateMapper;
  41. private final FundDeletionTask fundDeletionTask;
  42. private final CompetitionIndicatorCalcTask competitionIndicatorCalcTask;
  43. private final ThreadPoolTaskExecutor asyncExecutor;
  44. public CompetitionTask(FundNavService fundNavService, CompetitionConfig competitionConfig,
  45. EmailSystemConfigService emailSystemConfigService, RcCompetitionTaskDateMapper competitionTaskDateMapper,
  46. RcCompetitionCalcDateMapper competitionCalcDateMapper, FundDeletionTask fundDeletionTask,
  47. CompetitionIndicatorCalcTask competitionIndicatorCalcTask, @Qualifier("asyncExecutor") ThreadPoolTaskExecutor asyncExecutor) {
  48. this.fundNavService = fundNavService;
  49. this.competitionConfig = competitionConfig;
  50. this.emailSystemConfigService = emailSystemConfigService;
  51. this.competitionTaskDateMapper = competitionTaskDateMapper;
  52. this.competitionCalcDateMapper = competitionCalcDateMapper;
  53. this.fundDeletionTask = fundDeletionTask;
  54. this.competitionIndicatorCalcTask = competitionIndicatorCalcTask;
  55. this.asyncExecutor = asyncExecutor;
  56. }
  57. public String getResult(Integer type, Integer competitionId, String period) {
  58. asyncExecutor.execute(() -> {
  59. if (type == 1) {
  60. outputFundNavDetail(competitionId, period);
  61. } else if (type == 2) {
  62. List<RcCompetitionCalcDateDO> calcDateDOList = competitionCalcDateMapper.queryByPriod(ListUtil.toList(period), competitionId);
  63. if (CollUtil.isNotEmpty(calcDateDOList)) {
  64. outputFundNavDeletion(competitionId, period, calcDateDOList.get(0).getBeginDate(), calcDateDOList.get(0).getEndDate());
  65. }
  66. } else if (type == 3) {
  67. List<RcCompetitionCalcDateDO> calcDateDOList = competitionCalcDateMapper.queryByPriod(ListUtil.toList(period), competitionId);
  68. if (CollUtil.isNotEmpty(calcDateDOList)) {
  69. outputCompetitionResult(competitionId, period, calcDateDOList.get(0));
  70. }
  71. }
  72. });
  73. return "操作成功,请等到结果输出...";
  74. }
  75. /**
  76. * 输出基金净值采集结果明细任务
  77. * 每天10:00,15:00执行任务
  78. */
  79. @Scheduled(cron = "0 0 10,15 * * ?")
  80. public void fundNavDataTask() {
  81. Integer competitionId = competitionConfig.getId();
  82. String date = DateUtil.format(new Date(), DateConst.YYYY_MM_DD);
  83. List<RcCompetitionTaskDateDO> taskDateDOList = competitionTaskDateMapper.queryByNavDetailDate(date, competitionId);
  84. if (CollUtil.isEmpty(taskDateDOList)) {
  85. return;
  86. }
  87. for (RcCompetitionTaskDateDO taskDateDO : taskDateDOList) {
  88. String period = taskDateDO.getPriod();
  89. outputFundNavDetail(competitionId, period);
  90. }
  91. }
  92. /**
  93. * 输出基金净值缺失明细任务
  94. * 每天10:00,15:00执行任务
  95. */
  96. @Scheduled(cron = "0 0 10,15 * * ?")
  97. public void navDeletionTask() {
  98. Integer competitionId = competitionConfig.getId();
  99. String date = DateUtil.format(new Date(), DateConst.YYYY_MM_DD);
  100. List<RcCompetitionTaskDateDO> taskDateDOList = competitionTaskDateMapper.queryByNavDetailDate(date, competitionId);
  101. if (CollUtil.isEmpty(taskDateDOList)) {
  102. return;
  103. }
  104. // 输出之前 -> 执行净值缺失检测(确保净值不全的基金不参与榜单)
  105. fundDeletionTask.computeDeletion();
  106. List<String> periodList = taskDateDOList.stream().map(RcCompetitionTaskDateDO::getPriod).distinct().toList();
  107. List<RcCompetitionCalcDateDO> calcDateDOList = competitionCalcDateMapper.queryByPriod(periodList, competitionId);
  108. Map<String, RcCompetitionCalcDateDO> periodCalcDataDoMap = calcDateDOList.stream().collect(Collectors.toMap(RcCompetitionCalcDateDO::getPriod, v -> v));
  109. for (RcCompetitionTaskDateDO taskDateDO : taskDateDOList) {
  110. RcCompetitionCalcDateDO calcDateDO = periodCalcDataDoMap.get(taskDateDO.getPriod());
  111. if (calcDateDO == null) {
  112. continue;
  113. }
  114. String beginDate = calcDateDO.getBeginDate();
  115. String endDate = calcDateDO.getEndDate();
  116. outputFundNavDeletion(competitionId, taskDateDO.getPriod(), beginDate, endDate);
  117. }
  118. }
  119. /**
  120. * 输出基金净值衍生指标及排名结果明细任务
  121. * 每天10:00,15:00执行任务
  122. */
  123. @Scheduled(cron = "0 0 10,15 * * ?")
  124. public void competitionResultTask() {
  125. Integer competitionId = competitionConfig.getId();
  126. String date = DateUtil.format(new Date(), DateConst.YYYY_MM_DD);
  127. List<RcCompetitionTaskDateDO> taskDateDOList = competitionTaskDateMapper.queryByPriodDate(date, competitionId);
  128. if (CollUtil.isEmpty(taskDateDOList)) {
  129. return;
  130. }
  131. List<String> periodList = taskDateDOList.stream().map(RcCompetitionTaskDateDO::getPriod).distinct().collect(Collectors.toList());
  132. List<RcCompetitionCalcDateDO> calcDateDOList = competitionCalcDateMapper.queryByPriod(periodList, competitionId);
  133. Map<String, RcCompetitionCalcDateDO> periodCalcDataDoMap = calcDateDOList.stream().collect(Collectors.toMap(RcCompetitionCalcDateDO::getPriod, v -> v));
  134. for (RcCompetitionTaskDateDO taskDateDO : taskDateDOList) {
  135. String period = taskDateDO.getPriod();
  136. RcCompetitionCalcDateDO calcDateDO = periodCalcDataDoMap.get(period);
  137. outputCompetitionResult(competitionId, period, calcDateDO);
  138. }
  139. }
  140. public void outputFundNavDetail(Integer competitionId, String period) {
  141. List<FundNavDataDTO> navDataDTOList = fundNavService.getFungNavData(competitionId);
  142. if (CollUtil.isEmpty(navDataDTOList)) {
  143. return;
  144. }
  145. String filePath = competitionConfig.getDirectory() + competitionConfig.getName() + "_" + period + "_榜单_基金净值采集结果明细_" + DateUtil.format(new Date(), DateConst.YYYYMMDD) + ".xlsx";
  146. EasyExcel.write(filePath, FundNavDataDTO.class)
  147. .sheet("基金净值采集结果明细")
  148. .doWrite(navDataDTOList);
  149. log.info("基金净值采集结果明细表格已输出 -> 文件:{}", filePath);
  150. // 通过邮件发送"基金净值采集结果明细表格"
  151. if (competitionConfig.getMethod() == 1) {
  152. MailboxInfoDTO mailboxInfoDTO = emailSystemConfigService.getFromEmailInfo();
  153. String receivingMailbox = emailSystemConfigService.getRecipientEmail();
  154. if (mailboxInfoDTO == null || StrUtil.isBlank(receivingMailbox)) {
  155. log.info("未配置发件箱和收件箱,无法发送邮件");
  156. return;
  157. }
  158. try {
  159. EmailUtil.senEmail(mailboxInfoDTO, receivingMailbox, new File(filePath), "基金净值采集结果明细", "", period + "基金净值采集结果明细");
  160. log.info("基金净值采集结果明细表 -> 邮件已发送");
  161. } catch (Exception e) {
  162. log.error("邮件发送基金净值采集结果明细表异常 -> 堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
  163. }
  164. }
  165. }
  166. private void outputFundNavDeletion(Integer competitionId, String period, String beginDate, String endDate) {
  167. List<FundNavDeletionDTO> navDeletionDTOList = fundNavService.getFundNavDeletion(competitionId, beginDate, endDate);
  168. if (CollUtil.isEmpty(navDeletionDTOList)) {
  169. return;
  170. }
  171. String filePath = competitionConfig.getDirectory() + competitionConfig.getName() + "_" + period + "_榜单_基金净值缺失明细_" + DateUtil.format(new Date(), DateConst.YYYYMMDD) + ".xlsx";
  172. EasyExcel.write(filePath, FundNavDeletionDTO.class)
  173. .sheet("基金净值缺失明细")
  174. .doWrite(navDeletionDTOList);
  175. // 通过邮件发送"基金净值采集结果明细表格"
  176. if (competitionConfig.getMethod() == 1) {
  177. MailboxInfoDTO mailboxInfoDTO = emailSystemConfigService.getFromEmailInfo();
  178. String receivingMailbox = emailSystemConfigService.getRecipientEmail();
  179. if (mailboxInfoDTO == null || StrUtil.isBlank(receivingMailbox)) {
  180. log.info("未配置发件箱和收件箱,无法发送邮件");
  181. return;
  182. }
  183. try {
  184. EmailUtil.senEmail(mailboxInfoDTO, receivingMailbox, new File(filePath), "基金净值缺失明细", "", period + "_榜单_基金净值缺失明细");
  185. log.info("基金净值缺失明细表 -> 邮件已发送");
  186. } catch (Exception e) {
  187. log.error("邮件发送基金净值缺失明细表异常 -> 堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
  188. }
  189. }
  190. }
  191. private void outputCompetitionResult(Integer competitionId, String period, RcCompetitionCalcDateDO calcDateDO) {
  192. long startTime = System.currentTimeMillis();
  193. // 输出榜单之前 -> 执行净值缺失检测(确保净值不全的基金不参与榜单)
  194. fundDeletionTask.computeDeletion();
  195. // 输出榜单之前 -> 执行基金净值指标计算
  196. competitionIndicatorCalcTask.calculateIndicator(competitionId, calcDateDO);
  197. List<? extends CompetitionBaseResultDTO> competitionResultDTOList = fundNavService.getCompetitionResult(competitionId, period);
  198. if (CollUtil.isEmpty(competitionResultDTOList)) {
  199. return;
  200. }
  201. Class<? extends CompetitionBaseResultDTO> aClass = competitionResultDTOList.get(0).getClass();
  202. String filePath = competitionConfig.getDirectory() + competitionConfig.getName() + "_" + period + "_榜单_基金净值衍生指标及排名结果明细_" + DateUtil.format(new Date(), DateConst.YYYYMMDD) + ".xlsx";
  203. EasyExcel.write(filePath, aClass)
  204. .sheet("基金净值衍生指标及排名结果明细")
  205. .doWrite(competitionResultDTOList);
  206. log.info("基金净值衍生指标及排名结果明细表已输出 -> 文件:{},耗时:{}", filePath, (System.currentTimeMillis() - startTime));
  207. Integer method = competitionConfig.getMethod();
  208. // 通过邮件发送"基金净值采集结果明细表格"
  209. if (method == 1) {
  210. MailboxInfoDTO mailboxInfoDTO = emailSystemConfigService.getFromEmailInfo();
  211. String receivingMailbox = emailSystemConfigService.getRecipientEmail();
  212. if (mailboxInfoDTO == null || StrUtil.isBlank(receivingMailbox)) {
  213. log.info("未配置发件箱和收件箱,无法发送邮件");
  214. return;
  215. }
  216. try {
  217. String emailTitle = period + "_榜单_基金净值衍生指标及排名结果明细";
  218. EmailUtil.senEmail(mailboxInfoDTO, receivingMailbox, new File(filePath), emailTitle, "", emailTitle);
  219. log.info("基金净值衍生指标及排名结果明细表 -> 邮件已发送");
  220. } catch (Exception e) {
  221. log.error("邮件发送基金净值衍生指标及排名结果明细表异常 -> 堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
  222. }
  223. }
  224. }
  225. }