Как ограничить максимальную скидку на определенные товары при наличии общей скидки контрагента в 1С:УТ 10.3?

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

Разберем частую ситуацию, с которой сталкиваются пользователи конфигурации 1С:Управление торговлей 10.3. Предположим, у нас есть контрагент, которому назначена глобальная скидка 15% на весь ассортимент. Однако в базе присутствует определенная группа товаров (например, с низкой маржинальностью), на которую скидка не должна превышать 12%. При попытке настроить это типовыми средствами выясняется, что система всегда применяет 15%, полностью игнорируя наше ограничение в 12%.

Проанализируем причину такого поведения. В типовой конфигурации УТ 10.3 жестко зашит алгоритм «Максимальной скидки». Если на одну и ту же позицию номенклатуры при продаже срабатывает сразу несколько условий (общая скидка клиенту, скидка по ценовой группе и т.д.), система не суммирует их и не вытесняет по приоритету. Она просто выбирает максимальное значение. Именно поэтому 15% перекрывают 12%.

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

Решение 1: Обход проблемы с помощью «Типов цен» (без программирования)

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

  1. Создадим новый тип цены, например, Цена со скидкой 15%.
  2. Для основной массы товаров настроим расчет этого типа цены как Базовая (розничная) цена - 15%.
  3. Для товаров-исключений (где скидка не более 12%) назначим этот же тип цены, но рассчитаем его по формуле Базовая цена - 12% (или установим вручную).
  4. В документе Реализация товаров и услуг для данного контрагента будем подставлять именно этот тип цены. В таком случае конфликт механизмов скидок полностью исключается.

Также можно использовать механизм Ценовых групп. Присвоим всей номенклатуре одну ценовую группу, а товару с ограничением скидки — другую. Затем в установке скидок укажем проценты не на всю номенклатуру в целом, а по конкретным ценовым группам.

Решение 2: Программная доработка логики расчета скидок

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

Откроем общий модуль ОбработкаТабличныхЧастей и найдем процедуру РассчитатьСкидкиПриПродаже. Добавим в нее проверку родителя:


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

Такой подход позволяет задавать альтернативные скидки на группу номенклатуры. Если зарегистрирована скидка непосредственно на товар — применяется она, иначе система считывает условия группы.

Решение 3: Автоматическая подстановка дисконтных карт

Еще один обходной маневр с минимальным программированием — привязать особые условия к дисконтным картам. Создадим для контрагента информационную карту, на которую назначены специфические скидки. Чтобы менеджеры не забывали ее указывать, автоматизируем подстановку карты при выборе контрагента.

В модуле формы документа продажи (например, реализации или заказа) в процедуре КонтрагентПриИзменении вызовем нашу новую процедуру:


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

Важный нюанс: Этот способ имеет недостаток, если у контрагента несколько карт — запрос просто возьмет первую подходящую по сортировке кода. Но для жестко регламентированных VIP-клиентов это отличный полуавтоматический вариант.

Ограничение скидки: как работает типовой функционал?

В типовом документе Установка скидок номенклатуры присутствует реквизит Ограничение скидки. Однако стоит учитывать, что в УТ 10.3 он часто используется для установки максимального предела скидки в виде конкретной суммы, а не процента. То есть мы можем сказать: «Скидка 15%, но не более 1000 рублей на документ». Для нашей задачи (ограничить процент другой скидкой) этот реквизит без доработки кода не подходит.

Как это реализовано в новых конфигурациях 1С?

Проанализировав данную проблему, важно отметить, что архитектурные ограничения алгоритмов расчета скидок в УТ 10.3 были признаны разработчиками и полностью переработаны в современных редакциях (УТ 11, Комплексная автоматизация 2, ERP). Там реализован мощный функционал Дерево скидок.

В Дереве скидок можно гибко настраивать правила совместного применения, распределяя их по папкам со следующими условиями:

  1. Максимум — применяется одна максимальная скидка из группы (как в УТ 10.3).
  2. Минимум — применяется минимальная скидка (отлично решает нашу задачу ограничения).
  3. Сложение — проценты просто суммируются (например, 5% по акции + 3% по карте = 8%).
  4. Последовательное применение (умножение) — каждая последующая скидка применяется к сумме, оставшейся после вычета предыдущей.
  5. Вытеснение — скидка с высшим приоритетом отменяет действие всех остальных.

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

← На главную