mybpm!
Скачать в формате: PDF pdf DOCX word

Bracket - как составлять фильтры с помощью бракетов?


В этой статье мы рассмотрим.

  1. Структура бракета
    • Пример бракета
  2. Структура dynamicFilters
    • Пример бракета с динамичным фильтром для текстового поля
  3. Структура nativeFilters
    • Пример бракетом с нативным фильтром для автора

Структура бракета:

Бракеты используется для получения данных с определённым фильтром

var JSON = {
    "brackets": [
        {
            "id": "iCNZfgb0",
            "parentId": null,
            "parentTreeIds": [{"..."}],
            "connectionType": "",
            "brackets": [{"..."}],
            "dynamicFilters": [{"..."}],
            "nativeFilters": [{"..."}],
        }]
}
Атрибут входного JSON Описание
id (String): Уникальный идентификатор бракета.
parentId (String или null): Идентификатор родительского бракета, если таковой имеется. Если бракет является верхним уровнем, то это поле может быть null.
parentTreeIds (Массив String): Массив идентификаторов родительских бракетов данного бракета в дереве. Простыми словами это массив хранящий id родительского бракета, родителя родительского и т.д пока они имеются.
connectionType (String): Тип соединения между условиями внутри бракета. Например, "AND" или "OR". Этот тип определяет, какие условия должны выполняться внутри бракета.
brackets (Массив объектов): Массив вложенных бракетов, которые содержат дополнительные сложные фильтры. Это позволяет строить сложные логические выражения из бракетов.
dynamicFilters (Массив объектов): Массив фильтров, которые выполняют фильтрацию по динамичным полям бизнес-объекта. Подробнее об структуре dynamicFilters
nativeFilters (Массив объектов): Массив фильтров, которые могут быть применены к нативным данным (полям) бизнес-объекта. Подробнее об структуре nativeFilters

Как вы возможно уже поняли dynamicFilters и nativeFilters фильтруют по полям бизнес-объекта, а Бракеты содержат эти фильтры в себе, соединяя их через булеву логику (И / ИЛИ). Также бракеты содержат другие бракеты, создавая структуру где все выполняется постепенно по приоритету.

Например, чтобы было наглядно создадим БО "Задачи" в системе MyBPM, и сделаем следующий фильтр:

Простое объяснение:

  1. Внутри оранжевого бракета ищем задачи, где автор либо текущий пользователь, либо Цыпленков Денис, но статус задачи In Work или Автор последнего изменения задачи Темирлан Жумагулов
  2. Затем смотрим чтобы данные проходящие оранжевый бракет имели дату создания с 01.09 - 30.09

Техническое объяснение:

Предупреждение: Может быть изначально непонятным если вы не ознакомились со структурами dynamicFilters и nativeFilters (Прочитайте их сперва)

  1. У нас есть один начальный, главный массив brackets, который содержит в себе два бракета: оранжевый бракет и прозрачный бракет с нативным фильтром "Дата создания", соединенные через условие И. В итоге будут отображаться данные которые прошли через фильтры оранжевого бракета И чья дата создания попадает в указанный период.
    {
     "boCode": "TEST", // поле описано в таблице внутри "Получение списка инстанций бизнес-объектов"
     "paging": { // поле описано в таблице внутри "Получение списка инстанций бизнес-объектов"
         "offset": 0,
         "limit": 20
     },
     "brackets" :  [ // ВНИМАНИЕ! Вот здесь наши бракеты будут расположены:
         {
             "id": "id_1", // Это id оранжевого бракета (Так как фильтров нет можем не указывать их)
             "parentId": null,
             "parentTreeIds": [], 
             "connectionType": "AND", // Связь со следующим соседним бракетом в списке
             "brackets": [
              {...}, // Рассмотрим ниже
              {...}, // Рассмотрим ниже
              {...} // Рассмотрим ниже
             ]
         },
         {
             "id": "id_2", // Это id прозрачного бракета с нативным фильтром
             "parentId": null,
             "parentTreeIds": [],
             "nativeFilters": [{ // Нативный фильтр на дату создания задачи с "dateFrom" по "dateTo"
                 "id": "n1",
                 "type": "CREATED_AT",
                 "dateFrom": "2023-09-01T00:00:00.000Z",
                 "dateTo": "2023-09-30T00:00:00.000Z"
             }],
             "connectionType": "AND",
             "brackets": []
         }
     ],
     "state": "ALL", // поле описано в таблице внутри "Получение списка инстанций бизнес-объектов"
    }
    
  2. Внутри оранжевого бракета у нас есть: прозрачный бракет с нативным фильтром "Автор", фиолетовый бракет и прозрачный бракет с фильтром нативным фильтром "Автор последнего изменения", соединенные через условие ИЛИ. Бракет будет фильтровать задачи (данные) по Автору "Текущий пользователь" ИЛИ по фильтрам фиолетового бракета ИЛИ по Автору последнего изменения "Темирлан Жумагулов".
       {
          "id": "id_1", // Это id оранжевого бракета (Так как фильтров нет можем не указывать их)
          "parentId": null,
          "parentTreeIds": [],
          "connectionType": "AND", // Связь со следующим соседним бракетом в списке
          "brackets": [
             {
                 "id": "id_1_1", // Это id первого бракета вунтри оранжевого бракета
                 "parentId": "id_1",
                 "parentTreeIds": ["id_1"], 
                 "nativeFilters": [{ // С фильтром на нативное поле Автор
                    "id": "n2",
                    "type": "CREATED_BY",
                    "isCurrentUser": true // По текущему пользователю 
                 }],
                 "connectionType": "OR" // Связь со следующим соседним бракетом в списке
             }, 
             {
                 "id": "id_1_2", // Это id фиолетвого бракета нужного для группировки и порядка выполнения 
                 "parentId": "id_1",
                 "parentTreeIds": ["id_1"], 
                 "brackets": [
                     {...}, // Рассмотрим ниже
                     {...} // Рассмотрим ниже
                 ],
                 "connectionType": "OR" // Связь со следующим соседним бракетом в списке
             }, 
             {
                 "id": "id_1_3",
                 "parentId": "id_1",
                 "parentTreeIds": ["id_1"], 
                 "nativeFilters": [{ // С фильтром на нативное поле Автор
                    "id": "n3",
                    "type": "CREATED_BY",
                    "isCurrentUser": true // По текущему пользователю 
                 }],
                 "connectionType": "AND" // Дефолтная связь (Нужно ли вообще ставить тогда?)
             } 
          ]
      }
    
  3. Внутри фиолетового бракета у нас есть два прозрачных бракета: первый с нативным фильтром на поле "Автор", а второй с динамичным фильтром на динамическое поле "Статус" созданного внутри БО "Задачи", соединенные через условие И. Бракет будет фильтровать данные по Авторам "Денис Цыпленков" и "qwe qwe" И чей Статус задачи в работе "In work".
    {
       "id": "id_1_2", // Это id фиолетвого бракета нужного для группировки и порядка выполнения 
       "parentId": "id_1",
       "parentTreeIds": ["id_1"], 
       "brackets": [
           {
               "id": "id_1_2_1", // Это id первого бракета внутри фиолетеового бракета
               "parentId": "id_1_2",
               "parentTreeIds": ["id_1", "id_1_2"],
               "nativeFilters": [{ // С нативным фильтром на поле "Автор"
                   "id": "n3",
                   "type": "CREATED_BY",
                   "orgUnitRecords": [
                       {
                         "id":"dPLgJxgojYu2Q0OR", // Для пользователя с этим id
                         "type":"PERSON" 
                       }
                   ]
               }],
               "connectionType": "AND" 
           },
           {
               "id": "id_1_2_2", // Это id второго бракета внутри фиолетового бракета
               "parentId": "id_1_2",
               "parentTreeIds": ["id_1", "id_1_2"],
               "dynamicFilters": [{ // С фильтром на динамичное поле Статус
                   "id": "n2",
                   "fieldId": "sn4jBFXH9SSinZEZ", // С этим id поля
                   "type": "RADIO_BUTTON_GROUP", // С типос "Единичный список"
                   "value": "TYmt8hUli27oCoP4" // Где значения идентификатор option-а
               }],
               "connectionType": "AND"
           },
       ],
       "connectionType": "OR" // Связь со следующим соседним бракетом в списке
    }
    

Структура dynamicFilters

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

var dynamicFieldFilter = {
    {
        "id": "",
        "fieldId": "",
        "type": "",
        "value": "",
        "numberFrom": null,
        "numberTo": null,
        "dateFrom": null,
        "dateTo": null,
        "isCurrentUser": false,
        "businessObjectId": "", 
        "boiIds": [{"..."}],
        "fromFields": [{"..."}],
        "label": "",
        "options": [{"..."}],
        "businessFields": [{"..."}],
        "selectedBois": [{"..."}],
        "topLeftLat": 0,
        "topLeftLon": 0,
        "bottomRightLat": 0,
        "bottomRightLon": 0
    }
}

Атрибут входного JSON Описание
id (String): Уникальный идентификатор фильтра.
fieldId (String или null): Идентификатор поле для который применяется данный фильтр (Как получить id поля?)
type (String): Тип поле, пример INPUT_TEXT. Подробнее о всех типах полей и какие значения им передавать.
value (String или null): Искомое значение для данного поле.
Работает только для текстовых полей или для пойска по id.
numberFrom (Number): Начальное числовое значение, связанное с бракетом.
Работает только для числового поля.
numberTo (Number): Конечное числовое значение, связанное с бракетом.
Работает только для числового поля.
dateFrom (Date или null): Начальная дата, связанная с бракетом.
Работает только для полей с датой.
dateTo (Date или null): Конечная дата, связанная с бракетом.
Работает только для полей с датой.
isCurrentUser (Boolean): Признак того, нужно ли составлять фильтр еще и по текущему пользователю помимо других пользователей.
Работает только для полей с пользователями (Organization Units).
businessObjectId (String или null): Идентификатор вложенного БО внутри вашего БО. При указании будут показываться его .
boiIds (Массив String): Идентификаторы инстанций (вложенного) бизнес-объекта, который является полем внутри вашего бизнес-объекта.
Работает только с вложенными бизнес-объектами. Проверяет id БО поля у всех инстанции вашего БО на содержание хотя бы одного значения из массива boiIds.
fromFields (Массив объектов): Составление для вложенных бизнес объектов
label (String): Текстовое обозначение поле (название)
options (Массив объектов): Текстовое обозначение поле (название)
businessFields (Массив объектов): Массив бизнес-полей, которые могут быть связаны с бракетом.
selectedBois (Массив объектов): Массив выбранных инстанций бизнес-объектов, связанных с этим бракетом.
topLeftLat (Double): Широта верхнего левого угла квадрата (1/4 поле, для работы фильтра по карте должны быть все 4 поля)
topLeftLon (Double): Долгота верхнего левого угла квадрата (2/4 поле, для работы фильтра по карте должны быть все 4 поля)
bottomRightLat (Double): Широта нижнего правого угла квадрата. Это поле должно быть меньше чем topLeftLat. (3/4 поле, для работы фильтра по карте должны быть все 4 поля)
bottomRightLon (Double): Долгота нижнего правого угла квадрата. Это поле должно быть меньше чем topLeftLon. (4/4 поле, для работы фильтра по карте должны быть все 4 поля)

Пример бракета с динамичным фильтром для текстового поля

1) Для того чтобы составить фильтр по текстовому полю, сперва мы должны присвоить идентификатор бракету, идентификаторам будет "DTb445uu".

var bracketJson = {
    "id" : "DTb445uu"
}

2) Так как это простой фильтр (не вложенный) "parentId" и "parentTreeIds" можем присвойть null.

var bracketJson = {
    "id" : "DTb445uu",
    "parentId": null,
    "parentTreeIds": []
} 

3) Третьем этапом мы должны определить тип связи "AND", "OR".

var bracketJson = {
    "id" : "DTb445uu",
    "parentId": null,
    "parentTreeIds": [],
    "connectionType": "AND"
} 

4) Объявление вложенных бракетов, мы пишем простой фильтр поэтому он нам не нужен.

var bracketJson = {
    "id" : "DTb445uu",
    "parentId": null,
    "parentTreeIds": [],
    "connectionType": "AND",
    "brackets": []
} 

5) Определяем dynamicFilters:

id уникальное строковое значение будет "nl4Fcy3Z"

fieldId нужно взять из редактора БО:

Нажимает на шестиугольник.

Как мы видим идентификатор данного поле равен "nTCVOX8zaetMLFZF", а типом является INPUT_TEXT.

Зная всю эту информацию, можем составить фильтр.

Результат:

var bracketJson = {
    {
        "id": "DTb445uu",
        "parentId": null,
        "parentTreeIds": [],
        "connectionType": "AND",
        "brackets": [],
        "dynamicFilters": [
        {
            "id": "nl4Fcy3Z",
            "fieldId": "nTCVOX8zaetMLFZF",
            "type": "INPUT_TEXT",
            "value": "qwe"
        }]
    }
}

Объяснение простыми словами: Ищем у БО с текстовым полем который ровняется к qwe.

Внимание! Полученный JSON вставляем в массив brackets в запросе для получения списка. Пример:

{
    "boCode": "TEST", // Код БО
    "headCodes": ["NUMBER", "TEXT"], // Поле описано в таблице внутри "Получения списка"
    "orderingFieldCode": "NUMBER", // Код Поля
    "orderState": "ASC", // Поле описано в таблице внутри "Получения списка"
    "paging": { // Поле описано в таблице для "Получения списка"
        "offset": 0, 
        "limit": 20 
    },
    // "filters": [{...}] // Поле описано в таблице внутри "Получения списка"
    // "search": "1", // Поле описано в таблице внутри "Получения списка"
    "state": "ALL",
    "brackets" :  [{ // Вставляем сделанный запрос сюда
        "id": "DTb445uu", 
        "parentId": null,
        "parentTreeIds": [],
        "connectionType": "AND",
        "brackets": [],
        "dynamicFilters": [
        {
            "id": "nl4Fcy3Z",
            "fieldId": "kUVz8yNpVG@NuISC",
            "type": "INPUT_TEXT",
            "value": "123"
        }]
    }]
}

Структура nativeFilters

var nativeFieldFilter = {
   "id": "",
   "type": "",
   "value": "",
   "dateFrom": null,
   "dateTo": null,
   "isCurrentUser": false,
   "orgUnitRecords": [
      {
          "id": "user_id",
          "type": "PERSON" // Другие: DEPARTMENT (Департамент), GROUP (Рабочая группа)
      }
   ],
}

Атрибут входного JSON Описание
id (String): Уникальный идентификатор фильтра.
type (String): Тип навтивного поле, пример CREATED_BY. Подробнее о всех типах нативных полей.
dateFrom (Date или null): Начальная дата, связанная с бракетом.
Работает только для полей с датой.
dateTo (Date или null): Конечная дата, связанная с бракетом.
Работает только для полей с датой.
isCurrentUser (Boolean): Признак того, нужно ли составлять фильтр еще и по текущему пользователю помимо других пользователей.
Работает если только в type PARTICIPANTS или CREATED_BY
orgUnitRecords (Массив Объектов): Организационные единицы (Пользователи, Департаменты, Рабочие группы) по которым нужно сделать фильтрацию на авторов или участников инстанций.
Работает если только в type PARTICIPANTS или CREATED_BY
orgUnitRecords.id* (String): Идентификатор из 24 символов конкретного пользователя, департамента или рабочей группы. Подробнее о том, как получить данные идентификаторы.
orgUnitRecords.type* (String): Перечисление, указывающая к чему относится id: PERSON (Пользователь), DEPARTMENT (Департамент), GROUP (Рабочая группа)

Пример бракета с нативным фильтром на поле Автор

1) Для того чтобы составить фильтр по полю Автор, сперва мы должны присвоить идентификатор бракету, идентификаторам будет "DTb445uu".

var bracketJson = {
    "id" : "DTb445uu"
}

2) Так как это простой фильтр (не вложенный) "parentId" и "parentTreeIds" можем присвойть null.

var bracketJson = {
    "id" : "DTb445uu",
    "parentId": null,
    "parentTreeIds": []
} 

3) Третьем этапом мы должны определить тип связи "AND", "OR".

var bracketJson = {
    "id" : "DTb445uu",
    "parentId": null,
    "parentTreeIds": [],
    "connectionType": "AND"
} 

4) Объявление вложенных бракетов, мы пишем простой фильтр поэтому он нам не нужен.

var bracketJson = {
    "id" : "DTb445uu",
    "parentId": null,
    "parentTreeIds": [],
    "connectionType": "AND",
    "brackets": []
} 

5) Определяем nativeFilters:

id уникальное строковое значение будет "nl4Fcy3Z"

type будет CREATED_BY (Это вы можете узнать в таблице выше)

orgUnitRecords будет содержать пользователя, но как вариант возможно взять целый департамент или рабочую группу. Но, мы берем одного конкретного автора и не текущего, поэтому нам нужно получить его id и type будет Person

Зная всю эту информацию, можем составить фильтр:

var bracketJson = {
    {
        "id": "DTb445uu",
        "parentId": null,
        "parentTreeIds": [],
        "connectionType": "AND",
        "brackets": [], 
        "nativeFilters": [{ // Нативный фильтр на поле "Автор"
            "id": "nl4Fcy3Z",
            "type": "CREATED_BY",
            "orgUnitRecords": [
                {
                    "id":"dPLgJxgojYu2Q0OR", // id нашего пользователя
                    "type":"PERSON" 
                }
            ]
        }]
    }
}

Объяснение простыми словами: Ищем у БО инстанцию, которую создал пользователь с id "dPLgJxgojYu2Q0OR".

Внимание! Полученный JSON вставляем в массив brackets в запросе для получения списка. Пример:

{
    "boCode": "TEST", // Код БО
    "headCodes": ["NUMBER", "TEXT"], // Поле описано в таблице внутри "Получения списка"
    "orderingFieldCode": "NUMBER", // Код Поля
    "orderState": "ASC", // Поле описано в таблице внутри "Получения списка"
    "paging": { // Поле описано в таблице для "Получения списка"
        "offset": 0, 
        "limit": 20 
    },
    // "filters": [{...}] // Поле описано в таблице внутри "Получения списка"
    // "search": "1", // Поле описано в таблице внутри "Получения списка"
    "state": "ALL",
    "brackets" :  [{ // Вставляем сделанный запрос сюда
        "id": "DTb445uu", 
        "parentId": null,
        "parentTreeIds": [],
        "connectionType": "AND",
        "brackets": [],
        "nativeFilters": [{ // С нативным фильтром на поле "Автор"
            "id": "nl4Fcy3Z",
            "type": "CREATED_BY",
            "orgUnitRecords": [
                {
                    "id":"dPLgJxgojYu2Q0OR", // Для пользователя с этим id
                    "type":"PERSON" 
                }
            ]
        }]
    }]
}