Как получить розничные цены товаров для печатной формы накладной в 1С?

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

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

Анализ задачи и типичные ошибки начинающих разработчиков

Для получения актуальных цен в платформе «1С:Предприятие» используется виртуальная таблица СрезПоследних регистра сведений ЦеныНоменклатуры. При реализации этой логики разработчики часто сталкиваются со следующими ошибками:

  1. Неправильная передача параметров запроса: попытка передать объект ссылки вместо типа цен или забытый параметр &Номенклатура / &СписокНоменклатуры.
  2. Построчный вызов запроса в цикле: выполнение отдельного запроса к базе данных на каждую строку табличной части вместо одного пакетного запроса на весь массив позиций документа.
  3. Прямая передача объекта выборки в параметры макета: присвоение ОбластьМакета.Параметры.ЦенаРоз = Выборка вместо позиционирования выборки методом Выборка.Следующий() и получения конкретного числового значения поля.
  4. Игнорирование даты документа: передача ТекущаяДата() вместо даты проведения документа, из-за чего в печатную форму прошлых периодов попадают сегодняшние измененные цены.

Вариант 1. Запрос к регистру цен по массиву номенклатуры документа

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


// 1. Определяем нужный тип цен (например, розничный)
ТипЦенРозничный = Справочники.ТипыЦенНоменклатуры.НайтиПоКоду("000000001");

// 2. Получаем список номенклатуры из документа поступления
СписокНоменклатуры = СсылкаНаДокумент.Товары.ВыгрузитьКолонку("Номенклатура");

// 3. Формируем запрос к регистру сведений
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Цены.Номенклатура КАК Номенклатура,
    |	Цены.Цена КАК Цена
    |ИЗ
    |	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
    |		&Дата,
    |		ТипЦен = &ТипЦен И Номенклатура В (&СписокНоменклатуры)
    |	) КАК Цены";

// 4. Устанавливаем параметры среза
Запрос.УстановитьПараметр("Дата", СсылкаНаДокумент.Дата);
Запрос.УстановитьПараметр("ТипЦен", ТипЦенРозничный);
Запрос.УстановитьПараметр("СписокНоменклатуры", СписокНоменклатуры);

ТаблицаЦен = Запрос.Выполнить().Выгрузить();
ТаблицаЦен.Индексы.Добавить("Номенклатура");

// 5. Заполняем область макета при обходе строк документа
ТабличныйДокумент = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Накладная");
ОбластьСтроки = Макет.ПолучитьОбласть("Строка");

Для Каждого СтрокаТовара Из СсылкаНаДокумент.Товары Цикл
    НайденнаяЦена = ТаблицаЦен.Найти(СтрокаТовара.Номенклатура, "Номенклатура");
    РозничнаяЦена = 0;
    
    Если НайденнаяЦена <> Неопределено Тогда
        РозничнаяЦена = НайденнаяЦена.Цена;
    КонецЕсли;
    
    ОбластьСтроки.Параметры.Заполнить(СтрокаТовара);
    ОбластьСтроки.Параметры.ЦенаРоз = РозничнаяЦена;
    ОбластьСтроки.Параметры.СуммаРоз = СтрокаТовара.Количество * РозничнаяЦена;
    
    ТабличныйДокумент.Вывести(ОбластьСтроки);
КонецЦикла;

Вариант 2. Единый запрос с левым соединением к табличной части

Проанализируем более производительный подход. Вместо отдельной выгрузки колонок и поиска в таблице значений мы соединяем саму табличную часть документа ПоступлениеТоваровУслуг.Товары с виртуальной таблицей среза последних цен в рамках одного запроса.


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

Запрос.УстановитьПараметр("СсылкаНаДокумент", Ссылка);
Запрос.УстановитьПараметр("Дата", Ссылка.Дата);
Запрос.УстановитьПараметр("ТипЦен", Справочники.ТипыЦенНоменклатуры.НайтиПоКоду("000000001"));

Выборка = Запрос.Выполнить().Выбрать();
ОбластьСтроки = Макет.ПолучитьОбласть("Строка");

Пока Выборка.Следующий() Цикл
    ОбластьСтроки.Параметры.Заполнить(Выборка);
    ТабличныйДокумент.Вывести(ОбластьСтроки);
КонецЦикла;

Важные технические нюансы при расчете цен

При внедрении механизма вывода розничных цен обратите внимание на следующие особенности конфигурации:

  1. Учет характеристик номенклатуры: если в информационной базе включен учет по характеристикам, регистр ЦеныНоменклатуры хранит цены в разрезе измерения ХарактеристикаНоменклатуры. В условии соединения ПО необходимо обязательно связывать не только номенклатуру, но и характеристику (ДокТовары.ХарактеристикаНоменклатуры = Цены.ХарактеристикаНоменклатуры), иначе цены могут задвоиться или рассчитаться некорректно.
  2. Коэффициенты упаковок и единиц измерения: в регистре сведений цены чаще всего задаются за базовую единицу хранения. Если в строке документа товар указан в упаковках (местах), розничную цену из регистра необходимо умножать на коэффициент единицы измерения строки документа (ДокТовары.Коэффициент).
  3. Определение типа цен из склада: чтобы избежать жесткой привязки к конкретному коду типа цены в коде через НайтиПоКоду(...), рекомендуется считывать розничный тип цен непосредственно из реквизитов склада-получателя (например, Ссылка.Склад.ТипЦенРозничнойТорговли).
  4. Пересчет итогов по накладной: при замене цен в печатной форме необходимо программно накапливать общую сумму по розничным ценам для корректного вывода итогов в подвале документа (Всего по накладной).

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

← На главную