Skip to content

Бизнес-объекты

В этом разделе описывается, как настраивать бизнес-объекты — высокоуровневые абстракции над системными сущностями (классами, экземплярами, свойствами). Бизнес-объекты позволяют:

  • Работать с данными через удобный API, оперируя не техническими сущностями, а понятными бизнес-сущностями ("объектами" и их "атрибутами").
  • Индексировать и выполнять быстрый (в том числе полнотекстовый) поиск по объектам с использованием OpenSearch.
  • Копировать сложные структуры данных, состоящие из множества связанных экземпляров.
  • Переносить такие структуры между серверами (например, из тестовой среды в продакшен).

Настройка бизнес-объекта

Создание настройки

Перейдите в раздел "Настройки" → "Настройки объектов" и нажмите кнопку "Создать".

Настройка бизнес-объекта аналогична настройке семантического поиска: вы указываете корневой класс, от которого "раскручивается" дерево объекта, и добавляете нужные свойства.

Пример: объект "Отчёт"

Рассмотрим онтологию:

Результат настройки

img

Порядок настройки

  1. Выберите корневой классОтчёт.
  2. Нажмите иконку и добавьте свойства корневого класса:
    • дата отчёта
    • имеет статус
  3. Добавьте обратное свойство относится к отчёту (оно будет отображаться с синей иконкой ).
  4. Для этого свойства в меню параметров () установите флаг "Создавать новые" — это позволит включить в объект вложенные сущности (Строка отчёта).
  5. Добавьте свойства класса Строка отчёта:
    • код товара
    • кол-во, шт
    • цена, руб
  6. Для всех свойств и корневого класса задайте:
    • Псевдонимы — используются в API.
    • Человекочитаемые названия — отображаются в интерфейсе (например, при выборе колонок для поиска).

Важно

Если при создании или копировании объекта необходимо генерировать новые экземпляры связанных сущностей, у соответствующих свойств должен быть установлен флаг "Создавать новые".

В нашем примере при копировании отчёта будут созданы новые строки отчёта, но статусы — нет (они считаются справочными).

Примечания

  • Справа от свойств с флагом "Создавать новые" отображается специальная иконка .
  • Псевдонимы используются в API-запросах.
  • Человекочитаемые названия отображаются в интерфейсе (например, при выборе колонок для поиска в рабочих пространствах).

Взаимодействие с объектами через API

Требования к запросам

  • Все запросы выполняются методом POST.
  • Обязательно наличие одного из заголовков: Authorization или admin-token.

Создание объекта

Эндпоинт:
POST /api/object/create/{object_alias}

Пример запроса:

http
POST https://app.ru/api/object/create/report
Content-Type: application/json
Authorization: {token}

{
    "id": "e3023e11-8757-4c9f-85e9-c3ca973ed793",
    "name": "Отчет #1",
    "reportDate": "2025-10-15T00:00:00+03:00",
    "reportStatus": {"id": "0d3a6b53-4e83-4d12-aedc-3c528b3cd89a"},
    "reportLines": [{
        "id": "6d577020-316a-490c-843e-a709ba4fb846",
        "name": "Строка отчета #1.1",
        "code": "000011",
        "amount": 10,
        "cost": 2.5
      }, {
        "id": "25ea9260-77e0-40a3-a068-b602e33a37be",
        "name": "Строка отчета #1.2",
        "code": "000012",
        "amount": 3,
        "cost": 3.3333
      }
    ]
}

⚠️ Примечание
Идентификаторы (id) для создаваемых сущностей можно не указывать — они будут сгенерированы автоматически.

Ответ:

json
{
  "instId": "e3023e11-8757-4c9f-85e9-c3ca973ed793"
}

Получение одного объекта

Эндпоинт:
POST /api/object/get/{object_alias}/{id}

Пример запроса:

http
POST https://app.ru/api/object/get/report/e3023e11-8757-4c9f-85e9-c3ca973ed793
Content-Type: application/json
Authorization: {token}

Ответ: полная модель объекта с вложенными сущностями.

Получение коллекции объектов

Эндпоинт:
POST /api/object/get/{object_alias}

Поддерживает:

  • Пейджинг (limit, offset)
  • Фильтрацию в формате SQL-like

📌 Синтаксис фильтра
Путь к полю указывается через точку от корневого свойства и оборачивается в {$...}.
Пример: length({$handlers.handler.params}) > 0 and {$handlers.handler.id} in ('1112c000-7ed5-1111-2222-6ec1ea200000')

Пример запроса:

http
POST https://app.ru/api/object/get/report
Content-Type: application/json
Authorization: {token}

{
    "limit": 10,
    "offset": 0,
    "filter": "{$reportLines.name} like '%2'"
}

Ответ: массив объектов в том же формате, что и при получении одного объекта.

Обновление объекта

Эндпоинт:
POST /api/object/update/{object_alias}

Обновляются только собственные свойства корневого объекта. Коллекции полностью перезаписываются.

Пример запроса:

http
POST https://app.ru/api/object/update/report
Content-Type: application/json
Authorization: {token}

{
    "id": "e3023e11-8757-4c9f-85e9-c3ca973ed793",
    "reportStatus": {"id": "5511b000-9c2b-499b-8756-f2e6870f6fcc"}
}

Удаление объектов

Эндпоинт:
POST /api/object/delete

Удаляет только корневые объекты. Вложенные сущности не удаляются автоматически — их нужно удалять отдельно или настраивать каскадное удаление через обратные связи в онтологии.

Пример:

http
POST https://app.ru/api/object/delete
Content-Type: application/json
Authorization: {token}

{
  "ids": ["e3023e11-8757-4c9f-85e9-c3ca973ed793"]
}

Копирование объекта

Эндпоинт:
POST /api/object/copy

Создаёт полную копию объекта. Все сущности, помеченные флагом "Создавать новые", дублируются. Новые объекты получают суффикс "(копия)".

Пример запроса:

http
POST https://alpha.devtas.ru/api/object/copy
Content-Type: application/json
Authorization: {token}

{
    "settingId": "ef5c99fa-a587-4570-8490-c9373c8b013b",
    "instId": "e3023e11-8757-4c9f-85e9-c3ca973ed793"
}

Ответ: id нового корневого объекта.

Экспорт объекта

Эндпоинт:
POST /api/object/export

Возвращает команду set_data в формате API OSA, позволяющую воссоздать объект с оригинальными ID (без сессии).

Пример запроса:

http
POST https://app.ru/api/object/export
Content-Type: application/json
Authorization: {token}

{
    "settingId": "ef5c99fa-a587-4570-8490-c9373c8b013b",
    "instId": "e3023e11-8757-4c9f-85e9-c3ca973ed793"
}

Ответ: JSON с командой set_data, содержащей все экземпляры и связи.

Поиск через OpenSearch

Бизнес-объекты можно индексировать и искать с помощью OpenSearch — в том числе по полнотекстовому совпадению.

Алгоритм поиска:

  1. Отправить запрос в OpenSearch и получить коллекцию ID объектов, удовлетворяющих условиям поиска
  2. Выполнить get_data запрос к API OSA с фильтром по ID

Предварительные требования

❗ Только для администратора

Перед включением индексации необходимо:

  • Создать индекс в OpenSearch:
PUT
{
  "settings": {
    "index": {
      "number_of_replicas": 0
    },
    "analysis": {
      "analyzer": {
        "russian_analyzer": {
          "type": "russian"
        }
      }
    }
  },
  "mappings": {
    "dynamic_templates": [
      {
        "body_text_fields": {
          "path_match": "body.*",
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "analyzer": "russian",
            "fields": {
              "keyword": {
                "type":  "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    ]
  }
}
  • Назначить права:
    • indexer — запись
    • backend — чтение и поиск
  • Установить переменную окружения: INSTANCE_SEARCH_INDEX_NAME

Настройка индексации

  1. В настройке бизнес-объекта установите флаг "Для индексации".
  2. Настройте задачи в планировщике (для очереди Очередь индексации данных для быстрого поиска):
    • Без параметров — для регулярной индексации изменённых объектов.
    • С параметром {"fullScan": true} — для полной перестройки индекса (рекомендуется раз в сутки для удаления "мёртвых" записей).

Выполнение поиска

Эндпоинт:
POST /api/object/search

Пример запроса:

http
POST https://app.ru/api/object/search
Content-Type: application/json
Authorization: {token}

{
    "searchString": "иванов",
    "settingsId": "e0b78f48-45e9-4290-9879-1de44baed707",
    "selectedProps": [
        /* поля для поиска */
        {
            "parentId": "9dfb075f-af13-498c-b9ff-9bcb819d5ad4",
            "level": 1,
            "id": "c123a3c0-c5a3-4d24-81cd-2d4be56538d8",
            "idx": 2,
            "propId": "00000000-0000-0000-0000-000000000000",
            "propName": "Наименование",
            "typeId": "00000000-0000-0000-0000-000000000003",
            "name": "Наименование",
            "drillPossible": false,
            "reverse": false,
            "copy": false,
            "warning": false,
            "alias": "book_name",
            "humanReadableName": "Название книги"
        }
    ],
    "searchType": "contain",
    "sort": [
        {propId: "00000000-0000-0000-0000-000000000000", order: "asc"}
    ],
    "limit": 3,
    "offset": 0,
    "filter": [
        /* фильтры по корневым свойствам */
        {
            propId: "00000000-0000-0000-0000-000000010003",
            filter: "48d2f2ba-41e6-4314-8264-2996e6f6d25a"
        }
    ]
}

📌 Ограничения

  • Сортировка и фильтрация работают только по корневым свойствам.
  • Фильтрация возможна только по типизированным свойствам (отношениям).
  • Поддерживаемые типы поиска:
    fullText, contain, startWith, endWith, empty, notEmpty, match (совпадает).
  • поля для selectedProps нужно предварительно получить из экземпляра settingsId из свойства f4cfa90c-70b4-4172-9f36-6dd58bc011c6 ("настройки")

Ответ:

json
{
  "total": 5,
  "ids": [
    "9d051436-4e28-4ba1-996b-0c4f539cf330",
    "63490a4e-4610-4958-837c-2f609ddceeb5",
    "fd80528d-c718-4e63-9e56-ffbf0743c89c"
  ]
}