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