Старт бизнес-процесса из кода 1С: от СоздатьБизнесПроцесс() до HTTP-сервиса

· 9 мин

Содержание

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

Типичная ситуация: при проведении договора нужно автоматически отправить его на согласование юристу. Пользователь не должен ничего нажимать — процесс стартует из модуля документа, из регламентного задания или из обработчика HTTP-запроса внешней CRM. Всё описанное относится к платформе 1С:Предприятие 8.3 и не зависит от конфигурации.

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

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

Маршрут рисуется в конфигураторе на карте маршрута. На ней размещают точки:

  • 🟢 Старт — начало, одна на карту;
  • 📝 Действие — здесь создаются задачи для исполнителей;
  • ❓ Условие — ветвление по результату проверки;
  • 🔀 Разделение и Слияние — параллельные ветки;
  • ⚙️ Обработка — выполняет код без участия пользователя;
  • 📦 Вложенный бизнес-процесс — запускает другие процессы;
  • 🏁 Завершение — конец маршрута.

Продвижение по маршруту идёт «точками»: старт переводит процесс к следующей точке, выполнение задачи — дальше по стрелке. Когда процесс доходит до точки завершения, платформа ставит ему стандартный реквизит Завершен = Истина.

Стандартные реквизиты, которые нужны в коде

РеквизитУ когоЗачем
Стартованбизнес-процессзащищает от повторного старта
Завершенбизнес-процессмаршрут дошёл до конца
ВедущаяЗадачабизнес-процесссвязь с задачей родительского процесса
БизнесПроцессзадачассылка на процесс-владелец
ТочкаМаршрутазадачав какой точке создана задача
Выполненазадачазадача закрыта

Ссылка на точку маршрута в коде получается так: БизнесПроцессы.СогласованиеДоговора.ТочкиМаршрута.Согласовать. Имя точки — то, что задано у неё в свойстве «Имя» на карте маршрута.

Создание и старт экземпляра бизнес-процесса из кода

Основная схема — три шага: создать, записать, стартовать. Пример ниже запускает согласование договора. Предполагается, что у бизнес-процесса СогласованиеДоговора есть реквизиты Договор, Автор и Согласующий.

// Общий модуль СогласованиеСервер (флажок «Сервер»)
Функция ЗапуститьСогласование(ДоговорСсылка, Согласующий) Экспорт

    БП = БизнесПроцессы.СогласованиеДоговора.СоздатьБизнесПроцесс();
    БП.Дата        = ТекущаяДатаСеанса();
    БП.Договор     = ДоговорСсылка;
    БП.Автор       = Пользователи.ТекущийПользователь();
    БП.Согласующий = Согласующий;
    БП.Наименование = СтрШаблон("Согласование договора %1", ДоговорСсылка);

    БП.Записать();
    БП.Старт();

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

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

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

Зачем записывать перед стартом

Записать() создаёт ссылку на процесс. Задачи, которые платформа сформирует при старте, хранят ссылку на процесс в реквизите БизнесПроцесс. Записанный объект — надёжная опора для всех обработчиков маршрута.

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

БП = БизнесПроцессСсылка.ПолучитьОбъект();
Если Не БП.Стартован Тогда
    БП.Старт();
КонецЕсли;

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

Объект бизнес-процесса на тонком клиенте недоступен. С формы вызывайте серверную процедуру:

&НаКлиенте
Процедура ОтправитьНаСогласование(Команда)
    ОтправитьНаСогласованиеНаСервере();
    ОповеститьОбИзменении(Тип("БизнесПроцессСсылка.СогласованиеДоговора"));
КонецПроцедуры

&НаСервере
Процедура ОтправитьНаСогласованиеНаСервере()
    СогласованиеСервер.ЗапуститьСогласование(Объект.Ссылка, Объект.Юрист);
КонецПроцедуры

Права доступа

Для программного старта у роли должно быть право Старт на бизнес-процесс, а для кнопки на форме — ещё и Интерактивный старт. Для выполнения задач — права Выполнение и Интерактивное выполнение на задачу. Если процесс запускает служебный код от имени пользователя без этих прав, оберните вызов в УстановитьПривилегированныйРежим(Истина) и сразу верните режим обратно.

Точки маршрута и задачи: как процесс движется дальше

После старта процесс встаёт в первой точке «Действие» и ждёт. Дальше его двигает выполнение задачи.

Заполнение задач при их создании

В модуле объекта бизнес-процесса есть обработчик ПриСозданииЗадач. Он срабатывает в точке «Действие» и получает массив формируемых задач:

Процедура ПриСозданииЗадач(ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, Отказ)

    Для Каждого Задача Из ФормируемыеЗадачи Цикл
        Задача.Наименование = СтрШаблон("%1: %2",
            ТочкаМаршрутаБизнесПроцесса.НаименованиеЗадачи, Договор);
        Задача.Исполнитель = Согласующий; // реквизит задачи в вашей конфигурации
    КонецЦикла;

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

Реквизит Исполнитель — пример. В вашей задаче он может называться иначе или задаваться через адресацию (план видов характеристик и измерения адресации у объекта «Задача»).

Если нужно сформировать задачи полностью вручную, используйте обработчик ПередСозданиемЗадач. В нём можно отключить стандартное создание параметром СтандартнаяОбработка = Ложь и самому наполнить ФормируемыеЗадачи.

Ветвление и автоматические шаги

  • Точка Условие вызывает обработчик ПроверкаУсловия(ТочкаМаршрутаБизнесПроцесса, Результат). В нём выставьте Результат = Истина или Ложь — процесс пойдёт по соответствующей стрелке.
  • Точка Обработка вызывает ОбработкаВыполнения(ТочкаМаршрутаБизнесПроцесса). Сюда кладут действия без человека: записать статус договора, отправить уведомление, создать документ .
Процедура ПроверкаУсловия(ТочкаМаршрутаБизнесПроцесса, Результат)
    Если ТочкаМаршрутаБизнесПроцесса = БизнесПроцессы.СогласованиеДоговора.ТочкиМаршрута.СуммаБольшая Тогда
        Результат = Договор.Сумма > 1000000;
    КонецЕсли;
КонецПроцедуры

Выполнение задачи программно

Чтобы продвинуть процесс из кода (например, юрист ответил через внешнюю систему), выполните задачу методом ВыполнитьЗадачу():

Процедура ЗакрытьЗадачиСогласования(БизнесПроцессСсылка) Экспорт

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

    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        ЗадачаОбъект = Выборка.Ссылка.ПолучитьОбъект();
        ЗадачаОбъект.ВыполнитьЗадачу();
    КонецЦикла;

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

Имя задачи ЗадачаИсполнителя — условное, подставьте своё. ВыполнитьЗадачу() отмечает задачу выполненной и сразу проводит процесс к следующей точке. Обработчики следующих точек отработают в том же вызове.

Обработка исключений и отладка запуска

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

Функция ЗапуститьСогласованиеБезопасно(ДоговорСсылка, Согласующий) Экспорт

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

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

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

Если ошибку нужно не пробрасывать, а вернуть вызывающему коду (например, в ответ HTTP-сервиса), уберите ВызватьИсключение и верните Неопределено или структуру с текстом ошибки.

Как отлаживать

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

Отлаживайте на копии базы. Каждый тестовый старт в рабочей базе создаёт реальные задачи, которые увидят пользователи.

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

Способы запуска: сравнение в одной таблице

СпособКогда подходитНа что смотреть
СоздатьБизнесПроцесс() + Записать() + Старт()обычный старт из документа или обработкитранзакция, права «Старт»
Записать() без Старт(), старт позжепроцесс готовят заранее, запускают по событиюпроверка Стартован перед стартом
Точка «Вложенный бизнес-процесс»дочерний процесс — часть маршрута родителяплатформа создаёт вложенный процесс сама, код почти не нужен
Заполнение ВедущаяЗадача вручнуюподпроцесс из кода, привязанный к задачезаполнять до Старт()
Регламентное заданиемассовый запуск по расписаниювыполняется без пользователя — права и привилегированный режим
HTTP-сервисзапуск из внешней системыавторизация, ответ с кодом и ссылкой
Внешнее соединение (COM)интеграция со старыми Windows-системамивызывайте экспортную функцию общего модуля, а не собирайте объект через COM

Запуск по расписанию

Для массового старта (например, ежемесячная сверка по всем контрагентам) создайте регламентное задание. Его метод — экспортная процедура общего модуля, внутри которой в цикле вызывается та же функция запуска. Каждый процесс стартуйте в своей транзакции: ошибка в одном не должна откатывать остальные.

Запуск бизнес-процесса из внешней системы через HTTP-сервис

Внешняя CRM или портал может стартовать процесс в 1С одним POST-запросом. Создайте в конфигурации HTTP-сервис, например с корневым URL approval, шаблон /start и метод POST. Обработчик:

Функция СтартPOST(Запрос)

    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
    Данные = ПрочитатьJSON(Чтение);
    Чтение.Закрыть();

    Ответ = Новый HTTPСервисОтвет(201);
    Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");

    Попытка
        Договор = Документы.Договор.НайтиПоНомеру(Данные.number, ТекущаяДатаСеанса());
        Если Договор.Пустая() Тогда
            Ответ.КодСостояния = 404;
            Ответ.УстановитьТелоИзСтроки("{""error"":""contract not found""}");
            Возврат Ответ;
        КонецЕсли;

        Юрист = Справочники.Пользователи.НайтиПоНаименованию(Данные.approver, Истина);
        Ссылка = СогласованиеСервер.ЗапуститьСогласованиеБезопасно(Договор, Юрист);
        Ответ.УстановитьТелоИзСтроки(СтрШаблон("{""id"":""%1""}",
            Строка(Ссылка.УникальныйИдентификатор())));
    Исключение
        Ответ.КодСостояния = 500;
        Ответ.УстановитьТелоИзСтроки("{""error"":""start failed""}");
    КонецПопытки;

    Возврат Ответ;

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

Пример тела запроса:

{"number": "Д-0042", "approver": "Петрова Анна"}

Что важно при интеграции:

  • 🔐 HTTP-сервис работает от имени пользователя, под которым идёт авторизация на веб-сервере. Заведите отдельного служебного пользователя с минимальными правами.
  • 🧾 Возвращайте уникальный идентификатор процесса. По нему внешняя система потом запросит статус или закроет задачу.
  • 🔁 Защититесь от повторов. Сеть может повторить POST — перед стартом проверьте, нет ли уже незавершённого процесса по этому договору.
  • 🛑 Не отдавайте наружу текст исключения: в нём бывают имена таблиц и путей. Подробности пишите в журнал регистрации.

Сервис нужно опубликовать на веб-сервере (Apache или IIS) с флажком публикации HTTP-сервисов. После изменения состава сервисов публикацию обновляют.

Ошибки при программном старте и как ускорить работу

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

  • ⏳ Длинные транзакции. Если в ОбработкаВыполнения идёт тяжёлый расчёт или обращение к внешнему сервису, транзакция старта держит блокировки. Тяжёлое выносите в фоновое задание, а в обработчике только фиксируйте факт.
  • 🌐 HTTP-запросы внутри маршрута. Внешний сервис не ответил — откатился весь старт. Таймаут ставьте явно, а при неудаче пишите статус в регистр и повторяйте позже.
  • 🧮 Запросы в цикле. При массовом старте получайте всех исполнителей и данные одним запросом до цикла, а не внутри ПриСозданииЗадач для каждой задачи.
  • 🔒 Привилегированный режим «навсегда». Включили и забыли выключить — дальнейший код выполняется без проверки прав. Возвращайте УстановитьПривилегированныйРежим(Ложь) сразу после старта.
  • 📌 Жёсткие ссылки на точки по строке. Сравнивайте ТочкаМаршрутаБизнесПроцесса со ссылкой из ТочкиМаршрута, а не с наименованием задачи. Переименование в карте маршрута не должно ломать логику.
  • 🗑 Тестовые процессы в рабочей базе. Если они всё же попали, помечайте их на удаление вместе с задачами, а не удаляйте напрямую.

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

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

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