Проблематика
Для того чтобы управлять командой сотрудников необходимы чёткие KPI показатели, которые будут служить точным ориентиром в оценке эффективности их работы. Если в продажах все просто (лиды, сделки, конверсия, ROI и пр. показатели), то в процессной работе программистов, маркетологов, аналитиков, дизайнеров так четко измерить эффективность будет сложно т.к.:
Если в вашей команде более 1 человека - встаёт проблема, связанная со сложностью того, чтобы собрать в кучу всю информацию, в рамках оцениваемой продуктивности сотрудников.
Их результаты работы часто трудно оцифровать, а если и выбраны kpi то обработка данных, их учёт и ежедневный контроль может отнимать огромное количество рабочих часов.
Как решить первую задачу, не покупая лицензии agile платформ, я рассказал в своей предыдущей статье, а вот о том, как это все считать и наглядно визуализировать для оценки в общей рабочей среде мы поговорим ниже.
Решение задачи
В своей работе мы будем использовать таскменеджер Trello и пакет trelloR на языке программирования R. Почему именно такой "стек" можно ознакомиться тут>>
Перед тем как начать оценивать продуктивность выберем для себя основные kpi. Я буду оценивать продуктивность команды аналитиков и ключевыми показателями будут служить:
Объем решаемых задач за период
Скорость решения задач
Число задач закрытых в день постановки
Число закрытия "сложных" задач за период
*Это индивидуально мои метрики, которые важны в моей работе. Оценивать продуктивность, описываемым в этой статье методом, можно в любом разрезе, который только может прийти вам в голову и исходя из индивидуально вашего бизнес-процесса.
И так, сначала устанавливаем среду разработки и ключевые пакеты необходимые для работы. Для решения вышеописанной задачи нам потребуется установить пакеты для:
работы с API Trello — «trelloR»
работы со временем и временными периодами — «lubridate»
работы с таблицами и агрегации данных — «dplyr»
работы с визуализацией — «ggplot2»
сбор нескольких визуализаций в одну — «ggpubr»
Чтобы установить пакеты из основного репозитория CRAN примените базовую функцию install.packages, а для загрузки пакетов с github функцию install_github:
remotes::install_github("jchrom/trelloR")
install.packages("lubridate", dependencies = TRUE)
install.packages("dplyr ", dependencies = TRUE)
remotes::install_github("jchrom/trelloR")
install.packages("ggplot2", dependencies = TRUE)
install.packages("ggpubr ", dependencies = TRUE)
Для отправки запросов к API Trello нам потребуется токен, как его получить можно прочесть тут>>*
Еще одним важным шагом перед визуализацией является стандартизация всех досок сотрудников в рамках ваших бизнес-процессов. В своей работы мы внедрили:
Единый набор меток для каждой из задач в Trello, разделив их по "срочности-важности" и по направлениям деятельности в рамках задачи
Метки в карточках Trello
Обязательное заполнение даты начала и даты окончания выполнения каждой из задач
Настройка даты в карточке Trello
Перенос всех выполненных задач в столбцы с единым форматом и указания месяца выполнения задачи
К сожалению, без предварительной стандартизации всех досок выполнить дальнейший анализ будет невозможно
Получаем данные для визуализации
# Подключаем все необходимые пакеты для работы
library(trelloR)
library(lubridate)
library(dplyr)
library(ggplot2)
library(ggpubr)
# Указываем путь к папке где лежит полученный ранее token
setwd("C:\\*********\\R_script\\trello")
# Собираем в список доски сотрудников, которых мы будем анализировать
board_id <- c("https://trello.com/b/wNV1HMse/максим-м",
"https://trello.com/b/tXrO68ix/максим-я",
"https://trello.com/b/fCZrgJYg/арсений",
"https://trello.com/b/HeLC3RVE/анатолий",
"https://trello.com/b/xweaki49/софия")
# Собираем циклом статистику со всех досок в общую таблицу
stattrello <- data.frame() # будущая сводная таблица
for (xi in 1:length(board_id)) {
cardList <- get_board_lists(board_id[xi], query = list(customFieldItems = "true"))
cardList$zadach <- NA # число задач за каждый период
for (i in 1:length(cardList$id)) {
cardList$zadach[i] <- nrow(get_list_cards(cardList$id[i]))
}
cardList$spec <- stringr::str_to_title(basename(board_id[xi]))
cardList <- cardList %>% select(id, spec, name, zadach)
stattrello <- bind_rows(stattrello,cardList)
}

Собираем списки карточек всех сотрудников и сводим их в единую таблицу для получения ID столбцов по периодам и числа выполненных задач за данные периоды:
# Фильтруем сводные данные только по задачам за последние 3 месяца.
# (эффективность по основным kpi будет оцениваться в разрезе этого периода)
lid <- stattrello %>% filter(grepl("20",stattrello$name)==T)
lid$name <- parse_date_time(lid$name, "my")
lidvse <- lid
lid <- lid %>% filter(name > floor_date(today() - months(3), "month"))
# Используя ID списков с карточками собираем задачи по каждому списку
allvcard <- data.frame() # Все задачи всех сотрудников
type_zadach <- data.frame() # Типы задач по направлениям
#Запускаем цикл для сбора
for (i in 1:nrow(lid)) {
cards_v <- get_list_cards(lid$id[i])
cards_v$spec <- lid$spec[i]
cards_v$datezad <- lid$name[i]
if(length(bind_rows(cards_v$labels))!=0){
tmp <- bind_rows(cards_v$labels) %>% group_by(name) %>% summarise(ЧислоЗадач = n())
tmp$spec <- max(cards_v$spec)
tmp$datezad <- max(cards_v$datezad)
type_zadach <- bind_rows(type_zadach,tmp)
cards_v <- tidyr :: unnest_longer(cards_v,labels)
cards_v <- rename(cards_v$labels, Naprav=3) %>% select(Naprav) %>%
bind_cols(cards_v) %>% select(id, due, Naprav,spec)
# В поле ID зашифрована дата создания карточки. Проводим расшифровку для всех задач
cardID <- cards_v$id[i]
dateList <- data.frame(dateadd = NA)
dateList[1,1] <- strtoi(strtrim(cardID, 8), 16L)
dateList$dateadd <- as.POSIXct(dateList$dateadd, origin = "1970-01-01")
dateList <- data.frame(dateadd = NA)
for (i in 1:length(cards_v$id)) {
cardID <- cards_v$id[i]
dateList[i,1] <- strtoi(strtrim(cardID, 8), 16L)
}
dateList$dateadd <- as.POSIXct(dateList$dateadd, origin = "1970-01-01")
cards_v["dateadd"] <- dateList$dateadd
# Вычисляем время от создания задачи до плановой даты её завершения
cards_v <- cards_v %>% bind_cols() %>% data.frame(
raznica = trunc(as.numeric(as.POSIXct(cards_v$due) - cards_v$dateadd)/24)) %>%
select(-due)
allvcard <- bind_rows(allvcard,cards_v)
}else{print("no")
}}
После выполнения всех предварительных манипуляций с данными, мы можем приступить к оформлению
Визуализация
Выводим цифры в среду визуализации используя пакет ggplot2 и строим графики по каждому из показателей:
# Задаем единый стандарт отображения данных (стиль графиков)
tema <- theme(legend.position="right",axis.text=element_text(size=7),
axis.title=element_text(size=10,face="bold"),
legend.text=element_text(size=10),
legend.title = element_text(size=9),
plot.title = element_text(size=10),
plot.margin = margin(5, 20, 5.5, 5))
# Строим график по общему числу решенных задач за период
# Переводим даты в стандартный вид из того что были в списках Trello
stattrello$id <- as.character(as.Date(floor_date(as.POSIXct(strtoi(strtrim(stattrello$id, 8), 16L), origin = "1970-01-01"),"month"))+1)
# Подготавливаем столбцы к отображению на графике
stattrello <- stattrello %>% rename(date=id) %>% group_by(spec,date) %>% summarise(zadach = sum(zadach))
# Строим график
grafik_vse <- ggplot(data=stattrello, aes(x=as.character(date), y=zadach)) +
scale_fill_discrete(name = "Сотрудники" ) +
geom_bar(aes(fill=spec), position = position_dodge(), stat="identity") +
geom_text(aes(label=zadach, y = zadach +1, group = spec),
position = position_dodge(0.9), size=2.5) +
theme(legend.position="bottom",axis.text=element_text(size=7),
axis.title=element_text(size=10,face="bold"),
legend.text=element_text(size=10),
legend.title = element_text(size=9),
plot.title = element_text(size=10),
plot.margin = margin(10, 50, 20, 10)) +
labs(title = "Закрыто задач в прошлом периоде",
x = "Дата",
y = "Задач, шт.")
В результате получаем график по числу выполненных задач на каждого из сотрудников

Получаем графики и таблицы для остальных интересующих нас показателей:
# Формируем график по задачам для направлений деятельности
type_zad <- type_zadach %>% filter(grepl("ВАЖНО|Пауза", name)!=T) %>%
mutate(date = format(datezad, "%m-%Y")) %>%
group_by(spec,name) %>%
summarise(nwork= sum(ЧислоЗадач))
typ_p <- ggplot(data=type_zad, aes(x=name, y=nwork, group=spec)) +
scale_fill_discrete(name = "Сотрудники" ) +
geom_bar(aes(fill=spec), position = position_dodge(), stat="identity") +
geom_text(aes(label=nwork, y = nwork+1, group = spec),
position = position_dodge(0.9), size=2.5) +
tema +
labs(title = "Задачи по направлениям за 3 мес.",
x = "Дата",
y = "Задач, шт.")
График по "фокусу" в направлениях деятельности для каждого из сотрудников

*Получение графиков и таблиц остальных kpi показателей происходит аналогично выше описанному методу визуализации данных. Дабы не мучать вас кодом, ограничимся на этих примерах=)
После того как мы собрали нужные нам графики их необходимо соединить в один файл - дашборд:
# Объединение визуализации
ggarrange(grafik_vse,
ggarrange(typ_p, p1,
ncol = 2, nrow = 1,
heights = c(1, 1),common.legend = T,legend = "bottom"),
nrow = 2,legend = "right")
# Сохраняем полученный файл для загрузки в Trello
ggsave("sotrudniki.png", width =25, height = 20, units = "cm", device="png")
Итог сведения графиков:

Теперь визуализацию передаем в 1-ый список на нашем общем дашборде, который мы создавали в прошлой статье.
#Сначала удаляем старые визуалы если они там были
bid = get_id_board("o****W")
# 1ый лист в доске куда пишем наши графики
lid <- get_board_lists(bid)$id[1]
cid <- get_list_cards(lid)
# Удаление
delete_resource(resource = "card", id = cid$id[1])
delete_resource(resource = "card", id = cid$id[2])
# Создаем новые карточки в которые после добавим графики
payload = list(
idList = lid,
name = "Показатели работы",
pos = "bottom"
)
create_resource("card", body = payload)
payload = list(
idList = lid,
name = "Сводка",
pos = "bottom"
)
create_resource("card", body = payload)
# Снова обращаемся к этому листу с уже новыми но пока пустыми карточками
bid = get_id_board("o****W")
lid <- get_board_lists(bid)$id[1]
cid <- get_list_cards(lid)
# Добавляем наши сводные графики
add_card_attachment(cid$id[1], file = "sotrudniki.png", cover = TRUE)
add_card_attachment(cid$id[2], file = "zadachi.png", cover = TRUE)

По итогу на общей доске появились сводные графики по тем KPI которые важны для ежедневного контроля. При нажатии на изображения в Trello можно сразу раскрыть превью и оперативно оценить как идут дела в рамках необходимых показателей:

Далее настраиваем автоматический запуск скрипта для актуализации дашборда и задаём нужное количество раз обновлений в день.
Итог
Полученные данные, карточки и задачи расположены на одном листе и для оценки эффективности департамента не нужно открывать +100500 разных досок. Такой подход экономит кучу времени и делает контроль за исполнением задач оперативным, а работу с сотрудниками эффективнее.
При желании, можно анализировать и делать выводы о том, кто с какой эффективностью решает задачи с детализацией до каждого сотрудника, создавая им свои мини отчеты.
Используя оценочные коэффициенты по каждому из KPI, можно формировать стандарты работы, в рамках любого периода, наблюдать динамику и принимать решение о дополнительном премировании или депремирование сотрудников на основе близких к объективным* данных.
*Для повышения точности оценки сотрудников, перед построением автоматизации необходимо как следует продумать критерии "сложных" задач, чтобы присвоение и закрытие таких карточек контролировалось руководителем и не происходила чрезмерная "переоценка" важности-сложности работ.
Но это уже совсем другая история =)
П.С.: Буду признателен комментариям и конструктивной критике кода.