package com.ylx.massage.service.impl; import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ylx.common.core.domain.R; import com.ylx.common.core.domain.model.WxLoginUser; import com.ylx.massage.domain.Coupon; import com.ylx.massage.domain.UserCouponRelation; import com.ylx.massage.domain.vo.ClaimCouponRequestVO; import com.ylx.massage.domain.vo.CouponReceiveVo; import com.ylx.massage.domain.vo.CouponReceivesVO; import com.ylx.massage.mapper.CouponReceiveMapper; import com.ylx.massage.domain.CouponReceive; import com.ylx.massage.mapper.UserCouponRelationMapper; import com.ylx.massage.service.CouponReceiveService; import com.ylx.massage.service.CouponService; import com.ylx.massage.utils.DateTimeUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.utils.Lists; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static com.ylx.common.utils.SecurityUtils.getWxLoginUser; /** * 优惠券领取表(CouponReceive)表服务实现类 * * @author makejava * @since 2024-05-14 11:25:45 */ @Slf4j @Service("couponReceiveService") public class CouponReceiveServiceImpl extends ServiceImpl implements CouponReceiveService { private static final String SHARE_LOCK_KEY = "coupon_center:receiveCoupon:lock:"; private static final long LOCK_EXPIRE_TIME = 2L; // 锁过期时间2秒 @Resource private CouponService couponService; @Resource private CouponReceiveMapper couponReceiveMapper; @Resource private UserCouponRelationMapper userCouponRelationMapper; @Autowired private StringRedisTemplate redisTemplate; @Override public Coupon submit(CouponReceive couponReceive) { Coupon coupon = couponService.getById(couponReceive.getCouponId()); if (coupon == null) { return null; } LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(CouponReceive::getReceiveOpenId, couponReceive.getReceiveOpenId()).eq(CouponReceive::getCouponId, couponReceive.getCouponId()); //限制领取数量 List one = this.list(queryWrapper); if (coupon.getUserLimit() <= one.size()) { return null; } couponReceive.setExpirationTime(DateTimeUtils.addDays(new Date(), coupon.getTermDays())); this.save(couponReceive); return coupon; } @Override @Transactional(rollbackFor = Exception.class) public Integer submits(CouponReceivesVO couponReceive) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(Coupon::getId, couponReceive.getCouponIds()); List list = couponService.list(queryWrapper); if (CollectionUtil.isEmpty(list)) { log.info("优惠卷不存在"); return null; } ArrayList couponReceives = Lists.newArrayList(); list.forEach(coupon -> { CouponReceive couponRec = new CouponReceive(); couponRec.setId(Long.toString(IdWorker.getId(couponRec))); couponRec.setCouponId(coupon.getId()); couponRec.setReceiveOpenId(couponReceive.getOpenId()); /*couponRec.setDeptId(coupon.getDeptId()); couponRec.setDeptName(coupon.getDeptName());*/ couponRec.setCouponStatus(0); couponRec.setExpirationTime(DateTimeUtils.addDays(new Date(), coupon.getTermDays())); couponReceives.add(couponRec); }); return couponReceiveMapper.insertBatch(couponReceives); } @Override @Transactional(rollbackFor = Exception.class) public R receiveVolution(ClaimCouponRequestVO claimCouponRequestVO) { // 1、查询用户信息 WxLoginUser wxLoginUser = getWxLoginUser(); String openid = wxLoginUser.getCOpenid(); log.info("当前用户的openId:{}", openid); //2、保存优惠券信息到coupon_receive表 // 构建防重复提交的key:用户openId + 优惠卷id String lockKey = SHARE_LOCK_KEY + wxLoginUser.getCOpenid() + ":" + claimCouponRequestVO.getTemplateId(); // 尝试获取锁,防止重复提交 Boolean lockResult = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", LOCK_EXPIRE_TIME, TimeUnit.SECONDS); if (Boolean.FALSE.equals(lockResult)) { return R.fail("操作过于频繁,请稍后再试"); } CouponReceive couponReceive = new CouponReceive(); couponReceive.setIssuerCouponId(claimCouponRequestVO.getUserId()); couponReceive.setCouponId(claimCouponRequestVO.getTemplateId()); couponReceive.setCouponType(Integer.parseInt(claimCouponRequestVO.getType())); couponReceive.setReceiveOpenId(wxLoginUser.getCOpenid()); couponReceive.setReceiveTime(LocalDateTime.now()); //设置领取人手机号 couponReceive.setReceiveUserPhone(wxLoginUser.getCPhone()); //获取当前有效期类型 String validityType = claimCouponRequestVO.getValidityType(); switch (validityType) { // 固定日期范围 case "1": couponReceive.setValidityType(1); couponReceive.setValidStartTime(claimCouponRequestVO.getValidStartTime()); couponReceive.setExpirationTime(claimCouponRequestVO.getValidEndTime()); break; //领券后N天有效 case "2": couponReceive.setValidityType(2); couponReceive.setValidDays(Integer.parseInt(claimCouponRequestVO.getValidDays())); break; //长期有效 case "3": couponReceive.setValidityType(3); break; default: throw new IllegalArgumentException("有效期类型错误"); } // 设置使用状态:待使用 couponReceive.setCouponStatus(0); int insert = couponReceiveMapper.insert(couponReceive); if (insert == 0) { return R.fail("优惠券领取失败"); } // 3、将优惠券id和用户id做绑定插入用户优惠券关联表 UserCouponRelation userCouponRelation = new UserCouponRelation(); userCouponRelation.setOpenId(wxLoginUser.getCOpenid()); userCouponRelation.setCouponId(claimCouponRequestVO.getTemplateId()); userCouponRelation.setCouponName(claimCouponRequestVO.getName()); userCouponRelation.setImageUrl(claimCouponRequestVO.getImageUrl()); userCouponRelation.setCouponType(Integer.parseInt(claimCouponRequestVO.getType())); //设置状态为未使用 userCouponRelation.setCouponStatus(0); switch (validityType) { // 固定日期范围 case "1": userCouponRelation.setValidityType(Integer.parseInt(validityType)); couponReceive.setValidStartTime(claimCouponRequestVO.getValidStartTime()); couponReceive.setExpirationTime(claimCouponRequestVO.getValidEndTime()); break; //领券后N天有效 case "2": userCouponRelation.setValidityType(Integer.parseInt(validityType)); couponReceive.setValidDays(Integer.parseInt(claimCouponRequestVO.getValidDays())); break; //长期有效 case "3": userCouponRelation.setValidityType(Integer.parseInt(validityType)); break; default: throw new IllegalArgumentException("有效期类型错误"); } //市场售价 BigDecimal marketPrice = BigDecimal.ZERO; //2-折扣券 if ("2".equals(claimCouponRequestVO.getType())) { marketPrice = claimCouponRequestVO.getRuleMinSpendAmount().multiply(claimCouponRequestVO.getRuleDiscountRate()) .divide(new BigDecimal("10")).setScale(2, RoundingMode.HALF_UP); } else if ("3".equals(claimCouponRequestVO.getType())) { //满减券 marketPrice = claimCouponRequestVO.getRuleReductionAmount(); } else if ("1".equals(claimCouponRequestVO.getType())) { //兑换券 marketPrice = claimCouponRequestVO.getCostPrice(); } userCouponRelation.setMarketPrice(marketPrice); // 设置券来源 0:券中心 userCouponRelation.setTicketSource(0); userCouponRelation.setCountry(claimCouponRequestVO.getCountry()); userCouponRelation.setCountryAll(claimCouponRequestVO.getCountryAll()); userCouponRelation.setLocality(claimCouponRequestVO.getLocality()); userCouponRelation.setMerchantId(claimCouponRequestVO.getMerchantId()); userCouponRelation.setStoreName(claimCouponRequestVO.getStoreName()); userCouponRelation.setCenterShareUserId(claimCouponRequestVO.getUserId()); userCouponRelation.setRuleMinSpendAmount(claimCouponRequestVO.getRuleMinSpendAmount()); userCouponRelation.setRuleDiscountRate(claimCouponRequestVO.getRuleDiscountRate()); userCouponRelation.setRuleDiscountCapAmount(claimCouponRequestVO.getRuleDiscountCapAmount()); userCouponRelation.setRuleReductionAmount(claimCouponRequestVO.getRuleReductionAmount()); userCouponRelation.setReceiveTime(LocalDateTime.now()); userCouponRelationMapper.insert(userCouponRelation); return R.ok("领取成功"); } @Override public List getByOpenId(String openid) { List CouponReceiveVos = couponReceiveMapper.getByOpenId(openid); CouponReceiveVos.forEach(couponReceiveVo -> { if(couponReceiveVo.getExpirationTime() == null){ couponReceiveVo.setExpirationTimeString("长期有效"); }else{ couponReceiveVo.setExpirationTimeString(DateTimeUtils.formatDate(couponReceiveVo.getExpirationTime(), DateTimeUtils.DATE_FORMAT)); } }); return CouponReceiveVos; } @Override @Transactional(rollbackFor = Exception.class) public void removeCoupons(List coupons) { boolean b = this.removeByIds(coupons.stream().map(CouponReceiveVo::getId).collect(Collectors.toList())); //使用数量+1 coupons.forEach(coup -> { UpdateWrapper wrapper = new UpdateWrapper<>(); wrapper.lambda().eq(Coupon::getId, coup.getCouponId()); wrapper.setSql(" used_num = used_num + " + 1); couponService.update(wrapper); }); } @Override public List couponWindows(CouponReceive couponReceive) { //判断是否领过优惠卷 //查询领取优惠卷 LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(CouponReceive::getReceiveOpenId, couponReceive.getReceiveOpenId()); List couponReceive1 = this.list(query); //如果没有领取优惠卷 if (CollectionUtil.isEmpty(couponReceive1)) { //查询优惠卷 LambdaQueryWrapper couponLambdaQueryWrapper = new LambdaQueryWrapper<>(); couponLambdaQueryWrapper.eq(Coupon::getStatus, 1); //couponLambdaQueryWrapper.eq(Coupon::getStatus, 1).like(Coupon::getDeptName, couponReceive.getDeptName()); //返回新人优惠卷列表 return couponService.list(couponLambdaQueryWrapper); } else { return Collections.emptyList(); } } }