金币系统后端
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.

457 lines
18 KiB

5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
  1. package com.example.demo.serviceImpl;
  2. import java.text.SimpleDateFormat;
  3. import java.util.*;
  4. import java.util.concurrent.TimeUnit;
  5. import com.example.demo.Util.CheckIfNullUtil;
  6. import com.example.demo.domain.vo.Meium;
  7. import com.example.demo.domain.vo.Statistics;
  8. import com.example.demo.domain.vo.Statisticss;
  9. import com.example.demo.domain.vo.SumCoin;
  10. import com.example.demo.mapper.StatisticsMapper;
  11. import com.example.demo.sevice.StatisticsService;
  12. import lombok.RequiredArgsConstructor;
  13. import org.apache.ibatis.annotations.Param;
  14. import org.springframework.cache.annotation.CacheConfig;
  15. import org.springframework.cache.annotation.Cacheable;
  16. import org.springframework.stereotype.Service;
  17. import org.springframework.transaction.annotation.Transactional;
  18. import org.springframework.web.bind.annotation.RequestBody;
  19. import java.math.BigDecimal;
  20. import java.time.LocalDate;
  21. import java.time.ZoneId;
  22. import java.time.temporal.ChronoUnit;
  23. import java.util.List;
  24. @RequiredArgsConstructor
  25. @Transactional
  26. @Service
  27. @CacheConfig(cacheNames = "statistics")
  28. public class StatisticsServiceImpl implements StatisticsService {
  29. private final StatisticsMapper statisticsMapper;
  30. @Cacheable(key = "#root.method.name")
  31. @Override
  32. public Statistics getStatistics() {
  33. Statistics statistics = new Statistics();
  34. // 全年累计数据
  35. Statistics yearStats = CheckIfNullUtil.defaultIfNull(statisticsMapper.getTotalYearCoin(), new Statistics());
  36. statistics.setRechargeSumCoin(yearStats.getRechargeSumCoin());
  37. statistics.setFreeSumCoin(yearStats.getFreeSumCoin());
  38. statistics.setTaskSumCoin(yearStats.getTaskSumCoin());
  39. statistics.setTotalSumCoin(yearStats.getTotalSumCoin());
  40. // 昨日新增数据
  41. Statistics yesterdayStats = CheckIfNullUtil.defaultIfNull(statisticsMapper.getYesterdayNewCoin(), new Statistics());
  42. statistics.setRechargeYesterdaySumCoin(yesterdayStats.getRechargeYesterdaySumCoin());
  43. statistics.setFreeYesterdaySumCoin(yesterdayStats.getFreeYesterdaySumCoin());
  44. statistics.setTaskYesterdaySumCoin(yesterdayStats.getTaskYesterdaySumCoin());
  45. statistics.setTotalYesterdaySumCoin(yesterdayStats.getTotalYesterdaySumCoin());
  46. // 年累计充值人数
  47. statistics.setRechargeCount(statisticsMapper.getYearRechargeCount());
  48. // 本周和上周充值人数
  49. int thisWeekCount = statisticsMapper.getRechargeCountThisWeek();
  50. int lastWeekCount = statisticsMapper.getRechargeCountLastWeek();
  51. statistics.setRechargeCountThisWeek(thisWeekCount);
  52. statistics.setRechargeCountLastWeek(lastWeekCount);
  53. // 周同比计算
  54. BigDecimal weekOverWeekRate = BigDecimal.ZERO;//初始化为 0 表示如果没有足够的数据(如 lastWeekCount == 0),默认周同比增长率为 0。
  55. if (lastWeekCount > 0) {
  56. weekOverWeekRate = BigDecimal.valueOf((double) (thisWeekCount - lastWeekCount) / lastWeekCount * 100)//将计算结果转换为 BigDecimal 类型,保证高精度。
  57. .setScale(2, BigDecimal.ROUND_HALF_UP); // 保留两位小数
  58. }
  59. statistics.setWeekOverWeekRate(weekOverWeekRate);
  60. //今日和昨日充值人数
  61. int todayCount = statisticsMapper.getRechargeCountToday();
  62. int yesterdayCount = statisticsMapper.getRechargeCountYesterday();
  63. int firstYesterdayCount = statisticsMapper.getFirstRechargeCountYesterday();
  64. statistics.setRechargeCountToday(todayCount);
  65. statistics.setRechargeCountYesterday(yesterdayCount);
  66. statistics.setFirstRechargeCountYesterday(firstYesterdayCount);
  67. //日环比计算
  68. BigDecimal dayOverDayRate = BigDecimal.ZERO;
  69. if (yesterdayCount > 0) {
  70. dayOverDayRate = BigDecimal.valueOf((double) (todayCount - yesterdayCount) / yesterdayCount * 100).
  71. setScale(2, BigDecimal.ROUND_HALF_UP);
  72. }
  73. statistics.setDayOverDayRate(dayOverDayRate);
  74. return statistics;
  75. }
  76. @Cacheable(key = "#root.method.name")
  77. @Override
  78. public Statisticss stats() {
  79. Statisticss a = new Statisticss();
  80. a.setCoinSystemSum(statisticsMapper.getCoinSystemSum());
  81. a.setERPSum(statisticsMapper.getERPSum());
  82. a.setHomilyChartSum(statisticsMapper.getHomilyChartSum());
  83. a.setHomilyLinkSum(statisticsMapper.getHomilyLinkSum());
  84. return a;
  85. }
  86. //----------------------------------------------------------------------------------------------------//
  87. @Cacheable(key = "#root.method.name")
  88. public SumCoin getSumCoin() {
  89. return statisticsMapper.getSumCoin();
  90. }
  91. @Cacheable(key = "#root.method.name")
  92. @Override
  93. public SumCoin getYearConsumeCoin() {
  94. return statisticsMapper.getYearConsumeCoin();
  95. }
  96. @Cacheable(key = "#root.method.name")
  97. @Override
  98. public SumCoin getDayConsumeCoin() {
  99. return statisticsMapper.getDayConsumeCoin();
  100. }
  101. @Override
  102. public List<SumCoin> getMediuPayCoin() {
  103. return List.of();
  104. }
  105. @Override
  106. public List<SumCoin> getMediuConsumeCoin() {
  107. return List.of();
  108. }
  109. public SumCoin getMess(Integer jwcode) {
  110. return statisticsMapper.getMess(jwcode);
  111. }
  112. @Cacheable(key = "#root.method.name")
  113. @Override
  114. public List<SumCoin> getMediumAreaPay() {
  115. return statisticsMapper.getMediumAreaPay();
  116. }
  117. @Cacheable(key = "#root.method.name")
  118. @Override
  119. public List<SumCoin> getMediumAreaConsume() {
  120. return statisticsMapper.getMediumAreaConsume();
  121. }
  122. @Cacheable(key = "#root.method.name+ T(java.util.Objects).hashCode(#meium)")
  123. @Override
  124. public List<Meium> getMee(Meium meium) {
  125. if (0 == (meium.getUpdateType())) {
  126. if ("免费金币".equals(meium.getType())) {
  127. return statisticsMapper.getBuyAndFree(meium.getSearchStartTime(), meium.getSearchEndTime());
  128. } else if ("充值金币".equals(meium.getType())) {
  129. return statisticsMapper.getBuyAndRecharge(meium.getSearchStartTime(), meium.getSearchEndTime());
  130. } else if ("任务金币".equals(meium.getType())) {
  131. return statisticsMapper.getBuyAndTask(meium.getSearchStartTime(), meium.getSearchEndTime());
  132. } else {
  133. return statisticsMapper.getBuy(meium.getSearchStartTime(), meium.getSearchEndTime());
  134. }
  135. } else if (1 == (meium.getUpdateType())) {
  136. if ("免费金币".equals(meium.getType())) {
  137. return statisticsMapper.getPayAndFree(meium.getSearchStartTime(), meium.getSearchEndTime());
  138. } else if ("充值金币".equals(meium.getType())) {
  139. return statisticsMapper.getPayAndRecharge(meium.getSearchStartTime(), meium.getSearchEndTime());
  140. } else if ("任务金币".equals(meium.getType())) {
  141. return statisticsMapper.getPayAndTask(meium.getSearchStartTime(), meium.getSearchEndTime());
  142. } else {
  143. return statisticsMapper.getPay(meium.getSearchStartTime(), meium.getSearchEndTime());
  144. }
  145. } else
  146. return null;
  147. }
  148. @Override
  149. public List<SumCoin> getMediu() {
  150. return List.of();
  151. }
  152. // public List<SumCoin> getCoinTime( SumCoin sumcoin) {
  153. //
  154. // System.out.println(sumcoin+"-------sumcoin----");
  155. // Date searchStartTime=sumcoin.getSearchStartTime();
  156. // Date searchEndTime=sumcoin.getSearchEndTime();
  157. // String updateType=sumcoin.getUpdateType();
  158. //
  159. //// //提供开始时间与结束时间
  160. ////// if(searchStartTime!=null && searchEndTime!=null){
  161. //// //计算两个时间点之间的差值
  162. //// long daysBetween = ChronoUnit.DAYS.between(searchStartTime, searchEndTime);
  163. //
  164. //// 提供开始时间与结束时间
  165. //
  166. //
  167. // // 使用 Calendar 清除时间和时区的影响
  168. // Calendar startCal = Calendar.getInstance();
  169. // startCal.setTime(searchStartTime);
  170. // startCal.set(Calendar.HOUR_OF_DAY, 0);
  171. // startCal.set(Calendar.MINUTE, 0);
  172. // startCal.set(Calendar.SECOND, 0);
  173. // startCal.set(Calendar.MILLISECOND, 0);
  174. //
  175. // Calendar endCal = Calendar.getInstance();
  176. // endCal.setTime(searchEndTime);
  177. // endCal.set(Calendar.HOUR_OF_DAY, 0);
  178. // endCal.set(Calendar.MINUTE, 0);
  179. // endCal.set(Calendar.SECOND, 0);
  180. // endCal.set(Calendar.MILLISECOND, 0);
  181. //
  182. // // 计算两个时间点之间的天数差异
  183. // long diffInMillies = endCal.getTimeInMillis() - startCal.getTimeInMillis();
  184. // long daysBetween = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
  185. //
  186. //
  187. // //年
  188. // if(daysBetween>100 || searchStartTime==null & searchEndTime==null){
  189. // if("消费".equals(updateType)){
  190. // return statisticsMapper.getMediuConsumeCoin();
  191. // }else if("充值".equals(updateType)){
  192. // return statisticsMapper.getMediuPayCoin();
  193. // }
  194. //
  195. // }else {
  196. // if ("消费".equals(updateType)) {
  197. // return statisticsMapper.getMediuCounsumeCoinyue(searchStartTime,searchEndTime);
  198. // } else if ("充值".equals(updateType)) {
  199. // return statisticsMapper.getMediuPayCoinyue(searchStartTime,searchEndTime);
  200. // }
  201. // }
  202. // return null;
  203. //
  204. // }
  205. //
  206. // @Cacheable(key = "#root.method.name + #sumcoin.hashCode()")
  207. // public List<SumCoin> getCoinTime(SumCoin sumcoin) {
  208. // System.out.println(sumcoin + "-------sumcoin----");
  209. //
  210. // Date searchStartTime = sumcoin.getSearchStartTime();
  211. // Date searchEndTime = sumcoin.getSearchEndTime();
  212. // Integer updateType = sumcoin.getUpdateType();
  213. //
  214. // // 如果开始时间和结束时间都为空,则直接返回默认统计结果
  215. // if (searchStartTime == null && searchEndTime == null) {
  216. // if (1 == updateType) {
  217. // return statisticsMapper.getMediuConsumeCoin(null, null);
  218. // } else if (0 == updateType) {
  219. // return statisticsMapper.getMediuPayCoin(null, null);
  220. // }
  221. // return null; // 或者抛出异常,取决于业务需求
  222. // }
  223. //
  224. // // 如果只有其中一个时间为null,则可能需要处理或抛出异常,这里假设不允许这种情况
  225. // if (searchStartTime == null || searchEndTime == null) {
  226. // throw new IllegalArgumentException("开始时间和结束时间必须同时为空或不为空");
  227. // }
  228. //
  229. // // 使用 Calendar 清除时间和时区的影响
  230. // Calendar startCal = Calendar.getInstance();
  231. // startCal.setTime(searchStartTime);
  232. // startCal.set(Calendar.HOUR_OF_DAY, 0);
  233. // startCal.set(Calendar.MINUTE, 0);
  234. // startCal.set(Calendar.SECOND, 0);
  235. // startCal.set(Calendar.MILLISECOND, 0);
  236. //
  237. // Calendar endCal = Calendar.getInstance();
  238. // endCal.setTime(searchEndTime);
  239. // endCal.set(Calendar.HOUR_OF_DAY, 0);
  240. // endCal.set(Calendar.MINUTE, 0);
  241. // endCal.set(Calendar.SECOND, 0);
  242. // endCal.set(Calendar.MILLISECOND, 0);
  243. //
  244. // // 计算两个时间点之间的天数差异
  245. // long diffInMillies = endCal.getTimeInMillis() - startCal.getTimeInMillis();
  246. // long daysBetween = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
  247. //
  248. // // 根据条件选择查询方法
  249. // List<SumCoin> result = null;
  250. //
  251. // // 如果天数差大于100天
  252. // if (daysBetween > 100) {
  253. // if (1 == updateType) {
  254. // result = statisticsMapper.getMediuConsumeCoin(searchStartTime, searchEndTime);
  255. // } else if (0 == updateType) {
  256. // result = statisticsMapper.getMediuPayCoin(searchStartTime, searchEndTime);
  257. // }
  258. // }
  259. // // 如果天数差为0,即同一天
  260. // else if (daysBetween == 0) {
  261. // if (1 == updateType) {
  262. // result = statisticsMapper.getMediuConsumeCoinday(searchEndTime, updateType);
  263. // } else if (0 == updateType) {
  264. // result = statisticsMapper.getMediuPayCoinday(searchEndTime, updateType);
  265. // }
  266. // }
  267. // // 如果天数差小于100天,但不为0(即跨月或较短时间段)
  268. // else {
  269. // if (1 == updateType) {
  270. // result = statisticsMapper.getMediuCounsumeCoinyue(searchStartTime, searchEndTime);
  271. // } else if (0 == updateType) {
  272. // result = statisticsMapper.getMediuPayCoinyue(searchStartTime, searchEndTime);
  273. // }
  274. // }
  275. //
  276. // // 如果查询结果为空或没有数据,返回默认的SumCoin对象
  277. // if (result == null || result.isEmpty()) {
  278. // result = Collections.singletonList(createDefaultSumCoin());
  279. // }
  280. //
  281. // return result;
  282. // }
  283. //
  284. // // 创建默认的 SumCoin 对象
  285. // private SumCoin createDefaultSumCoin() {
  286. // SumCoin defaultSumCoin = new SumCoin();
  287. //
  288. // defaultSumCoin.setRechargeSumCoin(BigDecimal.ZERO);
  289. // defaultSumCoin.setFreeSumCoin(BigDecimal.ZERO);
  290. // defaultSumCoin.setTaskSumCoin(BigDecimal.ZERO);
  291. // // 获取当前日期并设置为字符串格式
  292. // Date currentDate = new Date();
  293. // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d"); // "yyyy-M-d" 格式
  294. // String formattedDate = sdf.format(currentDate); // 格式化日期为字符串
  295. //
  296. // // 设置当前日期
  297. // defaultSumCoin.setDay(formattedDate);
  298. // return defaultSumCoin;
  299. // }
  300. //}
  301. @Cacheable(key = "#root.method.name + #sumcoin.hashCode()")
  302. public List<SumCoin> getCoinTime(SumCoin sumcoin) {
  303. System.out.println(sumcoin + "-------sumcoin----");
  304. Date searchStartTime = sumcoin.getSearchStartTime();
  305. Date searchEndTime = sumcoin.getSearchEndTime();
  306. Integer updateType = sumcoin.getUpdateType();
  307. // 如果开始时间和结束时间都为空,则直接返回默认统计结果,即全查
  308. if (searchStartTime == null && searchEndTime == null) {
  309. if (1 == updateType) {
  310. return statisticsMapper.getMediuConsumeCoin(searchStartTime, searchEndTime);//前端没有选定时间,SQL会查询所有数据
  311. } else if (0 == updateType) {
  312. return statisticsMapper.getMediuPayCoin(null, null);
  313. }
  314. return null; // 或者抛出异常,取决于业务需求
  315. }
  316. // 如果只有其中一个时间为null,则可能需要处理或抛出异常,这里假设不允许这种情况
  317. if (searchStartTime == null || searchEndTime == null) {
  318. throw new IllegalArgumentException("开始时间和结束时间必须同时为空或不为空");
  319. }
  320. // 使用 Calendar 清除时间和时区的影响
  321. Calendar startCal = Calendar.getInstance();
  322. startCal.setTime(searchStartTime);
  323. startCal.set(Calendar.HOUR_OF_DAY, 0);
  324. startCal.set(Calendar.MINUTE, 0);
  325. startCal.set(Calendar.SECOND, 0);
  326. startCal.set(Calendar.MILLISECOND, 0);
  327. Calendar endCal = Calendar.getInstance();
  328. endCal.setTime(searchEndTime);
  329. endCal.set(Calendar.HOUR_OF_DAY, 0);
  330. endCal.set(Calendar.MINUTE, 0);
  331. endCal.set(Calendar.SECOND, 0);
  332. endCal.set(Calendar.MILLISECOND, 0);
  333. // 计算两个时间点之间的天数差异
  334. long diffInMillies = endCal.getTimeInMillis() - startCal.getTimeInMillis();
  335. long daysBetween = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
  336. // 根据条件选择查询方法
  337. List<SumCoin> result = new ArrayList<>();
  338. List<SumCoin> queryResult = null;
  339. // 如果天数差大于100天
  340. if (daysBetween > 100) {
  341. if (1 == updateType) {
  342. return statisticsMapper.getMediuConsumeCoin(searchStartTime, searchEndTime);
  343. } else if (0 == updateType) {
  344. return statisticsMapper.getMediuPayCoin(searchStartTime, searchEndTime);
  345. }
  346. }
  347. // 如果天数差为0,即同一天
  348. else if (daysBetween == 0) {
  349. if (1 == updateType) {
  350. queryResult = statisticsMapper.getMediuConsumeCoinday(searchEndTime, updateType);
  351. } else if (0 == updateType) {
  352. queryResult = statisticsMapper.getMediuPayCoinday(searchEndTime, updateType);
  353. }
  354. }
  355. // 如果天数差小于100天,但不为0(即跨月或较短时间段)
  356. else {
  357. if (1 == updateType) {
  358. queryResult = statisticsMapper.getMediuCounsumeCoinyue(searchStartTime, searchEndTime);
  359. } else if (0 == updateType) {
  360. queryResult = statisticsMapper.getMediuPayCoinyue(searchStartTime, searchEndTime);
  361. }
  362. }
  363. // 创建一个日期范围列表
  364. List<Date> allDates = getDateRange(searchStartTime, searchEndTime);
  365. // 将查询结果按日期映射,方便查找
  366. Map<String, SumCoin> resultMap = new HashMap<>();
  367. if (queryResult != null) {
  368. for (SumCoin coin : queryResult) {
  369. resultMap.put(coin.getDay(), coin);
  370. }
  371. }
  372. // 填充没有数据的日期,生成完整的结果
  373. for (Date date : allDates) {
  374. String dateString = new SimpleDateFormat("yyyy-MM-dd").format(date);
  375. if (!resultMap.containsKey(dateString)) {
  376. result.add(createDefaultSumCoin(dateString));
  377. } else {
  378. result.add(resultMap.get(dateString));
  379. }
  380. }
  381. return result;
  382. }
  383. // 获取日期范围的所有日期
  384. private List<Date> getDateRange(Date startDate, Date endDate) {
  385. List<Date> dates = new ArrayList<>();
  386. Calendar startCal = Calendar.getInstance();
  387. startCal.setTime(startDate);
  388. Calendar endCal = Calendar.getInstance();
  389. endCal.setTime(endDate);
  390. while (!startCal.after(endCal)) {
  391. dates.add(startCal.getTime());
  392. startCal.add(Calendar.DAY_OF_YEAR, 1);
  393. }
  394. return dates;
  395. }
  396. // 创建默认的 SumCoin 对象,并设置日期
  397. private SumCoin createDefaultSumCoin(String date) {
  398. SumCoin defaultSumCoin = new SumCoin();
  399. defaultSumCoin.setRechargeSumCoin(BigDecimal.ZERO);
  400. defaultSumCoin.setFreeSumCoin(BigDecimal.ZERO);
  401. defaultSumCoin.setTaskSumCoin(BigDecimal.ZERO);
  402. defaultSumCoin.setDay(date);
  403. return defaultSumCoin;
  404. }
  405. }