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