Как реализовать пересчет цен из упаковок в базовые единицы измерения в печатных формах 1С:ERP

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

В процессе работы с системой 1С:ERP Управление предприятием часто возникает ситуация, когда закупки или продажи ведутся в упаковках (например, бутыли по 50 литров или еврокубы по 1000 литров, для которых может потребоваться упаковочный лист из реализации товаров), но в печатной форме документа необходимо отображать данные строго в базовых единицах хранения — например, в литрах — для этого есть автоматический пересчет весогабаритных характеристик и упаковок. При этом цена также должна автоматически пересчитываться пропорционально объему упаковки.

Рассмотрим подробно, как устроен этот механизм «под капотом» системы и как правильно реализовать программный пересчет для вывода корректных данных в колонках «Единица измерения», «Количество» и «Цена» (особенно в УПД с изменениями 1 января 2026г.) — поможет подмена наименований и цен под требования контракта.

Механизм коэффициентов упаковок в 1С:ERP

Для начала проанализируем, как система хранит информацию о соотношении упаковки и базовой единицы (см. также вес и объём в документах) — есть готовый автоматический вывод весо-объемных характеристик в печатные формы. В современных версиях ERP (начиная с 2.4/2.5) справочник УпаковкиЕдиницыИзмерения объединяет в себе как индивидуальные упаковки номенклатуры, так и общие наборы упаковок.

Ключевыми реквизитами для нас являются Числитель и Знаменатель. Коэффициент пересчета всегда рассчитывается как результат деления числителя на знаменатель. Если мы имеем упаковку «Бутыль 50 л», то:

  1. Базовая единица: литры.
  2. Числитель: 50.
  3. Знаменатель: 1.
  4. Коэффициент: 50 / 1 = 50.

Когда пользователь меняет единицу измерения в табличной части документа (например, с «Бутыль» на «Литр»), встроенные механизмы (общий модуль НоменклатураКлиентСервер) используют этот коэффициент, чтобы разделить текущую цену на 50 и умножить количество на 50.

Реализация пересчета в печатной форме через расширение (на примере УПД 2026 с QR-Code)

Чтобы не «засорять» основную конфигурацию и сохранить возможность беспроблемного обновления, разберем решение через механизм Расширений — удобнее через конструктор печатных форм и настройки запросов 1С. Нам необходимо перехватить формирование данных для печатной формы (обычно это происходит в менеджере объекта, например, в модуле менеджера документа ПриобретениеТоваровУслуг).

Рассмотрим алгоритм действий программного пересчета:

  1. Получаем данные табличной части документа запросом.
  2. Соединяем таблицу товаров со справочником УпаковкиЕдиницыИзмерения.
  3. В цикле обхода выборки или в самом запросе производим математические операции.

Посмотрим на пример кода, который можно внедрить в процедуру подготовки данных печати:


// В обработке формирования данных печати
Для Каждого СтрокаТаблицы Из ДанныеДляПечати Цикл
    
    // Проверяем, заполнена ли упаковка и отличается ли она от единицы хранения
    Если ЗначениеЗаполнено(СтрокаТаблицы.Упаковка) Тогда
        
        // Получаем коэффициент через типовую функцию
        Коэффициент = УпаковкиСервер.КоэффициентУпаковки(СтрокаТаблицы.Упаковка);
        
        Если Коэффициент <> 0 Тогда
            // Пересчитываем количество: увеличиваем на коэффициент
            СтрокаТаблицы.Количество = СтрокаТаблицы.Количество * Коэффициент;
            
            // Пересчитываем цену: уменьшаем пропорционально коэффициенту
            СтрокаТаблицы.Цена = СтрокаТаблицы.Цена / Коэффициент;
            
            // Устанавливаем единицу измерения в значение "Литры" (ЕдиницаХранения)
            СтрокаТаблицы.ЕдиницаИзмерения = СтрокаТаблицы.Номенклатура.ЕдиницаИзмерения;
        КонецЕсли;
        
    КонецЕсли;
    
КонецЦикла;

Использование встроенных функций системы

Для обеспечения надежности кода и исключения ошибок (например, деления на ноль), рекомендуется использовать функции общих модулей. Разберем подробнее функцию УпаковкиСервер.КоэффициентУпаковки(). Она универсальна и умеет корректно обрабатывать ситуацию, когда передан пустой объект (в этом случае коэффициент вернется равным 1).

Если же вы решите «колхозить» (как выразился автор темы), проверяя тип значения, это может выглядеть так:


// Проверка типа в коде
Если ТипЗнч(Строка.Упаковка) = Тип("СправочникСсылка.УпаковкиЕдиницыИзмерения") Тогда
    Числитель = Строка.Упаковка.Числитель;
    Знаменатель = Строка.Упаковка.Знаменатель;
    
    Если Числитель > 0 Тогда
        Коэффициент = Числитель / ?(Знаменатель = 0, 1, Знаменатель);
        // Выполняем расчеты...
    КонецЕсли;
КонецЕсли;

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

Проблема округления цен

Выясним одну из главных причин расхождения сумм в документах. Когда мы делим цену за упаковку (например, 9500 руб.) на объем (например, 33 литра), мы получаем бесконечную дробь 287.878787.... В печатной форме цена обычно выводится с точностью до 2 знаков (копейки).

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

Работа с ценами поставщиков

Если вам нужно подтянуть цену именно из регистра ЦеныНоменклатурыПоставщиков, проанализируем ситуацию. В этом регистре цена может храниться как за 1 литр, так и за 1 упаковку. Если вы используете механизм Ценообразование в ERP, система сама умеет приводить цены к нужному виду в документах закупки, если в соглашении с поставщиком настроено использование упаковок.

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

Резюме

Для реализации задачи необходимо:

  1. Создать расширение для нужной печатной формы — есть инструмент создания произвольных печатных форм без программирования.
  2. В модуле формирования данных заменить стандартный вывод единиц на реквизит номенклатуры ЕдиницаИзмерения (или ЕдиницаДляОтчетов).
  3. Применить коэффициент упаковки к количеству (умножение) и цене (деление).
  4. Использовать функцию УпаковкиСервер.КоэффициентУпаковки для безопасности расчетов.
  5. Следить за тем, чтобы итоговая сумма строки не менялась из-за погрешностей округления цены.
← На главную