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

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача: при совершении одного действия (например, проведении документа возврата) автоматически создать другой документ (например, корректировку резервов) и сразу вывести его форму на экран пользователю. На первый взгляд, логичным решением кажется использование подписки на событие ОбработкаПроведения или ПриЗаписи. Однако здесь разработчики сталкиваются с жестким ограничением платформы. В этой статье мы подробно разберем, почему старый подход не работает и какими методами можно достичь желаемого результата.

Почему нельзя открыть форму из подписки на событие?

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

Метод ОткрытьФорму() является клиентским. Попытка вызвать его из модуля, работающего на сервере (даже если у модуля стоят флаги «Клиент» и «Сервер»), приведет к ошибке или отсутствию результата, так как сервер не может инициализировать окно в браузере или тонком клиенте. Рассмотрим основные причины, по которым архитектура «подписка + открытие формы» считается ошибочной:

  1. Разрыв контекста: Сервер не имеет доступа к методам отображения интерфейса.
  2. Транзакционные блокировки: Пока документ не зациклен в транзакции, открытие новых окон может привести к неопределенному поведению интерфейса.
  3. Групповое проведение: Представьте, что вы проводите 100 документов возврата обработкой. Если код сработает, система попытается открыть 100 окон корректировок, что приведет к зависанию клиентского приложения.

Решение 1: Использование расширений и механизма «ПослеЗаписи»

Если нам необходимо именно интерактивное открытие формы сразу после того, как менеджер нажал «Провести», наиболее правильным и современным способом будет использование расширения формы исходного документа. Выясним, как это реализовать по шагам.

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

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


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

Затем используем клиентский обработчик ПослеЗаписи. Этот код выполняется уже на стороне клиента, где доступны все методы управления интерфейсом.


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

Преимущества: Этот метод безопасен, соблюдает разделение контекстов и срабатывает только при интерактивной работе пользователя в форме.

Решение 2: Использование механизма оповещений

Если создание документа происходит глубоко в серверных модулях и вы не хотите привязываться к конкретной форме, можно рассмотреть вариант с методом Оповестить(). Рассмотрим подробнее этот сценарий.

В форме, которая должна среагировать на создание документа (это может быть форма списка или рабочий стол менеджера), прописывается обработчик ОбработкаОповещения. Когда в любом месте системы (в контексте данного пользователя) вызывается Оповестить("РезервСнят", СсылкаНаДокумент), форма-приемник «подхватит» это событие и предложит открыть документ.

Однако стоит помнить: Оповестить работает на клиенте. Чтобы передать сигнал с сервера, вам все равно придется сначала вернуть управление на клиентскую сторону, как было показано в Решении 1.

Решение 3: Специализированное рабочее место (АРМ)

Проанализируем ситуацию с точки зрения бизнес-процессов. Создание документов корректировки при каждом возврате может привести к хаосу, особенно если документы возврата часто редактируются или распроводятся. Специалисты рекомендуют уходить от модели «документ порождает документ» в сторону модели «очередь задач».

Вместо автоматического открытия формы можно реализовать следующее:

  1. При проведении возврата в специальный регистр сведений (например, ОчередьСнятияРезервов) записывается информация о необходимости корректировки.
  2. Менеджер открывает обработку (Рабочее место), где видит список всех «зависших» резервов по возвратам.
  3. Одним нажатием кнопки менеджер создает и проводит сразу все необходимые корректировки.

Такой подход (АРМ) гораздо надежнее для обеспечения целостности данных. Выясним причину: если документ возврата будет помечен на удаление, ваша подписка на событие должна будет найти и удалить созданную ранее корректировку, что сильно усложняет код и повышает риск ошибок.

Важные рекомендации по работе с транзакциями

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

  1. Не проводите документ в подписке: Старайтесь только записывать созданный документ (РежимЗаписиДокумента.Запись). Проведение другого документа внутри транзакции текущего часто вызывает взаимные блокировки (Deadlocks), так как оба документа могут пытаться обновить одни и те же регистры накопления.
  2. Проверка на «Загрузку»: В коде создания документа всегда проверяйте ОбменДанными.Загрузка. Если это истина, создавать ничего не нужно, чтобы не нарушить работу обменов.
  3. Использование фоновых заданий: Если процесс заполнения корректировки длительный (много товаров, сложные расчеты), лучше вынести это в фоновое задание. Пользователь не должен ждать, пока система сформирует вторичные документы.

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

← На главную