Pu Zhibing
5 天以前 ea1a62ba6484d6c6cb1ca67dcea938a95ba18fc6
ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/lottery/LotteryEventServiceImpl.java
@@ -1,10 +1,35 @@
package com.ruoyi.goods.service.impl.lottery;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.uuid.IdUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.goods.api.domain.LotteryEvent;
import com.ruoyi.goods.api.domain.LotteryEventPrize;
import com.ruoyi.goods.api.domain.UserLotteryEvent;
import com.ruoyi.goods.domain.vo.AppLotteryEventPageVo;
import com.ruoyi.goods.domain.vo.LotteryEventVo;
import com.ruoyi.goods.domain.vo.UserLotteryEventVo;
import com.ruoyi.goods.mapper.lottery.LotteryEventMapper;
import com.ruoyi.goods.service.lottery.ILotteryEventPrizeService;
import com.ruoyi.goods.service.lottery.ILotteryEventService;
import com.ruoyi.goods.service.lottery.IUserLotteryEventQuestionsAnswersService;
import com.ruoyi.goods.service.lottery.IUserLotteryEventService;
import com.ruoyi.system.api.service.RemoteCouponService;
import com.ruoyi.system.api.service.RemoteMemberService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
 * @author zhibing.pu
@@ -12,4 +37,149 @@
 */
@Service
public class LotteryEventServiceImpl extends ServiceImpl<LotteryEventMapper, LotteryEvent> implements ILotteryEventService {
   @Resource
   private IUserLotteryEventService userLotteryEventService;
   @Resource
   private ILotteryEventPrizeService lotteryEventPrizeService;
   @Resource
   private RemoteCouponService remoteCouponService;
   @Resource
   private RemoteMemberService remoteMemberService;
   @Resource
   private RedissonClient redissonClient;
   @Resource
   private IUserLotteryEventQuestionsAnswersService userLotteryEventQuestionsService;
   /**
    * 根据id查询抽奖活动信息
    *
    * @param id
    * @return
    */
   @Override
   public LotteryEventVo getLotteryEvent(String id) {
      LotteryEvent lotteryEvent = this.getById(id);
      //构建返回结果
      LotteryEventVo vo = new LotteryEventVo();
      vo.setId(lotteryEvent.getId());
      vo.setName(lotteryEvent.getName());
      vo.setActivityProfile(lotteryEvent.getActivityProfile());
      List<UserLotteryEvent> userLotteryEvents = userLotteryEventService.list(new QueryWrapper<UserLotteryEvent>().eq("lottery_event_id", id));
      vo.setLaveTimes(lotteryEvent.getTimes() - userLotteryEvents.size());
      //查询抽检活动奖品
      List<LotteryEventPrize> lotteryEventPrizeList = lotteryEventPrizeService.list(new QueryWrapper<LotteryEventPrize>().eq("lottery_event_id", id));
      vo.setPrizeList(lotteryEventPrizeList);
      //构建我的奖品明细
      List<UserLotteryEventVo> collect = userLotteryEvents.stream().map(s -> {
         UserLotteryEventVo userLotteryEventVo = new UserLotteryEventVo();
         userLotteryEventVo.setName(s.getObjectName());
         userLotteryEventVo.setPrizeType(s.getPrizeType());
         userLotteryEventVo.setNumber(s.getNumber());
         userLotteryEventVo.setVerifyCode(s.getVerifyCode());
         return userLotteryEventVo;
      }).collect(Collectors.toList());
      vo.setYourPrizeList(collect);
      return vo;
   }
   /**
    * 抽奖操作
    *
    * @param id
    * @return
    */
   @Override
   public R lotteryDraw(String id) {
      Long userId = SecurityUtils.getUserId();
      LotteryEvent lotteryEvent = this.getById(id);
      //判断答题抽奖是否满足抽奖条件
      if (lotteryEvent.getActivityType() == 5) {
         BigDecimal correctAnswerRate = userLotteryEventQuestionsService.getCorrectAnswerRate(userId, id);
         if (correctAnswerRate.compareTo(lotteryEvent.getAccuracy()) < 0) {
            return R.fail("答题抽奖失败,答题正确率低于活动要求");
         }
      }
      //使用redis锁处理高并发
      RLock lock = redissonClient.getLock("lottery_event::" + userId + "::" + id);
      try {
         boolean tryLock = lock.tryLock(30, TimeUnit.SECONDS);
         if (tryLock) {
            //判断抽奖次数是否用完
            int count = userLotteryEventService.count(new QueryWrapper<UserLotteryEvent>().eq("lottery_event_id", id).eq("user_id", userId));
            if (lotteryEvent.getTimes() <= count) {
               return R.fail("抽奖次数已用完");
            }
            List<LotteryEventPrize> lotteryEventPrizeList = lotteryEventPrizeService.list(new QueryWrapper<LotteryEventPrize>().eq("lottery_event_id", id));
            //开始抽奖,根据中奖概率来抽奖
            List<LotteryEventPrize> list = new ArrayList<>();
            for (LotteryEventPrize lotteryEventPrize : lotteryEventPrizeList) {
               int winRate = lotteryEventPrize.getWinRate().intValue();
               for (int i = 0; i < winRate; i++) {
                  LotteryEventPrize event = new LotteryEventPrize();
                  BeanUtil.copyProperties(lotteryEventPrize, event);
                  list.add(event);
               }
            }
            //将待抽奖的集合进行随机排序
            Collections.shuffle(list);
            //开始获取随机数
            int random = new Random().nextInt(list.size());
            LotteryEventPrize lotteryEventPrize = lotteryEventPrizeList.get(random);
            //添加中奖商品
            UserLotteryEvent userLotteryEvent = new UserLotteryEvent();
            userLotteryEvent.setId(IdUtils.simpleUUID());
            userLotteryEvent.setUserId(userId);
            userLotteryEvent.setLotteryEventId(id);
            userLotteryEvent.setLotteryEventPrizeId(lotteryEventPrize.getId());
            userLotteryEvent.setPrizeType(lotteryEventPrize.getPrizeType());
            userLotteryEvent.setObjectId(lotteryEventPrize.getObjectId());
            userLotteryEvent.setObjectName(lotteryEventPrize.getObjectName());
            userLotteryEvent.setNumber(lotteryEventPrize.getNumber());
            //商品需要生成核销码和核销状态
            if (Arrays.asList(2, 3).contains(lotteryEventPrize.getPrizeType())) {
               userLotteryEvent.setVerifyCode(IdUtils.simpleUUID());
               userLotteryEvent.setIsVerify(0);
            }
            //中奖优惠券
            if (1 == lotteryEventPrize.getPrizeType()) {
               remoteCouponService.addMemberCoupon(lotteryEventPrize.getObjectId(), lotteryEventPrize.getNumber(), userId);
            }
            //中奖积分
            if (4 == lotteryEventPrize.getPrizeType()) {
               remoteMemberService.addIntegralRecord(lotteryEventPrize.getNumber(), userId, id);
            }
            userLotteryEvent.setCreateTime(LocalDateTime.now());
            userLotteryEventService.save(userLotteryEvent);
            return R.ok();
         }
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         lock.unlock();
      }
      return R.fail("抽奖失败");
   }
   /**
    * 获取APP抽奖列表
    *
    * @param page
    * @param userId
    * @return
    */
   @Override
   public List<AppLotteryEventPageVo> pageAppLotteryEvent(Page<AppLotteryEventPageVo> page, Long userId) {
      return this.baseMapper.pageAppLotteryEvent(page, userId);
   }
}