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

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

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

В этой статье мы подробно разберем, почему стандартными методами не получается изменить доступность кнопки «Ввод на основании», и рассмотрим надежные практические способы реализации этого запрета как со стороны документа-источника, так и со стороны документов-приемников.

Почему не получается просто отключить кнопку на форме источника?

Выясним причину, по которой код вроде ЭлементыФормы.ДействияФормы.Кнопки.ВводНаОсновании.Доступность = Ложь в обычных формах не работает. По умолчанию у командной панели формы свойство Автозаполнение установлено в значение Истина. При таком режиме платформа генерирует стандартные кнопки и подменю динамически непосредственно во время отрисовки интерфейса. Любые попытки разработчика программно вмешаться в доступность или видимость этих динамических кнопок сбрасываются платформой при очередной перерисовке панели.

Кроме того, кнопка ввода на основании представляет собой объект типа КнопкаКоманднойПанели с видом Подменю, управление которым имеет свои особенности.


Способ 1. Управление доступностью кнопки на форме источника (Обычные формы)

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

Рассмотрим этот процесс по шагам:

  1. Откройте форму документа-источника в конфигураторе.
  2. Перейдите в свойства командной панели (например, ДействияФормы или КоманднаяПанель2) и снимите флажок Автозаполнение (установите в Ложь).
  3. Нажмите на командной панели правой кнопкой мыши и выберите пункт Заполнить автоматически. Платформа создаст статическую структуру кнопок в дереве элементов формы. Теперь подменю «Ввод на основании» стало полноценным элементом коллекции кнопок, которым можно управлять.
  4. Для динамического обновления доступности кнопки напишем код в обработчике события формы ОбновлениеОтображения. Это гарантирует, что доступность будет мгновенно пересчитываться при проведении, отмене проведения или записи документа.

Пример кода для обработчика формы документа-источника:


Процедура ОбновлениеОтображения()
    // Проверяем, проведен ли текущий документ
    ДокументПроведен = ЭтотОбъект.Проведен;
    
    // Управляем доступностью кнопки "Ввод на основании"
    Попытка
        ЭлементыФормы.ДействияФормы.Кнопки.ВводНаОсновании.Доступность = ДокументПроведен;
    Исключение
        // На случай, если кнопка называется иначе в вашей панели
    КонецПопытки;
КонецПроцедуры

Способ 2. Жесткий запрет в модуле объекта документа-приемника (через Исключение)

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

В модуле объекта каждого документа-приемника используется предопределенная процедура ОбработкаЗаполнения. В ней мы анализируем переданный источник заполнения, и если документ-основание не проведен, вызываем исключение.

Рассмотрим пример реализации:


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

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


Способ 3. Отмена открытия формы в документе-приемнике (Обычные формы)

Если решение с вызовом исключения кажется вам слишком грубым, можно предотвратить открытие формы нового документа на этапе ее инициализации.

При интерактивном вводе на основании платформа сначала отрабатывает событие ОбработкаЗаполнения в модуле объекта, а затем открывает форму нового документа, передавая ссылку на основание в параметры формы. Мы можем перехватить этот момент в событии ПередОткрытием формы документа-приемника.

Посмотрим на пример реализации в модуле формы документа-приемника:


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

Если у вас один документ-источник и много документов-приемников (более 5-10 штук), прописывать этот код в форме каждого приемника вручную может быть неоптимально. В таком случае логичнее использовать общие модули или механизм подписок на события.


Способ 4. Реализация проверки для Управляемых форм

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

Проанализируем пример кода:


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

В данном примере функция ОбщегоНазначения.ЗначениеРеквизитаОбъекта используется для быстрого получения статуса проведения документа без считывания всего объекта базы данных целиком, что повышает общую производительность системы.

Резюме

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

← На главную