...
|
...
|
@@ -2,6 +2,7 @@ package com.yohoufo.promotion.service.impl; |
|
|
|
|
|
import com.google.common.collect.Lists;
|
|
|
import com.google.common.collect.Range;
|
|
|
import com.yoho.core.redis.cluster.operations.serializer.RedisKeyBuilder;
|
|
|
import com.yoho.error.ServiceError;
|
|
|
import com.yoho.error.exception.ServiceException;
|
|
|
import com.yohobuy.ufo.model.promotion.UserCouponsBo;
|
...
|
...
|
@@ -14,6 +15,9 @@ import com.yohobuy.ufo.model.promotion.request.UserCouponListReq; |
|
|
import com.yohobuy.ufo.model.promotion.response.CouponInfo;
|
|
|
import com.yohobuy.ufo.model.promotion.response.CouponInfoListBo;
|
|
|
import com.yohobuy.ufo.model.promotion.response.CouponSendBo;
|
|
|
import com.yohoufo.common.exception.UfoServiceException;
|
|
|
import com.yohoufo.common.lock.RedisLock;
|
|
|
import com.yohoufo.common.lock.RedisLockFactory;
|
|
|
import com.yohoufo.common.utils.DateUtil;
|
|
|
import com.yohoufo.dal.promotion.CouponMapper;
|
|
|
import com.yohoufo.dal.promotion.UserCouponMapper;
|
...
|
...
|
@@ -32,6 +36,7 @@ import java.time.LocalDateTime; |
|
|
import java.time.LocalTime;
|
|
|
import java.time.ZoneOffset;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
...
|
...
|
@@ -53,6 +58,9 @@ public class CouponServiceImpl implements ICouponService { |
|
|
@Autowired
|
|
|
SingleCentCouponService singleCentSyncCoupNumService;
|
|
|
|
|
|
@Autowired
|
|
|
private RedisLockFactory redisLockFactory;
|
|
|
|
|
|
|
|
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
|
|
|
...
|
...
|
@@ -202,6 +210,7 @@ public class CouponServiceImpl implements ICouponService { |
|
|
logger.warn("sendCoupon query coupon info,coupontype is null:{}", couponToken);
|
|
|
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_NOT_EXISTS);
|
|
|
}
|
|
|
|
|
|
Coupon coupon = couponAndType.getCoupon();
|
|
|
//check receive start time
|
|
|
if(receiveStartTimeChkNecessary){
|
...
|
...
|
@@ -211,7 +220,7 @@ public class CouponServiceImpl implements ICouponService { |
|
|
|
|
|
if(!repeatable){
|
|
|
// 校验是否可以领取(重复领取,时间是否合法,状态)
|
|
|
checkCanAcquire(uid, couponToken, couponAndType);
|
|
|
redisLock = checkCanAcquire(uid, couponToken, couponAndType);
|
|
|
}
|
|
|
|
|
|
if (coupon.getStatus() != CouponsStatusEnum.VALID.getCode()){
|
...
|
...
|
@@ -235,19 +244,16 @@ public class CouponServiceImpl implements ICouponService { |
|
|
}
|
|
|
|
|
|
int count = 0;
|
|
|
// 不可重复
|
|
|
if (!repeatable){
|
|
|
count = userCouponMapper.insertWhere(userCoupon);
|
|
|
}else{
|
|
|
count = userCouponMapper.insert(userCoupon);
|
|
|
}
|
|
|
|
|
|
count = userCouponMapper.insert(userCoupon);
|
|
|
if (count == 0){
|
|
|
logger.info("can not repeatable acquire coupon. uid is {}, coupon is {}", uid, couponToken);
|
|
|
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED);
|
|
|
}
|
|
|
|
|
|
logger.info("senCoupon success,{},{},{},{}", uid, couponToken, couponCode, count);
|
|
|
if(Objects.nonNull(redisLock)){
|
|
|
redisLock.unlock();
|
|
|
}
|
|
|
return couponCode;
|
|
|
}
|
|
|
|
...
|
...
|
@@ -344,13 +350,22 @@ public class CouponServiceImpl implements ICouponService { |
|
|
}
|
|
|
|
|
|
|
|
|
private void checkCanAcquire(Integer uid, String couponToken, CouponAndType couponAndType) {
|
|
|
private RedisLock checkCanAcquire(Integer uid, String couponToken, CouponAndType couponAndType) {
|
|
|
// 验证该用户是否重复领取
|
|
|
UserCoupon userCoupon = userCouponMapper.selectByUidAndToken(uid, couponToken);
|
|
|
|
|
|
RedisLock redisLock = redisLockFactory.newLock(RedisKeyBuilder.newInstance()
|
|
|
.appendFixed("ufo:promotion:coupons:checkCanAcquire:")
|
|
|
.appendVar(uid + "-" + couponToken), 3, TimeUnit.SECONDS);
|
|
|
if (!redisLock.tryLock()) {
|
|
|
logger.info("{} checkCanAcquire fail, it already in the process", uid);
|
|
|
throw new UfoServiceException(400, "优惠券领取中");
|
|
|
}
|
|
|
if (userCoupon != null){
|
|
|
logger.warn("user has acquried this coupon before:{},{}", uid, couponToken);
|
|
|
throw new ServiceException(ServiceError.PROMOTION_COUPON_HAS_RECEIVED);
|
|
|
}
|
|
|
return redisLock;
|
|
|
|
|
|
}
|
|
|
|
...
|
...
|
|