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

Программист IT и автоматизация бизнеса
← На главную

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

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

Способ 1: Самый надежный — запрет на уровне модуля объекта

Этот метод является наиболее предпочтительным, так как он срабатывает независимо от того, где и как пользователь инициировал копирование — из формы списка, формы документа или другим программным способом. Запрет прописывается непосредственно в логике самого объекта.

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

Посмотрим на пример:

Перейдите в конфигуратор, найдите нужный документ, откройте его модуль объекта и добавьте следующий код:


Процедура ПриКопировании(ОбъектКопирования)
    ВызватьИсключение "Копирование данного документа запрещено!";
КонецПроцедуры

Теперь при любой попытке скопировать этот документ пользователь увидит сообщение «Копирование данного документа запрещено!» и новый документ создан не будет. Это простой и очень эффективный способ.

Способ 2: Запрет на уровне управляемой формы

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

Когда форма открывается для создания нового элемента путем копирования, в ее параметры передается источник копирования. Мы можем проанализировать эти параметры и, если они заполнены, прервать создание формы.

Разберем по шагам:

  1. Откройте форму документа в конфигураторе.
  2. Перейдите на вкладку «Модуль».
  3. Найдите или создайте процедуру-обработчик события ПриСозданииНаСервере.
  4. Добавьте проверку параметра ЗначениеКопирования.

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

Важный момент: если вы вносите это изменение через расширение конфигурации, код для отмены открытия формы следует размещать в обработчике с директивой &Перед, а не &После.

Способ 3: Запрет для обычных форм

В конфигурациях, использующих обычные формы, также есть несколько вариантов реализации запрета.

Для формы списка:

Самый распространенный способ — использовать событие формы списка ПередНачаломДобавления. Этот обработчик имеет параметр Копирование, который принимает значение Истина, если пользователь нажал кнопку «Добавить копированием» (или F9).

В модуле формы списка документа добавьте следующий код:


Процедура ПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа)
    
    Если Копирование Тогда
        Отказ = Истина;
        Предупреждение("Функция копирования для этого документа недоступна!");
    КонецЕсли;
    
КонецПроцедуры

Теперь при попытке копирования из списка операция будет отменена, и пользователь увидит предупреждение.

Для формы документа:

Можно также разместить проверку в событии ПередОткрытием самой формы документа. При открытии в режиме копирования у формы будет заполнен параметр ПараметрОбъектКопирования.


Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)

    Если ЗначениеЗаполнено(ПараметрОбъектКопирования) Тогда
        Отказ = Истина;
        Предупреждение("Копирование запрещено!");
    КонецЕсли;

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

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

Часто бывает необходимо запретить копирование не всем пользователям, а только определенной группе, например, «Менеджер по продажам». Для этого любой из вышеперечисленных методов нужно дополнить проверкой роли текущего пользователя с помощью функции РольДоступна().

Рассмотрим, как модифицировать самый надежный способ (через модуль объекта), чтобы запрет действовал только для пользователей, у которых нет роли «ПолныеПрава».


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

Аналогичную проверку можно встроить в любой другой обработчик события на форме, например, в ПриСозданииНаСервере для управляемых форм.

Альтернативный подход: не запрещать, а очищать поля

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

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

Лучшее место для такого кода — обработчик события ОбработкаЗаполнения в модуле объекта. Он вызывается как раз после того, как система скопировала данные из объекта-источника.

Пример для документа «РеализацияТоваровУслуг»:


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)

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

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

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

← На главную