Skip to content
Snippets Groups Projects
ajax.reports.php 5.64 KiB
Newer Older
<?php
/*********************************************************************
    ajax.reports.php

    AJAX interface for reports -- both plot and tabular data are retrievable
    in JSON format from this utility. Please put plumbing in /scp/ajax.php
    pattern rules.

    Jared Hancock <jared@osticket.com>
    Copyright (c)  2006-2012 osTicket
    http://www.osticket.com

    Released under the GNU General Public License WITHOUT ANY WARRANTY.
    See LICENSE.TXT for details.

    vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/

if(!defined('INCLUDE_DIR')) die('403');

include_once(INCLUDE_DIR.'class.ticket.php');

/**
 * Overview Report
 * 
 * The overview report allows for the display of basic ticket statistics in
 * both graphical and tabular formats.
 */
class OverviewReportAjaxAPI extends AjaxController {
    function enumTabularGroups() {
        return $this->encode(array("dept"=>"Department", "topic"=>"Topics",
        "staff"=>"Staff"));
    }

    function getData() {
        $start = $this->get('start', strtotime('last month'));
        $stop = $this->get('stop', time());

        $groups = array(
            "dept" => array(
                "table" => DEPT_TABLE,
                "pk" => "dept_id",
                "sort" => 'ORDER BY dept_name',
                "fields" => 'T1.dept_name',
                "headers" => array('Department')
            ),
            "topic" => array(
                "table" => TOPIC_TABLE,
                "pk" => "topic_id",
                "sort" => 'ORDER BY topic',
                "fields" => "T1.topic",
                "headers" => array('Help Topic')
            ),
            "staff" => array(
                "table" => STAFF_TABLE,
                "pk" => 'staff_id',
                "sort" => 'ORDER BY T1.lastname, T1.firstname',
                "fields" => "CONCAT_WS(' ', T1.firstname, T1.lastname)",
                "headers" => array('Staff Member')
            )
        );
        $group = $this->get('group', 'dept');
        $info = $groups[$group];
        # XXX: Die if $group not in $groups

        $res = db_query(
            'SELECT ' . $info['fields'] . ','
                .' COUNT(A1.ticket_id) AS Opened,'
                .' COUNT(A2.ticket_id) AS Closed,'
                .' COUNT(A3.ticket_id) AS Reopened'
            .' FROM ' . $info['table'] . ' T1'
            .' LEFT JOIN ' . TICKET_EVENT_TABLE 
                . ' A1 ON (T1.' . $info['pk'] . ' = A1.' . $info['pk']
                    .' AND A1.state=\'opened\' AND NOT A1.annulled)'
            .' LEFT JOIN ' . TICKET_EVENT_TABLE
                . ' A2 ON (T1.' . $info['pk'] . ' = A2.' . $info['pk']
                    .' AND A2.state=\'closed\' AND NOT A2.annulled)'
            .' LEFT JOIN ' . TICKET_EVENT_TABLE
                . ' A3 ON (T1.' . $info['pk'] . ' = A3.' . $info['pk']
                    .' AND A3.state=\'reopened\' AND NOT A3.annulled)'
            .' GROUP BY '.$info['fields']
        );
        $rows = array();
        while ($row = db_fetch_row($res)) {
            $rows[] = $row;
        }
        return array("columns" => array_merge($info['headers'],
                        array('Opened','Closed','Reopened')),
                     "data" => $rows);
    }

    function getTabularData() {
        return $this->encode($this->getData());
    }

    function downloadTabularData() {
        $data = $this->getData();
        $csv = array($data['columns']);
        $csv = array_merge($csv, $data['data']);
        Http::download(
            sprintf('%s-report.csv', $this->get('group', 'Department')),
            Format::implode_array(',', "\n", $csv));
    }

    function getPlotData() {
        $start = $this->get('start', strtotime('last month'));
        $stop = $this->get('stop', time());

        # Fetch all types of events over the timeframe
        $res = db_query('SELECT DISTINCT(state) FROM '.TICKET_EVENT_TABLE
            .' WHERE timestamp BETWEEN FROM_UNIXTIME('.db_input($start)
                .') AND FROM_UNIXTIME('.db_input($stop).')');
        $events = array();
        while ($row = db_fetch_row($res)) $events[] = $row[0];

        # TODO: Handle user => db timezone offset
        # XXX: Implement annulled column from the %ticket_event table
        $res = db_query('SELECT state, DATE_FORMAT(timestamp, \'%Y-%m-%d\'), '
                .'COUNT(ticket_id)'
            .' FROM '.TICKET_EVENT_TABLE
            .' WHERE timestamp BETWEEN FROM_UNIXTIME('.db_input($start)
                .') AND FROM_UNIXTIME('.db_input($stop)
            .') GROUP BY state, DATE_FORMAT(timestamp, \'%Y-%m-%d\')');
        # Initialize array of plot values
        $plots = array();
        foreach ($events as $e) { $plots[$e] = array(); }

        $time = null; $times = array();
        # Iterate over result set, adding zeros for missing ticket events
        while ($row = db_fetch_row($res)) {
            $row_time = strtotime($row[1]);
            if ($time != $row_time) {
                # New time (and not the first), figure out which events did
                # not have any tickets associated for this time slot
                if ($time !== null) {
                    # Not the first record
                    foreach (array_diff($events, $slots) as $slot) {
                        $plots[$slot][] = 0;
                    }
                }
                $slots = array();
                $times[] = $time = $row_time;
            }
            # Keep track of states for this timeframe
            if (!in_array($row[0], $slots)) $slots[] = $row[0];
            $plots[$row[0]][] = (int)$row[2];
        }
        return $this->encode(array("times" => $times, "plots" => $plots));
    }
}