|
|
@@ -24,7 +24,6 @@ import com.kym.service.admin.CouponService;
|
|
|
import com.kym.service.miniapp.UserCouponService;
|
|
|
import com.kym.service.miniapp.UserService;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
-import org.springframework.dao.DuplicateKeyException;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
@@ -179,7 +178,7 @@ public PageBean<UserCouponVo> listUserCoupons(CouponQueryParam params) {
|
|
|
// 活动
|
|
|
var activity = activityService.getById(coupon.getActivityId());
|
|
|
|
|
|
- // 先落库(靠(coupon_id,user_id)唯一索引兜底防重),成功后再写Redis,保证两者最终一致
|
|
|
+ // 组装用户优惠券
|
|
|
var userCoupon = new UserCoupon();
|
|
|
userCoupon.setActivityId(coupon.getActivityId());
|
|
|
userCoupon.setActivityName(activity.getName());
|
|
|
@@ -195,22 +194,9 @@ public PageBean<UserCouponVo> listUserCoupons(CouponQueryParam params) {
|
|
|
userCoupon.setAllowStacke(coupon.getAllowStacke());
|
|
|
userCoupon.setStatus(UserCoupon.STATUS_有效);
|
|
|
userCoupon.setRemark(coupon.getRemark());
|
|
|
- try {
|
|
|
- save(userCoupon);
|
|
|
- } catch (DuplicateKeyException e) {
|
|
|
- // 落库失败(重复领取),回退库存自增
|
|
|
- try {
|
|
|
- DynamicDataSourceContextHolder.push("db-admin");
|
|
|
- couponService.lambdaUpdate()
|
|
|
- .setSql("claimed_quantity = claimed_quantity - 1")
|
|
|
- .eq(Coupon::getId, couponId)
|
|
|
- .apply("claimed_quantity > 0")
|
|
|
- .update();
|
|
|
- } finally {
|
|
|
- DynamicDataSourceContextHolder.poll();
|
|
|
- }
|
|
|
- throw new BusinessException("优惠券已领取,请勿重复领取!");
|
|
|
- }
|
|
|
+
|
|
|
+ // 先落库,成功后写Redis(业务允许用户持有多张同种券,领取去重由上方Redis校验+互斥锁保证)
|
|
|
+ save(userCoupon);
|
|
|
redisTemplate.opsForSet().add(RedisKeys.COUPON_ID_TO_USERS, couponId + ":" + userId);
|
|
|
} finally {
|
|
|
redisTemplate.delete(lockKey);
|