Как получить реквизиты поля "Регистратор" в СКД, если у него установлена роль "Период"?

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

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

Почему возникает ограничение при работе с полем "Регистратор" с ролью "Период"

Когда полю Регистратор в СКД назначена роль "Период", система использует его в первую очередь для определения хронологической последовательности записей и правильного расчета итоговых показателей (остатков, оборотов) по временным интервалам. В этом контексте Регистратор воспринимается не столько как ссылка на конкретный объект метаданных, сколько как временная метка для упорядочивания данных регистра.

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

  1. Фокус на хронологии: Роль "Период" диктует СКД обрабатывать это поле как компонент для группировки по времени и вычисления агрегатных функций. Прямое "раскрытие" реквизитов может нарушить логику временных расчетов или привести к некорректным итогам, так как СКД не предполагает, что поле с этой ролью будет использоваться для навигации по объектам.
  2. Полиморфизм поля "Регистратор": Поле Регистратор может быть ссылкой на различные типы документов (например, Документ.РеализацияТоваровУслуг, Документ.ПоступлениеТоваровУслуг, Документ.ПлатежноеПоручение и т.д.). СКД по умолчанию не может однозначно определить конкретный тип объекта для каждой записи регистра без явного указания. Прямое обращение Регистратор.Реквизит1 будет неоднозначным, если Реквизит1 существует только в одном из возможных типов документов или имеет разные типы в разных документах.
  3. Проблемы с правами доступа: Если у пользователя, формирующего отчет, нет прав на чтение всех возможных типов документов, которые могут выступать в качестве регистратора, СКД может отказать в доступе к их реквизитам, возвращая пустые значения или генерируя ошибки.
  4. Производительность: Прямое раскрытие реквизитов через точку для полиморфного поля на большом объеме данных может быть неэффективным, так как СКД придется выполнять множество неявных соединений для каждого типа документа.

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

Решение 1: Использование левого соединения с отдельным набором данных регистраторов

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

Разберем этот процесс по шагам:

  1. Создание дополнительного набора данных "Запрос" для получения реквизитов регистраторов.

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

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

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

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

    Этот набор данных мы назовем, например, "ДанныеРегистраторов".

  2. Установка связи между основным и дополнительным наборами данных.

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

    • Источник: "ОсновнойНабор"
    • Приемник: "ДанныеРегистраторов"
    • Поле источника: Регистратор (из основного набора)
    • Поле приемника: РегистраторДокумента (из нашего нового набора)
    • Тип связи: Выбираем Левое соединение. Это критически важно! Левое соединение гарантирует, что все записи из основного набора данных (например, начальные остатки, которые могут не иметь регистратора, или записи, для которых по каким-либо причинам не нашлось документа) будут сохранены в отчете. Если бы мы использовали внутреннее соединение, то записи без соответствующего регистратора были бы отфильтрованы, что могло бы привести к некорректным итогам.
    • Параметры связи: Обычно достаточно одного поля, но при необходимости можно добавить дополнительные условия.

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

  3. Добавление полей в структуру отчета.

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

    Теперь в списке доступных полей будут отображаться, например, ДанныеРегистраторов.НомерДокумента, ДанныеРегистраторов.ДатаДокумента, ДанныеРегистраторов.ОтветственныйЛицо и т.д. Эти поля будут содержать нужные реквизиты документа-регистратора, при этом поле Регистратор из основного набора данных сохранит свою роль "Период" и продолжит корректно участвовать в расчете итогов.

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

Решение 2: Использование пользовательских полей (полей выражения) в СКД

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

Разберем процесс использования пользовательских полей:

  1. Создание пользовательского поля.

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

  2. Написание выражения для получения реквизита.

    В поле "Выражение" для созданного поля мы будем использовать функции языка запросов 1С для явного приведения типа регистратора и получения его реквизитов. Это может быть функция ВЫРАЗИТЬ.

    Если мы точно знаем, что в данном отчете Регистратор всегда будет одного конкретного типа (например, Документ.РеализацияТоваровУслуг), выражение будет относительно простым:

    ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг).Дата

    Это выражение "говорит" СКД, что поле Регистратор нужно трактовать как ссылку на документ "Реализация товаров и услуг" и получить его реквизит Дата.

    Однако, как мы уже знаем, Регистратор часто бывает полиморфным. В этом случае нам потребуется использовать конструкцию ВЫБОР КОГДА ... ТОГДА ... КОНЕЦ для обработки разных типов документов. Это позволяет гибко извлекать реквизиты в зависимости от фактического типа регистратора:

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

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

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

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

Важные нюансы и дополнительные рекомендации

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

Сохранение корректности итогов

Это один из наиболее критичных моментов. Поле Регистратор с ролью "Период" является фундаментальным для правильного расчета начальных и конечных остатков, а также оборотов. Любые изменения, которые игнорируют или неправильно обрабатывают эту роль, могут привести к некорректным данным в отчете, как это было замечено автором при попытке изменить роль на "Измерение".

Параметры виртуальных таблиц

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

Влияние прав доступа

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

Оптимизация производительности

Сложные запросы с множеством ОБЪЕДИНИТЬ ВСЕ или длинные конструкции ВЫБОР КОГДА в пользовательских полях могут значительно увеличить время формирования отчета, особенно на больших базах данных. Мы всегда должны стремиться к максимально производительным решениям:

В заключение, задача получения реквизитов поля Регистратор, имеющего роль "Период", в СКД требует внимательного подхода. Применение левого соединения с тщательно проработанным дополнительным набором данных является наиболее универсальным и рекомендуемым решением. Использование пользовательских полей с функцией ВЫРАЗИТЬ или конструкцией ВЫБОР КОГДА также возможно, но требует учета сложности и потенциального влияния на производительность.

← На главную