首页 > 其他分享 >领取优惠券

领取优惠券

时间:2022-10-19 23:12:36浏览次数:43  
标签:COMMENT 优惠券 领取 DEFAULT new NULL id

需求介绍

  • 优惠券业务需求介绍

    • 新用户注册-发放后端配置的新人优惠券
    • 用户可以主动领取优惠券
    • 下单可以选择对应的优惠券抵扣
    • 支持满减优惠券-无门槛优惠券两种
    • 多种元数据配置
      • 类型:无门槛、满减等
      • 每人领劵次数限制
      • 发券总量控制
      • 优惠券开始时间和结束时间
      • 优惠券状态配置
  • 核心知识:

    • 高并发下扣减劵库存
      • 超发
      • 单人超领取
  • 原生分布式锁+redisson框架分布锁使用

    • 分布式锁+最佳实践
  • 数据库表介绍

#优惠券表
CREATE TABLE `coupon` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `category` varchar(11) DEFAULT NULL COMMENT '优惠卷类型[NEW_USER注册赠券,TASK任务卷,PROMOTION促销劵]',
  `publish` varchar(11) DEFAULT NULL COMMENT '发布状态, PUBLISH发布,DRAFT草稿,OFFLINE下线',
  `coupon_img` varchar(524) DEFAULT NULL COMMENT '优惠券图片',
  `coupon_title` varchar(128) DEFAULT NULL COMMENT '优惠券标题',
  `price` decimal(16,2) DEFAULT NULL COMMENT '抵扣价格',
  `user_limit` int(11) DEFAULT NULL COMMENT '每人限制张数',
  `start_time` datetime DEFAULT NULL COMMENT '优惠券开始有效时间',
  `end_time` datetime DEFAULT NULL COMMENT '优惠券失效时间',
  `publish_count` int(11) DEFAULT NULL COMMENT '优惠券总量',
  `stock` int(11) DEFAULT '0' COMMENT '库存',
  `create_time` datetime DEFAULT NULL,
  `condition_price` decimal(16,2) DEFAULT NULL COMMENT '满多少才可以使用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4;


#优惠券领劵记录
CREATE TABLE `coupon_record` (
  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
  `coupon_id` bigint(11) DEFAULT NULL COMMENT '优惠券id',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间获得时间',
  `use_state` varchar(32) DEFAULT NULL COMMENT '使用状态  可用 NEW,已使用USED,过期 EXPIRED;',
  `user_id` bigint(11) DEFAULT NULL COMMENT '用户id',
  `user_name` varchar(128) DEFAULT NULL COMMENT '用户昵称',
  `coupon_title` varchar(128) DEFAULT NULL COMMENT '优惠券标题',
  `start_time` datetime DEFAULT NULL COMMENT '开始时间',
  `end_time` datetime DEFAULT NULL COMMENT '结束时间',
  `order_id` bigint(11) DEFAULT NULL COMMENT '订单id',
  `price` decimal(16,2) DEFAULT NULL COMMENT '抵扣价格',
  `condition_price` decimal(16,2) DEFAULT NULL COMMENT '满多少才可以使用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=141 DEFAULT CHARSET=utf8mb4;

分页查询优惠券

思路:查询为发布状态并且是促销优惠券类型的优惠券信息

@Override
public Map<String, Object> pageCouponActivity(int page, int size) {

    Page<CouponDO> pageInfo = new Page<>(page,size);

    IPage<CouponDO> couponDOIPage =  couponMapper.selectPage(pageInfo, new QueryWrapper<CouponDO>()
                                                             .eq("publish",CouponPublishEnum.PUBLISH)
                                                             .eq("category", CouponCategoryEnum.PROMOTION)
                                                             .orderByDesc("create_time"));

    Map<String,Object> pageMap = new HashMap<>(3);
    //总条数
    pageMap.put("total_record", couponDOIPage.getTotal());
    //总页数
    pageMap.put("total_page",couponDOIPage.getPages());

    pageMap.put("current_data",couponDOIPage.getRecords().stream().map(obj->beanProcess(obj)).collect(Collectors.toList()));


    return pageMap;
}

private CouponVO beanProcess(CouponDO couponDO) {
    CouponVO couponVO = new CouponVO();
    BeanUtils.copyProperties(couponDO,couponVO);
    return couponVO;
}

问题:HashMap初始化时为什么建议使用HashMap(int initialCapacity)

领取优惠券

思路:

* 领劵接口
* 1、获取优惠券是否存在
* 2、校验优惠券是否可以领取:时间、库存、超过限制
* 3、扣减库存
* 4、保存领劵记录
@Override
public JsonData addCoupon(long couponId, CouponCategoryEnum category) {

    LoginUser loginUser = LoginInterceptor.threadLocal.get();

    CouponDO couponDO = couponMapper.selectOne(new QueryWrapper<CouponDO>()
                                               .eq("id",couponId)
                                               .eq("category",category.name()));


    //优惠券是否可以领取
    this.checkCoupon(couponDO,loginUser.getId());


    //构建领劵记录
    CouponRecordDO couponRecordDO = new CouponRecordDO();
    BeanUtils.copyProperties(couponDO,couponRecordDO);
    couponRecordDO.setCreateTime(new Date());
    couponRecordDO.setUseState(CouponStateEnum.NEW.name());
    couponRecordDO.setUserId(loginUser.getId());
    couponRecordDO.setUserName(loginUser.getName());
    couponRecordDO.setCouponId(couponId);
    couponRecordDO.setId(null);


    //扣减库存  TODO
    int rows = 1; //couponMapper.reduceStock(couponId);

    if(rows==1){
        //库存扣减成功才保存记录
        couponRecordMapper.insert(couponRecordDO);

    }else {
        log.warn("发放优惠券失败:{},用户:{}",couponDO,loginUser);

        throw  new BizException(BizCodeEnum.COUPON_NO_STOCK);
    }

    return JsonData.buildSuccess();
}


private void checkCoupon(CouponDO couponDO, Long userId) {

    if(couponDO==null){
        throw new BizException(BizCodeEnum.COUPON_NO_EXITS);
    }

    //库存是否足够
    if(couponDO.getStock()<=0){
        throw new BizException(BizCodeEnum.COUPON_NO_STOCK);
    }

    //判断是否是否发布状态
    if(!couponDO.getPublish().equals(CouponPublishEnum.PUBLISH.name())){
        throw new BizException(BizCodeEnum.COUPON_GET_FAIL);
    }

    //是否在领取时间范围
    long time = CommonUtil.getCurrentTimestamp();
    long start = couponDO.getStartTime().getTime();
    long end = couponDO.getEndTime().getTime();
    if(time<start || time>end){
        throw new BizException(BizCodeEnum.COUPON_OUT_OF_TIME);
    }

    //用户是否超过限制
    int recordNum =  couponRecordMapper.selectCount(new QueryWrapper<CouponRecordDO>()
                                                    .eq("coupon_id",couponDO.getId())
                                                    .eq("user_id",userId));

    if(recordNum >= couponDO.getUserLimit()){
        throw new BizException(BizCodeEnum.COUPON_OUT_OF_LIMIT);
    }
}

标签:COMMENT,优惠券,领取,DEFAULT,new,NULL,id
From: https://www.cnblogs.com/youngleesin/p/16808170.html

相关文章