Настройка динамического ценообразования на 1С-Битрикс
Динамическое ценообразование — это когда цена меняется автоматически по заданным правилам: в зависимости от спроса, остатков, конкурентов, времени суток или поведения пользователя. В отличие от скидок и акций, здесь цена в b_catalog_price может меняться несколько раз в день. Реализация требует понимания, как Битрикс применяет цены, и чёткой архитектуры правил.
Как Битрикс считает итоговую цену
Цепочка расчёта: базовая цена (b_catalog_price) → скидки каталога (b_catalog_discount) → правила корзины (b_sale_discount) → итог. Динамическое ценообразование работает на первом уровне — меняет базовую цену, либо перехватывает её через событие OnGetOptimalPrice и возвращает другое значение.
Второй вариант (через событие) предпочтительнее: не загрязняет историю цен в b_catalog_price, не влияет на индексацию прайсов, легче откатить.
Правила динамического ценообразования
Правила хранятся в пользовательской таблице bl_dynamic_pricing_rules:
| Поле | Описание |
|---|---|
rule_type |
stock / demand / competitor / time |
iblock_id |
инфоблок или NULL (все) |
product_id |
конкретный товар или NULL (все в разделе) |
condition_json |
параметры условия (остаток, час, коэффициент) |
price_modifier |
коэффициент (1.15 = +15%, 0.9 = -10%) |
priority |
порядок применения при конфликте правил |
active |
включено/выключено |
Обработчик события
AddEventHandler('catalog', 'OnGetOptimalPrice', function(&$fields) {
$productId = $fields['PRODUCT_ID'];
$basePrice = $fields['PRICE']['PRICE'] ?? null;
if (!$basePrice) return;
$modifier = DynamicPricingEngine::getModifier($productId);
if ($modifier && $modifier != 1.0) {
$fields['PRICE']['PRICE'] = round($basePrice * $modifier, 2);
$fields['PRICE']['BASE_PRICE'] = $basePrice; // оригинал для отображения скидки
}
});
DynamicPricingEngine::getModifier() загружает применимые правила из кэша (\Bitrix\Main\Data\Cache, TTL 300 сек) и вычисляет результирующий коэффициент. При нескольких правилах — перемножаем или берём минимальный/максимальный в зависимости от бизнес-логики.
Правило по остаткам склада
Если остаток товара падает ниже порога — повышаем цену (стимул купить раньше или ограничение ажиотажа). Остатки берём из b_catalog_store_product через \Bitrix\Catalog\StoreProductTable:
$stock = \Bitrix\Catalog\StoreProductTable::getList([
'filter' => ['PRODUCT_ID' => $productId],
'select' => ['AMOUNT'],
'runtime' => [new \Bitrix\Main\ORM\Fields\ExpressionField('TOTAL', 'SUM(%s)', 'AMOUNT')],
])->fetch()['TOTAL'] ?? 0;
if ($stock < 5) return 1.2; // +20% при остатке < 5 шт
if ($stock < 20) return 1.1; // +10% при остатке < 20 шт
return 1.0;
Кэширование и производительность
Событие OnGetOptimalPrice вызывается при каждом рендере цены — в каталоге, на детальной, в корзине. Без кэша одна страница каталога с 48 товарами сделает 48 вызовов к БД. Кэшируйте модификатор по PRODUCT_ID с TTL 5 минут. При изменении остатков или правил — сбрасывайте кэш по тегу dynamic_price_{productId}.
Что настраиваем
- Таблицу
bl_dynamic_pricing_rulesс набором правил - Класс
DynamicPricingEngineс кэшированием и логикой применения правил - Обработчик события
OnGetOptimalPriceвinit.phpили модуле - Интерфейс администратора для управления правилами
- Логирование изменений цен в
bl_dynamic_pricing_logдля аудита







