При разработке и сопровождении внешних обработок в среде 1С:Предприятие 8.3 на управляемых формах разработчики нередко сталкиваются с ситуацией: обработка прекрасно открывается и работает под учетной записью с полными правами администратора, однако при запуске под пользователем с ограниченными правами возникает исключение вида «Поле объекта недоступно для чтения» при обращении к реквизитам объекта (например, в строке Объект.СтавкаНДС = "18";).
Особенно часто такое поведение наблюдается после обновления типовых конфигураций (например, 1С:Управление торговлей, 1С:Комплексная автоматизация или 1С:ERP). Проанализируем детально, почему коллекция ДанныеФормыСтруктура на стороне клиента блокирует доступ к полям, и разберем надежные способы устранения этой проблемы.
Рассмотрим основные технические факторы, приводящие к блокировке чтения реквизитов объекта на клиенте:
ПеречислениеСсылка.СтавкиНДС, а стал справочником СправочникСсылка.СтавкиНДС). Внешние обработки хранят внутренние идентификаторы типов метаданных. Если обработка не была пересохранена в обновленном конфигураторе, клиентский контекст не может корректно десериализовать тип, и доступ к полю блокируется.Объект (тип ДанныеФормыСтруктура). Попытка прочитать или записать такое свойство в клиентском коде приводит к фатальной ошибке.ДополнительныеОтчетыИОбработки после обновления конфигурации метаданные реквизитов могут оказаться рассинхронизированными с текущей структурой конфигурации.Разберем классическую архитектурную ошибку: инициализацию реквизитов объекта в клиентском событии ПриОткрытии(). По правилам клиент-серверной разработки управляемых форм начальное заполнение данных формы должно происходить в обработчике ПриСозданииНаСервере. На сервере контекст формы формируется напрямую, и платформа имеет полный доступ ко всем типам метаданных.
Посмотрим на пример правильного размещения серверной логики инициализации:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Инициализация реквизитов объекта на стороне сервера
Если Не ЗначениеЗаполнено(Объект.СтавкаНДС) Тогда
// Заполняем значение по умолчанию без клиентских ограничений
Объект.СтавкаНДС = Перечисления.СтавкиНДС.НДС18;
КонецЕсли;
КонецПроцедуры
Клиентский обработчик ПриОткрытии в таком случае освобождается от присвоения значений реквизитам объекта:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// На клиенте выполняем только действия с интерфейсом, если это необходимо
КонецПроцедуры
Если значение реквизита требуется только для работы интерфейса или вспомогательных расчетов, не обязательно объявлять его как реквизит самого объекта обработки в дереве метаданных. Реквизиты, добавленные на вкладку Реквизиты самой формы (а не вложенные в ветку Объект), обладают скалярным поведением и не подвержены строгим ограничениям метаданных объекта при сериализации на тонком клиенте.
Разберем по шагам, как перенести реквизит:
СтавкаНДСФормы) с простым типом (Строка, Число) или требуемым ссылочным типом.Объект.СтавкаНДС на прямое имя реквизита формы: СтавкаНДСФормы.Если проблема вызвана повреждением внутренних идентификаторов типов после обновления типовой конфигурации, выполним процедуру актуализации метаданных:
Проанализируем ситуацию, когда обычному пользователю ограничен доступ к объектам конфигурации, используемым в типе реквизита. Если логика обработки требует чтения данных, закрытых для пользователя правами доступа, обращение к таким данным должно производиться исключительно на сервере через серверные процедуры с директивой &НаСервереБезКонтекста или в общих модулях с признаком Привилегированный.
Посмотрим на пример безопасного получения данных на сервере:
&НаСервереБезКонтекста
Функция ПолучитьЗначениеСтавкиПоУмолчанию()
// Получение значения в серверном контексте
Возврат Справочники.СтавкиНДС.НайтиПоНаименованию("20%");
КонецФункции
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Объект.СтавкаНДС = ПолучитьЗначениеСтавкиПоУмолчанию();
КонецПроцедуры
Если ошибка воспроизводится только у отдельных пользователей после обновления версии конфигурации или платформы, выясним, не закэшировались ли старые метаданные. Для устранения проблемы очистим локальный кэш пользователя:
%AppData%\1C\1Cv8 и %LocalAppData%\1C\1Cv8.