define ('QR_SHOW_EXECUTIVE_REPORTS_MENU_PAGE', '?executive/');
define ('QR_LIST_EXECUTIVE_REPORTS_PAGE', '?executive/reports/');
define ('QR_CREATE_EXECUTIVE_REPORT_PAGE', 'executiveReport.php?');
+define ('QR_EXECUTIVE_REPORTS_MENU_COLUMNS', 3);
//login
define ('PINS_LOGOUT_EXPLICIT', 1);
//escape text shown in javascript alerts
define ('QR_DEFAULT_ESCAPE_PATTERNS', serialize(array("/\\\\/", '/ /', '/ /', '/\n/', '/\r/', '/\t/', '/\v/', '/\f/', "/'/", '/"/', '/"/')));
define ('QR_DEFAULT_ESCAPE_REPLACEMENTS', serialize(array('\\\\\\', '\n', '\r', '\n', '\r', '\t', '\v', '\f', ''', '\"', '\"')));
-?>
\ No newline at end of file
+?>
--- /dev/null
+<?php
+$report[] = (object) array (
+ 'id' => 'P1',
+ 'category' => 'Patrons',
+ 'name' => 'Active Users',
+ 'description' => 'Count of active users');
+
+$report[] = (object) array (
+ 'id' => 'P2',
+ 'category' => 'Patrons',
+ 'name' => 'New Users',
+ 'description' => 'Count of new users');
+
+$report[] = (object) array (
+ 'id' => 'P3',
+ 'category' => 'Patrons',
+ 'name' => 'Users Who Circulated Items',
+ 'description' => 'Count of users who circulated items');
+
+$report[] = (object) array (
+ 'id' => 'P4',
+ 'category' => 'Patrons',
+ 'name' => 'Users Who Placed Holds',
+ 'description' => 'Count of users who placed holds');
+
+$report[] = (object) array (
+ 'id' => 'B1',
+ 'category' => 'Bills',
+ 'format' => 'currency',
+ 'name' => 'Amount Owed By My Patrons',
+ 'description' => 'Total amount owed by my patrons');
+
+$report[] = (object) array (
+ 'id' => 'B2',
+ 'category' => 'Bills',
+ 'format' => 'currency',
+ 'name' => 'Amount Billed To My Patrons',
+ 'description' => 'Amount billed to my patrons this month');
+
+$report[] = (object) array (
+ 'id' => 'B3',
+ 'category' => 'Bills',
+ 'format' => 'currency',
+ 'name' => 'Amount Collected From My Patrons',
+ 'description' => 'Amount collected this month');
+
+$report[] = (object) array (
+ 'id' => 'C1',
+ 'category' => 'Circulation',
+ 'name' => 'Circulations',
+ 'description' => 'Count of circulation');
+
+$report[] = (object) array (
+ 'id' => 'C2',
+ 'category' => 'Circulation',
+ 'name' => 'Circulations by Circulation Modifier',
+ 'description' => 'Count of circulation by circulation modifier');
+
+$report[] = (object) array (
+ 'id' => 'C3',
+ 'category' => 'Circulation',
+ 'name' => 'Circulations by MARC Type',
+ 'description' => 'Count of circulation by MARC type');
+
+$report[] = (object) array (
+ 'id' => 'C4',
+ 'category' => 'Circulation',
+ 'name' => 'Circulations by Non-Cataloged',
+ 'description' => 'Count of circulation by non-cataloged types');
+
+$report[] = (object) array (
+ 'id' => 'C5',
+ 'category' => 'Circulation',
+ 'name' => 'In-House Use',
+ 'description' => 'Count of in-house use');
+
+$report[] = (object) array (
+ 'id' => 'H1',
+ 'category' => 'Holds/Transits',
+ 'name' => 'Holds Sent From My Library',
+ 'description' => 'Holds sent from my library');
+
+$report[] = (object) array (
+ 'id' => 'H2',
+ 'category' => 'Holds/Transits',
+ 'name' => 'Holds Received At My Library',
+ 'description' => 'Holds received at my library from another library');
+
+$report[] = (object) array (
+ 'id' => 'H3',
+ 'category' => 'Holds/Transits',
+ 'name' => 'Internal Holds',
+ 'description' => 'Internal holds');
+
+$report[] = (object) array (
+ 'id' => 'H4',
+ 'category' => 'Holds/Transits',
+ 'name' => 'Total Incoming Transits',
+ 'description' => 'Total incoming transits');
+
+$report[] = (object) array (
+ 'id' => 'H5',
+ 'category' => 'Holds/Transits',
+ 'name' => 'Total Outgoing Transits',
+ 'description' => 'Total outgoing transits');
+
+$report[] = (object) array (
+ 'id' => 'H6',
+ 'category' => 'Holds/Transits',
+ 'name' => 'Total IntraPINES Sent',
+ 'description' => 'Total IntraPINES sent (HQ-HQ)');
+
+$report[] = (object) array (
+ 'id' => 'H7',
+ 'category' => 'Holds/Transits',
+ 'name' => 'Total IntraPINES Received',
+ 'description' => 'Total IntraPINES received (HQ-HQ)');
+
+$report[] = (object) array (
+ 'id' => 'I1',
+ 'category' => 'Collections/Items',
+ 'name' => 'Total Items',
+ 'description' => 'Count of items');
+
+$report[] = (object) array (
+ 'id' => 'I2',
+ 'category' => 'Collections/Items',
+ 'format' => 'currency',
+ 'name' => 'Value of Items',
+ 'description' => 'Value of items');
+
+$report[] = (object) array (
+ 'id' => 'I3',
+ 'category' => 'Collections/Items',
+ 'name' => 'Added Items',
+ 'description' => 'Count of added items');
+
+$report[] = (object) array (
+ 'id' => 'I4',
+ 'category' => 'Collections/Items',
+ 'name' => 'Deleted Items',
+ 'description' => 'Count of deleted items');
+
+?>
//system configs
define ('QR_ERROR_REPORTING_LEVEL', E_ALL);
define ('QR_DEFAULT_TIME_ZONE', 'America/New_York');
-define ('QR_SITE_ROOT', '/report-creator-generic/');
define ('QR_REPORT_OUTPUT_URL_PREFIX', 'https://next.gapines.org/reporter/');
+define ('QR_SITE_ROOT', '/report-creator/');
//define ('QR_REPORT_OUTPUT_URL_PREFIX', 'https://reports-dev.gapines.org/reporter/');
define ('QR_REPORT_OUTPUT_URL_SUFFIX', '/report-data.html');
//page headings
define ('QR_DEFAULT_LOGO_TEXT', 'Quick Reports');
define ('QR_DEFAULT_TITLE_TAG_TEXT', 'Quick Reports');
-define ('QR_HOME_PAGE_WELCOME_TEXT', 'Welcome to the Quick Reports Tool');
-define ('QR_LOGIN_PAGE_WELCOME_TEXT', 'Welcome to the Quick Reports Tool.');
+define ('QR_HOME_PAGE_WELCOME_TEXT', 'Welcome to the PINES Quick Reports Tool');
+define ('QR_LOGIN_PAGE_WELCOME_TEXT', 'Welcome to the PINES Quick Reports Tool.');
define ('QR_PAGE_FOOTER_TEXT', '');
+//executive reports
+define ('QR_EXECUTIVE_REPORTS_ENABLED', true);
+define ('QR_EXECUTIVE_REPORTS_START_YEAR', '2016');
+define ('QR_EXECUTIVE_REPORTS_ADDITIONAL_ALLOWED_PERMISSIONS', '141,143');
+define ('QR_EXECUTIVE_REPORTS_DESCRIPTION_URL', '');
+define ('QR_EXECUTIVE_REPORTS_TITLE_TAG_TEXT', 'PINES Executive Reports');
+define ('QR_EXECUTIVE_REPORTS_OUTPUT_HEADER_TITLE', 'PINES Executive Reports');
+define ('QR_EXECUTIVE_REPORTS_CONSORTIUM_COLUMN_HEADING', 'PINES');
+define ('QR_EXECUTIVE_REPORTS_ZERO_VALUE', '---');
+define ('QR_EXECUTIVE_REPORTS_TOTAL_KEY', '__total__');
+define ('QR_EXECUTIVE_REPORTS_SUBREPORT_PADDING', ' ');
+define ('QR_EXECUTIVE_REPORTS_MISSING_SUBREPORT_LABEL', '*unknown');
+
//Sessions
define ('QR_SESSION_TIMEOUT', 120); //minutes
--- /dev/null
+<?php
+if (isset($_SERVER['SERVER_NAME']) && ($_SERVER['SERVER_NAME']=='localhost' || $_SERVER['SERVER_NAME']=='dev'))
+ include 'config/dev.config.php';
+else
+ include 'config/production.config.php';
+include 'config/app.config.php';
+include 'models/db.class.php';
+include 'models/executiveReport.class.php';
+include 'views/executiveReportGenerator.view.php';
+include 'models/security.class.php';
+include 'views/displayMessage.view.php';
+
+class executiveReportGenerator {
+
+ public function __construct() {
+
+ if (QR_PGSQL_USE_OPENSRF_XML_CONFIG || (QR_SESSIONS_IN_MEMCACHE && QR_MEMCACHE_USE_OPENSRF_XML_CONFIG)) {
+ include 'models/openilsConfig.class.php';
+ new openilsConfig(); //parse openils xml config file
+ }
+
+ $security = new security();
+ $security->sanitizeServerQueryString();
+
+ $report = new executiveReport();
+ $executiveReportsList = $report->getExecutiveReportsList();
+ $maxReportCount = count($executiveReportsList);
+
+ //url format will be ?[format]/ouID/year/month/reportID/reportID/...
+ //strip leading / if present, add trailing / if missing, and use explode to generate an array of strings
+ if (substr($_SERVER['QUERY_STRING'], 0, 1) == '/') $_SERVER['QUERY_STRING']=substr($_SERVER['QUERY_STRING'], 1);
+ if (substr($_SERVER['QUERY_STRING'],strlen($_SERVER['QUERY_STRING'])-1,1) != '/') $_SERVER['QUERY_STRING'] .= '/';
+ $qsParamsArray = explode('/', $_SERVER['QUERY_STRING']);
+
+ if ($qsParamsArray[0] == 'excel') { //download excel
+ $qsOffset = 1;
+ $outputFormat = 'excel';
+ unset($qsParamsArray[0]);
+ }
+ else {
+ $qsOffset = 0;
+ $outputFormat = 'html';
+ }
+
+ $reportView = new executiveReportsView($outputFormat);
+
+ if (count($qsParamsArray) < (4)) {
+ $reportView->displayReportHeader();
+ new displayMessageView('Invalid parameters.');
+ exit;
+ }
+
+ $buffer = '';
+ $numReports = 0;
+ $system = NULL;
+ $consortium = NULL;
+
+ $rowData = new stdClass();
+ $rowData->system = NULL;
+ $rowData->consortium = NULL;
+
+ $reportData = new stdClass();
+ $reportData->thisMonth = NULL;
+ $reportData->lastMonth = NULL;
+ $reportData->lastYear = NULL;
+ $reportData->reportYear = $qsParamsArray[1 + $qsOffset];
+ $reportData->reportMonth = $qsParamsArray[2 + $qsOffset];
+ $reportData->reportMonthStr = ($reportData->reportMonth < 10) ? '0'.$reportData->reportMonth : (string)$reportData->reportMonth;
+
+ $orgID = $qsParamsArray[0 + $qsOffset];
+ if (!$security->validateInteger($orgID)) {
+ $reportView->displayReportOutput();
+ new displayMessageView('Invalid branch or system specified.');
+ exit;
+ }
+
+ unset($qsParamsArray[0 + $qsOffset]);
+ unset($qsParamsArray[1 + $qsOffset]);
+ unset($qsParamsArray[2 + $qsOffset]);
+
+ $invalidDate = false;
+ if (!$security->validateInteger($reportData->reportYear) || !$security->validateInteger($reportData->reportMonth)) {
+ $invalidDate = true;
+ }
+ else {
+ switch ($reportData->reportMonth) {
+ case '1': $reportData->monthName='January'; $reportPriorMonthStr='12'; break;
+ case '2': $reportData->monthName='February'; $reportPriorMonthStr='01'; break;
+ case '3': $reportData->monthName='March'; $reportPriorMonthStr='02'; break;
+ case '4': $reportData->monthName='April'; $reportPriorMonthStr='03'; break;
+ case '5': $reportData->monthName='May'; $reportPriorMonthStr='04'; break;
+ case '6': $reportData->monthName='June'; $reportPriorMonthStr='05'; break;
+ case '7': $reportData->monthName='July'; $reportPriorMonthStr='06'; break;
+ case '8': $reportData->monthName='August'; $reportPriorMonthStr='07'; break;
+ case '9': $reportData->monthName='September'; $reportPriorMonthStr='08'; break;
+ case '10': $reportData->monthName='October'; $reportPriorMonthStr='09'; break;
+ case '11': $reportData->monthName='November'; $reportPriorMonthStr='10'; break;
+ case '12': $reportData->monthName='December'; $reportPriorMonthStr='11'; break;
+ default: $invalidDate = true; break;
+ }
+ }
+
+ if ($invalidDate) {
+ $reportView->displayReportHeader();
+ new displayMessageView('Invalid Report Date');
+ exit;
+ }
+
+ $ouInfo = $report->getOUInfo($orgID, QR_QUERY_RETURN_ONE_ROW, true);
+ if (NULL == $ouInfo) {
+ $reportView->displayReportHeader();
+ new displayMessageView('Invalid branch or system specified.');
+ exit;
+ }
+
+ $reportView->createReportSubHeader($ouInfo, $reportData);
+
+ //get current month, prior month and prior year data for this branch
+ $yearMonthList = $reportData->reportYear.$reportData->reportMonthStr; //current month
+ $yearMonthList .= ','.(($reportData->reportMonth==1) ? ($reportData->reportYear-1) : $reportData->reportYear).$reportPriorMonthStr; //last month
+ $yearMonthList .= ','.($reportData->reportYear-1).$reportData->reportMonthStr; //last year
+ $data = $report->getExecutiveReportData($ouInfo->id, $yearMonthList);
+
+ //Determine which row of data represents which month and which org type - branch, system, consortium
+ //Process only the most current rows of data. Records must be returned with "order by org_unit, year_month, desc, create_time desc"
+ $alreadyProcessed = array();
+ foreach ($data as $row) {
+ if (isset($alreadyProcessed[$row->org_unit.$row->year_month])) continue;
+
+ $alreadyProcessed[$row->org_unit.$row->year_month] = true;
+ if ($row->year_month == $yearMonthList) {
+ if ($row->org_unit == $ouInfo->id)
+ $reportData->thisMonth = $row;
+ elseif ($row->org_unit == $ouInfo->parent_ou && $ouInfo->ou_type == 3)
+ $system = $row;
+ else
+ $consortium = $row;
+ }
+ elseif ($row->org_unit == $ouInfo->id && $row->year_month == ($reportData->reportYear-1).$reportData->reportMonthStr)
+ $reportData->lastYear = $row;
+ elseif ($row->org_unit == $ouInfo->id && $row->year_month == (($reportData->reportMonth==1) ? ($reportData->reportYear-1) : $reportData->reportYear).$reportPriorMonthStr)
+ $reportData->lastMonth = $row;
+ }
+
+ if (NULL == $reportData->thisMonth) {
+ $reportView->displayReportOutput();
+ new displayMessageView("No data available for $reportData->monthName, $reportData->reportYear");
+ exit;
+ }
+
+ //if no reports are specified default is process all reports
+ if (isset($qsParamsArray[3 + $qsOffset]) && NULL == $qsParamsArray[3 + $qsOffset]) {
+ unset($qsParamsArray[3 + $qsOffset]);
+ foreach ($executiveReportsList as $reportListObj) $qsParamsArray[] = $reportListObj->id;
+ }
+
+ //process each selected report - one report is one row of output
+ $reportView->createColumnHeader($ouInfo);
+
+ foreach ($qsParamsArray as $reportID ) {
+
+ if (NULL == $reportID) continue; //skip trailing slash in querystring
+
+ if ($numReports++ > $maxReportCount) {
+ $reportView->displayReportOutput();
+ new displayMessageView('Too many parameters.');
+ exit;
+ }
+
+ //validate report exists
+ $reportInfo = NULL;
+ $reportID = strtolower($reportID); //accept querystring parameters in lower or upper case - (e.g.) /p1/ or /P1/
+ foreach ($executiveReportsList as $er) {
+ if ($reportID == strtolower($er->id)) $reportInfo = $er;
+ }
+ if (NULL == $reportInfo) continue; //invalid querystring parameter, skip reports that are not defined
+
+ $rowData->format = isset($reportInfo->format) ? $reportInfo->format : NULL;
+ $reportInfo->ou_type = $ouInfo->ou_type;
+
+ switch ($reportInfo->ou_type) {
+ case 1: $reportInfo->numColumns=6; break;
+ case 2: $reportInfo->numColumns=7; break;
+ default: $reportInfo->numColumns=8; break;
+ }
+
+ //data may be numeric or an array of json objects for reports that have subreports (group by in sql)
+ $dataSystem = (!isset($system->$reportID)) ? NULL : json_decode($system->$reportID, false);
+ $dataConsortium = (!isset($consortium->$reportID)) ? NULL : json_decode($consortium->$reportID, false);
+ $dataThisMonth = (!isset($reportData->thisMonth->$reportID)) ? NULL : json_decode($reportData->thisMonth->$reportID, false);
+ $dataLastMonth = (!isset($reportData->lastMonth->$reportID)) ? NULL : json_decode($reportData->lastMonth->$reportID, false);
+ $dataLastYear = (!isset($reportData->lastYear->$reportID)) ? NULL :json_decode($reportData->lastYear->$reportID, false);
+
+ if (is_array($dataThisMonth) || is_array($dataLastMonth)) { //one of the months is an array of json objects and contains subreports
+ $dataThisMonthArray=array();
+ $dataLastMonthArray=array();
+ $dataLastYearArray=array();
+ $dataSystemArray=array();
+ $dataConsortiumArray=array();
+
+
+ //convert [{"key":"total","value":number},{"key":subreport,"value":numeric},...] to a simple array of key/value pairs and calculate totals
+ $dataThisMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]=0;
+ $dataLastMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]=0;
+ $dataLastYearArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]=0;
+ $dataSystemArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]=0;
+ $dataConsortiumArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]=0;
+
+ if (NULL != $dataThisMonth) foreach ($dataThisMonth as $d) {$dataThisMonthArray[$d->key]=$d->value; $dataThisMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]+=$d->value;}
+ if (NULL != $dataLastMonth) foreach ($dataLastMonth as $d) {$dataLastMonthArray[$d->key]=$d->value; $dataLastMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]+=$d->value;}
+ if (NULL != $dataLastYear) foreach ($dataLastYear as $d) {$dataLastYearArray[$d->key]=$d->value; $dataLastYearArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]+=$d->value;}
+ if (NULL != $dataSystem) foreach ($dataSystem as $d) {$dataSystemArray[$d->key]=$d->value; $dataSystemArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]+=$d->value;}
+ if (NULL != $dataConsortium) foreach ($dataConsortium as $d) {$dataConsortiumArray[$d->key]=$d->value; $dataConsortiumArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]+=$d->value;}
+
+ //first display the total row
+ $rowData->thisMonth = (!isset($dataThisMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY])) ? NULL : $dataThisMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY];
+ $rowData->lastMonth = (!isset($dataLastMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY])) ? NULL : $dataLastMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY];
+ $rowData->lastYear = (!isset($dataLastYearArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY])) ? NULL : $dataLastYearArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY];
+ $rowData->system = (!isset($dataSystemArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY])) ? NULL : $dataSystemArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY];
+ $rowData->consortium = (!isset($dataConsortiumArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY])) ? NULL : $dataConsortiumArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY];
+
+ $reportView->createReportRow($reportInfo, $rowData);
+
+ unset($dataThisMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]);
+ unset($dataLastMonthArray[QR_EXECUTIVE_REPORTS_TOTAL_KEY]);
+
+ //merge and sort subreport data for the current and the prior months - a key/value pair could be missing from one of the months
+ $dataCombined = array_merge($dataThisMonthArray, $dataLastMonthArray);
+ uksort($dataCombined, "strcasecmp"); //case insensitive sort
+
+ //display each of the rows of data (subreports) that sum to the total
+ foreach ($dataCombined as $key => $value) {
+ $reportInfo->description = QR_EXECUTIVE_REPORTS_SUBREPORT_PADDING.$key;
+ $rowData->thisMonth = (!isset($dataThisMonthArray[$key])) ? NULL : $dataThisMonthArray[$key];
+ $rowData->lastMonth = (!isset($dataLastMonthArray[$key])) ? NULL : $dataLastMonthArray[$key];
+ $rowData->lastYear = (!isset($dataLastYearArray[$key])) ? NULL : $dataLastYearArray[$key];
+ $rowData->system = (!isset($dataSystemArray[$key])) ? NULL : $dataSystemArray[$key];
+ $rowData->consortium = (!isset($dataConsortiumArray[$key])) ? NULL : $dataConsortiumArray[$key];
+ $reportView->createReportRow($reportInfo, $rowData);
+ }
+ }
+ else { //data is a numeric value, not json
+ $rowData->thisMonth = $dataThisMonth;
+ $rowData->lastMonth = $dataLastMonth;
+ $rowData->lastYear = $dataLastYear;
+ $rowData->system = $dataSystem;
+ $rowData->consortium = $dataConsortium;
+ $reportView->createReportRow($reportInfo, $rowData);
+ }
+ }
+
+ $reportView->displayReportOutput($outputFormat);
+ }
+
+}
+?>
--- /dev/null
+<?php
+
+//This class allows the user to select reports to view
+class executiveReportsMenuController {
+
+ protected $security;
+
+ public function __construct($params=NULL) {
+
+ $this->security = new security();
+
+ switch ($params['action']) {
+ case NULL: $this->executiveReportsMenu(); break;
+ case 'reports': $this->createReportListLinks(); break;
+ case 'report': $this->createReport(); break;
+ }
+ }
+
+
+ protected function executiveReportsMenu() {
+ include_once 'models/db.class.php';
+ include 'models/report.class.php';
+ include 'models/executiveReport.class.php';
+ include 'views/baseReport.view.php';
+ include 'views/executiveReportsMenu.view.php';
+
+ $reportObj = new report();
+ $orgList = $reportObj->getListDataFromTable((object) array('dataType' => 'org_unit'));
+
+ $executiveReportObj = new executiveReport();
+ $executiveReportsList = $executiveReportObj->getExecutiveReportsList();
+
+ $executiveReports = new executiveReportsView();
+ $executiveReports->showExecutiveReportsMenu($orgList, $executiveReportsList);
+ }
+
+
+ protected function createReportListLinks() {
+
+ $params = new stdClass();
+ $invalidDate = false;
+
+ if (!isset($_POST['OUList']) || count($_POST['OUList']) == 0) {
+ $error = new displayMessageView('No locations were specified');
+ exit;
+ }
+ $orgList = $_POST['OUList'];
+
+ $params->reportYear = $_POST['reportYear'];
+ $params->reportMonth = $_POST['reportMonth'];
+ if (!$this->security->validateInteger($params->reportYear) ||
+ !$this->security->validateInteger($params->reportMonth) ||
+ $params->reportMonth<1 || $params->reportMonth>12 || $params->reportYear>date('Y')
+ ) $invalidDate = true;
+
+ if ($invalidDate) {
+ new displayMessageView('Invalid Report Date.');
+ exit;
+ }
+
+ unset($_POST['OUList']);
+ unset($_POST['reportYear']);
+ unset($_POST['reportMonth']);
+ //unset($_POST['currentMonthRadio']);
+ //unset($_POST['executiveReportDate']);
+
+ if (count($_POST) == 0) {
+ $error = new displayMessageView('No reports were specified');
+ exit;
+ }
+ $params->reportList = $_POST; //check boxes - save all remaining POST variables
+
+ include_once 'models/db.class.php';
+ include 'models/executiveReport.class.php';
+ include 'views/baseReport.view.php';
+ include 'views/executiveReportsMenu.view.php';
+
+ $reportObj = new executiveReport();
+ $params->orgList = $reportObj->getOUInfo(implode(',', $orgList), QR_QUERY_RETURN_ALL_ROWS);
+ $executiveReportsList = $reportObj->getExecutiveReportsList();
+
+ $executiveReports = new executiveReportsView();
+ $executiveReports->showReportListLinks($params, $executiveReportsList);
+ }
+
+}
+?>
+
--- /dev/null
+#executiveReport {
+ padding: 5px 0 0 10px;
+}
+#executiveReport table {
+ border-spacing: 0px;
+ border-collapse: separate;
+}
+#executiveReport td {
+ padding: 0px;
+ vertical-align: top;
+}
+#executiveReport input {
+ font-size: 1.0em;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+#executiveReport textarea {
+ font-size: 1.0em;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ width: 98%;
+ min-width: 500px;
+ height: 60px;
+}
+#executiveReport select {
+ font-size: 1.0em;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+.executiveReportMenu {
+ outline-style: solid;
+ outline-color: #15513d;
+ outline-width: 2px;
+ padding: 5px;
+}
+.executiveReportSubMenu {
+ outline-style: solid;
+ outline-color: #999;
+ outline-width: 1px;
+ padding: 0px;
+ width: 260px;
+ padding: 5px 0px 5px 5px;
+}
+.executiveReportSubMenu td {
+ font-size: 1.0em !important;
+}
+.executiveReportSubMenu input {
+ margin-top: 4px;
+ vertical-align: sub
+}
+.executiveReportTopMenu {
+ height: 155px;
+}
+.executiveReportSubMenuRow1 {
+ height: 130px;
+}
+.executiveReportSubMenuRow2 {
+ height: 170px;
+}
+#executiveReportDate {
+ width: 115px;
+ margin: 5px 0 0 25px;
+}
+.executiveReportTypeLink,
+#executiveReportTypeLink:link,
+#executiveReportTypeLink:visited,
+#executiveReportTypeLink:hover,
+#executiveReportDefinitionsLink:active {
+ color: #0066ff;
+ font-size: 9pt;
+ text-decoration: none
+}
+#executiveReportDefinitionsLink,
+#executiveReportDefinitionsLink:link,
+#executiveReportDefinitionsLink:visited,
+#executiveReportDefinitionsLink:hover,
+#executiveReportDefinitionsLink:active {
+ color: #00f;
+ text-decoration: none
+}
+.executiveReportCheckbox {}
+.width10 {
+ width: 10px;
+}
+.width20 {
+ width: 20px;
+}
+
--- /dev/null
+* {}
+html,
+body,
+td {
+ padding:0;
+ margin-left: 30px;
+ height: 100%;
+ background-color:#fff;
+ font-size:11pt;
+ font-family:Arial, Helvetica, Verdana, sans-serif;
+}
+
+#logo {
+ background: url(../images/PINESLogo.gif) no-repeat;
+ width:300px;
+ height:60px;
+ position:relative;
+}
+
+#subHeaderLeft {
+ min-width:300px;
+}
+
+.contentTable {
+ border-spacing:0px;
+ border-collapse:collapse;
+}
+
+.contentTable td {
+ border:1px solid #888;
+ padding:0 5px 0 5px;
+}
+
+.reportHeader {
+ font-weight:bold;
+ font-size:1.2em
+}
+
+.reportSubHeader {
+ font-weight:normal;
+}
+
+.rowLabel {
+ font-weight:bold;
+ vertical-align:top;
+ text-align:left;
+}
+
+.columnLabel {
+ font-weight:bold;
+ vertical-align:top;
+ text-align:center;
+}
+
+.errorText {
+ color:#f00;
+}
+
+.negativeValue {
+ color:#f00
+}
+
+.zeroValue {}
+
+.zeroValueBackground {
+ background-color:#ccc
+}
+
--- /dev/null
+<?php
+//This class generates a report output
+//There is no session / login security. Anyone can access a report from a shared URL.
+
+include 'controllers/executiveReportGenerator.controller.php';
+new executiveReportGenerator();
+?>
+
--- /dev/null
+var lastExpandedGroupName;
+var lastSelectAll = false;
+var lastSelectAllState = [];
+
+function toggleReportShowHide(className, labelName) {
+ var list = document.getElementsByClassName(className);
+ if (list.length>0) {
+ for (var i = 0; i < list.length; i++) {
+ if (reportFiltersState[className]) {
+ list[i].style.display="table-row";
+ }
+ else {
+ list[i].style.display="none";
+ }
+ }
+ }
+ reportFiltersState[className]=!reportFiltersState[className]; //toggle
+ if (reportFiltersState[className])
+ document.getElementById(labelName).innerHTML="+Show";
+ else
+ document.getElementById(labelName).innerHTML="-Hide";
+}
+
+function toggleRealRelativeDate(dateTypeElement, spanTagReal, spanTagRelative) {
+ if (dateTypeElement.value == "real") {
+ document.getElementById(spanTagReal).style.display = "";
+ document.getElementById(spanTagRelative).style.display = "none";
+ }
+ else {
+ document.getElementById(spanTagReal).style.display = "none";
+ document.getElementById(spanTagRelative).style.display = "";
+ }
+}
+
+function toggleCollapsibleSection(group) {
+ var rows;
+ var hide;
+ var spanPlusMinus = group + "_plus";
+ var rowName = group + "_row";
+
+ rows = document.getElementsByClassName(rowName);
+ if (!rows[0].className.match(/(?:^|\s)hideRow(?!\S)/) ) {
+ hide = true;
+ lastExpandedGroupName = undefined;
+ document.getElementById(spanPlusMinus).innerHTML = "+";
+ }
+ else {
+ hide = false;
+ if (typeof lastExpandedGroupName != 'undefined' && lastExpandedGroupName != group) toggleCollapsibleSection(lastExpandedGroupName);
+ lastExpandedGroupName = group;
+ document.getElementById(spanPlusMinus).innerHTML = "-";
+ }
+ for(var i=0; i<rows.length; i++) {
+ if (hide)
+ rows[i].className += " hideRow ";
+ else
+ rows[i].className = rows[i].className.replace("hideRow" , "");
+ }
+}
+
+function confirmDeleteReport(id, name, action, adminView, recurs, url) {
+ var message;
+ message = action + " the report "+name+"?";
+ if (recurs==1) message = message + "\r\nAll future recurrences will also be canceled.";
+ if (confirm(message)) {
+ url = url + "c/" + id + "/";
+ if (adminView) url = url + "a/";
+ window.location.href = url;
+ return true;
+ }
+ return false;
+}
+
+function showSelectChoices(list, span) {
+ var html='';
+ for (var i=0; i<list.length; i++) {
+ if (list[i].selected) html = html + list[i].label.trim() + " <br>";
+ }
+ document.getElementById(span).innerHTML=html;
+}
+
+function selectAllMultiselect(listName) {
+ var list = document.getElementById(listName);
+ for(var i=0; i<list.options.length; i++) {
+ list.options[i].selected = true;
+ }
+ showSelectChoices(list, listName+"_selected");
+}
+
+function toggleAllCheckboxes(className) {
+
+ if (className == "executiveReportCheckbox") {
+ toggleState = !lastSelectAll;
+ lastSelectAll = !lastSelectAll;
+
+ for (var key in lastSelectAllState) {
+ lastSelectAllState[key] = !lastSelectAllState[key];
+ }
+ }
+ else {
+ lastSelectAllState[className] = !lastSelectAllState[className];
+ toggleState = lastSelectAllState[className];
+ }
+
+ var list = document.getElementsByClassName(className);
+ for (var i=0; i<list.length; i++) {
+ list[i].checked = toggleState;
+ }
+
+ var newText = (toggleState) ? 'Clear All' : 'Select All';
+ if (className == "executiveReportCheckbox") document.getElementById("selectAllReportsLink").text = newText;
+
+ for (var key in lastSelectAllState) {
+ if (className == "executiveReportCheckbox" || className == key) {
+ document.getElementById(key+"SelectAllReportsLink").text = newText;
+ }
+ }
+}
+
+function submitExecutiveReport() {
+ var numChecked = 0;
+ var reportList = document.getElementsByClassName("executiveReportCheckbox");
+ for (var i=0; i<reportList.length; i++) {
+ if (reportList[i].checked) {
+ numChecked++;
+ break;
+ }
+ }
+ if (0 == numChecked) {
+ alert("Please select one or more reports.");
+ return false;
+ }
+ return true;
+}
+
+function setExecutiveReportDate(offset) {
+ var today=new Date();
+ var thisYear=today.getFullYear();
+ var thisMonth=today.getMonth();
+ var reportMonth;
+ var reportYear;
+ var reportYearIndex;
+
+ if (0 == offset) {
+ if (0 == thisMonth) {
+ reportMonth = 11;
+ reportYear = thisYear - 1;
+ }
+ else {
+ reportMonth = thisMonth - 1;
+ reportYearIndex = 0;
+ }
+ }
+ else {
+ reportMonth = document.getElementById("reportMonth").selectedIndex + offset;
+ reportYearIndex = document.getElementById("reportYear").selectedIndex;
+ if (reportMonth < 0 && reportYearIndex == document.getElementById("reportYear").length-1) return;
+ if (reportMonth > thisMonth-1 && reportYearIndex == 0) return;
+ if (reportMonth > 11) {
+ reportMonth = 0;
+ reportYearIndex -= 1;
+ }
+ else if (reportMonth < 0) {
+ reportMonth = 11;
+ reportYearIndex += 1;
+ }
+ }
+ document.getElementById("reportMonth").selectedIndex = reportMonth;
+ document.getElementById("reportYear").selectedIndex = reportYearIndex;
+}
+
+function submitReport(action) {
+
+ var userInputs;
+ var dateTypeName;
+ var colName;
+
+ if (document.getElementById("name").value.length==0) {
+ alert("Please enter a report name.");
+ return false;
+ }
+
+ if (action == 'save') {
+ return true;
+ }
+
+ userInputs = document.getElementsByClassName('userInput');
+ for (var i=0; i<userInputs.length; i++) {
+ if (userInputs[i].classList.contains('userText') && userInputs[i].value=="") {
+ if (userInputs[i].name.indexOf("_") != -1)
+ colName = columnNames[userInputs[i].name.substring(0,userInputs[i].name.indexOf("_"))];
+ else
+ colName = columnNames[userInputs[i].name];
+ alert("Please enter a value for " + colName);
+ userInputs[i].focus();
+ return false;
+ }
+ else if (userInputs[i].classList.contains('userInteger') && (userInputs[i].value=="" || !validateInteger(userInputs[i].value))) {
+ if (userInputs[i].name.indexOf("_") != -1)
+ colName = columnNames[userInputs[i].name.substring(0,userInputs[i].name.indexOf("_"))];
+ else
+ colName = columnNames[userInputs[i].name];
+ alert("Please enter an integer for " + colName);
+ userInputs[i].focus();
+ return false;
+ }
+ else if (userInputs[i].classList.contains('userDate')) {
+ dateTypeName = userInputs[i].name.replace("_date","_type");
+ if (document.getElementById(dateTypeName).value == 'real' && !validDate(userInputs[i].value) ) {
+ alert("You must specify a valid date for " + columnNames[userInputs[i].name.substring(0,userInputs[i].name.indexOf("_"))]);
+ userInputs[i].focus();
+ return false;
+ }
+ }
+ else if (userInputs[i].classList.contains('userSelect') && userInputs[i].selectedIndex==-1) {
+ alert("Please select a value for " + columnNames[userInputs[i].name.replace("[]","")]);
+ userInputs[i].focus();
+ return false;
+ }
+ }
+
+ if (!document.getElementById("intervalRadioOnce").checked && !document.getElementById("intervalRadioRecur").checked) {
+ alert("Please select the recurrence interval.");
+ return false;
+ }
+ if (document.getElementById("intervalRadioRecur").checked && (document.getElementById("interval").selectedIndex==0 || document.getElementById("intervalPeriod").selectedIndex==0)) {
+ alert("Please specify the recurrence frequency.");
+ return false;
+ }
+
+ if (!document.getElementById("runTimeRadioASAP").checked && !document.getElementById("runTimeRadioScheduled").checked) {
+ alert("Please select the run time.");
+ return false;
+ }
+ if (document.getElementById("runTimeRadioScheduled").checked) {
+ if (document.getElementById("runDate").value=="") {
+ alert("Please specify the scheduled run date.");
+ return false;
+ }
+ if (!validDate(runDate.value)) {
+ alert("Please specify a valid scheduled run date.");
+ return false;
+ }
+ }
+
+ if (!document.getElementById("excelOutput").checked && !document.getElementById("csvOutput").checked && !document.getElementById("htmlOutput").checked) {
+ alert("Please choose an output format.");
+ return false;
+ }
+
+ return true;
+}
+
+function setDaysLabel(elem, spanTag){
+ if (elem.value == -1)
+ document.getElementById(spanTag).innerHTML = "Day";
+ else
+ document.getElementById(spanTag).innerHTML = "Days";
+}
+
+function validateInteger(n) {
+ if (isNaN(parseFloat(n)) || !isFinite(n)) return false;
+ return true;
+}
+
+function emptyString(s) {
+ return (s=="");
+}
+
+function validDate(date) {
+ var matches = /^(\d{2})[-\/](\d{2})[-\/](\d{4})$/.exec(date);
+ if (matches == null) return false;
+ var d = matches[2];
+ var m = matches[1];
+ var y = matches[3];
+ if (!validateInteger(y) || !validateInteger(m) || !validateInteger(d)) return false;
+ if (m < 1 || m > 12) return false;
+ if (d < 1 || d > 31) return false;
+ if ((m == 4 || m == 6 || m == 9 || m == 11) && d > 30) return false;
+ if (m ==2) {
+ if ((y % 400) == 0 || ((y % 4) == 0 && (y % 100) != 0)) { //leap year
+ if (d > 29) return false;
+ }
+ else { //not leap year
+ if (d > 28) return false;
+ }
+ }
+ return true;
+}
+
+var win1=null;
+function openWindow(html) {
+ if (win1 != null && win1.open) win1.close();
+ win1=window.open('','win1','height=250,width=800,toolbar=no,location=no,menubar=no,titlebar=no,status=no,scrollbars=yes,resizable=yes,modal=yes');
+ win1.document.write("<pre>"+html+"</pre>");
+}
+
--- /dev/null
+<?php
+class executiveReport extends db
+{
+
+ public function __construct() {
+ parent::__construct();
+ }
+
+ public function getExecutiveReportsList() {
+ //Define all of the executive reports
+
+ $report = array();
+ include 'config/executiveReports.config.php';
+ return $report;
+ }
+
+
+ function getOUInfo($OUList, $rowsReturnedType, $includeName=false) {
+
+ $name = ($includeName) ? 'name,' : '';
+ try {
+ //Put library system at the top
+ $query = "
+ select id, shortname, ou_type, parent_ou, $name case when ou_type=1 then 1 else 0 end as isSystem
+ from actor.org_unit where id in ($OUList) order by isSystem desc, shortname";
+ return $this->executeQuery($query, NULL, $rowsReturnedType);
+ }
+ catch (PDOException $e) {
+ $this->handleDatabaseErrors($e);
+ }
+ }
+
+
+ public function getExecutiveReportData($orgID, $yearMonthList) {
+ //get the data for the report output
+ //must order by org_unit,year_month desc, create_time desc
+ //use select * - allows reports to be added without modifying this query
+ try {
+ $query = '
+ select *
+ from '.QR_DB_SCHEMA.".executive_reports_data where year_month in ($yearMonthList)
+ and org_unit in (:orgID,(select parent_ou from actor.org_unit where id=:orgID),
+ (select id from actor.org_unit where ou_type=1))
+ order by org_unit,year_month desc, create_time desc";
+ $params = array('orgID'=>$orgID);
+ return $this->executeQuery($query, $params, QR_QUERY_RETURN_ALL_ROWS);
+ }
+ catch (PDOException $e) {
+ $this->handleDatabaseErrors($e);
+ }
+ }
+
+}
+?>
+
--- /dev/null
+<?php
+class executiveReportsView {
+
+ private $lastCategory;
+ private $reportHeader;
+ private $reportOutput;
+ private $outputFormat;
+ private $resourcesPath;
+ private $reportFirstRow;
+
+ public function __construct($outputFormat = NULL) {
+
+ //automatically display the header in case we abort because of an error
+ $this->lastCategory = NULL;
+ $this->reportFirstRow = true;
+ $this->outputFormat = $outputFormat;
+ $this->createReportHeader();
+ }
+
+
+ private function createReportHeader() {
+
+ $sitePath = $this->outputFormat=='excel' ? ($_SERVER['SERVER_PORT']==443 ? 'https://':'http://') . $_SERVER['SERVER_NAME'] . QR_SITE_ROOT : '';
+ $this->reportHeader = '
+ <!doctype html>
+ <html>
+ <head>
+ <meta charset="utf-8">
+ <title>'.QR_EXECUTIVE_REPORTS_TITLE_TAG_TEXT.'</title>
+
+ <link type="text/css" href="'.$sitePath.'css/executiveReport_v1.0.css" rel="stylesheet">
+
+ </head>
+ <body>
+
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td id="subHeaderLeft">
+ <table cellpadding="0" cellspacing="0" border="0" >
+ <tr><td class="reportHeader" colspan="2">'.QR_EXECUTIVE_REPORTS_OUTPUT_HEADER_TITLE.'</td></tr>
+ ';
+ return;
+ }
+
+
+ public function createReportSubHeader($ouInfo, $reportDate) {
+
+ $buffer = '<tr><td class="reportSubHeader">';
+ switch ($ouInfo->ou_type) {
+ case 1: $buffer .= 'Consortium: '; break;
+ case 2: $buffer .= 'System: '; break;
+ default: $buffer .= 'Branch: '; break;
+ }
+
+ //subHeader (report name, org unit, date) followed by column headings
+ $buffer .= '
+ </td><td class="reportSubHeader">'.$ouInfo->name.'</td></tr>
+ <tr><td class="reportSubHeader">Date:</td><td class="reportSubHeader">'.$reportDate->monthName.', '.$reportDate->reportYear.'</td></tr></table>
+ </td>
+ <td id="logo"></td>
+ </tr>
+ <tr><td colspan="2"> </td></tr>
+ <tr><td colspan="2">
+ <table class="contentTable">
+ <tr>';
+ $this->reportOutput .= $buffer;
+ }
+
+
+ public function createColumnHeader($ouInfo){
+
+ $buffer = '
+ <td class="columnLabel">Category</td>
+ <td class="columnLabel">Report</td>
+ <td class="columnLabel">Current<br>Month</td>
+ <td class="columnLabel">Previous<br>Month</td>
+ <td class="columnLabel">% Change<br>from<br>Previous<br>Month</td>
+ <td class="columnLabel">% Change<br>from<br>Previous<br>Year</td>';
+
+ //add columns for system and/or consortium
+ if ($ouInfo->ou_type == 3) $buffer .= '<td class="columnLabel">% of<br>System<br>Total</td>';
+ if ($ouInfo->ou_type >= 2) $buffer .= '<td class="columnLabel">% of<br>'.QR_EXECUTIVE_REPORTS_CONSORTIUM_COLUMN_HEADING.'<br>Total</td>';
+ $this->reportOutput .= $buffer;
+ }
+
+
+ public function displayReportHeader() {
+
+ if ($this->outputFormat == 'excel') {
+ header("Content-Disposition: attachment; filename=\"executive_report.xls\"");
+ header("Content-Type: application/vnd.ms-excel");
+ }
+ echo $this->reportHeader;
+ }
+
+
+ public function displayReportOutput($outputFormat = NULL) {
+
+ $this->displayReportHeader($outputFormat);
+ echo $this->reportOutput;
+ $verID='3fca9f8aa945f04e090b258b2fcf10e4';
+ echo "</table></table><!--$verID--><br></body></html>";
+ }
+
+
+ public function createReportRow($reportInfo, $rowData) {
+
+ //setup the data display variables
+ $buffer = NULL;
+ $thisMonth = $rowData->thisMonth;
+ $lastMonth = $rowData->lastMonth;
+ $yearlyChange = NULL;
+ $monthlyChange = NULL;
+ $percentSystem = NULL;
+ $percentConsortium = NULL;
+ $thisMonthBackgroundClass = NULL;
+ $lastMonthBackgroundClass = NULL;
+ $yearlyChangeBackgroundClass = NULL;
+ $monthlyChangeBackgroundClass = NULL;
+ $percentSystemBackgroundClass = NULL;
+ $percentConsortiumBackgroundClass = NULL;
+
+ if (0 == $rowData->thisMonth) $rowData->thisMonth = NULL;
+ if (0 == $rowData->lastMonth) $rowData->lastMonth = NULL;
+
+ if (NULL == $rowData->thisMonth) {
+ $thisMonth = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $thisMonthBackgroundClass= ' class="zeroValueBackground" ';
+
+ $yearlyChange = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $yearlyChangeBackgroundClass = ' class="zeroValueBackground" ';
+
+ $monthlyChange = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $monthlyChangeBackgroundClass = ' class="zeroValueBackground" ';
+
+ $rowData->system = NULL;
+ $percentSystem = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $percentSystemBackgroundClass = ' class="zeroValueBackground" ';
+
+ $rowData->consortium = NULL;
+ $percentConsortium = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $percentConsortiumBackgroundClass = ' class="zeroValueBackground" ';
+ }
+
+ if (NULL == $rowData->lastMonth) {
+ $lastMonth = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $lastMonthBackgroundClass= ' class="zeroValueBackground" ';
+ $monthlyChange = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $monthlyChangeBackgroundClass = ' class="zeroValueBackground" ';
+ }
+
+ if (NULL == $rowData->lastYear) {
+ $yearlyChange = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $yearlyChangeBackgroundClass= ' class="zeroValueBackground" ';
+ }
+
+ if (NULL == $monthlyChange) {
+ if ($rowData->thisMonth == $rowData->lastMonth) {
+ $monthlyChange = '0%';
+ }
+ else {
+ $monthlyChange = number_format(100 * ($rowData->thisMonth - $rowData->lastMonth) / $rowData->lastMonth) . '%';
+ if ($monthlyChange == '-0%') $monthlyChange = '0%';
+ if (substr($monthlyChange, 0, 1) == '-') $monthlyChange = "<span class=\"negativeValue\">$monthlyChange</span>";
+ }
+ }
+
+ if (NULL == $yearlyChange) {
+ if ($rowData->thisMonth == $rowData->lastYear) {
+ $yearlyChange = '0%';
+ }
+ else {
+ $yearlyChange = number_format(100 * ($rowData->thisMonth - $rowData->lastYear) / $rowData->lastYear) . '%';
+ if ($yearlyChange == '-0%') $yearlyChange = '0%';
+ if (substr($yearlyChange, 0, 1) == '-') $yearlyChange = "<span class=\"negativeValue\">$yearlyChange</span>";
+ }
+ }
+
+ //create a new row. Do not repeat the category in the first column.
+ //Blank row between categories. No blank row after the column headers.
+ $buffer .= '<tr><td class="rowLabel">';
+ if ($reportInfo->category != $this->lastCategory) {
+ if ($this->reportFirstRow)
+ $this->reportFirstRow = false;
+ else {
+ //new category so this row will become the blank row between categories
+ $buffer .= '</td>';
+ for ($i=1; $i<=$reportInfo->numColumns-1; $i++) $buffer .= '<td> </td>';
+ $buffer .= '<tr><td class="rowLabel">';
+ }
+ $buffer .= $reportInfo->category; //column 1
+ $this->lastCategory = $reportInfo->category;
+ }
+
+ //if format is set to currency display as currency, else default to integer
+ $numDecimals = (isset($rowData->format) && $rowData->format == 'currency') ? 2 : 0;
+ if (NUll != $rowData->thisMonth) $thisMonth = ($rowData->format == 'currency' ? '$' : '') . number_format($rowData->thisMonth, $numDecimals);
+ if (NUll != $rowData->lastMonth) $lastMonth = ($rowData->format == 'currency' ? '$' : '') . number_format($rowData->lastMonth, $numDecimals);
+
+ //display the remainig data columns
+ $buffer .= '</td><td>'.((QR_EXECUTIVE_REPORTS_SUBREPORT_PADDING == $reportInfo->description) ? QR_EXECUTIVE_REPORTS_SUBREPORT_PADDING.QR_EXECUTIVE_REPORTS_MISSING_SUBREPORT_LABEL : $reportInfo->description).'</td>';
+ $buffer .= "<td align=\"right\" $thisMonthBackgroundClass>".$thisMonth.'</td>';
+ $buffer .= "<td align=\"right\" $lastMonthBackgroundClass>".$lastMonth.'</td>';
+ $buffer .= "<td align=\"right\" $monthlyChangeBackgroundClass>$monthlyChange</td>";
+ $buffer .= "<td align=\"right\" $yearlyChangeBackgroundClass>$yearlyChange</td>";
+
+ //% of system column
+ if ($reportInfo->ou_type == 3) {
+ if (NULL == $percentSystem) {
+ if (NULL == $rowData->system || NULL == $rowData->thisMonth) {
+ $percentSystem = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $percentSystemBackgroundClass = ' class="zeroValueBackground" ';
+ }
+ elseif ($rowData->thisMonth == $rowData->system) {
+ $percentSystem = '100%';
+ }
+ else {
+ $percentSystem = number_format(100 * $rowData->thisMonth / $rowData->system) . '%';
+ if ($percentSystem == '-0%') $percentSystem = '0%';
+ if (substr($percentSystem, 0, 1) == '-') $percentSystem = "<span class=\"negativeValue\">$percentSystem</span>";
+ }
+ }
+ $buffer .= "<td align=\"right\" $percentSystemBackgroundClass>$percentSystem</td>";
+ }
+
+ // % of consortium column
+ if ($reportInfo->ou_type >= 2) {
+ if (NULL == $percentConsortium) {
+ if (NULL == $rowData->consortium) {
+ $percentConsortium = '<span class="zeroValue">'.QR_EXECUTIVE_REPORTS_ZERO_VALUE.'</span>';
+ $percentConsortiumBackgroundClass = ' class="zeroValueBackground" ';
+ }
+ elseif ($rowData->thisMonth == $rowData->consortium) {
+ $percentConsortium = '100%';
+ }
+ else {
+ $percentConsortium = number_format(100 * $rowData->thisMonth / $rowData->consortium) . '%';
+ if ($percentConsortium == '-0%') $percentConsortium = '0%';
+ if (substr($percentConsortium, 0, 1) == '-') $percentConsortium = "<span class=\"negativeValue\">$percentConsortium</span>";
+ }
+ }
+ $buffer .= "<td align=\"right\" $percentConsortiumBackgroundClass>$percentConsortium</td>";
+ }
+
+ $buffer .= '</tr>'; //complete the row
+ $this->reportOutput .= $buffer;
+ return;
+ }
+
+}
+?>
+
--- /dev/null
+<?php
+class executiveReportsView extends baseReportView {
+
+ public function __construct() {}
+
+
+ public function showReportListLinks($params, $executiveReportsList) {
+
+ $pluralSuffix = (count($params->orgList)>1) ? 's' : '';
+ echo "Please click on the links below to view your report$pluralSuffix <br>";
+
+ //truncate report list if all reports, else insert / as delimiter
+ $params->reportList = (count($params->reportList) == count($executiveReportsList)) ? '' : implode('/', array_keys($params->reportList));
+
+ foreach ($params->orgList as $orgListObj) {
+ echo '<br>';
+ if ($orgListObj->ou_type == 2)
+ echo '<br> ';
+ elseif ($orgListObj->ou_type == 3)
+ echo ' ';
+ echo $orgListObj->shortname,' ';
+ echo ' <a target="_blank" class="executiveReportTypeLink" href="'.QR_CREATE_EXECUTIVE_REPORT_PAGE.$orgListObj->id.'/'.$params->reportYear.'/'.$params->reportMonth.'/'.$params->reportList.'">HTML</a>';
+ echo ' <span class="executiveReportTypeLink">|</span>';
+ echo ' <a class="executiveReportTypeLink" href="'.QR_CREATE_EXECUTIVE_REPORT_PAGE.'excel/'.$orgListObj->id.'/'.$params->reportYear.'/'.$params->reportMonth.'/'.$params->reportList.'">Excel</a>';
+ }
+
+ echo '<br><br>';
+ }
+
+
+ public function showExecutiveReportsMenu($orgList, $executiveReportsList) {
+
+ ?>
+ <form name="reportForm" id="reportForm" method="post" action="<?php echo QR_LIST_EXECUTIVE_REPORTS_PAGE; ?>">
+ <table cellpadding="0" cellspacing="0" border="0" width="100%">
+ <tr>
+ <td><tr><td colspan="3" style="background-color:#15513d; color:#fff; font-weight:bold; font-size:11pt">Create Your Executive Snapshot Report:</td>
+ </tr>
+ <tr>
+ <td>
+
+ <div id="executiveReport">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td width="562">
+ <table class="executiveReportMenu executiveReportTopMenu" cellpadding="0" cellspacing="0" border="0" width="100%">
+ <tr>
+ <td class="width10"><b>1. </b></td>
+ <td><b>Choose Location(s)</b></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>
+ <?php echo $this->createOrgUnitSelect($orgList, 'OUList', false); ?>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td class="width20"></td>
+ <td>
+ <table class="executiveReportMenu executiveReportTopMenu" cellpadding="0" cellspacing="0" border="0" width="100%">
+ <tr>
+ <td class="width10"><b>2. </b></td>
+ <td><b>Choose Month / Year</b><br><br>
+
+ <img class="imageBottom" src="images/icon_16_left_green.png" onclick="javascript:setExecutiveReportDate(-1);">
+
+ <select name="reportMonth" id="reportMonth">
+ <option value="1">Jan</option>
+ <option value="2">Feb</option>
+ <option value="3">Mar</option>
+ <option value="4">Apr</option>
+ <option value="5">May</option>
+ <option value="6">June</option>
+ <option value="7">July</option>
+ <option value="8">Aug</option>
+ <option value="9">Sep</option>
+ <option value="10">Oct</option>
+ <option value="11">Nov</option>
+ <option value="12">Dec</option>
+ </select>
+
+ <select name="reportYear" id="reportYear" class="">
+ <?php
+ $lastReportYear = (date('n') != 1) ? date('Y') : date('Y')-1;
+ for ($i=$lastReportYear; $i>=QR_EXECUTIVE_REPORTS_START_YEAR; $i--) {
+ echo '<option value="'.$i.'">'.$i.'</option>';
+ }
+ ?>
+ </select>
+ <img class="imageBottom" src="images/icon_16_right_green.png" onclick="javascript:setExecutiveReportDate(1);">
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr style="height:10px"><td colspan="3"></td></tr>
+ <tr>
+ <td colspan="3">
+ <table class="executiveReportMenu" cellpadding="0" cellspacing="0" border="0" width="100%">
+ <tr>
+ <td class="width10"><b>3. </b></td>
+ <td><b>Choose Report Data</b> <a id="selectAllReportsLink" class="selectAllLink" href="javascript:void(0);" onclick="toggleAllCheckboxes('executiveReportCheckbox');">Select All</a></td>
+ <td class="width20"></td>
+ <td></td>
+ <td class="width20"></td>
+ <td colspan="2" align="right">
+ <?php if (NULL != QR_EXECUTIVE_REPORTS_DESCRIPTION_URL)
+ echo '<a id="executiveReportDefinitionsLink" target="_blank" href="', QR_EXECUTIVE_REPORTS_DESCRIPTION_URL, '">Report Data Definitions</a>'; ?>
+ </td>
+ </tr>
+ <tr style="height:10px"><td colspan="7"></td></tr>
+ <tr>
+ <td></td>
+ <td><table class="executiveReportSubMenu executiveReportSubMenuRow1" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td>
+
+ <?php
+ $newColumn = false;
+ $numColumns = 1;
+ $currentCategory = NULL;
+ $categoryList = array();
+
+ foreach ($executiveReportsList as $er) {
+
+ // strip special characters and spaces from category
+ $cleanCategory = preg_replace(array('/[^a-zA-Z0-9_.]/'), array(''), $er->category);
+
+ if (NULL == $currentCategory) { //first row, first column
+ echo '<b>',$er->category,'</b> <a id="',$cleanCategory,'SelectAllReportsLink" class="selectAllLink" href="javascript:void(0);" onclick="toggleAllCheckboxes(\'', $cleanCategory,'\');">Select All</a>';
+ echo '<br><input class="executiveReportCheckbox ', $cleanCategory, '" type="checkbox" name="', strtolower($er->id),'" id="', strtolower($er->id),'">', $er->name;
+ $categoryList[] = $cleanCategory;
+ }
+
+ if ($er->category == $currentCategory)
+ echo '<br><input class="executiveReportCheckbox ', $cleanCategory, '" type="checkbox" name="', strtolower($er->id),'" id="', strtolower($er->id),'">', $er->name;
+ else { //new category
+ if ($er->category != $currentCategory && NULL != $currentCategory) {
+ echo '</td></tr></table></td>';
+ $newColumn = true;
+ if (QR_EXECUTIVE_REPORTS_MENU_COLUMNS == $numColumns) {
+ $numColumns = 1;
+ echo '</tr><tr style="height:15px"><td colspan="7"></td></tr><tr>';
+ }
+ else
+ $numColumns++;
+ }
+
+ if ($newColumn) {
+ $newColumn = false;
+ echo '<td></td>';
+ echo '<td><table class="executiveReportSubMenu executiveReportSubMenuRow1" cellpadding="0" cellspacing="0" border="0">';
+ echo '<tr><td>';
+ echo '<b>',$er->category,'</b> <a id="',$cleanCategory,'SelectAllReportsLink" class="selectAllLink" href="javascript:void(0);" onclick="toggleAllCheckboxes(\'', $cleanCategory,'\');">Select All</a>';
+ echo '<br><input class="executiveReportCheckbox ', $cleanCategory, '" type="checkbox" name="', strtolower($er->id),'" id="', strtolower($er->id),'">', $er->name;
+ $categoryList[] = $cleanCategory;
+ }
+ }
+ $currentCategory = $er->category;
+ }
+ ?>
+ </td></tr>
+ </table>
+ </td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </table>
+ </td>
+ <td></td>
+ <td>
+
+ </td>
+ </tr>
+
+ <tr>
+ <td align="center" colspan="7">
+ <br>
+ <input id="runButton" type="submit" class="submitButton" value="Run Report">
+ </td>
+ </tr>
+
+ </table>
+ </div>
+
+ </td>
+ </tr>
+ </table>
+ </form>
+ <br>
+
+ <script type="text/javascript">
+ setExecutiveReportDate(0);
+ document.getElementById("reportForm").onsubmit = function(){
+ return submitExecutiveReport();
+ }
+
+ <?php
+ //set javascript select all toggle array values
+ foreach ($categoryList as $cl) {
+ echo '
+ lastSelectAllState["',$cl,'"] = false;';
+ }
+ ?>
+ </script>
+<?php
+ }
+
+}
+?>
+
<td> </td>
<td>
<a class="homePageLink" href="<?php echo QR_SITE_ROOT,QR_LIST_REPORTS_PAGE; ?>"><b>My Quick Reports</b></a><br>
- View reports you have already run, or that you have scheduled.
+ View reports you have already run or that you have scheduled.
</td>
</tr>
<tr>
<title><?php echo QR_DEFAULT_TITLE_TAG_TEXT; ?></title>
<link type="text/css" href="css/site_v1.6.css" rel="stylesheet">
- <script type="text/JavaScript" src="lib/site_v1.4.js"></script>
+ <?php if (QR_EXECUTIVE_REPORTS_ENABLED) echo '<link type="text/css" href="css/executiveReportMenu_v1.0.css" rel="stylesheet">'; ?>
+
+ <script type="text/JavaScript" src="lib/site_v1.5.js"></script>
</head>
<body>
<div id="page">
<div id="footer">
<br>
<?php
- echo '@ 2015-',date('Y');
- echo 'Georgia Public Library Service, a Unit of the University System of Georgia.<br>', QR_PAGE_FOOTER_TEXT;
+ echo '© 2015-' . date('Y');
+ echo ' Georgia Public Library Service, a Unit of the University System of Georgia.<br/>';
+ echo '1800 Century Place Suite 150, Atlanta, GA 30345-4304 | 404-235-7200', QR_PAGE_FOOTER_TEXT;
?>
<br><br>
</div>