Как программно прервать или принудительно завершить бизнес-процесс в 1С

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

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

Разбор типичных ошибок и архитектурный подход

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

  1. Разделение контекстов: Бизнес-процессы и задачи — это объекты данных. Управление ими должно происходить на сервере, в то время как формы — это клиентский интерфейс. Как справедливо замечено в обсуждении, форму нельзя (и не нужно) получать на сервере.
  2. Масштабируемость: Если логика завершения привязана к форме, вы не сможете корректно прервать процесс из фонового задания, внешней обработки или при записи другого документа.
  3. Целостность данных: Простое «закрытие» формы не прекращает выполнение бизнес-процесса в базе данных.

Правильным решением является создание экспортного метода в модуле объекта бизнес-процесса, который будет отвечать за его корректную «остановку». Разобраться в тонкостях клиент-серверного взаимодействия поможет статья об управлении местом выполнения кода в управляемых формах.

Реализация метода принудительного завершения

Для того чтобы бизнес-процесс считался завершенным, недостаточно просто установить флаг Завершен. Если у процесса остались активные задачи, они продолжат висеть в списках «Мои задачи» у пользователей, создавая путаницу. Рассмотрим алгоритм правильного завершения БП:

  1. Поиск всех невыполненных задач, связанных с данным бизнес-процессом.
  2. Программная отметка этих задач как выполненных.
  3. Установка признака завершения самого бизнес-процесса.
  4. Фиксация даты завершения.

Проанализируем пример кода, который можно разместить в модуле объекта бизнес-процесса (например, БизнесПроцесс.Согласование):


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

Вызов прерывания из внешней обработки или другого объекта

Теперь рассмотрим, как использовать этот метод в вашей обработке. Допустим, нам нужно прервать все процессы согласования, связанные с определенной заявкой. Выясним причину остановки и выполним код:


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

Реализация логики «Отказ одного — стоп всем»

Вопрос из сообщения №10 касается популярного сценария: если в групповом согласовании один человек нажимает «Не согласовано», процесс должен немедленно завершиться. Рассмотрим, как это реализовать.

Наилучшее место для такой проверки — точка маршрута ПриВыполнении задачи или обработчик ПередЗавершением задачи. Проанализируем пример кода в модуле задачи или в коде точки маршрута на карте:


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

Важные нюансы и рекомендации

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

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

Таким образом, мы рассмотрели надежный способ программного управления жизненным циклом бизнес-процесса. Использование экспортных методов в модуле объекта и корректная работа с задачами через запросы позволяют создавать гибкие и отказоустойчивые алгоритмы автоматизации. Чтобы убедиться в правильности проводок после программного завершения процессов, логично проверить отсутствие расхождений в учете при помощи инструмента автоматической сверки.

← На главную