Разработка системы онлайн-бронирования для сайта

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

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

Информационные сайты или веб-приложения
Сайты визитки, 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 bookable_resources (
    id              SERIAL PRIMARY KEY,
    type            VARCHAR(50) NOT NULL,  -- 'specialist', 'room', 'table', 'car'
    name            VARCHAR(255) NOT NULL,
    config          JSONB,                 -- специфичные настройки ресурса
    is_active       BOOLEAN DEFAULT TRUE
);

-- Расписание доступности ресурса
CREATE TABLE resource_schedules (
    id              SERIAL PRIMARY KEY,
    resource_id     INTEGER REFERENCES bookable_resources(id),
    weekday         SMALLINT,              -- 0=пн, 6=вс; NULL = конкретная дата
    specific_date   DATE,
    start_time      TIME NOT NULL,
    end_time        TIME NOT NULL,
    slot_duration   INTERVAL,             -- NULL = ресурс не делится на слоты
    is_available    BOOLEAN DEFAULT TRUE
);

-- Собственно бронирования
CREATE TABLE bookings (
    id              BIGSERIAL PRIMARY KEY,
    resource_id     INTEGER REFERENCES bookable_resources(id),
    user_id         INTEGER,
    guest_name      VARCHAR(255),
    guest_email     VARCHAR(255),
    guest_phone     VARCHAR(50),
    starts_at       TIMESTAMP NOT NULL,
    ends_at         TIMESTAMP NOT NULL,
    status          VARCHAR(20) DEFAULT 'pending',
    -- pending | confirmed | cancelled | no_show | completed
    notes           TEXT,
    metadata        JSONB,
    created_at      TIMESTAMP DEFAULT NOW(),
    confirmed_at    TIMESTAMP,
    cancelled_at    TIMESTAMP,
    CONSTRAINT no_overlap EXCLUDE USING gist (
        resource_id WITH =,
        tsrange(starts_at, ends_at, '[)') WITH &&
    ) WHERE (status NOT IN ('cancelled'))
);

Constraint EXCLUDE USING gist с tsrange — самый надёжный способ предотвратить двойное бронирование на уровне БД. Он работает атомарно и не зависит от логики приложения.

Алгоритм проверки доступности

def get_available_slots(resource_id: int, date: date) -> list[TimeSlot]:
    # 1. Получить расписание ресурса на этот день
    schedule = get_schedule(resource_id, date)
    if not schedule or not schedule.is_available:
        return []

    # 2. Сгенерировать все теоретические слоты
    all_slots = generate_slots(
        start=schedule.start_time,
        end=schedule.end_time,
        duration=schedule.slot_duration or timedelta(hours=1),
    )

    # 3. Получить уже занятые интервалы из БД
    booked = get_booked_intervals(resource_id, date)

    # 4. Отфильтровать занятые
    return [
        slot for slot in all_slots
        if not any(slot.overlaps(b) for b in booked)
    ]

Временно́е удержание слота (hold)

Между выбором слота и оплатой проходит время. Чтобы слот не заняли в этот момент, реализуется механизм hold:

HOLD_TTL = 600  # 10 минут

def hold_slot(resource_id: int, starts_at: datetime, session_id: str) -> str:
    hold_key = f"hold:{resource_id}:{starts_at.isoformat()}"
    # SET NX — только если ещё не занято
    success = redis.set(hold_key, session_id, nx=True, ex=HOLD_TTL)
    if not success:
        existing = redis.get(hold_key)
        if existing and existing.decode() != session_id:
            raise SlotAlreadyHeld("Слот занят другим пользователем")
    return hold_key

def confirm_booking(hold_key: str, booking_data: dict) -> Booking:
    session_id = redis.get(hold_key)
    if not session_id:
        raise HoldExpired("Время удержания слота истекло")

    with db.transaction():
        booking = create_booking(booking_data)
        redis.delete(hold_key)
    return booking

Обработка конкурентных запросов

Даже с EXCLUDE constraint-ом возможна гонка: два запроса проверяют доступность одновременно, оба видят слот свободным. Constraint поймает второй INSERT и выбросит ExclusionViolationError. Приложение должно это обработать:

try:
    booking = create_booking(data)
except ExclusionViolationError:
    raise BookingConflict("Этот слот только что был забронирован. Выберите другое время.")

Уведомления

Событие Кому Канал
Бронирование создано Клиент Email + SMS
Бронирование подтверждено Клиент Email
Напоминание за 24 часа Клиент Email + SMS
Напоминание за 1 час Клиент SMS
Новое бронирование Администратор Email
Отмена Клиент + Администратор Email

Напоминания отправляются через scheduled jobs — cron каждый час выбирает брони, у которых starts_at через 24h или через 1h, и не было отправлено соответствующее уведомление.

Правила отмены и изменения

Гибкая система политик отмены:

{
  "cancellation_policy": {
    "free_cancellation_hours": 24,
    "partial_refund_hours": 12,
    "partial_refund_percent": 50,
    "no_refund_hours": 2
  }
}

Политика хранится на уровне ресурса или типа бронирования и применяется автоматически при расчёте возврата.

Интеграция с оплатой

Бронирование может требовать предоплату или полную оплату. Интеграция с Stripe:

def create_payment_intent(booking: Booking, amount: int, currency: str):
    intent = stripe.PaymentIntent.create(
        amount=amount,
        currency=currency,
        metadata={
            'booking_id': str(booking.id),
            'resource_id': str(booking.resource_id),
        },
        capture_method='manual',  # автооплата при подтверждении
    )
    booking.payment_intent_id = intent.id
    booking.save()
    return intent.client_secret

При capture_method='manual' деньги замораживаются на карте, но списываются только при вызове capture() — это удобно для бронирований с ручным подтверждением.

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

Базовая система с одним типом ресурса, без оплаты — 8–10 рабочих дней. Несколько типов ресурсов, управление расписанием через CMS, интеграция с оплатой, SMS-уведомления, политики отмены, мобильный вид — 14–18 рабочих дней.