电商系统运费计算模块设计

本文试图做一个模型设计上的思考试验,试图在需求没有细化、很有可能需要变更的情况下,做一个高度弹性、能充分应对需求变更的数据结构设计。

而电商系统的运费计算模板设计,是一个很常见的功能,虽然每个系统可能有一些定制化的要求,但总体的方式应该是在一定范围内的,主要参考淘宝、京东(有自营店)的常见方式。

所以以此做一个数据结构设计训练的发端与范例。

总体需求说明

系统能够根据客户选择的运送方式快递类型,以及用户所在的地区自动计算运费

设计需求与约束说明

  1. 模板需要支持包邮与不包邮
  2. 计费方式需要支持固定邮费、按件、按重量、按体积,并且需要支持2段计费,如10kg以内10元,每增加1kg加0.5元
  3. 支持用户选择不同的快递类型,但计费方式与运送区域可由商家配置
  4. 支持条件包邮,条件包括订单满一定金额(考虑跨店订单不能累加)、处于一定区域、商品数量在一定范围内,条件可并列,且支持多个条件(可支持and/or)
  5. 分区域计费的粒度暂时定为省级别,且可以直接设置全国默认

表结构设计

从上述需求可以看到有三个对象:整体计费模板、包邮条件、计费方式

初步表设计如下:


运费计算规则-FreightRule

列名 数据类型 备注
规则名称-name string -
是否包邮-free boolean 不包邮规则必须绑定计费方式
是否条件包邮-freeConditional boolean 选择条件包邮的规则必须绑定包邮条件数据
计费方式-chargeMode enum 固定、按件、按重量、按体积

包邮条件-FreightFreeCondition

列名 数据类型 备注
运费规则外键-FreightRuleId foreign key -
包邮地区-regions string 将地区名或id用连字符连接,留空表示全国
包邮件数-minPiece int 超过此件数包邮
包邮重量-minWeight int 超过此重量包邮
包邮体积-minVolume int 超过此体积包邮
包邮金额-minAmount int 超过此金额包邮

运费计算方式-FreightChargeMode

列名 数据类型 备注
运费规则外键-FreightRuleId foreign key -
适用地区-regions string 将地区名或id用连字符连接,留空表示全国
是否默认-default boolean 如果地区匹配失败,那么选中此条
快递公司-expressType enum -
固定邮费-fixedPrice int -
首件数量-firstPiece int -
首重数量-firstWeight int -
首体积-firstVolume int -
首段费用-firstPrice int -
续件数量-secondPiece int -
续重数量-secondWeight int -
续体积-secondVolume int -
续段费用-secondPrice int -

运费计算方法设计

单商品运费计算方式

  1. 判断是否包邮
  2. 判断是否满足条件包邮的条件
  3. 根据客户选择的运送方式、所在地区查询计费方式
  4. 计算运费

多商品(购物车)运费计算方式

  1. 如果多商品全部属于同一种计费方式,那么计算出最大首费+最小续费
  2. 如果多商品不属于同一种计费方式,此处将成为业务设定的难点,也从没在各大电商网站看到解决此问题的好方案,可选方案:
    • 将相同计费方式合算,最后累加不同计费方式(背后的逻辑是,相同的计费方式的商品会在同一个快递,不同的计费方式会在不同的快递)
    • 全部累加(背后的逻辑是,即使是相同的计费方式,也不一定或者不会发一份快递,比如同样按重量计费的大米与木地板,不会放在同一个包裹)

喵书商城表结构待改造部分

订单表

订单表需要添加字段标识用户选择的运送方式,增加字段保存运费值,将商品金额转移到订单行表上,并且记录原价与实际支付价格。

关于网站自营与商家店铺的区分

由于商家店铺与网站自营的商品不可能放在同一份快递,所以必须拆订单,分别计算运费。

参考文献

http://www.cnblogs.com/lintao0823/p/4230425.html