Почему в событии ПриОткрытии возникает ошибка Поле объекта недоступно для чтения и как ее исправить

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

При разработке и сопровождении внешних обработок в среде 1С:Предприятие 8.3 на управляемых формах разработчики нередко сталкиваются с ситуацией: обработка прекрасно открывается и работает под учетной записью с полными правами администратора, однако при запуске под пользователем с ограниченными правами возникает исключение вида «Поле объекта недоступно для чтения» при обращении к реквизитам объекта (например, в строке Объект.СтавкаНДС = "18";).

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

Причины возникновения ошибки

Рассмотрим основные технические факторы, приводящие к блокировке чтения реквизитов объекта на клиенте:

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

Способ 1. Перенос инициализации данных на сервер

Разберем классическую архитектурную ошибку: инициализацию реквизитов объекта в клиентском событии ПриОткрытии(). По правилам клиент-серверной разработки управляемых форм начальное заполнение данных формы должно происходить в обработчике ПриСозданииНаСервере. На сервере контекст формы формируется напрямую, и платформа имеет полный доступ ко всем типам метаданных.

Посмотрим на пример правильного размещения серверной логики инициализации:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Инициализация реквизитов объекта на стороне сервера
    Если Не ЗначениеЗаполнено(Объект.СтавкаНДС) Тогда
        // Заполняем значение по умолчанию без клиентских ограничений
        Объект.СтавкаНДС = Перечисления.СтавкиНДС.НДС18;
    КонецЕсли;
    
КонецПроцедуры

Клиентский обработчик ПриОткрытии в таком случае освобождается от присвоения значений реквизитам объекта:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    // На клиенте выполняем только действия с интерфейсом, если это необходимо
    
КонецПроцедуры

Способ 2. Использование реквизитов формы вместо реквизитов обработки

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

Разберем по шагам, как перенести реквизит:

  1. Открываем внешнюю обработку в Конфигураторе.
  2. В редакторе формы переходим на правую панель на вкладку Реквизиты.
  3. Создаем новый реквизит формы (например, СтавкаНДСФормы) с простым типом (Строка, Число) или требуемым ссылочным типом.
  4. В коде формы заменяем обращения Объект.СтавкаНДС на прямое имя реквизита формы: СтавкаНДСФормы.

Способ 3. Перепривязка типов и пересоздание реквизитов в Конфигураторе

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

  1. Открываем обработку в Конфигураторе той информационной базы, в которой она будет эксплуатироваться.
  2. Находим проблемный реквизит в дереве метаданных обработки.
  3. Открываем его свойства, очищаем поле Тип, нажимаем применить.
  4. Заново выбираем актуальный тип данных из дерева доступных типов конфигурации.
  5. Если перепривязка не помогла, удаляем проблемный реквизит и создаем его заново с тем же именем, после чего пересохраняем файл обработки.

Способ 4. Проверка прав доступа роли и использование привилегированного режима

Проанализируем ситуацию, когда обычному пользователю ограничен доступ к объектам конфигурации, используемым в типе реквизита. Если логика обработки требует чтения данных, закрытых для пользователя правами доступа, обращение к таким данным должно производиться исключительно на сервере через серверные процедуры с директивой &НаСервереБезКонтекста или в общих модулях с признаком Привилегированный.

Посмотрим на пример безопасного получения данных на сервере:


&НаСервереБезКонтекста
Функция ПолучитьЗначениеСтавкиПоУмолчанию()
    
    // Получение значения в серверном контексте
    Возврат Справочники.СтавкиНДС.НайтиПоНаименованию("20%");
    
КонецФункции

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Объект.СтавкаНДС = ПолучитьЗначениеСтавкиПоУмолчанию();
    
КонецПроцедуры

Способ 5. Очистка пользовательского кэша

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

  1. Завершаем все сеансы работы 1С у пользователя.
  2. Переходим в системные каталоги операционной системы: %AppData%\1C\1Cv8 и %LocalAppData%\1C\1Cv8.
  3. Удаляем каталоги с динамическими буквенно-цифровыми GUID-именами (кэш конфигураций и пользовательских настроек).
  4. Запускаем базу данных повторно и проверяем корректность открытия обработки.
← На главную