# Бизнес-процессы
1. Предназначены для управления заказами.
2. Привязаны к услугам. Один процесс может быть привязан к нескольким услугам.
3. При создании заказа создается копия бизнес-процесса выбранной услуги, после чего заказ управляется этой копией. Необходимо для обратной совместимости изменяемых процессов и уже запущенных по заказам.
4. В созданном заказе процесс всегда находится в определенном состоянии.
5. Доступны 4 роли пользователей для управления процессами (роли назначаются администратором провайдера в личном кабинете):
- `customer` - заказчик,
- `executor` - исполнитель,
- `courier` - курьер,
- `moderator` - модератор
6. Могут запускать в тестовом режиме - проходят тестовые транзакции оплаты без фактического списания средств. См. [https://developers.cloudpayments.ru/#testirovanie.](https://developers.cloudpayments.ru/#testirovanie.)
7. Синтаксис представлен в `json`-формате.
### Пример настроенного бизнес-процесса
[](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`. |