Мы заменили ручной труд кодом и вот, что из этого вышло: автоматизация процессов в банке «Ренессанс Кредит»

Логотип компании Ренессанс Банк

Команда банка «Ренессанс Кредит» продемонстрировала автоматизацию банковских процессов на реальном кейсе с примерами кода.

Рутинные задачи отнимают много времени специалистов разных линий и тормозят работу. Команда ИТ4ИТ разработала систему, которая автоматизирует действия сотрудников, перекладывая скучную работу на роботов. В результате у ИТ-департамента появилось больше времени на интересные задачи, а банковские процессы ускорились.

Как система росла

Сначала система называлась Jarvis в честь персонажа комиксов Marvel. Её целью было высвободить ресурсы сотрудников ИТ для более сложных задач. Jarvis постоянно развивался. Со временем он интегрировался с другими внешними системами: от Gitlab до мониторинга уязвимостей, стал связываться с базами данных, исполняя SQL-код. Среди рабочих инструментов автоматизации — умение работать с файлами Excel, запускать PowerShell и Bash-скрипты на удалённых серверах. Теперь система может загружать сайты, имитировать действия человека: вводить текст в поля, нажимать кнопки, переходить по страницам. Это используется для отправки запросов в MailStream. В июле текущего года Jarvis (теперь он называется Robot Vision) научился работать с новейшей системой управления услугами банка, ITSM Ivanti.

Система автоматизации занимает одно из ключевых мест в ИТ-ландшафте банка
Мы заменили ручной труд кодом и вот, что из этого вышло: автоматизация процессов в банке «Ренессанс Кредит» 1
Упрощенный процесс обработки обращений пользователей, основные механизмы, особенности системы, связи с базами данных и внешние интеграции
Мы заменили ручной труд кодом и вот, что из этого вышло: автоматизация процессов в банке «Ренессанс Кредит» 2
Инструменты автоматизации

Автоматизация всех рутинных задач банка

В Vision (краткое имя от Robot Vision) приходят заявки на автоматизацию какого-либо действия. Например, разблокировку учётной записи или перевод заявок по статусам на кредитном конвейере. Робот принимает заявку и запускает специализированный обработчик.

Сама автоматизация выглядит так: например, пользователь хочет разблокировать свою учётную запись. Он заходит на внутренний портал самообслуживания, выбирает нужную заявку и заполняет форму. Дальше ему остаётся только ждать согласования и исполнения. Если запрос согласован, то система забирает его из очереди, подбирает подходящий обработчик и запускает автоматизацию. В нашем примере — это обработчик для взаимодействия с системой IDM.

От открытия заявки до её выполнения проходит от часа до одного рабочего дня. В сутки система обрабатывает около 600 обращений.

Ключ к повышению производительности

В 2019 году мы работали с порталом самообслуживания для сотрудников банка HP Service Manager (HPSM). В нём регистрировались обращения, инциденты, все внутренние заявки. Например, запросы на обновление систем или установку ПО.

В HPSM есть несколько типов запросов. Мы обрабатывали только один — это sub-quote (SQ). В систему приходил номер sub-quote. Мы прямо в ядре запрашивали нужную информацию по ней. Забирали имя основного запроса и сравнивали его с обработчиками в базе данных для получения JS тела скрипта, отвечающего за автоматизацию.

			dynamic subquote = HPSMconnect.GetSubQuote(request.key);
if (subquote.status != "requested") return;
var subquoteDescription = subquote.Description[0];
var subquoteDetails = request.manual
    ? SubQuoteContext.GetByKeyNotActive(subquoteDescription)
    : SubQuoteContext.GetByKey(subquoteDescription);
var subquoteId = subquoteDetails.Data.Id;
var executionScript = JSContext.GetAllForSQ(subquoteId);
var executionResult = JS.RunScriptJS((executionScript.body, request.key, eventId);
		

Количество заявок было низким. При этом система не успевала обработать весь входящий поток. «Дорогие» специалисты тратили много времени на рутину.

Подход пришлось изменить, он стал более гибким. Теперь мы не проводим операций по определению имени задачи в ядре, а сразу делим задачи на группы автоматизации, у которых есть ключи определения обработчика (Key-Value-Pair) и свой «предобработчик». Предобработчик на основе полученных данных генерирует набор ключей-значений для последующего поиска обработчика. Происходит это так:

  1. Мы определяем тип запроса, например, SQ.
  2. Находим группу обработчиков, которые работают с этим типом. Нужный обработчик находим по ключу action, он указывает, какое действие необходимо совершить с запросом. На обработчике также указан ключ, значение которого равно действию, например, разблокировке учётной записи.
  3. Обработчик выполняет нужное действие.

Как и раньше мы ищем обработчик по наименованию задачи, но вдобавок имеем гибкую систему, которая способна интегрироваться с любой другой. Можем не привязываться к имени задачи, а искать по любому другому параметру или набору параметров хоть из 100 различных источников. Раньше мы обслуживали только SQ-заявки, а сейчас можем обрабатывать и RFC (запросы на изменение), и инциденты.

Сократили код в 26 раз

Скрипт — это кодовая часть обработчика, то есть самой автоматизации. Чем проще писать скрипты, тем быстрее обработчик будет готов, и автоматизация будет раньше поставлена на прод.

До улучшений разработка нового процесса состояла из копипаста 500 или 1000 строчек кода, которые определяли не только логику, но и методы обращения к системам, подключения к базе данных. В результате сроки разработки нового процесса автоматизации могли занимать до двух недель, учитывая согласования, тестирования и деплой.

О хорошем версионинге речь тоже не шла. При каждом редактировании мы сохраняли предыдущую версию скрипта в базе данных, поэтому тратили огромные ресурсы на хранение даже небольших изменений. Чтобы что-то протестировать, нужно это написать и сохранить, провести отладку, тестирование и рефакторинг, а это ещё десятки сохранений кода. Таким образом, условные 2000 символов умножаются на 50.

Я перевёл скрипты на GitLab и сократил количество кода в 26 раз. Для разработчика автоматизации ничего не поменялось, а вот под капотом мы провели большую оптимизацию процесса.

Сейчас чтобы автоматизировать процесс, не нужно копипастить. Весь основной код вынесен в встраиваемые пакеты на базе JS, например: HPSMPackage, JiraPackage и многие другие.

			Package HPSM
var hpsmHost = "http://{host}/SM/9/rest/".replace(/{host}/g, Variables["hpsm_host"]);
var workGroupCommentConstant = '\nВ журнале заявки подробности.\n' +
'Заявка была переназначена на исполнительную группу - ответственную за сервис.\n' +
'Исполнительной группе требуется:\n' +
'1) Устранить последствия: выполнить и закрыть заявку;\n' +
'2) Установить причины: провести анализ «почему заявка не была выполнена?»\n' +
'3) При необходимости завести инцидент на администраторов системы, на стороне которой произошла ошибка.';
this.getWorkGroupComment = function() {
    return workGroupCommentConstant;
};
/*
* Приведение значения поля из обращения к типу Boolean
*/
this.cartItemToBoolean = function(item) {
    return String(item).toLowerCase() == "true";
};
/*
* Переназначить сабквоту на другую исполнительную группу
*/
this.setWorkGroup = function(subquote, workGroup, comment) {
    var data = {
        NASTocmlUpdateRecord: {
            Action: ["toChangeAssignment", String(comment), String(workGroup)]
        }
    };
    return requestToHpsm("NASTocmlUpdateRecord/" + subquote, "POST", data);
};
		

Функционал по подключениям, специфичный API и другие вспомогательные методы вынесены во встраиваемые пакеты. Это тоже JS код, просто хранящийся в пакетах, которые импортируются в скрипты с бизнес-логикой методом require.

			var gitlab = require("package/gitlab");
		

Например, обработчик «Обновление тестовых сред». В скрипте с бизнес-логикой сейчас содержит всего 75 строчек кода и два подключения: package/gitlab, package/hpsm/sq. package/gitlab содержит 260 строчек кода. package/hpsm/sq — 365 строчек. И всего таких пакетов у нас 29. Некоторые из них могут содержать значительно больше кода.

Скрипты автоматизации настраивают взаимодействие между разными системами. В них сделан акцент на ключевых действиях, компактности кода, простоте использования и доработок

Подняли скорость деплоя от получаса до минуты

Раньше мы публиковали приложения, разработанные на .Net, на Windows-хостах под управлением IIS. Нам приходилось вручную заходить на сервер, подключаться по административному логину и паролю, загружать на хост пакет с приложением, разворачивать, останавливать IIS, разворачивать его заново. На это уходило в среднем пятнадцать минут — или полчаса, если возникали какие-то затруднения.

Теперь мы используем GitLab как систему для сборки кода, отправки его в репозиторий, в редких случаях для публикации этих пакетов на хостах. AWX используется как система для деплоя. Это сократило время публикации в разы.

По шагам это выглядит следующим образом:

  1. Мы публикуем код в систему контроля версий.
  2. Нажимаем кнопку «отправить на тест» или «отправить на препрод».
  3. Запрос уходит в AWX, он получает собранный пакет из GitLab либо из другой системы хранения кода.
  4. Запускается скрипт публикации на конечное устройство, приложение развёртывается. Выставляются необходимые настройки, и меньше чем через минуту мы видим результат.
Автоматизация доставки изменений сократила время публикации скриптов от получаса до минуты

Расширили функциональные возможности системы

Система получила обновления в виде модулей по работе с Powershell, Excel, CSV и прочими атрибутами корпоративных дел. Теперь чтобы подключиться к серверу и выполнить команду Powershell или Bash, достаточно ключей и адреса.

Реализовали на связке JS и C# с помощью движка Jint

Мы выбрали JS из-за его популярности и простоты — легче находить в команду новых людей и вводить их в курс дела.

В целом, совмещение C# с JS звучит странно, это разные языки. Но они похожи в одном — оба являются интерпретируемыми, но по-своему. Разные синтаксис, спецификации, среды исполнения.

Мы используем JS как язык разработки скриптов автоматизации. Можно было разрабатывать всё на C#, поскольку на нём написан backend. Но это долго и сложно, это нужно компилировать. Можно было подключить Python или F#, последний тоже живёт в контексте .Net. Мы этого не сделали потому, что текущих реализаций достаточно. В банке упор делается на другие вещи — экономичность и производительность.

Поначалу JS был встроен в проект неудобно. Часть общего JS кода писалась в .cs файлах, встраивалась в контекст движка Jint и тем самым дополняла функционал скриптов автоматизации. Со временем мы переписали эти расширения на C#.

Jint даёт набор инструментов, позволяющий настроить среду исполнения интерпретируемого кода, с его помощью мы связали C# и JS. Его задача — интерпретировать JS код и выполнить его в среде .Net. Движок Jint создаёт контекст выполнения, в рамках которого мы можем исполнять JS код, подгружать в него необходимые модули и встраиваемые пакеты. Благодаря Jint мы можем работать с результатами выполнения JS скрипта в контексте C# и наоборот.

Jint — это самая известная и простая библиотека. Она легко встраивается, реализует весь нужный нам функционал и развивается до сих пор. Чтобы начать пользоваться Jint, нужно только создать экземпляр движка и выполнить JS скрипт:

			new Jint.Engine().Execute("console.log('hello')");
		

Для объявления функции выполним следующий код. Таким же образом можно объявить переменную:

			_jintEngine.SetValue("tostr", new Func((source) => source.ToString()));
		

Если необходимо встроить типы целой сборки в контекст движка:

			_jintEngine.SetValue(type.FullName,TypeReference.CreateTypeReference(_jintEngine, type));
		

Из движка также можно вытащить все переменные контекста:

			_jintEngine.Global.GetOwnProperties()
		

Конечно, можно было использовать NodeJs, и запускать JS скрипты на нём, но тогда бы мы потеряли функционал расширения скриптов из .Net, и не смогли бы также легко забирать объекты из результата выполнения.

У Jint есть минусы. Хоть библиотека и развивается, она поддерживает не все функции спецификации ECMAScript. Сейчас есть намного более мощные инструменты, библиотеки, но они сложнее в реализации. Нашей основной задачей было сделать быстро и просто.

В реализации Jint тоже были затруднения, например в работе с JObject внутри движка.

Мы не могли просто взять и передать объект JSON (JObject из Newtonsoftjson) в бизнес-логику, у нас постоянно возникали вопросы с доступом к свойствам объектов, в работе с коллекциями и перечислениями. Поскольку дедлайны были близки, мы решили конвертировать объект в JSON строку и распарсить обратно внутри самого движка Jint.

			public static object JObjectToJintObject(JToken source) {
    var content = source.ToString(Formatting.None);
    var script = string.Format("var foo = {0}", content);
    var engine = new Jint.Engine();
    var value = engine.Execute(script).GetValue("foo");
    return value.ToObject();
}
		

Результаты автоматизации процессов банка

Представьте, пользователь создаёт заявку. Она некоторое время лежит и ждёт реакции оператора. Если всё идеально, то оператор примет её в работу и обработает за отведенное время. В любом случае ему нужно понять запрос пользователя, а затем выполнить его не допуская ошибок.

Сейчас система реагирует моментально и обрабатывает заявки одного типа в среднем за одинаковый промежуток времени. В месяц таким образом обрабатывается около 15000 обращений. Теперь операторы занимаются только сложными заявками.

Разные команды банка обращаются к нам для автоматизации процессов, от простых до сложных. Например, система может выполнить заявки по постановке сервера на мониторинг уязвимостей, выполнить копирование базы данных, настроить принтер, переместить имущество в системе между офисами, выдать сотруднику права после выхода из отпуска по уходу за ребёнком.

Система автоматизации оказывает услуги на портале самообслуживания. На текущий момент в портале порядка 300 стандартных запросов, и это количество продолжает расти
JavaScript
C#
Автоматизирование
2861