Овербукінг — головний біль будь-якого готельного бізнесу. Коли два гості одночасно бронюють останній номер, стандартний Бітрікс не може гарантувати, що не виникне подвійного запису. Втрати від таких конфліктів можуть сягати 500 000 руб на рік для невеликої мережі. Ми розробили кастомну систему бронювання на 1С-Бітрікс, яка повністю виключає овербукінг завдяки транзакційному блокуванню рядків та автоматичному звільненню прострочених броней. Кастомна розробка системи бронювання на 1С-Бітрікс починається з проєктування схеми даних: таблиця bl_booking, індекси та транзакції. Під капотом — SELECT FOR UPDATE, агент та AJAX-календар. Нижче — архітектура та реальний кейс.
Згідно з документацією 1С-Бітрікс, для складної логіки бронювання рекомендується використовувати кастомні таблиці замість інфоблоків. Ми використовуємо саме такий підхід: інфоблок rooms для опису номерів, а кастомну таблицю bl_booking для обліку зайнятості. Це дає гнучкість у запитах та продуктивність.
Чому стандартний інфоблок не підходить для бронювання?
Для календарного обліку доступності потрібна окрема схема. Інфоблок не дозволяє ефективно перевіряти перетинання дат і блокувати слоти.
Таблиця об'єктів — інфоблок типу room із властивостями PROPERTY_ROOM_TYPE, PROPERTY_CAPACITY та прив'язкою до готелю.
Таблиця броней — користувацька таблиця bl_booking:
CREATE TABLE bl_booking ( id SERIAL PRIMARY KEY, room_id INT NOT NULL, user_id INT, date_from DATE NOT NULL, date_to DATE NOT NULL, status VARCHAR(20) NOT NULL, -- pending, confirmed, cancelled, expired order_id INT, price_total NUMERIC(12,2), created_at TIMESTAMP DEFAULT NOW(), expires_at TIMESTAMP, guest_name VARCHAR(255), guest_phone VARCHAR(50), guest_email VARCHAR(255) ); CREATE INDEX idx_booking_room_dates ON bl_booking(room_id, date_from, date_to, status); Як працює перевірка доступності з захистом від race condition?
Ключовий запит — перевірка перетинів:
SELECT COUNT(*) FROM bl_booking WHERE room_id = :room_id AND status IN ('pending', 'confirmed') AND date_from < :date_to AND date_to > :date_from; Якщо COUNT > 0 — номер недоступний. Запит обертаємо в транзакцію з SELECT FOR UPDATE, щоб виключити race condition. Кроки реалізації:
- Відкрити транзакцію.
- Виконати SELECT FOR UPDATE по запису номера.
- Перевірити перетини дат.
- Якщо вільно — INSERT в bl_booking зі статусом pending.
- Commit транзакції.
При паралельних запитах другий запит чекає завершення першої транзакції, що гарантує відсутність подвійних броней. Кастомна перевірка на основі bl_booking відпрацьовує в 5 разів швидше, ніж спроба реалізувати аналогічну логіку на стандартних інфоблоках.
Як обробляється таймаут оплати?
Після створення броні в pending запускається таймер. Якщо оплата не надійшла за 15–30 хвилин, бронь переводиться в expired і слот звільняється.
Реалізація через агента:
function ReleasExpiredBookings(): string { $expiredIds = BookingTable::getList([ 'filter' => [ 'STATUS' => 'pending', '<=EXPIRES_AT' => new \Bitrix\Main\Type\DateTime(), ], 'select' => ['ID'], ])->fetchAll(); foreach ($expiredIds as $row) { BookingTable::update($row['ID'], ['STATUS' => 'expired']); } return __FUNCTION__ . '();'; } Реєструється через CAgent::AddAgent() з інтервалом 60 секунд.
Як влаштований інтерфейс вибору дат?
Календар доступності будується на AJAX-запиті /bitrix/services/main/ajax.php?action=BookingModule:getAvailability. Бекенд повертає зайняті дати. На фронті використовуємо Flatpickr з розміткою недоступних днів.
AJAX-контролер, спадкоємець \Bitrix\Main\Engine\Controller:
class BookingController extends \Bitrix\Main\Engine\Controller { public function getAvailabilityAction(int $roomId, string $month): array { // повертає зайняті дати за місяць } } Кейс з нашої практики: мережа апарт-готелів (3 об'єкти, 47 номерів)
Завдання: замінити ручне бронювання через дзвінки, виключити овербукінг.
Вихідна ситуація: менеджери вели Excel-таблицю, раз на тиждень звірялися — періодично траплялися подвійні броні, скандали з гостями. Втрати від овербукінгу до впровадження становили близько 500 000 руб на рік.
Реалізовані рішення:
- Інфоблок
roomsз 47 елементами, кожен з галереєю та властивостями (FLOOR,VIEW,BED_TYPE) - Таблиця
bl_bookingз індексом по діапазону дат - AJAX-контролер перевірки доступності (відповідає за 80–120 мс)
- Інтеграція з еквайрингом через модуль
sale.payment: бронь переходить в confirmed по вебхуку від платіжного шлюзу - Агент звільнення прострочених броней кожні 2 хвилини
- Адміністративний модуль з календарним представленням завантаження номерів
Результат: нульові овербукінги за 14 місяців роботи, конверсія форми бронювання 4.2% (була 0% — все йшло через дзвінок). Витрати на розробку окупилися за 2 місяці.
Процес розробки
| Етап | Строк |
|---|---|
| Проєктування схеми даних | 3 дні |
| Розробка бекенду (таблиця, агент, контролер) | 5 днів |
| Фронтенд (календар, форма, AJAX) | 4 дні |
| Інтеграція з платіжним шлюзом | 2 дні |
| Адміністративний інтерфейс | 3 дні |
| Тестування та запуск | 2 дні |
Строки можуть варіюватися залежно від складності інтеграцій та кількості об'єктів.
Порівняння підходів
| Аспект | Стандартний модуль sale | Кастомна bl_booking |
|---|---|---|
| Перевірка перетинів дат | Потребує складних доробок | Вбудована, швидка |
| Таймаут броні | Немає, тільки ручне скасування | Автоматичний агент |
| Race condition | Не вирішено | SELECT FOR UPDATE |
| Продуктивність перевірки | ~500 мс | 80–120 мс |
Що включає розробка системи бронювання?
- Проєктування моделі даних з урахуванням типів номерів і сезонних цін
- Розробка механізму перевірки доступності з захистом від race condition
- Інтерфейс вибору дат з візуалізацією зайнятості
- Агент автоматичного звільнення прострочених броней
- Інтеграція з модулем
saleдля виставлення рахунку та прийому оплати - Адміністративний розділ управління бронюваннями
- Налаштування сповіщень для гостя та адміністратора (email/SMS)
Отримайте консультацію по вашому проєкту. Замовте розробку системи бронювання під ключ — ми підготуємо комерційну пропозицію протягом 1 робочого дня. Зв'яжіться з нами для оцінки термінів та вартості розробки під ваші завдання.







