Овербукінг — головний біль будь-якого готельного бізнесу. Коли два гості одночасно бронюють останній номер, стандартний Бітрікс не може гарантувати, що не виникне подвійного запису. Втрати від таких конфліктів можуть сягати $4.5k–6.5k на рік для невеликої мережі. Ми розробили кастомну систему бронювання на 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-таблицю, раз на тиждень звірялися — періодично траплялися подвійні броні, скандали з гостями. Втрати від овербукінгу до впровадження становили близько $4.5k–6.5k на рік.
Реалізовані рішення:
- Інфоблок
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 робочого дня. Зв'яжіться з нами для оцінки термінів та вартості розробки під ваші завдання.







