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

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

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

Информационные сайты или веб-приложения
Сайты визитки, 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 events (
    id              SERIAL PRIMARY KEY,
    title           VARCHAR(255) NOT NULL,
    description     TEXT,
    venue_name      VARCHAR(255),
    venue_address   TEXT,
    starts_at       TIMESTAMP NOT NULL,
    ends_at         TIMESTAMP,
    sales_open_at   TIMESTAMP,
    sales_close_at  TIMESTAMP,
    status          VARCHAR(20) DEFAULT 'draft',  -- draft|on_sale|sold_out|finished
    schema_id       INTEGER,     -- схема зала
    cover_image     VARCHAR(500)
);

CREATE TABLE seat_categories (
    id          SERIAL PRIMARY KEY,
    event_id    INTEGER REFERENCES events(id),
    name        VARCHAR(100),   -- 'Партер', 'Балкон', 'VIP'
    color       VARCHAR(7),     -- цвет на схеме зала
    price       NUMERIC(10,2),
    total_seats INTEGER,
    available_seats INTEGER
);

CREATE TABLE seats (
    id          BIGSERIAL PRIMARY KEY,
    event_id    INTEGER REFERENCES events(id),
    category_id INTEGER REFERENCES seat_categories(id),
    row_label   VARCHAR(10),
    seat_number VARCHAR(10),
    x_pos       NUMERIC(6,2),   -- координата на схеме
    y_pos       NUMERIC(6,2),
    status      VARCHAR(20) DEFAULT 'available',
    -- available | held | sold | blocked | unavailable
    booking_id  BIGINT,
    held_until  TIMESTAMP,
    held_by     VARCHAR(100)   -- session_id
);

CREATE TABLE ticket_bookings (
    id              BIGSERIAL PRIMARY KEY,
    event_id        INTEGER REFERENCES events(id),
    customer_name   VARCHAR(255),
    customer_email  VARCHAR(255),
    customer_phone  VARCHAR(50),
    total_amount    NUMERIC(10,2),
    status          VARCHAR(20) DEFAULT 'pending',
    payment_id      VARCHAR(100),
    created_at      TIMESTAMP DEFAULT NOW(),
    paid_at         TIMESTAMP,
    cancelled_at    TIMESTAMP
);

CREATE TABLE ticket_booking_seats (
    booking_id  BIGINT REFERENCES ticket_bookings(id),
    seat_id     BIGINT REFERENCES seats(id),
    price       NUMERIC(10,2),
    PRIMARY KEY (booking_id, seat_id)
);

Удержание мест (hold) с TTL

В момент выбора мест клиентом они временно блокируются — до завершения оплаты или истечения таймера:

HOLD_TTL_SECONDS = 600  # 10 минут

def hold_seats(seat_ids: list[int], session_id: str) -> bool:
    with db.transaction():
        # Атомарно проверить и заблокировать
        result = db.execute("""
            UPDATE seats
            SET status = 'held',
                held_by = %(session)s,
                held_until = NOW() + INTERVAL '10 minutes'
            WHERE id = ANY(%(ids)s)
              AND status = 'available'
            RETURNING id
        """, {'ids': seat_ids, 'session': session_id})

        held_count = len(result)
        if held_count < len(seat_ids):
            # Не все места доступны — откатить транзакцию
            raise db.Rollback("Some seats are no longer available")

    return True

Освобождение просроченных hold-ов — фоновый процесс, запускается каждую минуту:

UPDATE seats
SET status = 'available', held_by = NULL, held_until = NULL
WHERE status = 'held' AND held_until < NOW();

Схема зала (seat map)

Визуальная схема зала рендерится на SVG или Canvas. Данные о местах запрашиваются с бэкенда:

{
  "sections": [
    {
      "id": 1,
      "name": "Партер",
      "rows": [
        {
          "label": "A",
          "seats": [
            { "id": 1001, "number": "1", "x": 100, "y": 200, "status": "available", "price": 2500 },
            { "id": 1002, "number": "2", "x": 130, "y": 200, "status": "sold", "price": 2500 }
          ]
        }
      ]
    }
  ]
}

Клиент кликает на место, оно подсвечивается, добавляется в корзину. При попытке добавить уже занятое — показывается ошибка без перезагрузки страницы (WebSocket или polling каждые 5 секунд).

Обновление в реальном времени

При высоком спросе места разбираются быстро. Обновление схемы в реальном времени — через WebSocket:

const ws = new WebSocket(`wss://api.example.com/events/${eventId}/seats`);

ws.onmessage = (event) => {
  const { seat_id, status } = JSON.parse(event.data);
  updateSeatStatus(seat_id, status);  // обновить цвет на схеме
};

Бэкенд рассылает обновления всем подключённым клиентам при каждом изменении статуса места.

Ценовые категории и волны продаж

CREATE TABLE pricing_tiers (
    id              SERIAL PRIMARY KEY,
    event_id        INTEGER REFERENCES events(id),
    name            VARCHAR(100),   -- 'Ранняя птица', 'Стандарт'
    category_id     INTEGER REFERENCES seat_categories(id),
    price           NUMERIC(10,2),
    available_from  TIMESTAMP,
    available_until TIMESTAMP,
    quota           INTEGER         -- лимит мест по этой цене
);

Система автоматически переключается между тирами по расписанию.

Электронные билеты

После оплаты каждый билет генерируется в PDF с QR-кодом:

import qrcode
from reportlab.pdfgen import canvas

def generate_ticket_pdf(ticket: dict) -> bytes:
    qr = qrcode.make(ticket['verification_code'])
    # ... наложить QR на шаблон PDF
    return pdf_bytes

QR содержит подписанный токен с ticket_id и booking_id. На входе — сканируется и проверяется через API.

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

Без схемы зала, простая нумерация мест, оплата онлайн — 10–12 рабочих дней. Полная схема зала (SVG seat map), real-time обновления, электронные билеты с QR, ценовые тиры, проверка на входе — 16–22 рабочих дня.