您好,欢迎来到意榕旅游网。
搜索
您的当前位置:首页租车系统模块与数据库设计

租车系统模块与数据库设计

来源:意榕旅游网
最近在看《Database modeling & design:logical design》一书,其中有一道练习题是对简单租车系统进行数据库逻辑设计并画出ER图。

这道题给我挺多遐想的,所以我在这里把这些想法记录下来,也试着设计一把。

要进行数据库设计,首先要对需求进行分析。需求分析一般会需要对业务人员进行随访,收集信息。我没办法进行随访,就通过自己的遐想来假设需求场景(可能会有错误与遗漏)。 最初想到的:

1. 租车公司有多个租车门店,分布于多个不同的地区,并有各自的租车电话。 2. 每个租车门店有多辆汽车可供租赁。

3. 供租赁的车辆需要登记车辆识别代号(VIN),购入时间,所属门店,车辆型号,车辆状态(可租Ready,维修中Repair,租出Inuse,无效Inactive)

4. 车辆的租用费用基本由车辆型号和日期类型(平日,周末,还是节假日)来决定。

5. 顾客在订车前需先进行注册,包括姓名,身份证号,驾照号,性别,手机号,固定电话,家庭住址,Email。

6. 注册顾客可通过系统下租车单,预约某车型,若干天的租赁(预约期最远为6个月)。

7. 租车单需记录顾客编号,车辆编号,租赁起始日期,租赁结束日期,提车门店,还车门店,租赁费用,预付款金额,订单状态(输入Entered,提交Booked,预约Reserved,使用中Inuse,交还Returned,取消Cancelled)。注:暂不提供送车上门和上门取车服务。

对于上述需求,比较明显的需创建的表有:车辆(Table_Car),门店(Table_Store),顾客(Table_Customer),订单(Table_Order)。

除此之外,车辆型号,车辆状态,日期类型和订单状态分别创建成四张枚举表Table_CarCategory,Table_CarStatus,Table_DateType,Table_OrderStatus。

还应有一张租车价位对照表(Table_BasePrice),其中会包含两个外键分别指向Table_CarCategory,Table_DateType。 简单表关系图如下:

大部分字段的含义大家可以从命名中猜测到。其中需要注意的有两点:

1. 这一设计中有4张枚举表(Table_DateType,Table_CarCategory,Table_OrderStatus,Table_CarStatus),在实际的信息系统或业务系统中这样的枚举表可能非常多。把这些枚举表整合到一张配置表中会带来哪些好处与哪些坏处?是否还有其他解决方案?大家可以进行思考。

2. 租车价位对照表在图中被设计成Table_BasePrice。其主键为一联合键,包括CarCategory_ID(表明车型,如:乐风 1.6 MT),DateType_ID(表明是平日,周末或节日),BasePrice_StartDate(表明从哪个时间点开始顾客在系统页面看到新的价格),其中CarCategory_ID,DateType_ID同时为外键。这是一种设计方式。

另有2种可选的设计方式:

待选方案1. 把Table_BasePrice中的DateType_ID去除,Table_BasePrice只存某种车型的初始租价。在Table_DateType中多加一列DateType_AdjustRate,存放一个大于等于1的比率,如:平日比率为1.0,双休日为1.1。某一日的基本租价为:比率×初始租价。

待选方案2. 在待选方案1的基础上,直接去除Table_BasePrice表。把BasePrice_Price放到Table_CarCategory中(可改名为CarCategory_Price)。其他修改和方案1相同。

这些方案会影响到系统使用的灵活性,易用性和可追溯性。大家可以对这些方案的优点和缺点进行思考和讨论。

时间差不多了,要去干活了。到现在为止,这一数据模型还远未达到基本可使用的阶段。我们将在其后的篇目中进一步讨论,提出新的需求和挑战,并修改、完善这一设计。 前篇回顾

租车信息系统数据库设计(1)中我们根据租车系统最基本的一些需求,设计出了如下表结构:

有朋友看了这个结构图后问我为什么对于订单没有设计成主从表(即分为OrderHeader,OrderDetail)。 订单的主从表设计在ERP系统中非常常见,在OrderHeader中存放客户信息,在OrderDetail中存放此客户本次订购的多种产品(每种产品若干数量),这种设计也更符合范式。我当初在进行设计时,首先想到的也是主从表设计,但思考了租车的需求场景,我最后选择了现在的这一设计。在我的电影院票务管

理系统数据库设计(2)中对于类似问题进行过详细的分析,所以这里不再展开。但现在的结构也未必是最符合实际需求的,毕竟我是闭门造车,大家可自己思考提出更合理的设计方案。 Order状态问题

在上一篇中我们设计了6种Order状态,分别是:输入Entered,提交Booked,预约Reserved,使用中Inuse,交还Returned,取消Cancelled。对于正常Order的结束状态为Returned,但我在和曾经租过车的同事闲聊后,我觉得需要再加一个Closed状态作为Order结束状态。一般顾客在还车后,租车公司还会收取约600元的预授权,租车公司会检查该车在租用期是否有违章罚款,如若没有,这笔费用将在约两个月后打回顾客卡内。只有到这个时候这个Order才真正结束了(预授权的600元也需要记录在Table_Order表中,大家可以自行加一些列,本文为简化不列出了)。 进一步的分析与设计

第一篇中的设计不能满足现实需求的重要一点是,系统中没有记录顾客实际取车和还车的时间,这对于计算实际费用是至关重要的。当前的设计也无法回答门店库存车辆的变化情况。还有像车辆的维修信息,保险信息也都没有记录在系统中。

我们把这些新的需求进行整理,接在第一篇的需求列表之后: 8. 需记录顾客实际取车和还车的时间,用于计算实际的租车费用。 9. 需记录门店库存车辆的变化情况,跟踪每一辆车的进出库信息。

10. 记录每辆车的维修历史,包括维修的时间,费用,维修公司,维修合同号。 11. 记录每辆车的保险历史,包括保险的时间,费用,保险公司,保险合同号。

12. 注册顾客会有多个等级,对于不同等级会给予不同的折扣率(如:黄金用户有95折的优惠)。 对于需求8,我们要在原先的Table_Order中加入新的列,加入Order_ActualStartDate,

Order_ActualEndDate来记录实际取车和还车时间,还要加入Order_ActualPrice来记录实际产生的租车费用。

对于需求9,我们可以加入一张Table_StoreTransaction表来记录车辆的进出库流水。表中的字段需包括:发生进出库的车辆ID(Car_ID),表示是进库还是出库的标签(StoreTransaction_InOutFlag),进出库的时间(StoreTransaction_Date)。Table_Car与Table_StoreTransaction为一对多关系。

对于需求10,我们要加入一张Table_RepairHistory表,Table_Car与Table_RepairHistory为一对多关系。间接的还会引入一张Table_RepairStation表,来记录维修点信息。Table_RepairStation与Table_RepairHistory之间也为一对多关系。

对于需求11,加入一张Table_InsuranceHistory表,Table_Car与Table_InsuranceHistory为一对多关系。间接引入Table_InsuranceCompany表,记录保险公司信息。Table_InsuranceCompany与Table_InsuranceHistory之间为一对多关系。

对于需求12,加入Table_Class表,表中会存放折扣信息(Class_Discount)。Table_Class与Table_Customer之间为一对多关系。 新的表关系图如下:

上图中用红色框标出了本次增加或改变的表和字段。

其中需要注意的是Table_StoreTransaction表中用黄色框标出的StoreTransaction_ReferenceID字段。这个字段存放某次出入库对应的Order_ID,这样就能知道StoreTransaction与Order的对应关系了。但对于车辆买入,或车辆报废,送修造成的出入库,这一字段暂时还没有对应的数据,这将在下一篇中讨论。 下篇预告

到现在为止租车系统的基本需求已经满足了,但还有不少问题值得思考。

1. 出入库管理还能丰富,车辆买入,车辆报废,送修,还有不同门店之间的车辆拆借(如门店A向门店B临时借用某辆车),如何更好的记录这些StoreTransaction信息?

2. 顾客对于租车费用的支付信息如何记录,顾客可以通过预先充值后消费的方式来支付(这也是区分会员级别的关键),又该如何支持?

3. 我们在第一篇中暂时没考虑“送车上门和上门取车”服务,要支持这一功能,我们对数据库结构要做些什么改动? 前篇回顾

在租车信息系统数据库设计(1)与租车信息系统数据库设计(2)中我们列出了租车信息系统的12条需求,并相应做了数据库设计,最后得到的表关系图如下:

在租车信息系统数据库设计(2)的最后提出了3个新问题:

1. 出入库管理还能丰富,车辆买入,车辆报废,送修,还有不同门店之间的车辆拆借(如门店A向门店B临时借用某辆车),如何更好的记录这些StoreTransaction信息?

2. 顾客对于租车费用的支付信息如何记录,顾客可以通过预先充值后消费的方式来支付(这也是区分会员级别的关键),又该如何支持?

3. 我们在第一篇中暂时没考虑“送车上门和上门取车”服务,要支持这一功能,我们对数据库结构要做些什么改动?

就这3个问题,今天我给出自己的解决方案与大家进行讨论。 更细致的出入库管理

对于问题1,可以通过细分StoreTransaction来解决。

在Table_StoreTransaction表中增加StoreTransaction_Type列来存放进出库类型,我把进出库类型分为3种(Purchase,Adjustment,Rental)。相应还需要加入两张表Table_Purchase(记录买入车辆的信息),Table_Adjustment(记录车辆拆借、送修、报废信息)。

Table_StoreTransaction表中的StoreTransaction_ReferenceID列根据不同的进出库类型指向不同表中的记录。

下表罗列了各种情况的进出库类型和Reference ID指向的表: 车辆出租 车辆买入 车辆拆借 车辆送修 车辆报废 进出库类型 Rental(In/Out) Purchase(In) Adjustment(In/Out) Adjustment(In/Out) Adjustment(Out) Reference ID指向的表记录 Table_Order Table_Purchase Table_Adjustment Table_Adjustment Table_Adjustment 我们来看一下需要新建的表的字段。实际上,除了要新建Table_Purchase,Table_Adjustment之外,还会间接引入Table_AdjustmentType表。 Table_Purchase: 列名 Purchase_ID Store_ID Car_VIN CarCategory_ID Purchase_Date Purchase_Price Purchase_Currency Purchase_CreatedBy Purchase_AuthorisedBy Purchase_Comment 解释 Identity字段 入库门店ID 车辆唯一编号 车辆型号ID 购买日期 购买价格 货币 购车申请人 购车批准人 购车备注 注意:

1. Table_Purchase表中没有Car_ID字段是因为在车辆买入之前,Table_Car中还没有对应记录。 2. 为了简化,我们的设计中Table_Purchase只记录成功购买车辆的信息。如果想对车辆购买进行像Order一样的流程控制,就需要增加些新的字段和表,如购车状态信息(记录Purchase的状态,如新建,审批通过,取消或完成等),大家自己根据需要添加。 Table_Adjustment: 列名 解释 Adjustment_ID AdjustmentType_ID Store_ID Car_ID Adjustment_Date Adjustment_ExpectDate Adjustment_CreatedBy Adjustment_AuthorisedBy Adjustment_Comment Identity字段 调库类型ID,指向Table_AdjustmentType记录 入库/出库门店ID 车辆ID 调库日期 预期归还时间 调库申请人 调库批准人 调库备注 注意:

1. Adjustment_ExpectDate表示预期归还时间,此字段只有在Adjustment Type对应为Borrow In, Lend Out, Send to Repair中有意义。当为其他Adjustment Type时,此字段置为NULL。

2. 在此设计中,当某车辆从一个门店Adjust Out后,Table_Car中对应的车辆记录的车辆状态变为Inactive。当某车辆被Adjust In到一个门店后,Table_Car中会相应插入一条车辆记录(也有可能只需做Update),且该车辆状态为Ready。

3. 对于公司各门店之间的拆借,上述方式之外,大家也可以考虑把个门店也看作内部客户,一个门店可以向另一个门店创建Order,走Order流程。但借入车辆的门店需要有一种机制来把车辆收入门店,大家可以思考,并比较两种方式的优劣。 Table_AdjustmentType: 列名 AdjustmentType_ID AdjustmentType_Name 解释 Identity字段 调库类型,包括:借入Borrow In,借出Lend Out,归还Return In,返还Return Out,送修Send to Repair,修完入库Return after Repair,报废Scrap AdjustmentType_InOutFlag 进出库标签 注意:

本设计中Adjustment Type分得较细,通过Adjustment Type就能区分是入库还是出库。

另一种设计是用较少的Adjustment Type来区分调库的种类(如只有Borrow,Return,Repair,Scrap四种),通过InOutFlag来区分进/出库。若要这么做就需要把InOutFlag字段放到Table_Adjustment中。至于两种方式的有缺点,大家可以思考。

新的表关系图

由于加入新的表之后,表关系链接出现了交错。所以我使用了数据库的‘自动整理表’功能把关系图重新排列了一下,得到下图:

其中用红色框圈出的表是这次新加入的表。 其中用黄色圈出的几个字段是我们需要注意的:

1. 在先前的Table_Car中(本文开始的关系图),有字段Car_PurchasePrice, Car_Currency。我们引入了Table_Purchase表之后,这两个字段的信息有冗余,可以省去。我把其中的Car_PurchasePrice改为了Car_CurrentPrice,用于记录每年折损后的车辆价值。

2. 在租车信息系统数据库设计(2)中,Table_StoreTransaction表中的StoreTransaction_ReferenceID字段对于车辆买入,车辆拆借、车辆报废和送修造成的出入库没有对应的信息。现在对于上述情况,此字段将引用Table_Purchase或Table_Adjustment的ID列。 下篇预告

没想到第一个问题就写了这么多,剩下的问题来不及写了,只能留到下一篇中讨论。

2. 顾客对于租车费用的支付信息如何记录,顾客可以通过预先充值后消费的方式来支付(这也是区分会员级别的关键),该如何支持?

3. 我们在第一篇中暂时没考虑“送车上门和上门取车”服务,要支持这一功能,我们对数据库结构要做些什么改动? 前篇回顾

在租车信息系统数据库设计(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:0 AccountTransactionType_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 Customer_ID CustomerAddress_Country CustomerAddress_Province CustomerAddress_City CustomerAddress_Address CustomerAddress_Rank 解释 Identity列 顾客ID,外键 国家 省 城市 详细地址 地址等级(数字越小等级越高,显示在最前面。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(如果有该车型的多辆车有档期,安排哪辆车能使车辆利用率最高呢?这个需要进一步思考)。

思考这些查询也算是验证先前的设计,一般在这个过程中有时会发现一些设计上的疏漏。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- yrrf.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务