Odyssey
miPayReport.prg
1 <?php
2 /**
3  * File: miPayReport.prg
4  * The purpose of this file is to upload iPay file to a directory so that Billing can pick up the counts like the domain_email_report.
5  */
6 
7  /*************************************************************
8  **** Common place for file includes and globals. *************
9  **************************************************************/
10 
11 $sharedLibrary = dirname(__FILE__) . "/../../shared/library";
12 $monLibrary = dirname(__FILE__) . "/../library";
13 require_once("$monLibrary/cu_top.i");
14 require_once("$sharedLibrary/commonJsFunctions.i");
15 require_once("$monLibrary/ck_hticket.i");
16 require_once("$sharedLibrary/reporting.i");
17 require_once("$sharedLibrary/cutrusted.i");
18 
19 if (!CheckPerm($link, $Hu, basename($_SERVER['SCRIPT_NAME']), $_SERVER['REMOTE_ADDR'])) {
20  header("Location: /hcuadm/hcu_noperm.prg");
21  exit;
22 }
23 
24 /**
25  * function GetResultsDir()
26  * Returns the directory to upload and view the CSV files from.
27  */
28 function GetResultsDir () {
29  return "/home/homecu/tmp/billing/";
30 }
31 
32 /**
33  * function GetXrcPrefix()
34  * Returns the base file name of the CSV file.
35  */
36 function GetXrcPrefix () {
37  return "ipayrpt";
38 }
39 
40 /**
41  * function GetMaxSize ()
42  * Returns the max size of the CSV file.
43  */
44 function GetMaxSize () {
45  return 10485760;
46 }
47 
48 /**
49  * function GetPageLabel ()
50  * Returns the label to put on the top of the page.
51  */
52 function GetPageLabel () {
53  return "iPay Report";
54 }
55 
56 /**
57  * function GetSelf ()
58  * Returns the PHP file name.
59  */
60 function GetSelf () {
61  return "miPayReport.prg";
62 }
63 
64 /**
65  * function GetUsualHeader ()
66  * This is what I expect for the header. It comes from Paul's file for March 2018. I am using it as a check to make sure that I get the right file.
67  */
68 function GetUsualHeader () {
69  return "Institution ID,FI Name,Subscribers Plus,Subscribers Plus Active,Subscribers Plus Inactive,Enrollments Plus,Total Transactions Plus,"
70  . "Total Electronic Transactions Plus,Total Check Transactions Plus,Subscribers Business,Subscribers Business Active,"
71  . "Subscribers Business Inactive,Enrollments Business,Total Transactions Business,Total Electronic Transactions Business,"
72  . "Total Check Transactions Business,Bus Invoice User,Bus Payroll User,Bus Bundle User,Invoice Count,Payroll Count,Billing Class,P2P Count,NSF Count,"
73  . "Stop Payment Count,Check Copies Count,Compliance Package Annual Fee,MFA Annual Fee,Bill Simple Invoice Only User,Bill Simple Invoice And Pmt User,"
74  . "Bill Simple Count CC,Bill Simple Count ACH,Bill Simple Count NOC RET";
75 }
76 
77 /**
78  * function GetFileErrors ()
79  * Returns file errors
80  */
81 function GetFileErrors () {
82  return array(
83  "1" => "1: The file you tried to upload is just too big. The allowable limit is 10MB.",
84  "2" => "2: The file you tried to upload is just too big. The allowable limit is 10MB.",
85  "3" => "3: The file was only partially uploaded",
86  "4" => "4: no file was uploaded");
87 }
88 
89 $string = array("filter" => FILTER_SANITIZE_STRING);
90 
91 $parameters = array();
92 HCU_ImportVars( $parameters, "", array("operation" => $string, "month" => $string));
93 extract($parameters);
94 
95 $operation = isset($operation) ? trim($operation) : "";
96 $month = isset($month) ? trim($month) : "";
97 
98 switch($operation) {
99  case "csv":
100  $returnArray = DownloadCSV($month);
101  break;
102  case "view": // Later
103  $returnArray = ViewReport();
104  break;
105  case "uploadFile":
106  $returnArray = UploadFile($dbh, $month);
107  break;
108  case "":
109  PrintPage(GetInitialData (), $homecuKendoVersion, $cloudfrontDomainName);
110  exit;
111  break;
112  default:
113  $returnArray = array("error" => "Operation is not recognized.");
114  break;
115 }
116 
117 header('Content-type: application/json');
118 print HCU_JsonEncode($returnArray);
119 exit; // At this point, all intentional things to do have been done. Do not continue.
120 
121 
122 /*************************************************************
123 **** Code for downloading CSV. *******************************
124 **************************************************************/
125 
126 /**
127  * function DownloadCSV ($month)
128  * This function downloads the CSV.
129  *
130  * @param $month -- the month to download the CSV for.
131  *
132  * @return if successful, prints out the CSV file. If not successful, returns the code and message of the error message.
133  */
134 function DownloadCSV ($month) {
135  try {
136  $uploadPath = GetResultsDir ();
137  $fileName = GetXrcPrefix ();
138 
139  if ($month == "") {
140  throw new exception("Please enter a month.", 8);
141  }
142 
143  $matches = array();
144  $pregMatch = preg_match('/(\d{4})_(\d{2})/', $month, $matches);
145 
146  // In theory, it doesn't really matter if the preg_match itself failed or it doesn't match the string.
147  if (!$pregMatch) {
148  throw new exception("Month is invalid.", 3);
149  }
150 
151  if ($matches[2] < 1 || $matches[2] > 12) { // Ensure that the month itself is within range.
152  throw new exception("Month is invalid.", 1);
153  }
154 
155  $fileName .= "_$month.csv"; // At this point, we know that the month string is valid so append it on the end of the filename.
156 
157  if (!is_writable($uploadPath)) {
158  throw new exception("CSV Directory is not set up correctly. Please contact HomeCU for assistance.", 2);
159  }
160 
161  $file = "${uploadPath}${fileName}";
162 
163  if (!file_exists($file)) {
164  throw new exception("File doesn't exist.", 4);
165  }
166 
167  header('Content-Description: File Transfer');
168  header('Content-Type: application/octet-stream');
169  header('Content-Disposition: attachment; filename="'.basename($file).'"');
170  header('Expires: 0');
171  header('Cache-Control: must-revalidate');
172  header('Pragma: public');
173  header('Content-Length: ' . filesize($file));
174  readfile($file);
175  exit;
176 
177  $returnArray = array("status" => "000", "error" => "");
178 
179  } catch (exception $e) {
180  $returnArray = array("status" => $e->getCode(), "error" => $e->getMessage());
181  }
182  return $returnArray;
183 }
184 
185 /*************************************************************
186 **** Code for viewing comparison report (later). *************
187 **************************************************************/
188 
189 function ViewReport () {
190 
191 }
192 
193 /*************************************************************
194 **** Code for uploading file. ********************************
195 **************************************************************/
196 
197 
198 /**
199  * function uploadFile($dbh, $month)
200  * This function uploads a file to the ipay report directory.
201  *
202  * @param $dbh -- the database connection
203  * @param $month -- the month to upload the file for
204  *
205  * @return array --
206  * $code -- zero if successful, non-zero otherwise.
207  * $error -- error message if not successful.
208  */
209 function UploadFile ($dbh, $month) {
210  try {
211  $fileErrors = GetFileErrors ();
212  $uploadPath = GetResultsDir ();
213  $maxSize = GetMaxSize ();
214  $fileName = GetXrcPrefix ();
215 
216  if ($month == "") {
217  throw new exception("Please enter a month.", 8);
218  }
219 
220  $matches = array();
221  $pregMatch = preg_match('/(\d{4})_(\d{2})/', $month, $matches);
222 
223  // In theory, it doesn't really matter if the preg_match itself failed or it doesn't match the string.
224  if (!$pregMatch) {
225  throw new exception("Month is invalid.", 3);
226  }
227 
228  if ($matches[2] < 1 || $matches[2] > 12) { // Ensure that the month itself is within range.
229  throw new exception("Month is invalid.", 1);
230  }
231 
232  $fileName .= "_$month.csv"; // At this point, we know that the month string is valid so append it on the end of the filename.
233 
234  if (!is_writable($uploadPath)) {
235  throw new exception("CSV Directory is not set up correctly. Please contact HomeCU for assistance.", 2);
236  }
237 
238  $file = $_FILES['files'];
239 
240  if ($file["size"] > $maxSize) {
241  throw new exception("File exceeds the max size.", 4);
242  }
243  if ($file["error"] != 0) {
244  $errorInt = $file["error"];
245  throw new exception(HCU_array_key_exists($errorInt, $fileErrors) ? $fileErrors[$errorInt] : "$errorInt: Unknown error.", 5);
246  }
247 
248  $filetmp = $file['tmp_name'];
249  if (!@move_uploaded_file($filetmp, "${uploadPath}${fileName}")) {
250  @unlink ($filetmp);
251  throw new exception("Couldn't post the file where it belongs. Better call HomeCU.", 7);
252  }
253 
254  @chmod("${uploadPath}${fileName}", 0644);
255 
256  // At this point, I need to open the CSV and add the Credit Union code for billing.
257  $convertFileReturn = ConvertFile($dbh, "${uploadPath}${fileName}");
258  if ($convertFileReturn["status"] !== "000") {
259  throw new exception($convertFileReturn["error"], 9);
260  }
261 
262  $returnArray = array("status" => "000", "error" => "");
263  } catch(exception $e) {
264  $returnArray = array("status" => $e->getCode(), "error" => $e->getMessage());
265  }
266  return $returnArray;
267 }
268 
269 /**
270  * function ConvertFile($dbh, $fileName)
271  * This will copy the file contents to a tmp file. Then it revise the data to fit billing needs.
272  *
273  * @param $dbh -- the database connection
274  * @param $fileName -- the fullpath of the file to convert
275  *
276  * @return an array with "code" and "error." If successful, code is zero and error doesn't exist. If not successful, code is nonzero and error does exist.
277  */
278 function ConvertFile($dbh, $fileName) {
279  try {
280  if (!@copy($fileName, "$fileName.tmp")) {
281  throw new exception("File could not be copied.", 1);
282  }
283 
284  $readFP = fopen("$fileName.tmp", "r");
285 
286  $header = null;
287  $headerCount = 0;
288  $csvLines = array();
289  // Get the header and check for columns.
290  while (($buffer = fgets($readFP)) !== false) {
291  if (!preg_match('/[^,\s]/', $buffer)) { // If there is an empty line, ignore it.
292  continue;
293  }
294 
295  if (strpos($buffer, "Reseller Report") !== false) {
296  continue;
297  }
298 
299  if (!isset($header)) {
300 
301  $header = str_getcsv($buffer);
302  $headerCount = count($header);
303  } else {
304  $buffer = str_getcsv($buffer);
305 
306  if (count($buffer) != $headerCount) {
307  throw new exception("File is invalid.", 3);
308  }
309 
310  $csvLines [trim($buffer[0])] = $buffer;
311  // Institution ID: need to get the credit union code by lookup in the bp_cuid attribute of the IPAY trust detail.
312  }
313  }
314 
315  fclose($readFP);
316 
317  $sql = "select user_name, name from cuinfo";
318  $sth = db_query($sql, $dbh);
319  if (!$sth) {
320  throw new exception("orgname query failed.", 4);
321  }
322  $cuResults = db_fetch_all($sth);
323  $cuResults = $cuResults === false ? array() : $cuResults;
324 
325  $results = GetCuLookup($dbh);
326  if ($results["status"] !== "000") {
327  throw new exception ("Cu Lookup failed.", 5);
328  }
329  $cuMap = $results["cuMap"];
330  $institutionMap = array();
331 
332  foreach ($cuResults as $cuResult) {
333  $cu = trim(strtoupper($cuResult["user_name"]));
334  if (HCU_array_key_exists($cu, $cuMap) && $cuMap[$cu] != "") {
335  $institutionMap[$cuMap[$cu]] = array("cu" => $cu, "orgname" => $cuResult["name"]);
336  }
337  }
338 
339  $header [0] = "CU Code";
340  $header [1] = "CU Name";
341 
342  $writeFP = fopen($fileName, "w");
343  fputcsv ($writeFP, $header);
344 
345  foreach ($csvLines as $institutionId => $line) {
346  if (HCU_array_key_exists($institutionId, $institutionMap)) {
347  $correction = $institutionMap[$institutionId];
348  $line [0] = $correction ["cu"];
349  $line [1] = $correction ["orgname"];
350  } else {
351  $line [0] = "E";
352  $line [1] = "Error: Need Lookup for $institutionId"; // Follow same style for error in lookup for the domain_email_report.
353  }
354 
355  fputcsv ($writeFP, $line);
356  }
357 
358  fclose($writeFP);
359 
360  // Cleanup: remove the tmp file.
361  @unlink("$fileName.tmp");
362 
363  $returnArray = array("status" => "000", "error" => "");
364  } catch (exception $e) {
365  $returnArray = array("status" => $e->getCode(), "error" => $e->getMessage());
366  }
367  return $returnArray;
368 }
369 
370 function GetCuLookup($dbh) {
371  try {
372  // Get all the iPay trusted details encrypted from the servers.
373  $parameters = array("report" => "ipayLookup", "showServer" => "Y", "showDuplicates" => "Y", "limit" => "-1", "offset" => "0");
374 
375  $mammothList = array("www3", "www5", "www6");
376  $dataList = array();
377  foreach($mammothList as $server) {
378  $cmd = "https://${server}.homecu.net/hcuadm/adm_reports?operation=readReport";
379  $results = HCU_JsonDecode(RunCurl($parameters, $cmd, false));
380  if (count($results) == 0) {
381  throw new exception ("$server has no results.", 1);
382  }
383  if (count($results["error"]) > 0) {
384  throw new exception ("$server threw: " . $results["error"][0], 2);
385  }
386  $dataList[$server] = $results["reportData"]["data"];
387  }
388 
389  $sql = "select cu, trustedid, parms from cutrusteddetail where substr(lower(trim(trustedid)), 1, 4) = 'ipay'";
390  $sth = db_query($sql, $dbh);
391  if (!$sth) {
392  throw new exception ("Select query failed.", 3);
393  }
394  $results = db_fetch_all($sth);
395  $results = $results === false ? array() : $results;
396 
397  $dataList["my"] = $results;
398 
399  // Then go through the results and decrypt. Then separate the values of bp_cuid by credit union and server.
400  $cuMap = array();
401  foreach ($dataList as $server => $serverData) {
402  foreach($serverData as $record) {
403  $cu = trim($record["cu"]);
404  $masterKey = sha1("${cu}:3pk4osso");
405 
406  try {
407  $decrypted = parmdecrypt($record["parms"], $masterKey);
408  } catch (exception $e) {
409  global $logger;
410  $logger->error("iPay Report failed encryption for $cu.");
411  continue;
412  }
413 
414  $detailArray = HCU_JsonDecode(parmdecrypt($record["parms"], $masterKey));
415 
416  if (isset($detailArray) && HCU_array_key_exists("bp_cuid", $detailArray)) {
417  if (!HCU_array_key_exists($cu, $cuMap)) {
418  $cuMap[$cu] = array();
419  }
420  $cuMap[$cu][$server] = trim($detailArray["bp_cuid"]);
421  }
422 
423  // This is a new key for IPAY_V3
424  if (isset($detailArray) && HCU_array_key_exists("ipay_instid", $detailArray)) {
425  if (!HCU_array_key_exists($cu, $cuMap)) {
426  $cuMap[$cu] = array();
427  }
428  $cuMap[$cu][$server] = trim($detailArray["ipay_instid"]);
429  }
430  }
431  }
432 
433  foreach ($cuMap as $cu => $cuRecord) {
434  if (HCU_array_key_exists("my", $cuRecord)) {
435  $cuMap[$cu] = $cuRecord["my"];
436  } else if (HCU_array_key_exists("www3", $cuRecord)) {
437  $cuMap[$cu] = $cuRecord["www3"];
438  } else if (HCU_array_key_exists("www6", $cuRecord)) {
439  $cuMap[$cu] = $cuRecord["www6"];
440  } else if (HCU_array_key_exists("www5", $cuRecord)) {
441  $cuMap[$cu] = $cuRecord["www5"];
442  } else {
443  $cuMap[$cu] = 0;
444  }
445  }
446 
447  $returnArray = array("status" => "000", "error" => "", "cuMap" => $cuMap);
448 
449  } catch (exception $e) {
450  $returnArray = array("status" => $e->getCode(), "error" => $e->getMessage());
451  }
452  return $returnArray;
453 }
454 
455 /**
456  * function GetInitialData ()
457  * This function goes through the Ipay report directory. It returns the file size and month from the file.
458  *
459  * @return array(month => fileSize)
460  */
461 function GetInitialData () {
462  try {
463  $uploadPath = GetResultsDir ();
464  $filePrefix = GetXrcPrefix ();
465  $filePrefixLength = strlen($filePrefix);
466 
467  if (!is_writable($uploadPath)) {
468  if (!mkdir($uploadPath)) {
469  throw new exception("CSV Directory is not set up correctly. Please contact HomeCU for assistance.", 2);
470  }
471  }
472 
473  $fileList = scandir ($uploadPath);
474 
475  $monthMap = array();
476  foreach ($fileList as $file) {
477  if (strncmp($file, $filePrefix, $filePrefixLength) == 0) {
478  $month = str_replace(".csv", "", str_replace("${filePrefix}_", "", $file));
479  $fileSize = floatval(@filesize("${uploadPath}${file}"));
480 
481  if ($fileSize < 1024) {
482  $fileSize = "$fileSize B";
483  } else if ($fileSize < 1024*1024) {
484  $fileSize = ($fileSize / 1024.0) . " KB";
485  } else if ($fileSize < 1024*1024*1024) {
486  $fileSize = ($fileSize / (1024.0*1024)) . " MB";
487  } else {
488  $fileSize = ($fileSize / (1024.0*1024*1024)) . " GB";
489  }
490  $monthMap [$month] = $fileSize;
491  }
492  }
493 
494  $returnArray = array("status" => "000", "error" => "", "data" => $monthMap);
495  } catch (exception $e) {
496  $returnArray = array("status" => $e->getCode(), "error" => $e->getMessage());
497  }
498  return $returnArray;
499 }
500 
501 /**
502  * function PrintPage ($initialData, $homecuKendoVersion, $cloudfrontDomainName)
503  * This function prints out the visual part of this script.
504  *
505  * @param $initialData -- Contains the data for what months already have a file uploaded and the filesizes of those files.
506  * @param $homecuKendoVersion -- Global to get the right kendo css and javascript.
507  * @param $cloudfrontDomainName -- Global to get the right cloudfront domain name.
508  */
509 function PrintPage ($initialData, $homecuKendoVersion, $cloudfrontDomainName) {
510  $pageLabel = GetPageLabel ();
511  $self = GetSelf ();
512  $maxSize = GetMaxSize ();
513 
514  printMonitorPageTop ($pageLabel, $homecuKendoVersion, $cloudfrontDomainName);
515  printMonitorPageMiddle ($pageLabel);
516 
517  /*************************************************************
518  **** Javascript code. ****************************************
519  **************************************************************/ ?>
520 
521  <script type="text/javascript">
522  <?php // INCLUDE COMMON JAVASCRIPT FUNCTIONS
523  getShowWaitFunctions (); ?>
524 
525  <?php
526  /**
527  * function OpenAuthFailedDialog(response)
528  * This opens a dialog if the uploader fails.
529  *
530  * @param response -- the response from the uploader.
531  */
532  ?>
533  function OpenAuthFailedDialog(response) {
534  var authFailedDialog = $("#authFailedDialog").data("kendoWindow");
535  if (authFailedDialog != null) {
536  authFailedDialog.destroy();
537  $("#authFailedDialog").empty();
538  }
539 
540  authFailedDialog = $("#authFailedDialog").kendoWindow({
541  content: {template: response.replace(/[#]/g, "\\#")}, <?php // have to escape the # for kendo. ?>
542  draggable: false,
543  visible: false,
544  actions: [],
545  modal: true,
546  title: false,
547  width: 400,
548  resizable: false
549  }).data("kendoWindow");
550 
551  authFailedDialog.open().center();
552  }
553 
554  <?php
555  /**
556  * function Init()
557  * Initializes all the kendo controls and jQuery click events on the page.
558  */
559  ?>
560  function Init() {
561 
562  $.homecuValidator.setup({formValidate:'uploadForm', formStatusField: 'statusDiv'});
563 
564  var initialData = <?php echo HCU_JsonEncode($initialData); ?>;
565  if (initialData.status !== "000") {
566  $.homecuValidator.displayMessage(initialData.error, $.homecuValidator.settings.statusError );
567  }
568 
569  <?php
570  /**
571  * @var uploader -- this is the kendo uploader widget responsible for uploading files.
572  */
573  ?>
574  var uploader = $("#uploader").kendoUpload({
575  async: {
576  saveUrl: "<?php echo $self; ?>?operation=uploadFile",
577  withCredentials: true,
578  autoUpload: false
579  },
580  multiple: false,
581  showFileList: true,
582  error: function(e) {
583  hideWaitWindow();
584  var response = e.XMLHttpRequest.responseText;
585 
586  if (response.indexOf("PDFUploadFirstErrorLi") != -1) {
587  $.homecuValidator.displayMessage(response, $.homecuValidator.settings.statusError );
588  } else {
589  openAuthFailedDialog(response);
590  }
591  $(".k-upload-files").remove();
592  },
593  success: function(e) {
594  hideWaitWindow();
595  if (e.response.status === "000") {
596  $.homecuValidator.validate();
597  $("#fileExists").hide();
598  $("#monthDatePicker").data("kendoDatePicker").value(null);
599  } else {
600  $.homecuValidator.displayMessage(e.response.error, $.homecuValidator.settings.statusError );
601  e.preventDefault();
602  return false;
603  }
604 
605  },
606  select: function(e) { <?php // When a file is selected. If we can prevent at this level, then the user doesn't have to click on the upload to know that the file is invalid. ?>
607  var error = [];
608  var file = e.files[0];
609  file.extension.toLowerCase() != ".csv" ? error.push ("File needs to be a CSV.") : null;
610  file.size > <?php echo $maxSize; ?> ? error.push ("File exceeds the max size.") : null;
611 
612  if (error.length > 0) {
613  $.homecuValidator.displayMessage(error, $.homecuValidator.settings.statusError );
614  e.preventDefault();
615  return false;
616  }
617  },
618  upload: function(e) {
619  var month = $("#monthDatePicker").data("kendoDatePicker").value();
620  var month = month == null ? "" : kendo.toString(month, "yyyy_MM");
621  e.data = {month: month};
622  showWaitWindow();
623  },
624  localization: {
625  select: "Select File"
626  }
627  }).data("kendoUpload");
628 
629  var monthDatePicker = $("#monthDatePicker").kendoDatePicker({
630  depth: "year",
631  start: "year",
632  format: "MMM yyyy",
633  parseFormats: ["yyyy_MM"],
634  change: function() {
635  var month = this.value();
636  month = kendo.toString(month, "yyyy_MM");
637  if (initialData.data[month] != null) {
638  $("#fileExists .size").text(initialData.data[month]);
639  $("#fileExists").show();
640  } else {
641  $("#fileExists").hide();
642  }
643  }
644  }).data("kendoDatePicker");
645 
646  $("#uploadBtn").click(function() {
647 
648  var error = [];
649 
650  var month = $("#monthDatePicker").data("kendoDatePicker").value();
651  month == null ? error.push ("Please select a month.") : null;
652  $("#uploadForm .k-upload-files .k-file:visible").length == 0 ? error.push ("Please select a file.") : null;
653 
654  error.length > 0 ? $.homecuValidator.displayMessage(error, $.homecuValidator.settings.statusError ) : $("#uploadForm .k-button.k-upload-selected").click();
655  });
656  }
657 
658  $(document).ready(function() {
659  Init();
660  });
661 
662  </script>
663 
664  <?php /*******************************************************
665  **** Page-specific CSS. **************************************
666  **************************************************************/ ?>
667 
668  <style>
669  #uploadForm {
670  max-width: 600px;
671  }
672 
673  .grid_12 {
674  margin-top: 5px;
675  }
676 
677  .hcuAll100 {
678  width: 100%;
679  }
680 
681  #uploadForm .k-clear-selected, #uploadForm .k-upload-selected, #uploadForm .k-upload-status {
682  display: none;
683  }
684  </style>
685 
686  <?php /*******************************************************
687  **** Kendo templates. ****************************************
688  **************************************************************/ ?>
689 
690  <script id="popupTemplateDetail" type="text/x-kendo-template">
691 
692  </script>
693 
694  <?php // Mammoth doesn't have bootstrap files but use grid_360. Will need to be updated to Bootstrap when migrated to Odyssey. ?>
695  <div class="container_12">
696  <div class="grid_12" id="statusDiv"></div>
697 
698  <?php /*******************************************************
699  **** GUI for uploading CSV. *********************************
700  *************************************************************/ ?>
701 
702  <div id="uploadForm">
703  <div class="grid_12"><input type="file" name="files" id="uploader" accept=".csv" /></div>
704  <div class="grid_12">
705  <div class="grid_3 alpha">
706  Month to Upload:
707  </div>
708  <div class="grid_4">
709  <input id="monthDatePicker">
710  </div>
711  <div class="grid_5 omega">
712  <h6 id="fileExists" style="display:none">File exists with a size of <span class="size"></span>.</h6>
713  </div>
714  </div>
715  <div class="grid_12">
716  <a class="k-button k-primary" id="uploadBtn">Upload File</a>
717  </div>
718  </div>
719 
720  <?php /*******************************************************
721  **** GUI for comparison report (later). *********************
722  *************************************************************/ ?>
723 
724  </div>
725 
726  <?php printMonitorPageBottom(); ?>
727 <?php }
728 
729