Разработка модуля управления акциями 1С-Битрикс
Штатный модуль sale содержит механизм скидок через b_sale_discount — правила, основанные на условиях корзины. Это мощный инструмент, но он заточен под автоматические скидки на уровне заказа. Маркетинговые акции с баннерами, периодами, счётчиками участников, лимитами использования, механикой «купи 2 — получи 3» — всё это либо не реализуется стандартными средствами, либо требует громоздких обходных решений. Модуль управления акциями закрывает этот пробел.
Модель данных
Модуль vendor.promo со следующими таблицами:
-
b_vendor_promo_action— акции: id, code, name, type (discount/gift/bundle/coupon/cashback), date_from, date_to, is_active, priority, usage_limit, usage_count, conditions (JSON), reward (JSON), banner_image_id, description -
b_vendor_promo_coupon— купоны: id, action_id, code, discount_type (percent/fixed), discount_value, usage_limit, usage_count, user_id (null = общий), expires_at, is_active -
b_vendor_promo_usage— история применения: id, action_id, coupon_id, order_id, user_id, discount_amount, applied_at -
b_vendor_promo_gift— подарочные товары акции: id, action_id, product_id, quantity
Типы акций
Скидка по условию: "conditions": {"min_sum": 3000, "iblock_section_id": 12} — скидка 10% на заказы от 3000 рублей в разделе «Электроника».
Комплект (bundle): "type": "bundle" — при добавлении товара A в корзину товар B добавляется автоматически со скидкой. Реализуется через событие OnSaleBasketItemAdd.
Купон: генерация уникальных кодов в b_vendor_promo_coupon, проверка при оформлении заказа.
Подарок: при выполнении условий корзины — автоматически добавляется товар из b_vendor_promo_gift с ценой 0.
Cashback: начисление баллов программы лояльности вместо скидки.
Проверка условий и применение
class PromoChecker
{
public function check(PromoAction $action, \Bitrix\Sale\Order $order): CheckResult
{
$conditions = $action->getConditions();
$basket = $order->getBasket();
if (isset($conditions['min_sum']) && $basket->getPrice() < $conditions['min_sum']) {
return CheckResult::fail('Минимальная сумма заказа не достигнута');
}
if ($action->getUsageLimit() && $action->getUsageCount() >= $action->getUsageLimit()) {
return CheckResult::fail('Лимит использования акции исчерпан');
}
return CheckResult::success();
}
}
Приоритет и совместимость акций
Несколько акций могут быть активны одновременно. Параметр priority определяет порядок применения. Поле exclusive в настройках акции означает, что другие акции с ней не совмещаются.
Логика: активные акции сортируются по убыванию приоритета. Для каждой проверяется CheckResult. Если акция exclusive и прошла проверку — применяется, цикл прерывается.
Генератор купонов
Массовая генерация уникальных кодов для email-рассылок:
$generator = new CouponGenerator($action);
$coupons = $generator->generate(1000, [
'length' => 8,
'prefix' => 'SALE24-',
'charset' => 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789',
]);
// batch insert в b_vendor_promo_coupon + CSV-файл для экспорта
Символы, похожие на цифры (O/0, I/1), исключаются из charset, чтобы избежать ошибок при ручном вводе.
Статистика акций
В административном интерфейсе по каждой акции видны:
- Количество применений и процент от лимита
- Суммарная скидка за период
- Конверсия: сколько пользователей добавили купон к незавершённому заказу vs завершили оплату
- Топ товаров, попавших под акцию
- Динамика использования по дням (график)
Административный интерфейс
- Список акций с фильтром по статусу, типу, дате
- Конструктор условий и вознаграждений
- Управление купонами: генерация пачками, деактивация, экспорт в CSV
- Отчёт по акции с разбивкой по заказам
Сроки разработки
| Этап | Срок |
|---|---|
| ORM-таблицы, модель акций | 1 день |
| Проверка условий, применение скидок | 2 дня |
| Механика подарков и бандлов | 2 дня |
| Генератор купонов, импорт/экспорт | 1 день |
| Приоритеты и совместимость акций | 1 день |
| Отчёты и статистика | 1 день |
| Административный интерфейс | 2 дня |
| Тестирование | 1 день |
Итого: 11 рабочих дней. Интеграция с email-платформой для автоматической рассылки купонов — дополнительно 1–2 дня.







