Authored by foxxy

促销重构

背景:
> 当前系统优惠券发放途径分散各处,维护成本高,且问题较多,无法打开产能,运营效率低下。
营销管理券相关:![Alt text](./QQ截图20160503104732.jpg)
促销活动:![Alt text](./1462349575530.png)
改造点:
1.新增优惠券,审批完成之后不再生成券号,只定义券的总数,前台发券时去控制发券是数量不超过后台定义的这个总数,并在发券的时候生成对应的券码(不再先生成码,然后再去码的池里面获取没有使用的码)。
2.领取规则和使用规则抽象,两者之间不能混淆。
`2.1`领取规则主要定义券的可领取时间,和用户相关信息的限定规则,包括黑名单,用户渠道等等。
`2.2`使用规则主要限定券可用的商品、品牌,订单金额等等。
3.券的使用规则逻辑类聚到促销,不再散落在订单模块。
实现细节(除公开券之外):
**发券**
1、校验用户是否已经领取--->校验券的基本信息--->校验领取规则。
2、校验领取是否已经超过最大券数,券总数做原子性递减,当为小于或等于0时报错(缓存失效之后回填数据库,将券总数-领取记录总数的值回填到redis),实现可参考计数器RedisCounter。
3、生成唯一优惠券码,插入到用户的领取记录表中,同时清除<用户id,券id,是否领取>hash结构的key。
4、发送券领取成功的消息盒子。
**查询用户可用券和不可用的券**
1、查询出用户所有可用的券(状态正确,在有效期内的)
2、根据商品,订单金额,用户身份,品牌等条件匹配出可以用的券
**检查券是否可用**
1、用户是否有该券,在用户的领取记录里面,先从缓存hash中查询用户id+券ID是否存在,缓存查不到查数据。
2、验证券本身的基本信息,这里可以直接查询券的信息(后续如果有性能瓶颈,券的基本信息这里可以缓存在redis里面几分钟,暂时不考虑)。
3、验证券是否已经使用,根据券类型不同做验证(公开券每人只能用一次,且不能超过最大使用次数)。
4、验证券是否符合这些商品,品牌,分类,身份,订单金额等(使用规则验证)。
**用券**
1、用户是否有该券,在用户的领取记录里面,先从缓存hash中查询用户id+券ID是否存在,缓存查不到查数据。
2、验证券本身的基本信息,这里可以直接查询券的信息(后续如果有性能瓶颈,券的基本信息这里可以缓存在redis里面几分钟,暂时不考虑)。
3、验证券是否已经使用,根据券类型不同做验证,公开券每人只能用一次,且不能超过最大使用次数。
4、验证券是否符合这些商品,品牌,分类,身份,订单金额等(使用规则验证)。
5、 修改券为已经使用。
**领券中心**
<li>用户如果没登录只查询券的剩余数量(剩余数量先去缓存查询,缓存key不存在就去数据库中查询,数据库中剩余数量=券总数-券 领取记录数,将查询的这个数量设置到缓存中,缓存时间为1天)。
<li> 用户登录情况下, 用户是否领取用 redis hash结构 <uid,couponid,Y>,如果key不存在,批量根据用户id和券id批量查询数据库,查到就放缓存,缓存时间为1天,如果用户本身没券,在redis中维护<uid,couponid,N>,避免每次都要查询数据库。
<li>用户在领券时清除用户的缓存,同时将券的剩余数减1,这里是原子性的操作。
**客服补券**
直接掉前台提供的发券接口给用户发券
**公开券**
公开券还是要先生成券码,这块的逻辑 单独拎开,因为不涉及发放,这里不涉及缓存,直接操作数据库就好,公开券相对较少
... ...