Розробка системи бронювання на 1С-Бітрікс
Бронювання — це не просто форма з датами. Під капотом: управління номерним фондом, перевірка доступності на конкретні дати без перетинів, блокування слота на час оплати, автоматичне звільнення при таймауті та інтеграція з менеджерами каналів (channel manager) або модулями онлайн-оплати. Спроби побудувати це на стандартному модулі замовлень sale без архітектурного опрацювання закінчуються перебронюваннями і дублями.
Модель даних
Стандартний інфоблок для об'єктів розміщення не підходить для календарного обліку доступності. Потрібна окрема схема.
Таблиця об'єктів — зберігається як інфоблок типу room (або користувацький тип hotel.room):
- Тип номера, місткість, базова ціна, властивості (
PROPERTY_ROOM_TYPE,PROPERTY_CAPACITY) - Зв'язок з інфоблоком готелю через властивість-прив'язку
Таблиця броней — користувацька таблиця bl_booking:
CREATE TABLE bl_booking (
id SERIAL PRIMARY KEY,
room_id INT NOT NULL, -- ID елемента інфоблока номера
user_id INT, -- b_user.ID
date_from DATE NOT NULL,
date_to DATE NOT NULL,
status VARCHAR(20) NOT NULL, -- pending, confirmed, cancelled, expired
order_id INT, -- b_sale_order.ID
price_total NUMERIC(12,2),
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP, -- для pending-броней
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);
Перевірка доступності
Ключовий запит — перевірити, чи немає перетинів для запитуваного періоду:
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 при паралельних запитах.
$connection = \Bitrix\Main\Application::getConnection();
$connection->startTransaction();
// SELECT FOR UPDATE
// INSERT у bl_booking зі статусом pending
// COMMIT
Блокування і таймаут
Після створення брані зі статусом pending запускається таймер. Якщо оплата не надійшла за N хвилин (зазвичай 15–30), бронь переводиться в expired і слот звільняється.
Реалізація через агент 1С-Бітрікс:
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 або Pikaday з розміткою недоступних днів.
На стороні бекенду — AJAX-контролер, нащадок \Bitrix\Main\Engine\Controller:
class BookingController extends \Bitrix\Main\Engine\Controller
{
public function getAvailabilityAction(int $roomId, string $month): array
{
// повертає зайняті дати за місяць
}
}
Кейс: мережа апарт-готелів, 3 об'єкти, 47 номерів
Завдання: замінити ручне бронювання через дзвінки, виключити перебронювання.
Що було: менеджери вели таблицю Excel, раз на тиждень звіряли — періодично траплялися подвійні брані, скандали з гостями.
Що зробили:
- Інфоблок
roomsз 47 елементами, кожен із галереєю і властивостями (FLOOR,VIEW,BED_TYPE) - Таблиця
bl_bookingз індексом за діапазоном дат - AJAX-контролер перевірки доступності (відповідає за 80–120 мс)
- Інтеграція з еквайрингом через модуль
sale.payment: бронь переходить уconfirmedпо вебхуку від платіжного шлюзу - Агент звільнення прострочених броней кожні 2 хвилини
- Адміністративний модуль з календарним представленням завантаженості номерів
Результат: нульові перебронювання за 14 місяців роботи, конверсія форми бронювання 4.2% (була 0% — все йшло через дзвінок).
| Етап | Термін |
|---|---|
| Проектування схеми даних | 3 дні |
| Розробка бекенду (таблиця, агент, контролер) | 5 днів |
| Фронтенд (календар, форма, AJAX) | 4 дні |
| Інтеграція з платіжним шлюзом | 2 дні |
| Адміністративний інтерфейс | 3 дні |
| Тестування і запуск | 2 дні |
Що входить у розробку
- Проектування моделі даних з урахуванням типів номерів і сезонних цін
- Розробка механізму перевірки доступності із захистом від race condition
- Інтерфейс вибору дат із візуалізацією зайнятості
- Агент автоматичного звільнення прострочених броней
- Інтеграція з модулем
saleдля виставлення рахунку і прийому оплати - Адміністративний розділ управління бронюваннями







