# Произвольные источники данных

**Произвольный источник данных** — это табличный список (грид) поверх объекта базы данных: таблицы, представления, функции или хранимой процедуры. Он выводит данные прямо в интерфейс «Первой Формы», где их можно просматривать, фильтровать, выбирать нужные поля и выгружать в Excel. Так администратор даёт пользователям удобный доступ к большим объёмам данных и сложной аналитической отчётности — как из самой системы, так и полученной через интеграции, — не заставляя их работать с базой напрямую.

Источники настраиваются в AdminSPA: на главном экране отображается список всех произвольных источников, а по каждому из них открывается окно настроек с вкладками «Общие», «Колонки», «Действия», «Настройки тулбара» и «Общий вид».

![Список произвольных источников данных](https://help.1forma.ru/help-images/grids/custom_data_sources-7.png)

## Как добавить и отредактировать источник

Чтобы добавить новый источник данных, нажмите кнопку **«Добавить»** — откроется модальное окно создания источника. Обязательные для заполнения поля выделены красным цветом.

![Окно создания произвольного источника](https://help.1forma.ru/help-images/grids/custom_data_sources-8.png)

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

⚠️ При создании нового источника необходимо настроить и сохранить колонки (вкладка «Колонки»).

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

## Вкладка «Общие»

На вкладке задаются основные параметры источника.

![Редактирование произвольного источника, вкладка «Общие»](https://help.1forma.ru/help-images/grids/custom_data_sources-0.png)

### Типы источника данных

- **Таблица**
- **Представление**
- **Функция**
- **Хранимая процедура** (на PostgreSQL работает через одноимённую функцию)
- **Хранимая процедура без явного ResultSet** (доступно только на MSSQL) — используется, когда в зависимости от контекста меняется количество возвращаемых колонок. Такой источник не описывает структуру возвращаемых данных и не определяет количество столбцов, поэтому часть пользовательских функций — сортировка, фильтрация, группировка, разбиение на страницы — будет недоступна. На PostgreSQL источник с этим типом сохранить нельзя: при сохранении возвращается ошибка. Уже сохранённый на PostgreSQL источник открывается без ошибок, но для работы его нужно пересоздать на поддерживаемом типе. При выборе этого типа в настройках источника выводится предупреждение «Часть пользовательских функций в таблице будут недоступны».

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

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

Примеры кода:

```sql
-- Функция
CREATE FUNCTION customDataSourceFunc ( @UserId int null )
RETURNS TABLE AS RETURN ( SELECT DisplayName, LastName from Users )

-- Хранимая процедура
CREATE PROCEDURE customDataSourceProc @UserId int null AS
BEGIN SELECT DisplayName, LastName from Users END
```

### Параметры вкладки

| Параметр | Описание |
|----------|----------|
| Тип источника данных | Вариант объекта БД (см. «Типы источника данных» выше). |
| Источник данных\* | Сам объект-источник в БД. |
| Загружать данные при открытии | Если настройка неактивна, при открытии отображается пустой список с уведомлением «Данные не были загружены автоматически» и кнопкой «Загрузить». По умолчанию активировано. |
| Название | Название произвольного источника. |
| Алиас\* | Наименование источника (псевдоним). |
| Путь | Полный путь до произвольного источника с учётом текущего алиаса. Заполняется автоматически после указания алиаса. |
| Описание | Описание произвольного источника. |
| Группы | Список групп, которым выданы права на источник. |
| Специальный тип | Произвольный источник можно открыть как отдельным роутом, так и из БИ. При выборе типа «Блок используется» к пути добавляется `spa/ds/{alias}?taskId=`. Обязательные параметры табличной функции для БИ: `UserID` (int) — ID пользователя, `TaskID` (int) — ID задачи. |

Поля, отмеченные `*`, обязательны для заполнения.

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

### Особенности работы с хранимой процедурой

Источником данных может являться хранимая процедура SQL. К таким процедурам предъявляется ряд требований.

Входные параметры хранимой процедуры:

- Обязательно: `@UserID` (int) — ID текущего пользователя.
- Опционально: `@TaskID` (int) — ID текущей задачи.

Если процедура принимает другие параметры, они не должны быть обязательными — при вычислении им будет передано значение `NULL`.

Хранимая процедура может возвращать произвольные данные и произвольный набор колонок. Названия колонок должны быть на латинице без пробелов.

Пример процедуры:

```sql
create PROCEDURE [dbo].[bi_sp_simple_example]
  @Userid int null,
  @TaskID int null
AS
BEGIN
  declare @result table (
    Taskid    int null,
    Userid    int null,
    SomeText  varchar(max) null
  );

  insert into @result
  select top 10
    t.TaskID,
    t.UserID,
    t.Description
  from Tasks t with(nolock)
  where t.TaskID = @TaskID;

  select TaskID, UserID, SomeText from @result;
END
```

### Запись имени источника и PostgreSQL

Имя источника можно записывать в нотации MS SQL — `[dbo].[Имя]`. При сборке вызова на PostgreSQL квадратные скобки снимаются, поэтому такая запись работает без правки настройки.

- Имя без схемы получает схему `dbo.`.
- Имя, квалифицированное другой схемой (`custom.foo`), остаётся как записано — префикс `dbo.` не добавляется.
- Регистр в тексте вызова сохраняется, но PostgreSQL выполняет незаквотированный идентификатор в нижнем регистре. Поэтому на стенде должна существовать функция с именем в нижнем регистре: источнику `[dbo].[crm_ZvonkiAndVstrechi]` соответствует функция `dbo.crm_zvonkiandvstrechi`.
- На MS SQL имя используется в записанном виде: квадратные скобки там — обычное квотирование имени.

Те же правила записи имени действуют для источника таблицы «Задачи, использованные в задаче» (БИ-блока).

### Иерархический режим источника

Ответ хранимой процедуры можно отдавать деревом. Режим включается настройкой `IsHierarchy`; настройки иерархии хранятся в настройках источника и задаются через административный API.

В этом режиме процедура дополнительно получает в JSON-параметрах ключи в нижнем регистре:

| Ключ | Когда приходит | Значение |
|---|---|---|
| `loadfulltree` | всегда | `true` — процедура должна вернуть дерево целиком, `false` — обычная выборка |
| `parentid` | когда клиент раскрывает узел | идентификатор узла, дочерние строки которого нужно вернуть |
| `datatype` | когда клиент передал режим выборки | значение передаётся процедуре как есть |
| `parentids` вместе с `datatype=getparents` | при подтяжке предков | список идентификаторов через запятую, узлы которых нужно вернуть |

Ответ процедуры обязан содержать колонки с идентификатором строки и идентификатором родителя — по умолчанию `id` и `parentid`, имена переопределяются настройками `IdField` и `ParentField`. Если этих колонок нет — ни в основном ответе, ни в ответе на `datatype=getparents`, — запрос завершается ошибкой 400 с описанием проблемы конфигурации: усечённое дерево не отдаётся, чтобы его нельзя было принять за полное.

Подтяжка предков выполняется автоматически, когда в гриде задан фильтр: сервер берёт найденные строки и запросами `datatype=getparents` добирает их предков уровень за уровнем до корня или до числа уровней, заданного настройкой `MaxDepth`. Запросы предков идут без фильтра и без пагинации, уже полученные узлы повторно не запрашиваются, кольцевые ссылки отсекаются. Подтяжку отключает настройка `LoadFullTreeOnFilter`; она также не выполняется, когда процедура и так вернула дерево целиком.

Остальные настройки иерархии — `HasChildrenField`, `PathField`, `GroupColumnField`, `RowStyleField`, `LazyLoad` — хранятся в настройках источника и на серверную выборку не влияют.

Для источников без `IsHierarchy` набор параметров процедуры не меняется: перечисленные ключи не добавляются.

### Источник, перенесённый из иерархии задач

Произвольный источник может быть создан переносом иерархии задач. Строки такого источника — узлы перенесённого дерева: отдаёт их сама иерархия задач, а не хранимая процедура источника, поэтому состав строк совпадает с деревом. Признак переноса хранится в настройках источника (поле `MigratedTaskHierarchyId`), а набор колонок — в слоте представления «Иерархия»; корневой набор колонок представления у такого источника пуст.

Обратиться к источнику можно двумя способами: по имени — открытием по адресу источника, и по сущности — через тикер или через задачу, в которой источник используется блоком «Используется». Оба способа дают одинаковый результат: тот же состав строк, что у дерева источника, и тот же состав колонок из слота «Иерархия». Это одинаково касается показа данных в гриде, выгрузки в Excel и чтения настроек колонок.

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

**Выгрузка и отчёты по перенесённому источнику.** «Выгрузка в Excel» отдаёт тот же состав строк и колонок, что виден в представлении «Иерархия»; ограничение по числу задач (50 000) действует на неё как обычно. Данные зарегистрированного отчёта по такому источнику собираются тем же путём, что и дерево, и раскладываются по карте колонок отчёта; пустое дерево — не ошибка: отчёт отдаёт пустой набор с колонками карты. Условия фильтра, сортировка и параметры отчёта для такого источника не поддерживаются: непустой отбор прерывает построение ошибкой конфигурации, её причина с именем источника записывается в журнал, а на экране показывается общий отказ «Не удалось построить отчёт.». Отбор для отчёта по такому источнику оставляют пустым.


## Вкладка «Колонки»

На вкладке доступны настройки колонок табличного вида.

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

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

![Редактирование произвольного источника, вкладка «Колонки»](https://help.1forma.ru/help-images/grids/custom_data_sources-1.png)

- Кнопка **«Обновить колонки»** — данные о колонках будут обновлены в соответствии с указанным источником. ⚠️ При изменении состава колонок в хранимой процедуре или функции обязательно обновите колонки этой кнопкой.
- Кнопка **«Сброс настроек всех пользователей»** — персональные настройки табличного вида пользователей будут сброшены к виду по умолчанию.

Настройки колонки:

| Параметр | Описание |
|----------|----------|
| Колонка в БД | Название колонки в БД. Подтягивается автоматически, поле недоступно для редактирования. ⚠️ При настройке произвольного источника используйте значения колонок именно в том виде (с сохранением регистра), в котором они передаются в поле «Колонка в БД». |
| Название | Название колонки. Рядом с названием отображается иконка локализации — по клику на неё открывается окно для задания названий колонки в разных локалях. ⚠️ Если необходимо открывать ссылки, в название колонки нужно указать TaskID. |
| Тип | Тип данных колонки. Доступные варианты: Число, Строка, Дата, Дата и время, Html, Html без тегов, Чекбокс. |
| Настройки фильтра | Тип фильтра для колонки: Базовый или Мультивыбор (см. ниже). |
| Доступно | Доступ поля для пользователей. |
| Детализируется | Клик по строке в списке отобразит целиком значения столбцов, для которых активна настройка (детализация, drill-down). |

⚠️ **Допустимый состав символов имён и псевдонимов колонок.** Значение поля «Колонка в БД» и заданный по нему псевдоним принимаются только если состоят из букв (включая кириллицу), цифр, пробела, точки, дефиса или подчёркивания — до 128 символов. Конструкция другого вида отклоняется отказом, а не выполняется. Если у действующего источника имя колонки содержит другие символы, после обновления его нужно будет исправить.

### Настройки колонок источника, перенесённого из иерархии задач

Источник, перенесённый из иерархии задач, открывается деревом: его колонки — статические поля дерева, а их состав и порядок заданы настройками иерархии. Отдельный набор колонок табличного вида у такого источника не заполняется.

Пользовательский порядок и видимость колонок у такого источника сохраняются персонально, как у обычного, и возвращаются при следующем открытии таблицы — независимо от того, по какому признаку она строится. Значения по умолчанию для всех задают переключатели «Доступность» и «Видимость по умолчанию» на этой вкладке; кнопка «Сброс настроек всех пользователей» возвращает к ним всех. Свой выбор пользователь возвращает кнопкой «Сброс персональных настроек» на вкладке «Общий вид».

### Настройки фильтра

Доступные типы фильтра: **Базовый** и **Мультивыбор**. Фильтр с типом «Мультивыбор» для колонки в списке задач категории позволяет дополнительно выбирать несколько значений из множества.

**Операторы сравнения.** Условия «меньше» и «больше» строгие — указанное значение в выборку не попадает; чтобы включить границу, используются «меньше или равно» и «больше или равно». Для дат граница берётся по дню: «больше» отбирает записи со следующего дня, «меньше или равно» — по конец указанного дня; время в сохранённом отборе на границу суток не влияет. Условия «равно» и «не равно» по дате тоже охватывают сутки целиком: «равно» отбирает все записи выбранного дня независимо от времени, «не равно» исключает только этот день. Поведение одинаково для MS SQL и PostgreSQL. Запись с незаполненной датой под «не равно» в выдачу не попадает. Если в фильтре указано время, сравнение идёт по моменту, а не по дню целиком.

**Маршрут объекта.** То же правило границ суток действует и при чтении данных по маршруту объекта — прямом чтении таблицы по её имени, без идентификатора формы. Датовые условия отбора этого маршрута обрабатываются теми же правилами, что и в основном пути формы: «равно» по дню охватывает все записи выбранного дня независимо от времени и не включает полночь следующих суток, «не равно» исключает только выбранный день. Правило одинаково для MS SQL и PostgreSQL. Некорректная модель отбора — неизвестный тип условия или значение вместо объекта — возвращает ошибку 400 с указанием колонки, а не пустую выдачу.

Для мультивыбора необходимо указать **источник фильтра** — функцию, которая возвращает таблицу с двумя колонками `name` и `value`. Колонка `name` содержит значения для отображения в пользовательском интерфейсе, а колонка `value` хранит значения, по которым фактически фильтруются данные. В интерфейсе пользователь видит значения из колонки `name`, и при выборе конкретного значения система применяет фильтр по соответствующему значению из колонки `value`.

Пример функции — источника фильтра:

```sql
CREATE OR ALTER FUNCTION [dbo].[testBoytsova] (@UserId int)
RETURNS @Table TABLE(
  name  nvarchar(300),
  value nvarchar(300)
)
AS
Begin
  insert into @Table (name, value)
    select s.Description, s.Description
    from States s
    where s.StateID IN (1,2,3,4)
  RETURN
END
```

## Вкладка «Действия»

Вкладка позволяет добавлять кастомные кнопки действий со строкой, которые отображаются в отдельной колонке «Действия». Настройка кнопок задаётся в формате JSON со следующими параметрами:

- `icon` — название иконки из набора, она будет отображаться на кнопке. Список доступных иконок — по ссылке `/spa/icons`.
- `name` — название кнопки.
- `showInMenu` — отображение кнопки в меню: `true` (отображать) / `false` (не отображать).
- `showInActions` — отображение кнопки в тулбаре действий: `true` (отображать) / `false` (не отображать).
- `type` — тип кнопки: `OpenUrl` (открыть ссылку из параметра `url`), `Request` (запрос), `OpenComponent` (открыть компонент — в настоящее время не поддерживается).
- `options`:
  - `url` — ссылка, которая открывается при нажатии на кнопку. Помимо статичной ссылки можно задать ссылку на конкретную строку таблицы в формате `{params:колонка}` — вместо `колонка` указывается название колонки, из которой нужно получить значение в этой строке.
  - `openMode` — режим отображения: `CurrentWindow` (в текущем окне), `NewWindow` (в новом окне), `ModalWindow` (в модальном окне).
  - `params` — может содержать элементы http-запроса: `headers`, `credentials`, `body` и т.п. Наиболее распространённое значение — `method` (API-метод: `GET`, `POST`).
  - `showResponse` — отображение результата запроса: `true` / `false`.
  - `isAvailable` — настройка доступа в формате `(params, ctx) => params.id === 123 && ctx.userId === 11`.

![Редактирование произвольного источника, вкладка «Действия»](https://help.1forma.ru/help-images/grids/custom_data_sources-2.png)

⚠️ Параметры в ссылке передавайте в нижнем регистре. Пример: `/admin/extparams/ExtParamsMainFrame.aspx?ExtParamID={params:extparamid}`

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

```json
[
  {
    "icon": "vh-tasks-add-24",
    "name": "Получить кэш",
    "showInMenu": null,
    "showInActions": null,
    "type": "Request",
    "options": {
      "url": "/spa/ds/films",
      "params": { "method": "POST" },
      "showResponse": true,
      "isAvailable": "(params, ctx) => params.id == 3 && ctx.userId == 8323"
    }
  },
  {
    "icon": "",
    "name": "Открыть группу",
    "showInMenu": null,
    "showInActions": null,
    "type": "OpenUrl",
    "options": {
      "url": "/spa/ds/films?f_id={params:id}",
      "openMode": "ModalWindow"
    }
  }
]
```

![Пример настройки действий](https://help.1forma.ru/help-images/grids/custom_data_sources-3.png)

В интерфейсе рядом с полем настройки доступна кнопка с готовым примером JSON.

![Отображение кнопок действий со строкой в пользовательском интерфейсе](https://help.1forma.ru/help-images/grids/custom_data_sources_example1.png)

## Вкладка «Настройки тулбара»

Вкладка позволяет добавлять кастомные кнопки действий в панели инструментов табличного вида. Настройка задаётся в формате JSON с теми же параметрами, что и на вкладке «Действия» (`icon`, `name`, `showInMenu`, `showInActions`, `type`, `options` с `url`, `openMode`, `params`, `showResponse`, `isAvailable`). В отличие от действий со строкой, кнопки тулбара не привязаны к конкретной строке, поэтому `url` задаётся как статичная ссылка. Настройки тулбара задаются **объектом** с ключом `actions` (в отличие от вкладки «Действия», где список кнопок — это массив).

![Редактирование произвольного источника, вкладка «Настройки тулбара»](https://help.1forma.ru/help-images/grids/custom_data_sources-4.png)

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

```json
{
  "actions": [
    {
      "icon": "vh-tasks-add-24",
      "name": "Группы",
      "showInMenu": null,
      "showInActions": null,
      "type": "OpenUrl",
      "options": {
        "url": "/groups.aspx",
        "openMode": "ModalWindow"
      }
    },
    {
      "icon": "vh-tasks-add-24",
      "name": "Получить настройки",
      "showInMenu": null,
      "showInActions": null,
      "type": "Request",
      "options": {
        "url": "/app-settings.json",
        "params": { "method": "GET" },
        "showResponse": true
      }
    }
  ]
}
```

![Пример настройки тулбара](https://help.1forma.ru/help-images/grids/custom_data_sources-5.png)

В интерфейсе рядом с полем настройки доступна кнопка с готовым примером JSON.

![Отображение кнопок действий в пользовательском интерфейсе](https://help.1forma.ru/help-images/grids/custom_data_sources_example2.png)

## Вкладка «Общий вид»

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

![Редактирование произвольного источника, вкладка «Общий вид»](https://help.1forma.ru/help-images/grids/custom_data_sources-6.png)

Панель инструментов табличного вида:

| Кнопка | Описание |
|--------|----------|
| Обновление данных | Обновляет данные в таблице. |
| Выбор колонок | Выбор нужного состава колонок для отображения. |
| Режим выбора | Переход в режим выбора задач, когда рядом с каждой задачей отображается флажок для выбора. Над выбранными задачами могут выполняться действия с помощью пакетной обработки. |
| Пакетная обработка | Пакетная обработка выбранных задач. |
| Выгрузка в Excel | Выгрузка данных в файл Excel. ⚠️ В системе нельзя экспортировать более 50 000 задач! |
| Сброс персональных настроек | Сброс персональных настроек табличного представления, сделанных пользователем (сортировка, группировка, список и порядок колонок), и возврат к настройкам таблицы, определённым по умолчанию для данной категории/раздела системным администратором. |

⚠️ Кнопки **«Режим выбора»** и **«Пакетная обработка»** доступны только у источников, в которых есть колонка `TaskID`.

⚠️ У источника, перенесённого из иерархии задач, кнопка **«Выгрузка в Excel»** выгружает строки представления «Иерархия» — тот же состав, что виден в дереве.

После внесения изменений нажмите кнопку **«Сохранить»**.

## Удаление источника

Чтобы удалить источник данных, нажмите кнопку с крестиком в конце соответствующей строки. Для подтверждения удаления нажмите «Ок», для отмены — «Отмена».

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

---

Где хранится настройка (таблица `DataSourceSettings`, ключи, типы источника) — в [Таблицы (grids) → Произвольные источники данных](https://help.1forma.ru/domains/grids/admin.md#произвольные-источники-данных-datasourcesettings).
