Как реализовать вопрос пользователю при создании документа на основании в управляемых формах 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке конфигураций на платформе 1С 8.3 в режиме управляемых форм программисты часто сталкиваются с задачей: необходимо проверить, не создавался ли уже документ на основании текущего, и если дубль найден — задать пользователю вопрос, стоит ли продолжать создание. Сложность заключается в том, что современная платформа работает в безмодальном режиме, и мы не можем просто приостановить выполнение кода на сервере или клиенте, чтобы дождаться ответа человека.

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

Почему стандартный механизм «Ввод на основании» вызывает сложности?

Стандартный механизм заполнения документа на основании работает в процедуре ОбработкаЗаполнения в модуле объекта. Этот код выполняется на сервере. Попытка вызвать здесь диалоговое окно (вопрос) технически невозможна, так как сервер не может взаимодействовать с интерфейсом пользователя. Если же мы перенесем логику в форму нового документа, то столкнемся с тем, что процедура ПриОткрытии на клиенте не может «ждать» ответа от ПоказатьВопрос — код просто пойдет дальше, и форма откроется до того, как пользователь нажмет кнопку «Да» или «Нет».

Решение 1: Использование пользовательской команды (Рекомендуемый способ)

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

Разберем алгоритм по шагам:

  1. В исходном документе (основании) создаем команду и выводим ее на панель навигации.
  2. В обработчике команды на клиенте вызываем серверную функцию для поиска существующих дублей.
  3. Если дублей нет, сразу открываем форму нового документа.
  4. Если дубли есть, вызываем ПоказатьВопрос.

Рассмотрим пример кода для такой команды:


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

&НаКлиенте
Процедура ПослеВопросаОСоздании(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        ОткрытьФормуНовогоДокумента(ДополнительныеПараметры);
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ОткрытьФормуНовогоДокумента(Основание)
    ПараметрыЗаполнения = Новый Структура("Основание", Основание);
    ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ПараметрыЗаполнения);
    ОткрытьФорму("Документ.НазваниеВашегоДокумента.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры

Решение 2: Паттерн «Повторного открытия» в процедуре ПриОткрытии

Если вам необходимо оставить стандартную команду ввода на основании (например, через правую кнопку мыши в списке), используется более сложная логика в форме самого создаваемого документа. Суть метода: при первом открытии мы всегда закрываем форму (Отказ = Истина), задаем вопрос, и если пользователь согласен — открываем форму заново, передавая в нее специальный параметр-флаг.

Проанализируем реализацию в коде формы нового документа:


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

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

Важные технические нюансы

Рассмотрим несколько критически важных моментов, которые помогут избежать ошибок:

Выбор конкретного метода зависит от ваших задач, но для большинства бизнес-сценариев в 1С 8.3 рекомендуется создание явной пользовательской команды, так как это дает полный контроль над жизненным циклом объекта еще до его фактического создания в памяти.

← На главную