Some sizing tweaks for patient PDF report, and cosmetic cleanup of vitals report...
[openemr.git] / interface / patient_file / report / custom_report.php
blob2aa72a1a6052dbf172139cc63442aab2aa0ccb55
1 <?php
2 // This program is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU General Public License
4 // as published by the Free Software Foundation; either version 2
5 // of the License, or (at your option) any later version.
7 require_once("../../globals.php");
8 require_once("$srcdir/forms.inc");
9 require_once("$srcdir/billing.inc");
10 require_once("$srcdir/pnotes.inc");
11 require_once("$srcdir/patient.inc");
12 require_once("$srcdir/options.inc.php");
13 require_once("$srcdir/acl.inc");
14 require_once("$srcdir/lists.inc");
15 require_once("$srcdir/report.inc");
16 require_once("$srcdir/classes/Document.class.php");
17 require_once("$srcdir/classes/Note.class.php");
18 require_once("$srcdir/formatting.inc.php");
19 require_once(dirname(__file__) . "/../../../custom/code_types.inc.php");
21 $PDF_OUTPUT = empty($_POST['pdf']) ? false : true;
23 if ($PDF_OUTPUT) {
24 require_once("$srcdir/html2pdf/html2pdf.class.php");
25 $pdf = new HTML2PDF('P', 'Letter', 'en');
26 ob_start();
29 // get various authorization levels
30 $auth_notes_a = acl_check('encounters', 'notes_a');
31 $auth_notes = acl_check('encounters', 'notes');
32 $auth_coding_a = acl_check('encounters', 'coding_a');
33 $auth_coding = acl_check('encounters', 'coding');
34 $auth_relaxed = acl_check('encounters', 'relaxed');
35 $auth_med = acl_check('patients' , 'med');
36 $auth_demo = acl_check('patients' , 'demo');
38 $printable = empty($_GET['printable']) ? false : true;
39 if ($PDF_OUTPUT) $printable = true;
40 unset($_GET['printable']);
42 // Number of columns in tables for insurance and encounter forms.
43 $N = $PDF_OUTPUT ? 4 : 6;
45 $first_issue = 1;
47 function getContent() {
48 global $web_root, $webserver_root;
49 $content = ob_get_clean();
50 // Fix a nasty html2pdf bug - it ignores document root!
51 $i = 0;
52 $wrlen = strlen($web_root);
53 $wsrlen = strlen($webserver_root);
54 while (true) {
55 $i = stripos($content, " src='/", $i + 1);
56 if ($i === false) break;
57 if (substr($content, $i+6, $wrlen) === $web_root &&
58 substr($content, $i+6, $wsrlen) !== $webserver_root)
60 $content = substr($content, 0, $i + 6) . $webserver_root . substr($content, $i + 6 + $wrlen);
63 return $content;
66 function postToGet($arin) {
67 $getstring="";
68 foreach ($arin as $key => $val) {
69 if (is_array($val)) {
70 foreach ($val as $k => $v) {
71 $getstring .= urlencode($key . "[]") . "=" . urlencode($v) . "&";
74 else {
75 $getstring .= urlencode($key) . "=" . urlencode($val) . "&";
78 return $getstring;
82 <?php if ($PDF_OUTPUT) { ?>
83 <link rel="stylesheet" href="<?php echo $webserver_root; ?>/interface/themes/style_pdf.css" type="text/css">
84 <?php } else {?>
85 <html>
86 <head>
87 <link rel="stylesheet" href="<?php echo $css_header;?>" type="text/css">
88 <?php } ?>
90 <?php // do not show stuff from report.php in forms that is encaspulated
91 // by div of navigateLink class. Specifically used for CAMOS, but
92 // can also be used by other forms that require output in the
93 // encounter listings output, but not in the custom report. ?>
94 <style> div.navigateLink {display:none;} </style>
96 <?php if (!$PDF_OUTPUT) { ?>
97 </head>
98 <body class="body_top">
99 <?php } ?>
101 <div id="report_custom"> <!-- large outer DIV -->
103 <?php
104 if (sizeof($_GET) > 0) { $ar = $_GET; }
105 else { $ar = $_POST; }
107 if ($printable) {
108 /*******************************************************************
109 $titleres = getPatientData($pid, "fname,lname,providerID");
110 $sql = "SELECT * FROM facility ORDER BY billing_location DESC LIMIT 1";
111 *******************************************************************/
112 $titleres = getPatientData($pid, "fname,lname,providerID,DATE_FORMAT(DOB,'%m/%d/%Y') as DOB_TS");
113 if ($_SESSION['pc_facility']) {
114 $sql = "select * from facility where id=" . $_SESSION['pc_facility'];
115 } else {
116 $sql = "SELECT * FROM facility ORDER BY billing_location DESC LIMIT 1";
118 /******************************************************************/
119 $db = $GLOBALS['adodb']['db'];
120 $results = $db->Execute($sql);
121 $facility = array();
122 if (!$results->EOF) {
123 $facility = $results->fields;
125 $practice_logo = "../../../custom/practice_logo.gif";
126 if (file_exists($practice_logo)) {
127 echo "<img src='$practice_logo' align='left'>\n";
130 <h2><?php echo $facility['name'] ?></h2>
131 <?php echo $facility['street'] ?><br>
132 <?php echo $facility['city'] ?>, <?php echo $facility['state'] ?> <?php echo $facility['postal_code'] ?><br clear='all'>
133 <?php echo $facility['phone'] ?><br>
135 <a href="javascript:window.close();"><span class='title'><?php echo $titleres['fname'] . " " . $titleres['lname']; ?></span></a><br>
136 <span class='text'><?php xl('Generated on','e'); ?>: <?php echo oeFormatShortDate(); ?></span>
137 <br><br>
139 <?php
142 else { // not printable
146 <a href="patient_report.php">
147 <span class='title'><?php xl('Patient Report','e'); ?></span>
148 <span class='back'><?php echo $tback;?></span>
149 </a><br><br>
150 <a href="custom_report.php?printable=1&<?php print postToGet($ar); ?>" class='link_submit' target='new'>
151 [<?php xl('Printable Version','e'); ?>]
152 </a><br>
154 <?php } // end not printable ?>
156 <?php
158 // include ALL form's report.php files
159 $inclookupres = sqlStatement("select distinct formdir from forms where pid = '$pid' AND deleted=0");
160 while($result = sqlFetchArray($inclookupres)) {
161 // include_once("{$GLOBALS['incdir']}/forms/" . $result{"formdir"} . "/report.php");
162 $formdir = $result['formdir'];
163 if (substr($formdir,0,3) == 'LBF')
164 include_once($GLOBALS['incdir'] . "/forms/LBF/report.php");
165 else
166 include_once($GLOBALS['incdir'] . "/forms/$formdir/report.php");
169 // For each form field from patient_report.php...
171 foreach ($ar as $key => $val) {
172 if ($key == 'pdf') continue;
174 // These are the top checkboxes (demographics, allergies, etc.).
176 if (stristr($key,"include_")) {
178 if ($val == "demographics") {
180 echo "<hr />";
181 echo "<div class='text demographics' id='DEM'>\n";
182 print "<h1>".xl('Patient Data').":</h1>";
183 // printRecDataOne($patient_data_array, getRecPatientData ($pid), $N);
184 $result1 = getPatientData($pid);
185 $result2 = getEmployerData($pid);
186 echo " <table>\n";
187 display_layout_rows('DEM', $result1, $result2);
188 echo " </table>\n";
189 echo "</div>\n";
191 } elseif ($val == "history") {
193 echo "<hr />";
194 echo "<div class='text history' id='HIS'>\n";
195 if (acl_check('patients', 'med')) {
196 print "<h1>".xl('History Data').":</h1>";
197 // printRecDataOne($history_data_array, getRecHistoryData ($pid), $N);
198 $result1 = getHistoryData($pid);
199 echo " <table>\n";
200 display_layout_rows('HIS', $result1);
201 echo " </table>\n";
203 echo "</div>";
205 // } elseif ($val == "employer") {
206 // print "<br><span class='bold'>".xl('Employer Data').":</span><br>";
207 // printRecDataOne($employer_data_array, getRecEmployerData ($pid), $N);
209 } elseif ($val == "insurance") {
211 echo "<hr />";
212 echo "<div class='text insurance'>";
213 echo "<h1>".xl('Insurance Data').":</h1>";
214 print "<br><span class=bold>".xl('Primary Insurance Data').":</span><br>";
215 printRecDataOne($insurance_data_array, getRecInsuranceData ($pid,"primary"), $N);
216 print "<span class=bold>".xl('Secondary Insurance Data').":</span><br>";
217 printRecDataOne($insurance_data_array, getRecInsuranceData ($pid,"secondary"), $N);
218 print "<span class=bold>".xl('Tertiary Insurance Data').":</span><br>";
219 printRecDataOne($insurance_data_array, getRecInsuranceData ($pid,"tertiary"), $N);
220 echo "</div>";
222 } elseif ($val == "billing") {
224 echo "<hr />";
225 echo "<div class='text billing'>";
226 print "<h1>".xl('Billing Information').":</h1>";
227 if (count($ar['newpatient']) > 0) {
228 $billings = array();
229 echo "<table>";
230 echo "<tr><td width='400' class='bold'>Code</td><td class='bold'>".xl('Fee')."</td></tr>\n";
231 $total = 0.00;
232 $copays = 0.00;
233 foreach ($ar['newpatient'] as $be) {
234 $ta = split(":",$be);
235 $billing = getPatientBillingEncounter($pid,$ta[1]);
236 $billings[] = $billing;
237 foreach ($billing as $b) {
238 echo "<tr>\n";
239 echo "<td class=text>";
240 echo $b['code_type'] . ":\t" . $b['code'] . "&nbsp;". $b['modifier'] . "&nbsp;&nbsp;&nbsp;" . $b['code_text'] . "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
241 echo "</td>\n";
242 echo "<td class=text>";
243 echo oeFormatMoney($b['fee']);
244 echo "</td>\n";
245 echo "</tr>\n";
246 $total += $b['fee'];
247 if ($b['code_type'] == "COPAY") {
248 $copays += $b['fee'];
252 echo "<tr><td>&nbsp;</td></tr>";
253 echo "<tr><td class=bold>".xl('Sub-Total')."</td><td class=text>" . oeFormatMoney($total + abs($copays)) . "</td></tr>";
254 echo "<tr><td class=bold>".xl('Paid')."</td><td class=text>" . oeFormatMoney(abs($copays)) . "</td></tr>";
255 echo "<tr><td class=bold>".xl('Total')."</td><td class=text>" . oeFormatMoney($total) . "</td></tr>";
256 echo "</table>";
257 echo "<pre>";
258 //print_r($billings);
259 echo "</pre>";
260 } else {
261 printPatientBilling($pid);
263 echo "</div>\n"; // end of billing DIV
265 /****
267 } elseif ($val == "allergies") {
269 print "<span class=bold>Patient Allergies:</span><br>";
270 printListData($pid, "allergy", "1");
272 } elseif ($val == "medications") {
274 print "<span class=bold>Patient Medications:</span><br>";
275 printListData($pid, "medication", "1");
277 } elseif ($val == "medical_problems") {
279 print "<span class=bold>Patient Medical Problems:</span><br>";
280 printListData($pid, "medical_problem", "1");
282 ****/
284 } elseif ($val == "immunizations") {
286 if (acl_check('patients', 'med')) {
287 echo "<hr />";
288 echo "<div class='text immunizations'>\n";
289 print "<h1>".xl('Patient Immunization').":</h1>";
290 $sql = "select i1.immunization_id, i1.administered_date, substring(i1.note,1,20) as immunization_note, c.code_text_short ".
291 " from immunizations i1 ".
292 " left join code_types ct on ct.ct_key = 'CVX' ".
293 " left join codes c on c.code_type = ct.ct_id AND i1.cvx_code = c.code ".
294 " where i1.patient_id = '$pid' ".
295 " order by administered_date desc";
296 $result = sqlStatement($sql);
297 while ($row=sqlFetchArray($result)) {
298 // Figure out which name to use (ie. from cvx list or from the custom list)
299 if ($GLOBALS['use_custom_immun_list']) {
300 $vaccine_display = generate_display_field(array('data_type'=>'1','list_id'=>'immunizations'), $row['immunization_id']);
302 else {
303 if (!empty($row['code_text_short'])) {
304 $vaccine_display = htmlspecialchars( xl($row['code_text_short']), ENT_NOQUOTES);
306 else {
307 $vaccine_display = generate_display_field(array('data_type'=>'1','list_id'=>'immunizations'), $row['immunization_id']);
310 echo $row['administered_date'] . " - " . $vaccine_display;
311 if ($row['immunization_note']) {
312 echo " - " . $row['immunization_note'];
314 echo "<br>\n";
316 echo "</div>\n";
319 // communication report
320 } elseif ($val == "batchcom") {
322 echo "<hr />";
323 echo "<div class='text transactions'>\n";
324 print "<h1>".xl('Patient Communication sent').":</h1>";
325 $sql="SELECT concat( 'Messsage Type: ', batchcom.msg_type, ', Message Subject: ', batchcom.msg_subject, ', Sent on:', batchcom.msg_date_sent ) AS batchcom_data, batchcom.msg_text, concat( users.fname, users.lname ) AS user_name FROM `batchcom` JOIN `users` ON users.id = batchcom.sent_by WHERE batchcom.patient_id='$pid'";
326 // echo $sql;
327 $result = sqlStatement($sql);
328 while ($row=sqlFetchArray($result)) {
329 echo $row{'batchcom_data'}.", By: ".$row{'user_name'}."<br>Text:<br> ".$row{'msg_txt'}."<br>\n";
331 echo "</div>\n";
333 } elseif ($val == "notes") {
335 echo "<hr />";
336 echo "<div class='text notes'>\n";
337 print "<h1>".xl('Patient Notes').":</h1>";
338 printPatientNotes($pid);
339 echo "</div>";
341 } elseif ($val == "transactions") {
343 echo "<hr />";
344 echo "<div class='text transactions'>\n";
345 print "<h1>".xl('Patient Transactions').":</h1>";
346 printPatientTransactions($pid);
347 echo "</div>";
351 } else {
353 // Documents is an array of checkboxes whose values are document IDs.
355 if ($key == "documents") {
357 echo "<hr />";
358 echo "<div class='text documents'>";
359 foreach($val as $valkey => $valvalue) {
360 $document_id = $valvalue;
361 if (!is_numeric($document_id)) continue;
362 $d = new Document($document_id);
363 $fname = basename($d->get_url());
364 $couch_docid = $d->get_couch_docid();
365 $couch_revid = $d->get_couch_revid();
366 $extension = substr($fname, strrpos($fname,"."));
367 echo "<h1>" . xl('Document') . " '" . $fname ."'</h1>";
368 $notes = Note::notes_factory($d->get_id());
369 if (!empty($notes)) echo "<table>";
370 foreach ($notes as $note) {
371 echo '<tr>';
372 echo '<td>' . xl('Note') . ' #' . $note->get_id() . '</td>';
373 echo '</tr>';
374 echo '<tr>';
375 echo '<td>' . xl('Date') . ': ' . oeFormatShortDate($note->get_date()) . '</td>';
376 echo '</tr>';
377 echo '<tr>';
378 echo '<td>'.$note->get_note().'<br><br></td>';
379 echo '</tr>';
381 if (!empty($notes)) echo "</table>";
383 $url_file = $d->get_url_filepath();
384 if($couch_docid && $couch_revid){
385 $url_file = $d->get_couch_url($pid,$encounter);
387 // just grab the last two levels, which contain filename and patientid
388 $from_all = explode("/",$url_file);
389 $from_filename = array_pop($from_all);
390 $from_patientid = array_pop($from_all);
391 if($couch_docid && $couch_revid) {
392 $from_file = $GLOBALS['OE_SITE_DIR'] . '/documents/temp/' . $from_filename;
393 $to_file = substr($from_file, 0, strrpos($from_file, '.')) . '_converted.jpg';
395 else {
396 $from_file = $GLOBALS["fileroot"] . "/sites/" . $_SESSION['site_id'] .
397 '/documents/' . $from_patientid . '/' . $from_filename;
398 $to_file = substr($from_file, 0, strrpos($from_file, '.')) . '_converted.jpg';
401 if ($extension == ".png" || $extension == ".jpg" || $extension == ".jpeg" || $extension == ".gif") {
402 if ($PDF_OUTPUT) {
403 // OK to link to the image file because it will be accessed by the
404 // HTML2PDF parser and not the browser.
405 $from_rel = $web_root . substr($from_file, strlen($webserver_root));
406 echo "<img src='$from_rel'><br><br>";
408 else {
409 echo "<img src='" . $GLOBALS['webroot'] .
410 "/controller.php?document&retrieve&patient_id=&document_id=" .
411 $document_id . "&as_file=false'><br><br>";
414 else {
416 // Most clinic documents are expected to be PDFs, and in that happy case
417 // we can avoid the lengthy image conversion process.
418 if ($PDF_OUTPUT && $extension == ".pdf") {
419 // HTML to PDF conversion will fail if there are open tags.
420 echo "</div></div>\n";
421 $content = getContent();
422 // $pdf->setDefaultFont('Arial');
423 $pdf->writeHTML($content, false);
424 $pagecount = $pdf->pdf->setSourceFile($from_file);
425 for($i = 0; $i < $pagecount; ++$i){
426 $pdf->pdf->AddPage();
427 $itpl = $pdf->pdf->importPage($i + 1, '/MediaBox');
428 $pdf->pdf->useTemplate($itpl);
430 // Make sure whatever follows is on a new page.
431 $pdf->pdf->AddPage();
432 // Resume output buffering and the above-closed tags.
433 ob_start();
434 echo "<div><div class='text documents'>\n";
436 else {
437 if (! is_file($to_file)) exec("convert -density 200 \"$from_file\" -append -resize 850 \"$to_file\"");
438 if (is_file($to_file)) {
439 if ($PDF_OUTPUT) {
440 // OK to link to the image file because it will be accessed by the
441 // HTML2PDF parser and not the browser.
442 echo "<img src='$to_file'><br><br>";
444 else {
445 echo "<img src='" . $GLOBALS['webroot'] .
446 "/controller.php?document&retrieve&patient_id=&document_id=" .
447 $document_id . "&as_file=false&original_file=false'><br><br>";
449 } else {
450 echo "<b>NOTE</b>: " . xl('Document') . "'" . $fname . "' " .
451 xl('cannot be converted to JPEG. Perhaps ImageMagick is not installed?') . "<br><br>";
452 if($couch_docid && $couch_revid) {
453 unlink($from_file);
458 } // end if-else
459 } // end Documents loop
460 echo "</div>";
462 } else if (strpos($key, "issue_") === 0) {
463 // display patient Issues
465 if ($first_issue) {
466 $prevIssueType = 'asdf1234!@#$'; // random junk so as to not match anything
467 $first_issue = 0;
468 echo "<hr />";
469 echo "<h1>".xl("Issues")."</h1>";
471 preg_match('/^(.*)_(\d+)$/', $key, $res);
472 $rowid = $res[2];
473 $irow = sqlQuery("SELECT type, title, comments, diagnosis " .
474 "FROM lists WHERE id = '$rowid'");
475 $diagnosis = $irow['diagnosis'];
476 if ($prevIssueType != $irow['type']) {
477 // output a header for each Issue Type we encounter
478 $disptype = $ISSUE_TYPES[$irow['type']][0];
479 echo "<div class='issue_type'>" . $disptype . ":</div>\n";
480 $prevIssueType = $irow['type'];
482 echo "<div class='text issue'>";
483 echo "<span class='issue_title'>" . $irow['title'] . ":</span>";
484 echo "<span class='issue_comments'> " . $irow['comments'] . "</span>\n";
485 // Show issue's chief diagnosis and its description:
486 if ($diagnosis) {
487 echo "<div class='text issue_diag'>";
488 echo "<span class='bold'>[".xl('Diagnosis')."]</span><br>";
489 $dcodes = explode(";", $diagnosis);
490 foreach ($dcodes as $dcode) {
491 echo "<span class='italic'>".$dcode."</span>: ";
492 echo lookup_code_descriptions($dcode)."<br>\n";
494 //echo $diagnosis." -- ".lookup_code_descriptions($diagnosis)."\n";
495 echo "</div>";
498 // Supplemental data for GCAC or Contraception issues.
499 if ($irow['type'] == 'ippf_gcac') {
500 echo " <table>\n";
501 display_layout_rows('GCA', sqlQuery("SELECT * FROM lists_ippf_gcac WHERE id = '$rowid'"));
502 echo " </table>\n";
504 else if ($irow['type'] == 'contraceptive') {
505 echo " <table>\n";
506 display_layout_rows('CON', sqlQuery("SELECT * FROM lists_ippf_con WHERE id = '$rowid'"));
507 echo " </table>\n";
510 echo "</div>\n"; //end the issue DIV
512 } else {
513 // we have an "encounter form" form field whose name is like
514 // dirname_formid, with a value which is the encounter ID.
516 // display encounter forms, encoded as a POST variable
517 // in the format: <formdirname_formid>=<encounterID>
519 if (($auth_notes_a || $auth_notes || $auth_coding_a || $auth_coding || $auth_med || $auth_relaxed)) {
520 $form_encounter = $val;
521 preg_match('/^(.*)_(\d+)$/', $key, $res);
522 $form_id = $res[2];
523 $formres = getFormNameByFormdirAndFormid($res[1],$form_id);
524 $dateres = getEncounterDateByEncounter($form_encounter);
526 if ($res[1] == 'newpatient') {
527 echo "<div class='text encounter'>\n";
528 echo "<h1>" . xl($formres["form_name"]) . "</h1>";
530 else {
531 echo "<div class='text encounter_form'>";
532 echo "<h1>" . xl_form_title($formres["form_name"]) . "</h1>";
535 // show the encounter's date
536 echo "(" . oeFormatSDFT(strtotime($dateres["date"])) . ") ";
537 if ($res[1] == 'newpatient') {
538 // display the provider info
539 $tmp = sqlQuery("SELECT u.title, u.fname, u.mname, u.lname " .
540 "FROM forms AS f, users AS u WHERE " .
541 "f.pid = '$pid' AND f.encounter = '$form_encounter' AND " .
542 "f.formdir = 'newpatient' AND u.username = f.user " .
543 " AND f.deleted=0 ". //--JRM--
544 "ORDER BY f.id LIMIT 1");
545 echo ' '. xl('Provider') . ': ' . $tmp['title'] . ' ' .
546 $tmp['fname'] . ' ' . $tmp['mname'] . ' ' . $tmp['lname'];
548 echo "<br>\n";
550 // call the report function for the form
551 if (substr($res[1],0,3) == 'LBF')
552 call_user_func("lbf_report", $pid, $form_encounter, $N, $form_id, $res[1]);
553 else
554 call_user_func($res[1] . "_report", $pid, $form_encounter, $N, $form_id);
556 if ($res[1] == 'newpatient') {
557 // display billing info
558 $bres = sqlStatement("SELECT b.date, b.code, b.code_text " .
559 "FROM billing AS b, code_types AS ct WHERE " .
560 "b.pid = ? AND " .
561 "b.encounter = ? AND " .
562 "b.activity = 1 AND " .
563 "b.code_type = ct.ct_key AND " .
564 "ct.ct_diag = 0 " .
565 "ORDER BY b.date",
566 array($pid, $form_encounter));
567 while ($brow=sqlFetchArray($bres)) {
568 echo "<span class='bold'>&nbsp;".xl('Procedure').": </span><span class='text'>" .
569 $brow['code'] . " " . $brow['code_text'] . "</span><br>\n";
573 print "</div>";
575 } // end auth-check for encounter forms
577 } // end if('issue_')... else...
579 } // end if('include_')... else...
581 } // end $ar loop
583 if ($printable)
584 echo "<br /><br />" . xl('Signature') . ": _______________________________<br />";
587 </div> <!-- end of report_custom DIV -->
589 <?php
590 if ($PDF_OUTPUT) {
591 $content = getContent();
592 // $pdf->setDefaultFont('Arial');
593 $pdf->writeHTML($content, false);
594 $pdf->Output('report.pdf', 'D'); // D = Download, I = Inline
596 else {
598 </body>
599 </html>
600 <?php } ?>