При работе в конфигурации «1С:Управление торговлей» (начиная с версии 11.4) разработчики и администраторы часто сталкиваются с неожиданным поведением системы после подключения расширений или обновления платформы. Пользователи с ограниченными правами (например, с типовым профилем «Менеджер по продажам») внезапно теряют возможность открыть справочник Номенклатура или запустить форму подбора товаров. При попытке выполнить эти действия система аварийно завершает работу и выдает следующую ошибку:
{ОбщийМодуль.ПодборТоваровСервер.Модуль(2865)}: Поле объекта не обнаружено (ВидыНоменклатурыСоздать) Форма.Элементы.ВидыНоменклатурыСоздать.Видимость = Ложь;
Что примечательно, до добавления расширения всё работало штатно. Более того, даже после полного удаления расширения из базы данных проблема часто сохраняется, приводя администраторов в замешательство. В этой статье мы подробно разберем внутренние механизмы платформы «1С:Предприятие», которые вызывают этот сбой, выясним, почему «виновато» расширение, и рассмотрим несколько практических способов устранения данной ошибки.
Для того чтобы понять природу этой ошибки, проанализируем поведение технологической платформы 1С в различных режимах совместимости.
В старых версиях платформы (когда в конфигурации или в расширении используется режим совместимости 8.3.10 и ниже) элементы стандартных команд динамического списка (кнопки «Создать», «Создать группу», «Изменить», «Скопировать») генерировались платформой в коллекции Элементы управляемой формы в любом случае. Даже если у текущего пользователя не было прав на добавление или изменение объектов этого списка (в данном случае — справочника Виды номенклатуры), кнопка на форме все равно существовала, пусть и была недоступна. Разработчики типовых конфигураций 1С использовали это поведение и писали прямой код для управления интерфейсом:
Форма.Элементы.ВидыНоменклатурыСоздать.Видимость = Ложь;
Начиная с версии платформы 8.3.11 (и особенно ярко это проявляется в 8.3.12 и выше при отключенном режиме совместимости), логика работы платформы стала более строгой и оптимизированной:
Элементы.ВидыНоменклатурыСоздать физически не создается на сервере.ПодборТоваровСервер, система пытается обратиться к несуществующему свойству коллекции по имени. В результате происходит закономерный отказ с ошибкой Поле объекта не обнаружено.Многие разработчики задаются вопросом: почему до подключения расширения все работало хорошо, ведь права пользователя не менялись? Дело в том, что при создании нового расширения платформа по умолчанию может выставить ему режим совместимости «Не использовать» или унаследовать актуальную версию платформы (например, 8.3.11/8.3.12), в то время как основная конфигурация УТ 11 все еще работает в режиме совместимости 8.3.10.
Как только в информационную базу загружается хотя бы одно активное расширение с более высоким режимом совместимости, платформа переводит сеанс работы пользователя на новые, более строгие правила компиляции форм. Отсюда и моментальное появление ошибки.
Если после удаления расширения ошибка не исчезла, это связано с кэшированием схем управляемых форм платформой 1С. Для устранения этого «остаточного эффекта» необходимо выполнить следующие действия:
%userprofile%\AppData\Local\1C\1Cv8)./ClearCache.Существует несколько способов решения этой проблемы: от простой настройки прав пользователей до элегантного программного обхода через расширение конфигурации. Рассмотрим каждый из них подробно.
В современных версиях Библиотеки Стандартных Подсистем (БСП) разработчики 1С отказались от прямого обращения к элементам формы по их имени. Вместо этого используется безопасный метод, который сначала проверяет физическое наличие элемента на форме, и только потом меняет его свойства.
Для того чтобы исправить ошибку по стандартам БСП, мы можем переопределить поведение системы с помощью расширения. Вместо строки прямого назначения видимости:
Форма.Элементы.ВидыНоменклатурыСоздать.Видимость = Ложь;
Необходимо использовать метод общего модуля:
ОбщегоНазначенияКлиентСервер.УстановитьСвойствоЭлементаФормы(Форма.Элементы, "ВидыНоменклатурыСоздать", "Видимость", Ложь);
Давайте разберем, как сделать это через расширение, не снимая основную конфигурацию с поддержки:
ПодборТоваровСервер.&Вместо или корректируем код перед вызовом. Безопасный код в расширении будет выглядеть так:
&Вместо("УстановитьСтраницуВариантаНавигации")
Процедура Расш_УстановитьСтраницуВариантаНавигации(Форма, ВариантНавигации)
// Вызываем оригинальный метод, предварительно подготовив элементы,
// либо полностью переписываем логику инициализации кнопок
ПродолжитьВызов(Форма, ВариантНавигации);
КонецПроцедуры
Или, если вы хотите точечно заменить код вызова, можно использовать следующий шаблон, предварительно проверив наличие реквизита на форме:
Если Форма.Элементы.Найти("ВидыНоменклатурыСоздать") <> Неопределено Тогда
Форма.Элементы.ВидыНоменклатурыСоздать.Видимость = Ложь;
КонецЕсли;
Если вы не хотите полностью переписывать типовой метод в общем модуле ПодборТоваровСервер, можно применить изящный прием. Мы можем перехватить событие ПриСозданииНаСервере у формы выбора или формы подбора номенклатуры и принудительно добавить недостающие кнопки-заглушки в коллекцию элементов формы, если платформа их не создала из-за отсутствия прав у пользователя. Штатный код УТ 11 найдет эти элементы, без ошибок установит им видимость в Ложь, и работа продолжится в обычном режиме.
Для этого выполним следующие шаги:
&Перед("ПриСозданииНаСервере").
&НаСервере
&Перед("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервереПеред(Отказ, СтандартнаяОбработка)
// Если у пользователя нет прав, платформа не создает стандартные кнопки.
// Добавим их программно как заглушки, чтобы избежать падения типового кода.
Если Элементы.Найти("ВидыНоменклатурыСоздать") = Неопределено Тогда
Элементы.Добавить("ВидыНоменклатурыСоздать", Тип("КнопкаФормы"));
КонецЕсли;
Если Элементы.Найти("ВидыНоменклатурыСоздатьГруппу") = Неопределено Тогда
Элементы.Добавить("ВидыНоменклатурыСоздатьГруппу", Тип("КнопкаФормы"));
КонецЕсли;
Если Элементы.Найти("ВидыНоменклатурыИзменить") = Неопределено Тогда
Элементы.Добавить("ВидыНоменклатурыИзменить", Тип("КнопкаФормы"));
КонецЕсли;
Если Элементы.Найти("ВидыНоменклатурыСкопировать") = Неопределено Тогда
Элементы.Добавить("ВидыНоменклатурыСкопировать", Тип("КнопкаФормы"));
КонецЕсли;
КонецПроцедуры
Этот способ крайне удобен, так как он локализован в рамках одной формы подбора, не затрагивает глобальные общие модули и гарантирует стабильную работу формы подбора при любых обновлениях конфигурации.
Если программное вмешательство в код нежелательно, проблему можно решить чисто административными методами 1С, предоставив пользователю необходимые права на метаданные. Ошибка возникает из-за отсутствия прав на справочник Виды номенклатуры. Мы можем дать эти права пользователю тремя путями:
Добавление и изменение классификации номенклатуры. В этом случае алгоритм проверки прав успешно отработает, платформа создаст кнопку на форме, и ошибка исчезнет. Минус этого подхода: Менеджер получит реальные права на редактирование видов номенклатуры, что часто нежелательно с точки зрения ведения учета.Виды номенклатуры и разрешите только чтение и просмотр (без интерактивного добавления). Назначьте эту роль проблемным пользователям.Самый простой способ избежать появления подобных «блох» при разработке собственных расширений — всегда следить за тем, чтобы свойства расширения полностью соответствовали свойствам основной конфигурации. Если ваша основная конфигурация УТ 11 использует режим совместимости 8.3.10, обязательно зайдите в свойства созданного расширения и установите аналогичный режим совместимости вместо значения «Не использовать».
Выполнение этого простого правила гарантирует, что платформа будет интерпретировать код расширения и основной конфигурации по одинаковым стандартам, предохраняя вас от непредвиденных ошибок при работе с динамическими списками и правами доступа.