Как в 1С:Розница 2.3 исключить начисление «бонусов на бонусы» и рассчитывать их только от суммы, оплаченной деньгами?

Программист 1С v8.3 (Управляемые формы) 1С:Розница Управленческий учет Торговля и дистрибуция
← На главную

В типовой конфигурации 1С:Розница 2.3 многие пользователи и предприниматели сталкиваются с логической дилеммой при работе с программами лояльности. Ситуация выглядит так: клиент покупает товар, часть суммы оплачивает накопленными бонусами, а остаток — наличными или картой. Программа, согласно стандартным правилам, часто начисляет новые бонусы на всю сумму чека, включая ту часть, которая была оплачена баллами. С точки зрения бизнеса это выглядит как «бонусы на бонусы», что ведет к необоснованным затратам.

В этой статье мы подробно разберем, почему так происходит и какими способами можно заставить программу рассчитывать бонусную базу только из «живых» денег.

Способ 1: Использование штатной настройки «Уменьшать сумму чека для скидок»

Начнем с самого простого и неочевидного метода, который помогает во многих релизах, начиная с 2.3.10. Проанализируем настройки бонусной программы лояльности. В 1С оплата бонусами технически может трактоваться системой по-разному: как скидка или как платежное средство.

Рассмотрим порядок действий:

  1. Перейдем в раздел Маркетинг — Бонусные программы лояльности.
  2. Откроем нужную бонусную программу.
  3. Найдем флаг (чекбокс) «Уменьшать сумму чека для скидок».

Важный нюанс: Несмотря на название, эта настройка во многих конфигурациях регулирует базу начисления. Если флаг установлен, программа при расчете новых баллов вычитает из общей суммы документа все примененные скидки и, в некоторых случаях, оплаты, приравненные к ним. Посмотрим на результат: если настройка активна, система должна увидеть оплату бонусами как фактор, уменьшающий базу для расчета последующих начислений. Однако стоит учитывать, что в некоторых старых релизах этот механизм может работать некорректно, так как оплата бонусами фискализируется как встречное предоставление (вид оплаты), а не как скидка в чистом виде.

Способ 2: Настройка через произвольную схему компоновки данных (СКД)

Если штатные флаги не помогают, разберем более гибкий, но технически сложный вариант. В 1С:Розница правила начисления бонусов могут использовать Произвольные схемы компоновки данных.

Проанализируем ситуацию: нам нужно, чтобы система при расчете суммы бонуса обращалась не к полю СуммаДокумента, а к разности между общей суммой и суммой, оплаченной конкретным видом оплаты (Бонусами).

Рассмотрим алгоритм настройки:

  1. В правилах начисления бонусных баллов выберем вариант «Схема компоновки данных».
  2. Создадим новую схему. В конструкторе запроса нам необходимо соединить таблицу ЧекиККМ с таблицей ЧекиККМОплата.
  3. В запросе установим условие: суммировать только те строки оплаты, где ТипОплаты НЕ равен БонусныеБаллы.

Такой подход позволяет на лету вычислять корректную базу для начисления, не изменяя программный код конфигурации. Это наиболее «чистый» способ с точки зрения поддержки системы.

Способ 3: Программная реализация через регламентное начисление

Рассмотрим ситуацию, когда стандартные механизмы начисления в момент пробития чека не подходят (например, если требуется сложная логика разделения бонусов по типам оплаты: 2% за наличные и 1% за карту). В этом случае мы можем отключить автоматическое начисление в чеке и реализовать его через внешнюю обработку, запускаемую по расписанию.

Разберем пример кода, который обходит чеки за текущий день, анализирует виды оплат и создает документ НачислениеИСписаниеБонусныхБаллов. Выясним причину использования такого метода: он позволяет полностью исключить тип оплаты ЗачетАванса (бонусы) из расчета.

Посмотрим на пример реализации серверной части такой обработки:


// Фрагмент кода для выборки данных из чеков и расчета бонусов
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|    ЧекККМ.Ссылка КАК Ссылка,
|    ЧекККМ.ДисконтнаяКарта КАК ДисконтнаяКарта,
|    ЧекККМОплата.Сумма КАК СуммаОплаты,
|    ЧекККМОплата.ВидОплаты.ТипОплаты КАК ТипОплаты
|ИЗ
|    Документ.ЧекККМ КАК ЧекККМ
|    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЧекККМ.Оплата КАК ЧекККМОплата
|    ПО ЧекККМ.Ссылка = ЧекККМОплата.Ссылка
|ГДЕ
|    ЧекККМ.Дата МЕЖДУ &НачалоПериода И &КонецПериода
|    И ЧекККМ.Проведен = ИСТИНА
|    И ЧекККМОплата.ВидОплаты.ТипОплаты <> ЗНАЧЕНИЕ(Перечисление.ТипыОплатЧекаККМ.ЗачетАванса)";

Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ТекущаяДата()));

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Начисление = Документы.НачислениеИСписаниеБонусныхБаллов.СоздатьДокумент();
Начисление.Дата = ТекущаяДата();
Начисление.БонуснаяПрограммаЛояльности = Справочники.БонусныеПрограммыЛояльности.НайтиПоНаименованию("Основная");

Пока Выборка.Следующий() Цикл
    Если ЗначениеЗаполнено(Выборка.ДисконтнаяКарта) Тогда
        НоваяСтрока = Начисление.Начисление.Добавить();
        НоваяСтрока.ДисконтнаяКарта = Выборка.ДисконтнаяКарта;
        
        // Логика: 2% на наличные, 1% на остальные (кроме бонусов, которые мы отсекли в запросе)
        Если Выборка.ТипОплаты = Перечисления.ТипыОплатЧекаККМ.Наличные Тогда
            НоваяСтрока.Баллы = Цел(Выборка.СуммаОплаты * 0.02);
        Иначе
            НоваяСтрока.Баллы = Цел(Выборка.СуммаОплаты * 0.01);
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Начисление.Записать(РежимЗаписиДокумента.Проведение);

Для того чтобы эта обработка работала автоматически, её необходимо зарегистрировать в системе как дополнительную. Для этого используем стандартную функцию СведенияОВнешнейОбработке:


Функция СведенияОВнешнейОбработке() Экспорт
    ПараметрыРегистрации = Новый Структура;
    ПараметрыРегистрации.Вставить("Вид", "ДополнительнаяОбработка");
    ПараметрыРегистрации.Вставить("Наименование", "Регламентное начисление бонусов (без учета баллов)");
    ПараметрыРегистрации.Вставить("Версия", "1.0");
    ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь);
    
    ТаблицаКоманд = Новый ТаблицаЗначений;
    ТаблицаКоманд.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
    ТаблицаКоманд.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
    ТаблицаКоманд.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
    
    НоваяКоманда = ТаблицаКоманд.Добавить();
    НоваяКоманда.Представление = "Выполнить начисление";
    НоваяКоманда.Идентификатор = "НачислитьБонусы";
    НоваяКоманда.Использование = "ВызовСерверногоМетода";
    
    ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
    Возврат ПараметрыРегистрации;
КонецФункции

Сравнение подходов: какой выбрать?

Проанализируем плюсы и минусы каждого метода:

Резюмируем: Для большинства типовых задач в 1С:Розница 2.3 достаточно правильно настроить бонусную программу через интерфейс или создать корректную схему компоновки данных. Если же условия акции требуют разграничения по типам оплат (нал/безнал), то программный метод через документ НачислениеИСписаниеБонусныхБаллов станет наиболее надежным решением.

← На главную