[ Index ]

PHP Cross Reference of Eventum

title

Body

[close]

/include/ -> class.report.php (source)

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4 encoding=utf-8: */
   3  // +----------------------------------------------------------------------+
   4  // | Eventum - Issue Tracking System                                      |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 2003, 2004, 2005, 2006, 2007 MySQL AB                  |
   7  // |                                                                      |
   8  // | This program is free software; you can redistribute it and/or modify |
   9  // | it under the terms of the GNU General Public License as published by |
  10  // | the Free Software Foundation; either version 2 of the License, or    |
  11  // | (at your option) any later version.                                  |
  12  // |                                                                      |
  13  // | This program is distributed in the hope that it will be useful,      |
  14  // | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
  15  // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
  16  // | GNU General Public License for more details.                         |
  17  // |                                                                      |
  18  // | You should have received a copy of the GNU General Public License    |
  19  // | along with this program; if not, write to:                           |
  20  // |                                                                      |
  21  // | Free Software Foundation, Inc.                                       |
  22  // | 59 Temple Place - Suite 330                                          |
  23  // | Boston, MA 02111-1307, USA.                                          |
  24  // +----------------------------------------------------------------------+
  25  // | Authors: João Prado Maia <jpm@mysql.com>                             |
  26  // +----------------------------------------------------------------------+
  27  //
  28  // @(#) $Id: class.report.php 3510 2007-12-17 19:56:20Z balsdorf $
  29  //
  30  
  31  require_once (APP_INC_PATH . "class.error_handler.php");
  32  require_once (APP_INC_PATH . "class.misc.php");
  33  require_once (APP_INC_PATH . "class.user.php");
  34  require_once (APP_INC_PATH . "class.date.php");
  35  require_once (APP_INC_PATH . "class.status.php");
  36  require_once (APP_INC_PATH . "class.history.php");
  37  require_once (APP_INC_PATH . "class.phone_support.php");
  38  require_once (APP_INC_PATH . "class.prefs.php");
  39  require_once(APP_PEAR_PATH . "Math/Stats.php");
  40  
  41  /**
  42   * Class to handle the business logic related to all aspects of the
  43   * reporting system.
  44   *
  45   * @version 1.0
  46   * @author João Prado Maia <jpm@mysql.com>
  47   */
  48  
  49  class Report
  50  {
  51  
  52  
  53      /**
  54       * Method used to get all open issues and group them by user.
  55       *
  56       * @access  public
  57       * @param   integer $prj_id The project ID
  58       * @return  array The list of issues
  59       */
  60      function getStalledIssuesByUser($prj_id, $users, $status, $before_date, $after_date, $sort_order)
  61      {
  62          $prj_id = Misc::escapeInteger($prj_id);
  63          $ts = Date_API::getCurrentUnixTimestampGMT();
  64          $before_ts = strtotime($before_date);
  65          $after_ts = strtotime($after_date);
  66  
  67          // split groups out of users array
  68          $groups = array();
  69          foreach ($users as $key => $value) {
  70              if (substr($value, 0, 3) == 'grp') {
  71                  $groups[] = substr($value, 4);
  72                  unset($users[$key]);
  73              }
  74          }
  75  
  76          $stmt = "SELECT
  77                      usr_full_name,
  78                      iss_id,
  79                      iss_summary,
  80                      sta_title,
  81                      iss_sta_id,
  82                      iss_created_date,
  83                      iss_updated_date,
  84                      iss_last_response_date,
  85                      sta_color,
  86                      iss_private
  87                   FROM
  88                      (
  89                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue,
  90                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_user,
  91                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user
  92                      )
  93                   LEFT JOIN
  94                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "status
  95                   ON
  96                      iss_sta_id=sta_id
  97                   WHERE
  98                      sta_is_closed=0 AND
  99                      iss_prj_id=$prj_id AND
 100                      iss_id=isu_iss_id AND
 101                      isu_usr_id=usr_id AND
 102                      UNIX_TIMESTAMP(iss_last_response_date) < $before_ts AND
 103                      UNIX_TIMESTAMP(iss_last_response_date) > $after_ts";
 104          if (count($users) > 0) {
 105              $stmt .= " AND\nisu_usr_id IN(" . join(', ', Misc::escapeInteger($users)) . ")";
 106          }
 107          if (count($groups) > 0) {
 108              $stmt .= " AND\nusr_grp_id IN(" . join(', ', Misc::escapeInteger($groups)) . ")";
 109          }
 110          if (count($status) > 0) {
 111              $stmt .= " AND\niss_sta_id IN(" . join(', ', Misc::escapeInteger($status)) . ")";
 112          }
 113          $stmt .= "
 114                   ORDER BY
 115                      usr_full_name,
 116                      iss_last_response_date " . Misc::escapeString($sort_order);
 117          $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC);
 118          if (PEAR::isError($res)) {
 119              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 120              return "";
 121          } else {
 122              Time_Tracking::getTimeSpentByIssues($res);
 123              $issues = array();
 124              for ($i = 0; $i < count($res); $i++) {
 125                  if (empty($res[$i]['iss_updated_date'])) {
 126                      $res[$i]['iss_updated_date'] = $res[$i]['iss_created_date'];
 127                  }
 128                  if (empty($res[$i]['iss_last_response_date'])) {
 129                      $res[$i]['iss_last_response_date'] = $res[$i]['iss_created_date'];
 130                  }
 131                  $issues[$res[$i]['usr_full_name']][$res[$i]['iss_id']] = array(
 132                      'iss_summary'         => $res[$i]['iss_summary'],
 133                      'sta_title'           => $res[$i]['sta_title'],
 134                      'iss_created_date'    => Date_API::getFormattedDate($res[$i]['iss_created_date']),
 135                      'iss_last_response_date'    => Date_API::getFormattedDate($res[$i]['iss_last_response_date']),
 136                      'time_spent'          => Misc::getFormattedTime($res[$i]['time_spent']),
 137                      'status_color'        => $res[$i]['sta_color'],
 138                      'last_update'         => Date_API::getFormattedDateDiff($ts, Date_API::getUnixTimestamp($res[$i]['iss_updated_date'], Date_API::getDefaultTimezone())),
 139                      'last_email_response' => Date_API::getFormattedDateDiff($ts, Date_API::getUnixTimestamp($res[$i]['iss_last_response_date'], Date_API::getDefaultTimezone()))
 140                  );
 141              }
 142              return $issues;
 143          }
 144      }
 145  
 146      /**
 147       * Method used to get all open issues and group them by assignee or reporter.
 148       *
 149       * @access  public
 150       * @param   integer $prj_id The project ID
 151       * @param   integer $cutoff_days The number of days to use as a cutoff period
 152       * @return  array The list of issues
 153       */
 154      function getOpenIssuesByUser($prj_id, $cutoff_days, $group_by_reporter = false)
 155      {
 156          $prj_id = Misc::escapeInteger($prj_id);
 157          $cutoff_days = Misc::escapeInteger($cutoff_days);
 158          $ts = Date_API::getCurrentUnixTimestampGMT();
 159          $ts_diff = $cutoff_days * DAY;
 160  
 161  
 162          $stmt = "SELECT
 163                      assignee.usr_full_name as assignee_name,
 164                      reporter.usr_full_name as reporter_name,
 165                      iss_id,
 166                      iss_summary,
 167                      sta_title,
 168                      iss_sta_id,
 169                      iss_created_date,
 170                      iss_updated_date,
 171                      iss_last_response_date,
 172                      sta_color
 173                   FROM
 174                      (
 175                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue,
 176                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_user,
 177                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user as assignee,
 178                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user as reporter
 179                      )
 180                   LEFT JOIN
 181                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "status
 182                   ON
 183                      iss_sta_id=sta_id
 184                   WHERE
 185                      sta_is_closed=0 AND
 186                      iss_prj_id=$prj_id AND
 187                      iss_id=isu_iss_id AND
 188                      isu_usr_id=assignee.usr_id AND
 189                      iss_usr_id=reporter.usr_id AND
 190                      UNIX_TIMESTAMP(iss_created_date) < (UNIX_TIMESTAMP() - $ts_diff)
 191                   ORDER BY\n";
 192          if ($group_by_reporter) {
 193              $stmt .= "reporter.usr_full_name";
 194          } else {
 195              $stmt .= "assignee.usr_full_name";
 196          }
 197          $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC);
 198          if (PEAR::isError($res)) {
 199              print_r($res);
 200              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 201              return "";
 202          } else {
 203              Time_Tracking::getTimeSpentByIssues($res);
 204              $issues = array();
 205              for ($i = 0; $i < count($res); $i++) {
 206                  if (empty($res[$i]['iss_updated_date'])) {
 207                      $res[$i]['iss_updated_date'] = $res[$i]['iss_created_date'];
 208                  }
 209                  if (empty($res[$i]['iss_last_response_date'])) {
 210                      $res[$i]['iss_last_response_date'] = $res[$i]['iss_created_date'];
 211                  }
 212                  if ($group_by_reporter) {
 213                      $name = $res[$i]['reporter_name'];
 214                  } else {
 215                      $name = $res[$i]['assignee_name'];
 216                  }
 217                  $issues[$name][$res[$i]['iss_id']] = array(
 218                      'iss_summary'         => $res[$i]['iss_summary'],
 219                      'sta_title'           => $res[$i]['sta_title'],
 220                      'iss_created_date'    => Date_API::getFormattedDate($res[$i]['iss_created_date']),
 221                      'time_spent'          => Misc::getFormattedTime($res[$i]['time_spent']),
 222                      'status_color'        => $res[$i]['sta_color'],
 223                      'last_update'         => Date_API::getFormattedDateDiff($ts, Date_API::getUnixTimestamp($res[$i]['iss_updated_date'], Date_API::getDefaultTimezone())),
 224                      'last_email_response' => Date_API::getFormattedDateDiff($ts, Date_API::getUnixTimestamp($res[$i]['iss_last_response_date'], Date_API::getDefaultTimezone()))
 225                  );
 226              }
 227              return $issues;
 228          }
 229      }
 230  
 231  
 232      /**
 233       * Method used to get the list of issues in a project, and group
 234       * them by the assignee.
 235       *
 236       * @access  public
 237       * @param   integer $prj_id The project ID
 238       * @return  array The list of issues
 239       */
 240      function getIssuesByUser($prj_id)
 241      {
 242          $stmt = "SELECT
 243                      usr_full_name,
 244                      iss_id,
 245                      iss_summary,
 246                      sta_title,
 247                      iss_sta_id,
 248                      iss_created_date,
 249                      sta_color
 250                   FROM
 251                      (
 252                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue,
 253                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_user,
 254                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user
 255                      )
 256                   LEFT JOIN
 257                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "status
 258                   ON
 259                      iss_sta_id=sta_id
 260                   WHERE
 261                      iss_prj_id=" . Misc::escapeInteger($prj_id) . " AND
 262                      iss_id=isu_iss_id AND
 263                      isu_usr_id=usr_id
 264                   ORDER BY
 265                      usr_full_name";
 266          $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC);
 267          if (PEAR::isError($res)) {
 268              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 269              return "";
 270          } else {
 271              Time_Tracking::getTimeSpentByIssues($res);
 272              $issues = array();
 273              for ($i = 0; $i < count($res); $i++) {
 274                  $issues[$res[$i]['usr_full_name']][$res[$i]['iss_id']] = array(
 275                      'iss_summary'      => $res[$i]['iss_summary'],
 276                      'sta_title'        => $res[$i]['sta_title'],
 277                      'iss_created_date' => Date_API::getFormattedDate($res[$i]['iss_created_date']),
 278                      'time_spent'       => Misc::getFormattedTime($res[$i]['time_spent']),
 279                      'status_color'     => $res[$i]['sta_color']
 280                  );
 281              }
 282              return $issues;
 283          }
 284      }
 285  
 286  
 287      /**
 288       * Returns the data used by the weekly report.
 289       *
 290       * @access  public
 291       * @param   string $usr_id The ID of the user this report is for.
 292       * @param   string The start date of this report.
 293       * @param   string The end date of this report.
 294       * @param   boolean If closed issues should be separated from other issues.
 295       * @param   boolean If issue status changes should be ignored in report.
 296       * @return  array An array of data containing all the elements of the weekly report.
 297       */
 298      function getWeeklyReport($usr_id, $start, $end, $separate_closed = false, $ignore_statuses = false)
 299      {
 300          $prj_id = Auth::getCurrentProject();
 301          $usr_id = Misc::escapeInteger($usr_id);
 302  
 303          // figure out timezone
 304          $user_prefs = Prefs::get($usr_id);
 305          $tz = @$user_prefs["timezone"];
 306  
 307          $start_dt = new Date();
 308          $end_dt = new Date();
 309          // set timezone to that of user.
 310          $start_dt->setTZById($tz);
 311          $end_dt->setTZById($tz);
 312  
 313          // set the dates in the users time zone
 314          $start_dt->setDate($start . " 00:00:00");
 315          $end_dt->setDate($end . " 23:59:59");
 316  
 317          // convert time to GMT
 318          $start_dt->toUTC();
 319          $end_dt->toUTC();
 320  
 321          $start_ts = $start_dt->getDate();
 322          $end_ts = $end_dt->getDate();
 323  
 324          $time_tracking = Time_Tracking::getSummaryByUser($usr_id, $start_ts, $end_ts);
 325  
 326          // replace spaces in index with _ and calculate total time
 327          $total_time = 0;
 328          foreach ($time_tracking as $category => $data) {
 329              unset($time_tracking[$category]);
 330              $time_tracking[str_replace(" ", "_", $category)] = $data;
 331              $total_time += $data["total_time"];
 332          }
 333  
 334          // get count of issues assigned in week of report.
 335          $stmt = "SELECT
 336                      COUNT(*)
 337                   FROM
 338                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue,
 339                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_user,
 340                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "status
 341                   WHERE
 342                      iss_id = isu_iss_id AND
 343                      iss_sta_id = sta_id AND
 344                      isu_usr_id = $usr_id AND
 345                      iss_prj_id = " . Auth::getCurrentProject() . " AND
 346                      isu_assigned_date BETWEEN '$start_ts' AND '$end_ts'";
 347          $newly_assigned = $GLOBALS["db_api"]->dbh->getOne($stmt);
 348          if (PEAR::isError($newly_assigned)) {
 349              Error_Handler::logError(array($newly_assigned->getMessage(), $newly_assigned->getDebugInfo()), __FILE__, __LINE__);
 350          }
 351  
 352          $email_count = array(
 353              "associated"    =>  Support::getSentEmailCountByUser($usr_id, $start_ts, $end_ts, true),
 354              "other"         =>  Support::getSentEmailCountByUser($usr_id, $start_ts, $end_ts, false)
 355          );
 356  
 357          $htt_exclude = array();
 358          if ($ignore_statuses) {
 359              $htt_exclude[] = 'status_changed';
 360              $htt_exclude[] = 'status_auto_changed';
 361              $htt_exclude[] = 'remote_status_change';
 362          }
 363  
 364          $data = array(
 365              "start"     => str_replace('-', '.', $start),
 366              "end"       => str_replace('-', '.', $end),
 367              "user"      => User::getDetails($usr_id),
 368              "group_name"=> Group::getName(User::getGroupID($usr_id)),
 369              "issues"    => History::getTouchedIssuesByUser($usr_id, $start_ts, $end_ts, $separate_closed, $htt_exclude),
 370              "status_counts" => History::getTouchedIssueCountByStatus($usr_id, $start_ts, $end_ts),
 371              "new_assigned_count"    =>  $newly_assigned,
 372              "time_tracking" => $time_tracking,
 373              "email_count"   => $email_count,
 374              "phone_count"   => Phone_Support::getCountByUser($usr_id, $start_ts, $end_ts),
 375              "note_count"    => Note::getCountByUser($usr_id, $start_ts, $end_ts),
 376              "total_time"    => Misc::getFormattedTime($total_time, false)
 377          );
 378  
 379          return $data;
 380      }
 381  
 382  
 383      /**
 384       * Returns data used by the workload by time period report.
 385       *
 386       * @access  public
 387       * @param   string $timezone Timezone to display time in in addition to GMT
 388       * @param   boolean $graph If the data should be formatted for use in a graph. Default false
 389       * @return  array An array of data.
 390       */
 391      function getWorkloadByTimePeriod($timezone, $graph = false)
 392      {
 393          $stmt = "SELECT
 394                      count(*) as events,
 395                      hour(his_created_date) AS time_period,
 396                      if (pru_role > 3, 'developer', 'customer') as performer,
 397                      SUM(if (pru_role > 3, 1, 0)) as dev_events,
 398                      SUM(if (pru_role > 3, 0, 1)) as cust_events
 399                   FROM
 400                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history,
 401                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "user,
 402                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_user
 403                   WHERE
 404                      his_usr_id = usr_id AND
 405                      usr_id = pru_usr_id AND
 406                      pru_prj_id = " . Auth::getCurrentProject() . "
 407                   GROUP BY
 408                      time_period, performer
 409                   ORDER BY
 410                      time_period";
 411          $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC);
 412          if (PEAR::isError($res)) {
 413              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 414              return array();
 415          }
 416          // get total number of developer and customer events
 417          $event_count = array(
 418              "developer" =>  0,
 419              "customer"  =>  0
 420          );
 421          foreach ($res as $row) {
 422              $event_count["developer"] += $row["dev_events"];
 423              $event_count["customer"] += $row["cust_events"];
 424          }
 425  
 426          $data = array();
 427          $sort_values = array();
 428          for ($i = 0; $i < 24; $i++) {
 429  
 430              // convert to the users time zone
 431              $dt = new Date(mktime($i,0,0));
 432              $gmt_time = $dt->format('%H:%M');
 433              $dt->convertTZbyID($timezone);
 434              if ($graph) {
 435                  $data["developer"][$dt->format('%H')] = "";
 436                  $data["customer"][$dt->format('%H')] = "";
 437              } else {
 438                  $data[$i]["display_time_gmt"] = $gmt_time;
 439                  $data[$i]["display_time_user"] = $dt->format('%H:%M');
 440              }
 441  
 442              // loop through results, assigning appropriate results to data array
 443              foreach ($res as $index => $row) {
 444                  if ($row["time_period"] == $i) {
 445                      $sort_values[$row["performer"]][$i] = $row["events"];
 446  
 447                      if ($graph) {
 448                          $data[$row["performer"]][$dt->format('%H')] = (($row["events"] / $event_count[$row["performer"]]) * 100);
 449                      } else {
 450                          $data[$i][$row["performer"]]["count"] = $row["events"];
 451                          $data[$i][$row["performer"]]["percentage"] = (($row["events"] / $event_count[$row["performer"]]) * 100);
 452                      }
 453                      unset($res[$index]);
 454                  }
 455              }
 456          }
 457  
 458          if (!$graph) {
 459              // get the highest action times
 460              foreach ($sort_values as $performer => $values) {
 461                  arsort($values);
 462                  reset($values);
 463                  $data[key($values)][$performer]["rank"] = 1;
 464              }
 465          }
 466  
 467          return $data;
 468      }
 469  
 470  
 471      /**
 472       * Returns data on when support emails are sent/recieved.
 473       *
 474       * @access  public
 475       * @param   string $timezone Timezone to display time in in addition to GMT
 476       * @param   boolean $graph If the data should be formatted for use in a graph. Default false
 477       * @return  array An array of data.
 478       */
 479      function getEmailWorkloadByTimePeriod($timezone, $graph = false)
 480      {
 481          // get total counts
 482          $stmt = "SELECT
 483                      hour(sup_date) AS time_period,
 484                      count(*) as events
 485                   FROM
 486                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "support_email
 487                   GROUP BY
 488                      time_period";
 489          $total = $GLOBALS["db_api"]->dbh->getAssoc($stmt);
 490          if (PEAR::isError($total)) {
 491              Error_Handler::logError(array($total->getMessage(), $total->getDebugInfo()), __FILE__, __LINE__);
 492              return array();
 493          }
 494  
 495          // get all developer email addresses
 496          $users = User::getActiveAssocList(Auth::getCurrentProject(), User::getRoleID("customer"));
 497          $emails = array();
 498          foreach ($users as $usr_id => $usr_full_name) {
 499              $emails[] = Misc::escapeString(User::getFromHeader($usr_id));
 500          }
 501  
 502          // get number of support emails from developers
 503          $stmt = "SELECT
 504                      hour(sup_date) AS time_period,
 505                      count(*) as events
 506                   FROM
 507                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "support_email
 508                   WHERE
 509                      sup_from IN('" . join("','", $emails) . "')
 510                   GROUP BY
 511                      time_period";
 512          $dev_stats = $GLOBALS["db_api"]->dbh->getAssoc($stmt);
 513          if (PEAR::isError($dev_stats)) {
 514              Error_Handler::logError(array($dev_stats->getMessage(), $dev_stats->getDebugInfo()), __FILE__, __LINE__);
 515              return array();
 516          }
 517  
 518          // get total number of developer and customer events and build cust_stats array
 519          $dev_count = 0;
 520          $cust_count = 0;
 521          $cust_stats = array();
 522          for ($i = 0; $i < 24; $i++) {
 523              if (empty($dev_stats[$i])) {
 524                  $dev_stats[$i] = 0;
 525              }
 526              $cust_stats[$i] = (@$total[$i] - @$dev_stats[$i]);
 527              $cust_count += (@$total[$i] - @$dev_stats[$i]);
 528              $dev_count += @$dev_stats[$i];
 529          }
 530  
 531          $data = array();
 532          $sort_values = array();
 533          for ($i = 0; $i < 24; $i++) {
 534  
 535              // convert to the users time zone
 536              $dt = new Date(mktime($i,0,0));
 537              $gmt_time = $dt->format('%H:%M');
 538              $dt->convertTZbyID($timezone);
 539              if ($graph) {
 540                  $data["developer"][$dt->format('%H')] = "";
 541                  $data["customer"][$dt->format('%H')] = "";
 542              } else {
 543                  $data[$i]["display_time_gmt"] = $gmt_time;
 544                  $data[$i]["display_time_user"] = $dt->format('%H:%M');
 545              }
 546  
 547              // use later to find highest value
 548              $sort_values["developer"][$i] = $dev_stats[$i];
 549              $sort_values["customer"][$i] = $cust_stats[$i];
 550  
 551              if ($graph) {
 552                  if ($dev_count == 0) {
 553                      $data["developer"][$dt->format('%H')] = 0;
 554                  } else {
 555                      $data["developer"][$dt->format('%H')] = (($dev_stats[$i] / $dev_count) * 100);
 556                  }
 557                  if ($cust_count == 0) {
 558                      $data["customer"][$dt->format('%H')] = 0;
 559                  } else {
 560                      $data["customer"][$dt->format('%H')] = (($cust_stats[$i] / $cust_count) * 100);
 561                  }
 562              } else {
 563                  $data[$i]["developer"]["count"] = $dev_stats[$i];
 564                  if ($dev_count == 0){
 565                      $data[$i]["developer"]["percentage"] = 0;
 566                  } else {
 567                      $data[$i]["developer"]["percentage"] = (($dev_stats[$i] / $dev_count) * 100);
 568                  }
 569                  $data[$i]["customer"]["count"] = $cust_stats[$i];
 570                  if ($cust_count == 0) {
 571                      $data[$i]["customer"]["percentage"] = 0;
 572                  } else {
 573                      $data[$i]["customer"]["percentage"] = (($cust_stats[$i] / $cust_count) * 100);
 574                  }
 575              }
 576          }
 577  
 578          if (!$graph) {
 579              // get the highest action times
 580              foreach ($sort_values as $performer => $values) {
 581                  arsort($values);
 582                  reset($values);
 583                  $data[key($values)][$performer]["rank"] = 1;
 584              }
 585          }
 586  
 587          return $data;
 588      }
 589  
 590  
 591      /**
 592       * Returns data for the custom fields report, based on the field and options passed in.
 593       *
 594       * @access  public
 595       * @param   integer $fld_id The id of the custom field.
 596       * @param   array $cfo_ids An array of option ids.
 597       * @param   string $group_by How the data should be grouped.
 598       * @param   string $start_date
 599       * @param   string $end_date
 600       * @param   boolean $list If the values should be listed out instead of just counted.
 601       * @param   string $interval The interval values should be grouped over time, empty (none) by default.
 602       * @param   integer $assignee The assignee the issue should belong to.
 603       * @return  array An array of data.
 604       */
 605      function getCustomFieldReport($fld_id, $cfo_ids, $group_by = "issue", $start_date, $end_date, $list = false, $interval = '', $assignee = false)
 606      {
 607          $prj_id = Auth::getCurrentProject();
 608          $fld_id = Misc::escapeInteger($fld_id);
 609          $cfo_ids = Misc::escapeInteger($cfo_ids);
 610  
 611          // get field values
 612          $options = Custom_Field::getOptions($fld_id, $cfo_ids);
 613  
 614          if ($group_by == "customer") {
 615              $group_by_field = "iss_customer_id";
 616          } else {
 617              $group_by_field = "iss_id";
 618          }
 619  
 620          if ($assignee == -1) {
 621              $assignee = false;
 622          }
 623  
 624          $label_field = '';
 625          $interval_group_by_field = '';
 626          switch ($interval) {
 627              case "day":
 628                  $label_field = "CONCAT(YEAR(iss_created_date), '-', MONTH(iss_created_date), '-', DAY(iss_created_date))";
 629                  $interval_group_by_field = "CONCAT(YEAR(iss_created_date), MONTH(iss_created_date), DAY(iss_created_date))";
 630                  break;
 631              case "week":
 632                  $label_field = "CONCAT(YEAR(iss_created_date), '/', WEEK(iss_created_date))";
 633                  $interval_group_by_field = "WEEK(iss_created_date)";
 634                  break;
 635              case "month":
 636                  $label_field = "CONCAT(YEAR(iss_created_date), '/', MONTH(iss_created_date))";
 637                  $interval_group_by_field = "MONTH(iss_created_date)";
 638                  break;
 639              case "year":
 640                  $label_field = "YEAR(iss_created_date)";
 641                  $interval_group_by_field = "YEAR(iss_created_date)";
 642                  break;
 643          }
 644  
 645          if ($list == true) {
 646              $sql = "SELECT
 647                          DISTINCT($group_by_field),
 648                          iss_id,
 649                          iss_summary,
 650                          iss_customer_id,
 651                          count(DISTINCT(iss_id)) as row_count,
 652                          iss_private,
 653                          " . Custom_Field::getDBValueFieldSQL() . " as field_value";
 654              if ($label_field != '') {
 655                  $sql .= ",
 656                          $label_field as interval_label";
 657              }
 658              $sql .= "
 659                      FROM
 660                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "custom_field,";
 661              if (count($options) > 0) {
 662                  $sql .= "
 663                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "custom_field_option,";
 664              }
 665              $sql .= "
 666                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_custom_field,
 667                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue,
 668                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_user
 669                      WHERE
 670                          fld_id = icf_fld_id AND";
 671              if (count($options) > 0) {
 672                  $sql .=
 673                          "cfo_id = icf_value AND";
 674              }
 675              $sql .= "
 676                          icf_iss_id = iss_id AND
 677                          isu_iss_id = iss_id AND
 678                          icf_fld_id = $fld_id";
 679              if (count($options) > 0) {
 680                  $sql .= " AND
 681                          cfo_id IN('" . join("','", Misc::escapeString(array_keys($options))) . "')";
 682              }
 683              if (($start_date != false) && ($end_date != false)) {
 684                  $sql .= " AND\niss_created_date BETWEEN '" . Misc::escapeString($start_date) . "' AND '" . Misc::escapeString($end_date) . "'";
 685              }
 686              if ($assignee != false) {
 687                  $sql .= " AND\nisu_usr_id = " . Misc::escapeInteger($assignee);
 688              }
 689              $sql .= "
 690                      GROUP BY
 691                          $group_by_field
 692                      ORDER BY";
 693              if ($label_field != '') {
 694                  $sql .= "
 695                          $label_field DESC,";
 696              }
 697              $sql .= "
 698                          row_count DESC";
 699              $res = $GLOBALS["db_api"]->dbh->getAll($sql, DB_FETCHMODE_ASSOC);
 700              if (PEAR::isError($res)) {
 701                  Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 702                  return array();
 703              }
 704              if (Customer::hasCustomerIntegration($prj_id)) {
 705                  Customer::getCustomerTitlesByIssues($prj_id, $res);
 706                  if ($group_by == "issue") {
 707                      usort($res, create_function('$a,$b', 'if ($a["customer_title"] < $b["customer_title"]) {
 708                          return -1;
 709                      } elseif ($a["customer_title"] > $b["customer_title"]) {
 710                          return 1;
 711                      } else {
 712                          return 0;
 713                      }'));
 714                  }
 715              }
 716              return $res;
 717          }
 718  
 719          $data = array();
 720          foreach ($options as $cfo_id => $value) {
 721              $stmt = "SELECT";
 722              if ($label_field != '') {
 723                  $stmt .= "
 724                          $label_field as label,";
 725              }
 726              $stmt .= "
 727                          COUNT(DISTINCT $group_by_field)
 728                      FROM
 729                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_custom_field,
 730                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue,
 731                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_user
 732                      WHERE
 733                          icf_iss_id = iss_id AND
 734                          isu_iss_id = iss_id AND
 735                          icf_fld_id = $fld_id AND
 736                          icf_value = '$cfo_id'";
 737              if (($start_date != false) && ($end_date != false)) {
 738                  $stmt .= " AND\niss_created_date BETWEEN '" . Misc::escapeString($start_date) . "' AND '" . Misc::escapeString($end_date) . "'";
 739              }
 740              if ($assignee != false) {
 741                  $sql .= " AND\nisu_usr_id = " . Misc::escapeInteger($assignee);
 742              }
 743              if ($interval_group_by_field != '') {
 744                  $stmt .= "
 745                      GROUP BY
 746                          $interval_group_by_field
 747                      ORDER BY
 748                          $label_field ASC";
 749                  $res = $GLOBALS['db_api']->dbh->getAssoc($stmt);
 750              } else {
 751                  $res = $GLOBALS["db_api"]->dbh->getOne($stmt);
 752              }
 753              if (PEAR::isError($res)) {
 754                  Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 755                  return array();
 756              }
 757              $data[$value] = $res;
 758          }
 759  
 760          // include count of all other values (used in pie chart)
 761          $stmt = "SELECT
 762                      COUNT(DISTINCT $group_by_field)
 763                  FROM
 764                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "custom_field_option,
 765                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_custom_field,
 766                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue
 767                  WHERE
 768                      cfo_id = icf_value AND
 769                      icf_iss_id = iss_id AND
 770                      icf_fld_id = $fld_id AND
 771                      cfo_id NOT IN(" . join(",", $cfo_ids) . ")";
 772          $res = $GLOBALS["db_api"]->dbh->getOne($stmt);
 773          if (PEAR::isError($res)) {
 774              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 775              return array();
 776          }
 777          $data["All Others"] = $res;
 778  
 779          return $data;
 780      }
 781  
 782  
 783      /**
 784       * Returns workload information for the specified date range and interval.
 785       *
 786       * @access  public
 787       * @param   string $interval The interval to use in this report.
 788       * @param   string $type If this report is aggregate or individual
 789       * @param   string $start The start date of this report.
 790       * @param   string $end The end date of this report.
 791       * @param   integer $category The category to restrict this report to
 792       * @return  array An array containing workload data.
 793       */
 794      function getWorkloadByDateRange($interval, $type, $start, $end, $category)
 795      {
 796          $data = array();
 797          $start = Misc::escapeString($start);
 798          $end = Misc::escapeString($end);
 799          $category = Misc::escapeInteger($category);
 800  
 801          // figure out the correct format code
 802          switch ($interval) {
 803              case "day":
 804                  $format = '%m/%d/%y';
 805                  $order_by = "%1\$s";
 806                  break;
 807              case "dow":
 808                  $format = '%W';
 809                  $order_by = "IF(DATE_FORMAT(%1\$s, '%%w') = 0, 7, DATE_FORMAT(%1\$s, '%%w'))";
 810                  break;
 811              case "week":
 812                  if ($type == "aggregate") {
 813                      $format = '%v';
 814                  } else {
 815                      $format = '%v/%y';
 816                  }
 817                  $order_by = "%1\$s";
 818                  break;
 819              case "dom":
 820                  $format = '%d';
 821                  break;
 822              case "month":
 823                  if ($type == "aggregate") {
 824                      $format = '%b';
 825                      $order_by = "DATE_FORMAT(%1\$s, '%%m')";
 826                  } else {
 827                      $format = '%b/%y';
 828                      $order_by = "%1\$s";
 829                  }
 830                  break;
 831          }
 832  
 833          // get issue counts
 834          $stmt = "SELECT
 835                      DATE_FORMAT(iss_created_date, '$format'),
 836                      count(*)
 837                   FROM
 838                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue
 839                   WHERE
 840                      iss_prj_id=" . Auth::getCurrentProject() . " AND
 841                      iss_created_date BETWEEN '$start' AND '$end'";
 842          if (!empty($category)) {
 843              $stmt .= " AND
 844                      iss_prc_id = $category";
 845          }
 846          $stmt .= "
 847                   GROUP BY
 848                      DATE_FORMAT(iss_created_date, '$format')";
 849          if (!empty($order_by)) {
 850              $stmt .= "\nORDER BY " . sprintf($order_by, 'iss_created_date');
 851          }
 852          $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt);
 853          if (PEAR::isError($res)) {
 854              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 855              return array();
 856          }
 857          $data["issues"]["points"] = $res;
 858  
 859          if (count($res) > 0) {
 860              $stats = new Math_Stats();
 861              $stats->setData($res);
 862  
 863              $data["issues"]["stats"] = array(
 864                  "total" =>  $stats->sum(),
 865                  "avg"   =>  $stats->mean(),
 866                  "median"    =>  $stats->median(),
 867                  "max"   =>  $stats->max()
 868              );
 869          } else {
 870              $data["issues"]["stats"] = array(
 871                  "total" =>  0,
 872                  "avg"   =>  0,
 873                  "median"    =>  0,
 874                  "max"   =>  0
 875              );
 876          }
 877  
 878  
 879          // get email counts
 880          $stmt = "SELECT
 881                      DATE_FORMAT(sup_date, '$format'),
 882                      count(*)
 883                   FROM
 884                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "support_email,
 885                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "email_account";
 886          if (!empty($category)) {
 887              $stmt .= ",
 888                       " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue";
 889          }
 890          $stmt .= "
 891                   WHERE
 892                      sup_ema_id=ema_id AND
 893                      ema_prj_id=" . Auth::getCurrentProject() . " AND
 894                      sup_date BETWEEN '$start' AND '$end'";
 895          if (!empty($category)) {
 896              $stmt .= " AND
 897                      sup_iss_id = iss_id AND
 898                      iss_prc_id = $category";
 899          }
 900          $stmt .= "
 901                   GROUP BY
 902                      DATE_FORMAT(sup_date, '$format')";
 903          if (!empty($order_by)) {
 904              $stmt .= "\nORDER BY " . sprintf($order_by, 'sup_date');
 905          }
 906          $res = $GLOBALS["db_api"]->dbh->getAssoc($stmt);
 907          if (PEAR::isError($res)) {
 908              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 909              return array();
 910          }
 911          $data["emails"]["points"] = $res;
 912  
 913          if (count($res) > 0) {
 914              $stats = new Math_Stats();
 915              $stats->setData($res);
 916  
 917              $data["emails"]["stats"] = array(
 918                  "total" =>  $stats->sum(),
 919                  "avg"   =>  $stats->mean(),
 920                  "median"    =>  $stats->median(),
 921                  "max"   =>  $stats->max()
 922              );
 923          } else {
 924              $data["emails"]["stats"] = array(
 925                  "total" =>  0,
 926                  "avg"   =>  0,
 927                  "median"    =>  0,
 928                  "max"   =>  0
 929              );
 930          }
 931  
 932  
 933          return $data;
 934      }
 935  }
 936  
 937  // benchmarking the included file (aka setup time)
 938  if (APP_BENCHMARK) {
 939      $GLOBALS['bench']->setMarker('Included Report Class');
 940  }


Generated: Wed Dec 19 21:21:33 2007 Cross-referenced by PHPXref 0.7