Реализация бронирования специалистов (врач, мастер, тренер) на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация бронирования специалистов (врач, мастер, тренер) на сайте
Сложная
~2-4 недели
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация бронирования специалистов (врач, мастер, тренер) на сайте

Бронирование специалиста сложнее, чем бронирование зала. У специалиста может быть нерегулярное расписание, перерывы между приёмами, отпуска, замены на другого специалиста. Клиент хочет видеть ближайший доступный слот, а не перебирать даты вручную.

Модель расписания специалиста

Расписание — это несколько слоёв с разным приоритетом:

-- Базовый недельный шаблон (повторяется каждую неделю)
CREATE TABLE specialist_schedules (
    id              SERIAL PRIMARY KEY,
    specialist_id   INTEGER NOT NULL,
    weekday         SMALLINT NOT NULL,  -- 0=пн ... 6=вс
    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),  -- 'day_off', 'custom_hours', 'vacation'
    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)
);

Алгоритм генерации доступных слотов

def get_available_slots(specialist_id: int, date: date) -> list[TimeSlot]:
    # 1. Проверить переопределение на эту дату
    override = get_override(specialist_id, date)
    if override and override.type == 'day_off':
        return []
    if override and override.type == 'vacation':
        return []

    # 2. Получить базовое расписание
    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

    # 3. Сгенерировать теоретические слоты
    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))

    # 4. Убрать заблокированные интервалы
    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)  # нельзя бронировать «прямо сейчас»
    ]

Ближайший доступный слот

Клиент часто не знает, когда записаться — он хочет «как можно скорее»:

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

Замена специалиста

Если клиент хочет попасть к конкретному специалисту, но ближайший слот через 2 недели, система может предложить аналогичного специалиста:

def find_same_service_specialists(specialist_id: int) -> list[int]:
    # Специалисты с теми же услугами
    return db.query("""
        SELECT DISTINCT s2.id
        FROM specialist_services ss1
        JOIN specialist_services ss2 ON ss1.service_id = ss2.service_id
        JOIN specialists s2 ON ss2.specialist_id = s2.id
        WHERE ss1.specialist_id = %s AND s2.id != %s AND s2.is_active = true
    """, [specialist_id, specialist_id])

Интерфейс записи

Поток клиента:

  1. Выбор услуги → фильтрация специалистов по услуге
  2. Выбор специалиста (или «любой доступный»)
  3. Выбор даты — показывается только если есть хотя бы один слот
  4. Выбор времени — слоты конкретной даты
  5. Форма контактов → hold → оплата / подтверждение

На шаге выбора даты удобно использовать inline calendar, где серые даты — нет слотов, зелёные — есть:

// react-day-picker + custom modifiers
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 клиенту (подтверждение) + email специалисту
За 24 часа → SMS + email клиенту
За 2 часа → SMS клиенту
Отмена клиентом → email специалисту
Отмена специалистом → email + SMS клиенту + предложение записи к другому

Отзывы после визита

Через 24 часа после окончания приёма — автоматическое письмо с просьбой оставить отзыв. Ссылка содержит подписанный токен, действительный 7 дней:

token = jwt.encode({
    'booking_id': booking.id,
    'exp': datetime.utcnow() + timedelta(days=7),
}, SECRET_KEY, algorithm='HS256')
review_url = f"https://example.com/review?token={token}"

Сроки реализации

Один специалист, базовое расписание, без оплаты — 7–9 рабочих дней. Несколько специалистов, гибкое расписание с переопределениями, замена специалиста, SMS-уведомления, отзывы — 13–16 рабочих дней.