# CSP 2 для разработчика

# Фреймворк Morphcluster 2

MorphCluster - это система организации структуры и взаимодействия внутри системы из множества процессов.
Задачи системы:


Автоматическая организация связи внутри системы. MorphCluster находит и организует связь между различными частями системы в микросервисной архитектуре.


Организация внутреннего контура. Разделение системы на внешний и внутренний трафик. Внешний трафик должен быть с защищен от злоумышленников, тогда как взаимодействие между доверенными частями системы должно происходить максимально быстро.


Отслеживание состояния системы - позволить следить за тем, как работает система, выявлять и локализовать ошибки и зависания в реальном времени


Тестирование. Система позволяет запускать отдельные части системы, чтобы проверить их работу, в процессе работы всей системы


*** Масштабирование


*** Модульность и взаимозаменяемость


*** Возможность дробления и слияния модулей

*** Возможность защиты исходного кода


# Структура ядра

## Сервис
Сервисы определяют неделимую единицу функционала приложения.

Имя сервиса идентифицирует его в системе и должно быть уникально.

Сервис, определенный, как локальный будет доступен только в пределах своего хоста. На разных хостах могут быть одноименные локальные сервисы. Локальные сервисы недоступны другим хостам

Сервис имеет состояние, показывающее, когда он будет готов к работе. В случае сбоя — сервис может сообщить о невозможности продолжить работу, и о восстановлении такой возможности (например, подключение к базе).
Для выполнения инициализации своего сервиса нужно перегрузить метод `start`.

```javascript
import {Service} from "@morphcluster/core"
export default class Test extends Service {
  async start() {
    console.log("Starting")
  }
}
```

`stop` работает по аналогии

<span lang="ru-RU">Запросы</span><span lang="ru-RU"> позволя</span><span lang="ru-RU">ют</span><span lang="ru-RU"> выполнять </span><span lang="ru-RU">специализированное действие</span><span lang="ru-RU">, </span><span lang="ru-RU">для управления сервисом или получения данных из него или с его помощью</span><span lang="ru-RU">.</span>

<span lang="ru-RU">События вызываются изнутри сервиса и другие сервисы могут быть на него подписаны, </span><span lang="ru-RU">для с</span><span lang="ru-RU">оздания действия, во </span><span lang="ru-RU">врем</span><span lang="ru-RU">я выполнения события</span><span lang="ru-RU">.</span>

Управления хостом. Сервис имеет ограниченный интерфейс, для того чтобы определять, какие сервисы, которые находится на одним с ним хостом запущены, и для получения прямого доступа к этим сервисам.

Поучить запущенный сервис вручную из `ServiceHost` можно через метод `requireService`. Если сервис не закончил запуск, он не вернется.
 
<span lang="ru-RU">Т</span><span lang="ru-RU">акже это позвол</span><span lang="ru-RU">яет</span><span lang="ru-RU"> сервис</span><span lang="ru-RU">ы</span><span lang="ru-RU"> запускать дочерние сервисы, которые создаются внутри сервиса а также отслеживать состояние тех сервисов которые нужны для работы текущего сервиса.</span>

Зависимости сервиса - это имена сервисов расположеных локально (на одном хосте с описываемым), которые необходимы для корректной работы описываемого сервиса. Они будут запущены до запуска текущего сервиса, и автоматически подключены.

Чтобы объявить зависимости сторонние сервисы в своем сервисе, можно наследовать свой класс от `ServiceRequire`.
Перед запуском, `ServiceRequire` дождется запуска всех своих зависимостей.

```javascript
import {ServiceRequire} from "@morphcluster/core"

export default class HelloWorlds extends ServiceRequire {
  constructor(host) {
    super(host)
    //Объявление поля для ссылки на зависимый сервис
    //Для работы подсказок внутри IDE и лучшей читаемости кода
    /** @type {Test} */
    this.HelloWorld = null
    //Список зависимостей
    this.requrements = [ "HelloWorld" ]
  }
  async start() {
    await super.start()
    //Вызов метода из другого сервиса, после super.start
    await this.Test.test({}, "common", null)
  }
}
```

Клиент – это способ взаимодействия между сервисами, который описывает схему сервиса, которая нужна текущему сервису, в котором он объявляен. <span style="font-style: normal;">К</span><span style="font-style: normal;">лиент позволяет организовывать зависимости с удаленными сервисами расположенными на другом хосте, также если клиент ссылается на сервис того же хоста, то вызов будет налажен без использования транспорта</span>

<span style="font-style: normal;">Таймер позволяет удобно запускать периодические д</span><span style="font-style: normal;">ействия</span><span style="font-style: normal;"> внутри сервиса, инициированные с определенным промежутком времени. </span>

<span lang="ru-RU"><span style="font-style: normal;">Триггер позволяет инициировать внутри сервиса д</span></span><span lang="ru-RU"><span style="font-style: normal;">ействие</span></span><span lang="ru-RU"><span style="font-style: normal;">, например, в случае получения запроса из внешней системы. Основные компоненты системы.</span></span>

### Хост
Корневой модуль запускаемый в процессе, который хранит остальные сущности и и управляет запуском системы.
***Разделение системы на хосты***
***Готовые модули***

```javascript
 import {ServiceHost} from '@morphcluster/core'
 host = new ServiceHost()      
 host.addService(new HelloWorld(host))
```

### Транспорт
Транспорт - абстракция для определения способа взаимодействия между хостами

### Контекст
Контекст определяет и идентифицирует действия в системе, и позволяет отслеживать ход их выполнения, в процессе которого может вызыватся действия в разных частях системы, в т.ч. в другом хосте.

- Монитор выполнения - позволяет понять в каком сейчас состоянии находится данный контекст, также можно понять где он сейчас находится
- Журнал выполнения - позволяет отслеживать действия которые были завершены, и просматривать отладочные данные
- Прерывание. По данным идентификации контекста можно послать сигнал прерывания, который сообщит внутрь действия том, что действие надо прервать, вызвав исключение.
- Информация о вызове. Внутри контекста хранится информация о том, кто создал этот контекст
- Данные о пользователе, если это внешний вызов. Это позволяет ограничивать доступ к системе и данным.

### Схема сервиса
Схема сервиса - это структурированные данные, описывающая сервис для взаимодействия между ними и визуализации сервисов. Она описывает все способы взаимодействия с сервисом для внутреннего контура.

Схема используется для передачи между хостами, возможностей сервисов.

Схема описывается через json такого вида:
```javascript
{
    name:"MyService",
    requests: [
        {
            name:"run",
            http: 'POST',
            request:{
                "type": "object",
                "properties": {
                    "name": { "type": "string" },
                    "params": {},
                },
                "required": [ "name" ]
            },
            response:{},
            description:"Выполнить метод",
        }
    ]
}
```

Схему целиком можно установить через метод `setSvcSchema(serviceSchema)`. Через метод `getSvcSchema()` можно получить текущую схему, вместе с добавленными изменениями отдельно.

### Исключения
В отличии от стандартных исключений, исключения в фреймворке лучше вызывать классом `ComplexError`:
```javascript
import { ComplexError } from '@morphcluster/core'
...
const name = "Test" //Имя исключения
//Дополнительные данные исключения в виде объекта (опционально)
const payload = { "mydata":123 }
//Опции
const options = {
  //Показывать ли внешнему серверу (FastifyRest) содержимое ошибки
  //Если пользователь - администратор, содержимое все равно будет показано
  "showUser": true,
	//Можно перегрузить HTTP код возврата в FastifyRest, по умолчанию 500

  "httpStatus": 403,
  //Если цепочку логов создавали в этом методе, можно передать ее id в исключении
  //FastifyRest вернет этот ID, чтобы цепочку было проще найти
  "logId": "..."
}
throw new ComplexError( "Сообщение исключения", name, payload, options )
```
Данные внутри такого исключения будут переданы в т.ч. и удаленным сервисам

## Конфигурация

## Журналирование

# Основные сервисы ядра

### Registry
Реестр позволяет хранить данные в структурированном виде доступны любому сервису. Используются для настройки системы. В реестре для доступа данных необходимо заполнить схему реестра, отправить ее, которая заявит о необходимости заполнения этих полей и создаст для них описание и тип.
С помощью локального сервиса RegistryHelper можно легко получить актуальный реестр без обработки событий.

### Nats
<span lang="ru-RU"><span style="font-weight: normal;">NA</span></span><span lang="ru-RU"><span style="font-weight: normal;">Т</span></span><span lang="ru-RU"><span style="font-weight: normal;">S реализует транспорт через </span></span><span lang="ru-RU"><span style="font-weight: normal;">брокер.</span></span>

### Logger
Логгер хранит весь процесс выполнение контекста для отслеживания уже выполненных контекстов, выполненных запросов или иных вызовов системы.

### AdminPanel

# Сервисы шлюза

### Proxy
Единая точка входа для http и websocket

### Fastify
Один из вариантов коммуникации с клиентами и сторонними сервисами - веб сервер [Fastify](https://www.fastify.io/).
Сервис-обвертка инициализирет библиотеку fastify c расширениями: `@fastify/cors, @fastify/swagger, @fastify/swagger-ui, @fastify/multipart`.
В отличии от оригинального Fastify, сервис позволяет динамически добавлять и удалять новые маршруты без прерывания работы запущенных запросов после запуска сервера.
Также реализована плавная(greceful) остановка сервиса.

Для начала, надо добавить пакет из corelibs:
```
npm install ./corelibs/fastify
```
Пример работы с Fastify:
```javascript

import {Fastify} from  '@morphcluster/fastify'
...
//Добавление Fastify к хосту
let fastify = new Fastify( host, {"host" : "127.0.0.1", "port" : 80} )
host.addService(fastify)
...
//Добавление маршрута, в формате fastify
fastify.addRoute({...})
//Запуск пересоздания машрутов, чтобы отобразились изменения. Начатые вызовы сброшены не будут
await fastify.restart()
```
Формат для добавления новых маршрутов можно посмотреть в [официальной документации](https://www.fastify.io/docs/latest/Reference/Routes/#full-declaration)

### Gateway
Шлюз это HTTP сервер, который позволяет общаться из внешней среды с сервисами. Чтобы запрос сервиса был доступен через шлюз, надо описать его схеме, что он доступен во внешнем контуре. Также внешний контур проверяет наличие сессии. При отсутствии сессии будут работать только анонимные методы.

Чтобы публичные запросы сервисов хоста были доступны по http(s), можно воспользоваться сервисом Gateway. Он автоматически обнаружит запросы сервиса к публикации и создаст маршруты.

```javascript
import {ServiceHost} from '@morphcluster/core'
import {Fastify,FastifyRest} from  '@morphcluster/fastify'
...
//Fastify - зависимость FastifyRest
host.addService(new Fastify( host, {"host" : "127.0.0.1", "port" : 80} ))
//Добавление FastifyRest
host.addService(new FastifyRest( host ))
//Для публикации, сервис должен обязателно быть добавлен в ServiceHost
host.addService(new Test())
```
Проверить работу можно будет по ссылке `http://127.0.0.1/documentation`. Там автоматически разворачиватся OpenApi/Swagger со всеми доступными маршрутами.
Вызов, производимый извне имеет проверку доступа, при этом запросы между сервисами не замедляются этой проверки, сессия передается напрямую.

### Sessions
Сессии соответственно хранят информацию о доступе, подтвержденную токеном. Токен создается при авторизации или иным способом. Пользователю или внешнему сервису нужен токен для взаимодействия с системой через шлюз. Система через него идентифицирует пользователя. Сессия может быть определена как привилегированная(isAdmin), что расширяет возможности такого пользователя.

### Auth

### Eventer

### Bridge
<span lang="ru-RU"><span style="font-weight: normal;">Мост. Мост позволяет общаться привилегированным </span></span><span lang="ru-RU"><span style="font-weight: normal;">сессиям</span></span><span lang="ru-RU"><span style="font-weight: normal;"> с внутренним контуром, недоступным через шлюз.</span></span>

# Компоненты CSP

Компоненты CSP запускаются поверх основных компонентов и запускаются для взимодействя с информацонной системой.

#### Основные компоненты
- Document Helper это локальный сервис который организовывает удобное взаимодействие с информационными объектами внутри баз данных.
- Eventer - сервис, позволяющий системе отправлять события (в т.ч. сообщения) в клиенту через websocket, так как HTTP шлюз не поддерживает обратного взаимодействия с клиентами.
- Users
- CarabiAuth это средство авторизации, использующее внутренних пользователей информационной системы.

#### Система хранения файлов
- Хранилище файлов позволяет прикреплять файлы к информационным объектам и другим сущностям и хранить эти файлы удаленно от самой системы
- StorageMaster это сервис который управляет запросами на загрузку и отправку сообщений загрузку и отправку на сервер файлами знает где хранится файл (???)
- Storage Host - это отдельная программа которая обеспечивает хранение файлов, и непосредственно и связывается со Storage Master для взаимодействия с системой. С самой системой помимо StorageMaster StorageHost не взаимодействует. 
- СервисFiles позволяет пользователям взаимодействовать с хранилищем файлов.
- StorageHelper это локальный сервис, который помогает в получении файлов, организуя всю цепочку общения между различными компонентами хранилища файлов.
- StorageBlob -

#### Система генерации отчетов

#### Интеграции с внешними сервисами
- DaData
- Mailer
- SMS
- Uiscom
- TelegramBot
- Firebase

# Сервисы



# Система взаимодействия с СУБД

#### DbQueryPool
DB Query Pool формирует специальный пул для быстрого взаимодействия с множеством клиентов.

Каждый клиент резервирует готовое соединение с базой на момент выполнения запроса. При этом в пуле существует ограничение количества возможных занимаемых сессий на пользователя, формируется очередь выполнения запросов, если пул переполнен.

#### DbTransactions
DB Transactions организовывает способ работы с транзакцией в отдельном соединении, с возможностью ее передачи между любыми сервисами.

Соответственно сам DB Transaction организовывает соединение на каждую транзакцию и завершает это соединение по команде сервиса (или таймаутом).

#### DbMigrator
DBMigrator позволяет следить и модернизировать версии базы. Это необходимо для поддержания актуальной структуры базы в случае обновлений.

#### DbLoader
DBLoader позволяет загружать сущности, такие как функции или типы (зависит от базы данных) и поддержания их в актуальной версии, через отслеживание их хеша.

#### DbServices
DbServices позволяет описывать сервисы, расположенные в базе данных, которые реализуют вызовы с определенным, продукомментированным интерфейсом, и не зависящим от типа базы.

Также это помогает определить, какие сервисы доступны в текущей системы и тестировать их функционал.

# Супервизор и система пакетов

Это специальный хост, который запускает другие хосты для организации автономной системы, которая может работать без использования внешних систем управления процессами.
- Запуск и отслеживание состояния, пакетов, перехват вывода управляемых процессов
- Указание общего конфиурационного файла
- Установка и удаление пакетов вручную
- Проверка обновлений пакетов через сервер обновления CarabiSolutions, получение новых пакетов 

#### Пакеты
Внутри супервизор оперирует Пакетами Супервизора - это Node приложение, особой структуры, распространяемое в виде архива.

#### Сервисы супервизора

### Microservice
Microservice это специальная библиотека позволяющая быстро создать первоначальную инфраструктуру хоста для связи с основными системами основными компонентами системы и упрощающую разработки новых хостов.

# Система развертывания СУБД

Система установки базы состоит из четырех частей, которые запускаются последовательно, до запуска основных сервисов. Их можно использовать для установки различных компонентов в базу. Чтобы использовать установщики, надо добавить в хост определенный набор сервисов. При запуске хоста эти сервисы будут сканировать директории, которые располагаются внутри пакета (хоста), выполнят подключение к базе через DbTransactions и совершать установку, а также зафиксируют текущее состояние установки.

## OraMigrator

OraMigrator работает по принципу последовательной установки изменений (миграций, патчей) базы. Каждое изменение должно иметь определенный номер (версию), определяющую порядок их установки. Каждое изменение выполнятеся онднократно за всю историю базы. OraMigrator выполняет любые SQL запросы без изменений.

Сохранять изменения необходимо в директории `./ora-migrations`. Внутри этой директории можно расположить файлы двумя способами:

- Название файла должна соответствовать версии миграции `{№миграции}.sql`.
- Как альтернатива, можно создать директорию `{№миграции}`, внутри которой разместить файл index.sql.

Внутри index.sql можно перечислить файлы в этой директории, которые будут выполняться последовательно. Формат index.sql принимает только имена файлов, либо комментарии:

```
@MY_FILE_1.sql;
-- Это комментарий
@MY_FILE_2.typ;

```

А формат дополнительных файлов соответствует одиночному SQL файлу. Символ \\ **на отдельной строке** разделяет запросы:

```
SELECT ORA_DATABASE_NAME FROM DUAL
\
SELECT ORA_DATABASE_NAME FROM DUAL

```
В конце оставлять символ \\ в конце файла SQL **запрещено**

Текущее состояние базы OraMigrator хранит внутри Oracle, в таблице `MIGRATIONS`

В случае успешного выполнения миграции он заполнит новую запись об успехе. Она предотвращает повторное выполнение этого изменения.

В случае ошибки выполнения SQL, будет сделана запись с ошибкой, с указанием текста самой ошибки (колонка `ERROR`) и работа OraMigrator прервется. Повторный запуск OraMigrator найдет в таблице ошибку мигратор и сразу прервется, дабы не нарушить дальнейшую работу мигратора. После устранения ошибки надо изменить эту запись вручную и перезапустить хост.

Чтобы не подключаться к Oracle напрямую, можно, через Админ панель, использовать сервис `OraMigratorAdmin`:

- fixError, если **не требуется** повторное выполнение миграцией с ошибкой
- delError, если **требуется** ее повторное выполнение

## PkgInstaller

Если OraMigrator предназначен для выполненеия любых SQL-запросов, PkgInstaller устанавливает в Oracle такие сущности, как типы, пакеты, структуры, функции и процедуры, сверяя актуальность их версий, и не выполняя повторную установку, если версия актуальна. PkgInstaller сравнивает версии с помощью вычисления хэш-значения содержимого файла по установке сущности с записью в таблице `PACKAGE_VERSIONS`, которая осталась после предыдущей установки.

В случае необходимости принудительной переустановки сущности, необходимо удалить предыдущую запись или изменить ее хэш-значение в колонке `package_hash`.

Установочные SQL файлы необходимо размещать в директориях с определенным расширением в зависимости от типа сущности:

- Пакеты: `./ora-packages/*.pck`
- Типы: `./ora-types/*.typ`

После установки всех новых пакетов PkgInstaller запустит компиляцию новых пакетов автоматически.

## DBServiceLoader

DB-сервисы это интерфейс, схожий с сервисами, позволяющий выполнять функции внутри баз данных, абстрагируясь от вида базы данных. Каждый DB-сервис содержит методы, которые будут выполнить напрямую внутри базы данных.

Создать, ознакомится с существующими DB-сервисами, и протестировать их, можно через админ панель.

DBServiceLoader позволяет автоматически загружать DB-сервисы из файлов которые размещены в директории `./db-services/*.json`. Формат файла - JSON, который можно скачать в админ панели (предварительно создав в ней DbService вручную).

Общий список DB-сервисов формирется каждый раз при запуске, в памяти сервиса `DbServices`, и нигде не хранится.

## DockindInstaller

Его задача загрузить через ядро информационных объектов ее сущности.

DockindInstaller использует DB-сервис `PKG_XML_REPL_CS` без привязки к базе для своей работы.

Контроль версии происходит по принципу PkgInstaller. Вычисляется хэш содержимого файла и сравнивается с хешом внутри ядра (с таблицей внутри базы данных Oracle `DOCKIND_VERSIONS`).

Внутри директории нужно расположить поддиректории, совпадающей с названием категории, в которой они будут размещены в браузере ИО. В каждой поддиректории-категории нужно расположить файл `category.json`, описывающий эту категорию:

```
{
  "name":"Документация по модулям",
  "sysname":"HELP",
  "roles": ["Administrator", "Developer"]
}

```

Там же, необходимо разместить файлы с определенным названием, которые совпадают с названием типа информационного объекта:

- `{dockind}_vocabs.xml` - Словари для типа ИО dockind
- `{dockind}_types.xml` - Определение типа ИО dockind

Например, для категории `HELP` с объектами `HELP_DOC`,`SECOND`

- ./dockinds/HELP/category.json
- ./dockinds/HELP/HELP\_DOC\_vocabs.xml
- ./dockinds/HELP/HELP\_DOC\_types.xml
- ./dockinds/HELP/SECOND\_vocabs.xml
- ./dockinds/HELP/SECOND\_types.xml

# Создание нового хоста (пакета)

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

Настройка новый хост

Создание схемы сервиса

Создание сервиса

Подключение сторонних сервисов

Размещение в репозитории

Настройка системы обновления

1. Зайти в [https://carabi.csp.carabisol.ru/](https://carabi.csp.carabisol.ru/)
2. Выбрать на рабочем столе "Пакеты"
3. Создать новый пакет, заполнить "Наименование" (<span style="white-space: pre;">PKG\_NAME в build.sh</span>), "Версия" (совпадает с веткой в GIT)
4. Сохранить

Подключение автосборщика

1. Зайти в автосборщик
2. "Добавить" слева снизу
3. Id - (<span style="white-space: pre;">PKG\_NAME в build.sh</span>)
4. Url - Url из GitTea
5. Branch совпадает с веткой в GIT
6. Execs - **/bin/bash ./makepkg.sh &lt;token системы обновления&gt;**
7. Сохраняйте и нажмите "Проверка репозитория"
8. Если все успешно - в системе обновления, в пакете, во вкладке "Релизы", появится первый релиз

Тестирование

1. в системе обновления на рабочем столе "Супервизоры"
2. Выбрать супервизор для теста
3. В **"Пакеты"** добавить новый пакет (не в релизах, а именно "Пакеты")
4. Сохранить супервизор
5. Зайти в админку этого супервизора, либо дождаться автообновления
6. Там в разделе "Пакеты" нажать "Получить обновления"

# Интерфейс адмнистратора



# Физическая Организация управления БД АИС

Все данные в АИС хранятся в СУБД ORCLE. Для хранения данных используется кодировка UNICODE (UTF-8), стандарт кодирования символов, позволяющий представить знаки практически всех письменных языков. Целостность данных и обработка статусов реализована на технологии CARABI. В СУБД используются встроенные пакетные функции и триггеры для чтения и обработки данных.

**Структура ИО**

Физически данные по ИО хранятся в группе таблиц и представляют собой объект БД с возможностями создания, модификации и удаления.

**Представление структуры ИО в формате XML**

```
<!—Описание ИО>
<FORMAL DOCKIND_NAME="< Латинское наименование ИО>" DOCKIND_DESCR="<Описание ИО>">
<!—Описание статуса ИО>
<EVENT VALUE="<Наименование статуса>" ACCESS="0" NAME=" <Латинское наименование статуса>">

   <!—Описание атрибута ИО для данного статуса>
      <PROP DOCPROP_DESCR="<Латинское наименование атрибута>" DOCPROP_NOTNULL="<Обязательность заполнения>" DOCPROP_VISIBLE="<Отображение в документах>" DOCPROP_REPEAT="<Множественность атрибута>" DOCPROP_UNIQUE="<Входит в состав ключа>" DOCPROP_RULE="<Правило связи для ссылочного атрибута>">
 <!— Доступ к атрибуту для данного статуса по роли>
        <PROPPERMEVENT PERMISSION="<Код уровня доступа>" ROLEVALUE="<Описание роли пользователя>” ROLEACCESS="0" ROLENAME="<Латинское наименование роль>"/>
…
<!— Возможные переходы из данного статуса в другой статус для конкретной роли>
      <TRACE CANUSER="<Возможен переход вручную>" PERMISSION="<Код доступа к полю для текущего статуса>" ROLEACCESS="<Возможен переход>" ROLENAME="Administrator" EVENTNAME="<Латинское наименование статуса>"/>
     …
</EVENT>
…
   <!—Описание атрибута ИО для данного для всего ИО>

 <PROPERTY SHOW_ORDER="<Порядок в документе>" DOC_FORMAT="<Тип данных>" DOCPROP_NAME="<Отображаемое описание поля>" DOCPROP_DESCR="<Латинское наименование атрибута>" DOCPROP_KIND="<Подтип данных>" DOCPROP_VISIBLE="<Отображать в документах>" DOCPROP_UNIQUE="<Входит в состав ключа>" DOCPROP_NOTNULL="<Обязательное>" DOCPROP_OBJECT="<Наименование ИО для ссылок>" DOCPROP_REPEAT="<Кратность поля>" DOCPROP_MULTI="<Множественность поля>" DOCPROP_FPATH="<Путь для отображаемых полей>" DOCPROP_TREE_KIND="Иерархичность значение в этом поле"/>
    …
      </FORMAL>
    </REFERENCE>

```

```
FORMAL – описание конкретного документа
PROPERTY – поле документа и его значение
Параметры тега FORMAL
DOCKIND_NAME		Наименование справочника, системное
DOCKIND_DESCR		Наименование справочника на русском языке
Параметры тега PROPERTY (поле документа, реквизит)
SHOW_ORDER			Порядок - порядковый номер в структуре документа
DOC_FORMAT			0 (определяет формат поля и шаблон хранения данных
DOCPROP_NAME		Наименование поля на русском языке
DOCPROP_DESCR		Системное наименование поля
DOCPROP_KIND		Тип поля
DOCPROP_VISIBLE		Видимость, (1 и более - отображается; 0 – нет)
DOCPROP_UNIQUE		Если 1, то является ключевым при идентификации документов
DOCPROP_NOTNULL		Если 1, то заполнение поля обязательно
DOCPROP_OBJECT	Подтип поля (Только если DOCPROP_KIND=1 - Простое поле) - документ Экспорт XML
DOCPROP_REPEAT	0 (фиксированное значение), для диапазонов дат и чисел указывает на номер значения в диапазоне
DOCPROP_MULTI		0 – одиночное поле, более 1 множественное
DOCPROP_SQL			0 (другой шаблон, для ссылочных полей принцип связи, 1)
DOCPROP_TREE_KIND		0, 1 – Признак наличия иерархии
DOCPROP_RULE_CHILD		0 (каскадные операции для ссылочных полей)
DOCPROP_RULE_PARENT	(каскадные операции для ссылочных полей)

```

Если есть DOCPROP\_KIND=9 (ссылка), то может быть задано подчиненно описание документа, с использованием тега FORMAL, вложенного в PROPERTY &lt;FORMAL DOCKIND\_NAME=&lt;Связанный объект&gt; DOCKIND\_DESCR=&lt;Наименование связанного объекта&gt; XML\_ID="0"/&gt;

***Представление документа ИО в формате XML***

```
<!—Документ ИО>
<FORMAL DOCKIND_NAME="<Латинское наименование ИО>" DOCEVENTKIND_NAME="<Статус ИО>" >
   <!—Значение простого атрибута ИО>
   <PROPERTY DOCPROP_NAME="<Латинское наименование атрибута>">
   <VALUE DOC_PROP_VALUE="<Значение атрибута>" />
   </PROPERTY>
…
   <!—Значение ссылочного атрибута ИО>
    <REFERENCE DOCPROP_NAME="<Латинское наименование атрибута>">
      <FORMAL DOCKIND_NAME="<Латинское наименование ИО>" DOCEVENTKIND_NAME="<Статус ИО>">
        <PROPERTY DOCPROP_NAME="<Латинское наименование атрибута>">
          <VALUE DOC_PROP_VALUE="<Значение атрибута>" />
        </PROPERTY>
      </FORMAL>
    </REFERENCE>
…
      </FORMAL>
    </REFERENCE>

```

***Изменение атрибутов ИО***

Изменение атрибутов ИО производится во время работы АИС после согласования изменения БП. Остановка системы не требуется. Если в этот момент производится модификация документа пользователя, использующего данный ИО, то АИС извещает об этом и просит повторить операцию. Действия по добавлению статусов описаны в руководстве разработчика CARABI SDK.

***Добавление новых статусов***

Добавление новых статусов производится во время работы АИС после согласования изменения БП. Остановка системы не требуется. Действия по добавлению статусов описаны в руководстве разработчика CARABI SDK.

\*\*\*Поиск ИО \*\*\* Поиск ИО производится 2 способами:

- При помощи контекстного поиска документа заданного типа по наименованию документа.
- При помощи формализации запроса к системе в формате XML.

Для всех поисковых полей СУБД построены специальные встроенные ключи. Поиск в формате XML выглядит следующим образом:

```
<!—Запрос на выборку списка ИО>
<query>
 <formal namevar="APPLY_BTI">
  <operation name="and">
   <operation name="and">
    <reference referencing="Тип поиска связанных элементов " condition="" count="" dockind_id="<Код ссылочного ИО>" leftp="(" rightp=")">
     <operation name="<Тип объединения>">
      <!—-Значение подчиненного уровня>
      <property type="<Тип данных введенного критерия>" condition="<условие>" doc_prop_value="<Критерий>" namevar="<Латинское наименование атрибута>"/>
…   
      <!—Статус подчиненного уровня>
      <status namevar="<Латинское наименование статуса>"/>
…
     </operation>
    </reference>
<!—Значение коревого уровня>
    <property type="<Тип данных введенного критерия>" condition="<условие>" doc_prop_value="<Критерий>" namevar="<Латинское наименование атрибута>"/>
   </operation>
   <operation name = "<Тип объединения>">
    <!—Статус коревого уровня>
    <status doceventkind_id = "3857" namevar="<Латинское наименование статуса>"/>
…
   </operation>
  </operation>
 </formal>
</query>

```

OPERATION – Правило объединения критериев – может принимать значения

- И
- ИЛИ
- 

CONDITION – Условие выборки - может принимать значение – Равно, Содержит, Начинается с, Не содержит, Значение не указано, Значение указано, Номер документа равен, Больше, Больше или равно, Меньше, Меньше или равно, Не равно

***Организация запросов по системе***

Для формирования запросов и визуализации результатов выборки данных для отчетов и статистик в АИС организован ИО Запрос

```
Название
Тип данных
Системное наименование
Номер
Счетчик
NUM
Наименование
Текстовый
NAME
Корневой тип
Выборка из таблицы "VOCABS"
ROOT_TYPE
Список типов для доступа
Выборка из таблицы "VOCABS" [множ.]
TYPE_LIST
Вариант запроса
Значение из словаря "QueryType"
QUERY_TYPE
Текст запроса
Текстовый
SQLTEXT
Параметры для отображения
Ссылочный [множ.]
VARVAR
Группа
Значение из словаря "SystemWorks"
GROUP
Доступ пользователей
Выборка из таблицы "CLIENTS_TREE" [множ.]
QUERY-ACCESS
Доступ ролей
Выборка из таблицы "VOCABS" [множ.]
ACCESS_ROLE
Шаблон отчета
Медиа-данные
REPORT_XLS
Сгруппировать множ. значения
Да/нет
ISGROUP
Внешний вызов
Да/нет
EXTERNAL
Использовать JOB для обработки запроса
Да/нет
ISJOB
Програма для внешнего вызова
Текстовый
EXE
Параметр внешнего вызова
Текстовый
EXTERNAL_PARAMS
Выдавать системные поля
Да/нет
IS_SYS_NAME
Режим групповой(нет - одиночный - передача ID документа)
Да/нет
QGROUP
Параметры для запроса
Ссылочный [множ.]
DOCQUERY-REF-REPORTS_PARAMS
Режим отображения
Значение из словаря "QUERY_TYPE"
DISPLAY
Структура параметров
Выборка из таблицы "VOCABS"
STRUC_PARAMS
Настройка отображения
Ссылочный [множ.]
DOCQUERY-REF-DOCQUERY_FIELD

```

Текст запроса должен выглядеть как комбинация поиска и перечня полей для выдачи с описанием названия выдаваемого поля:

```
<!—Простые поля
<select docprop_id="<Код атрибута>" display="" as="<Отображение поля в запросе>"/>
…
<!—Вычисляемые поля>
<calc pars_id="<Функция расчетов>" as="<Отображение поля в запросе>"/>

```

Шаблон запроса служит для вывода данных в другие подсистемы отображения или во встроенную система отчетов FASTREPORT.

***Запрос в формате SQL***

Возможно прямое обращение к БД при помощи SQL запроса. Правило формирование запроса см. в руководстве разработчика CARABI SDK.

***Импорт и экспорт во внешние системы***

Взаимодействие с другими информационными системами осуществляется с использованием обмена XML-данными. Для загрузки и выгрузки XML используется набор встроенных средств. Для выгрузки данных необходимо настроить выгрузку через интерфейс «Выгрузка данных». Для загрузки данных необходимо сначала подготовить XML-файл в требуемом формате, а затем запустить процедуру загрузки данных через интерфейс «Загрузка данных». Без использования пользовательского интерфейса, загрузка и выгрузка данных может выполняться посредством встроенных средств, которые позволяют: выполнять чтение данных из внешних источников:

- с файловой системы сервера;
- с файловой системы клиента;
- с FTP-ресурса;
- с HTTP-сервера;
- с использованием обращения к веб-сервису.

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

- на файловый сервер, доступный в сети;
- на FTP-сервер;
- передавать данные в интерактивном режиме на веб-сервис.

Пример описания структуры передачи данных в формате XML

```
<?xml version="1.0" encoding="windows-1251"?>
<LOAD>
  <FORMAL DOCKIND_NAME="BANK" DOCKIND_DESCR="Банк" XML_ID="19664">
    <PROPERTY SHOW_ORDER="1" XML_ID="6867" DOC_FORMAT="0" DOCPROP_NAME="БИК" 
     DOCPROP_DESCR="BIK" DOCPROP_KIND="1" DOCPROP_VISIBLE="1" 
     DOCPROP_UNIQUE="1" DOCPROP_NOTNULL="1" DOCPROP_OBJECT="4" 
     DOCPROP_REPEAT="0" DOCPROP_MULTI="0" DOCPROP_SQL="0" DOCPROP_TREE_KIND="0">
    </PROPERTY>
    <PROPERTY SHOW_ORDER="2" XML_ID="10289" DOC_FORMAT="0" DOCPROP_NAME="Название филиала(отделения)" DOCPROP_DESCR="NAME" DOCPROP_KIND="1" DOCPROP_VISIBLE="1" DOCPROP_UNIQUE="0" DOCPROP_NOTNULL="1" DOCPROP_OBJECT="4" DOCPROP_REPEAT="0" DOCPROP_MULTI="0" DOCPROP_SQL="0" DOCPROP_TREE_KIND="0">
    </PROPERTY>
    <PROPERTY SHOW_ORDER="3" XML_ID="12404" DOC_FORMAT="0" DOCPROP_NAME="Отделение(в ПП)" DOCPROP_DESCR="NAME_PP" DOCPROP_KIND="1" DOCPROP_VISIBLE="1" DOCPROP_UNIQUE="1" DOCPROP_NOTNULL="0" DOCPROP_OBJECT="4" DOCPROP_REPEAT="0" DOCPROP_MULTI="0" DOCPROP_SQL="0" DOCPROP_TREE_KIND="0">
    </PROPERTY>
    <PROPERTY SHOW_ORDER="4" XML_ID="12405" DOC_FORMAT="0" DOCPROP_NAME="Город(нас. пункт)" DOCPROP_DESCR="CITY" DOCPROP_KIND="1" DOCPROP_VISIBLE="1" DOCPROP_UNIQUE="0" DOCPROP_NOTNULL="1" DOCPROP_OBJECT="4" DOCPROP_REPEAT="0" DOCPROP_MULTI="0" DOCPROP_SQL="0" DOCPROP_TREE_KIND="0">
    </PROPERTY>
    <PROPERTY SHOW_ORDER="5" XML_ID="6866" DOC_FORMAT="0" DOCPROP_NAME="Корр. счет" DOCPROP_DESCR="KOR_SCHET" DOCPROP_KIND="1" DOCPROP_VISIBLE="1" DOCPROP_UNIQUE="0" DOCPROP_NOTNULL="1" DOCPROP_OBJECT="4" DOCPROP_REPEAT="0" DOCPROP_MULTI="0" DOCPROP_SQL="0" DOCPROP_TREE_KIND="0"/>
    <PROPERTY SHOW_ORDER="6" XML_ID="10290" DOC_FORMAT="0" DOCPROP_NAME="Адрес" 
       DOCPROP_DESCR="BANK-REF-ADRESS" DOCPROP_KIND="9" DOCPROP_VISIBLE="1" 
      DOCPROP_UNIQUE="0" DOCPROP_NOTNULL="0" DOCPROP_OBJECT="*" 
      DOCPROP_REPEAT="0" DOCPROP_MULTI="0" DOCPROP_SQL="1" 
      DOCPROP_RULE_CHILD="0" DOCPROP_RULE_PARENT="0" DOCPROP_TREE_KIND="0">
      <FORMAL DOCKIND_NAME="ADRESS" DOCKIND_DESCR="Адрес" XML_ID="19946"/>
    </PROPERTY>
    <PROPERTY SHOW_ORDER="8" XML_ID="6870" DOC_FORMAT="0" DOCPROP_NAME="Реквизиты" DOCPROP_DESCR="BANK-BREF-BANK_PROP" DOCPROP_KIND="12" DOCPROP_VISIBLE="1" DOCPROP_UNIQUE="0" DOCPROP_NOTNULL="0" DOCPROP_OBJECT="BANK_PROP" DOCPROP_REPEAT="0" DOCPROP_MULTI="1" DOCPROP_RULE_CHILD="3" DOCPROP_RULE_PARENT="3" DOCPROP_TREE_KIND="0">
      <FORMAL DOCKIND_NAME="BANK_PROP" DOCKIND_DESCR="Банковские реквизиты" XML_ID="20073"/>
    </PROPERTY>
    <PROPERTY SHOW_ORDER="9" XML_ID="10294" DOC_FORMAT="0" DOCPROP_NAME="Банк" DOCPROP_DESCR="BANK-REF-MBANK" DOCPROP_KIND="9" DOCPROP_VISIBLE="0" DOCPROP_UNIQUE="0" DOCPROP_NOTNULL="0" DOCPROP_OBJECT="*" DOCPROP_REPEAT="0" DOCPROP_MULTI="1" DOCPROP_SQL="11" DOCPROP_RULE_CHILD="0" DOCPROP_RULE_PARENT="0" DEFAULT_VALUE="9" DOCPROP_TREE_KIND="0">
      <FORMAL DOCKIND_NAME="MBANK" DOCKIND_DESCR="БанкЮр" XML_ID="24943"/>
    </PROPERTY>
  </FORMAL>
</LOAD>

```

LOAD – корневой элемент, содержащий перечень документов для обмена данными.

***Контроль прав доступа***

Настройка прав доступа к ИО осуществляется при помощи редактора реквизитов CARABI. Настройка осуществляется по ролям пользователей.

***Ограничение доступа к учетным ИО***

Ограничение пользователей к спискам ИО осуществляется в CARABI при помощи специального объекта – ИО Доступ к данным Название

```
Тип данных
Системное наименование
Подразделение
Выборка из таблицы "CLIENTS_TREE" [множ.]
DEPARTMENTS
Роль
Выборка из таблицы "VOCABS" [множ.]
ROLES
Пользователи
Выборка из таблицы "CLIENTS_TREE" [множ.]
USERS
Информационный объект
Выборка из таблицы "VOCABS"
IOBJECT
Фильтр
Текстовый
XMLFILTER
Комментарий
Текстовый
COMMENT

```

В фильтре при помощи специального экрана прописывается запрос в формате XML, ограничивающий Подразделение(или роль, или конкретного пользователя).

***Поддержка версий хранилища***

В специальной таблице СУБД ORACLE C\_LICENSE размещается информация о владельце БД, дата формирования, серийном номере и номере версии ПО Управляющим систему. Номер версии кодируется следующим образом

- MAJOR.MINOR.RELEASE.BUILD
- MAJOR и MINOR - определяет общий номер версии системы CARABI
- RELEASE - установленный комплекс ПО для управления БД
- BUILD – номер версии конкретного приложения АИС.

После тестирования разработчиками и установки нового ПП для управления бизнес - функциями, обеспечивающими работу комплекса, меняется номер BUILD. Таким образом, сохраняя предыдущий BUILD, поддерживаются версии АИС и обеспечивается возможность отката версии в случае непреднамеренных ошибок при разработке.