diff --git a/app/Controller/Budget.php b/app/Controller/Budget.php index 01090550d..b8279f195 100644 --- a/app/Controller/Budget.php +++ b/app/Controller/Budget.php @@ -26,6 +26,30 @@ class Budget extends Base ))); } + /** + * Cost breakdown by users/subtasks/tasks + * + * @access public + */ + public function breakdown() + { + $project = $this->getProject(); + + $paginator = $this->paginator + ->setUrl('budget', 'breakdown', array('project_id' => $project['id'])) + ->setMax(30) + ->setOrder('start') + ->setDirection('DESC') + ->setQuery($this->budget->getBreakdown($project['id'])) + ->calculate(); + + $this->response->html($this->projectLayout('budget/breakdown', array( + 'paginator' => $paginator, + 'project' => $project, + 'title' => t('Budget') + ))); + } + /** * Create budget lines * diff --git a/app/Model/Budget.php b/app/Model/Budget.php index 03a90f7f9..827182a3a 100644 --- a/app/Model/Budget.php +++ b/app/Model/Budget.php @@ -45,6 +45,66 @@ class Budget extends Base return isset($result['total']) ? (float) $result['total'] : 0; } + /** + * Get breakdown by tasks/subtasks/users + * + * @access public + * @param integer $project_id + * @return \PicoDb\Table + */ + public function getBreakdown($project_id) + { + return $this->db + ->table(SubtaskTimeTracking::TABLE) + ->columns( + SubtaskTimeTracking::TABLE.'.id', + SubtaskTimeTracking::TABLE.'.user_id', + SubtaskTimeTracking::TABLE.'.subtask_id', + SubtaskTimeTracking::TABLE.'.start', + SubtaskTimeTracking::TABLE.'.time_spent', + Subtask::TABLE.'.task_id', + Subtask::TABLE.'.title AS subtask_title', + Task::TABLE.'.title AS task_title', + Task::TABLE.'.project_id', + User::TABLE.'.username', + User::TABLE.'.name' + ) + ->join(Subtask::TABLE, 'id', 'subtask_id') + ->join(Task::TABLE, 'id', 'task_id', Subtask::TABLE) + ->join(User::TABLE, 'id', 'user_id') + ->eq(Task::TABLE.'.project_id', $project_id) + ->filter(array($this, 'applyUserRate')); + } + + /** + * Filter callback to apply the rate according to the effective date + * + * @access public + * @param array $records + * @return array + */ + public function applyUserRate(array $records) + { + $rates = $this->hourlyRate->getAllByProject($records[0]['project_id']); + + foreach ($records as &$record) { + + $hourly_price = 0; + + foreach ($rates as $rate) { + + if ($rate['user_id'] == $record['user_id'] && date('Y-m-d', $rate['date_effective']) <= date('Y-m-d', $record['start'])) { + $hourly_price = $rate['rate']; + break; + } + } + + $record['cost'] = $hourly_price * $record['time_spent']; + } + + return $records; + } + /** * Add a new budget line in the database * diff --git a/app/Model/HourlyRate.php b/app/Model/HourlyRate.php index c2ce3eaff..1550bdaee 100644 --- a/app/Model/HourlyRate.php +++ b/app/Model/HourlyRate.php @@ -20,6 +20,24 @@ class HourlyRate extends Base */ const TABLE = 'hourly_rates'; + /** + * Get all user rates for a given project + * + * @access public + * @param integer $project_id + * @return array + */ + public function getAllByProject($project_id) + { + $members = $this->projectPermission->getMembers($project_id); + + if (empty($members)) { + return array(); + } + + return $this->db->table(self::TABLE)->in('user_id', array_keys($members))->desc('date_effective')->findAll(); + } + /** * Get all rates for a given user * diff --git a/app/Template/budget/breakdown.php b/app/Template/budget/breakdown.php new file mode 100644 index 000000000..d4168406f --- /dev/null +++ b/app/Template/budget/breakdown.php @@ -0,0 +1,34 @@ +
= t('There is nothing to show.') ?>
+ +| = $paginator->order(t('Task'), 'task_title') ?> | += $paginator->order(t('Subtask'), 'subtask_title') ?> | += $paginator->order(t('User'), 'username') ?> | += t('Cost') ?> | += $paginator->order(t('Time spent'), 'time_spent') ?> | += $paginator->order(t('Date'), 'start') ?> | +
|---|---|---|---|---|---|
| = $this->a($this->e($record['task_title']), 'task', 'show', array('project_id' => $project['id'], 'task_id' => $record['task_id'])) ?> | += $this->a($this->e($record['subtask_title']), 'task', 'show', array('project_id' => $project['id'], 'task_id' => $record['task_id'])) ?> | += $this->e($record['name'] ?: $record['username']) ?> | += n($record['cost']) ?> | += n($record['time_spent']).' '.t('hours') ?> | += dt('%B %e, %Y', $record['start']) ?> | +