Паттерны Smart-автоматизации¶
Smart-выражения — основы¶
Два режима редактора¶
- SMART (по умолчанию) — графический конструктор с деревом сущностей
- T-SQL — прямой ввод SQL-запросов
Переключение в T-SQL необратимо — вернуться в режим SMART после конвертации невозможно.
Дерево сущностей¶
Содержит все доступные объекты для smart-выражения:
| Узел | Что содержит |
|---|---|
| Системные параметры | № задачи, ID заказчика, текст, дата создания, срок |
| ДП категории | Все ДП, настроенные в текущей категории |
| Свойства контекста | Зависят от точки вызова (событие, фильтр, подпись) |
| Результаты предыдущих действий | Доступны внутри пакета |
| Прочее | Все объекты системы вне контекста: категории, пользователи, группы |
Единичные объекты (например, заказчик) раскрываются стрелкой > для доступа к вложенным параметрам. Множественные объекты (ДП «Выбор пользователей», «Таблица») представлены как коллекции со специальными конструкциями.
Правила составления¶
- Строковые выражения заключаются в одинарные кавычки
- Для преобразования числа в строку — функция
ВСтроку - Вместо ручного ввода ID — кнопка «ID объекта» (вставляет типизированную ссылку)
- Не копировать выражения из других задач/уроков — выбирать элементы вручную из дерева
- Тестировать через поле «Протестировать на задаче №» + кнопка «Тест»
Smart-фильтры¶
Базовый принцип¶
Smart-фильтр — это smart-выражение, возвращающее: - boolean (true/false, 1/0) — для фильтрации отдельных задач - массив элементов — для отбора списка задач (в расписаниях на T-SQL)
Фильтрация в табличных представлениях (smart-поиск)¶
Путь: Настройки категории > Смарты > Доступен в смарт-поиске > + Создать.
Пример — отбор задач в статусе «Новая заявка»:
ID статуса = <ID нужного статуса>
Галка «Доступен в smart-поиске» управляет видимостью отбора в UI.
Фильтрация в БИ (Блок Используется)¶
БИ > Добавить таблицу > Источник: smart-фильтр. Фильтр возвращает true для задач, которые должны отображаться.
Пример — задачи не в статусе «Отклонено», где ДП совпадает с текущей задачей:
ID категории = 33 И ID статуса != 16 И Задача.ДП[90] = Текущая задача.ДП[90]
Ограничение: если отбор задач в БИ ограничивается smart-фильтром, связи по ДП Lookup не учитываются.
Фильтрация видимости кнопки перехода¶
Переход > Ограничить доступ > smart-фильтр видимости кнопки. Фильтр возвращает true — кнопка видна, false — скрыта.
Пример — кнопка видна, если задача в ДП Lookup находится в определенном статусе:
Задача.ДП[«Заявка на приём»].ID статуса = <ID статуса «Организация рабочего места»>
Фильтрация значений в ДП Lookup¶
Настройки ДП > smart-фильтр (блок «Табличный вид»). Фильтрует задачи, доступные для выбора.
Важно: smart-фильтр в ДП Lookup распространяется на этот ДП во всех категориях, где он добавлен. Для ограничения по категории — добавить дополнительное условие в фильтр.
Smart-события и триггеры¶
Основные события¶
| Событие | Параметры | Применение |
|---|---|---|
| После постановки | Инициатор | Заполнить ДП, назначить исполнителей |
| После перехода | Переход (опционально) | Автоматические действия при смене статуса |
| После смены ДП | ДП, инициатор, новое/старое значение | Пересчет зависимых полей |
| Перед сменой ДП | ДП, инициатор, новое/старое значение, причина | Валидация, блокировка |
Если для события «После перехода» не выбран конкретный переход — пакет выполняется после любого перехода.
Паттерн: расчет даты по условию¶
Событие: после смены ДП «Дата выхода на работу».
Кейс 1 — вычисление: если значение не пустое, рассчитать дату окончания испытательного срока:
Дата выхода + Период испытательного срока (месяцев)
ДП[«Дата выхода на работу»] есть значение
Кейс 2 — очистка: если значение пустое, очистить зависимое поле.
Smart-фильтр: ДП[«Дата выхода на работу»] нет значения
Паттерн: автоматический переход по условию¶
Событие: после перехода «Выполняется - Ожидание выдачи». Smart-фильтр (два условия через И):
ДП[«Заявка на приём сотрудника»] есть значение
И
Текущая дата >= ДП[«Дата выхода на работу»]
Smart-действия — типы¶
Действие: изменить срок¶
Параметры: - Инициатор — по умолчанию системный пользователь - Срок — значение или smart-выражение (рекомендуется Smart/TSQL) - Причина — обязательна - Задача — по умолчанию текущая - Не писать комментарий — опционально
Пример выражения для срока:
ДобавитьРабочихДней(ТекущиеДатаИВремя, 3)
Действие: изменить значение ДП¶
Указывается целевой ДП и новое значение (фиксированное или через smart-выражение). Для очистки значения — передать пустое значение.
Действие: назначить исполнителей¶
Два действия часто используются вместе: 1. «Удалить текущих исполнителей» 2. «Добавить группу исполнителей» (параметр «Кого (группа)»)
Порядок важен: сначала удаление, потом добавление.
Действие: создать задачу¶
Параметры: категория, заказчик, ДП при создании, связь с текущей задачей (подзадача или связанная).
Действие: запрос подписи¶
Условие запроса через smart-фильтр. Акцептанты — по smart-выражению.
Для проверки неуволенных пользователей в ДП «Выбор пользователей»:
в Согласующие есть элемент, такой что Уволен есть ложь
Коллекция ExtParamSelectUsersValues содержит значения ДП типа «Выбор пользователей».
Smart-пакеты¶
Последовательность¶
Действия внутри пакета выполняются строго по порядку (сверху вниз). Пакеты внутри события — тоже по порядку.
Можно менять очередность перетаскиванием строк.
Циклические пакеты¶
Для повторения действий над несколькими объектами. Настройка: 1. Переключить пакет в режим «Циклический» 2. Задать список итерируемых объектов — smart-выражение, возвращающее массив ID 3. Опционально — условие прерывания цикла 4. В действиях использовать переменные цикла из контекста SMART
Индекс итерации начинается с 0. Доступен в smart-выражениях внутри пакета.
Важно: если при создании действий в циклическом пакете переменные цикла не появляются в дереве — сохранить пакет, закрыть и открыть заново.
Smart-кнопки¶
Создание¶
Путь: Настройки категории > Кнопки > Создать. Указать имя, видимость, настройки доступа.
Отличие от кнопки перехода: smart-кнопка не связана с маршрутом. Примеры: рассчитать ДП, создать задачу, отправить email.
Видимость¶
Регулируется по: - Статусу задачи - Группам пользователя - Smart-фильтру
Привязка действий¶
К кнопке привязывается пакет действий (+ рядом с полем «Пакеты действий»). Несколько пакетов выполняются последовательно.
Пример: кнопка «Отменить приём сотрудника» — пакет 1 меняет статус текущей задачи на «Отклонено», событие смены статуса запускает циклический пакет 2, который переводит все связанные задачи.
Smart-расписания¶
Настройка¶
Путь: Настройки категории > Смарты > Smart-расписания > + Создать.
Параметры: - Периодичность — от минут до месяцев - Дата и время начала — должны быть в будущем - Продолжительность — по умолчанию «10 повторений» (обычно менять на «Без ограничений») - Попытки выполнения — при ошибках, по умолчанию 5, минимум 1 - Флажок «Активно» — вкл/выкл
Режимы выполнения¶
| Режим | Описание |
|---|---|
| Вне контекста задачи | Пакет выполняется для всех задач категории |
| Для каждой задачи, отфильтрованной | Smart-фильтр отбирает задачи |
Пример фильтра — задачи с датой выхода на работу = сегодня:
УсечьВремя(ДП[«Дата выхода на работу»]) = УсечьВремя(ТекущиеДатаИВремя)
Функция УсечьВремя необходима для сравнения дат без учета времени.
Ограничения¶
- Расписание работает только при наличии хотя бы одной задачи в категории
- Пакеты с действием «Отменить» недоступны в расписаниях
- Для действий без привязки к категории — глобальные smart-расписания (Общие SMART)
Проверка¶
- Тестирование фильтра через кнопку «Тест»
- Принудительный запуск: ПКМ на расписании > «Выполнить» (или кнопка «Запустить сейчас»)
T-SQL в Smart¶
Когда использовать¶
- Стандартных возможностей SMART недостаточно
- Нужны JOIN-ы между категориями
- Сложные условия с подзапросами
- Фильтрация расписаний (T-SQL фильтр возвращает список задач, не boolean)
Правило: в первую очередь используйте язык SMART. T-SQL — когда SMART не справляется.
Ключевые таблицы и переменные¶
| Объект | Описание |
|---|---|
TasksInSubcat{N}Denormalized |
Денормализованная таблица категории N |
ExtParam{N}NativeValue |
Значение ДП N (нативный тип) |
ExtParam{N}Value |
Значение ДП N (строка) |
@ContextID |
ID текущей задачи |
@eventParam0 |
ID задачи в контексте подписи |
ExtParamSelectUsersValues |
Таблица значений ДП «Выбор пользователей» |
Users |
Таблица пользователей (IsFired_2 = признак увольнения) |
TaskHelpers |
Исполнители задачи (IsResponsible = ответственный) |
dbo.tc_AddWorkingDays(date, days) |
Стандартная функция: добавить рабочие дни |
IsWaitingSign |
Признак «на подписи» (1/0) |
Паттерн: условный расчет срока¶
SELECT
CASE
WHEN Extparam84NativeValue IS NOT NULL
AND Extparam71NativeValue > GETDATE()
THEN dbo.tc_AddWorkingDays(Extparam71NativeValue, 1)
ELSE dbo.tc_AddWorkingDays(GETDATE(), 1)
END
FROM TasksInSubcat21Denormalized
WHERE Taskid = @ContextID
Паттерн: фильтр расписания — отбор задач¶
SELECT t29.Taskid
FROM TasksInSubcat29Denormalized t29
JOIN TasksInSubcat18Denormalized t18
ON t18.taskid = t29.Extparam114NativeValue
WHERE t29.Stateid = 28
AND t18.Extparam277Value <> ''
AND FORMAT(t29.Extparam74NativeValue,'dd.MM.yyyy')
<= FORMAT(GETDATE(),'dd.MM.yyyy')
AND t29.IsWaitingSign = 0
Паттерн: проверка акцептантов подписи через SQL¶
if exists (
select u.UserID
from TasksInSubcat22Denormalized t22 (nolock)
join TasksInSubcat19Denormalized t19 (nolock)
on t19.TaskID = t22.ExtParam88NativeValue
join ExtParamSelectUsersValues epvu (nolock)
on t19.TaskID = epvu.TaskID
and epvu.ExtParamID = 76
join Users u (nolock)
on u.UserID = epvu.UserID
where t22.TaskID = @ContextId
and u.IsFired_2 = 0
)
select 1
else
select 0
Для акцептантов: параметр задачи = @eventParam0 (не @ContextId).
Изменение настроек с учетом автоматизации¶
Чек-лист при изменениях¶
- Добавление ДП в категорию: проверить, есть ли автоматизация, создающая задачи в эту категорию (Маршрут > Постановка задач в категорию). Если ДП обязательный — добавить его в действие «Создать задачу»
- Удаление ДП: проверить все связанные выражения и пакеты. Лучше скрыть, чем удалить
- Удаление перехода: если на переходе настроена автоматизация — она удалится вместе с переходом. Лучше скрыть
- Проверка зависимостей: вкладка «Smart выражения» показывает, в каких пакетах используется выражение
LUA-автоматизация¶
Преимущества Lua перед SMART¶
- Снижение нагрузки на БД (скрипты выполняются вне СУБД)
- Быстрее SMART-выражений
- Обработка контекстных данных, которых еще нет в БД
- Полноценный язык: циклы, таблицы, строки
- Защита от SQL-инъекций
Для простых задач — SMART предпочтительнее (проще поддержка).
Основные библиотеки 1Формы¶
| Объект | Метод | Назначение |
|---|---|---|
CONTEXT |
.Id, .OwnerId, .ExtParamValues |
Контекст текущей задачи |
SQL |
:query(sql, params) |
Выполнить SQL-запрос, вернуть таблицу результатов |
SMART |
:execute_action(action, contextId, 'task', params) |
Вызвать смарт-действие |
UTILS |
:json_encode(table) |
Сериализовать таблицу в JSON |
EVENTPARAMS |
["HasChangedUser"], ["NewValue"] |
Параметры события |
SESSION_USER |
.Id |
Текущий пользователь сессии |
RESULT |
(зарезервировано) | Выходной параметр скрипта |
Паттерн: получение значения ДП из контекста¶
local function getExtParamValue(ep_id)
for _, value in pairs(CONTEXT.ExtParamValues) do
if value.ExtParamId == ep_id then
return value.DateTimeValue, value.ExtParamValue
end
end
return nil, nil
end
Возвращает два значения: timestamp и строковое представление.
Паттерн: SQL-запрос с параметрами¶
local query = [[
SELECT t.TaskID, t.ExtParam55Value as Name
FROM TasksInSubcat34Denormalized as t WITH (nolock)
WHERE t.StateID = 7
AND t.ExtParam114NativeValue = 1186
]]
local params = {}
local res = SQL:query(query, params)
for _, data in pairs(res) do
print(data.TaskID, data.Name)
end
Параметры передаются как таблица {ParamName = value}, в SQL используются как @ParamName. Ключи результата регистрозависимые (как в SQL-запросе).
Паттерн: создание задачи с заполнением ДП¶
local function createTask(owner, helpers, due_time, newtaskextparams_json)
SMART:execute_action('CreateTask', CONTEXT.Id, 'task', {
Owner = owner,
Subcat = 31, -- ID категории
TaskText = nil,
CreateLink = false,
CreateSubtask = true, -- подзадача текущей
Performers = helpers, -- таблица ID пользователей
DueTime = due_time, -- timestamp
ExtParams = newtaskextparams_json, -- JSON
NewTaskCopySubscribers = true,
Priority = 1
})
end
-- Подготовка ДП для новой задачи
local newtaskextparams = {
{ExtParamID = 99, FixedValue = project_id},
{ExtParamID = 55, FixedValue = name},
{ExtParamID = 102, FixedValue = description},
}
local json = UTILS:json_encode(newtaskextparams)
createTask(owner, helpers, due_time, json)
Паттерн: обновление срока задачи¶
local function updateTaskOrderedTime(task_id, due_time)
SMART:execute_action('UpdateTaskOrderedTime', task_id, 'task', {
InitUser = EVENTPARAMS["HasChangedUser"].Id,
DueTime = due_time,
Reason = 'Изменение даты планового открытия проекта',
Task = task_id,
DoNotWriteComment = false
})
end
Важно: при событии «После смены ДП» новое значение уже в БД. При «Перед сменой ДП» — новое значение в EVENTPARAMS["NewValue"], в БД еще старое.
Паттерн: расчет срока от плановой даты¶
local project_open_date = getExtParamValue(93) -- timestamp
if project_open_date then
due_time = project_open_date - work_days * 24 * 3600
end
if not due_time or due_time <= os.time() then
due_time = os.time() + 18 * 3600 -- fallback: сегодня + 18ч
end
Стиль кода Lua (рекомендации)¶
| Правило | Пример |
|---|---|
Всегда local |
local function f(), local x = 1 |
| snake_case для переменных | helpers_table, due_time |
| camelCase для функций | getExtParamValue(), createTask() |
| UPPER_CASE для констант | PI = 3.14, MAX_RETRY = 5 |
_ для неиспользуемых переменных |
for _, v in pairs(t) do |
| Проверка на nil без явного сравнения | if var then вместо if var ~= nil then |
| Объявлять функции до вызова | Порядок: вспомогательные, затем основной код |
Комментарии к end |
end -- if string, end -- for each t |
Значение по умолчанию:
x = x or 'default'
Тернарный оператор:
answer = (2*2 == 4) and 'Истина' or 'Ложь'
JS в карточках задач¶
Назначение¶
JS-вставки управляют представлением карточки задачи: скрытие/отображение ДП, подсветка полей, динамическое поведение в зависимости от условий.
Путь: Настройки категории > Формы > Настройки JS и CSS вставок (NTF).
Доступные API¶
| Переменная/объект | Описание |
|---|---|
taskId |
Номер текущей задачи |
StateID |
ID текущего статуса |
SessionUserId |
ID текущего пользователя |
getSessionUserInfo() |
{userId, isAdmin, groups[]} |
new ExtParam(id) |
Объект ДП для чтения/управления |
Паттерн: скрытие ДП по значению другого ДП¶
Скрыть поле «Телефон» если «Вид связи» = «E-mail личный»:
// Обработчик NTF — обернуть в событие открытия задачи
var epVidSvyazi = new ExtParam(1234); // ID ДП «Вид связи»
var epPhone = new ExtParam(1235); // ID ДП «Телефон»
var epEmail = new ExtParam(1236); // ID ДП «E-mail»
var val = epVidSvyazi.getValue();
if (val === 'E-mail личный') {
epPhone.hide();
epEmail.show();
} else if (val === 'Телефон личный') {
epEmail.hide();
epPhone.show();
} else {
epPhone.hide();
epEmail.hide();
}
Паттерн: подсветка незаполненных полей¶
var epList = [1234, 1235, 1236, 1237]; // ID обязательных ДП
epList.forEach(function(id) {
var ep = new ExtParam(id);
if (!ep.getValue()) {
ep.setLabelColor('red');
}
});
Активация вставки¶
- Создать вставку (тип: js)
- Добавить в категорию
- Поставить галку «Форма задачи» для активности
- Для NTF — обернуть код в обработчик события открытия задачи
- Для MTF — создать отдельную функцию-обработчик (для корректного удаления)
Рецепты смарт-кнопок с динамическим URL¶
Смарт-кнопка может открывать URL, сформированный динамически на основе данных текущей задачи. Механизм — поле URL в настройках кнопки (тип «Произвольная ссылка»), которое принимает смарт-выражение, возвращающее строку.
Справочник переменных: docs/domains/smart-actions/variables-reference.md
1. Открыть внешний URL с ID задачи¶
Сценарий: кнопка «Открыть в CRM» — переходит на внешний сервис, передавая taskId как параметр запроса.
Как настраивается (UI):
- Настройки категории → вкладка Кнопки → Создать
- Заполнить Имя кнопки
- В поле URL выбрать тип «Произвольная ссылка»
- Привязать смарт-выражение, возвращающее URL со встроенным ID задачи
- Открывать ссылку в → «В новом окне» (для внешних ресурсов рекомендуется)
Смарт-выражение (T-SQL):
SELECT 'https://external.service/form?taskId=' + CAST(@ContextID AS nvarchar(20))
@ContextID — ID текущей задачи (TaskID). Подставляется автоматически в контексте смарт-выражения.
Смарт-выражение (SMART-режим, без T-SQL):
В режиме SMART конкатенация строк: 'https://external.service/form?taskId=' + ВСтроку(№ задачи).
Важно: внешние ресурсы с заголовком X-Frame-Options: sameorigin нельзя открывать в модальном окне — браузер заблокирует. Используйте режим «В новом окне».
2. mailto с динамической темой и телом¶
Сценарий: кнопка «Написать письмо» — открывает почтовый клиент пользователя с заполненными получателем, темой и телом письма.
Вариант A — через поле URL кнопки (смарт-выражение):
SELECT 'mailto:support@example.com?subject=Задача%20' + CAST(@ContextID AS nvarchar(20))
+ '&body=Добрый%20день%2C%20прошу%20помочь%20с%20задачей%20' + CAST(@ContextID AS nvarchar(20))
Вариант B — через JS-выражение кнопки:
window.open('mailto:support@example.com?subject=Задача ' + taskId + '&body=Текст письма');
Переменная taskId доступна в JS-вставках карточки задачи. JS-выражение указывается в поле JavaScript выражение настроек кнопки. Если указаны и JS, и URL — сначала выполняется JS, затем открывается URL.
Кириллица в параметрах: браузеры обычно кодируют её автоматически, но для надёжности — кодируйте вручную: пробел = %20, запятая = %2C.
3. Открыть связанную задачу в новой вкладке¶
Сценарий: кнопка «Перейти к проекту» — открывает карточку связанной задачи (ID берётся из ДП текущей задачи).
Рекомендованный способ (тип URL = «Форма задачи»):
В поле URL выбрать тип «Форма задачи» (RedirectActionType.OpenTask = 3). Привязать смарт-выражение, возвращающее ID нужной задачи:
-- Вернуть ID связанной задачи из ДП (ДП №77 — ID проекта)
SELECT ExtParam77NativeValue
FROM TasksInSubcat{N}Denormalized
WHERE TaskID = @ContextID
Система сама сформирует корректный внутренний URL /tasks/{taskId}.
Альтернатива через OpenUrl (явный URL):
SELECT '/tasks/' + CAST(ExtParam77NativeValue AS nvarchar(20))
FROM TasksInSubcat{N}Denormalized
WHERE TaskID = @ContextID
Режим открытия: «В новом окне» или «В модальном окне» — на выбор администратора.
4. Вызов внешнего HTTP API без открытия браузера¶
Сценарий: кнопка «Отправить в 1С» — при нажатии выполняет HTTP-запрос к внешнему API серверной стороной, не открывая URL в браузере.
Механизм: пакет действий со стандартным действием «Отправить HTTP запрос» (StandardAction.SendHttpRequest). Кнопка запускает пакет через поле Пакет действий — не через поле URL.
Конфигурация пакета действий:
| Параметр | Значение |
|---|---|
| Метод | GET / POST / PUT / DELETE / PATCH |
| URL | Смарт-выражение → строка с адресом |
| Параметры запроса | Список Имя=Значение (для GET — query string, для POST — body) |
| Заголовки | Список Имя=Значение (например, Authorization) |
| Raw Body | Строка (для POST с JSON — вместо параметров) |
| Таймаут, мс | Необязательный, по умолчанию стандартный |
Пример URL в пакете (смарт-выражение):
SELECT 'https://api.external.service/tasks/' + CAST(@ContextID AS nvarchar(20)) + '/sync'
Отличие от поля URL кнопки: поле URL кнопки открывает адрес в браузере (клиентская сторона). Действие «Отправить HTTP запрос» выполняется сервером — пользователь не видит переход, ответ можно использовать в следующих действиях пакета.
Ловушки¶
| Проблема | Решение |
|---|---|
Внешний URL в модальном окне — ошибка X-Frame-Options: sameorigin |
Переключить «Открывать в» на «В новом окне» |
Кириллица в URL отображается как %D0%... |
Норма для HTTP; если нужна читаемость — использовать только ASCII в параметрах |
| Смарт-выражение возвращает NULL | Переход по ссылке не выполняется без сообщения. Добавьте проверку в SQL: ISNULL(result, 'https://fallback.url') |
| Длинный URL обрезается | Ограничений на стороне платформы не задокументировано; браузерный лимит — ~2000 символов. Длинные данные передавайте через POST-запрос в пакете |
| JS-выражение с ошибкой блокирует переход по URL | Если указаны и JS, и URL — при ошибке JS переход по URL не выполняется (проверить через консоль браузера) |
Переменная @ContextID не работает в JS-выражении кнопки |
@ContextID — только для смарт-выражений T-SQL. В JS используйте переменную taskId |