Трибуна
Ivan
135

Отслеживание изменений данных в ERP

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

В закладки

В прежних версиях Microsoft Dynamics AX с задачей фиксации изменений относительно приемлемо справлялся стандартный Журнал базы данных, хотя его интерфейс никогда не был удобен и понятен конечным пользователям. Но на это есть определенные причины. Его основная задача – скорость регистрации изменений, то есть минимальное влияние на производительность плюс компактность хранения информации. Помимо недружественного интерфейса у стандартного журнала есть еще ряд проблем: отсутствует удобный механизм настройки, поиск, понятное пользователю отображение информации.

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

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

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

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

Традиционное преимущество ERP-систем и Dynamics 365 for Finance and Operations как новой, современной версии – это порядок в данных, хранение единой версии правды для всей организации. Мы понимали, что унаследованный механизм отслеживания изменений требует серьезной переработки.

Наше решение – сделать заново

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

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

  • он не должен влиять на производительность системы;

  • не должен занимать много места в базе данных;

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

Помимо этого, необходимо было добавить недоступные тогда возможности:

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

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

Не должен влиять на производительность системы

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

Первоначальная идея была вроде бы очевидна – в фоновом режиме обрабатываем события изменения данных и превращаем их в записи «Журнала изменений». Звучит просто только на первый взгляд. Помните, что мы должны расшифровать ссылочные поля и найти родительские записи? Но к моменту запуска обработки данные могли серьезно поменяться, родительские и ссылочные записи – удалиться, переименоваться.

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

Не должен занимать много места в базе данных

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

Должен уметь расшифровывать значения в ссылочных полях в понятные пользователю описания

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

Попутно реализовали расшифровку значений складских и финансовых аналитик, что является частой задачей для отслеживания.

Расшифровка ссылочных полей, например, адресов или аналитик

Должен уметь собирать на один экран всю информацию из всех связанных таблиц

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

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

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

Позволять отслеживать события удаления связанных данных

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

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

Возможность поиска, сортировки и фильтрации по таблице, названию поля, описанию записи

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

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

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

Возможность настройки полей описания записей

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

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

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

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

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

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

Был разработан механизм заявок: в каждую форму была добавлена информация о том, какие события сейчас отслеживаются на конкретном поле, и кнопка для создания заявки на отслеживание новых событий. Уведомление по заявке приходит администратору. Так как заявка уже содержит полное описание названия таблицы, поля, форму, ему фактически остается только утвердить ее или отклонить, как и было задумано – в три клика.

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

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

Но заявки пользователей – это не просто средство экономии времени. Это важный инструмент оптимизации настроек: теперь мы точно знаем, кто конкретно запросил данную настройку, и можем управлять настройками журнала.

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

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

Регистрация решения

Так как данное решение оказалось достаточно полезным, мы решили оформить его в виде легко устанавливаемого дополнения системы и зарегистрировать на сайте приложений для продуктов семейства Microsoft Dynamics 365, который к тому времени уже начал свою жизнь и активное развитие. Так наша инициатива доработать продукт превратилась в готовое решение, которым теперь могут пользоваться клиенты и партнеры.

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

Написать
{ "author_name": "Ivan", "author_type": "self", "tags": [], "comments": 0, "likes": 3, "favorites": 8, "is_advertisement": false, "subsite_label": "tribuna", "id": 94885, "is_wide": false, "is_ugc": true, "date": "Thu, 28 Nov 2019 17:23:44 +0300", "is_special": false }
0
{ "id": 94885, "author_id": 403938, "diff_limit": 1000, "urls": {"diff":"\/comments\/94885\/get","add":"\/comments\/94885\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/94885"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 199116, "last_count_and_date": null }
Комментариев нет
Популярные
По порядку
{ "page_type": "article" }

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fizc" } } }, { "id": 4, "label": "Article Branding", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "cfovx", "p2": "glug" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "bscsh", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-223676-0", "render_to": "inpage_VI-223676-0-1104503429", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=bugf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Баннер в ленте на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudx", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byzqf", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvc" } } }, { "id": 19, "disable": true, "label": "Тизер на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "p1": "cbltd", "p2": "gazs" } } }, { "id": 20, "label": "Кнопка в сайдбаре", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "cgxmr", "p2": "gnwc" } } } ] { "page_type": "default" }