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