Запуск бизнес-процесса из кода: создание, точки старта и ошибки

· 9 мин

Содержание

Чтобы программно стартовать бизнес-процесс в 1С, на сервере создайте объект через БизнесПроцессы.<Имя>.СоздатьБизнесПроцесс(), заполните реквизиты, запишите его и вызовите метод Старт(). После этого платформа ставит процесс в точку старта карты маршрута, проходит маршрут до первой точки действия и создаёт задачи исполнителям.

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

Как устроен бизнес-процесс и откуда его можно запустить

Бизнес-процесс в конфигурации — это объект метаданных со своей картой маршрута. Карта состоит из точек: Старт, Действие, Условие, Выбор варианта, Разделение, Слияние, Обработка, Вложенный бизнес-процесс, Завершение. Работа людей идёт через связанный объект Задача: каждая точка действия порождает задачи.

Объект бизнес-процесса живёт в трёх состояниях:

  • 📝 записан, не стартован — флаг Стартован = Ложь, задач ещё нет;
  • ▶️ стартован — Стартован = Истина, по маршруту созданы задачи;
  • ✅ завершён — Завершен = Истина, процесс дошёл до точки завершения.

Программный старт — это перевод из первого состояния во второе. Вызвать его можно из разных мест:

Откуда запускаемГде выполняется кодТипичный сценарий
Команда формы документаСерверная процедура общего модуля или модуля формы &НаСервере«Отправить договор на согласование»
Обработка проведения документаМодуль объекта документаАвтостарт проверки после проведения
Регламентное заданиеПроцедура общего модуляЕжедневный старт отложенных процессов
Фоновое заданиеПроцедура общего модуляМассовый запуск сотен процессов
HTTP-сервис, обменМодуль сервиса или обработчик обменаЗапуск по событию из внешней системы
Точка «Вложенный бизнес-процесс»Платформа самаПодпроцесс внутри основного маршрута

Старт() — метод объекта, а объекты бизнес-процессов доступны только на сервере. С клиента вызывайте серверную функцию и передавайте в неё ссылки, а не объекты.

Метод Старт(): создать и запустить процесс за один вызов

Самый частый случай: пользователь нажал кнопку, процесс должен уйти в работу сразу. Код удобно держать в серверном общем модуле, чтобы его вызывали и формы, и регламентные задания.

// Общий модуль СогласованиеСервер (Сервер, Вызов сервера)
Функция СтартоватьСогласование(Предмет, Исполнитель, Комментарий = "") Экспорт

    БП = БизнесПроцессы.Согласование.СоздатьБизнесПроцесс();
    БП.Дата = ТекущаяДатаСеанса();
    БП.Предмет = Предмет;
    БП.Исполнитель = Исполнитель;
    БП.Описание = Комментарий;
    БП.Автор = Пользователи.ТекущийПользователь();

    НачатьТранзакцию();
    Попытка
        БП.Записать();
        БП.Старт();
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ВызватьИсключение;
    КонецПопытки;

    Возврат БП.Ссылка;

КонецФункции

Что здесь происходит по шагам:

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

Пользователи.ТекущийПользователь() — функция Библиотеки стандартных подсистем. Если конфигурация собрана без БСП, заполняйте автора своим способом.

Вызов с клиента выглядит так:

&НаКлиенте
Процедура ОтправитьНаСогласование(Команда)
    Ссылка = СогласованиеСервер.СтартоватьСогласование(Объект.Ссылка, Исполнитель);
    ПоказатьОповещениеПользователя("Согласование запущено", ПолучитьНавигационнуюСсылку(Ссылка));
КонецПроцедуры

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

Раздельное создание и отложенный запуск процесса

Иногда процесс нужно подготовить заранее, а запустить позже. Например, менеджер собирает маршрут согласования, а старт происходит в 9:00 следующего дня или после оплаты счёта.

В объектной модели платформы для этого нет отдельного метода «Запустить» — запуск всегда делает Старт(). Процедуры с названиями вроде «ЗапуститьПроцесс» в типовых конфигурациях — это обёртки поверх него. Схема раздельного запуска такая:

  1. Создайте и запишите процесс через Записать(), не вызывая Старт().
  2. Сохраните условие запуска: дату в реквизите процесса или запись в своём регистре сведений.
  3. В момент запуска получите объект по ссылке, проверьте флаг и стартуйте.
Процедура СтартоватьПодготовленный(СсылкаБП) Экспорт

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

    БП.Заблокировать();
    БП.Старт();

КонецПроцедуры

Заблокировать() ставит объектную блокировку. Если процесс в эту секунду открыт пользователем на редактирование, вызов выдаст исключение, и вы не стартуете то, что человек ещё правит.

Найти подготовленные, но не запущенные процессы помогает запрос:

Запрос = Новый Запрос(
"ВЫБРАТЬ
|    БП.Ссылка КАК Ссылка
|ИЗ
|    БизнесПроцесс.Согласование КАК БП
|ГДЕ
|    НЕ БП.Стартован
|    И НЕ БП.ПометкаУдаления
|    И БП.Дата <= &ТекущаяДата");
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());

В Библиотеке стандартных подсистем есть подсистема «Бизнес-процессы и задачи» с механизмом отложенного старта для её процессов. Если ваш процесс на ней построен, используйте штатный механизм, а не пишите свой регламент.

Точка старта и параметры запуска

У Старт() есть необязательный параметр — точка старта. Он нужен, когда на карте маршрута несколько точек Старт. Например, «Согласование» может начинаться с юриста для договоров и сразу с бухгалтера для счетов.

Ссылку на точку берут из менеджера по имени точки на карте:

Если ТипЗнч(Предмет) = Тип("ДокументСсылка.Договор") Тогда
    Точка = БизнесПроцессы.Согласование.ТочкиМаршрута.СтартЮрист;
Иначе
    Точка = БизнесПроцессы.Согласование.ТочкиМаршрута.СтартБухгалтер;
КонецЕсли;

БП.Записать();
БП.Старт(Точка);

Если точек старта несколько, а параметр не передан, запуск не пойдёт по нужной ветке. Передавайте точку явно всегда, когда стартов больше одного.

Как передать данные внутрь маршрута

Прямой передачи параметров в Старт() нет. Всё, что нужно маршруту, кладите в реквизиты и табличные части бизнес-процесса до записи:

  • 👤 исполнителей и роли — в реквизиты процесса, их читают обработчики точек действия при создании задач;
  • 📎 предмет (документ, договор, контрагент) — в реквизит ссылочного типа;
  • 📋 список согласующих — в табличную часть, если согласование идёт по очереди или параллельно;
  • 🗓 срок — в реквизит даты, из него задачам ставится срок исполнения.

Обработчики точки действия (ПередСозданиемЗадач, ПриСозданииЗадач) берут эти значения и заполняют задачи. Условие на точке Условие читает их в обработчике ПроверкаУсловия. Поэтому порядок жёсткий: сначала заполнить всё, потом стартовать. Изменение реквизита после старта не перестроит уже созданные задачи.

Права и привилегированный режим

У бизнес-процесса в роли есть отдельные права на старт: Старт для программного запуска и Интерактивный старт для запуска из формы. Если у пользователя нет права Старт, вызов метода из кода упадёт с ошибкой нарушения прав, даже если записывать процесс он может.

Варианты решения:

СпособКогда подходитРиск
Выдать право Старт в роли пользователяПользователь сам инициирует процессОн сможет стартовать и другие процессы этого вида
УстановитьПривилегированныйРежим(Истина) в серверной процедуреСтарт — служебное следствие действия, например проведенияПроверки прав пропускаются — контроль делайте в коде сами
Старт в регламентном задании от служебного пользователяОтложенный и массовый запускАвтором процесса станет служебный пользователь — заполняйте автора явно

Привилегированный режим включайте только в серверном общем модуле и на минимальный участок кода. Не выносите его в процедуру с параметрами, которую можно вызвать с клиента с произвольными данными.

Обработка ошибок при старте

Ошибки при запуске делятся на четыре группы. Их легко узнать по моменту, когда они возникают.

Диагностика: выберите симптом

Ошибка в обработчике точки — самая коварная. Старт проходит маршрут сразу, поэтому исключение в условии или в создании задач откатывает весь старт. Пользователь видит сообщение об ошибке, а не о маршруте.

Шаблон с записью в журнал регистрации:

Попытка
    СтартоватьПодготовленный(СсылкаБП);
Исключение
    ТекстОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
    ЗаписьЖурналаРегистрации("Бизнес-процессы.Старт",
        УровеньЖурналаРегистрации.Ошибка,
        Метаданные.БизнесПроцессы.Согласование,
        СсылкаБП,
        ТекстОшибки);
КонецПопытки;

На свежих версиях платформы вместо ПодробноеПредставлениеОшибки рекомендуется ОбработкаОшибок.ПодробноеПредставлениеОшибки. Старый вариант работает, но синтакс-помощник помечает его как устаревший.

Если старт идёт внутри внешней транзакции, правило такое: перехватили исключение — значит, транзакцию надо отменить и пробросить ошибку дальше через ВызватьИсключение. Иначе внешний код продолжит работу в транзакции, которая уже не может быть зафиксирована.

Массовый запуск бизнес-процессов и скорость

Когда нужно стартовать сотни процессов — например, годовую сверку по 400 контрагентам — запуск одним циклом в одной транзакции плох по трём причинам:

  • 🔒 транзакция держит блокировки на всё время цикла, и другие пользователи ждут;
  • 💥 одна ошибка откатывает все 400 стартов;
  • ⏳ интерфейс пользователя висит до конца цикла.

Рабочая схема:

  1. Отдельная транзакция на каждый процесс: запись и старт одного процесса — одна транзакция. Ошибка затрагивает только его.
  2. Запуск в фоне через ФоновыеЗадания.Выполнить("ОбщийМодуль.Процедура", Параметры). Пользователь получает управление сразу.
  3. Порции. Если процессов тысячи, делите список на части, например по 100–200 штук, и запускайте несколько фоновых заданий. Параллельно — только если процессы не пишут в одни и те же данные, иначе получите ожидания на блокировках.
  4. Итог в журнал или регистр: сколько стартовало, сколько упало и почему.
Процедура СтартоватьПакет(МассивПредметов, Исполнитель) Экспорт

    Успешно = 0;
    Ошибок = 0;
    Для Каждого Предмет Из МассивПредметов Цикл
        Попытка
            СогласованиеСервер.СтартоватьСогласование(Предмет, Исполнитель);
            Успешно = Успешно + 1;
        Исключение
            Ошибок = Ошибок + 1;
            ЗаписьЖурналаРегистрации("Бизнес-процессы.Массовый старт",
                УровеньЖурналаРегистрации.Ошибка, , Предмет,
                ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        КонецПопытки;
    КонецЦикла;

    ЗаписьЖурналаРегистрации("Бизнес-процессы.Массовый старт",
        УровеньЖурналаРегистрации.Информация, , ,
        СтрШаблон("Стартовано: %1, ошибок: %2", Успешно, Ошибок));

КонецПроцедуры

Функция СтартоватьСогласование из первого примера уже открывает свою транзакцию. Поэтому цикл здесь транзакцию не открывает, и одна ошибка не задевает остальные процессы.

Что ещё ускоряет массовый старт:

  • ⚡ тяжёлые запросы в обработчиках точек выполняйте один раз до цикла и передавайте результат в реквизиты процесса;
  • ⚡ не открывайте форму и не вызывайте клиентские оповещения из фонового задания;
  • ⚡ отключайте лишние подписки на события на время пакета только если точно понимаете их назначение — иначе потеряете связанные данные.
Перед массовым стартом в рабочей базе
Выполнено: 0 / 5

Частые вопросы

Можно ли стартовать бизнес-процесс без записи?
Явная запись перед стартом — надёжная практика: у процесса появляется ссылка, а запись и старт можно объединить в одну транзакцию. Так проще отлаживать и разбирать ошибки.
Как остановить уже стартованный процесс?
Метода обратного старта нет. В типовых решениях процесс прерывают через собственные механизмы остановки или помечают на удаление вместе с задачами. Для своего процесса заложите реквизит-признак остановки и проверяйте его в условиях маршрута.
Почему после старта не появились задачи?
Маршрут мог сразу дойти до точки завершения через условие или обработку. Ещё одна причина — обработчик точки действия отменил создание задач. Проверьте значения реквизитов, которые читают условия карты.
Можно ли стартовать процесс с клиента напрямую?
Нет. Объект бизнес-процесса существует только на сервере. С клиента вызывайте серверную функцию общего модуля и передавайте в неё ссылки.
Как запустить вложенный бизнес-процесс вручную?
Обычно этого не нужно: точка «Вложенный бизнес-процесс» на карте создаёт и стартует подпроцессы сама. Ручной старт отдельного процесса из кода не свяжет его с ведущей задачей основного маршрута.