При автоматизации розничной торговли часто возникают ситуации, когда маркетинговые активности накладываются друг на друга. Классический пример из практики — совместное проведение акции «Купи 6 товаров Х и получи товар Y в подарок» (то есть со скидкой 100%) и одновременное применение купона на фиксированную сумму (например, 100 рублей) на весь чек.
В конфигурации «1С:Розница» (начиная с версии 2.2) пользователи часто сталкиваются с неприятным эффектом: программа распределяет (пропорционально «размазывает») фиксированную сумму купона по всем строкам чека, включая и подарочный товар Y. Поскольку подарок и так отпускается со 100% скидкой (его стоимость для клиента равна 0 рублей), то часть купонной скидки, которая пришлась на эту строку, просто аннулируется. В итоге вместо положенных 100 рублей скидки по купону покупатель получает, например, только 80 рублей. Выясним причину этого поведения и подробно разберем, как исправить эту логику штатными и программными средствами.
Давайте проанализируем ситуацию на конкретном примере чека, чтобы понять внутреннюю логику системы:
Если в системе настроено совместное применение скидок по принципу «Максимум» или «Сложение» без жестких приоритетов, система производит расчет параллельно:
Сначала алгоритм распределяет купон в 100 рублей на общую сумму чека (1200 + 300 = 1500 руб.):
Затем срабатывает акция «Подарок», которая должна предоставить 100% скидку на товар Y. Программа рассчитывает скидку на товар Y от его текущей стоимости. Но максимальная скидка на товар не может превышать его цену. Поскольку на товар Y уже распределилось 20 рублей купона, скидка-подарок дает оставшиеся 280 рублей. В итоге товар Y уходит за 0 рублей, но из 100 рублей купона реально применились только 80 рублей, распределенные на товар X. Оставшиеся 20 рублей бесследно «сгорают».
Ниже мы подробно рассмотрим три практических способа решения этой проблемы.
---
Наиболее простым и правильным решением без изменения метаданных является настройка правильной иерархии в справочнике «Группы совместного действия скидок, наценок и ограничений». Нам необходимо заставить систему рассчитывать скидки строго по очереди: сначала полностью обнулить стоимость подарка, а затем распределить купон только на те строки, которые имеют положительную стоимость.
Давайте разберем настройку по шагам:
Проанализируем, как изменится математика расчета при такой настройке:
Таким образом, покупатель получает товар Y бесплатно, а за товары X платит 1100 рублей вместо 1200. Скидка по купону применилась в полном объеме!
---
Если по каким-то причинам использование последовательного применения неудобно (например, в вашей схеме лояльности купон обязательно должен рассчитываться в другой группе совместного действия), можно ограничить область применения самого купона, запретив ему распределяться на подарочные позиции.
Рассмотрим этот вариант по шагам:
ТоварыПодарки. Сформируем его состав — добавим туда товар Y (и любые другие товары, которые могут выступать в качестве бесплатных подарков по акциям). Настройку можно сделать как вручную, так и динамически (например, по определенной группе номенклатуры или свойству).ТоварыПодарки.При расчете чека система сразу исключит строку с товаром Y из алгоритма распределения 100 рублей, даже если расчет купона будет происходить параллельно с акцией «Подарок». Вся сумма купона без остатка распределится на товар X.
---
В конфигурации «1С:Розница 2.2» предусмотрен крайне гибкий механизм расширения возможностей расчета скидок с помощью механизма внешних обработок. Если маркетинговая политика компании очень сложная (например, состав подарков постоянно меняется, или сегменты пересекаются), стандартных настроек совместного действия может не хватить. В таком случае мы можем использовать внешнюю обработку для расчета условий или самой скидки.
При вызове внешней обработки система передает в нее объект, содержащий полную таблицу товаров чека. Мы можем программно проанализировать строки чека, определить строки-подарки и корректно перераспределить скидку.
Рассмотрим пример шаблона кода для модуля внешней обработки скидки. Нам необходимо переопределить алгоритм распределения суммы купона, исключая строки, у которых конечная цена уже равна нулю:
// Процедура рассчитывает скидку по купону, распределяя ее только на платные товары
Процедура РассчитатьСкидку(ПараметрыРасчета) Экспорт
ТаблицаТоваров = ПараметрыРасчета.ТаблицаТоваров;
СуммаКупона = 100; // Фиксированная сумма купона
// Шаг 1. Найдем строки, которые не являются подарками (цена > 0 после применения других скидок)
МассивПлатныхСтрок = Новый Массив;
ОбщаяСтоимостьПлатныхТоваров = 0;
Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
// Проверяем текущую стоимость строки с учетом уже примененных скидок
ТекущаяСтоимостьСтроки = СтрокаТовара.Сумма - СтрокаТовара.СуммаСкидки;
Если ТекущаяСтоимостьСтроки > 0 Тогда
МассивПлатныхСтрок.Добавить(СтрокаТовара);
ОбщаяСтоимостьПлатныхТоваров = ОбщаяСтоимостьПлатныхТоваров + ТекущаяСтоимостьСтроки;
КонецЕсли;
КонецЦикла;
Если МассивПлатныхСтрок.Количество() = 0 Или ОбщаяСтоимостьПлатныхТоваров = 0 Тогда
Возврат; // Не на что распределять скидку
КонецЕсли;
// Шаг 2. Распределяем сумму купона пропорционально стоимости платных товаров
ОстатокСкидки = СуммаКупона;
КоличествоСтрок = МассивПлатныхСтрок.Количество();
Для Индекс = 0 По КоличествоСтрок - 1 Цикл
СтрокаТовара = МассивПлатныхСтрок[Индекс];
ТекущаяСтоимостьСтроки = СтрокаТовара.Сумма - СтрокаТовара.СуммаСкидки;
Если Индекс = КоличествоСтрок - 1 Тогда
// В последнюю строку пишем весь остаток, чтобы избежать копеечных погрешностей округления
ТекущаяСкидкаСтроки = ОстатокСкидки;
Иначе
ТекущаяСкидкаСтроки = ОкруглитьДоКопеек(СуммаКупона * (ТекущаяСтоимостьСтроки / ОбщаяСтоимостьПлатныхТоваров));
ОстатокСкидки = ОстатокСкидки - ТекущаяСкидкаСтроки;
EndЕсли;
// Записываем рассчитанную скидку обратно в структуру данных 1С:Розницы
СтрокаТовара.СуммаСкидки = СтрокаТовара.СуммаСкидки + ТекущаяСкидкаСтроки;
КонецЦикла;
КонецПроцедуры
Функция ОкруглитьДоКопеек(Значение)
Возврат Окр(Значение, 2, РежимОкругления.Окр15_21);
КонецФункции
Использование этого кода гарантирует, что программа всегда будет анализировать реальную стоимость товарных позиций на момент расчета и никогда не попытается распределить скидку по купону на товар, который уже отпускается бесплатно.
Мы проанализировали проблему распределения скидок в «1С:Розница 2.2» и рассмотрели три метода борьбы с потерей скидки по купону: