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

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

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

Метод 1: Проверка в модуле объекта (универсальный способ)

Проанализируем механику работы платформы. Когда пользователь нажимает «Установить пометку на удаление», система инициирует запись объекта. Следовательно, самым надежным местом для внедрения проверки является обработчик ПередЗаписью в модуле объекта документа. Этот метод работает на стороне сервера и срабатывает независимо от того, откуда производится действие: из формы документа, из списка или программным кодом. Для наглядного анализа последовательности срабатывания различных обработчиков можно использовать разработку для изучения событий платформы 1С.

Основная сложность заключается в том, что при входе в процедуру ПередЗаписью реквизит ПометкаУдаления уже содержит новое значение (Истина), и нам нужно понять, изменилось ли оно именно сейчас. Для этого мы сравним текущее состояние объекта в оперативной памяти со значением, которое хранится в базе данных (ссылкой). Рассмотрим пример кода:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

    // Если идет загрузка данных (обмен), проверки обычно отключают
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Проверяем, меняется ли флаг пометки удаления с Ложь на Истина
    Если ПометкаУдаления И НЕ Ссылка.ПометкаУдаления Тогда
        
        // Здесь мы описываем наше условие запрета
        // Например: запрет пометки на удаление проведенного документа
        Если Проведен Тогда
            Отказ = Истина;
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = "Нельзя помечать на удаление проведенный документ!";
            Сообщение.Сообщить();
        КонецЕсли;
        
    КонецЕсли;

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

В этом примере мы использовали объект СообщениеПользователю. Это важный момент: если просто установить Отказ = Истина, система выдаст стандартное сообщение об ошибке записи, которое не объяснит пользователю причину. Использование СообщениеПользователю делает интерфейс дружелюбным.

Метод 2: Использование подписок на события

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

Выясним алгоритм создания такой проверки:

  1. Создадим новый объект метаданных Подписка на событие.
  2. В качестве источника выберем типы документов (или ДокументОбъект для всех документов сразу).
  3. Событие — ПередЗаписью.
  4. В обработчике (в общем модуле) пропишем логику, аналогичную методу выше, используя параметр Источник вместо ЭтотОбъект.

Процедура ЗапретПометкиНаУдалениеПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт

    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

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

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

Метод 3: Работа в управляемых формах и динамических списках

Посмотрим на ситуацию со стороны интерфейса. В старых (обычных) формах существовало событие ПередУстановкойПометкиУдаления. В современных управляемых формах (платформа 8.3) такого события напрямую у формы или списка нет. Однако мы можем перехватить действие пользователя на уровне командной панели динамического списка.

Тем не менее, важно помнить: пользователь может нажать клавишу Del или использовать контекстное меню. Поэтому визуальные запреты в формах — это лишь дополнение. Основная логика всегда должна оставаться в модуле объекта, как мы разобрали в первом методе, так как это гарантирует целостность данных при любых действиях пользователя.

Метод 4: Использование дополнительных свойств объекта

Иногда решение о запрете должно приниматься на основе данных, которых нет в самом документе, но они известны в форме. Рассмотрим ситуацию: нам нужно разрешить пометку на удаление только в том случае, если пользователь подтвердил это в специальном диалоговом окне. Для передачи информации из формы в модуль объекта удобно использовать коллекцию ДополнительныеСвойства.

В форме документа перед записью мы можем написать:

Объект.ДополнительныеСвойства.Вставить("РазрешитьУдаление", Истина);

А в модуле объекта проанализируем это свойство:


Если ПометкаУдаления И НЕ Ссылка.ПометкаУдаления Тогда
    Если НЕ ДополнительныеСвойства.Свойство("РазрешитьУдаление") Тогда
        Отказ = Истина;
    КонецЕсли;
КонецЕсли;

Рекомендации по оптимизации

Проанализируем важные нюансы, которые помогут избежать ошибок при реализации:

Подведем итог: наиболее корректным и современным способом реализации запрета пометки на удаление является сочетание проверки в модуле объекта (через сравнение текущего реквизита со ссылкой) и использование расширений для сохранения чистоты конфигурации.

← На главную