Print receipt header by provider.
[openemr.git] / interface / patient_file / pos_checkout.php
blob8924aa6d6d97fe8ef9fa7b8f1d973ad7c2dc71d1
1 <?php
2 // Copyright (C) 2006-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 // This module supports a popup window to handle patient checkout
10 // as a point-of-sale transaction. Support for in-house drug sales
11 // is included.
13 // Important notes about system design:
15 // (1) Drug sales may or may not be associated with an encounter;
16 // they are if they are paid for concurrently with an encounter, or
17 // if they are "product" (non-prescription) sales via the Fee Sheet.
18 // (2) Drug sales without an encounter will have 20YYMMDD, possibly
19 // with a suffix, as the encounter-number portion of their invoice
20 // number.
21 // (3) Payments are saved as AR only, don't mess with the billing table.
22 // See library/classes/WSClaim.class.php for posting code.
23 // (4) On checkout, the billing and drug_sales table entries are marked
24 // as billed and so become unavailable for further billing.
25 // (5) Receipt printing must be a separate operation from payment,
26 // and repeatable.
29 // TBD:
30 // If this user has 'irnpool' set
31 // on display of checkout form
32 // show pending next invoice number
33 // on applying checkout
34 // save next invoice number to form_encounter
35 // compute new next invoice number
36 // on receipt display
37 // show invoice number
39 require_once("../globals.php");
40 require_once("$srcdir/acl.inc");
41 require_once("$srcdir/patient.inc");
42 require_once("$srcdir/billing.inc");
43 require_once("$srcdir/sql-ledger.inc");
44 require_once("$srcdir/freeb/xmlrpc.inc");
45 require_once("$srcdir/freeb/xmlrpcs.inc");
46 require_once("$srcdir/formatting.inc.php");
47 require_once("$srcdir/formdata.inc.php");
48 require_once("../../custom/code_types.inc.php");
50 $currdecimals = $GLOBALS['currency_decimals'];
52 $INTEGRATED_AR = $GLOBALS['oer_config']['ws_accounting']['enabled'] === 2;
54 $details = empty($_GET['details']) ? 0 : 1;
56 $patient_id = empty($_GET['ptid']) ? $pid : 0 + $_GET['ptid'];
58 // Get the patient's name and chart number.
59 $patdata = getPatientData($patient_id, 'fname,mname,lname,pubpid,street,city,state,postal_code');
61 // Get the "next invoice reference number" from this user's pool.
63 function getInvoiceRefNumber() {
64 $trow = sqlQuery("SELECT lo.notes " .
65 "FROM users AS u, list_options AS lo " .
66 "WHERE u.username = '" . $_SESSION['authUser'] . "' AND " .
67 "lo.list_id = 'irnpool' AND lo.option_id = u.irnpool LIMIT 1");
68 return empty($trow['notes']) ? '' : $trow['notes'];
71 // Increment the "next invoice reference number" of this user's pool.
72 // This identifies the "digits" portion of that number and adds 1 to it.
73 // If it contains more than one string of digits, the last is used.
75 function updateInvoiceRefNumber() {
76 $irnumber = getInvoiceRefNumber();
77 // Here "?" specifies a minimal match, to get the most digits possible:
78 if (preg_match('/^(.*?)(\d+)(\D*)$/', $irnumber, $matches)) {
79 $newdigs = sprintf('%0' . strlen($matches[2]) . 'd', $matches[2] + 1);
80 $newnumber = add_escape_custom($matches[1] . $newdigs . $matches[3]);
81 sqlStatement("UPDATE users AS u, list_options AS lo " .
82 "SET lo.notes = '$newnumber' WHERE " .
83 "u.username = '" . $_SESSION['authUser'] . "' AND " .
84 "lo.list_id = 'irnpool' AND lo.option_id = u.irnpool");
86 return $irnumber;
89 //////////////////////////////////////////////////////////////////////
90 // The following functions are inline here temporarily, and should be
91 // moved to an includable module for common use. In particular
92 // WSClaim.class.php should be rewritten to use them.
93 //////////////////////////////////////////////////////////////////////
95 // Initialize the array of invoice information for posting to the
96 // accounting system.
98 function invoice_initialize(& $invoice_info, $patient_id, $provider_id,
99 $payer_id = 0, $encounter = 0, $dosdate = '')
101 $db = $GLOBALS['adodb']['db'];
103 // Get foreign ID (customer) for patient.
104 $sql = "SELECT foreign_id from integration_mapping as im " .
105 "LEFT JOIN patient_data as pd on im.local_id=pd.id " .
106 "where pd.pid = '" .
107 $patient_id .
108 "' and im.local_table='patient_data' and im.foreign_table='customer'";
109 $result = $db->Execute($sql);
110 if($result && !$result->EOF) {
111 $foreign_patient_id = $result->fields['foreign_id'];
113 else {
114 return "Patient '" . $patient_id . "' has not yet been posted to the accounting system.";
117 // Get foreign ID (salesman) for provider.
118 $sql = "SELECT foreign_id from integration_mapping WHERE " .
119 "local_id = $provider_id AND local_table='users' and foreign_table='salesman'";
120 $result = $db->Execute($sql);
121 if($result && !$result->EOF) {
122 $foreign_provider_id = $result->fields['foreign_id'];
124 else {
125 return "Provider '" . $provider_id . "' has not yet been posted to the accounting system.";
128 // Get foreign ID (customer) for insurance payer.
129 if ($payer_id && ! $GLOBALS['insurance_companies_are_not_customers']) {
130 $sql = "SELECT foreign_id from integration_mapping WHERE " .
131 "local_id = $payer_id AND local_table = 'insurance_companies' AND foreign_table='customer'";
132 $result = $db->Execute($sql);
133 if($result && !$result->EOF) {
134 $foreign_payer_id = $result->fields['foreign_id'];
136 else {
137 return "Payer '" . $payer_id . "' has not yet been posted to the accounting system.";
139 } else {
140 $foreign_payer_id = $payer_id;
143 // Create invoice notes for the new invoice that list the patient's
144 // insurance plans. This is so that when payments are posted, the user
145 // can easily see if a secondary claim needs to be submitted.
147 $insnotes = "";
148 $insno = 0;
149 foreach (array("primary", "secondary", "tertiary") as $instype) {
150 ++$insno;
151 $sql = "SELECT insurance_companies.name " .
152 "FROM insurance_data, insurance_companies WHERE " .
153 "insurance_data.pid = $patient_id AND " .
154 "insurance_data.type = '$instype' AND " .
155 "insurance_companies.id = insurance_data.provider " .
156 "ORDER BY insurance_data.date DESC LIMIT 1";
157 $result = $db->Execute($sql);
158 if ($result && !$result->EOF && $result->fields['name']) {
159 if ($insnotes) $insnotes .= "\n";
160 $insnotes .= "Ins$insno: " . $result->fields['name'];
163 $invoice_info['notes'] = $insnotes;
165 if (preg_match("/(\d\d\d\d)\D*(\d\d)\D*(\d\d)/", $dosdate, $matches)) {
166 $dosdate = $matches[2] . '-' . $matches[3] . '-' . $matches[1];
167 } else {
168 $dosdate = date("m-d-Y");
171 $invoice_info['salesman'] = $foreign_provider_id;
172 $invoice_info['customerid'] = $foreign_patient_id;
173 $invoice_info['payer_id'] = $foreign_payer_id;
174 $invoice_info['invoicenumber'] = $patient_id . "." . $encounter;
175 $invoice_info['dosdate'] = $dosdate;
176 $invoice_info['items'] = array();
177 $invoice_info['total'] = '0.00';
179 return '';
182 function invoice_add_line_item(& $invoice_info, $code_type, $code,
183 $code_text, $amount, $units=1)
185 $units = max(1, intval(trim($units)));
186 $amount = sprintf("%01.2f", $amount);
187 $price = $amount / $units;
188 $tmp = sprintf("%01.2f", $price);
189 if (abs($price - $tmp) < 0.000001) $price = $tmp;
190 $tii = array();
191 $tii['maincode'] = $code;
192 $tii['itemtext'] = "$code_type:$code";
193 if ($code_text) $tii['itemtext'] .= " $code_text";
194 $tii['qty'] = $units;
195 $tii['price'] = $price;
196 $tii['glaccountid'] = $GLOBALS['oer_config']['ws_accounting']['income_acct'];
197 $invoice_info['total'] = sprintf("%01.2f", $invoice_info['total'] + $amount);
198 $invoice_info['items'][] = $tii;
199 return '';
202 function invoice_post(& $invoice_info)
204 $function['ezybiz.add_invoice'] = array(new xmlrpcval($invoice_info, "struct"));
206 list($name, $var) = each($function);
207 $f = new xmlrpcmsg($name, $var);
209 $c = new xmlrpc_client($GLOBALS['oer_config']['ws_accounting']['url'],
210 $GLOBALS['oer_config']['ws_accounting']['server'],
211 $GLOBALS['oer_config']['ws_accounting']['port']);
213 $c->setCredentials($GLOBALS['oer_config']['ws_accounting']['username'],
214 $GLOBALS['oer_config']['ws_accounting']['password']);
216 $r = $c->send($f);
217 if (!$r) return "XMLRPC send failed";
219 // We are not doing anything with the return value yet... should we?
220 $tv = $r->value();
221 if (is_object($tv)) {
222 $value = $tv->getval();
224 else {
225 $value = null;
228 if ($r->faultCode()) {
229 return "Fault: Code: " . $r->faultCode() . " Reason '" . $r->faultString() . "'";
232 return '';
235 ///////////// End of SQL-Ledger invoice posting functions ////////////
237 // Output HTML for an invoice line item.
239 $prevsvcdate = '';
240 function receiptDetailLine($svcdate, $description, $amount, $quantity) {
241 global $prevsvcdate, $details;
242 if (!$details) return;
243 $amount = sprintf('%01.2f', $amount);
244 if (empty($quantity)) $quantity = 1;
245 $price = sprintf('%01.4f', $amount / $quantity);
246 $tmp = sprintf('%01.2f', $price);
247 if ($price == $tmp) $price = $tmp;
248 echo " <tr>\n";
249 echo " <td>" . ($svcdate == $prevsvcdate ? '&nbsp;' : oeFormatShortDate($svcdate)) . "</td>\n";
250 echo " <td>$description</td>\n";
251 echo " <td align='right'>" . oeFormatMoney($price) . "</td>\n";
252 echo " <td align='right'>$quantity</td>\n";
253 echo " <td align='right'>" . oeFormatMoney($amount) . "</td>\n";
254 echo " </tr>\n";
255 $prevsvcdate = $svcdate;
258 // Output HTML for an invoice payment.
260 function receiptPaymentLine($paydate, $amount, $description='') {
261 $amount = sprintf('%01.2f', 0 - $amount); // make it negative
262 echo " <tr>\n";
263 echo " <td>" . oeFormatShortDate($paydate) . "</td>\n";
264 echo " <td>" . xl('Payment') . " $description</td>\n";
265 echo " <td colspan='2'>&nbsp;</td>\n";
266 echo " <td align='right'>" . oeFormatMoney($amount) . "</td>\n";
267 echo " </tr>\n";
270 // Generate a receipt from the last-billed invoice for this patient,
271 // or for the encounter specified as a GET parameter.
273 function generate_receipt($patient_id, $encounter=0) {
274 global $sl_err, $sl_cash_acc, $css_header, $details, $INTEGRATED_AR;
276 // Get details for what we guess is the primary facility.
277 $frow = sqlQuery("SELECT * FROM facility " .
278 "ORDER BY billing_location DESC, accepts_assignment DESC, id LIMIT 1");
280 $patdata = getPatientData($patient_id, 'fname,mname,lname,pubpid,street,city,state,postal_code,providerID');
282 // Get the most recent invoice data or that for the specified encounter.
284 // Adding a provider check so that their info can be displayed on receipts
285 if ($INTEGRATED_AR) {
286 if ($encounter) {
287 $ferow = sqlQuery("SELECT id, date, encounter, provider_id FROM form_encounter " .
288 "WHERE pid = '$patient_id' AND encounter = '$encounter'");
289 } else {
290 $ferow = sqlQuery("SELECT id, date, encounter, provider_id FROM form_encounter " .
291 "WHERE pid = '$patient_id' " .
292 "ORDER BY id DESC LIMIT 1");
294 if (empty($ferow)) die(xl("This patient has no activity."));
295 $trans_id = $ferow['id'];
296 $encounter = $ferow['encounter'];
297 $svcdate = substr($ferow['date'], 0, 10);
299 if ($GLOBALS['receipts_by_provider']){
300 if (isset($ferow['provider_id']) ) {
301 $encprovider = $ferow['provider_id'];
302 } else if (isset($patdata['providerID'])){
303 $encprovider = $patdata['providerID'];
304 } else { $encprovider = -1; }
307 if ($encprovider){
308 $providerrow = sqlQuery("SELECT fname, mname, lname, title, street, streetb, " .
309 "city, state, zip, phone, fax FROM users WHERE id = $encprovider");
312 else {
313 SLConnect();
315 $arres = SLQuery("SELECT * FROM ar WHERE " .
316 "invnumber LIKE '$patient_id.%' " .
317 "ORDER BY id DESC LIMIT 1");
318 if ($sl_err) die($sl_err);
319 if (!SLRowCount($arres)) die(xl("This patient has no activity."));
320 $arrow = SLGetRow($arres, 0);
322 $trans_id = $arrow['id'];
324 // Determine the date of service. An 8-digit encounter number is
325 // presumed to be a date of service imported during conversion or
326 // associated with prescriptions only. Otherwise look it up in the
327 // form_encounter table.
329 $svcdate = "";
330 list($trash, $encounter) = explode(".", $arrow['invnumber']);
331 if (strlen($encounter) >= 8) {
332 $svcdate = substr($encounter, 0, 4) . "-" . substr($encounter, 4, 2) .
333 "-" . substr($encounter, 6, 2);
335 else if ($encounter) {
336 $tmp = sqlQuery("SELECT date FROM form_encounter WHERE " .
337 "encounter = $encounter");
338 $svcdate = substr($tmp['date'], 0, 10);
340 } // end not $INTEGRATED_AR
342 // Get invoice reference number.
343 $encrow = sqlQuery("SELECT invoice_refno FROM form_encounter WHERE " .
344 "pid = '$patient_id' AND encounter = '$encounter' LIMIT 1");
345 $invoice_refno = $encrow['invoice_refno'];
347 <html>
348 <head>
349 <?php html_header_show(); ?>
350 <link rel='stylesheet' href='<?php echo $css_header ?>' type='text/css'>
351 <title><?php xl('Receipt for Payment','e'); ?></title>
352 <script type="text/javascript" src="../../library/dialog.js"></script>
353 <script language="JavaScript">
355 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
357 // Process click on Print button.
358 function printme() {
359 var divstyle = document.getElementById('hideonprint').style;
360 divstyle.display = 'none';
361 window.print();
362 return false;
365 // Process click on Delete button.
366 function deleteme() {
367 dlgopen('deleter.php?billing=<?php echo "$patient_id.$encounter"; ?>', '_blank', 500, 450);
368 return false;
371 // Called by the deleteme.php window on a successful delete.
372 function imdeleted() {
373 window.close();
376 </script>
377 </head>
378 <body class="body_top">
379 <center>
380 <?php
381 if ( $GLOBALS['receipts_by_provider'] && !empty($providerrow) ) { printProviderHeader($providerrow); }
382 else { printFacilityHeader($frow); }
384 <?php
385 echo xl("Receipt Generated") . date(' F j, Y');
386 if ($invoice_refno) echo " " . xl("for Invoice") . " $invoice_refno dated " . $svcdate;
388 <br>&nbsp;
389 </b></p>
390 </center>
392 <?php echo $patdata['fname'] . ' ' . $patdata['mname'] . ' ' . $patdata['lname'] ?>
393 <br><?php echo $patdata['street'] ?>
394 <br><?php echo $patdata['city'] . ', ' . $patdata['state'] . ' ' . $patdata['postal_code'] ?>
395 <br>&nbsp;
396 </p>
397 <center>
398 <table cellpadding='5'>
399 <tr>
400 <td><b><?php xl('Date','e'); ?></b></td>
401 <td><b><?php xl('Description','e'); ?></b></td>
402 <td align='right'><b><?php echo $details ? xl('Price') : '&nbsp;'; ?></b></td>
403 <td align='right'><b><?php echo $details ? xl('Qty' ) : '&nbsp;'; ?></b></td>
404 <td align='right'><b><?php xl('Total','e'); ?></b></td>
405 </tr>
407 <?php
408 $charges = 0.00;
410 if ($INTEGRATED_AR) {
411 // Product sales
412 $inres = sqlStatement("SELECT s.sale_id, s.sale_date, s.fee, " .
413 "s.quantity, s.drug_id, d.name " .
414 "FROM drug_sales AS s LEFT JOIN drugs AS d ON d.drug_id = s.drug_id " .
415 // "WHERE s.pid = '$patient_id' AND s.encounter = '$encounter' AND s.fee != 0 " .
416 "WHERE s.pid = '$patient_id' AND s.encounter = '$encounter' " .
417 "ORDER BY s.sale_id");
418 while ($inrow = sqlFetchArray($inres)) {
419 $charges += sprintf('%01.2f', $inrow['fee']);
420 receiptDetailLine($inrow['sale_date'], $inrow['name'],
421 $inrow['fee'], $inrow['quantity']);
423 // Service and tax items
424 $inres = sqlStatement("SELECT * FROM billing WHERE " .
425 "pid = '$patient_id' AND encounter = '$encounter' AND " .
426 // "code_type != 'COPAY' AND activity = 1 AND fee != 0 " .
427 "code_type != 'COPAY' AND activity = 1 " .
428 "ORDER BY id");
429 while ($inrow = sqlFetchArray($inres)) {
430 $charges += sprintf('%01.2f', $inrow['fee']);
431 receiptDetailLine($svcdate, $inrow['code_text'],
432 $inrow['fee'], $inrow['units']);
434 // Adjustments.
435 $inres = sqlStatement("SELECT " .
436 "a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, " .
437 "s.payer_id, s.reference, s.check_date, s.deposit_date " .
438 "FROM ar_activity AS a " .
439 "LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " .
440 "a.pid = '$patient_id' AND a.encounter = '$encounter' AND " .
441 "a.adj_amount != 0 " .
442 "ORDER BY s.check_date, a.sequence_no");
443 while ($inrow = sqlFetchArray($inres)) {
444 $charges -= sprintf('%01.2f', $inrow['adj_amount']);
445 $payer = empty($inrow['payer_type']) ? 'Pt' : ('Ins' . $inrow['payer_type']);
446 receiptDetailLine($svcdate, $payer . ' ' . $inrow['memo'],
447 0 - $inrow['adj_amount'], 1);
449 } // end $INTEGRATED_AR
450 else {
451 // Request all line items with money belonging to the invoice.
452 $inres = SLQuery("SELECT * FROM invoice WHERE " .
453 "trans_id = $trans_id AND sellprice != 0 ORDER BY id");
454 if ($sl_err) die($sl_err);
455 for ($irow = 0; $irow < SLRowCount($inres); ++$irow) {
456 $row = SLGetRow($inres, $irow);
457 $amount = sprintf('%01.2f', $row['sellprice'] * $row['qty']);
458 $charges += $amount;
459 $desc = preg_replace('/^.{1,6}:/', '', $row['description']);
460 receiptDetailLine($svcdate, $desc, $amount, $row['qty']);
462 } // end not $INTEGRATED_AR
465 <tr>
466 <td colspan='5'>&nbsp;</td>
467 </tr>
468 <tr>
469 <td><?php echo oeFormatShortDate($svcdispdate); ?></td>
470 <td><b><?php xl('Total Charges','e'); ?></b></td>
471 <td align='right'>&nbsp;</td>
472 <td align='right'>&nbsp;</td>
473 <td align='right'><?php echo oeFormatMoney($charges, true) ?></td>
474 </tr>
475 <tr>
476 <td colspan='5'>&nbsp;</td>
477 </tr>
479 <?php
480 if ($INTEGRATED_AR) {
481 // Get co-pays.
482 $inres = sqlStatement("SELECT fee, code_text FROM billing WHERE " .
483 "pid = '$patient_id' AND encounter = '$encounter' AND " .
484 "code_type = 'COPAY' AND activity = 1 AND fee != 0 " .
485 "ORDER BY id");
486 while ($inrow = sqlFetchArray($inres)) {
487 $charges += sprintf('%01.2f', $inrow['fee']);
488 receiptPaymentLine($svcdate, 0 - $inrow['fee'], $inrow['code_text']);
490 // Get other payments.
491 $inres = sqlStatement("SELECT " .
492 "a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, " .
493 "s.payer_id, s.reference, s.check_date, s.deposit_date " .
494 "FROM ar_activity AS a " .
495 "LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " .
496 "a.pid = '$patient_id' AND a.encounter = '$encounter' AND " .
497 "a.pay_amount != 0 " .
498 "ORDER BY s.check_date, a.sequence_no");
499 $payer = empty($inrow['payer_type']) ? 'Pt' : ('Ins' . $inrow['payer_type']);
500 while ($inrow = sqlFetchArray($inres)) {
501 $charges -= sprintf('%01.2f', $inrow['pay_amount']);
502 receiptPaymentLine($svcdate, $inrow['pay_amount'],
503 $payer . ' ' . $inrow['reference']);
505 } // end $INTEGRATED_AR
506 else {
507 $chart_id_cash = SLQueryValue("select id from chart where accno = '$sl_cash_acc'");
508 if ($sl_err) die($sl_err);
509 if (! $chart_id_cash) die("There is no COA entry for cash account '$sl_cash_acc'");
511 // Request all cash entries belonging to the invoice.
512 $atres = SLQuery("SELECT * FROM acc_trans WHERE " .
513 "trans_id = $trans_id AND chart_id = $chart_id_cash ORDER BY transdate");
514 if ($sl_err) die($sl_err);
516 for ($irow = 0; $irow < SLRowCount($atres); ++$irow) {
517 $row = SLGetRow($atres, $irow);
518 $amount = sprintf('%01.2f', $row['amount']); // negative
519 $charges += $amount;
520 $rowsource = $row['source'];
521 if (strtolower($rowsource) == 'co-pay') $rowsource = '';
522 receiptPaymentLine($row['transdate'], 0 - $amount, $rowsource);
524 } // end not $INTEGRATED_AR
526 <tr>
527 <td colspan='5'>&nbsp;</td>
528 </tr>
529 <tr>
530 <td>&nbsp;</td>
531 <td><b><?php xl('Balance Due','e'); ?></b></td>
532 <td colspan='2'>&nbsp;</td>
533 <td align='right'><?php echo oeFormatMoney($charges, true) ?></td>
534 </tr>
535 </table>
536 </center>
537 <div id='hideonprint'>
539 &nbsp;
540 <a href='#' onclick='return printme();'><?php xl('Print','e'); ?></a>
541 <?php if (acl_check('acct','disc')) { ?>
542 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
543 <a href='#' onclick='return deleteme();'><?php xl('Undo Checkout','e'); ?></a>
544 <?php } ?>
545 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
546 <?php if ($details) { ?>
547 <a href='pos_checkout.php?details=0&ptid=<?php echo $patient_id; ?>&enc=<?php echo $encounter; ?>'><?php xl('Hide Details','e'); ?></a>
548 <?php } else { ?>
549 <a href='pos_checkout.php?details=1&ptid=<?php echo $patient_id; ?>&enc=<?php echo $encounter; ?>'><?php xl('Show Details','e'); ?></a>
550 <?php } ?>
551 </p>
552 </div>
553 </body>
554 </html>
555 <?php
556 if (!$INTEGRATED_AR) SLClose();
557 } // end function generate_receipt()
559 // Function to output a line item for the input form.
561 $lino = 0;
562 function write_form_line($code_type, $code, $id, $date, $description,
563 $amount, $units, $taxrates) {
564 global $lino;
565 $amount = sprintf("%01.2f", $amount);
566 if (empty($units)) $units = 1;
567 $price = $amount / $units; // should be even cents, but ok here if not
568 if ($code_type == 'COPAY' && !$description) $description = xl('Payment');
569 echo " <tr>\n";
570 echo " <td>" . oeFormatShortDate($date);
571 echo "<input type='hidden' name='line[$lino][code_type]' value='$code_type'>";
572 echo "<input type='hidden' name='line[$lino][code]' value='$code'>";
573 echo "<input type='hidden' name='line[$lino][id]' value='$id'>";
574 echo "<input type='hidden' name='line[$lino][description]' value='$description'>";
575 echo "<input type='hidden' name='line[$lino][taxrates]' value='$taxrates'>";
576 echo "<input type='hidden' name='line[$lino][price]' value='$price'>";
577 echo "<input type='hidden' name='line[$lino][units]' value='$units'>";
578 echo "</td>\n";
579 echo " <td>$description</td>";
580 echo " <td align='right'>$units</td>";
581 echo " <td align='right'><input type='text' name='line[$lino][amount]' " .
582 "value='$amount' size='6' maxlength='8'";
583 // Modifying prices requires the acct/disc permission.
584 // if ($code_type == 'TAX' || ($code_type != 'COPAY' && !acl_check('acct','disc')))
585 echo " style='text-align:right;background-color:transparent' readonly";
586 // else echo " style='text-align:right' onkeyup='computeTotals()'";
587 echo "></td>\n";
588 echo " </tr>\n";
589 ++$lino;
592 // Create the taxes array. Key is tax id, value is
593 // (description, rate, accumulated total).
594 $taxes = array();
595 $pres = sqlStatement("SELECT option_id, title, option_value " .
596 "FROM list_options WHERE list_id = 'taxrate' ORDER BY seq");
597 while ($prow = sqlFetchArray($pres)) {
598 $taxes[$prow['option_id']] = array($prow['title'], $prow['option_value'], 0);
601 // Print receipt header for facility
602 function printFacilityHeader($frow){
603 echo "<p><b>" . $frow['name'] .
604 "<br>" . $frow['street'] .
605 "<br>" . $frow['city'] . ', ' . $frow['state'] . ' ' . $frow['postal_code'] .
606 "<br>" . $frow['phone'] .
607 "<br>&nbsp" .
608 "<br>";
611 // Pring receipt header for Provider
612 function printProviderHeader($pvdrow){
613 echo "<p><b>" . $pvdrow['title'] . " " . $pvdrow['fname'] . " " . $pvdrow['mname'] . " " . $pvdrow['lname'] . " " .
614 "<br>" . $pvdrow['street'] .
615 "<br>" . $pvdrow['city'] . ', ' . $pvdrow['state'] . ' ' . $pvdrow['postal_code'] .
616 "<br>" . $pvdrow['phone'] .
617 "<br>&nbsp" .
618 "<br>";
621 // Mark the tax rates that are referenced in this invoice.
622 function markTaxes($taxrates) {
623 global $taxes;
624 $arates = explode(':', $taxrates);
625 if (empty($arates)) return;
626 foreach ($arates as $value) {
627 if (!empty($taxes[$value])) $taxes[$value][2] = '1';
631 $payment_methods = array(
632 'Cash',
633 'Check',
634 'MC',
635 'VISA',
636 'AMEX',
637 'DISC',
638 'Other');
640 $alertmsg = ''; // anything here pops up in an alert box
642 // If the Save button was clicked...
644 if ($_POST['form_save']) {
646 // On a save, do the following:
647 // Flag drug_sales and billing items as billed.
648 // Post the corresponding invoice with its payment(s) to sql-ledger
649 // and be careful to use a unique invoice number.
650 // Call the generate-receipt function.
651 // Exit.
653 $form_pid = $_POST['form_pid'];
654 $form_encounter = $_POST['form_encounter'];
656 // Get the posting date from the form as yyyy-mm-dd.
657 $dosdate = date("Y-m-d");
658 if (preg_match("/(\d\d\d\d)\D*(\d\d)\D*(\d\d)/", $_POST['form_date'], $matches)) {
659 $dosdate = $matches[1] . '-' . $matches[2] . '-' . $matches[3];
662 // If there is no associated encounter (i.e. this invoice has only
663 // prescriptions) then assign an encounter number of the service
664 // date, with an optional suffix to ensure that it's unique.
666 if (! $form_encounter) {
667 $form_encounter = substr($dosdate,0,4) . substr($dosdate,5,2) . substr($dosdate,8,2);
668 $tmp = '';
669 if ($INTEGRATED_AR) {
670 while (true) {
671 $ferow = sqlQuery("SELECT id FROM form_encounter WHERE " .
672 "pid = '$form_pid' AND encounter = '$form_encounter$tmp'");
673 if (empty($ferow)) break;
674 $tmp = $tmp ? $tmp + 1 : 1;
677 else {
678 SLConnect();
679 while (SLQueryValue("select id from ar where " .
680 "invnumber = '$form_pid.$form_encounter$tmp'")) {
681 $tmp = $tmp ? $tmp + 1 : 1;
683 SLClose();
685 $form_encounter .= $tmp;
688 if ($INTEGRATED_AR) {
689 // Delete any TAX rows from billing because they will be recalculated.
690 sqlStatement("UPDATE billing SET activity = 0 WHERE " .
691 "pid = '$form_pid' AND encounter = '$form_encounter' AND " .
692 "code_type = 'TAX'");
694 else {
695 // Initialize an array of invoice information for posting.
696 $invoice_info = array();
697 $msg = invoice_initialize($invoice_info, $form_pid,
698 $_POST['form_provider'], $_POST['form_payer'], $form_encounter, $dosdate);
699 if ($msg) die($msg);
702 $form_amount = $_POST['form_amount'];
703 $lines = $_POST['line'];
705 for ($lino = 0; $lines[$lino]['code_type']; ++$lino) {
706 $line = $lines[$lino];
707 $code_type = $line['code_type'];
708 $id = $line['id'];
709 $amount = sprintf('%01.2f', trim($line['amount']));
711 if (!$INTEGRATED_AR) {
712 $msg = invoice_add_line_item($invoice_info, $code_type,
713 $line['code'], $line['description'], $amount, $line['units']);
714 if ($msg) die($msg);
717 if ($code_type == 'PROD') {
718 // Product sales. The fee and encounter ID may have changed.
719 $query = "update drug_sales SET fee = '$amount', " .
720 "encounter = '$form_encounter', billed = 1 WHERE " .
721 "sale_id = '$id'";
722 sqlQuery($query);
724 else if ($code_type == 'TAX') {
725 // In the SL case taxes show up on the invoice as line items.
726 // Otherwise we gotta save them somewhere, and in the billing
727 // table with a code type of TAX seems easiest.
728 // They will have to be stripped back out when building this
729 // script's input form.
730 addBilling($form_encounter, 'TAX', 'TAX', 'Taxes', $form_pid, 0, 0,
731 '', '', $amount, '', '', 1);
733 else {
734 // Because there is no insurance here, there is no need for a claims
735 // table entry and so we do not call updateClaim(). Note we should not
736 // eliminate billed and bill_date from the billing table!
737 $query = "UPDATE billing SET fee = '$amount', billed = 1, " .
738 "bill_date = NOW() WHERE id = '$id'";
739 sqlQuery($query);
743 // Post discount.
744 if ($_POST['form_discount']) {
745 if ($GLOBALS['discount_by_money']) {
746 $amount = sprintf('%01.2f', trim($_POST['form_discount']));
748 else {
749 $amount = sprintf('%01.2f', trim($_POST['form_discount']) * $form_amount / 100);
751 $memo = xl('Discount');
752 if ($INTEGRATED_AR) {
753 $time = date('Y-m-d H:i:s');
754 $query = "INSERT INTO ar_activity ( " .
755 "pid, encounter, code, modifier, payer_type, post_user, post_time, " .
756 "session_id, memo, adj_amount " .
757 ") VALUES ( " .
758 "'$form_pid', " .
759 "'$form_encounter', " .
760 "'', " .
761 "'', " .
762 "'0', " .
763 "'" . $_SESSION['authUserID'] . "', " .
764 "'$time', " .
765 "'0', " .
766 "'$memo', " .
767 "'$amount' " .
768 ")";
769 sqlStatement($query);
771 else {
772 $msg = invoice_add_line_item($invoice_info, 'DISCOUNT',
773 '', $memo, 0 - $amount);
774 if ($msg) die($msg);
778 // Post payment.
779 if ($_POST['form_amount']) {
780 $amount = sprintf('%01.2f', trim($_POST['form_amount']));
781 $form_source = trim($_POST['form_source']);
782 $paydesc = trim($_POST['form_method']);
783 if ($INTEGRATED_AR) {
784 // Post the payment as a billed copay into the billing table.
785 // Maybe this should even be done for the SL case.
786 if (!empty($form_source)) $paydesc .= " $form_source";
787 # jason forced auth line to 1 here
788 addBilling($form_encounter, 'COPAY', $amount, $paydesc, $form_pid,
789 1, 0, '', '', 0 - $amount, '', '', 1);
791 else {
792 $msg = invoice_add_line_item($invoice_info, 'COPAY',
793 $paydesc, $form_source, 0 - $amount);
794 if ($msg) die($msg);
798 if (!$INTEGRATED_AR) {
799 $msg = invoice_post($invoice_info);
800 if ($msg) die($msg);
803 // If applicable, set the invoice reference number.
804 $invoice_refno = '';
805 if (isset($_POST['form_irnumber'])) {
806 $invoice_refno = formData('form_irnumber', 'P', true);
808 else {
809 $invoice_refno = add_escape_custom(updateInvoiceRefNumber());
811 if ($invoice_refno) {
812 sqlStatement("UPDATE form_encounter " .
813 "SET invoice_refno = '$invoice_refno' " .
814 "WHERE pid = '$form_pid' AND encounter = '$form_encounter'");
817 generate_receipt($form_pid, $form_encounter);
818 exit();
821 // If an encounter ID was given, then we must generate a receipt.
823 if (!empty($_GET['enc'])) {
824 generate_receipt($patient_id, $_GET['enc']);
825 exit();
828 // Get the unbilled billing table items and product sales for
829 // this patient.
831 $query = "SELECT id, date, code_type, code, modifier, code_text, " .
832 "provider_id, payer_id, units, fee, encounter " .
833 "FROM billing WHERE pid = '$patient_id' AND activity = 1 AND " .
834 "billed = 0 AND code_type != 'TAX' " .
835 "ORDER BY encounter DESC, id ASC";
836 $bres = sqlStatement($query);
838 $query = "SELECT s.sale_id, s.sale_date, s.prescription_id, s.fee, " .
839 "s.quantity, s.encounter, s.drug_id, d.name, r.provider_id " .
840 "FROM drug_sales AS s " .
841 "LEFT JOIN drugs AS d ON d.drug_id = s.drug_id " .
842 "LEFT OUTER JOIN prescriptions AS r ON r.id = s.prescription_id " .
843 "WHERE s.pid = '$patient_id' AND s.billed = 0 " .
844 "ORDER BY s.encounter DESC, s.sale_id ASC";
845 $dres = sqlStatement($query);
847 // If there are none, just redisplay the last receipt and exit.
849 if (mysql_num_rows($bres) == 0 && mysql_num_rows($dres) == 0) {
850 generate_receipt($patient_id);
851 exit();
854 // Get the valid practitioners, including those not active.
855 $arr_users = array();
856 $ures = sqlStatement("SELECT id, username FROM users WHERE " .
857 "( authorized = 1 OR info LIKE '%provider%' ) AND username != ''");
858 while ($urow = sqlFetchArray($ures)) {
859 $arr_users[$urow['id']] = '1';
862 // Now write a data entry form:
863 // List unbilled billing items (cpt, hcpcs, copays) for the patient.
864 // List unbilled product sales for the patient.
865 // Present an editable dollar amount for each line item, a total
866 // which is also the default value of the input payment amount,
867 // and OK and Cancel buttons.
869 <html>
870 <head>
871 <link rel='stylesheet' href='<?php echo $css_header ?>' type='text/css'>
872 <title><?php xl('Patient Checkout','e'); ?></title>
873 <style>
874 </style>
875 <style type="text/css">@import url(../../library/dynarch_calendar.css);</style>
876 <script type="text/javascript" src="../../library/textformat.js"></script>
877 <script type="text/javascript" src="../../library/dynarch_calendar.js"></script>
878 <?php include_once("{$GLOBALS['srcdir']}/dynarch_calendar_en.inc.php"); ?>
879 <script type="text/javascript" src="../../library/dynarch_calendar_setup.js"></script>
880 <script type="text/javascript" src="../../library/dialog.js"></script>
881 <script type="text/javascript" src="../../library/js/jquery-1.2.2.min.js"></script>
882 <script language="JavaScript">
883 var mypcc = '<?php echo $GLOBALS['phone_country_code'] ?>';
885 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
887 // This clears the tax line items in preparation for recomputing taxes.
888 function clearTax(visible) {
889 var f = document.forms[0];
890 for (var lino = 0; true; ++lino) {
891 var pfx = 'line[' + lino + ']';
892 if (! f[pfx + '[code_type]']) break;
893 if (f[pfx + '[code_type]'].value != 'TAX') continue;
894 f[pfx + '[price]'].value = '0.00';
895 if (visible) f[pfx + '[amount]'].value = '0.00';
899 // For a given tax ID and amount, compute the tax on that amount and add it
900 // to the "price" (same as "amount") of the corresponding tax line item.
901 // Note the tax line items include their "taxrate" to make this easy.
902 function addTax(rateid, amount, visible) {
903 if (rateid.length == 0) return 0;
904 var f = document.forms[0];
905 for (var lino = 0; true; ++lino) {
906 var pfx = 'line[' + lino + ']';
907 if (! f[pfx + '[code_type]']) break;
908 if (f[pfx + '[code_type]'].value != 'TAX') continue;
909 if (f[pfx + '[code]'].value != rateid) continue;
910 var tax = amount * parseFloat(f[pfx + '[taxrates]'].value);
911 tax = parseFloat(tax.toFixed(<?php echo $currdecimals ?>));
912 var cumtax = parseFloat(f[pfx + '[price]'].value) + tax;
913 f[pfx + '[price]'].value = cumtax.toFixed(<?php echo $currdecimals ?>); // requires JS 1.5
914 if (visible) f[pfx + '[amount]'].value = cumtax.toFixed(<?php echo $currdecimals ?>); // requires JS 1.5
915 if (isNaN(tax)) alert('Tax rate not numeric at line ' + lino);
916 return tax;
918 return 0;
921 // This mess recomputes the invoice total and optionally applies a discount.
922 function computeDiscountedTotals(discount, visible) {
923 clearTax(visible);
924 var f = document.forms[0];
925 var total = 0.00;
926 for (var lino = 0; f['line[' + lino + '][code_type]']; ++lino) {
927 var code_type = f['line[' + lino + '][code_type]'].value;
928 // price is price per unit when the form was originally generated.
929 // By contrast, amount is the dynamically-generated discounted line total.
930 var price = parseFloat(f['line[' + lino + '][price]'].value);
931 if (isNaN(price)) alert('Price not numeric at line ' + lino);
932 if (code_type == 'COPAY' || code_type == 'TAX') {
933 // This works because the tax lines come last.
934 total += parseFloat(price.toFixed(<?php echo $currdecimals ?>));
935 continue;
937 var units = f['line[' + lino + '][units]'].value;
938 var amount = price * units;
939 amount = parseFloat(amount.toFixed(<?php echo $currdecimals ?>));
940 if (visible) f['line[' + lino + '][amount]'].value = amount.toFixed(<?php echo $currdecimals ?>);
941 total += amount;
942 var taxrates = f['line[' + lino + '][taxrates]'].value;
943 var taxids = taxrates.split(':');
944 for (var j = 0; j < taxids.length; ++j) {
945 addTax(taxids[j], amount, visible);
948 return total - discount;
951 // Recompute displayed amounts with any discount applied.
952 function computeTotals() {
953 var f = document.forms[0];
954 var discount = parseFloat(f.form_discount.value);
955 if (isNaN(discount)) discount = 0;
956 <?php if (!$GLOBALS['discount_by_money']) { ?>
957 // This site discounts by percentage, so convert it to a money amount.
958 if (discount > 100) discount = 100;
959 if (discount < 0 ) discount = 0;
960 discount = 0.01 * discount * computeDiscountedTotals(0, false);
961 <?php } ?>
962 var total = computeDiscountedTotals(discount, true);
963 f.form_amount.value = total.toFixed(<?php echo $currdecimals ?>);
964 return true;
967 </script>
968 </head>
970 <body class="body_top">
972 <form method='post' action='pos_checkout.php'>
973 <input type='hidden' name='form_pid' value='<?php echo $patient_id ?>' />
975 <center>
978 <table cellspacing='5'>
979 <tr>
980 <td colspan='3' align='center'>
981 <b><?php xl('Patient Checkout for ','e'); ?><?php echo $patdata['fname'] . " " .
982 $patdata['lname'] . " (" . $patdata['pubpid'] . ")" ?></b>
983 </td>
984 </tr>
985 <tr>
986 <td><b><?php xl('Date','e'); ?></b></td>
987 <td><b><?php xl('Description','e'); ?></b></td>
988 <td align='right'><b><?php xl('Qty','e'); ?></b></td>
989 <td align='right'><b><?php xl('Amount','e'); ?></b></td>
990 </tr>
991 <?php
992 $inv_encounter = '';
993 $inv_date = '';
994 $inv_provider = 0;
995 $inv_payer = 0;
996 $gcac_related_visit = false;
997 $gcac_service_provided = false;
999 // Process billing table items. Note this includes co-pays.
1000 // Items that are not allowed to have a fee are skipped.
1002 while ($brow = sqlFetchArray($bres)) {
1003 // Skip all but the most recent encounter.
1004 if ($inv_encounter && $brow['encounter'] != $inv_encounter) continue;
1006 $thisdate = substr($brow['date'], 0, 10);
1007 $code_type = $brow['code_type'];
1009 // Collect tax rates, related code and provider ID.
1010 $taxrates = '';
1011 $related_code = '';
1012 if (!empty($code_types[$code_type]['fee'])) {
1013 $query = "SELECT taxrates, related_code FROM codes WHERE code_type = '" .
1014 $code_types[$code_type]['id'] . "' AND " .
1015 "code = '" . $brow['code'] . "' AND ";
1016 if ($brow['modifier']) {
1017 $query .= "modifier = '" . $brow['modifier'] . "'";
1018 } else {
1019 $query .= "(modifier IS NULL OR modifier = '')";
1021 $query .= " LIMIT 1";
1022 $tmp = sqlQuery($query);
1023 $taxrates = $tmp['taxrates'];
1024 $related_code = $tmp['related_code'];
1025 markTaxes($taxrates);
1028 write_form_line($code_type, $brow['code'], $brow['id'], $thisdate,
1029 ucfirst(strtolower($brow['code_text'])), $brow['fee'], $brow['units'],
1030 $taxrates);
1031 if (!$inv_encounter) $inv_encounter = $brow['encounter'];
1032 $inv_payer = $brow['payer_id'];
1033 if (!$inv_date || $inv_date < $thisdate) $inv_date = $thisdate;
1035 // Custom logic for IPPF to determine if a GCAC issue applies.
1036 if ($GLOBALS['ippf_specific'] && $related_code) {
1037 $relcodes = explode(';', $related_code);
1038 foreach ($relcodes as $codestring) {
1039 if ($codestring === '') continue;
1040 list($codetype, $code) = explode(':', $codestring);
1041 if ($codetype !== 'IPPF') continue;
1042 if (preg_match('/^25222/', $code)) {
1043 $gcac_related_visit = true;
1044 if (preg_match('/^25222[34]/', $code))
1045 $gcac_service_provided = true;
1051 // Process drug sales / products.
1053 while ($drow = sqlFetchArray($dres)) {
1054 if ($inv_encounter && $drow['encounter'] && $drow['encounter'] != $inv_encounter) continue;
1056 $thisdate = $drow['sale_date'];
1057 if (!$inv_encounter) $inv_encounter = $drow['encounter'];
1059 if (!$inv_provider && !empty($arr_users[$drow['provider_id']]))
1060 $inv_provider = $drow['provider_id'] + 0;
1062 if (!$inv_date || $inv_date < $thisdate) $inv_date = $thisdate;
1064 // Accumulate taxes for this product.
1065 $tmp = sqlQuery("SELECT taxrates FROM drug_templates WHERE drug_id = '" .
1066 $drow['drug_id'] . "' ORDER BY selector LIMIT 1");
1067 // accumTaxes($drow['fee'], $tmp['taxrates']);
1068 $taxrates = $tmp['taxrates'];
1069 markTaxes($taxrates);
1071 write_form_line('PROD', $drow['drug_id'], $drow['sale_id'],
1072 $thisdate, $drow['name'], $drow['fee'], $drow['quantity'], $taxrates);
1075 // Write a form line for each tax that has money, adding to $total.
1076 foreach ($taxes as $key => $value) {
1077 if ($value[2]) {
1078 write_form_line('TAX', $key, $key, date('Y-m-d'), $value[0], 0, 1, $value[1]);
1082 // Note that we don't try to get anything from the ar_activity table. Since
1083 // this is the checkout, nothing should be there yet for this invoice.
1085 if ($inv_encounter) {
1086 $erow = sqlQuery("SELECT provider_id FROM form_encounter WHERE " .
1087 "pid = '$patient_id' AND encounter = '$inv_encounter' " .
1088 "ORDER BY id DESC LIMIT 1");
1089 $inv_provider = $erow['provider_id'] + 0;
1092 </table>
1095 <table border='0' cellspacing='4'>
1097 <tr>
1098 <td>
1099 <?php echo $GLOBALS['discount_by_money'] ? xl('Discount Amount') : xl('Discount Percentage'); ?>:
1100 </td>
1101 <td>
1102 <input type='text' name='form_discount' size='6' maxlength='8' value=''
1103 style='text-align:right' onkeyup='computeTotals()'>
1104 </td>
1105 </tr>
1107 <tr>
1108 <td>
1109 <?php xl('Payment Method','e'); ?>:
1110 </td>
1111 <td>
1112 <select name='form_method'>
1113 <?php
1115 foreach ($payment_methods as $value) {
1116 echo " <option value='$value'";
1117 echo ">$value</option>\n";
1120 </select>
1121 </td>
1122 </tr>
1124 <tr>
1125 <td>
1126 <?php xl('Check/Reference Number','e'); ?>:
1127 </td>
1128 <td>
1129 <input type='text' name='form_source' size='10' value=''>
1130 </td>
1131 </tr>
1133 <tr>
1134 <td>
1135 <?php xl('Amount Paid','e'); ?>:
1136 </td>
1137 <td>
1138 <input type='text' name='form_amount' size='10' value='0.00'>
1139 </td>
1140 </tr>
1142 <tr>
1143 <td>
1144 <?php xl('Posting Date','e'); ?>:
1145 </td>
1146 <td>
1147 <input type='text' size='10' name='form_date' id='form_date'
1148 value='<?php echo $inv_date ?>'
1149 title='yyyy-mm-dd date of service'
1150 onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)' />
1151 <img src='../pic/show_calendar.gif' align='absbottom' width='24' height='22'
1152 id='img_date' border='0' alt='[?]' style='cursor:pointer'
1153 title='Click here to choose a date'>
1154 </td>
1155 </tr>
1157 <?php
1158 // If this user has a non-empty irnpool assigned, show the pending
1159 // invoice reference number.
1160 $irnumber = getInvoiceRefNumber();
1161 if (!empty($irnumber)) {
1163 <tr>
1164 <td>
1165 <?php xl('Tentative Invoice Ref No','e'); ?>:
1166 </td>
1167 <td>
1168 <?php echo $irnumber; ?>
1169 </td>
1170 </tr>
1171 <?php
1173 // Otherwise if there is an invoice reference number mask, ask for the refno.
1174 else if (!empty($GLOBALS['gbl_mask_invoice_number'])) {
1176 <tr>
1177 <td>
1178 <?php xl('Invoice Reference Number','e'); ?>:
1179 </td>
1180 <td>
1181 <input type='text' name='form_irnumber' size='10' value=''
1182 onkeyup='maskkeyup(this,"<?php echo addslashes($GLOBALS['gbl_mask_invoice_number']); ?>")'
1183 onblur='maskblur(this,"<?php echo addslashes($GLOBALS['gbl_mask_invoice_number']); ?>")'
1185 </td>
1186 </tr>
1187 <?php
1191 <tr>
1192 <td colspan='2' align='center'>
1193 &nbsp;<br>
1194 <input type='submit' name='form_save' value='<?php xl('Save','e'); ?>' /> &nbsp;
1195 <?php if (empty($_GET['framed'])) { ?>
1196 <input type='button' value='Cancel' onclick='window.close()' />
1197 <?php } ?>
1198 <input type='hidden' name='form_provider' value='<?php echo $inv_provider ?>' />
1199 <input type='hidden' name='form_payer' value='<?php echo $inv_payer ?>' />
1200 <input type='hidden' name='form_encounter' value='<?php echo $inv_encounter ?>' />
1201 </td>
1202 </tr>
1204 </table>
1205 </center>
1207 </form>
1209 <script language='JavaScript'>
1210 Calendar.setup({inputField:"form_date", ifFormat:"%Y-%m-%d", button:"img_date"});
1211 computeTotals();
1212 <?php
1213 // The following is removed, perhaps temporarily, because gcac reporting
1214 // no longer depends on gcac issues. -- Rod 2009-08-11
1215 /*********************************************************************
1216 // Custom code for IPPF. Try to make sure that a GCAC issue is linked to this
1217 // visit if it contains GCAC-related services.
1218 if ($gcac_related_visit) {
1219 $grow = sqlQuery("SELECT l.id, l.title, l.begdate, ie.pid " .
1220 "FROM lists AS l " .
1221 "LEFT JOIN issue_encounter AS ie ON ie.pid = l.pid AND " .
1222 "ie.encounter = '$inv_encounter' AND ie.list_id = l.id " .
1223 "WHERE l.pid = '$pid' AND " .
1224 "l.activity = 1 AND l.type = 'ippf_gcac' " .
1225 "ORDER BY ie.pid DESC, l.begdate DESC LIMIT 1");
1226 // Note that reverse-ordering by ie.pid is a trick for sorting
1227 // issues linked to the encounter (non-null values) first.
1228 if (empty($grow['pid'])) { // if there is no linked GCAC issue
1229 if (!empty($grow)) { // there is one that is not linked
1230 echo " if (confirm('" . xl('OK to link the GCAC issue dated') . " " .
1231 $grow['begdate'] . " " . xl('to this visit?') . "')) {\n";
1232 echo " $.getScript('link_issue_to_encounter.php?issue=" . $grow['id'] .
1233 "&thisenc=$inv_encounter');\n";
1234 echo " } else";
1236 echo " if (confirm('" . xl('Are you prepared to complete a new GCAC issue for this visit?') . "')) {\n";
1237 echo " dlgopen('summary/add_edit_issue.php?thisenc=$inv_encounter" .
1238 "&thistype=ippf_gcac', '_blank', 700, 600);\n";
1239 echo " } else {\n";
1240 echo " $.getScript('link_issue_to_encounter.php?thisenc=$inv_encounter');\n";
1241 echo " }\n";
1243 } // end if ($gcac_related_visit)
1244 *********************************************************************/
1246 if ($gcac_related_visit && !$gcac_service_provided) {
1247 // Skip this warning if the GCAC visit form is not allowed.
1248 $grow = sqlQuery("SELECT COUNT(*) AS count FROM list_options " .
1249 "WHERE list_id = 'lbfnames' AND option_id = 'LBFgcac'");
1250 if (!empty($grow['count'])) { // if gcac is used
1251 // Skip this warning if referral or abortion in TS.
1252 $grow = sqlQuery("SELECT COUNT(*) AS count FROM transactions " .
1253 "WHERE title = 'Referral' AND refer_date IS NOT NULL AND " .
1254 "refer_date = '$inv_date' AND pid = '$patient_id'");
1255 if (empty($grow['count'])) { // if there is no referral
1256 $grow = sqlQuery("SELECT COUNT(*) AS count FROM forms " .
1257 "WHERE pid = '$patient_id' AND encounter = '$inv_encounter' AND " .
1258 "deleted = 0 AND formdir = 'LBFgcac'");
1259 if (empty($grow['count'])) { // if there is no gcac form
1260 echo " alert('" . xl('This visit will need a GCAC form, referral or procedure service.') . "');\n";
1264 } // end if ($gcac_related_visit)
1266 </script>
1268 </body>
1269 </html>