前篇回顾
在租车信息系统数据库设计(3)中我们实现了更为细致的车辆出入库管理。
本篇将试图解决剩下的2个问题:
1. 顾客对于租车费用的支付信息如何记录,顾客可以通过预先充值后消费的方式来支付(这也是区分会员级别的关键),该如何支持?
2. 我们在第一篇中暂时没考虑“送车上门和上门取车”服务,要支持这一功能,我们对数据库结构要做些什么改动?
1. 支付管理
对于租车费用的支付,我想到了如下几个关键点:
1. 顾客可以预先向会员卡充值,之后进行消费。
2. 对于一个订单的费用,支付来源可以有多个。例如:订单总费用2500元,顾客选择先用完会员卡中的1000元,再刷卡1500元进行支付。
3. 对于顾客的一次支付,可以对应多个Order。例如:顾客租用了2辆车,在我们的系统中会对应2个Order,顾客可以1次刷卡支付这2个Order的全部费用。
对于关键点1,我们要在系统中为每个顾客创建账户(Account),顾客向会员卡充值或使用会员卡消费都对于一笔流水(Transaction)。
对于关键点2、3,说明了订单与顾客支付之间是一种多对多关系。
我的解决方案如下:
1. 在原先的Table_Customer表中增加Customer_AccountBalance,Customer_AccountCurrency字段,存放顾客账户结余。需要注意的是这个字段的信息是可以通过累加该顾客所有的账户流水得到,有些冗余但能提高获取账户余额的性能。Customer_AccountBalance和账户流水之间是总账和明细账的关系,需要计划一些时间点进行结算(即总账与明细账轧平)。
2. 增加Table_AccountTransaction表,即账户流水表,顾客每次充值与支付都会在该表中增加一条记录。在本设计中,我把顾客支付某Order时的现场刷卡或付现金行为也作为该顾客对自己账户的先充值,之后再从顾客账户扣款支付Order。这种设计方式能减少表的数量、好理解,但所用的顾客刷卡或付现都进入到了总账,之后再与Order关联,无法很明确的得到顾客的某次刷卡是为了支付哪个特定的Order(你只能通过时间和金额来推测)。大家对此可以进行思考,给出解决方案,并比较优劣。
Table_AccountTransaction字段
列名 解释 AccountTransaction_ID Identity字段 Customer_ID 顾客ID,外键 AccountTransactionType_ID 流水类型ID,外键 AccountTransaction_Date 流水产生日期 AccountTransaction_Amount 流水金额(正值为充值,负值为支付) AccountTransaction_ReferenceID 参考号码
1. 充值流水
信用卡:卡号
支票:支票号
现金:为空,
2. 支付流水
为空3. 对于Table_AccountTransaction中的AccountTransactionType_ID字段对应新增表Table_AccountTransactionType中的记录。
Table_AccountTransactionType字段
列名 解释 AccountTransactionType_ID Identity字段 AccountTransactionType_InOutFlag 0为支付,1为充值 AccountTransactionType_Name 账户流水类型名:
1. Cash:现金充值,对应AccountTransactionType_InOutFlag:1
2. Credit Card:信用卡充值,对应AccountTransactionType_InOutFlag:1
3. Check:支票充值,对应AccountTransactionType_InOutFlag:1
4. Pay Order:支付订单,对应AccountTransactionType_InOutFlag:0AccountTransactionType_Description 账户流水类型描述 4. 增加Table_PaymentApplication表,这张表建立了Order与AccountTransaction之间的多对多关系。
Table_PaymentApplication字段
列名 解释 PaymentApplication_ID Identity字段 Order_ID 订单ID,外键 AccountTransaction_ID 账户流水ID,外键 PaymentApplication_Amount 支付金额 PaymentApplication_Date 支付日期
加入支付管理功能后的表关系图
其中用红色标出了新增加的表,用黄色标出了新增加的列。
注意:
1. 一般在一个表中有金额字段时,我都会加一个对应的Currency字段来表示货币类型。在这次新增的Table_AccountTransaction和Table_PaymentApplication中虽有金额字段,但没有对应的Currency字段,这是因为我默认这些记录的Currency与Table_Customer表中新增的Customer_AccountCurrency一致。大家可以根据需要加上Currency字段。
2. 这个支付管理的设计我总感觉不是最好,就如上文解决方案中所说的。我试图给出了另一种设计(增加Table_Payment表,用以记录用户的支付来源,如信用卡信息等。简化Table_AccountTransaction表,只保留金额与时间,对于充值记录对应Table_Payment的ID。对于Table_PaymentApplication,可能有两种来源一种是直接的Payment,对应Table_Payment记录,另一种是用户Account,对应Table_AccountTransaction记录),但也并不满意。大家可以进行更多的尝试,并欢迎分享。
2. 送车上门和上门取车
这个功能是之前省略的,但现在的市场竞争如此激烈。提供这样的功能来提升用户满意度还是必须的。
对于这个功能有3个要求:
1. 系统应允许顾客在创建Order时选择送车上门和上门取车服务,并提供输入界面。
2. 顾客首次输入一个新地址后,该地址应被记录系统,供用户下次选择(就像淘宝送货地址一样)。
3. 顾客可以存储多个地址,并能改变地址的优先级(影响显示顺序),或设定Default地址。
解决方案:
1. 增加一个Table_CustomerAddress表,记录顾客多个可选地址。
Table_CustomerAddress字段
列名 解释 CustomerAddress_ID Identity列 Customer_ID 顾客ID,外键 CustomerAddress_Country 国家 CustomerAddress_Province 省 CustomerAddress_City 城市 CustomerAddress_Address 详细地址 CustomerAddress_Rank 地址等级(数字越小等级越高,显示在最前面。1为Default地址) 2. 有了Table_CustomerAddress表,Table_Customer中的Customer_Address可以去除。
3. 在Table_Order中,把Order_BorrowStore字段名改为:Order_GetCarLocation,增加Order_IsGetCarAtHome是否送车上门字段(bit类型字段),若该字段为1,则Order_GetCarLocation字段记录顾客选择的送车上门地址ID,若为0,则记录门店ID。同理,把Order_ReturnStore字段名改为:Order_ReturnCarLocation,增加Order_IsReturnCarAtHome是否上门取车字段。
加入送车上门和上门取车功能后的表关系图
图中用黄色标出了相应做的改变。
下篇预告
至此租车信息系统数据库设计基本完成了。
下一篇我们以这个设计为基础来写一些常见的查询,如:顾客试图预订某型号车,并给出了需要租借的时间段,写一个查询来查找该车型的车辆相应时间是否有档期,如果有则创建相应的Order(如果有该车型的多辆车有档期,安排哪辆车能使车辆利用率最高呢?这个需要进一步思考)。
思考这些查询也算是验证先前的设计,一般在这个过程中有时会发现一些设计上的疏漏。