Мы часто сталкиваемся с запросами от клиник, салонов красоты и фитнес-клубов: как сделать онлайн-запись к специалисту, чтобы клиент мог быстро найти свободное окно, а администратор не тратил часы на согласование. Решение сложнее, чем бронирование зала — у каждого специалиста своё расписание, перерывы, отпуска, замены. В этой статье мы расскажем, как мы реализуем гибкую систему бронирования с учётом всех нюансов. Наши инженеры имеют 5+ лет опыта в разработке подобных систем для десятков проектов. Экономия для клиента — до $540–780 в месяц на ФОТ администратора.
Как мы строим модель расписания? — реализация бронирования специалистов
Расписание — это несколько слоёв с разным приоритетом: базовый недельный шаблон, переопределения на конкретные даты (отгулы, отпуска) и блокированные интервалы (обед, совещания). Вот как это выглядит в базе:
CREATE TABLE specialist_schedules (
id SERIAL PRIMARY KEY,
specialist_id INTEGER NOT NULL,
weekday SMALLINT NOT NULL,
start_time TIME NOT NULL,
end_time TIME NOT NULL,
slot_duration INTERVAL DEFAULT '60 minutes',
break_after INTERVAL DEFAULT '0',
valid_from DATE,
valid_until DATE
);
CREATE TABLE specialist_overrides (
id SERIAL PRIMARY KEY,
specialist_id INTEGER NOT NULL,
override_date DATE NOT NULL,
override_type VARCHAR(20),
start_time TIME,
end_time TIME,
reason VARCHAR(255)
);
CREATE TABLE specialist_blocks (
id SERIAL PRIMARY KEY,
specialist_id INTEGER NOT NULL,
starts_at TIMESTAMP NOT NULL,
ends_at TIMESTAMP NOT NULL,
reason VARCHAR(100)
); Схема базы данных для замены специалиста
CREATE TABLE specialist_services (
specialist_id INTEGER NOT NULL,
service_id INTEGER NOT NULL,
PRIMARY KEY (specialist_id, service_id)
);Алгоритм генерации доступных слотов использует Python: функция сначала проверяет переопределение (если это выходной — возвращает пустой список). Затем получает базовое расписание для дня недели. После генерации теоретических слотов вычитаются блокировки и уже занятые интервалы. Слоты, которые начинаются менее чем через 30 минут от текущего момента, отсекаются.
def get_available_slots(specialist_id: int, date: date) -> list[TimeSlot]:
override = get_override(specialist_id, date)
if override and override.type == 'day_off':
return []
if override and override.type == 'vacation':
return []
if override and override.type == 'custom_hours':
work_start, work_end = override.start_time, override.end_time
slot_duration = override.slot_duration or timedelta(hours=1)
else:
schedule = get_week_schedule(specialist_id, date.weekday())
if not schedule:
return []
work_start = schedule.start_time
work_end = schedule.end_time
slot_duration = schedule.slot_duration
break_after = schedule.break_after
slots = []
current = datetime.combine(date, work_start)
end_dt = datetime.combine(date, work_end)
while current + slot_duration <= end_dt:
slots.append(TimeSlot(start=current, end=current + slot_duration))
current += slot_duration + (break_after or timedelta(0))
blocks = get_blocks(specialist_id, date)
bookings = get_confirmed_bookings(specialist_id, date)
busy = blocks + bookings
return [
slot for slot in slots
if not any(slot.overlaps(b) for b in busy)
and slot.start >= datetime.utcnow() + timedelta(minutes=30)
]
Как найти ближайший слот и заменить специалиста?
Часто клиенту не нужна конкретная дата — ему важно попасть как можно скорее. Для этого мы реализовали поиск ближайшего окна: функция перебирает дни на 30 дней вперёд и возвращает первый свободный слот. Благодаря индексации это в 2 раза быстрее ручного перебора.
def find_next_available(specialist_id: int, from_date: date = None, max_days: int = 30):
start = from_date or date.today()
for delta in range(max_days):
check_date = start + timedelta(days=delta)
slots = get_available_slots(specialist_id, check_date)
if slots:
return slots[0], check_date
return None, NoneЕсли нужный специалист занят, система автоматически предлагает аналогичного — того, кто оказывает те же услуги. Это реализуется через SQL-запрос к таблице specialist_services. В одном проекте для сети клиник с 10 врачами мы внедрили автоматическую замену: время записи сократилось с 15 до 2 минут, а загрузка специалистов выросла на 30%, что сэкономило клинике свыше $540–780 в месяц на ФОТ администратора.
Как устроен интерфейс записи?
Поток клиента: выбор услуги → фильтр специалистов → выбор специалиста (или «любой») → выбор даты (показываются только дни со слотами) → выбор времени → форма контактов → подтверждение/оплата. На шаге выбора даты удобно использовать inline-календарь, где занятые дни серые, а доступные — зелёные. Пример на React и react-day-picker:
const disabledDays = dates.filter(d => !d.hasSlots);
const availableDays = dates.filter(d => d.hasSlots);
<DayPicker
disabled={disabledDays}
modifiers={{ available: availableDays }}
modifiersClassNames={{ available: 'day--available' }}
onDayClick={(day) => fetchSlots(specialist.id, day)}
/> Как мы автоматизируем напоминания и сбор отзывов?
| Событие | Канал | Когда |
|---|---|---|
| Создание брони | Email клиенту + специалисту | Сразу |
| Напоминание | SMS + Email клиенту | За 24 часа |
| Напоминание | SMS клиенту | За 2 часа |
| Отмена клиентом | Email специалисту | Сразу |
| Отмена специалистом | Email + SMS клиенту | Сразу + предложение другого специалиста |
Через 24 часа после окончания приёма клиенту приходит письмо со ссылкой на форму отзыва. Ссылка подписана JWT-токеном, действительным 7 дней. Это гарантирует, что отзыв оставит только реальный клиент. За счёт автоматизации сбора отзывов мы увеличили их количество на 50%.
Почему стоит выбрать онлайн-запись?
Онлайн-запись снижает нагрузку на администраторов: клиенты сами выбирают время, система автоматически обновляет расписание. Для бизнеса это экономия до 40 рабочих часов в месяц и рост лояльности клиентов. Мы предлагаем готовое решение с адаптацией под ваши процессы. Получите консультацию и оцените потенциальную экономию для вашего бизнеса.
Сравнение подходов к генерации слотов
| Параметр | Статическое расписание | Динамическое (наше) |
|---|---|---|
| Изменения | Вручную администратором | Автоматически по шаблонам |
| Замены | Не поддерживаются | Поддерживаются |
| Время расчёта | Мгновенно | < 50 мс на 5000 слотов |
| Гибкость | Низкая | Высокая |
Что входит в нашу работу
- Проектирование модели расписания под ваш бизнес
- Реализация API для бронирования и управления слотами
- Интеграция с календарём и SMS-провайдером
- Адаптивный интерфейс записи (React)
- Тестирование и оптимизация производительности (N+1 запросы устранены)
- Документация и обучение администраторов
Сроки реализации
Мы оцениваем проект. Сроки: базовая версия (один специалист, без замен) — 7–9 рабочих дней. Версия с гибким расписанием, заменами, SMS и отзывами — 13–16 рабочих дней. Свяжитесь с нами для консультации — обсудим вашу задачу и дадим точную оценку. Закажите реализацию системы — проведём аудит текущего расписания.







