Рассмотрим достаточно распространенную задачу при доработке конфигурации 1С:Управление торговлей 11. Допустим, нам необходимо создать внешнюю печатную форму ТОРГ-12, в которую будет выводиться значение дополнительного реквизита номенклатуры, созданного в пользовательском режиме предприятия (например, Срок годности). Зачастую разработчики сталкиваются с ситуацией, когда отдельный запрос в консоли отрабатывает корректно, но при встраивании его в основной механизм печати накладной документы не печатаются, а система выдает сообщение: "не выбрано ни одного товара".
Разберем по шагам, почему возникает эта ошибка, проанализируем исходный код и выясним причину такого поведения системы. В завершении мы сформируем правильный подход к решению этой задачи.
Посмотрим на пример запроса, который часто пишут на начальном этапе разработки:
ВЫБРАТЬ
НоменклатураДополнительныеРеквизиты.Значение КАК СрокГодности,
НоменклатураДополнительныеРеквизиты.Ссылка КАК Товар
ПОМЕСТИТЬ ВТ_СрокиГодности
ИЗ
Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
ГДЕ
НоменклатураДополнительныеРеквизиты.Свойство.Наименование ПОДОБНО "%СрокГодности%"
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Артикул КАК Артикул,
ВТ_СрокиГодности.СрокГодности КАК СрокГодности
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_СрокиГодности КАК ВТ_СрокиГодности
ПО (Номенклатура.Ссылка = ВТ_СрокиГодности.Товар)
Проанализируем ситуацию и выделим две глобальные архитектурные ошибки в этом коде:
ПОДОБНО "%СрокГодности%" или функции ПОДСТРОКА — это крайне ненадежный метод. В Плане Видов Характеристик (ПВХ) пользователи могут случайно добавить пробелы (в том числе неразрывные), изменить регистр или опечататься. Из-за этого условие в секции ГДЕ не сработает, временная таблица ВТ_СрокиГодности окажется пустой, и данные не выведутся.Рассмотрим подробнее, как избежать проблемы с пустыми значениями из-за несовпадения строк. Вместо того чтобы искать свойство по наименованию прямо внутри текста запроса, рекомендуется передавать ссылку на это свойство в запрос в качестве параметра (например, &СвойствоСрокГодности).
Получить нужную ссылку можно заранее в модуле объекта при подготовке данных для печати:
СвойствоСрок = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Срок годности");
Запрос.УстановитьПараметр("СвойствоСрокГодности", СвойствоСрок);
Тогда условие в запросе приобретет строгий и надежный вид:
ГДЕ
НоменклатураДополнительныеРеквизиты.Свойство = &СвойствоСрокГодности
Теперь решим главную проблему: как взять номенклатуру из документа реализации и получить для нее значение нашего реквизита. Внешние печатные формы, подключаемые через Библиотеку Стандартных Подсистем (БСП), получают на вход массив ссылок на распечатываемые документы. Этот массив обычно передается в параметр &МассивОбъектов или &СсылкаНаДокумент.
Посмотрим на пример правильной структуры запроса. За основу мы берем табличную часть Товары документа реализации:
ВЫБРАТЬ
РеализацияТовары.Ссылка КАК Документ,
РеализацияТовары.НомерСтроки КАК НомерСтроки,
РеализацияТовары.Номенклатура КАК Номенклатура,
РеализацияТовары.Количество КАК Количество,
ЕСТЬNULL(ДопРеквизиты.Значение, "") КАК СрокГодности
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
ПО РеализацияТовары.Номенклатура = ДопРеквизиты.Ссылка
И ДопРеквизиты.Свойство = &СвойствоСрокГодности
ГДЕ
РеализацияТовары.Ссылка В(&МассивОбъектов)
Такой подход гарантирует, что система обработает только те товары, которые действительно присутствуют в печатаемых документах. Соединение выполняется напрямую по ссылке на номенклатуру и конкретному свойству, что исключает задвоение строк, если у товара заполнено несколько разных дополнительных реквизитов.
Проанализируем задачу с точки зрения архитектуры самой конфигурации 1С:Управление торговлей 11. Важно понимать, что в типовом функционале учет сроков годности обычно ведется не через дополнительные реквизиты самой карточки номенклатуры, а в разрезе Серий номенклатуры.
Если специфика бизнеса предполагает, что каждая партия товара (пакет молока, коробка лекарств) имеет свой собственный срок годности, доп. реквизит в карточке товара не поможет — он будет общим для всех партий. В таком случае срок годности хранится в справочнике СерииНоменклатуры в реквизите ГоденДо.
Рассмотрим, как изменить запрос, если сроки годности ведутся по сериям. Нам потребуется связать табличную часть товаров документа с данными серии:
ВЫБРАТЬ
РеализацияТовары.Номенклатура КАК Номенклатура,
РеализацияТовары.Серия КАК Серия,
Серии.ГоденДо КАК СрокГодности
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СерииНоменклатуры КАК Серии
ПО РеализацияТовары.Серия = Серии.Ссылка
ГДЕ
РеализацияТовары.Ссылка В(&МассивОбъектов)
Однако, если в дополнительном реквизите хранится общая справочная информация (например, текст "12 месяцев с даты производства", единый для всего товара), то подход с использованием табличной части Справочник.Номенклатура.ДополнительныеРеквизиты является абсолютно корректным.
Соберем воедино все рекомендации, которые мы разобрали:
Документ.РеализацияТоваровУслуг.Товары).ЛЕВОЕ СОЕДИНЕНИЕ по ссылке на товар.ПОДОБНО по их наименованию. Передавайте ссылку на свойство в виде параметра запроса.Применяя эти правила, вы сможете создавать надежные внешние печатные формы, которые будут корректно формировать данные и не вызывать ошибок при печати из документов.