Сервисные возможности для классов#

Возможности классов расширяются сервисным окружением, которое постоянно совершенствуется.

Служебные атрибуты#

Для сервисных возможностей фреймворк добавляет в таблицы служебные атрибуты. Служебные атрибуты заканчиваются постфиксом _dz.

Пример:

  • nVersion_dz

  • screateuser_dz

  • dcreatedate_dz

Внимание

Разработчикам запрещено создавать и изменять такие атрибуты.

Отображение состояния сессии в форме#

Состояние сессии можно определить по цвету системных операций Сохранить и Откатить на тулбаре формы.

Все состояния формы перечислены в таблице:

Пользовательская блокировка

Данные для отправки в базу данных

Кнопка «Сохранить»

Кнопка «Откатить»

Нет

Нет

не активна

не активна

Нет

Есть

активна

активна(крест)

Есть

Нет

не активна

активна(круг)

Есть

Есть

активна

активна(крест)

Автонумерация#

Автонумерация – процесс автоматической выдачи значения для атрибута класса. В основе лежит выдача порядкового номера (числа), которое может быть преобразовано в значение по маске.

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

Существует два режима работы автонумерации:

  • Без заполнения пропусков

  • С заполнением пропусков

Определение разреза автонумерации#

Автонумерация в пределах значений одного или нескольких атрибутов класса называется автонумерацией с разрезом. Значение разреза может вычисляться по правилу, указанному в теге «expression», если выражение не указано, будет использоваться значение атрибута.

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

Настройка автонумерации без разреза#

Для автонумерации без разреза в odm файле класса указываем для атрибута тип autonum, далее в блоке autonum задаем имя разреза «dimension»

<attr name="sNoDep"
      caption="Автонумерация без разреза"
      attribute-type="Varchar"
      type="autoNum"
      isHeadLine="true">
	<autonum id="1">
		<mask>lpad(counter,3,"0")</mask>
		<dimension name="dim1"/>
	</autonum>
</attr>

Настройка автонумерации с разрезом#

Для настройки разрезов dimension

  1. Задайте уникальные имена

  2. Укажите атрибуты разреза
    Разрезы указываются из атрибутов класса

  3. При необходимости задайте порядковый номер
    Если его не указывать, то они будут обрабатываться в алфавитном порядке.

Количество разрезов должно быть >= 1.

Указание нескольких разрезов:

<attr name="sTwoDepExpr"
		caption="Автонумерация с 2 разрезами"
		attribute-type="Varchar"
		type="autoNum">
	<autonum id="3">
		<mask>lpad(counter,3,"0")</mask>
		<dimension name="nNumber"
				attr="nNumber"
				order="10" />
		<dimension name="dDate_dim"
				attr="dDate"
				order="20">
			<expression>truncDate(dimValue)</expression>
		</dimension>
	</autonum>
</attr>

Если в настройках автонумерации указан разрез, то автоматически включено заполнение пропусков. Отключить заполнение пропусков можно через свойство isHoleFill

<attr name="sOneDepNoHoleFill"
      caption="Автонумерация с 1 разрезом без заполнения пропусков"
      attribute-type="Varchar"
      type="autoNum"
      isHeadLine="true">
	<autonum id="4"
	         isHoleFill="false">
		<dimension name="dDate"
		           attr="dDate"
		           order="10"/>
	</autonum>
</attr>

Общие настройки#

Возможно использовать маски для вывода значения счетчика. Значение, указанное в элементе mask, будет передано в обработчик Jexl-скриптов.

Параметр, заменяемый на значение счетчика, называется counter. В Jexl добавлены методы:

  • lpad(string, size, padChar) Добавление строки символами слева

  • rpad(string, size, padChar) Добавление строки символами справа

  • truncDate(date) Получение даты на начало дня от переданной

  • truncYear(date) Получение даты на начало года от переданной

В jexl скрипте можно обращаться к api и pkg объектам.

К значениям атрибутов разреза возможно применение выражений, они указываются в элементе expression для dimension.

На каждый разрез может быть не больше одного выражения.

Значение, указанное в элементе expression, будет передано в обработчик Jexl-скриптов, параметр, заменяемый на значение атрибута разреза, называется dimValue.

<attr name="sRegNumber" attribute-type="Varchar" caption="Рег. №"  order="230" type="autoNum" isVisible="false" isReadOnly="true">
	<autonum>
		<mask>
      var sOTCode = Btk_ObjectTypeApi.load(self.idObjectType()).getByAttrName(\"sCode\"); 
      if (sOTCode eq \"OperDecisionPrj\" 
          || sOTCode eq \"ProductDecisionPrj\") {
            counter + \"-Г\"
      } else {
        counter + \"-Г.\" + Bs_PrjVerApi.load(self.idPrjVer()).getByAttrName(\"sCode\")
      }
    </mask>
		<dimension name="idObjectType" attr="idObjectType" order="1">
			<expression>
          if (dimValue == null) { 
            null 
          } else { 
            var sCode = Btk_ObjectTypeApi.load(dimValue).getByAttrName(\"sCode\"); 
            if (sCode eq \"OperDecisionPrj\" 
                || sCode eq \"OperDecisionWrk\" 
                || sCode eq \"ProductDecisionPrj\" 
                || sCode eq \"ProductDecisionWrk\"
                ) 0L 
                else null;
          }
        </expression>
		</dimension>
	</autonum>
</attr> 

Для обращения к полям класса при вычислении маски используется переменная self, которая является объектом типа Aro, поэтому для получения значения атрибута необходимо добавлять в конце скобки (т.к. это метод). Например:

self.sCaption()

После генерации кода необходимо будет выполнить метод *Dpi.autoNumCreateTable.

Если с момента последнего выполнения данного метода были изменены данные автонумерации (имена разрезов, типы данных разрезов, количество разрезов), то таблицы и индексы будут пересозданы.

Так же генерация окружения автонумерации выполняется перед инициализацией первоначальных данных (init data), которая вызывается при обновлении проектного jar-кода или при выполнении генерации таблиц в Intellij Idea : External Tolls > Generate Tables

Присвоение значения автонумерации происходит в момент сохранения транзакции.

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

«Значение присваивается автоматически в момент сохранения, ввод данных отключит автонумерацию. Продолжить?»

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

Автонумерация в миксинах#

Возможно задание автонумерации в миксине. Атрибуты, которые объявлены как автонумерующиеся в миксине, но при этом как обычные в целевом классе, получат настройки автонумерации + сквозные таблицы хранения значений автонумерации для всех классов, использующих данный миксин. Если атрибут объявлен как автонумерующийся и в миксине, и в классе, то будет использована настройка класса.

Создание окружения автонумерации#

Для создания окружения автонумерации по классу:

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

  2. Откройте список классов

  3. Перевидите фокус на целевой класс
    Для данного класса должен стоять признак «Есть автонумерация»

  4. Выполните операцию «Создать структуры автонумерации»
    Данная операция находится под молоточками.
    При этом произойдет вызов метода *Dpi.autoNumCreateTable

Для создания окружения автонумерации по атрибуту класса:

  1. Откройте карточку класса

  2. Переведите фокус на целевой атрибут

  3. Выполните операцию «Создать структуру автонумерации»
    Данная операция вызывает метод *Dpi.autoNumCreateTableByAttr

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

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

Проектные настройки хранятся в БД и не сбрасываются при установке обновлений.

Для выполнения проектного переопределения:

  1. Зайдите в карточку класса

  2. Выберете автонумерующийся атрибут

  3. Откройте закладку «Настройки автонумерации»;

  4. На панели открытой закладки нажмите кнопку «Переопределить»

  5. Настройте разрезы и маску;

  6. Выполните операцию создания окружения нумерации.

Настройка счетчиков и данных разрезов.#

Если автонумерация без разрезов, то она и без заполнения пропусков. Счетчик такой автонумерации хранится в сиквенсе.

Автонумерация с разрезами хранит свои данные в двух таблицах:

  • Таблица разрезов
    В этой таблице на каждый уникальный набор значений разрезов хранится значение счетчика, маска, признак, что есть пропуски

  • Таблица пропусков
    Для каждого разреза (ссылка на таблицу разрезов) хранит информацию о имеющихся пропусках. В виде пар значений: «значение от» и «значение до»

Таким образом для изменения текущего значения счетчика для автонумерации без разрезов достаточно изменить значение сиквенса.

Для автонумерации с разрезами чтобы изменить счетчик нужно установить значение в таблице разрезов. Для настройки:

  1. Зайдите в карточку класса

  2. Выберете автонумерующийся атрибут

  3. Откройте закладку «Настройки автонумерации»

  4. Откройте закладку «Данные автонумерации»

  5. Настройте значение счетчика:

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

  7. Если автонумерация с разрезом, то на детальной закладке будут отображены данные из таблицы разрезов и таблицы пропусков. Для изменения счетчика в нужном разрезе указывается значение поле «Максимальное значение». Если разреза нет, то его можно создать. Если удалить разрез, то автонумерация начнется с 1 для этого разреза.

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

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

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

На уровне класса копирование настраивается свойством isCopyObjectEnabled

На уровне атрибута свойством isCopyInCopyObject

В случае, если на классе включено копирование:

В мастер-выборке EntityAvi#Default создана операция «Копировать», пустая и не активная по умолчанию. Для классов с включенным свойством isCopyObject операция будет содержать исполняемый код, в отображении List операция будет активна.

В отображении 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 атрибут будет копироваться в методе copyObject. По умолчанию не копируются системные атрибуты:

  • 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 - системное имя корня группировки класса

    <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" />
    
  4. Добавьте в набор коллекций класса развязку групп

    <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. Выполните операцию «Открыть группы»
    При этом слева откроется панель с деревом групп.

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

Сервис прикрепленных файлов#

Сервис прикрепленных файлов позволяет прикреплять к объектам класса произвольные файлы, которые сохраняются в специальном хранилище на сервере и сопоставляются с конечным объектом-владельцем.

Файловое хранилище#

Global3-Framework позволяет классифицировать места хранения файлов по функциональной принадлежности. Для этой цели используется справочник файловых хранилищ системы.

Файловое хранилище может быть локальным или сетевым. Локальное хранилище располагается в локальной директории сервера приложений. Сетевое хранилище использует SMB протокол.

Перед работой с файлами необходимо настроить файловые хранилища. Для открытия списка настроек:

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

  2. Выполните пункт меню Сущности > Файловые хранилища

Минимально в системе должно быть настроено два файловых хранилища:

  • Default – хранилище по умолчанию

  • btkAttach – хранилище прикрепленных файлов

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

  • Файл в хранилище загружается только один раз

  • копирование объектов системы, связанных с файлом, не создают

  • физическую копию файла, а создают символическую ссылку на файл (btk_attachitem).

Существует два режима работы прикрепленных файлов:

  • Простой

  • Версионный

Простое хранение файлов#

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

Для режима простого хранения файлов доступны операции:

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

  • Удаление
    Удаляется запись из закладки. В случае, если запись отмечена как основная, произойдет удаление файла из хранилища.

    Внимание

    Операция удаления записи из хранилища необратима

  • Скачать файл
    Из хранилища скачивается файл с именем и расширением, указанным в записи.

  • Сделать файл основным
    Для записи устанавливается флаг «Основной». Для записи, которая была основной до этого, флаг снимается.

При копировании родительской записи, так же копируются записи прикрепленных файлов, без флага «Основной».

Версионное хранение файлов#

Версионирование прикрепленных файлов позволяет сохранять историю изменений. Если включен режим версионирования, любое изменение файла приводит к созданию новой версии.

В режиме версионного хранения доступны операции обычного хранения, а также ряд дополнительных:

  • Добавить новую версию
    К записи добавляется новая версия. При этом предыдущая версия остается в хранилище.

  • Удалить последнюю версию
    Из хранилища удаляется последняя версия файла. В случае, если версия только одна, будет предложено удалить запись.

    Внимание

    Операция удаления записи из хранилища необратима

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

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

Настройка#

По умолчанию сервис прикрепленных файлов для класса отключен. Для подключения необходимо в odm файле в настройке класса указать тип хранения – обычный или версионный

<class xmlns="http://www.global-system.ru/xsd/global3-class-1.0"
       name="Gds_ControlDoc"
       caption="Документ контроля"
       cardEditor.representation="Card"
       listEditor.representation="List"
       viewOptions.openCardType="mdi"
       supertype="document"
       attachType="versioned"/>

При генерации avm файла в отображение List и Card, а также для классов с иерархией в отображение tree добавится закладка «Прикрепленные файлы»

Поиск по шаблону#

Поиск по шаблону - серверная возможность поиска объектов класса по частичному или полному совпадению введенного текса со значениями полей объекта или его заголовка и мнемокода.

Поиск регистронезависимый.

Алгоритм работы поиска#

  1. Определяются поля, по которым требуется осуществлять поиск, и их приоритет.

  2. Выполняются последовательно запросы пока не получен результат в виде одной записи

    1. по всем полям в порядке приоритета ищутся значения по полному совпадению введенного текста (=)

    2. по всем полям в порядке приоритета ищутся значения по частичному совпадению введенного текста (like)

  3. Возвращается результат
    Результатом поиска является первый запрос который вернул одну запись, или первый запрос который вернул данные.

По умолчанию для класса включен поиск по шаблону, и осуществляется по служебным полям sheadline_dz и smnemocode_dz. Сначала по заголовку, потом по мнемокоду.

Настройка поиска для класса#

В odm-файле для класса добавить тег patternSearch

<class>
	<patternSearch isActive="true"
	               headLineOrder="100"
	               mnemoCodeOrder="200"
	               searchType="startsWith"
	               indexHlMc="true"/>
</class>

Описание настроек:

  • isActive
    Активность поиска по шаблону на классе. Если выключено, то функция поиска по шаблону будет возвращать 0 записей. Умолчательное значение = true

  • headLineOrder
    Порядок поиска по служебному полю sheadline_dz. Умолчательное значение = 1. Чем меньше значение, тем выше приоритет описка по этому полю. Поля с наименьшими значениями порядкового номера обрабатываются в первую очередь.

  • mnemoCodeOrder
    Порядок поиска по служебному полю smnemocode_dz. Умолчательное значение = 2. Логика обработки как в headLineOrder

  • searchType
    Тип поиска:

    • по началу слова(по умолчанию)
      like с правым %

    • по вхождению
      like с правым и левым %

  • indexHlMc
    Индексировать поля sheadline_dz и smnemocode_dz. При включенном свойстве будут созданы индексы по этим поля в верхнем регистре.

Настройка поиска по атрибутам#

  1. Откройте odm файл

  2. Добавьте тэг patternSearch для нужного атрибута
    Если тег добавлен, то атрибут участвует в поиске по шаблону.

     <attr name="sText"
           attribute-type="Text"
           type="basic"
           order="130"
           caption="Text">
       <patternSearch order="10"
               searchType="contains"/>
     </attr>   
    

Описание настроек:

  • order
    Порядковый номер поиска по полю этого атрибута.
    Нумерация сквозная по классу, т.е. можно настроить, чтобы атрибут обрабатывался раньше заголовка и мнемокода.

  • searchType
    Тип поиска:

    • по началу слова(по умолчанию)
      like с правым %

    • по вхождению
      like с правым и левым %

Перекрытие метода поиска#

Метод реализован в одном из рутовых API:

ru.bitec.app.gtk.eclipse.rdb.SEntityBaseApiImpl#findByPattern

В наследниках его можно перекрыть, и написать свою логику поиска по шаблону.

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

Характеристика – это качественное или количественное свойство объекта. Характеристиками в системе являются специальные атрибуты, которые содержат дополнительную пользовательскую информацию. Система может хранить характеристики двумя способами:

  • Хранение в json контейнере объекта
    Этот способ является основным. Представляет собой NOSql расширение строки таблицы, что позволяет добавлять характеристики динамически, без пересборки проекта и обновления схемы базы данных.

  • Хранение в виде атрибута класса с признаком «объектная характеристика» \
    В некоторых случаях характеристики используются в высоконагруженной бизнес-логике, что не позволяет использовать json контейнер. Для снижения накладных расходов доступа к данным характеристика может хранится в колонке таблицы класса. При добавлении характеристик, которые хранятся в атрибуте класса требуется синхронизация схемы БД.

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

Для вывода характеристик используется универсальное отображение объектных характеристик. За необходимость генерации отображения отвечает настройка в Оdm objectAttrCardType Варианты настройки:

  • None
    Объектные характеристики не используются, отображение Card_ObjectAttr не формируется

  • Simple
    Объектные характеристики настраиваются в классе или на типе объекта. Если у класса есть тип объекта, то характеристики настраиваются на типах объекта этого класса. Если у класса нет типа объекта, то выводятся все объектные характеристики.

  • Group
    Объектные характеристики настраиваются для групп

  • GroupAndObjectType
    Объектные характеристики настраиваются для групп и дополняются характеристиками, настроенными на типе объекта.

Отсутствие настройки равнозначно

objectAttrCardType="simple" 

В отображение объектных характеристик выводятся значения атрибутов, настроенных в качестве объектных характеристик класса. Характеристики хранятся в системном json атрибуте jObjAttrs_dz, а также в атрибутах класса с признаком: isObjectAttr="true" 

Так же в этом отображении выводятся и универсальные характеристики (См. главу Универсальные характеристики в Документация по модулю btk)

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

Пользователь может добавить необходимые характеристики в карточке класса. Для этого:

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

  2. Выполните пункт меню Сущности > классы

  3. Перейдите на закладку атрибуты

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

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

    Примечание

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

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

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

    • Даты начинаются с d. Например, dDateAttrName

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

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

  7. Сбросьте кэш настройки
    Для на текущей закладке атрибутов выполните операцию Сбросить кеш настройки

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

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

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

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

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

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

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

Программное переопределение возможно в методе

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);

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

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

  • true
    Проверка пройдена

  • false
    Проверка не пройдена. Выводится ошибка, указанная в карточке правила

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

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

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

Примечание

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

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

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

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

Определение правил проверки для сущности осуществляется в детализации Правила проверки значений в соответствующей закладке приложения:

  • На тип объекта
    Объектные характеристики в пункте меню Сущности > Типы объектов \ Типы объектов

  • На группу
    Атрибуты группы в интерфейсе редактирования группы

Примечание

Так как правила кэшируются на загрузке выборки, при любых изменениях правил (добавлении новых, удалении или переопределении существующих и пр.) НЕОБХОДИМО переоткрывать выборку.

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

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

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

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

Аудит#

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

Аудит ведется в рамках бизнес-объектов и классов, входящих в БО. Для нужд аудита используется отдельная схема в БД, Для БО в схеме Aud формируется таблица с именем <Имя класса-шапки БО>_dzAud в табличном пространстве, указанном в настройке модуля btk Табличное пространство аудита (по умолчанию pg_default), в которой хранятся данные аудита. Подробнее о структурах аудита БД.

Внимание

Если в классе включен аудит, а в классе-шапке БО, в который входит этот класс – не включен или у него не синхронизирована структура аудита, аудит не будет сохраняться. Класс-шапка БО для объекта класса определяется через системное поле gidRoot_dz

Настройка:

  1. Зайдите в приложение Настройка системы

  2. Откройте список классов
    Пункт меню Сущности > Классы

  3. Выберите требуемый класс

  4. В закладке Характеристики установите признак Вести аудит

  5. Если класс не является шапкой БО, включите аудит для шапки БО

  6. Для класса шапки БО выполните операцию Создать оболочку аудита
    При этом произойдет создание таблицы аудита в схеме аудита

  7. Сбросьте shared кэш
    Для этого выполните пункт меню Сервис > Управление решением  > Очистить кэш ORM(shared кэш)

    Внимание

    Для того чтобы аудит вступил в силу, пользователь должен переоткрыть форму

Просмотр данных аудита:

  • В карточке объекта по пункту меню: Информация > Аудит объекта

  • В списке объектов класса из контекстного меню Информация > Аудит

  • Общий список аудита Настройка системы \ Аудит > Аудит

Методы работы с аудитом:

  • Btk_AuditPkg().isEnabledAudit
    Признак, что аудит ведется

  • Btk_AuditPkg().isEnabledAudit()
    Сеттер, для изменения признака ведения аудита в сессии

  • Btk_AuditPkg().insertRow
    создать запись в аудите.

Перенос существующих таблиц аудита в указанное табличное пространство:#

Для обновления табличного пространства:

  1. Зайдите в приложение Настройка системы

  2. Откройте настройки модуля btk
    Пункт меню Настройки и сервисы > Настройки модулей системы > Общие настройки модулей

  3. Выберите настройки модуля btk

  4. В настройке Табличное пространство аудита укажите желаемое табличное пространство

  5. По операции под молоточками Скачать файл со скриптом переноса таблиц аудита скачайте скрипт sql и запустите на выполнение

Автоматическая генерация штрих-кодов объекта#

Сервисная возможность при вставке объекта класса формировать ему штрихкод.

Для этого в Оdm в теге Class есть свойство barCodeObjectTypeName в качестве значения указывается системное имя объектов класса Bs_BarCodeObjectType.

Для регистрации новой записи используется метод

Bs_BarCodeObjectTypeApi().register

Описание работы маски#

В случае, если в маске указано: 001-[counter]

При этом:

  • Длина штрихкода составляет 10 символов.

  • Следующее значение счетчика: 12

Итоговый штрихкод:

001-000012

Подписи объектов для печати#

Сервисная возможность указания типа подписей объекта. Используется при печати отчетов. Позволяет формировать в печатной форме список лиц с местом для подписи.

Список подписей настраивается в коллекции для печатной формы. Список может быть переопределен у объекта. Для хранения подписей печатных бланков используется json-контейнер jSign_dz.

Приоритет отображения данных по типу подписи:

  1. Данные по типу подписи, хранимые в атрибуте объекта класса jSign_dz (формируется для всех классов)

  2. Данные из настроек подписей в отчете.

При печати отчета, если удалось определить сохраненные подписи объекта, то будут переданы настройки подписей на самом отчете.

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

Данные подписей передаются в параметр SIGNDATA_DZ. Представляют собой json-объект с ключами:

  • idComission – идентификатор комиссии.
    Определяется через тип объекта и подразделение.

  • data – массив подписей объекта
    Каждый элемент представляет собой json-объект, на каждый тип подписи. Описание полей json-объекта подписи:

    • idBlankSignType – ИД типа подписи

    • idBlankSignTypeMC – системное имя типа подписи

    • idBlankSignTypeHL – наименование типа подписи

    • sPosition – должность

    • sFIO – Фамилия Имя Отчество

    • sBasisDocument – Документ-основание

    • dDate – дата подписи

    • idDepartment – ИД подразделения

    • idDepartmentMC – код подразделения

    • idDepartmentHL – наименование подразделения

    • nOrder – Порядковый номер подписи комиссии

Для работы с атрибутом jSign_dz реализован API в пакете Bs_ObjectSignPkg

В случае, если для класса задан тип объекта для работы с подписями можно воспользоваться стандартной закладкой ru.bitec.app.bs.sign.Bs_ObjectSignAvi.List_Master

Полнотекстовый поиск#

Сервисная возможность класса осуществлять быстрый поиск по значению атрибутов класса.

Данные классов хранятся в индексе полнотекстового поиска в схеме fts:

  • Btk_FtsReg – индекс объектов классов

  • Btk_FtsWords – индекс используемых слов.

Форма поиска доступна в главном меню приложений, в меню «Сервис»

Настройка#

Для включения полнотекстового поиска в Odm установить свойство класса fts.Enabled в значение true

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

Для переопределения поиска по атрибуту используется свойство fts.Enabled

Обновление индекса#

После обновления кода на проекте и вызова ssh-команды init Data происходит анализ классов. Если настройки класса изменились (класс стал индексируемым или добавились новые индексируемые атрибуты, которые до этого не индексировались. Новые атрибуты не учитываются). Происходит планирование обновления индекса для всех объектов класса.

При изменении объектов классов и сохранении в БД (session.flush()), которые индексируются, или на которые ссылаются объекты индексируемых классов, эти объекты добавляются в лог измененных объектов индекса.

Значения ссылочных полей хранятся в строковом виде, и определяются как значение поля sHeadLine_dz ссылочного объекта.

В системе зарегистрировано задание «Синхронизация полнотекстового индекса», которое обновляет индекс. Это задание анализирует таблицу измененных объектов и таблицу измененных классов, сохраняет эти данные в общую очередь на индексацию, вычисляет и обновляет данные индекса.

Команды строки поиска#

Формат описания:

  • Введенная строка
    Логика обработки

Команды:

  • Цепь
    Найдет текст, в котором присутствует слово цепь, цепи, цепью и тд.

  • цепь звено
    Надет текст, в котором присутствуют оба слова и их склонения

  • Цепь И звено
    Тоже самое, что и цепь звено. Пробел считается оператором «И»

  • Цепь & звено
    Тоже самое, что и цепь звено

  • Цепь ИЛИ звено
    Надет текст, в котором присутствует одно из или оба слова и их склонения

  • Цепь | звено
    Тоже самое, что и цепь ИЛИ звено

  • Цепь И (Звено ИЛИ Кольцо)
    Найдет текст, в котором есть слово цепь и одно из слов звено или кольцо

  • Цепь#40
    Надет текст, в котором есть похожие на цепь слова, например, цеп. Число после # показывает точность поиска, от 1 до 100. Где 100 – полное совпадение

  • #Цепь
    Тоже самое, что и Цепь#40

  • Цеп*
    Найдет текст, слова в котором начинаются на цеп. Например, цепь, цепная и тд.

Пообъектный доступ#

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

Права выдаются ролям и пользователям.

Пользователи, замещающие других, обладают правами замещаемых пользователей.

Права на объекты выдаются в виде группы доступа (Btk_RlsAccessGroup), на каждый объект для пользователя или роли может быть только одна группа.

Управление правами#

Для управления правами в интерфейсах выборок используется библиотека Btk_RlsLib, и ее методы:

  • manageAccess
    Операция для стандартных выборок, вызывает интерфейс настройки прав для всех выделенных строк. Определяет объекты через поля gid или id/idClass

  • manageAccessByGid
    Открывает интерфейс настройки прав по одному переданному объекту

  • manageAccessByGidList
    Открывает интерфейс настройки прав по перечню объектов

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

Для выдачи прав в бизнес-логике используются методы пакета Btk_RlsPkg:

  • grantToUsers выдача прав пользователям

  • revokeFromUsers – отзыв прав у пользователей

  • grantToRoles – выдача прав ролям

  • revokeFromRoles – отзыв прав у ролей

Удаление администрируемых объектов.#

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

  • clearByObject

  • clearByObjectList

Проверка наличия прав на объекты#

Для проверки прав в запросах можно использовать таблицу Btk_RlsUserRightsFlat, при построении запроса необходимо использовать exists по gidObj и idUser

Для проверки прав в бизнес-логике используются методы пакета Btk_RlsPkg:

  • getAccessByObject

  • getAccessByObjectList

Сервис универсальных коллекций#

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

Для этого во всех Dpi методах удаления вызывается

Btk_UniversalTabPkg().deleteManualCollections(rop.gid)

При удалении записи в которой есть коллекции доступно 2 варианта действий:

  • Каскадное удаление
    Удаляются все записи коллекций, ссылающиеся на удаляемую запись

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

Подключение из приложения#

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

  2. Выполните пункт меню Сущности > Классы

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

  4. Перейдите на закладку Коллекции
    На данной закладке отображаются все коллекции класса, а также есть возможность добавить универсальную коллекцию

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

    Внимание

    Ссылочность возможна только для атрибутов с типом данных Long и типом RefObject с указанным классом для ссылочности или с типом данных Varchar и типом RefAnyObject. Ссылочность поддерживается в том числе и для проектных атрибутов и объектных характеристик, хранящихся в json контейнере jObjAttrs_dz

  6. При необходимости настройте «Действие при удалении»

  7. При необходимости «Удалите коллекцию»
    Удаление из списка доступно только для коллекций, добавленных вручную

  8. Сбросьте кэш Btk_ClassCollection является классом попадающим в кэш, после подключения новых коллекций необходим сброс объектного кэша

Внимание

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

Подключение из прикладного кода#

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

Btk_ClassCollectionApi().register(
  idpBtkClass: NLong, 
  idpRefClass: NLong, 
  idpRefAttr: NLong, 
  spDelAction: NString
): ApiRop

Доступные действия содержатся в объекте

Btk_ClassCollectionApi

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

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

Для работы системы с денормализацией древовидных классов реализован трейт (trait) TreeDenormApi (ru.bitec.app.btk.denormalization.TreeDenormApi). Данный трейт предоставляет функциональность создания/обновления/удаления денормализации по объектам из класса-дерева.

Пример: Пусть название класса-дерева будет Btk_TreeExample.

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

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

  • id

  • idClass

  • idParent

  • idChild

  • nParentLevel.

Для даного примера название такого класса Btk_TreeExampleDenormalization.

После создания класса Btk_TreeExampleDenormalization необходимо подключить к его Api трейт TreeDenormApi.

Затем имплементировать абстрактный метод masterTableName, который должен возвращать имя таблицы хранения класса-дерева Btk_TreeExample.

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

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"

Далее нужно запланировать событие заполнения денормализации. Обычно это делают в Api основного класса (Btk_TreeExample) в методе установки ссылки на предка предположим setidParent и в методе insert на случай, когда родительская запись остается пустой. В таком методе нужно вызвать

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

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

Также необходимо удалять денормализацию при удалении записи из основного класса. Обычно это делают в методе delete. В нём нужно вызвать метод

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

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

Также возможно обновление/удаление денормализации непосредственно в момент редактирования, а не после сохранения, однако такое использование замедлит работу сервиса, и оно не рекомендовано. Методы прямого обновления/удаления:

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

Примечание

Реализацию можно посмотреть в Bs_DepartmentTreeApi в связке к Bs_DepartmentApi.

Настройки приложения#

Настройки приложения позволяют задовать глобальные константы Для получения значения настройки используйте функцию

Btk_AppPropertiesTypeApi.GetbValue(  
  sType //- Системное имя настройки  
  idObjectType //Тип объекта  
) //возвращает true или false

Btk_AppPropertiesType#

Таблица настройки приложения, содержит поля:

  • sSysName - Системное имя

  • sCaption - Наименование

  • sDescription - Описание

  • idModule - Модуль

Btk_AppProperties#

Таблица значений настроек приложения, содержит поля:

  • idType - Настройка

  • idObjectType - Тип объекта

  • bValue - Значение boolean

  • nValue - Значение number

  • sValue - Значение string

  • dValue - Значение date

Вставка изображений в прикреплённый файлы типов word и pdf#

Для вставки изображений в прикрепляемые файлы документа необходимо настроить нужные изображения в коллекции-расширении(Настройки вставки изображений) к типу объекта этого документа.

В коллекции доступны следующие настройки:

  • Активность Данное поле отвечает будет ли вставленные изображения в прикрепляемый файл

  • Печатная форма В поле указывается печатная форма с типом jasper и форматом png, которой будет передан только один аргумент «IDDOC» - id документа.

  • Изображение Файл изображение в формате png

    Примечание

    В случае указания печатной формы как источник изображения файл изображения будет удалён. Если сначала будет указана печатка то при загрузке файла изображения, удалена будет ссылка на печатную форму.

  • Положение изображения по осям XY Поля отвечают за положение изображение внутри PDF документа, точкой отсчёта является нижний левый угол

  • Ширина и высота изображение Поля отвечают за размер изображения Как только в коллекции-расширении настройки изображений будет активное изображение для вставки, в отображении прикреплённых файлов к документу данного типа объекта станут активны операции для вставки данных изображений в один документ или вовсе сразу.

Справочник параметров#

Для создания локальных коллекций с параметрами класса реализован трейт (trait) Prm_ParamCalcApi (ru.bitec.app.prm.techparam.Prm_ParamCalcApi) и абстрактное отображение Prm_CalcTechOpParamAbsAvi (ru.bitec.app.prm.techparam.Prm_CalcTechOpParamAbsAvi).

Prm_ParamCalcApi#

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

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

  • idTechParameter - Ссылка на параметр Prm_TechParameter

  • idRefTable - Ссылка на таблицу значений параметров Prm_RefTable

  • nValue - Числовое значение

  • sValue - Строковое значение

  • dValue - Значение даты

  • bManualInput - Параметр заполнен вручную

Для использования функционала необходимо в Api нужного класса отнаследовать данный трейт и переопределить геттеры(сеттеры) параметров, Api родительского класса. Пример:

class Mnf_MCOperParamApi extends Mnf_MCOperParamDpi[Mnf_MCOperParamAro, Mnf_MCOperParamApi, Mnf_MCOperParamAta] with Prm_ParamCalcApi[EntityAbst, java.lang.Long, Mnf_MCOperParamAro] {
  override protected def entityAta: Mnf_MCOperParamAta = Mnf_MCOperParamAta

  override lazy val apiParent = Mnf_MCOperApi().asInstanceOf[SApi[AnyRef, Aro[_ <: AnyRef]]]

  override def getsValue(rop: ApiRop): NString = rop.get(_.sValue)
  override def getnValue(rop: ApiRop): NNumber = rop.get(_.nValue)
  override def getdValue(rop: ApiRop): NDate = rop.get(_.dValue)
  override def getidValue(rop: ApiRop): NLong = rop.get(_.idValue)

  override def setidTechParam(rop: ApiRop, value: NLong): Unit = setidTechParameter(rop, value)
  override def getidTechParam(rop: ApiRop): NLong = rop.get(_.idTechParameter)

  override def getidRefTable(rop: ApiRop): NLong = rop.get(_.idRefTable)

  override def getidCalcFormulaByParent(ropParent: AnyRop): NLong = ropParent.asInstanceOf[Mnf_MCOperApi#ApiRop].get(_.idCalcFormula)

  override def isManualInput(rop:ApiRop): Boolean = rop.get(_.bManualInput).toBoolean

}

Если в вашем классе не используются какие-либо из этих атрибутов, то их сеттеры и геттеры можно переопределить на Unit() и null-значение соответственно.

Функция isManualInput используется для выбора параметров, значения которых будут рассчитаны в функции refreshParamValByParent.

Дополнительные возможности:

  • setParamValueRichAnyRef - простановка значения параметра RichAnyRef(value)

  • getParamValue - получение значения параметра

  • clearAllValues - очищает значения параметра

  • fillByParent - заполнение параметров по формуле от родителя

  • getsParamsCodeAndValueByParent - возвращает строку со значениями параметров вида (код параметра: значение)

Prm_CalcTechOpParamAbsAvi#

Абстрактная Avi содержит в себе два функциональных трейта:

  • Default_Calc - Для расчета по формуле, параметры не хранятся

  • SavedParamsCalc - Для коллекций с хранимыми значениями, можно использовать в паре с трейтом Prm_ParamCalcApi

Default_Calc#

Примечание

Пример использования - Mct_TechOpParamAvi.List_idOperCardOperationForCalculate

В интерфейсе: Управление данными об изделии (Судостроение) -> Технология -> Справочник операционных карт (Mct_OperCardAvi.list) -> Закладка Операции -> Проверка формул по параметрам

Для использования необходимо отнаследоваться от данного отображения и переопределить методы getFormula (получение формулы) и getParams (получение параметров).

SavedParamsCalc#

Аналогично трейту Prm_ParamCalcApi переопределяются сеттеры значений, а также функции onRefresh, onRefreshItem и getAdditionalInfo

Примечание

Примеры использования:

ru.bitec.app.mnf.manufCard.Mnf_MCOperTestParamAvi.List_idMcOper

ru.bitec.app.mct.techproc.Mct_TechProcNormGroupParamAvi.List_idTechProcNorm

Необязательная функция refreshValues - заполнение параметров (по умолчанию active = false) - для вызова функции заполнения параметров refreshParamValByParent трейта Prm_ParamCalcApi и/или своего необходимого функционала