Как убрать дублирование строк в запросе и настроить иерархию документов Счет и Поступление в 1С

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Управленческий учет
← На главную

При разработке отчетов в системе 1С программисты часто сталкиваются с ситуацией, когда при соединении двух таблиц (например, Счетов на оплату и Поступлений на расчетный счет) данные «размножаются». Вместо одной строки со счетом и списком его оплат пользователь видит несколько строк, где данные счета дублируются для каждой платежки. Разберем подробно, почему это происходит и как правильно построить отчет «Счет — Поступления» с иерархической структурой и корректными статусами оплаты.

Анализ причины дублирования строк

Проанализируем ситуацию: когда мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ или ЛЕВОЕ СОЕДИНЕНИЕ между Счетом и Поступлением, СУБД формирует плоскую таблицу. Если к одному счету привязано три платежных документа, система создаст три строки. В каждой строке будут данные одного и того же счета, но разные данные документов оплаты.

Многие пытаются решить эту проблему с помощью предложения СГРУППИРОВАТЬ ПО в тексте запроса. Однако, если в список группировочных полей включена Ссылка документа оплаты (как в исходном сообщении), группировка не сработает так, как ожидает разработчик. Поскольку каждая ссылка на документ уникальна, система не может «схлопнуть» эти строки. В итоге мы получаем те же самые дубли, но с лишней нагрузкой на сервер базы данных.

Шаг 1: Правильное построение запроса

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

Рассмотрим пример правильной логики запроса, где мы используем ЛЕВОЕ СОЕДИНЕНИЕ, чтобы видеть даже те счета, по которым еще не было оплат:


ВЫБРАТЬ
    Счет.Ссылка КАК СчетНаОплату,
    Счет.Контрагент КАК Контрагент,
    Счет.СуммаДокумента КАК СуммаСчета,
    Поступление.Ссылка КАК ДокументОплаты,
    ЕСТЬNULL(Поступление.СуммаПлатежа, 0) КАК СуммаОплаты
ИЗ
    Документ.СчетНаОплатуПокупателю КАК Счет
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеНаРасчетныйСчет.РасшифровкаПлатежа КАК Поступление
    ПО Поступление.СчетНаОплату = Счет.Ссылка
        И Поступление.Ссылка.Проведен = ИСТИНА

Обратите внимание: мы убрали СГРУППИРОВАТЬ ПО из самого запроса. Теперь запрос возвращает «сырые» данные, которые мы будем оформлять в красивый отчет средствами Системы компоновки данных (СКД).

Шаг 2: Настройка иерархии в СКД

Чтобы реализовать требование «Счет на оплату и ответвления на документы поступления», необходимо перенести логику группировки из запроса в настройки отчета. Разберем по шагам, как это сделать в конструкторе СКД на вкладке «Настройки»:

  1. Удалите стандартную группировку Детальные записи, которая создается по умолчанию.
  2. Нажмите правую кнопку мыши на корне «Отчет» и выберите «Новая группировка». В качестве поля выберите СчетНаОплату.
  3. Внутри созданной группировки (на уровень ниже) добавьте еще одну группировку — на этот раз выберите Детальные записи.
  4. Теперь настроим Выбранные поля:
    • Для группировки СчетНаОплату выберите поля: СчетНаОплату, Контрагент, СуммаСчета.
    • Для вложенных Детальных записей выберите поля: ДокументОплаты, СуммаОплаты.

Такая структура позволит вывести информацию о счете один раз, а под ней — список всех относящихся к нему платежей. Если оплат нет, в детальных записях будет пусто (благодаря ЛЕВОМУ СОЕДИНЕНИЮ), но сам счет из отчета не пропадет.

Шаг 3: Реализация статусов «Оплачен», «Частично» и «Не оплачен»

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


ВЫБРАТЬ
    Счет.Ссылка КАК СчетНаОплату,
    Счет.СуммаДокумента КАК СуммаСчета,
    ЕСТЬNULL(ТаблицаОплат.ИтогоОплачено, 0) КАК ИтогоОплачено,
    ВЫБОР
        КОГДА ЕСТЬNULL(ТаблицаОплат.ИтогоОплачено, 0) >= Счет.СуммаДокумента ТОГДА "Оплачено"
        КОГДА ЕСТЬNULL(ТаблицаОплат.ИтогоОплачено, 0) > 0 ТОГДА "Оплачено частично"
        ИНАЧЕ "Не оплачено"
    КОНЕЦ КАК СтатусОплаты
ИЗ
    Документ.СчетНаОплатуПокупателю КАК Счет
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            Расшифровка.СчетНаОплату КАК СчетНаОплату,
            СУММА(Расшифровка.СуммаПлатежа) КАК ИтогоОплачено
        ИЗ
            Документ.ПоступлениеНаРасчетныйСчет.РасшифровкаПлатежа КАК Расшифровка
        ГДЕ
            Расшифровка.Ссылка.Проведен
        СГРУППИРОВАТЬ ПО
            Расшифровка.СчетНаОплату
    ) КАК ТаблицаОплат ПО ТаблицаОплат.СчетНаОплату = Счет.Ссылка

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

Шаг 4: Использование ресурсов в СКД

Для того чтобы отчет выводил корректные итоги по суммам, необходимо настроить вкладку «Ресурсы» в СКД. Выясним, какие поля должны стать ресурсами:

Рекомендации по оптимизации

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

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

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

← На главную