电商系统运费计算模块设计
本文试图做一个模型设计上的思考试验,试图在需求没有细化、很有可能需要变更的情况下,做一个高度弹性、能充分应对需求变更的数据结构设计。
而电商系统的运费计算模板设计,是一个很常见的功能,虽然每个系统可能有一些定制化的要求,但总体的方式应该是在一定范围内的,主要参考淘宝、京东(有自营店)的常见方式。
所以以此做一个数据结构设计训练的发端与范例。
总体需求说明
系统能够根据客户选择的运送方式快递类型,以及用户所在的地区自动计算运费
设计需求与约束说明
- 模板需要支持包邮与不包邮
- 计费方式需要支持固定邮费、按件、按重量、按体积,并且需要支持2段计费,如10kg以内10元,每增加1kg加0.5元
- 支持用户选择不同的快递类型,但计费方式与运送区域可由商家配置
- 支持条件包邮,条件包括订单满一定金额(考虑跨店订单不能累加)、处于一定区域、商品数量在一定范围内,条件可并列,且支持多个条件(可支持and/or)
- 分区域计费的粒度暂时定为省级别,且可以直接设置全国默认
表结构设计
从上述需求可以看到有三个对象:整体计费模板、包邮条件、计费方式
初步表设计如下:
运费计算规则-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 | - |
运费计算方法设计
单商品运费计算方式
- 判断是否包邮
- 判断是否满足条件包邮的条件
- 根据客户选择的运送方式、所在地区查询计费方式
- 计算运费
多商品(购物车)运费计算方式
- 如果多商品全部属于同一种计费方式,那么计算出最大首费+最小续费
- 如果多商品不属于同一种计费方式,此处将成为业务设定的难点,也从没在各大电商网站看到解决此问题的好方案,可选方案:
- 将相同计费方式合算,最后累加不同计费方式(背后的逻辑是,相同的计费方式的商品会在同一个快递,不同的计费方式会在不同的快递)
- 全部累加(背后的逻辑是,即使是相同的计费方式,也不一定或者不会发一份快递,比如同样按重量计费的大米与木地板,不会放在同一个包裹)
喵书商城表结构待改造部分
订单表
订单表需要添加字段标识用户选择的运送方式,增加字段保存运费值,将商品金额转移到订单行表上,并且记录原价与实际支付价格。
关于网站自营与商家店铺的区分
由于商家店铺与网站自营的商品不可能放在同一份快递,所以必须拆订单,分别计算运费。