При разработке механизмов ввода на основании в конфигурациях 1С часто возникает задача: ограничить повторное создание подчиненного документа, если по выбранному документу-основанию операция уже проведена или документ ввода уже существует. Попытка написать проверку в процедуре ОбработкаЗаполнения модуля объекта с использованием обычного оператора Возврат и команды Сообщить() приводит к тому, что сообщение выводится, но платформа 1С все равно открывает форму нового пустого документа.
Рассмотрим, почему происходит такое поведение платформы и какими способами можно корректно прервать процесс создания документа и предотвратить открытие его формы.
Процедура ОбработкаЗаполнения располагается в модуле объекта документа и вызывается платформой в момент инициализации нового объекта на основании переданных данных. В отличие от некоторых других обработчиков событий, в параметрах процедуры ОбработкаЗаполнения отсутствует параметр Отказ.
Когда в коде срабатывает конструкция:
Сообщить("На основании этой заявки уже создана реализация!");
Возврат;
Оператор Возврат лишь прерывает исполнение кода самой процедуры ОбработкаЗаполнения. Однако экземпляр документа в памяти уже создан платформой. После завершения процедуры сервер возвращает управление клиенту, и платформа переходит к следующему шагу — открытию формы нового (незаполненного) документа.
Для гарантированного предотвращения создания нового документа и отмены открытия его формы непосредственно из модуля объекта применяется оператор ВызватьИсключение. Этот подход прерывает транзакцию создания объекта на сервере, и форма документа не открывается.
Проанализируем пример кода в процедуре ОбработкаЗаполнения модуля объекта документа:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
ТипДанныхЗаполнения = ТипЗнч(ДанныеЗаполнения);
Если ТипДанныхЗаполнения = Тип("ДокументСсылка.ЗаявкаНаПеревозку") Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Первые 1
| РеализацияТоваровУслуг.Ссылка КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.ЗаказКлиента = &ЗаявкаНаПеревозку
| И НЕ РеализацияТоваровУслуг.ПометкаУдаления";
Запрос.УстановитьПараметр("ЗаявкаНаПеревозку", ДанныеЗаполнения);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
ВызватьИсключение "На основании этой заявки уже создана реализация!";
Иначе
ЗаполнитьДокументНаОснованииЗаявкиНаПеревозку(ДанныеЗаполнения);
ЗаполненНаОснованииДокумента = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
При вызове исключения обработка создания документа останавливается, пользователю показывается диалоговое окно с переданным сообщением, а интерактивное открытие формы полностью отменяется.
Если требуется вывести пользователю стандартное понятное предупреждение без системной детализации (кнопки «Подробно», характерной для исключений), проверку и отмену можно реализовать в форме создаваемого документа в обработчике ПриСозданииНаСервере.
Для того чтобы данное условие отрабатывало только при вводе на основании и не блокировало открытие ранее созданных документов, необходимо строго проверять признак нового документа и наличие параметров заполнения.
Разберем реализацию проверки в форме документа:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, что документ новый и передан параметр основания
Если Параметры.Ключ.Пустая() И Параметры.Свойство("ЗначениеЗаполнения") Тогда
ДанныеЗаполнения = Параметры.ЗначениеЗаполнения;
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаявкаНаПеревозку") Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Первые 1
| РеализацияТоваровУслуг.Ссылка КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.ЗаказКлиента = &ЗаявкаНаПеревозку
| И НЕ РеализацияТоваровУслуг.ПометкаУдаления";
Запрос.УстановитьПараметр("ЗаявкаНаПеревозку", ДанныеЗаполнения);
Если Не Запрос.Выполнить().Пустой() Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("На основании этой заявки уже создана реализация!");
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Установка параметра Отказ = Истина в событии ПриСозданииНаСервере предотвращает открытие формы документа без вызова критических исключений системы.
Еще один гибкий метод — совмещение логики модуля объекта и формы. В процедуре ОбработкаЗаполнения выполняется проверка данных, и в случае ошибки запись о ней добавляется в структуру ДополнительныеСвойства создаваемого объекта.
ОбработкаЗаполнения фиксируем факт ошибки:
Если Не РезультатЗапроса.Пустой() Тогда
ЭтотОбъект.ДополнительныеСвойства.Вставить("ОшибкаЗаполнения", "На основании этой заявки уже создана реализация!");
Возврат;
КонецЕсли;
ПриСозданииНаСервере считываем это свойство и отменяем открытие формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Ключ.Пустая() Тогда
ДокументОбъект = ДанныеФормыВЗначение(Объект, Тип("ДокументОбъект.РеализацияТоваровУслуг"));
ТекстОшибки = Неопределено;
Если ДокументОбъект.ДополнительныеСвойства.Свойство("ОшибкаЗаполнения", ТекстОшибки) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ТекстОшибки;
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Сравним предложенные решения: