在 Rails 建立预约系统
Building an appointment booking system in Rails
我希望构建具有以下特征的预约应用程序:
- 用户可以是服务提供者或购买者
- 服务提供商设置可用性(但最多只能提前 6 个月设置可用性)
- 买家然后可以根据这些可用性进行预约 - 每次预约,根据服务类型,需要不同的时间
- 根据买家选择的约会,根据服务需要多长时间显示一组不同的可用性
我构建的内容如下:
- TimeSlot
模型,我根据 start_time
和 end_time
属性创建了许多通用的 30 分钟时间段。为了使这些时隙延长到未来 6 个月,我每天都有一项后台工作 运行 来创建所有必要的新时隙
class TimeSlot < ActiveRecord::Base
has_many :user_time_slots
# ... more methods below
end
- 一个 UserTimeSlots
模型,基本上表示他们可以设置的服务提供商的可用性。因此,当他们创建 user_time_slot 时,他们实际上是在说他们当时可用。
class UserTimeSlot < ActiveRecord::Base
belongs_to :time_slot
belongs_to :service_provider, :class_name => "User"
belongs_to :appointment
end
- 具有许多 user_time_slot 的 Appointment
模型。它有很多,因为约会属于需要一定时间的服务(服务的 time_required
属性)并且它可能跨越多个 consecutive user_time_slot秒。
class Appointment < ActiveRecord::Base
has_many :user_time_slots
belongs_to :buyer, :class_name => "User"
belongs_to :service_provider, :class_name => "User"
belongs_to :service
end
- 一个 Service
模型,有很多约会并且属于创建该服务的服务提供商。
class Service < ActiveRecord::Base
has_many :appointments
belongs_to :service_provider, :class_name => "User"
end
这个领域模型有效;但是,我想知道是否有更好的方法来执行此操作,原因如下:
在我的后端使用后台作业每天创建 TimeSlot 记录对我来说似乎有点笨拙 - TimeSlots 的唯一目的是有一个开始和结束时间,然后被关联到.
- 一旦用户(买家)选择了他们想要的服务,我不确定我如何有效地找到 x 数量的 user_time_slot 连续的,因此可用于预订约会(对于例如,如果我有 30 分钟的时间段间隔并且用户选择了一个需要 3 小时的约会,我将不得不找到 6 个连续的时间段)。例如,如果用户单击服务实例,我必须 1) 获取该服务所需的时间(很容易做到)和 2) 我必须找到用户的所有 user_time_slot s 并收集它们的关联 time_slots,然后将每个时隙的开始和结束时间相互比较以找到连续的时间。对我来说,这似乎是太多的迭代,而且这似乎会使我的应用程序陷入困境!
有没有人有更好的方法或解决方案(特别是围绕寻找连续时隙的主题)?
创建具有任意开始和结束时间的约会,而不是任意分割时间段,特别是如果很少有约会可能恰好是一个 30 分钟的间隔。假设约会不会跨越几天,您可以有一个 has_many 约会的日模型。您将不得不以编程方式处理重叠计算,但您不会为此将数据库打死,您只需要加入 Day、Appointment 和 Providers,然后 运行 您的计算即可找到您的空缺插槽。约会可以是 5 分钟或 6 小时。没关系。
我会为每个可用期提供一个模型。每个时期都有一个 start_time
和 end_time
。可以很容易地确认它们不会提前超过 6 个月,并且您可以检查预约是否合适。您的时间段不需要 属于 这样的约会;该约会将只包含一个时间和一个服务提供商,并且所述服务提供商的可用性将发生变化以反映预订的约会。
class AvailabilityPeriod < ActiveRecord::Base
belongs_to :service_provider, :class_name => "User"
validates :end_time, :inclusion => { :in => Time.now..(Time.now + 6.months) }
end
例如,您可以像这样找到给定服务和提供商的所有可能可用性:
duration = @service.duration
available_times = @provider.availability_periods.where (end_time - start_time > duration)
预约有点棘手。您需要 split/shorten 可用性期限。例如,假设提供商具有以下可用性:
5 月 30 日 12:00 - 18:00
已预约 5 月 30 日 14:00 - 16:00
需要删除旧的可用性并用两个新的替换:
5 月 30 日 12:00 - 14:00
5 月 30 日 16:00 - 18:00
但这在模型方法中很容易做到。
我喜欢 jpriebe 的解决方案,尽管我会建议对验证进行轻微更改:使用 (Date.today + 6.months).end_of_day
作为范围的最末端。
我提出这个建议的原因是为了让系统稍微更加人性化。如果您使用了 Time.now
,并且用户想要创建一个在下午 4 点结束的 AvailabilityPeriod,但现在还是凌晨一点(比如 10:15am 左右),那么下午 4 点将超出范围。要创建 AvailabilityPeriod,他们必须记住稍后回来 - 他们可能会忘记/正在将烤宽面条从烤箱中取出/在此处插入分心。
诚然,这种情况实际上只有一个可能发生的时间,那就是如果用户试图在 正好 提前 6 个月(例如, 5 月 27 日 => 11 月 27 日)。大多数时候,我敢肯定大多数用户 不会 提前这么长时间设置 AvailabilityPeriod。不过,使用 .end_of_day
会将可接受的时间范围延长到适当的一天结束。
看起来是个有趣的项目。 :)
我个人不会为 "existing time" 建模,即我不会让后台作业创建 "empty" 数据。
我会尝试这样的模型:
用户在哪里table?
我不会为两种不同的用户类型使用共享用户模型。我的直觉是,他们需要有所不同,即使不是现在,随着时间的推移也会变得更加乖张。在我看来,这也使模型更加清晰。如果有登录名或任何身份验证,我会为该特定数据添加一个用户 table,而有 服务提供商 和 消费者和这个有关系。
服务提供商管理可用性
服务提供商只需要一个空日历(或类似日历),仅列出她已经输入的服务可用性,根据服务。
消费预约
消费者会search/browse/navigate服务可用性,根据服务
取决于业务逻辑,即 消费者 是否总是安排整个定义的时间段?或者 消费者 可以预订一个首选时间段。只要预订的时段在给定服务的可用时段内?
计划
所以我们只在服务提供商管理她对特定服务的可用性时记录服务可用性 =72=]。空的只是被认为是不可用的。
我们仅在消费者预订服务时将约会记录,基于服务可用性.
如果 Consumer 可以只预订 Service Availability 时段的一部分,我建议创建两个 (或一)剩余时间的新服务可用性记录。可以通过比较 Service Availability 和 Appointment 来检查时间是否可用,但这并不是最佳选择。
更好的方法是只查询 Service Availability 以获取特定 Service 并获得可用性时间表,其中没有记录就意味着没有可用性。
这里有很多假设,具体取决于您的具体需求和请求的业务逻辑。但我希望这有助于一些灵感和想法。
我希望构建具有以下特征的预约应用程序: - 用户可以是服务提供者或购买者 - 服务提供商设置可用性(但最多只能提前 6 个月设置可用性) - 买家然后可以根据这些可用性进行预约 - 每次预约,根据服务类型,需要不同的时间 - 根据买家选择的约会,根据服务需要多长时间显示一组不同的可用性
我构建的内容如下:
- TimeSlot
模型,我根据 start_time
和 end_time
属性创建了许多通用的 30 分钟时间段。为了使这些时隙延长到未来 6 个月,我每天都有一项后台工作 运行 来创建所有必要的新时隙
class TimeSlot < ActiveRecord::Base
has_many :user_time_slots
# ... more methods below
end
- 一个 UserTimeSlots
模型,基本上表示他们可以设置的服务提供商的可用性。因此,当他们创建 user_time_slot 时,他们实际上是在说他们当时可用。
class UserTimeSlot < ActiveRecord::Base
belongs_to :time_slot
belongs_to :service_provider, :class_name => "User"
belongs_to :appointment
end
- 具有许多 user_time_slot 的 Appointment
模型。它有很多,因为约会属于需要一定时间的服务(服务的 time_required
属性)并且它可能跨越多个 consecutive user_time_slot秒。
class Appointment < ActiveRecord::Base
has_many :user_time_slots
belongs_to :buyer, :class_name => "User"
belongs_to :service_provider, :class_name => "User"
belongs_to :service
end
- 一个 Service
模型,有很多约会并且属于创建该服务的服务提供商。
class Service < ActiveRecord::Base
has_many :appointments
belongs_to :service_provider, :class_name => "User"
end
这个领域模型有效;但是,我想知道是否有更好的方法来执行此操作,原因如下:
在我的后端使用后台作业每天创建 TimeSlot 记录对我来说似乎有点笨拙 - TimeSlots 的唯一目的是有一个开始和结束时间,然后被关联到.
- 一旦用户(买家)选择了他们想要的服务,我不确定我如何有效地找到 x 数量的 user_time_slot 连续的,因此可用于预订约会(对于例如,如果我有 30 分钟的时间段间隔并且用户选择了一个需要 3 小时的约会,我将不得不找到 6 个连续的时间段)。例如,如果用户单击服务实例,我必须 1) 获取该服务所需的时间(很容易做到)和 2) 我必须找到用户的所有 user_time_slot s 并收集它们的关联 time_slots,然后将每个时隙的开始和结束时间相互比较以找到连续的时间。对我来说,这似乎是太多的迭代,而且这似乎会使我的应用程序陷入困境!
有没有人有更好的方法或解决方案(特别是围绕寻找连续时隙的主题)?
创建具有任意开始和结束时间的约会,而不是任意分割时间段,特别是如果很少有约会可能恰好是一个 30 分钟的间隔。假设约会不会跨越几天,您可以有一个 has_many 约会的日模型。您将不得不以编程方式处理重叠计算,但您不会为此将数据库打死,您只需要加入 Day、Appointment 和 Providers,然后 运行 您的计算即可找到您的空缺插槽。约会可以是 5 分钟或 6 小时。没关系。
我会为每个可用期提供一个模型。每个时期都有一个 start_time
和 end_time
。可以很容易地确认它们不会提前超过 6 个月,并且您可以检查预约是否合适。您的时间段不需要 属于 这样的约会;该约会将只包含一个时间和一个服务提供商,并且所述服务提供商的可用性将发生变化以反映预订的约会。
class AvailabilityPeriod < ActiveRecord::Base
belongs_to :service_provider, :class_name => "User"
validates :end_time, :inclusion => { :in => Time.now..(Time.now + 6.months) }
end
例如,您可以像这样找到给定服务和提供商的所有可能可用性:
duration = @service.duration
available_times = @provider.availability_periods.where (end_time - start_time > duration)
预约有点棘手。您需要 split/shorten 可用性期限。例如,假设提供商具有以下可用性:
5 月 30 日 12:00 - 18:00
已预约 5 月 30 日 14:00 - 16:00
需要删除旧的可用性并用两个新的替换: 5 月 30 日 12:00 - 14:00 5 月 30 日 16:00 - 18:00
但这在模型方法中很容易做到。
我喜欢 jpriebe 的解决方案,尽管我会建议对验证进行轻微更改:使用 (Date.today + 6.months).end_of_day
作为范围的最末端。
我提出这个建议的原因是为了让系统稍微更加人性化。如果您使用了 Time.now
,并且用户想要创建一个在下午 4 点结束的 AvailabilityPeriod,但现在还是凌晨一点(比如 10:15am 左右),那么下午 4 点将超出范围。要创建 AvailabilityPeriod,他们必须记住稍后回来 - 他们可能会忘记/正在将烤宽面条从烤箱中取出/在此处插入分心。
诚然,这种情况实际上只有一个可能发生的时间,那就是如果用户试图在 正好 提前 6 个月(例如, 5 月 27 日 => 11 月 27 日)。大多数时候,我敢肯定大多数用户 不会 提前这么长时间设置 AvailabilityPeriod。不过,使用 .end_of_day
会将可接受的时间范围延长到适当的一天结束。
看起来是个有趣的项目。 :)
我个人不会为 "existing time" 建模,即我不会让后台作业创建 "empty" 数据。
我会尝试这样的模型:
用户在哪里table?
我不会为两种不同的用户类型使用共享用户模型。我的直觉是,他们需要有所不同,即使不是现在,随着时间的推移也会变得更加乖张。在我看来,这也使模型更加清晰。如果有登录名或任何身份验证,我会为该特定数据添加一个用户 table,而有 服务提供商 和 消费者和这个有关系。
服务提供商管理可用性
服务提供商只需要一个空日历(或类似日历),仅列出她已经输入的服务可用性,根据服务。
消费预约
消费者会search/browse/navigate服务可用性,根据服务
取决于业务逻辑,即 消费者 是否总是安排整个定义的时间段?或者 消费者 可以预订一个首选时间段。只要预订的时段在给定服务的可用时段内?
计划
所以我们只在服务提供商管理她对特定服务的可用性时记录服务可用性 =72=]。空的只是被认为是不可用的。
我们仅在消费者预订服务时将约会记录,基于服务可用性.
如果 Consumer 可以只预订 Service Availability 时段的一部分,我建议创建两个 (或一)剩余时间的新服务可用性记录。可以通过比较 Service Availability 和 Appointment 来检查时间是否可用,但这并不是最佳选择。 更好的方法是只查询 Service Availability 以获取特定 Service 并获得可用性时间表,其中没有记录就意味着没有可用性。
这里有很多假设,具体取决于您的具体需求和请求的业务逻辑。但我希望这有助于一些灵感和想法。