summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2015-02-07 19:39:39 -0500
committerFrederic Guillot <fred@kanboard.net>2015-02-07 19:39:39 -0500
commit2d890cbc712371f17ba4bbceb02af3c5ba04e6da (patch)
treef16630432aa7fa22ebc3784839ed77c55e96e6a8
parentfa6d19928abcfa03861e264222dbe46ad2fdc15a (diff)
Update task time tracking based on subtask time tracking
-rw-r--r--app/Controller/Base.php1
-rw-r--r--app/Controller/Task.php1
-rw-r--r--app/Model/Base.php69
-rw-r--r--app/Model/Subtask.php39
-rw-r--r--app/Model/TimeTracking.php45
-rw-r--r--app/Subscriber/Base.php2
-rw-r--r--app/Template/task/show.php2
-rw-r--r--app/Template/task/timesheet.php8
-rw-r--r--assets/css/app.css4
-rw-r--r--assets/css/src/confirm.css2
-rw-r--r--assets/css/src/form.css1
-rw-r--r--tests/units/TimeTrackingTest.php48
12 files changed, 85 insertions, 137 deletions
diff --git a/app/Controller/Base.php b/app/Controller/Base.php
index ac7e8907..7f65e882 100644
--- a/app/Controller/Base.php
+++ b/app/Controller/Base.php
@@ -56,6 +56,7 @@ use Symfony\Component\EventDispatcher\Event;
* @property \Model\TaskValidator $taskValidator
* @property \Model\CommentHistory $commentHistory
* @property \Model\SubtaskHistory $subtaskHistory
+ * @property \Model\SubtaskTimeTracking $subtaskTimeTracking
* @property \Model\TimeTracking $timeTracking
* @property \Model\User $user
* @property \Model\UserSession $userSession
diff --git a/app/Controller/Task.php b/app/Controller/Task.php
index 626ac9e6..67dfe14f 100644
--- a/app/Controller/Task.php
+++ b/app/Controller/Task.php
@@ -72,7 +72,6 @@ class Task extends Base
'subtasks' => $subtasks,
'task' => $task,
'values' => $values,
- 'timesheet' => $this->timeTracking->getTaskTimesheet($task, $subtasks),
'columns_list' => $this->board->getColumnsList($task['project_id']),
'colors_list' => $this->color->getList(),
'date_format' => $this->config->get('application_date_format'),
diff --git a/app/Model/Base.php b/app/Model/Base.php
index cf5f2e9f..319e53fc 100644
--- a/app/Model/Base.php
+++ b/app/Model/Base.php
@@ -10,40 +10,41 @@ use Pimple\Container;
* @package model
* @author Frederic Guillot
*
- * @property \Core\Session $session
- * @property \Core\Template $template
- * @property \Model\Acl $acl
- * @property \Model\Action $action
- * @property \Model\Authentication $authentication
- * @property \Model\Board $board
- * @property \Model\Category $category
- * @property \Model\Comment $comment
- * @property \Model\CommentHistory $commentHistory
- * @property \Model\Color $color
- * @property \Model\Config $config
- * @property \Model\DateParser $dateParser
- * @property \Model\File $file
- * @property \Model\Helper $helper
- * @property \Model\LastLogin $lastLogin
- * @property \Model\Notification $notification
- * @property \Model\Project $project
- * @property \Model\ProjectDuplication $projectDuplication
- * @property \Model\ProjectPermission $projectPermission
- * @property \Model\Subtask $subtask
- * @property \Model\SubtaskHistory $subtaskHistory
- * @property \Model\Swimlane $swimlane
- * @property \Model\Task $task
- * @property \Model\TaskCreation $taskCreation
- * @property \Model\TaskDuplication $taskDuplication
- * @property \Model\TaskExport $taskExport
- * @property \Model\TaskFinder $taskFinder
- * @property \Model\TaskHistory $taskHistory
- * @property \Model\TaskPosition $taskPosition
- * @property \Model\TaskValidator $taskValidator
- * @property \Model\TimeTracking $timeTracking
- * @property \Model\User $user
- * @property \Model\UserSession $userSession
- * @property \Model\Webhook $webhook
+ * @property \Core\Session $session
+ * @property \Core\Template $template
+ * @property \Model\Acl $acl
+ * @property \Model\Action $action
+ * @property \Model\Authentication $authentication
+ * @property \Model\Board $board
+ * @property \Model\Category $category
+ * @property \Model\Comment $comment
+ * @property \Model\CommentHistory $commentHistory
+ * @property \Model\Color $color
+ * @property \Model\Config $config
+ * @property \Model\DateParser $dateParser
+ * @property \Model\File $file
+ * @property \Model\Helper $helper
+ * @property \Model\LastLogin $lastLogin
+ * @property \Model\Notification $notification
+ * @property \Model\Project $project
+ * @property \Model\ProjectDuplication $projectDuplication
+ * @property \Model\ProjectPermission $projectPermission
+ * @property \Model\Subtask $subtask
+ * @property \Model\SubtaskHistory $subtaskHistory
+ * @property \Model\Swimlane $swimlane
+ * @property \Model\Task $task
+ * @property \Model\TaskCreation $taskCreation
+ * @property \Model\TaskDuplication $taskDuplication
+ * @property \Model\TaskExport $taskExport
+ * @property \Model\TaskFinder $taskFinder
+ * @property \Model\TaskHistory $taskHistory
+ * @property \Model\TaskPosition $taskPosition
+ * @property \Model\TaskValidator $taskValidator
+ * @property \Model\TimeTracking $timeTracking
+ * @property \Model\SubtaskTimeTracking $subtaskTimeTracking
+ * @property \Model\User $user
+ * @property \Model\UserSession $userSession
+ * @property \Model\Webhook $webhook
*/
abstract class Base
{
diff --git a/app/Model/Subtask.php b/app/Model/Subtask.php
index 9ecd2c6a..1d5ed566 100644
--- a/app/Model/Subtask.php
+++ b/app/Model/Subtask.php
@@ -176,6 +176,9 @@ class Subtask extends Base
$subtask_id = $this->persist(self::TABLE, $values);
if ($subtask_id) {
+
+ $this->updateTaskTimeTracking($values['task_id']);
+
$this->container['dispatcher']->dispatch(
self::EVENT_CREATE,
new SubtaskEvent(array('id' => $subtask_id) + $values)
@@ -198,6 +201,11 @@ class Subtask extends Base
$result = $this->db->table(self::TABLE)->eq('id', $values['id'])->save($values);
if ($result) {
+
+ if (isset($values['task_id'])) {
+ $this->updateTaskTimeTracking($values['task_id']);
+ }
+
$this->container['dispatcher']->dispatch(
self::EVENT_UPDATE,
new SubtaskEvent($values)
@@ -260,6 +268,37 @@ class Subtask extends Base
}
/**
+ * Update task time tracking based on subtasks time tracking
+ *
+ * @access public
+ * @param integer $task_id Task id
+ * @return bool
+ */
+ public function updateTaskTimeTracking($task_id)
+ {
+ $result = $this->db
+ ->table(self::TABLE)
+ ->eq('task_id', $task_id)
+ ->columns(
+ 'SUM(time_spent) AS total_spent',
+ 'SUM(time_estimated) AS total_estimated'
+ )
+ ->findOne();
+
+ if (empty($result['total_spent']) && empty($result['total_estimated'])) {
+ return true;
+ }
+
+ return $this->db
+ ->table(Task::TABLE)
+ ->eq('id', $task_id)
+ ->update(array(
+ 'time_spent' => $result['total_spent'],
+ 'time_estimated' => $result['total_estimated'],
+ ));
+ }
+
+ /**
* Remove
*
* @access public
diff --git a/app/Model/TimeTracking.php b/app/Model/TimeTracking.php
deleted file mode 100644
index 4ddddf12..00000000
--- a/app/Model/TimeTracking.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-namespace Model;
-
-/**
- * Time tracking model
- *
- * @package model
- * @author Frederic Guillot
- */
-class TimeTracking extends Base
-{
- /**
- * Calculate time metrics for a task
- *
- * Use subtasks time metrics if not empty otherwise return task time metrics
- *
- * @access public
- * @param array $task Task properties
- * @param array $subtasks Subtasks list
- * @return array
- */
- public function getTaskTimesheet(array $task, array $subtasks)
- {
- $timesheet = array(
- 'time_spent' => 0,
- 'time_estimated' => 0,
- 'time_remaining' => 0,
- );
-
- foreach ($subtasks as &$subtask) {
- $timesheet['time_estimated'] += $subtask['time_estimated'];
- $timesheet['time_spent'] += $subtask['time_spent'];
- }
-
- if ($timesheet['time_estimated'] == 0 && $timesheet['time_spent'] == 0) {
- $timesheet['time_estimated'] = $task['time_estimated'];
- $timesheet['time_spent'] = $task['time_spent'];
- }
-
- $timesheet['time_remaining'] = $timesheet['time_estimated'] - $timesheet['time_spent'];
-
- return $timesheet;
- }
-}
diff --git a/app/Subscriber/Base.php b/app/Subscriber/Base.php
index 19f41c84..489d49b0 100644
--- a/app/Subscriber/Base.php
+++ b/app/Subscriber/Base.php
@@ -16,12 +16,14 @@ use Pimple\Container;
* @property \Model\Notification $notification
* @property \Model\Project $project
* @property \Model\ProjectPermission $projectPermission
+ * @property \Model\ProjectActivity $projectActivity
* @property \Model\ProjectAnalytic $projectAnalytic
* @property \Model\ProjectDailySummary $projectDailySummary
* @property \Model\Subtask $subtask
* @property \Model\Task $task
* @property \Model\TaskExport $taskExport
* @property \Model\TaskFinder $taskFinder
+ * @property \Model\SubtaskTimeTracking $subtaskTimeTracking
* @property \Model\UserSession $userSession
* @property \Model\Webhook $webhook
*/
diff --git a/app/Template/task/show.php b/app/Template/task/show.php
index 3bc6796f..b8243cc6 100644
--- a/app/Template/task/show.php
+++ b/app/Template/task/show.php
@@ -2,6 +2,6 @@
<?= $this->render('task/time', array('task' => $task, 'values' => $values, 'date_format' => $date_format, 'date_formats' => $date_formats)) ?>
<?= $this->render('task/show_description', array('task' => $task)) ?>
<?= $this->render('subtask/show', array('task' => $task, 'subtasks' => $subtasks)) ?>
-<?= $this->render('task/timesheet', array('timesheet' => $timesheet)) ?>
+<?= $this->render('task/timesheet', array('task' => $task)) ?>
<?= $this->render('file/show', array('task' => $task, 'files' => $files)) ?>
<?= $this->render('task/comments', array('task' => $task, 'comments' => $comments, 'project' => $project)) ?> \ No newline at end of file
diff --git a/app/Template/task/timesheet.php b/app/Template/task/timesheet.php
index fa76b84d..0210be7e 100644
--- a/app/Template/task/timesheet.php
+++ b/app/Template/task/timesheet.php
@@ -1,13 +1,13 @@
-<?php if ($timesheet['time_estimated'] > 0 || $timesheet['time_spent'] > 0): ?>
+<?php if ($task['time_estimated'] > 0 || $task['time_spent'] > 0): ?>
<div class="page-header">
<h2><?= t('Time tracking') ?></h2>
</div>
<ul class="listing">
- <li><?= t('Estimate:') ?> <strong><?= $this->e($timesheet['time_estimated']) ?></strong> <?= t('hours') ?></li>
- <li><?= t('Spent:') ?> <strong><?= $this->e($timesheet['time_spent']) ?></strong> <?= t('hours') ?></li>
- <li><?= t('Remaining:') ?> <strong><?= $this->e($timesheet['time_remaining']) ?></strong> <?= t('hours') ?></li>
+ <li><?= t('Estimate:') ?> <strong><?= $this->e($task['time_estimated']) ?></strong> <?= t('hours') ?></li>
+ <li><?= t('Spent:') ?> <strong><?= $this->e($task['time_spent']) ?></strong> <?= t('hours') ?></li>
+ <li><?= t('Remaining:') ?> <strong><?= $this->e($task['time_estimated'] - $task['time_spent']) ?></strong> <?= t('hours') ?></li>
</ul>
<?php endif ?> \ No newline at end of file
diff --git a/assets/css/app.css b/assets/css/app.css
index 0089d5f8..6c675ccd 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -919,7 +919,6 @@ select {
}
.form-actions {
- clear: both;
margin-top: 20px;
}
@@ -1908,7 +1907,8 @@ a.task-board-nobody {
.confirm {
max-width: 700px;
font-size: 1.1em;
-}/* sidebar */
+}
+/* sidebar */
.sidebar-container {
margin-top: 10px;
clear: both;
diff --git a/assets/css/src/confirm.css b/assets/css/src/confirm.css
index 78f3f1ec..fbc6bdf3 100644
--- a/assets/css/src/confirm.css
+++ b/assets/css/src/confirm.css
@@ -2,4 +2,4 @@
.confirm {
max-width: 700px;
font-size: 1.1em;
-} \ No newline at end of file
+}
diff --git a/assets/css/src/form.css b/assets/css/src/form.css
index b6cb891e..7073f2a4 100644
--- a/assets/css/src/form.css
+++ b/assets/css/src/form.css
@@ -73,7 +73,6 @@ select {
}
.form-actions {
- clear: both;
margin-top: 20px;
}
diff --git a/tests/units/TimeTrackingTest.php b/tests/units/TimeTrackingTest.php
deleted file mode 100644
index 447f1c96..00000000
--- a/tests/units/TimeTrackingTest.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-use Model\Subtask;
-use Model\TaskModification;
-use Model\TaskCreation;
-use Model\TaskFinder;
-use Model\Project;
-use Model\TimeTracking;
-
-class TimeTrackingTest extends Base
-{
- public function testCalculateTime()
- {
- $tm = new TaskModification($this->container);
- $tc = new TaskCreation($this->container);
- $tf = new TaskFinder($this->container);
- $p = new Project($this->container);
- $s = new Subtask($this->container);
- $ts = new TimeTracking($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'Project #1')));
- $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'time_estimated' => 4.5)));
- $this->assertTrue($tm->update(array('id' => 1, 'time_spent' => 3.5)));
-
- $task = $tf->getById(1);
- $this->assertNotEmpty($task);
- $this->assertEquals(4.5, $task['time_estimated']);
- $this->assertEquals(3.5, $task['time_spent']);
-
- $timesheet = $ts->getTaskTimesheet($task, array());
- $this->assertNotEmpty($timesheet);
- $this->assertEquals(4.5, $timesheet['time_estimated']);
- $this->assertEquals(3.5, $timesheet['time_spent']);
- $this->assertEquals(1, $timesheet['time_remaining']);
-
- // Subtasks calculation
- $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_estimated' => 5.5, 'time_spent' => 3)));
- $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => '', 'time_spent' => 4)));
-
- $timesheet = $ts->getTaskTimesheet($task, $s->getAll(1));
- $this->assertNotEmpty($timesheet);
- $this->assertEquals(5.5, $timesheet['time_estimated']);
- $this->assertEquals(7, $timesheet['time_spent']);
- $this->assertEquals(-1.5, $timesheet['time_remaining']);
- }
-}