CompetitionTask.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. outputFundNavDeletion(competitionId, period, true);
  63. } else if (type == 3) {
  64. List<RcCompetitionCalcDateDO> calcDateDOList = competitionCalcDateMapper.queryByPriod(ListUtil.toList(period), competitionId);
  65. if (CollUtil.isNotEmpty(calcDateDOList)) {
  66. outputCompetitionResult(competitionId, period, calcDateDOList.get(0));
  67. }
  68. }
  69. });
  70. return "操作成功,请等到结果输出...";
  71. }
  72. /**
  73. * 输出基金净值采集结果明细任务
  74. * 每天10:00,15:00执行任务
  75. */
  76. @Scheduled(cron = "0 0 10,15 * * ?")
  77. public void fundNavDataTask() {
  78. Integer competitionId = competitionConfig.getId();
  79. String date = DateUtil.format(new Date(), DateConst.YYYY_MM_DD);
  80. List<RcCompetitionTaskDateDO> taskDateDOList = competitionTaskDateMapper.queryByNavDetailDate(date, competitionId);
  81. if (CollUtil.isEmpty(taskDateDOList)) {
  82. return;
  83. }
  84. for (RcCompetitionTaskDateDO taskDateDO : taskDateDOList) {
  85. String period = taskDateDO.getPriod();
  86. outputFundNavDetail(competitionId, period);
  87. }
  88. }
  89. /**
  90. * 输出基金净值缺失明细任务
  91. * 每天10:00,15:00执行任务
  92. */
  93. @Scheduled(cron = "0 0 10,15 * * ?")
  94. public void navDeletionTask() {
  95. Integer competitionId = competitionConfig.getId();
  96. // 输出之前 -> 执行净值缺失检测
  97. fundDeletionTask.computeDeletion();
  98. String period = DateUtil.format(new Date(), DateConst.YYYY_MM);
  99. outputFundNavDeletion(competitionId, period, false);
  100. }
  101. /**
  102. * 输出基金净值衍生指标及排名结果明细任务
  103. * 每天10:00,15:00执行任务
  104. */
  105. @Scheduled(cron = "0 0 10,15 * * ?")
  106. public void competitionResultTask() {
  107. Integer competitionId = competitionConfig.getId();
  108. String date = DateUtil.format(new Date(), DateConst.YYYY_MM_DD);
  109. List<RcCompetitionTaskDateDO> taskDateDOList = competitionTaskDateMapper.queryByPriodDate(date, competitionId);
  110. if (CollUtil.isEmpty(taskDateDOList)) {
  111. return;
  112. }
  113. // 输出榜单之前 -> 执行净值缺失检测(确保净值不全的基金不参与榜单)
  114. fundDeletionTask.computeDeletion();
  115. List<String> periodList = taskDateDOList.stream().map(RcCompetitionTaskDateDO::getPriod).distinct().collect(Collectors.toList());
  116. List<RcCompetitionCalcDateDO> calcDateDOList = competitionCalcDateMapper.queryByPriod(periodList, competitionId);
  117. Map<String, RcCompetitionCalcDateDO> periodCalcDataDoMap = calcDateDOList.stream().collect(Collectors.toMap(RcCompetitionCalcDateDO::getPriod, v -> v));
  118. for (RcCompetitionTaskDateDO taskDateDO : taskDateDOList) {
  119. String period = taskDateDO.getPriod();
  120. RcCompetitionCalcDateDO calcDateDO = periodCalcDataDoMap.get(period);
  121. outputCompetitionResult(competitionId, period, calcDateDO);
  122. }
  123. }
  124. public void outputFundNavDetail(Integer competitionId, String period) {
  125. List<FundNavDataDTO> navDataDTOList = fundNavService.getFungNavData(competitionId);
  126. if (CollUtil.isEmpty(navDataDTOList)) {
  127. return;
  128. }
  129. String filePath = competitionConfig.getDirectory() + competitionConfig.getName() + "_" + period + "_基金净值采集结果明细_" + DateUtil.format(new Date(), DateConst.YYYYMMDD) + ".xlsx";
  130. EasyExcel.write(filePath, FundNavDataDTO.class)
  131. .sheet("基金净值采集结果明细")
  132. .doWrite(navDataDTOList);
  133. log.info("基金净值采集结果明细表格已输出 -> 文件:{}", filePath);
  134. // 通过邮件发送"基金净值采集结果明细表格"
  135. if (competitionConfig.getMethod() == 1) {
  136. MailboxInfoDTO mailboxInfoDTO = emailSystemConfigService.getFromEmailInfo();
  137. String receivingMailbox = emailSystemConfigService.getRecipientEmail();
  138. if (mailboxInfoDTO == null || StrUtil.isBlank(receivingMailbox)) {
  139. log.info("未配置发件箱和收件箱,无法发送基金净值采集结果明细邮件");
  140. return;
  141. }
  142. try {
  143. EmailUtil.senEmail(mailboxInfoDTO, receivingMailbox, new File(filePath), "基金净值采集结果明细", "", period + "_基金净值采集结果明细");
  144. log.info("基金净值采集结果明细表 -> 邮件已发送");
  145. } catch (Exception e) {
  146. log.error("邮件发送基金净值采集结果明细表异常 -> 堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
  147. }
  148. }
  149. }
  150. private void outputFundNavDeletion(Integer competitionId, String period, boolean isComputeDeletion) {
  151. String endDate = DateUtil.format(new Date(), DateConst.YYYY_MM_DD);
  152. // 输出榜单之前 -> 执行净值缺失检测(确保净值不全的基金不参与榜单)
  153. if (isComputeDeletion) {
  154. // fundDeletionTask.computeDeletion();
  155. }
  156. List<FundNavDeletionDTO> navDeletionDTOList = fundNavService.getFundNavDeletion(competitionId, endDate);
  157. if (CollUtil.isEmpty(navDeletionDTOList)) {
  158. return;
  159. }
  160. String filePath = competitionConfig.getDirectory() + competitionConfig.getName() + "_" + period + "_基金净值缺失明细_" + DateUtil.format(new Date(), DateConst.YYYYMMDD) + ".xlsx";
  161. EasyExcel.write(filePath, FundNavDeletionDTO.class)
  162. .sheet("基金净值缺失明细")
  163. .doWrite(navDeletionDTOList);
  164. log.info("基金净值缺失明细表格已输出 -> 文件:{}", filePath);
  165. // 通过邮件发送"基金净值采集结果明细表格"
  166. if (competitionConfig.getMethod() == 1) {
  167. MailboxInfoDTO mailboxInfoDTO = emailSystemConfigService.getFromEmailInfo();
  168. String receivingMailbox = emailSystemConfigService.getRecipientEmail();
  169. if (mailboxInfoDTO == null || StrUtil.isBlank(receivingMailbox)) {
  170. log.info("未配置发件箱和收件箱,无法发送基金净值缺失明细邮件");
  171. return;
  172. }
  173. try {
  174. EmailUtil.senEmail(mailboxInfoDTO, receivingMailbox, new File(filePath), "基金净值缺失明细", "", period + "_基金净值缺失明细");
  175. log.info("基金净值缺失明细表 -> 邮件已发送");
  176. } catch (Exception e) {
  177. log.error("邮件发送基金净值缺失明细表异常 -> 堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
  178. }
  179. }
  180. }
  181. private void outputCompetitionResult(Integer competitionId, String period, RcCompetitionCalcDateDO calcDateDO) {
  182. long startTime = System.currentTimeMillis();
  183. // 输出榜单之前 -> 执行基金净值指标计算
  184. competitionIndicatorCalcTask.calculateIndicator(competitionId, calcDateDO);
  185. List<? extends CompetitionBaseResultDTO> competitionResultDTOList = fundNavService.getCompetitionResult(competitionId, period);
  186. if (CollUtil.isEmpty(competitionResultDTOList)) {
  187. log.info("当前榜单:{}无结果数据", period);
  188. return;
  189. }
  190. Class<? extends CompetitionBaseResultDTO> aClass = competitionResultDTOList.get(0).getClass();
  191. String filePath = competitionConfig.getDirectory() + competitionConfig.getName() + "_" + period + "_基金净值衍生指标及排名结果明细_" + DateUtil.format(new Date(), DateConst.YYYYMMDD) + ".xlsx";
  192. EasyExcel.write(filePath, aClass)
  193. .sheet("基金净值衍生指标及排名结果明细")
  194. .doWrite(competitionResultDTOList);
  195. log.info("基金净值衍生指标及排名结果明细表已输出 -> 文件:{},耗时:{}", filePath, (System.currentTimeMillis() - startTime));
  196. Integer method = competitionConfig.getMethod();
  197. // 通过邮件发送"基金净值采集结果明细表格"
  198. if (method == 1) {
  199. MailboxInfoDTO mailboxInfoDTO = emailSystemConfigService.getFromEmailInfo();
  200. String receivingMailbox = emailSystemConfigService.getRecipientEmail();
  201. if (mailboxInfoDTO == null || StrUtil.isBlank(receivingMailbox)) {
  202. log.info("未配置发件箱和收件箱,无法发送基金净值衍生指标及排名结果明细邮件");
  203. return;
  204. }
  205. try {
  206. String emailTitle = period + "_基金净值衍生指标及排名结果明细";
  207. EmailUtil.senEmail(mailboxInfoDTO, receivingMailbox, new File(filePath), emailTitle, "", emailTitle);
  208. log.info("基金净值衍生指标及排名结果明细表 -> 邮件已发送");
  209. } catch (Exception e) {
  210. log.error("邮件发送基金净值衍生指标及排名结果明细表异常 -> 堆栈信息:{}", ExceptionUtil.stacktraceToString(e));
  211. }
  212. }
  213. }
  214. }