Реалізація бронювання місць на захід на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, 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 робочі дні.