Fix for possible reporting of deductible or coinsurance when it is zero.
[openemr.git] / interface / patient_file / pos_checkout.php
blob6d74365e6a12d638b8ded96e45f7bf4d18612597
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');
282 // Get the most recent invoice data or that for the specified encounter.
284 if ($INTEGRATED_AR) {
285 if ($encounter) {
286 $ferow = sqlQuery("SELECT id, date, encounter FROM form_encounter " .
287 "WHERE pid = '$patient_id' AND encounter = '$encounter'");
288 } else {
289 $ferow = sqlQuery("SELECT id, date, encounter FROM form_encounter " .
290 "WHERE pid = '$patient_id' " .
291 "ORDER BY id DESC LIMIT 1");
293 if (empty($ferow)) die(xl("This patient has no activity."));
294 $trans_id = $ferow['id'];
295 $encounter = $ferow['encounter'];
296 $svcdate = substr($ferow['date'], 0, 10);
298 else {
299 SLConnect();
301 $arres = SLQuery("SELECT * FROM ar WHERE " .
302 "invnumber LIKE '$patient_id.%' " .
303 "ORDER BY id DESC LIMIT 1");
304 if ($sl_err) die($sl_err);
305 if (!SLRowCount($arres)) die(xl("This patient has no activity."));
306 $arrow = SLGetRow($arres, 0);
308 $trans_id = $arrow['id'];
310 // Determine the date of service. An 8-digit encounter number is
311 // presumed to be a date of service imported during conversion or
312 // associated with prescriptions only. Otherwise look it up in the
313 // form_encounter table.
315 $svcdate = "";
316 list($trash, $encounter) = explode(".", $arrow['invnumber']);
317 if (strlen($encounter) >= 8) {
318 $svcdate = substr($encounter, 0, 4) . "-" . substr($encounter, 4, 2) .
319 "-" . substr($encounter, 6, 2);
321 else if ($encounter) {
322 $tmp = sqlQuery("SELECT date FROM form_encounter WHERE " .
323 "encounter = $encounter");
324 $svcdate = substr($tmp['date'], 0, 10);
326 } // end not $INTEGRATED_AR
328 // Get invoice reference number.
329 $encrow = sqlQuery("SELECT invoice_refno FROM form_encounter WHERE " .
330 "pid = '$patient_id' AND encounter = '$encounter' LIMIT 1");
331 $invoice_refno = $encrow['invoice_refno'];
333 <html>
334 <head>
335 <?php html_header_show(); ?>
336 <link rel='stylesheet' href='<?php echo $css_header ?>' type='text/css'>
337 <title><?php xl('Receipt for Payment','e'); ?></title>
338 <script type="text/javascript" src="../../library/dialog.js"></script>
339 <script language="JavaScript">
341 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
343 // Process click on Print button.
344 function printme() {
345 var divstyle = document.getElementById('hideonprint').style;
346 divstyle.display = 'none';
347 window.print();
348 return false;
351 // Process click on Delete button.
352 function deleteme() {
353 dlgopen('deleter.php?billing=<?php echo "$patient_id.$encounter"; ?>', '_blank', 500, 450);
354 return false;
357 // Called by the deleteme.php window on a successful delete.
358 function imdeleted() {
359 window.close();
362 </script>
363 </head>
364 <body class="body_top">
365 <center>
366 <p><b><?php echo $frow['name'] ?>
367 <br><?php echo $frow['street'] ?>
368 <br><?php echo $frow['city'] . ', ' . $frow['state'] . ' ' . $frow['postal_code'] ?>
369 <br><?php echo $frow['phone'] ?>
370 <br>&nbsp;
371 <br>
372 <?php
373 echo xl("Receipt Generated") . date(' F j, Y');
374 if ($invoice_refno) echo " " . xl("for Invoice") . " $invoice_refno";
376 <br>&nbsp;
377 </b></p>
378 </center>
380 <?php echo $patdata['fname'] . ' ' . $patdata['mname'] . ' ' . $patdata['lname'] ?>
381 <br><?php echo $patdata['street'] ?>
382 <br><?php echo $patdata['city'] . ', ' . $patdata['state'] . ' ' . $patdata['postal_code'] ?>
383 <br>&nbsp;
384 </p>
385 <center>
386 <table cellpadding='5'>
387 <tr>
388 <td><b><?php xl('Date','e'); ?></b></td>
389 <td><b><?php xl('Description','e'); ?></b></td>
390 <td align='right'><b><?php echo $details ? xl('Price') : '&nbsp;'; ?></b></td>
391 <td align='right'><b><?php echo $details ? xl('Qty' ) : '&nbsp;'; ?></b></td>
392 <td align='right'><b><?php xl('Total','e'); ?></b></td>
393 </tr>
395 <?php
396 $charges = 0.00;
398 if ($INTEGRATED_AR) {
399 // Product sales
400 $inres = sqlStatement("SELECT s.sale_id, s.sale_date, s.fee, " .
401 "s.quantity, s.drug_id, d.name " .
402 "FROM drug_sales AS s LEFT JOIN drugs AS d ON d.drug_id = s.drug_id " .
403 // "WHERE s.pid = '$patient_id' AND s.encounter = '$encounter' AND s.fee != 0 " .
404 "WHERE s.pid = '$patient_id' AND s.encounter = '$encounter' " .
405 "ORDER BY s.sale_id");
406 while ($inrow = sqlFetchArray($inres)) {
407 $charges += sprintf('%01.2f', $inrow['fee']);
408 receiptDetailLine($inrow['sale_date'], $inrow['name'],
409 $inrow['fee'], $inrow['quantity']);
411 // Service and tax items
412 $inres = sqlStatement("SELECT * FROM billing WHERE " .
413 "pid = '$patient_id' AND encounter = '$encounter' AND " .
414 // "code_type != 'COPAY' AND activity = 1 AND fee != 0 " .
415 "code_type != 'COPAY' AND activity = 1 " .
416 "ORDER BY id");
417 while ($inrow = sqlFetchArray($inres)) {
418 $charges += sprintf('%01.2f', $inrow['fee']);
419 receiptDetailLine($svcdate, $inrow['code_text'],
420 $inrow['fee'], $inrow['units']);
422 // Adjustments.
423 $inres = sqlStatement("SELECT " .
424 "a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, " .
425 "s.payer_id, s.reference, s.check_date, s.deposit_date " .
426 "FROM ar_activity AS a " .
427 "LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " .
428 "a.pid = '$patient_id' AND a.encounter = '$encounter' AND " .
429 "a.adj_amount != 0 " .
430 "ORDER BY s.check_date, a.sequence_no");
431 while ($inrow = sqlFetchArray($inres)) {
432 $charges -= sprintf('%01.2f', $inrow['adj_amount']);
433 $payer = empty($inrow['payer_type']) ? 'Pt' : ('Ins' . $inrow['payer_type']);
434 receiptDetailLine($svcdate, $payer . ' ' . $inrow['memo'],
435 0 - $inrow['adj_amount'], 1);
437 } // end $INTEGRATED_AR
438 else {
439 // Request all line items with money belonging to the invoice.
440 $inres = SLQuery("SELECT * FROM invoice WHERE " .
441 "trans_id = $trans_id AND sellprice != 0 ORDER BY id");
442 if ($sl_err) die($sl_err);
443 for ($irow = 0; $irow < SLRowCount($inres); ++$irow) {
444 $row = SLGetRow($inres, $irow);
445 $amount = sprintf('%01.2f', $row['sellprice'] * $row['qty']);
446 $charges += $amount;
447 $desc = preg_replace('/^.{1,6}:/', '', $row['description']);
448 receiptDetailLine($svcdate, $desc, $amount, $row['qty']);
450 } // end not $INTEGRATED_AR
453 <tr>
454 <td colspan='5'>&nbsp;</td>
455 </tr>
456 <tr>
457 <td><?php echo oeFormatShortDate($svcdispdate); ?></td>
458 <td><b><?php xl('Total Charges','e'); ?></b></td>
459 <td align='right'>&nbsp;</td>
460 <td align='right'>&nbsp;</td>
461 <td align='right'><?php echo oeFormatMoney($charges, true) ?></td>
462 </tr>
463 <tr>
464 <td colspan='5'>&nbsp;</td>
465 </tr>
467 <?php
468 if ($INTEGRATED_AR) {
469 // Get co-pays.
470 $inres = sqlStatement("SELECT fee, code_text FROM billing WHERE " .
471 "pid = '$patient_id' AND encounter = '$encounter' AND " .
472 "code_type = 'COPAY' AND activity = 1 AND fee != 0 " .
473 "ORDER BY id");
474 while ($inrow = sqlFetchArray($inres)) {
475 $charges += sprintf('%01.2f', $inrow['fee']);
476 receiptPaymentLine($svcdate, 0 - $inrow['fee'], $inrow['code_text']);
478 // Get other payments.
479 $inres = sqlStatement("SELECT " .
480 "a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, " .
481 "s.payer_id, s.reference, s.check_date, s.deposit_date " .
482 "FROM ar_activity AS a " .
483 "LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " .
484 "a.pid = '$patient_id' AND a.encounter = '$encounter' AND " .
485 "a.pay_amount != 0 " .
486 "ORDER BY s.check_date, a.sequence_no");
487 $payer = empty($inrow['payer_type']) ? 'Pt' : ('Ins' . $inrow['payer_type']);
488 while ($inrow = sqlFetchArray($inres)) {
489 $charges -= sprintf('%01.2f', $inrow['pay_amount']);
490 receiptPaymentLine($svcdate, $inrow['pay_amount'],
491 $payer . ' ' . $inrow['reference']);
493 } // end $INTEGRATED_AR
494 else {
495 $chart_id_cash = SLQueryValue("select id from chart where accno = '$sl_cash_acc'");
496 if ($sl_err) die($sl_err);
497 if (! $chart_id_cash) die("There is no COA entry for cash account '$sl_cash_acc'");
499 // Request all cash entries belonging to the invoice.
500 $atres = SLQuery("SELECT * FROM acc_trans WHERE " .
501 "trans_id = $trans_id AND chart_id = $chart_id_cash ORDER BY transdate");
502 if ($sl_err) die($sl_err);
504 for ($irow = 0; $irow < SLRowCount($atres); ++$irow) {
505 $row = SLGetRow($atres, $irow);
506 $amount = sprintf('%01.2f', $row['amount']); // negative
507 $charges += $amount;
508 $rowsource = $row['source'];
509 if (strtolower($rowsource) == 'co-pay') $rowsource = '';
510 receiptPaymentLine($row['transdate'], 0 - $amount, $rowsource);
512 } // end not $INTEGRATED_AR
514 <tr>
515 <td colspan='5'>&nbsp;</td>
516 </tr>
517 <tr>
518 <td>&nbsp;</td>
519 <td><b><?php xl('Balance Due','e'); ?></b></td>
520 <td colspan='2'>&nbsp;</td>
521 <td align='right'><?php echo oeFormatMoney($charges, true) ?></td>
522 </tr>
523 </table>
524 </center>
525 <div id='hideonprint'>
527 &nbsp;
528 <a href='#' onclick='return printme();'><?php xl('Print','e'); ?></a>
529 <?php if (acl_check('acct','disc')) { ?>
530 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
531 <a href='#' onclick='return deleteme();'><?php xl('Undo Checkout','e'); ?></a>
532 <?php } ?>
533 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
534 <?php if ($details) { ?>
535 <a href='pos_checkout.php?details=0&ptid=<?php echo $patient_id; ?>&enc=<?php echo $encounter; ?>'><?php xl('Hide Details','e'); ?></a>
536 <?php } else { ?>
537 <a href='pos_checkout.php?details=1&ptid=<?php echo $patient_id; ?>&enc=<?php echo $encounter; ?>'><?php xl('Show Details','e'); ?></a>
538 <?php } ?>
539 </p>
540 </div>
541 </body>
542 </html>
543 <?php
544 if (!$INTEGRATED_AR) SLClose();
545 } // end function generate_receipt()
547 // Function to output a line item for the input form.
549 $lino = 0;
550 function write_form_line($code_type, $code, $id, $date, $description,
551 $amount, $units, $taxrates) {
552 global $lino;
553 $amount = sprintf("%01.2f", $amount);
554 if (empty($units)) $units = 1;
555 $price = $amount / $units; // should be even cents, but ok here if not
556 if ($code_type == 'COPAY' && !$description) $description = xl('Payment');
557 echo " <tr>\n";
558 echo " <td>" . oeFormatShortDate($date);
559 echo "<input type='hidden' name='line[$lino][code_type]' value='$code_type'>";
560 echo "<input type='hidden' name='line[$lino][code]' value='$code'>";
561 echo "<input type='hidden' name='line[$lino][id]' value='$id'>";
562 echo "<input type='hidden' name='line[$lino][description]' value='$description'>";
563 echo "<input type='hidden' name='line[$lino][taxrates]' value='$taxrates'>";
564 echo "<input type='hidden' name='line[$lino][price]' value='$price'>";
565 echo "<input type='hidden' name='line[$lino][units]' value='$units'>";
566 echo "</td>\n";
567 echo " <td>$description</td>";
568 echo " <td align='right'>$units</td>";
569 echo " <td align='right'><input type='text' name='line[$lino][amount]' " .
570 "value='$amount' size='6' maxlength='8'";
571 // Modifying prices requires the acct/disc permission.
572 // if ($code_type == 'TAX' || ($code_type != 'COPAY' && !acl_check('acct','disc')))
573 echo " style='text-align:right;background-color:transparent' readonly";
574 // else echo " style='text-align:right' onkeyup='computeTotals()'";
575 echo "></td>\n";
576 echo " </tr>\n";
577 ++$lino;
580 // Create the taxes array. Key is tax id, value is
581 // (description, rate, accumulated total).
582 $taxes = array();
583 $pres = sqlStatement("SELECT option_id, title, option_value " .
584 "FROM list_options WHERE list_id = 'taxrate' ORDER BY seq");
585 while ($prow = sqlFetchArray($pres)) {
586 $taxes[$prow['option_id']] = array($prow['title'], $prow['option_value'], 0);
589 // Mark the tax rates that are referenced in this invoice.
590 function markTaxes($taxrates) {
591 global $taxes;
592 $arates = explode(':', $taxrates);
593 if (empty($arates)) return;
594 foreach ($arates as $value) {
595 if (!empty($taxes[$value])) $taxes[$value][2] = '1';
599 $payment_methods = array(
600 'Cash',
601 'Check',
602 'MC',
603 'VISA',
604 'AMEX',
605 'DISC',
606 'Other');
608 $alertmsg = ''; // anything here pops up in an alert box
610 // If the Save button was clicked...
612 if ($_POST['form_save']) {
614 // On a save, do the following:
615 // Flag drug_sales and billing items as billed.
616 // Post the corresponding invoice with its payment(s) to sql-ledger
617 // and be careful to use a unique invoice number.
618 // Call the generate-receipt function.
619 // Exit.
621 $form_pid = $_POST['form_pid'];
622 $form_encounter = $_POST['form_encounter'];
624 // Get the posting date from the form as yyyy-mm-dd.
625 $dosdate = date("Y-m-d");
626 if (preg_match("/(\d\d\d\d)\D*(\d\d)\D*(\d\d)/", $_POST['form_date'], $matches)) {
627 $dosdate = $matches[1] . '-' . $matches[2] . '-' . $matches[3];
630 // If there is no associated encounter (i.e. this invoice has only
631 // prescriptions) then assign an encounter number of the service
632 // date, with an optional suffix to ensure that it's unique.
634 if (! $form_encounter) {
635 $form_encounter = substr($dosdate,0,4) . substr($dosdate,5,2) . substr($dosdate,8,2);
636 $tmp = '';
637 if ($INTEGRATED_AR) {
638 while (true) {
639 $ferow = sqlQuery("SELECT id FROM form_encounter WHERE " .
640 "pid = '$form_pid' AND encounter = '$form_encounter$tmp'");
641 if (empty($ferow)) break;
642 $tmp = $tmp ? $tmp + 1 : 1;
645 else {
646 SLConnect();
647 while (SLQueryValue("select id from ar where " .
648 "invnumber = '$form_pid.$form_encounter$tmp'")) {
649 $tmp = $tmp ? $tmp + 1 : 1;
651 SLClose();
653 $form_encounter .= $tmp;
656 if ($INTEGRATED_AR) {
657 // Delete any TAX rows from billing because they will be recalculated.
658 sqlStatement("UPDATE billing SET activity = 0 WHERE " .
659 "pid = '$form_pid' AND encounter = '$form_encounter' AND " .
660 "code_type = 'TAX'");
662 else {
663 // Initialize an array of invoice information for posting.
664 $invoice_info = array();
665 $msg = invoice_initialize($invoice_info, $form_pid,
666 $_POST['form_provider'], $_POST['form_payer'], $form_encounter, $dosdate);
667 if ($msg) die($msg);
670 $form_amount = $_POST['form_amount'];
671 $lines = $_POST['line'];
673 for ($lino = 0; $lines[$lino]['code_type']; ++$lino) {
674 $line = $lines[$lino];
675 $code_type = $line['code_type'];
676 $id = $line['id'];
677 $amount = sprintf('%01.2f', trim($line['amount']));
679 if (!$INTEGRATED_AR) {
680 $msg = invoice_add_line_item($invoice_info, $code_type,
681 $line['code'], $line['description'], $amount, $line['units']);
682 if ($msg) die($msg);
685 if ($code_type == 'PROD') {
686 // Product sales. The fee and encounter ID may have changed.
687 $query = "update drug_sales SET fee = '$amount', " .
688 "encounter = '$form_encounter', billed = 1 WHERE " .
689 "sale_id = '$id'";
690 sqlQuery($query);
692 else if ($code_type == 'TAX') {
693 // In the SL case taxes show up on the invoice as line items.
694 // Otherwise we gotta save them somewhere, and in the billing
695 // table with a code type of TAX seems easiest.
696 // They will have to be stripped back out when building this
697 // script's input form.
698 addBilling($form_encounter, 'TAX', 'TAX', 'Taxes', $form_pid, 0, 0,
699 '', '', $amount, '', '', 1);
701 else {
702 // Because there is no insurance here, there is no need for a claims
703 // table entry and so we do not call updateClaim(). Note we should not
704 // eliminate billed and bill_date from the billing table!
705 $query = "UPDATE billing SET fee = '$amount', billed = 1, " .
706 "bill_date = NOW() WHERE id = '$id'";
707 sqlQuery($query);
711 // Post discount.
712 if ($_POST['form_discount']) {
713 if ($GLOBALS['discount_by_money']) {
714 $amount = sprintf('%01.2f', trim($_POST['form_discount']));
716 else {
717 $amount = sprintf('%01.2f', trim($_POST['form_discount']) * $form_amount / 100);
719 $memo = xl('Discount');
720 if ($INTEGRATED_AR) {
721 $time = date('Y-m-d H:i:s');
722 $query = "INSERT INTO ar_activity ( " .
723 "pid, encounter, code, modifier, payer_type, post_user, post_time, " .
724 "session_id, memo, adj_amount " .
725 ") VALUES ( " .
726 "'$form_pid', " .
727 "'$form_encounter', " .
728 "'', " .
729 "'', " .
730 "'0', " .
731 "'" . $_SESSION['authUserID'] . "', " .
732 "'$time', " .
733 "'0', " .
734 "'$memo', " .
735 "'$amount' " .
736 ")";
737 sqlStatement($query);
739 else {
740 $msg = invoice_add_line_item($invoice_info, 'DISCOUNT',
741 '', $memo, 0 - $amount);
742 if ($msg) die($msg);
746 // Post payment.
747 if ($_POST['form_amount']) {
748 $amount = sprintf('%01.2f', trim($_POST['form_amount']));
749 $form_source = trim($_POST['form_source']);
750 $paydesc = trim($_POST['form_method']);
751 if ($INTEGRATED_AR) {
752 // Post the payment as a billed copay into the billing table.
753 // Maybe this should even be done for the SL case.
754 if (!empty($form_source)) $paydesc .= " $form_source";
755 addBilling($form_encounter, 'COPAY', $amount, $paydesc, $form_pid,
756 0, 0, '', '', 0 - $amount, '', '', 1);
758 else {
759 $msg = invoice_add_line_item($invoice_info, 'COPAY',
760 $paydesc, $form_source, 0 - $amount);
761 if ($msg) die($msg);
765 if (!$INTEGRATED_AR) {
766 $msg = invoice_post($invoice_info);
767 if ($msg) die($msg);
770 // If applicable, set the invoice reference number.
771 $invoice_refno = '';
772 if (isset($_POST['form_irnumber'])) {
773 $invoice_refno = formData('form_irnumber', 'P', true);
775 else {
776 $invoice_refno = add_escape_custom(updateInvoiceRefNumber());
778 if ($invoice_refno) {
779 sqlStatement("UPDATE form_encounter " .
780 "SET invoice_refno = '$invoice_refno' " .
781 "WHERE pid = '$form_pid' AND encounter = '$form_encounter'");
784 generate_receipt($form_pid, $form_encounter);
785 exit();
788 // If an encounter ID was given, then we must generate a receipt.
790 if (!empty($_GET['enc'])) {
791 generate_receipt($patient_id, $_GET['enc']);
792 exit();
795 // Get the unbilled billing table items and product sales for
796 // this patient.
798 $query = "SELECT id, date, code_type, code, modifier, code_text, " .
799 "provider_id, payer_id, units, fee, encounter " .
800 "FROM billing WHERE pid = '$patient_id' AND activity = 1 AND " .
801 "billed = 0 AND code_type != 'TAX' " .
802 "ORDER BY encounter DESC, id ASC";
803 $bres = sqlStatement($query);
805 $query = "SELECT s.sale_id, s.sale_date, s.prescription_id, s.fee, " .
806 "s.quantity, s.encounter, s.drug_id, d.name, r.provider_id " .
807 "FROM drug_sales AS s " .
808 "LEFT JOIN drugs AS d ON d.drug_id = s.drug_id " .
809 "LEFT OUTER JOIN prescriptions AS r ON r.id = s.prescription_id " .
810 "WHERE s.pid = '$patient_id' AND s.billed = 0 " .
811 "ORDER BY s.encounter DESC, s.sale_id ASC";
812 $dres = sqlStatement($query);
814 // If there are none, just redisplay the last receipt and exit.
816 if (mysql_num_rows($bres) == 0 && mysql_num_rows($dres) == 0) {
817 generate_receipt($patient_id);
818 exit();
821 // Get the valid practitioners, including those not active.
822 $arr_users = array();
823 $ures = sqlStatement("SELECT id, username FROM users WHERE " .
824 "( authorized = 1 OR info LIKE '%provider%' ) AND username != ''");
825 while ($urow = sqlFetchArray($ures)) {
826 $arr_users[$urow['id']] = '1';
829 // Now write a data entry form:
830 // List unbilled billing items (cpt, hcpcs, copays) for the patient.
831 // List unbilled product sales for the patient.
832 // Present an editable dollar amount for each line item, a total
833 // which is also the default value of the input payment amount,
834 // and OK and Cancel buttons.
836 <html>
837 <head>
838 <link rel='stylesheet' href='<?php echo $css_header ?>' type='text/css'>
839 <title><?php xl('Patient Checkout','e'); ?></title>
840 <style>
841 </style>
842 <style type="text/css">@import url(../../library/dynarch_calendar.css);</style>
843 <script type="text/javascript" src="../../library/textformat.js"></script>
844 <script type="text/javascript" src="../../library/dynarch_calendar.js"></script>
845 <?php include_once("{$GLOBALS['srcdir']}/dynarch_calendar_en.inc.php"); ?>
846 <script type="text/javascript" src="../../library/dynarch_calendar_setup.js"></script>
847 <script type="text/javascript" src="../../library/dialog.js"></script>
848 <script type="text/javascript" src="../../library/js/jquery-1.2.2.min.js"></script>
849 <script language="JavaScript">
850 var mypcc = '<?php echo $GLOBALS['phone_country_code'] ?>';
852 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
854 // This clears the tax line items in preparation for recomputing taxes.
855 function clearTax(visible) {
856 var f = document.forms[0];
857 for (var lino = 0; true; ++lino) {
858 var pfx = 'line[' + lino + ']';
859 if (! f[pfx + '[code_type]']) break;
860 if (f[pfx + '[code_type]'].value != 'TAX') continue;
861 f[pfx + '[price]'].value = '0.00';
862 if (visible) f[pfx + '[amount]'].value = '0.00';
866 // For a given tax ID and amount, compute the tax on that amount and add it
867 // to the "price" (same as "amount") of the corresponding tax line item.
868 // Note the tax line items include their "taxrate" to make this easy.
869 function addTax(rateid, amount, visible) {
870 if (rateid.length == 0) return 0;
871 var f = document.forms[0];
872 for (var lino = 0; true; ++lino) {
873 var pfx = 'line[' + lino + ']';
874 if (! f[pfx + '[code_type]']) break;
875 if (f[pfx + '[code_type]'].value != 'TAX') continue;
876 if (f[pfx + '[code]'].value != rateid) continue;
877 var tax = amount * parseFloat(f[pfx + '[taxrates]'].value);
878 tax = parseFloat(tax.toFixed(<?php echo $currdecimals ?>));
879 var cumtax = parseFloat(f[pfx + '[price]'].value) + tax;
880 f[pfx + '[price]'].value = cumtax.toFixed(<?php echo $currdecimals ?>); // requires JS 1.5
881 if (visible) f[pfx + '[amount]'].value = cumtax.toFixed(<?php echo $currdecimals ?>); // requires JS 1.5
882 if (isNaN(tax)) alert('Tax rate not numeric at line ' + lino);
883 return tax;
885 return 0;
888 // This mess recomputes the invoice total and optionally applies a discount.
889 function computeDiscountedTotals(discount, visible) {
890 clearTax(visible);
891 var f = document.forms[0];
892 var total = 0.00;
893 for (var lino = 0; f['line[' + lino + '][code_type]']; ++lino) {
894 var code_type = f['line[' + lino + '][code_type]'].value;
895 // price is price per unit when the form was originally generated.
896 // By contrast, amount is the dynamically-generated discounted line total.
897 var price = parseFloat(f['line[' + lino + '][price]'].value);
898 if (isNaN(price)) alert('Price not numeric at line ' + lino);
899 if (code_type == 'COPAY' || code_type == 'TAX') {
900 // This works because the tax lines come last.
901 total += parseFloat(price.toFixed(<?php echo $currdecimals ?>));
902 continue;
904 var units = f['line[' + lino + '][units]'].value;
905 var amount = price * units;
906 amount = parseFloat(amount.toFixed(<?php echo $currdecimals ?>));
907 if (visible) f['line[' + lino + '][amount]'].value = amount.toFixed(<?php echo $currdecimals ?>);
908 total += amount;
909 var taxrates = f['line[' + lino + '][taxrates]'].value;
910 var taxids = taxrates.split(':');
911 for (var j = 0; j < taxids.length; ++j) {
912 addTax(taxids[j], amount, visible);
915 return total - discount;
918 // Recompute displayed amounts with any discount applied.
919 function computeTotals() {
920 var f = document.forms[0];
921 var discount = parseFloat(f.form_discount.value);
922 if (isNaN(discount)) discount = 0;
923 <?php if (!$GLOBALS['discount_by_money']) { ?>
924 // This site discounts by percentage, so convert it to a money amount.
925 if (discount > 100) discount = 100;
926 if (discount < 0 ) discount = 0;
927 discount = 0.01 * discount * computeDiscountedTotals(0, false);
928 <?php } ?>
929 var total = computeDiscountedTotals(discount, true);
930 f.form_amount.value = total.toFixed(<?php echo $currdecimals ?>);
931 return true;
934 </script>
935 </head>
937 <body class="body_top">
939 <form method='post' action='pos_checkout.php'>
940 <input type='hidden' name='form_pid' value='<?php echo $patient_id ?>' />
942 <center>
945 <table cellspacing='5'>
946 <tr>
947 <td colspan='3' align='center'>
948 <b><?php xl('Patient Checkout for ','e'); ?><?php echo $patdata['fname'] . " " .
949 $patdata['lname'] . " (" . $patdata['pubpid'] . ")" ?></b>
950 </td>
951 </tr>
952 <tr>
953 <td><b><?php xl('Date','e'); ?></b></td>
954 <td><b><?php xl('Description','e'); ?></b></td>
955 <td align='right'><b><?php xl('Qty','e'); ?></b></td>
956 <td align='right'><b><?php xl('Amount','e'); ?></b></td>
957 </tr>
958 <?php
959 $inv_encounter = '';
960 $inv_date = '';
961 $inv_provider = 0;
962 $inv_payer = 0;
963 $gcac_related_visit = false;
964 $gcac_service_provided = false;
966 // Process billing table items. Note this includes co-pays.
967 // Items that are not allowed to have a fee are skipped.
969 while ($brow = sqlFetchArray($bres)) {
970 // Skip all but the most recent encounter.
971 if ($inv_encounter && $brow['encounter'] != $inv_encounter) continue;
973 $thisdate = substr($brow['date'], 0, 10);
974 $code_type = $brow['code_type'];
976 // Collect tax rates, related code and provider ID.
977 $taxrates = '';
978 $related_code = '';
979 if (!empty($code_types[$code_type]['fee'])) {
980 $query = "SELECT taxrates, related_code FROM codes WHERE code_type = '" .
981 $code_types[$code_type]['id'] . "' AND " .
982 "code = '" . $brow['code'] . "' AND ";
983 if ($brow['modifier']) {
984 $query .= "modifier = '" . $brow['modifier'] . "'";
985 } else {
986 $query .= "(modifier IS NULL OR modifier = '')";
988 $query .= " LIMIT 1";
989 $tmp = sqlQuery($query);
990 $taxrates = $tmp['taxrates'];
991 $related_code = $tmp['related_code'];
992 markTaxes($taxrates);
995 write_form_line($code_type, $brow['code'], $brow['id'], $thisdate,
996 ucfirst(strtolower($brow['code_text'])), $brow['fee'], $brow['units'],
997 $taxrates);
998 if (!$inv_encounter) $inv_encounter = $brow['encounter'];
999 $inv_payer = $brow['payer_id'];
1000 if (!$inv_date || $inv_date < $thisdate) $inv_date = $thisdate;
1002 // Custom logic for IPPF to determine if a GCAC issue applies.
1003 if ($GLOBALS['ippf_specific'] && $related_code) {
1004 $relcodes = explode(';', $related_code);
1005 foreach ($relcodes as $codestring) {
1006 if ($codestring === '') continue;
1007 list($codetype, $code) = explode(':', $codestring);
1008 if ($codetype !== 'IPPF') continue;
1009 if (preg_match('/^25222/', $code)) {
1010 $gcac_related_visit = true;
1011 if (preg_match('/^25222[34]/', $code))
1012 $gcac_service_provided = true;
1018 // Process drug sales / products.
1020 while ($drow = sqlFetchArray($dres)) {
1021 if ($inv_encounter && $drow['encounter'] && $drow['encounter'] != $inv_encounter) continue;
1023 $thisdate = $drow['sale_date'];
1024 if (!$inv_encounter) $inv_encounter = $drow['encounter'];
1026 if (!$inv_provider && !empty($arr_users[$drow['provider_id']]))
1027 $inv_provider = $drow['provider_id'] + 0;
1029 if (!$inv_date || $inv_date < $thisdate) $inv_date = $thisdate;
1031 // Accumulate taxes for this product.
1032 $tmp = sqlQuery("SELECT taxrates FROM drug_templates WHERE drug_id = '" .
1033 $drow['drug_id'] . "' ORDER BY selector LIMIT 1");
1034 // accumTaxes($drow['fee'], $tmp['taxrates']);
1035 $taxrates = $tmp['taxrates'];
1036 markTaxes($taxrates);
1038 write_form_line('PROD', $drow['drug_id'], $drow['sale_id'],
1039 $thisdate, $drow['name'], $drow['fee'], $drow['quantity'], $taxrates);
1042 // Write a form line for each tax that has money, adding to $total.
1043 foreach ($taxes as $key => $value) {
1044 if ($value[2]) {
1045 write_form_line('TAX', $key, $key, date('Y-m-d'), $value[0], 0, 1, $value[1]);
1049 // Note that we don't try to get anything from the ar_activity table. Since
1050 // this is the checkout, nothing should be there yet for this invoice.
1052 if ($inv_encounter) {
1053 $erow = sqlQuery("SELECT provider_id FROM form_encounter WHERE " .
1054 "pid = '$patient_id' AND encounter = '$inv_encounter' " .
1055 "ORDER BY id DESC LIMIT 1");
1056 $inv_provider = $erow['provider_id'] + 0;
1059 </table>
1062 <table border='0' cellspacing='4'>
1064 <tr>
1065 <td>
1066 <?php echo $GLOBALS['discount_by_money'] ? xl('Discount Amount') : xl('Discount Percentage'); ?>:
1067 </td>
1068 <td>
1069 <input type='text' name='form_discount' size='6' maxlength='8' value=''
1070 style='text-align:right' onkeyup='computeTotals()'>
1071 </td>
1072 </tr>
1074 <tr>
1075 <td>
1076 <?php xl('Payment Method','e'); ?>:
1077 </td>
1078 <td>
1079 <select name='form_method'>
1081 foreach ($payment_methods as $value) {
1082 echo " <option value='$value'";
1083 echo ">$value</option>\n";
1086 </select>
1087 </td>
1088 </tr>
1090 <tr>
1091 <td>
1092 <?php xl('Check/Reference Number','e'); ?>:
1093 </td>
1094 <td>
1095 <input type='text' name='form_source' size='10' value=''>
1096 </td>
1097 </tr>
1099 <tr>
1100 <td>
1101 <?php xl('Amount Paid','e'); ?>:
1102 </td>
1103 <td>
1104 <input type='text' name='form_amount' size='10' value='0.00'>
1105 </td>
1106 </tr>
1108 <tr>
1109 <td>
1110 <?php xl('Posting Date','e'); ?>:
1111 </td>
1112 <td>
1113 <input type='text' size='10' name='form_date' id='form_date'
1114 value='<?php echo $inv_date ?>'
1115 title='yyyy-mm-dd date of service'
1116 onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)' />
1117 <img src='../pic/show_calendar.gif' align='absbottom' width='24' height='22'
1118 id='img_date' border='0' alt='[?]' style='cursor:pointer'
1119 title='Click here to choose a date'>
1120 </td>
1121 </tr>
1123 <?php
1124 // If this user has a non-empty irnpool assigned, show the pending
1125 // invoice reference number.
1126 $irnumber = getInvoiceRefNumber();
1127 if (!empty($irnumber)) {
1129 <tr>
1130 <td>
1131 <?php xl('Tentative Invoice Ref No','e'); ?>:
1132 </td>
1133 <td>
1134 <?php echo $irnumber; ?>
1135 </td>
1136 </tr>
1137 <?php
1139 // Otherwise if there is an invoice reference number mask, ask for the refno.
1140 else if (!empty($GLOBALS['gbl_mask_invoice_number'])) {
1142 <tr>
1143 <td>
1144 <?php xl('Invoice Reference Number','e'); ?>:
1145 </td>
1146 <td>
1147 <input type='text' name='form_irnumber' size='10' value=''
1148 onkeyup='maskkeyup(this,"<?php echo addslashes($GLOBALS['gbl_mask_invoice_number']); ?>")'
1149 onblur='maskblur(this,"<?php echo addslashes($GLOBALS['gbl_mask_invoice_number']); ?>")'
1151 </td>
1152 </tr>
1153 <?php
1157 <tr>
1158 <td colspan='2' align='center'>
1159 &nbsp;<br>
1160 <input type='submit' name='form_save' value='<?php xl('Save','e'); ?>' /> &nbsp;
1161 <?php if (empty($_GET['framed'])) { ?>
1162 <input type='button' value='Cancel' onclick='window.close()' />
1163 <?php } ?>
1164 <input type='hidden' name='form_provider' value='<?php echo $inv_provider ?>' />
1165 <input type='hidden' name='form_payer' value='<?php echo $inv_payer ?>' />
1166 <input type='hidden' name='form_encounter' value='<?php echo $inv_encounter ?>' />
1167 </td>
1168 </tr>
1170 </table>
1171 </center>
1173 </form>
1175 <script language='JavaScript'>
1176 Calendar.setup({inputField:"form_date", ifFormat:"%Y-%m-%d", button:"img_date"});
1177 computeTotals();
1178 <?php
1179 // The following is removed, perhaps temporarily, because gcac reporting
1180 // no longer depends on gcac issues. -- Rod 2009-08-11
1181 /*********************************************************************
1182 // Custom code for IPPF. Try to make sure that a GCAC issue is linked to this
1183 // visit if it contains GCAC-related services.
1184 if ($gcac_related_visit) {
1185 $grow = sqlQuery("SELECT l.id, l.title, l.begdate, ie.pid " .
1186 "FROM lists AS l " .
1187 "LEFT JOIN issue_encounter AS ie ON ie.pid = l.pid AND " .
1188 "ie.encounter = '$inv_encounter' AND ie.list_id = l.id " .
1189 "WHERE l.pid = '$pid' AND " .
1190 "l.activity = 1 AND l.type = 'ippf_gcac' " .
1191 "ORDER BY ie.pid DESC, l.begdate DESC LIMIT 1");
1192 // Note that reverse-ordering by ie.pid is a trick for sorting
1193 // issues linked to the encounter (non-null values) first.
1194 if (empty($grow['pid'])) { // if there is no linked GCAC issue
1195 if (!empty($grow)) { // there is one that is not linked
1196 echo " if (confirm('" . xl('OK to link the GCAC issue dated') . " " .
1197 $grow['begdate'] . " " . xl('to this visit?') . "')) {\n";
1198 echo " $.getScript('link_issue_to_encounter.php?issue=" . $grow['id'] .
1199 "&thisenc=$inv_encounter');\n";
1200 echo " } else";
1202 echo " if (confirm('" . xl('Are you prepared to complete a new GCAC issue for this visit?') . "')) {\n";
1203 echo " dlgopen('summary/add_edit_issue.php?thisenc=$inv_encounter" .
1204 "&thistype=ippf_gcac', '_blank', 700, 600);\n";
1205 echo " } else {\n";
1206 echo " $.getScript('link_issue_to_encounter.php?thisenc=$inv_encounter');\n";
1207 echo " }\n";
1209 } // end if ($gcac_related_visit)
1210 *********************************************************************/
1212 if ($gcac_related_visit && !$gcac_service_provided) {
1213 // Skip this warning if the GCAC visit form is not allowed.
1214 $grow = sqlQuery("SELECT COUNT(*) AS count FROM list_options " .
1215 "WHERE list_id = 'lbfnames' AND option_id = 'LBFgcac'");
1216 if (!empty($grow['count'])) { // if gcac is used
1217 // Skip this warning if referral or abortion in TS.
1218 $grow = sqlQuery("SELECT COUNT(*) AS count FROM transactions " .
1219 "WHERE title = 'Referral' AND refer_date IS NOT NULL AND " .
1220 "refer_date = '$inv_date' AND pid = '$patient_id'");
1221 if (empty($grow['count'])) { // if there is no referral
1222 $grow = sqlQuery("SELECT COUNT(*) AS count FROM forms " .
1223 "WHERE pid = '$patient_id' AND encounter = '$inv_encounter' AND " .
1224 "deleted = 0 AND formdir = 'LBFgcac'");
1225 if (empty($grow['count'])) { // if there is no gcac form
1226 echo " alert('" . xl('This visit will need a GCAC form, referral or procedure service.') . "');\n";
1230 } // end if ($gcac_related_visit)
1232 </script>
1234 </body>
1235 </html>