领取优惠券

文章目录

概要

领券的本质就是新增一条记录到user_coupon表,去记录用户和领券的优惠券之间的关系,使用状态等信息。那因此请求的需要两个参数:

  • 用户id

  • 优惠券id

不过,用户id我们可以自己获取,因此前端只要传递优惠券id即可。只传一个参数,我们可以直接用路径占位符传参。

返回值就更不需要了,因此接口信息非常简单,如下:

需求分析以及接口设计

技术细节

不过,需要注意的是,优惠券并不是任何人来了都可以领取的,我们需要做一系列的校验:

  • 校验优惠券是否存在,不存在无法领取

  • 校验优惠券的发放时间,是不是正在发放中

  • 校验优惠券剩余库存是否充足

  • 校验优惠券的每人限领数量

只有全部校验通过,才可以领取优惠券,而领券要做两件事:

  • 新增一个记录到user_coupon表

  • 更新coupon表中已经领取的数量,别忘了在coupon表中是有一些统计字段的

      更新发行数量(已领取数量),不仅仅起到统计作用,同时也可以帮助我们判断库存是否充足。

      issue_num >= total_num时,那就证明库存已经不足了。

      1.Controller层

      package com.tianji.promotion.controller;
      
      import com.tianji.promotion.service.IUserCouponService;
      import io.swagger.annotations.Api;
      import io.swagger.annotations.ApiOperation;
      import io.swagger.annotations.ApiParam;
      import lombok.RequiredArgsConstructor;
      import org.springframework.web.bind.annotation.*;
      
      import java.util.List;
      
      @RestController
      @RequiredArgsConstructor
      @RequestMapping("/user-coupons")
      @Api(tags = "优惠券相关接口")
      public class UserCouponController {
      
          private final IUserCouponService userCouponService;
      
          @ApiOperation("领取优惠券接口")
          @PostMapping("/{couponId}/receive")
          public void receiveCoupon(@PathVariable("couponId") Long couponId){
              userCouponService.receiveCoupon(couponId);
          }
      }

      2.Service层:

      package com.tianji.promotion.service.impl;
      
      import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
      import com.tianji.common.exceptions.BizIllegalException;
      import com.tianji.common.exceptions.DbException;
      import com.tianji.common.utils.BeanUtils;
      import com.tianji.common.utils.CollUtils;
      import com.tianji.common.utils.NumberUtils;
      import com.tianji.common.utils.UserContext;
      import com.tianji.promotion.constants.PromotionConstants;
      import com.tianji.promotion.domain.dto.UserCouponDTO;
      import com.tianji.promotion.domain.po.Coupon;
      import com.tianji.promotion.domain.po.UserCoupon;
      import com.tianji.promotion.enums.UserCouponStatus;
      import com.tianji.promotion.mapper.CouponMapper;
      import com.tianji.promotion.mapper.UserCouponMapper;
      import com.tianji.promotion.service.IUserCouponService;
      import com.tianji.promotion.utils.CodeUtil;
      import lombok.RequiredArgsConstructor;
      import org.springframework.stereotype.Service;
      import org.springframework.transaction.annotation.Transactional;
      
      import java.time.LocalDateTime;
      import java.util.*;
      import java.util.stream.Collectors;
      
      @Service
      @RequiredArgsConstructor
      public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements IUserCouponService {
      
          private final CouponMapper couponMapper;
      
          @Override
          @Transactional
          public void receiveCoupon(Long couponId) {
              // 1.查询优惠券
              Coupon coupon = couponMapper.selectById(couponId);
              if (coupon == null) {
                  throw new BadRequestException("优惠券不存在");
              }
              // 2.校验发放时间
              LocalDateTime now = LocalDateTime.now();
              if (now.isBefore(coupon.getIssueBeginTime()) || now.isAfter(coupon.getIssueEndTime())) {
                  throw new BadRequestException("优惠券发放已经结束或尚未开始");
              }
              // 3.校验库存
              if (coupon.getIssueNum() >= coupon.getTotalNum()) {
                  throw new BadRequestException("优惠券库存不足");
              }
              Long userId = UserContext.getUser();
              // 4.校验每人限领数量
              // 4.1.统计当前用户对当前优惠券的已经领取的数量
              Integer count = lambdaQuery()
                      .eq(UserCoupon::getUserId(), userId)
                      .eq(UserCoupon::getCouponId(), couponId)
                      .count();
              // 4.2.校验限领数量
              if(count != null && count >= coupon.getUserLimit()){
                  throw new BadRequestException("超出领取数量");
              }
              // 5.更新优惠券的已经发放的数量 + 1
              couponMapper.incrIssueNum(coupon.getId());
              // 6.新增一个用户券
              saveUserCoupon(coupon, userId);
          }
      
          private void saveUserCoupon(Coupon coupon, Long userId) {
              // 1.基本信息
              UserCoupon uc = new UserCoupon();
              uc.setUserId(userId);
              uc.setCouponId(coupon.getId());
              // 2.有效期信息
              LocalDateTime termBeginTime = coupon.getTermBeginTime();
              LocalDateTime termEndTime = coupon.getTermEndTime();
              if (termBeginTime == null) {
                  termBeginTime = LocalDateTime.now();
                  termEndTime = termBeginTime.plusDays(coupon.getTermDays());
              }
              uc.setTermBeginTime(termBeginTime);
              uc.setTermEndTime(termEndTime);
              // 3.保存
              save(uc);
          }
      }

      3.Mapper层

      package com.tianji.promotion.mapper;
      
      import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      import com.tianji.promotion.domain.po.Coupon;
      import org.apache.ibatis.annotations.Param;
      import org.apache.ibatis.annotations.Update;
      
      
      public interface CouponMapper extends BaseMapper<Coupon> {
          @Update("UPDATE coupon SET issue_num = issue_num + 1 WHERE id = #{couponId}")
          int incrIssueNum(@Param("couponId") Long couponId);
      }

      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值