【Lilishop商城】No3-11.模块详细设计,促销模块(优惠券、满减、秒杀、积分)的详细设计

仅涉及后端,全部目录看顶部专栏,代码、文档、接口路径在: 

【Lilishop商城】记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客


全篇会结合业务介绍重点设计逻辑,其中重点包括接口类、业务类,具体的结合源代码分析,读起来也不复杂~

谨慎:源代码中有一些注释是错误的,有的注释意思完全相反,有的注释对不上号,我在阅读过程中就顺手更新了,并且在我不会的地方添加了新的注释,所以在读源代码过程中一定要谨慎啊! 

目录

A1.优惠券

B1.M端(属于显式操作)

B2.S端(属于显式操作)

B3.B端(属于显式操作)

B4.consumer端(属于业务操作)

A2.券活动

B1.M端(属于显式操作)

A3.满减

B1.S端(属于显式操作)

B2.M端(属于显式操作)

 A4.秒杀

B1.M端(属于显式操作)

B2.S端(属于显式操作)

B3.B端(属于显式操作)

B4.consumer端(属于业务操作)

A5.A6.拼团和砍价(待记录)

A7.积分商品

B1.积分分类

C1.M端(属于显式操作)

 C2.B端(属于显式操作)

B2.积分商品

C1.M端(属于显式操作)

C1.B端(属于显式操作)


开始前先说一下,促销的各类管理上不是特别的难理解,只要理解各个表结构和页面需要的接口就行,重点在于促销活动的业务service类底层都是实现自一个接口,因为所有的促销都是有相似的通用逻辑(例如,增加促销、修改促销、初始化等等)。

A1.优惠券

B1.M端(属于显式操作)

这儿的接口没啥好说的

  • 获取优惠券列表、通过id获取优惠券详情、添加优惠券、修改优惠券、修改优惠券状态、批量删除
  • 查询全部分类列表(见商品分类,M端)
  • 分页获取商品sku列表(见商品,M端)

    ​   

B2.S端(属于显式操作)

这里的和M端的逻辑类似,只是有些属性需要修改

  • 获取优惠券列表、通过id获取优惠券详情、添加优惠券、修改优惠券、修改优惠券状态、批量删除
  • 获取店铺经营的分类(见商品分类,S端)
  • 分页获取商品Sku列表(见商品,S端)

   

    

B3.B端(属于显式操作)

这里的就是B端前台显示的,和用户已领取的;

但是 获取可领取优惠券列表 接口有点不方便,只返回了平台所有优惠券,并没有标注当前登录账号是否有该优惠券~

  • 获取可领取优惠券列表、获取当前会员的优惠券列表、会员领取优惠券

       

B4.consumer端(属于业务操作)

用户领取的优惠券有截止日期的,所以需要添加定时任务来操作会员优惠券的状态变为过期。

详见:cn.lili.timetask.handler.impl.coupon.CouponExecute

但是不明白,这里为什么用EveryDayExecute,按理说应该用每秒检测的,在线上看这也是按秒的,可能这里写错了~

/**
 * 优惠券状态监测
 *
 * @author Bulbasaur
 * @since 2021/5/24 10:08 上午
 */
@Component
public class CouponExecute implements EveryDayExecute {

    /**
     * 过期常量,过期后或者使用后一定时间内,删除无效的优惠券,物理删除
     */
    static final int EXPIRATION_DAY = 3;

    @Autowired
    private MemberCouponService memberCouponService;

    /**
     * 检测优惠券的使用时间,超期未使用则失效
     * 此方法用于领取*天后失效优惠券使用
     */
    @Override
    public void execute() {
        //业务 1
        //将过期优惠券从领取状态变更为过期状态
        LambdaUpdateWrapper<MemberCoupon> updateWrapper = new LambdaUpdateWrapper<MemberCoupon>()
                .eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name())
                .le(MemberCoupon::getEndTime, new Date())
                .set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name());
        this.memberCouponService.update(updateWrapper);

        //业务 2
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - EXPIRATION_DAY);
        Date removeTime = calendar.getTime();
        //删除过期/已使用的优惠券(过期一定时间后物理删除)
        LambdaUpdateWrapper<MemberCoupon> deleteWrapper = new LambdaUpdateWrapper<MemberCoupon>()
                //如果结束时间小于 当前时间增加指定删除日期,则删除
                .le(MemberCoupon::getEndTime, removeTime);
        this.memberCouponService.remove(deleteWrapper);


    }

}

A2.券活动

根据优惠券添加券活动,关联的会员直接存到主表里面的scope里面,关联的券存到子表li_coupon_activity_item 里面。

这个业务就是给指定用户发放优惠券的,他的活动开始时间和结束时间其实没有用,在创建活动的时候就直接给指定用户发放了,并且即便活动未开始、活动已结束也可以使用,所以真正的业务效果是啥呢?TvT

B1.M端(属于显式操作)

  • 获取优惠券活动分页、通过id获取优惠券活动、添加优惠券活动、关闭优惠券活动
  • 获取优惠券列表(见优惠券,M端)
  • 会员分页列表(见会员,S端)

 

A3.满减

满减是由店铺发起的,运营M端可以关闭,其中满减里面回赠送包邮、优惠券、赠品~

包邮会在下单时满足条件的时候去掉邮费,赠送优惠券会在下单付款后赠送会员指定券(该券是店铺创建的活动券),赠品会在下单后生成赠品类型的子订单,价格为零。

同一个商品sku只能存在一个满减活动,所以不能存在多个全品类的满减活动~

满减活动失效是没有定时任务的,对于S端M端来说只是每次获取时进行判断,然后记录状态,表中并不存在状态这个字段,如果想要关闭满减活动,会直接将开始-截止日期清空的,这样会根据时间判断为已关闭。在B端只会在获取sku的详情时会获取该sku绑定的、有效的促销满减活动。

(私以为这样的设计不太合理,这样关闭是不会记录下来这个被关闭的满减活动的开始日期的。所以可以添加一个状态字段来记录,也方便。)

之后的促销活动:秒杀,也是这个逻辑的!

B1.S端(属于显式操作)

  • 根据条件分页查询满优惠活动、通过id获取、新增满优惠活动、修改满优惠活动、删除满优惠活动、修改满额活动状态
  • 获取店铺经营的分类(见商品分类,S端)
  • 分页获取商品Sku列表(见商品,S端)

 

  

B2.M端(属于显式操作)

  • 获取满优惠列表、获取满优惠详情、修改满额活动状态

  

 A4.秒杀

每一天的秒杀是由系统自动添加的,然后想参加的店铺可以往某个秒杀的某个时间里面添加商品sku,运营端可以删除商品sku或者关闭秒杀。

系统一开始就需要先往系统里面添加后几天秒杀,然后之后的每一天都添加秒杀。例如:12-01日系统一开始添加七天的秒杀到 12-08,第二天 12-02 会执行定时任务,继续添加秒杀直到 12-09,由于 12-03 到 12-08 已经添加了定时任务,就会跳过,只添加 12-09 的秒杀。(这只是简单逻辑哈,实际上是判断后7天哪天没有开启的秒杀就添加秒杀,因为已生成的秒杀可以关闭~)

买方B端可以查看秒杀列表,进行秒杀商品购买,秒杀商品即使不再秒杀列表里面也会限时秒杀信息的。秒杀列表只是一个快捷入口。 

B1.M端(属于显式操作)

  • 初始化秒杀活动、分页查询秒杀活动列表、通过id获取、修改秒杀活动、删除一个秒杀活动、操作秒杀活动状态
  • 获取秒杀活动申请列表、删除秒杀活动申请
  • 获取店铺经营的分类(见商品分类,S端)
  • 分页获取商品Sku列表(见商品,S端)

 

 

B2.S端(属于显式操作)

  • 获取秒杀活动列表、通过id获取秒杀活动信息、获取秒杀活动申请列表、通过id获取秒杀活动申请、添加秒杀活动申请、删除秒杀活动商品
  • 获取店铺经营的分类(见商品分类,S端)
  • 分页获取商品Sku列表(见商品,S端)

 

 

B3.B端(属于显式操作)

  • 获取当天秒杀活动信息、获取某个时刻的秒杀活动商品信息

 

B4.consumer端(属于业务操作)

每日定时任务,创建秒杀活动

详见:cn.lili.timetask.handler.impl.promotion.PromotionEverydayExecute

/**
 * 促销活动每日定时器
 *
 * @author Chopper
 * @since 2021/3/18 3:23 下午
 */
@Slf4j
@Component
public class PromotionEverydayExecute implements EveryDayExecute {

    /**
     * ES商品索引
     */
    @Autowired
    private EsGoodsIndexService esGoodsIndexService;
    /**
     * 系统设置
     */
    @Autowired
    private SettingService settingService;
    /**
     * 秒杀活动
     */
    @Autowired
    private SeckillService seckillService;

    /**
     * 将已过期的促销活动置为结束,添加秒杀活动
     */
    @Override
    public void execute() {
        try {
            //清除所有商品索引的无效促销活动
            this.esGoodsIndexService.cleanInvalidPromotion();
        } catch (Exception e) {
            log.error("清楚商品索引中无效促销异常", e);
        }
        try {
            //定时创建活动
            addSeckill();
        } catch (Exception e) {
            log.error("秒杀活动添加异常", e);
        }

    }

    /**
     * 添加秒杀活动
     * 从系统设置中获取秒杀活动的配置
     * 添加明天后的秒杀活动
     */
    private void addSeckill() {
        Setting setting = settingService.get(SettingEnum.SECKILL_SETTING.name());
        SeckillSetting seckillSetting = new Gson().fromJson(setting.getSettingValue(), SeckillSetting.class);
        log.info("生成秒杀活动设置:{}", seckillSetting);
        for (int i = 1; i <= SeckillService.PRE_CREATION; i++) {
            Seckill seckill = new Seckill(i, seckillSetting.getHours(), seckillSetting.getSeckillRule());

            //如果已经存在促销,则不再次保存
            if (seckillService.list(PromotionTools.checkActiveTime(seckill.getStartTime(), seckill.getEndTime(), PromotionTypeEnum.SECKILL, null, seckill.getId())).isEmpty()) {
                boolean result = seckillService.savePromotions(seckill);
                log.info("生成秒杀活动参数:{},结果:{}", seckill, result);
            }
        }
    }
}

A5.A6.拼团和砍价(待记录)

拼团和砍价也是只有买方小程序/APP端才有的业务,买方PC端是没有的。

拼团和砍价的详细业务来不及了解,后面记录。

A7.积分商品

积分商品也是只有买方小程序/APP端才有的业务,买方PC端是没有的。

积分商品的每个活动都包含一个商品sku,并且只由运营M端可以管理积分,店铺S端是不会管理的。添加为积分商品的商品sku下单后的金额为 0 ,也就是这单收益为 0 ,但是在店对账中会通过设置的积分结算金额再补给店铺,所以最终可以说是运营端出费的~~~(补充一下平台优惠券也是会在结算时补给店铺,具体补多少看优惠券里面店铺占比的~)

积分分类是为了买方B端进行的分类,和商品没关联的。

B1.积分分类

C1.M端(属于显式操作)

  • 获取积分商品分类分页、通过id获取积分商品分类、添加积分商品分类、修改积分商品分类、删除积分商品分类

 

 C2.B端(属于显式操作)

这个接口直接放到了买方端的积分商品里面,见积分商品,买方B端。

B2.积分商品

C1.M端(属于显式操作)

  • 分页获取积分商品、通过id获取积分商品详情、添加积分商品、修改积分商品、删除积分商品、修改积分商品状态

 

  

C1.B端(属于显式操作)

  • 分页获取积分商品、获取积分活动商品

  • 获取积分商品分类分页

 

猜你喜欢

转载自blog.csdn.net/vaevaevae233/article/details/128373032