# Задачи

Раздел «Задачи» в администрировании отвечает за иерархии (деревья) задач, шаблоны создания задач и часть поведения задач в жизненном цикле. Большинство настроек поведения задаётся на уровне категории (см. [Категории](https://help.1forma.ru/domains/categories/admin.md)); здесь — собственные настройки домена задач: ключевые параметры, CustomSettings, чипы планирования и типичные ошибки.

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

Настройки домена задач доступны через несколько механизмов: формы автоадминки, EntityEditor и Admin API.

**Автоадминка (dbadmin)**

Часть настроек задаётся через формы автоадминки по их alias:

| Alias формы | Название | Таблица БД | Полей | Секций | Папка |
|-------------|----------|-----------|-------|--------|-------|
| `task-hierarchies` | Иерархии задач | dbo.TaskHierarchy | 14 | 1 | Пользовательский интерфейс |
| `task-templates` | Шаблоны задач | dbo.TaskUniversalTemplates | 15 | 1 | (корень) |

**EntityEditor**

Расширенные настройки шаблонов задач задаются через EntityEditor:

| Схема JSON | Таблица | Назначение |
|-----------|---------|------------|
| `taskuniversaltemplate` | dbo.TaskUniversalTemplates | Расширенная настройка шаблона задачи |
| `templates` | dbo.Templates | Основные шаблоны |
| `templatesDetails` | (связанная) | Детали шаблона |
| `templateList` | (связанная) | Список шаблонов |
| `templateColor` | (связанная) | Цвет шаблона |
| `templateIcon` | (связанная) | Иконка шаблона |

**Admin API**

Программно домен задач настраивается через Admin API:

| Маршрут | Методы | Назначение |
|---------|--------|------------|
| `/api/admin/tasks/hierarchy` | GET, POST, PUT, DELETE | Управление иерархиями, их полями и динамическими узлами |
| `/api/admin/tasks/{taskId}/access` | GET | Аудит доступа к конкретной задаче |

## Ключевые настройки домена задач

### Иерархии задач (TaskHierarchy)

**Где настраивается:** автоадминка → форма `task-hierarchies` или Admin API (`/api/admin/tasks/hierarchy`)
**Таблица БД:** `dbo.TaskHierarchy`

14 полей, определяющих структуру дерева задач в интерфейсе:

| Группа полей | Что контролирует |
|-------------|------------------|
| Имя, описание | Идентификация иерархии |
| Поля иерархии | Какие данные отображаются на каждом уровне |
| Динамические узлы | Узлы, вычисляемые при отображении |
| Привязка к категориям | Какие категории используют иерархию |

**Эффект:** иерархия строится платформой и отображается в левой панели/дереве.

### Шаблоны, поведение в категории и денормализация

**Шаблоны задач (TaskUniversalTemplates)**

**Где настраивается:** автоадминка → форма `task-templates` или EntityEditor (`taskuniversaltemplate`)
**Таблица БД:** `dbo.TaskUniversalTemplates`

15 полей: предзаполненные значения для создания задач (категория, исполнитель, срок, ДП).

**Контекст шаблона.** Поле «Контекст» определяет, где применяется шаблон, и хранится числом: `Cell` = 0 — краткое представление в списке задач, `MTF` = 1 — карточка задачи, `NTF` = 2 — форма создания новой задачи, `Calendar` = 3 — календарь, `Grid` = 4 — ячейка системной колонки «Описание» в таблице категории ([grids/business.md](https://help.1forma.ru/domains/grids/business.md)). В форме админки пункт со значением 4 подписан «Грид», а в окне «Шаблонизация» настроек категории тот же контекст подписан «Таблица» ([mobile/mobile-templates.md](https://help.1forma.ru/domains/mobile/mobile-templates.md)). Список значений формы берётся не из C#-перечисления `TemplateContext`, а из `enumValues` поля схемы `taskuniversaltemplate`: новое значение контекста заводится пунктом в схеме, а строка с тем же `Value` — миграцией в `dbadmin.SystemEnumMembers`.

**Эффект:** при создании задачи из шаблона поля автозаполняются из `TaskUniversalTemplates`.

**Языковые версии JSON.** У одного шаблона может быть отдельное JSON-описание на каждый язык — своя версия на пару «шаблон + язык»; название и описание самой записи к языку не привязаны и при переключении не меняются. В редакторе — и в форме настроек шаблона, и в модальном окне правки JSON — версия выбирается полем «Язык»: по умолчанию в нём русский, он же подставляется, если язык шаблона не задан или не найден в справочнике языков, а список поля — языки площадки. Смена языка подгружает описание выбранного языка; если у языка своей версии нет, сервер отдаёт пустой контент — запасного перехода на другой язык нет, — и редактор оставляет содержимое прежним. Сохранение пишет JSON только в выбранную версию, остальные остаются как были; чтение без явного языка по-прежнему идёт по языку сессии. Если смена языка застаёт несохранённую правку, платформа спрашивает подтверждение и при отказе возвращает прежний язык, не теряя введённое; когда справочник языков не загрузился, форма показывает индикатор и блокирует сохранение, а не открывается с пустым полем.

**Сохранение строки формы.** Строку формы `task-templates` сохраняет собственный обработчик: перед записью он проверяет обязательные поля (название, тип, содержимое), валидность JSON в содержимом и наличие блока `data` в теле запроса. Тело без блока `data` отклоняется ошибкой валидации «Форма заполнена неверно» — частично такая строка не сохраняется, поля журнала не проставляются. При успешном сохранении обработчик обновляет `Modified` и `ModifiedUserID` (в PostgreSQL — в нижнем регистре).

**Тип клиента в правиле назначения.** Правило назначения шаблона хранит тип клиента строкой. Канон — имя (`all`, `web`, `mobile`), но форма назначения могла записать числовой код того же перечисления. Отбор правил понимает оба вида, а список правил приводит значение к имени, поэтому в форме виден не код, а название типа клиента.

**Поведение задач в категории (смежный домен)**

**Где настраивается:** форма настроек категории `subcategories` → секции задач, сроков, исполнителей
**Таблица БД:** `dbo.Subcategories`

Большая часть поведения задач задаётся флагами категории:

- Подтверждение переноса срока через подпись
- Ограничения на смену исполнителей для просроченных задач
- Делегирование и права
- Автоматические действия при переходах

**Связь с категориями:** см. [Категории](https://help.1forma.ru/domains/categories/admin.md).

**Денормализация**

**Таблицы БД:** `dbo.TasksInSubcat*Denormalized`

Скорость и корректность списков задач (гридов) зависят от актуальности денормализованных данных. Рассинхрон приводит к отображению устаревших данных при корректной таблице `Tasks`.

## CustomSettings — прочие ключи задач

Дополнительное поведение задач задаётся ключами `CustomSettings`:

| Ключ | Тип / по умолчанию | Назначение |
|------|---------------|------------|
| `UseOldSurveys` | `0` / `1` | Выбор редактора опросов: `0` — **SurveyJS** (рекомендуется), `1` — **SurveyProject** (устаревший). Меняется только при наличии причин для возврата к старому редактору |
| `SearchEncryptedTasks` | bool | Включает поиск по зашифрованным задачам (если в категории включено шифрование). См. [бизнес-логику задач](https://help.1forma.ru/domains/tasks/business.md), раздел «Шифрование задач» |
| `personalDynSignaturesOnly` | array (SubcatID), по умолчанию `[]` | Список ID категорий, в задачах которых окно «Запросить подпись» показывает только личные подписи — должностную подпись из окна запросить нельзя. Сервер ключ не проверяет. Подробнее: [Кастомные настройки → personalDynSignaturesOnly](https://help.1forma.ru/domains/system/settings-custom.md#personaldynsignaturesonly) |
| `SmartActionMaxPerformers` | int, по умолчанию `20` | Лимит числа исполнителей при назначении через смарт-действия «Добавить исполнителя»/«Добавить группу исполнителей»; `0` отключает проверку. Подробнее: [Кастомные настройки → SmartActionMaxPerformers](https://help.1forma.ru/domains/system/settings-custom.md#smartactionmaxperformers) |
| `enableSpellCheck` | bool | Включает проверку орфографии в текстовых полях задачи: название, текстовые ДП и колонки типа «Текст» в ДП «Таблица». При выключенном ключе проверка не выполняется и предупреждения об опечатках не отображаются. Поведение для пользователя — см. [business.md, раздел «Проверка орфографии»](https://help.1forma.ru/domains/tasks/business.md) |

## Чипы быстрого планирования — ограничения

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

Описание поведения каждого чипа и блока — см. [business.md, раздел «Изменить срок задачи»](https://help.1forma.ru/domains/tasks/business.md#изменить-срок-задачи).

## Типичные ошибки настройки и связанные документы

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

| Симптом | Причина | Где проверить | SQL-диагностика |
|---------|---------|---------------|-----------------|
| Не удаётся изменить срок задачи | Включён режим подтверждения через подпись | Настройки категории | `select * from dbo.StatesRoutesSignatures where StepID in (select StepID from dbo.StatesRoutesInSubcat where SubcatID = {subcatId})` |
| Не удаётся сменить исполнителя | Ограничения категории для просроченных задач | Настройки категории | Проверить флаги делегирования в `dbo.Subcategories` |
| Иерархия задач пустая/неверная | Некорректные поля или динамические узлы | Форма `task-hierarchies` | `select * from dbo.TaskHierarchy where Id = {hierarchyId}` |
| Список задач показывает устаревшие данные | Рассинхрон денормализации | `TasksInSubcat*Denormalized` | Сравнить `Tasks` и `TasksInSubcat*Denormalized` для задачи |
| Шаблон не заполняет поля | Неверные ссылки на категорию/ДП в шаблоне | Форма `task-templates` | `select * from dbo.TaskUniversalTemplates where Id = {templateId}` |

## Связи таблиц задач (модель данных)

Центральная таблица — `Tasks`: каждая задача ссылается на заказчика (`UserID` → `Users`), статус (`StateID` → `States`), категорию (`SubcatID` → `Subcategories`) и, для подзадач, на родительскую задачу (`ParentTaskID` → `Tasks`). Исполнители хранятся в `TaskHelpers`. Категории группируются в разделы (`Subcategories.CategoryID` → `Categories`), разделы образуют дерево через само-ссылку `Categories.ParentCategoryID`.

```mermaid
graph LR
    T["Tasks — задачи"]
    TH["TaskHelpers — исполнители"]
    U["Users — пользователи"]
    ST["States — статусы"]
    SC["Subcategories — категории"]
    C["Categories — разделы"]

    T -- "UserID (заказчик)" --> U
    T -- "StateID" --> ST
    T -- "SubcatID" --> SC
    T -- "ParentTaskID" --> T
    TH -- "TaskID" --> T
    TH -- "UserID" --> U
    SC -- "CategoryID" --> C
    C -- "ParentCategoryID" --> C
```

> Завершённой считается задача при `IsClosed = 1` **и** `States.FinishWork = 1`; у отклонённой `CloseTask = 1`, но `FinishWork = 0`. `EndTime` при восстановлении задачи не очищается.

Полная версия с колонками и схемы связей других подсистем БД — в [system/db-er-diagrams.md](https://help.1forma.ru/domains/system/db-er-diagrams.md).

См. также:

- [Настройка категорий](https://help.1forma.ru/domains/categories/admin.md) — поведенческие флаги задач
- [Работа с задачами](https://help.1forma.ru/domains/tasks/business.md) — бизнес-логика и жизненный цикл задач

## Инструменты карточки задачи для тестов и агентов (WebMCP)

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

**Включение.** Включение — ключ браузера `1f.agentTools` со значением `1`:

```
localStorage['1f.agentTools'] = '1'
```

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

**Точки доступа.** При включённом ключе инструменты доступны двумя способами:

- через WebMCP — если браузер поддерживает этот интерфейс, инструменты регистрируются в нём автоматически; если не поддерживает, карточка работает как обычно, без ошибок;
- через тестовую точку `window.__1fTools` в консоли браузера: `window.__1fTools.list()` возвращает перечень инструментов — имя, описание и схему, — а `window.__1fTools.call('ИмяИнструмента', { ... })` выполняет вызов.

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

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

```
await window.__1fTools.call('DescribeTaskCard', {})
await window.__1fTools.call('DescribeTaskCard', { taskId: 2072298 })
```

Без идентификатора описывается единственная открытая карточка. Если открыто несколько карточек, вызов возвращает ошибку со списком их идентификаторов; если карточка с указанным идентификатором не открыта — ошибку «карточка задачи не открыта».

Ответ — описание по блокам карточки с теми же подписями, которые видит пользователь:

| Раздел ответа | Что содержит |
|---|---|
| задача | идентификатор, тема, раздел и категория, статус, текст задачи |
| смотрящий | идентификатор текущего пользователя |
| системные поля | подпись и значение |
| переходы | кнопки переходов, показанные этому пользователю: подпись, шаг, целевой статус, доступна ли кнопка, а также незаполненные обязательные параметры, которые сейчас блокируют переход |
| кнопки | прочие кнопки, смарт-кнопки: подпись и доступность |
| дополнительные параметры | показанные параметры: идентификатор, имя, тип, значение и отображаемое значение, можно ли редактировать, обязателен ли; для табличных — колонки и показанные строки |
| подписи | подписи по задаче: от кого, кому, состояние, может ли текущий пользователь дать резолюцию и какие варианты ему доступны |
| связи | подзадачи и связанные задачи: идентификатор, тема, статус |

В описание попадают только те блоки и кнопки, которые карточка показывает именно этому пользователю: скрытые по правам или условию видимости в описание не входят. Описание — только чтение: действия, меняющие задачу, в него не входят и описаны отдельно в webmcp-card.md.

**Чем проверить после включения:**

- при ключе `1f.agentTools` = `1` и открытой карточке `list()` содержит инструмент описания;
- у заблокированного перехода в ответе перечислены незаполненные обязательные параметры — те же, что в подсказке кнопки;
- после удаления ключа и перезагрузки страницы тестовой точки нет, а карточка выглядит и ведёт себя как прежде.
