Перейти к основному содержанию
`Ctrl`+`K`

# Объектные характеристики

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

## Характеристики: понятие и назначение

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

Существует два способа хранения:

- В JSON-контейнере объекта
  Основной способ. Представляет собой NoSQL-расширение строки таблицы. Позволяет динамически добавлять характеристики без пересборки проекта и обновления схемы БД.

- Как атрибут класса с признаком «объектная характеристика»
  Используется в высоконагруженных сценариях, где доступ к JSON-полям недостаточно эффективен. Характеристика хранится в отдельной колонке таблицы. Требует синхронизации схемы БД при добавлении.

## Интеграция с выборкой

Для вывода характеристик используется универсальное отображение `Card_ObjectAttr`. Его генерация управляется параметром `objectAttrCardType` в ODM.

### Варианты настройки

Значение | Описание
--- | ---
`None` | Объектные характеристики не используются. Отображение не формируется.
`Simple` | Характеристики настраиваются на уровне класса или типа объекта. Если у класса есть тип объекта — настраивается на нём. Если нет — отображаются все характеристики.
`Group` | Характеристики настраиваются для групп.
`GroupAndObjectType` | Характеристики настраиваются для групп и дополняются теми, что заданы на типе объекта.

Отсутствие настройки эквивалентно `objectAttrCardType="Simple"`.

### Что отображается в закладке

В отображении выводятся:

- Значения атрибутов с флагом `isObjectAttr="true"`.

- Значения из JSON-контейнера `jObjAttrs_dz`.

- Универсальные характеристики (см. раздел Универсальные характеристики в Документации по модулю btk).

## Настройка характеристик на проекте

Пользователь может добавить характеристики через интерфейс:

1. Откройте приложение «Настройка системы».

2. Перейдите в раздел «Сущности > Классы».

3. Откройте карточку нужного класса.

4. Перейдите на закладку «Атрибуты».

5. При необходимости задайте значение по умолчанию для существующих атрибутов.

6. Создайте атрибут объектной характеристики.

Примечание

Имена атрибутов должны соответствовать соглашению:

- Строковые: начинаются с `s`, например `sStringAttrName`.

- Числовые: начинаются с `n`, например `nNumberAttrName`.

- Даты: начинаются с `d`, например `dDateAttrName`.

- Логические: начинаются с `b`, например `bBooleanAttrName`.

7. Сбросьте кэш метаданных:
   Снимите галочку в пункте меню `Сервис > Управление решением > Использовать кэш метаданных выборок`.

8. Выполните операцию «Сбросить кэш настройки» на текущей закладке.

## Значения по умолчанию

Значения по умолчанию подставляются при создании объекта.
Если класс использует группировку — значения берутся из основной группы.

### Для базовых атрибутов

- Указываются в ODM.

- Устанавливаются через DPI при вставке.

- Могут быть переопределены на проекте.

#### Проектное переопределение

- В списке атрибутов укажите значение в поле «Значение по умолчанию».

- Для сброса: выполните операцию «Удалить переопределение значения по умолчанию».

#### Программное переопределение

Используйте метод:

    ru.bitec.app.btk.Btk_AttributeApi#overrideDefaultValue

### Формат значений по умолчанию

1. Ссылочные поля: ID ссылочного объекта.

2. Переменная ссылочность: GID ссылочного объекта.

3. Числа: десятичный разделитель — точка.

4. Дата: формат `dd.MM.yyyy HH:mm:ss`.
   Значение `sysdate` → текущая дата при вставке объекта.

## Программная установка значений JSON-характеристик

### В бизнес-логике

    val rop = Bs_GoodsApi.load(209851.nl)
    // Установка ссылочной характеристики
    Bs_GoodsApi().setAttrValue(rop, "idGradeJson", 77016.nl)

### В Jexl-скрипте

var rop = Bs_GoodsApi.load(209851L); // Установка ссылочной характеристики Bs_GoodsApi.setAttrValue(rop, «idGradeJson», 77016L);

## Проверка значений объектных характеристик

Для валидации характеристик доступны два типа правил:

1. Проверка значений атрибутов — контроль корректности вводимых данных.

2. Ограничение выбора ссылочных атрибутов — фильтрация доступных значений.

Совет

Ограничивающие атрибуты
При изменении ограничивающего атрибута проверяются правила зависимых атрибутов. При нарушении — значение обнуляется.

Правила настраиваются в закладке:
`Настройки и сервисы > Правила для атрибута`.

### Проверка значений атрибутов

Контролирует значения, устанавливаемые пользователем. Каждое правило — Jexl-скрипт, возвращающий логическое выражение:

- `true` — проверка пройдена.

- `false` — проверка не пройдена. Отображается сообщение об ошибке из карточки правила.

#### Приоритет применения правил

1. Уровень типа объекта (или шаблона атрибутов).

2. Уровень группы.

   Примечание

   Правила наследуются от родительских групп. Возможна переустановка на детализации «Правила для атрибута». Используется переопределённая версия.

3. Уровень характеристики.

#### Типы вызова проверки

- На установку значения характеристики
  Проверка после завершения редактирования.

- На завершение редактирования объекта
  Проверка на событии `afterEdit`, после сохранения.

### Ограничение выбора атрибутов

Ограничивает список доступных значений для ссылочных атрибутов.
Правило — Jexl-скрипт, возвращающий SQL-условие для таблицы ссылочного класса.

Если текущее значение не удовлетворяет условию — оно обнуляется.
Проверка выполняется рекурсивно: обнуление одного атрибута вызывает проверку зависимых.

Примечание

В контексте Jexl-скрипта доступна ROP объекта, которому принадлежит атрибут.

Внутренняя логика работы ограничения значений

JEXL-скрипт должен возвращать SQL-условие в виде строки. Это условие вставляется в `WHERE` финального запроса к таблице ссылочного класса.

Пример скрипта:

`if (nNum < 5) { "upper(&sname) like '%БОЛТ%'" } else { "upper(&sname) like '%ВИНТ%'" }`

При `nNum = 7` результат: `"upper(&sname) like '%ВИНТ%'"`.

Это условие будет использовано в SQL: `SELECT * FROM (SELECT * FROM Bs_Goods) t WHERE upper(t.sname) like '%ВИНТ%'`

Важно:

- Символ & заменяется на алиас таблицы (t.sName, g.sCaption и т.п.).

- Возвращённая строка становится частью условия WHERE.

- Правила не работают с выборками, сформированными объектным запросом — такие источники не поддерживают дополнительные SQL-условия.

#### Параметры правила

Позволяют переиспользовать одно правило на разных объектах. Значения параметров задаются на уровне объекта.

##### Пример

В классе `SupplyRequest` есть атрибут `idWarehouse`. Нужно ограничить выбор складов по региону. Регион может быть:

- В самом `SupplyRequest` (`idRegion`).

- В связанном контрагенте (`Bs_Contras.idRegion`), на который ссылается `idContras`.

Правило одинаковое:

    "&idRegion = " + regionId

Скрипты получения `regionId` могут отличаться:

1. Через атрибут объекта:

       rop.idRegion;

2. Через контрагента:

       val ropContras = Bs_ContrasApi().load(rop.idContras);
       ropContras.idRegion;

#### Скрипты правила и параметров

Параметры могут быть:

- Значением.

- Ссылкой.

- Jexl-скриптом, исполняемым перед проверкой.

Для указания скрипта установите флажок «Jexl-скрипт» в детализации «Параметры проверки» карточки правила.

Значение скрипта можно настроить на объекте в закладке «Jexl-скрипт» детализации:
`Правила для атрибута > Параметр для правила атрибута`.

Совет

В скрипте правила алиас таблицы можно заменять символом `&`.
Например, вместо `t.idObjectType` пишите `&idObjectType`.

#### Пример правила

Цель: для атрибута `idGoods` (класс `RplTst_AllDbTypes`) показывать только болты или винты в зависимости от значения `nNum`.

JEXL-скрипт правила:

    if (nNum < 5) {
      "upper(&sname) like '%БОЛТ%'"
    } else {
      "upper(&sname) like '%ВИНТ%'"
    }

JEXL-скрипт параметра `nNum`:

    RplTst_AllDbTypesApi.getAttrValue(rop, "nNumber");

#### Ограничивающие атрибуты

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

Ограничивающий атрибут может быть:

- Атрибутом самого объекта.

- Атрибутом его родителя (бизнес-объекта), если зависимый атрибут — в коллекции.

Типы настройки:

- На типе объекта.

- На группе.

- На шаблоне атрибутов типа объекта.

Примечание

Обнуление происходит через стандартные сеттеры:

- Для атрибутов БД — сеттеры в `Api` класса.

- Для JSON-характеристик — `JObjectAttrApi.setObjAttrValue(rop: AnyRop, idpAttr: NLong, pValue: Any)`.

## Установка и изменение правил валидации

Правила настраиваются в детализации «Правила для атрибута»:

- На тип объекта
  В закладке `Объектные характеристики` → `Сущности > Типы объектов` или в карточке класса.

- На группу
  В закладке `Атрибуты группы` при редактировании группы.

- На шаблон атрибутов
  В закладке `Объектные характеристики` → `Сущности > Типы объектов` или в карточке класса.

Кэширование правил

- Правила проверки значений: кэшируются при загрузке выборки.
  → Необходимо переоткрыть выборку после изменения.

- Правила ограничения и ограничивающие атрибуты: кэшируются стандартно.
  → После настройки выполните «Очистить все кэши» в меню `Сервис > Управление решением`.

Внимание

Параметры правила на объекте являются обязательными.
Если хотя бы один не заполнен — все сеттеры в классе будут падать с ошибкой:
`Заполнены не все параметры правила "<заголовок правила>" на атрибуте типа "<заголовок типа атрибута>" c id = <идентификатор атрибута>`