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

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

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

В чем заключается коренная причина проблемы некорректного дублирования остатков?

Корневая причина проблемы кроется в механизме работы виртуальной таблицы ОстаткиИОбороты регистра накопления, особенно когда мы используем ее с параметром периодичности "Авто" или "Регистратор" и одновременно выводим поля СуммаВзаиморасчетовНачальныйОстаток и СуммаВзаиморасчетовКонечныйОстаток вместе с полем Регистратор.

Когда мы запрашиваем данные из ОстаткиИОбороты с детализацией по Регистратор, система возвращает отдельную строку для каждого движения, совершенного каждым документом-регистратором в выбранном периоде. При этом начальные и конечные остатки, которые по своей природе являются агрегированными значениями для всего выбранного периода (или для каждой точки смены периода), будут дублироваться для каждой такой строки движения. Например, если у контрагента за отчетный период было 5 документов (3 реализации, 1 оплата, 1 возврат), то при запросе с детализацией по регистратору, для этого контрагента будет получено 5 строк. В каждой из этих 5 строк будут продублированы одни и те же значения начального и конечного остатка за весь период. При последующем суммировании в СКД (например, если мы просто выведем эти поля как ресурсы), эти остатки многократно просуммируются, что приведет к их значительному завышению и некорректным итоговым показателям.

Проанализируем ваш исходный запрос, который хорошо демонстрирует эту ситуацию:


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

В этом запросе поля СуммаВзаиморасчетовНачальныйОстаток и СуммаВзаиморасчетовКонечныйОстаток выбираются для каждой строки, генерируемой движением по регистратору. Это именно та причина, по которой происходит их многократное дублирование. Нам необходимо обеспечить, чтобы начальный и конечный остаток был получен один раз для каждого контрагента за весь отчетный период, независимо от количества движений.

Рекомендуемый подход: Использование нескольких наборов данных в СКД

Наиболее надежным, гибким и правильным с методологической точки зрения способом решения этой задачи является разделение запроса на две или более логические части (набора данных) в СКД. Каждый набор данных будет отвечать за свою область информации: один — за остатки на начало и конец периода, другой — за обороты с необходимой детализацией. Затем эти наборы данных связываются между собой в настройках СКД.

  1. Набор данных 1: Получение начальных и конечных остатков

    Первый набор данных мы целиком посвятим получению корректных начальных и конечных остатков по контрагентам за весь период отчета. Для этого мы будем использовать виртуальную таблицу Остатки регистра накопления "ВзаиморасчетыСКонтрагентами" и запросим ее дважды: один раз на начало периода, другой раз на конец периода. Затем объединим результаты с помощью оператора ОБЪЕДИНИТЬ ВСЕ, добавив поля-индикаторы для различия начальных и конечных остатков.

    Запрос для первого набора данных:

    
    ВЫБРАТЬ
        ВзаиморасчетыСКонтрагентамиОстатки.Контрагент КАК Контрагент,
        ВЫБОР
            КОГДА ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток > 0
                ТОГДА ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток
            ИНАЧЕ 0
        КОНЕЦ КАК ДолгКлиента,
        ВЫБОР
            КОГДА ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток < 0
                ТОГДА -ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток
            ИНАЧЕ 0
        КОНЕЦ КАК НашДолг,
        ИСТИНА КАК ЭтоНачальныйОстаток,
        ЛОЖЬ КАК ЭтоКонечныйОстаток
    ИЗ
        РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки(&НачалоПериода, , Контрагент, ) КАК ВзаиморасчетыСКонтрагентамиОстатки
    ГДЕ
        НЕ ВзаиморасчетыСКонтрагентамиОстатки.Контрагент.Экспедитор = ЗНАЧЕНИЕ(Справочник.СотрудникиОрганизаций.ПустаяСсылка)
            
    ОБЪЕДИНИТЬ ВСЕ
            
    ВЫБРАТЬ
        ВзаиморасчетыСКонтрагентамиОстатки.Контрагент,
        ВЫБОР
            КОГДА ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток > 0
                ТОГДА ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток
            ИНАЧЕ 0
        КОНЕЦ,
        ВЫБОР
            КОГДА ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток < 0
                ТОГДА -ВзаиморасчетыСКонтрагентамиОстатки.СуммаВзаиморасчетовОстаток
            ИНАЧЕ 0
        КОНЕЦ,
        ЛОЖЬ,
        ИСТИНА
    ИЗ
        РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки(&КонецПериода, , Контрагент, ) КАК ВзаиморасчетыСКонтрагентамиОстатки
    ГДЕ
        НЕ ВзаиморасчетыСКонтрагентамиОстатки.Контрагент.Экспедитор = ЗНАЧЕНИЕ(Справочник.СотрудникиОрганизаций.ПустаяСсылка)
    

    Пояснения к запросу Набора данных 1:

    1. Виртуальная таблица Остатки: Мы используем ее, поскольку она предназначена именно для получения остатков на определенный момент времени. В отличие от ОстаткиИОбороты, она не детализируется по регистраторам, если явно не указано.
    2. Параметры периода: &НачалоПериода и &КонецПериода — это параметры запроса, которые мы сопоставим со стандартными параметрами отчета СКД. Первый запрос получает остатки на начало периода, второй — на конец.
    3. Параметр "Разделитель": В РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки(&НачалоПериода, , Контрагент, ), третий параметр – это "Разделитель". Указывая Контрагент, мы говорим системе агрегировать остатки по каждому контрагенту.
    4. Разделение на "ДолгКлиента" и "НашДолг": С помощью условного оператора ВЫБОР мы классифицируем остаток (СуммаВзаиморасчетовОстаток) на положительный ("ДолгКлиента") и отрицательный ("НашДолг"). Отрицательный остаток инвертируется, чтобы отображаться как положительное число долга.
    5. Поля-индикаторы: ЭтоНачальныйОстаток и ЭтоКонечныйОстаток — это булевы поля, которые мы добавляем к каждой части запроса ОБЪЕДИНИТЬ ВСЕ. Они позволят нам в СКД однозначно определить, какая строка относится к начальному остатку, а какая к конечному. Это критически важно для правильного агрегирования в ресурсах СКД.
    6. Условие ГДЕ НЕ ... ПустаяСсылка: Оно фильтрует контрагентов, у которых поле "Экспедитор" не заполнено (предполагаем, что такие контрагенты не являются целевыми для отчета).
  2. Набор данных 2: Получение оборотов с детализацией по регистратору

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

    Запрос для второго набора данных:

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

    Пояснения к запросу Набора данных 2:

    1. Виртуальная таблица Обороты: Мы используем ее, поскольку она оптимальна для получения информации только об оборотах между двумя моментами времени.
    2. Периодичность Регистратор: В параметрах виртуальной таблицы Обороты(&НачалоПериода, &КонецПериода, Регистратор, Контрагент, ), третий параметр - это периодичность. Указание Регистратор гарантирует, что мы получим отдельную строку для каждого движения, вызванного каждым документом. Это позволит нам в СКД разделить обороты по типам документов.
    3. Параметр "Разделитель": Как и в первом запросе, Контрагент используется как разделитель, чтобы обороты агрегировались по контрагентам до детализации по регистратору.
    4. Поле СуммаВзаиморасчетовОборот: Это ключевое поле, содержащее сумму движения (оборот) по регистру.
    5. Условие ГДЕ НЕ ... ПустаяСсылка: Аналогично первому запросу, используется для фильтрации нецелевых контрагентов.
  3. Объединение наборов данных и настройка полей в СКД

    После того как мы подготовили два отдельных набора данных, следующим шагом является их правильное связывание и настройка полей и ресурсов в конструкторе СКД.

    Настройка связей наборов данных:

    Перейдите на вкладку "Связи наборов данных" в конструкторе СКД. Мы установим связь между "НаборДанных1" (наши остатки) и "НаборДанных2" (наши обороты).

    1. Создайте новую связь (обычно кнопкой с плюсом или "Добавить").
    2. В качестве источника выберите "НаборДанных1", в качестве приемника — "НаборДанных2".
    3. Укажите выражение для связи: НаборДанных1.Контрагент = НаборДанных2.Контрагент. Это означает, что данные из второго набора будут присоединены к данным из первого набора по совпадению контрагентов.
    4. Выберите тип связи, например, "Левое соединение" (Left Join). Это очень важно, так как "Левое соединение" гарантирует, что в отчете будут показаны все контрагенты из "НаборДанных1" (то есть все контрагенты, имеющие остатки на начало или конец периода), даже если у них не было оборотов за отчетный период (во "НаборДанных2"). Если бы мы использовали "Внутреннее соединение", то контрагенты без оборотов были бы исключены из отчета.

    Настройка полей и ресурсов СКД:

    Теперь переходим на вкладку "Поля" и "Ресурсы" в СКД для определения того, как данные будут отображаться и агрегироваться.

    1. Измерения:
      • Поле Контрагент (можно выбрать из любого набора данных, например, НаборДанных1.Контрагент) должно быть определено как основное измерение в отчете.
    2. Ресурсы: Все поля, которые должны суммироваться или отображаться как итоги (начальные/конечные остатки, продажи, оплаты, возвраты), должны быть определены как ресурсы. Это позволит СКД правильно агрегировать данные на уровне группировок.
      • Для начальных и конечных остатков (на основе НаборДанных1):

        Используя поля-индикаторы, которые мы добавили в первый запрос, мы можем корректно агрегировать остатки:

        
        // Долг клиента на начало периода
        МАКСИМУМ(ВЫБОР КОГДА ЭтоНачальныйОстаток ТОГДА ДолгКлиента ИНАЧЕ 0 КОНЕЦ)
        // Наш долг на начало периода
        МАКСИМУМ(ВЫБОР КОГДА ЭтоНачальныйОстаток ТОГДА НашДолг ИНАЧЕ 0 КОНЕЦ)
        // Долг клиента на конец периода
        МАКСИМУМ(ВЫБОР КОГДА ЭтоКонечныйОстаток ТОГДА ДолгКлиента ИНАЧЕ 0 КОНЕЦ)
        // Наш долг на конец периода
        МАКСИМУМ(ВЫБОР КОГДА ЭтоКонечныйОстаток ТОГДА НашДолг ИНАЧЕ 0 КОНЕЦ)
        

        Мы используем функцию МАКСИМУМ(), потому что для каждого контрагента будет ровно одна строка с ЭтоНачальныйОстаток = ИСТИНА и одна строка с ЭтоКонечныйОстаток = ИСТИНА. Остальные значения в этих строках будут нулями благодаря условию ВЫБОР КОГДА ... ИНАЧЕ 0 КОНЕЦ. Таким образом, МАКСИМУМ() надежно "выберет" единственное не-нулевое значение.

      • Для оборотов по типу документа (на основе НаборДанных2):

        Создаем вычисляемые поля-ресурсы, используя агрегатную функцию СУММА() и условные выражения ВЫБОР на основе поля Регистратор из "НаборДанных2".

        
        // Продажи
        СУММА(ВЫБОР КОГДА ТипЗнч(НаборДанных2.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг) ТОГДА НаборДанных2.СуммаОборот ИНАЧЕ 0 КОНЕЦ)
                                
        // Оплачено контрагентом (поступление денег)
        СУММА(ВЫБОР КОГДА ТипЗнч(НаборДанных2.Регистратор) = ТИП(Документ.ПриходныйКассовыйОрдер)
                        ИЛИ ТипЗнч(НаборДанных2.Регистратор) = ТИП(Документ.ПлатежноеПоручениеВходящее)
                    ТОГДА -НаборДанных2.СуммаОборот ИНАЧЕ 0 КОНЕЦ)
                                
        // Возврат от контрагента (уменьшение задолженности покупателя)
        СУММА(ВЫБОР КОГДА ТипЗнч(НаборДанных2.Регистратор) = ТИП(Документ.ВозвратТоваровОтПокупателя)
                    ТОГДА -НаборДанных2.СуммаОборот ИНАЧЕ 0 КОНЕЦ)
                                
        // Оплачено нами (расход денег контрагенту)
        СУММА(ВЫБОР КОГДА ТипЗнч(НаборДанных2.Регистратор) = ТИП(Документ.РасходныйКассовыйОрдер)
                        ИЛИ ТипЗнч(НаборДанных2.Регистратор) = ТИП(Документ.ПлатежноеПоручениеИсходящее)
                    ТОГДА НаборДанных2.СуммаОборот ИНАЧЕ 0 КОНЕЦ)
        

        Важный нюанс: Обратите внимание на использование функции ТипЗнч() в выражениях СКД. Это более надежный и корректный способ проверки типа ссылки документа в вычисляемых полях СКД, чем оператор ССЫЛКА, который обычно используется в запросах. ТипЗнч(ПолеСсылка) = ТИП(Документ.ИмяДокумента) позволяет безопасно сравнить тип значения, даже если поле-ссылка оказалось незаполненным (NULL).

Альтернативные подходы и их ограничения

Рассмотрим другие подходы, которые могут быть предложены, и объясним, почему они могут быть менее предпочтительными для вашей специфической задачи.

  1. Использование вложенного запроса или ОБЪЕДИНИТЬ для остатков (в рамках одного набора данных)

    Существует теоретическая возможность получить все данные (остатки и обороты) в одном основном запросе, используя оператор ОБЪЕДИНИТЬ. В этом случае один подзапрос выбирает только остатки (без детализации по регистратору, заполняя поля оборотов нулями или NULL), а другой подзапрос выбирает только обороты (с детализацией по регистратору, заполняя поля остатков нулями или NULL). Затем эти результаты объединяются.

    Пример структуры такого запроса:

    
    ВЫБРАТЬ
        Остатки.Контрагент КАК Контрагент,
        Остатки.ДолгКлиентаНачальныйОстаток КАК ДолгКлиентаНачальныйОстаток,
        Остатки.НашДолгНачальныйОстаток КАК НашДолгНачальныйОстаток,
        Остатки.ДолгКлиентаКонечныйОстаток КАК ДолгКлиентаКонечныйОстаток,
        Остатки.НашДолгКонечныйОстаток КАК НашДолгКонечныйОстаток,
        NULL КАК Регистратор, // Для строк с остатками регистратор будет пустым
        0 КАК СуммаОборот
    ИЗ
        (ВЫБРАТЬ 
            ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.Контрагент,
            МАКСИМУМ(ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовНачальныйОстаток) КАК ДолгКлиентаНачальныйОстаток,
            МАКСИМУМ(ВЫБОР КОГДА ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовНачальныйОстаток < 0 ТОГДА -ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовНачальныйОстаток ИНАЧЕ 0 КОНЕЦ) КАК НашДолгНачальныйОстаток,
            МАКСИМУМ(ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовКонечныйОстаток) КАК ДолгКлиентаКонечныйОстаток,
            МАКСИМУМ(ВЫБОР КОГДА ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовКонечныйОстаток < 0 ТОГДА -ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.СуммаВзаиморасчетовКонечныйОстаток ИНАЧЕ 0 КОНЕЦ) КАК НашДолгКонечныйОстаток
        ИЗ 
            РегистрНакопления.ВзаиморасчетыСКонтрагентами.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК ВзаиморасчетыСКонтрагентамиОстаткиИОбороты
        СГРУППИРОВАТЬ ПО
            ВзаиморасчетыСКонтрагентамиОстаткиИОбороты.Контрагент) КАК Остатки
            
    ОБЪЕДИНИТЬ ВСЕ
            
    ВЫБРАТЬ
        Обороты.Контрагент,
        0,
        0,
        0,
        0,
        Обороты.Регистратор,
        Обороты.СуммаВзаиморасчетовОборот
    ИЗ
        (ВЫБРАТЬ 
            ВзаиморасчетыСКонтрагентамиОбороты.Контрагент,
            ВзаиморасчетыСКонтрагентамиОбороты.Регистратор,
            ВзаиморасчетыСКонтрагентамиОбороты.СуммаВзаиморасчетовОборот
        ИЗ 
            РегистрНакопления.ВзаиморасчетыСКонтрагентами.Обороты(&НачалоПериода, &КонецПериода, Регистратор, Контрагент, ) КАК ВзаиморасчетыСКонтрагентамиОбороты) КАК Обороты
    

    Ограничения этого подхода:

    • Сложность и читаемость: Такой запрос становится очень громоздким и трудночитаемым, что усложняет его отладку и поддержку.
    • Производительность: Для больших объемов данных объединение сложных подзапросов может быть менее производительным по сравнению с двумя независимыми запросами, которые затем связываются на уровне СКД.
    • Обработка в СКД: Требует аккуратной работы с агрегатными функциями (например, МАКСИМУМ() для остатков) и может привести к трудностям при настройке группировок, так как "строки остатков" и "строки оборотов" имеют принципиально разную детализацию по регистратору.

    Именно из-за этих сложностей мы не рекомендуем данный подход для вашей задачи.

  2. Использование поля "Период, секунда"

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

    Почему это не решает вашу основную проблему и когда это уместно:

    • Не решает проблему дублирования общих остатков: Добавление Период, секунда не устраняет проблему дублирования общих начальных и конечных остатков для всего периода отчета, если вы стремитесь получить одну итоговую сумму по этим показателям для каждого контрагента. Остатки все равно будут повторяться для каждой записи движения в пределах выбранного периода.
    • Излишняя детализация: Если вы добавите Период, секунда в группировки СКД, то отчет станет чрезмерно детализированным, показывая остатки и обороты для каждой секунды, когда произошло движение. Это, как правило, не соответствует требованиям сводного отчета по взаиморасчетам, где нужны агрегированные данные.
    • Когда это уместно: Использование Период, секунда (или Период) полезно, когда вам нужно построить хронологическую выписку по движениям, видеть изменение остатка после каждого документа, или когда важна очень точная последовательность событий. Для сводного отчета с общими остатками и агрегированными оборотами этот подход не подходит.

    Таким образом, хотя "Период, секунда" является мощным инструментом для специфических аналитических задач, он не является решением для корректного отображения сводных начальных и конечных остатков в вашем случае.

Общие рекомендации по настройке СКД для данного отчета

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

  1. Определение ролей полей в СКД:
    • Измерения: Все поля, по которым планируются группировки в отчете (например, Контрагент), должны быть определены как измерения. Это позволяет СКД строить иерархические структуры отчета.
    • Ресурсы: Все числовые поля, которые должны быть агрегированы (суммированы, найден максимум/минимум и т.д.) на уровне группировок или в общих итогах, должны быть определены как ресурсы. Убедитесь, что для остатков используются агрегатные функции, которые "поднимают" одно уникальное значение (как мы рассмотрели выше с МАКСИМУМ(ВЫБОР КОГДА ЭтоНачальныйОстаток ТОГДА ДолгКлиента ИНАЧЕ 0 КОНЕЦ)), а для оборотов — стандартная функция СУММА().
  2. Использование вычисляемых полей: Активно используйте вычисляемые поля на вкладке "Вычисляемые поля" в СКД. Это позволяет:
    • Сохранить запрос данных более чистым и фокусированным.
    • Гибко управлять логикой отчета без необходимости модифицировать основной запрос.
    • Использовать сложные условные выражения (как для разделения оборотов по типам документов) и агрегатные функции.
  3. Настройка параметров отчета:
    • Определите стандартные параметры &НачалоПериода и &КонецПериода на вкладке "Параметры" СКД. Для них обычно устанавливается тип данных Дата, режим редактирования "Стандартный период" и возможность выводить в быстрые настройки.
    • Убедитесь, что эти параметры привязаны к соответствующим параметрам виртуальных таблиц в обоих ваших наборах данных.
  4. Структура отчета:
    • В структуре отчета добавьте необходимую группировку (например, по Контрагент).
    • В выбранных полях для этой группировки (или для общей детализации, если нет других группировок) укажите все необходимые ресурсы: начальные остатки, обороты по типам документов, конечные остатки.
    • Вы можете настроить порядок следования колонок и их заголовки на вкладке "Выбранные поля".

Заключение

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

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

← На главную