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