Как выбрать документы, введенные на основании других документов в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Способ 1. Прямой запрос к документам через условие или соединение

Самый производительный и гибкий способ — использование языка запросов 1С. Логика запроса зависит от того, где именно в конфигурации хранится ссылка на документ-основание: в реквизите шапки или в строках табличной части.

1. Если основание хранится в реквизите шапки

Когда в подчиненном документе есть реквизит ДокументОснование, мы можем выбрать все документы за период, передав массив ссылок исходных документов в параметр:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	СписаниеБезналичныхДенежныхСредств.Ссылка КАК Платежка,
    |	СписаниеБезналичныхДенежныхСредств.ДокументОснование КАК СчетНаОплату,
    |	СписаниеБезналичныхДенежныхСредств.СуммаДокумента КАК Сумма
    |ИЗ
    |	Документ.СписаниеБезналичныхДенежныхСредств КАК СписаниеБезналичныхДенежныхСредств
    |ГДЕ
    |	СписаниеБезналичныхДенежныхСредств.ДокументОснование В(&МассивСчетов)
    |	И НЕ СписаниеБезналичныхДенежныхСредств.ПометкаУдаления";

Запрос.УстановитьПараметр("МассивСчетов", МассивСчетов);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

2. Если основание хранится в табличной части

В современных типовых конфигурациях (1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей, 1С:Бухгалтерия предприятия) один платежный документ может закрывать сразу несколько счетов. В этом случае основание хранится в строках табличной части (например, РасшифровкаПлатежа, поле ОснованиеПлатежа или ДокументРасчетовСКонтрагентом):


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

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

Оптимизация запросов по составным типам данных

Поле ДокументОснование практически всегда имеет составной тип данных. На уровне СУБД фильтрация или соединение по составному полю без уточнения типа порождает множество неэффективных соединений (LEFT JOIN) со всеми таблицами, входящими в тип. Чтобы запрос работал максимально быстро, соблюдаем два правила:

  1. Использование оператора ВЫРАЗИТЬ: при явном приведении типа платформа обращается только к нужной таблице: ВЫРАЗИТЬ(Платежка.ДокументОснование КАК Документ.СчетНаОплатуПоставщика)
  2. Проверка типа через ССЫЛКА: если мы фильтруем выборку, добавляем условие проверки типа перед проверкой вхождения в массив:
    
    ГДЕ
    	Платежка.ДокументОснование ССЫЛКА Документ.СчетНаОплатуПоставщика
    	И Платежка.ДокументОснование В (&МассивСчетов)
    

Способ 2. Использование критериев отбора

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

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	СвязанныеДокументы.Ссылка КАК ПодчиненныйДокумент
    |ИЗ
    |	КритерийОтбора.СвязанныеДокументы(&СчетОснование) КАК СвязанныеДокументы
    |ГДЕ
    |	СвязанныеДокументы.Ссылка ССЫЛКА Документ.СписаниеБезналичныхДенежныхСредств";

Запрос.УстановитьПараметр("СчетОснование", СсылкаНаСчет);
Результат = Запрос.Выполнить().Выгрузить();

Нюансы использования критериев отбора:

  1. Запрос к критерию отбора работает только по одному значению параметра (нельзя передать массив ссылок напрямую в виртуальную таблицу). Если требуется обработать список счетов, предпочтительнее использовать прямой запрос к таблицам документов.
  2. Если разработчик конфигурации не включил реквизит подчиненного документа в состав критерия отбора, платформа не найдет этот документ.

Способ 3. Поиск через регистры взаиморасчетов

Если в процессе учета реквизит основания не был заполнен напрямую, но платеж разносился по конкретному счету, восстановить цепочку можно через движения регистров накопления (например, РасчетыСПоставщиками или ВзаиморасчетыСКонтрагентами).


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

Запрос.УстановитьПараметр("МассивСчетов", МассивСчетов);
Выборка = Запрос.Выполнить().Выгрузить();

Способ 4. Использование механизмов БСП (Библиотеки стандартных подсистем)

Если необходимо сформировать полное дерево связей с учетом программных алгоритмов, переопределенных в конфигурации, используем подсистему СвязанныеДокументы. Программный интерфейс БСП собирает подчиненные объекты не только по жестким реквизитам метаданных, но и по правилам, заданным в общем модуле СвязанныеДокументыПереопределяемый.

Для интерактивного открытия дерева подчиненности документа в управляемой форме используется вызов общей формы структуры подчиненности:


ПараметрыОткрытия = Новый Структура("ВыделенныеСтроки", Новый Массив);
ПараметрыОткрытия.ВыделенныеСтроки.Добавить(СсылкаНаСчет);
ОткрытьФорму("ОбщаяФорма.СвязанныеДокументы", ПараметрыОткрытия);

Резюме

Для массовой выборки подчиненных документов за период оптимальным решением является прямой запрос к табличной части или шапке подчиненного документа с типизацией через ССЫЛКА / ВЫРАЗИТЬ и фильтрацией по массиву оснований В (&МассивОснований). Критерии отбора и функции БСП удобнее использовать для единичного интерактивного анализа связей конкретного документа.

← На главную