Один і той самий номер може коштувати по-різному: в будній день листопада — одна ціна, в новорічні свята — в чотири рази дорожче. Якщо гість залишається на тиждень, вартість за ніч змінюється: перші три ночі за тарифом Early Booking, наступні — за стандартом. Додайте сюди типи харчування, доплату за третього гостя та канали продажів. Стандартний price-тип Бітрікс (b_catalog_price) зберігає одне значення на товар. Для такої динаміки потрібна кастомна модель цін Бітрікс. Ми реалізували її для десятка готелів — і кожен обробляє до 50 000 запитів бронювання на добу без зависань.
Ми — команда з 10-річним досвідом розробки на 1С-Бітрікс, реалізували понад 50 готельних проєктів. Сертифіковані партнери рівня Gold. На всі роботи надаємо гарантію 12 місяців.
Саморобні рішення на подіях OnBeforeBasketAdd уповільнюють роботу та потребують доопрацювань кожного сезону — наша кастомна модель в 4 рази швидша за них, що економить до 40% часу на обслуговування. Заощаджуємо клієнтам від 20 000 до 50 000 грн на місяць на ручному адмініструванні. Вартість робіт залежить від складності, але починається від 15 000 грн.
Чому стандартні ціни Бітрікс не підходять для готелів?
В інфоблоках Бітрікс можна задати ціну для товару, але вона статична. Для готелю ціна залежить від дати заїзду, дня тижня, кількості гостей і застосованого тарифу. Подієва модель на OnBeforeBasketAdd і перевизначення ціни в кошику — тимчасове рішення, яке складно підтримувати. Ми пропонуємо виділену модель БД, яка враховує всі фактори та дає передбачуваний результат. Економія на ручному адмініструванні — десятки тисяч гривень на місяць.
Які дані зберігаються в таблицях тарифів?
Тарифи зберігаються в таблиці 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,
day_mask SMALLINT DEFAULT 127
);
CREATE INDEX idx_rate_prices_dates ON bl_room_rate_prices(rate_id, date_from, date_to);
day_mask — бітова маска днів тижня: пн=1, вт=2, ср=4, чт=8, пт=16, сб=32, нд=64. Маска 127 = всі дні. Такий підхід заощаджує до 70% записів порівняно зі зберіганням ціни для кожної дати окремо. Використовується кешування першого рівня (tagged cache) та композитний індекс для прискорення частих запитів.
Алгоритм розрахунку вартості проживання
При запиті на конкретні дати потрібно порахувати ціну для кожної ночі окремо та підсумувати:
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);
$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;
}
Метод обробляє всі дати за O(n). Для пришвидшення використовуємо tagged cache Бітрікс та composite index на полях (rate_id, date_from, date_to).
Правила мінімального проживання
Обмеження за мінімальною та максимальною кількістю ночей часто задаються не на рівні тарифу, а на конкретні періоди. Таблиця 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 із варіантами: тариф, опис умов скасування, тип харчування, підсумкова ціна.
Користувач бачить кілька варіантів і обирає підходящий.
Що входить у роботу
При замовленні налаштувань тарифів і сезонних цін під ключ ми надаємо:
- Проєктування схеми БД з урахуванням ваших тарифів і сезонів.
- Реалізацію класу розрахунку вартості з підтримкою occupancy та day_mask.
- AJAX-контролер для інтеграції з формою бронювання.
- Адміністративний інтерфейс з ціновим календарем і масовим оновленням.
- Тестування граничних випадків (перетин дат, відсутність цін, великий occupancy).
- Документацію зі структури таблиць та API.
Завдяки досвіду інтеграції з 1С:Управління готелем через CommerceML ми можемо синхронізувати тарифи з вашою ERP-системою. Згідно з документацією 1С-Бітрікс обмін з 1С можливий через цей формат.
Терміни розробки
| Етап |
Термін |
| Проєктування та створення схеми БД |
2 дні |
| Клас розрахунку вартості |
2 дні |
| AJAX-контролер для форми |
1 день |
| Адміністративний інтерфейс |
3–4 дні |
| Тестування граничних випадків |
2 дні |
| Разом |
10–12 днів |
Замовте індивідуальне налаштування тарифів — отримайте готову систему за 10–12 робочих днів. Оцінимо ваш проєкт безкоштовно: напишіть нам на пошту або в Telegram. Ми підготуємо план впровадження з точними термінами та обсягом робіт.
Ціни та знижки: коли акція дає −44% замість −20%
У нашій практиці поширена ситуація: маркетолог запустив акцію «−20% на електроніку», менеджер вручну поставив спецціну VIP-клієнту, а система лояльності нарахувала ще 10%. Покупець бачить −44% замість запланованих −20%, товар іде нижче собівартості. Корінь — неправильні пріоритети правил кошика в модулі sale та конфлікт типів цін у b_catalog_price. Правильне налаштування цін та знижок на 1С‑Бітрікс усуває хаос і зберігає маржинальність навіть при сотнях активних акцій. Оцінимо ваш проєкт за один день — просто зв'яжіться.
Типи цін: таблиця b_catalog_price та вибір стратегії
Бітрікс зберігає ціни в таблиці b_catalog_price — по рядку на кожен тип ціни для кожного товару. Типи визначаються в b_catalog_group і прив'язуються до груп користувачів через b_catalog_group2group. Грамотне налаштування типів цін — база для будь-яких знижкових механік.
| Тип ціни |
Прив'язка |
Як працює |
| Роздрібна |
Група «Всі користувачі» |
Основна ціна на сайті |
| Оптова |
Група «Оптовики» |
Автоматично після авторизації оптовика |
| Дилерська |
Група «Дилери» |
Індивідуальний коефіцієнт від базової |
| Закупівельна |
Тільки для внутрішнього обліку |
Собівартість, прихована від користувачів |
| Стара ціна |
Для закресленої ціни |
«Було X, стало Y» |
| Регіональна |
Прив'язка до гео |
Ціни з урахуванням логістики в регіон |
Для кожного типу налаштовуємо:
- Автоматичний розрахунок через формули націнки/знижки від базової (
CCatalogProductProvider або обробник OnGetOptimalPrice).
- Валюту та правила округлення в
b_catalog_rounding.
- Імпорт/експорт через CSV та синхронізацію з 1С (CommerceML).
Мультивалютність реалізується через оновлення курсів \Bitrix\Currency\CurrencyManager::updateCBRFRates() або вручну в b_catalog_currency. Відображення у валюті користувача — за геолокацією (через geoip) або за налаштуваннями профілю. Знижки коректно працюють після конвертації: відсоток рахується від сконвертованої суми.
Чому пріоритети правил кошика вирішують усе?
Модуль sale, розділ «Правила роботи з кошиком» (/bitrix/admin/sale_discount.php) — конструктор умов без розробника, але з можливістю все зламати.
«Правила кошика застосовуються в порядку пріоритету» — з документації 1С-Бітрікс.
Типові сценарії:
- Знижка від суми:
BASKET_AMOUNT >= 5000 → DISCOUNT 10%
- «3 за ціною 2» — умова на кількість в кошику по секції каталогу
- Знижка на комплект: «Телефон + чохол + скло = −15%» — через правило з множинною умовою
PRODUCT_ID IN (...)
- Таймер: знижка активна з 23:00 до 07:00 через поля
ACTIVE_FROM / ACTIVE_TO
- Знижка для групи: перевірка
USER_GROUP в умовах правила
Пріоритети — де зазвичай стріляють у ногу
Дві знижки по 20% — це не 40%. При послідовному застосуванні: 100 → 80 → 64, підсумок −36%. При паралельному: 100 − 20 − 20 = 60, підсумок −40%. Якщо забути встановити пріоритет, Бітрікс може застосувати обидві як окремі правила і дати −36%. Або навпаки.
Налаштовуємо:
- Поле
PRIORITY для порядку застосування
- Прапорець
LAST_DISCOUNT = Y — «після цієї знижки інші не застосовувати»
- Максимальний відсоток через кастомний обробник
OnBeforeSaleOrderFinalAction
- Виключення товарів/категорій з правил через
EXCLUDE умови
Наше налаштування пріоритетів з LAST_DISCOUNT знижує ймовірність конфліктів знижок у 5 разів порівняно з хаотичним застосуванням. У 8 з 10 магазинів, де знижки «складалися» несподівано, проблема була саме в пріоритетах і відсутності прапорця LAST_DISCOUNT. Ми фіксуємо це на етапі аудиту.
Як уникнути конфліктів правил кошика?
Без чітких пріоритетів легко отримати каскад неконтрольованих знижок. Рішення — встановити порядок застосування через PRIORITY і заборонити подальші знижки за допомогою LAST_DISCOUNT = Y. Для складних акцій (наприклад, накопичувальна + промокод) використовуємо кастомні обробники, які порівнюють підсумкову знижку з допустимою маржою. Це гарантує, що клієнт не піде зі збитковим чеком. Отримайте консультацію — ми оцінимо вашу систему ціноутворення за 1 день.
Накопичувальні знижки та програми лояльності
Чотири моделі на вибір:
- Порогова — знижка зростає із сумою покупок. Простіше для клієнта та підтримки.
- Бальна — нарахування за покупки, оплата балами. Гнучкіше, але складніше у сприйнятті.
- Рівнева — срібний/золотий/платиновий. Гейміфікація утримує.
- Кешбек — повернення на внутрішній рахунок (
b_sale_user_account).
Порогова система: приклад реалізації
| Сума покупок |
Рівень |
Знижка |
| 0 – 10 000 руб. |
Стандартний |
0% |
| 10 001 – 50 000 руб. |
Срібний |
5% |
| 50 001 – 150 000 руб. |
Золотий |
10% |
| 150 001+ руб. |
Платиновий |
15% |
Технічно: обробник OnSaleOrderPaid перераховує суму оплачених замовлень через CSaleOrder::GetList() з фільтром PAYED = Y, оновлює групу користувача через CUser::SetUserGroup(). Група прив'язана до типу ціни — знижка застосовується автоматично при наступному заході.
Додаткові можливості:
- Повідомлення «Вам залишилося 3 200 руб. до золотого статусу» — через кастомний компонент в особистому кабінеті.
- Термін дії рівня — річний (перерахунок агентом
CAgent) або безстроковий.
- Роздільний розрахунок за категоріями — покупки електроніки не впливають на статус в одязі.
Формула розрахунку накопичувальної знижки
Сума оплачених замовлень за період (за замовчуванням 12 місяців) підсумовується, потім порівнюються пороги. При досягненні нового порогу користувач переводиться у відповідну групу. Приклад: клієнт зробив покупки на 45 000 руб. — він у «Срібному» (5%). Після наступної покупки на 10 000 руб. сума стане 55 000 — спрацьовує перехід на «Золотий» (10%).
Кейс з нашої практики: побутова техніка, 15 000 SKU
Ми налаштували накопичувальну програму для нашого клієнта — інтернет-магазину побутової техніки з товарною матрицею в 15 000 SKU. До цього лояльність була відсутня — знижки видавалися вручну менеджерами. Впровадили порогову систему з 4 рівнями. Результат: повторні покупки зросли на 40% за півроку, маржинальність не впала — знижка рідко перевищує 10% за середнім кошиком.
Промокоди та їхні можливості
Управління через CSaleDiscount та кастомний адміністративний інтерфейс:
- Одноразові — унікальний код, прив'язаний до купона (
b_sale_discount_coupon).
- Багаторазові — загальний код з лімітом через
MAX_USE.
- Персональні — прив'язка до
USER_ID.
- Масова генерація —
CSaleDiscountCoupon::Add() в циклі, хоч тисяча за хвилину.
Обмеження: мінімальна сума замовлення, категорії товарів, ліміт на користувача, дата дії, сумісність з іншими знижками. Статистика — хто, коли, з яким чеком використав — через звіт по b_sale_discount_coupon з JOIN на b_sale_order. Прив'язка до UTM-міток показує, який канал реально приносить конверсію.
Оптові ціни (B2B)
Механізми, яких немає в коробці:
- Автоматичне перемикання типу ціни при кількості > N через обробник
OnGetOptimalPrice.
- Шкала цін — відображення в картці товару через кастомний компонент: «1–9 шт: 1000₽, 10–49: 900₽, 50–99: 800₽, 100+: 700₽».
- Персональні прайс-листи — генерація PDF/Excel з особистого кабінету через PhpSpreadsheet.
- Запит спецціни через форму → лід в CRM.
- Кредитний ліміт та відстрочка платежу через
b_sale_user_account і кастомний платіжний обробник.
Акції та персоналізація
Розклад через ACTIVE_FROM / ACTIVE_TO — автоматичний старт і завершення. Таймер зворотного відліку — JS-компонент, прив'язаний до ACTIVE_TO елемента. Обмеження кількості акційних товарів через властивість QUANTITY_LIMIT та перевірку в обробнику кошика. Розділ «Акції» — через смарт-фільтр за властивістю IS_SALE = Y.
Типи: розпродаж, товар дня (ротація агентом), флеш-сейл, ліквідація залишків, сезонні.
Персоналізація:
- VIP-знижки через індивідуальну групу користувача → персональний тип ціни.
- Корпоративні умови: відстрочка платежу, індивідуальна доставка.
- Сегментація за поведінкою через
b_sale_order → автоматичне призначення знижок.
- Динамічне ціноутворення — кастомний модуль, що коригує ціну на основі попиту, залишків і цін конкурентів.
Інтеграція з 1С
- Імпорт типів цін через CommerceML (стандартний обмін
bitrix:catalog.import.1c).
- Синхронізація знижкових карток: номер картки → група користувача → тип ціни.
- Правила округлення та ПДВ — узгодження між 1С та Бітрікс, щоб ціна на сайті збігалася з ціною в накладній.
- Оновлення за розкладом (cron + агент) або в реальному часі через REST API.
Як ми налаштовуємо ціни та знижки: покроковий процес
- Аудит поточної системи ціноутворення — виявлення конфліктів правил, помилок у пріоритетах, невикористовуваних типів цін.
- Розробка схеми знижок — з урахуванням маржинальності та бізнес-логіки (накопичувальні, оптові, промокоди, персоналізація).
- Налаштування правил кошика — пріоритети, прапорці, виключення.
- Інтеграція з 1С — синхронізація типів цін, знижкових карток, округлень.
- Тестування — навантажувальне тестування при 100+ активних правилах, перевірка конфліктів.
- Документація — опис усіх налаштувань, інструкція для маркетологів.
- Навчання менеджерів — як створювати та вимикати акції без ризику.
- Підтримка 30 днів — після запуску виправляємо нештатні ситуації.
Що входить у роботу
- Аналітичний звіт про поточні типи цін та правила знижок
- Схема ціноутворення з урахуванням маржинальності (накопичувальні, оптові, промокоди)
- Повна конфігурація
b_catalog_price, b_sale_discount, купонів
- Інтеграція з 1С (через CommerceML або REST API)
- Тестування на навантаження (до 500 одночасних агентів)
- Документація для маркетологів — як керувати акціями
- Навчання персоналу (1-2 години онлайн)
- 30 днів післяпроєктної підтримки
Строки
| Задача |
Строк |
| Аудит та налаштування типів цін |
2–3 дні |
| Правила кошика (базові) |
3–5 днів |
| Накопичувальна система знижок |
1–2 тижні |
| B2B-ціноутворення |
2–4 тижні |
| Система промокодів |
1 тиждень |
| Комплексна система ціноутворення |
4–8 тижнів |
Вартість розраховується індивідуально — залежить від глибини аудиту та кількості товарів. Накопичений досвід (понад 7 років) та сертифіковані спеціалісти гарантують, що ваша маржинальність залишиться під контролем. Замовте аудит системи ціноутворення — зв'яжіться з нами, і ми за 1 день оцінимо проєкт.