У нас огромное металлургическое производство, и, поскольку ИТ в некоторых своих частях до нас дошло сильно позже банков, то разные нужные документы, например, на отпуск или командировку мы делали руками.

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

Что самое парадоксальное, эти бумажные документы сразу сканировались и складывались в СЭД.

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

Автоматизировать это очень хотелось, но задача оказалась трудной. Готовых решений нужной нам сложности нет. Коробок, которые можно аккуратно обработать напильником, тоже не нашлось. Процессы у нас очень хитрозапутанные, и когда мы туда полезли, оказалось, что начинать надо именно с их разбора. Потому что там буквально нагромождение археологических слоёв правил.

Иногда — прямо алмазы.

Мы одними из первых в России сделали реальный автоматизированный КЭДО для крупного производства, но, как говорится, есть нюанс.

И не один.

Задача


Итак, нужен сервис, где можно нажать кнопку на портале и получить, например, отпуск. Или любую другую полезную услугу. Не ехать в отдел кадров, не стоять в очереди, чтобы потом люди не печатали и не сканировали документ с подписью.

В общем, сделать так, чтобы душа радовалась.

Первая идея была очевидной: взять готовое рыночное решение, купить коробку, посадить интегратора и пусть занимается.

У нас был список из 20 кадровых процессов и более-менее хорошо прописанные требования к отпускам. Именно на отпусках мы поняли, насколько сильно металлургическое производство отличается от всего того, что есть на рынке.

Точнее, даже не так.

Поначалу нам казалось, что это приключение на 20 минут — войти и выйти. Ожидания бизнес-заказчика были такими: за год внедряем 20 автоматизированных кадровых процессов, после чего больше никаких очередей на заводе, система работает сама по себе, бумага — в сохранности, нервы — тоже: все счастливы!

Мы на это не купились и попросили нормально оформить требования.

Именно в этом месте, наверное, сюжет пошёл не по пути «как мы героически превозмогали невозможное», а по пути нормальной промышленной разработки. Месяца три мы рисовали архитектуру и собирали команду под то, что должно было получиться по замыслу архитекторов (да, у нас их было целых три). Ещё четыре месяца заняли глубокая аналитика и конкретный выбор решения: тут дело в том, что часть процессов и задач пересекалась у нас с другой командой. Чтобы не изобретать сразу два велосипеда, нужно было задокументироваться, договориться и всё устаканить.

Причем иногда — буквально.

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

Героически превозмогаем


Требования не подошли.

Всё, что мы так кропотливо собирали до этого, оказалось недостаточным. Начиная с первого шага — подачи заявки. Например, у разных бизнес-единиц оказались разные маршруты согласований.

Мы ожидали, что процесс согласования будет везде стандартным: руководитель и HR-партнёр. Но не тут-то было! Например, у некоторых юрлиц не было HR-партнёра, зато где-то появились профсоюзы. И дальше многие процессы обросли нюансами, характерными именно для их юрлиц.

На детальные требования с шагами, статусами и всеми параметрами пути заявки мы смотрели с высоты птичьего полёта.

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

Параллельно начали обсуждать итеративный запуск процессов.

План был такой: сначала — быстрые победы (низковисящие фрукты) а-ля «Создай заявку со сканом, а потом человек за ширмой что-то сделает в кадровой системе, и ты получишь желаемое». Потом — автоматизация описанного: четвертьручник, полуручник — 80 % процессов автоматизировано, 99,9 % — ручник, 99,99 % готовности: ещё год — и почти все процессы работают в автоматическом режиме.

То есть фактически мы сначала сделали тикет-систему. У любого сотрудника в компании был интерфейс для отправки заявки.

Потом эта заявка попадала внутрь системы, где её обрабатывали в большинстве случаев по старым принципам, но с понятными входом и выходом, т. е. руками. Затем мы автоматизировали то, что имело чёткие правила, и шли дальше.

image
Обработка заявок, данные с ландшафта разработки

Пример быстрой победы — внесение персональных данных. Это когда, например, человеку стукает 45 годиков, и он из молодого, подающего надежды специалиста становится опытным сотрудником. При этом ему выдают новый паспорт. Этот паспорт надо внести в учётную систему, в нашем случае — SAP. Никаких согласований, просто взять паспорт и внести.

То есть тикеты могли разбирать и давать им статусы люди (увидел, выполнил и т. п.). Задача была в том, чтобы в финале люди только изредка поглядывали в трекер и подгоняли отбившиеся от стада заявки.

В чём сложности


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

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

Понадобилась система обмена, потому что нужно было всё это не только собрать, но ещё посчитать и упорядочить. Придумали НСИ-систему, которая собирала и агрегировала данные сотрудников по SAP, из других учётных систем. Все данные человека аккумулировались в табличках: благодаря им мы получали срез 15-минутной давности, а не по прошлому отчётному периоду.

Вот верхнеуровневая архитектура решения:

image

Портал ОМК (внутренний сайт сотрудников) создаёт заявку и прикладывает файл, но перед этим жёстко валидирует данные самостоятельно или с помощью НСИ. На портале можно отслеживать статусы, проверять вложения — в общем, по-всякому веселиться с документами. А если вы руководитель или его замещаете — можно повеселиться ещё и с согласованиями.

Чтобы выяснить, кто будет решать судьбу сотрудника, КЭДО ОМК отправляет запросы в НСИ. НСИ занимается агрегацией данных и проведением сложных вычислений. Там есть модуль по сбору маршрутов под каждое подразделение, в каждом юрлице, с учетом всех актуальных отсутствий и всех возможных льгот.

КЭДО ОМК — оркестратор для всего процесса, центральный элемент, где все заявки проходят свой путь от создания до подписания. Здесь управляют согласованием, собирают данные в формате JSON для SAP, отправляют уведомления и предоставляют доступ сотрудникам кадровой службы.

Веб-сервис КЭДО ОМК написан на REST API, у нас есть метод, который по входным параметрам определяет процесс, раскидывая заявки. Сами маршруты настраиваются вручную через консоль администратора. Для каждого процесса — свой шаблонный набор таблиц, в которых всегда есть неизменная часть с общими для всех заявок атрибутами, и уникальная — присущая конкретному процессу.

Получив информацию, система принимает решение, куда двигаться в заявке дальше: человеку на разбор или заводить данные в SAP.

На каждом этапе — свой кусок логики, собрав всё это воедино, получаем цельный процесс.

SAP, например, проводит весь багаж данных, собранных нами, и после этого рождает документ.

Кадровый сотрудник подписывает этот документ квалифицированной электронной подписью. Дальше он передаётся на портал. Юристы сделали так, что если сотрудник увидел печатную форму — значит, автоматически ознакомился.

В общем, во всём этом нам нужно было написать движок универсального обработчика для любых процессов, чтобы можно было упихнуть что угодно. Это формирование таких JSON, где описывается, какие действия от какой системы нам нужны. По одной заявке в одной транзакции может быть до 15 логических блоков. Например, найти отсутствие, проверить, какое оно, удалить отсутствие, добавить ещё одно, добавить проверки. Вот пример переноса отпуска на два месяца вперёд. Для этого мы должны:

image
На всякий случай: здесь ИТ — это инфотип

То есть сначала нужно выполнить операции удаления по старому периоду отпуска и только потом создавать записи по новому. Если по очередному отпуску уже проведена выплата отпускных, а сам его перенос — меньше чем на 30 дней, то удалять запись ИТ «Отсутствия» по уже введённому очередному отпуску с информацией об оплате нельзя. Обязательно нужно именно сдвинуть период у записи, т. е. уже необходима операция изменения. А по новому периоду требуется провести само мероприятие отпуска (выпустить приказы). И в этом случае набор операций уже другой:

image

А ещё возможны блокировки! Потому что если кто-то из кадров работает с этим пользователем, то его поля закрыты для записи, и просто всё вернётся с ошибкой. Такие блокировки очень часто ставятся при закрытии периода, например. Поэтому механизм взаимодействия SAP HCM и КЭДО ОМК базируется на промежуточном буфере. Т. е. заявка от КЭДО, содержащая набор операций с инфотипами, сначала попадает во внутренний буфер SAP HCM. HCM же с некоторой периодичностью (сейчас это 15 минут) пытается выполнить заявки из буфера, причём он будет там висеть, пока не запишется или не выдаст ошибку.

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

КЭДО ОМК решает, что со всем этим делать, выбирает релевантную информацию в таблице и подтягивает её в SAP.

Но и это ещё не всё.
Вот пример обменного сообщения в SAP HCM
{
	"sysid": "BS_EAR",
	"sdate": "20240729",
	"stime": "072106",
	"item": [
		{
			"reqid": "P0204_0004626",
			"reqnm": "1_3",
			"pernr": "0001",
			"infty": "2001",
			"subty": "0400",
			"begda": "20240801",
			"endda": "20240828",
			"opera": "DEL",
			"fields": {
				"item": {
					"id": "SPRPS",
					"value": "X"
				}
			}
		},
		{
			"reqid": "P0204_0004626",
			"reqnm": "1_3",
			"pernr": "0001",
			"infty": "2001",
			"subty": "0402",
			"begda": "20240801",
			"endda": "20240828",
			"opera": "INS",
			"fields": {
				"item": {
					"id": "SPRPS",
					"value": "X"
				}
			}
		},
		{
			"reqid": "P0204_0004626",
			"reqnm": "1_3",
			"pernr": "0001",
			"infty": "0302",
			"begda": "20240801",
			"endda": "20240801",
			"opera": "DEL",
			"fields": {
				"item": [
					{
						"id": "MASSN",
						"value": "M7"
					},
					{
						"id": "MASSG",
						"value": "01"
					}
				]
			}
		},
		{
			"reqid": "P0204_0004626",
			"reqnm": "1_3",
			"pernr": "0001",
			"infty": "0298",
			"begda": "20240801",
			"endda": "20240801",
			"opera": "DEL",
			"fields": {
				"item": [
					{
						"id": "MASSN",
						"value": "M7"
					},
					{
						"id": "MASSG",
						"value": "01"
					}
				]
			}
		},
		{
			"reqid": "P0204_0004626",
			"reqnm": "1_3",
			"pernr": "0001",
			"infty": "0001",
			"subty": "1",				"begda": "20240801",
			"endda": "20240801",
			"opera": "DEL",
			"fields": {
				"item": [
					{
						"id": "MASSN",
						"value": "M7"
					},
					{
						"id": "MASSG",
						"value": "01"
					}
				]
			}
		},
		{
			"reqid": "P0204_0004626",
			"reqnm": "1_3",
			"pernr": "0001",
			"infty": "2001",
			"subty": "0101",
			"begda": "20240801",
			"endda": "20240828",
			"opera": "MOD",
			"fields": {
				"item": [
					{
						"id": "BEGDA_NEW",
						"value": "20240819"
					},
					{
						"id": "ENDDA_NEW",
						"value": "20240915"
					}
				]
			}
		},
		{
			"reqid": "P0204_0004626",
			"reqnm": "2_3",
			"pernr": "0001",
			"infty": "2001",
			"subty": "0400",
			"begda": "20240819",
			"endda": "20240915",
			"opera": "INS",
			"fields": {
				"item": {
					"id": "SPRPS",
					"value": "X"
				}
			}
		},
		{
			"reqid": "P0204_0004626",
			"reqnm": "2_3_MASSN",
			"pernr": "0001",
			"massn": "M7",
			"begda": "20240819",
			"opera": "INS",
			"fields": {
				"item": [
					{
						"id": "P0000-MASSG",
						"value": "01"
					},
					{
						"id": "P0298-ORDNU",
						"value": "#AUTONUM"
					},
					{
						"id": "P0298-ORDDT",
						"value": "#TODAY"
					},
					{
						"id": "P2001-SPRPS",
						"value": "X"
					}
				]
			}
		}
	]
}

Так как внутри тега item может быть дополнительная информация, мы добиваем данными ещё и эти кейсы.

Это сообщение по заявке P0204_0004626 на перенос отпуска состоит в данном случае из восьми операций. Последовательность выполнения задаётся полем REQNM, получаем:
  • 1-й этап (REQNM = «1_3») — работа со старым периодом отпуска.
  • 2-й этап (REQNM = «2_3») — работа с новым периодом отпуска, создание нового планового отпуска.
  • 3-й этап (REQNM = «2_3_MASSN») — работа с новым периодом отпуска, проведение мероприятия «Отпуск».


Вся последовательность операций в заявке в HCM — единая транзакция: или всё, или ничего.

В смысле либо все шаги выполняются успешно, либо не выполняется ничего, если где-то возникла ошибка.

С лимитами же связан ещё один момент в реализации. Период лимитов на отпуск — это рабочий год сотрудника (отсчёт идёт от даты приёма), и некорректно допускать «переиспользование» лимитов по текущему рабочему году. То есть в некоторых случаях нужен дополнительный шаг в НСМ по генерации лимитов на следующий рабочий год.

Вот пример лога заявки с самым большим числом операций — как раз по переносу отпуска:

image
Тут видно, что каждый блок со своим кейсом последовательно отрабатывает со своим кейсом: если хотя бы один из них упадёт — упадёт всё, и заявка уйдёт на разбор

Стек


Мы пишем на C#.

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

Архитектура кода в КЭДО ОМК по луковичной модели — достаточно хорошо об этом написано вот тут.

image

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

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

Но всё вместе оно оптимально использует имеющиеся на старте ресурсы и складывается в единую картину, как пазл.

Как внедряли


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

Как только запустили перенос отпуска — в техреализации больше не было проблем. Все тяжёлые этапы были на стадии универсализации архитектуры. Дальше как горячие пирожки начали выплёвывать процессы.

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

Заказчик доволен, что клиентский сервис для сотрудников — всегда на высшем уровне.

Пострадали, естественно, сроки.

Всплывало много вспомогательных задач. Например, то же подписание: мы пользуемся КриптоПро и их плагином. Фронт КЭДО ОМК — на реакте, бэк — на C#, и нам пришлось написать собственное приложение, которое выводится в трее — просто слушающую службу. Мы посылаем клиентский вызов на эту службу, она подписывает на машине пользователя XML и ставит штамп в PDF. Отдаёт на фронт, мы загружаем через наш бэк в систему.

Первый запуск в бой прошёл на удивление хорошо. Пользователи осмотрелись и начали потихоньку использовать. Меня сильно удивило, что негатива в сторону сервиса почти не было, в основном писали, что удобно, показывали коллегам. Как только «пионеры КЭДО» прошли несколько итераций различных заявок, произошёл бум по использованию сервиса, т. к. сработало сарафанное радио, и всем захотелось попробовать запустить заявку. Вот график перехода людей из физического обслуживания в КЭДО:

image
Небольшая ремарка: это график подписания согласия на КЭДО, реальных заявок меньше в силу того, что у 30 тысяч сотрудников не может одновременно случиться отпуск или надо поменять персональные данные

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

Помощь в написании статьи:

SAP HCM и интеграция c ним — erinio
Портал и общая координация КЭДО — ASKh6

Комментарии (4)


  1. askv
    10.10.2024 08:06

    Ощущение, что IT — постоянное изобретение велосипеда. У нас в банке подобная система начала работать точно больше 10 лет назад.


    1. Yuriy_krd
      10.10.2024 08:06

      Если они сами себя не похвалят - то кто же это сделает? По теме - да, во многих местах это уже давно работает, и почему такая огромная организация это реализовала только сейчас - это вопрос к управленцам, т.к. процесс давно уже откатан на самых разных размерах организаций.


    1. butsefal Автор
      10.10.2024 08:06
      +2

      и, поскольку ИТ в некоторых своих частях до нас дошло сильно позже банков

      В тексте про банки я указал)

      Интересно узнать, как у вас автоматизирован процесс, например, отпуск по уходу за ребенком-инвалидом? Я согласен, что сейчас давно уже внедрены системы КЭДО, и есть коробки, но это все цифровой выход для сотрудника (по крайней мере то, что удалось найти в открытых источниках), но бэк отрабатывает все равно человек. У нас же до подписания человек не участвует.


      1. askv
        10.10.2024 08:06

        как у вас автоматизирован процесс

        Это я сейчас уже не скажу, уже там не работаю. И я смотрел со стороны пользователя, а не IT. Но вроде бы всё электронно обрабатывалось автоматически — сотрудник заполняет заявку (при этом он видит остатки отпусков разных видов, в том числе в разбивке по периодам, за которые этот отпуск возник), дальше она приходит на согласование руководителю (руководителям), после согласования отправляется в кадры на исполнение. Я думаю, в организации на несколько тысяч сотрудников никто руками ничего не делал, там максимум кнопочку надо было нажать. Тем более кадровикам эти отпуска автоматически вставлялись в табель, и т.д. и т.п.

        С отпуском за ребёнком-инвалидом не сталкивался, возможно и такая опция была, а может, что-то руками обрабатывали. Это я не скажу.