Как программно запретить копирование объектов в 1С?

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

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

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

Способ 1. Проверка внутри модуля формы объекта

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


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

Главный недостаток такого метода — если требуется запретить копирование массово, придется проделать немалую работу, изменяя модули форм абсолютно всех необходимых объектов.

Способ 2. Использование Хранилища настроек и подписок на события

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

Создадим подписку на событие ПриКопировании:


Процедура ПриКопировании(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка) 
    ХранилищеОбщихНастроек.Сохранить("инт_ОтказПриКопировании",, Истина,, ПараметрыСеанса.ТекущийПользователь); 
КонецПроцедуры

А затем в форме объекта (или в расширении общих форм) в процедуре ПриСозданииНаСервере считаем этот флаг:


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

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

Способ 3. Вызов программного исключения

Если нет желания работать с параметрами форм, можно пойти радикальным путем. Разберем вариант использования метода ВызватьИсключение в обработчике или подписке ПриКопировании.


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

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

Способ 4. Современное решение для управляемых форм

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


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

Здесь параметр Отказ полностью легален и форма просто не отобразится, а пользователь увидит аккуратное информационное уведомление внизу экрана.

Способ 5. Использование механизма Расширений

Если типовая конфигурация закрыта от изменений, или вы не хотите снимать объекты с поддержки, воспользуемся функционалом Расширений. Мы можем заимствовать форму нужного справочника или документа и использовать аннотацию &Перед.


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

Способ 6. Блокировка непосредственно в списках (формах списка)

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


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

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

Способ 7. "Мягкий" запрет — очистка данных объекта

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

Сделаем это в модуле объекта:


Процедура ПриКопировании(ОбъектКопирования)
    // Очищаем реквизиты, чтобы они не перенеслись в новый документ
    Контрагент = Справочники.Контрагенты.ПустаяСсылка();
    Договор = Справочники.ДоговорыКонтрагентов.ПустаяСсылка();
    Организация = Справочники.Организации.ПустаяСсылка();
    
    // Очищаем табличные части
    Товары.Очистить();
КонецПроцедуры

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

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

← На главную