Как программно остановить бизнес-процесс в 1С, если обычная запись объекта не помогает?

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

При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда попытка программно завершить или остановить бизнес-процесс (БП) через изменение реквизитов объекта не приносит желаемого результата. Код выполняется без ошибок, транзакция фиксируется, но в интерфейсе бизнес-процесс по-прежнему значится как активный, а его задачи остаются открытыми. Рассмотрим подробно, почему это происходит и как правильно реализовать программную остановку БП.

Анализ проблемы: почему флаг Завершен не работает?

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


БизнесПроцессОбъект = СсылкаНаБП.ПолучитьОбъект();
БизнесПроцессОбъект.ДатаЗавершения = ТекущаяДата();
БизнесПроцессОбъект.Завершен = Истина;
БизнесПроцессОбъект.Состояние = Перечисления.СостоянияБизнесПроцессов.Остановлен;
БизнесПроцессОбъект.Записать();

Выясним причину, по которой этот код может не работать. В современных конфигурациях (таких как ERP, КА, УТ 11 или Документооборот), построенных на базе Библиотеки стандартных подсистем (БСП), логика управления состояниями гораздо сложнее, чем простая проверка булева флага Завершен. Бизнес-процесс — это не просто запись в таблице БД, это живой механизм, тесно связанный с задачами исполнителей и регистрами сведений.

Проанализируем основные причины «игнорирования» записи:

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

Решение 1: Использование инструментов БСП

Разберем наиболее правильный метод, который рекомендуется для конфигураций, использующих подсистему «Бизнес-процессы и задачи». Вместо прямой модификации объекта следует использовать программный интерфейс (API) библиотеки. Посмотрим на пример использования серверного общего модуля:


// Используем метод БСП для установки состояния
ПараметрыОстановки = Новый Структура;
ПараметрыОстановки.Вставить("Состояние", Перечисления.СостоянияБизнесПроцессов.Остановлен;
БизнесПроцессыИЗадачиВызовСервера.УстановитьСостояниеБизнесПроцесса(СсылкаНаБП, ПараметрыОстановки);

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

Решение 2: Корректное завершение задач

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


// 1. Получаем объект БП
БПОбъект = Выборка.Ссылка.ПолучитьОбъект();

// 2. Устанавливаем признаки завершения
БПОбъект.Завершен = Истина;
БПОбъект.ДатаЗавершения = ТекущаяДата();
БПОбъект.Состояние = Перечисления.СостоянияБизнесПроцессов.Остановлен;

// 3. Обрабатываем задачи (важный шаг!)
ЗапросЗадачи = Новый Запрос;
ЗапросЗадачи.Текст = 
    "ВЫБРАТЬ
    |	ЗадачаИсполнителя.Ссылка КАК Ссылка
    |ИЗ
    |	Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
    |ГДЕ
    |	ЗадачаИсполнителя.БизнесПроцесс = &БизнесПроцесс
    |	И НЕ ЗадачаИсполнителя.Выполнена
    |	И НЕ ЗадачаИсполнителя.ПометкаУдаления";

ЗапросЗадачи.УстановитьПараметр("БизнесПроцесс", БПОбъект.Ссылка);
ВыборкаЗадач = ЗапросЗадачи.Выполнить().Выбрать();

Пока ВыборкаЗадач.Следующий() Цикл
    ЗадачаОбъект = ВыборкаЗадач.Ссылка.ПолучитьОбъект();
    // Можно пометить на удаление или программно завершить
    ЗадачаОбъект.Выполнена = Истина; 
    ЗадачаОбъект.РезультатВыполнения = "Остановлено программно";
    ЗадачаОбъект.Записать();
КонецЦикла;

// 4. Финальная запись процесса
БПОбъект.Записать();

Выясним, почему это работает: когда мы устанавливаем ЗадачаОбъект.Выполнена = Истина, платформа закрывает текущую точку маршрута. Если при этом сам объект бизнес-процесса помечается как Завершен, система перестает генерировать новые задачи по карте маршрута.

Решение 3: Использование режима загрузки данных

Иногда логика в модуле объекта настолько жестко прописана, что не дает программно менять состояние. В таких исключительных случаях (и если вы уверены в своих действиях) можно использовать свойство ОбменДанными.Загрузка. Рассмотрим, как это выглядит:


БПОбъект = Ссылка.ПолучитьОбъект();
БПОбъект.ОбменДанными.Загрузка = Истина; // Отключаем проверки в модуле объекта
БПОбъект.Завершен = Истина;
БПОбъект.Состояние = Перечисления.СостоянияБизнесПроцессов.Остановлен;
БПОбъект.Записать();

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

Посмотрим на нюансы транзакций

Проанализируем еще один неочевидный момент. Если ваш код выполняется внутри большой транзакции, в которой позже происходит ошибка, то запись бизнес-процесса будет откачена. Проверьте, нет ли в вашем цикле блоков Попытка...Исключение, которые могут скрывать ошибки при выполнении метода Записать().

Рекомендуется всегда проверять результат записи:


Попытка
    БПОбъект.Записать();
Исключение
    ЗаписьЖурналаРегистрации("ПрограммнаяОстановкаБП", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    Сообщить("Не удалось остановить процесс: " + Ссылка);
КонецПопытки;

Резюме и рекомендации

Подведем итоги. Если программная остановка не срабатывает:

  1. Убедитесь, что вы не просто меняете флаг Завершен, но и обновляете реквизит Состояние (если он есть в конфигурации).
  2. Проверьте наличие активных задач по данному БП. В большинстве случаев именно они «держат» процесс активным.
  3. В приоритетном порядке используйте функции общего модуля БизнесПроцессыИЗадачиВызовСервера или аналогичные методы вашей конфигурации.
  4. Изучите модуль менеджера или модуль объекта бизнес-процесса на предмет специфических проверок перед записью.

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

← На главную