Commit e19e942a by 吕明尚

增加抽奖接口

parent e5d6e325
...@@ -46,6 +46,9 @@ public class Constants ...@@ -46,6 +46,9 @@ public class Constants
/** 订单支付成功后Task */ /** 订单支付成功后Task */
public static final String ORDER_TASK_PAY_SUCCESS_AFTER = "orderPaySuccessTask"; public static final String ORDER_TASK_PAY_SUCCESS_AFTER = "orderPaySuccessTask";
//抽奖锁定key
public static final String LOTTERY_LOCK_KEY = "lottery_lock_key";
//订单操作redis队列 //订单操作redis队列
public static final String ORDER_TASK_REDIS_KEY_AFTER_DELETE_BY_USER = "alterOrderDeleteByUser"; // 用户删除订单后续操作 public static final String ORDER_TASK_REDIS_KEY_AFTER_DELETE_BY_USER = "alterOrderDeleteByUser"; // 用户删除订单后续操作
......
...@@ -7,29 +7,38 @@ public enum PrizeTypeEnum { ...@@ -7,29 +7,38 @@ public enum PrizeTypeEnum {
INTEGRAL(3, "积分"), INTEGRAL(3, "积分"),
THANK(4, "谢谢参与"); THANK(4, "谢谢参与");
private Integer index; private Integer code;
private String name; private String name;
PrizeTypeEnum() { PrizeTypeEnum() {
} }
PrizeTypeEnum(Integer index, String name) { PrizeTypeEnum(Integer code, String name) {
this.index = index; this.code = code;
this.name = name; this.name = name;
} }
public Integer getIndex() { public static PrizeTypeEnum getTypeCode(Integer code) {
return index; for (PrizeTypeEnum type : PrizeTypeEnum.values()) {
if (type.getCode().equals(code)) {
return type;
}
}
return null;
} }
public void setIndex(Integer index) { public Integer getCode() {
this.index = index; return code;
} }
public String getName() { public String getName() {
return name; return name;
} }
public void setCode(Integer code) {
this.code = code;
}
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
......
package share.web.controller.system; package share.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import share.common.annotation.Log; import share.common.annotation.Log;
import share.common.core.controller.BaseController; import share.common.core.controller.BaseController;
...@@ -30,7 +29,6 @@ public class WheelGameController extends BaseController { ...@@ -30,7 +29,6 @@ public class WheelGameController extends BaseController {
/** /**
* 查询转盘游戏列表 * 查询转盘游戏列表
*/ */
@PreAuthorize("@ss.hasPermi('system:wheelGame:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(WheelGame wheelGame) { public TableDataInfo list(WheelGame wheelGame) {
startPage(); startPage();
...@@ -41,7 +39,6 @@ public class WheelGameController extends BaseController { ...@@ -41,7 +39,6 @@ public class WheelGameController extends BaseController {
/** /**
* 导出转盘游戏列表 * 导出转盘游戏列表
*/ */
@PreAuthorize("@ss.hasPermi('system:wheelGame:export')")
@Log(title = "转盘游戏", businessType = BusinessType.EXPORT) @Log(title = "转盘游戏", businessType = BusinessType.EXPORT)
@PostMapping("/export") @PostMapping("/export")
public void export(HttpServletResponse response, WheelGame wheelGame) { public void export(HttpServletResponse response, WheelGame wheelGame) {
...@@ -53,7 +50,6 @@ public class WheelGameController extends BaseController { ...@@ -53,7 +50,6 @@ public class WheelGameController extends BaseController {
/** /**
* 获取转盘游戏详细信息 * 获取转盘游戏详细信息
*/ */
@PreAuthorize("@ss.hasPermi('system:wheelGame:query')")
@GetMapping(value = "/{id}") @GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) { public AjaxResult getInfo(@PathVariable("id") Long id) {
return success(wheelGameService.selectWheelGameById(id)); return success(wheelGameService.selectWheelGameById(id));
...@@ -62,7 +58,6 @@ public class WheelGameController extends BaseController { ...@@ -62,7 +58,6 @@ public class WheelGameController extends BaseController {
/** /**
* 新增转盘游戏 * 新增转盘游戏
*/ */
@PreAuthorize("@ss.hasPermi('system:wheelGame:add')")
@Log(title = "转盘游戏", businessType = BusinessType.INSERT) @Log(title = "转盘游戏", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@RequestBody WheelGame wheelGame) { public AjaxResult add(@RequestBody WheelGame wheelGame) {
...@@ -72,7 +67,6 @@ public class WheelGameController extends BaseController { ...@@ -72,7 +67,6 @@ public class WheelGameController extends BaseController {
/** /**
* 修改转盘游戏 * 修改转盘游戏
*/ */
@PreAuthorize("@ss.hasPermi('system:wheelGame:edit')")
@Log(title = "转盘游戏", businessType = BusinessType.UPDATE) @Log(title = "转盘游戏", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@RequestBody WheelGame wheelGame) { public AjaxResult edit(@RequestBody WheelGame wheelGame) {
...@@ -82,10 +76,15 @@ public class WheelGameController extends BaseController { ...@@ -82,10 +76,15 @@ public class WheelGameController extends BaseController {
/** /**
* 删除转盘游戏 * 删除转盘游戏
*/ */
@PreAuthorize("@ss.hasPermi('system:wheelGame:remove')")
@Log(title = "转盘游戏", businessType = BusinessType.DELETE) @Log(title = "转盘游戏", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}") @DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) { public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(wheelGameService.deleteWheelGameByIds(ids)); return toAjax(wheelGameService.deleteWheelGameByIds(ids));
} }
//抽奖接口
@PostMapping("/draw")
public AjaxResult draw(@RequestBody WheelGame wheelGame) {
return success(wheelGameService.draw(wheelGame));
}
} }
...@@ -155,7 +155,6 @@ public class RedisTask { ...@@ -155,7 +155,6 @@ public class RedisTask {
wrapper.isNotNull(SConsumerCoupon::getCouponCode); wrapper.isNotNull(SConsumerCoupon::getCouponCode);
List<SConsumerCoupon> coupons = isConsumerCouponService.list(wrapper); List<SConsumerCoupon> coupons = isConsumerCouponService.list(wrapper);
List<SStore> stores = storeService.list(); List<SStore> stores = storeService.list();
List<Long> expiredCoupons = new ArrayList<>(); List<Long> expiredCoupons = new ArrayList<>();
if (!CollectionUtils.isEmpty(coupons)) { if (!CollectionUtils.isEmpty(coupons)) {
for (SConsumerCoupon coupon : coupons) { for (SConsumerCoupon coupon : coupons) {
......
...@@ -61,7 +61,7 @@ public class LotteryRecordsLog extends BaseEntity { ...@@ -61,7 +61,7 @@ public class LotteryRecordsLog extends BaseEntity {
* 是否中奖 0:未中奖 1:中奖 * 是否中奖 0:未中奖 1:中奖
*/ */
@Excel(name = "是否中奖 0:未中奖 1:中奖") @Excel(name = "是否中奖 0:未中奖 1:中奖")
private Long isHit; private Integer isHit;
/** /**
* 中奖奖品 * 中奖奖品
...@@ -73,7 +73,7 @@ public class LotteryRecordsLog extends BaseEntity { ...@@ -73,7 +73,7 @@ public class LotteryRecordsLog extends BaseEntity {
* 是否发放 1未发放,2 已发放 3 发放失败 * 是否发放 1未发放,2 已发放 3 发放失败
*/ */
@Excel(name = " 是否发放 1未发放,2 已发放 3 发放失败") @Excel(name = " 是否发放 1未发放,2 已发放 3 发放失败")
private Long isSend; private Integer isSend;
/** /**
* 发放结果 * 发放结果
......
...@@ -7,8 +7,6 @@ import org.apache.commons.lang3.builder.ToStringStyle; ...@@ -7,8 +7,6 @@ import org.apache.commons.lang3.builder.ToStringStyle;
import share.common.annotation.Excel; import share.common.annotation.Excel;
import share.common.core.domain.BaseEntity; import share.common.core.domain.BaseEntity;
import java.math.BigDecimal;
/** /**
* 奖品对象 s_prize * 奖品对象 s_prize
* *
...@@ -71,7 +69,7 @@ public class Prize extends BaseEntity { ...@@ -71,7 +69,7 @@ public class Prize extends BaseEntity {
* 中奖几率 * 中奖几率
*/ */
@Excel(name = "中奖几率") @Excel(name = "中奖几率")
private BigDecimal ratio; private Double ratio;
@Override @Override
...@@ -82,8 +80,8 @@ public class Prize extends BaseEntity { ...@@ -82,8 +80,8 @@ public class Prize extends BaseEntity {
.append("prizeType", getPrizeType()) .append("prizeType", getPrizeType())
.append("prizeName", getPrizeName()) .append("prizeName", getPrizeName())
.append("prizeValue", getPrizeValue()) .append("prizeValue", getPrizeValue())
.append("currentNum", getCurrentNum()) // .append("currentNum", getCurrentNum())
.append("maxNum", getMaxNum()) // .append("maxNum", getMaxNum())
.append("ratio", getRatio()) .append("ratio", getRatio())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())
.append("createTime", getCreateTime()) .append("createTime", getCreateTime())
......
...@@ -74,7 +74,7 @@ public interface ISConsumerCouponService extends IService<SConsumerCoupon> ...@@ -74,7 +74,7 @@ public interface ISConsumerCouponService extends IService<SConsumerCoupon>
List<SConsumerCouponVo> availableCouponList(CouponRequest couponRequest); List<SConsumerCouponVo> availableCouponList(CouponRequest couponRequest);
int give(SConsumerCoupon sConsumerCoupon); SConsumerCoupon give(SConsumerCoupon sConsumerCoupon);
public Integer give(Long consumerId, Long couponId, Integer giveDay); public Integer give(Long consumerId, Long couponId, Integer giveDay);
......
...@@ -59,4 +59,6 @@ public interface WheelGameService extends IService<WheelGame> { ...@@ -59,4 +59,6 @@ public interface WheelGameService extends IService<WheelGame> {
* @return 结果 * @return 结果
*/ */
public int deleteWheelGameById(Long id); public int deleteWheelGameById(Long id);
String draw(WheelGame wheelGame);
} }
...@@ -496,11 +496,11 @@ public class SConsumerCouponServiceImpl extends ServiceImpl<SConsumerCouponMappe ...@@ -496,11 +496,11 @@ public class SConsumerCouponServiceImpl extends ServiceImpl<SConsumerCouponMappe
} }
@Override @Override
public int give(SConsumerCoupon sConsumerCoupon) { public SConsumerCoupon give(SConsumerCoupon sConsumerCoupon) {
//根据优惠券id查询优惠券信息 //根据优惠券id查询优惠券信息
SCoupon sCoupon = sCouponService.selectSCouponById(sConsumerCoupon.getCouponId()); SCoupon sCoupon = sCouponService.selectSCouponById(sConsumerCoupon.getCouponId());
if (ObjectUtils.isEmpty(sCoupon)) { if (ObjectUtils.isEmpty(sCoupon)) {
return 0; return new SConsumerCoupon();
} }
if (sCoupon.getNumber().equals(ZERO)) { if (sCoupon.getNumber().equals(ZERO)) {
throw new RuntimeException("优惠券数量为0"); throw new RuntimeException("优惠券数量为0");
...@@ -546,7 +546,7 @@ public class SConsumerCouponServiceImpl extends ServiceImpl<SConsumerCouponMappe ...@@ -546,7 +546,7 @@ public class SConsumerCouponServiceImpl extends ServiceImpl<SConsumerCouponMappe
sCoupon.setNumber(sCoupon.getNumber() - 1); sCoupon.setNumber(sCoupon.getNumber() - 1);
sCouponService.updateById(sCoupon); sCouponService.updateById(sCoupon);
} }
return insert; return newSConsumerCoupon;
} }
@Override @Override
......
package share.system.service.impl; package share.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import share.common.constant.Constants;
import share.common.core.redis.RedisUtil;
import share.common.enums.PrizeTypeEnum;
import share.common.enums.YesNoEnum;
import share.common.exception.base.BaseException;
import share.common.utils.DateUtils; import share.common.utils.DateUtils;
import share.system.domain.WheelGame; import share.system.domain.*;
import share.system.domain.vo.FrontTokenComponent;
import share.system.mapper.WheelGameMapper; import share.system.mapper.WheelGameMapper;
import share.system.service.ISConsumerCouponService;
import share.system.service.LotteryRecordsLogService;
import share.system.service.PrizeService;
import share.system.service.WheelGameService; import share.system.service.WheelGameService;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
/** /**
* 转盘游戏Service业务层处理 * 转盘游戏Service业务层处理
...@@ -18,8 +37,17 @@ import java.util.List; ...@@ -18,8 +37,17 @@ import java.util.List;
*/ */
@Service @Service
public class WheelGameServiceImpl extends ServiceImpl<WheelGameMapper, WheelGame> implements WheelGameService { public class WheelGameServiceImpl extends ServiceImpl<WheelGameMapper, WheelGame> implements WheelGameService {
private static final Logger logger = LoggerFactory.getLogger(WheelGameServiceImpl.class);
@Autowired @Autowired
private WheelGameMapper wheelGameMapper; private WheelGameMapper wheelGameMapper;
@Autowired
private PrizeService prizeService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private ISConsumerCouponService sConsumerCouponService;
@Autowired
private LotteryRecordsLogService lotteryRecordsLogService;
/** /**
* 查询转盘游戏 * 查询转盘游戏
...@@ -88,4 +116,157 @@ public class WheelGameServiceImpl extends ServiceImpl<WheelGameMapper, WheelGame ...@@ -88,4 +116,157 @@ public class WheelGameServiceImpl extends ServiceImpl<WheelGameMapper, WheelGame
public int deleteWheelGameById(Long id) { public int deleteWheelGameById(Long id) {
return wheelGameMapper.deleteWheelGameById(id); return wheelGameMapper.deleteWheelGameById(id);
} }
@Override
public String draw(WheelGame wheelGame) {
if (wheelGame == null || wheelGame.getId() == null) {
throw new IllegalArgumentException("无效的游戏对象或游戏ID为空");
}
SConsumer user = FrontTokenComponent.getWxSConsumerEntry();
if (ObjectUtil.isNull(user)) {
throw new BaseException("您的登录已过期,请先登录");
}
if (Objects.equals(user.getPrizeDrawNumbr(), YesNoEnum.no.getIndex())) {
throw new BaseException("用户抽奖次数为0,请联系客服");
}
List<Prize> prizeList = prizeService.list(new LambdaQueryWrapper<Prize>().eq(Prize::getGameId, wheelGame.getId()));
Prize prize = luckDraw(prizeList, wheelGame.getId());
LotteryRecordsLog log = new LotteryRecordsLog();
log.setGameId(wheelGame.getId());
log.setUserId(user.getId());
log.setUserName(user.getNickName());
log.setPhone(user.getPhone());
log.setDrawTime(DateUtils.getNowDate());
if (ObjectUtil.isNotEmpty(prize)) {
PrizeTypeEnum couponType = PrizeTypeEnum.getTypeCode(prize.getPrizeType());
try {
switch (couponType) {
case COUPON:
SConsumerCoupon sConsumerCoupon = new SConsumerCoupon();
sConsumerCoupon.setConsumerId(user.getId());
sConsumerCoupon.setCouponId(prize.getCouponId());
SConsumerCoupon give = sConsumerCouponService.give(sConsumerCoupon);
log.setIsHit(YesNoEnum.yes.getIndex());
log.setIsSend(YesNoEnum.yes.getIndex());
log.setHitPrize(prize.getPrizeName() + ":" + give.getName());
log.setSendMsg(PrizeTypeEnum.COUPON.getName() + ":" + give.getName() + "以发放");
lotteryRecordsLogService.save(log);
break;
case GOODS:
log.setIsHit(YesNoEnum.yes.getIndex());
log.setIsSend(YesNoEnum.yes.getIndex());
log.setHitPrize(PrizeTypeEnum.GOODS.getName() + ":" + prize.getPrizeName());
log.setSendMsg(PrizeTypeEnum.GOODS.getName() + ":" + prize.getPrizeName() + "以发放");
lotteryRecordsLogService.save(log);
break;
case INTEGRAL:
log.setIsHit(YesNoEnum.yes.getIndex());
log.setIsSend(YesNoEnum.yes.getIndex());
log.setHitPrize(PrizeTypeEnum.INTEGRAL.getName());
log.setSendMsg(prize.getPrizeValue() + ":" + PrizeTypeEnum.INTEGRAL.getName() + "以发放");
lotteryRecordsLogService.save(log);
break;
case THANK:
log.setIsHit(YesNoEnum.no.getIndex());
log.setIsSend(YesNoEnum.no.getIndex());
log.setHitPrize("谢谢参与");
log.setSendMsg("谢谢参与");
lotteryRecordsLogService.save(log);
break;
default:
throw new BaseException("奖品类型异常");
}
} catch (BaseException be) {
logger.error("抽奖过程中发生业务异常: {}", be.getMessage(), be);
throw be;
} catch (Exception e) {
logger.error("抽奖过程中发生未知异常: {}", e.getMessage(), e);
throw new RuntimeException(e);
}
} else {
log.setIsHit(YesNoEnum.no.getIndex());
log.setIsSend(YesNoEnum.no.getIndex());
log.setHitPrize("谢谢参与");
log.setSendMsg("谢谢参与");
lotteryRecordsLogService.save(log);
return "谢谢参与";
}
return null;
}
private Prize luckDraw(List<Prize> prizeList, Long gameId) {
// 奖品列表中的概率为累加概率
// 需要按照添加进列表的顺序进行累加,为了数据处理方便中奖几率*100
String lockResult = "";
try {
lockResult = lockGame(gameId);
double sum = 0;
List<Prize> newList = new ArrayList<>();
for (int i = 0; i < prizeList.size(); i++) {
Prize entity = prizeList.get(i);
Prize newEntity = new Prize();
BeanUtils.copyProperties(entity, newEntity);
sum = sum + (entity.getRatio() * 100);
newEntity.setRatio(sum);
newList.add(newEntity);
}
// 生成一个随机数
Random random = new Random();
Double userSelect = random.nextDouble() * 10000;
for (Prize prize : prizeList) {
// 随机数小于中奖几率,则中奖
if (userSelect < prize.getRatio()) {
// 最大中奖数(0:代表不限制次数)
int maxNum = prize.getMaxNum();
// 判断游戏奖品当前中奖数及最大中奖数
if (maxNum != 0 && maxNum <= prize.getCurrentNum()) {
// 超过最大中奖数则不中
break;
} else {
return prize;
}
}
}
// 谢谢参与
List<Prize> prize = prizeList.stream().filter(item -> item.getPrizeType() == 4).collect(Collectors.toList());
if (prize.size() > 0) {
return prize.get(0);
}
return null;
} catch (BaseException e) {
throw e;
} finally {
unLockGame(gameId, lockResult);
}
}
private String lockGame(Long gameId) throws BaseException {
try {
//自旋10次,每次等待1秒
String lockResult = "";
for (int i = 0; i < 10; i++) {
lockResult = redisUtil.lockWithTimeout(Constants.LOTTERY_LOCK_KEY + gameId, 11, 2);
if (StringUtils.isBlank(lockResult)) {
Thread.sleep(1000L);
} else {
break;
}
}
return lockResult;
} catch (Exception e) {
throw new BaseException("当前抽奖太火爆了,请稍后再试!");
}
}
private void unLockGame(Long gameId, String keyValue) {
if (StringUtils.isNotBlank(keyValue)) {
redisUtil.unLock(Constants.LOTTERY_LOCK_KEY + gameId, keyValue, 2);
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment