| | |
| | | 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; |
| | |
| | | private static final String STORE_COUPON_CLAIM = "store_coupon_claim:"; |
| | | private final MemberCouponService memberCouponService; |
| | | private final StoreCouponService storeCouponService; |
| | | private final StoreCouponSingleService storeCouponSingleService; |
| | | /** |
| | | * 添加 |
| | | * @param form |
| | |
| | | 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() { |
| | |
| | | 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; |
| | | } |
| | | } |