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