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