Полный цикл в digital

Условие (condition) в модуле Бизнес Процессы

Готовый код можно скачать в моем репозитории на GitFlic.

В рамках шаблона Бизнес Процессов помимо действий или activity есть еще и условия или condition. Условия это особый подвид активити, который может быть использован в блоках Условие и Цикл, наряду с Полем документа, PHP код, Смешанное и Истина.

Мы будем рассматривать условие на примере штатного условия codecondition, все сводится к PHP коду который должен отдать true.

Расположение

Порядок поиска является приоритетным, директории будут перебираться последовательно пока не будет найдена директория с условием. Condition, могут располагаться в следующих местах:

  • /local/activities
  • /local/activities/custom
  • /bitrix/activities/custom
  • /bitrix/activities/bitrix
  • /bitrix/modules/bizproc/activities

Файловая структура

Для нашего случая будет использоваться название действия phpcodecondition, по сути я скопировал штатный condition который выполняит PHP код, в случае если PHP код отдаст true, выполнение пойдет дальше.

          • .description.php
          • properties_dialog.php
          • testcodeactivity.php
        • .description.php содержит мета-информацию описывающую наше действие, аналог .description.php в компонентах
        • icon.gif аватарка
        • phpcodeactivity.php содержит основную логику нашего активити, аналог class.php в компонентах
        • properties_dialog.php содержит код для визуального отображения, аналог template.php в компонентах

Файл .description.php

Основная задача файла, установить переменную $arActivityDescription как массив описывающий действие:

/local/activities/phpcodecondition/.description.php<?php

use Bitrix\Main\Localization\Loc;

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true)
{
	die();
}

$arActivityDescription = [
	'NAME' => Loc::getMessage('BPC_DESCR_NAME'),
	'DESCRIPTION' => Loc::getMessage('BPC_DESCR_DESCR'),
	'TYPE' => 'condition',
	'FILTER' => [
		'EXCLUDE' => CBPHelper::DISTR_B24,
	],
];

Рассмотрим все возможные ключи массива $arActivityDescription:

  • NAME (string) локализованное название действия, отображается в списке действий, а так же в заголовке всплывающего окна настроек
  • DESCRIPTION (string) локализованное описание действия, отображается во всплывающем окне настроек
  • TYPE (string or array) тип действия, в случае условия может принимать только condition, в случае действия может быть либо activiy, либо robot_activity либо массивом из этих же элементов
  • CLASS (string) название php-класса обработчика действия, должен совпадать с названием директории
  • JSCLASS (string) название js-класса обработчика действия, по умолчанию BizProcActivity
  • CATEGORY (array) опциональное описание раздела для отображения в дизайнере БП в случае TYPE=activity
  • ROBOT_SETTINGS (array) опциональное описание раздела для отображения в роботах в случае TYPE=robot_activity
  • FILTER (array) структура описывающая условия отображения действия
  • RETURN (array) структура описывающая возвращаемые значения
  • ADDITIONAL_RESULT (array) набор из кодов свойств действия, возвращающихся как дополнительные значения, которые могут быть переданы в другие действия во время выполнения бизнес-процесса

CATEGORY

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

CATEGORY

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

'CATEGORY' => [
    'ID' => 'other',
]

Это является минимально необходимым описанием для размещения действия в панели редактора шаблона бизнес-процесса.

Однако иногда бывает полезным создать собственный раздел. Для этого в категории необходимо указать еще несколько ключей: OWN_ID (string) — симв. код нового раздела и OWN_NAME (string) — отображаемое название раздела, например, так:

'CATEGORY' => [
    'ID'       => 'own_super_group',
    'OWN_ID'   => 'own_super_group',
    'OWN_NAME' => 'My own super group',
],

ROBOT_SETTINGS

Аналогично структуре CATEGORY есть структура описывающая расположение карточки робота в интерфейсе выбора роботов:

'ROBOT_SETTINGS' => [
    'GROUP' => ['elementControl'],
    'SORT' => 2800,
]

Описание структуры:

  • GROUP набор групп в которых отображается робот
  • SORT приоритет отображения робота в группе

Список доступных групп (на момент написания статьи):

  • clientCommunication коммуникация с клиентом
  • informingEmployee информирование сотрудников
  • employeeControl контроль сотрудников
  • paperwork оформление документов
  • payment оплата товаров и услуг
  • delivery управление доставкой
  • repeatSales повторные продажи
  • ads запуск рекламы
  • elementControl управление элементом
  • clientData данные о клиентах
  • taskManagement управление задачами
  • modificationData хранение и изменение данных
  • digitalWorkplace автоматизация рабочих мест
  • other другие роботы

FILTER

Некоторые действия имеют смысл только в определенных документах, поэтому существует специальные ограничения для сокрытия и показа таких действий. За подобную работу отвечает ключ FILTER, который может содержать 2 ключа:

  • INCLUDE описывает типы документов к которым применимо данное активити
  • EXCLUDE описывает типы документов к не применимо данное активити

Например, разрешить действие только для шаблонов по сделкам:

"FILTER" => [
    'INCLUDE' => [
        ['crm', 'CCrmDocumentDeal'],
    ]
],

RETURN

Действие может возвращать значения в ходе своего выполнения. Для описания возвращаемых значений в мета-описании действия необходимо использовать ключ RETURN, содержащий структуры возвращаемых значений.

Например:

'RETURN' => [
    'ElementId' => [
        'NAME' => 'Displayed name for ElementId property',
        'TYPE' => 'int',
    ],
    'ErrorMessage' => [
        'NAME' => 'Displayed name for Error message',
        'TYPE' => 'string',
    ],
],

Доступные типы TYPE возвращаемых значений описаны константами в классе Bitrix\Bizproc\FieldType, например:

  • FieldType::BOOL (bool)
  • FieldType::DATE (date)
  • FieldType::DATETIME (datetime)
  • FieldType::DOUBLE (double)
  • FieldType::FILE (file)
  • FieldType::INT (int)
  • FieldType::SELECT (select)
  • FieldType::INTERNALSELECT (internalselect)
  • FieldType::STRING (string)
  • FieldType::TEXT (text)
  • FieldType::USER (user)
  • FieldType::TIME (time)

Значения возвращаемые в RESULT без перечисления в ADDITIONAL_RESULT недоступны для использования в других действиях бизнес-процессов.

ADDITIONAL_RESULT

Возвращаемые значения действия (RESULT) имеют ряд недостатков:

  • Они должны быть объявлены явно, т.е. нет возможности динамически определять их состав
  • Их нельзя использовать при настройке других действий бизнес-процессов

Чтобы избежать этой ситуации, разработчики добавили специальный ключ ADDITIONAL_RESULT, содержащий перечисление кодов свойств действия, которые будут транслированы в дизайнер бизнес-процессов и могут быть использованы для вставки в параметры других действий через инструмент «Вставка значения».

Пример использования в мета-файле:

'ADDITIONAL_RESULT' => [
    'FieldsMap'
]

В самом FieldsMap должен содержаться ассоциативный массив, в качестве ключей которого должны выступать свойства действия, а значениями — описание типа значения. В качестве примера рассмотрим действие «Получить информацию об элементе списка» (GetListsDocumentActivity).

В мета-описании файла определено возвращаемое значение FieldsMap.

Рассмотрим части файла связанные непосредственно с обработкой FieldsMap:

class CBPGetListsDocumentActivity extends CBPActivity
{
    // ...
    public function __construct($name)
    {
        // ..
        $this->arProperties = [
            // ...
            "Fields" => null,
            "FieldsMap" => null,
        ];
    }
    // ..
    public function ReInitialize()
    {
        // ...

        $fields = $this->Fields;
        if ($fields && is_array($fields))
        {
            foreach ($fields as $field)
            {
                $this->{$field} = null;
            }
        }
    }
    // ...
    public function Execute()
    {
        // ...
        $map = $this->FieldsMap;

        // ...

        $this->SetPropertiesTypes($map);
        $values = [];

        foreach ($map as $id => $field)
        {
            // ...
            $this->arProperties[$id] = $document[$id];
        }

        // ...
    }
    // ...
    public static function GetPropertiesDialogValues($documentType, $activityName, &$arWorkflowTemplate,
        &$arWorkflowParameters, &$arWorkflowVariables, $arCurrentValues, &$errors)
    {
        // ..

        $properties['FieldsMap'] = self::buildFieldsMap($properties['DocumentType'], $properties['Fields']);

        $arCurrentActivity = &CBPWorkflowTemplateLoader::FindActivityByName($arWorkflowTemplate, $activityName);
        $arCurrentActivity["Properties"] = $properties;

        // ..
    }
    // ...
    private static function buildFieldsMap(array $documentType, $fields)
    {
        // ...
        $map = [];
        foreach ($fields as $field)
        {
            // ...
                $map[$field] = \Bitrix\Bizproc\FieldType::normalizeProperty($documentFields[$field]);
            // ...
        }
        return $map;
    }

// ...
}

Файл phpcodeactivity.php

Мы создаем простое условие, родительским классом в данном случае будет являться Activity, а наш класс должен иметь префикс CBP.

В классе нашего активити нам необходимо:

  1. __construct описать конструктор, задав значения по-умолчанию для наших свойств
  2. Execute метод который будет выполняться в запущенном бизнес-процессе
  3. GetPropertiesDialog отображение диалога настроек
  4. GetPropertiesDialogValues сохранение введенных значений
/local/activities/phpcodeactivity/phpcodeactivity.php<?php

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

use Bitrix\Main\Localization\Loc;

class CBPPhpCodeCondition extends CBPActivityCondition
{
    public $condition = '';

    public function __construct($condition)
    {
        // записываем PHP выражение
        $this->condition = $condition;
    }

    // метод который будет выполняться в запущенном бизнес-процессе, доступны свойства обьявленные в конструкторе
    public function Evaluate(CBPActivity $ownerActivity)
    {
        // выполним php код
        @eval("\$result = " . $this->condition . ";");

        // вернем результат выполнения кода
        return CBPActivityExecutionStatus::Closed;

        // возможные варианты ответа
        // CBPActivityExecutionStatus::Executing; действие еще не завершило свою работу
        // CBPActivityExecutionStatus::Closed; действие завершило свою работу
        // CBPActivityExecutionStatus::Faulting; ошибка при выполнении действия, прекратить выполнение бизнес-процесса
    }

    // валидация
    public static function validateProperties($value = null, CBPWorkflowTemplateUser $user = null)
    {
        $arErrors = [];

        if ($user == null || !$user->isAdmin()) {
            $arErrors[] = [
                'code' => 'perm',
                'message' => Loc::getMessage('BPCC_NO_PERMS'),
            ];
        }

        return array_merge($arErrors, parent::validateProperties($value, $user));
    }

    // диалог настроек, показываем поля формы для заполнения
    public static function GetPropertiesDialog(
        $documentType,
        $arWorkflowTemplate,
        $arWorkflowParameters,
        $arWorkflowVariables,
        $defaultValue,
        $arCurrentValues = null
    )
    {
        $runtime = CBPRuntime::GetRuntime();

        if (!is_array($arCurrentValues)) {
            $arCurrentValues = ['condition_php_code' => ($defaultValue == null ? '' : $defaultValue)];
        }

        // инклудим файл который выведет html-верстку, штатно это делается через менеджер текущего выполнения
        return $runtime->ExecuteResourceFile(
            __FILE__,
            'properties_dialog.php',
            ['arCurrentValues' => $arCurrentValues]
        );
    }

    // сохранение введенных значений в поля формы
    public static function GetPropertiesDialogValues(
        $documentType,
        $arWorkflowTemplate,
        $arWorkflowParameters,
        $arWorkflowVariables,
        $arCurrentValues,
        &$arErrors
    )
    {
        $arErrors = [];

        if (!array_key_exists('condition_php_code', $arCurrentValues) || $arCurrentValues['condition_php_code'] == '') {
            $arErrors[] = [
                'code' => '',
                'message' => Loc::getMessage('BPCC_EMPTY_CODE'),
            ];

            return null;
        }

        $arErrors = self::validateProperties(
            $arCurrentValues['condition_php_code'],
            new CBPWorkflowTemplateUser(CBPWorkflowTemplateUser::CurrentUser)
        );

        if (count($arErrors) > 0) {
            return null;
        }

        return $arCurrentValues['condition_php_code'];
    }
}

Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!