Управление данными объекта#

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

Времязависимые значения#

Времязависимые атрибуты хранят разные значения для разных периодов времени. Реализовано через таблицу Btk_TimeDepValue, где каждая запись содержит значение атрибута для объекта на указанном периоде. Период ограничен датой начала (dBegin) и датой окончания (dEnd). Если дата не заполнена — это открытый период. Сам атрибут класса хранит только одно актуальное значение.

Примечание

Для каждой пары объекта и атрибута периоды не могут пересекаться.

Создание времязависимого значения#

Создать времязависимое значение можно:

  • Указав свойство isTimeDepValue у атрибута в ODM.

  • Включив настройку «Времязависимое значение» в интерфейсе.

Изменение времязависимых значений#

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

  • Если значений нет — создается запись без указания границ периода.

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

    • Новый период начинается с текущей даты.

    • Для предыдущего периода dEnd устанавливается как «текущая дата минус 1 день».

Редактор времязависимых значений#

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

  • Дата начала.

  • Дата окончания.

  • Значение (обязательное).

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

Использование в бизнес-логике#

Пример получения значений#

// Получение последовательности rop по объекту и атрибуту
Btk_TimeDepValueApi().getByObjectAndAttr("30151/146451".ng, 757.nl)

// Получение последовательности rop в отсортированном порядке
Btk_TimeDepValueApi().getByObjectAndAttrSorted("30151/146451".ng, 757.nl)

// Получение числового значения на текущую дату
Btk_TimeDepValueApi().findValueByCurrendDateByAttr("30151/146451".ng, 757.nl).asNNumber

// Получение строкового значения на определённую дату
Btk_TimeDepValueApi().getByObjectAndAttr("30151/146451".ng, 757.nl)
  .find(rop => rop.get(_.dBegin) < "04.04.2025".nd && rop.get(_.dEnd) > "04.04.2025".nd)
  .map(_.get(_.jValue))
  .getOrElse(NString())

Пример установки значения#

// Добавление значения на определённый диапазон
val rop = Btk_TimeDepValueApi().insertByAttr("30151/146451".ng, 757.nl, "01.01.2025".nd, "31.12.2025".nd)
Btk_TimeDepValueApi().setValue(rop, "15.10.2025".nd)

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

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

Также возможно добавить данные из одного объекта в другой.

Копирование управляется свойствами в метаданных (по умолчанию = true). Настройка возможна:

  • На уровне класса — включение/отключение копирования.

  • На уровне атрибута — исключение конкретных полей из копирования.

Уровни настройки#

  • На уровне класса: свойство isCopyObjectEnabled.

  • На уровне атрибута: свойство isCopyInCopyObject.

Если копирование включено для класса:

  • В мастер-выборке EntityAvi#Default создана операция «Копировать». По умолчанию пустая и неактивная. Для классов с isCopyObjectEnabled="true" операция активируется и содержит исполняемый код.

  • В отображении Card создается операция copyObjectCard, которая создаёт новый объект и копирует в него данные по CardRep.IdItemSharp. Параметр idBOParent# используется как мастер-объект.

Обновление клонируемых операций#

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

Для обновления клонируемых операций используется метод UpdateMultiplicatingOperations(). Метод синхронизирует состояние клонируемых операций в рамках текущей выборки.

Метод можно вызвать без параметров — в этом случае будут обновлены все клонируемые операции текущей выборки:

Selection.UpdateMultiplicatingOperations;

Чтобы обновить только отдельные клонируемые операции, передайте массив их системных имен:

Selection.UpdateMultiplicatingOperations(['clnOper1', 'clnOper2']);

Настройка в ODM#

Пример настройки класса:

<class xmlns="http://www.global-system.ru/xsd/global3-class-1.0"
       name="Mct_OperCard"
       caption="Справочник операционных карт"
       cardEditor.representation="Card"
       listEditor.representation="List"
       viewOptions.openCardType="mdi"
       supertype="reference"
       isCopyObjectEnabled="true"
       attachType="simple"/>

Пример настройки атрибута:

<attr name="sCreateUser"
      attribute-type="Varchar"
      type="basic"
      isCopyInCopyObject="false"/>

При генерации метода copyObject в мастер-классе автоматически добавляются вызовы copyObject из коллекций — если для их классов копирование включено.

Если свойство isCopyInCopyObject не указано — атрибут будет копироваться.

По умолчанию не копируются системные атрибуты:

  • id

  • gid

  • gidRef

  • sImpExpKey_dz

  • nImpExpFlag_dz

  • sMnemoCode_dz

  • sHeadLine_dz

  • Атрибуты связи с мастер-сущностью.

Параметры метода copyObject#

  • Для миксинов: (gidFrom: NGid, gidTo: NGid, gidParent: NGid)

  • Для V-коллекций: (idFrom: NLong, idTo: NLong, gidParent: NGid)

  • Для остальных: (idFrom: NLong, idTo: NLong, gidParent: NLong)

Метод copyObject создаёт объект (если gidTo/idTo не передан) через DPI-метод. Установка значений выполняется через DPI-сеттеры.

Группировка#

Группировка используется для:

  • Систематизации хранения объектов.

  • Удобства восприятия пользователем.

  • Массового управления характеристиками и настройками объектов.

Дерево групп — иерархическая структура, где потомки наследуют характеристики предков с возможностью переопределения.

Включение группировки#

Чтобы включить группировку для класса:

  1. Откройте ODM-файл класса.

  2. Укажите group.type — тип группировки:

    • single — объект может входить только в одну группу.

    • multi — объект может входить в несколько групп.

  3. Укажите group.root — системное имя корня группировки.

  4. Добавьте в набор коллекций класса развязку групп:

<class xmlns="http://www.global-system.ru/xsd/global3-class-1.0"
       name="Bs_Contras"
       caption="Контрагент"
       supertype="reference"
       cardEditor.representation="MainCard"
       listEditor.representation="MainRoList"
       roListEditor.representation="ROList"
       viewOptions.openCardType="mdi"
       group.type="multi"
       group.root="Group3" />
<var-collection name="Btk_ObjectGroup"
                ref.attr="gidSrcObject"/> 

Требования#

Для подключения группировки класс должен иметь глобальный идентификатор (gid).

Добавление закладки в карточку#

Для управления группами в карточке объекта можно добавить закладку:

  1. Откройте AVM-файл класса.

  2. Добавьте элемент:

<tabItems isVisible="true">
  <tabItem selection="gtk-ru.bitec.app.btk.Btk_ObjectGroupAvi"
           representation="List_Object"
           id="2"
           caption="Группы объекта"/>
</tabItems>

Реализация и использование#

  • Связь объекта с группой — через класс Btk_ObjectGroup.

  • Денормализованное дерево групп — в таблице Btk_FlatObjectGroup.

Эти таблицы можно использовать в запросах для фильтрации объектов или реализации прикладной логики.

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

При включении группировки в список объектов добавляются операции по работе с группами.

Чтобы открыть панель группировки:

  1. Откройте список объектов.

  2. Выполните операцию «Открыть группы» — слева появится панель с деревом групп.

После открытия:

  • В основной части отображаются объекты из текущей группы и её потомков.

  • Новые объекты создаются в выбранной группе.

Денормализация классов-деревьев#

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

Реализован трейт TreeDenormApi (ru.bitec.app.btk.denormalization.TreeDenormApi), предоставляющий функциональность:

  • Создание.

  • Обновление.

  • Удаление денормализации по объектам из класса-дерева.

Пример#

Пусть класс-дерево называется Btk_TreeExample.

Необходимо создать класс денормализации, например — Btk_TreeExampleDenormalization.

Обычно такой класс содержит атрибуты:

  • id

  • idClass

  • idParent

  • idChild

  • nParentLevel

Подключение трейта#

Подключите трейт TreeDenormApi к API класса денормализации и реализуйте абстрактный метод masterTableName, возвращающий имя таблицы класса-дерева:

class Btk_TreeExampleDenormalizationApi extends
  Btk_TreeExampleDenormalizationDpi[
    Btk_TreeExampleDenormalizationAro,
    Btk_TreeExampleDenormalizationApi, 
    Btk_TreeExampleDenormalizationAta
  ]
  with TreeDenormApi[
    EntityAbst, java.lang.Long,
    Btk_TreeExampleDenormalizationAro
  ] {
  
  override def masterTableName: NString = "Btk_TreeExample"
}

Переопределение имён полей#

Если имена полей отличаются от стандартных, переопределите методы:

def idParentFieldName = "idParent"
def idChildFieldName = "idChild"
def nParentLevelFieldName = "nParentLevel"

Обновление денормализации#

Запланируйте событие заполнения денормализации:

  • В методе установки ссылки на предка (например, setidParent).

  • В методе insert — на случай, если родительская запись изначально пуста.

Вызовите метод:

ru.bitec.app.btk.denormalization.TreeDenormApi#updateDenormAfterFlush

Метод накапливает все переданные записи и обновляет денормализацию после сброса данных в БД.

Удаление денормализации#

Удаляйте денормализацию при удалении записи из основного класса — обычно в методе delete. Вызовите:

ru.bitec.app.btk.denormalization.TreeDenormApi#deleteDenormBeforeFlush

Метод накапливает записи и удаляет денормализацию перед сохранением в БД.

Прямое обновление (не рекомендуется)#

Возможно обновление/удаление непосредственно при редактировании, но это замедляет работу системы.

Используйте только при крайней необходимости:

ru.bitec.app.btk.denormalization.TreeDenormApi#updateDenorm
ru.bitec.app.btk.denormalization.TreeDenormApi#deleteByObject

Примечание

Пример реализации см. в Bs_DepartmentTreeApi в связке с Bs_DepartmentApi.