Fix for printed fee sheet, and estimated DOB indicator for IPPF
[openemr.git] / interface / patient_file / printed_fee_sheet.php
blob1b8b77fdec741ccf0424b9c8ca73d2cb358f851b
1 <?php
2 // Copyright (C) 2007-2010 Rod Roark <rod@sunsetsystems.com>
3 //
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 require_once("../globals.php");
10 require_once("$srcdir/acl.inc");
11 require_once("$srcdir/patient.inc");
12 require_once("$srcdir/classes/Address.class.php");
13 require_once("$srcdir/classes/InsuranceCompany.class.php");
14 require_once("$srcdir/formatting.inc.php");
16 // This value is initially a maximum, and will be recomputed to
17 // distribute lines evenly among the pages.
18 $lines_per_page = 55;
20 $lines_in_stats = 8;
22 $header_height = 44; // height of page headers in points
24 // This tells us if patient/encounter data is to be filled in.
26 $form_fill = empty($_GET['fill']) ? 0 : 1;
28 // This file is optional. You can create it to customize how the printed
29 // fee sheet looks, otherwise you'll get a mirror of your actual fee sheet.
31 if (file_exists("../../custom/fee_sheet_codes.php"))
32 include_once ("../../custom/fee_sheet_codes.php");
34 // TBD: Move these to globals.php, or make them user-specific.
35 $fontsize = 7;
36 $page_height = 700;
38 $padding = 0;
40 // The $SBCODES table is a simple indexed array whose values are
41 // strings of the form "code|text" where code may be either a billing
42 // code or one of the following:
44 // *H - A main heading, where "text" is its title (to be centered).
45 // *G - Specifies a new category, where "text" is its name.
46 // *B - A borderless blank row.
47 // *C - Ends the current column and starts a new one.
49 // If $SBCODES is not provided, then manufacture it from the Fee Sheet.
51 if (empty($SBCODES)) {
52 $SBCODES = array();
53 $last_category = '';
55 // Create entries based on the fee_sheet_options table.
56 $res = sqlStatement("SELECT * FROM fee_sheet_options " .
57 "ORDER BY fs_category, fs_option");
58 while ($row = sqlFetchArray($res)) {
59 $fs_category = $row['fs_category'];
60 $fs_option = $row['fs_option'];
61 $fs_codes = $row['fs_codes'];
62 if($fs_category !== $last_category) {
63 $last_category = $fs_category;
64 $SBCODES[] = '*G|' . substr($fs_category, 1);
66 $SBCODES[] = " |" . substr($fs_option, 1);
69 // Create entries based on categories defined within the codes.
70 $pres = sqlStatement("SELECT option_id, title FROM list_options " .
71 "WHERE list_id = 'superbill' ORDER BY seq");
72 while ($prow = sqlFetchArray($pres)) {
73 $SBCODES[] = '*G|' . $prow['title'];
74 $res = sqlStatement("SELECT code_type, code, code_text FROM codes " .
75 "WHERE superbill = '" . $prow['option_id'] . "' AND active = 1 " .
76 "ORDER BY code_text");
77 while ($row = sqlFetchArray($res)) {
78 $SBCODES[] = $row['code'] . '|' . $row['code_text'];
82 // Create one more group, for Products.
83 if ($GLOBALS['sell_non_drug_products']) {
84 $SBCODES[] = '*G|' . xl('Products');
85 $tres = sqlStatement("SELECT " .
86 "dt.drug_id, dt.selector, d.name, d.ndc_number " .
87 "FROM drug_templates AS dt, drugs AS d WHERE " .
88 "d.drug_id = dt.drug_id AND d.active = 1 " .
89 "ORDER BY d.name, dt.selector, dt.drug_id");
90 while ($trow = sqlFetchArray($tres)) {
91 $tmp = $trow['selector'];
92 if ($trow['name'] !== $trow['selector']) $tmp .= ' ' . $trow['name'];
93 $prodcode = empty($trow['ndc_number']) ? ('(' . $trow['drug_id'] . ')') :
94 $trow['ndc_number'];
95 $SBCODES[] = "$prodcode|$tmp";
99 // Extra stuff for the labs section.
100 $SBCODES[] = '*G|' . xl('Notes');
101 $percol = intval((count($SBCODES) + 2) / 3);
102 while (count($SBCODES) < $percol * 3) $SBCODES[] = '*B|';
104 // Adjust lines per page to distribute lines evenly among the pages.
105 $pages = intval(($percol + $lines_in_stats + $lines_per_page - 1) / $lines_per_page);
106 $lines_per_page = intval(($percol + $lines_in_stats + $pages - 1) / $pages);
108 // Figure out page and column breaks.
109 $pages = 1;
110 $lines = $percol;
111 $page_start_index = 0;
112 while ($lines + $lines_in_stats > $lines_per_page) {
113 ++$pages;
114 $lines_this_page = $lines > $lines_per_page ? $lines_per_page : $lines;
115 $lines -= $lines_this_page;
116 array_splice($SBCODES, $lines_this_page*3 + $page_start_index, 0, '*C|');
117 array_splice($SBCODES, $lines_this_page*2 + $page_start_index, 0, '*C|');
118 array_splice($SBCODES, $lines_this_page*1 + $page_start_index, 0, '*C|');
119 $page_start_index += $lines_this_page * 3 + 3;
121 array_splice($SBCODES, $lines*2 + $page_start_index, 0, '*C|');
122 array_splice($SBCODES, $lines*1 + $page_start_index, 0, '*C|');
125 $lheight = sprintf('%d', ($page_height - $header_height) / $lines_per_page);
127 <html>
128 <head>
129 <?php html_header_show(); ?>
131 <style>
132 body {
133 font-family: sans-serif;
134 font-weight: normal;
136 .bordertbl {
137 width: 100%;
138 border-style: solid;
139 border-width: 0 0 1px 1px;
140 border-spacing: 0;
141 border-collapse: collapse;
142 border-color: #999999;
144 td.toprow {
145 height: 1px;
146 padding: 0;
147 border-style: solid;
148 border-width: 0 0 0 0;
149 border-color: #999999;
151 td.fsgroup {
152 height: <?php echo $lheight; ?>pt;
153 font-family: sans-serif;
154 font-weight: bold;
155 font-size: <?php echo $fontsize ?>pt;
156 background-color: #cccccc;
157 padding: <?php echo $padding ?>pt 2pt 0pt 2pt;
158 border-style: solid;
159 border-width: 1px 1px 0 0;
160 border-color: #999999;
162 td.fshead {
163 height: <?php echo $lheight; ?>pt;
164 font-family: sans-serif;
165 font-weight: bold;
166 font-size: <?php echo $fontsize ?>pt;
167 padding: <?php echo $padding ?>pt 2pt 0pt 2pt;
168 border-style: solid;
169 border-width: 1px 1px 0 0;
170 border-color: #999999;
172 td.fscode {
173 height: <?php echo $lheight; ?>pt;
174 font-family: sans-serif;
175 font-weight: normal;
176 font-size: <?php echo $fontsize ?>pt;
177 padding: <?php echo $padding ?>pt 2pt 0pt 2pt;
178 border-style: solid;
179 border-width: 1px 1px 0 0;
180 border-color: #999999;
183 .ftitletable {
184 width: 100%;
185 height: <?php echo $header_height; ?>pt;
186 margin: 0 0 8pt 0;
188 .ftitlecell1 {
189 vertical-align: top;
190 text-align: left;
191 font-size: 14pt;
192 font-weight: bold;
194 .ftitlecell2 {
195 vertical-align: top;
196 text-align: right;
197 font-size: 9pt;
199 </style>
201 <?php
203 // Get the co-pay amount that is effective on the given date.
204 // Or if no insurance on that date, return -1.
206 function getCopay($patient_id, $encdate) {
207 $tmp = sqlQuery("SELECT provider, copay FROM insurance_data " .
208 "WHERE pid = '$patient_id' AND type = 'primary' " .
209 "AND date <= '$encdate' ORDER BY date DESC LIMIT 1");
210 if ($tmp['provider']) return sprintf('%01.2f', 0 + $tmp['copay']);
211 return -1;
214 function genColumn($ix) {
215 global $SBCODES;
216 for ($imax = count($SBCODES); $ix < $imax; ++$ix) {
217 $a = explode('|', $SBCODES[$ix], 2);
218 $cmd = trim($a[0]);
219 if ($cmd == '*C') { // column break
220 return ++$ix;
222 if ($cmd == '*B') { // Borderless and empty
223 echo " <tr><td colspan='5' class='fscode' style='border-width:0 1px 0 0;padding-top:1px;' nowrap>&nbsp;</td></tr>\n";
225 else if ($cmd == '*G') {
226 $title = htmlspecialchars($a[1]);
227 if (!$title) $title='&nbsp;';
228 echo " <tr><td colspan='5' align='center' class='fsgroup' style='vertical-align:middle' nowrap>$title</td></tr>\n";
230 else if ($cmd == '*H') {
231 $title = htmlspecialchars($a[1]);
232 if (!$title) $title='&nbsp;';
233 echo " <tr><td colspan='5' class='fshead' style='vertical-align:middle' nowrap>$title</td></tr>\n";
235 else {
236 $title = htmlspecialchars($a[1]);
237 if (!$title) $title='&nbsp;';
238 $b = explode(':', $cmd);
239 echo " <tr>\n";
240 echo " <td class='fscode' style='vertical-align:middle;width:14pt' nowrap>&nbsp;</td>\n";
241 if (count($b) <= 1) {
242 $code = $b[0];
243 if (!$code) $code='&nbsp;';
244 echo " <td class='fscode' style='vertical-align:middle' nowrap>$code</td>\n";
245 echo " <td colspan='3' class='fscode' style='vertical-align:middle' nowrap>$title</td>\n";
247 else {
248 echo " <td colspan='2' class='fscode' style='vertical-align:middle' nowrap>" . $b[0] . '/' . $b[1] . "</td>\n";
249 echo " <td colspan='2' class='fscode' style='vertical-align:middle' nowrap>$title</td>\n";
251 echo " </tr>\n";
254 return $ix;
257 $today = date('Y-m-d');
259 $alertmsg = ''; // anything here pops up in an alert box
261 // Get details for what we guess is the primary facility.
262 $frow = sqlQuery("SELECT * FROM facility " .
263 "ORDER BY billing_location DESC, accepts_assignment DESC, id LIMIT 1");
265 if ($form_fill) {
266 // Get the patient's name and chart number.
267 $patdata = getPatientData($pid);
270 // This tracks our position in the $SBCODES array.
271 $cindex = 0;
274 <title><?php echo htmlspecialchars($frow['name']); ?></title>
275 <script type="text/javascript" src="../../library/dialog.js"></script>
276 <script language="JavaScript">
278 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
280 // Process click on Print button.
281 function printme() {
282 var divstyle = document.getElementById('hideonprint').style;
283 divstyle.display = 'none';
284 window.print();
287 </script>
288 </head>
289 <body bgcolor='#ffffff'>
290 <form name='theform' method='post' action='printed_fee_sheet.php?fill=<?php echo $form_fill; ?>'
291 onsubmit='return top.restoreSession()'>
292 <center>
294 <?php while (--$pages >= 0) { ?>
296 <?php echo genFacilityTitle(xl('Fee Sheet'), -1); ?>
298 <table class='bordertbl' cellspacing='0' cellpadding='0' width='100%'>
299 <tr>
300 <td valign='top'>
301 <table border='0' cellspacing='0' cellpadding='0' width='100%'>
302 <tr>
303 <td class='toprow' style='width:10%'></td>
304 <td class='toprow' style='width:10%'></td>
305 <td class='toprow' style='width:25%'></td>
306 <td class='toprow' style='width:55%'></td>
307 </tr>
308 <?php
309 $cindex = genColumn($cindex); // Column 1
312 <?php if ($pages == 0) { // if this is the last page ?>
314 <tr>
315 <td colspan='3' valign='top' class='fshead' style='height:<?php echo $lheight * 2; ?>pt'>
316 Patient:<br />
317 <?php
318 if ($form_fill) {
319 echo $patdata['fname'] . ' ' . $patdata['mname'] . ' ' . $patdata['lname'] . "<br />\n";
320 echo $patdata['street'] . "<br />\n";
321 echo $patdata['city'] . ', ' . $patdata['state'] . ' ' . $patdata['postal_code'] . "\n";
324 </td>
325 <td valign='top' class='fshead'>
326 DOB:<br /><?php if ($form_fill) echo $patdata['DOB']; ?><br />
327 ID:<br /><?php if ($form_fill) echo $patdata['pubpid']; ?>
328 </td>
329 </tr>
330 <tr>
331 <td colspan='3' valign='top' class='fshead' style='height:<?php echo $lheight; ?>pt'>
332 Doctor:<br />
333 <?php
334 $encdata = false;
335 if ($form_fill && $encounter) {
336 $query = "SELECT fe.reason, fe.date, u.fname, u.mname, u.lname, u.username " .
337 "FROM forms AS f " .
338 "JOIN form_encounter AS fe ON fe.id = f.form_id " .
339 "LEFT JOIN users AS u ON u.username = f.user " .
340 "WHERE f.pid = '$pid' AND f.encounter = '$encounter' AND f.formdir = 'newpatient' AND f.deleted = 0 " .
341 "ORDER BY f.id LIMIT 1";
342 $encdata = sqlQuery($query);
343 if (!empty($encdata['username'])) {
344 echo $encdata['fname'] . ' ' . $encdata['mname'] . ' ' . $encdata['lname'];
348 </td>
349 <td valign='top' class='fshead'>
350 Reason:<br />
351 <?php
352 if (!empty($encdata)) {
353 echo $encdata['reason'];
356 </td>
357 </tr>
358 <tr>
359 <td colspan='4' valign='top' class='fshead' style='height:<?php echo $lheight; ?>pt'>
360 <?php
361 if (empty($GLOBALS['ippf_specific'])) {
362 echo "Insurance:\n";
363 if ($form_fill) {
364 foreach (array('primary','secondary','tertiary') as $instype) {
365 $query = "SELECT * FROM insurance_data WHERE " .
366 "pid = '$pid' AND type = '$instype' " .
367 "ORDER BY date DESC LIMIT 1";
368 $row = sqlQuery($query);
369 if ($row['provider']) {
370 $icobj = new InsuranceCompany($row['provider']);
371 $adobj = $icobj->get_address();
372 $insco_name = trim($icobj->get_name());
373 if ($instype != 'primary') echo ",";
374 if ($insco_name) {
375 echo "&nbsp;$insco_name";
376 } else {
377 echo "&nbsp;<font color='red'><b>Missing Name</b></font>";
383 else {
384 // IPPF wants a visit date box with the current date in it.
385 echo "Visit date:<br />\n";
386 if (!empty($encdata)) {
387 echo substr($encdata['date'], 0, 10);
389 else {
390 echo oeFormatShortDate(date('Y-m-d')) . "\n";
394 </td>
395 </tr>
396 <tr>
397 <td colspan='4' valign='top' class='fshead' style='height:<?php echo $lheight; ?>pt'>
398 Prior balance:<br />
399 </td>
400 </tr>
401 <tr>
402 <td colspan='4' valign='top' class='fshead' style='height:<?php echo $lheight; ?>pt'>
403 Today's charges:<br />
404 </td>
405 </tr>
406 <tr>
407 <td colspan='4' valign='top' class='fshead' style='height:<?php echo $lheight; ?>pt'>
408 Today's payment:<br />
409 </td>
410 </tr>
411 <tr>
412 <td colspan='4' valign='top' class='fshead' style='height:<?php echo $lheight; ?>pt'>
413 Notes:<br />
414 </td>
415 </tr>
417 <?php } // end if last page ?>
419 </table>
420 </td>
421 <td valign='top'>
422 <table border='0' cellspacing='0' cellpadding='0' width='100%'>
423 <tr>
424 <td class='toprow' style='width:10%'></td>
425 <td class='toprow' style='width:10%'></td>
426 <td class='toprow' style='width:25%'></td>
427 <td class='toprow' style='width:55%'></td>
428 </tr>
429 <?php
430 $cindex = genColumn($cindex); // Column 2
433 <?php if ($pages == 0) { // if this is the last page ?>
435 <tr>
436 <td colspan='4' valign='top' class='fshead' style='height:<?php echo $lheight * 8; ?>pt'>
437 Notes:<br />
438 </td>
439 </tr>
441 <?php } // end if last page ?>
443 </table>
444 </td>
445 <td valign='top'>
446 <table border='0' cellspacing='0' cellpadding='0' width='100%'>
447 <tr>
448 <td class='toprow' style='width:10%'></td>
449 <td class='toprow' style='width:10%'></td>
450 <td class='toprow' style='width:25%'></td>
451 <td class='toprow' style='width:55%'></td>
452 </tr>
453 <?php
454 $cindex = genColumn($cindex); // Column 3
457 <?php if ($pages == 0) { // if this is the last page ?>
459 <tr>
460 <td valign='top' colspan='4' class='fshead' style='height:<?php echo $lheight * 6; ?>pt;border-width:0 1px 0 0'>
461 &nbsp;
462 </td>
463 </tr>
464 <tr>
465 <td valign='top' colspan='4' class='fshead' style='height:<?php echo $lheight * 2; ?>pt'>
466 Signature:<br />
467 </td>
468 </tr>
470 <?php } // end if last page ?>
472 </table>
473 </td>
474 </tr>
476 </table>
478 <?php
479 if ($pages > 0) echo "<p style='page-break-after: always' />\n";
480 } // end while
482 <div id='hideonprint'>
484 <input type='button' value='<?php xl('Print','e'); ?>' onclick='printme()' />
486 </div>
487 </form>
488 </center>
489 </body>
490 </html>