minor fixes
[openemr.git] / interface / reports / ippf_statistics.php
blob47f8875ca4d02a95a3e657e01eab0426fc1dd778
1 <?php
2 // This module creates statistical reports related to family planning
3 // and sexual and reproductive health.
5 include_once("../globals.php");
6 include_once("../../library/patient.inc");
7 include_once("../../library/acl.inc");
9 // Might want something different here.
11 if (! acl_check('acct', 'rep')) die("Unauthorized access.");
13 $report_type = empty($_GET['t']) ? 'i' : $_GET['t'];
15 $from_date = fixDate($_POST['form_from_date']);
16 $to_date = fixDate($_POST['form_to_date'], date('Y-m-d'));
17 $form_by = $_POST['form_by']; // this is a scalar
18 $form_show = $_POST['form_show']; // this is an array
19 $form_facility = isset($_POST['form_facility']) ? $_POST['form_facility'] : '';
20 $form_sexes = isset($_POST['form_sexes']) ? $_POST['form_sexes'] : '3';
21 $form_cors = isset($_POST['form_cors']) ? $_POST['form_cors'] : '1';
22 $form_output = isset($_POST['form_output']) ? 0 + $_POST['form_output'] : 1;
24 if (empty($form_by)) $form_by = '1';
25 if (empty($form_show)) $form_show = array('1');
27 // One of these is chosen as the left column, or Y-axis, of the report.
29 if ($report_type == 'm') {
30 $report_title = xl('Member Association Statistics Report');
31 $arr_by = array(
32 101 => xl('MA Category'),
33 102 => xl('Specific Service'),
34 17 => xl('Patient'),
35 9 => xl('Internal Referrals'),
36 10 => xl('External Referrals'),
37 103 => xl('Referral Source'),
38 2 => xl('Total'),
40 $arr_content = array(
41 1 => xl('Services'),
42 2 => xl('Unique Clients'),
43 4 => xl('Unique New Clients')
45 $arr_report = array(
46 // Items are content|row|column|column|...
47 '2|2|3|4|5|8|11' => xl('Client Profile - Unique Clients'),
48 '4|2|3|4|5|8|11' => xl('Client Profile - New Clients'),
51 else if ($report_type == 'g') {
52 $report_title = xl('GCAC Statistics Report');
53 $arr_by = array(
54 13 => xl('Abortion-Related Categories'),
55 1 => xl('Total SRH & Family Planning'),
56 12 => xl('Pre-Abortion Counseling'),
57 5 => xl('Abortion Method'), // includes surgical and drug-induced
58 8 => xl('Post-Abortion Followup'),
59 7 => xl('Post-Abortion Contraception'),
60 11 => xl('Complications of Abortion'),
62 $arr_content = array(
63 1 => xl('Services'),
64 2 => xl('Unique Clients'),
65 4 => xl('Unique New Clients'),
67 $arr_report = array(
68 '1|11|13' => xl('Complications by Service Provider'),
71 else {
72 $report_title = xl('IPPF Statistics Report');
73 $arr_by = array(
74 3 => xl('General Service Category'),
75 4 => xl('Specific Service'),
76 6 => xl('Contraceptive Method'),
77 9 => xl('Internal Referrals'),
78 10 => xl('External Referrals'),
80 $arr_content = array(
81 1 => xl('Services'),
82 3 => xl('New Acceptors'),
84 $arr_report = array(
88 if ($report_type == 'm') {
90 else {
93 // This will become the array of reportable values.
94 $areport = array();
96 // This accumulates the bottom line totals.
97 $atotals = array();
99 $arr_show = array(
100 '.total' => array('title' => 'Total'),
101 '.age' => array('title' => 'Age Category'),
102 ); // info about selectable columns
104 $arr_titles = array(); // will contain column headers
106 // Query layout_options table to generate the $arr_show table.
107 // Table key is the field ID.
108 $lres = sqlStatement("SELECT field_id, title, data_type, list_id, description " .
109 "FROM layout_options WHERE " .
110 "form_id = 'DEM' AND uor > 0 AND field_id NOT LIKE 'em%' " .
111 "ORDER BY group_name, seq, title");
112 while ($lrow = sqlFetchArray($lres)) {
113 $fid = $lrow['field_id'];
114 if ($fid == 'fname' || $fid == 'mname' || $fid == 'lname') continue;
115 $arr_show[$fid] = $lrow;
116 $arr_titles[$fid] = array();
119 // Compute age in years given a DOB and "as of" date.
121 function getAge($dob, $asof='') {
122 if (empty($asof)) $asof = date('Y-m-d');
123 $a1 = explode('-', substr($dob , 0, 10));
124 $a2 = explode('-', substr($asof, 0, 10));
125 $age = $a2[0] - $a1[0];
126 if ($a2[1] < $a1[1] || ($a2[1] == $a1[1] && $a2[2] < $a1[2])) --$age;
127 // echo "<!-- $dob $asof $age -->\n"; // debugging
128 return $age;
131 $cellcount = 0;
133 function genStartRow($att) {
134 global $cellcount, $form_output;
135 if ($form_output != 3) echo " <tr $att>\n";
136 $cellcount = 0;
139 function genEndRow() {
140 global $form_output;
141 if ($form_output == 3) {
142 echo "\n";
144 else {
145 echo " </tr>\n";
149 /*********************************************************************
150 function genAnyCell($data, $right=false, $class='') {
151 global $cellcount;
152 if ($_POST['form_csvexport']) {
153 if ($cellcount) echo ',';
154 echo '"' . $data . '"';
156 else {
157 echo " <td";
158 if ($class) echo " class='$class'";
159 if ($right) echo " align='right'";
160 echo ">$data</td>\n";
162 ++$cellcount;
164 *********************************************************************/
166 function getListTitle($list, $option) {
167 $row = sqlQuery("SELECT title FROM list_options WHERE " .
168 "list_id = '$list' AND option_id = '$option'");
169 if (empty($row['title'])) return $option;
170 return $row['title'];
173 // Usually this generates one cell, but allows for two or more.
175 function genAnyCell($data, $right=false, $class='') {
176 global $cellcount, $form_output;
177 if (!is_array($data)) {
178 $data = array(0 => $data);
180 foreach ($data as $datum) {
181 if ($form_output == 3) {
182 if ($cellcount) echo ',';
183 echo '"' . $datum . '"';
185 else {
186 echo " <td";
187 if ($class) echo " class='$class'";
188 if ($right) echo " align='right'";
189 echo ">$datum</td>\n";
191 ++$cellcount;
195 function genHeadCell($data, $right=false) {
196 genAnyCell($data, $right, 'dehead');
199 // Create an HTML table cell containing a numeric value, and track totals.
201 function genNumCell($num, $cnum) {
202 global $atotals, $form_output;
203 $atotals[$cnum] += $num;
204 if (empty($num) && $form_output != 3) $num = '&nbsp;';
205 genAnyCell($num, true, 'detail');
208 // Translate an IPPF code to the corresponding descriptive name of its
209 // contraceptive method, or to an empty string if none applies.
211 function getContraceptiveMethod($code) {
212 $key = '';
213 if (preg_match('/^111101/', $code)) {
214 $key = xl('Pills');
216 else if (preg_match('/^11111[1-9]/', $code)) {
217 $key = xl('Injectables');
219 else if (preg_match('/^11112[1-9]/', $code)) {
220 $key = xl('Implants');
222 else if (preg_match('/^111132/', $code)) {
223 $key = xl('Patch');
225 else if (preg_match('/^111133/', $code)) {
226 $key = xl('Vaginal Ring');
228 else if (preg_match('/^112141/', $code)) {
229 $key = xl('Male Condoms');
231 else if (preg_match('/^112142/', $code)) {
232 $key = xl('Female Condoms');
234 else if (preg_match('/^11215[1-9]/', $code)) {
235 $key = xl('Diaphragms/Caps');
237 else if (preg_match('/^11216[1-9]/', $code)) {
238 $key = xl('Spermicides');
240 else if (preg_match('/^11317[1-9]/', $code)) {
241 $key = xl('IUD');
243 else if (preg_match('/^145212/', $code)) {
244 $key = xl('Emergency Contraception');
246 else if (preg_match('/^121181.13/', $code)) {
247 $key = xl('Female VSC');
249 else if (preg_match('/^122182.13/', $code)) {
250 $key = xl('Male VSC');
252 else if (preg_match('/^131191.10/', $code)) {
253 $key = xl('Awareness-Based');
255 return $key;
258 // Translate an IPPF code to the corresponding descriptive name of its
259 // abortion method, or to an empty string if none applies.
261 function getAbortionMethod($code) {
262 $key = '';
263 if (preg_match('/^25222[34]/', $code)) {
264 if (preg_match('/^2522231/', $code)) {
265 $key = xl('D&C');
267 else if (preg_match('/^2522232/', $code)) {
268 $key = xl('D&E');
270 else if (preg_match('/^2522233/', $code)) {
271 $key = xl('MVA');
273 else if (preg_match('/^252224/', $code)) {
274 $key = xl('Medical');
276 else {
277 $key = xl('Other Surgical');
280 return $key;
283 // Helper function to look up the GCAC issue associated with a visit.
284 // Ideally this is the one and only GCAC issue linked to the encounter.
285 // However if there are multiple such issues, or if only unlinked issues
286 // are found, then we pick the one with its start date closest to the
287 // encounter date.
289 function getGcacData($row, $what, $morejoins="") {
290 $patient_id = $row['pid'];
291 $encounter_id = $row['encounter'];
292 $encdate = substr($row['encdate'], 0, 10);
293 $query = "SELECT $what " .
294 "FROM lists AS l " .
295 "JOIN lists_ippf_gcac AS lg ON l.type = 'ippf_gcac' AND lg.id = l.id " .
296 "LEFT JOIN issue_encounter AS ie ON ie.pid = '$patient_id' AND " .
297 "ie.encounter = '$encounter_id' AND ie.list_id = l.id " .
298 "$morejoins " .
299 "WHERE l.pid = '$patient_id' AND " .
300 "l.activity = 1 AND l.type = 'ippf_gcac' " .
301 "ORDER BY ie.pid DESC, ABS(DATEDIFF(l.begdate, '$encdate')) ASC " .
302 "LIMIT 1";
303 // Note that reverse-ordering by ie.pid is a trick for sorting
304 // issues linked to the encounter (non-null values) first.
305 return sqlQuery($query);
308 // Get the "client status" field from the related GCAC issue.
310 function getGcacClientStatus($row) {
311 $irow = getGcacData($row, "lo.title", "LEFT JOIN list_options AS lo ON " .
312 "lo.list_id = 'clientstatus' AND lo.option_id = lg.client_status");
313 if (empty($irow['title'])) {
314 $key = xl('Indeterminate');
316 else {
317 // The client status description should be just fine for this.
318 $key = $irow['title'];
320 return $key;
323 // Helper function called after the reporting key is determined for a row.
325 function loadColumnData($key, $row) {
326 global $areport, $arr_titles, $form_cors, $from_date, $to_date, $arr_show;
328 // If first instance of this key, initialize its arrays.
329 if (empty($areport[$key])) {
330 $areport[$key] = array();
331 $areport[$key]['.prp'] = 0; // previous pid
332 $areport[$key]['.wom'] = 0; // number of services for women
333 $areport[$key]['.men'] = 0; // number of services for men
334 $areport[$key]['.age'] = array(0,0,0,0,0,0,0,0,0); // age array
335 foreach ($arr_show as $askey => $dummy) {
336 if (substr($askey, 0, 1) == '.') continue;
337 $areport[$key][$askey] = array();
341 // Skip this key if we are counting unique patients and the key
342 // has already seen this patient.
343 if ($form_cors == '2' && $row['pid'] == $areport[$key]['.prp']) return;
345 // If we are counting new acceptors, then require a unique patient
346 // whose contraceptive start date is within the reporting period.
347 if ($form_cors == '3') {
348 // if ($row['pid'] == $areport[$key]['prp']) return;
349 if ($row['pid'] == $areport[$key]['.prp']) return;
350 // Check contraceptive start date.
351 if (!$row['contrastart'] || $row['contrastart'] < $from_date ||
352 $row['contrastart'] > $to_date) return;
355 // If we are counting new clients, then require a unique patient
356 // whose registration date is within the reporting period.
357 if ($form_cors == '4') {
358 if ($row['pid'] == $areport[$key]['.prp']) return;
359 // Check registration date.
360 if (!$row['regdate'] || $row['regdate'] < $from_date ||
361 $row['regdate'] > $to_date) return;
364 // Flag this patient as having been encountered for this report row.
365 // $areport[$key]['prp'] = $row['pid'];
366 $areport[$key]['.prp'] = $row['pid'];
368 // Increment the correct sex category.
369 if (strcasecmp($row['sex'], 'Male') == 0)
370 ++$areport[$key]['.men'];
371 else
372 ++$areport[$key]['.wom'];
374 // Increment the correct age category.
375 $age = getAge(fixDate($row['DOB']), $row['encdate']);
376 $i = min(intval(($age - 5) / 5), 8);
377 if ($age < 11) $i = 0;
378 ++$areport[$key]['.age'][$i];
380 foreach ($arr_show as $askey => $dummy) {
381 if (substr($askey, 0, 1) == '.') continue;
382 $status = empty($row[$askey]) ? 'Unspecified' : $row[$askey];
383 $areport[$key][$askey][$status] += 1;
384 $arr_titles[$askey][$status] += 1;
388 // This is called for each IPPF service code that is selected.
390 function process_ippf_code($row, $code) {
391 global $areport, $arr_titles, $form_by;
393 $key = 'Unspecified';
395 // SRH including Family Planning
397 if ($form_by === '1') {
398 if (preg_match('/^1/', $code)) {
399 $key = xl('SRH - Family Planning');
401 else if (preg_match('/^2/', $code)) {
402 $key = xl('SRH Non Family Planning');
404 else {
405 return;
409 // General Service Category
411 else if ($form_by === '3') {
412 if (preg_match('/^1/', $code)) {
413 $key = xl('SRH - Family Planning');
415 else if (preg_match('/^2/', $code)) {
416 $key = xl('SRH Non Family Planning');
418 else if (preg_match('/^3/', $code)) {
419 $key = xl('Non-SRH Medical');
421 else if (preg_match('/^4/', $code)) {
422 $key = xl('Non-SRH Non-Medical');
424 else {
425 $key = xl('Invalid Service Codes');
429 // Abortion-Related Category
431 else if ($form_by === '13') {
432 if (preg_match('/^252221/', $code)) {
433 $key = xl('Pre-Abortion Counseling');
435 else if (preg_match('/^252222/', $code)) {
436 $key = xl('Pre-Abortion Consultation');
438 else if (preg_match('/^252223/', $code)) {
439 $key = xl('Induced Abortion');
441 else if (preg_match('/^252224/', $code)) {
442 $key = xl('Medical Abortion');
444 else if (preg_match('/^252225/', $code)) {
445 $key = xl('Incomplete Abortion Treatment');
447 else if (preg_match('/^252226/', $code)) {
448 $key = xl('Post-Abortion Care');
450 else if (preg_match('/^252227/', $code)) {
451 $key = xl('Post-Abortion Counseling');
453 else if (preg_match('/^25222/', $code)) {
454 $key = xl('Other/Generic Abortion-Related');
456 else {
457 return;
461 // Specific Services. One row for each IPPF code.
463 else if ($form_by === '4') {
464 $key = $code;
467 // Abortion Method.
469 else if ($form_by === '5') {
470 $key = getAbortionMethod($code);
471 if (empty($key)) return;
474 // Contraceptive Method.
476 else if ($form_by === '6') {
477 $key = getContraceptiveMethod($code);
478 if (empty($key)) return;
481 // Contraceptive method for new contraceptive adoption following abortion.
482 // Get it from the IPPF code if an abortion issue is linked to the visit.
483 // Note we are handling this during processing of services rather than
484 // by enumerating issues, because we need the service date.
486 else if ($form_by === '7') {
487 $key = getContraceptiveMethod($code);
488 if (empty($key)) return;
489 $patient_id = $row['pid'];
490 $encounter_id = $row['encounter'];
491 $query = "SELECT COUNT(*) AS count " .
492 "FROM lists AS l " .
493 "JOIN issue_encounter AS ie ON ie.pid = '$patient_id' AND " .
494 "ie.encounter = '$encounter_id' AND ie.list_id = l.id " .
495 "WHERE l.pid = '$patient_id' AND " .
496 "l.activity = 1 AND l.type = 'ippf_gcac'";
497 // echo "<!-- $key: $query -->\n"; // debugging
498 $irow = sqlQuery($query);
499 if (empty($irow['count'])) return;
502 // Post-Abortion Care and Followup by Source.
503 // Requirements just call for counting sessions, but this way the columns
504 // can be anything - age category, religion, whatever.
506 else if ($form_by === '8') {
507 if (preg_match('/^25222[67]/', $code)) { // all post-abortion care and followup
508 $key = getGcacClientStatus($row);
509 } else {
510 return;
514 // Complications from abortion by abortion method and complication type.
515 // These may be noted either during recovery or during a followup visit.
516 // Again, driven by services in order to report by service date.
517 // Note: If there are multiple complications, they will all be reported.
519 else if ($form_by === '11') {
520 $compl_type = '';
521 if (preg_match('/^25222[345]/', $code)) { // all abortions including incomplete
522 $compl_type = 'rec_compl';
524 else if (preg_match('/^25222[67]/', $code)) { // all post-abortion care and followup
525 $compl_type = 'fol_compl';
527 else {
528 return;
530 $irow = getGcacData($row, "lg.$compl_type, lo.title",
531 "LEFT JOIN list_options AS lo ON lo.list_id = 'in_ab_proc' AND " .
532 "lo.option_id = lg.in_ab_proc");
533 if (empty($irow)) return; // this should not happen
534 if (empty($irow[$compl_type])) return; // ok, no complications
535 // We have one or more complications.
536 $abtype = empty($irow['title']) ? xl('Indeterminate') : $irow['title'];
537 $acompl = explode('|', $irow[$compl_type]);
538 foreach ($acompl as $compl) {
539 $crow = sqlQuery("SELECT title FROM list_options WHERE " .
540 "list_id = 'complication' AND option_id = '$compl'");
541 $key = "$abtype / " . $crow['title'];
542 loadColumnData($key, $row);
544 return; // because loadColumnData() is already done.
547 // Pre-Abortion Counseling. Three possible situations:
548 // Provided abortion in the MA clinics
549 // Referred to other service providers (govt,private clinics)
550 // Decided not to have the abortion
552 else if ($form_by === '12') {
553 if (preg_match('/^252221/', $code)) { // all pre-abortion counseling
554 $key = getGcacClientStatus($row);
555 } else {
556 return;
560 // Patient Name.
562 else if ($form_by === '17') {
563 $key = $row['lname'] . ', ' . $row['fname'] . ' ' . $row['mname'];
566 else {
567 return;
570 // OK we now have the reporting key for this issue.
572 loadColumnData($key, $row);
575 // This is called for each MA service code that is selected.
577 function process_ma_code($row) {
578 global $form_by, $arr_content, $form_cors;
580 $key = 'Unspecified';
582 // One row for each service category.
584 if ($form_by === '101') {
585 if (!empty($row['lo_title'])) $key = xl($row['lo_title']);
588 // Specific Services. One row for each MA code.
590 else if ($form_by === '102') {
591 $key = $row['code'];
594 // One row for each referral source.
596 else if ($form_by === '103') {
597 $key = $row['referral_source'];
600 // Just one row.
602 else if ($form_by === '2') {
603 $key = $arr_content[$form_cors];
606 else {
607 return;
610 loadColumnData($key, $row);
613 /*********************************************************************
614 // This is called for each issue that is selected.
616 function process_issue($row) {
617 global $form_by;
619 $key = 'Unspecified';
621 // Pre-Abortion Counseling. Three possible rows:
622 // Provided abortion in the MA clinics
623 // Referred to other service providers (govt,private clinics)
624 // Decided not to have the abortion
626 if ($form_by === '12') {
628 // TBD: Assign one of the 3 keys, or just return.
632 // Others TBD
634 else {
635 return;
638 // TBD: Load column data from the issue.
639 // loadColumnData($key, $row);
641 *********************************************************************/
643 // This is called for each selected referral.
644 // Row keys are the first specified MA code, if any.
646 function process_referral($row) {
647 global $form_by;
648 $key = 'Unspecified';
650 if (!empty($row['refer_related_code'])) {
651 $relcodes = explode(';', $row['refer_related_code']);
652 foreach ($relcodes as $codestring) {
653 if ($codestring === '') continue;
654 list($codetype, $code) = explode(':', $codestring);
656 if ($codetype !== 'IPPF') continue;
658 if ($form_by === '1') {
659 if (preg_match('/^[12]/', $code)) {
660 $key = xl('SRH Referrals');
661 loadColumnData($key, $row);
664 else { // $form_by is 9 (internal) or 10 (external) referrals
665 $key = $code;
666 loadColumnData($key, $row);
667 break;
669 } // end foreach
674 // If we are doing the CSV export then generate the needed HTTP headers.
675 // Otherwise generate HTML.
677 if ($form_output == 3) {
678 header("Pragma: public");
679 header("Expires: 0");
680 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
681 header("Content-Type: application/force-download");
682 header("Content-Disposition: attachment; filename=service_statistics_report.csv");
683 header("Content-Description: File Transfer");
685 else {
687 <html>
688 <head>
689 <?php html_header_show(); ?>
690 <title><?php echo $report_title; ?></title>
691 <style type="text/css">@import url(../../library/dynarch_calendar.css);</style>
692 <style type="text/css">
693 body { font-family:sans-serif; font-size:10pt; font-weight:normal }
694 .dehead { color:#000000; font-family:sans-serif; font-size:10pt; font-weight:bold }
695 .detail { color:#000000; font-family:sans-serif; font-size:10pt; font-weight:normal }
696 </style>
697 <script type="text/javascript" src="../../library/textformat.js"></script>
698 <script type="text/javascript" src="../../library/dynarch_calendar.js"></script>
699 <script type="text/javascript" src="../../library/dynarch_calendar_en.js"></script>
700 <script type="text/javascript" src="../../library/dynarch_calendar_setup.js"></script>
701 <script language="JavaScript">
702 var mypcc = '<?php echo $GLOBALS['phone_country_code'] ?>';
704 // Begin experimental code
706 function selectByValue(sel, val) {
707 for (var i = 0; i < sel.options.length; ++i) {
708 if (sel.options[i].value == val) sel.options[i].selected = true;
712 function selreport() {
713 var f = document.forms[0];
714 var isdis = 'visible';
715 var s = f.form_report;
716 var v = (s.selectedIndex < 0) ? '' : s.options[s.selectedIndex].value;
717 if (v.length > 0) {
718 isdis = 'hidden';
719 var a = v.split("|");
720 f.form_cors.selectedIndex = -1;
721 f.form_by.selectedIndex = -1;
722 f['form_show[]'].selectedIndex = -1;
723 selectByValue(f.form_cors, a[0]);
724 selectByValue(f.form_by, a[1]);
725 for (var i = 2; i < a.length; ++i) {
726 selectByValue(f['form_show[]'], a[i]);
729 f.form_by.style.visibility = isdis;
730 f.form_cors.style.visibility = isdis;
731 f['form_show[]'].style.visibility = isdis;
734 // End experimental code
736 </script>
737 </head>
739 <body leftmargin='0' topmargin='0' marginwidth='0' marginheight='0'>
741 <center>
743 <h2><?php echo $report_title; ?></h2>
745 <form name='theform' method='post'
746 action='ippf_statistics.php?t=<?php echo $report_type ?>'>
748 <table border='0' cellspacing='5' cellpadding='1'>
750 <!-- Begin experimental code -->
751 <tr<?php if (empty($arr_report)) echo " style='display:none'"; ?>>
752 <td valign='top' class='dehead' nowrap>
753 <?php xl('Report','e'); ?>:
754 </td>
755 <td valign='top' class='detail' colspan='3'>
756 <select name='form_report' title='Predefined reports' onchange='selreport()'>
757 <?php
758 echo " <option value=''>" . xl('Custom') . "</option>\n";
759 foreach ($arr_report as $key => $value) {
760 echo " <option value='$key'";
761 if ($key == $form_report) echo " selected";
762 echo ">" . $value . "</option>\n";
765 </select>
766 </td>
767 <td valign='top' class='detail'>
768 &nbsp;
769 </td>
770 </tr>
771 <!-- End experimental code -->
773 <tr>
774 <td valign='top' class='dehead' nowrap>
775 <?php xl('Rows','e'); ?>:
776 </td>
777 <td valign='top' class='detail'>
778 <select name='form_by' title='Left column of report'>
779 <?php
780 foreach ($arr_by as $key => $value) {
781 echo " <option value='$key'";
782 if ($key == $form_by) echo " selected";
783 echo ">" . $value . "</option>\n";
786 </select>
787 </td>
788 <td valign='top' class='dehead' nowrap>
789 <?php xl('Content','e'); ?>:
790 </td>
791 <td valign='top' class='detail'>
792 <select name='form_cors' title='<?php xl('What is to be counted?','e'); ?>'>
793 <?php
794 foreach ($arr_content as $key => $value) {
795 echo " <option value='$key'";
796 if ($key == $form_cors) echo " selected";
797 echo ">$value</option>\n";
800 </select>
801 </td>
802 <td valign='top' class='detail'>
803 &nbsp;
804 </td>
805 </tr>
806 <tr>
807 <td valign='top' class='dehead' nowrap>
808 <?php xl('Columns','e'); ?>:
809 </td>
810 <td valign='top' class='detail'>
811 <select name='form_show[]' size='4' multiple
812 title='<?php xl('Hold down Ctrl to select multiple items','e'); ?>'>
813 <?php
814 foreach ($arr_show as $key => $value) {
815 $title = $value['title'];
816 if (empty($title) || $key == 'title') $title = $value['description'];
817 echo " <option value='$key'";
818 if (is_array($form_show) && in_array($key, $form_show)) echo " selected";
819 echo ">$title</option>\n";
822 </select>
823 </td>
824 <td valign='top' class='dehead' nowrap>
825 <?php xl('Filters','e'); ?>:
826 </td>
827 <td colspan='2' class='detail' style='border-style:solid;border-width:1px;border-color:#cccccc'>
828 <table>
829 <tr>
830 <td valign='top' class='detail' nowrap>
831 <?php xl('Sex','e'); ?>:
832 </td>
833 <td class='detail' valign='top'>
834 <select name='form_sexes' title='<?php xl('To filter by sex','e'); ?>'>
835 <?php
836 foreach (array(3 => xl('Men and Women'), 1 => xl('Women Only'), 2 => xl('Men Only')) as $key => $value) {
837 echo " <option value='$key'";
838 if ($key == $form_sexes) echo " selected";
839 echo ">$value</option>\n";
842 </select>
843 </td>
844 </tr>
845 <tr>
846 <td valign='top' class='detail' nowrap>
847 <?php xl('Facility','e'); ?>:
848 </td>
849 <td valign='top' class='detail'>
850 <?php
851 // Build a drop-down list of facilities.
853 $query = "SELECT id, name FROM facility ORDER BY name";
854 $fres = sqlStatement($query);
855 echo " <select name='form_facility'>\n";
856 echo " <option value=''>-- All Facilities --\n";
857 while ($frow = sqlFetchArray($fres)) {
858 $facid = $frow['id'];
859 echo " <option value='$facid'";
860 if ($facid == $_POST['form_facility']) echo " selected";
861 echo ">" . $frow['name'] . "\n";
863 echo " </select>\n";
865 </td>
866 </tr>
867 <tr>
868 <td colspan='2' class='detail' nowrap>
869 <?php xl('From','e'); ?>
870 <input type='text' name='form_from_date' id='form_from_date' size='10' value='<?php echo $from_date ?>'
871 onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)' title='Start date yyyy-mm-dd'>
872 <img src='../pic/show_calendar.gif' align='absbottom' width='24' height='22'
873 id='img_from_date' border='0' alt='[?]' style='cursor:pointer'
874 title='<?php xl('Click here to choose a date','e'); ?>'>
875 <?php xl('To','e'); ?>
876 <input type='text' name='form_to_date' id='form_to_date' size='10' value='<?php echo $to_date ?>'
877 onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)' title='End date yyyy-mm-dd'>
878 <img src='../pic/show_calendar.gif' align='absbottom' width='24' height='22'
879 id='img_to_date' border='0' alt='[?]' style='cursor:pointer'
880 title='<?php xl('Click here to choose a date','e'); ?>'>
881 </td>
882 </tr>
883 </table>
884 </td>
885 </tr>
886 <tr>
887 <td valign='top' class='dehead' nowrap>
888 <?php xl('To','e'); ?>:
889 </td>
890 <td colspan='3' valign='top' class='detail' nowrap>
891 <?php
892 foreach (array(1 => 'Screen', 2 => 'Printer', 3 => 'Export File') as $key => $value) {
893 echo " <input type='radio' name='form_output' value='$key'";
894 if ($key == $form_output) echo ' checked';
895 echo " />$value &nbsp;";
898 </td>
899 <td align='right' valign='top' class='detail' nowrap>
900 <input type='submit' name='form_submit' value='<?php xl('Submit','e'); ?>'
901 title='<?php xl('Click to generate the report','e'); ?>' />
902 </td>
903 </tr>
904 <tr>
905 <td colspan='5' height="1">
906 </td>
907 </tr>
908 </table>
909 <?php
910 } // end not export
912 if ($_POST['form_submit']) {
913 $pd_fields = '';
914 foreach ($arr_show as $askey => $asval) {
915 if (substr($askey, 0, 1) == '.') continue;
916 if ($askey == 'regdate' || $askey == 'sex' || $askey == 'DOB' ||
917 $askey == 'lname' || $askey == 'fname' || $askey == 'mname' ||
918 $askey == 'contrastart' || $askey == 'referral_source') continue;
919 $pd_fields .= ', pd.' . $askey;
922 $sexcond = '';
923 if ($form_sexes == '1') $sexcond = "AND pd.sex NOT LIKE 'Male' ";
924 else if ($form_sexes == '2') $sexcond = "AND pd.sex LIKE 'Male' ";
926 // Get referrals and related patient data.
927 if ($form_by === '9' || $form_by === '10' || $form_by === '1') {
928 $exttest = $form_by === '9' ? '=' : '!=';
929 $query = "SELECT " .
930 "t.refer_related_code, t.pid, pd.regdate, pd.referral_source, " .
931 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, " .
932 "pd.contrastart$pd_fields " .
933 "FROM transactions AS t " .
934 "JOIN patient_data AS pd ON pd.pid = t.pid $sexcond" .
935 "WHERE t.title = 'Referral' AND t.refer_date >= '$from_date' AND " .
936 "t.refer_date <= '$to_date' AND refer_external $exttest '0' " .
937 "ORDER BY t.pid, t.id";
938 $res = sqlStatement($query);
939 while ($row = sqlFetchArray($res)) {
940 process_referral($row);
943 /*****************************************************************
944 else if ($form_by === '12') {
945 // We are reporting on a date range, and assume the applicable date is
946 // the issue start date which is presumably also the date of pre-
947 // abortion counseling. The issue end date and the surgery date are
948 // not of interest here.
949 $query = "SELECT " .
950 "l.type, l.begdate, l.pid, " .
951 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, pd.userlist5, " .
952 "pd.country_code, pd.status, pd.state, pd.occupation, " .
953 "lg.client_status, lg.ab_location " .
954 "FROM lists AS l " .
955 "JOIN patient_data AS pd ON pd.pid = l.pid $sexcond" .
956 "LEFT OUTER JOIN lists_ippf_gcac AS lg ON l.type = 'ippf_gcac' AND lg.id = l.id " .
957 // "LEFT OUTER JOIN lists_ippf_con AS lc ON l.type = 'contraceptive' AND lc.id = l.id " .
958 "WHERE l.begdate >= '$from_date' AND l.begdate <= '$to_date' AND " .
959 "l.activity = 1 AND l.type = 'ippf_gcac' " .
960 "ORDER BY l.pid, l.id";
961 $res = sqlStatement($query);
962 while ($row = sqlFetchArray($res)) {
963 process_issue($row);
966 *****************************************************************/
968 // else {
969 if ($form_by !== '9' && $form_by !== '10') {
970 // This gets us all MA codes, with encounter and patient
971 // info attached and grouped by patient and encounter.
972 $query = "SELECT " .
973 "fe.pid, fe.encounter, fe.date AS encdate, pd.regdate, " .
974 "f.user AS provider, " .
975 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, " .
976 "pd.contrastart, pd.referral_source$pd_fields, " .
977 "b.code_type, b.code, c.related_code, lo.title AS lo_title " .
978 "FROM form_encounter AS fe " .
979 "JOIN forms AS f ON f.pid = fe.pid AND f.encounter = fe.encounter AND " .
980 "f.formdir = 'newpatient' AND f.form_id = fe.id AND f.deleted = 0 " .
981 "JOIN patient_data AS pd ON pd.pid = fe.pid $sexcond" .
982 "LEFT OUTER JOIN billing AS b ON " .
983 "b.pid = fe.pid AND b.encounter = fe.encounter AND b.activity = 1 " .
984 "AND b.code_type = 'MA' " .
985 "LEFT OUTER JOIN codes AS c ON b.code_type = 'MA' AND c.code_type = '12' AND " .
986 "c.code = b.code AND c.modifier = b.modifier " .
987 "LEFT OUTER JOIN list_options AS lo ON " .
988 "lo.list_id = 'superbill' AND lo.option_id = c.superbill " .
989 "WHERE fe.date >= '$from_date 00:00:00' AND " .
990 "fe.date <= '$to_date 23:59:59' ";
992 if ($form_facility) {
993 $query .= "AND fe.facility_id = '$form_facility' ";
995 $query .= "ORDER BY fe.pid, fe.encounter, b.code";
996 $res = sqlStatement($query);
997 while ($row = sqlFetchArray($res)) {
998 if ($row['code_type'] === 'MA') {
999 process_ma_code($row);
1000 if (!empty($row['related_code'])) {
1001 $relcodes = explode(';', $row['related_code']);
1002 foreach ($relcodes as $codestring) {
1003 if ($codestring === '') continue;
1004 list($codetype, $code) = explode(':', $codestring);
1005 if ($codetype !== 'IPPF') continue;
1006 process_ippf_code($row, $code);
1010 } // end while
1011 } // end else
1013 // Sort everything by key for reporting.
1014 ksort($areport);
1015 foreach ($arr_titles as $atkey => $dummy) ksort($arr_titles[$atkey]);
1017 if ($form_output != 3) {
1018 echo "<table border='0' cellpadding='1' cellspacing='2' width='98%'>\n";
1019 } // end not csv export
1021 genStartRow("bgcolor='#dddddd'");
1023 // If the key is an MA or IPPF code, then add a column for its description.
1024 if ($form_by === '4' || $form_by === '102' || $form_by === '9' || $form_by === '10') {
1025 genHeadCell(array($arr_by[$form_by], xl('Description')));
1026 } else {
1027 genHeadCell($arr_by[$form_by]);
1030 // Generate headings for values to be shown.
1031 foreach ($form_show as $value) {
1032 // if ($value == '1') { // Total Services
1033 if ($value == '.total') { // Total Services
1034 genHeadCell(xl('Total'));
1036 // else if ($value == '2') { // Age
1037 else if ($value == '.age') { // Age
1038 genHeadCell(xl('0-10' ), true);
1039 genHeadCell(xl('11-14'), true);
1040 genHeadCell(xl('15-19'), true);
1041 genHeadCell(xl('20-24'), true);
1042 genHeadCell(xl('25-29'), true);
1043 genHeadCell(xl('30-34'), true);
1044 genHeadCell(xl('35-39'), true);
1045 genHeadCell(xl('40-44'), true);
1046 genHeadCell(xl('45+' ), true);
1049 else if ($arr_show[$value]['list_id']) {
1050 foreach ($arr_titles[$value] as $key => $dummy) {
1051 genHeadCell(getListTitle($arr_show[$value]['list_id'],$key), true);
1054 else if (!empty($arr_titles[$value])) {
1055 foreach ($arr_titles[$value] as $key => $dummy) {
1056 genHeadCell($key, true);
1061 if ($form_output != 3) {
1062 genHeadCell(xl('Total'), true);
1065 genEndRow();
1067 $encount = 0;
1069 foreach ($areport as $key => $varr) {
1070 $bgcolor = (++$encount & 1) ? "#ddddff" : "#ffdddd";
1072 $dispkey = $key;
1074 // If the key is an MA or IPPF code, then add a column for its description.
1075 if ($form_by === '4' || $form_by === '102' || $form_by === '9' || $form_by === '10') {
1076 $dispkey = array($key, '');
1077 $type = $form_by === '102' ? 12 : 11; // MA or IPPF
1078 $crow = sqlQuery("SELECT code_text FROM codes WHERE " .
1079 "code_type = '$type' AND code = '$key' ORDER BY id LIMIT 1");
1080 if (!empty($crow['code_text'])) $dispkey[1] = $crow['code_text'];
1083 genStartRow("bgcolor='$bgcolor'");
1085 genAnyCell($dispkey, false, 'detail');
1087 // This is the column index for accumulating column totals.
1088 $cnum = 0;
1089 $totalsvcs = $areport[$key]['.wom'] + $areport[$key]['.men'];
1091 // Generate data for this row.
1092 foreach ($form_show as $value) {
1093 // if ($value == '1') { // Total Services
1094 if ($value == '.total') { // Total Services
1095 genNumCell($totalsvcs, $cnum++);
1097 else if ($value == '.age') { // Age
1098 for ($i = 0; $i < 9; ++$i) {
1099 genNumCell($areport[$key]['.age'][$i], $cnum++);
1102 else if (!empty($arr_titles[$value])) {
1103 foreach ($arr_titles[$value] as $title => $dummy) {
1104 genNumCell($areport[$key][$value][$title], $cnum++);
1109 // Write the Total column data.
1110 if ($form_output != 3) {
1111 $atotals[$cnum] += $totalsvcs;
1112 genAnyCell($totalsvcs, true, 'dehead');
1115 genEndRow();
1116 } // end foreach
1118 if ($form_output != 3) {
1119 // Generate the line of totals.
1120 genStartRow("bgcolor='#dddddd'");
1122 // If the key is an MA or IPPF code, then add a column for its description.
1123 if ($form_by === '4' || $form_by === '102' || $form_by === '9' || $form_by === '10') {
1124 genHeadCell(array(xl('Totals'), ''));
1125 } else {
1126 genHeadCell(xl('Totals'));
1129 for ($cnum = 0; $cnum < count($atotals); ++$cnum) {
1130 genHeadCell($atotals[$cnum], true);
1132 genEndRow();
1133 // End of table.
1134 echo "</table>\n";
1137 } // end of if refresh or export
1139 if ($form_output != 3) {
1141 </form>
1142 </center>
1144 <script language='JavaScript'>
1145 selreport();
1146 Calendar.setup({inputField:"form_from_date", ifFormat:"%Y-%m-%d", button:"img_from_date"});
1147 Calendar.setup({inputField:"form_to_date", ifFormat:"%Y-%m-%d", button:"img_to_date"});
1148 <?php if ($form_output == 2) { ?>
1149 window.print();
1150 <?php } ?>
1151 </script>
1153 </body>
1154 </html>
1155 <?php
1156 } // end not export