Как перехватить действие «Ввести на основании» и поставить условие при создании документа?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При разработке в среде 1С часто возникает задача: ограничить возможность ввода одного документа на основании другого, если не выполняются определенные бизнес-условия (для этого подойдёт настройка ввода документов на основании по правилам). Например, запретить создание документа РеализацияТоваровУслуг на основании документа ЗаказПокупателя, если заказ не согласован или клиент имеет долги. Чтобы точно понимать, в какой момент внедрять проверку, полезно изучить последовательность вызова событий 1С при программировании.

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

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

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

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

Разберем алгоритм действий:

  1. Открываем модуль объекта создаваемого документа (например, РеализацияТоваровУслуг).
  2. Находим или создаем процедуру ОбработкаЗаполнения.
  3. Проверяем тип основания и пишем наше условие.

Пример кода, основанный на обсуждении:


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

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

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

Способ 2. Блокировка открытия формы (Связка Модуль объекта + Модуль формы)

Чтобы документ не просто не заполнился, а вообще не открылся (или закрылся сразу), нужно использовать событие ПриСозданииНаСервере (для управляемых форм) или ПередОткрытием.

Рассмотрим современный подход для управляемых форм. Логика следующая:

  1. В ОбработкаЗаполнения (см. пример выше) мы проверяем условие. Если оно нарушено, мы не заполняем документ и добавляем флаг в ДополнительныеСвойства объекта.
  2. В модуле формы в процедуре ПриСозданииНаСервере мы проверяем этот флаг. Если он есть — устанавливаем Отказ = Истина.

Код в модуле формы документа:


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

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

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

Способ 3. Переопределение командного интерфейса (Сложный путь)

Иногда требуется не просто запретить ввод, а вообще скрыть конкретный документ из меню «Создать на основании» или изменить логику вызова. Для быстрого тестирования состава команд и форм удобно использовать расширение Демоны 2.0, которое упрощает доступ к функциям системы.

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

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

Способ 4. «Трюк» с промежуточным документом

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

  1. Создается новый (технический) вид документа в конфигураторе.
  2. Указывается, что он вводится на основании нужного документа-источника.
  3. В модуле объекта этого тех-документа в ОбработкаЗаполнения прописывается логика открытия реально нужной формы через ОткрытьФорму(...).
  4. У формы самого тех-документа в ПередОткрытием ставится Отказ = Истина.

Если же ваша логика требует действий уже после того, как новый документ был успешно создан и записан, можно реализовать самодельный обработчик ПослеЗаписи объекта.

Резюме

Для решения задачи проверки условий при вводе на основании, наиболее рекомендуемым является Способ 2:

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

← На главную