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