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