Управление данными объекта#
Документ описывает ключевые механизмы управления данными объектов в системе: времязависимые значения, копирование, группировку и денормализацию деревьев. Все функции доступны на уровне метаданных и поддерживают конфигурацию через 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#используется как мастер-объект.
Настройка в 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 не указано — атрибут будет копироваться.
По умолчанию не копируются системные атрибуты:
idgidgidRefsImpExpKey_dznImpExpFlag_dzsMnemoCode_dzsHeadLine_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-сеттеры.
Группировка#
Группировка используется для:
Систематизации хранения объектов.
Удобства восприятия пользователем.
Массового управления характеристиками и настройками объектов.
Дерево групп — иерархическая структура, где потомки наследуют характеристики предков с возможностью переопределения.
Включение группировки#
Чтобы включить группировку для класса:
Откройте ODM-файл класса.
Укажите
group.type— тип группировки:single— объект может входить только в одну группу.multi— объект может входить в несколько групп.
Укажите
group.root— системное имя корня группировки.Добавьте в набор коллекций класса развязку групп:
<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).
Добавление закладки в карточку#
Для управления группами в карточке объекта можно добавить закладку:
Откройте AVM-файл класса.
Добавьте элемент:
<tabItems isVisible="true">
<tabItem selection="gtk-ru.bitec.app.btk.Btk_ObjectGroupAvi"
representation="List_Object"
id="2"
caption="Группы объекта"/>
</tabItems>
Реализация и использование#
Связь объекта с группой — через класс
Btk_ObjectGroup.Денормализованное дерево групп — в таблице
Btk_FlatObjectGroup.
Эти таблицы можно использовать в запросах для фильтрации объектов или реализации прикладной логики.
Интеграция с выборкой#
При включении группировки в список объектов добавляются операции по работе с группами.
Чтобы открыть панель группировки:
Откройте список объектов.
Выполните операцию «Открыть группы» — слева появится панель с деревом групп.
После открытия:
В основной части отображаются объекты из текущей группы и её потомков.
Новые объекты создаются в выбранной группе.
Денормализация классов-деревьев#
Для древовидных классов часто требуется вспомогательный класс денормализации, обеспечивающий быстрый доступ к иерархическим данным без рекурсивных запросов.
Реализован трейт TreeDenormApi (ru.bitec.app.btk.denormalization.TreeDenormApi), предоставляющий функциональность:
Создание.
Обновление.
Удаление денормализации по объектам из класса-дерева.
Пример#
Пусть класс-дерево называется Btk_TreeExample.
Необходимо создать класс денормализации, например — Btk_TreeExampleDenormalization.
Обычно такой класс содержит атрибуты:
ididClassidParentidChildnParentLevel
Подключение трейта#
Подключите трейт 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.