Настройка REST роботов (действий) через приложение (встройку)
Описание
С версии 20.0.600 модуля Бизнес-процессы появилась возможность настраивать робота/действие, используя интерфейс приложения. Реализована стандартным механизмом встройки rest.placement.
Реализация на примере приложения
Рассмотрим реализацию на конкретном примере приложения (полный код приложения представлен в следующем табе страницы).
В нашем примере приложение добавляет робота, у которого есть 2 параметра типа Строка:
var params = { 'CODE': 'robot', 'HANDLER': 'http://handler.com', 'AUTH_USER_ID': 1, 'NAME': 'Пример робота-встройки', 'USE_PLACEMENT': 'Y', 'PLACEMENT_HANDLER': 'http://handler.com', 'PROPERTIES': { 'string': { 'Name': 'Параметр 1', 'Type': 'string' }, 'stringm': { 'Name': 'Параметр 2', 'Type': 'string', 'Multiple': 'Y', 'Default': ['value 1', 'value 2'] }, } }; BX24.callMethod( 'bizproc.robot.add', params, function(result) { if(result.error()) alert("Ошибка: " + result.error()); } );
Для того, чтобы параметры можно было настраивать через приложение, при добавлении робота передаем параметры USE_PLACEMENT=Y
и обработчик PLACEMENT_HANDLER
.
Останется написать обработчик встройки, задача которого отрисовать параметры и сохранить их значения. Для этого в обработчик в PLACEMENT_OPTIONS
мы передаем данные:
- code — код вашего робота при регистрации
- activity_name — идентификатор действия в шаблоне бизнес-процесса
- properties — список свойств и их описание
- current_values — текущие значения свойств
- document_type — тип документа, над которым идет настройка
- document_fields — список полей документа
- template — список доступных полей шаблона (в коробке Битрикс24 доступно с версии 24.200.0)
Для параметра
template
доступны элементы:- parameters — список параметров шаблона
- variables — список переменных шаблона
- constants — список констант шаблона
- global_variables — список глобальных переменных
- global_constants — список глобальных констант
- return_activities — список действий (роботов), которые генерируют дополнительные результаты
При этом, структура свойств в этих списках приведена к единому формату и представляет из себя структуру:
{ Id: строка, идентификатор (код) свойства Type: строка, идентификатор типа свойства Name: строка, название Description: строка, описание Multiple: булевое, множественное свойство или нет Required: булевое, обязательное свойство или нет Options: смешанное. Зависит от типа свойства Settings: список настроек. Зависит от типа свойства Default: смешанное. Значение по умолчанию для свойства }
Список
return_activities
состоит из списка действий, которые возвращают результаты и их свойства. Имеет структуру:{ Id: строка, идентификатор действия в шаблоне Type: строка, тип действия Title: строка, название действия в шаблоне Return: список, доступные свойства }
В приложение все это приходит так:
Array ( [code] => robot [activity_name] => A72788_31169_37133_27365 [properties] => Array ( [string] => Array ( [NAME] => Параметр 1 [TYPE] => string ) [stringm] => Array ( [NAME] => Параметр 2 [TYPE] => string [MULTIPLE] => Y [DEFAULT] => Array ( [0] => value 1 [1] => value 2 ) ) ) [current_values] => Array ( [string] => 1 [stringm] => Array ( [0] => 2 ) ) [document_type] => Array ( [0] => crm [1] => CCrmDocumentDeal [2] => DEAL ) [document_fields] => Array ( [ID] => Array ( [Name] => ID [Type] => int [Filterable] => 1 [Editable] => [Required] => [BaseType] => int ) [TITLE] => Array ( [Name] => Название [Type] => string [Filterable] => 1 [Editable] => 1 [Required] => 1 [BaseType] => string ) [...] ) [template] => Array ( [parameters] => Array ( ) [variables] => Array ( [0] => Array ( [Id] => Approver [Type] => user [Name] => Утверждающий [Description] => [Multiple] => 1 [Required] => [Options] => [Settings] => [Default] => ) ) [constants] => Array ( [0] => Array ( [Id] => Manager [Type] => user [Name] => Кто утверждает [Description] => директор или заместитель [Multiple] => 1 [Required] => 1 [Options] => [Settings] => [Default] => Array ( [0] => user_4 ) ) ) [global_variables] => Array ( [0] => Array ( [Id] => Variable1666332520655 [Type] => user [Name] => test u [Description] => [Multiple] => 1 [Required] => [Options] => [Settings] => [Default] => Array ( [0] => user_1 ) ) ) [global_constants] => Array ( [0] => Array ( [Id] => Constant1666332578194 [Type] => user [Name] => test u 1 [Description] => [Multiple] => [Required] => [Options] => [Settings] => [Default] => user_1 ) ) [return_activities] => Array ( [0] => Array ( [Id] => A71026_84473_24610_19894 [Type] => LogActivity [Title] => Запись в отчет [Return] => Array ( [0] => Array ( [Id] => Report [Name] => Отчет [Type] => string ) ) ) [1] => Array ( [Id] => A58853_60082_34258_61777 [Type] => ApproveActivity [Title] => Утверждение [Return] => Array ( [0] => Array ( [Id] => TaskId [Name] => ID [Type] => int ) [1] => Array ( [Id] => Comments [Name] => Комментарии [Type] => string ) [2] => Array ( [Id] => VotedCount [Name] => Сколько проголосовало [Type] => int ) [3] => Array ( [Id] => TotalCount [Name] => Сколько должно проголосовать [Type] => int ) [4] => Array ( [Id] => VotedPercent [Name] => Процент проголосовавших [Type] => int ) [5] => Array ( [Id] => ApprovedPercent [Name] => Процент утвердивших [Type] => int ) [6] => Array ( [Id] => NotApprovedPercent [Name] => Процент отклонивших [Type] => int ) [7] => Array ( [Id] => ApprovedCount [Name] => Количество утвердивших [Type] => int ) [8] => Array ( [Id] => NotApprovedCount [Name] => Количество отклонивших [Type] => int ) [9] => Array ( [Id] => LastApprover [Name] => Последний голосовавший [Type] => user ) [10] => Array ( [Id] => LastApproverComment [Name] => Комментарий последнего голосовавшего [Type] => string ) [11] => Array ( [Id] => UserApprovers [Name] => Утвердили пользователи [Type] => user ) [12] => Array ( [Id] => Approvers [Name] => Утвердили пользователи (текст) [Type] => string ) [13] => Array ( [Id] => UserRejecters [Name] => Отклонили пользователи [Type] => user ) [14] => Array ( [Id] => Rejecters [Name] => Отклонили пользователи (текст) [Type] => string ) [15] => Array ( [Id] => IsTimeout [Name] => Автоматическое отклонение [Type] => int ) ) ) ) ) )
Осталось сделать верстку и научиться сохранять параметры непосредственно в Робота.
Для этого мы используем функцию setPropertyValue
, которая доступна нам через BX24.placement.call.
BX24.placement.call( 'setPropertyValue', {string: 'test string'} )
В качестве параметров передаются ID свойства и значения. Можно передавать несколько значений свойств, например:
BX24.placement.call( 'setPropertyValue', {string: 'test string', stringm: ['test2', 'test3']} )
Далее пользователь сохраняет робота как обычно.
Так это выглядит в Роботах:
А так в дизайнере бизнес-процессов:
Примечание: Белая область — встройка (фрейм приложения).
Полный код приложения
<?php header('Content-Type: text/html; charset=UTF-8'); $protocol = $_SERVER['SERVER_PORT'] == '443' ? 'https' : 'http'; $host = explode(':', $_SERVER['HTTP_HOST']); $host = $host[0]; define('BP_APP_HANDLER', $protocol.'://'.$host.explode('?', $_SERVER['REQUEST_URI'])[0]); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <script src="//api.bitrix24.com/api/v1/"></script> <?if (!isset($_POST['PLACEMENT']) || $_POST['PLACEMENT'] === 'DEFAULT'):?> <h1>Робот-встройка</h1> <div class="container-fluid"> <div class="container-fluid"> <h2>Робот</h2> <button onclick="installRobot();" class="btn btn-primary">Установить</button> – <button onclick="uninstallRobot();" class="btn btn-danger">Удалить</button> </div> <hr/> <div class="container-fluid"> <button onclick="getList();" class="btn btn-light">Получить список установленных роботов</button> </div> </div> <script type="text/javascript"> document.body.style.display = 'none'; BX24.init(function() { document.body.style.display = ''; }); function installRobot() { var params = { 'CODE': 'robot', 'HANDLER': '<?=BP_APP_HANDLER?>', 'AUTH_USER_ID': 1, 'NAME': 'Пример робота-встройки', 'USE_PLACEMENT': 'Y', 'PLACEMENT_HANDLER': '<?=BP_APP_HANDLER?>', 'PROPERTIES': { 'string': { 'Name': 'Параметр 1', 'Type': 'string' }, 'stringm': { 'Name': 'Параметр 2', 'Type': 'string', 'Multiple': 'Y', 'Default': ['value 1', 'value 2'] }, } }; BX24.callMethod( 'bizproc.robot.add', params, function(result) { if(result.error()) alert("Ошибка: " + result.error()); else alert("Успешно"); } ); } function uninstallRobot() { BX24.callMethod( 'bizproc.robot.delete', { 'CODE': 'robot' }, function(result) { if(result.error()) alert('Ошибка: ' + result.error()); else alert("Успешно"); } ); } function getList() { BX24.callMethod( 'bizproc.robot.list', {}, function(result) { if(result.error()) alert("Ошибка: " + result.error()); else alert("Коды установленных роботов: " + result.data().join(', ')); } ); } </script> <?php else:?> <form name="props" class="container-fluid"> <?php $options = json_decode($_POST['PLACEMENT_OPTIONS'], true); foreach ($options['properties'] as $id => $property) { $multiple = isset($property['MULTIPLE']) && $property['MULTIPLE'] === 'Y'; $val = (array) $options['current_values'][$id]; if (!$val) { $val[] = ''; } if ($multiple) { $val[] = ''; } $name = $multiple ? $id.'[]' : $id; ?> <div class="form-group"> <label><?=htmlspecialchars($property['NAME'])?>:</label> <?foreach ($val as $v):?> <p><input name="<?=$name?>" value="<?=htmlspecialchars((string)$v)?>" class="form-control" onchange="setPropertyValue('<?=$id?>', this.name, <?=(int)$multiple?>)"></p> <?endforeach;?> </div> <? } ?> <script> function setPropertyValue(name, inputName, multiple) { var form = new FormData(document.forms.props); var value = multiple? form.getAll(inputName) : form.get(inputName); var params = {}; params[name] = value; BX24.placement.call( 'setPropertyValue', params ) } </script> </form> <?php endif;?> </body> </html>