Овербукинг — головная боль любого отельного бизнеса. Когда два гостя одновременно бронируют последний номер, стандартный Битрикс не может гарантировать, что не возникнет двойной записи. Потери от таких конфликтов могут достигать 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 рабочего дня. Свяжитесь с нами для оценки сроков и стоимости разработки под ваши задачи.







