Как открыть форму документа, созданного в подписке на событие?

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

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

Архитектурные ограничения платформы 1С

Выясним причину, по которой открыть форму из подписки на событие напрямую невозможно:

  1. Разделение на клиентский и серверный контекст. Подписки на события записи или проведения объектов базы данных выполняются строго на стороне сервера внутри транзакции записи. Пользовательский интерфейс, диалоговые окна и экранные формы существуют исключительно на клиенте (в тонком или веб-клиенте). Серверный контекст в управляемом приложении не имеет доступа к интерфейсным методам (таким как ОткрытьФорму() или ОткрытьЗначение()).
  2. Ошибки компиляции общего модуля. Попытка включить свойство Клиент (управляемое приложение) у общего модуля, где расположена подписка, не решит проблему, а приведет к аварийной остановке системы. Если в модуле содержится серверный код (обращения к менеджерам объектов через Документы, запросы, работа с объектами ТаблицаЗначений), модуль не сможет скомпилироваться на тонком клиенте при старте программы.
  3. Непривязанность подписок к интерфейсу. Подписка на событие срабатывает при любой записи объекта: при интерактивной работе пользователя, в фоновых заданиях, при обмене данными через РИБ или внешние API. Если вызывать интерфейсные действия внутри механизма записи, фоновые процессы завершатся критической ошибкой.

Способ 1. Передача ссылки через ДополнительныеСвойства в форму

Если бизнес-логика требует создавать и записывать подчиненный документ именно в подписке на событие, необходимо передать ссылку на созданный объект обратно в клиентскую форму исходного документа через цепочку параметров.

Рассмотрим реализацию по шагам:

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

Способ 2. Использование механизма ввода на основании

Проанализируем альтернативный и наиболее правильный с точки зрения стандартов разработки подход: перенос создания документа из серверной подписки в стандартный механизм ввода на основании.

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

Разберем реализацию этого механизма:

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

При таком подходе форма откроется с уже заполненными реквизитами, при этом система не выполняет лишних серверных транзакций, а пользователь самостоятельно решает, проводить или отменять новый документ.

← На главную