В процессе разработки часто возникает задача автоматизировать многоэтапный процесс, например, последовательное подписание документа несколькими ответственными лицами. Первая мысль — запустить длительную операцию на клиенте и ожидать ее завершения. Однако такой подход имеет серьезный недостаток: если пользователь закроет форму, весь процесс прервется. Проанализируем, почему это происходит, и разберем правильные, надежные архитектурные решения для этой задачи.
Изначальная проблема заключается в использовании клиентских механизмов, таких как ДлительныеОперацииКлиент.ОжидатьЗавершение, для управления серверной логикой. Этот метод привязывает выполнение кода к конкретному клиентскому сеансу и открытой форме. Как только форма закрывается, обработчик ожидания перестает существовать, и цепочка действий обрывается. Чтобы процесс был надежным и отказоустойчивым, его логика должна быть полностью перенесена на сервер и не зависеть от действий пользователя на клиенте.
Рассмотрим два наиболее правильных подхода для реализации подобных задач.
Это самый подходящий и стандартный для платформы «1С:Предприятие» метод для автоматизации процессов, в которых участвуют разные исполнители. Механизм бизнес-процессов специально создан для объединения отдельных операций в управляемые и наглядные цепочки действий.
Как это работает? Разберем по шагам:
Создаем Бизнес-процесс. В конфигураторе необходимо создать новый объект метаданных «Бизнес-процесс», например, назовем его СогласованиеПодписи. Для него создается карта маршрута — это визуальная схема, которая описывает все этапы (точки действия), которые должен пройти процесс от старта до завершения. Для нашей задачи карта будет простой линейной последовательностью.
Создаем Задачу. К нашему бизнес-процессу нужно привязать объект «Задача», например, ЗадачаСогласования. Задача — это то, что видит конкретный исполнитель. Она адресуется пользователю или роли и содержит всю необходимую информацию, в первую очередь — ссылку на документ, который нужно подписать. У задачи будут кнопки для выполнения, например, «Подписано» и «Отклонено».
Запускаем процесс. В форме документа, который нужно подписать, добавляем кнопку, например, «Отправить на подписание». По нажатию на эту кнопку мы программно создаем и стартуем новый экземпляр нашего бизнес-процесса СогласованиеПодписи, передавая в него ссылку на текущий документ и список подписывающих.
Процесс идет по маршруту. После старта бизнес-процесс, следуя карте маршрута, автоматически создает первую задачу и адресует ее первому пользователю в списке. У этого пользователя в списке «Мои задачи» появляется новый пункт. Он открывает задачу, видит ссылку на документ, переходит в него, выполняет подписание и в форме задачи нажимает «Подписано».
Автоматический переход к следующему этапу. Как только первая задача выполнена, бизнес-процесс автоматически переходит к следующей точке на карте маршрута и создает новую задачу для следующего сотрудника в цепочке. Этот цикл повторяется, пока все ответственные не подпишут документ или кто-то не отклонит его.
Ключевые преимущества этого подхода:
Этот способ также полностью переносит логику на сервер. Он более «ручной» по сравнению с бизнес-процессами, но дает полный контроль над логикой и не требует создания большого количества объектов метаданных. Отлично подходит для более простых, линейных процессов.
Как это работает? Разберем по шагам:
Создаем регистр сведений. В конфигураторе создаем периодический регистр сведений, например, СтатусыПодписанияДокументов. Он будет хранить текущее состояние всех процессов. Структура может быть такой:
ДокументСсылка (Измерение) — ссылка на наш подписываемый документ.Этап (Измерение) — номер этапа по порядку (1, 2, 3...).Пользователь (Ресурс) — сотрудник, который должен подписать на данном этапе.Статус (Ресурс) — перечисление со значениями «Ожидает», «Подписан», «Отклонен».ДатаОбновления (Ресурс) — время последнего изменения статуса.Запускаем процесс. По кнопке «Отправить на подписание» в документе мы вызываем серверную процедуру. Эта процедура формирует весь список этапов и для первого подписывающего создает запись в нашем регистре со статусом «Ожидает». Здесь же можно отправить ему уведомление (через систему взаимодействия, по почте или другим способом).
Обрабатываем подписание. Когда пользователь подписывает документ, мы находим его запись в регистре СтатусыПодписанияДокументов и меняем ее статус на «Подписан».
Передаем эстафету. Теперь нам нужно запустить следующий этап. Это можно сделать двумя способами:
ПриЗаписи для нашего регистра. В обработчике проверяем, что новый статус — «Подписан». Если да, то находим следующий по номеру этап для этого документа, создаем новую запись в регистре для следующего пользователя со статусом «Ожидает» и отправляем ему уведомление. Этот способ обеспечивает мгновенную реакцию.Обработано). Найдя такие записи, оно определяет следующего подписывающего, создает для него новую запись со статусом «Ожидает», отправляет уведомление и помечает обработанную запись. Этот способ более отказоустойчив к возможным сбоям в момент записи.Преимущества этого подхода:
Важно правильно понимать назначение некоторых клиентских механизмов, чтобы не допускать архитектурных ошибок.
Асинхронные вызовы (Асинх / Ждать): Этот механизм предназначен в первую очередь для того, чтобы не блокировать интерфейс пользователя на клиенте во время выполнения серверного вызова. Он не решает проблему выполнения кода *после* закрытия формы. Ваша логика должна быть изначально спроектирована так, чтобы она не зависела от формы, а не просто выполнялась асинхронно на клиенте.
Длительные операции (ДлительныеОперации.ВыполнитьФункцию): Этот инструмент полезен для запуска ресурсоемкой задачи в фоновом задании на сервере, чтобы не блокировать сеанс пользователя и не получить ошибку таймаута. Его можно использовать для первоначального старта нашего процесса (например, для создания всех записей в регистре или старта бизнес-процесса). Однако дальнейшее продвижение процесса по цепочке должно управляться серверными механизмами (событиями, регламентными заданиями, бизнес-процессами), а не клиентским ожиданием через ДлительныеОперацииКлиент.ОжидатьЗавершение.
Итоговый вывод: для создания надежных многоэтапных процессов всегда переносите управляющую логику на сервер, используя либо штатный механизм бизнес-процессов, либо собственную реализацию на базе регистров сведений и серверной обработки событий.