You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
15 KiB

2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
  1. package com.example.demo.serviceImpl;
  2. import com.example.demo.domain.entity.Statistics;
  3. import com.example.demo.domain.entity.UserGoldRecord;
  4. import com.example.demo.mapper.StatisticsMapper;
  5. import com.example.demo.service.GeneralService;
  6. import com.example.demo.service.StatisticsService;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.scheduling.annotation.Scheduled;
  11. import org.springframework.stereotype.Service;
  12. import java.time.LocalDate;
  13. import java.time.LocalDateTime;
  14. import java.time.LocalTime;
  15. import java.time.ZoneId;
  16. import java.time.format.DateTimeFormatter;
  17. import java.util.*;
  18. /**
  19. * @program: gold-java
  20. * @ClassName StatisticsServiceImpl
  21. * @description: 统计相关
  22. * @author: Ethan
  23. * @create: 202506-18 12:00
  24. * @Version 1.0
  25. **/
  26. @Service
  27. public class StatisticsServiceImpl implements StatisticsService {
  28. private static final Logger log = LoggerFactory.getLogger(StatisticsServiceImpl.class);
  29. @Autowired
  30. private StatisticsMapper statisticsMapper;
  31. @Autowired
  32. private GeneralService generalService;
  33. /*
  34. 12点18点23点30分执行定时任务更新当天part1数据
  35. */
  36. @Override
  37. @Scheduled(cron = "0 0 12,18 * * ?") // 分别在 12:00 和 18:00 执行
  38. @Scheduled(cron = "0 30 23 * * ?") // 在 23:30 执行
  39. public void runHourlyTaskPart1() {
  40. Date today = new Date(); //取当天日期
  41. for(String market : generalService.getMarket()){
  42. saveStatisticsPart1(market,today);
  43. }
  44. }
  45. /*
  46. 12点18点执行定时任务更新当天part2数据
  47. */
  48. @Override
  49. @Scheduled(cron = "0 0 12,18 * * ?")
  50. public void runHourlyTaskPart2() {
  51. Date today = new Date(); //取当天日期
  52. for(String market : generalService.getMarket()){
  53. saveStatisticsPart2(market,today);
  54. }
  55. }
  56. /*
  57. 0点执行定时任务更新近一周part2数据
  58. */
  59. @Override
  60. @Scheduled(cron = "0 0 0 * * ?")
  61. public void runDailyTaskPart2() {
  62. Calendar cal = Calendar.getInstance();
  63. cal.add(Calendar.DAY_OF_YEAR, -7); // 一周前
  64. Date startDate = cal.getTime();
  65. Date yesterday = generalService.getYesterday(); // 昨天
  66. // 获取 Calendar 实例并设置为昨天的日期
  67. Calendar calendar = Calendar.getInstance();
  68. calendar.setTime(yesterday);
  69. // 设置时间为昨天的23:55
  70. calendar.set(Calendar.HOUR_OF_DAY, 23);
  71. calendar.set(Calendar.MINUTE, 59);
  72. calendar.set(Calendar.SECOND, 55);
  73. //把yesterday的结束时间设为结束时间
  74. Date endDate= calendar.getTime();
  75. //近一周的日期列表
  76. List<Date> dateList =generalService.getAllDatesBetween(startDate, endDate);
  77. for (Date date : dateList) {
  78. for (String market : generalService.getMarket()) {
  79. saveStatisticsPart2(market, date);
  80. }
  81. }
  82. }
  83. /*
  84. 查询某地区某天已存在的统计数据
  85. */
  86. @Override
  87. public Statistics getExistStatistics(String market, Date date) {
  88. LocalDateTime startTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().with(LocalTime.MIN);
  89. LocalDateTime endTime= startTime.plusDays(1).minusSeconds(1);
  90. return statisticsMapper.selectByMarketAndDate(market,
  91. Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
  92. Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()));
  93. }
  94. /*
  95. 新增或更新或不修改某地区某天part1统计数据
  96. */
  97. @Override
  98. public void saveStatisticsPart1(String market, Date date) {
  99. //获取该地区该日期part1(余量属性)统计数据
  100. Statistics newStats=getStatisticsPart1(market,date);
  101. //获取该地区该日期已存在的数据
  102. Statistics existStats = getExistStatistics(market, date);
  103. //判断是否存在已存在的数据
  104. if(existStats==null){
  105. //没有记录,新增
  106. statisticsMapper.insertPart1(newStats );
  107. }else {
  108. //判断新旧数据part1部分(余量属性)是否一致
  109. if (!isSameStatisticsPart1(existStats,newStats)){
  110. statisticsMapper.updatePart1(newStats);
  111. }else{
  112. System.out.println("数据未发生改变");
  113. }
  114. }
  115. }
  116. /*
  117. 新增或更新或不修改某地区某天part2统计数据
  118. */
  119. @Override
  120. public void saveStatisticsPart2(String market, Date date){
  121. //获取该地区该日期part2(余量外属性)统计数据
  122. Statistics newStats=getStatisticsPart2(market,date);
  123. //获取该地区该日期已存在的数据
  124. Statistics existStats = getExistStatistics(market, date);
  125. //判断是否存在已存在的数据
  126. if(existStats==null){
  127. //没有记录,新增
  128. statisticsMapper.insertPart2(newStats );
  129. }else {
  130. //判断新旧数据part2部分(余量外属性)是否一致
  131. if (!isSameStatisticsPart2(existStats,newStats)){
  132. statisticsMapper.updatePart2(newStats);
  133. }else{
  134. System.out.println("数据未发生改变");
  135. }
  136. }
  137. }
  138. //根据地区与日期获取part1(余量属性)统计数据
  139. @Override
  140. public Statistics getStatisticsPart1(String market, Date date) {
  141. //获取日期
  142. LocalDate localDate=date.toInstant()
  143. .atZone(ZoneId.of("Asia/Shanghai")) // 使用系统默认时区
  144. .toLocalDate();
  145. //初始化Statistics对象
  146. Statistics statistics = new Statistics();
  147. statistics.setMarket(market);
  148. statistics.setCurrentDatetime(localDate);
  149. //计算属性
  150. //当前金币余量
  151. Integer currentGold = statisticsMapper.sumCurrentPermanentGold(market)+
  152. statisticsMapper.sumCurrentFreeJune( market)+
  153. statisticsMapper.sumCurrentFreeDecember(market)+
  154. statisticsMapper.sumCurrentTaskGold( market);
  155. statistics.setCurrentGold(currentGold);
  156. //较前一日变化
  157. Date yesterday =generalService.getYesterday();
  158. //把yesterday改为昨天的开始时间和结束时间
  159. LocalDateTime startTime = yesterday.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().with(LocalTime.MIN);
  160. LocalDateTime endTime= startTime.plusDays(1).minusSeconds(1);
  161. //昨天金币余量
  162. Statistics ydayStats = statisticsMapper.selectByMarketAndDate(market, Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),
  163. Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()));
  164. Integer yesterdayGold=0;
  165. if (ydayStats != null) {
  166. yesterdayGold = ydayStats.getCurrentGold();
  167. }
  168. Integer dailyChange = currentGold - yesterdayGold;
  169. statistics.setDailyChange(dailyChange);
  170. //当前永久金币
  171. Integer currentPermanent = statisticsMapper.sumCurrentPermanentGold(market);
  172. statistics.setCurrentPermanent(currentPermanent);
  173. //当前免费六月金币
  174. Integer currentFreeJune = statisticsMapper.sumCurrentFreeJune(market);
  175. statistics.setCurrentFreeJune(currentFreeJune);
  176. //当前免费十二月金币
  177. Integer currentFreeDecember = statisticsMapper.sumCurrentFreeDecember(market);
  178. statistics.setCurrentFreeDecember(currentFreeDecember);
  179. //当前任务金币
  180. Integer currentTask = statisticsMapper.sumCurrentTaskGold(market);
  181. statistics.setCurrentTask(currentTask);
  182. return statistics;
  183. }
  184. /*
  185. 根据地区与日期获取part2(余量外属性)统计数据
  186. */
  187. @Override
  188. public Statistics getStatisticsPart2(String market, Date date) {
  189. //获取日期
  190. LocalDate localDate=date.toInstant()
  191. .atZone(ZoneId.of("Asia/Shanghai")) // 使用系统默认时区
  192. .toLocalDate();
  193. //把date改为当天的开始时间和结束时间
  194. LocalDateTime startTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().with(LocalTime.MIN);
  195. LocalDateTime endTime= startTime.plusDays(1).minusSeconds(1);
  196. //定义审核状态列表
  197. List<Integer> auditStatusList = new ArrayList<>();
  198. auditStatusList.add(1); // 审核通过
  199. auditStatusList.add(3); // 外部传入默认通过
  200. //查询当天该地区审核通过的所有数据
  201. List<UserGoldRecord> records = statisticsMapper.findByMarketAndAuditStatus(market, auditStatusList,
  202. Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()));
  203. //初始化Statistics对象
  204. Statistics statistics = new Statistics();
  205. statistics.setMarket(market);
  206. statistics.setCurrentDatetime(localDate);
  207. //计算属性
  208. //充值相关-当日充值(永久+免费)
  209. Integer recharge = records.stream()
  210. .filter(record -> record.getType() == 0) // 类型为充值
  211. .mapToInt(record -> record.getPermanentGold() + record.getFreeJune() + record.getFreeDecember() + record.getTaskGold())
  212. .sum();
  213. statistics.setRecharge(recharge);
  214. //充值相关-当日金额(永久)
  215. Integer money = records.stream()
  216. .filter(record -> record.getType() == 0) // 类型为充值
  217. .mapToInt(UserGoldRecord::getPermanentGold)
  218. .sum();
  219. statistics.setMoney(money);
  220. //消费相关-当日新增消费(永久)
  221. Integer consumePermanent = records.stream()
  222. .filter(record -> record.getType() == 1) // 类型为消费
  223. .mapToInt(UserGoldRecord::getPermanentGold)
  224. .sum();
  225. statistics.setConsumePermanent(consumePermanent);
  226. //消费相关-当日新增消费(六月免费)
  227. Integer consumeFreeJune = records.stream()
  228. .filter(record -> record.getType() == 1) // 类型为消费
  229. .mapToInt(UserGoldRecord::getFreeJune)
  230. .sum();
  231. statistics.setConsumeFreeJune(consumeFreeJune);
  232. //消费相关-当日新增消费(十二月免费)
  233. Integer consumeFreeDecember = records.stream()
  234. .filter(record -> record.getType() == 1) // 类型为消费
  235. .mapToInt(UserGoldRecord::getFreeDecember)
  236. .sum();
  237. statistics.setConsumeFreeDecember(consumeFreeDecember);
  238. //消费相关-当日新增消费(任务)
  239. Integer consumeTask = records.stream()
  240. .filter(record -> record.getType() == 1) // 类型为消费
  241. .mapToInt(UserGoldRecord::getTaskGold)
  242. .sum();
  243. statistics.setConsumeTask(consumeTask);
  244. //退款相关-当日退款(永久)
  245. Integer refundPermanent = records.stream()
  246. .filter(record -> record.getType() == 2) // 类型为退款
  247. .mapToInt(UserGoldRecord::getPermanentGold)
  248. .sum();
  249. statistics.setRefundPermanent(refundPermanent);
  250. //退款相关-当日退款(六月免费)
  251. Integer refundFreeJune = records.stream()
  252. .filter(record -> record.getType() == 2) // 类型为退款
  253. .mapToInt(UserGoldRecord::getFreeJune)
  254. .sum();
  255. statistics.setRefundFreeJune(refundFreeJune);
  256. //退款相关-当日退款(十二月免费)
  257. Integer refundFreeDecember = records.stream()
  258. .filter(record -> record.getType() == 2) // 类型为退款
  259. .mapToInt(UserGoldRecord::getFreeDecember)
  260. .sum();
  261. statistics.setRefundFreeDecember(refundFreeDecember);
  262. //退款相关-当日退款(任务)
  263. Integer refundTask = records.stream()
  264. .filter(record -> record.getType() == 2) // 类型为退款
  265. .mapToInt(UserGoldRecord::getTaskGold)
  266. .sum();
  267. statistics.setRefundTask(refundTask);
  268. //充值人数
  269. int rechargeNum= statisticsMapper.countRechargeNum(market,Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()));
  270. statistics.setRechargeNum(rechargeNum);
  271. //首充人数
  272. int firstRecharge= statisticsMapper.countFirstRecharge(market,Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant()),Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant()));
  273. statistics.setFirstRecharge(firstRecharge);
  274. return statistics;
  275. }
  276. /*
  277. * 判断两个统计对象part1(余量属性)是否相同
  278. */
  279. private boolean isSameStatisticsPart1(Statistics oldStats, Statistics newStats) {
  280. return Objects.equals(oldStats.getCurrentGold(), newStats.getCurrentGold()) &&
  281. Objects.equals(oldStats.getCurrentPermanent(), newStats.getCurrentPermanent()) &&
  282. Objects.equals(oldStats.getCurrentFreeJune(), newStats.getCurrentFreeJune()) &&
  283. Objects.equals(oldStats.getCurrentFreeDecember(), newStats.getCurrentFreeDecember()) &&
  284. Objects.equals(oldStats.getCurrentTask(), newStats.getCurrentTask()) &&
  285. Objects.equals(oldStats.getDailyChange(), newStats.getDailyChange()) ;
  286. }
  287. /*
  288. * 判断两个统计对象part2(余量外属性)是否相同
  289. */
  290. private boolean isSameStatisticsPart2(Statistics oldStats, Statistics newStats) {
  291. return Objects.equals(oldStats.getRecharge(), newStats.getRecharge()) &&
  292. Objects.equals(oldStats.getMoney(), newStats.getMoney()) &&
  293. Objects.equals(oldStats.getConsumePermanent(), newStats.getConsumePermanent()) &&
  294. Objects.equals(oldStats.getConsumeFreeJune(), newStats.getConsumeFreeJune()) &&
  295. Objects.equals(oldStats.getConsumeFreeDecember(), newStats.getConsumeFreeDecember()) &&
  296. Objects.equals(oldStats.getConsumeTask(), newStats.getConsumeTask()) &&
  297. Objects.equals(oldStats.getRefundPermanent(), newStats.getRefundPermanent()) &&
  298. Objects.equals(oldStats.getRefundFreeJune(), newStats.getRefundFreeJune()) &&
  299. Objects.equals(oldStats.getRefundFreeDecember(), newStats.getRefundFreeDecember()) &&
  300. Objects.equals(oldStats.getRefundTask(), newStats.getRefundTask()) &&
  301. Objects.equals(oldStats.getRechargeNum(), newStats.getRechargeNum()) &&
  302. Objects.equals(oldStats.getFirstRecharge(), newStats.getFirstRecharge()) &&
  303. Objects.equals(oldStats.getCurrentGold(), newStats.getCurrentGold()) &&
  304. Objects.equals(oldStats.getDailyChange(), newStats.getDailyChange()) &&
  305. Objects.equals(oldStats.getCurrentPermanent(), newStats.getCurrentPermanent()) &&
  306. Objects.equals(oldStats.getCurrentFreeJune(), newStats.getCurrentFreeJune()) &&
  307. Objects.equals(oldStats.getCurrentFreeDecember(), newStats.getCurrentFreeDecember()) &&
  308. Objects.equals(oldStats.getCurrentTask(), newStats.getCurrentTask());
  309. }
  310. }