Modified patient report for PDF output and faster inclusion of documents.
[openemr.git] / interface / patient_file / report / custom_report.php
blobeffcf2ba93848b2856b2d8b19f54ba1d99b1725e
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 $N = 6;
43 $first_issue = 1;
45 function getContent() {
46 global $web_root, $webserver_root;
47 $content = ob_get_clean();
48 // Fix a nasty html2pdf bug - it ignores document root!
49 $i = 0;
50 $wrlen = strlen($web_root);
51 $wsrlen = strlen($webserver_root);
52 while (true) {
53 $i = stripos($content, " src='/", $i + 1);
54 if ($i === false) break;
55 if (substr($content, $i+6, $wrlen) === $web_root &&
56 substr($content, $i+6, $wsrlen) !== $webserver_root)
58 $content = substr($content, 0, $i + 6) . $webserver_root . substr($content, $i + 6 + $wrlen);
61 return $content;
64 function postToGet($arin) {
65 $getstring="";
66 foreach ($arin as $key => $val) {
67 if (is_array($val)) {
68 foreach ($val as $k => $v) {
69 $getstring .= urlencode($key . "[]") . "=" . urlencode($v) . "&";
72 else {
73 $getstring .= urlencode($key) . "=" . urlencode($val) . "&";
76 return $getstring;
80 <?php if ($PDF_OUTPUT) { ?>
81 <link rel="stylesheet" href="<?php echo $webserver_root; ?>/interface/themes/style_pdf.css" type="text/css">
82 <?php } else {?>
83 <html>
84 <head>
85 <link rel="stylesheet" href="<?php echo $css_header;?>" type="text/css">
86 <?php } ?>
88 <?php // do not show stuff from report.php in forms that is encaspulated
89 // by div of navigateLink class. Specifically used for CAMOS, but
90 // can also be used by other forms that require output in the
91 // encounter listings output, but not in the custom report. ?>
92 <style> div.navigateLink {display:none;} </style>
94 <?php if (!$PDF_OUTPUT) { ?>
95 </head>
96 <body class="body_top">
97 <?php } ?>
99 <div id="report_custom"> <!-- large outer DIV -->
101 <?php
102 if (sizeof($_GET) > 0) { $ar = $_GET; }
103 else { $ar = $_POST; }
105 if ($printable) {
106 /*******************************************************************
107 $titleres = getPatientData($pid, "fname,lname,providerID");
108 $sql = "SELECT * FROM facility ORDER BY billing_location DESC LIMIT 1";
109 *******************************************************************/
110 $titleres = getPatientData($pid, "fname,lname,providerID,DATE_FORMAT(DOB,'%m/%d/%Y') as DOB_TS");
111 if ($_SESSION['pc_facility']) {
112 $sql = "select * from facility where id=" . $_SESSION['pc_facility'];
113 } else {
114 $sql = "SELECT * FROM facility ORDER BY billing_location DESC LIMIT 1";
116 /******************************************************************/
117 $db = $GLOBALS['adodb']['db'];
118 $results = $db->Execute($sql);
119 $facility = array();
120 if (!$results->EOF) {
121 $facility = $results->fields;
123 $practice_logo = "../../../custom/practice_logo.gif";
124 if (file_exists($practice_logo)) {
125 echo "<img src='$practice_logo' align='left'>\n";
128 <h2><?php echo $facility['name'] ?></h2>
129 <?php echo $facility['street'] ?><br>
130 <?php echo $facility['city'] ?>, <?php echo $facility['state'] ?> <?php echo $facility['postal_code'] ?><br clear='all'>
131 <?php echo $facility['phone'] ?><br>
133 <a href="javascript:window.close();"><span class='title'><?php echo $titleres['fname'] . " " . $titleres['lname']; ?></span></a><br>
134 <span class='text'><?php xl('Generated on','e'); ?>: <?php echo oeFormatShortDate(); ?></span>
135 <br><br>
137 <?php
140 else { // not printable
144 <a href="patient_report.php">
145 <span class='title'><?php xl('Patient Report','e'); ?></span>
146 <span class='back'><?php echo $tback;?></span>
147 </a><br><br>
148 <a href="custom_report.php?printable=1&<?php print postToGet($ar); ?>" class='link_submit' target='new'>
149 [<?php xl('Printable Version','e'); ?>]
150 </a><br>
152 <?php } // end not printable ?>
154 <?php
156 // include ALL form's report.php files
157 $inclookupres = sqlStatement("select distinct formdir from forms where pid = '$pid' AND deleted=0");
158 while($result = sqlFetchArray($inclookupres)) {
159 // include_once("{$GLOBALS['incdir']}/forms/" . $result{"formdir"} . "/report.php");
160 $formdir = $result['formdir'];
161 if (substr($formdir,0,3) == 'LBF')
162 include_once($GLOBALS['incdir'] . "/forms/LBF/report.php");
163 else
164 include_once($GLOBALS['incdir'] . "/forms/$formdir/report.php");
167 // For each form field from patient_report.php...
169 foreach ($ar as $key => $val) {
171 // These are the top checkboxes (demographics, allergies, etc.).
173 if (stristr($key,"include_")) {
175 if ($val == "demographics") {
177 echo "<hr />";
178 echo "<div class='text demographics' id='DEM'>\n";
179 print "<h1>".xl('Patient Data').":</h1>";
180 // printRecDataOne($patient_data_array, getRecPatientData ($pid), $N);
181 $result1 = getPatientData($pid);
182 $result2 = getEmployerData($pid);
183 echo " <table>\n";
184 display_layout_rows('DEM', $result1, $result2);
185 echo " </table>\n";
186 echo "</div>\n";
188 } elseif ($val == "history") {
190 echo "<hr />";
191 echo "<div class='text history' id='HIS'>\n";
192 if (acl_check('patients', 'med')) {
193 print "<h1>".xl('History Data').":</h1>";
194 // printRecDataOne($history_data_array, getRecHistoryData ($pid), $N);
195 $result1 = getHistoryData($pid);
196 echo " <table>\n";
197 display_layout_rows('HIS', $result1);
198 echo " </table>\n";
200 echo "</div>";
202 // } elseif ($val == "employer") {
203 // print "<br><span class='bold'>".xl('Employer Data').":</span><br>";
204 // printRecDataOne($employer_data_array, getRecEmployerData ($pid), $N);
206 } elseif ($val == "insurance") {
208 echo "<hr />";
209 echo "<div class='text insurance'>";
210 echo "<h1>".xl('Insurance Data').":</h1>";
211 print "<br><span class=bold>".xl('Primary Insurance Data').":</span><br>";
212 printRecDataOne($insurance_data_array, getRecInsuranceData ($pid,"primary"), $N);
213 print "<span class=bold>".xl('Secondary Insurance Data').":</span><br>";
214 printRecDataOne($insurance_data_array, getRecInsuranceData ($pid,"secondary"), $N);
215 print "<span class=bold>".xl('Tertiary Insurance Data').":</span><br>";
216 printRecDataOne($insurance_data_array, getRecInsuranceData ($pid,"tertiary"), $N);
217 echo "</div>";
219 } elseif ($val == "billing") {
221 echo "<hr />";
222 echo "<div class='text billing'>";
223 print "<h1>".xl('Billing Information').":</h1>";
224 if (count($ar['newpatient']) > 0) {
225 $billings = array();
226 echo "<table>";
227 echo "<tr><td width='400' class='bold'>Code</td><td class='bold'>".xl('Fee')."</td></tr>\n";
228 $total = 0.00;
229 $copays = 0.00;
230 foreach ($ar['newpatient'] as $be) {
231 $ta = split(":",$be);
232 $billing = getPatientBillingEncounter($pid,$ta[1]);
233 $billings[] = $billing;
234 foreach ($billing as $b) {
235 echo "<tr>\n";
236 echo "<td class=text>";
237 echo $b['code_type'] . ":\t" . $b['code'] . "&nbsp;". $b['modifier'] . "&nbsp;&nbsp;&nbsp;" . $b['code_text'] . "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
238 echo "</td>\n";
239 echo "<td class=text>";
240 echo oeFormatMoney($b['fee']);
241 echo "</td>\n";
242 echo "</tr>\n";
243 $total += $b['fee'];
244 if ($b['code_type'] == "COPAY") {
245 $copays += $b['fee'];
249 echo "<tr><td>&nbsp;</td></tr>";
250 echo "<tr><td class=bold>".xl('Sub-Total')."</td><td class=text>" . oeFormatMoney($total + abs($copays)) . "</td></tr>";
251 echo "<tr><td class=bold>".xl('Paid')."</td><td class=text>" . oeFormatMoney(abs($copays)) . "</td></tr>";
252 echo "<tr><td class=bold>".xl('Total')."</td><td class=text>" . oeFormatMoney($total) . "</td></tr>";
253 echo "</table>";
254 echo "<pre>";
255 //print_r($billings);
256 echo "</pre>";
257 } else {
258 printPatientBilling($pid);
260 echo "</div>\n"; // end of billing DIV
262 /****
264 } elseif ($val == "allergies") {
266 print "<span class=bold>Patient Allergies:</span><br>";
267 printListData($pid, "allergy", "1");
269 } elseif ($val == "medications") {
271 print "<span class=bold>Patient Medications:</span><br>";
272 printListData($pid, "medication", "1");
274 } elseif ($val == "medical_problems") {
276 print "<span class=bold>Patient Medical Problems:</span><br>";
277 printListData($pid, "medical_problem", "1");
279 ****/
281 } elseif ($val == "immunizations") {
283 if (acl_check('patients', 'med')) {
284 echo "<hr />";
285 echo "<div class='text immunizations'>\n";
286 print "<h1>".xl('Patient Immunization').":</h1>";
287 $sql = "select i1.immunization_id, i1.administered_date, substring(i1.note,1,20) as immunization_note, c.code_text_short ".
288 " from immunizations i1 ".
289 " left join code_types ct on ct.ct_key = 'CVX' ".
290 " left join codes c on c.code_type = ct.ct_id AND i1.cvx_code = c.code ".
291 " where i1.patient_id = '$pid' ".
292 " order by administered_date desc";
293 $result = sqlStatement($sql);
294 while ($row=sqlFetchArray($result)) {
295 // Figure out which name to use (ie. from cvx list or from the custom list)
296 if ($GLOBALS['use_custom_immun_list']) {
297 $vaccine_display = generate_display_field(array('data_type'=>'1','list_id'=>'immunizations'), $row['immunization_id']);
299 else {
300 if (!empty($row['code_text_short'])) {
301 $vaccine_display = htmlspecialchars( xl($row['code_text_short']), ENT_NOQUOTES);
303 else {
304 $vaccine_display = generate_display_field(array('data_type'=>'1','list_id'=>'immunizations'), $row['immunization_id']);
307 echo $row['administered_date'] . " - " . $vaccine_display;
308 if ($row['immunization_note']) {
309 echo " - " . $row['immunization_note'];
311 echo "<br>\n";
313 echo "</div>\n";
316 // communication report
317 } elseif ($val == "batchcom") {
319 echo "<hr />";
320 echo "<div class='text transactions'>\n";
321 print "<h1>".xl('Patient Communication sent').":</h1>";
322 $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'";
323 // echo $sql;
324 $result = sqlStatement($sql);
325 while ($row=sqlFetchArray($result)) {
326 echo $row{'batchcom_data'}.", By: ".$row{'user_name'}."<br>Text:<br> ".$row{'msg_txt'}."<br>\n";
328 echo "</div>\n";
330 } elseif ($val == "notes") {
332 echo "<hr />";
333 echo "<div class='text notes'>\n";
334 print "<h1>".xl('Patient Notes').":</h1>";
335 printPatientNotes($pid);
336 echo "</div>";
338 } elseif ($val == "transactions") {
340 echo "<hr />";
341 echo "<div class='text transactions'>\n";
342 print "<h1>".xl('Patient Transactions').":</h1>";
343 printPatientTransactions($pid);
344 echo "</div>";
348 } else {
350 // Documents is an array of checkboxes whose values are document IDs.
352 if ($key == "documents") {
354 echo "<hr />";
355 echo "<div class='text documents'>";
356 foreach($val as $valkey => $valvalue) {
357 $document_id = $valvalue;
358 if (!is_numeric($document_id)) continue;
359 $d = new Document($document_id);
360 $fname = basename($d->get_url());
361 $couch_docid = $d->get_couch_docid();
362 $couch_revid = $d->get_couch_revid();
363 $extension = substr($fname, strrpos($fname,"."));
364 echo "<h1>" . xl('Document') . " '" . $fname ."'</h1>";
365 $notes = Note::notes_factory($d->get_id());
366 if (!empty($notes)) echo "<table>";
367 foreach ($notes as $note) {
368 echo '<tr>';
369 echo '<td>' . xl('Note') . ' #' . $note->get_id() . '</td>';
370 echo '</tr>';
371 echo '<tr>';
372 echo '<td>' . xl('Date') . ': ' . oeFormatShortDate($note->get_date()) . '</td>';
373 echo '</tr>';
374 echo '<tr>';
375 echo '<td>'.$note->get_note().'<br><br></td>';
376 echo '</tr>';
378 if (!empty($notes)) echo "</table>";
380 $url_file = $d->get_url_filepath();
381 if($couch_docid && $couch_revid){
382 $url_file = $d->get_couch_url($pid,$encounter);
384 // just grab the last two levels, which contain filename and patientid
385 $from_all = explode("/",$url_file);
386 $from_filename = array_pop($from_all);
387 $from_patientid = array_pop($from_all);
388 if($couch_docid && $couch_revid) {
389 $from_file = $GLOBALS['OE_SITE_DIR'] . '/documents/temp/' . $from_filename;
390 $to_file = substr($from_file, 0, strrpos($from_file, '.')) . '_converted.jpg';
392 else {
393 $from_file = $GLOBALS["fileroot"] . "/sites/" . $_SESSION['site_id'] .
394 '/documents/' . $from_patientid . '/' . $from_filename;
395 $to_file = substr($from_file, 0, strrpos($from_file, '.')) . '_converted.jpg';
398 if ($extension == ".png" || $extension == ".jpg" || $extension == ".jpeg" || $extension == ".gif") {
399 if ($PDF_OUTPUT) {
400 // OK to link to the image file because it will be accessed by the
401 // HTML2PDF parser and not the browser.
402 $from_rel = $web_root . substr($from_file, strlen($webserver_root));
403 echo "<img src='$from_rel'><br><br>";
405 else {
406 echo "<img src='" . $GLOBALS['webroot'] .
407 "/controller.php?document&retrieve&patient_id=&document_id=" .
408 $document_id . "&as_file=false'><br><br>";
411 else {
413 // Most clinic documents are expected to be PDFs, and in that happy case
414 // we can avoid the lengthy image conversion process.
415 if ($PDF_OUTPUT && $extension == ".pdf") {
416 // HTML to PDF conversion will fail if there are open tags.
417 echo "</div></div>\n";
418 $content = getContent();
419 // $pdf->setDefaultFont('Arial');
420 $pdf->writeHTML($content, false);
421 $pagecount = $pdf->pdf->setSourceFile($from_file);
422 for($i = 0; $i < $pagecount; ++$i){
423 $pdf->pdf->AddPage();
424 $itpl = $pdf->pdf->importPage($i + 1, '/MediaBox');
425 $pdf->pdf->useTemplate($itpl);
427 // Make sure whatever follows is on a new page.
428 $pdf->pdf->AddPage();
429 // Resume output buffering and the above-closed tags.
430 ob_start();
431 echo "<div><div class='text documents'>\n";
433 else {
434 if (! is_file($to_file)) exec("convert -density 200 \"$from_file\" -append -resize 850 \"$to_file\"");
435 if (is_file($to_file)) {
436 if ($PDF_OUTPUT) {
437 // OK to link to the image file because it will be accessed by the
438 // HTML2PDF parser and not the browser.
439 echo "<img src='$to_file'><br><br>";
441 else {
442 echo "<img src='" . $GLOBALS['webroot'] .
443 "/controller.php?document&retrieve&patient_id=&document_id=" .
444 $document_id . "&as_file=false&original_file=false'><br><br>";
446 } else {
447 echo "<b>NOTE</b>: " . xl('Document') . "'" . $fname . "' " .
448 xl('cannot be converted to JPEG. Perhaps ImageMagick is not installed?') . "<br><br>";
449 if($couch_docid && $couch_revid) {
450 unlink($from_file);
455 } // end if-else
456 } // end Documents loop
457 echo "</div>";
459 } else if (strpos($key, "issue_") === 0) {
460 // display patient Issues
462 if ($first_issue) {
463 $prevIssueType = 'asdf1234!@#$'; // random junk so as to not match anything
464 $first_issue = 0;
465 echo "<hr />";
466 echo "<h1>".xl("Issues")."</h1>";
468 preg_match('/^(.*)_(\d+)$/', $key, $res);
469 $rowid = $res[2];
470 $irow = sqlQuery("SELECT type, title, comments, diagnosis " .
471 "FROM lists WHERE id = '$rowid'");
472 $diagnosis = $irow['diagnosis'];
473 if ($prevIssueType != $irow['type']) {
474 // output a header for each Issue Type we encounter
475 $disptype = $ISSUE_TYPES[$irow['type']][0];
476 echo "<div class='issue_type'>" . $disptype . ":</div>\n";
477 $prevIssueType = $irow['type'];
479 echo "<div class='text issue'>";
480 echo "<span class='issue_title'>" . $irow['title'] . ":</span>";
481 echo "<span class='issue_comments'> " . $irow['comments'] . "</span>\n";
482 // Show issue's chief diagnosis and its description:
483 if ($diagnosis) {
484 echo "<div class='text issue_diag'>";
485 echo "<span class='bold'>[".xl('Diagnosis')."]</span><br>";
486 $dcodes = explode(";", $diagnosis);
487 foreach ($dcodes as $dcode) {
488 echo "<span class='italic'>".$dcode."</span>: ";
489 echo lookup_code_descriptions($dcode)."<br>\n";
491 //echo $diagnosis." -- ".lookup_code_descriptions($diagnosis)."\n";
492 echo "</div>";
495 // Supplemental data for GCAC or Contraception issues.
496 if ($irow['type'] == 'ippf_gcac') {
497 echo " <table>\n";
498 display_layout_rows('GCA', sqlQuery("SELECT * FROM lists_ippf_gcac WHERE id = '$rowid'"));
499 echo " </table>\n";
501 else if ($irow['type'] == 'contraceptive') {
502 echo " <table>\n";
503 display_layout_rows('CON', sqlQuery("SELECT * FROM lists_ippf_con WHERE id = '$rowid'"));
504 echo " </table>\n";
507 echo "</div>\n"; //end the issue DIV
509 } else {
510 // we have an "encounter form" form field whose name is like
511 // dirname_formid, with a value which is the encounter ID.
513 // display encounter forms, encoded as a POST variable
514 // in the format: <formdirname_formid>=<encounterID>
516 if (($auth_notes_a || $auth_notes || $auth_coding_a || $auth_coding || $auth_med || $auth_relaxed)) {
517 $form_encounter = $val;
518 preg_match('/^(.*)_(\d+)$/', $key, $res);
519 $form_id = $res[2];
520 $formres = getFormNameByFormdirAndFormid($res[1],$form_id);
521 $dateres = getEncounterDateByEncounter($form_encounter);
523 if ($res[1] == 'newpatient') {
524 echo "<div class='text encounter'>\n";
525 echo "<h1>" . xl($formres["form_name"]) . "</h1>";
527 else {
528 echo "<div class='text encounter_form'>";
529 echo "<h1>" . xl_form_title($formres["form_name"]) . "</h1>";
532 // show the encounter's date
533 echo "(" . oeFormatSDFT(strtotime($dateres["date"])) . ") ";
534 if ($res[1] == 'newpatient') {
535 // display the provider info
536 $tmp = sqlQuery("SELECT u.title, u.fname, u.mname, u.lname " .
537 "FROM forms AS f, users AS u WHERE " .
538 "f.pid = '$pid' AND f.encounter = '$form_encounter' AND " .
539 "f.formdir = 'newpatient' AND u.username = f.user " .
540 " AND f.deleted=0 ". //--JRM--
541 "ORDER BY f.id LIMIT 1");
542 echo ' '. xl('Provider') . ': ' . $tmp['title'] . ' ' .
543 $tmp['fname'] . ' ' . $tmp['mname'] . ' ' . $tmp['lname'];
545 echo "<br>\n";
547 // call the report function for the form
548 if (substr($res[1],0,3) == 'LBF')
549 call_user_func("lbf_report", $pid, $form_encounter, $N, $form_id, $res[1]);
550 else
551 call_user_func($res[1] . "_report", $pid, $form_encounter, $N, $form_id);
553 if ($res[1] == 'newpatient') {
554 // display billing info
555 $bres = sqlStatement("SELECT b.date, b.code, b.code_text " .
556 "FROM billing AS b, code_types AS ct WHERE " .
557 "b.pid = ? AND " .
558 "b.encounter = ? AND " .
559 "b.activity = 1 AND " .
560 "b.code_type = ct.ct_key AND " .
561 "ct.ct_diag = 0 " .
562 "ORDER BY b.date",
563 array($pid, $form_encounter));
564 while ($brow=sqlFetchArray($bres)) {
565 echo "<span class='bold'>&nbsp;".xl('Procedure').": </span><span class='text'>" .
566 $brow['code'] . " " . $brow['code_text'] . "</span><br>\n";
570 print "</div>";
572 } // end auth-check for encounter forms
574 } // end if('issue_')... else...
576 } // end if('include_')... else...
578 } // end $ar loop
580 if ($printable)
581 echo "<br /><br />" . xl('Signature') . ": _______________________________<br />";
584 </div> <!-- end of report_custom DIV -->
586 <?php
587 if ($PDF_OUTPUT) {
588 $content = getContent();
589 // $pdf->setDefaultFont('Arial');
590 $pdf->writeHTML($content, false);
591 $pdf->Output('report.pdf', 'D'); // D = Download, I = Inline
593 else {
595 </body>
596 </html>
597 <?php } ?>