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