Разберем ситуацию, когда компоновщик Системы Компоновки Данных (СКД) перестает "видеть" поля метаданных, хотя, казалось бы, все права установлены корректно и прямые запросы к базе данных возвращают ожидаемые результаты. Эта проблема часто вызывает замешательство у разработчиков, поскольку интуитивно кажется, что полные права должны обеспечивать полный доступ ко всем объектам и их реквизитам.
Наш читатель столкнулся с тем, что при создании формы выбора записи регистра сведений с использованием динамического списка на произвольном запросе, список не отображался, и отбор не работал. При этом, для других регистров аналогичная схема прекрасно функционировала. Выяснение причин привело к интересному открытию, касающемуся взаимодействия СКД с функциональными опциями и правами доступа.
Для начала, давайте воспроизведем ситуацию и поймем, как наш читатель диагностировал проблему. Он разработал тестовую процедуру, которая последовательно обходит все метаданные различных типов (справочники, документы, регистры и т.д.), создает для каждого объекта схему компоновки данных и пытается инициализировать КомпоновщикНастроекКомпоновкиДанных. Цель – проверить, какие объекты метаданных не предоставляют доступных полей для выбора.
&НаСервереБезКонтекста
Процедура ТестНаСервере
МассивКоллекцийМД = Новый Массив;
МассивКоллекцийМД.Добавить(Метаданные.Справочники);
МассивКоллекцийМД.Добавить(Метаданные.Документы);
МассивКоллекцийМД.Добавить(Метаданные.ЖурналыДокументов);
МассивКоллекцийМД.Добавить(Метаданные.ПланыВидовХарактеристик);
МассивКоллекцийМД.Добавить(Метаданные.ПланыСчетов);
МассивКоллекцийМД.Добавить(Метаданные.ПланыВидовРасчета);
МассивКоллекцийМД.Добавить(Метаданные.ПланыОбмена);
МассивКоллекцийМД.Добавить(Метаданные.БизнесПроцессы);
МассивКоллекцийМД.Добавить(Метаданные.Задачи);
МассивКоллекцийМД.Добавить(Метаданные.РегистрыСведений);
МассивКоллекцийМД.Добавить(Метаданные.РегистрыНакопления);
МассивКоллекцийМД.Добавить(Метаданные.РегистрыРасчета);
МассивКоллекцийМД.Добавить(Метаданные.РегистрыНакопления); // Дублирование, но для теста не критично
Для каждого Тек_КоллекцияМД Из МассивКоллекцийМД Цикл
Для Каждого ОбъектМД Из Тек_КоллекцияМД Цикл
Схема = Новый СхемаКомпоновкиДанных;
ИсточникДанных = Схема.ИсточникиДанных.Добавить;
ИсточникДанных.Имя = "ИсточникДанных1";
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанных = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Имя = "Набор1";
НаборДанных.ИсточникДанных = ИсточникДанных.Имя;
НаборДанных.АвтоЗаполнениеДоступныхПолей = Истина;
ПолноеИмяТаблицыБД = ОбъектМД.ПолноеИмя;
ТекстЗапроса = "ВЫБРАТЬ Т.* ИЗ " + ПолноеИмяТаблицыБД + " КАК Т";
НаборДанных.Запрос = ТекстЗапроса;
Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема));
Если Компоновщик.Настройки.ДоступныеПоляВыбора.Элементы.Количество = 1 Тогда // Одно поле - это обычно ссылка, не данные
Сообщить("Нет доступных полей: " + ПолноеИмяТаблицыБД);
Иначе
//Сообщить("Есть доступные поля для регистра - " + ПолноеИмяТаблицыБД);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура Тест(Команда)
ТестНаСервере;
КонецПроцедуры
В результате выполнения этой процедуры, был получен список множества таблиц, для которых КомпоновщикНастроекКомпоновкиДанных не видел никаких полей. При этом важно отметить, что:
Это указывало на то, что проблема лежит не в отсутствии прав на объект как таковой, а в некоем механизме, который влияет на видимость метаданных именно для СКД в рантайме.
После дальнейших экспериментов, было замечено, что для некоторых объектов (например, справочника "НомераГТД"), включение определенной функциональной опции (в данном случае "Торговля импортным товаром") сразу же "оживляло" компоновщик СКД, и он начинал видеть все поля. Это стало ключевой подсказкой.
Функциональные опции в 1С оказывают существенное влияние на видимость полей метаданных и их реквизитов, а также на работу Системы Компоновки Данных (СКД). Даже при наличии полных прав у пользователя, если объект или его реквизит включены в состав функциональной опции, которая отключена, то СКД не будет видеть эти поля.
Давайте подробнее рассмотрим влияние функциональных опций на СКД:
Платформа 1С автоматически изменяет пользовательский интерфейс в соответствии с установленными значениями функциональных опций. Значения функциональных опций кэшируются на сервере. Объект или реквизит будет доступен, если включена хотя бы одна из всех функциональных опций, подключенных к нему.
Возник вопрос: почему при полных правах компоновщик все равно не видит поля? Мы выяснили, что "Полные права" — это тоже обычная роль. И хотя она обычно автоматически добавляется ко всем объектам, есть нюансы:
Просмотр на сам объект, но и права Просмотр на его реквизиты. Галочка "Устанавливать права для реквизитов и табличных частей по умолчанию" призвана обеспечить это, но в некоторых случаях (например, для ролей в расширениях) она может быть "сломана", и права для реквизитов приходится выставлять вручную.Таким образом, утверждение "Прав достаточно. Простой запрос всё видит" верно для прямого доступа, но не для компоновщика СКД, который оперирует на уровне метаданных с учетом функциональных опций.
Чтобы точно определить, какие объекты страдают от проблем с видимостью полей и какие функциональные опции с ними связаны, наш читатель модифицировал свою тестовую процедуру. Давайте посмотрим на этот усовершенствованный диагностический код:
&НаСервереБезКонтекста
Процедура ТестНаСервере
МассивКоллекцийМД = Новый Массив;
МассивКоллекцийМД.Добавить(Метаданные.Справочники);
МассивКоллекцийМД.Добавить(Метаданные.Документы);
МассивКоллекцийМД.Добавить(Метаданные.ЖурналыДокументов);
МассивКоллекцийМД.Добавить(Метаданные.ПланыВидовХарактеристик);
МассивКоллекцийМД.Добавить(Метаданные.ПланыСчетов);
МассивКоллекцийМД.Добавить(Метаданные.ПланыВидовРасчета);
МассивКоллекцийМД.Добавить(Метаданные.ПланыОбмена);
МассивКоллекцийМД.Добавить(Метаданные.БизнесПроцессы);
МассивКоллекцийМД.Добавить(Метаданные.Задачи);
МассивКоллекцийМД.Добавить(Метаданные.РегистрыСведений);
МассивКоллекцийМД.Добавить(Метаданные.РегистрыНакопления);
МассивКоллекцийМД.Добавить(Метаданные.РегистрыРасчета);
МассивКоллекцийМД.Добавить(Метаданные.РегистрыНакопления);
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("ИмяМД");
ТЗ.Колонки.Добавить("ИмяФО");
ТЗ.Колонки.Добавить("ЗначениеФО");
ТЗ.Колонки.Добавить("ХранениеФО");
ТЗ.Колонки.Добавить("Проблема");
// Заполняем ТЗ информацией о функциональных опциях и их связи с объектами
Для каждого Тек_ФО Из Метаданные.ФункциональныеОпции Цикл
Для каждого Тек_Состав Из Тек_ФО.Состав Цикл
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяМД = ?(Тек_Состав.Объект = Неопределено, Неопределено, Тек_Состав.Объект.ПолноеИмя);
НоваяСтрока.ИмяФО = Тек_ФО.ПолноеИмя;
НоваяСтрока.ЗначениеФО = ПолучитьФункциональнуюОпцию(Тек_ФО.Имя);
НоваяСтрока.ХранениеФО = Тек_ФО.Хранение.ПолноеИмя;
НоваяСтрока.Проблема = Ложь;
КонецЦикла;
КонецЦикла;
// Проверяем видимость полей для каждого объекта метаданных
Для каждого Тек_КоллекцияМД Из МассивКоллекцийМД Цикл
Для Каждого ОбъектМД Из Тек_КоллекцияМД Цикл
Схема = Новый СхемаКомпоновкиДанных;
ИсточникДанных = Схема.ИсточникиДанных.Добавить;
ИсточникДанных.Имя = "ИсточникДанных1";
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанных = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Имя = "Набор1";
НаборДанных.ИсточникДанных = ИсточникДанных.Имя;
НаборДанных.АвтоЗаполнениеДоступныхПолей = Истина;
ПолноеИмяТаблицыБД = ОбъектМД.ПолноеИмя;
ТекстЗапроса = "ВЫБРАТЬ Т.* ИЗ " + ПолноеИмяТаблицыБД + " КАК Т";
НаборДанных.Запрос = ТекстЗапроса;
Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема));
Если Компоновщик.Настройки.ДоступныеПоляВыбора.Элементы.Количество = 1 Тогда
Сообщить("Нет доступных полей: " + ПолноеИмяТаблицыБД);
// Помечаем строки в ТЗ, связанные с проблемным объектом, как проблемные
СтрокиФО = ТЗ.НайтиСтроки(Новый Структура("ИмяМД", ПолноеИмяТаблицыБД));
Для каждого Тек_СтрокиФО Из СтрокиФО Цикл
Тек_СтрокиФО.Проблема = Истина;
КонецЦикла;
// Если объект не связан ни с одной ФО, но проблема есть, добавляем запись
Если СтрокиФО.Количество = 0 Тогда
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяМД = ПолноеИмяТаблицыБД;
НоваяСтрока.ИмяФО = "Не обнаружено";
НоваяСтрока.ЗначениеФО = "";
НоваяСтрока.ХранениеФО = "";
НоваяСтрока.Проблема = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
ТЗ.Сортировать("ИмяМД, ИмяФО");
// Здесь можно поставить точку останова и проанализировать ТЗ
СтрокиСПроблемами = ТЗ.НайтиСтроки(Новый Структура("Проблема", Истина));
СтрокиСПроблемамиБезФО = ТЗ.НайтиСтроки(Новый Структура("Проблема, ИмяФО", Истина, "Не обнаружено"));
КонецПроцедуры
Эта модифицированная процедура не только выявляет проблемные объекты, но и собирает информацию о связанных с ними функциональных опциях, их текущем значении и способе хранения. Анализируя полученную таблицу значений ТЗ, мы можем сделать выводы:
Проблема для объекта равно Истина и при этом ЗначениеФО для связанной функциональной опции равно Ложь, то мы нашли вероятную причину проблемы.СтрокиСПроблемамиБезФО не пустые, это может указывать на то, что объект отключается не напрямую, а косвенно через какую-либо подсистему, которая сама привязана к функциональной опции.Именно такой анализ привел к окончательному пониманию: "Некоторые объекты отключаются не непосредственно, а опосредовано через подсистемы, но тоже через ФО." То есть, сам объект может не входить напрямую в состав функциональной опции, но быть частью подсистемы, которая, в свою очередь, управляется функциональной опцией. Отключение этой функциональной опции приведет к недоступности всех объектов подсистемы для компоновщика СКД.
Теперь, когда мы выяснили причину, давайте сформулируем шаги по решению и предотвращению подобной ситуации:
В первую очередь, если вы сталкиваетесь с тем, что СКД не видит поля, хотя права, казалось бы, есть, всегда проверяйте соответствующие функциональные опции. Перейдите в раздел "НСИ и администрирование" (или аналогичный, в зависимости от конфигурации), найдите настройки функциональности и убедитесь, что все необходимые опции, связанные с используемыми объектами метаданных, включены.
Например, если вы работаете с отчетами по импортным товарам, убедитесь, что включена опция "Торговля импортным товаром".
Приведенный выше модифицированный код является отличным инструментом для диагностики. Запустите его в своей информационной базе и проанализируйте таблицу значений ТЗ. Он поможет вам:
Важно помнить, что функциональные опции и их параметры не влияют на состав базы данных. Все таблицы и поля присутствуют в базе данных независимо от состояния функциональных опций. Они управляют только отображением информации в программе и доступностью функциональности.
Когда мы работаем с СКД, она, при программном создании или в пользовательском режиме, учитывает активные функциональные опции, фильтруя доступные поля. Конфигуратор же, как среда разработки, обычно показывает все поля, игнорируя функциональные опции.
В некоторых случаях может потребоваться программно управлять значением функциональной опции. Для этого используем метод ПолучитьФункциональнуюОпцию(), а для установки значения - УстановитьФункциональнуюОпцию(). Однако будьте осторожны: установка значения функциональной опции не вызывает автоматического изменения пользовательского командного интерфейса, для отработки изменения следует вызвать метод ОбновитьИнтерфейс.
Не рекомендуется использовать функциональные опции для управления видимостью элементов управления конкретной формы. Их следует применять для управления доступностью функциональности для всей конфигурации.
Хотя в данном случае причиной были ФО, всегда стоит перепроверить, что у роли пользователя есть права Просмотр не только на сам объект, но и на его реквизиты. Это особенно актуально для ролей, созданных в расширениях, где механизм автоматической установки прав на реквизиты может не сработать.
Проблема, когда компоновщик СКД "слепнет" и не видит поля метаданных, даже при полных правах, чаще всего кроется в отключенных функциональных опциях. Этот механизм предназначен для гибкого управления функциональностью прикладного решения и активно используется в современных типовых конфигурациях 1С. Понимание того, как функциональные опции взаимодействуют с СКД и правами доступа, является критически важным для каждого разработчика и позволяет эффективно диагностировать и решать подобные проблемы.
Всегда начинайте поиск причины с проверки функциональных опций, используйте диагностические инструменты, подобные приведенному в этой статье, и помните о косвенных связях объектов с ФО через подсистемы. Это позволит вам оперативно восстановить работоспособность ваших отчетов и динамических списков на СКД.