# Бизнес-процессы 1. Предназначены для управления заказами. 2. Привязаны к услугам. Один процесс может быть привязан к нескольким услугам. 3. При создании заказа создается копия бизнес-процесса выбранной услуги, после чего заказ управляется этой копией. Необходимо для обратной совместимости изменяемых процессов и уже запущенных по заказам. 4. В созданном заказе процесс всегда находится в определенном состоянии. 5. Доступны 4 роли пользователей для управления процессами (роли назначаются администратором провайдера в личном кабинете): - `customer` - заказчик, - `executor` - исполнитель, - `courier` - курьер, - `moderator` - модератор 6. Могут запускать в тестовом режиме - проходят тестовые транзакции оплаты без фактического списания средств. См. [https://developers.cloudpayments.ru/#testirovanie.](https://developers.cloudpayments.ru/#testirovanie.) 7. Синтаксис представлен в `json`-формате. ### Пример настроенного бизнес-процесса [![image-1727457358440.15.49@2x.png](https://wiki.crabler.com/uploads/images/gallery/2024-09/scaled-1680-/image-1727457358440-15-49-at-2x.png)](https://wiki.crabler.com/uploads/images/gallery/2024-09/image-1727457358440-15-49-at-2x.png) **JSON-файл в котором производится настройка** ```JSON { "state0": { "label": "Создание заказа", "onStart": { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field*": [] } }, "step1": { "next": "step2", "text": "Заказ #{{ order.code }}

Услуга: {{ order.service.title }}
Доставка: {{ order.delivery }}
Оплачен: {{ order.payed }}
Сумма к оплате: {{ order.sum }}
Выплаченная сумма: {{ order.sum_payed }}
Общая сумма: {{ order.sum_total }}
Организация заказчика: {{ order.customer.title }}
Заказчик: {{ order.customerUser.title }} {{ order.customerUser.phone_number }}
Провайдер: {{ order.executor.title }}
Исполнитель: {{ order.executorUser.title }}
Статус: {{ order.status.title }}
Дата запланированного завершения: {{ order.deadline }}

{% for item in order.fieldsData %}{{ item.field.title }}: {{ item.valueFormatted }}
{% endfor %}
Детали заказа доступны в личном кабинете.", "type": "email", "subject": "Новый заказ", "recipients": [ "zakaz@crabler.com", "moderator" ] }, "step2": { "type": "setState", "state": "state1" } } } }, "state1": { "label": "Оплата заказа", "actions": [ { "bp": { "step0": { "next": "step1", "type": "pay" }, "step1": { "type": "if", "conditions": [ [ { "service.need_moderation": true }, "step2" ], [ true, "step3" ] ] }, "step2": { "type": "setState", "state": "state2" }, "step3": { "type": "setState", "state": "state3" } }, "code": "pay", "allow": [ "customer" ], "label": "Оплатить" }, { "bp": { "step0": { "type": "setState", "state": "stateCancel" } }, "code": "cancel", "allow": [ "customer" ], "label": "Отменить" } ] }, "state2": { "label": "На модерации", "actions": [ { "bp": { "step0": { "type": "setState", "state": "state3" } }, "code": "action1", "allow": [ "moderator" ], "label": "Модерация пройдена" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "executor_user_id": { "required": true } } }, "step1": { "body": "Вас назначили исполнителем. Свяжитесь с клиентом и подтвердите выезд.", "next": "step2", "type": "push", "title": "Заказ #{{ order.code }}", "recipients": [ "executor" ] }, "step2": { "type": "setState", "state": "state4" } }, "code": "action2", "allow": [ "moderator" ], "label": "Назначить исполнителя" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.customerUser.title }} к заказу #{{ order.code }}", "recipients": [ "moderator" ] } }, "code": "action1_chat", "allow": [ "customer" ], "label": "Написать сообщение" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.moderatorUser.title }} к заказу #{{ order.code }}", "recipients": [ "customer" ] } }, "code": "action2_chat", "allow": [ "moderator" ], "label": "Написать сообщение" }, { "bp": { "step0": { "type": "setState", "state": "stateCancel" } }, "code": "cancel", "allow": [ "customer" ], "label": "Отменить" }, { "bp": { "step0": { "type": "setState", "state": "stateReject" } }, "code": "cancel", "allow": [ "moderator" ], "label": "Отклонить" } ] }, "state3": { "label": "Поиск исполнителя", "actions": [ { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "executor_user_id": { "value": "_CURRENT_USER_" }, "hidden_customer_contact": { "value": false } } }, "step1": { "type": "setState", "state": "state4" } }, "code": "action1", "allow": [ "executor" ], "label": "Взять в работу" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.customerUser.title }} к заказу #{{ order.code }}", "recipients": [ "moderator" ] } }, "code": "action1_chat", "allow": [ "customer" ], "label": "Написать сообщение" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.moderatorUser.title }} к заказу #{{ order.code }}", "recipients": [ "customer" ] } }, "code": "action2_chat", "allow": [ "moderator" ], "label": "Написать сообщение" }, { "bp": { "step0": { "type": "setState", "state": "stateCancel" } }, "code": "cancel", "allow": [ "customer" ], "label": "Отменить" }, { "bp": { "step0": { "type": "setState", "state": "stateReject" } }, "code": "cancel", "allow": [ "moderator" ], "label": "Отклонить" } ], "onStart": { "bp": { "step0": { "body": "{{ order.service.title}}, {{ order.fieldDeliveryAddress }} {{ order.fieldDateTimeDelivery }} - {{ order.service.organization.currency.sum }} {{ order.service.organization.currency.short_title }}", "type": "push", "title": "Новый заказ #{{ order.code }}", "recipients": [ "executor" ] } } } }, "state4": { "label": "Исполнитель назначен", "actions": [ { "bp": { "step0": { "body": "Исполнитель {{ order.executor.title }} подтвердил выезд", "next": "step1", "type": "push", "title": "Заказ #{{ order.code }}", "recipients": [ "customer" ] }, "step1": { "type": "setState", "state": "state5" } }, "code": "action1", "allow": [ "executor" ], "label": "Подтвердить выезд" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "executor_user_id": { "value": "_NULL_" } } }, "step1": { "body": "На заказ будет назначен другой исполнитель, ожидайте", "next": "step2", "type": "push", "title": "Заказ #{{ order.code }}", "recipients": [ "customer" ] }, "step2": { "type": "setState", "state": "state3" } }, "code": "action2", "allow": [ "executor" ], "label": "Отменить выезд" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "executor_user_id": { "value": "_NULL_" } } }, "step1": { "body": "На заказ будет назначен другой исполнитель, ожидайте", "next": "step2", "type": "push", "title": "Заказ #{{ order.code }}", "recipients": [ "customer" ] }, "step2": { "type": "setState", "state": "state3" } }, "code": "action2", "allow": [ "moderator" ], "label": "Вернуть в поиск" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.customerUser.title }} к заказу #{{ order.code }}", "recipients": [ "executor", "moderator" ] } }, "code": "action1_chat", "allow": [ "customer" ], "label": "Написать сообщение" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.executorUser.title }} к заказу #{{ order.code }}", "recipients": [ "customer" ] } }, "code": "action2_chat", "allow": [ "executor" ], "label": "Написать сообщение" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.moderatorUser.title }} к заказу #{{ order.code }}", "recipients": [ "customer" ] } }, "code": "action3_chat", "allow": [ "moderator" ], "label": "Написать сообщение" }, { "bp": { "step0": { "type": "setState", "state": "stateReject" } }, "code": "cancel", "allow": [ "moderator" ], "label": "Отклонить" } ], "onStart": { "bp": { "step0": { "body": "Исполнитель найден, ожидайте звонка", "type": "push", "title": "Заказ #{{ order.code }}", "recipients": [ "customer" ] } } } }, "state5": { "label": "В работе", "actions": [ { "bp": { "step0": { "type": "setState", "state": "stateDone" } }, "code": "action2", "allow": [ "executor" ], "label": "Завершить заказ" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "executor_user_id": { "required": true } } }, "step1": { "body": "Вас назначили исполнителем. Свяжитесь с клиентом и подтвердите выезд.", "next": "step2", "type": "push", "title": "Заказ #{{ order.code }}", "recipients": [ "executor" ] }, "step2": { "type": "setState", "state": "state4" } }, "code": "action2", "allow": [ "moderator" ], "label": "Заменить исполнителя" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.customerUser.title }} к заказу #{{ order.code }}", "recipients": [ "executor", "moderator" ] } }, "code": "action1_chat", "allow": [ "customer" ], "label": "Написать сообщение" }, { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "field1416182395": { "required": true } } }, "step1": { "body": "{{ clientData['field1416182395'] }}", "type": "push", "title": "Сообщение от {{ order.executorUser.title }} к заказу #{{ order.code }}", "recipients": [ "customer" ] } }, "code": "action2_chat", "allow": [ "executor" ], "label": "Написать сообщение" }, { "bp": { "step0": { "type": "setState", "state": "stateReject" } }, "code": "cancel", "allow": [ "moderator" ], "label": "Отклонить" } ], "onStart": { "bp": { "step0": { "type": "setData", "fields": { "status_id": { "value": "ACCEPTED" } } } } } }, "stateDone": { "label": "Выполнен", "actions": [ { "bp": [], "code": "rate", "allow": [ "customer", "executor" ], "label": "Оценить выезд" } ], "onStart": { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "status_id": { "value": "DONE" } } }, "step1": { "body": "Заказ #{{ order.code }} выполнен, пожалуйста, оцените", "type": "push", "title": "{{ order.executor.title }}", "recipients": [ "customer" ] } } } }, "stateCancel": { "label": "Отменен", "onStart": { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "status_id": { "value": "REJECTED" } } }, "step1": { "body": "Заказ #{{ order.code }} отменен", "type": "push", "title": "{{ order.executor.title }}", "recipients": [ "executor" ] } } } }, "stateReject": { "label": "Отклонен", "onStart": { "bp": { "step0": { "next": "step1", "type": "setData", "fields": { "status_id": { "value": "REJECTED" } } }, "step1": { "body": "Заказ #{{ order.code }} отклонен", "type": "push", "title": "{{ order.executor.title }}", "recipients": [ "customer" ] } } } } } ``` ## Структура
``` { "state0": { // Состояние (индексация всегда должна начинаться с 0). "label": "Заголовок состояния", "onState": { // Действия, выполняемые при переходе в состояние (каждый раз) "bp": { "step0": { // Индексация шагов всегда должна начинаться с 0 "type": "Тип действия", "next": "step1", // Переход к следующему шагу (необязательный параметр) // Дополнительные параметры шага }, "step1": {}, ... } }, "actions": [ // Действия пользователей { "label": "Заголовок кнопки", "code": "action1", // Код действия в формате `[\w]+` "allow": [ // Доступ к действию для роли / ролей "customer", "executor", "courier", "moderator" ], "bp": [], // Действия, выполняемые после нажатия кнопки пользователем. "visible": { // Условия отображения кнопки (необязательный параметр). "conditions": [] } }, ... ] }, ... } ```
## Типы действий
ДействиеОписание
`if`Проверка условия.
`setData`Установка значений заказа (включая значения доп. полей).
`setState`Переход к состоянию.
`pay`Оплата заказчиком: - При одностадийной оплате средства списываются сразу. - При двустадийсной оплате происходит заморозка средств, после чего их можно списать с помощью метода `confirmPay` либо вернуть средства с помощью `voidPay`.
`confirmPay`Подтверждение оплаты заказчика.
`confirmPayWithoutPayment`Подтверждение оплаты заказчика без фактической оплаты.
`confirmPayExecutorWithoutPayment`Подтверждение оплаты исполнителя без фактической оплаты.
`voidPay`Отмена оплаты.
`registerExecutor`Регистрация исполнителя.
`createEntity`Создание сущности.
`push`Отправка `push`-уведомления.
`sms`Отправка `sms`-сообщения.
`email`Отправка `email`-сообщения.
### Проверка условия (`if`)
``` { "type": "if", "conditions": [ // Список условий, выполняемых по порядку, до первого истинного [ [], // Условие в json-формате с поддержкой twig-переменных. См. https://www.yiiframework.com/doc/guide/2.0/ru/db-query-builder#where "step1" // Переход к шагу, если условие истинно ], // Другие условия [ true, // Выполняется всегда, когда неистинны все предыдущие условия "step2" ] ] } ```
### Установка значений заказа (включая значения доп. полей) (`setData`)
``` { "type": "setData", "fields": { "field*": [], // Вывести все поля заказа и его доп. поля для заполнения со своими настройками обязательности и контекста (необязательный параметр) // Управление конкретными доп. полями "field": { // Управление конкретным полем (необязательный параметр) "required": false, // Переписывает значение обязательности доп. поля (необязательный параметр) "value": "Значение" // Установка конкретного значения (необязательный параметр) }, // Управление полями заказа "": [] // См. структуру заказа в https://admin.crabler.com/constructor/object/view?id=order } } ```
### Переход к состоянию (`setState`)
``` { "type": "setState", "state": "stateN" // Указывается состояние, к которому осуществляется переход. } ```
### Оплата заказчиком (`pay`)
``` { "type": "pay" } ```
### Подтверждение оплаты заказчика (`confirmPay`)
``` { "type": "confirmPay" } ```
### Подтверждение оплаты заказчика без фактической оплаты (`confirmPayWithoutPayment`)
``` { "type": "confirmPayWithoutPayment" } ```
### Подтверждение оплаты исполнителя без фактической оплаты (`confirmPayExecutorWithoutPayment`)
``` { "type": "confirmPayExecutorWithoutPayment" } ```
### Отмена оплаты (`voidPay`)
``` { "type": "voidPay" } ```
### Регистрация исполнителя (`registerExecutor`)
``` { "type": "registerExecutor" } ```
### Создание сущности (`createEntity`)
``` { "type": "createEntity" } ```
### Отправка `push`-уведомления (`push`)
``` { "type": "push", "title": "Заголовок", // Поддерживает twig-переменные "body": "Текст", // Поддерживает twig-переменные "recipients": [ // Получатели (один либо несколько ролей / пользователей) "executor", // Название роли. Если у заказа задан исполнитель, то push-уведомление получает конкретно он иначе push-уведомление получают все исполнители провайдера, имеющих доступ к услуге. Аналогично для других ролей. "", // В качестве получателя может быть передан UUID конкретного пользователя. "+70001234567" // В качестве получателя может быть передан номер телефона в свободном формате. Будет осуществлен поиск пользователя в базе по номеру телефона. ] } ```
### Отправка `sms`-сообщения (`sms`)
``` { "type": "sms", "message": "Текст сообщения", // Поддерживает twig-переменные "recipients": [ // Получатели (один либо несколько ролей / пользователей) "executor", // Название роли. Если у заказа задан исполнитель, то push-уведомление получает конкретно он иначе push-уведомление получают все исполнители провайдера, имеющих доступ к услуге. Аналогично для других ролей. "", // В качестве получателя может быть передан UUID конкретного пользователя. "+70001234567" // В качестве получателя может быть передан номер телефона в свободном формате. Будет осуществлен поиск пользователя в базе по номеру телефона. ] } ```
### Отправка `email`-сообщения (`email`)
``` { "type": "email", "subject": "Тема письма", // Поддерживает twig-переменные "text": "Текст письма", // Поддерживает twig-переменные "recipients": [ // Получатели (один либо несколько ролей / пользователей) "executor", // Название роли. Если у заказа задан исполнитель, то push-уведомление получает конкретно он иначе push-уведомление получают все исполнители провайдера, имеющих доступ к услуге. Аналогично для других ролей. "", // В качестве получателя может быть передан UUID конкретного пользователя. "example@crabler.com" // В качестве получателя может быть передан конкретный email. ] } ```
## Константы для значений полей
КонстантаЗначение
`_NULL_``null`
`_CURRENT_USER_`ID текущего пользователя
## `TWIG`-переменные
ПеременнаяЗначение
`order`Текущий заказ. Можно обращаться к вложенным сущностям.
`clientData`Данные, полученные с клиента через `POST`.