package cn.lili.modules.lmk.service.impl; import cn.lili.base.Result; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.modules.goods.service.GoodsService; import cn.lili.modules.lmk.domain.entity.CouponVirtual; import cn.lili.modules.lmk.domain.form.CouponVirtualForm; import cn.lili.modules.lmk.domain.query.CouponVirtualQuery; import cn.lili.modules.lmk.domain.vo.CouponVirtualVO; import cn.lili.modules.lmk.domain.vo.CouponVirtualVOInfo; import cn.lili.modules.lmk.mapper.CouponVirtualMapper; import cn.lili.modules.lmk.service.CouponVirtualService; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.OrderItem; import cn.lili.modules.order.order.entity.enums.ClaimStatusEnum; import cn.lili.modules.order.order.entity.enums.OrderStatusEnum; import cn.lili.modules.order.order.entity.enums.RefundStatusEnum; import cn.lili.modules.order.order.entity.enums.ShareStatusEnum; import cn.lili.modules.order.order.service.OrderItemService; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.utils.COSUtil; import cn.lili.utils.PageUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import java.util.Date; import java.util.List; import java.util.stream.Collectors; /** * 虚拟商品优惠卷 服务实现类 * * @author zxl * @since 2025-09-10 */ @Service @RequiredArgsConstructor @Slf4j public class CouponVirtualServiceImpl extends ServiceImpl implements CouponVirtualService { private final CouponVirtualMapper couponVirtualMapper; private final RedissonClient redissonClient; private final static String LOCK_COUPON_VIRTUAL_CARD_ID = "lock_coupon_virtual_card_id:"; private final OrderItemService orderItemService; private final OrderService orderService; private final MemberCouponService memberCouponService; private final GoodsService goodsService; private final COSUtil cosUtil; /** * 添加 * * @param form * @return */ @Override public Result add(CouponVirtualForm form) { CouponVirtual entity = CouponVirtualForm.getEntityByForm(form, null); baseMapper.insert(entity); return Result.ok("添加成功"); } /** * 修改 * * @param form * @return */ @Override public Result update(CouponVirtualForm form) { CouponVirtual entity = baseMapper.selectById(form.getId()); // 为空抛IllegalArgumentException,做全局异常处理 Assert.notNull(entity, "记录不存在"); BeanUtils.copyProperties(form, entity); baseMapper.updateById(entity); return Result.ok("修改成功"); } /** * 批量删除 * * @param ids * @return */ @Override public Result remove(List ids) { baseMapper.deleteBatchIds(ids); return Result.ok("删除成功"); } /** * id删除 * * @param id * @return */ @Override public Result removeById(String id) { baseMapper.deleteById(id); return Result.ok("删除成功"); } /** * 分页查询 * * @param query * @return */ @Override public Result page(CouponVirtualQuery query) { IPage page = PageUtil.getPage(query, CouponVirtualVO.class); baseMapper.getPage(page, query); for (CouponVirtualVO record : page.getRecords()) { String original = record.getOriginal(); if (StringUtils.isNotBlank(original) && !original.contains("http")) { record.setOriginal(cosUtil.getPreviewUrl(original)); } } return Result.ok().data(page.getRecords()).total(page.getTotal()); } /** * 根据id查找 * * @param id * @return */ @Override public Result detail(Integer id) { CouponVirtualVO vo = baseMapper.getById(id); Assert.notNull(vo, "记录不存在"); return Result.ok().data(vo); } /** * 列表 * * @return */ @Override public Result all() { List entities = baseMapper.selectList(null); List vos = entities.stream() .map(entity -> CouponVirtualVO.getVoByEntity(entity, null)) .collect(Collectors.toList()); return Result.ok().data(vos); } @Override @Transactional(rollbackFor = Exception.class) public Result tackCardById(String cardId) { log.info("被领取的礼品卡的id为--------------------------->{}",cardId); AuthUser currentUser = UserContext.getCurrentUser(); if (currentUser == null) { throw new ServiceException("当前用户没有登录"); } String userId = currentUser.getId(); String nickName = currentUser.getNickName(); RLock lock = null; try { lock = redissonClient.getLock(LOCK_COUPON_VIRTUAL_CARD_ID + cardId); lock.lock(); LambdaQueryWrapper forUpdate = Wrappers.lambdaQuery().eq(CouponVirtual::getId, cardId).last("FOR UPDATE"); CouponVirtual cardInfo = this.getOne(forUpdate); if (cardInfo == null) { throw new ServiceException("当前优惠卷不存在"); } if (ClaimStatusEnum.CLAIM.name().equals(cardInfo.getClaimStatus())) { throw new ServiceException("当前购物卡已经被领取"); } //校验订单状态是否正常 String orderNo = cardInfo.getOrderId(); if (StringUtils.isBlank(orderNo)) { throw new ServiceException("当前订单不存在无法领取"); } String itemOrderId = cardInfo.getItemOrderId(); Order order = orderService.getBySn(orderNo); if (order == null) { throw new ServiceException("当前订单不存在无法领取"); } if (!OrderStatusEnum.COMPLETED.name().equals(order.getOrderStatus())) { throw new ServiceException("订单状态异常无法领取"); } OrderItem orderItem = orderItemService.getById(itemOrderId); if (orderItem == null) { throw new ServiceException("当前订单不存在"); } String orderSn = orderItem.getOrderSn(); if (!orderNo.equals(orderSn)) { throw new ServiceException("订单无法对应无法领取"); } if (!RefundStatusEnum.NO_REFUND.name().equals(orderItem.getIsRefund())) { throw new ServiceException("当前订单已退款无法领取"); } //领取对应的优惠卷 memberCouponService.receiveCoupon(cardInfo.getCouponId(),userId , nickName); cardInfo.setUserNickname(nickName); cardInfo.setUserId(userId); cardInfo.setClaimStatus(ClaimStatusEnum.CLAIM.name()); cardInfo.setShareStatus(ShareStatusEnum.SHARE.name()); cardInfo.setClaimTime(new Date()); boolean b = this.updateById(cardInfo); //去领取优惠卷 if (!b) { throw new RuntimeException("领取失败"); } return Result.ok().data(cardInfo.getCouponId()); } finally { if ( lock != null && lock.isHeldByCurrentThread()) { lock.unlock(); } } } @Override public Result changShareStatus(String cardId) { CouponVirtual couponVirtual = this.getById(cardId); couponVirtual.setShareStatus(ShareStatusEnum.SHARE.name()); this.updateById(couponVirtual); return Result.ok(); } @Override public Result couponCardInfo(String cardId) { CouponVirtual couponVirtual = this.getById(cardId); if (couponVirtual == null) { throw new ServiceException("当前购物卡不存在"); } CouponVirtualVOInfo virtualVOInfo = new CouponVirtualVOInfo(); BeanUtils.copyProperties(couponVirtual, virtualVOInfo); String goodsId = virtualVOInfo.getGoodsId(); String url = goodsService.getById(goodsId).getOriginal(); if (StringUtils.isNotBlank(url) && !url.contains("http")) { virtualVOInfo.setGoodsUrl(cosUtil.getPreviewUrl(url)); } return Result.ok().data(virtualVOInfo); } }