2 // Copyright (C) 2008-2009 Rod Roark <rod@sunsetsystems.com>
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 // This module creates statistical reports related to family planning
10 // and sexual and reproductive health.
12 include_once("../globals.php");
13 include_once("../../library/patient.inc");
14 include_once("../../library/acl.inc");
16 // Might want something different here.
18 if (! acl_check('acct', 'rep')) die("Unauthorized access.");
20 $report_type = empty($_GET['t']) ?
'i' : $_GET['t'];
22 $from_date = fixDate($_POST['form_from_date']);
23 $to_date = fixDate($_POST['form_to_date'], date('Y-m-d'));
24 $form_by = $_POST['form_by']; // this is a scalar
25 $form_show = $_POST['form_show']; // this is an array
26 $form_facility = isset($_POST['form_facility']) ?
$_POST['form_facility'] : '';
27 $form_sexes = isset($_POST['form_sexes']) ?
$_POST['form_sexes'] : '3';
28 $form_cors = isset($_POST['form_cors']) ?
$_POST['form_cors'] : '1';
29 $form_output = isset($_POST['form_output']) ?
0 +
$_POST['form_output'] : 1;
31 if (empty($form_by)) $form_by = '1';
32 if (empty($form_show)) $form_show = array('1');
34 // One of these is chosen as the left column, or Y-axis, of the report.
36 if ($report_type == 'm') {
37 $report_title = xl('Member Association Statistics Report');
39 101 => xl('MA Category'),
40 102 => xl('Specific Service'),
42 9 => xl('Internal Referrals'),
43 10 => xl('External Referrals'),
44 103 => xl('Referral Source'),
49 2 => xl('Unique Clients'),
50 4 => xl('Unique New Clients')
53 // Items are content|row|column|column|...
54 /*****************************************************************
55 '2|2|3|4|5|8|11' => xl('Client Profile - Unique Clients'),
56 '4|2|3|4|5|8|11' => xl('Client Profile - New Clients'),
57 *****************************************************************/
60 else if ($report_type == 'g') {
61 $report_title = xl('GCAC Statistics Report');
63 13 => xl('Abortion-Related Categories'),
64 1 => xl('Total SRH & Family Planning'),
65 12 => xl('Pre-Abortion Counseling'),
66 5 => xl('Abortion Method'), // includes surgical and drug-induced
67 8 => xl('Post-Abortion Followup'),
68 7 => xl('Post-Abortion Contraception'),
69 11 => xl('Complications of Abortion'),
70 10 => xl('External Referrals'),
71 20 => xl('External Referral Followups'),
75 2 => xl('Unique Clients'),
76 4 => xl('Unique New Clients'),
79 /*****************************************************************
80 '1|11|13' => xl('Complications by Service Provider'),
81 *****************************************************************/
85 $report_title = xl('IPPF Statistics Report');
87 3 => xl('General Service Category'),
88 4 => xl('Specific Service'),
89 6 => xl('Contraceptive Method'),
90 9 => xl('Internal Referrals'),
91 10 => xl('External Referrals'),
95 3 => xl('New Acceptors'),
101 if ($report_type == 'm') {
106 // This will become the array of reportable values.
109 // This accumulates the bottom line totals.
113 '.total' => array('title' => 'Total'),
114 '.age' => array('title' => 'Age Category'),
115 ); // info about selectable columns
117 $arr_titles = array(); // will contain column headers
119 // Query layout_options table to generate the $arr_show table.
120 // Table key is the field ID.
121 $lres = sqlStatement("SELECT field_id, title, data_type, list_id, description " .
122 "FROM layout_options WHERE " .
123 "form_id = 'DEM' AND uor > 0 AND field_id NOT LIKE 'em%' " .
124 "ORDER BY group_name, seq, title");
125 while ($lrow = sqlFetchArray($lres)) {
126 $fid = $lrow['field_id'];
127 if ($fid == 'fname' ||
$fid == 'mname' ||
$fid == 'lname') continue;
128 $arr_show[$fid] = $lrow;
129 $arr_titles[$fid] = array();
132 // Compute age in years given a DOB and "as of" date.
134 function getAge($dob, $asof='') {
135 if (empty($asof)) $asof = date('Y-m-d');
136 $a1 = explode('-', substr($dob , 0, 10));
137 $a2 = explode('-', substr($asof, 0, 10));
138 $age = $a2[0] - $a1[0];
139 if ($a2[1] < $a1[1] ||
($a2[1] == $a1[1] && $a2[2] < $a1[2])) --$age;
140 // echo "<!-- $dob $asof $age -->\n"; // debugging
146 function genStartRow($att) {
147 global $cellcount, $form_output;
148 if ($form_output != 3) echo " <tr $att>\n";
152 function genEndRow() {
154 if ($form_output == 3) {
162 /*********************************************************************
163 function genAnyCell($data, $right=false, $class='') {
165 if ($_POST['form_csvexport']) {
166 if ($cellcount) echo ',';
167 echo '"' . $data . '"';
171 if ($class) echo " class='$class'";
172 if ($right) echo " align='right'";
173 echo ">$data</td>\n";
177 *********************************************************************/
179 function getListTitle($list, $option) {
180 $row = sqlQuery("SELECT title FROM list_options WHERE " .
181 "list_id = '$list' AND option_id = '$option'");
182 if (empty($row['title'])) return $option;
183 return $row['title'];
186 // Usually this generates one cell, but allows for two or more.
188 function genAnyCell($data, $right=false, $class='') {
189 global $cellcount, $form_output;
190 if (!is_array($data)) {
191 $data = array(0 => $data);
193 foreach ($data as $datum) {
194 if ($form_output == 3) {
195 if ($cellcount) echo ',';
196 echo '"' . $datum . '"';
200 if ($class) echo " class='$class'";
201 if ($right) echo " align='right'";
202 echo ">$datum</td>\n";
208 function genHeadCell($data, $right=false) {
209 genAnyCell($data, $right, 'dehead');
212 // Create an HTML table cell containing a numeric value, and track totals.
214 function genNumCell($num, $cnum) {
215 global $atotals, $form_output;
216 $atotals[$cnum] +
= $num;
217 if (empty($num) && $form_output != 3) $num = ' ';
218 genAnyCell($num, true, 'detail');
221 // Translate an IPPF code to the corresponding descriptive name of its
222 // contraceptive method, or to an empty string if none applies.
224 function getContraceptiveMethod($code) {
226 if (preg_match('/^111101/', $code)) {
229 else if (preg_match('/^11111[1-9]/', $code)) {
230 $key = xl('Injectables');
232 else if (preg_match('/^11112[1-9]/', $code)) {
233 $key = xl('Implants');
235 else if (preg_match('/^111132/', $code)) {
238 else if (preg_match('/^111133/', $code)) {
239 $key = xl('Vaginal Ring');
241 else if (preg_match('/^112141/', $code)) {
242 $key = xl('Male Condoms');
244 else if (preg_match('/^112142/', $code)) {
245 $key = xl('Female Condoms');
247 else if (preg_match('/^11215[1-9]/', $code)) {
248 $key = xl('Diaphragms/Caps');
250 else if (preg_match('/^11216[1-9]/', $code)) {
251 $key = xl('Spermicides');
253 else if (preg_match('/^11317[1-9]/', $code)) {
256 else if (preg_match('/^145212/', $code)) {
257 $key = xl('Emergency Contraception');
259 else if (preg_match('/^121181.13/', $code)) {
260 $key = xl('Female VSC');
262 else if (preg_match('/^122182.13/', $code)) {
263 $key = xl('Male VSC');
265 else if (preg_match('/^131191.10/', $code)) {
266 $key = xl('Awareness-Based');
271 // Translate an IPPF code to the corresponding descriptive name of its
272 // abortion method, or to an empty string if none applies.
274 function getAbortionMethod($code) {
276 if (preg_match('/^25222[34]/', $code)) {
277 if (preg_match('/^2522231/', $code)) {
280 else if (preg_match('/^2522232/', $code)) {
283 else if (preg_match('/^2522233/', $code)) {
286 else if (preg_match('/^252224/', $code)) {
287 $key = xl('Medical');
290 $key = xl('Other Surgical');
296 /*********************************************************************
297 // Helper function to look up the GCAC issue associated with a visit.
298 // Ideally this is the one and only GCAC issue linked to the encounter.
299 // However if there are multiple such issues, or if only unlinked issues
300 // are found, then we pick the one with its start date closest to the
303 function getGcacData($row, $what, $morejoins="") {
304 $patient_id = $row['pid'];
305 $encounter_id = $row['encounter'];
306 $encdate = substr($row['encdate'], 0, 10);
307 $query = "SELECT $what " .
309 "JOIN lists_ippf_gcac AS lg ON l.type = 'ippf_gcac' AND lg.id = l.id " .
310 "LEFT JOIN issue_encounter AS ie ON ie.pid = '$patient_id' AND " .
311 "ie.encounter = '$encounter_id' AND ie.list_id = l.id " .
313 "WHERE l.pid = '$patient_id' AND " .
314 "l.activity = 1 AND l.type = 'ippf_gcac' " .
315 "ORDER BY ie.pid DESC, ABS(DATEDIFF(l.begdate, '$encdate')) ASC " .
317 // Note that reverse-ordering by ie.pid is a trick for sorting
318 // issues linked to the encounter (non-null values) first.
319 return sqlQuery($query);
322 // Get the "client status" field from the related GCAC issue.
324 function getGcacClientStatus($row) {
325 $irow = getGcacData($row, "lo.title", "LEFT JOIN list_options AS lo ON " .
326 "lo.list_id = 'clientstatus' AND lo.option_id = lg.client_status");
327 if (empty($irow['title'])) {
328 $key = xl('Indeterminate');
331 // The client status description should be just fine for this.
332 $key = $irow['title'];
336 *********************************************************************/
338 // Get the "client status" as descriptive text.
339 // This comes from the most recent GCAC visit form for visits within
340 // the past 2 weeks, although there really should be such a form
341 // attached to the visit associated with $row.
343 function getGcacClientStatus($row) {
345 $encdate = $row['encdate'];
346 $query = "SELECT lo.title " .
347 "FROM forms AS f, form_encounter AS fe, lbf_data AS d, list_options AS lo " .
348 "WHERE f.pid = '$pid' AND " .
349 "f.formdir = 'LBFgcac' AND " .
350 "f.deleted = 0 AND " .
351 "fe.pid = f.pid AND fe.encounter = f.encounter AND " .
352 "fe.date <= '$encdate' AND " .
353 "DATE_ADD(fe.date, INTERVAL 14 DAY) > '$encdate' AND " .
354 "d.form_id = f.form_id AND " .
355 "d.field_id = 'client_status' AND " .
356 "lo.list_id = 'clientstatus' AND " .
357 "lo.option_id = d.field_value " .
358 "ORDER BY d.form_id DESC LIMIT 1";
359 $irow = sqlQuery($query);
360 // echo "<!-- $query -->\n"; // debugging
361 return empty($irow['title']) ?
xl('Indeterminate') : $irow['title'];
364 // Helper function called after the reporting key is determined for a row.
366 function loadColumnData($key, $row) {
367 global $areport, $arr_titles, $form_cors, $from_date, $to_date, $arr_show;
369 // If first instance of this key, initialize its arrays.
370 if (empty($areport[$key])) {
371 $areport[$key] = array();
372 $areport[$key]['.prp'] = 0; // previous pid
373 $areport[$key]['.wom'] = 0; // number of services for women
374 $areport[$key]['.men'] = 0; // number of services for men
375 $areport[$key]['.age'] = array(0,0,0,0,0,0,0,0,0); // age array
376 foreach ($arr_show as $askey => $dummy) {
377 if (substr($askey, 0, 1) == '.') continue;
378 $areport[$key][$askey] = array();
382 // Skip this key if we are counting unique patients and the key
383 // has already seen this patient.
384 if ($form_cors == '2' && $row['pid'] == $areport[$key]['.prp']) return;
386 // If we are counting new acceptors, then require a unique patient
387 // whose contraceptive start date is within the reporting period.
388 if ($form_cors == '3') {
389 // if ($row['pid'] == $areport[$key]['prp']) return;
390 if ($row['pid'] == $areport[$key]['.prp']) return;
391 // Check contraceptive start date.
392 if (!$row['contrastart'] ||
$row['contrastart'] < $from_date ||
393 $row['contrastart'] > $to_date) return;
396 // If we are counting new clients, then require a unique patient
397 // whose registration date is within the reporting period.
398 if ($form_cors == '4') {
399 if ($row['pid'] == $areport[$key]['.prp']) return;
400 // Check registration date.
401 if (!$row['regdate'] ||
$row['regdate'] < $from_date ||
402 $row['regdate'] > $to_date) return;
405 // Flag this patient as having been encountered for this report row.
406 // $areport[$key]['prp'] = $row['pid'];
407 $areport[$key]['.prp'] = $row['pid'];
409 // Increment the correct sex category.
410 if (strcasecmp($row['sex'], 'Male') == 0)
411 ++
$areport[$key]['.men'];
413 ++
$areport[$key]['.wom'];
415 // Increment the correct age category.
416 $age = getAge(fixDate($row['DOB']), $row['encdate']);
417 $i = min(intval(($age - 5) / 5), 8);
418 if ($age < 11) $i = 0;
419 ++
$areport[$key]['.age'][$i];
421 foreach ($arr_show as $askey => $dummy) {
422 if (substr($askey, 0, 1) == '.') continue;
423 $status = empty($row[$askey]) ?
'Unspecified' : $row[$askey];
424 $areport[$key][$askey][$status] +
= 1;
425 $arr_titles[$askey][$status] +
= 1;
429 // This is called for each IPPF service code that is selected.
431 function process_ippf_code($row, $code) {
432 global $areport, $arr_titles, $form_by;
434 $key = 'Unspecified';
436 // SRH including Family Planning
438 if ($form_by === '1') {
439 if (preg_match('/^1/', $code)) {
440 $key = xl('SRH - Family Planning');
442 else if (preg_match('/^2/', $code)) {
443 $key = xl('SRH Non Family Planning');
450 // General Service Category
452 else if ($form_by === '3') {
453 if (preg_match('/^1/', $code)) {
454 $key = xl('SRH - Family Planning');
456 else if (preg_match('/^2/', $code)) {
457 $key = xl('SRH Non Family Planning');
459 else if (preg_match('/^3/', $code)) {
460 $key = xl('Non-SRH Medical');
462 else if (preg_match('/^4/', $code)) {
463 $key = xl('Non-SRH Non-Medical');
466 $key = xl('Invalid Service Codes');
470 // Abortion-Related Category
472 else if ($form_by === '13') {
473 if (preg_match('/^252221/', $code)) {
474 $key = xl('Pre-Abortion Counseling');
476 else if (preg_match('/^252222/', $code)) {
477 $key = xl('Pre-Abortion Consultation');
479 else if (preg_match('/^252223/', $code)) {
480 $key = xl('Induced Abortion');
482 else if (preg_match('/^252224/', $code)) {
483 $key = xl('Medical Abortion');
485 else if (preg_match('/^252225/', $code)) {
486 $key = xl('Incomplete Abortion Treatment');
488 else if (preg_match('/^252226/', $code)) {
489 $key = xl('Post-Abortion Care');
491 else if (preg_match('/^252227/', $code)) {
492 $key = xl('Post-Abortion Counseling');
494 else if (preg_match('/^25222/', $code)) {
495 $key = xl('Other/Generic Abortion-Related');
502 // Specific Services. One row for each IPPF code.
504 else if ($form_by === '4') {
510 else if ($form_by === '5') {
511 $key = getAbortionMethod($code);
512 if (empty($key)) return;
515 // Contraceptive Method.
517 else if ($form_by === '6') {
518 $key = getContraceptiveMethod($code);
519 if (empty($key)) return;
522 /*******************************************************************
523 // Contraceptive method for new contraceptive adoption following abortion.
524 // Get it from the IPPF code if an abortion issue is linked to the visit.
525 // Note we are handling this during processing of services rather than
526 // by enumerating issues, because we need the service date.
528 else if ($form_by === '7') {
529 $key = getContraceptiveMethod($code);
530 if (empty($key)) return;
531 $patient_id = $row['pid'];
532 $encounter_id = $row['encounter'];
533 $query = "SELECT COUNT(*) AS count " .
535 "JOIN issue_encounter AS ie ON ie.pid = '$patient_id' AND " .
536 "ie.encounter = '$encounter_id' AND ie.list_id = l.id " .
537 "WHERE l.pid = '$patient_id' AND " .
538 "l.activity = 1 AND l.type = 'ippf_gcac'";
539 // echo "<!-- $key: $query -->\n"; // debugging
540 $irow = sqlQuery($query);
541 if (empty($irow['count'])) return;
543 *******************************************************************/
545 // Post-Abortion Care and Followup by Source.
546 // Requirements just call for counting sessions, but this way the columns
547 // can be anything - age category, religion, whatever.
549 else if ($form_by === '8') {
550 if (preg_match('/^25222[67]/', $code)) { // all post-abortion care and followup
551 $key = getGcacClientStatus($row);
557 /*******************************************************************
558 // Complications of abortion by abortion method and complication type.
559 // These may be noted either during recovery or during a followup visit.
560 // Again, driven by services in order to report by service date.
561 // Note: If there are multiple complications, they will all be reported.
563 else if ($form_by === '11') {
565 if (preg_match('/^25222[345]/', $code)) { // all abortions including incomplete
566 $compl_type = 'rec_compl';
568 else if (preg_match('/^25222[67]/', $code)) { // all post-abortion care and followup
569 $compl_type = 'fol_compl';
574 $irow = getGcacData($row, "lg.$compl_type, lo.title",
575 "LEFT JOIN list_options AS lo ON lo.list_id = 'in_ab_proc' AND " .
576 "lo.option_id = lg.in_ab_proc");
577 if (empty($irow)) return; // this should not happen
578 if (empty($irow[$compl_type])) return; // ok, no complications
579 // We have one or more complications.
580 $abtype = empty($irow['title']) ? xl('Indeterminate') : $irow['title'];
581 $acompl = explode('|', $irow[$compl_type]);
582 foreach ($acompl as $compl) {
583 $crow = sqlQuery("SELECT title FROM list_options WHERE " .
584 "list_id = 'complication' AND option_id = '$compl'");
585 $key = "$abtype / " . $crow['title'];
586 loadColumnData($key, $row);
588 return; // because loadColumnData() is already done.
590 *******************************************************************/
592 // Pre-Abortion Counseling. Three possible situations:
593 // Provided abortion in the MA clinics
594 // Referred to other service providers (govt,private clinics)
595 // Decided not to have the abortion
597 else if ($form_by === '12') {
598 if (preg_match('/^252221/', $code)) { // all pre-abortion counseling
599 $key = getGcacClientStatus($row);
607 else if ($form_by === '17') {
608 $key = $row['lname'] . ', ' . $row['fname'] . ' ' . $row['mname'];
612 return; // no match, so do nothing
615 // OK we now have the reporting key for this issue.
616 loadColumnData($key, $row);
618 } // end function process_ippf_code()
620 // This is called for each MA service code that is selected.
622 function process_ma_code($row) {
623 global $form_by, $arr_content, $form_cors;
625 $key = 'Unspecified';
627 // One row for each service category.
629 if ($form_by === '101') {
630 if (!empty($row['lo_title'])) $key = xl($row['lo_title']);
633 // Specific Services. One row for each MA code.
635 else if ($form_by === '102') {
639 // One row for each referral source.
641 else if ($form_by === '103') {
642 $key = $row['referral_source'];
647 else if ($form_by === '2') {
648 $key = $arr_content[$form_cors];
655 loadColumnData($key, $row);
658 function LBFgcac_query($pid, $encounter, $name) {
659 $query = "SELECT d.form_id, d.field_value " .
660 "FROM forms AS f, form_encounter AS fe, lbf_data AS d " .
661 "WHERE f.pid = '$pid' AND " .
662 "f.encounter = '$encounter' AND " .
663 "f.formdir = 'LBFgcac' AND " .
664 "f.deleted = 0 AND " .
665 "fe.pid = f.pid AND fe.encounter = f.encounter AND " .
666 "d.form_id = f.form_id AND " .
667 "d.field_id = '$name'";
668 return sqlStatement($query);
671 function LBFgcac_title($form_id, $field_id, $list_id) {
672 $query = "SELECT lo.title " .
673 "FROM lbf_data AS d, list_options AS lo WHERE " .
674 "d.form_id = '$form_id' AND " .
675 "d.field_id = '$field_id' AND " .
676 "lo.list_id = '$list_id' AND " .
677 "lo.option_id = d.field_value " .
679 $row = sqlQuery($query);
680 return empty($row['title']) ?
'' : $row['title'];
683 // This is called for each encounter that is selected.
685 function process_visit($row) {
688 if ($form_by !== '7' && $form_by !== '11') return;
690 // New contraceptive method following abortion.
692 if ($form_by === '7') {
693 $dres = LBFgcac_query($row['pid'], $row['encounter'], 'contrameth');
694 while ($drow = sqlFetchArray($dres)) {
695 $a = explode('|', $drow['field_value']);
696 foreach ($a as $methid) {
697 if (empty($methid)) continue;
698 $crow = sqlQuery("SELECT title FROM list_options WHERE " .
699 "list_id = 'contrameth' AND option_id = '$methid'");
700 $key = $crow['title'];
701 if (empty($key)) $key = xl('Indeterminate');
702 loadColumnData($key, $row);
707 // Complications of abortion by abortion method and complication type.
708 // These may be noted either during recovery or during a followup visit.
709 // Note: If there are multiple complications, they will all be reported.
711 else if ($form_by === '11') {
712 $dres = LBFgcac_query($row['pid'], $row['encounter'], 'complications');
713 while ($drow = sqlFetchArray($dres)) {
714 $a = explode('|', $drow['field_value']);
715 foreach ($a as $complid) {
716 if (empty($complid)) continue;
717 $crow = sqlQuery("SELECT title FROM list_options WHERE " .
718 "list_id = 'complication' AND option_id = '$complid'");
719 $abtype = LBFgcac_title($drow['form_id'], 'in_ab_proc', 'in_ab_proc');
720 if (empty($abtype)) $abtype = xl('Indeterminate');
721 $key = "$abtype / " . $crow['title'];
722 loadColumnData($key, $row);
727 // loadColumnData() already done as needed.
730 /*********************************************************************
731 // This is called for each issue that is selected.
733 function process_issue($row) {
736 $key = 'Unspecified';
738 // Pre-Abortion Counseling. Three possible rows:
739 // Provided abortion in the MA clinics
740 // Referred to other service providers (govt,private clinics)
741 // Decided not to have the abortion
743 if ($form_by === '12') {
745 // TBD: Assign one of the 3 keys, or just return.
755 // TBD: Load column data from the issue.
756 // loadColumnData($key, $row);
758 *********************************************************************/
760 // This is called for each selected referral.
761 // Row keys are the first specified MA code, if any.
763 function process_referral($row) {
765 $key = 'Unspecified';
767 if (!empty($row['refer_related_code'])) {
768 $relcodes = explode(';', $row['refer_related_code']);
769 foreach ($relcodes as $codestring) {
770 if ($codestring === '') continue;
771 list($codetype, $code) = explode(':', $codestring);
773 if ($codetype !== 'IPPF') continue;
775 if ($form_by === '1') {
776 if (preg_match('/^[12]/', $code)) {
777 $key = xl('SRH Referrals');
778 loadColumnData($key, $row);
782 else { // $form_by is 9 (internal) or 10 or 20 (external) referrals
789 if ($form_by !== '1') loadColumnData($key, $row);
792 // If we are doing the CSV export then generate the needed HTTP headers.
793 // Otherwise generate HTML.
795 if ($form_output == 3) {
796 header("Pragma: public");
797 header("Expires: 0");
798 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
799 header("Content-Type: application/force-download");
800 header("Content-Disposition: attachment; filename=service_statistics_report.csv");
801 header("Content-Description: File Transfer");
807 <?php
html_header_show(); ?
>
808 <title
><?php
echo $report_title; ?
></title
>
809 <style type
="text/css">@import
url(../../library
/dynarch_calendar
.css
);</style
>
810 <style type
="text/css">
811 body
{ font
-family
:sans
-serif
; font
-size
:10pt
; font
-weight
:normal
}
812 .dehead
{ color
:#000000; font-family:sans-serif; font-size:10pt; font-weight:bold }
813 .detail
{ color
:#000000; font-family:sans-serif; font-size:10pt; font-weight:normal }
815 <script type
="text/javascript" src
="../../library/textformat.js"></script
>
816 <script type
="text/javascript" src
="../../library/dynarch_calendar.js"></script
>
817 <?php
include_once("{$GLOBALS['srcdir']}/dynarch_calendar_en.inc.php"); ?
>
818 <script type
="text/javascript" src
="../../library/dynarch_calendar_setup.js"></script
>
819 <script language
="JavaScript">
820 var mypcc
= '<?php echo $GLOBALS['phone_country_code
'] ?>';
822 // Begin experimental code
824 function selectByValue(sel
, val
) {
825 for (var i
= 0; i
< sel
.options
.length
; ++i
) {
826 if (sel
.options
[i
].value
== val
) sel
.options
[i
].selected
= true;
830 function selreport() {
831 var f
= document
.forms
[0];
832 var isdis
= 'visible';
833 var s
= f
.form_report
;
834 var v
= (s
.selectedIndex
< 0) ?
'' : s
.options
[s
.selectedIndex
].value
;
837 var a
= v
.split("|");
838 f
.form_cors
.selectedIndex
= -1;
839 f
.form_by
.selectedIndex
= -1;
840 f
['form_show[]'].selectedIndex
= -1;
841 selectByValue(f
.form_cors
, a
[0]);
842 selectByValue(f
.form_by
, a
[1]);
843 for (var i
= 2; i
< a
.length
; ++i
) {
844 selectByValue(f
['form_show[]'], a
[i
]);
847 f
.form_by
.style
.visibility
= isdis
;
848 f
.form_cors
.style
.visibility
= isdis
;
849 f
['form_show[]'].style
.visibility
= isdis
;
852 // End experimental code
857 <body leftmargin
='0' topmargin
='0' marginwidth
='0' marginheight
='0'>
861 <h2
><?php
echo $report_title; ?
></h2
>
863 <form name
='theform' method
='post'
864 action
='ippf_statistics.php?t=<?php echo $report_type ?>'>
866 <table border
='0' cellspacing
='5' cellpadding
='1'>
868 <!-- Begin experimental code
-->
869 <tr
<?php
if (empty($arr_report)) echo " style='display:none'"; ?
>>
870 <td valign
='top' class='dehead' nowrap
>
871 <?php
xl('Report','e'); ?
>:
873 <td valign
='top' class='detail' colspan
='3'>
874 <select name
='form_report' title
='Predefined reports' onchange
='selreport()'>
876 echo " <option value=''>" . xl('Custom') . "</option>\n";
877 foreach ($arr_report as $key => $value) {
878 echo " <option value='$key'";
879 if ($key == $form_report) echo " selected";
880 echo ">" . $value . "</option>\n";
885 <td valign
='top' class='detail'>
889 <!-- End experimental code
-->
892 <td valign
='top' class='dehead' nowrap
>
893 <?php
xl('Rows','e'); ?
>:
895 <td valign
='top' class='detail'>
896 <select name
='form_by' title
='Left column of report'>
898 foreach ($arr_by as $key => $value) {
899 echo " <option value='$key'";
900 if ($key == $form_by) echo " selected";
901 echo ">" . $value . "</option>\n";
906 <td valign
='top' class='dehead' nowrap
>
907 <?php
xl('Content','e'); ?
>:
909 <td valign
='top' class='detail'>
910 <select name
='form_cors' title
='<?php xl('What is to be counted?
','e
'); ?>'>
912 foreach ($arr_content as $key => $value) {
913 echo " <option value='$key'";
914 if ($key == $form_cors) echo " selected";
915 echo ">$value</option>\n";
920 <td valign
='top' class='detail'>
925 <td valign
='top' class='dehead' nowrap
>
926 <?php
xl('Columns','e'); ?
>:
928 <td valign
='top' class='detail'>
929 <select name
='form_show[]' size
='4' multiple
930 title
='<?php xl('Hold down Ctrl to select multiple items
','e
'); ?>'>
932 foreach ($arr_show as $key => $value) {
933 $title = $value['title'];
934 if (empty($title) ||
$key == 'title') $title = $value['description'];
935 echo " <option value='$key'";
936 if (is_array($form_show) && in_array($key, $form_show)) echo " selected";
937 echo ">$title</option>\n";
942 <td valign
='top' class='dehead' nowrap
>
943 <?php
xl('Filters','e'); ?
>:
945 <td colspan
='2' class='detail' style
='border-style:solid;border-width:1px;border-color:#cccccc'>
948 <td valign
='top' class='detail' nowrap
>
949 <?php
xl('Sex','e'); ?
>:
951 <td
class='detail' valign
='top'>
952 <select name
='form_sexes' title
='<?php xl('To filter by sex
','e
'); ?>'>
954 foreach (array(3 => xl('Men and Women'), 1 => xl('Women Only'), 2 => xl('Men Only')) as $key => $value) {
955 echo " <option value='$key'";
956 if ($key == $form_sexes) echo " selected";
957 echo ">$value</option>\n";
964 <td valign
='top' class='detail' nowrap
>
965 <?php
xl('Facility','e'); ?
>:
967 <td valign
='top' class='detail'>
969 // Build a drop-down list of facilities.
971 $query = "SELECT id, name FROM facility ORDER BY name";
972 $fres = sqlStatement($query);
973 echo " <select name='form_facility'>\n";
974 echo " <option value=''>-- All Facilities --\n";
975 while ($frow = sqlFetchArray($fres)) {
976 $facid = $frow['id'];
977 echo " <option value='$facid'";
978 if ($facid == $_POST['form_facility']) echo " selected";
979 echo ">" . $frow['name'] . "\n";
986 <td colspan
='2' class='detail' nowrap
>
987 <?php
xl('From','e'); ?
>
988 <input type
='text' name
='form_from_date' id
='form_from_date' size
='10' value
='<?php echo $from_date ?>'
989 onkeyup
='datekeyup(this,mypcc)' onblur
='dateblur(this,mypcc)' title
='Start date yyyy-mm-dd'>
990 <img src
='../pic/show_calendar.gif' align
='absbottom' width
='24' height
='22'
991 id
='img_from_date' border
='0' alt
='[?]' style
='cursor:pointer'
992 title
='<?php xl('Click here to choose a date
','e
'); ?>'>
993 <?php
xl('To','e'); ?
>
994 <input type
='text' name
='form_to_date' id
='form_to_date' size
='10' value
='<?php echo $to_date ?>'
995 onkeyup
='datekeyup(this,mypcc)' onblur
='dateblur(this,mypcc)' title
='End date yyyy-mm-dd'>
996 <img src
='../pic/show_calendar.gif' align
='absbottom' width
='24' height
='22'
997 id
='img_to_date' border
='0' alt
='[?]' style
='cursor:pointer'
998 title
='<?php xl('Click here to choose a date
','e
'); ?>'>
1005 <td valign
='top' class='dehead' nowrap
>
1006 <?php
xl('To','e'); ?
>:
1008 <td colspan
='3' valign
='top' class='detail' nowrap
>
1010 foreach (array(1 => 'Screen', 2 => 'Printer', 3 => 'Export File') as $key => $value) {
1011 echo " <input type='radio' name='form_output' value='$key'";
1012 if ($key == $form_output) echo ' checked';
1013 echo " />$value ";
1017 <td align
='right' valign
='top' class='detail' nowrap
>
1018 <input type
='submit' name
='form_submit' value
='<?php xl('Submit
','e
'); ?>'
1019 title
='<?php xl('Click to generate the report
','e
'); ?>' />
1023 <td colspan
='5' height
="1">
1030 if ($_POST['form_submit']) {
1032 foreach ($arr_show as $askey => $asval) {
1033 if (substr($askey, 0, 1) == '.') continue;
1034 if ($askey == 'regdate' ||
$askey == 'sex' ||
$askey == 'DOB' ||
1035 $askey == 'lname' ||
$askey == 'fname' ||
$askey == 'mname' ||
1036 $askey == 'contrastart' ||
$askey == 'referral_source') continue;
1037 $pd_fields .= ', pd.' . $askey;
1041 if ($form_sexes == '1') $sexcond = "AND pd.sex NOT LIKE 'Male' ";
1042 else if ($form_sexes == '2') $sexcond = "AND pd.sex LIKE 'Male' ";
1044 // Get referrals and related patient data.
1045 if ($form_by === '9' ||
$form_by === '10' ||
$form_by === '20' ||
$form_by === '1') {
1047 $exttest = "t.refer_external = '1'";
1048 $datefld = "t.refer_date";
1050 if ($form_by === '9') {
1051 $exttest = "t.refer_external = '0'";
1053 else if ($form_by === '20') {
1054 $datefld = "t.reply_date";
1057 $query = "SELECT " .
1058 "t.refer_related_code, t.pid, pd.regdate, pd.referral_source, " .
1059 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, " .
1060 "pd.contrastart$pd_fields " .
1061 "FROM transactions AS t " .
1062 "JOIN patient_data AS pd ON pd.pid = t.pid $sexcond" .
1063 "WHERE t.title = 'Referral' AND $datefld IS NOT NULL AND " .
1064 "$datefld >= '$from_date' AND $datefld <= '$to_date' AND $exttest " .
1065 "ORDER BY t.pid, t.id";
1066 $res = sqlStatement($query);
1067 while ($row = sqlFetchArray($res)) {
1068 process_referral($row);
1071 /*****************************************************************
1072 else if ($form_by === '12') {
1073 // We are reporting on a date range, and assume the applicable date is
1074 // the issue start date which is presumably also the date of pre-
1075 // abortion counseling. The issue end date and the surgery date are
1076 // not of interest here.
1077 $query = "SELECT " .
1078 "l.type, l.begdate, l.pid, " .
1079 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, pd.userlist5, " .
1080 "pd.country_code, pd.status, pd.state, pd.occupation, " .
1081 "lg.client_status, lg.ab_location " .
1082 "FROM lists AS l " .
1083 "JOIN patient_data AS pd ON pd.pid = l.pid $sexcond" .
1084 "LEFT OUTER JOIN lists_ippf_gcac AS lg ON l.type = 'ippf_gcac' AND lg.id = l.id " .
1085 // "LEFT OUTER JOIN lists_ippf_con AS lc ON l.type = 'contraceptive' AND lc.id = l.id " .
1086 "WHERE l.begdate >= '$from_date' AND l.begdate <= '$to_date' AND " .
1087 "l.activity = 1 AND l.type = 'ippf_gcac' " .
1088 "ORDER BY l.pid, l.id";
1089 $res = sqlStatement($query);
1090 while ($row = sqlFetchArray($res)) {
1091 process_issue($row);
1094 *****************************************************************/
1097 if ($form_by !== '9' && $form_by !== '10' && $form_by !== '20') {
1098 // This gets us all MA codes, with encounter and patient
1099 // info attached and grouped by patient and encounter.
1100 $query = "SELECT " .
1101 "fe.pid, fe.encounter, fe.date AS encdate, pd.regdate, " .
1102 "f.user AS provider, " .
1103 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, " .
1104 "pd.contrastart, pd.referral_source$pd_fields, " .
1105 "b.code_type, b.code, c.related_code, lo.title AS lo_title " .
1106 "FROM form_encounter AS fe " .
1107 "JOIN forms AS f ON f.pid = fe.pid AND f.encounter = fe.encounter AND " .
1108 "f.formdir = 'newpatient' AND f.form_id = fe.id AND f.deleted = 0 " .
1109 "JOIN patient_data AS pd ON pd.pid = fe.pid $sexcond" .
1110 "LEFT OUTER JOIN billing AS b ON " .
1111 "b.pid = fe.pid AND b.encounter = fe.encounter AND b.activity = 1 " .
1112 "AND b.code_type = 'MA' " .
1113 "LEFT OUTER JOIN codes AS c ON b.code_type = 'MA' AND c.code_type = '12' AND " .
1114 "c.code = b.code AND c.modifier = b.modifier " .
1115 "LEFT OUTER JOIN list_options AS lo ON " .
1116 "lo.list_id = 'superbill' AND lo.option_id = c.superbill " .
1117 "WHERE fe.date >= '$from_date 00:00:00' AND " .
1118 "fe.date <= '$to_date 23:59:59' ";
1120 if ($form_facility) {
1121 $query .= "AND fe.facility_id = '$form_facility' ";
1123 $query .= "ORDER BY fe.pid, fe.encounter, b.code";
1124 $res = sqlStatement($query);
1126 $prev_encounter = 0;
1128 while ($row = sqlFetchArray($res)) {
1129 if ($row['encounter'] != $prev_encounter) {
1130 $prev_encounter = $row['encounter'];
1131 process_visit($row);
1133 if ($row['code_type'] === 'MA') {
1134 process_ma_code($row);
1135 if (!empty($row['related_code'])) {
1136 $relcodes = explode(';', $row['related_code']);
1137 foreach ($relcodes as $codestring) {
1138 if ($codestring === '') continue;
1139 list($codetype, $code) = explode(':', $codestring);
1140 if ($codetype !== 'IPPF') continue;
1141 process_ippf_code($row, $code);
1148 // Sort everything by key for reporting.
1150 foreach ($arr_titles as $atkey => $dummy) ksort($arr_titles[$atkey]);
1152 if ($form_output != 3) {
1153 echo "<table border='0' cellpadding='1' cellspacing='2' width='98%'>\n";
1154 } // end not csv export
1156 genStartRow("bgcolor='#dddddd'");
1158 // If the key is an MA or IPPF code, then add a column for its description.
1159 if ($form_by === '4' ||
$form_by === '102' ||
$form_by === '9' ||
1160 $form_by === '10' ||
$form_by === '20')
1162 genHeadCell(array($arr_by[$form_by], xl('Description')));
1164 genHeadCell($arr_by[$form_by]);
1167 // Generate headings for values to be shown.
1168 foreach ($form_show as $value) {
1169 // if ($value == '1') { // Total Services
1170 if ($value == '.total') { // Total Services
1171 genHeadCell(xl('Total'));
1173 // else if ($value == '2') { // Age
1174 else if ($value == '.age') { // Age
1175 genHeadCell(xl('0-10' ), true);
1176 genHeadCell(xl('11-14'), true);
1177 genHeadCell(xl('15-19'), true);
1178 genHeadCell(xl('20-24'), true);
1179 genHeadCell(xl('25-29'), true);
1180 genHeadCell(xl('30-34'), true);
1181 genHeadCell(xl('35-39'), true);
1182 genHeadCell(xl('40-44'), true);
1183 genHeadCell(xl('45+' ), true);
1186 else if ($arr_show[$value]['list_id']) {
1187 foreach ($arr_titles[$value] as $key => $dummy) {
1188 genHeadCell(getListTitle($arr_show[$value]['list_id'],$key), true);
1191 else if (!empty($arr_titles[$value])) {
1192 foreach ($arr_titles[$value] as $key => $dummy) {
1193 genHeadCell($key, true);
1198 if ($form_output != 3) {
1199 genHeadCell(xl('Total'), true);
1206 foreach ($areport as $key => $varr) {
1207 $bgcolor = (++
$encount & 1) ?
"#ddddff" : "#ffdddd";
1211 // If the key is an MA or IPPF code, then add a column for its description.
1212 if ($form_by === '4' ||
$form_by === '102' ||
$form_by === '9' ||
1213 $form_by === '10' ||
$form_by === '20')
1215 $dispkey = array($key, '');
1216 $type = $form_by === '102' ?
12 : 11; // MA or IPPF
1217 $crow = sqlQuery("SELECT code_text FROM codes WHERE " .
1218 "code_type = '$type' AND code = '$key' ORDER BY id LIMIT 1");
1219 if (!empty($crow['code_text'])) $dispkey[1] = $crow['code_text'];
1222 genStartRow("bgcolor='$bgcolor'");
1224 genAnyCell($dispkey, false, 'detail');
1226 // This is the column index for accumulating column totals.
1228 $totalsvcs = $areport[$key]['.wom'] +
$areport[$key]['.men'];
1230 // Generate data for this row.
1231 foreach ($form_show as $value) {
1232 // if ($value == '1') { // Total Services
1233 if ($value == '.total') { // Total Services
1234 genNumCell($totalsvcs, $cnum++
);
1236 else if ($value == '.age') { // Age
1237 for ($i = 0; $i < 9; ++
$i) {
1238 genNumCell($areport[$key]['.age'][$i], $cnum++
);
1241 else if (!empty($arr_titles[$value])) {
1242 foreach ($arr_titles[$value] as $title => $dummy) {
1243 genNumCell($areport[$key][$value][$title], $cnum++
);
1248 // Write the Total column data.
1249 if ($form_output != 3) {
1250 $atotals[$cnum] +
= $totalsvcs;
1251 genAnyCell($totalsvcs, true, 'dehead');
1257 if ($form_output != 3) {
1258 // Generate the line of totals.
1259 genStartRow("bgcolor='#dddddd'");
1261 // If the key is an MA or IPPF code, then add a column for its description.
1262 if ($form_by === '4' ||
$form_by === '102' ||
$form_by === '9' ||
1263 $form_by === '10' ||
$form_by === '20')
1265 genHeadCell(array(xl('Totals'), ''));
1267 genHeadCell(xl('Totals'));
1270 for ($cnum = 0; $cnum < count($atotals); ++
$cnum) {
1271 genHeadCell($atotals[$cnum], true);
1278 } // end of if refresh or export
1280 if ($form_output != 3) {
1285 <script language
='JavaScript'>
1287 Calendar
.setup({inputField
:"form_from_date", ifFormat
:"%Y-%m-%d", button
:"img_from_date"});
1288 Calendar
.setup({inputField
:"form_to_date", ifFormat
:"%Y-%m-%d", button
:"img_to_date"});
1289 <?php
if ($form_output == 2) { ?
>