Настройка тарифов и сезонных цен на проживание 1С-Битрикс
Ценообразование в гостинице устроено сложнее, чем в интернет-магазине. Один номер может стоить по-разному в зависимости от даты заезда, длины проживания, дня недели, типа питания и канала продажи. Стандартный механизм цен Битрикс (b_catalog_price) рассчитан на фиксированные прайс-типы, а не на матрицу «дата × тариф × длина проживания». Нужна кастомная модель.
Модель тарифов
Тарифы хранятся в таблице bl_room_rates:
CREATE TABLE bl_room_rates (
id SERIAL PRIMARY KEY,
room_type_id INT NOT NULL,
rate_code VARCHAR(64) NOT NULL,
rate_name VARCHAR(255) NOT NULL,
meal_plan VARCHAR(20) DEFAULT 'RO', -- RO, BB, HB, FB
cancellation VARCHAR(20) DEFAULT 'free',-- free, non_refundable, 48h
min_nights SMALLINT DEFAULT 1,
max_nights SMALLINT,
active BOOLEAN DEFAULT true
);
Сезонные цены — в bl_room_rate_prices:
CREATE TABLE bl_room_rate_prices (
id SERIAL PRIMARY KEY,
rate_id INT REFERENCES bl_room_rates(id),
date_from DATE NOT NULL,
date_to DATE NOT NULL,
price_night NUMERIC(10,2) NOT NULL,
occupancy SMALLINT DEFAULT 2, -- для каких гостей (1, 2, 3...)
day_mask SMALLINT DEFAULT 127 -- битовая маска дней: пн=1, вт=2, ср=4...
);
CREATE INDEX idx_rate_prices_dates ON bl_room_rate_prices(rate_id, date_from, date_to);
day_mask позволяет задать разные цены на выходные и будни в рамках одного сезона. Бит 64 = воскресенье, 32 = суббота, и т.д. Маска 127 = все дни.
Расчёт стоимости проживания
При запросе на конкретные даты нужно посчитать цену для каждой ночи отдельно (разные ночи могут попасть в разные ценовые периоды) и просуммировать:
public function calculatePrice(int $rateId, \DateTime $dateFrom, \DateTime $dateTo, int $occupancy): float
{
$total = 0.0;
$current = clone $dateFrom;
while ($current < $dateTo) {
$dayBit = pow(2, (int)$current->format('N') - 1); // 1=пн, 7=вс
$priceRow = \Bitrix\Main\Application::getConnection()->query(
"SELECT price_night FROM bl_room_rate_prices
WHERE rate_id = ?
AND date_from <= ?
AND date_to > ?
AND occupancy <= ?
AND (day_mask & ?) > 0
ORDER BY occupancy DESC
LIMIT 1",
[$rateId, $current->format('Y-m-d'), $current->format('Y-m-d'), $occupancy, $dayBit]
)->fetch();
if (!$priceRow) {
throw new \RuntimeException('Нет цены для даты ' . $current->format('Y-m-d'));
}
$total += (float)$priceRow['price_night'];
$current->modify('+1 day');
}
return $total;
}
Правила минимального проживания
Ограничения по минимальному и максимальному количеству ночей часто задаются не на уровне тарифа в целом, а на конкретные периоды. Таблица bl_room_min_stay:
CREATE TABLE bl_room_min_stay (
room_type_id INT NOT NULL,
date_from DATE NOT NULL,
date_to DATE NOT NULL,
min_nights SMALLINT NOT NULL DEFAULT 1,
max_nights SMALLINT
);
В новогодние праздники минимальный срок = 4 ночи, в обычное время = 1. При расчёте формы бронирования проверяем ограничение и показываем пользователю предупреждение, если он выбрал недопустимый диапазон.
Надбавки за доп. гостей
Базовая цена рассчитана на двух гостей. За третьего и четвёртого гостя — надбавка. Хранится в bl_room_rate_extra_guest:
| rate_id | guest_num | price_per_night |
|---|---|---|
| 1 | 3 | 800.00 |
| 1 | 4 | 800.00 |
При расчёте стоимости для 3 гостей: базовая цена + (кол-во ночей × надбавка).
Административный интерфейс управления ценами
В /bitrix/admin/ создаём раздел «Тарифы и цены». Ключевые функции:
- Список тарифов по типам номеров с возможностью включить/отключить
- Ценовой календарь — таблица с датами по горизонтали и тарифами по вертикали, редактирование через клик
- Копирование периода — скопировать цены прошлого года на текущий с применением коэффициента (например ×1.1)
- Массовое обновление — изменить цены для диапазона дат и набора тарифов за один запрос
Интеграция с формой бронирования
На сайте форма бронирования при выборе дат делает AJAX-запрос к контроллеру RatesController::getAvailableAction. Контроллер:
- Проверяет доступность номеров через
bl_room_booking - Загружает доступные тарифы из
bl_room_rates - Считает цену для каждого тарифа через
calculatePrice() - Возвращает JSON с вариантами: тариф, описание условий отмены, тип питания, итоговая цена
Пользователь видит несколько вариантов бронирования и выбирает подходящий.
Сроки
| Этап | Срок |
|---|---|
| Проектирование и создание схемы БД | 2 дня |
| Класс расчёта стоимости | 2 дня |
| AJAX-контроллер для формы | 1 день |
| Административный интерфейс | 3–4 дня |
| Тестирование граничных случаев | 2 дня |
| Итого | 10–12 дней |







