文章目录
概要
领券的本质就是新增一条记录到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);
}

2077

被折叠的 条评论
为什么被折叠?



