Старт бизнес-процесса из кода 1С: от СоздатьБизнесПроцесс() до HTTP-сервиса
Содержание
Чтобы запустить бизнес-процесс
1С программно, создайте объект через менеджер БизнесПроцессы.<Имя>.СоздатьБизнесПроцесс(), заполните реквизиты, вызовите Записать(), а затем Старт(). Код выполняется на сервере. После Старт() платформа проводит точку старта по карте маршрута и сама создаёт задачи в первой точке «Действие».
Типичная ситуация: при проведении договора нужно автоматически отправить его на согласование юристу. Пользователь не должен ничего нажимать — процесс стартует из модуля документа, из регламентного задания или из обработчика HTTP-запроса внешней CRM. Всё описанное относится к платформе 1С:Предприятие 8.3 и не зависит от конфигурации.
Как устроен бизнес-процесс в платформе 1С
Бизнес-процесс — отдельный вид объектов метаданных. Он всегда работает в паре с объектом «Задача». Бизнес-процесс задаёт маршрут, задача — конкретную работу конкретного исполнителя.
Маршрут рисуется в конфигураторе на карте маршрута. На ней размещают точки:
- 🟢 Старт — начало, одна на карту;
- 📝 Действие — здесь создаются задачи для исполнителей;
- ❓ Условие — ветвление по результату проверки;
- 🔀 Разделение и Слияние — параллельные ветки;
- ⚙️ Обработка — выполняет код без участия пользователя;
- 📦 Вложенный бизнес-процесс — запускает другие процессы;
- 🏁 Завершение — конец маршрута.
Продвижение по маршруту идёт «точками»: старт переводит процесс к следующей точке, выполнение задачи — дальше по стрелке. Когда процесс доходит до точки завершения, платформа ставит ему стандартный реквизит Завершен = Истина.
Стандартные реквизиты, которые нужны в коде
| Реквизит | У кого | Зачем |
|---|---|---|
Стартован | бизнес-процесс | защищает от повторного старта |
Завершен | бизнес-процесс | маршрут дошёл до конца |
ВедущаяЗадача | бизнес-процесс | связь с задачей родительского процесса |
БизнесПроцесс | задача | ссылка на процесс-владелец |
ТочкаМаршрута | задача | в какой точке создана задача |
Выполнена | задача | задача закрыта |
Ссылка на точку маршрута в коде получается так: БизнесПроцессы.СогласованиеДоговора.ТочкиМаршрута.Согласовать. Имя точки — то, что задано у неё в свойстве «Имя» на карте маршрута.
Создание и старт экземпляра бизнес-процесса из кода
Основная схема — три шага: создать, записать, стартовать. Пример ниже запускает согласование договора. Предполагается, что у бизнес-процесса СогласованиеДоговора есть реквизиты Договор, Автор и Согласующий.
// Общий модуль СогласованиеСервер (флажок «Сервер»)
Функция ЗапуститьСогласование(ДоговорСсылка, Согласующий) Экспорт
БП = БизнесПроцессы.СогласованиеДоговора.СоздатьБизнесПроцесс();
БП.Дата = ТекущаяДатаСеанса();
БП.Договор = ДоговорСсылка;
БП.Автор = Пользователи.ТекущийПользователь();
БП.Согласующий = Согласующий;
БП.Наименование = СтрШаблон("Согласование договора %1", ДоговорСсылка);
БП.Записать();
БП.Старт();
Возврат БП.Ссылка;
КонецФункции
Функция Пользователи.ТекущийПользователь() есть в конфигурациях на Библиотеке стандартных подсистем. В своей конфигурации подставьте собственный способ получить текущего пользователя.
Зачем записывать перед стартом
Записать() создаёт ссылку на процесс. Задачи, которые платформа сформирует при старте, хранят ссылку на процесс в реквизите БизнесПроцесс. Записанный объект — надёжная опора для всех обработчиков маршрута.
Иногда процесс нужно только подготовить, а стартовать позже. Тогда вызовите Записать() без Старт(). Позже стартуйте так:
БП = БизнесПроцессСсылка.ПолучитьОбъект();
Если Не БП.Стартован Тогда
БП.Старт();
КонецЕсли;
Вызов из клиентского кода
Объект бизнес-процесса на тонком клиенте недоступен. С формы вызывайте серверную процедуру:
&НаКлиенте
Процедура ОтправитьНаСогласование(Команда)
ОтправитьНаСогласованиеНаСервере();
ОповеститьОбИзменении(Тип("БизнесПроцессСсылка.СогласованиеДоговора"));
КонецПроцедуры
&НаСервере
Процедура ОтправитьНаСогласованиеНаСервере()
СогласованиеСервер.ЗапуститьСогласование(Объект.Ссылка, Объект.Юрист);
КонецПроцедуры
Права доступа
Для программного старта у роли должно быть право Старт на бизнес-процесс, а для кнопки на форме — ещё и Интерактивный старт. Для выполнения задач — права Выполнение и Интерактивное выполнение на задачу. Если процесс запускает служебный код от имени пользователя без этих прав, оберните вызов в УстановитьПривилегированныйРежим(Истина) и сразу верните режим обратно.
Точки маршрута и задачи: как процесс движется дальше
После старта процесс встаёт в первой точке «Действие» и ждёт. Дальше его двигает выполнение задачи.
Заполнение задач при их создании
В модуле объекта бизнес-процесса есть обработчик ПриСозданииЗадач. Он срабатывает в точке «Действие» и получает массив формируемых задач:
Процедура ПриСозданииЗадач(ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, Отказ)
Для Каждого Задача Из ФормируемыеЗадачи Цикл
Задача.Наименование = СтрШаблон("%1: %2",
ТочкаМаршрутаБизнесПроцесса.НаименованиеЗадачи, Договор);
Задача.Исполнитель = Согласующий; // реквизит задачи в вашей конфигурации
КонецЦикла;
КонецПроцедуры
Реквизит Исполнитель — пример. В вашей задаче он может называться иначе или задаваться через адресацию (план видов характеристик и измерения адресации у объекта «Задача»).
Если нужно сформировать задачи полностью вручную, используйте обработчик ПередСозданиемЗадач. В нём можно отключить стандартное создание параметром СтандартнаяОбработка = Ложь и самому наполнить ФормируемыеЗадачи.
Ветвление и автоматические шаги
- Точка Условие вызывает обработчик
ПроверкаУсловия(ТочкаМаршрутаБизнесПроцесса, Результат). В нём выставьтеРезультат = ИстинаилиЛожь— процесс пойдёт по соответствующей стрелке. - Точка Обработка вызывает
ОбработкаВыполнения(ТочкаМаршрутаБизнесПроцесса). Сюда кладут действия без человека: записать статус договора, отправить уведомление, создать документ .
Процедура ПроверкаУсловия(ТочкаМаршрутаБизнесПроцесса, Результат)
Если ТочкаМаршрутаБизнесПроцесса = БизнесПроцессы.СогласованиеДоговора.ТочкиМаршрута.СуммаБольшая Тогда
Результат = Договор.Сумма > 1000000;
КонецЕсли;
КонецПроцедуры
Выполнение задачи программно
Чтобы продвинуть процесс из кода (например, юрист ответил через внешнюю систему), выполните задачу методом ВыполнитьЗадачу():
Процедура ЗакрытьЗадачиСогласования(БизнесПроцессСсылка) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Задачи.Ссылка КАК Ссылка
|ИЗ
| Задача.ЗадачаИсполнителя КАК Задачи
|ГДЕ
| Задачи.БизнесПроцесс = &БП
| И НЕ Задачи.Выполнена
| И НЕ Задачи.ПометкаУдаления";
Запрос.УстановитьПараметр("БП", БизнесПроцессСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ЗадачаОбъект = Выборка.Ссылка.ПолучитьОбъект();
ЗадачаОбъект.ВыполнитьЗадачу();
КонецЦикла;
КонецПроцедуры
Имя задачи ЗадачаИсполнителя — условное, подставьте своё. ВыполнитьЗадачу() отмечает задачу выполненной и сразу проводит процесс к следующей точке. Обработчики следующих точек отработают в том же вызове.
Обработка исключений и отладка запуска
Старт процесса запускает цепочку обработчиков. Ошибка в любом из них прерывает весь вызов. Поэтому старт стоит оборачивать в транзакцию: либо процесс создан и задачи сформированы, либо в базе не остаётся ничего.
Функция ЗапуститьСогласованиеБезопасно(ДоговорСсылка, Согласующий) Экспорт
НачатьТранзакцию();
Попытка
Ссылка = ЗапуститьСогласование(ДоговорСсылка, Согласующий);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписьЖурналаРегистрации("Согласование.Старт",
УровеньЖурналаРегистрации.Ошибка,
Метаданные.БизнесПроцессы.СогласованиеДоговора,
ДоговорСсылка,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
Возврат Ссылка;
КонецФункции
Если ошибку нужно не пробрасывать, а вернуть вызывающему коду (например, в ответ HTTP-сервиса), уберите ВызватьИсключение и верните Неопределено или структуру с текстом ошибки.
Как отлаживать
- Поставьте точки останова в модуле объекта бизнес-процесса: в
ПриСозданииЗадач,ПроверкаУсловия,ОбработкаВыполнения. - Запустите отладку в режиме сервера. Обработчики маршрута выполняются на сервере, поэтому отладка клиентского кода их не покажет.
- Пройдите старт по шагам и посмотрите параметр
ТочкаМаршрутаБизнесПроцесса— так видно, в какой точке процесс сейчас. - После старта откройте список задач с отбором по процессу. Нет задач — значит, процесс ушёл другой веткой или споткнулся в условии.
- Проверьте журнал регистрации по событию, которое вы пишете в блоке
Исключение.
Отлаживайте на копии базы. Каждый тестовый старт в рабочей базе создаёт реальные задачи, которые увидят пользователи.
Старт() или проверьте Стартован. Если стартован — смотрите ветку после точки «Условие»: возможно, Результат ушёл в ветку без действия.ПриСозданииЗадач или в настройках адресации точки «Действие». Проверьте имя реквизита задачи.Способы запуска: сравнение в одной таблице
| Способ | Когда подходит | На что смотреть |
|---|---|---|
СоздатьБизнесПроцесс() + Записать() + Старт() | обычный старт из документа или обработки | транзакция, права «Старт» |
Записать() без Старт(), старт позже | процесс готовят заранее, запускают по событию | проверка Стартован перед стартом |
| Точка «Вложенный бизнес-процесс» | дочерний процесс — часть маршрута родителя | платформа создаёт вложенный процесс сама, код почти не нужен |
Заполнение ВедущаяЗадача вручную | подпроцесс из кода, привязанный к задаче | заполнять до Старт() |
| Регламентное задание | массовый запуск по расписанию | выполняется без пользователя — права и привилегированный режим |
| 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-запросы внутри маршрута. Внешний сервис не ответил — откатился весь старт. Таймаут ставьте явно, а при неудаче пишите статус в регистр и повторяйте позже.
- 🧮 Запросы в цикле. При массовом старте получайте всех исполнителей и данные одним запросом до цикла, а не внутри
ПриСозданииЗадачдля каждой задачи. - 🔒 Привилегированный режим «навсегда». Включили и забыли выключить — дальнейший код выполняется без проверки прав. Возвращайте
УстановитьПривилегированныйРежим(Ложь)сразу после старта. - 📌 Жёсткие ссылки на точки по строке. Сравнивайте
ТочкаМаршрутаБизнесПроцессасо ссылкой изТочкиМаршрута, а не с наименованием задачи. Переименование в карте маршрута не должно ломать логику. - 🗑 Тестовые процессы в рабочей базе. Если они всё же попали, помечайте их на удаление вместе с задачами, а не удаляйте напрямую.
Если маршрут становится сложным — десятки условий и разделений — проверьте, не проще ли разбить его на несколько процессов через точку «Вложенный бизнес-процесс». Такой маршрут легче отлаживать и менять.
Частые вопросы
Можно ли стартовать бизнес-процесс на клиенте?
Как остановить процесс, запущенный по ошибке?
Как найти процесс, запущенный по документу?
Завершен. Поэтому реквизит с документом стоит заводить в каждом процессе.Можно ли передать параметры в старт?
Старт() нет. Всё, что нужно маршруту, кладите в реквизиты процесса до записи — обработчики точек прочитают их оттуда.Почему после `ВыполнитьЗадачу()` новые задачи не появились?
Завершен и незакрытые задачи параллельных веток.