Создание системы бронирования встреч в Rails

Я хочу создать приложение для записи на прием со следующими характеристиками: - Пользователи могут быть поставщиками услуг или покупателями - Поставщики услуг устанавливают свою доступность (но могут устанавливать свою доступность только на срок не более 6 месяцев вперед) - Покупатели могут затем записывать встречи на основе в зависимости от этих возможностей - каждая встреча, в зависимости от типа услуги, занимает разное количество времени - В зависимости от встречи, которую выбирает покупатель, отображается другой набор доступных возможностей в зависимости от того, сколько времени занимает услуга

Я построил следующее: - Модель TimeSlot, в которой я создаю ряд общих 30-минутных временных интервалов на основе атрибутов start_time и end_time. Чтобы продлить эти временные интервалы на 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

- Модель Appointment, имеющая много user_time_slots. Их много, потому что встреча принадлежит службе, которая занимает определенное время (атрибут time_required в службах) и может охватывать несколько последовательных пользовательских_времени_слотов.

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 действительно имеют единственную цель - иметь время начала и время окончания, а затем связываться с ними.

    • Once the user (buyer) selects a service they want, I am not sure how I would efficiently find the x number of user_time_slots that are consecutive and, therefore, available for booking the appointment (for example, if I have 30 minute time slot intervals and a user selects an appointment that will take 3 hours, I would have to find 6 consecutive time slots). For example, if a user clicks on an instance of a service I would have to 1) get the time required for that service (easy enough to do) and 2) I'd have to find ALL of the user's user_time_slots and collect their associated time_slots, then compare each time slot's start and end times to one another to find consecutive ones. This just seems like way too much iteration to me and seems like this will bog down my application!

Есть ли у кого-нибудь лучший способ или решение для этого (особенно по теме поиска последовательных временных интервалов)?


person Karim    schedule 20.05.2015    source источник
comment
О каких достоверных и / или официальных источниках вы здесь думаете?   -  person David Aldridge    schedule 26.05.2015
comment
На самом деле просто ищу здесь хорошо продуманное решение этой проблемы - никаких настоящих официальных квалификаций не требуется.   -  person Karim    schedule 26.05.2015


Ответы (4)


Выглядит как забавный проект. :)

Я бы лично не моделировал «существующее время», т.е. у меня не было бы фонового задания для создания «пустых» данных.

Я бы попробовал такую ​​модель:

введите описание изображения здесь

Где таблица пользователей?

Я бы не стал использовать общую модель User для двух разных типов пользователей. Мое чутье подсказывает, что они должны стать другими, если не сейчас, то со временем - особенно угрюмыми. Также, на мой взгляд, это делает модель более понятной. Если есть логин или авторизация, я бы добавил таблицу User для этих конкретных данных и, скорее, Service Provider и Consumer имеют к этому какое-то отношение.

Поставщик услуг управляет доступностью

Поставщику услуг потребуется только пустой календарь (или аналогичный), в котором будут перечислены только те, которые уже указали Доступность услуги для каждой Услуги.

Консультации по продаже потребительских книг

Потребитель будет искать / просматривать / перемещаться по доступности службы для каждой службы

В зависимости от бизнес-логики, т.е. всегда ли Потребитель будет планировать весь определенный временной интервал? Или может Потребитель забронировать предпочтительный временной интервал. Пока забронированный интервал находится в доступном временном интервале данной Услуги?

Расписание

Таким образом, мы помещаем записи Доступность службы только тогда, когда Поставщик услуг управляет своей доступностью для конкретной Службы. Пустой считается просто недоступным.

Мы помещаем записи Встречи только тогда, когда Потребитель бронирует Услугу на основании Доступности услуги.

Если Потребитель может забронировать только часть временного интервала Доступность службы, я бы рекомендовал создать два (или один) новых Доступность службы записей за оставшееся время. Проверить, доступно ли время, можно путем сравнения доступности услуг с встречей, но это не было бы оптимальным вариантом. Лучше было бы просто запросить Доступность службы для конкретной Службы и получить график доступности, где отсутствие записи означает отсутствие доступности.

Здесь есть множество «если», в зависимости от ваших конкретных потребностей и запрошенной бизнес-логики. Но я надеюсь, что это поможет с вдохновением и идеями.

person Mikael Hellman    schedule 30.05.2015

У меня была бы одна модель на каждый период доступности. Каждый период имеет 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)

Запись на прием немного сложнее. Вам необходимо разделить / сократить период доступности. Например, предположим, что у поставщика есть следующие возможности:

30 мая с 12:00 до 18:00

Запись на прием назначена на 30 мая 14:00 - 16:00.

Необходимо удалить старую версию и заменить ее двумя новыми: 30 мая 12:00 - 14:00, 30 мая 16:00 - 18:00

Но это довольно просто сделать модельным методом.

person jpriebe    schedule 27.05.2015

Мне нравится решение jpriebe, хотя я бы предложил небольшое изменение валидации: используйте (Date.today + 6.months).end_of_day для крайнего конца диапазона.

Причина моего предложения - сделать систему немного более удобной для пользователя. Если вы использовали Time.now, и пользователь хочет создать AvailabilityPeriod, заканчивающийся в 16:00, но еще рано утром (скажем, около 10:15), 16:00 будет вне допустимого диапазона. Чтобы создать период доступности, им нужно будет не забыть вернуться позже - и они могут забыть / достать лазанью из духовки / добавить сюда отвлекающий маневр.

Следует признать, что на самом деле существует только одно возможное время, в которое может произойти этот сценарий, и это если пользователь пытается создать AvailabilityPeriod ровно на 6 месяцев вперед (например, 27 мая => 27 ноября). В большинстве случаев я уверен, что большинство пользователей не будут настраивать период доступности так далеко заранее. Тем не менее, использование .end_of_day расширит допустимый временной диапазон до конца соответствующего дня.

person Fluffy    schedule 27.05.2015

Вместо того, чтобы произвольно сегментировать временные интервалы, особенно если несколько встреч могут быть точно с одним 30-минутным интервалом, создавайте встречи с произвольным временем начала и окончания. Предполагая, что встречи не будут охватывать несколько дней, у вас может быть модель дня, в которой есть_мало встреч. Вам придется программно обрабатывать вычисления перекрытия, но вы не будете забивать свою базу данных до смерти, вам нужно будет только присоединиться к Day, Appointment и Providers, а затем выполнить свои вычисления, чтобы найти свои свободные слоты. Назначения могут быть на 5 минут или 6 часов. Неважно.

person Joseph Freivald    schedule 26.05.2015
comment
Это имеет смысл - однако, как поставщик услуг может установить их доступность? Например, если кто-то доступен с 9:00 до 12:00, то с 15:00 до 18:00 (и даже более детально). Управление, которое кажется, что мне нужна какая-то другая модель, связанная с этим днем? - person Karim; 26.05.2015
comment
Я бы так и поступил. У вас могут быть другие модели для группирования встреч, дней, доступности и т. Д., Например, неделя, рабочая неделя, месяц, год и т. Д. -использовать приложение. Уровень абстракции дает вам TimeBlock, который has_many TimeBlocks через TimeUseAssociation, который has_one TimeUseAssociationCategory. Это круговая ссылка, от которой у большинства людей болит голова, поэтому, если вы не стремитесь к общности, я бы выбрал более простые, но более жесткие модели. - person Joseph Freivald; 26.05.2015
comment
Я также хотел бы отметить, что Postgresql предоставляет типы данных диапазона, включая диапазоны дат и отметки даты и времени (с часовым поясом и без него), которые могут упростить обработку TimeBlocks. - person Joseph Freivald; 01.06.2015