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

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

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

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

Анализ структуры связей документов

Прежде чем приступать к написанию кода, проанализируем, как документы связаны в базе данных. В большинстве типовых и доработанных конфигураций связь реализуется через реквизит ДокументОснование. В нашей ситуации цепочка выглядит следующим образом:

  1. Заказ покупателя — является основанием для Реализации.
  2. Реализация товаров и услуг — имеет в поле ДокументОснование ссылку на Заказ.
  3. Платежное поручение входящее — имеет в поле ДокументОснование ссылку на Реализацию.

Наша цель — получить сумму из Платежного поручения, зная только ссылку на Заказ покупателя. Давайте разберем, как это реализовать пошагово.

Способ 1. Использование вложенного запроса для связи через посредника

Рассмотрим вариант, когда мы строим запрос к таблице заказов и присоединяем к ней вложенную выборку, которая уже содержит связь "Реализация — Платеж". Это наиболее наглядный способ для понимания логики соединения.

Проанализируем пример кода:


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

В данном примере во вложенном запросе мы сначала связываем реализацию с платежом, а затем результат этого соединения "подтягиваем" к заказу. Обратите внимание на использование ЛЕВОЕ СОЕДИНЕНИЕ к основной таблице заказов — это гарантирует, что в отчет попадут все заказы, даже те, по которым еще не было оплат.

Способ 2. Оптимизация через временные таблицы

Для сложных отчетов в СКД использование вложенных запросов может привести к снижению производительности. Разберем более профессиональный подход — использование временных таблиц (ПОМЕСТИТЬ). Это позволяет СУБД лучше оптимизировать план выполнения запроса.

Разобьем задачу на этапы: сначала соберем все данные по счетам (заказам), затем по отгрузкам и в конце — по оплатам. Посмотрим на структуру такого запроса:


// Шаг 1: Собираем данные по заказам
ВЫБРАТЬ
    Заказ.Ссылка КАК СчетНаОплату,
    Заказ.СуммаДокумента КАК СуммаСчета
ПОМЕСТИТЬ ВТ_Заказы
ИЗ
    Документ.ЗаказПокупателя КАК Заказ
ГДЕ
    Заказ.Дата МЕЖДУ &НачалоПериода И &КонецПериода;

////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Собираем оплаты, связывая их через реализации
ВЫБРАТЬ
    Реализация.ДокументОснование КАК СчетНаОплату,
    СУММА(Платеж.СуммаДокумента) КАК СуммаПлатежа
ПОМЕСТИТЬ ВТ_Оплаты
ИЗ
    Документ.ПлатежноеПоручениеВходящее КАК Платеж
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
    ПО Платеж.ДокументОснование = Реализация.Ссылка
СГРУППИРОВАТЬ ПО
    Реализация.ДокументОснование;

////////////////////////////////////////////////////////////////////////////////
// Шаг 3: Соединяем всё в итоговой выборке
ВЫБРАТЬ
    ВТ_Заказы.СчетНаОплату,
    ВТ_Заказы.СуммаСчета,
    ЕСТЬNULL(ВТ_Оплаты.СуммаПлатежа, 0) КАК СуммаОплаты
ИЗ
    ВТ_Заказы КАК ВТ_Заказы
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Оплаты КАК ВТ_Оплаты
    ПО ВТ_Заказы.СчетНаОплату = ВТ_Оплаты.СчетНаОплату

Этот метод значительно прозрачнее. Мы четко видим, откуда берутся данные на каждом этапе. Важный момент: при соединении платежей и реализаций обязательно используйте СГРУППИРОВАТЬ ПО, чтобы не возникло дублирования строк, если на основании одной реализации введено несколько платежных документов.

Способ 3. Обработка смешанных связей (UNION)

Выясним причину, по которой отчет может показывать неверные данные, если бизнес-процессы в компании изменились. Например, бухгалтер начал вводить платежи напрямую на основании заказов, минуя реализацию. В этом случае наша цепочка "Заказ -> Реализация -> Платеж" разорвется.

Для решения этой проблемы выясним, как объединить оба способа связи во вложенном запросе. Нам поможет оператор ОБЪЕДИНИТЬ ВСЕ.


ВЫБРАТЬ
    Заказ.Ссылка КАК СчетНаОплату,
    СУММА(Оплаты.СуммаДокумента) КАК СуммаПлатежа
ПОМЕСТИТЬ ВТ_ВсеОплаты
ИЗ
    (
    // Вариант 1: Оплата на основании Реализации
    ВЫБРАТЬ
        Реализация.ДокументОснование КАК ЗаказОснование,
        Платеж.СуммаДокумента КАК СуммаДокумента
    ИЗ
        Документ.ПлатежноеПоручениеВходящее КАК Платеж
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
        ПО Платеж.ДокументОснование = Реализация.Ссылка
    
    ОБЪЕДИНИТЬ ВСЕ
    
    // Вариант 2: Оплата напрямую на основании Заказа
    ВЫБРАТЬ
        Платеж.ДокументОснование,
        Платеж.СуммаДокумента
    ИЗ
        Документ.ПлатежноеПоручениеВходящее КАК Платеж
    ГДЕ
        Платеж.ДокументОснование ССЫЛКА Документ.ЗаказПокупателя
    ) КАК Оплаты
СГРУППИРОВАТЬ ПО
    Оплаты.ЗаказОснование

Проанализируем ситуацию: теперь наш отчет универсален. Он найдет оплату, даже если она привязана к промежуточному документу или напрямую к заказу. Использование конструкции ССЫЛКА позволяет отфильтровать только нужные типы оснований во второй части объединения.

Тонкости оптимизации в СКД

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

Таким образом, мы рассмотрели основные методы получения данных по цепочкам документов в СКД. Выбор конкретного метода зависит от сложности вашей конфигурации и того, насколько жестко соблюдается последовательность ввода документов в системе.

← На главную