summaryrefslogtreecommitdiff
path: root/plugins/TimeMachine/Helper/AnalyticsTimes.php
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2020-05-05 14:25:42 +0200
committeremkael <emkael@tlen.pl>2020-05-05 14:25:42 +0200
commit62827e6cf470449c117624058fb36ad94804bcc0 (patch)
tree10cd1e4d36c34b694acfadaa69fc7f6ae2b1eabd /plugins/TimeMachine/Helper/AnalyticsTimes.php
parent7b66ddf2e4fbdb837e78d8b7dbaa9fc38391bc32 (diff)
Time tracking related pluginsHEADmaster
Diffstat (limited to 'plugins/TimeMachine/Helper/AnalyticsTimes.php')
-rw-r--r--plugins/TimeMachine/Helper/AnalyticsTimes.php177
1 files changed, 177 insertions, 0 deletions
diff --git a/plugins/TimeMachine/Helper/AnalyticsTimes.php b/plugins/TimeMachine/Helper/AnalyticsTimes.php
new file mode 100644
index 00000000..c865a52a
--- /dev/null
+++ b/plugins/TimeMachine/Helper/AnalyticsTimes.php
@@ -0,0 +1,177 @@
+<?php
+
+namespace Kanboard\Plugin\TimeMachine\Helper;
+
+use Kanboard\Core\Base;
+use Kanboard\Model\SubtaskModel;
+use Kanboard\Model\SubtaskTimeTrackingModel;
+use Kanboard\Model\TaskModel;
+
+/**
+ * Analytics Times Comparison
+ *
+ * @package AnalyticsTimes
+ * @author yvalentin
+ */
+class AnalyticsTimes extends Base
+{
+
+ /**
+ * @param $project_id
+ *
+ * @return array
+ */
+ public function buildBySwimlane($project_id)
+ {
+ return $this->build($project_id, 'swimlaneModel', 'swimlane_id');
+ }
+
+ /**
+ * @param $project_id
+ *
+ * @return array
+ */
+ public function buildByCategories($project_id)
+ {
+ return $this->build($project_id, 'categoryModel', 'category_id');
+ }
+
+ /**
+ * Build report
+ *
+ * @param $project_id
+ * @param $model
+ * @param $column
+ *
+ * @return array
+ */
+ public function build($project_id, $model, $column)
+ {
+ $rows = $this->db->table(TaskModel::TABLE)
+ ->columns('SUM(time_estimated) AS time_estimated', 'SUM(time_spent) AS time_spent', 'is_active', $column)
+ ->eq('project_id', $project_id)
+ ->groupBy('is_active', $column)
+ ->findAll();
+
+// ->gte('day', $from)
+// ->lte('day', $to)
+
+ $metrics = [];
+ $names = [];
+
+ foreach ($rows as $row) {
+ if (!array_key_exists($row[$column],$names)) {
+ $name = $this->$model->getNameById($row[$column]);
+ $names[$row[$column]] = empty($name) ? t("Default") : $name;
+ $metrics[$names[$row[$column]]]['open']['time_spent'] = 0;
+ $metrics[$names[$row[$column]]]['open']['time_estimated'] = 0;
+ $metrics[$names[$row[$column]]]['closed']['time_spent'] = 0;
+ $metrics[$names[$row[$column]]]['closed']['time_estimated'] = 0;
+ }
+ $key = $row['is_active'] == TaskModel::STATUS_OPEN ? 'open' : 'closed';
+ $metrics[$names[$row[$column]]][$key]['time_spent'] = round((float) $row['time_spent'],2);
+ $metrics[$names[$row[$column]]][$key]['time_estimated'] = round((float) $row['time_estimated'],2);
+ }
+
+ return array($metrics, $names);
+ }
+
+ /**
+ * @param $project_id
+ * @param \DateTime $from
+ * @param \DateTime $to
+ *
+ * @return array
+ */
+ public function buildByDates($project_id, \DateTime $from, \DateTime $to)
+ {
+ $rows = $this->db->table(TaskModel::TABLE)
+ ->columns(
+ 'tasks.id',
+ 'subtasks.id as s_id',
+ 'subtask_time_tracking.id as stt_id',
+ 'is_active',
+ 'category_id',
+ 'swimlane_id',
+ 'tasks.time_spent',
+ 'subtasks.time_spent as s_time_spent',
+ 'subtask_time_tracking.time_spent as stt_time_spent',
+ 'subtask_time_tracking.start as stt_start',
+ 'subtask_time_tracking.end as stt_end'
+ )
+ ->eq('project_id', $project_id)
+ ->join(SubtaskModel::TABLE, 'task_id', 'id')
+ ->join(SubtaskTimeTrackingModel::TABLE, 'subtask_id', 'id', SubtaskModel::TABLE)
+ ->orderBy('tasks.id')
+ ->findAll();
+
+ $tasks = [];
+ $categories = [];
+ $swimlanes = [];
+ $tmp = [];
+ foreach ($rows as $row) {
+ $task = $row['id'];
+ $subtask = $row['s_id'];
+ $stt = $row['stt_id'];
+ // Has sub tasks with time tracking
+ if (!is_null($task) && !is_null($subtask) && !is_null($stt)) {
+ // set Datetime
+ $sttStart = (new \DateTime())->setTimestamp($row['stt_start']);
+ $sttEnd = (new \DateTime())->setTimestamp($row['stt_end']);
+ // check if start after the date from and end date before date to
+ if ($this->isInDate($sttStart, $sttEnd, $from, $to)) {
+ // recalculate time spent
+ // Get time spent for the period form
+ $startCal = $sttStart <= $from ? $from : $sttStart;
+ $endCal = $sttEnd > $to ? $to : $sttEnd;
+ // Override stt_time_spent
+ $row['stt_time_spentt'] = $this->dateParser->getHours($startCal, $endCal);
+ // regroup data by task id and subTask for debug
+ $tmp[$row['id']][$row['s_id']][$row['stt_id']] = $row;
+ // Get value of spentTime to recalculate
+ $this->initAndAdd($tasks, $task, $row);
+
+ if (!array_key_exists($row['category_id'],$categories)) {
+ $categories[$row['category_id']] = $this->categoryModel->getNameById($row['category_id']);
+ }
+ if (!array_key_exists($row['swimlane_id'],$swimlanes)) {
+ $swimlanes[$row['swimlane_id']] = $this->swimlaneModel->getNameById($row['swimlane_id']);
+ }
+ }
+ }
+ }
+ return array($tasks, $categories, $swimlanes);
+ }
+
+ /**
+ * @param array $tasks
+ * @param $taskId
+ * @param array $row
+ */
+ private function initAndAdd(array &$tasks, $taskId, array $row)
+ {
+ if(!array_key_exists($taskId, $tasks)) {
+ $tasks[$taskId]['open']['stt_time_spent'] = 0;
+ $tasks[$taskId]['closed']['stt_time_spent'] = 0;
+ $tasks[$taskId]['open']['time_spent'] = 0;
+ $tasks[$taskId]['closed']['time_spent'] = 0;
+ $tasks[$taskId]['swimlane_id'] = $row['swimlane_id'];
+ $tasks[$taskId]['category_id'] = $row['category_id'];
+ }
+ $isActive = $row['is_active'] == TaskModel::STATUS_OPEN ? 'open' : 'closed';
+ $tasks[$taskId][$isActive]['stt_time_spent'] += $row['stt_time_spent'];
+ $tasks[$taskId][$isActive]['time_spent'] = round((float) $row['time_spent'],2);
+ }
+
+ private function isInDate(\DateTime $sttStart, \DateTime $sttEnd, \DateTime $from, \DateTime $to)
+ {
+ return (
+ // stt is In the $from boundary
+ (($sttStart <= $from) && ($sttEnd > $from))
+ // stt is In the $to boundary
+ || (($sttStart < $to) && ($sttEnd >= $to))
+ // stt is In the $from and $to boundary
+ || (($sttStart >= $from) && ($sttEnd < $to ))
+ );
+ }
+}