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