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

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

При разработке в 1С часто возникает задача ограничить права пользователей на установку пометки на удаление. Самый очевидный способ — использовать подписку на события в расширении. Однако здесь есть нюанс: если подписаться на событие ПередЗаписью или ПриЗаписи, то проверка прав будет срабатывать при каждом сохранении объекта, а не только в момент установки пометки. Давайте разберемся, как правильно отделить эти два действия и реализовать точечную проверку.

Анализ проблемы: почему проверка срабатывает всегда?

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


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

Проблема этого кода в том, что он не анализирует, какое именно действие привело к записи объекта. Любое изменение реквизитов и последующее сохранение вызовут эту процедуру. В результате пользователь без специальных прав не сможет не только пометить объект на удаление, но и просто отредактировать и сохранить его. Это не то, чего мы добиваемся.

Ключевая сложность заключается в том, что платформа "1С:Предприятие" не предоставляет отдельного, специального события для отслеживания установки пометки на удаление (например, ПередУстановкойПометкиУдаления). Для платформы это действие — просто изменение системного реквизита ПометкаУдаления и последующая запись объекта. Поэтому нам нужно научиться "ловить" именно это изменение внутри общего события записи.

Правильное решение: сравнение состояния объекта до и после записи

Чтобы точно определить, что происходит именно установка пометки на удаление, нам нужно сравнить два состояния объекта:

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

Если в новом состоянии пометка на удаление установлена (равна Истина), а в старом — нет (равна Ложь), значит, пользователь именно сейчас устанавливает эту пометку. Этот логический трюк позволяет нам безошибочно идентифицировать нужное нам действие.

Для реализации этой проверки лучше всего подходит событие ПередЗаписью, так как оно позволяет отменить действие через параметр Отказ.

Пошаговая реализация в расширении

Давайте создадим корректный обработчик подписки на событие ПередЗаписью. В качестве источника можно указать все нужные справочники и документы.

Шаг 1. Создаем подписку на событие

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

Шаг 2. Пишем код обработчика

Теперь напишем код, который будет выполнять нашу логику сравнения. В обработчике события нам доступен параметр Источник — это и есть тот объект, который мы пытаемся записать.


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

    // 1. Проверяем, что это не запись нового объекта. 
    //    Для нового объекта ссылка еще не заполнена, и сравнивать не с чем.
    Если Источник.ЭтоНовый() Тогда
        Возврат;
    КонецЕсли;

    // 2. Основная логика: определяем момент установки пометки на удаление.
    //    Проверяем, что у записываемого объекта флаг пометки установлен в "Истина",
    //    а у объекта в базе данных (по его ссылке) этот флаг еще "Ложь".
    Если Источник.ПометкаУдаления = Истина И НЕ Источник.Ссылка.ПометкаУдаления() Тогда

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

    КонецЕсли;

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

Разберем логику кода подробнее:

Таким образом, условие Источник.ПометкаУдаления И НЕ Источник.Ссылка.ПометкаУдаления() будет истинным только в одном единственном случае: когда происходит переход состояния пометки из Ложь в Истина. При обычной записи объекта, когда состояние пометки не меняется (было Ложь и осталось Ложь, или было Истина и осталось Истина), это условие не выполнится, и проверка прав не сработает.

Дополнительно: как отследить снятие пометки на удаление

Используя тот же подход, можно реализовать и проверку на снятие пометки на удаление, если это потребуется. Логика будет обратной.

Чтобы отследить момент, когда пользователь снимает пометку (переводит ее из Истина в Ложь), условие будет выглядеть так:


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

КонецЕсли;
// ...

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

← На главную