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