При формировании печатных форм на основании документа ПоступлениеТоваровУслуг в типовых конфигурациях (например, «1С:Управление торговлей 10.3») по умолчанию выводятся закупочные цены, указанные непосредственно в табличной части документа. Однако для внутреннего учета или оформления передачи товара в розничные торговые точки часто требуется вывести накладную с действующими розничными ценами. Разберем по шагам, как правильно составить запрос к регистру сведений цен, избежать типичных ошибок при передаче параметров и корректно заполнить макет печатной формы.
Для получения актуальных цен в платформе «1С:Предприятие» используется виртуальная таблица СрезПоследних регистра сведений ЦеныНоменклатуры. При реализации этой логики разработчики часто сталкиваются со следующими ошибками:
&Номенклатура / &СписокНоменклатуры.ОбластьМакета.Параметры.ЦенаРоз = Выборка вместо позиционирования выборки методом Выборка.Следующий() и получения конкретного числового значения поля.ТекущаяДата() вместо даты проведения документа, из-за чего в печатную форму прошлых периодов попадают сегодняшние измененные цены.Рассмотрим оптимальный способ получения цен сразу для всех позиций, указанных в табличной части документа. Мы выгружаем список позиций в массив, передаем его в параметры виртуальной таблицы среза последних и связываем полученные цены с выводом строк.
// 1. Определяем нужный тип цен (например, розничный)
ТипЦенРозничный = Справочники.ТипыЦенНоменклатуры.НайтиПоКоду("000000001");
// 2. Получаем список номенклатуры из документа поступления
СписокНоменклатуры = СсылкаНаДокумент.Товары.ВыгрузитьКолонку("Номенклатура");
// 3. Формируем запрос к регистру сведений
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Номенклатура КАК Номенклатура,
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &Дата,
| ТипЦен = &ТипЦен И Номенклатура В (&СписокНоменклатуры)
| ) КАК Цены";
// 4. Устанавливаем параметры среза
Запрос.УстановитьПараметр("Дата", СсылкаНаДокумент.Дата);
Запрос.УстановитьПараметр("ТипЦен", ТипЦенРозничный);
Запрос.УстановитьПараметр("СписокНоменклатуры", СписокНоменклатуры);
ТаблицаЦен = Запрос.Выполнить().Выгрузить();
ТаблицаЦен.Индексы.Добавить("Номенклатура");
// 5. Заполняем область макета при обходе строк документа
ТабличныйДокумент = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Накладная");
ОбластьСтроки = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТовара Из СсылкаНаДокумент.Товары Цикл
НайденнаяЦена = ТаблицаЦен.Найти(СтрокаТовара.Номенклатура, "Номенклатура");
РозничнаяЦена = 0;
Если НайденнаяЦена <> Неопределено Тогда
РозничнаяЦена = НайденнаяЦена.Цена;
КонецЕсли;
ОбластьСтроки.Параметры.Заполнить(СтрокаТовара);
ОбластьСтроки.Параметры.ЦенаРоз = РозничнаяЦена;
ОбластьСтроки.Параметры.СуммаРоз = СтрокаТовара.Количество * РозничнаяЦена;
ТабличныйДокумент.Вывести(ОбластьСтроки);
КонецЦикла;
Проанализируем более производительный подход. Вместо отдельной выгрузки колонок и поиска в таблице значений мы соединяем саму табличную часть документа ПоступлениеТоваровУслуг.Товары с виртуальной таблицей среза последних цен в рамках одного запроса.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДокТовары.НомерСтроки КАК НомерСтроки,
| ДокТовары.Номенклатура КАК Номенклатура,
| ДокТовары.Номенклатура.Наименование КАК ТоварНаименование,
| ДокТовары.Количество КАК Количество,
| ДокТовары.Коэффициент КАК Коэффициент,
| ЕСТЬNULL(Цены.Цена, 0) КАК РозничнаяЦенаБазовая,
| ЕСТЬNULL(Цены.Цена * ДокТовары.Коэффициент, 0) КАК ЦенаРоз,
| ЕСТЬNULL(Цены.Цена * ДокТовары.Коэффициент * ДокТовары.Количество, 0) КАК СуммаРоз
|ИЗ
| Документ.ПоступлениеТоваровУслуг.Товары КАК ДокТовары
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &Дата,
| ТипЦен = &ТипЦен
| ) КАК Цены
| ПО ДокТовары.Номенклатура = Цены.Номенклатура
|ГДЕ
| ДокТовары.Ссылка = &СсылкаНаДокумент
|УПОРЯДОЧИТЬ ПО
| НомерСтроки";
Запрос.УстановитьПараметр("СсылкаНаДокумент", Ссылка);
Запрос.УстановитьПараметр("Дата", Ссылка.Дата);
Запрос.УстановитьПараметр("ТипЦен", Справочники.ТипыЦенНоменклатуры.НайтиПоКоду("000000001"));
Выборка = Запрос.Выполнить().Выбрать();
ОбластьСтроки = Макет.ПолучитьОбласть("Строка");
Пока Выборка.Следующий() Цикл
ОбластьСтроки.Параметры.Заполнить(Выборка);
ТабличныйДокумент.Вывести(ОбластьСтроки);
КонецЦикла;
При внедрении механизма вывода розничных цен обратите внимание на следующие особенности конфигурации:
ЦеныНоменклатуры хранит цены в разрезе измерения ХарактеристикаНоменклатуры. В условии соединения ПО необходимо обязательно связывать не только номенклатуру, но и характеристику (ДокТовары.ХарактеристикаНоменклатуры = Цены.ХарактеристикаНоменклатуры), иначе цены могут задвоиться или рассчитаться некорректно.ДокТовары.Коэффициент).НайтиПоКоду(...), рекомендуется считывать розничный тип цен непосредственно из реквизитов склада-получателя (например, Ссылка.Склад.ТипЦенРозничнойТорговли).Всего по накладной).Для сохранения типовой конфигурации на полной поддержке рекомендуется выносить подобную печатную форму во внешнюю печатную форму (внешнюю обработку) и регистрировать ее через справочник ВнешниеОбработки.