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

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

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

Почему штатный механизм скидок не блокирует оплату бонусами

Проанализируем внутреннее устройство документов продажи в 1С:Розница. В системе расчет скидок и процедура оплаты четко разнесены по разным этапам:

  1. Расчет автоматических скидок выполняется для строк табличной части Товары еще до того, как кассир переходит к приему оплаты. Правила совместного применения (такие как Вытеснение, Максимум или Сложение) действуют исключительно внутри справочника Скидки (наценки, ограничения).
  2. Справочник скидок умеет начислять бонусные баллы как скидку особого типа, но он не управляет их списанием.
  3. Списание бонусов — это не предоставление скидки, а вид безналичного платежа. Запись о списании попадает в табличную часть Оплата чека с отдельным видом оплаты Бонусные баллы.

Из-за такого разделения система не может при расчете скидок в строках корзины знать, какой именно вид оплаты выберет кассир на следующем шаге. Поэтому скидка рассчитывается всегда, даже если клиент собирается закрыть 100% чека баллами.

Что дает флаг «Уменьшать сумму чека для скидок»

В настройках элемента справочника Бонусные программы лояльности предусмотрена опция Уменьшать сумму чека для скидок. Разберем, как она влияет на итоговый расчет:

  1. При выключенном флаге: чек на сумму 1000 рублей с автоматической скидкой 10% и оплатой бонусами 500 баллов даст скидку 100 рублей. Покупатель платит 500 рублей бонусами и 400 рублей наличными.
  2. При включенном флаге: система сначала уменьшит базу для расчета скидки на сумму бонусной оплаты (1000 - 500 = 500 рублей), а затем применит скидку 10%. Скидка составит 50 рублей, и деньгами клиент внесет 450 рублей.

Таким образом, флаг лишь уменьшает размер скидки, но не отменяет ее применение. Полного взаимоисключения эта настройка не дает.

Вариант 1. Ограничение через ценовые группы и минимальные цены (штатно)

Если требуется обойтись без доработки программного кода, рассмотрим комбинированную настройку маркетинга:

  1. Перейдем в карточку используемой бонусной программы в справочнике Бонусные программы лояльности.
  2. Установим флаг Детальное управление ограничениями оплаты.
  3. В появившейся табличной части укажем сегменты номенклатуры или ценовые группы товаров, которые участвуют в распродажах и акциях, установив для них максимальный процент оплаты бонусами, равный 0%. В таком случае товар со скидкой система принципиально не позволит закрыть баллами.
  4. Дополнительно включим контроль минимальных цен в правилах ценообразования. Это гарантирует, что даже при пересечении программ лояльности цена за единицу товара не упадет ниже заданного порога рентабельности.

Вариант 2. Подключение внешней обработки скидки

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

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

Вариант 3. Доработка логики РМК через расширение конфигурации

Для создания полноценного сценария «или скидка, или списание бонусов» без снятия конфигурации с типовой поддержки создадим расширение (.cfe). Реализуем в нем перехват действий в форме ФормаРМКУправляемая.

Разберем логику доработки по шагам:

  1. Перехватываем процедуру открытия окна оплаты бонусами (команда ОплатитьБонусами).
  2. Проверяем наличие в чеке рассчитанных скидок. Если скидки присутствуют, выдаем кассиру предупреждающий диалог: «В чеке применены скидки. При списании бонусов скидки будут аннулированы. Продолжить?».
  3. При согласии кассира программно очищаем скидки в строках чека и открываем диалог списания баллов.

Посмотрим на пример перехвата команды в расширении формы РМК:


&Вместо("ОплатитьБонусами")
Процедура Расш_ОплатитьБонусами()
    
    // Проверяем наличие предоставленных скидок в корзине
    ЕстьСкидки = Ложь;
    Для Каждого СтрТовар Из Объект.Товары Цикл
        Если СтрТовар.СуммаАвтоматическойСкидки > 0 Или СтрТовар.СуммаРучнойСкидки > 0 Тогда
            ЕстьСкидки = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если ЕстьСкидки Тогда
        ТекстВопроса = "В чеке присутствуют скидки. Списание бонусов отменит все скидки в чеке. Продолжить?";
        Оповещение = Новый ОписаниеОповещения("Расш_ПослеОтветаПоСкидкам", ЭтотОбъект);
        ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
        Возврат;
    КонецЕсли;
    
    ПродолжитьВызов();
    
КонецПроцедуры

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


&Вместо("РассчитатьСкидки")
Процедура Расш_РассчитатьСкидки(ПараметрыРасчета)
    
    // Если в таблице оплат уже присутствует оплата бонусами, блокируем начисление скидок
    ОплатаБонусамиПрисутствует = Ложь;
    Для Каждого СтрОплата Из Объект.Оплата Цикл
        Если СтрОплата.ВидОплаты = ПредопределенноеЗначение("Справочник.ВидыОплатЧекаККМ.БонусныеБаллы") Тогда
            ОплатаБонусамиПрисутствует = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если ОплатаБонусамиПрисутствует Тогда
        // Очищаем колонки со скидками во всех строках
        Для Каждого СтрТовар Из Объект.Товары Цикл
            СтрТовар.ПроцентАвтоматическойСкидки = 0;
            СтрТовар.СуммаАвтоматическойСкидки = 0;
            СтрТовар.Сумма = СтрТовар.Количество * СтрТовар.Цена;
        КонецЦикла;
        Возврат;
    КонецЕсли;
    
    ПродолжитьВызов(ПараметрыРасчета);
    
КонецПроцедуры

Как эта задача решается в 1С:Розница 3.0

В редакции 1С:Розница 3.0 (построенной на базе архитектуры 1С:УНФ) подход к программам лояльности был кардинально переработан. В третьей редакции начисление и списание баллов объединены в единое рабочее пространство скидок и наценок. Это позволяет гибко настраивать иерархические деревья совместного применения (Бонусы до скидок, Бонусы после скидок, вытеснение и приоритеты), исключая конфликт между скидками и бонусами стандартными пользовательскими настройками.

← На главную