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