购物车下单和商品直接购买,有很大的不同,其中最大的不同点就是购物车下单可以同时购买多种商品,并且购物车中的商品还会按照不同的属性进行分组,生成不同的订单,对应不同的发货流程,这里先不考虑那么复杂的场景,先从简单的设计。
首先,我们要知道,在普通的电商项目中,每个用户都有唯一一个购物车(shopping_cart),购物车会显示商品数量,商品总价格等信息,那么来设计一下购物车的表结构
字段 | 类型 | 说明 |
---|---|---|
id | num | 购物车id |
item_count | num | 商品总数 |
selected_item_count | num | 选中的商品总数 |
total_price | num | 购物车中选中商品的实际总价格 |
real_total_price | num | 购物车中选中商品的优惠后总价格 |
order_count | num | 购物车中订单数量 |
select_order_count | num | 购物车中勾选的订单数量 |
uid | num | 用户id |
上面对应的就是一个简单的购物车字段结构,由于先不考虑商品分组,优惠信息等情况,暂时先设计这些字段
按照上面的设计,当一个用户创建的时候,就会产生一个专属于这个用户的购物车
初始化的购物车信息
{
"id": 1299477521234563,
"item_count": 0,
"selected_item_count":0,
"total_price": 0,
"real_total_price": 0,
"order_count": 0,
"select_order_count": 0,
"uid": 123456
}
下面我们要将商品添加到购物车中
顺着文章一的设计,添加商品的时候,生成一个订单order
,并将相应的价格信息更新到购物车数据中,并且正常情况下添加进购物车的订单都是被选中的,此时我们要在order
中追加两个字段
字段 | 类型 | 说明 |
---|---|---|
shopping_cart_id | num | 购物车id(通过该id将购物车和订单关联) |
is_selected | num | 订单是否被选中(0=未选中,1=选中)默认是1 |
此时将一个商品添加进购物车后,相应的生成的订单数据结构如下
{
"id": 1299477521523456,
"state": 0,
"item_id":1299477521563661,
"name": "可口可乐",
"sub_name": "可口可乐真好喝",
"title_pics": ["我是图片连接","我是图片连接"],
"total_count": 10,
"item_price": 1,
"settlement_price": 100,
"uid": 123456,
"shopping_cart_id":1299477521234563,
"is_selected":1
}
此时的购物车数据如下
{
"id": 1299477521234563,
"item_count": 10,
"selected_item_count":10,
"total_price": 100,
"real_total_price": 100,
"order_count": 1,
"select_order_count": 1,
"uid": 123456
}
由于这里还未设计优惠信息,所以total_price
和real_total_price
的值是相同的,后续关于优惠信息的文章会讲解这一部分
接下来对购物车的操作分一下几种情况
- 将多种商品添加进购物车,创建新的
order
并更新购物车中的数据信息 - 删除某个商品,将对应的
order
删除并更新购物车中数据信息 - 对购物车中的订单进行选中或未选中操作做,更新
order
中的is_selected
值,并对购物车的数据信息进行更新 - 修改某个商品数量,更新对应
order
信息,并更新购物车数据信息
接下来是将选中的商品从购物车中提取出来,生成即将支付的订单,此时或许已经发现了问题,我们不能再生成order
了,一方面order
的设计不满足多种商品的订单要求,另一方面再生成order
,无法区别购物车订单和支付订单的区别,这时要再设计一种订单,姑且叫总订单(user_order),实际上前后端展示在用户界面的是这个user_order
的数据信息
字段 | 类型 | 说明 |
---|---|---|
id | num | 总订单id |
uid | num | 用户id |
state | num | 订单状态:-2=订单支付失效(未在指定时间内支付);-1=删除;0=在购物车中;1=待付款;2=已支付(代发货);3=已发货(待收货);4=待评价;5=交易完成;6=已取消;7=维权中(退款中);8=订单关闭(全额退款);9=部分退款(维权成功);10=退款拒绝(维权失败) |
total_price | num | 订单总价格(含商品费用,运费,保险费用等,再减去优惠的价格) |
item_total_price | num | 商品总价格 |
ship_fee | num | 邮费 |
sub_order_count | num | 子订单数量 |
这里只是列举了重要字段,实际上user_order
中还有很多信息,例如优惠减免价格、是否支持退货、收货地址id(对应查找收货地址信息)、改签状态等
那么,当从购物车中提取商品订单order
生成总订单user_order
的时候,我们生成的user_order
大致是这样的
{
"id": 1299477521238888,
"uid": 123456
"state": 1,
"total_price":105,
"item_total_price": 100,
"ship_fee": 5,
"sub_order_count": 1
}
此时购物车勾选出的商品订单order
中要再追加一个字段
字段 | 类型 | 说明 |
---|---|---|
user_order_id | num | 总订单id(通过该id将总订单和子订单关联) |
那么我们总结一下,当从购物车中选出商品,形成支付信息的时候要做的操作
- 生成总订单
user_order
,再次强调,实际前后台显示在用户面前的是user_order
中的信息,这个很重要 - 更新
order
中的state
字段为1(表示订单已经不是购物车订单),并在order
中追加字段user_order_id
- 更新
shopping_cart
相关数据信息
注意事项:从购物车中挑选出商品形成user_order
的时候,此时user_order
和order
的具体状态state
字段要看具体的产品需求,只有真正的生成未支付订单时state
字段才会等于1,并且更新shopping_cart
信息
此时再做接口设计
- 只要根据uid就可以查出相应的购物车信息
shopping_cart
以及根据order
中的state
字段(等于0)和shopping_cart_id
查出购物车中的商品订单order
用于给前端展示 - 根据uid可查出生成的总订单信息
user_order
以及根据order
中的user_order_id
查出总订单中对应的子订单order
用于给前端展示
注意:user_order
中没有具体的商品信息,只有对应的价格等信息
接下来的付款、发货、收货、评价等对订单操作的流程,只要更新对应的状态state
字段即可
结合前面的文章一,或许我们对于两种不同的购物流程给前端同学返回的数据结构是不一样的,文章一直接购买只返回一个order
,而购物车下单却返回一个user_order
外加多个order
,这样似乎对前端开发很不友好,同样都是订单,却有不同的数据结构
综合考虑,为了追求数据结构的一致性,在直接下单的购物流程中也要生成user_order
,这样数据结构的一致性对开发来说是很好的一件事情
此时,我们要在order
和user_order
中都各自追加一个字段
order
中追加的字段
字段 | 类型 | 说明 |
---|---|---|
order_type | num | 订单类型:0=购物车订单;1=立即购买订单;2=虚拟电商购物车;3=虚拟电商立即购买;199=改签订单;200=优惠券(主要用于后端逻辑) |
user_order
中追加字段
字段 | 类型 | 说明 |
---|---|---|
user_order_type | num | 订单类型:0=实物购物车产生的用户订单;1=实物立即购买产生的用户订单;2=虚拟购物车产生的用户订单;3=虚拟立即购买产生的用户订单; 199=改签订单;200=优惠券(主要用于后端逻辑) |
其中的虚拟物品购买暂时先不做考虑,值区分购物车购买和直接下单购买
另外说一下这两个字段的其他用处
除了简单的区分订单类型之外,在用户进行下单操作的时候,由于这两个字段的存在,每次用户下单我们只要update原有的user_order
即可,而不用每次都new数据
例如,第一次我们下单某商品,new一个user_order
数据,其中
{
"state": 0,
"user_order_type": 1,
"uid": 123456
}
这样,只要订单的state
状态不变(即订单未变成待付款订单),每次客户下单的时候,只要根据state
、user_order_type
、uid
查出相应的user_order
更新即可,而不是每次客户下单都要new一个新的user_order
,也就是说每个用户uid
会只有一个state
等于0的user_order
,只有当state
状体变为1才会再创建一个state
等于0的新user_order
,这样做似乎更合理(注意:订单状态state
由0变成1的操作时不可逆的)
另外在创建数据的时候,尽量保证创建的数据都有用,而不是创建很多临时数据,用后在删除,这样做风险很大。后台真正操作删除数据,应该是在用户的手动物理删除操作的时候。