|  | @@ -1,15 +1,41 @@
 | 
	
		
			
				|  |  |  package cn.newfeifan.mall.module.distri.service.partitioncrash;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.framework.common.util.json.JsonUtils;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.controller.admin.integral.vo.IntegralSaveReqVO;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.controller.admin.partitionbrothers.vo.PartitionBrothersSaveReqVO;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.controller.admin.partitionson.vo.PartitionSonSaveReqVO;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.dal.dataobject.duser.DuserDO;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.dal.dataobject.integral.IntegralDO;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.dal.dataobject.ordercalc.OrderCalcDO;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.dal.dataobject.orderpercentage.OrderPercentageDO;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.dal.dataobject.ptprofit.PtProfitDO;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.enums.CaclEnum;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.service.duser.DuserService;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.service.integral.IntegralService;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.service.orderpercentage.OrderPercentageService;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.service.partitionbrothers.PartitionBrothersService;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.service.partitionson.PartitionSonService;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.service.ptprofit.PtProfitService;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.service.ptprofitlog.PtProfitLogService;
 | 
	
		
			
				|  |  | +import cn.newfeifan.mall.module.distri.service.sharepath.SharePathService;
 | 
	
		
			
				|  |  |  import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import javax.annotation.Resource;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import org.springframework.validation.annotation.Validated;
 | 
	
		
			
				|  |  | -import org.springframework.transaction.annotation.Transactional;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import java.math.BigDecimal;
 | 
	
		
			
				|  |  | +import java.time.LocalDate;
 | 
	
		
			
				|  |  | +import java.time.LocalDateTime;
 | 
	
		
			
				|  |  | +import java.time.LocalTime;
 | 
	
		
			
				|  |  |  import java.util.*;
 | 
	
		
			
				|  |  | +import java.util.concurrent.CompletableFuture;
 | 
	
		
			
				|  |  | +import java.util.stream.Collectors;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  import cn.newfeifan.mall.module.distri.controller.admin.partitioncrash.vo.*;
 | 
	
		
			
				|  |  |  import cn.newfeifan.mall.module.distri.dal.dataobject.partitioncrash.PartitionCrashDO;
 | 
	
		
			
				|  |  |  import cn.newfeifan.mall.framework.common.pojo.PageResult;
 | 
	
		
			
				|  |  | -import cn.newfeifan.mall.framework.common.pojo.PageParam;
 | 
	
		
			
				|  |  |  import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import cn.newfeifan.mall.module.distri.dal.mysql.partitioncrash.PartitionCrashMapper;
 | 
	
	
		
			
				|  | @@ -29,6 +55,31 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
 | 
	
		
			
				|  |  |      @Resource
 | 
	
		
			
				|  |  |      private PartitionCrashMapper partitionCrashMapper;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private SharePathService sharePathService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private PartitionSonService partitionSonService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private PartitionBrothersService partitionBrothersService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private DuserService duserService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private PtProfitLogService ptProfitLogService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private IntegralService integralService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private OrderPercentageService orderPercentageService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private PtProfitService ptProfitService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public Long createPartitionCrash(PartitionCrashSaveReqVO createReqVO) {
 | 
	
		
			
				|  |  |          // 插入
 | 
	
	
		
			
				|  | @@ -71,4 +122,196 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
 | 
	
		
			
				|  |  |          return partitionCrashMapper.selectPage(pageReqVO);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void calcCrash(List<Long> userId) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 获取所有的营销用户
 | 
	
		
			
				|  |  | +        List<DuserDO> duserDOS = duserService.selectAllUser();
 | 
	
		
			
				|  |  | +        if (duserDOS.isEmpty()) {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 获取当前合赢奖百分比
 | 
	
		
			
				|  |  | +        OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();
 | 
	
		
			
				|  |  | +        List<HashMap<Long, Integer>> afterCrashMap = duserDOS.stream().map(k -> CompletableFuture.supplyAsync(() -> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 获取当前用户的钱包
 | 
	
		
			
				|  |  | +            IntegralDO integralDO = integralService.selectByUser(k.getUserId());
 | 
	
		
			
				|  |  | +            // 获取当前父亲的钱包
 | 
	
		
			
				|  |  | +            IntegralDO parentIntegralDo = integralService.selectUserParent(k.getUserId());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 创建一个分区编号
 | 
	
		
			
				|  |  | +            String todayNo = crashTodayNo(k.getUserId());
 | 
	
		
			
				|  |  | +            String yesterdayNo = crashYesterdayNo(k.getUserId());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            PartitionSonSaveReqVO.PartitionSonSaveReqVOBuilder sonBuilder = PartitionSonSaveReqVO.builder();
 | 
	
		
			
				|  |  | +            PartitionBrothersSaveReqVO.PartitionBrothersSaveReqVOBuilder brotherBuilder = PartitionBrothersSaveReqVO.builder();
 | 
	
		
			
				|  |  | +            PartitionCrashSaveReqVO.PartitionCrashSaveReqVOBuilder crashSaveReqVOBuilder = PartitionCrashSaveReqVO.builder();
 | 
	
		
			
				|  |  | +            sonBuilder.partNo(todayNo);
 | 
	
		
			
				|  |  | +            sonBuilder.name(k.getName());
 | 
	
		
			
				|  |  | +            sonBuilder.nickName(k.getNickName());
 | 
	
		
			
				|  |  | +            sonBuilder.hasHit(1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            brotherBuilder.partNo(todayNo);
 | 
	
		
			
				|  |  | +            brotherBuilder.name(k.getName());
 | 
	
		
			
				|  |  | +            brotherBuilder.nickName(k.getNickName());
 | 
	
		
			
				|  |  | +            brotherBuilder.hasHit(1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            crashSaveReqVOBuilder.partNo(todayNo);
 | 
	
		
			
				|  |  | +            crashSaveReqVOBuilder.nickName(k.getNickName());
 | 
	
		
			
				|  |  | +            crashSaveReqVOBuilder.userName(k.getName());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 获取当前用户的后代分区 , 并且该分区存在有下单的用户
 | 
	
		
			
				|  |  | +            List<OrderCalcDO> sonOrderCalcDOS = sharePathService.selectSons(k.getUserId(), userId);
 | 
	
		
			
				|  |  | +            if (sonOrderCalcDOS.isEmpty()) {
 | 
	
		
			
				|  |  | +                // 插入空数据
 | 
	
		
			
				|  |  | +                sonBuilder = addSonEmpty(sonBuilder, k);
 | 
	
		
			
				|  |  | +                crashSaveReqVOBuilder.sonPrice(0);
 | 
	
		
			
				|  |  | +                partitionSonService.createPartitionSon(sonBuilder.build());
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            // 合计儿子分支额度
 | 
	
		
			
				|  |  | +            Integer sonSumPrice = sonOrderCalcDOS.stream().mapToInt(OrderCalcDO::getGrossProfitBonusQuota).sum();
 | 
	
		
			
				|  |  | +            crashSaveReqVOBuilder.sonPrice(sonSumPrice);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 获取当前用户的兄弟分区
 | 
	
		
			
				|  |  | +            List<OrderCalcDO> brothersOrderCalcDOS = sharePathService.selectBrothers(k.getUserId(), userId);
 | 
	
		
			
				|  |  | +            if (brothersOrderCalcDOS.isEmpty()) {
 | 
	
		
			
				|  |  | +                // 插入空数据
 | 
	
		
			
				|  |  | +                brotherBuilder = addBrotherEmpty(brotherBuilder, k);
 | 
	
		
			
				|  |  | +                crashSaveReqVOBuilder.brotherPrice(0);
 | 
	
		
			
				|  |  | +                partitionBrothersService.createPartitionBrothers(brotherBuilder.build());
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 合并兄弟分支额度
 | 
	
		
			
				|  |  | +            Integer brotherSumPrice = brothersOrderCalcDOS.stream().mapToInt(OrderCalcDO::getGrossProfitBonusQuota).sum();
 | 
	
		
			
				|  |  | +            crashSaveReqVOBuilder.brotherPrice(sonSumPrice);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 判断,昨天是否有存余的分支
 | 
	
		
			
				|  |  | +            PartitionCrashDO yesterdayCrash = partitionCrashMapper.selectOne(new LambdaQueryWrapperX<PartitionCrashDO>().eqIfPresent(PartitionCrashDO::getPartNo, yesterdayNo));
 | 
	
		
			
				|  |  | +            // 如果不为空, 则判断增加到哪个分支中
 | 
	
		
			
				|  |  | +            if (yesterdayCrash.getSonPrice() >= yesterdayCrash.getBrotherPrice()) {
 | 
	
		
			
				|  |  | +                sonSumPrice = sonSumPrice + yesterdayCrash.getSonPrice();
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                brotherSumPrice = brotherSumPrice + yesterdayCrash.getBrotherPrice();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            int afterCrash = 0;
 | 
	
		
			
				|  |  | +            Integer smallQuota = 0;
 | 
	
		
			
				|  |  | +            // 碰撞计算
 | 
	
		
			
				|  |  | +            if (sonSumPrice >= brotherSumPrice) {
 | 
	
		
			
				|  |  | +                sonBuilder.size(1);
 | 
	
		
			
				|  |  | +                brotherBuilder.size(0);
 | 
	
		
			
				|  |  | +                afterCrash = sonSumPrice - brotherSumPrice;
 | 
	
		
			
				|  |  | +                smallQuota = brotherSumPrice;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                sonBuilder.size(0);
 | 
	
		
			
				|  |  | +                brotherBuilder.size(1);
 | 
	
		
			
				|  |  | +                afterCrash = brotherSumPrice - sonSumPrice;
 | 
	
		
			
				|  |  | +                smallQuota = sonSumPrice;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            crashSaveReqVOBuilder.brotherPrice(brotherSumPrice);
 | 
	
		
			
				|  |  | +            crashSaveReqVOBuilder.sonPrice(sonSumPrice);
 | 
	
		
			
				|  |  | +            crashSaveReqVOBuilder.afterHitQuota(afterCrash);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 积分添加 添加的时候, 需要注意当前用户是否有足够的积分可以获取
 | 
	
		
			
				|  |  | +            // 碰撞后的额度的
 | 
	
		
			
				|  |  | +            Integer highQuota = integralDO.getHighQuota();
 | 
	
		
			
				|  |  | +            Integer parentHighQuota = parentIntegralDo.getHighQuota();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            BigDecimal smallBigDecimal = new BigDecimal(String.valueOf(smallQuota));
 | 
	
		
			
				|  |  | +            BigDecimal multiply = smallBigDecimal.multiply(new BigDecimal(String.valueOf(orderPercentageDO.getDivideIntoPerc())));
 | 
	
		
			
				|  |  | +            if (compare(highQuota, multiply)) {
 | 
	
		
			
				|  |  | +                Integer currentQuota = integralDO.getCurrentQuota();
 | 
	
		
			
				|  |  | +                integralDO.setCurrentQuota(currentQuota + multiply.intValue());
 | 
	
		
			
				|  |  | +                // 碰撞后的额度添加到日志中 增加日志模块
 | 
	
		
			
				|  |  | +                integralService.updateIntegral(BeanUtils.toBean(integralDO, IntegralSaveReqVO.class));
 | 
	
		
			
				|  |  | +                ptProfitLogService.addMessage(k.getUserId(), CaclEnum.SMALL_QUOTA_CRASH, currentQuota, integralDO.getCurrentQuota(), JsonUtils.toJsonString(orderPercentageDO));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if (compare(parentHighQuota, multiply)) {
 | 
	
		
			
				|  |  | +                Integer currentQuota = parentIntegralDo.getCurrentQuota();
 | 
	
		
			
				|  |  | +                parentIntegralDo.setCurrentQuota(currentQuota + multiply.intValue());
 | 
	
		
			
				|  |  | +                // 碰撞后的额度添加到日志中 增加日志模块
 | 
	
		
			
				|  |  | +                integralService.updateIntegral(BeanUtils.toBean(parentIntegralDo, IntegralSaveReqVO.class));
 | 
	
		
			
				|  |  | +                ptProfitLogService.addMessage(parentIntegralDo.getUserId(), CaclEnum.SMALL_QUOTA_CRASH, currentQuota, parentIntegralDo.getCurrentQuota(), JsonUtils.toJsonString(orderPercentageDO));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 获取计算后积分, Long为userId, Integer为碰撞后额度
 | 
	
		
			
				|  |  | +            HashMap<Long, Integer> map = new HashMap<>();
 | 
	
		
			
				|  |  | +            map.put(k.getUserId(), multiply.intValue());
 | 
	
		
			
				|  |  | +            map.put(parentIntegralDo.getUserId(), multiply.intValue());
 | 
	
		
			
				|  |  | +            return map;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        })).collect(Collectors.toList()).stream().map(CompletableFuture::join).collect(Collectors.toList());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 计算平台积分
 | 
	
		
			
				|  |  | +        // 获取当前平台的额度
 | 
	
		
			
				|  |  | +        PtProfitDO ptProfit = ptProfitService.getPtProfit();
 | 
	
		
			
				|  |  | +        // 遍历hashMap
 | 
	
		
			
				|  |  | +        for (HashMap<Long, Integer> longIntegerHashMap : afterCrashMap) {
 | 
	
		
			
				|  |  | +            for (Map.Entry<Long, Integer> entry : longIntegerHashMap.entrySet()) {
 | 
	
		
			
				|  |  | +                if (ptProfit.getPtTotalAdd() <= 0) {
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                // 当前平台总积分
 | 
	
		
			
				|  |  | +                Integer ptTotalAdd = ptProfit.getPtTotalAdd();
 | 
	
		
			
				|  |  | +                // 平台扣除积分
 | 
	
		
			
				|  |  | +                ptProfit.setPtTotalAdd(ptProfit.getPtTotalAdd() - entry.getValue());
 | 
	
		
			
				|  |  | +                // 碰撞后的额度添加到日志中 增加日志模块
 | 
	
		
			
				|  |  | +                ptProfitLogService.addMessage(entry.getKey(), CaclEnum.AFTER_CRASH_CALC_PT_TOTAL_QUOTA
 | 
	
		
			
				|  |  | +                        , ptTotalAdd, ptProfit.getPtTotalAdd() - entry.getValue(), JsonUtils.toJsonString(orderPercentageDO));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public Boolean compare(Integer highQuota, BigDecimal afterCrash) {
 | 
	
		
			
				|  |  | +        BigDecimal high = new BigDecimal(String.valueOf(highQuota));
 | 
	
		
			
				|  |  | +        int i = high.compareTo(afterCrash);
 | 
	
		
			
				|  |  | +        return i >= 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private PartitionBrothersSaveReqVO.PartitionBrothersSaveReqVOBuilder addBrotherEmpty(PartitionBrothersSaveReqVO.PartitionBrothersSaveReqVOBuilder brotherBuilder, DuserDO duserDO) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return brotherBuilder.name(duserDO.getName())
 | 
	
		
			
				|  |  | +                .nickName(duserDO.getNickName())
 | 
	
		
			
				|  |  | +                .size(0)
 | 
	
		
			
				|  |  | +                .price(0)
 | 
	
		
			
				|  |  | +                .afterHitQuota(0)
 | 
	
		
			
				|  |  | +                .hasHit(0);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private PartitionSonSaveReqVO.PartitionSonSaveReqVOBuilder addSonEmpty(
 | 
	
		
			
				|  |  | +            PartitionSonSaveReqVO.PartitionSonSaveReqVOBuilder sonBuilder,
 | 
	
		
			
				|  |  | +            DuserDO duserDO) {
 | 
	
		
			
				|  |  | +        return sonBuilder.name(duserDO.getName())
 | 
	
		
			
				|  |  | +                .nickName(duserDO.getNickName())
 | 
	
		
			
				|  |  | +                .size(0)
 | 
	
		
			
				|  |  | +                .price(0)
 | 
	
		
			
				|  |  | +                .afterHitQuota(0)
 | 
	
		
			
				|  |  | +                .hasHit(0);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 创建编号 创建今天的编号
 | 
	
		
			
				|  |  | +    public String crashTodayNo(Long userId) {
 | 
	
		
			
				|  |  | +        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT); // 今天的开始时间,即午夜12点
 | 
	
		
			
				|  |  | +        String todayStartString = todayStart.toString();
 | 
	
		
			
				|  |  | +        return "CRASH:" + userId + todayStartString;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 获取昨天的编号
 | 
	
		
			
				|  |  | +    public String crashYesterdayNo(Long userId) {
 | 
	
		
			
				|  |  | +        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT); // 今天的开始时间,即午夜12点
 | 
	
		
			
				|  |  | +        LocalDateTime localDateTime = todayStart.minusDays(1);
 | 
	
		
			
				|  |  | +        String yesterdayString = localDateTime.toString();
 | 
	
		
			
				|  |  | +        return "CRASH:" + userId + yesterdayString;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }
 |