Как в 1С программно ограничить удаление и отмену проведения документов в зависимости от их реквизитов

Программист 1С v8.3 (Обычные формы)
← На главную

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

Использование подписки на событие ПередЗаписью

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

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


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

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

    // Получаем текущие значения из базы данных для сравнения
    СостояниеВБазе = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Источник.Ссылка, "ПометкаУдаления, Проведен, ВидОперации");

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

    // Сценарий 2: Отмена проведения
    Если НЕ Источник.Проведен И СостояниеВБазе.Проведен И РежимЗаписи <> РежимЗаписиДокумента.Проведение Тогда
        // Если документ был проведен, а теперь — нет, и это не перепроведение
        Если СостояниеВБазе.ВидОперации = Перечисления.ВидыОпераций.Расход Тогда
             Сообщить("Для документов вида 'Расход' запрещена отмена проведения!");
             Отказ = Истина;
        КонецЕсли;
    КонецЕсли;

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

Важный нюанс: использование Источник.Ссылка внутри подписки позволяет получить состояние объекта до транзакции. Это критически важно для корректного сравнения реквизитов.

Обработка непосредственного удаления

Если в системе разрешено непосредственное удаление (физическое стирание записи кнопкой Shift+Del), подписка на ПередЗаписью не сработает. Для этого случая необходимо создать отдельную подписку на событие ПередУдалением. Выясним, как это реализовать:


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

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

Учтите, что параметр Отказ = Истина полностью блокирует выполнение операции и откатывает транзакцию. Это гарантирует целостность данных в соответствии с вашими бизнес-правилами.

Особенности работы в обычных формах (ОФ)

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

Также важно правильно настроить свойства модуля, в котором располагаются обработчики подписок. Убедитесь, что установлены флаги Сервер, Внешнее соединение и, если требуется поддержка старого кода, Толстый клиент (обычное приложение). Как показано в сообщениях форума, иногда ошибка "неверное количество параметров" лечится добавлением фиктивного третьего параметра (Dummy), но правильнее будет проверить соответствие сигнатуры метода требованиям платформы для конкретного события.

Использование механизма RLS (Row Level Security)

Рассмотрим более продвинутый и надежный метод — ограничение доступа на уровне записей. В отличие от программного кода в подписках, RLS работает на уровне SQL-запросов. Это означает, что пользователь даже не увидит кнопки "Удалить" или "Пометить на удаление", если условие не соблюдено.

Проанализируем, как настроить ограничение в роли на право "Удаление":

  1. Откройте нужную роль в конфигураторе.
  2. Найдите документ и выберите право Удаление или Изменение.
  3. Добавьте ограничение доступа (RLS).
  4. Пропишите условие: ГДЕ ВидОперации <> ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Расход).

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

Улучшение пользовательского интерфейса

Хотя серверные проверки (подписки и RLS) являются первичными, хорошим тоном считается визуальное информирование пользователя. Если мы запрещаем удаление документа с определенным атрибутом, целесообразно заблокировать соответствующие кнопки на форме. Разберем шаги для управляемых форм:

  1. В процедуре ПриЧтенииНаСервере проанализируйте реквизиты документа.
  2. Если условие запрета выполняется, установите ТолькоПросмотр = Истина для всей формы или точечно отключите команды.
  3. Используйте условное оформление в списках документов, чтобы визуально выделить (например, серым цветом) записи, которые нельзя удалять.

Такой комплексный подход (проверка на сервере + визуальный запрет в интерфейсе) минимизирует количество ошибок и делает работу пользователя более комфортной, исключая ситуации, когда действие совершается, но в конце выдается системная ошибка об отказе.

← На главную