Перейти к содержанию

Смарт-действия — Администрирование

Обзор

Домен smart-actions охватывает автоматизацию: смарт-правила (событие -> условие -> пакет действий), смарт-доступ, очереди событий, потоки сообщений и смарт-скрипты. Администрирование использует два механизма:

  • Автоадминка (dbadmin) -- 8 форм (SmartAccess, Queues, CustomEvents, MessageFlows и связанные)
  • Кастомные SPA-страницы -- 3 формы (general-smart, all-smart, custom-queue-actions) -- зарегистрированы в дереве автоадминки, но открывают собственные SPA-страницы
  • Admin API -- 10+ контроллеров для редактора пакетов действий, смарт-правил, конструктора условий, смарт-скриптов

EntityEditor для данного домена не используется.

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

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

Alias формы Название Таблица БД Полей Секций Папка
smart-access Смарт-доступ dbo.SmartAccess 5 1 Общая бизнес-логика
smart-access-subcategories Смарт доступ -- Категории dbo.SmartAccessSubcategories 4 1 Служебное
smart-access-trigger-extparams Смарт доступ -- Пересчет при смене ДП dbo.SmartAccessTriggerExtParams 4 1 Служебное
smart-access-trigger-groups Смарт доступ -- Пересчет при добавлении в группу dbo.SmartAccessTriggerGroups 4 1 Служебное
queues Очереди событий dbo.Queues 6 1 Общая бизнес-логика
custom-events Произвольные события dbo.CustomEvents 5 1 Служебное
message-flows Потоки dbo.MessageFlows 7 1 Общая бизнес-логика
custom-queue-actions-2 События (Custom Queue Actions) dbo.CustomQueueActions 10 1 Служебное

Кастомные SPA-страницы (в дереве автоадминки)

Alias формы Название Url Таблица БД Папка
general-smart Общие смарты /administration/smart-packs dbo.SmartExpressions Общая бизнес-логика
all-smart Все смарты /administration/smart-packs?globalEventsOnly=false dbo.SmartExpressions Общая бизнес-логика
custom-queue-actions Привязка действий к событиям очереди /administration/queues dbo.CustomQueueActions Общая бизнес-логика

Admin API контроллеры

Редактор пакетов действий

Контроллер Маршрут Методы Назначение
SmartActionsPacksController /api/admin/smart/packs GET, POST, DELETE CRUD пакетов, список по категории
SmartActionsPacksOnEventsController /api/admin/smart/packs-on-events GET, POST, DELETE CRUD смарт-правил (событие -> пакет)
ActionsPackEditorController /api/admin/smart/packs GET, POST, DELETE Схема/содержимое пакета, действия внутри пакета

Конструктор условий и выражений

Контроллер Маршрут Методы Назначение
SmartQueryController /api/admin/smart/query GET, POST Конструктор запросов (condition builder)
QueryConstructorController /api/admin/smart/query-constructor GET, POST Конструктор TSQL-условий
SmartExpressionsController /api/admin/smart/expressions GET, POST, DELETE CRUD смарт-выражений
SmartExpressionEditorController /api/admin/smart/expression-editor GET, POST Редактор выражений (UI-схема)
SmartExpressionConstructorController /api/admin/smart/expression-constructor GET, POST Конструктор выражений (QueryBuilder)
SmartExpressionTestCasesController /api/admin/smart/expression-test-cases GET, POST, DELETE Тест-кейсы для выражений

Доступ и скрипты

Контроллер Маршрут Методы Назначение
SmartAccessController /api/admin/smart/access GET, POST, DELETE Управление смарт-доступом
SmartScriptsController /api/admin/smart/scripts GET, POST, DELETE Смарт-скрипты (JS/TSQL)
SmartRecurrenceController /api/admin/smart/recurrence GET, POST Расписание повторяющихся правил

Подробная спецификация эндпоинтов (параметры, DTO, маршруты) -- см. backend.md раздел 1.

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

Смарт-выражения (SmartExpressions)

Где настраивается: SPA-страница /administration/smart-packs (пункт general-smart в дереве автоадминки) / Admin API -> SmartExpressionsController Таблица БД: dbo.SmartExpressions

Смарт-выражения -- универсальный механизм, используемый и как условия (фильтры), и как правила автоматизации (событие + пакет действий).

Поле Тип Что контролирует
Content nvarchar(max) JSON-содержимое выражения (дерево условий)
Name nvarchar Название выражения (отображается в UI)
SubcatID int Привязка к категории (NULL = глобальное)
IsFilter bit Тип: фильтр (true) или правило автоматизации (false)
EventID int Событие-триггер (для правил)
ParameterValue nvarchar Значение параметра события (уточнение триггера)
NoContextMode int Режим без контекста задачи
AvailAsSmartSearch bit Доступно как смарт-поиск
TSqlContent nvarchar(max) TSQL-представление выражения
Public bit Публичное (видимо другим администраторам)
OwnerUserId int Владелец выражения
QueryBuilderState nvarchar(max) Состояние визуального конструктора
OriginID int Происхождение (системное / пользовательское)
IsDeleted bit Мягкое удаление

Зависимости между полями: - IsFilter = 1 -> EventID и ParameterValue не используются при вычислении фильтра (это фильтр, не правило; в записи БД поля могут быть заполнены) - IsFilter = 0 -> EventID обязателен (определяет триггер) - SubcatID = NULL -> глобальное правило/фильтр - NoContextMode -> влияет на доступность действий, требующих контекст задачи

Эффект в runtime: - Content парсится в SmartExpressionsLogic и вычисляется SmartEvaluator - TSqlContent используется для серверного выполнения (прямой SQL) - EventID определяет, на какое событие срабатывает правило (см. ../smart-filters/admin.md)

Пакеты действий (ActionsPacks)

Где настраивается: AdminSPA → настройки категории → вкладка «Смарт» / Общие смарты (/administration/smart-packs) / Admin API → ActionsPackEditorController Таблицы БД: dbo.ActionsPacks, dbo.PacksActions, dbo.PacksActionsParameters

Пакеты настраиваются через Admin API (визуальный редактор в SPA). В автоадминке формы для ActionsPacks нет.

Структура: - ActionsPacks -- метаданные пакета (имя, GUID, категория) - PacksActions -- действия внутри пакета (тип, порядок) - PacksActionsParameters -- параметры каждого действия

Типы действий: 70+ типов -- полный каталог в actions-reference.md

Ключевые группы действий: - Задачи: создание, изменение статуса, полей, исполнителей - Комментарии: добавление, изменение - Уведомления: email, push, SMS - Файлы: генерация документов, копирование - Интеграции: HTTP-запросы, SQL, внешние системы - Управление: остановка/возобновление таймеров, JS-скрипты

Создание пакета

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

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

Ограничения именования: апострофы (') в названии пакета делают его неработоспособным — использовать только кавычки (").

Привязка к событию через скрипт: если пакет использует смарт-скрипты, привязанные к событию A, он недоступен для выбора в контексте события B.

Добавление действий

Кнопка «+Действие» открывает список всех действий, сгруппированных по смысловым блокам. Поддерживается поиск по слову в названии.

После выбора действия открываются его параметры. Для каждого параметра выбирается формат значения:

Формат Описание
Значение Фиксированное значение нужного типа
Smart / TSQL Смарт-выражение. Должно возвращать тип, соответствующий параметру. Список — в формате {А, В, С}. Тестовая выборка ограничена 100 записями.
Lua-скрипт Lua-скрипт из репозитория. Требования к типам аналогичны Smart/TSQL.
Оставить пустым Для необязательных параметров — значение не присваивается
Текущая задача Только для параметров типа «Задача» — выполнить в задаче текущего события

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

Поле «Задача»: по умолчанию действие выполняется в контекстной задаче. Чтобы выполнить в другой — указать ID через выражение. Если выражение вернёт несколько ID, действие выполнится для каждой задачи.

Порядок действий изменяется перетаскиванием строк.

Выполнение от имени пользователя

Если действие выполняется от имени конкретного пользователя, у него должны быть соответствующие права. Рекомендуется использовать системного робота (настраивается в Общих настройках приложения → «Диспетчер задач») — он обладает максимальными правами.

«Тихий» комментарий

При добавлении комментария через смарт-действие можно сделать его «тихим»: без адресатов, без увеличения счётчика непрочитанных, без push-уведомлений — независимо от настроек подписки.

Передача переменных между действиями

Некоторые действия возвращают результат (отмечены возвращает XXX в описании). Результат записывается в переменную и доступен в последующих действиях пакета через узел «Переменные» в дереве смарт-выражения.

Циклические пакеты

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

Настройка Описание
Список итерируемых объектов Смарт-выражение, возвращающее ID через запятую
Условие прерывания цикла Смарт-выражение: когда истинно — цикл прерывается

Индекс итерации начинается с 0 и доступен в смарт-выражениях пакета вместе с текущим значением итератора. Переменные цикла доступны в редакторе выражений только если заданы оба поля (список и условие).

⚠️ Проверка глубины рекурсии смарт-пакетов к циклическим пакетам не применяется.

Меню быстрых действий с пакетом

Действие Описание
Редактировать название Изменить имя пакета
Редактировать описание Произвольный текст (отображается при наведении на кнопку информации)
Редактировать модуль Привязать пакет к модулю; без выбора — глобальный модуль
Дублировать пакет Создать копию в текущей категории
Удалить пакет Удалить пакет

Автогенерация описания действия: при настройке параметров можно пометить ключевые из них как «Показ превью» — система сгенерирует краткое описание действия в списке пакета.

Эффект в runtime: - Выполнение через ActionPackExecutor -> PacksLogic.ExecuteActionsPack() - Действия выполняются последовательно (в порядке ActionOrder) - Асинхронные правила уходят в очередь

Смарт-правила (событие -> пакет)

Где настраивается: Admin API -> SmartActionsPacksOnEventsController Таблица БД: dbo.EventsActions

Связывает событие с пакетом действий через условие (смарт-выражение).

Ключевые концепции: - Правило = событие + (опциональное) условие + пакет действий - Правила привязаны к категории (SubcatID) или глобальные - Порядок правил определяет приоритет выполнения (reorder через API) - Флаг IsAsync -- асинхронное выполнение через очередь - Флаг Cancelable -- возможность отмены пользователем - Флаг IsActive -- если отключён, правило сохраняется, но не срабатывает (удобно для отладки)

Асинхронность правил

Флаг IsAsync влияет на порядок выполнения нескольких правил для одного и того же события: - Синхронное правило — следующие по списку правила ждут его завершения. - Асинхронное правило — следующие правила запускаются немедленно, не ожидая результата.

⚠️ Включать асинхронность стоит только если все правила события независимы друг от друга и порядок выполнения не важен.

Порядок событий при смене исполнителя / ответственного

Нелинейная последовательность событий при делегировании и удалении важна для правильной настройки смарт-правил:

Действие Условие Последовательность событий
Назначение ответственного Назначается единственный исполнитель Перед назначением исполнителя → После назначения исполнителя → Перед сменой ответственного → После смены ответственного
Назначение ответственного Новый ответственный уже в списке исполнителей Перед сменой ответственного → После смены ответственного
Удаление исполнителя Не ответственный Перед удалением исполнителя → После удаления исполнителя
Удаление исполнителя Ответственный, других нет Перед сменой ответственного → После смены → Перед удалением → После удаления
Удаление исполнителя Ответственный, есть один другой То же, что выше
Удаление исполнителя Ответственный, есть 2+ других Смарт-события не выполняются — система требует ручного назначения ответственного
Делегирование Новый ответственный уже в списке, «Удалить всех» = OFF Перед сменой ответственного → После смены → Перед удалением прежнего → После удаления
Делегирование Новый ответственный не в списке, «Удалить всех» = OFF Перед назначением → После назначения → Перед сменой → После смены → Перед удалением → После удаления
Делегирование «Удалить всех» = ON, несколько исполнителей Перед сменой → После смены → Перед удалением × N → После удаления × N

Отображение параметра в списке правил

В AdminSPA на странице настройки смарт-правил (привязка событий к пакетам действий) в колонке «Параметр» таблицы отображается расширенная информация о значении параметра события в зависимости от его типа:

  • Переход: название перехода, ID, исходный и целевой статусы (например, «Завершить (172060, Выполняется → Завершена)»). Название перехода — ссылка на страницу администрирования маршрута.
  • Дополнительный параметр: название параметра, ID, тип (например, «Приоритет (172, Число)»). Название параметра — ссылка на настройки дополнительных параметров категории.
  • Статус: название статуса, ID (например, «В работе (27)»).

Каталог событий и контекстные параметры

Полный реестр всех EventID (197 событий, значения 0–196) с C#-именами, группами и контекстными параметрами @eventParam* — в reference/automation/smart-events-catalog.md.

Ключевые правила, важные для настройки правил:

  1. Отменяемые события (префикс «Перед …»). Если событие начинается со слова «Перед …» (BeforeTaskCreate, BeforeStateChange, BeforeExtParamChange и т. п.), пакет действий может отменить событие через действие Отменить. Используется для запретов («нельзя понизить приоритет, если заказчик — гендиректор»). После «После …» отмена невозможна.

  2. Глобализация категорийных событий (с v2.268 Скульптор). Событие, помеченное флагом CanBeGlobal, можно привязать к пакету в Общих SMART без SubcatID — пакет сработает в любой задаче системы. Сначала отрабатывают категорийные пакеты, затем глобальные. Первое событие с флагом — AfterPostComment (29). Список расширяется добавлением canBeGlobal: true в EventsInfoInitialization.cs (помечено ⚑ в каталоге).

  3. Изначально глобальные группы. Группы Глобальные, Exchange, Пользователи работают только в Общих SMART без привязки к категории — это историческое поведение, не путать с глобализированными.

  4. События ресурсного планирования — два разных «Исполнителя». В контекстных параметрах присутствуют два различающихся параметра:

Параметр Что передаётся Когда использовать
Исполнитель (пользователь) UserID пользователя Для внесения затрат по сотруднику
Исполнитель (задача) TaskID задачи из Справочника ресурсов (раздел «Системный») Для внесения затрат по ресурсу

Не взаимозаменяемы — путаница приводит к ошибочной аналитике.

  1. @eventParam* для специальных событий. Часть событий передаёт массив (например, в ресурсном планировании параметр «Дата» — массив; читается через OPENJSON в SQL). Для EventID=64 («Во время открытия задачи») контекст UI приходит в @eventParam1. Для Exchange-событий (новое письмо, изменено событие в календаре) подробности встречи/письма не приходят в параметры — нужно дополнительно вызвать смарт-действие «Получить встречу» / «Получить письмо».

  2. Нумерация enum нелинейная. Числовые EventID не совпадают с порядком объявления в C# (AfterSignatureSigned=70 объявлен после BeforeSubscriberAdded=58). При SQL-диагностике используйте точные числовые значения.

Смарт-доступ (SmartAccess)

Где настраивается: автоадминка -> форма smart-access / Admin API -> SmartAccessController Таблица БД: dbo.SmartAccess

Динамические права доступа к задачам на основе смарт-выражений.

Поле Что контролирует
Name Название правила смарт-доступа
UsersSmartExpressionID Выражение, определяющее набор пользователей
ActionID Действие/право (чтение, запись, и т.д.)
GUID Уникальный идентификатор для миграции

Связанные формы: - smart-access-subcategories -- к каким категориям применяется правило (dbo.SmartAccessSubcategories) - smart-access-trigger-extparams -- при изменении каких ДП пересчитывать доступ (dbo.SmartAccessTriggerExtParams) - smart-access-trigger-groups -- при изменении членства в каких группах пересчитывать (dbo.SmartAccessTriggerGroups)

Эффект в runtime: - При изменении триггерного ДП или группы -- автоматический пересчет прав - Результат кешируется и применяется при проверке доступа к задаче - Тяжелая операция -- неправильная настройка триггеров вызывает массовые пересчеты

Типы доступа

Область Тип доступа Описание
Задача Просмотр Видимость задачи в списках и карточке
Задача Исполнение Право выполнять задачу
Задача Редактирование заказчика Изменение поля «Заказчик»
Задача Редактирование исполнителя Изменение состава исполнителей
Задача Редактирование акцептантов Изменение состава акцептантов подписи
Задача Редактирование срока Изменение дедлайна
Задача Добавление в исполнители Право стать исполнителем
Задача Добавление в подписчики Право подписаться на задачу
ДП Просмотр Видимость ДП в карточке
ДП Редактирование Изменение значения ДП

⚠️ Правила смарт-доступа действуют только в уже созданных задачах и не применяются при создании.

Смарт-выражение для пользователей

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

Результат выражения Поведение
Список ID Доступ предоставлен указанным пользователям
Пустая строка "" Доступ не предоставлен никому (нормальная ситуация)
null Пересчёт прерывается — ошибка конфигурации
Ошибка выполнения Пересчёт прерывается

⚠️ Возвращайте пустую строку "", а не null, если список пользователей пуст. Иначе пересчёт прерывается и предыдущее состояние доступа «замораживается».

Триггеры пересчёта

Пересчёт смарт-доступа инициируется при изменении ДП, указанных в форме smart-access-trigger-extparams, или при изменении членства в группах (smart-access-trigger-groups).

⚠️ Пересчёт выполняется только при изменении указанных ДП — даже если смарт-выражение ссылается на другие параметры (заказчик, исполнитель и т.п.). Для подписки на изменение не-DP параметров: создайте вспомогательные ДП, копируйте в них значения основных параметров (через отдельное смарт-правило), и настройте триггер на эти вспомогательные ДП.

При наличии настроенных триггеров по ДП, смарт-доступ пересчитывается также после создания задачи (если ДП уже заполнен при постановке — повторный пересчёт не производится).

Видимость в дереве категорий

Если на категорию настроен смарт-доступ, она отображается в дереве категорий всегда — даже если у пользователя нет доступа ни к одной задаче в этой категории.

Действия (меню)

Действие Описание
Синк активных задач Принудительный пересчёт для всех активных задач привязанных категорий
Синк всех задач Пересчёт для всех задач (включая завершённые) привязанных категорий
Удалить привязки доступа к задачам Очистка таблицы SmartAccessViewTasks для данного правила. Выполнить перед удалением самого правила
Пересчет при смене ДП Настройка списка ДП-триггеров
Пересчет при добавлении в группу Настройка групп-триггеров

⚠️ Ручной синк («Синк активных задач» / «Синк всех задач») необходим при первичном подключении правила — в этом случае автоматического пересчёта ещё не было. Также синк можно привязать к расписанию через смарт-действие «Пересчитать смарт-доступ в задачах».

AdminSPA — сохранение правил ДП

В AdminSPA правила смарт-доступа к ДП сохраняются независимо от основной формы настроек ДП. Каждое правило фиксируется сразу при нажатии кнопки «Добавить параметр» в модальном окне. После сохранения форма автоматически очищается для добавления следующего правила. Это предотвращает потерю данных при добавлении множественных правил.

Очереди событий (Queues + CustomQueueActions)

Где настраивается: автоадминка -> формы queues, custom-queue-actions Таблицы БД: dbo.Queues, dbo.CustomQueueActions

Очереди -- механизм асинхронной обработки событий.

dbo.Queues -- определение очереди:

Поле Что контролирует
Alias Уникальный псевдоним очереди
Description Описание
Origin Происхождение (системная / пользовательская)
IsReadOnly Запрет редактирования

dbo.CustomQueueActions -- привязка действий к очереди:

Поле Что контролирует
QueueId Ссылка на очередь
OrderID Порядок обработки
Alias Псевдоним действия
SmartFilterID Условие (смарт-фильтр)
ActionPackID Пакет действий для выполнения
Origin Происхождение
IsReadOnly Запрет редактирования

Назначение и типы событий

Очереди используются преимущественно при интеграции с внешними системами.

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

На странице «Привязки действий к событиям» пакеты внутри одного события можно переупорядочить перетаскиванием.

Обработка событий запускается заданием QueueEventsJob.

Системные события (из коробки)

Событие Описание
ChangeEdocumentStatus Изменился статус электронного документа в Диадоке
ReceiveNewEdocument Получен новый электронный документ через Диадок

Подробнее об архитектуре очередей: docs/platform/backend/message-queues.md

Эффект в runtime: - При поступлении события в очередь выполняются привязанные действия в порядке OrderID - Фильтр (SmartFilterID) определяет, подходит ли событие для данного действия - Обработка очередей -- через Valhalla.Scheduler (фоновые сервисы)

Произвольные события (CustomEvents)

Где настраивается: - Настройки категории → Смарты → вкладка «Произвольные события» - Общие смарты (/administration/smart-packs) → вкладка «Произвольные события» (глобальные) - Автоадминка → форма custom-events

Таблица БД: dbo.CustomEvents

Поле Что контролирует
SubcatId Категория, к которой привязано событие
Code Уникальный код события. Только буквы латиницы и цифры, без пробелов. Уникален в рамках категории.
Description Название события (отображается в интерфейсе)

Назначение

Произвольные события позволяют запустить пакет действий для множества задач категории по условию. Типичные сценарии: - Массовый пересчёт данных во всех задачах категории (по кнопке или расписанию). - Инициирование обработки задач из другой категории из контекста текущей.

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

Как настроить

  1. Создать событие — в настройках категории добавить запись с уникальным Code и названием.
  2. Привязать обработчик — создать смарт-правило на системное событие «При произвольном событии», указав конкретный Code.
  3. Вызвать событие — через смарт-действие «Инициировать произвольное событие» из любой категории. В действии указывается:
  4. Целевое событие (категория + код)
  5. Сфера действия: текущая задача / конкретный ID / ID из смарт-выражения / список ID / смарт-отбор коллекции

Потоки сообщений (MessageFlows)

Где настраивается: автоадминка → форма message-flows (страница «Потоки» в разделе очередей) Таблица БД: dbo.MessageFlows

Потоки определяют стратегию обработки событий в очереди. Рекомендуется создавать отдельные потоки для событий из разных внешних систем — это позволяет изолировать ошибки одной интеграции от другой. Обработка запускается заданием QueueEventsJob.

Поле Что контролирует
FlowName Имя потока
IsStoppable Можно ли остановить поток при ошибках
HasErrors Флаг наличия ошибок (красный индикатор в списке)
FailedAttemptsCounter Накопленный счётчик неудачных попыток
ActionOnError Стратегия при ошибке: skip (пропустить) / stop (остановить)

Стратегии при ошибке

Стратегия Поведение Счётчик попыток
Пропускать Ошибочное событие пропускается, остальные продолжают обрабатываться Не увеличивается
Останавливать После ошибки обработка всего потока прекращается Увеличивается

При стратегии «Останавливать»: администратор должен удалить ошибочное событие из очереди или устранить причину ошибки, после чего запустить повторную обработку вручную.

Подробнее об архитектуре: docs/platform/backend/message-queues.md

Смарт-скрипты

Где настраивается: Admin API -> SmartScriptEditorController Нет формы автоадминки -- настраиваются только через API/SPA Базовый путь: /api/admin/smart/scripts/...

Смарт-скрипты -- произвольный код на 5 языках (Lua/JavaScript/Python/OneScript/C#), выполняемый как действие в пакете или по расписанию.

Документация по языкам: js-scripting-jint.md, csharp-scripting-roslyn.md, python-scripting.md.

Получение списка скриптов

POST /api/admin/smart/scripts/list

Возвращает список смарт-скриптов для грида в AdminSPA — используется в общих смартах и на вкладке «Скрипты» в настройках категории.

Параметры запроса (SmartScriptsQueryRequestDto):

Параметр Тип Назначение
IsContextual bool? Фильтр по признаку контекстности: true — только контекстные скрипты, false — только неконтекстные. Игнорируется, если задан ContextType
ContextType enum Фильтр по конкретному типу контекста скрипта; имеет приоритет над IsContextual
SubcatId int? Категория
EventId int? Событие
IsLibrary bool? Фильтр библиотечных скриптов
DescriptionFilter, ScriptFilter string? Поиск по названию и по коду
Skip, Take, OrderBy, Order Пагинация и сортировка

Создание нового скрипта

editor_dto = {
    "script": {
        "id": 0,                    # 0 = новый (сервер назначит ID)
        "description": "Название",
        "scriptCode": js_code,
        "language": "JavaScript",   # "Lua" | "JavaScript" | "Python" | "OneScript" | "CSharp"
        "contextType": "None",      # СТРОКА, не null, не ""
        "isLibrary": False,
        "isDisabled": False
    },
    "context": None                 # null при программном создании
}
# POST /api/admin/smart/scripts/editor

Значения language (enum ScriptLanguage / LanguageId в БД):

Строка LanguageId Runtime Модель Таймаут Возврат результата Доступ к API платформы
"Lua" 0 NLua (in-process) Внутренний 5 мин RESULT = value SQL, SMART, HTTP, CACHE, REGISTRY, FILES, UTILS
"JavaScript" 1 Jint 4.6.0 (in-process) Внутренний 5 мин RESULT = value SQL, SMART, HTTP, CACHE, REGISTRY, FILES, UTILS
"Python" 2 Python Executor (HTTP) Внешний сервис (Docker) 30 сек return value из execute(ctx) Нет — только данные из ctx
"OneScript" 3 OneScriptEngine (in-process) Внутренний 5 мин RESULT = value SQL, SMART, HTTP, CACHE, REGISTRY, FILES, UTILS
"CSharp" 4 Roslyn Scripting API (in-process) Внутренний 5 мин Последнее выражение SmartScriptGlobals — прямой доступ, без маршалинга

Архитектурные различия: Lua, JS, OneScript, C# — in-process (выполняются внутри бэкенда). Python — внешний HTTP-сервис (POST /execute/code на Docker-контейнер). Python получает только сериализуемые данные через ctx. Подробнее: python-scripting.md, csharp-scripting-roslyn.md.

Контекстные переменные

Основные переменные (CONTEXT, EVENTPARAMS, SESSION_USER) — см. academy-patterns.md. Дополнительные:

Переменная Доступна в Описание
DB_TYPE Lua, JS, OneScript Тип СУБД: "MSSQL" или "PG". Используется для условного ветвления SQL-кода
SYSTEM_INFO Lua, JS, OneScript Объект с полями: version — версия приложения, app — имя приложения (TC или Uniform)
RESULT Все языки Выходной параметр скрипта. В Lua/JS/OneScript: RESULT = value. В Python: return value из execute(ctx). В C#: последнее вычисленное выражение

Репозиторий и include()

Скрипты-библиотеки подключаются функцией include:

  • include(id) — по ID (рекомендуется)
  • include("Description") — по названию (не рекомендуется)
  • include(id, subcatId) — по ID из указанной категории (снимает ограничение «только из репозитория»)

⚠️ Максимальная глубина рекурсии include5 уровней. В подключаемых скриптах не должно быть вычислений, только определения функций и глобальных переменных.

UI редактора скриптов

  • — история версий скрипта (каждый POST в /editor создаёт новую версию)
  • ··· — меню: «Из репозитория/библиотеки» (пометка библиотечного скрипта), переход в «Репозиторий»
  • Выполнить — тестовый запуск скрипта. Результаты отображаются в нижней панели
  • Параметры выполнения (раскрывающаяся панель) — поля «Id контекста» и параметры события для тестирования

Обновление существующего

# 1. GET текущий DTO
resp = GET(f"/api/admin/smart/scripts/{script_id}/editor")
dto = resp["data"]

# 2. Обновить ТОЛЬКО код — остальные поля НЕ ТРОГАТЬ
dto["script"]["scriptCode"] = new_code

# 3. POST обратно
POST("/api/admin/smart/scripts/editor", {"script": dto["script"], "context": None})

Критически важно: при деплое менять только scriptCode. Все остальные поля (eventId, language, contextType, subcatId) — из GET, как есть. Ручная установка eventId — только при создании нового SS (id=0).

Версии и откат

GET /api/admin/smart/scripts/{scriptId}/versions — возвращает не более 10 последних версий скрипта, отсортированных по убыванию номера версии. Версия создаётся автоматически при каждом POST в /editor.

Откат: получить scriptCode нужной версии → POST в /editor с тем же id. Это создаст новую версию (не перезапишет).

Удаление версий: DELETE /{scriptId}/versions/{version} (одна) или DELETE /{scriptId}/versions/ (все). Текущая активная версия не удаляется.

MCP-тулы SmartScript (платформа)

MCP-сервер Тулы
/mcp-admin-api-smart-scripts smart_scripts_versions, smart_scripts_query_scripts, smart_scripts_query_scripts_groupped_by_subcat, smart_scripts_delete_version, smart_scripts_delete_versions
/mcp-admin-api-v2-smart-editor smart_editor_get_editor(scriptId), smart_editor_update_script(save), smart_editor_execute_script(editor), smart_editor_delete_script(scriptId, confirm), smart_editor_get_action_params()

Деплой SS через MCP (если сервер подключён):

smart_editor_get_editor({ scriptId: 492 })  → dto
dto.script.scriptCode = новый_код            → НЕ ТРОГАТЬ eventId, language, contextType!
smart_editor_update_script({ save: dto })    → сохранено + автоверсия

Прод = source of truth для SmartScript

Локальные копии SS-кода (в docs/, ServiceFlow/) устаревают. Перед любым патчем: 1. Загрузи актуальный код с прода: GET /api/admin/smart/scripts/{id}/editor 2. Проверь историю версий: GET /api/admin/smart/scripts/{id}/versions 3. Патчи применяй к продовому коду, не к локальной копии

Таблица SmartScripts — колонки БД

Ожидаемое Реальное Ловушка
SmartScriptId Id Invalid column name 'SmartScriptId'
Language LanguageId Enum int, не строка в БД
Name Description Нет колонки Name

URL — частая ошибка

smart-scripts (дефис) → 404. Правильно: smart/scripts (слеш).

  • GET /api/admin/smart/scripts/{id}/editor — читать
  • POST /api/admin/smart/scripts/editor — сохранить

Типичные ошибки SmartScript API

Проблема Причина Решение
500 при POST Payload без обёртки {script, context} Всегда {script: {...}, context: null}
EVENTPARAMS undefined в runtime eventId сброшен в null после GET→POST Проверить что GET вернул правильный eventId. Если null — восстановить оригинальное значение
contextType ошибка Передали null или пустую строку Строка "None" (или "Task", "User")
GET /editor vs GET /{id}/editor Первый = новый пустой DTO, второй = существующий Для чтения: /{id}/editor
include(503) → crash SS 503 занят другим скриптом Проверить ID скрипта перед include()
Jint StatementsCountOverflow Лимит statements на production MaxStatements(100_000_000) по умолчанию. Для ETL — разбивать на batch
languageId вместо language API молча игнорирует languageId, ставит Lua=0 Поле называется language. Значения: "JavaScript" (строка) или 1 (int). Enum: Lua=0, JavaScript=1, Python=2, OneScript=3, CSharp=4
RESULT is not defined Jint ReferenceError при if (!RESULT) Использовать typeof RESULT === "undefined" или var RESULT; в начале
include(N) → 500 без диагностики Ошибка при загрузке include — до try/catch Отладка: POST /api/admin/smart/scripts/editor/execute. Тестировать include по одному
Публикация → 500 без деталей Publication endpoint глотает ошибки SS Для отладки: editor/execute возвращает {success, error, output, result}

HTTP из SmartScript

Проблема Причина Решение
HTTP.send_http_request + multipart → FormatException StringContent(body, enc, contentType) ломается на boundary Не подходит для multipart. Использовать HTTP.post_multipart
HTTP.post_multipart без filename Value (без FileId) → StringContent без filename= Для загрузки файлов: только через FileId (из хранилища 1Формы)
Большой SS-код через shell → crash jq --argjson / переменные > 64KB Python для отправки больших SS: urllib.request + json.dumps()

Таблицы логов SmartScript

AutomationScriptsLog: Id, Type, ObjectKey, ObjectParams, AdditionalInfo, TaskId, UserID, ThreadId, Duration, Date, ObjectName, PlanExecution, AppPool - НЕ существует: Tag, Message, ScriptId, EventName, CreatedDate - API /api/admin/smart/scripts/logs ненадёжен — может вернуть невалидный JSON. Использовать SQL.

Lua SmartScript — особенности

Проблема Симптом Решение
SQL:query(sql) без второго аргумента Запросы молча возвращают nil Всегда SQL:query(sql, {}) — второй аргумент обязателен, даже если пустой
PG: кавычки вокруг идентификаторов "Tasks"relation "Tasks" does not exist На dev-pg таблицы/колонки lowercase без кавычек (схема dbo)
PG: CASE ветки с разными типами 42804: CASE types text and timestamp cannot be matched Обе ветки CASE должны возвращать одинаковый тип
PG: WITH RECURSIVE syntax error at or near "UNION" PG требует WITH RECURSIVE. MSSQL не принимает. Решение: WITH {PG}RECURSIVE{/PG}

Jint / SmartScript runtime — production

Проблема Симптом Решение
NpgsqlDataReader leak Запрос к PG висит 16+ часов, wait_event=ClientWrite try/finally для reader.Close() + cmd.Dispose(). SET statement_timeout = '300s'
pg_terminate_backend → permission denied d10taskreader не может убить чужие сессии Нужен superuser или роль pg_signal_backend

Журнал автоматизации

Журнал фиксирует выполнение смарт-автоматизаций: смарт-запросов, действий, расписаний, пакетов, смарт-доступа и смарт-скриптов. Запись SQL-запросов — через NLog.

Пороги логирования (Общие настройки приложения)

Для каждого типа смарт-операции задаётся отдельный порог в миллисекундах. Логика общая: - поле пустое → логирование выключено; - 0 → логируются все вызовы; - >0 → логируются только вызовы дольше порога.

⚠️ Минимально допустимое значение — 100 мс (форма не позволит сохранить меньше). Рекомендуемое значение для большинства типов — 200 мс.

Настройка Тип Рекомендация
Логировать время выполнения smart-запросов дольше, мс smart expressions 200
Логировать время выполнения smart-действий дольше, мс actions 200
Логировать выполнение smart-пакетов дольше, мс packs (с 2.264 «Кассиопея» — также смарт-расписания) 200
Логировать выполнение smart-доступа дольше, мс smart access 200
Логировать SQL-запросы NLog SQL 200 (по умолчанию)
Логировать обращение в WS из БД дольше, мс внешние HTTP-вызовы из SQL 5000
Логировать обращения к опубликованным объектам дольше, мс publications по необходимости
Ограничение длины трейса ошибок, кб exception traces 2 кб (по умолчанию)

Связанные тонкие настройки:

  • Логировать тело запроса к WS из БД — флаг. Если включён, тело запроса пишется в «Входящие параметры», тело ответа — в «Доп. информация» лога автоматизации.
  • Запускать SMART-запросы и фильтры с использованием ReadUncommitted транзакцийустаревшая (не используется). Для MS SQL Server включала отдельную транзакцию с уровнем изоляции READ UNCOMMITTED для смарт-выражений; на PostgreSQL не применяется (требовала бы prepared transactions). На PG разрешено подавление ambient-транзакции (SuppressTransaction) для смарт-выражений с отдельной строкой подключения (SmartConnectionString).

Глубина рекурсии смарт-пакетов

Параметр «Глубина рекурсии смарт-пакетов» (значение по умолчанию — 10) ограничивает количество рекурсивных вызовов смарт-действия в рамках одного потока (поток определяется TaskID + UserID + текущим контекстом). При превышении смарт-действие не выполняется, ошибка фиксируется в журнале ошибок.

⚠️ Проверка не применяется к пакетам, выполняющимся в рамках расписаний, и к циклическим пакетам.

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

Кастомная настройка SmartScriptLogLevel управляет объёмом записей от скриптов.

Значение Записываются Макс. сообщений за выполнение
Debug Все: debug + info + error debug ≤ 10, info ≤ 30, error ≤ 50
Info Информационные + ошибки info ≤ 30, error ≤ 50
Error (default) Только ошибки error ≤ 50

Методы в скриптах: SS.logDebug(), SS.logInfo(), SS.logError() (Lua/JS/OneScript); console.log(), console.warn(), console.error() (JS). Сообщения сверх лимита отбрасываются.

⚠️ SS.logError() и console.error() дублируются в журнал исключений (ExceptionsLog) независимо от SmartScriptLogLevel. Ошибки скриптов всегда видны в журнале «Ошибки» как тип SmartScript.

⚠️ При ручном запуске скрипта из UI администрирования в журнал автоматически записывается текст исполняемого скрипта и пользователь-инициатор.

Идентификация в стек-трейсах и ExceptionsLog: формат SmartScript {ID} ("{Название}").

Реализация и затронутые файлы — см. known-issues.md § 6 «SmartScript Execution Logger».

План запроса (только PostgreSQL)

Колонка «План запроса» отображается при условиях: 1. СУБД — PostgreSQL 2. Включено логирование SQL-запросов в общих настройках приложения 3. Задана кастомная настройка LogPlanExecution (порог в миллисекундах) 4. Фактическое время выполнения превысило порог

CustomSettings — таймауты и логирование скриптов

Ключ Тип / Default Назначение
SmartScriptJSEngineTimeoutMinutes int (мин) Таймаут выполнения JavaScript SmartScript в движке Jint. Применяется как к таймауту скрипта, так и к PromiseTimeout. Изменение вступает в силу без перезапуска сервера
LogPlanExecution int (мс) Порог для записи плана выполнения SQL-запроса в журнал автоматизации (только PG, см. выше)

Расписание (SmartRecurrence)

Где настраивается: - Настройки категории → Смарты → Расписания - Общие смарты (/administration/smart-packs) — для расписаний без привязки к конкретной категории - Admin API → SmartRecurrenceController (/api/admin/smart/recurrence, GET, POST)

Механизм периодического запуска пакетов действий по таймеру. В отличие от смарт-правил, не привязан к событию — запускается заданием SmartRecurrenceJob.

Список расписаний

Расписания с ошибками выделены красным. Колонка «Из лимита» — накопленное число неудачных попыток; «Лимит» — максимально допустимое (соответствует настройке «Попыток выполнения»).

Поля формы

Настройка Описание
Активно Включает/выключает расписание. Отключённое расписание сохраняется, но не запускается.
Интервал Частота запуска: Ежеминутно / Ежедневно / Еженедельно / Ежемесячно / Ежегодно. Синтаксис отличается от cron — настраивается через UI-форму, не строкой.
Начало повторения Дата и время первого запуска.
Прекратить после Дата и время, после которых расписание не запускается, даже если интервал наступает.
Повторять до Конечная дата действия расписания; после достижения выполнение прекращается.
Вложенные файлы Режим работы с файлами задач: «Не копировать» / «Использовать ссылки на оригинал» / «Создать новые копии».
Попыток выполнения Максимальное число повторных попыток при ошибке. По умолчанию: 5, минимум: 1. При превышении расписание становится красным и не запускается до сброса счётчика.
Асинхронно Пакет выполняется в отдельном потоке. По умолчанию все расписания используют один поток — «тяжёлый» пакет может задержать остальные. Флаг устраняет это: пакет запускается параллельно.
Режим выполнения «Вне контекста задачи» — пакет выполняется независимо от конкретной задачи (доступен ограниченный набор действий). «Для каждой задачи [смарт-фильтр]» — пакет выполняется для каждой задачи категории, удовлетворяющей условию фильтра.
Пакет действий Пакет, который запускается в назначенное время.
Игнорировать ошибки в процессе выполнения Если включено — при ошибке на одной задаче выполнение продолжается для следующих. По умолчанию выключено: ошибка прерывает весь запуск.

Операции со строкой расписания

Действие Как вызвать
Создать Кнопка «Создать смарт-расписание» над таблицей
Редактировать Клик по строке или контекстное меню → «Редактировать»
Принудительно выполнить Контекстное меню → «Выполнить» — запускает пакет вне графика
Сбросить счётчик ошибок Контекстное меню → «Сбросить счётчик неудачных попыток» — расписание перестаёт быть красным и снова доступно
Удалить Контекстное меню → «Удалить»

Ограничения

  • Расписание в настройках категории работает только в рамках этой категории и только при наличии хотя бы одной задачи. Для задач из другой категории — используй расписания в Общих смартах.
  • Пакеты с действием «Отменить» недоступны для расписаний.
  • Проверка глубины рекурсии смарт-пакетов (см. выше) к расписаниям не применяется.

Смарт-фильтр в режиме «для каждой задачи»

Если фильтр был создан как смарт-выражение, а затем преобразован в TSQL, он по умолчанию содержит условие привязки к контексту задачи:

WHERE ([Extent1].[TaskID] = @ContextID) AND [...]

При использовании в расписании это условие нужно убрать: у расписания нет контекста одиночной задачи.

Логирование

С версии 2.264 «Кассиопея» выполнение расписаний логируется через настройку «Логировать выполнение smart-пакетов дольше, мс» (см. раздел «Журнал автоматизации» выше).

Типичные ошибки настройки

Симптом Причина Где проверить SQL-диагностика
Правило не срабатывает Неверный EventID или ParameterValue Форма general-smart -> EventID, ParameterValue select ID, Name, EventID, ParameterValue, IsFilter, SubcatID from dbo.SmartExpressions where SubcatID = {id} and IsFilter = 0
Правило срабатывает дважды Дубль в EventsActions + правило на глобальном уровне SmartActionsPacksOnEventsController -> list select * from dbo.EventsActions where SubcatID = {id} and EventID = {eventId}
Смарт-доступ не пересчитывается Не настроены триггеры (ExtParams/Groups) Формы smart-access-trigger-* select sa.Name, count(te.Id) as TriggerEP, count(tg.Id) as TriggerGrp from dbo.SmartAccess sa left join dbo.SmartAccessTriggerExtParams te on sa.ID = te.SmartAccessId left join dbo.SmartAccessTriggerGroups tg on sa.ID = tg.SmartAccessId group by sa.Name
Массовые тормоза при изменении ДП Слишком широкий триггер смарт-доступа (все ДП категории) Форма smart-access-trigger-extparams select sa.Name, count(*) as TriggerCount from dbo.SmartAccessTriggerExtParams te inner join dbo.SmartAccess sa on te.SmartAccessId = sa.ID group by sa.Name order by count(*) desc
Действие в пакете не выполняется Асинхронное правило, очередь заполнена / остановлена Форма message-flows -> HasErrors select FlowName, HasErrors, FailedAttemptsCounter from dbo.MessageFlows where HasErrors = 1
Произвольное событие не вызывается Неверный Code или SubcatId Форма custom-events select * from dbo.CustomEvents where SubcatId = {id}

Недавние изменения (2.268.62–2.268.83)

Редактор пакетов — очистка ДП через «Оставить пустым» (v2.268)

В редакторе пакетов действий исправлена передача пустого значения ДП: если в конфигурации действия для ДП выбрано «Оставить пустым», теперь корректно передаётся isEmpty: true в payload при сохранении. Ранее такие ДП молча исчезали из конфигурации. Позволяет настраивать массовую очистку значений ДП через смарт-действия без отдельного ClearExtParamValue.

AdminSPA — вкладка Lua-скрипты (2.268.62)

Доработка вкладки Lua-скрипты в AdminSPA — улучшенный UI для управления Lua-скриптами.

AdminSPA — smart grid ID column (#2.268.75, Гусев)

Исправлена ширина колонки ID в smart-гриде AdminSPA.

API сохранения шаблона автогенерации без перегенерации задач (2.268.74)

Новый endpoint POST api/admin/smart/packs/{subcatId}/save-template — сохраняет шаблон автогенерации без пересоздания задач. Ранее при любом сохранении шаблона задачи перегенерировались. SPA-кнопка: 2.268.75.

System-enums sync API (2.268.60–2.268.62)

Новый endpoint POST /api/admin/system-enums/{enumName}/sync — синхронизация системных enum-ов между площадками.

JSON-синтаксис модификации ДП

Форматы значений для смарт-действий «Изменить значение ДП», «Копировать значение ДП» и аналогичных. Для сложных типов ДП платформа ожидает JSON-строку.

SelectUsers — Выбор пользователей

{"Users":{"Added":[ID1,ID2],"Deleted":[ID3]},"Groups":{"Added":[ID4]},"OrgUnits":{"Deleted":[ID5]}}
  • Ключи верхнего уровня: Users, Groups, OrgUnits
  • Операции внутри: Added (добавить), Deleted (удалить)
  • Значения — ID (int), преобразованные в строку
  • Три способа указания значений: напрямую (ID), через другое ДП, через SQL-запрос

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

Email — Адресаты

{"ValsToAdd":[{"UserId":1821},{"Email":"user@example.com"}],"ValsToDelete":[{"UserId":14}]}
  • ValsToAdd — добавить адресатов
  • ValsToDelete — удалить адресатов
  • Каждый адресат: {"UserId": ID} или {"Email": "address"}

Таблица — строки и ячейки

Ячейка: {ID_колонки:{"First":"значение","Second":"доп.значение"}}

  • First — основное значение (тип должен соответствовать типу колонки)
  • Second — только для выпадающих списков (колонка значения). Для остальных типов — пропускается или null
Операция Префикс Синтаксис Пример
Добавить строку + '+[{111:{"First":"текст"},222:{"First":"123"}}]' ID строки не указывается
Изменить строку = '={"First":"ID_строки","Second":{111:{"First":"новое"}}}' ID строки в кавычках
Удалить строку - '-ID_строки' '-111'
Массовое обновление = '=[{"First":"1","Second":{...}},{"First":"2","Second":{...}}]' Массив объектов
Заменить все (full replace) # '#{"1":{11:{"First":"x"}},"2":{11:{"First":"y"}}}' Удаляет отсутствующие строки, изменяет существующие, добавляет новые
Пересоздать все \| '|{"1":{...},"2":{...}}' Удаляет все строки, затем создаёт из переданных данных

⚠️ Если ID существующих строк неизвестны — используйте оператор \|. При # строки с отсутствующими ID будут удалены.

⚠️ Если в таблице есть скрытые колонки — они обязаны быть заполнены, иначе возникнет ошибка.

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

'-111#222|||текст_комментария'

Массовое обновление нескольких строк — через массив объектов (префикс =).

Выбор нескольких задач

Операция Синтаксис Пример
Добавить задачу ВСтроку(ID) "123456"
Добавить несколько ID + "]\|\|[" + ID "111111]\|\|[222222]\|\|[333333"
Удалить задачу "-" + ВСтроку(ID) "-123456"
Обновить комментарий "=" + ID + "\|\|" + "текст" "=123456\|\|комментарий"
Полная замена "$" + ID + "]\|\|[" + ID "$123]\|\|[456]\|\|[789" — заменяет все значения
Несколько операций Через # "-111111#222222\|\|коммент"

Файл

Режим Описание
Единичный Без признака «Мультифайл» — обращение как к одному объекту
Мультифайл С признаком «Мультифайл» — обращение как к коллекции
Добавить к существующим Префикс +: '+id1,id2,id3'
Версия файла Формат FileID.VersionID
Из другой задачи Через SQL-запрос к FileStorageFiles + FileStorageFileToTaskLinks

Экранирование в значениях

Символ Экранирование Пример
" \" "начало \"ABC\" продолжение"
\ \\ "начало \\\\ продолжение"
' '' "начало ''ABC'' продолжение"
\n, \r Не экранировать Работает только для колонок «Большой текст»

Связанные документы

  • docs/domains/smart-actions/backend.md -- backend-архитектура (контроллеры, сервисы, маршрут данных)
  • docs/domains/smart-actions/actions-reference.md -- каталог 70+ типов действий с параметрами
  • docs/domains/smart-actions/data-flow.md -- E2E диагностика выполнения пакетов
  • docs/domains/smart-filters/backend.md -- смарт-фильтры (условия для правил)
  • docs/platform/backend/admin-architecture.md -- общая архитектура администрирования
  • docs/reference/database/dbadmin-forms-map.md -- карта всех форм автоадминки