Как мы устали терять данные и сделали систему проектирования ручного ввода KDI

от автора

Марк Локшин

руководитель центра компетенций в компании «ДАР» (ГК «КОРУС Консалтинг»)

Анжелика Дубровская

младший аналитик в компании «ДАР» (ГК «КОРУС Консалтинг»)

Кто хоть раз собирал сводный отчет из десятка табличек, тот знает, что самые важные данные чаще всего живут в чьем-то личном Excel-файле, актуальная версия которого лежит в каком-нибудь личном чате. Мы столько раз проходили этот круг, что решили сделать большой шаг в сторону управляемой работы с данными для себя и наших клиентов.

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

Предпосылки создания KDI

Исторически мы в ДАРе работаем с данными: вытаскиваем их из разных систем (ETL/ELT), складываем в хранилища (DWH), строим витрины и отчеты (BI). Сами по себе эти задачи давно закрываются стандартным стеком инструментов, и у каждого заказчика уже есть свой зоопарк систем.

Но чем больше мы делали проекты, тем чаще упирались в одну и ту же ситуацию, которая формально не про «большие данные», а про человеческий фактор и боль. 

👉Первая боль — данные, которых «нигде нет», и их появление связано больше с людьми, чем с ИТ‑системами. Это та самая информация, которая прилетела в телефонных разговорах, лежит в виде фото на смартфоне или живет в виде «священного» Excel‑файла у одного ответственного человека. Формально бизнес‑процесс идет, а в корпоративных системах этих данных как будто не существует. 

👉Вторая боль — зоопарк Excel‑файлов. Excel остается любимым инструментом для всего: от бюджета до учета заявок. Но как только в процессе появляется файл, начинается знакомый многим сюжет — его начинают пересылать в почте и мессенджерах, у каждого сотрудника появляется свой «актуальный» вариант, множатся разные версии шаблонов, и все заканчивается ручным сведением N файлов в один. Облачные таблицы проблему снимают лишь частично: построчное разграничение доступа там сделать непросто, и в итоге кто‑то все равно ночами сводит все руками, пытаясь понять, где «та самая» цифра. 

Логичным ответом на эту боль стало предложение «быстро» собрать небольшую подсистему для операторского ввода данных. Пара форм, простенькие front‑end и back‑end, неделя‑другая разработки — и вот уже есть локальное решение под конкретный процесс. 

И тут появились новые проблемы:

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

Такие подсистемы плохо живут за пределами одного отдела. Сегодня сделали три формы для финслужбы. Завтра придет соседний департамент с похожей задачей, но другими данными. Вместо того, чтобы «просто добавить еще один процесс», мы по сути снова пишем отдельное решение с новыми формами и API. Масштабирование бизнеса превращается в череду однотипных проектных разработок. 

Когда таких «локальных» решений у нас накопилось уже больше трех, стало понятно, что мы каждый раз решаем по сути одну и ту же задачу, только в разных декорациях. Бизнес‑паттерны у заказчиков очень похожи, а вот разработка и сопровождение кастомных подсистем обходятся дорого и плохо масштабируются. В какой‑то момент стало очевидно, что вместо очередной проектной разработки нам нужен отдельный продукт для управляемого ручного ввода данных.

Этот продукт — Кorus Data Input (далее KDI). Он родился как внутренняя инициатива для наших проектов. Но довольно скоро стало понятно, что он закрывает типовую для многих компаний боль. Поэтому сегодня наша команда развивает его как отдельное решение, которое можно внедрять и тиражировать, а не переписывать с нуля под каждого.

Каким мы видели KDI на старте

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

KDI мы спроектировали как no‑code self‑service платформу. Большую часть конфигурации можно собрать через визуальные инструменты и настройки без полноценной разработки с нуля. Под self‑service мы понимали, что с платформой должны уметь работать аналитики и администраторы данных, которые знают предметную область, но не умеют писать сложный код.

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

Отдельное требование — прозрачная и безопасная работа с данными. В архитектуре KDI мы сразу закладывали объектно‑ролевую модель безопасности, встроенные форматно‑логические проверки и аудит действий пользователей. 

В итоге платформа должна была стать управляемой заменой разрозненным Excel‑файлам: с тем же удобством работы с таблицами, но с контролем версий, статусов и ответственности за каждое изменение.

Пример простой формы ввода для строительного магазина

Пример простой формы ввода для строительного магазина

Ключевые отличия от аналогичных инструментов

Отдельное хранение вводимых данных

Возможность самостоятельно создавать формы для ввода данных уже реализована на рынке и не раз. В тех же BI-решениях вроде Форсайт и Visiology уже есть функционал создания пользовательских форм ввода. Но есть одна общая особенность — запись вводимых данных ведется во внутренние «подкапотные» хранилища. Работать с ними вполне удобно, находясь «внутри» системы. А что делать, если эти данные нужны где-то еще? 

Например, в рамках обратного потока данных с внутренними CRM или еще какой-то аналитики «сбоку». К тому же зачастую метаописание формы ввода хранится в перемешку с самими данными. С такими структурами работать сложно.

Мы решили — а почему бы не хранить их отдельно?! Реляционная структура хранения сама по себе может быть инструкцией для получения данных. Какие данные, как и куда их забирать — уже задача другого процесса. В KDI всегда есть своя база для хранения метаописания форм и сопутствующих артефактов. Данные можно писать, как в уже имеющиеся реляционки, так и в реляционный слой DWH, создаваемый в рамках проекта. Для простоты назвали внешние по отношению к системе БД — «Источники».

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

Гибкий конструктор разграничения данных 

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

  • форма ввода — к чему применяется правило;

  • роль/пользователь — к кому применяются правила;

  • where-условия — что применяется.

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

Машины состояний

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

  • Простая машина состояния. Пользователь набирает данные и отправляет их в источник.

  • С верификацией. Пользователь вводит данные и переводит их на проверку условному контроллеру. Контроллер же принимает решение отправить их автору на доработку или протолкнуть дальше в источник.

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

Работа с Excel

Мы хотели увести пользователей от работы с файлами. Но давайте будем честны, что полностью это сделать все равно не получится. Выгрузка данных в xlsl-формате — это стандартный и не очень сложный функционал. Берем структуру таблицы, собираем данные, склеиваем в ячейки и отдаем пользователю. Но! Получив выгрузку в свое распоряжение, у пользователя часто возникает желание ее тут же отредактировать вдоль и поперек. 

Как мы учли это в KDI:

👉Файл, сформированный при выгрузке, является шаблоном и для загрузки. Поэтому добавить новую колонку не выйдет.

👉Есть консистентность. Данные, выгружаемые из формы, содержат ссылки на справочники, представленные в web, как лукапы. 

Что делать в Excel? То же самое!

Вместе с данными основной формы справочники выгружаются в виде скрытых закладок самого Excel-файла. Пользователь при всем желании не сможет выбрать в выпадающем списке то, чего не существует. Решение получилось неординарное, но стабильно работающее и оберегающее данные от того, чего быть не может.

👉Если по каким-то причинам пользователю не нужны проверки, остается возможность выгрузить данные в csv-формате. При обратной загрузке такого файла в систему форма будет валидировать данные и в случае ошибки либо отметит их как невалидные, либо пропустит.

Технологический стек продукта

Технологический стек выбрали стандартный — под компетенции команды, но который полностью закрывает все задачи продукта. 

В итоге получилось:

  • Front-end — Angular + Ant Zorro

  • Back-end — NestJS + TypeORM (служит так же как механизм коннекторов к различным СУБД-источникам)

  • БД метаданных — Postgres

  • SSO — KeyCloak.

Когда стали появляться новые модули, стек стал больше — далее расскажем об этом.

Разрастание функционала

Базовый продуктовый бэклог, помимо описанных выше фич, состоял из стандартных для подобных систем функций:

  • Подключение к сторонним СУБД и ведение справочника подключений.

  • Формы ввода:

    • конструктор моделей данных;

    • «Холст» для составления структуры формы ввода и свойств компонентов, обеспечивающих упрощенный форматно-логический контроль при вводе;

    • настройка визуального представления — шрифты, выравнивание, цвета и пр.

  • Конструктор пользовательского меню. Пользователь создает простое древовидное меню и привязывает к его пунктам нужные формы ввода.

  • Управление ролевым доступом. Получая роли и пользователей из KeyCloak, пользователь системы настраивает кому, какие формы и операции на них доступны.

  • Клиентское представление форм ввода — основное место работы «операторов ввода», сформированное на основании описанных выше артефактов.

  • Уведомления пользователей и управление «подписками» на формы ввода.

Дальше начались внедрения и хотелки!

ИИ-помощник качества ввода

Работая с большими объемами данных (~100 Мб на таблицу), вероятность ручных ошибок ввода стала выше. В целом, на уровне системы нельзя было считать какой-то текст или цифру неверной с точки зрения структуры. Поэтому отвалидировать некорректные данные на 100% не представлялось возможным. В качестве решения проблемы сделали отдельный микросервис (Python + FastAPI), который анализирует массив уже имеющихся данных формы ввода, находит в данных зависимости, в соответствии с настройками в конструкторе формы начинает анализировать на «схожесть» то, что вводит пользователь.

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

Интерфейс настройки корреляции данных

Интерфейс настройки корреляции данных

Мобильный клиент

Часто операторами ввода могут быть сотрудники, в обязанности которых входит занесение информации «с полей». Для этого мы создали отдельное приложение (PWA), которое предназначено только для ввода данных без возможности настройки и управления формами. По сути, это отдельное легкое приложение, которое работает на том же back-end и использует те же данные. Табличные формы развернули в списочный вид с соответствующей настройкой представления в конструкторе. 

Так выглядит мобильный клиент

Так выглядит мобильный клиент

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

Прикрепленные документы

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

Для этого расширили архитектуру системы файлохранилищем S3 Minio и интеграцией с ним. Можно было обойтись и без него и записывать файлы в строковом представлении в текстовые поля БД, но мы решили, что так делать не будем. Поэтому в настройки системы добавили опцию по интеграции с файлохранилищем, а в БД начали записываться ссылки на конкретные загруженные артефакты.

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

Перенос метаданных

Как правило, классическое продуктовое внедрение для заказчика строится на поэтапной инсталляции и отладке в нескольких контурах развертывания — Dev, Test, Preprod, Prod. Может быть и меньше, а может и больше. У каждого контура свои задачи. Но артефакты, которые создают пользователи и которые для нас являются связанными метаданными, должны между ними переноситься. Каждый раз целиком снимать и поднимать дамп БД метаданных — не вариант.

Для кейса миграции метаданных между средами развертывания мы сделали гибкий механизм экспорта и импорта. 

👉Экспорт объекта, например, пункта меню, выгружает в файл все связанные сущности, такие как вложенные пункты меню, зацепленные за них формы ввода и источники данных, на которых экспортируемые формы ввода были основаны.

👉При импорте система ищет совпадения с уже существующими объектами и предлагает выбрать стратегию: обновить найденный объект или создать новый с другим именем.

Кроме того, при создании некоторых объектов может потребоваться ввод «чувствительных» данных. Например, при переносе подключения к источнику данных также переносится пароль от БД — его, как и другие параметры подключения, можно отредактировать вручную. Когда объект обновляется, можно выбрать опцию «использовать» — это означает, что сам объект не будет обновлен, но его связи с другими объектами миграции сохранятся.

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

Ввод по полям

Когда мы переводили ввод данных из Excel в нашу систему, часто встречались таблицы с 20+ колонками, которые оператор заполнял построчно, постоянно прокручивая таблицу вправо. Можно было оставить все как есть, но мы решили сделать иначе. 

По аналогии с мобильным представлением мы добавили альтернативный формат — форму с полями для ввода. Но она не решала проблему: полей все равно было много. 

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

В чем бизнес-ценность KDI

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

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

Как развиваем платформу дальше

Занимаемся «санитайзингом». Одна старая шутка гласит, что единожды написанный код через час уже становится legacy. Вот и мы доросли до момента, когда нужно не только развивать новый функционал KDI, но и уделить время оптимизации алгоритмов, поднятию версий базовых библиотек и накопившемуся техническому долгу.

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

Реализуем свой бэклог идей, которые могут закрыть еще больше типовых проблем. Сейчас в этом списке есть диаграммы Ганта (частичная замена MS Project), сводные таблицы для ввода БЕЗ агрегации, администрирование источников данных (DBeaver для бизнес аналитиков) и многое другое…

ссылка на оригинал статьи https://habr.com/ru/articles/1059868/