summaryrefslogtreecommitdiff
path: root/app/Model/ProjectDailyColumnStats.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/Model/ProjectDailyColumnStats.php')
-rw-r--r--app/Model/ProjectDailyColumnStats.php193
1 files changed, 193 insertions, 0 deletions
diff --git a/app/Model/ProjectDailyColumnStats.php b/app/Model/ProjectDailyColumnStats.php
new file mode 100644
index 00000000..26e9d8b7
--- /dev/null
+++ b/app/Model/ProjectDailyColumnStats.php
@@ -0,0 +1,193 @@
+<?php
+
+namespace Model;
+
+/**
+ * Project Daily Column Stats
+ *
+ * @package model
+ * @author Frederic Guillot
+ */
+class ProjectDailyColumnStats extends Base
+{
+ /**
+ * SQL table name
+ *
+ * @var string
+ */
+ const TABLE = 'project_daily_column_stats';
+
+ /**
+ * Update daily totals for the project and foreach column
+ *
+ * "total" is the number open of tasks in the column
+ * "score" is the sum of tasks score in the column
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param string $date Record date (YYYY-MM-DD)
+ * @return boolean
+ */
+ public function updateTotals($project_id, $date)
+ {
+ return $this->db->transaction(function($db) use ($project_id, $date) {
+
+ $column_ids = $db->table(Board::TABLE)->eq('project_id', $project_id)->findAllByColumn('id');
+
+ foreach ($column_ids as $column_id) {
+
+ // This call will fail if the record already exists
+ // (cross database driver hack for INSERT..ON DUPLICATE KEY UPDATE)
+ $db->table(ProjectDailyColumnStats::TABLE)->insert(array(
+ 'day' => $date,
+ 'project_id' => $project_id,
+ 'column_id' => $column_id,
+ 'total' => 0,
+ 'score' => 0,
+ ));
+
+ $db->table(ProjectDailyColumnStats::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('column_id', $column_id)
+ ->eq('day', $date)
+ ->update(array(
+ 'score' => $db->table(Task::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('column_id', $column_id)
+ ->eq('is_active', Task::STATUS_OPEN)
+ ->sum('score'),
+ 'total' => $db->table(Task::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('column_id', $column_id)
+ ->count()
+ ));
+ }
+ });
+ }
+
+ /**
+ * Count the number of recorded days for the data range
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param string $from Start date (ISO format YYYY-MM-DD)
+ * @param string $to End date
+ * @return integer
+ */
+ public function countDays($project_id, $from, $to)
+ {
+ $rq = $this->db->execute(
+ 'SELECT COUNT(DISTINCT day) FROM '.self::TABLE.' WHERE day >= ? AND day <= ? AND project_id=?',
+ array($from, $to, $project_id)
+ );
+
+ return $rq !== false ? $rq->fetchColumn(0) : 0;
+ }
+
+ /**
+ * Get raw metrics for the project within a data range
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param string $from Start date (ISO format YYYY-MM-DD)
+ * @param string $to End date
+ * @return array
+ */
+ public function getRawMetrics($project_id, $from, $to)
+ {
+ return $this->db->table(ProjectDailyColumnStats::TABLE)
+ ->columns(
+ ProjectDailyColumnStats::TABLE.'.column_id',
+ ProjectDailyColumnStats::TABLE.'.day',
+ ProjectDailyColumnStats::TABLE.'.total',
+ ProjectDailyColumnStats::TABLE.'.score',
+ Board::TABLE.'.title AS column_title'
+ )
+ ->join(Board::TABLE, 'id', 'column_id')
+ ->eq(ProjectDailyColumnStats::TABLE.'.project_id', $project_id)
+ ->gte('day', $from)
+ ->lte('day', $to)
+ ->asc(ProjectDailyColumnStats::TABLE.'.day')
+ ->findAll();
+ }
+
+ /**
+ * Get raw metrics for the project within a data range grouped by day
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param string $from Start date (ISO format YYYY-MM-DD)
+ * @param string $to End date
+ * @return array
+ */
+ public function getRawMetricsByDay($project_id, $from, $to)
+ {
+ return $this->db->table(ProjectDailyColumnStats::TABLE)
+ ->columns(
+ ProjectDailyColumnStats::TABLE.'.day',
+ 'SUM('.ProjectDailyColumnStats::TABLE.'.total) AS total',
+ 'SUM('.ProjectDailyColumnStats::TABLE.'.score) AS score'
+ )
+ ->eq(ProjectDailyColumnStats::TABLE.'.project_id', $project_id)
+ ->gte('day', $from)
+ ->lte('day', $to)
+ ->asc(ProjectDailyColumnStats::TABLE.'.day')
+ ->groupBy(ProjectDailyColumnStats::TABLE.'.day')
+ ->findAll();
+ }
+
+ /**
+ * Get aggregated metrics for the project within a data range
+ *
+ * [
+ * ['Date', 'Column1', 'Column2'],
+ * ['2014-11-16', 2, 5],
+ * ['2014-11-17', 20, 15],
+ * ]
+ *
+ * @access public
+ * @param integer $project_id Project id
+ * @param string $from Start date (ISO format YYYY-MM-DD)
+ * @param string $to End date
+ * @param string $column Column to aggregate
+ * @return array
+ */
+ public function getAggregatedMetrics($project_id, $from, $to, $column = 'total')
+ {
+ $columns = $this->board->getColumnsList($project_id);
+ $column_ids = array_keys($columns);
+ $metrics = array(array_merge(array(e('Date')), array_values($columns)));
+ $aggregates = array();
+
+ // Fetch metrics for the project
+ $records = $this->db->table(ProjectDailyColumnStats::TABLE)
+ ->eq('project_id', $project_id)
+ ->gte('day', $from)
+ ->lte('day', $to)
+ ->findAll();
+
+ // Aggregate by day
+ foreach ($records as $record) {
+
+ if (! isset($aggregates[$record['day']])) {
+ $aggregates[$record['day']] = array($record['day']);
+ }
+
+ $aggregates[$record['day']][$record['column_id']] = $record[$column];
+ }
+
+ // Aggregate by row
+ foreach ($aggregates as $aggregate) {
+
+ $row = array($aggregate[0]);
+
+ foreach ($column_ids as $column_id) {
+ $row[] = (int) $aggregate[$column_id];
+ }
+
+ $metrics[] = $row;
+ }
+
+ return $metrics;
+ }
+}