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