| package cc.mrbird.febs.vip.service.impl; | 
|   | 
| import cc.mrbird.febs.common.enumerates.FlowTypeEnum; | 
| import cc.mrbird.febs.common.enumerates.ScoreFlowTypeEnum; | 
| import cc.mrbird.febs.mall.entity.*; | 
| import cc.mrbird.febs.mall.mapper.MallMemberMapper; | 
| import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; | 
| import cc.mrbird.febs.mall.mapper.MallOrderItemMapper; | 
| import cc.mrbird.febs.mall.service.IApiMallGoodsService; | 
| import cc.mrbird.febs.mall.service.IApiMallMemberWalletService; | 
| import cc.mrbird.febs.mall.service.IMallMoneyFlowService; | 
| import cc.mrbird.febs.rabbit.producter.AgentProducer; | 
| import cc.mrbird.febs.vip.entity.MallVipBenefits; | 
| import cc.mrbird.febs.vip.entity.MallVipConfig; | 
| import cc.mrbird.febs.vip.mapper.MallVipConfigMapper; | 
| import cc.mrbird.febs.vip.service.IMallVipConfigService; | 
| import cc.mrbird.febs.vip.service.IVipCommonService; | 
| import cn.hutool.core.collection.CollUtil; | 
| import cn.hutool.core.date.DateUtil; | 
| import cn.hutool.core.util.ObjectUtil; | 
| import cn.hutool.core.util.StrUtil; | 
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
| import lombok.RequiredArgsConstructor; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.stereotype.Service; | 
| import org.springframework.transaction.annotation.Transactional; | 
|   | 
| import java.math.BigDecimal; | 
| import java.math.RoundingMode; | 
| import java.util.*; | 
| import java.util.stream.Collectors; | 
|   | 
| @Slf4j | 
| @Service | 
| @RequiredArgsConstructor | 
| public class VipCommonServiceImpl implements IVipCommonService { | 
|   | 
|     private final MallOrderInfoMapper mallOrderInfoMapper; | 
|     private final IMallVipConfigService mallVipConfigService; | 
|     private final IMallMoneyFlowService mallMoneyFlowService; | 
|     private final IApiMallMemberWalletService mallMemberWalletService; | 
|     private final MallMemberMapper mallMemberMapper; | 
|     private final MallVipConfigMapper mallVipConfigMapper; | 
|     private final AgentProducer agentProducer; | 
|     private final IApiMallGoodsService mallGoodsService; | 
|     private final MallOrderItemMapper mallOrderItemMapper; | 
|   | 
|     @Override | 
|     @Transactional(rollbackFor = Exception.class) | 
|     public void getScore(Long orderId) { | 
| //        MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderDetailsById(orderId); | 
|   | 
|         MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectById(orderId); | 
|         List<MallOrderItem> mallOrderItemList = mallOrderItemMapper.selectListByOrderId(mallOrderInfo.getId()); | 
|         mallOrderInfo.setItems(mallOrderItemList); | 
|   | 
|         if (mallOrderInfo == null) { | 
|             return; | 
|         } | 
|   | 
|         Long memberId = mallOrderInfo.getMemberId(); | 
|         MallVipBenefits mallVipBenefits = mallVipConfigService.hasVipBenefits(memberId); | 
|   | 
|         MallMember member = mallMemberMapper.selectById(memberId); | 
|         BigDecimal multiple = BigDecimal.ONE; | 
|         String name = ""; | 
|         if (mallVipBenefits != null) { | 
|             multiple = mallVipBenefits.getScoreMultiple(); | 
|             name = mallVipBenefits.getName(); | 
|         } | 
|   | 
|         List<String> skuNames = mallOrderInfo.getItems().stream().map(MallOrderItem::getSkuName).collect(Collectors.toList()); | 
| //        double sum = mallOrderInfo.getItems().stream().map(MallOrderItem::getAmount).mapToDouble(BigDecimal::doubleValue).sum(); | 
|         BigDecimal sum = mallOrderInfo.getItems().stream().map(MallOrderItem::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); | 
|   | 
|         int score = multiple.multiply(sum).intValue(); | 
|   | 
|         log.info("会员:{},购买商品:{},购买金额:{},会员等级:{},会员等级名称:{},会员等级积分倍数:{},会员获得积分:{}", | 
|                 member.getName(), | 
|                 skuNames, | 
|                 sum, | 
|                 member.getLevel(), | 
|                 name, | 
|                 multiple, | 
|                 score); | 
|         mallMoneyFlowService.addMoneyFlow(memberId, new BigDecimal(score), ScoreFlowTypeEnum.BUY.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), CollUtil.join(skuNames, ","), 2); | 
|         mallMemberWalletService.add(new BigDecimal(score), memberId, "prizeScore"); | 
|   | 
|         List<Long> itemGoodsIds = mallOrderInfo.getItems().stream().map(MallOrderItem::getGoodsId).distinct().collect(Collectors.toList()); | 
|         List<MallGoods> goodsList = mallGoodsService.listByIds(itemGoodsIds); | 
|         Map<Long, MallGoods> goodsMap = goodsList.stream() | 
|                 .filter( | 
|                         goods -> ObjectUtil.isNotEmpty(goods.getStaticMulti()) | 
|                 ) | 
|                 .collect(Collectors.toMap(MallGoods::getId, MallGoods -> MallGoods)); | 
|   | 
|         Map<Long, BigDecimal> recommendScoreMap = new HashMap<>(); | 
|         mallOrderInfo.getItems().forEach(item -> { | 
|             if (StrUtil.isNotBlank(item.getMemberInviteId()) && !member.getInviteId().equals(item.getMemberInviteId())) { | 
|                 MallGoods mallGoods = goodsMap.get(item.getGoodsId()); | 
|                 if (ObjectUtil.isEmpty(mallGoods)) { | 
|                     return; | 
|                 } | 
|   | 
|                 BigDecimal multi = mallGoods.getStaticMulti().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); | 
|                 MallMember mallMember = mallMemberMapper.selectInfoByInviteId(item.getMemberInviteId()); | 
|                 if (mallMember == null) { | 
|                     return; | 
|                 } | 
|   | 
|                 BigDecimal recommendScore = recommendScoreMap.get(mallMember.getId()); | 
|                 recommendScore = recommendScore == null ? BigDecimal.ZERO : recommendScore; | 
|                 recommendScore = recommendScore.add(item.getAmount().multiply(multi)); | 
|   | 
|                 recommendScoreMap.put(mallMember.getId(), recommendScore); | 
|             } | 
|         }); | 
|   | 
|         recommendScoreMap.forEach((key, value) -> { | 
|             if (value != null) { | 
|                 mallMoneyFlowService.addMoneyFlow(key, value, ScoreFlowTypeEnum.RECOMMEND.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), CollUtil.join(skuNames, ","), 2); | 
|                 mallMemberWalletService.add(value, key, "prizeScore"); | 
|             } | 
|         }); | 
|   | 
|     } | 
|   | 
|     @Override | 
|     public void levelUp(Long orderId) { | 
|         MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderDetailsById(orderId); | 
|         if (mallOrderInfo == null) { | 
|             return; | 
|         } | 
|   | 
|         MallMember member = mallMemberMapper.selectById(mallOrderInfo.getMemberId()); | 
|         if (member == null) { | 
|             log.info("会员不存在"); | 
|             return; | 
|         } | 
|   | 
|         MallVipConfig config = mallVipConfigMapper.selectVipConfigByCode(member.getLevel()); | 
|         if (config == null) { | 
|             log.info("会员等级配置不存在"); | 
|             return; | 
|         } | 
|   | 
| //        LambdaQueryWrapper<MallVipConfig> configQuery = new LambdaQueryWrapper<>(); | 
| //        configQuery.gt(MallVipConfig::getLevel, config.getLevel()) | 
| //                .orderByAsc(MallVipConfig::getLevel) | 
| //                .last("limit 1"); | 
| //        MallVipConfig nextLevel = mallVipConfigMapper.selectOne(configQuery); | 
|   | 
|         List<MallVipConfig> configs = mallVipConfigMapper.selectVipConfigList(); | 
|   | 
|         String nextLevelCode = ""; | 
|         for (MallVipConfig nextLevel : configs) { | 
|             if (config.getLevel() >= nextLevel.getLevel()) { | 
|                 continue; | 
|             } | 
|   | 
|             // 指定商品 | 
|             if (nextLevel.getType() == 1) { | 
|                 boolean hasMatch = mallOrderInfo.getItems().stream().anyMatch(item -> { | 
|                     return item.getGoodsId().equals(nextLevel.getTargetId()); | 
|                 }); | 
|   | 
|                 if (hasMatch) { | 
|                     nextLevelCode = nextLevel.getCode(); | 
|                     continue; | 
|                 } | 
|             } | 
|   | 
|             // 时间区间内金额 | 
|             if (nextLevel.getType() == 2) { | 
|                 Date endTime = DateUtil.endOfDay(new Date()); | 
|                 Date startTime = getStartTime(nextLevel.getValidType()); | 
|   | 
|                 LambdaQueryWrapper<MallOrderInfo> query = new LambdaQueryWrapper<>(); | 
|                 query.ge(MallOrderInfo::getReceivingTime, startTime) | 
|                         .le(MallOrderInfo::getReceivingTime, endTime) | 
|                         .eq(MallOrderInfo::getStatus, 4) | 
|                         .eq(MallOrderInfo::getMemberId, member.getId()); | 
|                 List<MallOrderInfo> orderList = mallOrderInfoMapper.selectList(query); | 
|                 if (CollUtil.isEmpty(orderList)) { | 
|                     continue; | 
|                 } | 
|   | 
|                 double totalAmount = orderList.stream().mapToDouble(item -> { | 
|                     return item.getAmount().doubleValue(); | 
|                 }).sum(); | 
|   | 
|                 if (nextLevel.getAmount().compareTo(BigDecimal.valueOf(totalAmount)) <= 0) { | 
|                     nextLevelCode = nextLevel.getCode(); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         if (StrUtil.isNotBlank(nextLevelCode)) { | 
|             MallMember update = new MallMember(); | 
|             update.setId(member.getId()); | 
|             update.setLevel(nextLevelCode); | 
|             update.setVipLevelTime(new Date()); | 
|             mallMemberMapper.updateById(update); | 
|         } | 
|     } | 
|   | 
|     private Date getStartTime(String type) { | 
|         Date date = new Date(); | 
|         switch (type) { | 
|             case "day" : | 
|                 return DateUtil.beginOfDay(date); | 
|             case "month": | 
|                 return DateUtil.beginOfMonth(date); | 
|             case "year": | 
|                 return DateUtil.beginOfYear(date); | 
|             default: | 
|                 return date; | 
|         } | 
|     } | 
| } |