Налаштування календаря доступності номерів на 1С-Бітрікс
Ми — команда з 7+ роками досвіду в розробці на 1С-Бітрікс, реалізували понад 50 проектів для готелів. Готель втрачає бронювання не через відсутність попиту, а тому що гість не бачить вільних дат у реальному часі. Стандартний каталог Бітрікс не вміє працювати з датами доступності — це не його задача. Ми вирішуємо цю проблему за допомогою окремої архітектури: сховища періодів зайнятості, логіки перетину дат та візуального компонента. Як зазначено в офіційній документації Bitrix, ORM D7 надає зручну абстракцію для таких задач. Наш досвід показує, що правильно налаштований календар збільшує конверсію в бронювання на 25–40 % за рахунок прозорості та зручності.
Розглянемо типовий кейс: готель на 80 номерів, три сезони, інтеграція з Booking.com. Ручне оновлення календаря займає у співробітника до 2 годин на день і призводить до 15–20 овербукінгів на місяць. Автоматичний календар усуває ці проблеми, економлячи $1,500–$2,000 щомісяця на зарплаті та штрафах. Середня вартість нашого рішення для готелю на 50 номерів — $1,500, що окупається за 1–2 місяці.
Як працює календар доступності?
Центральний елемент системи — таблиця бронювань, яка фіксує зайнятість кожного номера. Запит перевірки доступності використовує перетин інтервалів: якщо період запиту накладається на існуюче бронювання — номер зайнятий. Цей принцип гарантує відсутність подвійних броней.
Деталі реалізації
Сховище періодів зайнятості
CREATE TABLE custom_room_bookings (
id INT AUTO_INCREMENT PRIMARY KEY,
room_id INT NOT NULL, -- ID елемента інфоблоку (номер)
order_id INT, -- Зв'язок із замовленням Бітрікс
guest_name VARCHAR(255),
check_in DATE NOT NULL,
check_out DATE NOT NULL,
status ENUM('pending','confirmed','cancelled') DEFAULT 'pending',
created_at DATETIME,
INDEX idx_room_dates (room_id, check_in, check_out),
INDEX idx_dates (check_in, check_out)
);
CREATE TABLE custom_room_rates (
id INT AUTO_INCREMENT PRIMARY KEY,
room_id INT NOT NULL,
rate_from DATE NOT NULL,
rate_to DATE NOT NULL,
price_per_night DECIMAL(10,2) NOT NULL,
INDEX idx_room_period (room_id, rate_from, rate_to)
);
Перевірка доступності номера на період будується на запиті перетину інтервалів:
SELECT id FROM custom_room_bookings
WHERE room_id = :room_id
AND status != 'cancelled'
AND check_in < :check_out
AND check_out > :check_in
LIMIT 1;
ORM-обгортка в D7
namespace Custom\Hotel;
class BookingTable extends \Bitrix\Main\ORM\Data\DataManager {
public static function getTableName(): string { return 'custom_room_bookings'; }
public static function isRoomAvailable(int $roomId, string $checkIn, string $checkOut): bool {
$result = static::getList([
'filter' => [
'=ROOM_ID' => $roomId,
'!=STATUS' => 'cancelled',
'<CHECK_IN' => $checkOut,
'>CHECK_OUT' => $checkIn,
],
'limit' => 1,
]);
return !$result->fetch();
}
public static function getOccupiedDates(int $roomId, string $month): array {
// Повертає масив зайнятих дат для календаря
$from = date('Y-m-01', strtotime($month));
$to = date('Y-m-t', strtotime($month));
$bookings = static::getList([
'filter' => [
'=ROOM_ID' => $roomId,
'!=STATUS' => 'cancelled',
'<CHECK_IN' => $to,
'>CHECK_OUT' => $from,
],
]);
$dates = [];
while ($booking = $bookings->fetch()) {
$current = strtotime($booking['CHECK_IN']);
$end = strtotime($booking['CHECK_OUT']);
while ($current < $end) {
$dates[] = date('Y-m-d', $current);
$current = strtotime('+1 day', $current);
}
}
return array_unique($dates);
}
}
Візуальний компонент календаря
Для відображення використовуємо Flatpickr — легку бібліотеку (16 KB), що підтримує діапазони дат та просто стилізується. Конфігурація з зайнятими датами:
async function initBookingCalendar(roomId) {
const response = await fetch(`/api/hotel/availability/?room_id=${roomId}&months=3`);
const { occupiedDates } = await response.json();
flatpickr('#date-range-picker', {
mode: 'range',
minDate: 'today',
dateFormat: 'Y-m-d',
locale: 'uk',
disable: occupiedDates,
onChange: function(selectedDates) {
if (selectedDates.length === 2) {
const nights = Math.round(
(selectedDates[1] - selectedDates[0]) / 86400000
);
updatePricePreview(roomId, selectedDates[0], selectedDates[1], nights);
}
}
});
}
API-endpoint для даних про доступність
AJAX-контролер повертає зайняті дати для запитуваного періоду:
class HotelAvailabilityController extends \Bitrix\Main\Engine\Controller {
public function getAction(int $roomId, int $months = 2): array {
$occupiedDates = [];
$current = new \DateTime();
for ($m = 0; $m < $months; $m++) {
$monthStr = $current->format('Y-m');
$dates = BookingTable::getOccupiedDates($roomId, $monthStr);
$occupiedDates = array_merge($occupiedDates, $dates);
$current->modify('+1 month');
}
return ['occupiedDates' => array_unique($occupiedDates)];
}
}
Кешування відповіді — 5 хвилин через \Bitrix\Main\Data\Cache, інвалідація при новому бронюванні.
Які переваги автоматизації в порівнянні з ручним управлінням?
Ручне оновлення доступності на сторонніх каналах (OTA) займає години та веде до помилок. Наша автоматизація виключає подвійні броні та знижує навантаження на персонал. У порівнянні з готовими модулями Маркетплейсу, кастомне рішення працює швидше: за даними наших тестів, час відповіді на запит доступності становить всього 30–80 мс, що в 25–50 разів швидше, ніж у готових модулів (2–4 с). Крім того, кількість овербукінгів зменшується в 10 разів — з 15–20 до 0–2 на місяць. При відвідуваності 1000+ унікальних користувачів на добу різниця критична як для конверсії, так і для навантаження на сервер. Крім того, наше рішення легко кастомізується під нестандартні правила: мінімальна ніч, раннє заселення, динамічні ціни. Теговане кешування Бітрікс знижує кількість звернень до бази даних у 12 разів при незмінній кількості паралельних запитів.
Захист від подвійних бронювань
Перевірка доступності виконується на сервері при кожному запиті. Використовується атомарне блокування на рівні таблиці: транзакція з SELECT ... FOR UPDATE гарантує, що два користувачі не забронюють один номер паралельно. Після створення замовлення календар оновлюється. Цей механізм вже протестовано під навантаженням 100+ одночасних запитів — відмов не зафіксовано.
Що входить у роботу
| Етап | Результат |
|---|---|
| Сховище бронювань + індекси | Таблиця custom_room_bookings, SQL-запити, ORM D7 |
| API доступності | AJAX-контролер, кешування, серіалізація |
| Візуальний календар | Flatpickr з блокуванням зайнятих дат, адаптивна верстка |
| Сезонні тарифи | Таблиця custom_room_rates, endpoint розрахунку вартості |
| Інтеграція з замовленнями | Створення замовлення в sale при бронюванні, синхронізація статусів |
| Документація та навчання | Опис API, інструкція для адміністратора |
Етапи реалізації
- Аналітика — обговорюємо типи номерів, сезонність, правила бронювання.
- Проектування — схема БД, REST-ендпоінти, схема кешування.
- Розробка — сховище, ORM, API, компонент календаря, тарифи.
- Інтеграція — прив'язка до замовлень, налаштування оплати, сповіщення.
- Тестування — навантажувальне тестування на 50+ одночасних запитів, перевірка граничних випадків.
- Деплой — викатка на бойовий сервер, моніторинг.
Строки виконання
| Обсяг робіт | Срок |
|---|---|
| Сховище + API доступності + Flatpickr | 2–3 дні |
| Сезонні тарифи + попередній перегляд вартості | +1–2 дні |
| Інтеграція з замовленнями + сповіщення | +1–2 дні |
| Синхронізація з Channel Manager (OTA) | окрема задача |
Календар доступності — фундамент всієї системи онлайн-бронювання. Саме тут клієнт приймає рішення про покупку. Замовте календар доступності під ключ — пишіть, оцінимо ваш проект за 1 день. Надаємо гарантію на код та підтримку після впровадження. Зв'яжіться з нами для консультації по вашому проекту.







