Журнал технических изменений
Версия 6.15
Добавление комплексного атрибута в узел классификатора
В индекс узлов классификатора добавлено поле entry_nested_links, которое отвечает за вложенные объекты, связанные с этим узлом.
Новый тип простого атрибута "Диапазон"
BACKEND:
Валидации:
На значение атрибута настроены валидации: проверка консистентности границ - нижняя граница больше верхней (если обе границы заданы), а также проверка флага включения границ в диапазон в случае равенства границ (флаг должен быть true).
Импорт/экспорт XLSX:
Новый тип атрибута доступен для импорта/экспорта XLSX. Пример заполнения значений для обычного диапазона и диапазона с измеряемой единицей.
Диапазон распознается по префиксам (LOWER_BOUND, UPPER_BOUND) для корректного импорта в файле должны присутствовать все 3 колонки. Для передачи значения в запись, одна из границ должна быть заполнена. Флаг включения границ (INCLUSIVE_BOUNDS) может быть пустым, в таком случае проставляется false (границы НЕ включены). При наличии значения только этого флага при импорте будет выведена ошибка о некорректных заголовках. Для диапазона с единицами измерения можно задать ее так же, как и для обычного числового атрибута.
DQ:
Новый тип атрибута не поддерживается существующими функциями правил качества. Диапазон является новым типом входного параметра. Поэтому он доступен для реализации новых Java функций. ValueType для входного параметра диапазона - RANGE.
Из существующих функций исключением является функция "СуществованиеАтрибута", т.к. она принимает любой тип данных на вход.
Индексация:
Атрибуты с типом диапазон имеют уникальную структуру в индексе - они разбиты на 3 поля: attr_name$lower - значение нижней границы диапазона, attr_name$upper - значение верхней границы, attr_name$inclusive - значение флага вхождения границ в диапазон.
Производственный календарь
Формат файла
<?xml version='1.1' encoding='UTF-8'?>
<!--
year - год, для которого создан календарь
s - стандартное начало рабочего дня (формат HH:mm)
e - стандартное завершение рабочего дня (формат HH:mm)
-->
<calendar year="2026" s="09:00" e="18:00" typeId="CALENDAR">
<!--
days - праздники/сокращенные дни/рабочие дни
d - день (формат dd.MM)
t - тип дня: 1 - нерабочий день, 2 - рабочий и сокращенный день (может использоваться для любого дня недели), 3 - рабочий день (суббота/воскресенье)
s - начало рабочего дня (формат HH:mm)
e - конец рабочего дня (формат HH:mm)
Суббота и воскресенье считаются выходными, если для этого дня нет тегов day с t=2 или t=3
-->
<days>
<day d="01.01" t="1"/>
<day d="02.01" t="1"/>
<day d="03.01" t="2" s="09:00" e="17:00"/>
</days>
</calendar>
Функция удаления первых и последних символов
Добавлена новая системная строковая функция УдалитьПервыеИПоследниеСимволы (RemoveLeadingAndTrailingCharacters).
Блокировка записей на создание черновиков
Backend:
Добавлен канал операций DataRecordChannel (manual/import/integration) и использование для lock-type тегов черновиков.
Модифицирован сегмент пайплайна RecordDraftUpsertValidationExecutor для блокировки создания черновиков при достижении maxOneRecordDrafts и для валидации владельца в режиме single-draft.
Добавлена ошибка EX_MAXIMUM_DRAFT_FOR_CURRENT_RECORD и сообщения в локализации.
В XLSX-импорте дополнен отчёт: выводится сводка по блокировкам (external_id (GID)).
В API поиска данных добавлено вычисляемое поле $draft_locked (возвращается в preview только если запрошено в returnFields).
API (поиск данных)
POST /api/v2/search
Чтобы получить признак блокировки, нужно явно запросить вычисляемое поле $draft_locked в returnFields. Поле будет находится в ответе, в preview.
{
payload: {
"org.unidata.mdm.rest.v2.data": {
...,
"returnFields": [
"$etalon_id",
"$created_at",
"$draft_locked"
],
...
},
...,
}
}
Примечания:
$draft_locked вычисляется только если он присутствует в returnFields;
вычисление выполняется только для ETALON/RECORD;
для поиска по черновикам используется DraftHeaderField.FIELD_SUBJECT для получения etalonId.
Канал операции и теги блокировок
Добавлен DataRecordChannel (manual/import/integration) и проброс канала через UpsertRequestContext. На основании канала выставляются lock-type теги у черновиков:
manual
import
integration
Примечания: при загрузки без указания канала на основе загрузки напрямую (UI например) или через import, автоматически проставляется тег manual / import.
Чтобы подменить канал загрузки, при создании черновика можно передать параметр (по дефолту будет manual):
POST /api/v2/draft/upsert
{
...
"parameters": {
...
"DRAFT_LOCK_TYPE": "integration"
}
}
Ссылка на реестр
Backend:
Изменена индексация системного поля $external_keys, после обновления необходимо запустить операцию переиндексации.
Frontend:
@universe-platform/meta
AttributeTypeCategory: Добавлен новый тип атрибута - Ссылка на реестр
AttributesTree, AttributeRow: prop renderLookup переименован в renderEntity
SimpleAttribute, ArrayAttribute: добавлены поля для работы атрибута типы Ссылка на реестр - registerEntityType, registerEntitySearchAttributes, registerEntityDisplayAttributes
AttributeTypesUtil: добавлен метод renderEntityType для вывода подсказки для атрибутов типа "Ссылка на реестр" и "Ссылка на справочник"
MetaTypeGuards: Добавлены тайпгарды для распознавания атрибутов:
Ссылка на реестр;
Перечисление;
Локальное перечисление;
Ссылка на сущность - реестр или справочник.
@universe-platform/record
RecordTypeGuards - Добавлены тайпгарды для распознавания поисковых колонок:
Ссылка на реестр;
Ссылка на сущность - реестр или справочник.
@unidata-mdm/data
ExtendedLookupSearchModal => ExtendedSearchModal
LookupAttributeSearchTermWrapper => EntityAttributeSearchTermWrapper. Поддержан RegisterAttributeST
CellLookup => CellEntity. RegisterSearchColumn
LookupSelect => EntityRecordSelect. Поддержан выбор из реестра
LookupArrayAttributeField => EntityArrayAttributeField. Поддержан namespace=register
LookupAttributeFieldController => EntityAttributeFieldController. Поддержан namespace=register
LookupWithLink => EntityWithLink. Поддержан namespace=registe
SimpleLookupAttributeStore => SimpleEntityAttributeStore. Поддержан namespace=register
LookupAttributeField => EntityAttributeField. Поддержан namespace=register
LookupAttributeStore => EntityAttributeStore. Поддержаны props.relatedMeta: Entity
LookupEntityAttributePreview => ArrayEntityAttributePreview. Поддержан namespace=register
EditableFieldLookupWrapper => EditableFieldEntityWrapper. Поддержан namespace=register
LookupAttributeST: добавлены свойства entityName и namespace для унификации с RegisterAttributeST
FormatUtil: Добавлен метод форматирования серверного значения externalId
RelatedDataRecordStore: поддержка проброса OptionBuilder
DataRecordsUtils: loadLookupSimpleAttributeDisplayName переименована в loadEntitySimpleAttributeDisplayName и адаптирована для загрузки отображаемых имен атрибутов - ссылок на сущность.
DataTypeGuards: Добавлены тайпгарды для проверки поисковых критериев по атрибутам - ссылкам на сущности
LookupAttributeSearchTermWrapperComponentType,
LookupAttributeSTFieldRenderer,
LookupAttributeSTProps,
LookupAttributeSTRecordsStoreBuilder,
LookupAttributeSTRendererProps,
LookupRecordSelectComponentType,
LookupSelectProps: объявлены deprecated
@unidata-mdm/meta-data
AttributeTypePropertyPanel,
AttributeSettingsPanel,
MetaModelCard,
RelationTab,
AttributesTab: prop.renderLookup переименован в renderEntity
AttributesTab: prop.renderLookupType переименована в renderEntityType
LookupAttributeDefaultValue => EntityAttributeDefaultValue. Поддержан namespace=register
LookupPropertyPanel => EntityPropertyPanel. Поддержан namespace=register
EntityAttributeDefaultValueController: контроллер адаптирован для EntityAttributeDefaultValue
AttributeTypePropertyStore: Поддержаны настройки атрибутов типа Ссылка на реестр
Изменение отображаемого наименования и статуса виджетов
Backend:
Добавлен новый API для работы с админскими и пользовательскими настройками виджетов:
v2/core/widgets.Созданы 2 новые таблицы в БД:
postgres.org_unidata_mdm_core.widget_settingиpostgres.org_unidata_mdm_core.widget_layout.Настройки расположения виджетов мигрированы из таблицы
postgres.org_unidata_mdm_core.s_custom_storageв новую таблицуpostgres.org_unidata_mdm_core.widget_layout.Добавлена точка расширения BE для подгрузки кастомных виджетов в систему.
Описание API:
Для обеспечения возможности настройки имени, описания и статуса виджетов был реализован новый API v2/core/widgets. Данный API состоит из двух частей - админских настроек виджетов (v2/core/widgets/settings) и пользовательской раскладки виджетов на главной странице (v2/core/widgets/layout).
Endpoint: GET v2/core/widgets/settings Описание: Предназначен для получения всех зарегистрированных виджетов с их настройками.
code - системный идентификатор виджета.
defaultName - имя виджета по умолчанию.
name - заданное админом имя виджета.
description - заданное админом описание виджета.
isSystem - флаг, показывающий, является ли виджет системным, или был загружен как кастомизация.
isActive - статус видимости виджета (также регулируется админом).
Если дефолтные имена виджетов, описание и статусы не изменялись, то будут заполнены только код виджета и его имя по умолчанию.
Запрос: Тело и параметры отсутствуют.
Ответ
"widgets": [
{
"code": "OBJECT_USAGE_METRIC_WIDGET",
"defaultName": "Статистика использования объектов",
"name": "",
"description": null,
"isSystem": true,
"isActive": true
},
{
"code": "SEARCH_WIDGET",
"defaultName": "Сквозной поиск",
"name": null,
"description": null,
"isSystem": true,
"isActive": false
}
]
Endpoint: PUT v2/core/widgets/settings/{code} Описание: Предназначен для обновления имени виджета, задания описания, или статуса активности. Эндпоинт доступен пользователям с правом "Управление настройками виджетов".
Запрос: параметр запроса code - идентификатор виджета
Тело запроса
{
"name": "Виджет для отображения статистики использования объектов",
"description": null,
"isActive": false
}
Обновленный виджет
{
"code": "OBJECT_USAGE_METRIC_WIDGET",
"defaultName": "Статистика использования объектов",
"name": "Виджет для отображения статистики использования объектов",
"description": null,
"isSystem": true,
"isActive":false
}
Endpoint: GET v2/core/widgets/layout Описание: Предназначен для получения настроек раскладки виджетов для текущего пользователя. Возвращает информацию о раскладке только для тех виджетов, которые доступны для размещения данному пользователю - он имеет права на них, и данный виджет активен.
code - системный идентификатор виджета
isHidden - флаг, показывающий, выбран ли пользователем данный виджет для размещения
layout - JSON-объект с фронтенд-специфичными данными о положении виджета на главной странице, может быть любой структуры
Для виджетов, у которых isHidden=true, layout может быть не заполнен.
Запрос: Тело и параметры отсутствуют.
Ответ
"widgets": [
{
"code": "CUSTOM_SUPER_WIDGET",
"isHidden": false,
"layout": {
"h": 5,
"i": "CUSTOM_SUPER_WIDGET",
"w": 5,
"x": 5,
"y": 5,
"moved": false,
"static": false
}
},
{
"code": "DATA_QUALITY_WITH_ERRORS_WIDGET",
"isHidden": true,
"layout": null
},
]
}
Endpoint: POST v2/core/widgets/layout Описание: Предназначен для перезаписывания настроек раскладки виджетов для определенного пользователя. Сохранение раскладки/видимости виджетов, которые неактивны, либо на которые у пользователя отсутствуют права, будет пропущено.
Запрос
{
"widgets": [
{
"code": "CUSTOM_SUPER_WIDGET",
"isHidden": false,
"layout": {
"w": 2,
"h": 2,
"x": 0,
"y": 0
}
},
{
"code": "DRAFT_LIST_WIDGET",
"isHidden": true,
"layout": null
}
]
}
Ответ
{
"widgets": [
{
"code": "CUSTOM_SUPER_WIDGET",
"isHidden": false,
"layout": {
"w": 2,
"h": 2,
"x": 0,
"y": 0
}
},
{
"code": "DRAFT_LIST_WIDGET",
"isHidden": true,
"layout": null
}
]
}
Миграция
Для переноса старых сохраненных пользователями раскладок виджетов добавлена миграция, переносящая старые настройки в новое хранилище. Соответственно для пользователя расположение его виджетов на главной странице должно сохраниться.
Возможность добавления описания версии информационного объекта
Backend
Добавлена возможность просматривать и редактировать новое поле описания версии
Добавлено GetDescriptionResultRO:
org.unidata.mdm.rest.v2.data.ro.records.history.GetDescriptionResultRO#description.Добавлено UpdateDescriptionRequestRO:
org.unidata.mdm.rest.v2.data.ro.records.history.UpdateDescriptionRequestRO#description.Добавлено новая настройка доступа к редактированию поля описания версии.
При импорте добавлена возможность проставлять всем записям одинаковый комментарий.
При интеграции, описание версии проставляется автоматически на основе channel=integration.
Настроена миграция БД для добавления новой колонки данных
descriptionвrecord_vistoryс типом text.
Добавлены новые API-ендпоинты:
Получение описания версии:
GET /v2/data/records-history/description/{originId}/{revision}
Ответ
{
"details": {
"info": [],
"warning": [],
"error": []
},
"description": null
}
При невозможности найти по originId + revision – будет выдана ошибка EX_DATA_RECORD_HISTORY_REVISION_NOT_FOUND.
Обновление описания версии:
PUT /v2/data/records-history/description/{originId}/{revision}
Тело запроса
{
"description": "TEST"
}
Проставление описания через import:
POST {{address}}/v2/core/import-data
{
"org.unidata.mdm.data.importRelationsEnabled":false,
"importClassifications":false,
"multidraft":false,
"operationId":null,
"draftId":null,
"processName":null,
"approvalType":null,
"org.unidata.mdm.data.description": "TEST_IMPORT" // Меняется описание версии для всех записей в импорте
}
Проверка изменение описания при интеграции. Можно создать черновик, у которого будет typeLock:integration в тегах. То есть, DataRecordChannel проставляется пользователем. Таким образом на основе канала будет автоматически при публикации записи проставлено описание версии:
POST {{address}}/v2/draft/upsert
Тело запроса
{
"type": "record",
"subjectId": "",
"description": "Версия интеграция", // Это не описание версии, а описание драфта, который отображается при выборе черновика
"tags": [
"entity-name:typeLockTest", // Свой реестр
"namespace:register"
],
"parameters": {
"entity-name": "typeLockTest", // Свой реестр
"DRAFT_LOCK_TYPE": "integration" // Вот это поле меняем manual/import/integration. По дефолту/некорректном значении будет manual
}
}
Затем нужно зайти на черновик, заполнить нужные значения и опубликовать их.
Настройка ограничения импорта записей
Backend:
Добавлена группа параметров "Настройки импорта данных".
Добавлен параметр "Допустимое количество записей для одной операции импорта"" (org.unidata.mdm.data.import.max.records.count).
Параметр "Размер блока импорта данных"" (org.unidata.mdm.data.internal.import.data.block.size) перенесен в новую группу.
Добавлен эндпоинт "Проверка импортируемых данных"" (POST universe-backend/api/v2/core/import-data/check).
Реализован функционал ограничения импортируемых записей.
Эндпоинт "Проверка импортируемых данных" (POST universe-backend/api/v2/core/import-data/check), вычисляет сколько записей в прикрепленном файле и сколько будет импортировано с учетом ограничения.
Запрос (Content-Type: multipart/form-data):
Параметр |
Описание |
Тип |
file |
File |
Файл импорта |
format |
String |
Формат файла (пока что только XLSX) |
target |
String |
ID обработчика импорта (пока что только records-and-relations) |
entityName |
String |
Имя сущности |
Ответ
{
"details": {
"info": [],
"warning": [],
"error": []
},
"payload": {
"records-import-check-fragment-v2": { /* Фрагмент проверки импортируемых записей */
"totalRecords": 50000, /* Всего записей в файле */
"maxRecords": 10000, /* Максимально допустимое количество записей для одной операции импорта */
"recordsToImport": 10000 /* Количество записей, которые будут импортированы */
}
},
"success": false /* Индикатор успешности проверок (true, если ограничение не достигнуто, иначе false) */
}
Возможность удаления лишних пробелов
Добавлена новая системная cleanse-функция RemoveExtraWhitespaces.
Срок хранения черновика
Frontend:
Добавлены новые расширенные параметры timeToNotify, timeToRun для модели данных реестров и справочников.
Поля поддерживают формат: d h m.
Backend:
В модели данных (lookup/register) добавлены поля timeToNotify, timeToRun, timeToNotifyNew и timeToRunNew. Они доступны в REST v2 модели данных и в REST v1 flyweight lookups.
Добавлен email-шаблон email_draft_removal_notification.vm (ru/en).
Добавлены две операции: одна для нотификации об истечении срока, вторая - для удаления записей.
Механизм системных кнопок
Backend:
Созданы новые модули com.universe.mdm.buttons и com.universe.mdm.rest.v1.buttons
Созданы GET, POST, PUT и DELETE методы API (api/v1/buttons)
Создана новая схема в БД com_universe_mdm_buttons с таблицей buttons
Frontend:
Добавлена страница редактора системных кнопок.
Добавлено отображение системных кнопок в шапке приложения.
На замену UE RightHeaderItem добавлена точка расширения HederItem с возможностью настройки позиции.
В RouterStore добавлен метод нахождения роута по pathname.
В Field.Select добавлена поддержка генерик-типа значения.
Описание API
Был поддержан новый API: api/v1/buttons:
Метод: Post
Endpoint: api/v1/buttons
Описание:
Метод для создания системной кнопки.
Обязательные параметры - name, displayName, type, enabled, configuration.
В качестве типа в поле type должен находиться один из четырех возможных типов кнопки:
MODULE - ссылка на модуль системы;
NETWORK_FOLDER - ссылка на сетевую папку;
ENTITY_RECORD - ссылка на запись в системе;
EXTERNAL_URL - внешняя ссылка.
В поле roles содержится массив системных имен ролей, для которых может быть показана данная кнопка на UI. Поле configuration - является подструктурой JSON произвольного состава. Единственное требование - JSON должен быть корректен. Вызов эндпоинта доступен при наличие у пользователя права на "Администрирование системных кнопок".
Параметры/Тело запроса
POST api/v1/buttons
{
"button": {
"name": "myButton1",
"displayName": "Моя кнопка",
"description": "Кнопка, содержащая ссылку на внешний ресурс",
"type": "EXTERNAL_URL",
"roles": [
"ADMIN", "MANAGER"
],
"enabled": true,
"configuration": {
"link": "https://stackoverflow.com/questions/5717093"
}
}
}
Параметры/Тело ответа
{
"button": {
"id": 1,
"name": "myButton1",
"displayName": "Моя кнопка",
"description": "Кнопка, содержащая ссылку на внешний ресурс",
"type": "EXTERNAL_URL",
"roles": [
"ADMIN", "MANAGER"
],
"enabled": true,
"configuration": {
"link": "https://stackoverflow.com/questions/5717093"
}
}
}
Метод: PUT
Endpoint: api/v1/buttons/{id}
Описание: Метод для редактирования системной кнопки. Обязательный параметр запроса - id кнопки. Тело запроса аналогично POST методу. Вызов эндпоинта доступен при наличие у пользователя права на "Администрирование системных кнопок".
Параметры/Тело запроса
PUT api/v1/buttons/1
{
"button": {
"name": "myButton1",
"displayName": "Моя измененная кнопка",
"description": "Кнопка, содержащая ссылку на внешний ресурс",
"type": "EXTERNAL_URL",
"roles": [
"ADMIN", "MANAGER"
],
"enabled": true,
"configuration": {
"link": "https://stackoverflow.com/questions/5717093"
}
}
}
Параметры/Тело ответа
{
"button": {
"id": 1,
"name": "myButton1",
"displayName": "Моя измененная кнопка",
"description": "Кнопка, содержащая ссылку на внешний ресурс",
"type": "EXTERNAL_URL",
"roles": [
"ADMIN", "MANAGER"
],
"enabled": true,
"configuration": {
"link": "https://stackoverflow.com/questions/5717093"
}
}
}
Метод: DELETE
Endpoint: api/v1/buttons/{id}
Описание: Метод для удаления системной кнопки. Обязательный параметр - id кнопки. Вызов эндпоинта доступен при наличие у пользователя права на "Администрирование системных кнопок".
Параметры/Тело запроса
DELETE api/v1/buttons/1
Параметры/Тело ответа
"success": true
Метод: GET
Endpoint: api/v1/buttons
Описание: Метод для получения всех системных кнопок. Кнопки упорядочены по времени создания (от самой новой к самой старой).
Параметры/Тело запроса
GET api/v1/buttons
Параметры/Тело ответа
"buttons": [
{
"id": 2,
"name": "myButton2",
"displayName": "Моя любимая кнопка",
"description": "Кнопка, содержащая ссылку на модуль системы",
"type": "MODULE",
"roles": [
"ADMIN"
],
"enabled": true,
"configuration": {
"link": "http://localhost:8082/#/metamodel"
}
}
]
Метод: GET
Endpoint: api/v1/buttons/filtered-by-user
Описание: Метод для получения системных кнопок, которые должны быть доступны для показа текущему пользователю на основе его ролей. Кнопка будет возвращена, если хотя бы одна роль пользователя содержится в поле roles у данной кнопки.
Параметры/Тело запроса
GET api/v1/buttons/filtered-by-user
Параметры/Тело ответа
Идентично GET запросу для получения всех кнопок.
Фильтрация назначенных БП при импорте посредством мультичерновика
Добавлен контекст ImportWizardParametersFormContext для передачи importStore в дочернии элементы ParametersForm.
Поиск узла классификатора и данных в иерархическом справочнике
Backend:
Для поиска узлов добавлен новый REST поинт POST v1/classifiers/model/nodes/search
В formGroup ожидается, что для каждого критерия поиска будет приходить своя childGroup. Уже внутри каждой childGroup будут находиться formFields по каждому критерию. Эти поля будут соединяться с помощью указанного groupType внутри группы.
В поле name для полей при поиске по отображаемому имени будет передаваться entry_display_name, при поиске по описанию - entry_description, по атрибутам - entry_attributes.entry_attribute_display_name.
Пример запроса
{
"formGroup": {
"formFields": [],
"childGroups": [
{ // первая childGroup
"formFields": [
{
"type": "Date",
"name": "string",
"value": {},
"values": [
{}
],
"range": [
{}
],
"inverted": true,
"like": true,
"startWith": true,
"fuzzy": true,
"morphological": true,
"searchType": "DEFAULT"
}
],
"childGroups": [],
"groupType": "OR" // по какому условию будут соединяться formFields для этой группы
}
],
"groupType": "OR"
},
"text": "string", // Текст поиска
"classifier": "string", // Для какого классификатора происходит поиск
"version": "string", // Для какой версии классификатора происходит поиск
"withAttributes": true, // Загружать ли атрибуты для узлов
"parentDraftId": 0, // Номер черновика
"parent": "string" // Для какого родителя происходит поиск
}
Пример ответа
{
"nodes": [
{
"name": "string",// Логическое имя узла
"displayName": "string",// Отображаемое имя узла
"description": "string",// Описание узла
"parentName": "string",// Родитель узла
"classifierName": "string",// Имя классификатора
"classifierVersion": "string",// Имя версии классификатора
"draftId": 0,
"path": [// Путь до корня
"string"
],
"pathDisplayNames": [// Путь до корня по отображаемым именам
"string"
],
"hasData": true,
"customProperties": [
{
"name": "string",
"value": "string"
}
],
"simpleAttributes": [...],
"inheritedSimpleAttributes": [...],
"arrayAttributes": [...],
"inheritedArrayAttributes": [...],
"revision": 0,
"modified": true,
"leaf": true,
"inheritanceOverrides": [
"string"
],
"displayOverrides": [
"string"
],
"defaultsOverrides": {
"additionalProp1": [
"string"
],
"additionalProp2": [
"string"
],
"additionalProp3": [
"string"
]
}
}
]
}
При поиске данных иерархического справочника в search теперь также приходит поле path со списком всех родителей до корневого узла.
Поинт GET v1/classifiers/model/search/{classifier}/version помечен deprecated. Вместо него рекомендуется использовать POST v1/classifiers/model/nodes/search
Атрибуты узлов классификатора теперь индексируются в индексе классификаторов как nested поле
Маппинг атрибутов
"entry_attributes": {
"type": "nested",
"properties": {
"entry_attribute_display_name": {
"type": "keyword"
},
"entry_attribute_name": {
"type": "keyword"
}
}
}
Выбора базового/основного классификатора
Backend:
Был добавлен новый поинт на переключение флага основной для классификаторов: POST v1/classifiers/model/classifier/default
Пример запроса
{
"nameSpace": "string", // namespace сущности
"entityName": "string", // тип сущности
"classifier": "string", // классификатор, который нужно сделать основным для данной сущности
}
Пример ответа
{
"success": true
}
Доработка экрана операций
Frontend:
Доработан компонент ItemsList для работы отдельно от Editor.Items;
SelectPaginated - переработан метод кастомного рендера отображаемого значения;
JobDefinitionStore теперь используется AbstractEntityStore вместо устаревшего AbstractCrudStore;
Добавлена новая операция ReadJobDefinitionByIds для получения операций по их ID.
Backend:
Изменен запрос POST /v2/core/jobs/definitions/search.
В тело запроса добавлено поле "displayName" (раньше его не было). Данное поле используется для регистронезависимого поиска имен операций содержащих указанный текст. Игнорируется если указаны точные имена в поле "definitionNames".
Поле "name" объявлено deprecated, вместо него стоит указывать список искомых полных имен операций в поле "definitionNames". Имена в списке должны точно совпадать с именами операций (для неточного совпадения используется поле "displayName"). Если данное поле заполнено, то поиск вернет те операции, имя которых точно совпадает с указанными, поле "displayName" будет проигнорировано.
Поле "jobName" объявлено deprecated, вместо него стоит указывать список искомых типов операций в поле "jobNames"
Тело запроса с использованием поиска по имени
{
"displayName": "def", // Часть имени искомых операций
// Типы искомых операций
"jobNames": [
"reindexDataJob",
"statisticJob"
],
"activeOnly": false, // Искать только активные операции
"inactiveOnly": false, // Искать только не активные операции (игнорируется при activeOnly: true)
"lastExecutionStatus": "COMPLETED", // Искать только операции, последний запуск которых был успешным
"tags": [],
"createdBy": "admin", // Искать только операции созданные пользователем admin
"count": 20, // Вернуть максимум 20 операций
"start": 0, // Начинать отсчет возвращаемых операций с 0-й
"sortField": "ID", // Отсортировать операции в результате по ID
"sortOrder": "ASC" // Порядок сортировки по возрастанию
}
Тело запроса с указанием конкретных имен
{
// Полные имена операций
"definitionNames": [
"fullDefinitionName",
"myFavoriteOp"
],
// Типы искомых операций
"jobNames": [
"reindexDataJob",
"statisticJob"
],
"activeOnly": false, // Искать только активные операции
"inactiveOnly": false, // Искать только не активные операции (игнорируется при activeOnly: true)
"lastExecutionStatus": null, // Искать операции не учитывая статус их последнего выполнения
"tags": [],
"createdBy": null, // Искать операции не учитывая создателя операции
"count": 20, // Вернуть максимум 20 операций
"start": 0, // Начинать отсчет возвращаемых операций с 0-й
"sortField": "ID", // Отсортировать операции в результате по ID
"sortOrder": "ASC" // Порядок сортировки по возрастанию
}
В результат запроса было добавлено поле "totalFilteredCount" хранящие в себе количество записей, удовлетворяющих поисковым фильтрам, без учета "count" и "start".
В результате запроса была изменена логика подсчета "totalCount". Теперь данное поле хранит количество записей доступных данному пользователю с учетом его прав на операции.
Результат запроса
{
"definitions": [
// Список найденных операций
],
"totalFilteredCount": 35, // Количество операций найденных с учетом фильтра
"totalCount": 60 // Общее количество операций доступных данному пользователю
}
Создан новый endpoint получения операций по их ID: POST /v2/core/jobs/definitions/by-ids
Endpoint принимает список id операций.
Результат запроса
{
"jobDefinitionsIds": [
1, 6 // id операций
]
}
Если список пуст, то вернет все операции, на которые у пользователя есть права.
Результат запроса
{
"definitions": [
// Список найденных операций
],
"totalFilteredCount": 35, // Количество операций найденных с учетом фильтра
"totalCount": 60 // Общее количество операций доступных данному пользователю
}
Технические задачи БП для проверки правил качества
В систему добавлена поддержка сохранения результатов проверки качества данных и возможности отображать их в пользовательских задачах.
При обновлении системы дополнительные действия не требуются — существующие процессы продолжают работать без изменений. Новые процессы могут использовать автоматическую проверку данных.
Если требуется использовать обновленный подход в уже существующих BPMN-схемах, достаточно добавить шаг проверки перед нужными пользовательскими задачами и назначить слушателя на завершение пользовательской задачи.
SSO: OAuth2. Признак "skip update" для авторизации внешнего пользователя
В SDK backend в класс com.universe.mdm.rest.v1.oauth2.type.OAuth2UserInfo добавлено boolean поле updateUser.
Ограничение по количеству сравниваемых записей
Backend:
Добавлен системный параметр org.unidata.mdm.system.maxCompareRecordsCount.
Frontend:
В PaginationStore добавлена возможность устанавливать размер страницы без принудительной перезагрузки данных.
На странице поиска и в карточке записи добавлен лимит на максимальное количество записей, доступных для сравнения.
В таблице сравнения записей была добавлена пагинация.
Возможность переключения оператора ИЛИ/И в поисковых критериях атрибутов
В абстрактный класс AbstractAttributeST, вынесенный в SDK, добавлен параметр canBeConvertedToSupplementary, определяющий, может ли поисковый терм атрибута иметь supplementaryGroup и, следовательно, иметь возможность смены оператора с ИЛИ на И.
Поиск по атрибутам в модуле "Поиск по данным" с учетом спецсимволов
Backend:
В SearchFormFieldRO был добавлен новый searchType - тип поиска, STRICT_LIKE. При указании этого типа в FormField, поиск будет происходить с учетом пробелом и не разделяться на несколько wildcard.
Возможность группировать несколько избранных записей в одну "папку"
Backend:
Были добавлены новые REST запросы в модуль v2/data:
GET /v2/data/favorite-folders |
Метод для получения всех пользовательских избранных папок со списком записей в них, сгруппированных по имени сущности |
|
GET /v2/data/favorite-folders/{folderId} |
Метод для получения данных об определенной папке пользователя по ее идентификатору, если она существует для этого пользователя, со списком записей в ней, сгруппированных по имени сущности |
|
POST /v2/data/favorite-folders |
Метод для создания новой папки. Создается папка с переданным именем и описанием, системой присваивается новый идентификатор для нее |
{ "folderName": "string", "description": "string" } |
PUT /v2/data/favorite-folders/{folderId} |
Метод для обновления имени и описания существующей папки для текущего пользователя. Проверяется существование этой папки этого пользователя по идентификатору. Также в ответе возвращаются записи в этой папке, если они есть. |
{ "folderName": "string", "description": "string" } |
DELETE /v2/data/favorite-folders/{folderId} |
Метод для удаления избранной папки текущего пользователя. Папка удаляется по идентификатору, к записям применяется переданное в параметре действия. Если действие не передано - применяется "EXCLUDE" |
Для запроса применимы query параметры: etalonsAction - действие, которое применить к записям внутри этой папки. Возможны следующие варианты: EXCLUDE - записи перемещаются в "системную" папку, "MOVE" - перемещение в папку, заданную в следующем параметре, "DELETE" - удаление записей из избранного. Регистр не имеет значения (EXCLUDE = exclude), при неизвестном/непереданном параметре применяется EXCLUDE. destination - id папки, в которую необходимо переместить записи при выбранном действии MOVE. |
POST /v2/data/favorite-etalons/move |
Метод для перемещения записей в папки. В теле, в "etalons" указываются эталоны записей, которые необходимо переместить. "folderId" - идентификатор папки, в которую будут перемещены записи, null для перемещения в системную. Перед перемещением производится проверка на существование папки для текущего пользователя. |
{ "etalons": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ], "folderId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" } |
Были изменены REST запросы favorite-etalons:
GET /v2/data/favorite-etalons и GET /v2/data/favorite-etalons/etalons-map |
По умолчанию, возвращается записи только из системной папки (старое поведение). Добавлен query параметр folderId - идентификатор папки, при наличии параметра, возвращает список записей в конкретной папке, при ее существовании. entityName так же учитывается. Так же добавлен query параметр fetchAll - флаг для загрузки эталонов из всех папок. Значение true вернет избранные эталоны пользователя из всех папок, включая системную (по умолчанию флаг в false). Совместим с параметром entityName, игнорируется при наличии параметра folderId (загрузка будет по folderId). |
POST /v2/data/favorite-etalons |
В тело запроса добавлено поле "folderId" - идентификатор папки. При null записи уходят в "системную" папку. Проверяется наличие папки для текущего пользователя. |
DELETE /v2/data/favorite-etalons/entity/{entityName} |
Добавлен query параметр folderId - идентификатор папки. При указании идентификатора, запросы будут применены к записям внутри папки. Отсутствующий параметр - работа с "системной" папкой |
При создании/изменении существующей папки, валидируются имя и описание папки на кол-во символов, максимально допустимое - 255. Так же недопустимо пустое имя.
При любой работе с папкой по ее идентификатору осуществляется проверка на ее наличие для текущего пользователя, отправившего запрос, связанный с этой папкой.
В БД добавлена новая таблица favorite_folder, а в таблицу favorite_etalons добавлено новое поле folder_id, связывающее запись с папкой.
Были добавлены новые ресурсы безопасности для доступа к элементам виджета избранных записей. Появилась категория "Избранное" в разделе "Менеджмент записей". Новые права называются "Управление избранными записями" и "Управление избранными папками".
Для POST, DELETE запросов /v2/data/favorite-etalons необходимы права "Управление избранными записями". Для POST, PUT, DELETE запросов /v2/data/favorite-folders/ необходимы права "Управление избранными папками".
Проверка работоспособности платформы
Добавлен метод /health в com.universe.mdm.rest.v1.hpe.core
Добавлен метод /ping в com.universe.mdm.rest.v1.hpe.core
Добавлен модуль com.universe.mdm.rest.v1.hpe.core
Настройка ограничения количества записей, отмеченных как «Избранная»
@universe-ee/data:
В UE FavoriteWidget добавлено отображение общего и максимального числа избранных записей.
В FavoriteManager измененен текст сообщения о превышении лимита.
Возможность установки перечня и/или диапазона допустимых значений для атрибутов
Модель данных
Для поддержания механизма одновременной валидации атрибутов на FE и BE, в модели данных для простых и кодовых атрибутов было поддержано новое поле hints. Данное поле представляет собой массив объектов-ограничителей значений атрибута. Ограничитель (hint) в свою очередь состоит из 2 полей - type, и params. Поддержанные на текущий момент типы ограничителей - RANGE (диапазон) и MASK (маска). Набор параметров params у каждого типа свой. Пример json конфигурации ограничителей каждого типа приведен ниже.
RANGE
"hints": [
{
"type": "RANGE",
"params": {
"min": 1,
"max": 115
}
}
],
MASK
"hints": [
{
"type": "MASK",
"params": {
"mask": "+7-(999)-999-99-99"
}
}
],
Ограничитель-диапазон может быть назначен на простом или кодовом атрибуте типа число, целое число, дата, время, дата/время.
Ограничитель-маска может быть назначен на простом или кодовом атрибуте типа строка.
Попытка назначения ограничителя на атрибут неподходящего типа данных приведет к ошибке валидации модели.
Ограничители поддержаны для атрибутов реестров, справочников, связей и узлов классификатора.
Проверка значений атрибутов, на которых назначены ограничители, производятся на BE при любом способе вставки записей.
Frontend
В компоненты Field и FieldLabel добавлена возможность кастомизировать цвет иконки подсказки.
В модели SimpleAttribute, CodeAttribute и AliasCodeAttribute добавлено поле hint, содержащее набор ограничителей данного атрибута.
Backend
В тело запроса POST /v2/data/model/upsert и всех других методов, содержащих в себе read-object SimpleAttributeDefRO добавлено необязательное поле hints.
В процесс вставки записей добавлены валидации атрибутов на соответствие ограничителям.
Уведомление пользователей о завершении / отклонении задачи
Backend
Часть
TaskAssignmentSubscriptionsNotifierвынесена в абстрактный классAbstractSubscriptionsNotifier.TaskAssignmentSubscriptionsResolverпеределан в общийTaskSubscriptionsResolver. Триггеры для которых происходит resolve теперь передаются внутри контекстаTaskSubscriptionsResolveContext. Если триггеры не указаны, то resolve ищет все триггеры.Созданы
TaskCompletionSubscriptionsNotifierиспользующий триггерWorkflowNotificationTriggers#TASK_COMPLETION. Для триггера созданы шаблоны нотификацииTaskCompletionPanelTemplateи отправки EmailTaskCompletionEmailTemplate.
Массовое назначение прав доступа в разделе "Данные"
Backend
Создан endpoint
RoleRestService#updateByFilterустанавливающий указанные права всем ресурсам удовлетворяющим фильтру.В ответ на запрос
v2/core/security/secured-resources/resources-paginated/добавлено полеchildrenFilteredCount, содержащие количество отфильтрованных потомков корня, без учета offset и count.В запрос
v2/core/security/secured-resources/resources-paginated/добавлен параметрresultDepth. Данный параметр определяет, на какую глубину отображать результат поиска. Не может быть меньше depth.
url
PUT /api/v2/core/security/role/{roleName}/{categoryId}/rights
В теле запроса принимается список прав, фильтр поиска прав и флаг снятия прав с потомков.
Тело запроса
{
"rightsQuery": {
"query": { // Поисковый запрос
"searchText": "unidata",
"offset": 0,
"count": 100,
"depth": 5,
"maxNestedChildren": 100
},
"rights": [ // Применяемые права
"READ",
"CREATE",
"UPDATE"
]
},
"clearChildrenRights": true // флаг снятия прав с потомков
}
Права будут применены к найденному ресурсу и ко всем его родителям в дереве ресурсов.
Если установлен флаг clearChildrenRights, тогда для листа результата поиска будут назначены указанные права, а для его потомков будут сняты все права. Этот флаг нужен для прав с прямым наследованием - чтобы потомки унаследовали права родителя.
Отображение краткого описание объектов модели данных
Backend:
Backend добавляет поле description для узлов дерева (группы/сущности), чтобы Frontend мог показать краткое описание рядом с названием. При формировании дерева model/entity-groups сервер собирает description из модели (для register/lookup), добавляет в маппинг и прокидывает в DTO; фильтр безопасности удаляет описания для недоступных сущностей.
В REST v2 дерево узлов теперь содержит description (на уровне TreeNodeRO).
В DTO дерева групп добавлен маппинг описаний сущностей, которые используются в ответе сервиса.
GET /api/v2/data/model/entity-groups` (по EntitiesGroupRestService): в ответе у узлов дерева добавлено поле description.
Пример:
{
"name": "ROOT",
"displayName": "Корневая группа",
"description": null,
"parentName": null,
"type": "group",
"children": [
{
"name": "reg",
"displayName": "reg",
"description": "reg",
"parentName": "ROOT",
"type": "register",
"hierarchical": false,
"leaf": true
}
],
"leaf": false
}
Отображение времени обработки поискового запроса в модуле "Поиск по данным"
Добавлено измерение и возврат времени обработки поискового запроса в модуле "Поиск по данным".
Теперь ответ поиска содержит два новых поля:
totalProcessingTimeMillis - общее время обработки запроса на стороне сервера (мс), от начала обработки REST-запроса до формирования ответа.
searchProcessingTimeMillis - суммарное время работы поисковой подсистемы (OpenSearch took, мс), суммируется по всем ответам (включая scroll/scan).
Алгоритм работы:
В начале REST-запроса стартует захват таймингов (SearchTimingContext.startCapture() + отметка System.nanoTime()).
Во время выполнения поиска сервис накапливает took из OpenSearch (в т.ч. для scroll/scan).
Перед отдачей ответа выставляются поля totalProcessingTimeMillis и searchProcessingTimeMillis.
В finally контекст очищается.
Backend:
В ответ POST /api/v2/search добавлены поля totalProcessingTimeMillis и searchProcessingTimeMillis (мс).
Введен служебный контекст SearchTimingContext для накопления took из OpenSearch.
Логика сервиса поиска теперь суммирует took по всем ответам (включая scroll/scan).
POST /api/v2/search
Пример фрагмента ответа:
{
"details": {...},
"payload": {...},
"totalProcessingTimeMillis": 17,
"searchProcessingTimeMillis": 8
}
Отслеживание статуса запущенных пакетных операций
Обновлен формат выдачи информации о запущенных и завершенных задачах в API мониторинга задач (core/task-execution). Изменения были необходимы для внедрения нового механизма отслеживания статуса пакетных операций, который использует Snowflake ID для генерации идентификаторов отслеживания.
Причина изменений:
JavaScript некорректно обрабатывает очень большие целые числа (Snowflake ID), поэтому формат ответа API был изменен для обеспечения совместимости и гармонизации с bulk API.
Изменения в формате ответа:
В объекте, описывающем задачу, были переименованы и изменены следующие поля:
Старое название поля |
Новое название поля |
Описание |
id |
trackingId (String) |
Идентификатор отслеживания. Большое целое число, сгенерированное Snowflake генератором. |
task |
taskId (String) |
Внутреннее имя задачи (например, 'reindexJob'). Может использоваться для фильтрации задач одного типа. |
taskType (TaskTypeRO) |
Тип задачи: читаемое имя и отображаемое имя. |
|
initiator |
taskInitiator (UserRO) |
Объект пользователя, инициировавшего выполнение. |
initiatorUsername |
taskInitiatorUsername (String) |
Человеко-читаемый идентификатор инициатора. |
externalExecutionId |
taskExecutionId (String) |
Внутренний идентификатор выполнения задачи (информационный). |
tags |
taskTags (Set<String>) |
Теги, связанные с этим выполнением. Содержимое может различаться в зависимости от типа задачи. |
Поля taskInstanceId и taskExecutionId остались без изменений по названию, но теперь являются частью новой согласованной структуры.
Пример измененной структуры объекта задачи:
{
"trackingId": "1627925810373197824",
"taskId": "reindexJob",
"taskInstanceId": "Reindex Job #12",
"taskExecutionId": "ext-abc-123",
"taskType": {
"name": "REINDEX",
"displayName": "Операция переиндексации"
},
"taskInitiator": { ... },
"taskInitiatorUsername": "ivanov_ii",
"taskTags": ["BULK", "ENTITY:customer"]
}
Рекомендация:
Разработчикам, использующим API core/task-execution для интеграций, необходимо обновить клиентский код в соответствии с новой структурой полей.
Лимит черновиков записи
В реестры и справочники добавлено новое поле maxOneRecordDrafts. Поле отвечает за максимальное количество черновиков для одной записи данного реестра/справочника.
Отрицательные числа и 0 обозначают отсутствие ограничения;
Положительные числа обозначают максимальное количество одновременно существующих в БД черновиков для одной записи указанного реестра/справочника.
Часть ответа на запросы сущностей
{ "registerEntity": { "simpleAttributes": [], "arrayAttributes": [], "entityDependency": null, "customProperties": [], "name": "rst1", "displayName": "rst11", "description": "", "order": 0, "version": "5", "hasData": true, "complexAttributes": [], "modelName": null, "outgoingRelations": [], "incomingRelations": [], "mergeSettings": null, "attributeGroups": [], "relationGroups": [], "flyweight": false, "validityPeriod": null, "externalIdGenerationStrategy": null, "hierarchical": false, "maxHierarchyLevel": 0, "globalSearchEnabled": false, "hideValidityPeriods": false, "maxOneRecordDrafts": -1, // Максимальное количество черновиков для одной записи "dashboardVisible": false }
}
- {
- "lookupEntity": {
"simpleAttributes": [], "arrayAttributes": [], "entityDependency": null, "customProperties": [], "name": "testLookup", "displayName": "testLookup1", "description": "", "order": 0, "version": "5", "hasData": true, "modelName": null, "codeAttribute": {}, "aliasCodeAttributes": [], "attributeGroups": [], "mergeSettings": null, "validityPeriod": null, "externalIdGenerationStrategy": null, "dashboardVisible": false, "flyweight": false, "hierarchical": false, "maxHierarchyLevel": 0, "hideValidityPeriods": false, "maxOneRecordDrafts": -1, // Максимальное количество черновиков для одной записи "globalSearchEnabled": false
}
}
Если реестр/справочник имеет данное ограничение, то вставка черновика для записи данного реестра заблокирует поток выполнения для других вставок черновика этой записи, до окончания вставки черновика. То есть, если одновременно 2 пользователя создадут черновик для одной записи "Запись 1", то один пользователь заблокирует операцию создания черновика для "Запись 1", создаст черновик, а затем разблокирует операцию создания черновика для "Запись 1", в то время как другой пользователь будет ожидать разблокировки операции создания черновика для "Запись 1" и только после разблокировки попробует создать черновик.
Во время создания черновика записи реестра, имеющего maxOneRecordDrafts (>0), производится валидация количества существующих черновиков. Если количество созданных черновиков для указанной записи >= maxOneRecordDrafts, то возникнет ошибка.
Несмотря на то, что через FE получить ошибку должно быть невозможно (на FE должны быть валидации не допускающие создания запроса на большее количество черновиков), ошибку все еще можно получить используя POST запрос на вставку черновика.
Обработка логического удаления записи
Проблема с логическим удалением записи в том, что на удаление может быть назначен бизнес-процесс. По этому при логическом удалении скрыто для пользователя создается черновик на удаление. Это черновик, к которому пользователь в нормальной ситуации не имеет доступа (при желании он может открыть его через задачу БП). Для обработки этого исключения в параметры черновика добавлен флаг draft-for-delete. Если в параметрах есть данный флаг и на реестр/справочник НЕ НАЗНАЧЕНЫ бизнес-процессы на удаление, то черновик будет создан БЕЗ проверки ограничения черновиков.
/api/v2/draft/upsert
{
"type": "record",
"subjectId": "a891140b-f146-11f0-ae22-b35a117995b3",
"description": "Версия от 14.01.2026 15:44:22",
"tags": [
"entity-name:testRst",
"namespace:register"
],
"parameters": {
"entity-name": "testRst",
"draft-for-delete": true // флаг помечающий черновик как черновик для удаления
}
}
Предупреждение
Флаг добавлен только для обработки данного исключения и должен быть использован с осторожностью - ведь для системы этот черновик ничем не отличается от других. Применение флага декларирует намерение пользователя использовать черновик для логического удаления записи, но никак его не ограничивает в его использовании. Корректность использования флага полностью возлагается на пользователя.
Frontend:
MainSettings.tsx
Поля в расширенных настройках вынесены в геттер, которой возвращает отсортированный массив элементов по order
UEMetaModelAdvancedSetting.ts
Стал поддерживать order.
Модели Реестра и Справочника
Получили новое поле maxOneRecordDrafts, по дефолту значение с BE -1 = бесконечное количество черновиков.
DraftStore.ts
Добавлено новое поле класса maxDraftCount.
DraftWrapper.tsx
Изменена логика работы кнопки активации черновика. Модалка не открывается, а сразу запись переходит в режим черновика, если уже существует черновик и задан maxDraftCount = 1.
Backend:
В RegisterEntity и LookupEntity добавлено поле maxOneRecordDrafts. Поле отвечает за максимальное количество черновиков, которое может быть создано для одной записи сущности.
В пайплайн вставки черновика записи добавлен RECORD_DRAFT_UPSERT_VALIDATION. В нем проверяется количество существующих на данный момент черновиков. Если черновиков для указанной записи больше чем максимально допустимое - возникает ошибка.
Добавлен lock по subjectID при вставке нового черновика для избежания race condition в RECORD_DRAFT_UPSERT_VALIDATION при запросе количества draft на указанный subjectID.
Добавлена валидация на соответствие subjectID указанному entityName.
Пакетная операция клонирования записей
Backend:
Добавлена новая CloneRecordsExecutionRequestRO, которая содержит:
entityName
recordIds
recordSearch
additional
Добавилось три новых модуля для пакетной операции клонирования записей:
com.unidata.mdm.bulk.clone.records
сom.unidata.mdm.rest.v1.bulk.clone.records
com.universe.mdm.bulk.clone.classifications
Был добавлен пайплайн пакетного клонирования записей с сегментами:
RecordsCloneStartExecutor
RecordsCloneProcessExecutor
RecordsClonePersistenceExecutor
RecordsCloneMultiDraftExecutor
RecordsCloneFinishExecutor
RecordsCloneDraftSkipExecutor
RecordsCloneConnectorExecutor
RecordsAuditEventExecutor
Он записан в enterpise-pipelines.json:
{
"startId": "org.unidata.mdm.data[BATCH_RECORD_CLONE_START]",
"subjectId": "",
"description": "org.unidata.mdm.data.batch.record.clone.start.description",
"segments": [
{
"segmentType": "START",
"id": "org.unidata.mdm.data[BATCH_RECORD_CLONE_START]"
},
{
"segmentType": "POINT",
"id": "org.unidata.mdm.data[BATCH_RECORD_CLONE_MULTI_DRAFT]"
},
{
"segmentType": "POINT",
"id": "org.unidata.mdm.data[BATCH_RECORD_CLONE_PROCESS]"
},
{
"segmentType": "POINT",
"id": "org.unidata.mdm.data[BATCH_RECORD_CLONE_DRAFT_SKIP]"
},
{
"segmentType": "POINT",
"id": "org.unidata.mdm.data[BATCH_RECORD_CLONE_PERSISTENCE]"
},
{
"segmentType": "POINT",
"id": "org.unidata.mdm.data[BATCH_RECORD_AUDIT_EVENT]"
},
{
"segmentType": "FINISH",
"id": "org.unidata.mdm.data[BATCH_RECORD_CLONE_FINISH]"
}
]
}
Вызов операции восстановление через POST bulk-operations/execute:
{
"bulkOperationId": "com.universe.mdm.bulk.clone.records[operation]",
"content": {
"entityName": ..., /* Имя сущности */
"recordIds": [...], /* Список etalonId записей для клонирования */
"recordSearch": {...}, /* Поисковой запрос записей для клонирования */
"additional": { /* Опциональные параметры */
"multidraft": ..., /* Клонирование через мультичерновик (true/false) */
"processName": ..., /* Имя бизнес-процесса */
"approvalType": ..., /* Тип согласования (BLOCK/INDIVIDUAL) */
"autopublish": ... /* Автопубликация бизнес-процесса (true/false) */
},
"payload": {
/* Фрагмент параметров клонирования связей */
"clone-relations-request-fragment-v1": {
"includeAll": ..., /* Клонирование всех связей (true/false) */
"includeIncoming": ..., /* Клонирование входящих связей (true/false) */
"includeOutgoing": ..., /* Клонирование исходящих связей (true/false) */
"inclomingRelationNames": [...], /* Список имен входящих связей для клонирования */
"outgoingRelationNames": [...], /* Список имен исходящих связей для клонирования */
"cleanUnique": ... /* Очищать уникальные атрибуты связей (true/false) */
},
/* Фрагмент параметров клонирования классификаций */
"clone-classifications-request-fragment-v1": {
"includeAll": ..., /* Клонирование всех классификаций (true/false) */
"classifierNames": [...], /* Список имен классификаций для клонирования */
"cleanUnique": ... /* Очищать уникальные атрибуты классификаций (true/false) */
},
/* Фрагмент параметров клонирования записей */
"clone-records-request-fragment-v1": {
"cleanUnique": ... /* Очищать уникальные атрибуты записей (true/false) */
}
}
}
}
Согласование пакетного удаления записей
Была поддержана возможность согласования логического пакетного удаления записей при помощи создания и публикации мультичерновика. Для этого поддержана передача параметров создания мультчерновика в API массовых операций. Использован механизм мультичерновика для формирования одного процесса на пакет записей (опция block).
Физическое удаление будет продолжать удаляться без согласования.
Backend:
Эндпоинт балк-операций /v2/bulk-operations/execute был дополнен опциональной секцией "additional" для возможности передачи параметров создания мультичерновика.
Добавлено новое право "Прямое удаление без запуска бизнес-процесса", позволяющее запустить операцию массового удаления в обход БП.
Frontend:
Добавлен user-exit
DeleteRecordStore, позволяющий добавлять дополнительную логику при удалении записи.Добавлен user-exit
DeleteRecordStep, позволяющий добавлять шаги в визард удаления записи.Добавлен user-exit
BulkOperationSettingsStepStore, позволяющий добавлять шаги в визард настройки bulk-операций.
Согласование пакетного изменения записей
Bulk операции - /v2/bulk-operations/execute
Формат прежний, но дополнен опциональной секцией - ассоциативным массивом - "additional":
...
"payload": { },
"additional": {
"multidraft": true, // Сигнал завести мультичерновик для согласования пакетной операции. Следует выставлять в true для согласования, в false для публикации как раньше
"processName":"Process_3462b290-baf6-11f0-b0ea-473dced7c7ab", // Имя процесса согласования, если используется согласование. В противном случае null
"approvalType":"BLOCK", // Тип согласования, INDIVIDUAL или BLOCK, если используется согласование. В противном случае null
"autopublish": true // Флаг, определяющий будет ли созданный мультичерновик автоматически опубликован
}
Backend:
Эндпоинт балк-операций /v2/bulk-operations/execute был дополнен опциональной секцией "additional" для возможности передачи параметров создания мультичерновика.
Добавлено новое право "Прямое удаление без запуска бизнес-процесса", который позволяет запустить операцию массового удаления в обход БП.
Frontend:
Добавлен user-exit BulkOperationSettingsStepStore, который позволяет добавлять шаги в визард настройки bulk-операций.
Пакетная операция восстановления логически удаленных записей
Backend:
Создано два новых модуля. В них располагается основная логика выполнения операции. Реализация похожа на модуль: com.unidata.mdm.bulk.remove.records
Добавлена новая RestoreRecordsExecutionRequestRO, которая содержит:
entityName
recordIds
recordSearch
additional
При восстановлении записей также восстанавливаются и классификаторы.
Вызов операции восстановление через POST bulk-operations/execute:
{
"bulkOperationId": "com.unidata.mdm.bulk.restore.records[operation]",
"content": {
"entityName": ...,
"recordIds": [...],
"recordSearch": ...,
"additional": ...
}
Выбор только конечных записей в иерархическом справочнике
Добавлен флаг linkByLeafOnly для атрибутов ссылка на справочник.
Добавлена проверка выбора только конечных элементов иерархического справочника для атрибутов с признаком linkByLeafOnly.
Реализация поиска и вывод ресурсов категории "Данные" в алфавитном порядке
Backend:
Обновлен запрос получения дерева ресурсов безопасности выбранной категории GET /v2/core/security/secured-resources/resources-paginated/{category}.
Добавлен query параметр searchText:
Искомый текст ищется в именах и отображаемых ресурсов безопасности;
Регистронезависимый поиск;
Если в тексте несколько слов, то каждое слово отдельно должно быть найдено;
Найденные ресурсы возвращаются со всеми ресурсами-потомками соответственно остальным параметрам запроса (depth, maxNestedChildren);
Найденные ресурсы возвращаются со всеми ресурсами-родителями вверх по иерархии до узла (не включительно), запрошенного как корень дерева.
В запросы получения категорий для категорий добавлен параметр searchable – флаг, который обозначает возможность поиска по категории.
Для дерева ресурсов безопасности категории "Данные" (DATA) включена сортировка в алфавитном порядке (регистронезависимая) по отображаемому имени на всех уровнях дерева.
Сортировку можно включить для любых категорий соответствующим флажком при создании категории.
Сортировка корректно работает только для тех категорий, где отображаемое имя ресурсов не имеет локализованных вариантов, а только один (в ином случае требуется доработка бэкенда).
Frontend:
Основные изменения в VirtualCategoryViewStore.ts
Переопределен стор searchStore на новый VirtualCategoryTreeSearchStore
Реализован метод doSearch
TreeSearchStore
Логика добавления найденных ключей вынесена в метод processFoundSearchKeys, для возмонжости переопределить ее.
VirtualCategoryTreeSearchStore
Переопределен новый метод processFoundSearchKeys из TreeSearchStore. Который среди полного дерева находит элементы совпадающие с поисковой строкой и добавляет ключи в searchResult для дальнейшей корректной подсветки найденных элементов.
platform/security - Category.ts
Добавлен новый флаг получаемый с BE для отображения поиска по табам.
platform/security - ReadCategoryResourcePaginatedListOp.ts
Добавлен параметр
searchTextдля отправки строки поиска в запрос.
platform/tree - VirtualTreeController.tsx
При отображении найденной ноды добавлен проброс defaultRenderer, чтобы не ломать пользовательское отображение узлов в дереве.
Права на типы операций системы
Убраны ресурсы безопасности Запуск операций (JOBS_EXECUTIONS), Операции (JOBS_MANAGEMENT).
Добавлена категория Операции с действиями (Запуск, Редактирование).
Добавлена миграция прав: если были выданы права на Запуск операций, то пользователь получит права на Запуск всех операций; если были выданы права на Операции, то пользователь получит права на Редактирование всех операций.
Права на параметры системы
Для гибкой настройки прав доступа к различным группам системных параметров используется параметр конфигурации:
В файле backend.properties:
org.unidata.mdm.core.secured.property.groupsВ Docker-окружении (.env):
SECURED_PROPERTY_GROUPS
Назначение:
Параметр позволяет определить список групп параметров системы, для которых будут созданы отдельные дочерние ресурсы безопасности внутри права "Параметры системы".
Формат значения:
Список внутренних ключей групп, разделенных запятыми.
Пример переменной в .env:
SECURED_PROPERTY_GROUPS=com.unidata.mdm.bulk.export.properties.group, com.unidata.mdm.classifiers.model.group, com.unidata.mdm.ee.guest.mode.group, com.unidata.mdm.license.group, com.unidata.mdm.workflow.core.properties.group, com.universe.mdm.core.group.audit.ttl.policy, com.universe.mdm.core.group.notification.policy, com.universe.mdm.data.recipient.group, com.universe.mdm.dqw.quality.publishing.group, com.universe.mdm.dqw.quality.workflow.group, com.universe.mdm.hpe.core.property.group, com.universe.mdm.hpe.job.archive.vistory.data.properties.group, com.universe.mdm.job.export.audit.group, com.universe.mdm.ldap.integration.properties.group, com.universe.mdm.metadriven.core.group, com.universe.mdm.monitoring.core.properties.group, com.universe.mdm.notifications.group, com.universe.mdm.rest.v1.oauth2.properties.group, org.unidata.mdm.core.async.task.executor.group, org.unidata.mdm.core.fields.cache.group, org.unidata.mdm.core.group.audit, org.unidata.mdm.core.group.email, org.unidata.mdm.core.group.index, org.unidata.mdm.core.group.job, org.unidata.mdm.core.group.model.service, org.unidata.mdm.core.group.password.policy, org.unidata.mdm.core.group.security, org.unidata.mdm.core.group.system.jobs, org.unidata.mdm.core.upload.group, org.unidata.mdm.data.data.group, org.unidata.mdm.data.index.group, org.unidata.mdm.data.indexing.group, org.unidata.mdm.data.validity.period.group, org.unidata.mdm.dq.data.quality.upsert.group, org.unidata.mdm.draft.group.system.jobs, org.unidata.mdm.matching.core.main.group, org.unidata.mdm.matching.data.matching.group, org.unidata.mdm.matching.storage.postgres.properties.group, org.unidata.mdm.meta.admin.source.system.group, org.unidata.mdm.rest.system.properties.group, org.unidata.mdm.search.fuzziness.group, org.unidata.mdm.search.main.group, org.unidata.mdm.search.score.group, org.unidata.mdm.system.cache.group, org.unidata.mdm.system.library.group, org.unidata.mdm.system.messaging.group, org.unidata.mdm.system.system.group, org.universe.mdm.marks.group.marks
Результат:
После добавления параметра и перезапуска системы в интерфейсе настройки ролей (вкладка "Права доступа" → "Система" → "Параметры системы") появятся дополнительные пункты для управления доступом к указанным группам параметров.
Список всех кодов групп:
com.unidata.dg.bulk.export.assets.xlsx.group.key -> Пакетная операция экспорта активов
com.unidata.dg.dq.template.properties.group -> Настройки импорта шаблонов проверок DQ
com.unidata.mdm.bulk.export.properties.group -> Настройки экспорта в XLSX
com.unidata.mdm.ee.guest.mode.group -> Параметры гостевого режима
com.unidata.mdm.license.group -> Настройки лицензии
com.unidata.mdm.workflow.core.properties.group -> Настройки бизнес-процессов
com.universe.dg.data.labeling.group.properties -> Настройки разметки данных
com.universe.dg.data.versioning.properties.group -> Настройки версионирования
com.universe.dg.dis.integration.properties.group -> Настройки интеграции с DIS
com.universe.dg.discovery.client.properties.group -> Настройки клиента Discovery
com.universe.dg.dq.checks.group.properties -> Настройки проверок DQ
com.universe.mdm.core.group.audit.ttl.policy -> Фоновая операция очистки данных журнала аудита системы
com.universe.mdm.core.group.notification.policy -> Параметры групп пользователей
com.universe.mdm.job.export.audit.group -> Операция выгрузки аудита
com.universe.mdm.ldap.integration.properties.group -> Настройки модуля интеграции LDAP
com.universe.mdm.sso.kerberos.properties.group -> Настройки модуля SSO
org.unidata.dg.data.index.group -> Настройки индексирования данных
org.unidata.dg.data.information.system.group -> Настройка информационных систем
org.unidata.dg.data.job.calculate.asset.popularity.group -> Задача "Обновление популярности активов"
org.unidata.dg.data.job.clean.asset.draft.group -> Удаление неиспользуемых черновиков записей
org.unidata.dg.data.scanner.group.properties -> Сканеры
org.unidata.dg.data.xlsx.import.group -> Импорт XLSX-файла
org.unidata.mdm.core.async.task.executor.group -> Исполнение асинхронных задач
org.unidata.mdm.core.fields.cache.group -> Свойства системного кэша полей
org.unidata.mdm.core.group.audit -> Настройки аудита системы
org.unidata.mdm.core.group.email -> Почтовые настройки
org.unidata.mdm.core.group.index -> Индексы
org.unidata.mdm.core.group.job -> Конфигурация стандартных операций
org.unidata.mdm.core.group.model.service -> Общие свойства сервиса моделей
org.unidata.mdm.core.group.password.policy -> Настройки хранения паролей
org.unidata.mdm.core.group.security -> Параметры безопасности приложения
org.unidata.mdm.core.group.system.jobs -> Параметры системных операций модуля Core
org.unidata.mdm.core.upload.group -> Настройки загрузки файлов
org.unidata.mdm.data.data.group -> Настройки хранилища данных
org.unidata.mdm.data.index.group -> Настройки индексирования данных
org.unidata.mdm.data.indexing.group -> Настройки индексирования модели данных
org.unidata.mdm.draft.group.system.jobs -> Служебные задачи модуля черновиков
org.unidata.mdm.meta.admin.source.system.group -> Настройки системного источника данных
org.unidata.mdm.rest.system.properties.group -> Системные свойства REST
org.unidata.mdm.search.fuzziness.group -> Настройки нечеткого поиска
org.unidata.mdm.search.main.group -> Настройки поиска
org.unidata.mdm.search.score.group -> Настройки скоринга при поиске
org.unidata.mdm.system.cache.group -> Настройки кэширования
org.unidata.mdm.system.library.group -> Параметры библиотек
org.unidata.mdm.system.messaging.group -> Настройки подсистемы сообщений
org.unidata.mdm.system.system.group -> Системные настройки
org.universe.mdm.marks.group.marks -> Параметры модуля Marks
Ограничения на роли для групп
Был добавлен новый эндпоинт:
GET /users-group/available-roles - который выдает в теле ответа список ролей которые являются уникальными и могут быть назначены на группы при включенном параметре com.universe.mdm.core.group.unique.roles = true
Группы пользователей теперь могут иметь ограничения на уникальность и количество ролей, которые можно на них назначить.
Продуктивизация значения по умолчанию в атрибутах типа "Ссылка на справочник"
Backend:
Добавлена валидация удаления справочника используемого в атрибуте узла классификатора;
Добавлена валидация импорта модели классификатора. Проверка скрытых периодов актуальности при использовании значения по умолчанию для ссылки на справочник;
Добавлена валидация смены флага "Отображение периодов актуальности" для реестров и справочников;
Добавлена валидация импорта модели части модели, в которой реестр использует значение по умолчанию для справочника с периодом актуальности;
В валидацию удаления записи справочника, добавлена проверка использования записи в дочерних узлах классификации и в атрибутах связи;
При вставке классификатора добавлена проверка наличия значения справочника указанного как значение по умолчанию в атрибуте узла справочника и в наследуемом атрибуте;
Добавлена очистка кеша классификатора при удалении версии;
Добавлена очистка кеша классификатора при удалении классификатора.
Корректировка уведомления операции архивации ревизий
Уведомление разбивается по типам для записей, связей и классификаций.
Описание полей:
Обработано записей/связей/классификаций – количество эталонов, которые были проанализированы на наличие невидимых ревизий.
Архивировано ревизий – количество ревизий, которые были помещены в архивную БД.
Удалено ревизий – количество ревизий, которые были удалены.
Без изменений – количество эталонов, у которых не нашлось подходящих ревизий для архиваций/удаления.
Изменена логика подсчета статистики и генерации уведомления для операции архивации невидимых ревизий.
В AbstractRelationPartitioner и AbstractClassificationPartitioner добавлен функционал для подсчета количества эталонов в партиции (при countRelations == true и countClassifications == true). В операцию добавлен агрегатор ArchiveVistoryAggregator для подсчета общей статистики между партициями. Общая логика формирования блока уведомления для каждого шага операции вынесена в AbstractArchiveVistoryStepListener.
Права доступа вкладка "Данные"
В ответ на запрос GET /v2/core/security/secured-resources/categories внутрь объекта массива categories добавлено поле depthOfExpansion, которое указывает глубину раскрываемых узлов дерева. 1 - отображать только корень; 2 - отображать корень и потомков корня; 3 - отображать корень, потомков корня и потомков потомков корня.
Пример:
{
"categories": [
{
"name": "string",
"displayName": "string",
"view": "STATIC",
"autoSelectParents": true,
"depthOfExpansion": 0, // поле глубины отображения
"actions": [
{
"name": "string",
"displayName": "string"
}
]
}
]
}
Frontend:
Поддержка нового поля
depthOfExpansionполучаемого с BE, отвечающего за уровень раскрытия дерева категорий в ролях.Раньше на FE за это отвечала константа -
const LOAD_DATA_DEPTH = 5. Теперь это поле в модели Category, которое пробрасывается в VirtualCategoryViewStore.ts вместе с активной категорией и передается в запрос загрузки дерева. По умолчанию если поле depthOfExpansion === undefined, проставляется бывшее значение константы 5.
Backend:
Добавлено поле depthOfExpansion отвечающие за количество уровней раскрытия дерева прав.
Категориям через константы указаны значения поля.
Согласование изменений в рамках БП пользователем без прав на изменение записи
Операция - v2/workflow/process-definitions
Формат прежний, но дополнен флагом "publishByInitiatorIdentity":
...
{
"name": "Process_6ce4a730-cc36-11f0-a266-733c22457379",
"displayName": "test1",
"description": "",
"manualStart": false,
"variables": [],
"assignmentMappings": [],
"customProperties": [
{
"name": "singleFlowRestriction",
"value": "true"
},
{
"name": "publishByInitiatorIdentity",
"value": "true"
}
],
"singleFlowRestriction": true,
"publishByInitiatorIdentity": true, // Публикация от имени инициатора. Если true — при финальном согласовании запись публикуется от имени пользователя, запустившего процесс, а не от имени текущего согласующего
"executable": false
}
Если флаг "publishByInitiatorIdentity" включен и в процессе сохранен логин инициатора - на этапе финальной публикации черновика система автоматически выполняет ее от имени инициатора (в отдельном потоке). Это позволяет пользователям без прав на запись в реестр/справочник успешно завершать согласование - изменения все равно корректно запишутся от имени реального автора.
Backend
Добавлено поле в REST API: publishByInitiatorIdentity (в корне)
Добавлена системная переменная процесса: StandardWorkflowVariables.VAR_PUBLICATION_BY_INITIATOR
Хранится в customProperties как publishByInitiatorIdentity = true/false
ProcessHeaderField.FIELD_PUBLICATION_BY_INITIATOR - поле в поисковом индексе
Добавлено новое исключение: WorkflowExceptionIds.EX_WF_PROCESS_INITIATOR_NOT_AVAILABLE
Добавлена локализация: app.wf.process.initiator.not.available
Добавлен ProcessInstance#isPublicationByInitiator() и ProcessInstance#setPublicationByInitiator(Boolean;
Добавлен ProcessIndexInfo#isPublicationByInitiator() и ProcessIndexInfo#setPublicationByInitiator(boolean)
Добавлен ProcessDefinitionSource#withPublishByInitiatorIdentity(boolean)
Отключение периодов актуальности для моделей сущностей реестров, справочников и связей
Новый признак hideValidityPeriods на моделях сущностей (реестры, справочники, связи), позволяющий полностью отключить использование периодов актуальности для данной модели.
Добавлен флаг "Скрыть периоды актуальности" в настройках Реестра, Справочника и Связи, полностью отключающий функционал периодов актуальностей для указанных сущностей.
Скрыты колонки FROM/TO в импорте/экспорте в XLSX для реестров/справочников/связей, для которых выключены периоды актуальности.
Отображаемое имя операции в уведомлении о ее завершении
В generateGeneralMessage добавлено получение и вывод displayName через JobExecutionsComponent.
Обратная совместимость не нарушена, обновление не требует действий.
API метод пакетного создания комментариев
Метод обрабатывает список комментариев, выполняет валидацию (subject, parentId), сохраняет их одной batch-операцией и вызывает lifecycle-обработчики до и после вставки.
При ошибке выполнение останавливается, транзакция откатывается, а сообщение указывает проблемный комментарий по id или индексу.
Добавлен новый REST-эндпоинт POST /v1/marks/comments/multi-upsert для массового сохранения комментариев.
Добавлен метод multiUpsert в CommentsService и реализация в DAO.
Структура новых RO:
MultiUpsertCommentRequestRO
List<CommentRO> comments — список комментариев для сохранения.
MultiUpsertCommentResultRO (наследуется от AbstractSuccessfulResultRO)
boolean success — флаг успешности операции.
Функция замены всех вхождений подстроки
Добавлена системная функция "Замена" – выполняет замену подстроки / шаблона регулярного выражения в строке, с поддержкой префикса regex: для использования регулярных выражений.
ИзвлечьДату, ИзвлечьВремя из значения с типом DateTime
Добавлены новые функции "ИзвлечьDate" и "ИзвлечьTime", которые извлекают дату и время из значения с типом дата-время.
Ограничения на группы пользователей
Для поиска пользователя, которого можно добавить в группу необходимо использовать новый REST. Сейчас используется v2/core/security/user/list необходимо использовать новый поинт v1/commercial-core/users/list.
В usersGroup необходимо передавать родительскую группу, либо null, если группа является корневой:
{
"text": "string", // Текст фильтрации
"roles": [ // Роли пользователей
"string"
],
"usersGroups": [ // Группы пользователей
"string"
],
"includeUsers": [ // Пользователи, которые должны быть включены в ответ
"string"
],
"excludeUsers": [ // Пользователи, которые должны быть выключены из ответа
"string"
],
"active": true, // Статус пользователя
"limit": 0, // Лимит
"offset": 0, // offset
"enrichUsers": true, // Пропустить заполнение пользователей (меток безопасности)
"fullInfo": true // Вернуть полную информацию пользователей
}
Ответ аналогичен v2/core/security/user/list
Пример ответа
{
"details": {
"info": [],
"warning": [],
"error": []
},
"totalCount": 0,
"users": [
{
"createdAt": "2025-09-15T10:02:43.639Z",
"updatedAt": "2025-09-15T10:02:43.639Z",
"createdBy": "string",
"updatedBy": "string",
"login": "string",
"firstName": "string",
"middleName": "string",
"lastName": "string",
"fullName": "string",
"admin": true,
"active": true,
"email": "string",
"locale": "string",
"tags": [
"string"
],
"roles": [
"string"
],
"delegatedRoles": [
"string"
],
"rolesData": [
{
"createdAt": "2025-09-15T10:02:43.639Z",
"updatedAt": "2025-09-15T10:02:43.639Z",
"createdBy": "string",
"updatedBy": "string",
"name": "string",
"displayName": "string",
"type": "SYSTEM",
"rights": [
{
"createdAt": "2025-09-15T10:02:43.639Z",
"updatedAt": "2025-09-15T10:02:43.639Z",
"createdBy": "string",
"updatedBy": "string",
"securedResource": {
"id": "string",
"name": "string",
"displayName": "string",
"type": "SYSTEM",
"category": "string",
"parent": "string",
"children": [
"string"
],
"grantsRightsToChildren": true,
"requiresParentRights": true
},
"rights": [
"string"
]
}
],
"securityLabels": [
{
"name": "string",
"displayName": "string",
"description": "string",
"attributes": [
{
"id": 0,
"path": "string",
"description": "string",
"value": "string"
}
]
}
],
"properties": [
{
"id": 0,
"name": "string",
"displayName": "string",
"fieldType": "string",
"value": "string",
"required": true,
"readOnly": true
}
]
}
],
"securityLabels": [
{
"name": "string",
"displayName": "string",
"description": "string",
"attributes": [
{
"id": 0,
"path": "string",
"description": "string",
"value": "string"
}
]
}
],
"properties": [
{
"id": 0,
"name": "string",
"displayName": "string",
"fieldType": "string",
"value": "string",
"required": true,
"readOnly": true
}
],
"external": true,
"securityDataSource": "string",
"emailNotification": true,
"blockedBySystem": true
}
]
}
Обновление зависимостей
Был добавлен флаг assignedByAdmin для REST:
GET /v2/data/model/relations
GET /v2/data/model/relations/outgoing/{name}
GET /v2/data/model/relations/incoming/{name}
GET /v2/data/model/entity-groups
GET /v2/data/model/entity-groups/{id}
GET /v2/data/model/lookup-entities
GET /v2/data/model/register-entities
GET /v2/data/model/register-entities/{id}
GET /v1/dg/meta/relations
GET /v1/dg/meta/relations/{id}
GET /v1/dg/meta/relations/type/{type}
GET /v1/dg/meta/asset-types
GET /v1/dg/meta/asset-types/{id}
GET /v1/dg/meta/asset-tree
GET /v1/dg/meta/asset-hierarchical-tree
Флаг assignedByAdmin позволяет регулировать проверку прав. При значении флага assignedByAdmin = true проверяются права на администрирование модели данных, если у пользователя есть права на этот ресурс безопасности, то endpoint возвращает всю модель данных.
При значении флага assignedByAdmin = false проверяются права на отдельные реестры/справочники/активы и возвращается отфильтрованная модель (только те реестры/справочники/активы) на которые у пользователя есть права на чтение.
Фильтрация и сортировка правил качества и сопоставления
В разделах "Правила сопоставления" и "Правила качества" добавлен функционал сортировки, фильтрации и пагинации для различных столбцов таблиц.
Была отключена сортировка для следующих столбцов:
Раздел "Правила качества" - вкладка "Назначения": отключена сортировка по всем фазам.
Раздел "Правила сопоставления" - вкладка "Назначения": отключена сортировка столбцов "Таблицы" и "Наборы правил".
Добавлены 3 новых столбца в разделе "Правила качества": режим правила, критичность, система источник.
В разделе "Правила качества" добавлен новый пагинированный селектор для фильтрации по наборам правил. Также пагинированный селектор добавлен в редактор набора правил при выборе правила.
Изменения на Backend
Проиндексированы модели сопоставления и правил качества - их индекс добавлен к индексу мета-модели $[model] и [model] .
Доработан endpoint /v2/search/. Добавлена возможность обрабатывать запрос поиска мета-модели. Для этого используется объект
org.unidata.mdm.rest.v2.core.В операции переиндексации созданы пункты очистки маппинга метамодели, индексации модели сопоставления, индексации модели правил качества.
Разделены маппинг модели данных и метамодели.
По аналогии с
DataSearchRestRenderingComponentв рендерингSearchRestRenderingTypes#SEARCH_ATOMICдобавлен обработчикMetaModelRestRenderingComponent.Для проверки прав доступа пользователя к чтению запрашиваемой модели создан рендеринг
CoreRestRenderingTypes#METAMODEL_RIGHTS_RENDERING, который накапливает имена моделей, к которым у пользователя есть доступ.Для локализации полей индекса добавлен
MetaModelSearchResultHitModifier, использующийdisplayNameResolver.В индексе $[model] и [model] в поле entry_details добавлено поле display_version. Если данное поле присутствует, значит value данного details имеет локализованную версию.
Таблицы, правила, наборы правил и назначения модели сопоставления вынесены в индекс
default_default_[model].Добавлен шаг в операцию переиндексации для переиндексации модели сопоставления.
Добавлен поток выполнения удаления черновика модели сопоставления, где удаляются значения из индекса черновика метамодели.
Правила, наборы правил и назначения модели правил качества вынесены в индекс
default_default_[model].Добавлен шаг в операцию переиндексации для переиндексации модели правил качества.
Добавлен поток выполнения удаления черновика модели правил качества, где удаляются значения из индекса черновика метамодели.
Пример поиска таблицы сопоставления по имени колонки
"org.unidata.mdm.rest.v2.core": {
"countOnly": false,
"formFields": [],
"formGroups": [
{
"groupType": "AND",
"formFields": [
{
"name": "model_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "MATCHING"
},
{
"name": "subject_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "TABLE"
},
{
"name": "columns",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "columName"
}
],
"childGroups": []
}
],
"searchFields": [],
"returnFields": [
"model_type",
"subject_type",
"subject_name",
"entry_type",
"entry_name",
"entry_description",
"entry_display_name",
"columns",
"$draft_id"
],
"fetchAll": false,
"totalCount": true,
"supplementary": [],
"page": 1,
"count": 20,
"start": 0,
"sortFields": []
}
Пример поиска правила сопоставления по используемому алгоритму
"org.unidata.mdm.rest.v2.core": {
"countOnly": false,
"formFields": [],
"formGroups": [
{
"groupType": "AND",
"formFields": [
{
"name": "model_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "MATCHING"
},
{
"name": "subject_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "RULE"
},
{
"name": "matching_algorithms",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "ExactAlgorithm"
}
],
"childGroups": []
}
],
"searchFields": [],
"returnFields": [
"model_type",
"subject_type",
"subject_name",
"entry_type",
"entry_name",
"entry_description",
"entry_display_name",
"matching_algorithms",
"$draft_id"
],
"fetchAll": false,
"totalCount": true,
"supplementary": [],
"page": 1,
"count": 20,
"start": 0,
"sortFields": []
}
Пример поиска набора правил сопоставления по имени правила
"org.unidata.mdm.rest.v2.core": {
"countOnly": false,
"formFields": [],
"formGroups": [
{
"groupType": "AND",
"formFields": [
{
"name": "model_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "MATCHING"
},
{
"name": "subject_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "SET"
},
{
"name": "matching_rules",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "ruleName"
}
],
"childGroups": []
}
],
"searchFields": [],
"returnFields": [
"model_type",
"subject_type",
"subject_name",
"entry_type",
"entry_name",
"entry_description",
"entry_display_name",
"matching_rules",
"$draft_id"
],
"fetchAll": false,
"totalCount": true,
"supplementary": [],
"page": 1,
"count": 20,
"start": 0,
"sortFields": []
}
Пример поиска назначений наборов правил сопоставления
"org.unidata.mdm.rest.v2.core":{
"countOnly": false,
"formFields": [],
"formGroups": [
{
"groupType": "AND",
"formFields": [],
"childGroups": [
{
"groupType": "AND",
"formFields": [
{
"name": "model_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "MATCHING"
},
{
"name": "subject_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "ASSIGNMENT"
},
{
"name": "subject_name",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "register:registerName"
}
],
"childGroups": []
}
]
}
],
"searchFields": [
],
"returnFields": [
"$t",
"model_type",
"subject_type",
"subject_name",
"entry_type",
"entry_name",
"entry_description",
"entry_display_name",
"namespace",
"tables",
"matching_rule_sets",
"$draft_id"
],
"fetchAll": false,
"totalCount": true,
"supplementary": [],
"page": 1,
"count": 20,
"start": 0,
"sortFields": []
}
Пример поиска правила качества по условию запуска
"org.unidata.mdm.rest.v2.core": {
"countOnly": false,
"formFields": [],
"formGroups": [
{
"groupType": "AND",
"formFields": [
{
"name": "model_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "DATA_QUALITY"
},
{
"name": "subject_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "RULE"
},
{
"name": "run_condition",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "RUN_ALWAYS"
}
],
"childGroups": []
}
],
"searchFields": [],
"returnFields": [
"model_type",
"subject_type",
"subject_name",
"entry_type",
"entry_name",
"entry_description",
"entry_display_name",
"entry_description",
"dq_function_name",
"run_condition",
"severity",
"dq_function_type",
"applied_source_systems",
"$draft_id"
],
"fetchAll": false,
"totalCount": true,
"supplementary": [],
"page": 1,
"count": 20,
"start": 0,
"sortFields": []
}
Пример поиска наборов правил качества по имени правила качества
"org.unidata.mdm.rest.v2.core": {
"countOnly": false,
"formFields": [],
"formGroups": [
{
"groupType": "AND",
"formFields": [
{
"name": "model_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "DATA_QUALITY"
},
{
"name": "subject_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "SET"
},
{
"name": "dq_rules",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "ruleName"
}
],
"childGroups": []
}
],
"searchFields": [],
"returnFields": [
"model_type",
"subject_type",
"subject_name",
"entry_type",
"entry_name",
"entry_description",
"entry_display_name",
"dq_rules",
"$draft_id"
],
"fetchAll": false,
"totalCount": true,
"supplementary": [],
"page": 1,
"count": 20,
"start": 0,
"sortFields": []
}
Пример поиска назначений правил качества по набору правил в фазе
"org.unidata.mdm.rest.v2.core": {
"countOnly": false,
"formFields": [],
"formGroups": [
{
"groupType": "AND",
"formFields": [
{
"name": "model_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "DATA_QUALITY"
},
{
"name": "subject_type",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "ASSIGNMENT"
},
{
"name": "namespace",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "register"
}
],
"childGroups": []
},
{
"groupType": "AND",
"formFields": [
{
"name": "entry_details.key",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "PROCESS"
},
{
"name": "entry_details.value",
"type": "STRING",
"searchType": "EXACT",
"inverted": false,
"value": "ruleSetName"
}
],
"childGroups": []
}
],
"searchFields": [],
"returnFields": [
"model_type",
"subject_type",
"subject_name",
"entry_type",
"entry_name",
"entry_description",
"entry_display_name",
"namespace",
"entry_details",
"$draft_id"
],
"fetchAll": false,
"totalCount": true,
"supplementary": [],
"page": 1,
"count": 20,
"start": 0,
"sortFields": []
}
Алгоритмы модели сопоставления и функции правил качества локализуются при запросе.
Новые endpoint-ы обновления и удаления назначений DQ
Обновление назначения: PUT /v2/data-quality/quality-rules/type-assignments?draftId=162
draftId - опциональный параметр, id черновика модели правил качества, в который производится вставка. Если параметр не указан или равен 0, то вставка производится в чистовую версию.
Если назначение не существует - оно будет добавлено в соответствующий namespace. Если назначение существует, то его фазы будут заменены на фазы из тела запроса (удаление фаз, которых нет в теле запроса).
Тело запроса:
{
"assignment": {
"nameSpace": "lookup", // lookup/register
"assignments": [
{
"entityName": "lookupName", // Имя сущности на которую назначаются наборы
"assignment": [
{
"phase": "DEFAULT", // Фаза
"sets": [
"testSet" // Массив имен наборов правил качества
]
}
]
}
]
}
}
Удаление назначения: POST /v2/data-quality/quality-rules/type-assignments/delete?draftId=162
draftId - опциональный параметр, id черновика модели правил качества, из который удаляется назначение. Если параметр не указан или равен 0, то удаление производится из чистовой версии.
Тело запроса:
{
"assignment": {
"nameSpace": "lookup", // lookup/register
"entities": ["SS32", "SS1"] // Массив имен удаляемых сущностей
}
}
Указанные сущности будут удалены из модели правил качества.
Поля фильтрации в DQ
Для фильтрации по системам источникам правил в DQ в индекс модели правил качества вынесен источник "Для каких систем-источников применяется" в поле
applied_source_systems.
Индекс правила модели DQ:
{
"$t": "undefined",
"model_type": "DATA_QUALITY", // Модель DQ
"subject_type": "RULE", // Вкладка правила
"subject_name": "upperRule",
"entry_type": "RULE",
"entry_name": "upperRule",
"entry_description": null,
"entry_display_name": "верхнее правило",
"dq_function_name": "UpperCase",
"run_condition": "RUN_ALWAYS",
"dq_function_type": "enriching",
"applied_source_systems": "universe" // Источник по которому можно осуществлять фильтрацию
}
Для фильтрации по системам источникам правил в DQ в индекс модели правил качества вынесена критичность правила валидации в поле
severity.
{
...
"severity": "GREEN", // Критичность, по которой можно осуществлять фильтрацию
...
}
Для фильтрации по кодовому имени функции в DQ в индекс модели правил качества вынесено кодовое имя функции в поле
dq_function_name.
{
...
"dq_function_name": "UpperCase", // Имя функции, по которой можно осуществлять фильтрацию
...
}
Для фильтрации по режиму (валидация/обогащения) в DQ в индекс модели правил качества вынесен режим в поле
dq_function_type:
{
...
"dq_function_type": "enriching", // Режим, по которому можно осуществлять фильтрацию
...
}
Фильтрацию, используется ли она в наборе или нет, необходимо осуществлять на Frontend при помощи комбинируемого запроса или нескольких запросов.
Сортировка списков
Работа сортировки в OpenSearch, если указан не конкретный элемент, а массив.
Допустим, у нас есть 2 элемента: - strA: ["1", "2"] и strA: ["2", "3"]. Мы заказываем сортировку по убыванию. В этом случае сортировка идет по максимальному элементу массива, т.е. сравниваться будут "2" и "3", и в результате отсортированный результат будет таким: - strA: ["2", "3"] - strA: ["1", "2"], т.к. "3" >"2".
Если мы заказываем сортировку по возрастанию, то сортировка идет по минимальном элементу массива, т.е. сравниваться будут "1" и "2", и в результате отсортированный результат будет таким:
strA: ["1", "2"]
strA: ["2", "3"], т.к. "1" <"2".
Порядок элементов массива не важен.
Пример: связи с строковым массивом атрибутов:
["!", "1", "Aen", "aen", "Ару", "ару"] (min: "!"; max: "ару")
["1", "Aen", "aen", "Ару", "ару"] (min: "1"; max: "ару")
["Aen", "aen", "Ару", "ару"] (min: "Aen"; max: "ару")
["aen", "Ару", "ару"] (min: "aen"; max: "ару")
["Ару", "ару"] (min: "Ару"; max: "ару")
["ару"] (min: "ару"; max: "ару")
["!", "1", "Aen", "aen", "Ару", "ару"] (min: "!"; max: "ару")
["!", "1", "Aen", "aen", "Ару"] (min: "!"; max: "Ару")
["!", "1", "Aen", "aen"] (min: "!"; max: "aen")
["!", "1", "Aen"] (min: "!"; max: "Aen")
["!", "1"] (min: "!"; max: "1")
["!"] (min: "!"; max: "!")
Изменения на Frontend
Произведен рефакторинг модулей матчинга и DQ:
DQ - были изменены сторы: MappingStore, AssignmentStore, QualityRuleStore.
Matching - были изменены сторы: MatchingTableStore, MatchingRuleStore, MatchingRuleSetStore, MatchingAssignmentsStore.
В обоих модулях был использован стор AbstractEntityStore. Созданы соотвествующие сторы, наследуемые от AbstractEntityEditorStore и AbstractEntityListStore.
Функционал не изменился, был расширен поддержкой загрузкой данных при помощи нового поискового запроса org.unidata.mdm.rest.v2.core.
Расширенный импорт/экспорт модели данных
Новые API запросы:
GET /v2/core/model-graph/types - получение графа типов сущностей, который представляет типы элементов моделей системы и их связи с друг другом: например, тип "Реестры" имеет зависимость от типа "Справочники" через ссылки на справочники в атрибутах. Запрос не используется на Frontend – этот запрос помогает понять связи, заданные в моделях системы.
Параметры запроса:
getTree- получение графа в виде дерева, где типы сущностей сгруппированы по моделям;
getGraphNodes- получение узлов графа (типы сущностей);
getGraphEdges- получение ребер графа (связи/зависимости между типами сущностей);
getDotGraph- получение графа в формате DOT;
getModelGraph- получение графа моделей;
getModelDotGraph- получение графа моделей в формате DOT.
GET /v2/core/model-graph/entities - получение графа сущностей, который представляет элементы моделей системы их связи с друг другом: например, реестр "Граждане" имеет зависимость от справочника "Регионы" через атрибут, являющийся ссылкой на справочник.
Параметры запроса:
getTree- получение графа в виде дерева, где сущности сгруппированы по моделям и типам сущностей;
getGraphNodes- получение узлов графа (сущности);
getGraphEdges- получение ребер графа (связи/зависимости между сущностями). В ответе список ребер разделен на validGraphEdges (оба конца ребра есть в списке узлов) и invalidGraphEdges (одного из концов ребра нет в списке узлов, т.е. это некорректная связь);
lobId- ID ранее загруженного файла. Если не указан, то будут использоваться текущие модели в системе;
override- использование режима пересоздания моделей или нет:
Если true, то для вычисления графа используются только модели из указанного файла, текущие модели в системе игнорируются;
Если false, то для вычисления графа используются и модели из указанного файла, и текущие модели в системе. Исключительное поведение для некоторых моделей описано ниже.
POST /v2/core/model-graph/export - экспорт всех модели в одном ZIP-файле.
POST /v2/core/model-graph/upload - загрузка ZIP-файла со всеми моделями, в ответе будет возвращен ответ на запрос получения графа сущностей для загруженного файла: поддерживается параметр override как в запросе получения графа сущностей.
POST /v2/core/model-graph/apply - применение (импорт) загруженного ZIP-файла со всеми моделями:
Параметры в теле запроса:
lobId- ID ранее загруженного файла;
override- пересоздание модели или объединение с существующими;
allNodes- импорт всех элементов моделей;
graphNodes- список узлов (тип и имя) из графа сущностей, которые должны быть импортированы (если allNodes = false).
POST /v2/core/model-graph/entities/dependencies - получение зависимостей в графе сущностей для выбранных узлов графа:
Параметры в теле запроса:
nodes- список узлов графа сущностей (тип узла и имя узла). Типы узлов можно узнать в запросе получения графа типов сущностей; имена узлов как правило равны именам сущности;
getFromEdges- получение ребер графа, где выбранные узлы являются 'from' (исходящие ребра);
getToEdges- получение ребер графа, где выбранные узлы являются 'to' (входящие ребра);
Ответ на запрос:
nodesDependencies- список узлов и их зависимостей:node- узел графа сущностей (тип узла и имя узла);found- индикатор, найден ли узел;fromEdges- ребра, где узел является 'from' (исходящие ребра);toEdges- ребра, где узел является 'to' (входящие ребра).
Пример запроса:
{
"nodes": [
{
"nodeType": "org.unidata.mdm.data.entity.graph.data.model.node.lookup",
"nodeName": "someSpr"
},
{
"nodeType": "org.unidata.mdm.data.entity.graph.data.model.node.register",
"nodeName": "reg4"
}
],
"getFromEdges": true,
"getToEdges": true
}
Пример ответа
{
"details": {
"info": [],
"warning": [],
"error": []
},
"nodesDependencies": [
{
"node": {
"nodeType": "org.unidata.mdm.data.entity.graph.data.model.node.lookup",
"nodeName": "someSpr"
},
"found": true,
"fromEdges": [
{
"edgeType": "org.unidata.mdm.data.entity.graph.data.model.edge.lookup.group",
"fromNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.lookup",
"toNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.entities.group",
"displayName": "Справочник [someSpr] в группе [Корневая группа]",
"from": "someSpr",
"to": "ROOT",
"required": true
}
],
"toEdges": [
{
"edgeType": "org.unidata.mdm.data.entity.graph.data.model.edge.register.lookup.link",
"fromNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.register",
"toNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.lookup",
"displayName": "Реестр [reg4] имеет ссылку на справочник [someSpr] в простых/массив-атрибутах [ssilak]",
"from": "reg4",
"to": "someSpr",
"required": true
},
{
"edgeType": "org.unidata.mdm.data.entity.graph.data.model.edge.register.lookup.link",
"fromNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.register",
"toNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.lookup",
"displayName": "Реестр [testSort1] имеет ссылку на справочник [someSpr] в простых/массив-атрибутах [ssilak]",
"from": "testSort1",
"to": "someSpr",
"required": true
}
]
},
{
"node": {
"nodeType": "org.unidata.mdm.data.entity.graph.data.model.node.register",
"nodeName": "reg4"
},
"found": true,
"fromEdges": [
{
"edgeType": "org.unidata.mdm.data.entity.graph.data.model.edge.register.lookup.link",
"fromNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.register",
"toNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.lookup",
"displayName": "Реестр [reg4] имеет ссылку на справочник [someSpr] в простых/массив-атрибутах [ssilak]",
"from": "reg4",
"to": "someSpr",
"required": true
},
{
"edgeType": "org.unidata.mdm.data.entity.graph.data.model.edge.register.group",
"fromNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.register",
"toNodeType": "org.unidata.mdm.data.entity.graph.data.model.node.entities.group",
"displayName": "Реестр [reg4] в группе [Корневая группа]",
"from": "reg4",
"to": "ROOT",
"required": true
}
],
"toEdges": null
}
]
}
Список моделей, участвующих в расширенном импорте/экспорте:
Потоки выполнения
Потоки выполнения
Библиотеки
Важно: для данной модели флаг "Пересоздать" (override) не используется. Библиотеки не удаляются при импорте с этим флагом.
Библиотеки
Хранилища
Контейнеры хранилищ
Источники данных
Источники данных
Примечание: в модели источников данных могут присутствовать краулеры, но т.к. в MDM они не используются, то сейчас нет их обработки в расширенном импорте
Перечисления
Перечисления
Единицы измерения
Единицы измерения
Модель данных
Группы
Справочники
Реестры
Связи
Вложенные объекты
Модель качества данных
Правила качества
Наборы правил качества
Фазы
Назначения правил качества (один элемент содержит все назначения на один реестр/справочник)
Функции
Группы функций
Категории правил качества
Модель сопоставления
Таблицы сопоставления
Правила сопоставления
Наборы правил сопоставления
Алгоритмы сопоставления
Назначения сопоставления (один элемент содержит все назначения на один реестр/справочник)
Модель бизнес-процессов
Бизнес-процессы
Назначения бизнес-процессов (один элемент содержит назначение одного бизнес-процесса на один реестр/справочник)
Обработчики
Классификаторы
Классификаторы
Назначения классификаторов (один элемент содержит назначение одного классификатора на один реестр/справочник)
Поддержка других моделей: для поддержки других моделей (новых моделей или в отдельных продуктах) требуется реализовывать отдельную поддержку расширенного импорта/экспорта с определением разбиения модели на элементы, зависимостей модели и записи/чтения модели.
Сквозной поиск
Frontend:
module-ee/data: добавлена точка расширения search_widget, добавляющая виджет “Сквозного поиска” на главную страницу.
module-ee/meta: добавлена точка расширения для добавления флага активации “Сквозного поиска” в реестре/справочнике.
mdm/meta-data:
Добавлена поддержка точки расширения для добавления кастомных параметров в мета модель реестра/справочника.
Поддержано поле “Сквозного поиска” в модели реестра/справочника/связи.
Добавлена точка расширения для рендера элемента в настройках модели связей.
RelationSettings.tsx: компоненты полей вынесены в массив объектов с заданным order.
platform/icon: добавлена иконка.
platform/uikit: добавлен новый цвет.
Backend:
Добавлен новый параметр системы
org.unidata.mdm.search.global.enabled.В индексы добавлено новое техническое поле
$all_info.В модели данных у реестров, справочников, связей и назначений классификаторов добавлен новый флаг
globalSearchEnabled.В поисковый запрос /v2/search добавлен новый флаг
searchGlobally, вызывающий обработку сквозного поискового запроса.В поисковый запрос добавлено поле
searchDataTypes, использующийся в паре сsearchGloballyдля задания типов искомых документов вместоsearchDataTypeдля обычного поискового запроса.
Группы черновиков (Мультичерновики)
Frontend
Пакетная вставка: /v2/data/atomic/bulk
Формат дополнен опциональной секцией - ассоциативным массивом "additional".
...
],
"withResult": true,
"skipSegments": [],
"additional" : {
"operationId": "test_pseudo_TX1005", // Необязательный сквозной operation ID, идентификатор псевдотранзакции
"draftId": 1082, // ID мультичерновика. При первой вставке до создания объекта null. Заполнен при обновлениях
"multidraft": true, // Сигнал завести мультичерновик, если "draftId": null. Лучше всегда выставлять в true для мультичерновиков
"approvalType":"INDIVIDUAL", // Тип согласования, INDIVIDUAL или BLOCK, если используется согласование. В противном случае null
"processName":"Process_aeb1c480-3c63-11f0-bbd4-012e261aeb93" // Имя процесса согласования, если используется согласование. В противном случае null
}
Пакетная вставка возвращает теперь поля draftId и operationId.
Вставка через XLSX: /v2/core/import-data
Формат прежний, но поле "additional", бывшее ранее строкой, содержимое которой делалось с помощью JSON.stringify(...) из ассоциативного массива, стало просто ассоциативным массивом, аналогичным по содержанию примеру выше.
Провайдеры черновиков: /v2/draft/types
Дескриптор провайдера дополнился полем "multidraft". В поле будет true, если этот тип используется для создания мультичерновиков:
"types": [
{
"id": "the-ID",
"description": "Records multi draft",
"tags": [
"tag1"
],
"multidraft": true // для мультичерновиков
}
]
Поиск по черновикам: /v2/draft/drafts
Запрос дополнился запросом на подсчет дочерних черновиков:
{
"query": {
"type": "string",
"owner": "string",
"subjectId": "string",
"draftId": 0,
"parentDraftId": 0,
"tags": [
"string"
],
"state": "string",
"childrenCount": true // Вернуть количество дочерних черновиков, если true. 0 в ответе, если false
},
"offset": 0,
"limit": 0
}
Ответ дополнен полями "multidraftChild" и "childrenCount". "multidraftChild" будет выставлен в true, если черновик участвует в мультичерновике. "childrenCount" может содержать значение > 0, если запрос на подсчет дочерних черновиков был равен true и если количество дочерних черновиков > 0.
Список состояний черновика: /v2/draft/states
Выводит дополнительно системное состояние "PENDING".
Количество черновиков по заданным критериям: /v2/draft/count
Формат запроса такой же, как в /v2/draft/drafts. Ответ - целое положительно число или 0. Может быть использован, например, для выяснения готовности мультичерновика с типом согласования "INDIVIDUAL" к публикации (число дочерних черновиков всего - число дочерних черновиков в статусе "PENDING" равно 0).
Типы массового согласования: /v2/workflow/model/mass-approval-types
Возвращает доступные типы массового согласования с описаниями. В данный момент это "INDIVIDUAL" и "BLOCK".
Доступные типы процессов согласования: /v2/workflow/process-definitions
Интерфейс расширен полями "nameSpace", "typeName"и "triggerName" для выбора процесса согласования, например, при импорте из эксель.
Backend
Платформенный пакет multi-draft
Добавлен новый платформенный пакет multi-draft, в котором содержатся основные компоненты для рендера компонентов мультичерновика
Добавлены новые точки расширения:
UEMultiDraftCardRightExtraButton - Точка расширения позволяет получить кнопку для правой части карточки мультичерновика;
UEMultiDraftCellRenderer - Точка расширения позволяет кастомный рендерер ячейки таблицы draftId;
UEMultiDraftOverviewColumnRenderer - Точка расширения позволяет добавить элементы в правую и левую колонку шапки карточки мульти черновика;
UEMultiDraftTableColumn - Точка расширения позволяет добавить новую колонку в таблицу.
Платформенный пакет draft
Добавлен новый компонент DraftStateTag для рендера тега текущего статуса черновика.
Поддержаны новые поля в моделе черновика Draft.ts:
parentDraftId - Идентификатор родительского черновика
multiDraftChild - Является ли черновик частью мульти черновика
childrenCount - Количество дочерних черновиков
Добавлено два новый запроса:
ReadDraftTypesOp - Сервис получения доступных типов черновиков
ReadDraftCountOp - Сервис получение количества черновиков
Расширен конфиг запроса ReadDraftListOp:
parentDraftId: DraftId
childrenCount: boolean
Добавлен новый статус черновика - PENDING
Платформенный пакет uikit
Расширены пропсы компонента Tag.tsx новым параметром - maxWidth?: number - максимальная ширина тега
Платформенный пакет select
Добавлен новый компонент ControlledSelect - компонент селекта с возможностью указать загрузчик опций
Платформенный пакет parameters
Расширен резолвер точки расширения UEParameterItem:
export type UEParameterItemResolver = ( parameterDescriptor: IParameterDescriptor, formId?: string | symbol ) => boolean;
Модуль DATA
AbstractImportWizardStore.ts:
Переработан стор - вместо множества полей создан единый объект с параметрами.
Обновлена логика генерации importHandlerParameters - теперь помимо параметров, полученных с BE, реализуются кастомные параметры getCustomParameterDescriptors.
MultiDraftParamUtils.ts:
Создан утильный класс для работы с параметрами мультичерновика при импорте. Часть параметров определена сразу (DEFAULT_PARAMS_META), а другая часть подтягивается из нового UE UEMultiDraftImportParamMetaMeta (например: параметры, связанные с бизнес-процессами).
ImportWizardButtonStore.ts:
Расширен набор правил скрытия/раскрытия параметров, учтены параметры мультичерновика.
МОДУЛЬ WORKFLOW
Объявлены параметры импорта с мультичерновиком, связанные с бизнес-процессами.