Настройка модуля онлайн-бронирования номеров на 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Настройка модуля онлайн-бронирования номеров на 1С-Битрикс
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Настройка модуля онлайн-бронирования номеров на 1С-Битрикс

В Битрикс нет стандартного модуля бронирования номеров. Есть модуль sale (заказы), инфоблоки, агенты. Из этого собирается система бронирования, но разрыв между «есть инструменты» и «работает бронирование» — это несколько недель проектирования и разработки. Главная техническая проблема, которую решает модуль: атомарная проверка доступности с защитой от одновременного резервирования одного номера двумя пользователями.

Структура данных

Типовая схема для объектов размещения:

Инфоблок hotel_rooms — каталог номеров:

  • PROPERTY_ROOM_TYPE — тип (стандарт, люкс, апартаменты)
  • PROPERTY_CAPACITY — вместимость
  • PROPERTY_AREA — площадь
  • PROPERTY_FLOOR — этаж
  • PROPERTY_BED_TYPE — тип кроватей (одна двуспальная, две односпальные)
  • PROPERTY_AMENITIES — список удобств (множественное свойство)

Таблица броней bl_room_booking:

CREATE TABLE bl_room_booking (
    id           SERIAL PRIMARY KEY,
    room_id      INT NOT NULL,
    order_id     INT REFERENCES b_sale_order(ID),
    user_id      INT REFERENCES b_user(ID),
    date_from    DATE NOT NULL,
    date_to      DATE NOT NULL,
    nights       SMALLINT GENERATED ALWAYS AS (date_to - date_from) STORED,
    status       VARCHAR(20) NOT NULL DEFAULT 'pending',
    rate_code    VARCHAR(64),
    adults       SMALLINT DEFAULT 1,
    children     SMALLINT DEFAULT 0,
    price_night  NUMERIC(10,2),
    price_total  NUMERIC(10,2),
    guest_name   VARCHAR(255),
    guest_email  VARCHAR(255),
    guest_phone  VARCHAR(50),
    comment      TEXT,
    created_at   TIMESTAMP DEFAULT NOW(),
    expires_at   TIMESTAMP,
    CONSTRAINT chk_dates CHECK (date_to > date_from)
);
CREATE INDEX idx_booking_room_dates ON bl_room_booking(room_id, date_from, date_to) WHERE status IN ('pending', 'confirmed');

Атомарная проверка и создание брони

Race condition — главный враг систем бронирования. Два пользователя одновременно открыли форму на один номер, оба проверили доступность (свободно), оба нажали «Забронировать». Без блокировки оба получают подтверждение.

Решение — транзакция с явной блокировкой строки:

$connection = \Bitrix\Main\Application::getConnection();
$connection->startTransaction();

try {
    // Блокируем запись номера для обновления
    $connection->query(
        "SELECT id FROM bl_room_booking
         WHERE room_id = ?
           AND status IN ('pending', 'confirmed')
           AND date_from < ?
           AND date_to > ?
         FOR UPDATE",
        [$roomId, $dateTo, $dateFrom]
    );

    $conflicts = $connection->getAffectedRowsCount();
    if ($conflicts > 0) {
        $connection->rollbackTransaction();
        return ['error' => 'Номер недоступен на выбранные даты'];
    }

    $bookingId = $connection->query(
        "INSERT INTO bl_room_booking
         (room_id, user_id, date_from, date_to, status, expires_at, price_total)
         VALUES (?, ?, ?, ?, 'pending', NOW() + INTERVAL '20 minutes', ?)
         RETURNING id",
        [$roomId, $userId, $dateFrom, $dateTo, $totalPrice]
    )->fetch()['id'];

    $connection->commitTransaction();
    return ['booking_id' => $bookingId];
} catch (\Exception $e) {
    $connection->rollbackTransaction();
    throw $e;
}

Связь с модулем sale

После создания брони в статусе pending создаём заказ в модуле sale:

$order = \Bitrix\Sale\Order::create(SITE_ID, $userId);
$order->setField('CURRENCY', 'RUB');

$basket = $order->getBasket();
$item = \Bitrix\Sale\BasketItem::create($basket, 'catalog', $roomProductId);
$item->setFields([
    'NAME'      => 'Номер ' . $roomName . ' (' . $nights . ' ночей)',
    'QUANTITY'  => 1,
    'PRICE'     => $totalPrice,
    'CURRENCY'  => 'RUB',
]);
$basket->addItem($item);
$order->save();

// Привязываем order_id к брони
BookingTable::update($bookingId, ['ORDER_ID' => $order->getId()]);

При оплате заказа (событие OnSalePaymentEntitySaved, IS_PAID = Y) переводим бронь в confirmed.

Агент освобождения просроченных броней

Брони со статусом pending и истёкшим expires_at должны освобождаться автоматически:

function ReleaseExpiredRoomBookings(): string
{
    \Bitrix\Main\Application::getConnection()->queryExecute(
        "UPDATE bl_room_booking
         SET status = 'expired'
         WHERE status = 'pending' AND expires_at < NOW()"
    );
    // Отменяем связанные заказы в sale
    $expired = \Bitrix\Main\Application::getConnection()->query(
        "SELECT order_id FROM bl_room_booking WHERE status = 'expired' AND order_id IS NOT NULL AND notified = false"
    );
    while ($row = $expired->fetch()) {
        $order = \Bitrix\Sale\Order::load($row['order_id']);
        if ($order) $order->setField('STATUS_ID', 'CANCEL');
    }
    return __FUNCTION__ . '();';
}

Агент регистрируется с интервалом 60 секунд.

Административный интерфейс

В /bitrix/admin/ добавляется раздел «Бронирования». Ключевые представления:

  • Календарная сетка — строки = типы номеров, столбцы = даты. Ячейки закрашены по статусу брони. Реализуется через кастомную страницу с таблицей из bl_room_booking.
  • Список броней — стандартный грид с фильтрами по статусу, датам, гостю.
  • Карточка брони — детали, кнопки изменения статуса, привязанный заказ.

Сроки

Этап Срок
Инфоблок номеров + схема БД 2 дня
Бэкенд: проверка, создание, агент 4 дня
Форма бронирования на сайте (AJAX, календарь) 3 дня
Связь с модулем sale и платёжными системами 2 дня
Административный интерфейс 3 дня
Тестирование 2 дня
Итого 2–3 недели