package com.cyksj.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.cyksj.common.constant.Constant; import com.cyksj.common.task.GlobalThreadPoolTaskExecutor; import com.cyksj.mapper.GoodsDonMapper; import com.cyksj.mapper.RegisterAccountDataMapper; import com.cyksj.mapper.RegisterOrderDonMapper; import com.cyksj.mapper.manage.statistics.AppleOneDataMapper; import com.cyksj.mapper.manage.statistics.RealGoodsDataMapper; import com.cyksj.mapper.manage.statistics.StatisticsUserDataMapper; import com.cyksj.mapper.manage.statistics.StreamingAccountDataMapper; import com.cyksj.model.entity.*; import com.cyksj.model.views.CorpUserTagView; import com.cyksj.service.mange.CmsAccountService; import com.cyksj.service.mange.CmsGoodsDonSkuService; import com.cyksj.service.order.OrderDonService; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.param.Operator; import com.ejlchina.searcher.util.MapUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /* *项目名: netflix *文件名: StatisticsDataScheduler *创建者: JavaZou *创建时间:2022/10/18 12:07 */ @Component @Slf4j @RequiredArgsConstructor public class StatisticsDataScheduler { private final OrderDonService orderDonService; private final CmsGoodsDonSkuService goodsDonSkuService; private final CmsAccountService accountService; private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance(); private final AppleOneDataMapper appleOneDataMapper; private final StreamingAccountDataMapper streamingAccountDataMapper; private final static String APPLE_ONE = "Apple One"; public static List noOrderStatus = List.of("close", "noPayment"); public static List payType = List.of("月", "季", "年"); private final static List registerAccount = List.of("apple", "spotify", "google"); private final GoodsDonMapper goodsDonMapper; private final RealGoodsDataMapper realGoodsDataMapper; private final RegisterOrderDonMapper registerOrderDonMapper; private final RegisterAccountDataMapper registerAccountDataMapper; private final StatisticsUserDataMapper statisticsUserDataMapper; private final BeanSearcher beanSearcher; /** * 后台数据统计 定时器 */ @Scheduled(cron = "0 0 1 * * ?") public void statisticsData() { Date thisZeroDate = DateUtil.beginOfDay(DateTime.now()); Date yesZeroDate = DateTime.of(thisZeroDate.getTime() - Constant.DAY_MILLS); //统计AppleOne数据 TASK_POOL.execute(() -> statisticsAppleOneData(yesZeroDate, thisZeroDate, false)); //统计流媒体账号数据 TASK_POOL.execute(() -> statisticsStreamingAccountData(yesZeroDate, thisZeroDate, false)); //统计实物数据 TASK_POOL.execute(() -> statisticsRealGoodsData(yesZeroDate, thisZeroDate, false)); //注册账号数据 TASK_POOL.execute(() -> statisticsRegisterAccountData(yesZeroDate, thisZeroDate, false)); //用户数据统计 statisticsUserData(yesZeroDate, thisZeroDate); } /** * 用户数据统计 */ private void statisticsUserData(Date yesZeroDate, Date thisZeroDate) { StatisticsUserData yesData = statisticsUserDataMapper.selectOne(Wrappers.lambdaQuery(StatisticsUserData.class).orderByDesc(StatisticsUserData::getId).select(StatisticsUserData::getNumOfUser, StatisticsUserData::getPcNumOfUser).last("limit 1")); Integer yesNumOfUser = yesData == null ? 0 : yesData.getNumOfUser(); Integer yesPcNumOfUser = yesData == null ? 0 : yesData.getPcNumOfUser(); StatisticsUserData statisticsUserData = new StatisticsUserData(); statisticsUserData.setNumOfNewUser(statisticsUserDataMapper.getNumOfNewUser(yesZeroDate, thisZeroDate)); statisticsUserData.setNumOfActiveUser(statisticsUserDataMapper.getNumOfActiveUser(yesZeroDate, thisZeroDate)); statisticsUserData.setNumOfUser(yesNumOfUser + statisticsUserData.getNumOfNewUser()); statisticsUserData.setNumOfDistributeUser(statisticsUserDataMapper.getNumOfDistributeUserToday(yesZeroDate, thisZeroDate)); List corpUserLists = Optional.ofNullable(beanSearcher.searchAll(CorpUserTagView.class, MapUtils.builder().field(CorpUserTagView::getCreatedTime, yesZeroDate, thisZeroDate).op(Operator.Between).build())).orElse(new ArrayList<>()); statisticsUserData.setNumOfCorpUser(corpUserLists.size()); statisticsUserData.setNumOfCorpEquipmentUser(corpUserLists.stream().filter(data -> "设备".equals(data.getTagName())).collect(Collectors.toList()).size()); statisticsUserData.setNumOfCorpAccountUser(corpUserLists.stream().filter(data -> "账号".equals(data.getTagName())).collect(Collectors.toList()).size()); statisticsUserData.setPcNumOfNewUser(statisticsUserDataMapper.getPcNumOfNewUser(yesZeroDate, thisZeroDate)); statisticsUserData.setPcNumOfActiveUser(statisticsUserDataMapper.getPcNumOfActiveUser(yesZeroDate, thisZeroDate)); statisticsUserData.setPcNumOfUser(yesPcNumOfUser + statisticsUserData.getPcNumOfNewUser()); statisticsUserData.setStatisticsDate(yesZeroDate); statisticsUserDataMapper.insert(statisticsUserData); } /** * 注册账号数据 */ public List statisticsRegisterAccountData(Date yesZeroDate, Date thisZeroDate, Boolean today) { List list = new ArrayList<>(); registerAccount.forEach(platform -> { RegisterAccountData entity = Optional.ofNullable(registerOrderDonMapper.registerAccountDataEveryDay(yesZeroDate, thisZeroDate, platform)).orElse(new RegisterAccountData()); entity.setPlatform(platform); RegisterAccountData dto = Optional.ofNullable(registerOrderDonMapper.selectRefundOrderDetail(yesZeroDate, thisZeroDate, platform)).orElse(new RegisterAccountData()); entity.setNumOfRefundOrder(dto.getNumOfRefundOrder()); entity.setRefundMoney(dto.getRefundMoney()); entity.setStatisticsDate(yesZeroDate); if (today) { list.add(entity); return; } registerAccountDataMapper.insert(entity); }); if (today) { return list; } return null; } /** * 统计AppleOne数据 * * @return */ public List statisticsAppleOneData(Date yesZeroDate, Date thisZeroDate, Boolean today) { GoodsDon goodsDon = goodsDonMapper.selectOne(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getTitle, APPLE_ONE).last("limit 1")); List list = goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goodsDon.getId()).select(GoodsDonSku::getId, GoodsDonSku::getSpecVal)); Set area = new HashSet<>(); list.forEach(sku -> { String areaName = sku.getSpecVal().substring(0, sku.getSpecVal().indexOf("区") + 1); if (!area.contains(areaName)) { area.add(areaName); } }); Map> areaDataMap = new HashMap<>(); for (String name : area) { List sku = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).like(GoodsDonSku::getSpecVal, name).select(GoodsDonSku::getId, GoodsDonSku::getGoodsId))).orElse(new ArrayList<>()); areaDataMap.put(name, sku); } List appleOneSave = new ArrayList<>(); List appleOneData = new ArrayList<>(); areaDataMap.forEach((areaName, skus) -> { AppleOneData appleOne = new AppleOneData(); appleOne.setAreaName(areaName); //通过skuIds找到对应的appleOne统计数据 List skuIds = skus.stream().map(GoodsDonSku::getId).collect(Collectors.toList()); List goodsId = skus.stream().map(GoodsDonSku::getGoodsId).distinct().collect(Collectors.toList()); List orderDons = Optional.ofNullable(orderDonService.getAppleOneOrderDons(APPLE_ONE, skuIds, goodsId, noOrderStatus, yesZeroDate, thisZeroDate)).orElse(new ArrayList<>()); appleOneDataStatistics(orderDons, appleOne, appleOneSave); }); for (AbstractBackData appleOne : appleOneSave) { appleOne.setStatisticsDate(yesZeroDate); if (today) { appleOneData.add((AppleOneData) appleOne); continue; } appleOneDataMapper.insert((AppleOneData) appleOne); } if (today) { return appleOneData; } return null; } private void appleOneDataStatistics(List orderDons, AppleOneData appleOne, List appleOneSave) { if (CollUtil.isNotEmpty(orderDons)) { //用户人数 Set numOfUser = Optional.ofNullable(orderDons.stream().map(OrderDon::getUserId).collect(Collectors.toSet())).orElse(new HashSet<>()); appleOne.setNumOfUser(numOfUser.size()); //订单数 appleOne.setNumOfOrder(orderDons.size()); //兑换码订单数 List exCodeOrders = Optional.ofNullable(orderDons.stream().filter(order -> order.getType() == OrderDon.Type.EX_CODE).collect(Collectors.toList())).orElse(new ArrayList<>()); appleOne.setNumOfCodeOrder(exCodeOrders.size()); //金额 Optional money = orderDons.stream().map(OrderDon::getMoney).reduce(BigDecimal::add); if (money.isPresent()) { appleOne.setMoney(money.get()); } else appleOne.setMoney(BigDecimal.ZERO); //分销订单 List distributeOrders = Optional.ofNullable(orderDons.stream().filter(ord -> ord.getIsDistribute()).collect(Collectors.toList())).orElse(new ArrayList<>()); appleOne.setNumOfDistributeOrder(distributeOrders.size()); Optional distributeMoney = distributeOrders.stream().map(OrderDon::getMoney).reduce(BigDecimal::add); appleOne.setDistributeOrderMoney(distributeMoney.isPresent() ? distributeMoney.get() : BigDecimal.ZERO); getNumOfOrderByPayType(orderDons, appleOne); } appleOneSave.add(appleOne); } /** * 统计流媒体账号数据 */ public List statisticsStreamingAccountData(Date yesZeroDate, Date thisZeroDate, Boolean today) { List accounts = accountService.getNoAppleOneAccount(APPLE_ONE); Map> accountMaps = accounts.stream().collect(Collectors.groupingBy(Account::getGoodsId)); List streamingAccountDataSave = new ArrayList<>(accounts.size()); accountMaps.forEach((goodsId, accountList) -> { StreamingAccountData streamingAccount = new StreamingAccountData(); streamingAccount.setAccountName(accountList.get(0).getTitle()); streamingAccount.setGoodsId(goodsId); streamingAccountDataStatistics(goodsId, streamingAccount, streamingAccountDataSave, yesZeroDate, thisZeroDate); }); if (today) { return streamingAccountDataSave; } for (StreamingAccountData streamingAccountData : streamingAccountDataSave) { streamingAccountData.setStatisticsDate(yesZeroDate); streamingAccountDataMapper.insert(streamingAccountData); } return null; } /** * 统计实物数据 */ public List statisticsRealGoodsData(Date yesZeroDate, Date thisZeroDate, Boolean today) { List goodsDons = goodsDonMapper.selectList(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getType, 2)); List realGoodsDataList = new ArrayList<>(); if (!goodsDons.isEmpty()) { goodsDons.forEach(goods -> { List skuList = goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goods.getId())); if (!skuList.isEmpty()) { skuList.forEach(sku -> { RealGoodsData realGoodsData = new RealGoodsData(); realGoodsData.setGoodsId(goods.getId()); realGoodsData.setGoodsTitle(goods.getTitle()); realGoodsData.setSkuId(sku.getId()); realGoodsData.setSpecVal(sku.getSpecVal()); //订单 List 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<>()); Set userList = Optional.ofNullable(orderDon.stream().map(OrderDon::getUserId).collect(Collectors.toSet())).orElse(new HashSet<>()); //用户数 realGoodsData.setNumOfUser(userList.size()); //订单数 realGoodsData.setNumOfOrder(orderDon.size()); //金额 Optional money = orderDon.stream().map(OrderDon::getMoney).reduce(BigDecimal::add); realGoodsData.setMoney(money.isPresent() ? money.get() : BigDecimal.ZERO); realGoodsDataList.add(realGoodsData); }); } }); } if (today) { return realGoodsDataList; } if (!realGoodsDataList.isEmpty()) { realGoodsDataList.forEach(data -> { data.setStatisticsDate(yesZeroDate); realGoodsDataMapper.insert(data); }); } return null; } /** * @param goodsId 平台id * @param streamingAccountData * @param dataSave 入库实体集合 * @param yesZeroDate 昨日零时 * @param thisZeroDate 今日零时 */ private void streamingAccountDataStatistics(Long goodsId, StreamingAccountData streamingAccountData, List dataSave, Date yesZeroDate, Date thisZeroDate) { //规格 List list = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).eq(GoodsDonSku::getGoodsId, goodsId).select(GoodsDonSku::getId))).orElse(new ArrayList<>()); List skuIds = list.stream().map(GoodsDonSku::getId).collect(Collectors.toList()); if (CollUtil.isNotEmpty(skuIds)) { List orderDons = Optional.ofNullable(accountService.getNoAppleOneOrderDon(skuIds, yesZeroDate, thisZeroDate, noOrderStatus)).orElse(new ArrayList<>()); //用户数 streamingAccountData.setNumOfUser(orderDons.stream().map(OrderDon::getUserId).collect(Collectors.toSet()).size()); getNumOfOrderByPayType(orderDons, streamingAccountData); //兑换码订单数 List exCodeOrders = Optional.ofNullable(orderDons.stream().filter(order -> order.getType() == OrderDon.Type.EX_CODE).collect(Collectors.toList())).orElse(new ArrayList<>()); streamingAccountData.setNumOfCodeOrder(exCodeOrders.size()); streamingAccountData.setNumOfOrder(orderDons.size()); Optional reduce = orderDons.stream().map(OrderDon::getMoney).reduce(BigDecimal::add); BigDecimal totalMoney = BigDecimal.valueOf(0); if (reduce.isPresent()) { totalMoney = reduce.get(); } //金额 streamingAccountData.setMoney(totalMoney); //分销订单 List distributeOrders = Optional.ofNullable(orderDons.stream().filter(ord -> ord.getIsDistribute()).collect(Collectors.toList())).orElse(new ArrayList<>()); streamingAccountData.setNumOfDistributeOrder(distributeOrders.size()); Optional distributeMoney = distributeOrders.stream().map(OrderDon::getMoney).reduce(BigDecimal::add); streamingAccountData.setDistributeOrderMoney(distributeMoney.isPresent() ? distributeMoney.get() : BigDecimal.ZERO); } dataSave.add(streamingAccountData); } /** * 根据不同支付条件统计对应月、季、年订单 */ private void getNumOfOrderByPayType(List orderDons, AbstractBackData backData) { Integer numOfMonthOrder = 0; Integer numOfSeasonOrder = 0; Integer numOfYearOrder = 0; Map> skuIdMaps = Optional.ofNullable(orderDons.stream().collect(Collectors.groupingBy(OrderDon::getSkuId))).orElse(new HashMap<>()); if (!skuIdMaps.isEmpty()) { List goodsDonSkus = Optional.ofNullable(goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class).in(GoodsDonSku::getId, skuIdMaps.keySet()))).orElse(new ArrayList<>()); for (GoodsDonSku donSkus : goodsDonSkus) { int size = skuIdMaps.get(donSkus.getId()).size(); if (donSkus.getSpecVal().contains(payType.get(0)) && !donSkus.getSpecVal().contains(payType.get(2))) { numOfMonthOrder += size; } else if (donSkus.getSpecVal().contains(payType.get(1))) { numOfSeasonOrder += size; } else if (donSkus.getSpecVal().contains(payType.get(2))) { numOfYearOrder += size; } } } //月付 backData.setNumOfMonthOrder(numOfMonthOrder); //季付 backData.setNumOfSeasonOrder(numOfSeasonOrder); //年付 backData.setNumOfYearOrder(numOfYearOrder); } }