added date to oldEvt call
[openemr.git] / interface / forms / fee_sheet / view.php
blobb48990328f9823e27c1321312e63df0f29664eaf
1 <?php
2 //////////////////////////////////////////////////////////////////////
3 // ------------------ DO NOT MODIFY VIEW.PHP !!! ---------------------
4 // View.php is an exact duplicate of new.php. If you wish to make
5 // any changes, then change new.php and either (recommended) make
6 // view.php a symbolic link to new.php, or copy new.php to view.php.
7 //
8 // And if you check in a change to either module, be sure to check
9 // in the other (identical) module also.
11 // This nonsense will go away if we ever move to subversion.
12 //////////////////////////////////////////////////////////////////////
14 // Copyright (C) 2005-2008 Rod Roark <rod@sunsetsystems.com>
16 // This program is free software; you can redistribute it and/or
17 // modify it under the terms of the GNU General Public License
18 // as published by the Free Software Foundation; either version 2
19 // of the License, or (at your option) any later version.
21 require_once("../../globals.php");
22 require_once("$srcdir/acl.inc");
23 require_once("$srcdir/api.inc");
24 require_once("codes.php");
25 require_once("../../../custom/code_types.inc.php");
26 require_once("../../drugs/drugs.inc.php");
28 // Possible units of measure for NDC drug quantities.
30 $ndc_uom_choices = array(
31 'ML' => 'ML',
32 'GR' => 'Grams',
33 'F2' => 'I.U.',
34 'UN' => 'Units'
37 // $FEE_SHEET_COLUMNS should be defined in codes.php.
38 if (empty($FEE_SHEET_COLUMNS)) $FEE_SHEET_COLUMNS = 2;
40 $returnurl = $GLOBALS['concurrent_layout'] ? 'encounter_top.php' : 'patient_encounter.php';
42 // If Save was clicked, save the new and modified billing lines;
43 // then if no error, redirect to $returnurl.
45 if ($_POST['bn_save']) {
46 $provid = $_POST['ProviderID'];
47 if (! $provid) $provid = $_SESSION["authUserID"];
49 $bill = $_POST['bill'];
50 for ($lino = 1; $bill["$lino"]['code_type']; ++$lino) {
51 $iter = $bill["$lino"];
53 // Skip disabled (billed) line items.
54 if ($iter['billed']) continue;
56 $id = $iter['id'];
57 $code_type = $iter['code_type'];
58 $code = $iter['code'];
59 $modifier = trim($iter['mod']);
60 $units = max(1, intval(trim($iter['units'])));
61 $fee = sprintf('%01.2f',(0 + trim($iter['price'])) * $units);
62 if ($code_type == 'COPAY') {
63 if ($fee > 0) $fee = 0 - $fee;
64 $code = sprintf('%01.2f', 0 - $fee);
66 $justify = trim($iter['justify']);
67 if ($justify) $justify = str_replace(',', ':', $justify) . ':';
68 // $auth = $iter['auth'] ? "1" : "0";
69 $auth = "1";
70 $del = $iter['del'];
72 $ndc_info = '';
73 if ($iter['ndcnum']) {
74 $ndc_info = 'N4' . trim($iter['ndcnum']) . ' ' . $iter['ndcuom'] .
75 trim($iter['ndcqty']);
78 // If the item is already in the database...
79 if ($id) {
80 if ($del) {
81 deleteBilling($id);
83 else {
84 // authorizeBilling($id, $auth);
85 sqlQuery("UPDATE billing SET code = '$code', " .
86 "units = '$units', fee = '$fee', modifier = '$modifier', " .
87 "authorized = $auth, provider_id = '$provid', " .
88 "ndc_info = '$ndc_info', justify = '$justify' WHERE " .
89 "id = '$id' AND billed = 0 AND activity = 1");
93 // Otherwise it's a new item...
94 else if (! $del) {
95 $query = "select code_text from codes where code_type = '" .
96 $code_types[$code_type]['id'] . "' and " .
97 "code = '$code' and ";
98 if ($modifier) {
99 $query .= "modifier = '$modifier'";
100 } else {
101 $query .= "(modifier is null or modifier = '')";
103 $result = sqlQuery($query);
104 $code_text = addslashes($result['code_text']);
105 addBilling($encounter, $code_type, $code, $code_text, $pid, $auth,
106 $provid, $modifier, $units, $fee, $ndc_info, $justify);
108 } // end for
110 // Doing similarly to the above but for products.
111 $prod = $_POST['prod'];
112 for ($lino = 1; $prod["$lino"]['drug_id']; ++$lino) {
113 $iter = $prod["$lino"];
115 if (!empty($iter['billed'])) continue;
117 $drug_id = $iter['drug_id'];
118 $sale_id = $iter['sale_id']; // present only if already saved
119 $units = max(1, intval(trim($iter['units'])));
120 $fee = sprintf('%01.2f',(0 + trim($iter['price'])) * $units);
121 $del = $iter['del'];
123 // If the item is already in the database...
124 if ($sale_id) {
125 if ($del) {
126 // Zero out this sale and reverse its inventory update. We bring in
127 // drug_sales twice so that the original quantity can be referenced
128 // unambiguously.
129 sqlStatement("UPDATE drug_sales AS dsr, drug_sales AS ds, " .
130 "drug_inventory AS di " .
131 "SET di.on_hand = di.on_hand + dsr.quantity, " .
132 "ds.quantity = 0, ds.fee = 0 WHERE " .
133 "dsr.sale_id = '$sale_id' AND ds.sale_id = dsr.sale_id AND " .
134 "di.inventory_id = ds.inventory_id");
135 // And delete the sale for good measure.
136 sqlStatement("DELETE FROM drug_sales WHERE sale_id = '$sale_id'");
138 else {
139 // Modify the sale and adjust inventory accordingly.
140 $query = "UPDATE drug_sales AS dsr, drug_sales AS ds, " .
141 "drug_inventory AS di " .
142 "SET di.on_hand = di.on_hand + dsr.quantity - $units, " .
143 "ds.quantity = '$units', ds.fee = '$fee' WHERE " .
144 "dsr.sale_id = '$sale_id' AND ds.sale_id = dsr.sale_id AND " .
145 "di.inventory_id = ds.inventory_id";
146 sqlStatement($query);
150 // Otherwise it's a new item...
151 else if (! $del) {
152 $sale_id = sellDrug($drug_id, $units, $fee, $pid, $encounter);
153 if (!$sale_id) die("Insufficient inventory for product ID \"$drug_id\".");
155 } // end for
157 // This part exists for IPPF clinics and will not be invoked unless
158 // contrastart is enabled in the demographics layout.
159 if (!empty($_POST['contrastart'])) {
160 sqlStatement("UPDATE patient_data SET contrastart = '" .
161 $_POST['contrastart'] . "' WHERE pid = '$pid'");
164 // Note: I was going to compute taxes here, but now I think better to
165 // do that at checkout time (in pos_checkout.php which also posts to SL).
166 // Currently taxes with insurance claims make no sense, so for now we'll
167 // ignore tax computation in the insurance billing logic.
169 formHeader("Redirecting....");
170 formJump();
171 formFooter();
172 exit;
175 $billresult = getBillingByEncounter($pid, $encounter, "*");
177 <html>
178 <head>
179 <?php html_header_show(); ?>
180 <link rel="stylesheet" href="<?php echo $css_header;?>" type="text/css">
181 <style>
182 .billcell { font-family: sans-serif; font-size: 10pt }
183 </style>
184 <script language="JavaScript">
186 var diags = new Array();
188 <?php
189 // Generate JavaScript to build the array of diagnoses.
190 function genDiagJS($code_type, $code) {
191 if ($code_type == 'ICD9') {
192 echo "diags.push('$code');\n";
195 if ($billresult) {
196 foreach ($billresult as $iter) {
197 genDiagJS($iter["code_type"], trim($iter["code"]));
200 if ($_POST['bill']) {
201 foreach ($_POST['bill'] as $iter) {
202 if ($iter["del"]) continue; // skip if Delete was checked
203 if ($iter["id"]) continue; // skip if it came from the database
204 genDiagJS($iter["code_type"], $iter["code"]);
207 if ($_POST['newcodes']) {
208 $arrcodes = explode('~', $_POST['newcodes']);
209 foreach ($arrcodes as $codestring) {
210 if ($codestring === '') continue;
211 $arrcode = explode('|', $codestring);
212 list($code, $modifier) = explode(":", $arrcode[1]);
213 genDiagJS($arrcode[0], $code);
218 // This is invoked by <select onchange> for the various dropdowns,
219 // including search results.
220 function codeselect(selobj) {
221 var i = selobj.selectedIndex;
222 if (i > 0) {
223 top.restoreSession();
224 var f = document.forms[0];
225 f.newcodes.value = selobj.options[i].value;
226 f.submit();
230 function copayselect() {
231 top.restoreSession();
232 var f = document.forms[0];
233 f.newcodes.value = 'COPAY||';
234 f.submit();
237 function validate(f) {
238 for (var lino = 1; f['bill['+lino+'][code_type]']; ++lino) {
239 var pfx = 'bill['+lino+']';
240 if (f[pfx+'[ndcnum]'] && f[pfx+'[ndcnum]'].value) {
241 // Check NDC number format.
242 var ndcok = true;
243 var ndc = f[pfx+'[ndcnum]'].value;
244 var a = ndc.split('-');
245 if (a.length != 3) {
246 ndcok = false;
248 else if (a[0].length < 1 || a[1].length < 1 || a[2].length < 1 ||
249 a[0].length > 5 || a[1].length > 4 || a[2].length > 2) {
250 ndcok = false;
252 else {
253 for (var i = 0; i < 3; ++i) {
254 for (var j = 0; j < a[i].length; ++j) {
255 var c = a[i].charAt(j);
256 if (c < '0' || c > '9') ndcok = false;
260 if (!ndcok) {
261 alert('<?php xl('Format incorrect for NDC','e') ?> "' + ndc +
262 '", <?php xl('should be like nnnnn-nnnn-nn','e') ?>');
263 if (f[pfx+'[ndcnum]'].focus) f[pfx+'[ndcnum]'].focus();
264 return false;
266 // Check for valid quantity.
267 var qty = f[pfx+'[ndcqty]'].value - 0;
268 if (isNaN(qty) || qty <= 0) {
269 alert('<?php xl('Quantity for NDC','e') ?> "' + ndc +
270 '" <?php xl('is not valid (decimal fractions are OK).','e') ?>');
271 if (f[pfx+'[ndcqty]'].focus) f[pfx+'[ndcqty]'].focus();
272 return false;
276 top.restoreSession();
277 return true;
280 // When a justify selection is made, apply it to the current list for
281 // this procedure and then rebuild its selection list.
283 function setJustify(seljust) {
284 var theopts = seljust.options;
285 var jdisplay = theopts[0].text;
286 // Compute revised justification string. Note this does nothing if
287 // the first entry is still selected, which is handy at startup.
288 if (seljust.selectedIndex > 0) {
289 var newdiag = seljust.value;
290 if (newdiag.length == 0) {
291 jdisplay = '';
293 else {
294 if (jdisplay.length) jdisplay += ',';
295 jdisplay += newdiag;
298 // Rebuild selection list.
299 var jhaystack = ',' + jdisplay + ',';
300 var j = 0;
301 theopts.length = 0;
302 theopts[j++] = new Option(jdisplay,jdisplay,true,true);
303 for (var i = 0; i < diags.length; ++i) {
304 if (jhaystack.indexOf(',' + diags[i] + ',') < 0) {
305 theopts[j++] = new Option(diags[i],diags[i],false,false);
308 theopts[j++] = new Option('Clear','',false,false);
311 </script>
312 </head>
314 <body class="body_top">
315 <form method="post" action="<?php echo $rootdir; ?>/forms/fee_sheet/new.php"
316 onsubmit="return validate(this)">
317 <span class="title"><?php xl('Fee Sheet','e'); ?></span><br>
318 <input type='hidden' name='newcodes' value=''>
320 <center>
321 <table width='95%'>
322 <?php
323 $i = 0;
324 $last_category = '';
326 function alphaCodeType($id) {
327 global $code_types;
328 foreach ($code_types as $key => $value) {
329 if ($value['id'] == $id) return $key;
331 return '';
334 // Helper function for creating drop-lists.
335 function endFSCategory() {
336 global $i, $last_category, $FEE_SHEET_COLUMNS;
337 if (! $last_category) return;
338 echo " </select>\n";
339 echo " </td>\n";
340 if ($i >= $FEE_SHEET_COLUMNS) {
341 echo " </tr>\n";
342 $i = 0;
346 // Create drop-lists based on the fee_sheet_options table.
347 $res = sqlStatement("SELECT * FROM fee_sheet_options " .
348 "ORDER BY fs_category, fs_option");
349 while ($row = sqlFetchArray($res)) {
350 $fs_category = $row['fs_category'];
351 $fs_option = $row['fs_option'];
352 $fs_codes = $row['fs_codes'];
353 if($fs_category !== $last_category) {
354 endFSCategory();
355 $last_category = $fs_category;
356 ++$i;
357 echo ($i <= 1) ? " <tr>\n" : "";
358 echo " <td width='50%' align='center' nowrap>\n";
359 echo " <select style='width:96%' onchange='codeselect(this)'>\n";
360 echo " <option value=''> " . substr($fs_category, 1) . "</option>\n";
362 echo " <option value='$fs_codes'>" . substr($fs_option, 1) . "</option>\n";
364 endFSCategory();
366 // Create drop-lists based on categories defined within the codes.
367 $pres = sqlStatement("SELECT option_id, title FROM list_options " .
368 "WHERE list_id = 'superbill' ORDER BY seq");
369 while ($prow = sqlFetchArray($pres)) {
370 ++$i;
371 echo ($i <= 1) ? " <tr>\n" : "";
372 echo " <td width='50%' align='center' nowrap>\n";
373 echo " <select style='width:96%' onchange='codeselect(this)'>\n";
374 echo " <option value=''> " . $prow['title'] . "\n";
375 $res = sqlStatement("SELECT code_type, code, code_text FROM codes " .
376 "WHERE superbill = '" . $prow['option_id'] . "' " .
377 "ORDER BY code_text");
378 while ($row = sqlFetchArray($res)) {
379 echo " <option value='" . alphaCodeType($row['code_type']) . '|' .
380 $row['code'] . "|'>" . $row['code_text'] . "</option>\n";
382 echo " </select>\n";
383 echo " </td>\n";
384 if ($i >= $FEE_SHEET_COLUMNS) {
385 echo " </tr>\n";
386 $i = 0;
390 // Create one more drop-list, for Products.
391 if ($GLOBALS['sell_non_drug_products']) {
392 ++$i;
393 echo ($i <= 1) ? " <tr>\n" : "";
394 echo " <td width='50%' align='center' nowrap>\n";
395 echo " <select name='Products' style='width:96%' onchange='codeselect(this)'>\n";
396 echo " <option value=''> " . xl('Products') . "\n";
397 $tres = sqlStatement("SELECT dt.drug_id, dt.selector, d.name " .
398 "FROM drug_templates AS dt, drugs AS d WHERE " .
399 "d.drug_id = dt.drug_id " .
400 "ORDER BY d.name, dt.selector, dt.drug_id");
401 while ($trow = sqlFetchArray($tres)) {
402 echo " <option value='PROD|" . $trow['drug_id'] . '|' . $trow['selector'] . "'>" .
403 $trow['drug_id'] . ':' . $trow['selector'];
404 if ($trow['name'] !== $trow['selector']) echo ' ' . $trow['name'];
405 echo "</option>\n";
407 echo " </select>\n";
408 echo " </td>\n";
409 if ($i >= $FEE_SHEET_COLUMNS) {
410 echo " </tr>\n";
411 $i = 0;
415 $search_type = $default_search_type;
416 if ($_POST['search_type']) $search_type = $_POST['search_type'];
418 $ndc_applies = true; // Assume all payers require NDC info.
420 echo $i ? " <td></td>\n </tr>\n" : "";
421 echo " <tr>\n";
422 echo " <td colspan='$FEE_SHEET_COLUMNS' align='center' nowrap>\n";
424 // If Search was clicked, do it and write the list of results here.
425 // There's no limit on the number of results!
427 $numrows = 0;
428 if ($_POST['bn_search'] && $_POST['search_term']) {
429 $query = "select code, modifier, code_text from codes where " .
430 "(code_text like '%" . $_POST['search_term'] . "%' or " .
431 "code like '%" . $_POST['search_term'] . "%') and " .
432 "code_type = '" . $code_types[$search_type]['id'] . "' " .
433 "order by code";
434 $res = sqlStatement($query);
435 $numrows = mysql_num_rows($res); // FIXME - not portable!
438 echo " <select name='Search Results' style='width:98%' " .
439 "onchange='codeselect(this)'";
440 if (! $numrows) echo ' disabled';
441 echo ">\n";
442 echo " <option value=''> Search Results ($numrows items)\n";
444 if ($numrows) {
445 while ($row = sqlFetchArray($res)) {
446 $code = $row['code'];
447 if ($row['modifier']) $code .= ":" . $row['modifier'];
448 echo " <option value='$search_type|$code|'>$code " .
449 ucfirst(strtolower($row['code_text'])) . "</option>\n";
453 echo " </select>\n";
454 echo " </td>\n";
455 echo " </tr>\n";
458 </table>
460 <p style='margin-top:8px;margin-bottom:8px'>
461 <table>
462 <tr>
463 <td>
464 <input type='button' value='<?php xl('Add Copay','e');?>'
465 onclick="copayselect()" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
466 </td>
467 <td>
468 <?php xl('Search','e'); ?>&nbsp;
469 <?php
470 foreach ($code_types as $key => $value) {
471 if (!empty($value['nofs'])) continue;
472 echo " <input type='radio' name='search_type' value='$key'";
473 if ($key == $default_search_type) echo " checked";
474 echo " />$key&nbsp;\n";
477 <?php xl('for','e'); ?>&nbsp;
478 </td>
479 <td>
480 <input type='text' name='search_term' value=''> &nbsp;
481 </td>
482 <td>
483 <input type='submit' name='bn_search' value='<?php xl('Search','e');?>'>
484 </td>
485 </tr>
486 </table>
487 </p>
489 <p style='margin-top:16px;margin-bottom:8px'>
490 <table cellspacing='5'>
491 <tr>
492 <td class='billcell'><b><?php xl('Type','e');?></b></td>
493 <td class='billcell'><b><?php xl('Code','e');?></b></td>
494 <?php if (modifiers_are_used(true)) { ?>
495 <td class='billcell'><b><?php xl('Mod','e');?></b></td>
496 <?php } ?>
497 <?php if (fees_are_used()) { ?>
498 <td class='billcell' align='right'><b><?php xl('Price','e');?></b>&nbsp;</td>
499 <td class='billcell' align='center'><b><?php xl('Units','e');?></b></td>
500 <td class='billcell' align='center'><b><?php xl('Justify','e');?></b></td>
501 <?php } ?>
502 <td class='billcell' align='center'><b><?php xl('Auth','e');?></b></td>
503 <td class='billcell' align='center'><b><?php xl('Delete','e');?></b></td>
504 <td class='billcell'><b><?php xl('Description','e');?></b></td>
505 </tr>
507 <?php
508 $justinit = "var f = document.forms[0];\n";
510 // This writes a billing line item to the output page.
512 function echoLine($lino, $codetype, $code, $modifier, $ndc_info='',
513 $auth = TRUE, $del = FALSE, $units = NULL, $fee = NULL, $id = NULL,
514 $billed = FALSE, $code_text = NULL, $justify = NULL)
516 global $code_types, $ndc_applies, $ndc_uom_choices, $justinit, $pid;
518 if ($codetype == 'COPAY') {
519 if (!$code_text) $code_text = 'Cash';
520 if ($fee > 0) $fee = 0 - $fee;
522 if (! $code_text) {
523 // $query = "select units, fee, code_text from codes where code_type = '" .
524 $query = "select id, units, code_text from codes where code_type = '" .
525 $code_types[$codetype]['id'] . "' and " .
526 "code = '$code' and ";
527 if ($modifier) {
528 $query .= "modifier = '$modifier'";
529 } else {
530 $query .= "(modifier is null or modifier = '')";
532 $result = sqlQuery($query);
533 $code_text = $result['code_text'];
534 if (empty($units)) $units = max(1, intval($result['units']));
535 if (!isset($fee)) {
536 // $fee = $result['fee'];
537 // The above is obsolete now, fees come from the prices table:
538 $query = "SELECT prices.pr_price " .
539 "FROM patient_data, prices WHERE " .
540 "patient_data.pid = '$pid' AND " .
541 "prices.pr_id = '" . $result['id'] . "' AND " .
542 "prices.pr_selector = '' AND " .
543 "prices.pr_level = patient_data.pricelevel " .
544 "LIMIT 1";
545 echo "\n<!-- $query -->\n"; // debugging
546 $prrow = sqlQuery($query);
547 $fee = empty($prrow) ? 0 : $prrow['pr_price'];
550 $fee = sprintf('%01.2f', $fee);
551 if (empty($units)) $units = 1;
552 $units = max(1, intval($units));
553 // We put unit price on the screen, not the total line item fee.
554 $price = sprintf('%01.2f', $fee / $units);
555 $strike1 = ($id && $del) ? "<strike>" : "";
556 $strike2 = ($id && $del) ? "</strike>" : "";
557 echo " <tr>\n";
558 echo " <td class='billcell'>$strike1$codetype$strike2";
559 if ($id) {
560 echo "<input type='hidden' name='bill[$lino][id]' value='$id'>";
562 echo "<input type='hidden' name='bill[$lino][code_type]' value='$codetype'>";
563 echo "<input type='hidden' name='bill[$lino][code]' value='$code'>";
564 echo "<input type='hidden' name='bill[$lino][billed]' value='$billed'>";
565 echo "</td>\n";
566 if ($codetype != 'COPAY') {
567 echo " <td class='billcell'>$strike1$code$strike2</td>\n";
568 } else {
569 echo " <td class='billcell'>&nbsp;</td>\n";
571 if ($billed) {
572 if (modifiers_are_used(true)) {
573 echo " <td class='billcell'>$strike1$modifier$strike2" .
574 "<input type='hidden' name='bill[$lino][mod]' value='$modifier'></td>\n";
576 if (fees_are_used()) {
577 echo " <td class='billcell' align='right'>$price</td>\n";
578 if ($codetype != 'COPAY') {
579 echo " <td class='billcell' align='center'>$units</td>\n";
580 } else {
581 echo " <td class='billcell'>&nbsp;</td>\n";
583 echo " <td class='billcell' align='center'>$justify</td>\n";
585 echo " <td class='billcell' align='center'><input type='checkbox'" .
586 ($auth ? " checked" : "") . " disabled /></td>\n";
587 echo " <td class='billcell' align='center'><input type='checkbox'" .
588 " disabled /></td>\n";
589 } else {
590 if (modifiers_are_used(true)) {
591 if ($codetype != 'COPAY' && ($code_types[$codetype]['mod'] || $modifier)) {
592 echo " <td class='billcell'><input type='text' name='bill[$lino][mod]' " .
593 "value='$modifier' size='" . $code_types[$codetype]['mod'] . "'></td>\n";
594 } else {
595 echo " <td class='billcell'>&nbsp;</td>\n";
598 if (fees_are_used()) {
599 if ($codetype == 'COPAY' || $code_types[$codetype]['fee'] || $fee != 0) {
600 echo " <td class='billcell' align='right'>" .
601 "<input type='text' name='bill[$lino][price]' " .
602 "value='$price' size='6'";
603 if (acl_check('acct','disc'))
604 echo " style='text-align:right'";
605 else
606 echo " style='text-align:right;background-color:transparent' readonly";
607 echo "></td>\n";
608 echo " <td class='billcell' align='center'>";
609 if ($codetype != 'COPAY') {
610 echo "<input type='text' name='bill[$lino][units]' " .
611 "value='$units' size='2' style='text-align:right'>";
612 } else {
613 echo "<input type='hidden' name='bill[$lino][units]' value='$units'>";
615 echo "</td>\n";
616 if ($code_types[$codetype]['just'] || $justify) {
617 echo " <td class='billcell' align='center'>";
618 echo "<select name='bill[$lino][justify]' onchange='setJustify(this)'>";
619 echo "<option value='$justify'>$justify</option></select>";
620 echo "</td>\n";
621 $justinit .= "setJustify(f['bill[$lino][justify]']);\n";
622 } else {
623 echo " <td class='billcell'>&nbsp;</td>\n";
625 } else {
626 echo " <td class='billcell'>&nbsp;</td>\n";
627 echo " <td class='billcell'>&nbsp;</td>\n";
628 echo " <td class='billcell'>&nbsp;</td>\n";
631 echo " <td class='billcell' align='center'><input type='checkbox' name='bill[$lino][auth]' " .
632 "value='1'" . ($auth ? " checked" : "") . " /></td>\n";
633 echo " <td class='billcell' align='center'><input type='checkbox' name='bill[$lino][del]' " .
634 "value='1'" . ($del ? " checked" : "") . " /></td>\n";
637 echo " <td class='billcell'>$strike1" . ucfirst(strtolower($code_text)) . "$strike2</td>\n";
638 echo " </tr>\n";
640 // If NDC info exists or may be required, add a line for it.
641 if ($codetype == 'HCPCS' && $ndc_applies && !$billed) {
642 $ndcnum = ''; $ndcuom = ''; $ndcqty = '';
643 if (preg_match('/^N4(\S+)\s+(\S\S)(.*)/', $ndc_info, $tmp)) {
644 $ndcnum = $tmp[1]; $ndcuom = $tmp[2]; $ndcqty = $tmp[3];
646 echo " <tr>\n";
647 echo " <td class='billcell' colspan='2'>&nbsp;</td>\n";
648 echo " <td class='billcell' colspan='6'>&nbsp;NDC:&nbsp;";
649 echo "<input type='text' name='bill[$lino][ndcnum]' value='$ndcnum' " .
650 "size='11' style='background-color:transparent'>";
651 echo " &nbsp;Qty:&nbsp;";
652 echo "<input type='text' name='bill[$lino][ndcqty]' value='$ndcqty' " .
653 "size='3' style='background-color:transparent;text-align:right'>";
654 echo " ";
655 echo "<select name='bill[$lino][ndcuom]' style='background-color:transparent'>";
656 foreach ($ndc_uom_choices as $key => $value) {
657 echo "<option value='$key'";
658 if ($key == $ndcuom) echo " selected";
659 echo ">$value</option>";
661 echo "</select>";
662 echo "</td>\n";
663 echo " </tr>\n";
665 else if ($ndc_info) {
666 echo " <tr>\n";
667 echo " <td class='billcell' colspan='2'>&nbsp;</td>\n";
668 echo " <td class='billcell' colspan='6'>&nbsp;NDC Data: $ndc_info</td>\n";
669 echo " </tr>\n";
673 // This writes a product (drug_sales) line item to the output page.
675 function echoProdLine($lino, $drug_id, $del = FALSE, $units = NULL,
676 $fee = NULL, $sale_id = 0, $billed = FALSE)
678 global $code_types, $ndc_applies, $pid;
680 /*******************************************************************
681 list ($drug_id, $selector) = explode(':', $drugsel);
682 if (! $units) { // if this is a new selection then apply defaults for it
683 $query = "SELECT dt.*, d.name FROM drug_templates, drugs WHERE " .
684 "dt.drug_id = '$drug_id' AND dt.selector = '$selector' AND " .
685 "d.drug_id = dt.drug_id";
686 $result = sqlQuery($query);
687 $code_text = $result['name'] . " ($selector)";
688 if (empty($units)) $units = max(1, intval($result['quantity']));
689 if (!isset($fee)) {
690 // Fees come from the prices table:
691 $query = "SELECT prices.pr_price " .
692 "FROM patient_data, prices WHERE " .
693 "patient_data.pid = '$pid' AND " .
694 "prices.pr_id = '$drug_id' AND " .
695 "prices.pr_selector = '$selector' AND " .
696 "prices.pr_level = patient_data.pricelevel " .
697 "LIMIT 1";
698 // echo "\n<!-- $query -->\n"; // debugging
699 $prrow = sqlQuery($query);
700 $fee = empty($prrow) ? 0 : $prrow['pr_price'];
703 *******************************************************************/
704 $drow = sqlQuery("SELECT name FROM drugs WHERE drug_id = '$drug_id'");
705 $code_text = $drow['name'];
706 /******************************************************************/
708 $fee = sprintf('%01.2f', $fee);
709 if (empty($units)) $units = 1;
710 $units = max(1, intval($units));
711 // We put unit price on the screen, not the total line item fee.
712 $price = sprintf('%01.2f', $fee / $units);
713 $strike1 = ($sale_id && $del) ? "<strike>" : "";
714 $strike2 = ($sale_id && $del) ? "</strike>" : "";
715 echo " <tr>\n";
716 echo " <td class='billcell'>{$strike1}Product$strike2";
717 echo "<input type='hidden' name='prod[$lino][sale_id]' value='$sale_id'>";
718 echo "<input type='hidden' name='prod[$lino][drug_id]' value='$drug_id'>";
719 echo "<input type='hidden' name='prod[$lino][billed]' value='$billed'>";
720 echo "</td>\n";
721 echo " <td class='billcell'>$strike1$drug_id$strike2</td>\n";
722 if (modifiers_are_used(true)) {
723 echo " <td class='billcell'>&nbsp;</td>\n";
725 if ($billed) {
726 if (fees_are_used()) {
727 echo " <td class='billcell' align='right'>$price</td>\n";
728 echo " <td class='billcell' align='center'>$units</td>\n";
729 echo " <td class='billcell' align='center'>&nbsp;</td>\n"; // justify
731 echo " <td class='billcell' align='center'>&nbsp;</td>\n"; // auth
732 echo " <td class='billcell' align='center'><input type='checkbox'" . // del
733 " disabled /></td>\n";
734 } else {
735 if (fees_are_used()) {
736 echo " <td class='billcell' align='right'>" .
737 "<input type='text' name='prod[$lino][price]' " .
738 "value='$price' size='6'";
739 if (acl_check('acct','disc'))
740 echo " style='text-align:right'";
741 else
742 echo " style='text-align:right;background-color:transparent' readonly";
743 echo "></td>\n";
744 echo " <td class='billcell' align='center'>";
745 echo "<input type='text' name='prod[$lino][units]' " .
746 "value='$units' size='2' style='text-align:right'>";
747 echo "</td>\n";
748 echo " <td class='billcell'>&nbsp;</td>\n";
750 echo " <td class='billcell' align='center'>&nbsp;</td>\n"; // auth
751 echo " <td class='billcell' align='center'><input type='checkbox' name='prod[$lino][del]' " .
752 "value='1'" . ($del ? " checked" : "") . " /></td>\n";
755 echo " <td class='billcell'>$strike1" . ucfirst(strtolower($code_text)) . "$strike2</td>\n";
756 echo " </tr>\n";
759 $encounter_provid = -1;
761 // Generate lines for items already in the billing table for this encounter,
762 // and also set the rendering provider if we come across one.
764 $bill_lino = 0;
765 if ($billresult) {
766 foreach ($billresult as $iter) {
767 ++$bill_lino;
768 $bline = $_POST['bill']["$bill_lino"];
769 $del = $bline['del']; // preserve Delete if checked
771 $modifier = trim($iter["modifier"]);
772 $units = $iter["units"];
773 $fee = $iter["fee"];
774 $authorized = $iter["authorized"];
775 $ndc_info = $iter["ndc_info"];
776 $justify = trim($iter['justify']);
777 if ($justify) $justify = substr(str_replace(':', ',', $justify), 0, strlen($justify) - 1);
779 // Also preserve other items from the form, if present.
780 if ($bline['id'] && !$iter["billed"]) {
781 $modifier = trim($bline['mod']);
782 // $units = trim($bline['units']);
783 // $fee = trim($bline['fee']);
784 $units = max(1, intval(trim($bline['units'])));
785 $fee = sprintf('%01.2f',(0 + trim($bline['price'])) * $units);
786 $authorized = $bline['auth'];
787 $ndc_info = '';
788 if ($bline['ndcnum']) {
789 $ndc_info = 'N4' . trim($bline['ndcnum']) . ' ' . $bline['ndcuom'] .
790 trim($bline['ndcqty']);
792 $justify = $bline['justify'];
795 // list($code, $modifier) = explode("-", $iter["code"]);
796 echoLine($bill_lino, $iter["code_type"], trim($iter["code"]),
797 $modifier, $ndc_info, $authorized,
798 $del, $units, $fee, $iter["id"], $iter["billed"],
799 $iter["code_text"], $justify);
800 // If no default provider yet then try this one.
801 if ($encounter_provid < 0 && ! $del) $encounter_provid = $iter["provider_id"];
805 // Echo new billing items from this form here, but omit any line
806 // whose Delete checkbox is checked.
808 if ($_POST['bill']) {
809 foreach ($_POST['bill'] as $key => $iter) {
810 if ($iter["id"]) continue; // skip if it came from the database
811 if ($iter["del"]) continue; // skip if Delete was checked
812 $ndc_info = '';
813 if ($iter['ndcnum']) {
814 $ndc_info = 'N4' . trim($iter['ndcnum']) . ' ' . $iter['ndcuom'] .
815 trim($iter['ndcqty']);
817 // $fee = 0 + trim($iter['fee']);
818 $units = max(1, intval(trim($iter['units'])));
819 $fee = sprintf('%01.2f',(0 + trim($iter['price'])) * $units);
820 if ($iter['code_type'] == 'COPAY' && $fee > 0) $fee = 0 - $fee;
821 echoLine(++$bill_lino, $iter["code_type"], $iter["code"], trim($iter["mod"]),
822 $ndc_info, $iter["auth"], $iter["del"], $units,
823 $fee, NULL, FALSE, NULL, $iter["justify"]);
827 // Generate lines for items already in the drug_sales table for this encounter.
829 $query = "SELECT * FROM drug_sales WHERE " .
830 "pid = '$pid' AND encounter = '$encounter' " .
831 "ORDER BY sale_id";
832 $sres = sqlStatement($query);
833 $prod_lino = 0;
834 while ($srow = sqlFetchArray($sres)) {
835 ++$prod_lino;
836 $pline = $_POST['prod']["$prod_lino"];
837 $del = $pline['del']; // preserve Delete if checked
838 $sale_id = $srow['sale_id'];
839 $drug_id = $srow['drug_id'];
840 $units = $srow['quantity'];
841 $fee = $srow['fee'];
842 $billed = $srow['billed'];
843 // Also preserve other items from the form, if present and unbilled.
844 if ($pline['sale_id'] && !$srow['billed']) {
845 // $units = trim($pline['units']);
846 // $fee = trim($pline['fee']);
847 $units = max(1, intval(trim($pline['units'])));
848 $fee = sprintf('%01.2f',(0 + trim($pline['price'])) * $units);
850 echoProdLine($prod_lino, $drug_id, $del, $units, $fee, $sale_id, $billed);
853 // Echo new product items from this form here, but omit any line
854 // whose Delete checkbox is checked.
856 if ($_POST['prod']) {
857 foreach ($_POST['prod'] as $key => $iter) {
858 if ($iter["sale_id"]) continue; // skip if it came from the database
859 if ($iter["del"]) continue; // skip if Delete was checked
860 // $fee = 0 + trim($iter['fee']);
861 $units = max(1, intval(trim($iter['units'])));
862 $fee = sprintf('%01.2f',(0 + trim($iter['price'])) * $units);
863 echoProdLine(++$prod_lino, $iter['drug_id'], FALSE, $units, $fee);
867 // If new billing code(s) were <select>ed, add their line(s) here.
869 if ($_POST['newcodes']) {
870 $arrcodes = explode('~', $_POST['newcodes']);
871 foreach ($arrcodes as $codestring) {
872 if ($codestring === '') continue;
873 $arrcode = explode('|', $codestring);
874 $newtype = $arrcode[0];
875 $newcode = $arrcode[1];
876 $newsel = $arrcode[2];
877 if ($newtype == 'COPAY') {
878 $tmp = sqlQuery("SELECT copay FROM insurance_data WHERE pid = '$pid' " .
879 "AND type = 'primary' ORDER BY date DESC LIMIT 1");
880 $code = sprintf('%01.2f', 0 + $tmp['copay']);
881 echoLine(++$bill_lino, $newtype, $code, '', '', '1', '0', '1',
882 sprintf('%01.2f', 0 - $code));
884 else if ($newtype == 'PROD') {
885 $result = sqlQuery("SELECT * FROM drug_templates WHERE " .
886 "drug_id = '$newcode' AND selector = '$newsel'");
887 $units = max(1, intval($result['quantity']));
888 $prrow = sqlQuery("SELECT prices.pr_price " .
889 "FROM patient_data, prices WHERE " .
890 "patient_data.pid = '$pid' AND " .
891 "prices.pr_id = '$newcode' AND " .
892 "prices.pr_selector = '$newsel' AND " .
893 "prices.pr_level = patient_data.pricelevel " .
894 "LIMIT 1");
895 $fee = empty($prrow) ? 0 : $prrow['pr_price'];
896 echoProdLine(++$prod_lino, $newcode, FALSE, $units, $fee);
898 else {
899 list($code, $modifier) = explode(":", $newcode);
900 $ndc_info = '';
901 // If HCPCS, find last NDC string used for this code.
902 if ($newtype == 'HCPCS' && $ndc_applies) {
903 $tmp = sqlQuery("SELECT ndc_info FROM billing WHERE " .
904 "code_type = '$newtype' AND code = '$code' AND ndc_info LIKE 'N4%' " .
905 "ORDER BY date DESC LIMIT 1");
906 if (!empty($tmp)) $ndc_info = $tmp['ndc_info'];
908 echoLine(++$bill_lino, $newtype, $code, trim($modifier), $ndc_info);
913 // If no valid provider yet, try setting it to that of the new encounter form.
915 $tmp = sqlQuery("SELECT authorized FROM users WHERE id = '$encounter_provid'");
916 if (empty($tmp['authorized'])) {
917 $encounter_provid = -1;
918 $tmp = sqlQuery("SELECT users.id FROM forms, users WHERE " .
919 "forms.pid = '$pid' AND forms.encounter = '$encounter' AND " .
920 "forms.formdir='newpatient' AND users.username = forms.user AND " .
921 "users.authorized = 1");
922 if ($tmp['id']) $encounter_provid = $tmp['id'];
925 // If still no default provider then make it the logged-in user.
927 if ($encounter_provid < 0) $encounter_provid = $_SESSION["authUserID"];
929 </table>
930 </p>
932 <br>
933 &nbsp;
935 <?php
936 // If applicable, ask for the contraceptive services start date.
937 $trow = sqlQuery("SELECT count(*) AS count FROM layout_options WHERE " .
938 "form_id = 'DEM' AND field_id = 'contrastart' AND uor > 0");
939 if ($trow['count']) {
940 $trow = sqlQuery("SELECT contrastart " .
941 "FROM patient_data, prices WHERE " .
942 "patient_data.pid = '$pid' LIMIT 1");
943 if (empty($trow['contrastart']) || substr($trow['contrastart'], 0, 4) == '0000') {
944 $trow = sqlQuery("SELECT date FROM form_encounter WHERE " .
945 "pid = '$pid' AND encounter = '$encounter' LIMIT 1");
946 $date1 = substr($trow['date'], 0, 10);
947 $date0 = date('Y-m-d', strtotime($date1) - (60 * 60 * 24));
948 echo " <select name='contrastart'>\n";
949 echo " <option value='$date1'>" . xl('This visit begins new contraceptive use') . "</option>\n";
950 echo " <option value='$date0'>" . xl('Contraceptive services previously started') . "</option>\n";
951 echo " <option value=''>" . xl('None of the above') . "</option>\n";
952 echo " </select>\n";
953 echo "&nbsp; &nbsp; &nbsp;\n";
958 <span class="billcell"><b><?php xl('Provider:','e');?></b></span>
960 <?php
961 // Build a drop-down list of providers. This includes users who
962 // have the word "provider" anywhere in their "additional info"
963 // field, so that we can define providers (for billing purposes)
964 // who do not appear in the calendar.
966 $query = "SELECT id, lname, fname FROM users WHERE " .
967 "( authorized = 1 OR info LIKE '%provider%' ) AND username != '' " .
968 "ORDER BY lname, fname";
969 $res = sqlStatement($query);
971 echo " <select name='ProviderID'>\n";
972 echo " <option value=''>-- Please Select --\n";
974 while ($row = sqlFetchArray($res)) {
975 $provid = $row['id'];
976 echo " <option value='$provid'";
977 if ($provid == $encounter_provid) echo " selected";
978 echo ">" . $row['lname'] . ", " . $row['fname'] . "\n";
981 echo " </select>\n";
984 &nbsp; &nbsp; &nbsp;
986 <input type='submit' name='bn_save' value='<?php xl('Save','e');?>' />
987 &nbsp;
988 <input type='submit' name='bn_refresh' value='<?php xl('Refresh','e');?>'>
989 &nbsp;
990 <input type='button' value='<?php xl('Cancel','e');?>'
991 onclick="top.restoreSession();location='<?php echo "$rootdir/patient_file/encounter/$returnurl" ?>'" />
993 <?php if ($code_types['UCSMC']) { ?>
994 <p style='font-family:sans-serif;font-size:8pt;color:#666666;'>
995 &nbsp;<br>
996 <?php xl('UCSMC codes provided by the University of Calgary Sports Medicine Centre','e');?>
997 </p>
998 <?php } ?>
1000 </center>
1002 </form>
1004 <?php
1005 // TBD: If $alertmsg, display it with a JavaScript alert().
1008 <script language='JavaScript'>
1009 <?php echo $justinit; ?>
1010 </script>
1012 </body>
1013 </html>