记得上下班打卡 | git大法好,push需谨慎

Commit cba45393 authored by wangyifan's avatar wangyifan

福袋功能-分配兑换码

parent 07c1a26c
...@@ -126,4 +126,6 @@ public class KylinRedisConst { ...@@ -126,4 +126,6 @@ public class KylinRedisConst {
// 福袋活动 // 福袋活动
public static final String LUCKY_BAG_ACTIVITY = "kylin:luckybag:activity"; public static final String LUCKY_BAG_ACTIVITY = "kylin:luckybag:activity";
public static final String LUCKY_BAG = "kylin:luckybag"; public static final String LUCKY_BAG = "kylin:luckybag";
public static final String LUCKY_BAG_CODE_LOCK = "kylin:luckybag:code:lock:";
} }
...@@ -3,5 +3,5 @@ package com.liquidnet.service.kylin.service; ...@@ -3,5 +3,5 @@ package com.liquidnet.service.kylin.service;
import com.liquidnet.service.kylin.dto.vo.KylinLuckyBagVo; import com.liquidnet.service.kylin.dto.vo.KylinLuckyBagVo;
public interface IKylinLuckyBagService { public interface IKylinLuckyBagService {
KylinLuckyBagVo getLuckyBagBenefitsByOrderId(String orderId); KylinLuckyBagVo getLuckyBagByOrderId(String orderId);
} }
...@@ -68,16 +68,6 @@ public class KylinLuckyBag implements Serializable, Cloneable{ ...@@ -68,16 +68,6 @@ public class KylinLuckyBag implements Serializable, Cloneable{
*/ */
private String sendTime; private String sendTime;
/**
* 福袋发放数量
*/
private Integer sendTotal;
/**
* 发放状态: 0:未解锁 1:已解锁
*/
private Integer sendState;
/** /**
* 创建时间 * 创建时间
*/ */
......
package com.liquidnet.service.kylin.controller; package com.liquidnet.service.kylin.controller;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.dto.vo.KylinLuckyBagVo; import com.liquidnet.service.kylin.dto.vo.KylinLuckyBagVo;
import com.liquidnet.service.kylin.service.IKylinLuckyBagService; import com.liquidnet.service.kylin.service.IKylinLuckyBagService;
...@@ -13,8 +12,6 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -13,8 +12,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Api(tags = "前端-获取福袋相关") @Api(tags = "前端-获取福袋相关")
@RestController @RestController
@RequestMapping("/luckyBag") @RequestMapping("/luckyBag")
...@@ -27,7 +24,7 @@ public class KylinLuckyBagController { ...@@ -27,7 +24,7 @@ public class KylinLuckyBagController {
@GetMapping("") @GetMapping("")
@ApiOperation("获取福袋权益列表") @ApiOperation("获取福袋权益列表")
public ResponseDto<KylinLuckyBagVo> getLuckyBagBenefitsByOrderId(@RequestParam(value = "orderId") String orderId) { public ResponseDto<KylinLuckyBagVo> getLuckyBagByOrderId(@RequestParam(value = "orderId") String orderId) {
return ResponseDto.success(benefitsService.getLuckyBagBenefitsByOrderId(orderId)); return ResponseDto.success(benefitsService.getLuckyBagByOrderId(orderId));
} }
} }
package com.liquidnet.service.kylin.service.impl; package com.liquidnet.service.kylin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.common.exception.LiquidnetServiceException; import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.CurrentUtil; import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.base.ErrorMapping; import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.dto.vo.KylinLuckyBagVo; import com.liquidnet.service.kylin.dto.vo.KylinLuckyBagVo;
import com.liquidnet.service.kylin.dto.vo.returns.OrderDetailsVo; import com.liquidnet.service.kylin.dto.vo.returns.OrderDetailsVo;
import com.liquidnet.service.kylin.entity.KylinLuckyBag; import com.liquidnet.service.kylin.entity.KylinLuckyBag;
import com.liquidnet.service.kylin.entity.KylinLuckyBagActivity; import com.liquidnet.service.kylin.entity.KylinLuckyBagActivity;
import com.liquidnet.service.kylin.entity.KylinRewardCode;
import com.liquidnet.service.kylin.entity.KylinRewardUser; import com.liquidnet.service.kylin.entity.KylinRewardUser;
import com.liquidnet.service.kylin.mapper.KylinBrandsMapper; import com.liquidnet.service.kylin.mapper.KylinBrandsMapper;
import com.liquidnet.service.kylin.mapper.KylinLuckyBagMapper; import com.liquidnet.service.kylin.mapper.KylinLuckyBagMapper;
import com.liquidnet.service.kylin.mapper.KylinRewardCodeMapper; import com.liquidnet.service.kylin.mapper.KylinRewardCodeMapper;
import com.liquidnet.service.kylin.mapper.KylinRewardUserMapper;
import com.liquidnet.service.kylin.service.IFeishuBotService; import com.liquidnet.service.kylin.service.IFeishuBotService;
import com.liquidnet.service.kylin.service.IKylinLuckyBagService; import com.liquidnet.service.kylin.service.IKylinLuckyBagService;
import com.liquidnet.service.kylin.service.IKylinOrderTicketsService; import com.liquidnet.service.kylin.service.IKylinOrderTicketsService;
...@@ -20,6 +27,7 @@ import org.slf4j.LoggerFactory; ...@@ -20,6 +27,7 @@ import org.slf4j.LoggerFactory;
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 java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
...@@ -33,6 +41,8 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService { ...@@ -33,6 +41,8 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService {
@Autowired @Autowired
private DataUtils dataUtils; private DataUtils dataUtils;
@Autowired
RedisUtil redisUtil;
@Autowired @Autowired
IKylinOrderTicketsService orderTicketsService; IKylinOrderTicketsService orderTicketsService;
...@@ -45,21 +55,24 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService { ...@@ -45,21 +55,24 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService {
private KylinBrandsMapper kylinBrandsMapper; private KylinBrandsMapper kylinBrandsMapper;
@Autowired @Autowired
private KylinRewardCodeMapper kylinRewardCodeMapper; private KylinRewardCodeMapper kylinRewardCodeMapper;
@Autowired
private KylinRewardUserMapper kylinRewardUserMapper;
@Override @Override
public KylinLuckyBagVo getLuckyBagBenefitsByOrderId(String orderId) { public KylinLuckyBagVo getLuckyBagByOrderId(String orderId) {
//1. 首先校验用户权限 //1. 首先校验用户权限
OrderDetailsVo vo = orderTicketsService.orderDetails(orderId); OrderDetailsVo vo = orderTicketsService.orderDetails(orderId);
String uid = CurrentUtil.getCurrentUid(); String uid = CurrentUtil.getCurrentUid();
if (null == vo) { if (null == vo) {
log.error("[getLuckyBagBenefitsByOrderId] 无权查看, orderId: {}, uid: {}.", orderId, uid); log.error("[getLuckyBagByOrderId] 无权查看该订单, orderId: {}, uid: {}.", orderId, uid);
ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("20003"); ErrorMapping.ErrorMessage errorMessage = ErrorMapping.get("20003");
throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage()); throw new LiquidnetServiceException(errorMessage.getCode(), errorMessage.getMessage());
} }
log.info("[getLuckyBagByOrderId] 获取福袋详情, orderId: {}, uid: {}.", orderId, uid);
// 判断订单状态 // 判断订单状态
if (vo.getOrderTicketVo().getStatus() != 1 || vo.getOrderTicketVo().getPayStatus() != 1) { if (vo.getOrderTicketVo().getStatus() != 1 || vo.getOrderTicketVo().getPayStatus() != 1) {
log.info("[getLuckyBagBenefitsByOrderId] 订单状态不满足权益要求, orderId: {}, uid: {}, status: {}, payStatus: {}.", orderId, log.info("[getLuckyBagByOrderId] 该订单状态不满足权益要求, orderId: {}, uid: {}, status: {}, payStatus: {}.", orderId,
uid, vo.getOrderTicketVo().getStatus(), vo.getOrderTicketVo().getPayStatus()); uid, vo.getOrderTicketVo().getStatus(), vo.getOrderTicketVo().getPayStatus());
return KylinLuckyBagVo.ofEmpty(); return KylinLuckyBagVo.ofEmpty();
} }
...@@ -68,7 +81,7 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService { ...@@ -68,7 +81,7 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService {
List<KylinLuckyBagVo.LuckyBagActivityVo> activityVos = getLuckyBagActivityVos(vo.getOrderTicketVo().getPerformanceId()); List<KylinLuckyBagVo.LuckyBagActivityVo> activityVos = getLuckyBagActivityVos(vo.getOrderTicketVo().getPerformanceId());
//3. 再查询满足的权益 //3. 再查询满足的权益
List<KylinLuckyBagVo.LuckyBagVo> luckyBagVos = getLuckyBagVos(vo.getOrderTicketVo().getPerformanceId(), orderId, uid); List<KylinLuckyBagVo.LuckyBagVo> luckyBagVos = getLuckyBagVos(vo);
return KylinLuckyBagVo.of(luckyBagVos, activityVos); return KylinLuckyBagVo.of(luckyBagVos, activityVos);
} }
...@@ -76,17 +89,18 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService { ...@@ -76,17 +89,18 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService {
/** /**
* 获取福袋列表 * 获取福袋列表
* *
* @param performanceId * @param vo
* @param orderId
* @param uid
* @return * @return
*/ */
private List<KylinLuckyBagVo.LuckyBagVo> getLuckyBagVos(String performanceId, String orderId, String uid) { private List<KylinLuckyBagVo.LuckyBagVo> getLuckyBagVos(OrderDetailsVo vo) {
log.info("[getLuckyBagVos] performanceId: {}, orderId: {}, uid: {}.", performanceId, orderId, uid); final String performanceId = vo.getOrderTicketVo().getPerformanceId();
final String orderId = vo.getOrderTicketVo().getOrderTicketsId();
final String uid = vo.getOrderTicketVo().getUserId();
List<KylinLuckyBag> luckyBagList = dataUtils.getKylinLuckyBagList(); List<KylinLuckyBag> luckyBagList = dataUtils.getKylinLuckyBagList();
if (luckyBagList.isEmpty()) { if (luckyBagList.isEmpty()) {
log.info("[getLuckyBagVos] 获取福袋列表为空"); log.info("[getLuckyBagVos] 获取福袋列表为空.");
return Collections.emptyList(); return Collections.emptyList();
} }
...@@ -102,15 +116,27 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService { ...@@ -102,15 +116,27 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService {
luckyBagVo.setLuckyBagId(l.getLuckyBagId()); luckyBagVo.setLuckyBagId(l.getLuckyBagId());
luckyBagVo.setName(l.getName()); luckyBagVo.setName(l.getName());
luckyBagVo.setIntroduction(l.getIntroduction()); luckyBagVo.setIntroduction(l.getIntroduction());
if (l.getSendState() == 1) {
// 查询数据库获取兑换码 final String sendTime = l.getSendTime();
List<KylinRewardUser> kylinRewardUserList = dataUtils.getKylinRewardUserList(orderId, uid, l.getLuckyBagId()); final String nowTime = DateUtil.getNowTime();
Set<String> codeSet = kylinRewardUserList.stream().map(KylinRewardUser::getCode).collect(Collectors.toSet()); // 判断发放时间
luckyBagVo.setStatus(codeSet.isEmpty() ? 0 : 1); if (null != sendTime && !sendTime.isEmpty()) {
luckyBagVo.setRewardCodeList(codeSet); if (DateUtil.compareStrDay(nowTime, sendTime) >= 0) { // 当前时间小于发放时间 还未开始呢
} else{ // 查询数据库获取兑换码
luckyBagVo.setStatus(0); List<KylinRewardUser> kylinRewardUserList = dataUtils.getKylinRewardUserList(orderId, uid, l.getLuckyBagId());
luckyBagVo.setRewardCodeList(Collections.emptySet()); if (kylinRewardUserList.isEmpty()) {
// 根据购买数量来分配兑换码
log.info("[getLuckyBagVos] 福袋[{}]已到发放时间,但未给用户分配兑换码, uid: {}, orderId: {}.", l.getName(), uid, orderId);
kylinRewardUserList = getRandomRewardCode(vo, l.getLuckyBagId());
}
Set<String> codeSet = kylinRewardUserList.stream().map(KylinRewardUser::getCode).collect(Collectors.toSet());
luckyBagVo.setRewardCodeList(codeSet);
luckyBagVo.setStatus(kylinRewardUserList.isEmpty() ? 0 : 1);
} else {
log.info("[getLuckyBagVos] 福袋[{}]未到发放时间.", l.getName());
luckyBagVo.setStatus(0);
luckyBagVo.setRewardCodeList(Collections.emptySet());
}
} }
activityVos.add(luckyBagVo); activityVos.add(luckyBagVo);
}); });
...@@ -118,6 +144,82 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService { ...@@ -118,6 +144,82 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService {
return activityVos; return activityVos;
} }
/**
* 分配兑换码
*
* @param vo
* @return
*/
private List<KylinRewardUser> getRandomRewardCode(OrderDetailsVo vo, String luckyBagId) {
String lockKey = KylinRedisConst.LUCKY_BAG_CODE_LOCK + luckyBagId;
try {
// 1. 获取分布式锁,防止并发问题
boolean locked = redisUtil.lock(lockKey, 1, 30);
if (!locked) {
log.info("[getRandomRewardCode] 未获取到分布式锁.");
return Collections.emptyList();
}
final int limitTotal = vo.getOrderTicketVo().getNumber();
if (limitTotal <= 0) {
log.error("[getRandomRewardCode] 用户订单购买数量错误, orderId: {}.", vo.getOrderTicketVo().getOrderTicketsId());
return Collections.emptyList();
}
LambdaQueryWrapper<KylinRewardCode> lambdaQueryWrapper = new QueryWrapper<KylinRewardCode>().lambda()
.eq(KylinRewardCode::getLuckyBagId, luckyBagId)
.eq(KylinRewardCode::getState, 1)
.last(true, "ORDER BY RAND() limit " + limitTotal);
//2. 搜索兑换码
List<KylinRewardCode> rewardCodes = kylinRewardCodeMapper.selectList(lambdaQueryWrapper);
if (rewardCodes.isEmpty() || rewardCodes.size() < limitTotal) {
log.error("[getRandomRewardCode] 兑换码不足, luckyBagId: {}, need total: {}.", luckyBagId, limitTotal);
// 报警
String msg = String.format("福袋ID [%s] 兑换码不足,请及时补充.", luckyBagId);
iFeishuBotService.sendTextMessage(msg);
return Collections.emptyList();
}
//3. 写入
List<KylinRewardUser> rewardUsers = new ArrayList<>(limitTotal);
for (int i = 0; i < rewardCodes.size(); i++) {
KylinRewardCode rewardCode = rewardCodes.get(i);
rewardCode.setState(0);
int updateResult = kylinRewardCodeMapper.updateById(rewardCode);
if (updateResult > 0) {
KylinRewardUser user = new KylinRewardUser();
user.setUid(vo.getOrderTicketVo().getUserId());
user.setLuckyBagId(luckyBagId);
user.setOrderId(vo.getOrderTicketVo().getOrderTicketsId());
user.setOrderTicketEntitiesId(vo.getOrderTicketVo().getEntitiesVoList().get(i).getOrderTicketEntitiesId());
user.setCode(rewardCode.getCode());
user.setState(1);
user.setCreatedAt(LocalDateTime.now());
user.setUpdatedAt(LocalDateTime.now());
kylinRewardUserMapper.insert(user);
rewardUsers.add(user);
log.info("[getRandomRewardCode] 兑换码分配成功, luckyBagId: {}, orderId: {}, code: {}.", luckyBagId, vo.getOrderTicketVo().getOrderTicketsId(), rewardCode.getCode());
} else {
log.error("[getRandomRewardCode] 兑换码分配失败, luckyBagId: {}, orderId: {}.", luckyBagId, vo.getOrderTicketVo().getOrderTicketsId());
// 报警
String msg = String.format("福袋ID [%s] 分配兑换码失败:用户ID [%s] 的订单ID [%s] 已分配了 [%s] 个,应分配 [%s] 个。",
luckyBagId, vo.getOrderTicketVo().getUserId(), vo.getOrderTicketVo().getOrderTicketsId(), rewardUsers.size(), limitTotal);
iFeishuBotService.sendTextMessage(msg);
}
}
return rewardUsers;
} catch (Exception e) {
log.error("error", e);
// 报警
iFeishuBotService.sendTextMessage("error: " + e.getMessage());
return Collections.emptyList();
} finally {
redisUtil.uLock(lockKey);
}
}
/** /**
* 获取福袋活动列表 * 获取福袋活动列表
* *
...@@ -125,7 +227,6 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService { ...@@ -125,7 +227,6 @@ public class KylinLuckyBagServiceImpl implements IKylinLuckyBagService {
* @return * @return
*/ */
private List<KylinLuckyBagVo.LuckyBagActivityVo> getLuckyBagActivityVos(String performanceId) { private List<KylinLuckyBagVo.LuckyBagActivityVo> getLuckyBagActivityVos(String performanceId) {
log.info("[getLuckyBagActivityVos] performanceId: {}.", performanceId);
List<KylinLuckyBagVo.LuckyBagActivityVo> activityVos = new ArrayList<>(); List<KylinLuckyBagVo.LuckyBagActivityVo> activityVos = new ArrayList<>();
//2. 先查询活动 //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