StationStatJob.java 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package com.kym.admin.jobs;
  2. import cn.hutool.core.date.DateUtil;
  3. import com.kym.common.utils.CommUtil;
  4. import com.kym.entity.admin.ConnectorInfo;
  5. import com.kym.entity.admin.StationStatDay;
  6. import com.kym.entity.admin.StationStatMonth;
  7. import com.kym.entity.miniapp.ChargeOrder;
  8. import com.kym.service.admin.ConnectorInfoService;
  9. import com.kym.service.admin.StationStatDayService;
  10. import com.kym.service.admin.StationStatMonthService;
  11. import com.kym.service.miniapp.ChargeOrderService;
  12. import lombok.extern.slf4j.Slf4j;
  13. import org.springframework.scheduling.annotation.Scheduled;
  14. import org.springframework.stereotype.Component;
  15. import java.time.LocalDate;
  16. import java.time.LocalDateTime;
  17. import java.time.LocalTime;
  18. import java.time.temporal.TemporalAdjusters;
  19. import java.util.*;
  20. import java.util.stream.Collectors;
  21. /**
  22. * 站点统计定时任务
  23. *
  24. * @author skyline
  25. */
  26. @Component
  27. @Slf4j
  28. public class StationStatJob {
  29. private final ChargeOrderService chargeOrderService;
  30. private final StationStatDayService dayService;
  31. private final StationStatMonthService monthService;
  32. private final ConnectorInfoService connectorInfoService;
  33. public StationStatJob(ChargeOrderService chargeOrderService, StationStatDayService stationStatDayService, StationStatMonthService stationStatMonthService, ConnectorInfoService connectorInfoService) {
  34. this.chargeOrderService = chargeOrderService;
  35. this.dayService = stationStatDayService;
  36. this.monthService = stationStatMonthService;
  37. this.connectorInfoService = connectorInfoService;
  38. }
  39. // 每天14:30执行一次,通过charge_app.t_charge_order表统计start_time为前一天且充电金额大于100的充电订单,分别统计充电人数、订单数、充电总费用、充电总电量、平均充电电量、平均充电费用、平均订单费用、平均订单电量
  40. /**
  41. * 日统计,每日下午14:30启动,统计上日数据
  42. */
  43. // @Scheduled(cron = "0 30 14 * * ?")
  44. // 定时每日下午14:30
  45. private void dayStat() {
  46. log.info("执行站点日统计定时任务-开始");
  47. var statDay = LocalDateTime.now().minusDays(1);
  48. var startTime = LocalDateTime.of(statDay.toLocalDate(), LocalTime.MIN);
  49. var endTime = LocalDateTime.of(statDay.toLocalDate(), LocalTime.MAX);
  50. var chargeOrderList = getChargeOrders(startTime, endTime);
  51. dayService.saveBatch((Collection<StationStatDay>) getStationStat(chargeOrderList, true));
  52. log.info("执行站点日统计定时任务-结束");
  53. }
  54. /**
  55. * 月统计,每月第一天下午15:00启动,统计上月数据
  56. */
  57. // @Scheduled(cron = "0 0 15 1 * ?")
  58. private void monthStat() {
  59. log.info("执行站点月统计定时任务-开始");
  60. var statMonth = LocalDateTime.now().minusMonths(1);
  61. var startTime = statMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
  62. var endTime = statMonth.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
  63. var chargeOrderList = getChargeOrders(startTime, endTime);
  64. monthService.saveBatch((Collection<StationStatMonth>) getStationStat(chargeOrderList, false));
  65. log.info("执行站点月统计定时任务-结束");
  66. }
  67. // 只执行一次
  68. // @PostConstruct
  69. private void init() {
  70. log.info("执行站点初始化定时任务-开始");
  71. // 2023-08-01 00:00:00
  72. // var statMonth = LocalDateTime.of(2023, 12, 1, 0, 0);
  73. // var endMonth = LocalDateTime.of(2023, 12, 1, 0, 0);
  74. // var startTime = statMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
  75. // var endTime = endMonth.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
  76. // var chargeOrderList = getChargeOrders(startTime, endTime);
  77. // monthService.saveBatch((Collection<StationStatMonth>) getStationStat(chargeOrderList, false));
  78. //
  79. // // 将订单按照日为单位分组
  80. // var chargeOrderMap = chargeOrderList.stream().collect(Collectors.groupingBy(order ->
  81. // order.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
  82. // ));
  83. // // chargeOrderMap按照key升序排序
  84. // var chargeOrderMapSort = chargeOrderMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(
  85. // Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
  86. //
  87. // chargeOrderMapSort.forEach((k, v) -> dayService.saveBatch(((Collection<StationStatDay>) getStationStat(v, true))));
  88. log.info("执行站点初始化定时任务-结束");
  89. }
  90. private List<ChargeOrder> getChargeOrders(LocalDateTime startTime, LocalDateTime endTime) {
  91. // 通过charge_app.t_charge_order表统计start_time为前一天且充电金额大于0的有效充电订单
  92. var res = chargeOrderService.lambdaQuery()
  93. .ge(ChargeOrder::getStartTime, startTime)
  94. .le(ChargeOrder::getStartTime, endTime)
  95. .gt(ChargeOrder::getTotalMoney, 0)
  96. .list();
  97. return res;
  98. }
  99. private Collection<?> getStationStat(List<ChargeOrder> chargeOrderList, boolean isDayStat) {
  100. // 统计每个站点的connector_id数量
  101. var stationConnectorCountMap = connectorInfoService.list().stream().collect(Collectors.groupingBy(ConnectorInfo::getStationId, Collectors.counting()));
  102. // 将chargeOrderList按照stationId分组
  103. var chargeOrderMap = chargeOrderList.stream().collect(Collectors.groupingBy(ChargeOrder::getStationId));
  104. // 根据分组计算每个站点的充电人数、订单数、充电总费用、充电总电量、平均充电电量、平均充电费用、平均订单费用、平均订单电量
  105. return chargeOrderMap.entrySet().stream().collect(Collectors.toMap(
  106. Map.Entry::getKey,
  107. entry -> {
  108. var chargeOrders = entry.getValue();
  109. var chargeUsers = chargeOrders.stream().collect(Collectors.collectingAndThen(
  110. Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ChargeOrder::getUserId))), ArrayList<ChargeOrder>::new)).size();
  111. var totalMoney = chargeOrders.stream().mapToInt(ChargeOrder::getTotalMoney).sum();
  112. var elecMoney = chargeOrders.stream().mapToInt(ChargeOrder::getElecMoney).sum();
  113. var serviceMoney = chargeOrders.stream().mapToInt(ChargeOrder::getServiceMoney).sum();
  114. var serviceMoneyDiscount = chargeOrders.stream().mapToInt(ChargeOrder::getServiceMoneyDiscount).sum();
  115. var discountAmount = chargeOrders.stream().mapToInt(ChargeOrder::getDiscountAmount).sum();
  116. var totalPower = chargeOrders.stream().mapToDouble(ChargeOrder::getTotalPower).sum();
  117. var avgPower = chargeOrders.stream().mapToDouble(ChargeOrder::getTotalPower).average().orElse(0.0);
  118. var avgOrderMoney = chargeOrders.stream().mapToInt(ChargeOrder::getTotalMoney).average().orElse(0);
  119. // 充电桩使用率 = 有订单的充电桩数量 / 总充电桩数
  120. var connectorUsageRate = (double) chargeOrders.stream().filter(CommUtil.distinctByKey(ChargeOrder::getConnectorId)).count() / stationConnectorCountMap.get(entry.getKey());
  121. ;
  122. return isDayStat
  123. ? new StationStatDay()
  124. .setStationId(entry.getKey())
  125. .setStatDay(DateUtil.format(LocalDateTime.now().minusDays(1), "yyyy-MM-dd"))
  126. .setChargeUsers(chargeUsers)
  127. .setValidOrders(chargeOrders.size())
  128. .setTotalMoney(totalMoney)
  129. .setElecMoney(elecMoney)
  130. .setServiceMoney(serviceMoney)
  131. .setServiceMoneyDiscount(serviceMoneyDiscount)
  132. .setDiscountAmount(discountAmount)
  133. .setTotalPower(totalPower)
  134. .setAvgOrderElec(avgPower)
  135. .setAvgOrderMoney((int) avgOrderMoney)
  136. .setAvgConnectorElec(totalPower / (stationConnectorCountMap.get(entry.getKey())))
  137. .setConnectorUsageRate(connectorUsageRate)
  138. : new StationStatMonth()
  139. .setStationId(entry.getKey())
  140. .setStatMonth(DateUtil.format(LocalDateTime.now().minusMonths(1), "yyyy-MM"))
  141. .setChargeUsers(chargeUsers)
  142. .setValidOrders(chargeOrders.size())
  143. .setTotalMoney(totalMoney)
  144. .setElecMoney(elecMoney)
  145. .setServiceMoney(serviceMoney)
  146. .setServiceMoneyDiscount(serviceMoneyDiscount)
  147. .setDiscountAmount(discountAmount)
  148. .setTotalPower(totalPower)
  149. .setAvgOrderElec(avgPower)
  150. .setAvgOrderMoney((int) avgOrderMoney)
  151. .setAvgConnectorElec(totalPower / (stationConnectorCountMap.get(entry.getKey()) * (LocalDate.now().minusMonths(1).lengthOfMonth())));
  152. })).values();
  153. }
  154. }