StatisticsDataScheduler.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. package com.cyksj.task;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.date.DateTime;
  4. import cn.hutool.core.date.DateUtil;
  5. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  6. import com.cyksj.common.constant.Constant;
  7. import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
  8. import com.cyksj.mapper.GoodsDonMapper;
  9. import com.cyksj.mapper.RegisterAccountDataMapper;
  10. import com.cyksj.mapper.RegisterOrderDonMapper;
  11. import com.cyksj.mapper.manage.statistics.AppleOneDataMapper;
  12. import com.cyksj.mapper.manage.statistics.RealGoodsDataMapper;
  13. import com.cyksj.mapper.manage.statistics.StatisticsUserDataMapper;
  14. import com.cyksj.mapper.manage.statistics.StreamingAccountDataMapper;
  15. import com.cyksj.model.entity.*;
  16. import com.cyksj.model.views.CorpUserTagView;
  17. import com.cyksj.service.mange.CmsAccountService;
  18. import com.cyksj.service.mange.CmsGoodsDonSkuService;
  19. import com.cyksj.service.order.OrderDonService;
  20. import com.ejlchina.searcher.BeanSearcher;
  21. import com.ejlchina.searcher.param.Operator;
  22. import com.ejlchina.searcher.util.MapUtils;
  23. import lombok.RequiredArgsConstructor;
  24. import lombok.extern.slf4j.Slf4j;
  25. import org.springframework.scheduling.annotation.Scheduled;
  26. import org.springframework.stereotype.Component;
  27. import java.math.BigDecimal;
  28. import java.util.*;
  29. import java.util.stream.Collectors;
  30. /*
  31. *项目名: netflix
  32. *文件名: StatisticsDataScheduler
  33. *创建者: JavaZou
  34. *创建时间:2022/10/18 12:07
  35. */
  36. @Component
  37. @Slf4j
  38. @RequiredArgsConstructor
  39. public class StatisticsDataScheduler {
  40. private final OrderDonService orderDonService;
  41. private final CmsGoodsDonSkuService goodsDonSkuService;
  42. private final CmsAccountService accountService;
  43. private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
  44. private final AppleOneDataMapper appleOneDataMapper;
  45. private final StreamingAccountDataMapper streamingAccountDataMapper;
  46. private final static String APPLE_ONE = "Apple One";
  47. public static List<String> noOrderStatus = List.of("close", "noPayment");
  48. public static List<String> payType = List.of("月", "季", "年");
  49. private final static List<String> registerAccount = List.of("apple", "spotify", "google");
  50. private final GoodsDonMapper goodsDonMapper;
  51. private final RealGoodsDataMapper realGoodsDataMapper;
  52. private final RegisterOrderDonMapper registerOrderDonMapper;
  53. private final RegisterAccountDataMapper registerAccountDataMapper;
  54. private final StatisticsUserDataMapper statisticsUserDataMapper;
  55. private final BeanSearcher beanSearcher;
  56. /**
  57. * 后台数据统计 定时器
  58. */
  59. @Scheduled(cron = "0 0 1 * * ?")
  60. public void statisticsData() {
  61. Date thisZeroDate = DateUtil.beginOfDay(DateTime.now());
  62. Date yesZeroDate = DateTime.of(thisZeroDate.getTime() - Constant.DAY_MILLS);
  63. //统计AppleOne数据
  64. TASK_POOL.execute(() -> statisticsAppleOneData(yesZeroDate, thisZeroDate, false));
  65. //统计流媒体账号数据
  66. TASK_POOL.execute(() -> statisticsStreamingAccountData(yesZeroDate, thisZeroDate, false));
  67. //统计实物数据
  68. TASK_POOL.execute(() -> statisticsRealGoodsData(yesZeroDate, thisZeroDate, false));
  69. //注册账号数据
  70. TASK_POOL.execute(() -> statisticsRegisterAccountData(yesZeroDate, thisZeroDate, false));
  71. //用户数据统计
  72. statisticsUserData(yesZeroDate, thisZeroDate);
  73. }
  74. /**
  75. * 用户数据统计
  76. */
  77. private void statisticsUserData(Date yesZeroDate, Date thisZeroDate) {
  78. StatisticsUserData yesData = statisticsUserDataMapper.selectOne(Wrappers.lambdaQuery(StatisticsUserData.class).orderByDesc(StatisticsUserData::getId).select(StatisticsUserData::getNumOfUser, StatisticsUserData::getPcNumOfUser).last("limit 1"));
  79. Integer yesNumOfUser = yesData == null ? 0 : yesData.getNumOfUser();
  80. Integer yesPcNumOfUser = yesData == null ? 0 : yesData.getPcNumOfUser();
  81. StatisticsUserData statisticsUserData = new StatisticsUserData();
  82. statisticsUserData.setNumOfNewUser(statisticsUserDataMapper.getNumOfNewUser(yesZeroDate, thisZeroDate));
  83. statisticsUserData.setNumOfActiveUser(statisticsUserDataMapper.getNumOfActiveUser(yesZeroDate, thisZeroDate));
  84. statisticsUserData.setNumOfUser(yesNumOfUser + statisticsUserData.getNumOfNewUser());
  85. statisticsUserData.setNumOfDistributeUser(statisticsUserDataMapper.getNumOfDistributeUserToday(yesZeroDate, thisZeroDate));
  86. List<CorpUserTagView> corpUserLists = Optional.ofNullable(beanSearcher.searchAll(CorpUserTagView.class, MapUtils.builder().field(CorpUserTagView::getCreatedTime, yesZeroDate, thisZeroDate).op(Operator.Between).build())).orElse(new ArrayList<>());
  87. statisticsUserData.setNumOfCorpUser(corpUserLists.size());
  88. statisticsUserData.setNumOfCorpEquipmentUser(corpUserLists.stream().filter(data -> "设备".equals(data.getTagName())).collect(Collectors.toList()).size());
  89. statisticsUserData.setNumOfCorpAccountUser(corpUserLists.stream().filter(data -> "账号".equals(data.getTagName())).collect(Collectors.toList()).size());
  90. statisticsUserData.setPcNumOfNewUser(statisticsUserDataMapper.getPcNumOfNewUser(yesZeroDate, thisZeroDate));
  91. statisticsUserData.setPcNumOfActiveUser(statisticsUserDataMapper.getPcNumOfActiveUser(yesZeroDate, thisZeroDate));
  92. statisticsUserData.setPcNumOfUser(yesPcNumOfUser + statisticsUserData.getPcNumOfNewUser());
  93. statisticsUserData.setStatisticsDate(yesZeroDate);
  94. statisticsUserDataMapper.insert(statisticsUserData);
  95. }
  96. /**
  97. * 注册账号数据
  98. */
  99. public List<RegisterAccountData> statisticsRegisterAccountData(Date yesZeroDate, Date thisZeroDate, Boolean today) {
  100. List<RegisterAccountData> list = new ArrayList<>();
  101. registerAccount.forEach(platform -> {
  102. RegisterAccountData entity = Optional.ofNullable(registerOrderDonMapper.registerAccountDataEveryDay(yesZeroDate, thisZeroDate, platform)).orElse(new RegisterAccountData());
  103. entity.setPlatform(platform);
  104. RegisterAccountData dto = Optional.ofNullable(registerOrderDonMapper.selectRefundOrderDetail(yesZeroDate, thisZeroDate, platform)).orElse(new RegisterAccountData());
  105. entity.setNumOfRefundOrder(dto.getNumOfRefundOrder());
  106. entity.setRefundMoney(dto.getRefundMoney());
  107. entity.setStatisticsDate(yesZeroDate);
  108. if (today) {
  109. list.add(entity);
  110. return;
  111. }
  112. registerAccountDataMapper.insert(entity);
  113. });
  114. if (today) {
  115. return list;
  116. }
  117. return null;
  118. }
  119. /**
  120. * 统计AppleOne数据
  121. *
  122. * @return
  123. */
  124. public List<AppleOneData> statisticsAppleOneData(Date yesZeroDate, Date thisZeroDate, Boolean today) {
  125. GoodsDon goodsDon = goodsDonMapper.selectOne(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getTitle, APPLE_ONE).last("limit 1"));
  126. List<GoodsDonSku> list = goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goodsDon.getId()).select(GoodsDonSku::getId, GoodsDonSku::getSpecVal));
  127. Set<String> area = new HashSet<>();
  128. list.forEach(sku -> {
  129. String areaName = sku.getSpecVal().substring(0, sku.getSpecVal().indexOf("区") + 1);
  130. if (!area.contains(areaName)) {
  131. area.add(areaName);
  132. }
  133. });
  134. Map<String, List<GoodsDonSku>> areaDataMap = new HashMap<>();
  135. for (String name : area) {
  136. List<GoodsDonSku> sku = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).like(GoodsDonSku::getSpecVal, name).select(GoodsDonSku::getId, GoodsDonSku::getGoodsId))).orElse(new ArrayList<>());
  137. areaDataMap.put(name, sku);
  138. }
  139. List<AbstractBackData> appleOneSave = new ArrayList<>();
  140. List<AppleOneData> appleOneData = new ArrayList<>();
  141. areaDataMap.forEach((areaName, skus) -> {
  142. AppleOneData appleOne = new AppleOneData();
  143. appleOne.setAreaName(areaName);
  144. //通过skuIds找到对应的appleOne统计数据
  145. List<Long> skuIds = skus.stream().map(GoodsDonSku::getId).collect(Collectors.toList());
  146. List<Long> goodsId = skus.stream().map(GoodsDonSku::getGoodsId).distinct().collect(Collectors.toList());
  147. List<OrderDon> orderDons = Optional.ofNullable(orderDonService.getAppleOneOrderDons(APPLE_ONE, skuIds, goodsId, noOrderStatus, yesZeroDate, thisZeroDate)).orElse(new ArrayList<>());
  148. appleOneDataStatistics(orderDons, appleOne, appleOneSave);
  149. });
  150. for (AbstractBackData appleOne : appleOneSave) {
  151. appleOne.setStatisticsDate(yesZeroDate);
  152. if (today) {
  153. appleOneData.add((AppleOneData) appleOne);
  154. continue;
  155. }
  156. appleOneDataMapper.insert((AppleOneData) appleOne);
  157. }
  158. if (today) {
  159. return appleOneData;
  160. }
  161. return null;
  162. }
  163. private void appleOneDataStatistics(List<OrderDon> orderDons, AppleOneData appleOne, List<AbstractBackData> appleOneSave) {
  164. if (CollUtil.isNotEmpty(orderDons)) {
  165. //用户人数
  166. Set<Long> numOfUser = Optional.ofNullable(orderDons.stream().map(OrderDon::getUserId).collect(Collectors.toSet())).orElse(new HashSet<>());
  167. appleOne.setNumOfUser(numOfUser.size());
  168. //订单数
  169. appleOne.setNumOfOrder(orderDons.size());
  170. //兑换码订单数
  171. List<OrderDon> exCodeOrders = Optional.ofNullable(orderDons.stream().filter(order -> order.getType() == OrderDon.Type.EX_CODE).collect(Collectors.toList())).orElse(new ArrayList<>());
  172. appleOne.setNumOfCodeOrder(exCodeOrders.size());
  173. //金额
  174. Optional<BigDecimal> money = orderDons.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
  175. if (money.isPresent()) {
  176. appleOne.setMoney(money.get());
  177. } else appleOne.setMoney(BigDecimal.ZERO);
  178. //分销订单
  179. List<OrderDon> distributeOrders = Optional.ofNullable(orderDons.stream().filter(ord -> ord.getIsDistribute()).collect(Collectors.toList())).orElse(new ArrayList<>());
  180. appleOne.setNumOfDistributeOrder(distributeOrders.size());
  181. Optional<BigDecimal> distributeMoney = distributeOrders.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
  182. appleOne.setDistributeOrderMoney(distributeMoney.isPresent() ? distributeMoney.get() : BigDecimal.ZERO);
  183. getNumOfOrderByPayType(orderDons, appleOne);
  184. }
  185. appleOneSave.add(appleOne);
  186. }
  187. /**
  188. * 统计流媒体账号数据
  189. */
  190. public List<StreamingAccountData> statisticsStreamingAccountData(Date yesZeroDate, Date thisZeroDate, Boolean today) {
  191. List<Account> accounts = accountService.getNoAppleOneAccount(APPLE_ONE);
  192. Map<Long, List<Account>> accountMaps = accounts.stream().collect(Collectors.groupingBy(Account::getGoodsId));
  193. List<StreamingAccountData> streamingAccountDataSave = new ArrayList<>(accounts.size());
  194. accountMaps.forEach((goodsId, accountList) -> {
  195. StreamingAccountData streamingAccount = new StreamingAccountData();
  196. streamingAccount.setAccountName(accountList.get(0).getTitle());
  197. streamingAccount.setGoodsId(goodsId);
  198. streamingAccountDataStatistics(goodsId, streamingAccount, streamingAccountDataSave, yesZeroDate, thisZeroDate);
  199. });
  200. if (today) {
  201. return streamingAccountDataSave;
  202. }
  203. for (StreamingAccountData streamingAccountData : streamingAccountDataSave) {
  204. streamingAccountData.setStatisticsDate(yesZeroDate);
  205. streamingAccountDataMapper.insert(streamingAccountData);
  206. }
  207. return null;
  208. }
  209. /**
  210. * 统计实物数据
  211. */
  212. public List<RealGoodsData> statisticsRealGoodsData(Date yesZeroDate, Date thisZeroDate, Boolean today) {
  213. List<GoodsDon> goodsDons = goodsDonMapper.selectList(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getType, 2));
  214. List<RealGoodsData> realGoodsDataList = new ArrayList<>();
  215. if (!goodsDons.isEmpty()) {
  216. goodsDons.forEach(goods -> {
  217. List<GoodsDonSku> skuList = goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goods.getId()));
  218. if (!skuList.isEmpty()) {
  219. skuList.forEach(sku -> {
  220. RealGoodsData realGoodsData = new RealGoodsData();
  221. realGoodsData.setGoodsId(goods.getId());
  222. realGoodsData.setGoodsTitle(goods.getTitle());
  223. realGoodsData.setSkuId(sku.getId());
  224. realGoodsData.setSpecVal(sku.getSpecVal());
  225. //订单
  226. List<OrderDon> orderDon = Optional.ofNullable(orderDonService.list(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getSkuId, sku.getId()).between(OrderDon::getCreatedTime, yesZeroDate, thisZeroDate).notIn(OrderDon::getStatus, noOrderStatus).select(OrderDon::getUserId, OrderDon::getMoney, OrderDon::getId))).orElse(new ArrayList<>());
  227. Set<Long> userList = Optional.ofNullable(orderDon.stream().map(OrderDon::getUserId).collect(Collectors.toSet())).orElse(new HashSet<>());
  228. //用户数
  229. realGoodsData.setNumOfUser(userList.size());
  230. //订单数
  231. realGoodsData.setNumOfOrder(orderDon.size());
  232. //金额
  233. Optional<BigDecimal> money = orderDon.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
  234. realGoodsData.setMoney(money.isPresent() ? money.get() : BigDecimal.ZERO);
  235. realGoodsDataList.add(realGoodsData);
  236. });
  237. }
  238. });
  239. }
  240. if (today) {
  241. return realGoodsDataList;
  242. }
  243. if (!realGoodsDataList.isEmpty()) {
  244. realGoodsDataList.forEach(data -> {
  245. data.setStatisticsDate(yesZeroDate);
  246. realGoodsDataMapper.insert(data);
  247. });
  248. }
  249. return null;
  250. }
  251. /**
  252. * @param goodsId 平台id
  253. * @param streamingAccountData
  254. * @param dataSave 入库实体集合
  255. * @param yesZeroDate 昨日零时
  256. * @param thisZeroDate 今日零时
  257. */
  258. private void streamingAccountDataStatistics(Long goodsId, StreamingAccountData streamingAccountData, List<StreamingAccountData> dataSave, Date yesZeroDate, Date thisZeroDate) {
  259. //规格
  260. List<GoodsDonSku> list = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goodsId).select(GoodsDonSku::getId))).orElse(new ArrayList<>());
  261. List<Long> skuIds = list.stream().map(GoodsDonSku::getId).collect(Collectors.toList());
  262. if (CollUtil.isNotEmpty(skuIds)) {
  263. List<OrderDon> orderDons = Optional.ofNullable(accountService.getNoAppleOneOrderDon(skuIds, yesZeroDate, thisZeroDate, noOrderStatus)).orElse(new ArrayList<>());
  264. //用户数
  265. streamingAccountData.setNumOfUser(orderDons.stream().map(OrderDon::getUserId).collect(Collectors.toSet()).size());
  266. getNumOfOrderByPayType(orderDons, streamingAccountData);
  267. //兑换码订单数
  268. List<OrderDon> exCodeOrders = Optional.ofNullable(orderDons.stream().filter(order -> order.getType() == OrderDon.Type.EX_CODE).collect(Collectors.toList())).orElse(new ArrayList<>());
  269. streamingAccountData.setNumOfCodeOrder(exCodeOrders.size());
  270. streamingAccountData.setNumOfOrder(orderDons.size());
  271. Optional<BigDecimal> reduce = orderDons.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
  272. BigDecimal totalMoney = BigDecimal.valueOf(0);
  273. if (reduce.isPresent()) {
  274. totalMoney = reduce.get();
  275. }
  276. //金额
  277. streamingAccountData.setMoney(totalMoney);
  278. //分销订单
  279. List<OrderDon> distributeOrders = Optional.ofNullable(orderDons.stream().filter(ord -> ord.getIsDistribute()).collect(Collectors.toList())).orElse(new ArrayList<>());
  280. streamingAccountData.setNumOfDistributeOrder(distributeOrders.size());
  281. Optional<BigDecimal> distributeMoney = distributeOrders.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
  282. streamingAccountData.setDistributeOrderMoney(distributeMoney.isPresent() ? distributeMoney.get() : BigDecimal.ZERO);
  283. }
  284. dataSave.add(streamingAccountData);
  285. }
  286. /**
  287. * 根据不同支付条件统计对应月、季、年订单
  288. */
  289. private void getNumOfOrderByPayType(List<OrderDon> orderDons, AbstractBackData backData) {
  290. Integer numOfMonthOrder = 0;
  291. Integer numOfSeasonOrder = 0;
  292. Integer numOfYearOrder = 0;
  293. Map<Long, List<OrderDon>> skuIdMaps = Optional.ofNullable(orderDons.stream().collect(Collectors.groupingBy(OrderDon::getSkuId))).orElse(new HashMap<>());
  294. if (!skuIdMaps.isEmpty()) {
  295. List<GoodsDonSku> goodsDonSkus = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).in(GoodsDonSku::getId, skuIdMaps.keySet()))).orElse(new ArrayList<>());
  296. for (GoodsDonSku donSkus : goodsDonSkus) {
  297. int size = skuIdMaps.get(donSkus.getId()).size();
  298. if (donSkus.getSpecVal().contains(payType.get(0)) && !donSkus.getSpecVal().contains(payType.get(2))) {
  299. numOfMonthOrder += size;
  300. } else if (donSkus.getSpecVal().contains(payType.get(1))) {
  301. numOfSeasonOrder += size;
  302. } else if (donSkus.getSpecVal().contains(payType.get(2))) {
  303. numOfYearOrder += size;
  304. }
  305. }
  306. }
  307. //月付
  308. backData.setNumOfMonthOrder(numOfMonthOrder);
  309. //季付
  310. backData.setNumOfSeasonOrder(numOfSeasonOrder);
  311. //年付
  312. backData.setNumOfYearOrder(numOfYearOrder);
  313. }
  314. }