跳到主要内容

订单架构

购物车架构思路​

难点​

购物车促销的显示和价格计算

结算页促销的显示和价格计算

计算和显示逻辑复杂,还要时时判断活动的有效性

两个地方的购物车显示和计算,有一样的逻辑的地方,也有差异的

思路​

一、将存储分为两部分:

sku原始数据

用户选择的促销活动

每次购物车的显示,都根据这些数据进行一次重新渲染和计算

二、将促销规则的算法和计算分开

抽像出规则对象,由每个活动根据原始数据去生成这些规则

然后统一将这些规则进行计算形成要显示的效果和价格

三、把不可避免的耗性能的操作,放在加入购物车中完成,而不是在列表循环中完成

领域模型​

image-20181225171446757

CartVO​

属性说明备注
skuList规格列表对应CartSkuVO对象
sellerId卖家id
price价格对象对应PriceDetailVO对象
ruleList促销规则列表对应PromotionRule对象
couponList优惠卷列表对应CouponVO对象
giftList赠品列表对应FullDiscountGiftDO
giftCouponList赠送优惠卷列表对应CouponVO对象
promotionNotice促销提示目前只有满优惠提示

CartSkuVO​

属性说明备注
name商品名称
skuIdskuid
specList规则列表对应SpecValueVo对象
singleList单品活动列表对应CartPromotionVo对象,显示在列表中供用户选择
groupList组合活动列表对应CartPromotionVo对象
invalid是否失效
errorMessage失效原因
originalPrice商品原价用于计算优惠的基础价格
purchasePrice成交价
num数量
subtotal小计
promotionTags促销标签显示当前sku应用了何种优惠

PriceDetailVO​

属性说明备注
originalPrice原价
goodsPrice成交价
freightPrice运费
totalPrice合计
discountPrice总优惠价格
cashBack返现金额所有单品活动产生的优惠
fullMinus满减金额
couponPrice优惠卷抵扣金额不计在返现中
isFreeFreight是否免运费
exchangePoint用了多少积分用于兑换此商品

PromotionRule​

属性说明备注
originalPrice原价
goodsPrice成交价
freightPrice运费
totalPrice合计
discountPrice总优惠价格
cashBack返现金额所有单品活动产生的优惠
fullMinus满减金额
couponPrice优惠卷抵扣金额不计在返现中
isFreeFreight是否免运费
exchangePoint用了多少积分用于兑换此商品

CouponVO​

属性说明备注
memberCouponId会员优惠卷id会员领取后的唯一id,取消时或使用时 要用此id
couponId此优惠卷的id会员领取后,此值不变,不能做为使用时调用
sellerId卖家id
amount面值
endTime有效期到秒的时间戳
useTerm使用条件如:“满100元可用”
selected是否选中当用户选择此优惠卷时,会标记为1,未选中时为0
enable是否可用当不可用时(不满足条件或已过期)为0,可用为1

数据存储​

image-20181225173644308

SelectedPromotionVo​

属性说明备注
singlePromotionMap用户选择的单品活动
couponMap用户选择的优惠卷

1、singlePromotionMap​

类型:Map\<Integer, List\<PromotionVO>>

key是店铺id ,对应此店铺对应的促销活动

2、couponMap​

类型:Map\<Integer,CouponVO>

key是店铺id ,对应此店铺使用的优惠卷

项前缀连接存储对象
购物车原始数据CART_ORIGIN_DATA_PREFIXbuyer.uidList\<CartSkuOriginVo>
购物车促销CART_PROMOTION_PREFIXbuyer.uidSelectedPromotionVo

购物车的添加​

image-20181225182540835

1、调用原始数据业务类(CartOriginDataManager)的添加方法

根据sku读出商品数据,并形成CartSkuOriginVo

2、填充促销信息

读取此商品的促销活动,填充到上述的Vo中

此时如果传递了要使用的活动id(需要使用活动的,见下面)

3、写入缓存

形成list\<CartSkuOriginVo>并写入redis

4、使用活动

如果传递了活动id,则调用CartPromotionManager 使用此活动

5、写入缓存

在使用活动时,会将组合好的 singlePromotionMap 写入redis

购物车显示​

通过“建造者”模式来完成购物车的促销信息渲染、价格计算的。

其中要建造的“产品”是CartView,包含一个List和一个price 对象(即列表和总价)

建造过程是一条流水线:

image-20181225211540226

1、首先由SkuRenderer(Sku构建器)构建出全新的一个CartList

这个CartList是由缓存中OriginSku的skulist做为物料生成出来的

2、接下来由促销规则渲染器(PromotionRuleRenderer)构建出促销规则(Promotion)

此时的物料是用户选择的Promotiont生成出来的,具体的制造过程参见《促销规则的构建》

3、流水线中下一个制造环节是生产Price

此时的物料是上一步生产的Rule,按照一定的规则算法对价格进行计算:

具体的制造过程参见《价格的计算过程》

4、流水线是由CartBuilder来总体控制的,最终由他来组装成品:CartView

调用时序如下:

image-20181225183038761

促销规则的构建​

根据需求,促销规则主要有以下几种:

组合促销:满减

单品促销:第二件半价、单品立减、团购,秒杀等

优惠卷

其中组合促销是应用在整个购物车中的,

单品促销是应用在Sku上的,

优惠卷只有在结算页才能使用和计算,而且不计算在返现金额中。

综上所述,我们分别针对如上的种类,定义了:

SkuPromotionRuleBuilder(Sku促销规则构建器)

CartPromotionRuleBuilder(Cart促销规则构建器)

CartCouponRuleBuilder(优惠卷促销规则构建器)

image-20181225232451394

image-20181225231316997

调用关系上:

先调用CartPromotionManager 获取已经选中的促销

再分别调用各种构建器构建出Rule,

从流水线的控制上,优惠卷的构建是要被跳过的(因为购物车是不处理优惠卷的)

将Rule分别放在Cart和Sku中的Rule中

SKU规则构建器​

image-20181225232956964

根据目前的单品促销类型,实现了5个具体的构建器:

SeckillPluginNew 秒杀

GroupBuyGoodsPluginNew 团购

MinusPluginNew 单品立减

HalfPricePluginNew 第二件半件

ExchangePluginNew 积分兑换

具体调用哪个构建器完build rule ,则由实现者的

getPromotionType(): PromotionTypeEnum

方法来决定

Cart规则构建器​

image-20181225233256999

这是应用在购物车上的规则构建器,目前只有一个满减的实现

优惠卷规则构建器​

image-20181225233324221

目前只有一个默认实现

结算页购物车的显示和价格计算​

根据需求,在结算页要计算运费和优惠卷,因此在流水线上要控制其制造流程:

image-20181225235022698

在促销规则的构建过程中加入了优惠卷的构建

在计算价格之前加入了运费的计算

在最后加入了优惠卷的渲染CartVo中的CouponLIst

购物车构建器的总体类图​

那么最终购物车构建器总体类图如下:

image-20181225235312791

促销规则和价格计算​

促销规则​

从上面的架构可以看出,促销规则的定义非常重要,可以参见《PromotionRule》,即:

image-20181225235539403

在这里我们定义了:

reducedTotalPrice是总体减的金额

reducedPrice:是单品减的金额

useCoupon:是要使用的优惠卷

invalid: 定义了是否失效了,比如加入购物车时活动还有效,但过了一会正好失效了。

invalidReason:

不光定义了失效的原因,还有一些特殊情况:比如加入购物车是商品活动售空数是5,买了5个,过了一会别人下单成功了,售后数是3个了,此时在这里要提示用户,但不失效,用户可以勾选改为3个继续下单

价格计算​

价格计算统一面向规则,而不管规则的构建过程,从而实现了算法和计算的分离。

这是在CartPriceCalculator中来完成的,实现过程就比较简单了:

将规则循环,进行相应的扣减和记录,构建出Price