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