通用预约系统设计
系列文章总目录
github地址:github地址:https://github.com/gishys/abp.generalreservation
概述
从预约的本质考虑,之所以会存在预约是因为我们所需要办理的事物是一种稀缺资源,或者我们想提高办理事物的效率亦或者我们想让办理者提高办理成功概率。在这篇文章中预约场景可以描述为,在某一个时间去某一个地方办理一种事物。
预约的组成
预约管理信息
首先预约需要一个可以被识别的名称,在创建预约时还需要配置开放预约天数,以及开放预约的时间段。在关系型数据库中我们定义预约信息为预约名称、预约开放天数、预约开放时间、是否包含当天、预约备注、创建预约时间。存储结构图1所示。
同时预约唯一标识(Id)在字典中定义为根节点,所有其他配置项以预约信息为父节点。
图1
预约内容
预约的选择条件包含三个组成部分,某一个时间段、某一个地方、需要处理的事物。
时间段
为了让预约这件事情符合它本身的定义,预约的时间段应该尽量保持在一个较小的范围内,如果这个范围很大,比如几天,预约这件事情就失去了意义,所以预约的时间段的最大范围规定为1天内,也就是说我们预约的事物应该在一天内完结。
在实际使用场景中我们把预约的时间段分得更细,预约时间分为二级或者甚至还有三级的情况,比如选择某一天之后,还有某一个时间段(9:00-10:30,10:30-12:00),如果时间段分的足够多,可能我们还需要三级,要在时间段的上面增加上午、下午。
时间段如果存在多级就需要考虑一个问题,我们在实现预约界面的时候需要选择的级别是不确定的,可能是一个级别,我们只需要选择某一天,也可能是多个级别。这样我们设计时间段选择的时候,是需要根据时间段级别动态的创建多级选择,基于这个需求,在关系型数据库中设计存储结构如(图2)所示,其实就是把时间段的存储视为字典的存储,字典包含主键Id、父节点Id、项名称、项值。
图2
地点
预约的地点一种情况为办理网点或者履行预约的位置,在实际使用场景中也有可能存在多级,比如某市某区的某一个街道等等,在关系型数据库中设计存储结构如(图2)所示。
还有一种复杂的使用场景,办理的地点用字符串数组不能直观的体现出表达的信息,我们可以通过二维表的形式展现,比如预约的地点为一层以上建筑的某一个房间,我们通过表格的形式能更直观的体现出预约位置信息。
办理的事物
办理的事物可以是一段描述,也可以是多个描述,多个描述又可以分为多个级别。比如我们预约不动产登记,我们可以选择大类转移登记,还可以进一步选择,选择转移登记里的二手房转移登记。
预约资源池
预约资源池就是我们可预约的资源,我们可以把预约资源池理解为预约内容描述的资源,在某一个时间段、在某一个地点、需要办理的事物可以预约的个数或次数,比如以上面的例子来举例,就是在某一天的某一个办理地点我可以通过预约的方式可以有多少个用户来办理二手房转移登记。
预约资源池可以通过几个基本标识来表示,唯一Id、资源总数量、可预约数量、是否可用、是否可以重放、时间Id、地点Id、办理事物Id、资源池编号。
预约信息
预约用户信息是我们管理预约记录的标识信息,最基本的预约信息为电话号码,通过填写电话号码我们可以标记用户,在一些使用场景我们还可以发送预约通知,打电话通知等。除了基本的预约信息,我们在一些使用场景可能还需要姓名、证件号码等其他标识信息。如果是预约房间,我们还需要记录是几个人赴约等等。
以上的预约用户信息是为了保证预约能够准确的履行,保证预约的资源可以正确的分配。我们通过几个基本信息来表示预约信息:所属预约资源池Id、预约信息创建时间、预约人电话、预约人姓名、预约人证件类型、预约人证件号码、预约编号、预约起始时间、预约结束时间、预约状态(已预约、已取消、爽约、已完成、已关闭)、预约备注。
预约黑名单
在我们履行预约的过程中,由于各种原因,很多用户在一些特殊情况下不得不取消预约或者爽约。还有一些群体(黄牛)想通过不法手段控制预约资源(稀缺资源)来为自己谋利。我们需要制定完善的机制,来保证第一种情况,可以在后面的时间内继续申请预约,我们还要制定规则来防范第二种情况对公平的预约环境的破坏。
黑名单就是保护预约行为在公平公正的规则下运行的有力武器,比如我们把爽约(占用了资源而不去使用)的用户放入黑名单,我们也可以把多次取消预约的人放入黑名单,惩罚破坏规则的人对其他申请用户起到警醒作用,已达到资源配置最大化。