Как правильно запретить удаление записей в независимом регистре сведений?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие 8 часто возникает задача ограничить права пользователей на удаление данных. Если для справочников или документов это решается стандартными ролями, то с регистрами сведений ситуация сложнее. Технически удаление записи в регистре — это запись пустого набора записей по определенному отбору. Из-за этой особенности стандартная проверка на количество записей в наборе часто блокирует не только удаление, но и обычное редактирование. Разберем детально, как решить эту задачу профессионально.

Почему стандартный подход «Количество = 0» не всегда работает?

Рассмотрим ситуацию: мы хотим запретить удаление в модуле набора записей. Если мы напишем простую проверку Если ЭтотОбъект.Количество() = 0 Тогда Отказ = Истина; КонецЕсли;, мы столкнемся с проблемой при интерактивном редактировании записи. Проанализируем механику работы платформы: когда пользователь меняет существующую запись через менеджер записи (в форме записи), система выполняет два шага:

  1. Первый проход: Записывается пустой набор записей по старым измерениям, чтобы «стереть» предыдущее состояние.
  2. Второй проход: Записывается новый набор с измененными данными.

Если мы просто запретим запись пустого набора, пользователь не сможет даже отредактировать запись, так как первый шаг (очистка) будет заблокирован. Выясним, как отличить эти ситуации.

Способ 1. Использование свойства «Модифицированность»

Это наиболее эффективный метод для контроля интерактивных действий пользователя. Свойство Модифицированность ведет себя по-разному в зависимости от того, как инициирована запись. Проанализируем логику поведения платформы:

Таким образом, мы можем точно определить намерение пользователя. Реализуем этот алгоритм в модуле набора записей регистра:


Процедура ПередЗаписью(Отказ, Замещение)
    
    // Если мы в привилегированном режиме, проверку можно пропустить
    Если УстановленПривилегированныйРежим() Тогда
        Возврат;
    КонецЕсли;

    // Проверяем попытку удаления
    Если ЭтотОбъект.Количество() = 0 И ЭтотОбъект.Модифицированность Тогда
        
        // Проверяем права текущего пользователя
        Если НЕ РольДоступна("ПолныеПрава") Тогда
            ТекстСообщения = "Удаление записей из данного регистра запрещено правилами системы.";
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения);
            Отказ = Истина;
        КонецЕсли;
        
    КонецЕсли;

КонецПроцедуры

Важное примечание: Данный метод отлично работает при интерактивной работе пользователя через стандартные формы. Однако стоит помнить, что при программной записи набора (через создание нового объекта СоздатьНаборЗаписей() в коде), свойство Модифицированность может вести себя иначе в зависимости от заполнения набора. Рассмотрим, как сделать защиту более универсальной.

Способ 2. Применение «Дополнительных свойств»

Если вам нужно разрешить удаление записей только определенным обработкам или в конкретных контекстах, используем механизм ДополнительныеСвойства. Это «карман», в который можно положить флаг-разрешение перед выполнением записи.

Разберем по шагам. Сначала в модуле набора записей пропишем строгую проверку:


Процедура ПередЗаписью(Отказ, Замещение)
    
    Если ЭтотОбъект.Количество() = 0 Тогда
        // Проверяем наличие специального ключа в свойствах
        Если НЕ ЭтотОбъект.ДополнительныеСвойства.Свойство("РазрешитьУдалениеАдминистративно") Тогда
            Отказ = Истина;
            ВызватьИсключение "Прямое удаление записей запрещено. Используйте специализированные инструменты.";
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Теперь, если нам все же нужно программно очистить регистр в легитимной обработке, мы пишем следующий код:


Набор = РегистрыСведений.НашРегистр.СоздатьНаборЗаписей();
Набор.Отбор.Организация.Установить(ВыбОрганизация);
// Добавляем ключ разрешения
Набор.ДополнительныеСвойства.Вставить("РазрешитьУдалениеАдминистративно", Истина);
Набор.Записать();

Этот подход считается наиболее профессиональным в среде разработчиков 1С, так как он исключает случайные ошибки и четко разделяет уровни доступа к данным.

Способ 3. Ограничение через настройки прав (RLS)

Хотя у регистров сведений в метаданных нет отдельной галочки «Удаление», мы можем использовать Record Level Security (RLS). Право на удаление в регистрах сведений технически привязано к праву «Изменение».

Если мы настроим RLS на право Изменение с условием, которое всегда ложно для определенных условий (например, запрет редактирования записей прошлых периодов), пользователь не сможет выполнить запись пустого набора поверх существующих данных. Платформа просто не даст изменить состояние базы данных. В качестве альтернативы для настройки ограничений можно использовать готовое расширение для гибкого управления правами доступа на основе метаданных.

Способ 4. Подчинение регистра документу (Режим записи)

Рассмотрим архитектурное решение. Если записи регистра неразрывно связаны с какими-то событиями, лучшим способом запретить их удаление будет изменение режима записи регистра на Подчинение регистратору.

В этом случае записи нельзя будет удалить отдельно от документа. Чтобы удалить данные из регистра, пользователю придется либо пометить документ на удаление, либо отменить его проведение. Это автоматически включает все стандартные механизмы контроля ссылочной целостности 1С. Для корректной очистки информационной базы от всех документов и движений конкретного юридического лица можно использовать выборочное удаление организаций.

Способ 5. Мягкое удаление (Архитектурный подход)

В критически важных системах, где аудит данных стоит на первом месте, проанализируем ситуацию внедрения «мягкого удаления». Вместо физического удаления записей:

  1. Добавим в регистр новый ресурс или измерение Удалена (тип Булево).
  2. В модуле набора записей полностью запретим запись набора с количеством 0.
  3. Вместо удаления будем устанавливать флаг Удалена = Истина.
  4. Все запросы и отчеты перенастроим так, чтобы они игнорировали записи с этим флагом.

Посмотрим на пример кода в модуле набора для такой схемы:


Процедура ПередЗаписью(Отказ, Замещение)
    
    // Запрещаем любую очистку регистра (запись пустого набора)
    Если ЭтотОбъект.Количество() = 0 И Замещение Тогда
        Текст = "Физическое удаление данных запрещено. Используйте пометку неактивности.";
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Текст);
        Отказ = Истина;
    КонецЕсли;

КонецПроцедуры

Резюме и рекомендации

Проанализировав все способы, мы можем сделать вывод: наиболее сбалансированным решением для обычных задач является Способ 1 (проверка модифицированности). Он не мешает пользователям работать, но пресекает попытки намеренного или случайного удаления данных кнопкой Del или через стандартное меню. Для контроля за отсутствием расхождений в учете после внесения подобных программных доработок удобно проводить автоматическую сверку бухгалтерских и налоговых проводок.

Для систем с повышенными требованиями к безопасности данных рекомендуем комбинировать проверку в модуле набора с использованием ДополнительныеСвойства, чтобы даже программный код сторонних обработок не мог бесконтрольно очищать регистры.

← На главную