peng
2 天以前 14b3dd223d4a148a4ca681a5c542901dfe74f029
framework/src/main/java/cn/lili/modules/lmk/service/impl/StoreCouponClaimRecordServiceImpl.java
@@ -4,13 +4,18 @@
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.modules.lmk.domain.entity.StoreCoupon;
import cn.lili.modules.lmk.domain.entity.StoreCouponSingle;
import cn.lili.modules.lmk.enums.general.PrizeStatusEnum;
import cn.lili.modules.lmk.enums.general.StoreCouponStausEnum;
import cn.lili.modules.lmk.service.StoreCouponService;
import cn.lili.modules.lmk.service.StoreCouponSingleService;
import cn.lili.modules.order.order.entity.enums.ClaimStatusEnum;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.service.MemberCouponService;
import cn.lili.rocketmq.RocketmqSendCallbackBuilder;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.lili.modules.lmk.domain.entity.StoreCouponClaimRecord;
import cn.lili.modules.lmk.mapper.StoreCouponClaimRecordMapper;
@@ -50,6 +55,7 @@
    private static final String STORE_COUPON_CLAIM = "store_coupon_claim:";
    private final MemberCouponService memberCouponService;
    private final StoreCouponService storeCouponService;
    private final StoreCouponSingleService storeCouponSingleService;
    /**
     * 添加
     * @param form
@@ -147,33 +153,63 @@
        String userId = currentUser.getId();
        String nickName = currentUser.getNickName();
        //锁住店铺某一个优惠卷
        //锁住礼品码id
        RLock redissonLock = redissonClient.getLock(STORE_COUPON_CLAIM + id);
        try {
            redissonLock.lock();
            StoreCoupon storeCoupon = storeCouponService.getById(id);
            if (storeCoupon == null) {
                throw new ServiceException("当前店铺不存在优惠卷");
            LambdaQueryWrapper<StoreCouponSingle> forUpdate = Wrappers.<StoreCouponSingle>lambdaQuery()
                    .eq(StoreCouponSingle::getId, id).last("FOR UPDATE");
            StoreCouponSingle storeCouponSingle = storeCouponSingleService.getOne(forUpdate);
            if (storeCouponSingle == null) {
                throw new ServiceException("当前礼品码不存在");
            }
            if (!ClaimStatusEnum.NOT_CLAIM.name().equals(storeCouponSingle.getClaimStatus())) {
                throw new ServiceException("当前礼品码状态异常");
            }
            LambdaQueryWrapper<StoreCouponSingle> claimListQuery = Wrappers.<StoreCouponSingle>lambdaQuery()
                    .eq(StoreCouponSingle::getClaimUserId, userId)
                    .eq(StoreCouponSingle::getStoreCoupRef, storeCouponSingle.getStoreCoupRef())
                    .eq(StoreCouponSingle::getClaimStatus, ClaimStatusEnum.CLAIM.name());
            List<StoreCouponSingle> claimList = storeCouponSingleService.list(claimListQuery);
            if (!claimList.isEmpty()) {
                throw new ServiceException("已经领取过该类型的礼品码无法领取");
            }
            //处理幂等问题限制一个用户只能该店铺领取一种优惠卷
            LambdaQueryWrapper<StoreCouponClaimRecord> memCoupon = Wrappers.<StoreCouponClaimRecord>lambdaQuery()
                    .eq(StoreCouponClaimRecord::getUserId, userId)
                    .eq(StoreCouponClaimRecord::getCouponId, storeCoupon.getCouponId());
                    .eq(StoreCouponClaimRecord::getCouponId, storeCouponSingle.getCouponId());
            List<StoreCouponClaimRecord> list = this.list(memCoupon);
            if (!list.isEmpty()){
                throw new ServiceException("当前用户已经领取过了无法再次领取");
            }
            //更新单品被领取的记录
            storeCouponSingle.setClaimStatus(ClaimStatusEnum.CLAIM.name());
            storeCouponSingle.setClaimUserId(userId);
            storeCouponSingle.setClaimUserName(nickName);
            storeCouponSingleService.updateById(storeCouponSingle);
            //校验是否在单品卷类领取过
            LambdaQueryWrapper<StoreCoupon> storeCoupQuery = Wrappers.<StoreCoupon>lambdaQuery()
                    .eq(StoreCoupon::getId, storeCouponSingle.getStoreCoupRef()).last("FOR UPDATE");
            StoreCoupon storeCoupon = storeCouponService.getOne(storeCoupQuery);
            if (storeCoupon == null) {
                throw new ServiceException("当前店铺优惠卷不存在");
            }
            if (!StoreCouponStausEnum.ENABLE.name().equals(storeCoupon.getStatus())) {
                throw new ServiceException("当前店铺优惠卷状态异常");
            }
            //领取对应的优惠卷写入记录
            memberCouponService.receiveCoupon(storeCoupon.getCouponId(),userId , nickName);
            StoreCouponClaimRecord storeCouponClaimRecord = new StoreCouponClaimRecord();
            storeCouponClaimRecord.setCouponId(storeCoupon.getCouponId());
            storeCouponClaimRecord.setCouponName(storeCoupon.getCouponName());
            storeCouponClaimRecord.setStoreId(storeCoupon.getStoreId());
            storeCouponClaimRecord.setStoreName(storeCoupon.getStoreName());
            storeCouponClaimRecord.setUserId(userId);
            memberCouponService.receiveCoupon(storeCouponSingle.getCouponId(),userId , nickName);
            StoreCouponClaimRecord storeCouponClaimRecord = getStoreCouponClaimRecord(storeCouponSingle, userId);
            this.save(storeCouponClaimRecord);
            LambdaUpdateWrapper<StoreCoupon> updateStoreCoupon = Wrappers.<StoreCoupon>lambdaUpdate().eq(StoreCoupon::getId, storeCoupon.getId())
                    .set(StoreCoupon::getCouponClaimNum, storeCoupon.getCouponClaimNum() + 1)
                    .gt(StoreCoupon::getCouponClaimNum, storeCoupon.getCouponClaimNum() + 1);
            boolean update = storeCouponService.update(updateStoreCoupon);
            if (!update) {
                throw new ServiceException("更新失败");
            }
            //领取成功返回优惠卷id用于跳转购物使用
            return Result.ok().data(storeCoupon.getCouponId());
            return Result.ok().data(storeCouponSingle.getCouponId());
        } finally {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@@ -183,8 +219,28 @@
                        redissonLock.unlock();
                    }
                }
                @Override
                public void afterCompletion(int status) {
                    // 确保即使在事务回滚的情况下也能释放锁
                    if (redissonLock.isHeldByCurrentThread()) {
                        redissonLock.unlock();
                    }
                }
            });
        }
    }
    private static StoreCouponClaimRecord getStoreCouponClaimRecord(StoreCouponSingle storeCouponSingle, String userId) {
        StoreCouponClaimRecord storeCouponClaimRecord = new StoreCouponClaimRecord();
        storeCouponClaimRecord.setCouponId(storeCouponSingle.getCouponId());
        storeCouponClaimRecord.setCouponName(storeCouponSingle.getCouponName());
        storeCouponClaimRecord.setStoreId(storeCouponSingle.getStoreId());
        storeCouponClaimRecord.setStoreName(storeCouponSingle.getStoreName());
        storeCouponClaimRecord.setUserId(userId);
        storeCouponClaimRecord.setStoreCouponId(storeCouponSingle.getStoreCoupRef());
        return storeCouponClaimRecord;
    }
}