Как программно получить скидку по номенклатуре и соглашению в УТ 11.2?

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

При интеграции сторонних систем с 1С:Управление торговлей 11.2 часто возникает необходимость узнать итоговую цену товара с учетом всех автоматических скидок, настроенных в базе. Сложность заключается в том, что механизм скидок в УТ 11 достаточно громоздкий: он учитывает множество условий (соглашения, партнеров, склады, объемы продаж, виды цен). В данной статье мы разберем, как программно инициировать расчет скидок, используя типовой функционал конфигурации, особенно если вы работаете через внешнее соединение (COM).

Механизм подсистемы скидок в УТ 11.2

Для начала проанализируем, как система работает "под капотом". Основная логика сосредоточена в общем модуле СкидкиНаценкиСервер. Главная функция, которая нас интересует — Рассчитать(). Она универсальна и вызывается при изменении документов (Заказ клиента, Реализация товаров и услуг и т.д.).

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

Решение №1: Создание временного объекта документа (надежный способ)

Этот метод считается наиболее простым в реализации, так как мы используем готовый механизм платформы по заполнению и расчету. Суть метода: создать в памяти объект ЗаказКлиента, заполнить его минимально необходимыми данными и вызвать расчет.

Рассмотрим пример кода, который можно использовать при работе через COM-соединение:


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

Важный нюанс: при передаче ТаблицыЗначений через COM-соединение следите за тем, чтобы типы данных в колонках соответствовали типам в 1С (ссылки на Номенклатуру, Характеристики и т.д.). Лучше создавать таблицу прямо внутри COM-соединения методом мВнешниеСоединение.NewObject("ValueTable").

Решение №2: Использование структуры вместо объекта (оптимизация)

Создание целого объекта документа (ДокументОбъект) — операция довольно ресурсоемкая, особенно при массовом расчете. Разберем ситуацию, когда можно обойтись структурой. Модуль СкидкиНаценкиСервер.Рассчитать во многих случаях может принять структуру, имитирующую документ.

Для корректного расчета структура должна содержать следующие поля:

  1. Дата — влияет на актуальность скидок в регистре.
  2. Соглашение — источник условий продаж.
  3. Партнер и Контрагент — если скидки привязаны к клиенту.
  4. Склад — если есть складские скидки.
  5. Товары — таблица значений с колонками: Номенклатура, Количество, Цена, Сумма, КлючСвязи.

Выясним причину, почему это работает быстрее: при передаче структуры система пропускает тяжелые процедуры инициализации объекта и подписки на события, работая только с данными для расчета.

Решение №3: Проверка попадания номенклатуры в отбор скидки

Если ваша задача — просто узнать, попадает ли "Товар А" в конкретную скидку (как в сообщении 0), не производя полный расчет суммы, можно воспользоваться методом ДанныеФильтраПоНоменклатуре. Рассмотрим, как это реализовать:

Система хранит условия скидок в виде компоновки данных или специфических отборов. Функция СкидкиНаценкиСервер.ДанныеФильтраПоНоменклатуре(СкидкаСсылка, "ИмяВременнойТаблицы") возвращает текст запроса, который можно встроить в свой алгоритм. Это позволяет быстро проверить тысячи позиций номенклатуры одним запросом к базе данных, не создавая фиктивные заказы.

Критически важные параметры для расчета

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

Таким образом, для получения скидки в УТ 11.2 наиболее "типовым" и безопасным путем является имитация документа ЗаказКлиента. Это гарантирует, что будут учтены все нюансы: от графиков оплаты до специфических настроек конкретного соглашения с клиентом.

← На главную