понедельник, 2 июля 2018 г.

JIRA: JQL. Статистика из проекта по определенному полю (SIL)

Задача

Получить данные по периодам а) за 2017 год б) 2018 год:
  • Утверждено задач за период
  • Из них выполнено без переноса сроков
  • Из них выполнено с одним переносом сроков
  • Из них выполнено с двумя и более переносами
  • Из них выполнено
  • Из них отклонено

Корректировки, на основе реальных данных

Для фильтрации необходимо определиться с пониманием того, за какие данные мы будем "цепляться". 
В данном случае, имеются необходимые статусы: УТВЕРЖДЕНА CLOSED ОТКЛОНЕНА но помимо статусов, коллеги использовали стандартное поле Due Date для обозначения сроков. 
Во время анализа проекта IA можно обнаружить задачи, в которых имеется значение поля Due Date, а в некоторых этого значения нет. 
Чтобы разбить необходимые данные - я нарисовал следующую таблицу: 

Таблица уже заполнена готовыми данными, с целью удобства
ВСЕГОНаличие установленных сроковБез установленных сроов
ВыполненоБез переноса сроковС 1 переносом сроковС 2 и более переносовОтклоненоЕще НЕ ВЫПОЛНЕНОВыполненоОтклоненоЕще НЕ ВЫПОЛНЕНО
Утверждено за 2017/01/01 - 2017/12/312121155265711159719














Утверждено за 2018/01/01 - 2018/06/29









Чтобы более детально получить данные - будем использовать именно эту таблицу. 

Поэтапное решение


Я буду описывать решение только для одного периода. Остальные временные рамки можно менять самостоятельно
Для начала получим полное кол-во утвержденных заявок для периода
Всего утвержденных заявок за период
project = IA AND (status  changed TO Утверждена AFTER "2017/01/01" BEFORE "2017/12/31")
//поиск осуществляется именно тех обращений, которые утверждались в этот период. т.е. были переведены в соответствующий статус УТВЕРЖДЕНА
//Результат: 212 задач
Теперь разобьем эти части на Выполненные, где были установлены сроки и где этих сроков не было
Выполнено с наличием срока
project = IA AND (status  changed TO Утверждена AFTER "2017/01/01" BEFORE "2017/12/31" and duedate is not EMPTY ) and status = closed
//Результат: 115 задач
Выполнено БЕЗ установленного срока
project = IA AND (status  changed TO Утверждена AFTER "2017/01/01" BEFORE "2017/12/31" and duedate is EMPTY ) and status = closed
//Результат: 59 задач

Заполним столбцы, где срок был установлен, но задачи еще не закрыты и не отклонены
Еще в работе БЕЗ установленного срока
project = IA AND (status  changed TO Утверждена AFTER "2017/01/01" BEFORE "2017/12/31" and duedate is EMPTY ) and status != closed AND status != Отклонена
//Результат: 19 задач
Еще в работе с наличием установленного срока
project = IA AND (status  changed TO Утверждена AFTER "2017/01/01" BEFORE "2017/12/31" and duedate is not EMPTY ) and status != closed AND status != Отклонена
//Результат: 11 задач
Узнаем, сколько задач отклонено
Отклонено С установленными сроками
project = IA AND (status  changed TO Утверждена AFTER "2017/01/01" BEFORE "2017/12/31" and duedate is not EMPTY ) and status = Отклонена
//Результат: 1 задача
Отклонено БЕЗ установленных сроков
project = IA AND (status  changed TO Утверждена AFTER "2017/01/01" BEFORE "2017/12/31" and duedate is EMPTY ) and status = Отклонена
//Результат: 7 задач

Учет перенесенных сроков

Теперь началось самое интересное. Необходимо учесть, сколько было переносов и были ли они вообще. 
С учетом того, что за основу мы взяли поле Due Date. То одно изменение этого поля - будет равняться одному перенесенному сроку. 
Необходимо учитывать, что если изначально, при создании задачи, Due Date не был проставлен. То в последствии - установка какого-либо значения - тоже, фактически, для JIRA - будет являться изменением поля. Но нам необходимо учесть, что это не перенос срока, а его установка. 
Для решения задачи будем использовать функцию: silJQLExpression и Dashboard для формирования данных. Хотя, можно было бы и воспользоваться issue navigator и тогда для поиска, с помощью SIL скрипта нам понадобится silJQLList.
Для поиска изменений полей в Hystory будем использовать 2 функции: getFieldChanges и fieldHistory 
Создаем файл скрипта, в котором будем осуществлять поиск. Назовем его IA_jql_search_1.sil
IA_jql_search_1.sil
//Нам надо получить список задач, в какой-то массив, по выбранному фильтру с silJQLExpression + JQL (где duedate НЕ пустой) и равен 1.
string jql = "key in silJQLExpression('size(getFieldChanges(key, \"duedate\"))<=1', 'project = IA AND (status  changed TO Утверждена AFTER \"2017/01/01\" BEFORE \"2017/12/31\" and duedate is not EMPTY) and status = closed')";
string[] key = selectIssues(jql);
string[] field_history;
string[] ret;
string[] ret2;
for(string k in key)
    {
        field_history = fieldHistory(k, "duedate");
        if(field_history[1] == "")
            {
               ret += k;
               //runnerLog(k); //для возможности вывода списка задач
            }
        else
            {
                ret2 += k;
                //runnerLog(k); //для возможности вывода списка задач
            }
    }
     
     
runnerLog("Кол-во задач, где изначальная дата не менялась: " + size(ret));
runnerLog("Кол-во задач, где сроки исполнения были перенесены 1 раз: " + size(ret2));
/*
Результат выполнения данного скрипта нам сначала сделает выборку задач, где поле Due Date НЕ пустое и в Hystory имеется ровно одно изменение этого поля('size(getFieldChanges(key, \"duedate\"))<=1'). Size - возвращает кол-во элементов массива.
Но как и говорилось ранее - необходимо учитывать, что одно такое изменение может являться лишь тем, что при создании задачи Due Date был пустым и это значение установили позже.
Поэтому добавляем условие if(field_history[1] == "")
Таким образом, в "ret" мы соберем задачи, которым проставили Due Date в последствии, но при этом больше изменений не было и задачи уже закрыты.
Результат выполнения:
Кол-во задач, где изначальная дата не менялась: 52
Результат выполнения второй части условия:
Кол-во задач, где сроки исполнения были перенесены 1 раз: 6
Это уже гарантированно те задачи, где срок изначально был установлен, но после произошло ОДНО его изменение.
*/
Осталось скорректировать строчку поиска для отображения результатов, где было более 2х переносов сроков. Или просто сложением и вычитанием получить остаток. 
115 - 52 - 6 = 57
Скрипт будет использоваться тот же, только изменяем JQL
2 и более переносов
string jql = "key in silJQLExpression('size(getFieldChanges(key, \"duedate\"))>=2', 'project = IA AND (status  changed TO Утверждена AFTER \"2017/01/01\" BEFORE \"2017/12/31\" and duedate is not EMPTY) and status = closed')";
/*
Результат выполнения:
Кол-во задач, где изначальная дата не менялась: 54
Кол-во задач, где сроки исполнения были перенесены 1 раз: 3
Складываем полученные данные и получаем все те-же 57 задач.
*/

Вариант использования Issue Navigator + silJQLList

Если не использовать Dashboard - можно добиться того же результата с помощью функции silJQLList
Будем использовать тот-же скрипт. Т.к. в строке поиска у нас имеются все условия - то использовать аргументы не требуется.
Строка JQL поиска будет выглядеть так: 
key in silJQLList("All_SIL/JQL_Search/IA_jql_search_1.sil")
Результат вывода будет точно такой же, только уже списком задач.