3 * This module creates statistical reports related to family planning
4 * and sexual and reproductive health.
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2008-2015 Rod Roark <rod@sunsetsystems.com>
11 * @copyright Copyright (c) 2017 Brady Miller <brady.g.miller@gmail.com>
12 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 include_once("../globals.php");
16 include_once("../../library/patient.inc");
17 include_once("../../library/acl.inc");
19 use OpenEMR\Services\FacilityService
;
21 // Might want something different here.
23 if (! acl_check('acct', 'rep')) {
24 die("Unauthorized access.");
27 $facilityService = new FacilityService();
29 $report_type = empty($_GET['t']) ?
'i' : $_GET['t'];
31 $from_date = fixDate($_POST['form_from_date']);
32 $to_date = fixDate($_POST['form_to_date'], date('Y-m-d'));
33 $form_by = $_POST['form_by']; // this is a scalar
34 $form_show = $_POST['form_show']; // this is an array
35 $form_facility = isset($_POST['form_facility']) ?
$_POST['form_facility'] : '';
36 $form_sexes = isset($_POST['form_sexes']) ?
$_POST['form_sexes'] : '3';
37 $form_content = isset($_POST['form_content']) ?
$_POST['form_content'] : '1';
38 $form_output = isset($_POST['form_output']) ?
0 +
$_POST['form_output'] : 1;
40 if (empty($form_by)) {
44 if (empty($form_show)) {
45 $form_show = array('1');
48 // One of these is chosen as the left column, or Y-axis, of the report.
50 if ($report_type == 'm') {
51 $report_title = xl('Member Association Statistics Report');
53 101 => xl('MA Category'),
54 102 => xl('Specific Service'),
55 // 6 => xl('Contraceptive Method'),
56 // 104 => xl('Specific Contraceptive Service');
58 9 => xl('Internal Referrals'),
59 10 => xl('External Referrals'),
60 103 => xl('Referral Source'),
65 2 => xl('Unique Clients'),
66 4 => xl('Unique New Clients'),
67 // 5 => xl('Contraceptive Products'),
70 // Items are content|row|column|column|...
71 /*****************************************************************
72 '2|2|3|4|5|8|11' => xl('Client Profile - Unique Clients'),
73 '4|2|3|4|5|8|11' => xl('Client Profile - New Clients'),
74 *****************************************************************/
76 } else if ($report_type == 'g') {
77 $report_title = xl('GCAC Statistics Report');
79 13 => xl('Abortion-Related Categories'),
80 1 => xl('Total SRH & Family Planning'),
81 12 => xl('Pre-Abortion Counseling'),
82 5 => xl('Abortion Method'), // includes surgical and drug-induced
83 8 => xl('Post-Abortion Followup'),
84 7 => xl('Post-Abortion Contraception'),
85 11 => xl('Complications of Abortion'),
86 10 => xl('External Referrals'),
87 20 => xl('External Referral Followups'),
91 2 => xl('Unique Clients'),
92 4 => xl('Unique New Clients'),
95 /*****************************************************************
96 '1|11|13' => xl('Complications by Service Provider'),
97 *****************************************************************/
100 $report_title = xl('IPPF Statistics Report');
102 3 => xl('General Service Category'),
103 4 => xl('Specific Service'),
104 104 => xl('Specific Contraceptive Service'),
105 6 => xl('Contraceptive Method'),
106 9 => xl('Internal Referrals'),
107 10 => xl('External Referrals'),
109 $arr_content = array(
111 3 => xl('New Acceptors'),
112 5 => xl('Contraceptive Products'),
118 // This will become the array of reportable values.
121 // This accumulates the bottom line totals.
125 '.total' => array('title' => 'Total'),
126 '.age2' => array('title' => 'Age Category (2)'),
127 '.age9' => array('title' => 'Age Category (9)'),
128 ); // info about selectable columns
130 $arr_titles = array(); // will contain column headers
132 // Query layout_options table to generate the $arr_show table.
133 // Table key is the field ID.
134 $lres = sqlStatement("SELECT field_id, title, data_type, list_id, description " .
135 "FROM layout_options WHERE " .
136 "form_id = 'DEM' AND uor > 0 AND field_id NOT LIKE 'em%' " .
137 "ORDER BY group_name, seq, title");
138 while ($lrow = sqlFetchArray($lres)) {
139 $fid = $lrow['field_id'];
140 if ($fid == 'fname' ||
$fid == 'mname' ||
$fid == 'lname') {
144 $arr_show[$fid] = $lrow;
145 $arr_titles[$fid] = array();
148 // Compute age in years given a DOB and "as of" date.
150 function getAge($dob, $asof = '')
153 $asof = date('Y-m-d');
156 $a1 = explode('-', substr($dob, 0, 10));
157 $a2 = explode('-', substr($asof, 0, 10));
158 $age = $a2[0] - $a1[0];
159 if ($a2[1] < $a1[1] ||
($a2[1] == $a1[1] && $a2[2] < $a1[2])) {
163 // echo "<!-- $dob $asof $age -->\n"; // debugging
169 function genStartRow($att)
171 global $cellcount, $form_output;
172 if ($form_output != 3) {
182 if ($form_output == 3) {
189 /*********************************************************************
190 function genAnyCell($data, $right=false, $class='') {
192 if ($_POST['form_csvexport']) {
193 if ($cellcount) echo ',';
194 echo '"' . $data . '"';
198 if ($class) echo " class='$class'";
199 if ($right) echo " align='right'";
200 echo ">$data</td>\n";
204 *********************************************************************/
206 function getListTitle($list, $option)
208 $row = sqlQuery("SELECT title FROM list_options WHERE " .
209 "list_id = '$list' AND option_id = '$option'");
210 if (empty($row['title'])) {
214 return $row['title'];
217 // Usually this generates one cell, but allows for two or more.
219 function genAnyCell($data, $right = false, $class = '', $colspan = 1)
221 global $cellcount, $form_output;
222 if (!is_array($data)) {
223 $data = array(0 => $data);
226 foreach ($data as $datum) {
227 if ($form_output == 3) {
232 echo '"' . $datum . '"';
236 echo " class='$class'";
240 echo " colspan='$colspan' align='center'";
242 echo " align='right'";
245 echo ">$datum</td>\n";
252 function genHeadCell($data, $right = false, $colspan = 1)
254 genAnyCell($data, $right, 'dehead', $colspan);
257 // Create an HTML table cell containing a numeric value, and track totals.
259 function genNumCell($num, $cnum)
261 global $atotals, $form_output;
262 $atotals[$cnum] +
= $num;
263 if (empty($num) && $form_output != 3) {
267 genAnyCell($num, true, 'detail');
270 // Translate an IPPF code to the corresponding descriptive name of its
271 // contraceptive method, or to an empty string if none applies.
273 function getContraceptiveMethod($code)
276 if (preg_match('/^111101/', $code)) {
278 } else if (preg_match('/^11111[1-9]/', $code)) {
279 $key = xl('Injectables');
280 } else if (preg_match('/^11112[1-9]/', $code)) {
281 $key = xl('Implants');
282 } else if (preg_match('/^111132/', $code)) {
284 } else if (preg_match('/^111133/', $code)) {
285 $key = xl('Vaginal Ring');
286 } else if (preg_match('/^112141/', $code)) {
287 $key = xl('Male Condoms');
288 } else if (preg_match('/^112142/', $code)) {
289 $key = xl('Female Condoms');
290 } else if (preg_match('/^11215[1-9]/', $code)) {
291 $key = xl('Diaphragms/Caps');
292 } else if (preg_match('/^11216[1-9]/', $code)) {
293 $key = xl('Spermicides');
294 } else if (preg_match('/^11317[1-9]/', $code)) {
296 } else if (preg_match('/^145212/', $code)) {
297 $key = xl('Emergency Contraception');
298 } else if (preg_match('/^121181.13/', $code)) {
299 $key = xl('Female VSC');
300 } else if (preg_match('/^122182.13/', $code)) {
301 $key = xl('Male VSC');
302 } else if (preg_match('/^131191.10/', $code)) {
303 $key = xl('Awareness-Based');
309 // Helper function to find a contraception-related IPPF code from
310 // the related_code element of the given array.
312 function getRelatedContraceptiveCode($row)
314 if (!empty($row['related_code'])) {
315 $relcodes = explode(';', $row['related_code']);
316 foreach ($relcodes as $codestring) {
317 if ($codestring === '') {
321 list($codetype, $code) = explode(':', $codestring);
322 if ($codetype !== 'IPPF') {
326 // Check if the related code concerns contraception.
327 $tmp = getContraceptiveMethod($code);
337 // Helper function to find an abortion-method IPPF code from
338 // the related_code element of the given array.
340 function getRelatedAbortionMethod($row)
342 if (!empty($row['related_code'])) {
343 $relcodes = explode(';', $row['related_code']);
344 foreach ($relcodes as $codestring) {
345 if ($codestring === '') {
349 list($codetype, $code) = explode(':', $codestring);
350 if ($codetype !== 'IPPF') {
354 // Check if the related code concerns contraception.
355 $tmp = getAbortionMethod($code);
365 // Translate an IPPF code to the corresponding descriptive name of its
366 // abortion method, or to an empty string if none applies.
368 function getAbortionMethod($code)
371 if (preg_match('/^25222[34]/', $code)) {
372 if (preg_match('/^2522231/', $code)) {
374 } else if (preg_match('/^2522232/', $code)) {
376 } else if (preg_match('/^2522233/', $code)) {
378 } else if (preg_match('/^252224/', $code)) {
379 $key = xl('Medical');
381 $key = xl('Other Surgical');
388 /*********************************************************************
389 // Helper function to look up the GCAC issue associated with a visit.
390 // Ideally this is the one and only GCAC issue linked to the encounter.
391 // However if there are multiple such issues, or if only unlinked issues
392 // are found, then we pick the one with its start date closest to the
395 function getGcacData($row, $what, $morejoins="") {
396 $patient_id = $row['pid'];
397 $encounter_id = $row['encounter'];
398 $encdate = substr($row['encdate'], 0, 10);
399 $query = "SELECT $what " .
401 "JOIN lists_ippf_gcac AS lg ON l.type = 'ippf_gcac' AND lg.id = l.id " .
402 "LEFT JOIN issue_encounter AS ie ON ie.pid = '$patient_id' AND " .
403 "ie.encounter = '$encounter_id' AND ie.list_id = l.id " .
405 "WHERE l.pid = '$patient_id' AND " .
406 "l.activity = 1 AND l.type = 'ippf_gcac' " .
407 "ORDER BY ie.pid DESC, ABS(DATEDIFF(l.begdate, '$encdate')) ASC " .
409 // Note that reverse-ordering by ie.pid is a trick for sorting
410 // issues linked to the encounter (non-null values) first.
411 return sqlQuery($query);
414 // Get the "client status" field from the related GCAC issue.
416 function getGcacClientStatus($row) {
417 $irow = getGcacData($row, "lo.title", "LEFT JOIN list_options AS lo ON " .
418 "lo.list_id = 'clientstatus' AND lo.option_id = lg.client_status");
419 if (empty($irow['title'])) {
420 $key = xl('Indeterminate');
423 // The client status description should be just fine for this.
424 $key = $irow['title'];
428 *********************************************************************/
430 // Determine if a recent gcac service was performed.
432 function hadRecentAbService($pid, $encdate)
434 $query = "SELECT COUNT(*) AS count " .
435 "FROM form_encounter AS fe, billing AS b, codes AS c WHERE " .
436 "fe.pid = '$pid' AND " .
437 "fe.date <= '$encdate' AND " .
438 "DATE_ADD(fe.date, INTERVAL 14 DAY) > '$encdate' AND " .
439 "b.pid = fe.pid AND " .
440 "b.encounter = fe.encounter AND " .
441 "b.activity = 1 AND " .
442 "b.code_type = 'MA' AND " .
443 "c.code_type = '12' AND " .
444 "c.code = b.code AND c.modifier = b.modifier AND " .
445 "( c.related_code LIKE '%IPPF:252223%' OR c.related_code LIKE '%IPPF:252224%' )";
446 $tmp = sqlQuery($query);
447 return !empty($tmp['count']);
450 // Get the "client status" as descriptive text.
452 function getGcacClientStatus($row)
455 $encdate = $row['encdate'];
457 if (hadRecentAbService($pid, $encdate)) {
458 return xl('MA Client Accepting Abortion');
461 // Check for a GCAC visit form.
462 // This will the most recent GCAC visit form for visits within
463 // the past 2 weeks, although there really should be such a form
464 // attached to the visit associated with $row.
465 $query = "SELECT lo.title " .
466 "FROM forms AS f, form_encounter AS fe, lbf_data AS d, list_options AS lo " .
467 "WHERE f.pid = '$pid' AND " .
468 "f.formdir = 'LBFgcac' AND " .
469 "f.deleted = 0 AND " .
470 "fe.pid = f.pid AND fe.encounter = f.encounter AND " .
471 "fe.date <= '$encdate' AND " .
472 "DATE_ADD(fe.date, INTERVAL 14 DAY) > '$encdate' AND " .
473 "d.form_id = f.form_id AND " .
474 "d.field_id = 'client_status' AND " .
475 "lo.list_id = 'clientstatus' AND " .
476 "lo.option_id = d.field_value " .
477 "ORDER BY d.form_id DESC LIMIT 1";
478 $irow = sqlQuery($query);
479 if (!empty($irow['title'])) {
480 return $irow['title'];
483 // Check for a referred abortion.
485 $query = "SELECT COUNT(*) AS count " .
486 "FROM transactions AS t, codes AS c WHERE " .
487 "t.title = 'Referral' AND " .
488 "t.refer_date IS NOT NULL AND " .
489 "t.refer_date <= '$encdate' AND " .
490 "DATE_ADD(t.refer_date, INTERVAL 14 DAY) > '$encdate' AND " .
491 "t.refer_related_code LIKE 'REF:%' AND " .
492 "c.code_type = '16' AND " .
493 "c.code = SUBSTRING(t.refer_related_code, 5) AND " .
494 "( c.related_code LIKE '%IPPF:252223%' OR c.related_code LIKE '%IPPF:252224%' )";
496 $query = "SELECT COUNT(*) AS count " .
497 "FROM transactions AS t " .
498 "LEFT JOIN codes AS c ON t.refer_related_code LIKE 'REF:%' AND " .
499 "c.code_type = '16' AND " .
500 "c.code = SUBSTRING(t.refer_related_code, 5) " .
502 "t.title = 'Referral' AND " .
503 "t.refer_date IS NOT NULL AND " .
504 "t.refer_date <= '$encdate' AND " .
505 "DATE_ADD(t.refer_date, INTERVAL 14 DAY) > '$encdate' AND " .
506 "( t.refer_related_code LIKE '%IPPF:252223%' OR " .
507 "t.refer_related_code LIKE '%IPPF:252224%' OR " .
508 "( c.related_code IS NOT NULL AND " .
509 "( c.related_code LIKE '%IPPF:252223%' OR " .
510 "c.related_code LIKE '%IPPF:252224%' )))";
512 $tmp = sqlQuery($query);
513 if (!empty($tmp['count'])) {
514 return xl('Outbound Referral');
517 return xl('Indeterminate');
520 // Helper function called after the reporting key is determined for a row.
522 function loadColumnData($key, $row, $quantity = 1)
524 global $areport, $arr_titles, $form_content, $from_date, $to_date, $arr_show;
526 // If first instance of this key, initialize its arrays.
527 if (empty($areport[$key])) {
528 $areport[$key] = array();
529 $areport[$key]['.prp'] = 0; // previous pid
530 $areport[$key]['.wom'] = 0; // number of services for women
531 $areport[$key]['.men'] = 0; // number of services for men
532 $areport[$key]['.age2'] = array(0,0); // age array
533 $areport[$key]['.age9'] = array(0,0,0,0,0,0,0,0,0); // age array
534 foreach ($arr_show as $askey => $dummy) {
535 if (substr($askey, 0, 1) == '.') {
539 $areport[$key][$askey] = array();
543 // Skip this key if we are counting unique patients and the key
544 // has already seen this patient.
545 if ($form_content == '2' && $row['pid'] == $areport[$key]['.prp']) {
549 // If we are counting new acceptors, then require a unique patient
550 // whose contraceptive start date is within the reporting period.
551 if ($form_content == '3') {
552 // if ($row['pid'] == $areport[$key]['prp']) return;
553 if ($row['pid'] == $areport[$key]['.prp']) {
557 // Check contraceptive start date.
558 if (!$row['contrastart'] ||
$row['contrastart'] < $from_date ||
559 $row['contrastart'] > $to_date) {
564 // If we are counting new clients, then require a unique patient
565 // whose registration date is within the reporting period.
566 if ($form_content == '4') {
567 if ($row['pid'] == $areport[$key]['.prp']) {
571 // Check registration date.
572 if (!$row['regdate'] ||
$row['regdate'] < $from_date ||
573 $row['regdate'] > $to_date) {
578 // Flag this patient as having been encountered for this report row.
579 // $areport[$key]['prp'] = $row['pid'];
580 $areport[$key]['.prp'] = $row['pid'];
582 // Increment the correct sex category.
583 if (strcasecmp($row['sex'], 'Male') == 0) {
584 $areport[$key]['.men'] +
= $quantity;
586 $areport[$key]['.wom'] +
= $quantity;
589 // Increment the correct age categories.
590 $age = getAge(fixDate($row['DOB']), $row['encdate']);
591 $i = min(intval(($age - 5) / 5), 8);
596 $areport[$key]['.age9'][$i] +
= $quantity;
597 $i = $age < 25 ?
0 : 1;
598 $areport[$key]['.age2'][$i] +
= $quantity;
600 foreach ($arr_show as $askey => $dummy) {
601 if (substr($askey, 0, 1) == '.') {
605 $status = empty($row[$askey]) ?
'Unspecified' : $row[$askey];
606 $areport[$key][$askey][$status] +
= $quantity;
607 $arr_titles[$askey][$status] +
= $quantity;
611 // This is called for each IPPF service code that is selected.
613 function process_ippf_code($row, $code, $quantity = 1)
615 global $areport, $arr_titles, $form_by, $form_content;
617 $key = 'Unspecified';
619 // SRH including Family Planning
621 if ($form_by === '1') {
622 if (preg_match('/^1/', $code)) {
623 $key = xl('SRH - Family Planning');
624 } else if (preg_match('/^2/', $code)) {
625 $key = xl('SRH Non Family Planning');
627 if ($form_content != 5) {
631 } // General Service Category
633 else if ($form_by === '3') {
634 if (preg_match('/^1/', $code)) {
635 $key = xl('SRH - Family Planning');
636 } else if (preg_match('/^2/', $code)) {
637 $key = xl('SRH Non Family Planning');
638 } else if (preg_match('/^3/', $code)) {
639 $key = xl('Non-SRH Medical');
640 } else if (preg_match('/^4/', $code)) {
641 $key = xl('Non-SRH Non-Medical');
643 $key = xl('Invalid Service Codes');
645 } // Abortion-Related Category
647 else if ($form_by === '13') {
648 if (preg_match('/^252221/', $code)) {
649 $key = xl('Pre-Abortion Counseling');
650 } else if (preg_match('/^252222/', $code)) {
651 $key = xl('Pre-Abortion Consultation');
652 } else if (preg_match('/^252223/', $code)) {
653 $key = xl('Induced Abortion');
654 } else if (preg_match('/^252224/', $code)) {
655 $key = xl('Medical Abortion');
656 } else if (preg_match('/^252225/', $code)) {
657 $key = xl('Incomplete Abortion Treatment');
658 } else if (preg_match('/^252226/', $code)) {
659 $key = xl('Post-Abortion Care');
660 } else if (preg_match('/^252227/', $code)) {
661 $key = xl('Post-Abortion Counseling');
662 } else if (preg_match('/^25222/', $code)) {
663 $key = xl('Other/Generic Abortion-Related');
665 if ($form_content != 5) {
669 } // Specific Services. One row for each IPPF code.
671 else if ($form_by === '4') {
673 } // Specific Contraceptive Services. One row for each IPPF code.
675 else if ($form_by === '104') {
676 if ($form_content != 5) {
677 // Skip codes not for contraceptive services.
678 $tmp = getContraceptiveMethod($code);
685 } // Abortion Method.
687 else if ($form_by === '5') {
688 $key = getAbortionMethod($code);
690 if ($form_content != 5) {
694 $key = 'Unspecified';
696 } // Contraceptive Method.
698 else if ($form_by === '6') {
699 $key = getContraceptiveMethod($code);
701 if ($form_content != 5) {
705 $key = 'Unspecified';
707 } /*******************************************************************
708 // Contraceptive method for new contraceptive adoption following abortion.
709 // Get it from the IPPF code if an abortion issue is linked to the visit.
710 // Note we are handling this during processing of services rather than
711 // by enumerating issues, because we need the service date.
713 else if ($form_by === '7') {
714 $key = getContraceptiveMethod($code);
715 if (empty($key)) return;
716 $patient_id = $row['pid'];
717 $encounter_id = $row['encounter'];
718 $query = "SELECT COUNT(*) AS count " .
720 "JOIN issue_encounter AS ie ON ie.pid = '$patient_id' AND " .
721 "ie.encounter = '$encounter_id' AND ie.list_id = l.id " .
722 "WHERE l.pid = '$patient_id' AND " .
723 "l.activity = 1 AND l.type = 'ippf_gcac'";
724 // echo "<!-- $key: $query -->\n"; // debugging
725 $irow = sqlQuery($query);
726 if (empty($irow['count'])) return;
728 *******************************************************************/
730 // Contraceptive method for new contraceptive adoption following abortion.
731 // Get it from the IPPF code if there is a suitable recent GCAC form.
733 else if ($form_by === '7') {
734 $key = getContraceptiveMethod($code);
739 $patient_id = $row['pid'];
740 $encdate = $row['encdate'];
741 // Skip this if no recent gcac service nor gcac form with acceptance.
742 if (!hadRecentAbService($patient_id, $encdate)) {
743 $query = "SELECT COUNT(*) AS count " .
744 "FROM forms AS f, form_encounter AS fe, lbf_data AS d " .
745 "WHERE f.pid = '$patient_id' AND " .
746 "f.formdir = 'LBFgcac' AND " .
747 "f.deleted = 0 AND " .
748 "fe.pid = f.pid AND fe.encounter = f.encounter AND " .
749 "fe.date <= '$encdate' AND " .
750 "DATE_ADD(fe.date, INTERVAL 14 DAY) > '$encdate' AND " .
751 "d.form_id = f.form_id AND " .
752 "d.field_id = 'client_status' AND " .
753 "( d.field_value = 'maaa' OR d.field_value = 'refout' )";
754 $irow = sqlQuery($query);
755 if (empty($irow['count'])) {
759 } // Post-Abortion Care and Followup by Source.
760 // Requirements just call for counting sessions, but this way the columns
761 // can be anything - age category, religion, whatever.
763 else if ($form_by === '8') {
764 if (preg_match('/^25222[567]/', $code)) { // care, followup and incomplete abortion treatment
765 $key = getGcacClientStatus($row);
769 } /*******************************************************************
770 // Complications of abortion by abortion method and complication type.
771 // These may be noted either during recovery or during a followup visit.
772 // Again, driven by services in order to report by service date.
773 // Note: If there are multiple complications, they will all be reported.
775 else if ($form_by === '11') {
777 if (preg_match('/^25222[345]/', $code)) { // all abortions including incomplete
778 $compl_type = 'rec_compl';
780 else if (preg_match('/^25222[67]/', $code)) { // all post-abortion care and followup
781 $compl_type = 'fol_compl';
786 $irow = getGcacData($row, "lg.$compl_type, lo.title",
787 "LEFT JOIN list_options AS lo ON lo.list_id = 'in_ab_proc' AND " .
788 "lo.option_id = lg.in_ab_proc");
789 if (empty($irow)) return; // this should not happen
790 if (empty($irow[$compl_type])) return; // ok, no complications
791 // We have one or more complications.
792 $abtype = empty($irow['title']) ? xl('Indeterminate') : $irow['title'];
793 $acompl = explode('|', $irow[$compl_type]);
794 foreach ($acompl as $compl) {
795 $crow = sqlQuery("SELECT title FROM list_options WHERE " .
796 "list_id = 'complication' AND option_id = '$compl'");
797 $key = "$abtype / " . $crow['title'];
798 loadColumnData($key, $row);
800 return; // because loadColumnData() is already done.
802 *******************************************************************/
804 // Pre-Abortion Counseling. Three possible situations:
805 // Provided abortion in the MA clinics
806 // Referred to other service providers (govt,private clinics)
807 // Decided not to have the abortion
809 else if ($form_by === '12') {
810 if (preg_match('/^252221/', $code)) { // all pre-abortion counseling
811 $key = getGcacClientStatus($row);
817 else if ($form_by === '17') {
818 $key = $row['lname'] . ', ' . $row['fname'] . ' ' . $row['mname'];
820 return; // no match, so do nothing
823 // OK we now have the reporting key for this issue.
824 loadColumnData($key, $row, $quantity);
825 } // end function process_ippf_code()
827 // This is called for each MA service code that is selected.
829 function process_ma_code($row)
831 global $form_by, $arr_content, $form_content;
833 $key = 'Unspecified';
835 // One row for each service category.
837 if ($form_by === '101') {
838 if (!empty($row['lo_title'])) {
839 $key = xl($row['lo_title']);
841 } // Specific Services. One row for each MA code.
843 else if ($form_by === '102') {
845 } // One row for each referral source.
847 else if ($form_by === '103') {
848 $key = $row['referral_source'];
851 else if ($form_by === '2') {
852 $key = $arr_content[$form_content];
857 loadColumnData($key, $row);
860 function LBFgcac_query($pid, $encounter, $name)
862 $query = "SELECT d.form_id, d.field_value " .
863 "FROM forms AS f, form_encounter AS fe, lbf_data AS d " .
864 "WHERE f.pid = '$pid' AND " .
865 "f.encounter = '$encounter' AND " .
866 "f.formdir = 'LBFgcac' AND " .
867 "f.deleted = 0 AND " .
868 "fe.pid = f.pid AND fe.encounter = f.encounter AND " .
869 "d.form_id = f.form_id AND " .
870 "d.field_id = '$name'";
871 return sqlStatement($query);
874 function LBFgcac_title($form_id, $field_id, $list_id)
876 $query = "SELECT lo.title " .
877 "FROM lbf_data AS d, list_options AS lo WHERE " .
878 "d.form_id = '$form_id' AND " .
879 "d.field_id = '$field_id' AND " .
880 "lo.list_id = '$list_id' AND " .
881 "lo.option_id = d.field_value " .
883 $row = sqlQuery($query);
884 return empty($row['title']) ?
'' : $row['title'];
887 // This is called for each encounter that is selected.
889 function process_visit($row)
893 if ($form_by !== '7' && $form_by !== '11') {
897 // New contraceptive method following abortion. These should only be
898 // present for inbound referrals.
900 if ($form_by === '7') {
901 // We think this case goes away, but not sure yet.
902 /*****************************************************************
903 $dres = LBFgcac_query($row['pid'], $row['encounter'], 'contrameth');
904 while ($drow = sqlFetchArray($dres)) {
905 $a = explode('|', $drow['field_value']);
906 foreach ($a as $methid) {
907 if (empty($methid)) continue;
908 $crow = sqlQuery("SELECT title FROM list_options WHERE " .
909 "list_id = 'contrameth' AND option_id = '$methid'");
910 $key = $crow['title'];
911 if (empty($key)) $key = xl('Indeterminate');
912 loadColumnData($key, $row);
915 *****************************************************************/
916 } // Complications of abortion by abortion method and complication type.
917 // These may be noted either during recovery or during a followup visit.
918 // Note: If there are multiple complications, they will all be reported.
920 else if ($form_by === '11') {
921 $dres = LBFgcac_query($row['pid'], $row['encounter'], 'complications');
922 while ($drow = sqlFetchArray($dres)) {
923 $a = explode('|', $drow['field_value']);
924 foreach ($a as $complid) {
925 if (empty($complid)) {
929 $crow = sqlQuery("SELECT title FROM list_options WHERE " .
930 "list_id = 'complication' AND option_id = '$complid'");
931 $abtype = LBFgcac_title($drow['form_id'], 'in_ab_proc', 'in_ab_proc');
932 if (empty($abtype)) {
933 $abtype = xl('Indeterminate');
936 $key = "$abtype / " . $crow['title'];
937 loadColumnData($key, $row);
942 // loadColumnData() already done as needed.
945 /*********************************************************************
946 // This is called for each issue that is selected.
948 function process_issue($row) {
951 $key = 'Unspecified';
953 // Pre-Abortion Counseling. Three possible rows:
954 // Provided abortion in the MA clinics
955 // Referred to other service providers (govt,private clinics)
956 // Decided not to have the abortion
958 if ($form_by === '12') {
960 // TBD: Assign one of the 3 keys, or just return.
970 // TBD: Load column data from the issue.
971 // loadColumnData($key, $row);
973 *********************************************************************/
975 // This is called for each selected referral.
976 // Row keys are the first specified MA code, if any.
978 function process_referral($row)
981 $key = 'Unspecified';
983 // For followups we care about the actual service provided, otherwise
984 // the requested service.
985 $related_code = $form_by === '20' ?
986 $row['reply_related_code'] : $row['refer_related_code'];
988 if (!empty($related_code)) {
989 $relcodes = explode(';', $related_code);
990 foreach ($relcodes as $codestring) {
991 if ($codestring === '') {
995 list($codetype, $code) = explode(':', $codestring);
997 if ($codetype == 'REF') {
998 // This is the expected case; a direct IPPF code is obsolete.
999 $rrow = sqlQuery("SELECT related_code FROM codes WHERE " .
1000 "code_type = '16' AND code = '$code' AND active = 1 " .
1001 "ORDER BY id LIMIT 1");
1002 if (!empty($rrow['related_code'])) {
1003 list($codetype, $code) = explode(':', $rrow['related_code']);
1007 if ($codetype !== 'IPPF') {
1011 if ($form_by === '1') {
1012 if (preg_match('/^[12]/', $code)) {
1013 $key = xl('SRH Referrals');
1014 loadColumnData($key, $row);
1017 } else { // $form_by is 9 (internal) or 10 or 20 (external) referrals
1024 if ($form_by !== '1') {
1025 loadColumnData($key, $row);
1029 function uses_description($form_by)
1031 return ($form_by === '4' ||
$form_by === '102' ||
$form_by === '9' ||
1032 $form_by === '10' ||
$form_by === '20' ||
$form_by === '104');
1035 // If we are doing the CSV export then generate the needed HTTP headers.
1036 // Otherwise generate HTML.
1038 if ($form_output == 3) {
1039 header("Pragma: public");
1040 header("Expires: 0");
1041 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
1042 header("Content-Type: application/force-download");
1043 header("Content-Disposition: attachment; filename=service_statistics_report.csv");
1044 header("Content-Description: File Transfer");
1049 <?php
html_header_show(); ?
>
1050 <title
><?php
echo $report_title; ?
></title
>
1052 <link rel
='stylesheet' href
='<?php echo $css_header ?>' type
='text/css'>
1053 <link rel
="stylesheet" href
="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery-datetimepicker/build/jquery.datetimepicker.min.css">
1055 <style type
="text/css">
1056 body
{ font
-family
:sans
-serif
; font
-size
:10pt
; font
-weight
:normal
}
1057 .dehead
{ color
:#000000; font-family:sans-serif; font-size:10pt; font-weight:bold }
1058 .detail
{ color
:#000000; font-family:sans-serif; font-size:10pt; font-weight:normal }
1061 <script type
="text/javascript" src
="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery/dist/jquery.min.js"></script
>
1062 <script type
="text/javascript" src
="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery-datetimepicker/build/jquery.datetimepicker.full.min.js"></script
>
1063 <script type
="text/javascript" src
="../../library/textformat.js?v=<?php echo $v_js_includes; ?>"></script
>
1065 <script language
="JavaScript">
1067 // Begin experimental code
1069 function selectByValue(sel
, val
) {
1070 for (var i
= 0; i
< sel
.options
.length
; ++i
) {
1071 if (sel
.options
[i
].value
== val
) sel
.options
[i
].selected
= true;
1075 function selreport() {
1076 var f
= document
.forms
[0];
1077 var isdis
= 'visible';
1078 var s
= f
.form_report
;
1079 var v
= (s
.selectedIndex
< 0) ?
'' : s
.options
[s
.selectedIndex
].value
;
1082 var a
= v
.split("|");
1083 f
.form_content
.selectedIndex
= -1;
1084 f
.form_by
.selectedIndex
= -1;
1085 f
['form_show[]'].selectedIndex
= -1;
1086 selectByValue(f
.form_content
, a
[0]);
1087 selectByValue(f
.form_by
, a
[1]);
1088 for (var i
= 2; i
< a
.length
; ++i
) {
1089 selectByValue(f
['form_show[]'], a
[i
]);
1092 f
.form_by
.style
.visibility
= isdis
;
1093 f
.form_content
.style
.visibility
= isdis
;
1094 f
['form_show[]'].style
.visibility
= isdis
;
1097 // End experimental code
1099 $
(document
).ready(function() {
1100 $
('.datepicker').datetimepicker({
1101 <?php
$datetimepicker_timepicker = false; ?
>
1102 <?php
$datetimepicker_showseconds = false; ?
>
1103 <?php
$datetimepicker_formatInput = false; ?
>
1104 <?php
require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?
>
1105 <?php
// can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
1112 <body leftmargin
='0' topmargin
='0' marginwidth
='0' marginheight
='0'>
1116 <h2
><?php
echo $report_title; ?
></h2
>
1118 <form name
='theform' method
='post'
1119 action
='ippf_statistics.php?t=<?php echo $report_type ?>'>
1121 <table border
='0' cellspacing
='5' cellpadding
='1'>
1123 <!-- Begin experimental code
-->
1124 <tr
<?php
echo (empty($arr_report)) ?
" style='display:none'" : ""; ?
>>
1125 <td valign
='top' class='dehead' nowrap
>
1126 <?php
xl('Report', 'e'); ?
>:
1128 <td valign
='top' class='detail' colspan
='3'>
1129 <select name
='form_report' title
='Predefined reports' onchange
='selreport()'>
1131 echo " <option value=''>" . xl('Custom') . "</option>\n";
1132 foreach ($arr_report as $key => $value) {
1133 echo " <option value='$key'";
1134 if ($key == $form_report) {
1138 echo ">" . $value . "</option>\n";
1143 <td valign
='top' class='detail'>
1147 <!-- End experimental code
-->
1150 <td valign
='top' class='dehead' nowrap
>
1151 <?php
xl('Rows', 'e'); ?
>:
1153 <td valign
='top' class='detail'>
1154 <select name
='form_by' title
='Left column of report'>
1156 foreach ($arr_by as $key => $value) {
1157 echo " <option value='$key'";
1158 if ($key == $form_by) {
1162 echo ">" . $value . "</option>\n";
1167 <td valign
='top' class='dehead' nowrap
>
1168 <?php
xl('Content', 'e'); ?
>:
1170 <td valign
='top' class='detail'>
1171 <select name
='form_content' title
='<?php xl('What is to be counted?
', 'e
'); ?>'>
1173 foreach ($arr_content as $key => $value) {
1174 echo " <option value='$key'";
1175 if ($key == $form_content) {
1179 echo ">$value</option>\n";
1184 <td valign
='top' class='detail'>
1189 <td valign
='top' class='dehead' nowrap
>
1190 <?php
xl('Columns', 'e'); ?
>:
1192 <td valign
='top' class='detail'>
1193 <select name
='form_show[]' size
='4' multiple
1194 title
='<?php xl('Hold down Ctrl to select multiple items
', 'e
'); ?>'>
1196 foreach ($arr_show as $key => $value) {
1197 $title = $value['title'];
1198 if (empty($title) ||
$key == 'title') {
1199 $title = $value['description'];
1202 echo " <option value='$key'";
1203 if (is_array($form_show) && in_array($key, $form_show)) {
1207 echo ">$title</option>\n";
1212 <td valign
='top' class='dehead' nowrap
>
1213 <?php
xl('Filters', 'e'); ?
>:
1215 <td colspan
='2' class='detail' style
='border-style:solid;border-width:1px;border-color:#cccccc'>
1218 <td valign
='top' class='detail' nowrap
>
1219 <?php
xl('Sex', 'e'); ?
>:
1221 <td
class='detail' valign
='top'>
1222 <select name
='form_sexes' title
='<?php xl('To filter by sex
', 'e
'); ?>'>
1224 foreach (array(3 => xl('Men and Women'), 1 => xl('Women Only'), 2 => xl('Men Only')) as $key => $value) {
1225 echo " <option value='$key'";
1226 if ($key == $form_sexes) {
1230 echo ">$value</option>\n";
1237 <td valign
='top' class='detail' nowrap
>
1238 <?php
xl('Facility', 'e'); ?
>:
1240 <td valign
='top' class='detail'>
1242 // Build a drop-down list of facilities.
1244 $fres = $facilityService->getAll();
1245 echo " <select name='form_facility'>\n";
1246 echo " <option value=''>-- All Facilities --\n";
1247 foreach ($fres as $frow) {
1248 $facid = $frow['id'];
1249 echo " <option value='$facid'";
1250 if ($facid == $_POST['form_facility']) {
1254 echo ">" . $frow['name'] . "\n";
1257 echo " </select>\n";
1262 <td colspan
='2' class='detail' nowrap
>
1263 <?php
xl('From', 'e'); ?
>
1264 <input type
='text' class='datepicker' name
='form_from_date' id
='form_from_date' size
='10' value
='<?php echo $from_date ?>'
1265 title
='Start date yyyy-mm-dd'>
1266 <?php
xl('To', 'e'); ?
>
1267 <input type
='text' class='datepicker' name
='form_to_date' id
='form_to_date' size
='10' value
='<?php echo $to_date ?>'
1268 title
='End date yyyy-mm-dd'>
1275 <td valign
='top' class='dehead' nowrap
>
1276 <?php
xl('To', 'e'); ?
>:
1278 <td colspan
='3' valign
='top' class='detail' nowrap
>
1280 foreach (array(1 => 'Screen', 2 => 'Printer', 3 => 'Export File') as $key => $value) {
1281 echo " <input type='radio' name='form_output' value='$key'";
1282 if ($key == $form_output) {
1286 echo " />$value ";
1290 <td align
='right' valign
='top' class='detail' nowrap
>
1291 <input type
='submit' name
='form_submit' value
='<?php xl('Submit
', 'e
'); ?>'
1292 title
='<?php xl('Click to generate the report
', 'e
'); ?>' />
1296 <td colspan
='5' height
="1">
1303 if ($_POST['form_submit']) {
1305 foreach ($arr_show as $askey => $asval) {
1306 if (substr($askey, 0, 1) == '.') {
1310 if ($askey == 'regdate' ||
$askey == 'sex' ||
$askey == 'DOB' ||
1311 $askey == 'lname' ||
$askey == 'fname' ||
$askey == 'mname' ||
1312 $askey == 'contrastart' ||
$askey == 'referral_source') {
1316 $pd_fields .= ', pd.' . $askey;
1320 if ($form_sexes == '1') {
1321 $sexcond = "AND pd.sex NOT LIKE 'Male' ";
1322 } else if ($form_sexes == '2') {
1323 $sexcond = "AND pd.sex LIKE 'Male' ";
1326 // In the case where content is contraceptive product sales, we
1327 // scan product sales at the top level because it is important to
1328 // account for each of them only once. For each sale we determine
1329 // the one and only IPPF code representing the primary related
1330 // contraceptive service, and that might be either a service in
1331 // the Tally Sheet or the IPPF code attached to the product.
1333 if ($form_content == 5) { // sales of contraceptive products
1334 $query = "SELECT " .
1335 "ds.pid, ds.encounter, ds.sale_date, ds.quantity, " .
1336 "d.cyp_factor, d.related_code, " .
1337 "pd.regdate, pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, " .
1338 "pd.contrastart, pd.referral_source$pd_fields, " .
1339 "fe.date AS encdate, fe.provider_id " .
1340 "FROM drug_sales AS ds " .
1341 "JOIN drugs AS d ON d.drug_id = ds.drug_id " .
1342 "JOIN patient_data AS pd ON pd.pid = ds.pid $sexcond" .
1343 "LEFT JOIN form_encounter AS fe ON fe.pid = ds.pid AND fe.encounter = ds.encounter " .
1344 "WHERE ds.sale_date >= '$from_date' AND " .
1345 "ds.sale_date <= '$to_date' AND " .
1346 "ds.pid > 0 AND ds.quantity != 0";
1348 if ($form_facility) {
1349 $query .= " AND fe.facility_id = '$form_facility'";
1352 $query .= " ORDER BY ds.pid, ds.encounter, ds.drug_id";
1353 $res = sqlStatement($query);
1355 while ($row = sqlFetchArray($res)) {
1358 if ($row['cyp_factor'] > 0) {
1362 $tmp = getRelatedContraceptiveCode($row);
1369 continue; // skip if not a contraceptive product
1372 // If there is a visit and it has a contraceptive service use that, else $prodcode.
1373 if (!empty($row['encounter'])) {
1374 $query = "SELECT " .
1375 "b.code_type, b.code, c.related_code " .
1376 "FROM billing AS b " .
1377 "LEFT OUTER JOIN codes AS c ON c.code_type = '12' AND " .
1378 "c.code = b.code AND c.modifier = b.modifier " .
1379 "WHERE b.pid = " . (0 +
$row['pid']) . " AND " .
1380 "b.encounter = " . (0 +
$row['encounter']) . " AND " .
1381 "b.activity = 1 AND b.code_type = 'MA' " .
1383 $bres = sqlStatement($query);
1384 while ($brow = sqlFetchArray($bres)) {
1385 $tmp = getRelatedContraceptiveCode($brow);
1393 // At this point $prodcode is the desired IPPF code, or empty if none.
1394 process_ippf_code($row, $prodcode, $row['quantity']);
1398 // Get referrals and related patient data.
1399 if ($form_content != 5 && ($form_by === '9' ||
$form_by === '10' ||
$form_by === '20' ||
$form_by === '1')) {
1400 $exttest = "t.refer_external = '1'";
1401 $datefld = "t.refer_date";
1403 if ($form_by === '9') {
1404 $exttest = "t.refer_external = '0'";
1405 } else if ($form_by === '20') {
1406 $datefld = "t.reply_date";
1409 $query = "SELECT " .
1410 "t.pid, t.refer_related_code, t.reply_related_code, " .
1411 "pd.regdate, pd.referral_source, " .
1412 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, " .
1413 "pd.contrastart$pd_fields " .
1414 "FROM transactions AS t " .
1415 "JOIN patient_data AS pd ON pd.pid = t.pid $sexcond" .
1416 "WHERE t.title = 'Referral' AND $datefld IS NOT NULL AND " .
1417 "$datefld >= '$from_date' AND $datefld <= '$to_date' AND $exttest " .
1418 "ORDER BY t.pid, t.id";
1419 $res = sqlStatement($query);
1420 while ($row = sqlFetchArray($res)) {
1421 process_referral($row);
1425 /*****************************************************************
1426 else if ($form_by === '12') {
1427 // We are reporting on a date range, and assume the applicable date is
1428 // the issue start date which is presumably also the date of pre-
1429 // abortion counseling. The issue end date and the surgery date are
1430 // not of interest here.
1431 $query = "SELECT " .
1432 "l.type, l.begdate, l.pid, " .
1433 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, pd.userlist5, " .
1434 "pd.country_code, pd.status, pd.state, pd.occupation, " .
1435 "lg.client_status, lg.ab_location " .
1436 "FROM lists AS l " .
1437 "JOIN patient_data AS pd ON pd.pid = l.pid $sexcond" .
1438 "LEFT OUTER JOIN lists_ippf_gcac AS lg ON l.type = 'ippf_gcac' AND lg.id = l.id " .
1439 // "LEFT OUTER JOIN lists_ippf_con AS lc ON l.type = 'contraceptive' AND lc.id = l.id " .
1440 "WHERE l.begdate >= '$from_date' AND l.begdate <= '$to_date' AND " .
1441 "l.activity = 1 AND l.type = 'ippf_gcac' " .
1442 "ORDER BY l.pid, l.id";
1443 $res = sqlStatement($query);
1444 while ($row = sqlFetchArray($res)) {
1445 process_issue($row);
1448 *****************************************************************/
1452 /*****************************************************************
1453 if ($form_by === '104' || $form_by === '105') {
1454 $query = "SELECT " .
1455 "d.name, d.related_code, ds.pid, ds.quantity, " .
1456 "pd.regdate, pd.referral_source, " .
1457 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, " .
1458 "pd.contrastart$pd_fields " .
1459 "FROM drug_sales AS ds " .
1460 "JOIN drugs AS d ON d.drug_id = ds.drug_id " .
1461 "JOIN patient_data AS pd ON pd.pid = ds.pid $sexcond" .
1462 "WHERE ds.sale_date IS NOT NULL AND ds.pid != 0 AND " .
1463 "ds.sale_date >= '$from_date' AND ds.sale_date <= '$to_date' " .
1464 "ORDER BY ds.pid, ds.sale_id";
1465 $res = sqlStatement($query);
1466 while ($row = sqlFetchArray($res)) {
1467 $key = "(Unspecified)";
1468 if (!empty($row['related_code'])) {
1469 $relcodes = explode(';', $row['related_code']);
1470 foreach ($relcodes as $codestring) {
1471 if ($codestring === '') continue;
1472 list($codetype, $code) = explode(':', $codestring);
1473 if ($codetype !== 'IPPF') continue;
1474 $key = getContraceptiveMethod($code);
1475 if (!empty($key)) break;
1476 $key = "(No Method)";
1479 if ($form_by === '104') $key .= " / " . $row['name'];
1480 loadColumnData($key, $row, $row['quantity']);
1484 if ($form_by !== '9' && $form_by !== '10' && $form_by !== '20' &&
1485 $form_by !== '104' && $form_by !== '105')
1486 *****************************************************************/
1488 if ($form_content != 5 && $form_by !== '9' && $form_by !== '10' && $form_by !== '20') {
1489 // This gets us all MA codes, with encounter and patient
1490 // info attached and grouped by patient and encounter.
1491 $query = "SELECT " .
1492 "fe.pid, fe.encounter, fe.date AS encdate, pd.regdate, " .
1493 "f.user AS provider, " .
1494 "pd.sex, pd.DOB, pd.lname, pd.fname, pd.mname, " .
1495 "pd.contrastart, pd.referral_source$pd_fields, " .
1496 "b.code_type, b.code, c.related_code, lo.title AS lo_title " .
1497 "FROM form_encounter AS fe " .
1498 "JOIN forms AS f ON f.pid = fe.pid AND f.encounter = fe.encounter AND " .
1499 "f.formdir = 'newpatient' AND f.form_id = fe.id AND f.deleted = 0 " .
1500 "JOIN patient_data AS pd ON pd.pid = fe.pid $sexcond" .
1501 "LEFT OUTER JOIN billing AS b ON " .
1502 "b.pid = fe.pid AND b.encounter = fe.encounter AND b.activity = 1 " .
1503 "AND b.code_type = 'MA' " .
1504 "LEFT OUTER JOIN codes AS c ON b.code_type = 'MA' AND c.code_type = '12' AND " .
1505 "c.code = b.code AND c.modifier = b.modifier " .
1506 "LEFT OUTER JOIN list_options AS lo ON " .
1507 "lo.list_id = 'superbill' AND lo.option_id = c.superbill " .
1508 "WHERE fe.date >= '$from_date 00:00:00' AND " .
1509 "fe.date <= '$to_date 23:59:59' ";
1511 if ($form_facility) {
1512 $query .= "AND fe.facility_id = '$form_facility' ";
1515 $query .= "ORDER BY fe.pid, fe.encounter, b.code";
1516 $res = sqlStatement($query);
1518 $prev_encounter = 0;
1520 while ($row = sqlFetchArray($res)) {
1521 if ($row['encounter'] != $prev_encounter) {
1522 $prev_encounter = $row['encounter'];
1523 process_visit($row);
1526 if ($row['code_type'] === 'MA') {
1527 process_ma_code($row);
1528 if (!empty($row['related_code'])) {
1529 $relcodes = explode(';', $row['related_code']);
1530 foreach ($relcodes as $codestring) {
1531 if ($codestring === '') {
1535 list($codetype, $code) = explode(':', $codestring);
1536 if ($codetype !== 'IPPF') {
1540 process_ippf_code($row, $code);
1547 // Sort everything by key for reporting.
1549 foreach ($arr_titles as $atkey => $dummy) {
1550 ksort($arr_titles[$atkey]);
1553 if ($form_output != 3) {
1554 echo "<table border='0' cellpadding='1' cellspacing='2' width='98%'>\n";
1555 } // end not csv export
1557 // Generate first column headings line, with category titles.
1559 genStartRow("bgcolor='#dddddd'");
1560 // If the key is an MA or IPPF code, then add a column for its description.
1561 if (uses_description($form_by)) {
1562 genHeadCell(array('', ''));
1567 // Generate headings for values to be shown.
1568 foreach ($form_show as $value) {
1569 if ($value == '.total') { // Total Services
1571 } else if ($value == '.age2') { // Age
1572 genHeadCell($arr_show[$value]['title'], false, 2);
1573 } else if ($value == '.age9') { // Age
1574 genHeadCell($arr_show[$value]['title'], false, 9);
1575 } else if ($arr_show[$value]['list_id']) {
1576 genHeadCell($arr_show[$value]['title'], false, count($arr_titles[$value]));
1577 } else if (!empty($arr_titles[$value])) {
1578 genHeadCell($arr_show[$value]['title'], false, count($arr_titles[$value]));
1582 if ($form_output != 3) {
1588 // Generate second column headings line, with individual titles.
1590 genStartRow("bgcolor='#dddddd'");
1591 // If the key is an MA or IPPF code, then add a column for its description.
1592 if (uses_description($form_by)) {
1593 genHeadCell(array($arr_by[$form_by], xl('Description')));
1595 genHeadCell($arr_by[$form_by]);
1598 // Generate headings for values to be shown.
1599 foreach ($form_show as $value) {
1600 if ($value == '.total') { // Total Services
1601 genHeadCell(xl('Total'));
1602 } else if ($value == '.age2') { // Age
1603 genHeadCell(xl('0-24'), true);
1604 genHeadCell(xl('25+'), true);
1605 } else if ($value == '.age9') { // Age
1606 genHeadCell(xl('0-10'), true);
1607 genHeadCell(xl('11-14'), true);
1608 genHeadCell(xl('15-19'), true);
1609 genHeadCell(xl('20-24'), true);
1610 genHeadCell(xl('25-29'), true);
1611 genHeadCell(xl('30-34'), true);
1612 genHeadCell(xl('35-39'), true);
1613 genHeadCell(xl('40-44'), true);
1614 genHeadCell(xl('45+'), true);
1615 } else if ($arr_show[$value]['list_id']) {
1616 foreach ($arr_titles[$value] as $key => $dummy) {
1617 genHeadCell(getListTitle($arr_show[$value]['list_id'], $key), true);
1619 } else if (!empty($arr_titles[$value])) {
1620 foreach ($arr_titles[$value] as $key => $dummy) {
1621 genHeadCell($key, true);
1626 if ($form_output != 3) {
1627 genHeadCell(xl('Total'), true);
1634 foreach ($areport as $key => $varr) {
1635 $bgcolor = (++
$encount & 1) ?
"#ddddff" : "#ffdddd";
1639 // If the key is an MA or IPPF code, then add a column for its description.
1640 if (uses_description($form_by)) {
1641 $dispkey = array($key, '');
1642 $type = $form_by === '102' ?
12 : 11; // MA or IPPF
1643 $crow = sqlQuery("SELECT code_text FROM codes WHERE " .
1644 "code_type = '$type' AND code = '$key' ORDER BY id LIMIT 1");
1645 if (!empty($crow['code_text'])) {
1646 $dispkey[1] = $crow['code_text'];
1650 genStartRow("bgcolor='$bgcolor'");
1652 genAnyCell($dispkey, false, 'detail');
1654 // This is the column index for accumulating column totals.
1656 $totalsvcs = $areport[$key]['.wom'] +
$areport[$key]['.men'];
1658 // Generate data for this row.
1659 foreach ($form_show as $value) {
1660 // if ($value == '1') { // Total Services
1661 if ($value == '.total') { // Total Services
1662 genNumCell($totalsvcs, $cnum++
);
1663 } else if ($value == '.age2') { // Age
1664 for ($i = 0; $i < 2; ++
$i) {
1665 genNumCell($areport[$key]['.age2'][$i], $cnum++
);
1667 } else if ($value == '.age9') { // Age
1668 for ($i = 0; $i < 9; ++
$i) {
1669 genNumCell($areport[$key]['.age9'][$i], $cnum++
);
1671 } else if (!empty($arr_titles[$value])) {
1672 foreach ($arr_titles[$value] as $title => $dummy) {
1673 genNumCell($areport[$key][$value][$title], $cnum++
);
1678 // Write the Total column data.
1679 if ($form_output != 3) {
1680 $atotals[$cnum] +
= $totalsvcs;
1681 genAnyCell($totalsvcs, true, 'dehead');
1687 if ($form_output != 3) {
1688 // Generate the line of totals.
1689 genStartRow("bgcolor='#dddddd'");
1691 // If the key is an MA or IPPF code, then add a column for its description.
1692 if (uses_description($form_by)) {
1693 genHeadCell(array(xl('Totals'), ''));
1695 genHeadCell(xl('Totals'));
1698 for ($cnum = 0; $cnum < count($atotals); ++
$cnum) {
1699 genHeadCell($atotals[$cnum], true);
1706 } // end of if refresh or export
1708 if ($form_output != 3) {
1713 <script language
='JavaScript'>
1715 <?php
if ($form_output == 2) { ?
>
1716 var win
= top
.printLogPrint ? top
: opener
.top
;
1717 win
.printLogPrint(window
);