Всем привет, меня зовут Алексей - я руководитель отдела интеграции EvaTeam. Это статья о том, как реализована настройка автоматизаций в EvaProject - российском аналоге Jira. В ней рассказывается о том, с чем пришлось столкнуться при переезде с Jira, и как мы реализовали функционал в нашей системе.

Об автоматизации в Jira

Базовая автоматизация в Jira, прямо скажем, весьма скудная. Она подойдёт только небольшим и нетребовательным командам. По факту более менее полноценную автоматизацию можно получить только с использованием расширений и плагинов. Например, есть официальное расширение Jira Automation, которое позволяет добавлять свои правила. Но работа с ним тоже не очевидная и его болтает как матроса в лодке. Полноценно работает в премиум тарифе Cloud-версии. С недавних пор встроено в версию Data Centre. А для Server-тарифа устанавливается только как отдельное расширение с возможностью продлить его до февраля 2024 года. 

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

В целом у Jira богатая автоматизация за счет плагинов и расширений. Можно настроить всё что угодно: от смены исполнителя при изменении статуса по задаче, до включения кофемашины каждый день в 9 утра.

Поэтому возникают сложности у людей при переходе на российское ПО. Мало систем, которые позволят также гибко автоматизировать процессы, но и мы не из трусливых. Рассказываю о том, как работает этот функционал у нас в системе.

Автоматизация переходов

За основу работы автоматизации брались привычные настройки Jira, а также популярные плагины. В данный момент уже многое из этого реализовано в EvaProject, но ещё получаем много запросов, по специфичным настройкам, которые постоянно добавляем. Главное что сделано - заложены архитектурные возможности для дальнейшего развития в сторону замены Atlassian.

Для настройки логики бизнес-процессов используем классические 3 кита автоматизации:

  1. Условия перехода;

  2. Валидаторы;

  3. Действия.

Условия перехода

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

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

Валидатор

Это дополнительные условия для статусов. Если условие валидатора не выполняется, при переходе на определённый статус возникает ошибка. Валидатор фиксирует почему возникла ошибка и выводит информативное окно с причиной её возникновения.

Появление окна с предупреждением при невыполненном условии
Появление окна с предупреждением при невыполненном условии

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

Настройка валидатора
Настройка валидатора

Примеры использования валидатора.

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

Действия

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

Помимо предустановленных опций для настроек переходов также доступен более гибкий инструмент bzPython, который является аналогом плагина ScriptRunner в Jira.

bzPyton

Используя bzPyton можно реализовать абсолютно любую автоматизацию.

Пример добавления bzPython
Пример добавления bzPython

bzPyton – внутренний бизнес-интерпретатор. Задача, в которой совершается определенный переход, передаётся в интерпретатор в переменной self, которая является объектом класса CmfTask и содержит всю информацию об этой задаче, то есть все поля и методы объекта CmfTask. Мы можем поменять статус, можем поменять будильник и любые другие поля, которые есть в модели CmfTask. Список доступных полей можно найти в официальной документации. 

Для примера, сделаем чтобы ответственным для задачи стал пользователь, изменивший статус задачи. Добавляем новое действие для статуса, Вид Действия – bzPyton. В окно интерпретатора пишем:

self.responsible = g.current_user

В этом примере:

self.responsible – ответственный за текущую задачу;

g.current_user – специальная переменная, в которой содержится текущий пользователь, который совершает переход.

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

Популярные шаблоны реализации автоматизации с помощью bzPyton можно посмотреть в официальной документации (https://docs.evateam.ru/docs/docs/DOC-000193#primery-bz-python)

Для переходов количество кода обычно невелико. Можно использовать более объемные скрипты в Триггерах или Cron.

И ещё один пример bzPython для валидатора. "Разрешить выполнять переход только тому пользователю, который является исполнителем по задаче":

if self.responsible != g.current_user:
    return False

Триггеры

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

Добавление события для триггера
Добавление события для триггера

События для триггеров:

  1. Комментирование;

  2. Создание;

  3. Удаление;

  4. Сохранение;

  5. Обновление.

Любое это событие может быть использовано вместе с моделями:

  1. Задача (CmfTask);

  2. Документ (CmfDocument);

  3. Список (CmfList);

  4. Сделка (CmfDeal).

Для создания нового триггера необходимо перейти в настройки, выбрать режим администратора, нажать «Автоматизация триггеры».

В поле «Название» впишите нужное имя триггера и нажмите «Добавить».

Нажмите «Изменить», откроется окно с параметрами триггера.

Настройка триггера
Настройка триггера

Есть уже предустановленные фильтры. Это "Фильтр по логическому типу объекта", "Фильтр по виду деятельности", "Фильтр по схеме бизнес-процессов". Для более гибкой настройки фильтра есть возможность использовать интерпретатор bzPyton.

Подробное описание по настройкам содержится в официальной документации (https://docs.evateam.ru/docs/docs/DOC-000238#avtomatizacziya-triggery)

Попробуем работу триггеров. 

Задача для триггера: Автоматизация по созданию дочерней задачи с типом "Подзадача".

Для этого выбираем такие настройки:

Добавляем такой код:

task_code = self.name.value
relation_task = models.CmfTask.get(code=task_code, fields=['name', 'cf_custom_field_1'])
if relation_task:
# Меняем имя дочерней задачи
self.name = f'{task_code} - {relation_task.name}'
# Получаем кастомное поле из второй задачи
custom_1 = relation_task.cf_custom_field_1
# Меняем текст дочерней задачи
self.text = f'<p>Это текст первой строки. Кастом поле-{custom_1}</p>\n<p>Это текст второй строки</p>'
# Получаем нужный тип связи. В данном случае тип связи "Взаимная" - "Относится к"
relation_type = models.CmfRelationType.get(code='system.link')
# Создаем связь между второй задачей и новой созданной(дочерней)
new_rel = models.CmfRelationOption(out_link=self, in_link=relation_task, relation_type=relation_type)
new_rel.save()

А логика скрипта получается такой:

  1. Скрипт выполняется если в основной задаче нажать кнопку "Добавить дочернюю задачу" и прописать в названиеcode другой уже созданной задачи.

  2. По полю code будет найдена вторая задача. Из этой задачи будут получены поля name и cf_custom_field_1.

  3. Полученные поля из второй задачи будут прописаны в дочернюю.

  4. Между дочерней и второй задаче создается связь с типом system.link (Взаимная).

  5. В настройках триггера указано "Событие: Создание", "Фильтр по логическому типу объекта - Подзадача".

Cron

Автоматизировать работу системы можно не только по определённым действиям со стороны пользователей, но и по времени. Для этого есть специальный инструмент-планировщик. С помощью него, к примеру можно убирать выполненные задачи из списка задач, или настроить периодическую очистку архива.

Создать действие по времени можно также в настройках в режиме администратора. Для этого выбираем «Автоматизация Cron». Создаём новое правило и переходим к редактированию:

Окно настройки Cron
Окно настройки Cron

Выполняемые задачи для Cron не содержат переменную self. Вызываемые по расписанию объекты должны быть найдены в БД по определенному критерию. К примеру, по расписанию можно найти все задачи, у которых просрочен будильник, и изменить их статус. То есть с помощью Cron обычно производится автоматизация по большому списку задач, которые нужно раз в какой-то промежуток времени обработать.

Правила заполнения поля «Выражение Cron»

Время выполнения задается пятью колонками, разделёнными пробелами: минуты (0—59), часы (0—23), дни месяца(1—31), месяцы(1—12) и день недели(0—7). Значения могут быть в виде чисел, диапазонов или «». Примеры заполнения:

5 0 * * * – выполняется каждый день в 0 часов 5 минут;0-59 * * * * – выполняется ежеминутно;/5 * * * * – выполняется каждые пять минут;
5 4 * * sun – выполняется в 4:05 в воскресенье;

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

from datetime import timedelta
# Находим нужный workflow
wf = models.CmfWorkflow.get(code='WF-000005')
# Статус закрыто в нужном workflow
status_closed = models.CmfStatus.get(code='closed', workflow=wf)
seven_days_ago = g.now - timedelta(days=7)
# Находим задачи, у которых статус не менялся 7 дней
tasks = models.CmfTask.list(filter=['status_modified_at', '<=', seven_days_ago])
for task in tasks:
task.status = status_closed
task.save()
# Отправляем сообщение владельцу задачи
models.CmfNotify.place_notify(obj=task, person_id=task.cmf_owner.id.value,
msg=f'Заявка {task.code} отмечена как выполненная автоматически', text='Заголовок')

Помимо трёх вариантов автоматизации в EvaProject есть ещё Webhook и Git. Основные варианты автоматизации, благодаря bzPyton, имеют максимальную гибкость. Конкретные описания полей можно посмотреть в документации, либо обратиться в техподдержку.

Встроенный интерпретатор поддерживает подсветку синтаксиса, а также имеет подсказки по доступным командам. К примеру, если после self. нажать букву r, то мы увидим все возможные варианты. Все названия «говорящие», то есть по названию можно понять, что это за функция или переменная. 

Конец

В следующей статье расскажу как мы помогали настраивать автоматизацию на примере одной крупной компании. Ну и это ещё минимальная часть от реализованного и планируемого функционала. Постоянно от клиентов получаем информацию о том как они "интересно" использовали Джиру и продолжаем добавлять фичи для автоматизаций.

Комментарии (9)


  1. Bessnov
    00.00.0000 00:00
    +8

    Большую часть условно бесплатного западного ПО можно скачть или сразу или после регистрации.

    Ососбенности же отечествнного ПО - заполни форму регистрации, ФИО, телефон. Тебе позвонят, покажут как работает. удалённо. наверное... Потом...

    Желание попробовать есть, а преодолевать такие сложности чтобы посмотреть - нет.
    Представляете сколько возможных пользователей вашего продукта проходят мимо?


    1. DMGarikk
      00.00.0000 00:00

      Представляете сколько возможных пользователей вашего продукта проходят мимо?

      отвечу цитатой основателя стартапа в котором я когдато работал (стартап обанкротился кстати)


      "Это не наша ЦА, вопрос закрыт' ©


      ==
      это кстати маркер того что люди которое так делают, довольно далеки от реалий отрасли


      1. aborouhin
        00.00.0000 00:00
        +2

        Это маркер структуры российской экономики. В B2B сегменте малого бизнеса, который реально покупает продукт по итогам инициативы снизу, исчезающе мало.

        Даже до появления обязательных требований по импортозамещению ПО я несколько раз на примере своих знакомых наблюдал такую картинку - запускали проект для широкого рынка, удобное демо, оплата в один клик картой, всё прекрасно. Потом получали первый крупный корпоративный заказ, сравнивали соотношение деньги/усилия от розничных продаж и крупнокорпоративных... - и забивали на розницу вообще, сосредотачиваясь только на последних. А корпорациям продают не потому, что кто-то там смог демку без лишних телодвижений получить, а совсем через другие каналы.

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


        Справедливости ради отмечу:

        1. Не только в России такое. Те продукты, которые реально нужны только средне-крупному бизнесу, мало где вот просто так пощупать дадут, пока контакты их тебя не вытрясут.

        1. Создатели обсуждаемого продукта хотя бы цены выложили на сайте для всеобщего обозрения, это уже большой прогресс :) Вот когда чтобы узнать, хватит у тебя денег на такое счастье хотя бы примерно или вообще нет, тоже надо отправить заявку - реально бесит.


        1. kuchaev
          00.00.0000 00:00

          всё верно. Пока сфокусированы на корпоративных клиентах из среднего и крупного бизнеса. Но много продаж (в штуках.) и 5 и 10 юзеров. В облако.


      1. kuchaev
        00.00.0000 00:00

        Вынужден не согласиться. Можете мне в лс написать, расскажу опыт, и почему в данном случае так сделано.


        1. anticyclope
          00.00.0000 00:00
          +1

          шикарно! :)


    1. kuchaev
      00.00.0000 00:00
      +1

      Откроем чуть позже. Закрыли временно. Т.к. пиковый спрос и нагрузка в связи с массовым импортозамещением. Чтобы немного отсеять слишком малозаинтересованных заказчиков. А вообще просто так даём, можем и не показывать, есть отличная дока, много обучающих видео. Во второй половине 23г. откроем, а в 24 фри лицензию сделаем.


  1. little-brother
    00.00.0000 00:00

    Мне кажется у вас что-то с UI-разработкой явно не то:

    • в разделе "Валидатор" в статье сразу видно 2 открытых диалога.

    • документация местами вызывает вопросы (с разбегу):

      • картинка под спойлером (что за некликабельное "Еще"?)

      • где-то в оглавлении осуществляется переход на новую страницу, где-то в том же окне роутится

      • тут, например, https://docs.evateam.ru/docs/docs/DOC-000053#sozdanie-i-nastrojka после картинки 3 этапа пустое место и потом текст.

    А так удачи в нелегком деле написания системы для погромистов, которые более капризны чем офисные работяги :)

    Еще


    1. kuchaev
      00.00.0000 00:00

      ого, спасибо за фидбек. Создал задачу на тестеров.