5 * This module supports a popup window to handle patient checkout
6 * as a point-of-sale transaction. Support for in-house drug sales
10 * Important notes about system design:
11 * (1) Drug sales may or may not be associated with an encounter;
12 * they are if they are paid for concurrently with an encounter, or
13 * if they are "product" (non-prescription) sales via the Fee Sheet.
14 * (2) Drug sales without an encounter will have 20YYMMDD, possibly
15 * with a suffix, as the encounter-number portion of their invoice
17 * (3) Payments are saved as AR only, don't mess with the billing table.
18 * See library/classes/WSClaim.class.php for posting code.
19 * (4) On checkout, the billing and drug_sales table entries are marked
20 * as billed and so become unavailable for further billing.
21 * (5) Receipt printing must be a separate operation from payment,
25 * If this user has 'irnpool' set
26 * on display of checkout form
27 * show pending next invoice number
28 * on applying checkout
29 * save next invoice number to form_encounter
30 * compute new next invoice number
35 * Copyright (C) 2006-2010 Rod Roark <rod@sunsetsystems.com>
37 * LICENSE: This program is free software; you can redistribute it and/or
38 * modify it under the terms of the GNU General Public License
39 * as published by the Free Software Foundation; either version 2
40 * of the License, or (at your option) any later version.
41 * This program is distributed in the hope that it will be useful,
42 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 * GNU General Public License for more details.
45 * You should have received a copy of the GNU General Public License
46 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>;.
49 * @author Rod Roark <rod@sunsetsystems.com>
50 * @author Brady Miller <brady@sparmy.com>
51 * @link http://www.open-emr.org
55 $fake_register_globals=false;
56 $sanitize_all_escapes=true;
58 require_once("../globals.php");
59 require_once("$srcdir/acl.inc");
60 require_once("$srcdir/patient.inc");
61 require_once("$srcdir/billing.inc");
62 require_once("$srcdir/sql-ledger.inc");
63 require_once("$srcdir/freeb/xmlrpc.inc");
64 require_once("$srcdir/freeb/xmlrpcs.inc");
65 require_once("$srcdir/formatting.inc.php");
66 require_once("$srcdir/formdata.inc.php");
67 require_once("../../custom/code_types.inc.php");
69 $currdecimals = $GLOBALS['currency_decimals'];
71 $INTEGRATED_AR = $GLOBALS['oer_config']['ws_accounting']['enabled'] === 2;
73 $details = empty($_GET['details']) ?
0 : 1;
75 $patient_id = empty($_GET['ptid']) ?
$pid : 0 +
$_GET['ptid'];
77 // Get the patient's name and chart number.
78 $patdata = getPatientData($patient_id, 'fname,mname,lname,pubpid,street,city,state,postal_code');
80 // Get the "next invoice reference number" from this user's pool.
82 function getInvoiceRefNumber() {
83 $trow = sqlQuery("SELECT lo.notes " .
84 "FROM users AS u, list_options AS lo " .
85 "WHERE u.username = ? AND " .
86 "lo.list_id = 'irnpool' AND lo.option_id = u.irnpool LIMIT 1", array($_SESSION['authUser']) );
87 return empty($trow['notes']) ?
'' : $trow['notes'];
90 // Increment the "next invoice reference number" of this user's pool.
91 // This identifies the "digits" portion of that number and adds 1 to it.
92 // If it contains more than one string of digits, the last is used.
94 function updateInvoiceRefNumber() {
95 $irnumber = getInvoiceRefNumber();
96 // Here "?" specifies a minimal match, to get the most digits possible:
97 if (preg_match('/^(.*?)(\d+)(\D*)$/', $irnumber, $matches)) {
98 $newdigs = sprintf('%0' . strlen($matches[2]) . 'd', $matches[2] +
1);
99 $newnumber = $matches[1] . $newdigs . $matches[3];
100 sqlStatement("UPDATE users AS u, list_options AS lo " .
101 "SET lo.notes = ? WHERE " .
102 "u.username = ? AND " .
103 "lo.list_id = 'irnpool' AND lo.option_id = u.irnpool", array($newnumber,$_SESSION['authUser']) );
108 //////////////////////////////////////////////////////////////////////
109 // The following functions are inline here temporarily, and should be
110 // moved to an includable module for common use. In particular
111 // WSClaim.class.php should be rewritten to use them.
112 //////////////////////////////////////////////////////////////////////
114 // Initialize the array of invoice information for posting to the
115 // accounting system.
117 function invoice_initialize(& $invoice_info, $patient_id, $provider_id,
118 $payer_id = 0, $encounter = 0, $dosdate = '')
120 $db = $GLOBALS['adodb']['db'];
122 // Get foreign ID (customer) for patient.
123 $sql = "SELECT foreign_id from integration_mapping as im " .
124 "LEFT JOIN patient_data as pd on im.local_id=pd.id " .
125 "where pd.pid = ? and im.local_table='patient_data' and im.foreign_table='customer'";
126 $result = $db->Execute($sql, array($patient_id) );
127 if($result && !$result->EOF
) {
128 $foreign_patient_id = $result->fields
['foreign_id'];
131 return "Patient '" . $patient_id . "' has not yet been posted to the accounting system.";
134 // Get foreign ID (salesman) for provider.
135 $sql = "SELECT foreign_id from integration_mapping WHERE " .
136 "local_id = ? AND local_table='users' and foreign_table='salesman'";
137 $result = $db->Execute($sql, array($provider_id) );
138 if($result && !$result->EOF
) {
139 $foreign_provider_id = $result->fields
['foreign_id'];
142 return "Provider '" . $provider_id . "' has not yet been posted to the accounting system.";
145 // Get foreign ID (customer) for insurance payer.
146 if ($payer_id && ! $GLOBALS['insurance_companies_are_not_customers']) {
147 $sql = "SELECT foreign_id from integration_mapping WHERE " .
148 "local_id = ? AND local_table = 'insurance_companies' AND foreign_table='customer'";
149 $result = $db->Execute($sql, array($payer_id) );
150 if($result && !$result->EOF
) {
151 $foreign_payer_id = $result->fields
['foreign_id'];
154 return "Payer '" . $payer_id . "' has not yet been posted to the accounting system.";
157 $foreign_payer_id = $payer_id;
160 // Create invoice notes for the new invoice that list the patient's
161 // insurance plans. This is so that when payments are posted, the user
162 // can easily see if a secondary claim needs to be submitted.
166 foreach (array("primary", "secondary", "tertiary") as $instype) {
168 $sql = "SELECT insurance_companies.name " .
169 "FROM insurance_data, insurance_companies WHERE " .
170 "insurance_data.pid = ? AND " .
171 "insurance_data.type = ? AND " .
172 "insurance_companies.id = insurance_data.provider " .
173 "ORDER BY insurance_data.date DESC LIMIT 1";
174 $result = $db->Execute($sql, array($patient_id,$instype) );
175 if ($result && !$result->EOF
&& $result->fields
['name']) {
176 if ($insnotes) $insnotes .= "\n";
177 $insnotes .= "Ins$insno: " . $result->fields
['name'];
180 $invoice_info['notes'] = $insnotes;
182 if (preg_match("/(\d\d\d\d)\D*(\d\d)\D*(\d\d)/", $dosdate, $matches)) {
183 $dosdate = $matches[2] . '-' . $matches[3] . '-' . $matches[1];
185 $dosdate = date("m-d-Y");
188 $invoice_info['salesman'] = $foreign_provider_id;
189 $invoice_info['customerid'] = $foreign_patient_id;
190 $invoice_info['payer_id'] = $foreign_payer_id;
191 $invoice_info['invoicenumber'] = $patient_id . "." . $encounter;
192 $invoice_info['dosdate'] = $dosdate;
193 $invoice_info['items'] = array();
194 $invoice_info['total'] = '0.00';
199 function invoice_add_line_item(& $invoice_info, $code_type, $code,
200 $code_text, $amount, $units=1)
202 $units = max(1, intval(trim($units)));
203 $amount = sprintf("%01.2f", $amount);
204 $price = $amount / $units;
205 $tmp = sprintf("%01.2f", $price);
206 if (abs($price - $tmp) < 0.000001) $price = $tmp;
208 $tii['maincode'] = $code;
209 $tii['itemtext'] = "$code_type:$code";
210 if ($code_text) $tii['itemtext'] .= " $code_text";
211 $tii['qty'] = $units;
212 $tii['price'] = $price;
213 $tii['glaccountid'] = $GLOBALS['oer_config']['ws_accounting']['income_acct'];
214 $invoice_info['total'] = sprintf("%01.2f", $invoice_info['total'] +
$amount);
215 $invoice_info['items'][] = $tii;
219 function invoice_post(& $invoice_info)
221 $function['ezybiz.add_invoice'] = array(new xmlrpcval($invoice_info, "struct"));
223 list($name, $var) = each($function);
224 $f = new xmlrpcmsg($name, $var);
226 $c = new xmlrpc_client($GLOBALS['oer_config']['ws_accounting']['url'],
227 $GLOBALS['oer_config']['ws_accounting']['server'],
228 $GLOBALS['oer_config']['ws_accounting']['port']);
230 $c->setCredentials($GLOBALS['oer_config']['ws_accounting']['username'],
231 $GLOBALS['oer_config']['ws_accounting']['password']);
234 if (!$r) return "XMLRPC send failed";
236 // We are not doing anything with the return value yet... should we?
238 if (is_object($tv)) {
239 $value = $tv->getval();
245 if ($r->faultCode()) {
246 return "Fault: Code: " . $r->faultCode() . " Reason '" . $r->faultString() . "'";
252 ///////////// End of SQL-Ledger invoice posting functions ////////////
254 // Output HTML for an invoice line item.
257 function receiptDetailLine($svcdate, $description, $amount, $quantity) {
258 global $prevsvcdate, $details;
259 if (!$details) return;
260 $amount = sprintf('%01.2f', $amount);
261 if (empty($quantity)) $quantity = 1;
262 $price = sprintf('%01.4f', $amount / $quantity);
263 $tmp = sprintf('%01.2f', $price);
264 if ($price == $tmp) $price = $tmp;
266 echo " <td>" . ($svcdate == $prevsvcdate ?
' ' : text(oeFormatShortDate($svcdate))) . "</td>\n";
267 echo " <td>" . text($description) . "</td>\n";
268 echo " <td align='right'>" . text(oeFormatMoney($price)) . "</td>\n";
269 echo " <td align='right'>" . text($quantity) . "</td>\n";
270 echo " <td align='right'>" . text(oeFormatMoney($amount)) . "</td>\n";
272 $prevsvcdate = $svcdate;
275 // Output HTML for an invoice payment.
277 function receiptPaymentLine($paydate, $amount, $description='') {
278 $amount = sprintf('%01.2f', 0 - $amount); // make it negative
280 echo " <td>" . text(oeFormatShortDate($paydate)) . "</td>\n";
281 echo " <td>" . xlt('Payment') . " " . text($description) . "</td>\n";
282 echo " <td colspan='2'> </td>\n";
283 echo " <td align='right'>" . text(oeFormatMoney($amount)) . "</td>\n";
287 // Generate a receipt from the last-billed invoice for this patient,
288 // or for the encounter specified as a GET parameter.
290 function generate_receipt($patient_id, $encounter=0) {
291 global $sl_err, $sl_cash_acc, $css_header, $details, $INTEGRATED_AR;
293 // Get details for what we guess is the primary facility.
294 $frow = sqlQuery("SELECT * FROM facility " .
295 "ORDER BY billing_location DESC, accepts_assignment DESC, id LIMIT 1");
297 $patdata = getPatientData($patient_id, 'fname,mname,lname,pubpid,street,city,state,postal_code,providerID');
299 // Get the most recent invoice data or that for the specified encounter.
301 // Adding a provider check so that their info can be displayed on receipts
302 if ($INTEGRATED_AR) {
304 $ferow = sqlQuery("SELECT id, date, encounter, provider_id FROM form_encounter " .
305 "WHERE pid = ? AND encounter = ?", array($patient_id,$encounter) );
307 $ferow = sqlQuery("SELECT id, date, encounter, provider_id FROM form_encounter " .
309 "ORDER BY id DESC LIMIT 1", array($patient_id) );
311 if (empty($ferow)) die(xlt("This patient has no activity."));
312 $trans_id = $ferow['id'];
313 $encounter = $ferow['encounter'];
314 $svcdate = substr($ferow['date'], 0, 10);
316 if ($GLOBALS['receipts_by_provider']){
317 if (isset($ferow['provider_id']) ) {
318 $encprovider = $ferow['provider_id'];
319 } else if (isset($patdata['providerID'])){
320 $encprovider = $patdata['providerID'];
321 } else { $encprovider = -1; }
325 $providerrow = sqlQuery("SELECT fname, mname, lname, title, street, streetb, " .
326 "city, state, zip, phone, fax FROM users WHERE id = ?", array($encprovider) );
332 $arres = SLQuery("SELECT * FROM ar WHERE " .
333 "invnumber LIKE '$patient_id.%' " .
334 "ORDER BY id DESC LIMIT 1");
335 if ($sl_err) die(text($sl_err));
336 if (!SLRowCount($arres)) die(xlt("This patient has no activity."));
337 $arrow = SLGetRow($arres, 0);
339 $trans_id = $arrow['id'];
341 // Determine the date of service. An 8-digit encounter number is
342 // presumed to be a date of service imported during conversion or
343 // associated with prescriptions only. Otherwise look it up in the
344 // form_encounter table.
347 list($trash, $encounter) = explode(".", $arrow['invnumber']);
348 if (strlen($encounter) >= 8) {
349 $svcdate = substr($encounter, 0, 4) . "-" . substr($encounter, 4, 2) .
350 "-" . substr($encounter, 6, 2);
352 else if ($encounter) {
353 $tmp = sqlQuery("SELECT date FROM form_encounter WHERE " .
354 "encounter = ?", array($encounter) );
355 $svcdate = substr($tmp['date'], 0, 10);
357 } // end not $INTEGRATED_AR
359 // Get invoice reference number.
360 $encrow = sqlQuery("SELECT invoice_refno FROM form_encounter WHERE " .
361 "pid = ? AND encounter = ? LIMIT 1", array($patient_id,$encounter) );
362 $invoice_refno = $encrow['invoice_refno'];
366 <?php
html_header_show(); ?
>
367 <link rel
='stylesheet' href
='<?php echo $css_header ?>' type
='text/css'>
368 <title
><?php
echo xlt('Receipt for Payment'); ?
></title
>
369 <script type
="text/javascript" src
="../../library/js/jquery-1.2.2.min.js"></script
>
370 <script type
="text/javascript" src
="../../library/dialog.js"></script
>
371 <script language
="JavaScript">
373 <?php
require($GLOBALS['srcdir'] . "/restoreSession.php"); ?
>
375 $
(document
).ready(function() {
376 var win
= top
.printLogSetup ? top
: opener
.top
;
377 win
.printLogSetup(document
.getElementById('printbutton'));
380 // Process click on Print button.
381 function printlog_before_print() {
382 var divstyle
= document
.getElementById('hideonprint').style
;
383 divstyle
.display
= 'none';
386 // Process click on Delete button.
387 function deleteme() {
388 dlgopen('deleter.php?billing=<?php echo attr("$patient_id.$encounter"); ?>', '_blank', 500, 450);
392 // Called by the deleteme.php window on a successful delete.
393 function imdeleted() {
399 <body
class="body_top">
402 if ( $GLOBALS['receipts_by_provider'] && !empty($providerrow) ) { printProviderHeader($providerrow); }
403 else { printFacilityHeader($frow); }
406 echo xlt("Receipt Generated") . ":" . text(date(' F j, Y'));
407 if ($invoice_refno) echo " " . xlt("Invoice Number") . ": " . text($invoice_refno) . " " . xlt("Service Date") . ": " . text($svcdate);
413 <?php
echo text($patdata['fname']) . ' ' . text($patdata['mname']) . ' ' . text($patdata['lname']) ?
>
414 <br
><?php
echo text($patdata['street']) ?
>
415 <br
><?php
echo text($patdata['city']) . ', ' . text($patdata['state']) . ' ' . text($patdata['postal_code']) ?
>
419 <table cellpadding
='5'>
421 <td
><b
><?php
echo xlt('Date'); ?
></b
></td
>
422 <td
><b
><?php
echo xlt('Description'); ?
></b
></td
>
423 <td align
='right'><b
><?php
echo $details ?
xlt('Price') : ' '; ?
></b
></td
>
424 <td align
='right'><b
><?php
echo $details ?
xlt('Qty' ) : ' '; ?
></b
></td
>
425 <td align
='right'><b
><?php
echo xlt('Total'); ?
></b
></td
>
431 if ($INTEGRATED_AR) {
433 $inres = sqlStatement("SELECT s.sale_id, s.sale_date, s.fee, " .
434 "s.quantity, s.drug_id, d.name " .
435 "FROM drug_sales AS s LEFT JOIN drugs AS d ON d.drug_id = s.drug_id " .
436 // "WHERE s.pid = '$patient_id' AND s.encounter = '$encounter' AND s.fee != 0 " .
437 "WHERE s.pid = ? AND s.encounter = ? " .
438 "ORDER BY s.sale_id", array($patient_id,$encounter) );
439 while ($inrow = sqlFetchArray($inres)) {
440 $charges +
= sprintf('%01.2f', $inrow['fee']);
441 receiptDetailLine($inrow['sale_date'], $inrow['name'],
442 $inrow['fee'], $inrow['quantity']);
444 // Service and tax items
445 $inres = sqlStatement("SELECT * FROM billing WHERE " .
446 "pid = ? AND encounter = ? AND " .
447 // "code_type != 'COPAY' AND activity = 1 AND fee != 0 " .
448 "code_type != 'COPAY' AND activity = 1 " .
449 "ORDER BY id", array($patient_id,$encounter) );
450 while ($inrow = sqlFetchArray($inres)) {
451 $charges +
= sprintf('%01.2f', $inrow['fee']);
452 receiptDetailLine($svcdate, $inrow['code_text'],
453 $inrow['fee'], $inrow['units']);
456 $inres = sqlStatement("SELECT " .
457 "a.code_type, a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, " .
458 "s.payer_id, s.reference, s.check_date, s.deposit_date " .
459 "FROM ar_activity AS a " .
460 "LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " .
461 "a.pid = ? AND a.encounter = ? AND " .
462 "a.adj_amount != 0 " .
463 "ORDER BY s.check_date, a.sequence_no", array($patient_id,$encounter) );
464 while ($inrow = sqlFetchArray($inres)) {
465 $charges -= sprintf('%01.2f', $inrow['adj_amount']);
466 $payer = empty($inrow['payer_type']) ?
'Pt' : ('Ins' . $inrow['payer_type']);
467 receiptDetailLine($svcdate, $payer . ' ' . $inrow['memo'],
468 0 - $inrow['adj_amount'], 1);
470 } // end $INTEGRATED_AR
472 // Request all line items with money belonging to the invoice.
473 $inres = SLQuery("SELECT * FROM invoice WHERE " .
474 "trans_id = $trans_id AND sellprice != 0 ORDER BY id");
475 if ($sl_err) die($sl_err);
476 for ($irow = 0; $irow < SLRowCount($inres); ++
$irow) {
477 $row = SLGetRow($inres, $irow);
478 $amount = sprintf('%01.2f', $row['sellprice'] * $row['qty']);
480 $desc = preg_replace('/^.{1,6}:/', '', $row['description']);
481 receiptDetailLine($svcdate, $desc, $amount, $row['qty']);
483 } // end not $INTEGRATED_AR
487 <td colspan
='5'> 
;</td
>
490 <td
><?php
echo text(oeFormatShortDate($svcdispdate)); ?
></td
>
491 <td
><b
><?php
echo xlt('Total Charges'); ?
></b
></td
>
492 <td align
='right'> 
;</td
>
493 <td align
='right'> 
;</td
>
494 <td align
='right'><?php
echo text(oeFormatMoney($charges, true)) ?
></td
>
497 <td colspan
='5'> 
;</td
>
501 if ($INTEGRATED_AR) {
503 $inres = sqlStatement("SELECT fee, code_text FROM billing WHERE " .
504 "pid = ? AND encounter = ? AND " .
505 "code_type = 'COPAY' AND activity = 1 AND fee != 0 " .
506 "ORDER BY id", array($patient_id,$encounter) );
507 while ($inrow = sqlFetchArray($inres)) {
508 $charges +
= sprintf('%01.2f', $inrow['fee']);
509 receiptPaymentLine($svcdate, 0 - $inrow['fee'], $inrow['code_text']);
511 // Get other payments.
512 $inres = sqlStatement("SELECT " .
513 "a.code_type, a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, " .
514 "s.payer_id, s.reference, s.check_date, s.deposit_date " .
515 "FROM ar_activity AS a " .
516 "LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " .
517 "a.pid = ? AND a.encounter = ? AND " .
518 "a.pay_amount != 0 " .
519 "ORDER BY s.check_date, a.sequence_no", array($patient_id,$encounter) );
520 while ($inrow = sqlFetchArray($inres)) {
521 $payer = empty($inrow['payer_type']) ?
'Pt' : ('Ins' . $inrow['payer_type']);
522 $charges -= sprintf('%01.2f', $inrow['pay_amount']);
523 receiptPaymentLine($svcdate, $inrow['pay_amount'],
524 $payer . ' ' . $inrow['reference']);
526 } // end $INTEGRATED_AR
528 $chart_id_cash = SLQueryValue("select id from chart where accno = '$sl_cash_acc'");
529 if ($sl_err) die($sl_err);
530 if (! $chart_id_cash) die("There is no COA entry for cash account '$sl_cash_acc'");
532 // Request all cash entries belonging to the invoice.
533 $atres = SLQuery("SELECT * FROM acc_trans WHERE " .
534 "trans_id = $trans_id AND chart_id = $chart_id_cash ORDER BY transdate");
535 if ($sl_err) die($sl_err);
537 for ($irow = 0; $irow < SLRowCount($atres); ++
$irow) {
538 $row = SLGetRow($atres, $irow);
539 $amount = sprintf('%01.2f', $row['amount']); // negative
541 $rowsource = $row['source'];
542 if (strtolower($rowsource) == 'co-pay') $rowsource = '';
543 receiptPaymentLine($row['transdate'], 0 - $amount, $rowsource);
545 } // end not $INTEGRATED_AR
548 <td colspan
='5'> 
;</td
>
552 <td
><b
><?php
echo xlt('Balance Due'); ?
></b
></td
>
553 <td colspan
='2'> 
;</td
>
554 <td align
='right'><?php
echo text(oeFormatMoney($charges, true)) ?
></td
>
558 <div id
='hideonprint'>
561 <a href
='#' id
='printbutton'><?php
echo xlt('Print'); ?
></a
>
562 <?php
if (acl_check('acct','disc')) { ?
>
563  
; 
; 
; 
; 
;
564 <a href
='#' onclick
='return deleteme();'><?php
echo xlt('Undo Checkout'); ?
></a
>
566  
; 
; 
; 
; 
;
567 <?php
if ($details) { ?
>
568 <a href
='pos_checkout.php?details=0&ptid=<?php echo attr($patient_id); ?>&enc=<?php echo attr($encounter); ?>' onclick
='top.restoreSession()'><?php
echo xlt('Hide Details'); ?
></a
>
570 <a href
='pos_checkout.php?details=1&ptid=<?php echo attr($patient_id); ?>&enc=<?php echo attr($encounter); ?>' onclick
='top.restoreSession()'><?php
echo xlt('Show Details'); ?
></a
>
577 if (!$INTEGRATED_AR) SLClose();
578 } // end function generate_receipt()
580 // Function to output a line item for the input form.
583 function write_form_line($code_type, $code, $id, $date, $description,
584 $amount, $units, $taxrates) {
586 $amount = sprintf("%01.2f", $amount);
587 if (empty($units)) $units = 1;
588 $price = $amount / $units; // should be even cents, but ok here if not
589 if ($code_type == 'COPAY' && !$description) $description = xl('Payment');
591 echo " <td>" . text(oeFormatShortDate($date));
592 echo "<input type='hidden' name='line[$lino][code_type]' value='" . attr($code_type) . "'>";
593 echo "<input type='hidden' name='line[$lino][code]' value='" . attr($code) . "'>";
594 echo "<input type='hidden' name='line[$lino][id]' value='" . attr($id) . "'>";
595 echo "<input type='hidden' name='line[$lino][description]' value='" . attr($description) . "'>";
596 echo "<input type='hidden' name='line[$lino][taxrates]' value='" . attr($taxrates) . "'>";
597 echo "<input type='hidden' name='line[$lino][price]' value='" . attr($price) . "'>";
598 echo "<input type='hidden' name='line[$lino][units]' value='" . attr($units) . "'>";
600 echo " <td>" . text($description) . "</td>";
601 echo " <td align='right'>" . text($units) . "</td>";
602 echo " <td align='right'><input type='text' name='line[$lino][amount]' " .
603 "value='" . attr($amount) . "' size='6' maxlength='8'";
604 // Modifying prices requires the acct/disc permission.
605 // if ($code_type == 'TAX' || ($code_type != 'COPAY' && !acl_check('acct','disc')))
606 echo " style='text-align:right;background-color:transparent' readonly";
607 // else echo " style='text-align:right' onkeyup='computeTotals()'";
613 // Create the taxes array. Key is tax id, value is
614 // (description, rate, accumulated total).
616 $pres = sqlStatement("SELECT option_id, title, option_value " .
617 "FROM list_options WHERE list_id = 'taxrate' ORDER BY seq");
618 while ($prow = sqlFetchArray($pres)) {
619 $taxes[$prow['option_id']] = array($prow['title'], $prow['option_value'], 0);
622 // Print receipt header for facility
623 function printFacilityHeader($frow){
624 echo "<p><b>" . text($frow['name']) .
625 "<br>" . text($frow['street']) .
626 "<br>" . text($frow['city']) . ', ' . text($frow['state']) . ' ' . text($frow['postal_code']) .
627 "<br>" . text($frow['phone']) .
632 // Pring receipt header for Provider
633 function printProviderHeader($pvdrow){
634 echo "<p><b>" . text($pvdrow['title']) . " " . text($pvdrow['fname']) . " " . text($pvdrow['mname']) . " " . text($pvdrow['lname']) . " " .
635 "<br>" . text($pvdrow['street']) .
636 "<br>" . text($pvdrow['city']) . ', ' . text($pvdrow['state']) . ' ' . text($pvdrow['postal_code']) .
637 "<br>" . text($pvdrow['phone']) .
642 // Mark the tax rates that are referenced in this invoice.
643 function markTaxes($taxrates) {
645 $arates = explode(':', $taxrates);
646 if (empty($arates)) return;
647 foreach ($arates as $value) {
648 if (!empty($taxes[$value])) $taxes[$value][2] = '1';
652 $payment_methods = array(
661 $alertmsg = ''; // anything here pops up in an alert box
663 // If the Save button was clicked...
665 if ($_POST['form_save']) {
667 // On a save, do the following:
668 // Flag drug_sales and billing items as billed.
669 // Post the corresponding invoice with its payment(s) to sql-ledger
670 // and be careful to use a unique invoice number.
671 // Call the generate-receipt function.
674 $form_pid = $_POST['form_pid'];
675 $form_encounter = $_POST['form_encounter'];
677 // Get the posting date from the form as yyyy-mm-dd.
678 $dosdate = date("Y-m-d");
679 if (preg_match("/(\d\d\d\d)\D*(\d\d)\D*(\d\d)/", $_POST['form_date'], $matches)) {
680 $dosdate = $matches[1] . '-' . $matches[2] . '-' . $matches[3];
683 // If there is no associated encounter (i.e. this invoice has only
684 // prescriptions) then assign an encounter number of the service
685 // date, with an optional suffix to ensure that it's unique.
687 if (! $form_encounter) {
688 $form_encounter = substr($dosdate,0,4) . substr($dosdate,5,2) . substr($dosdate,8,2);
690 if ($INTEGRATED_AR) {
692 $ferow = sqlQuery("SELECT id FROM form_encounter WHERE " .
693 "pid = ? AND encounter = ?", array($form_pid, $form_encounter.$tmp) );
694 if (empty($ferow)) break;
695 $tmp = $tmp ?
$tmp +
1 : 1;
700 while (SLQueryValue("select id from ar where " .
701 "invnumber = '$form_pid.$form_encounter$tmp'")) {
702 $tmp = $tmp ?
$tmp +
1 : 1;
706 $form_encounter .= $tmp;
709 if ($INTEGRATED_AR) {
710 // Delete any TAX rows from billing because they will be recalculated.
711 sqlStatement("UPDATE billing SET activity = 0 WHERE " .
712 "pid = ? AND encounter = ? AND " .
713 "code_type = 'TAX'", array($form_pid,$form_encounter) );
716 // Initialize an array of invoice information for posting.
717 $invoice_info = array();
718 $msg = invoice_initialize($invoice_info, $form_pid,
719 $_POST['form_provider'], $_POST['form_payer'], $form_encounter, $dosdate);
723 $form_amount = $_POST['form_amount'];
724 $lines = $_POST['line'];
726 for ($lino = 0; $lines[$lino]['code_type']; ++
$lino) {
727 $line = $lines[$lino];
728 $code_type = $line['code_type'];
730 $amount = sprintf('%01.2f', trim($line['amount']));
732 if (!$INTEGRATED_AR) {
733 $msg = invoice_add_line_item($invoice_info, $code_type,
734 $line['code'], $line['description'], $amount, $line['units']);
738 if ($code_type == 'PROD') {
739 // Product sales. The fee and encounter ID may have changed.
740 $query = "update drug_sales SET fee = ?, " .
741 "encounter = ?, billed = 1 WHERE " .
743 sqlQuery($query, array($amount,$form_encounter,$id) );
745 else if ($code_type == 'TAX') {
746 // In the SL case taxes show up on the invoice as line items.
747 // Otherwise we gotta save them somewhere, and in the billing
748 // table with a code type of TAX seems easiest.
749 // They will have to be stripped back out when building this
750 // script's input form.
751 addBilling($form_encounter, 'TAX', 'TAX', 'Taxes', $form_pid, 0, 0,
752 '', '', $amount, '', '', 1);
755 // Because there is no insurance here, there is no need for a claims
756 // table entry and so we do not call updateClaim(). Note we should not
757 // eliminate billed and bill_date from the billing table!
758 $query = "UPDATE billing SET fee = ?, billed = 1, " .
759 "bill_date = NOW() WHERE id = ?";
760 sqlQuery($query, array($amount,$id) );
765 if ($_POST['form_discount']) {
766 if ($GLOBALS['discount_by_money']) {
767 $amount = sprintf('%01.2f', trim($_POST['form_discount']));
770 $amount = sprintf('%01.2f', trim($_POST['form_discount']) * $form_amount / 100);
772 $memo = xl('Discount');
773 if ($INTEGRATED_AR) {
774 $time = date('Y-m-d H:i:s');
775 $query = "INSERT INTO ar_activity ( " .
776 "pid, encounter, code, modifier, payer_type, post_user, post_time, " .
777 "session_id, memo, adj_amount " .
790 sqlStatement($query, array($form_pid,$form_encounter,$_SESSION['authUserID'],$time,$memo,$amount) );
793 $msg = invoice_add_line_item($invoice_info, 'DISCOUNT',
794 '', $memo, 0 - $amount);
800 if ($_POST['form_amount']) {
801 $amount = sprintf('%01.2f', trim($_POST['form_amount']));
802 $form_source = trim($_POST['form_source']);
803 $paydesc = trim($_POST['form_method']);
804 if ($INTEGRATED_AR) {
805 //Fetching the existing code and modifier
806 $ResultSearchNew = sqlStatement("SELECT * FROM billing LEFT JOIN code_types ON billing.code_type=code_types.ct_key ".
807 "WHERE code_types.ct_fee=1 AND billing.activity!=0 AND billing.pid =? AND encounter=? ORDER BY billing.code,billing.modifier",
808 array($form_pid,$form_encounter));
809 if($RowSearch = sqlFetchArray($ResultSearchNew))
811 $Codetype=$RowSearch['code_type'];
812 $Code=$RowSearch['code'];
813 $Modifier=$RowSearch['modifier'];
819 $session_id=idSqlStatement("INSERT INTO ar_session (payer_id,user_id,reference,check_date,deposit_date,pay_total,".
820 " global_amount,payment_type,description,patient_id,payment_method,adjustment_code,post_to_date) ".
821 " VALUES ('0',?,?,now(),?,?,'','patient','COPAY',?,?,'patient_payment',now())",
822 array($_SESSION['authId'],$form_source,$dosdate,$amount,$form_pid,$paydesc));
823 $insrt_id=idSqlStatement("INSERT INTO ar_activity (pid,encounter,code_type,code,modifier,payer_type,post_time,post_user,session_id,pay_amount,account_code)".
824 " VALUES (?,?,?,?,?,0,?,?,?,?,'PCP')",
825 array($form_pid,$form_encounter,$Codetype,$Code,$Modifier,$dosdate,$_SESSION['authId'],$session_id,$amount));
828 $msg = invoice_add_line_item($invoice_info, 'COPAY',
829 $paydesc, $form_source, 0 - $amount);
834 if (!$INTEGRATED_AR) {
835 $msg = invoice_post($invoice_info);
839 // If applicable, set the invoice reference number.
841 if (isset($_POST['form_irnumber'])) {
842 $invoice_refno = trim($_POST['form_irnumber']);
845 $invoice_refno = updateInvoiceRefNumber();
847 if ($invoice_refno) {
848 sqlStatement("UPDATE form_encounter " .
849 "SET invoice_refno = ? " .
850 "WHERE pid = ? AND encounter = ?", array($invoice_refno,$form_pid,$form_encounter) );
853 generate_receipt($form_pid, $form_encounter);
857 // If an encounter ID was given, then we must generate a receipt.
859 if (!empty($_GET['enc'])) {
860 generate_receipt($patient_id, $_GET['enc']);
864 // Get the unbilled billing table items for this patient.
865 $query = "SELECT id, date, code_type, code, modifier, code_text, " .
866 "provider_id, payer_id, units, fee, encounter " .
867 "FROM billing WHERE pid = ? AND activity = 1 AND " .
868 "billed = 0 AND code_type != 'TAX' " .
869 "ORDER BY encounter DESC, id ASC";
870 $bres = sqlStatement($query, array($patient_id) );
872 // Get the product sales for this patient.
873 $query = "SELECT s.sale_id, s.sale_date, s.prescription_id, s.fee, " .
874 "s.quantity, s.encounter, s.drug_id, d.name, r.provider_id " .
875 "FROM drug_sales AS s " .
876 "LEFT JOIN drugs AS d ON d.drug_id = s.drug_id " .
877 "LEFT OUTER JOIN prescriptions AS r ON r.id = s.prescription_id " .
878 "WHERE s.pid = ? AND s.billed = 0 " .
879 "ORDER BY s.encounter DESC, s.sale_id ASC";
880 $dres = sqlStatement($query, array($patient_id) );
882 // If there are none, just redisplay the last receipt and exit.
884 if (sqlNumRows($bres) == 0 && sqlNumRows($dres) == 0) {
885 generate_receipt($patient_id);
889 // Get the valid practitioners, including those not active.
890 $arr_users = array();
891 $ures = sqlStatement("SELECT id, username FROM users WHERE " .
892 "( authorized = 1 OR info LIKE '%provider%' ) AND username != ''");
893 while ($urow = sqlFetchArray($ures)) {
894 $arr_users[$urow['id']] = '1';
897 // Now write a data entry form:
898 // List unbilled billing items (cpt, hcpcs, copays) for the patient.
899 // List unbilled product sales for the patient.
900 // Present an editable dollar amount for each line item, a total
901 // which is also the default value of the input payment amount,
902 // and OK and Cancel buttons.
906 <link rel
='stylesheet' href
='<?php echo $css_header ?>' type
='text/css'>
907 <title
><?php
echo xlt('Patient Checkout'); ?
></title
>
910 <style type
="text/css">@import
url(../../library
/dynarch_calendar
.css
);</style
>
911 <script type
="text/javascript" src
="../../library/textformat.js"></script
>
912 <script type
="text/javascript" src
="../../library/dynarch_calendar.js"></script
>
913 <?php
include_once("{$GLOBALS['srcdir']}/dynarch_calendar_en.inc.php"); ?
>
914 <script type
="text/javascript" src
="../../library/dynarch_calendar_setup.js"></script
>
915 <script type
="text/javascript" src
="../../library/dialog.js"></script
>
916 <script type
="text/javascript" src
="../../library/js/jquery-1.2.2.min.js"></script
>
917 <script language
="JavaScript">
918 var mypcc
= '<?php echo $GLOBALS['phone_country_code
'] ?>';
920 <?php
require($GLOBALS['srcdir'] . "/restoreSession.php"); ?
>
922 // This clears the tax line items in preparation for recomputing taxes.
923 function clearTax(visible
) {
924 var f
= document
.forms
[0];
925 for (var lino
= 0; true; ++lino
) {
926 var pfx
= 'line[' + lino +
']';
927 if (! f
[pfx +
'[code_type]']) break;
928 if (f
[pfx +
'[code_type]'].value
!= 'TAX') continue;
929 f
[pfx +
'[price]'].value
= '0.00';
930 if (visible
) f
[pfx +
'[amount]'].value
= '0.00';
934 // For a given tax ID and amount, compute the tax on that amount and add it
935 // to the "price" (same as "amount") of the corresponding tax line item.
936 // Note the tax line items include their "taxrate" to make this easy.
937 function addTax(rateid
, amount
, visible
) {
938 if (rateid
.length
== 0) return 0;
939 var f
= document
.forms
[0];
940 for (var lino
= 0; true; ++lino
) {
941 var pfx
= 'line[' + lino +
']';
942 if (! f
[pfx +
'[code_type]']) break;
943 if (f
[pfx +
'[code_type]'].value
!= 'TAX') continue;
944 if (f
[pfx +
'[code]'].value
!= rateid
) continue;
945 var tax
= amount
* parseFloat(f
[pfx +
'[taxrates]'].value
);
946 tax
= parseFloat(tax
.toFixed(<?php
echo $currdecimals ?
>));
947 var cumtax
= parseFloat(f
[pfx +
'[price]'].value
) + tax
;
948 f
[pfx +
'[price]'].value
= cumtax
.toFixed(<?php
echo $currdecimals ?
>); // requires JS 1.5
949 if (visible
) f
[pfx +
'[amount]'].value
= cumtax
.toFixed(<?php
echo $currdecimals ?
>); // requires JS 1.5
950 if (isNaN(tax
)) alert('Tax rate not numeric at line ' + lino
);
956 // This mess recomputes the invoice total and optionally applies a discount.
957 function computeDiscountedTotals(discount
, visible
) {
959 var f
= document
.forms
[0];
961 for (var lino
= 0; f
['line[' + lino +
'][code_type]']; ++lino
) {
962 var code_type
= f
['line[' + lino +
'][code_type]'].value
;
963 // price is price per unit when the form was originally generated.
964 // By contrast, amount is the dynamically-generated discounted line total.
965 var price
= parseFloat(f
['line[' + lino +
'][price]'].value
);
966 if (isNaN(price
)) alert('Price not numeric at line ' + lino
);
967 if (code_type
== 'COPAY' || code_type
== 'TAX') {
968 // This works because the tax lines come last.
969 total +
= parseFloat(price
.toFixed(<?php
echo $currdecimals ?
>));
972 var units
= f
['line[' + lino +
'][units]'].value
;
973 var amount
= price
* units
;
974 amount
= parseFloat(amount
.toFixed(<?php
echo $currdecimals ?
>));
975 if (visible
) f
['line[' + lino +
'][amount]'].value
= amount
.toFixed(<?php
echo $currdecimals ?
>);
977 var taxrates
= f
['line[' + lino +
'][taxrates]'].value
;
978 var taxids
= taxrates
.split(':');
979 for (var j
= 0; j
< taxids
.length
; ++j
) {
980 addTax(taxids
[j
], amount
, visible
);
983 return total
- discount
;
986 // Recompute displayed amounts with any discount applied.
987 function computeTotals() {
988 var f
= document
.forms
[0];
989 var discount
= parseFloat(f
.form_discount
.value
);
990 if (isNaN(discount
)) discount
= 0;
991 <?php
if (!$GLOBALS['discount_by_money']) { ?
>
992 // This site discounts by percentage, so convert it to a money amount.
993 if (discount
> 100) discount
= 100;
994 if (discount
< 0 ) discount
= 0;
995 discount
= 0.01 * discount
* computeDiscountedTotals(0, false);
997 var total
= computeDiscountedTotals(discount
, true);
998 f
.form_amount
.value
= total
.toFixed(<?php
echo $currdecimals ?
>);
1005 <body
class="body_top">
1007 <form method
='post' action
='pos_checkout.php'>
1008 <input type
='hidden' name
='form_pid' value
='<?php echo attr($patient_id) ?>' />
1013 <table cellspacing
='5'>
1015 <td colspan
='3' align
='center'>
1016 <b
><?php
echo xlt('Patient Checkout for '); ?
><?php
echo text($patdata['fname']) . " " .
1017 text($patdata['lname']) . " (" . text($patdata['pubpid']) . ")" ?
></b
>
1021 <td
><b
><?php
echo xlt('Date'); ?
></b
></td
>
1022 <td
><b
><?php
echo xlt('Description'); ?
></b
></td
>
1023 <td align
='right'><b
><?php
echo xlt('Qty'); ?
></b
></td
>
1024 <td align
='right'><b
><?php
echo xlt('Amount'); ?
></b
></td
>
1027 $inv_encounter = '';
1031 $gcac_related_visit = false;
1032 $gcac_service_provided = false;
1034 // Process billing table items.
1035 // Items that are not allowed to have a fee are skipped.
1037 while ($brow = sqlFetchArray($bres)) {
1038 // Skip all but the most recent encounter.
1039 if ($inv_encounter && $brow['encounter'] != $inv_encounter) continue;
1041 $thisdate = substr($brow['date'], 0, 10);
1042 $code_type = $brow['code_type'];
1044 // Collect tax rates, related code and provider ID.
1047 $sqlBindArray = array();
1048 if (!empty($code_types[$code_type]['fee'])) {
1049 $query = "SELECT taxrates, related_code FROM codes WHERE code_type = ? " .
1052 array_push($sqlBindArray,$code_types[$code_type]['id'],$brow['code']);
1053 if ($brow['modifier']) {
1054 $query .= "modifier = ?";
1055 array_push($sqlBindArray,$brow['modifier']);
1057 $query .= "(modifier IS NULL OR modifier = '')";
1059 $query .= " LIMIT 1";
1060 $tmp = sqlQuery($query,$sqlBindArray);
1061 $taxrates = $tmp['taxrates'];
1062 $related_code = $tmp['related_code'];
1063 markTaxes($taxrates);
1066 write_form_line($code_type, $brow['code'], $brow['id'], $thisdate,
1067 $brow['code_text'], $brow['fee'], $brow['units'],
1069 if (!$inv_encounter) $inv_encounter = $brow['encounter'];
1070 $inv_payer = $brow['payer_id'];
1071 if (!$inv_date ||
$inv_date < $thisdate) $inv_date = $thisdate;
1073 // Custom logic for IPPF to determine if a GCAC issue applies.
1074 if ($GLOBALS['ippf_specific'] && $related_code) {
1075 $relcodes = explode(';', $related_code);
1076 foreach ($relcodes as $codestring) {
1077 if ($codestring === '') continue;
1078 list($codetype, $code) = explode(':', $codestring);
1079 if ($codetype !== 'IPPF') continue;
1080 if (preg_match('/^25222/', $code)) {
1081 $gcac_related_visit = true;
1082 if (preg_match('/^25222[34]/', $code))
1083 $gcac_service_provided = true;
1091 $totalCopay = getPatientCopay($patient_id,$encounter);
1092 if ($totalCopay < 0) {
1093 write_form_line("COPAY", "", "", "", "", $totalCopay, "", "");
1096 // Process drug sales / products.
1098 while ($drow = sqlFetchArray($dres)) {
1099 if ($inv_encounter && $drow['encounter'] && $drow['encounter'] != $inv_encounter) continue;
1101 $thisdate = $drow['sale_date'];
1102 if (!$inv_encounter) $inv_encounter = $drow['encounter'];
1104 if (!$inv_provider && !empty($arr_users[$drow['provider_id']]))
1105 $inv_provider = $drow['provider_id'] +
0;
1107 if (!$inv_date ||
$inv_date < $thisdate) $inv_date = $thisdate;
1109 // Accumulate taxes for this product.
1110 $tmp = sqlQuery("SELECT taxrates FROM drug_templates WHERE drug_id = ? " .
1111 " ORDER BY selector LIMIT 1", array($drow['drug_id']) );
1112 // accumTaxes($drow['fee'], $tmp['taxrates']);
1113 $taxrates = $tmp['taxrates'];
1114 markTaxes($taxrates);
1116 write_form_line('PROD', $drow['drug_id'], $drow['sale_id'],
1117 $thisdate, $drow['name'], $drow['fee'], $drow['quantity'], $taxrates);
1120 // Write a form line for each tax that has money, adding to $total.
1121 foreach ($taxes as $key => $value) {
1123 write_form_line('TAX', $key, $key, date('Y-m-d'), $value[0], 0, 1, $value[1]);
1127 // Besides copays, do not collect any other information from ar_activity,
1128 // since this is for appt checkout.
1130 if ($inv_encounter) {
1131 $erow = sqlQuery("SELECT provider_id FROM form_encounter WHERE " .
1132 "pid = ? AND encounter = ? " .
1133 "ORDER BY id DESC LIMIT 1", array($patient_id,$inv_encounter) );
1134 $inv_provider = $erow['provider_id'] +
0;
1140 <table border
='0' cellspacing
='4'>
1144 <?php
echo $GLOBALS['discount_by_money'] ?
xlt('Discount Amount') : xlt('Discount Percentage'); ?
>:
1147 <input type
='text' name
='form_discount' size
='6' maxlength
='8' value
=''
1148 style
='text-align:right' onkeyup
='computeTotals()'>
1154 <?php
echo xlt('Payment Method'); ?
>:
1157 <select name
='form_method'>
1159 $query1112 = "SELECT * FROM list_options where list_id=? ORDER BY seq, title ";
1160 $bres1112 = sqlStatement($query1112,array('payment_method'));
1161 while ($brow1112 = sqlFetchArray($bres1112))
1163 if($brow1112['option_id']=='electronic' ||
$brow1112['option_id']=='bank_draft')
1165 echo "<option value='".attr($brow1112['option_id'])."'>".text(xl_list_label($brow1112['title']))."</option>";
1174 <?php
echo xlt('Check/Reference Number'); ?
>:
1177 <input type
='text' name
='form_source' size
='10' value
=''>
1183 <?php
echo xlt('Amount Paid'); ?
>:
1186 <input type
='text' name
='form_amount' size
='10' value
='0.00'>
1192 <?php
echo xlt('Posting Date'); ?
>:
1195 <input type
='text' size
='10' name
='form_date' id
='form_date'
1196 value
='<?php echo attr($inv_date) ?>'
1197 title
='yyyy-mm-dd date of service'
1198 onkeyup
='datekeyup(this,mypcc)' onblur
='dateblur(this,mypcc)' />
1199 <img src
='../pic/show_calendar.gif' align
='absbottom' width
='24' height
='22'
1200 id
='img_date' border
='0' alt
='[?]' style
='cursor:pointer'
1201 title
='<?php echo xla("Click here to choose a date"); ?>'>
1206 // If this user has a non-empty irnpool assigned, show the pending
1207 // invoice reference number.
1208 $irnumber = getInvoiceRefNumber();
1209 if (!empty($irnumber)) {
1213 <?php
echo xlt('Tentative Invoice Ref No'); ?
>:
1216 <?php
echo text($irnumber); ?
>
1221 // Otherwise if there is an invoice reference number mask, ask for the refno.
1222 else if (!empty($GLOBALS['gbl_mask_invoice_number'])) {
1226 <?php
echo xlt('Invoice Reference Number'); ?
>:
1229 <input type
='text' name
='form_irnumber' size
='10' value
=''
1230 onkeyup
='maskkeyup(this,"<?php echo addslashes($GLOBALS['gbl_mask_invoice_number
']); ?>")'
1231 onblur
='maskblur(this,"<?php echo addslashes($GLOBALS['gbl_mask_invoice_number
']); ?>")'
1240 <td colspan
='2' align
='center'>
1242 <input type
='submit' name
='form_save' value
='<?php echo xla('Save
'); ?>' />  
;
1243 <?php
if (empty($_GET['framed'])) { ?
>
1244 <input type
='button' value
='<?php echo xla('Cancel
'); ?>' onclick
='window.close()' />
1246 <input type
='hidden' name
='form_provider' value
='<?php echo attr($inv_provider) ?>' />
1247 <input type
='hidden' name
='form_payer' value
='<?php echo attr($inv_payer) ?>' />
1248 <input type
='hidden' name
='form_encounter' value
='<?php echo attr($inv_encounter) ?>' />
1257 <script language
='JavaScript'>
1258 Calendar
.setup({inputField
:"form_date", ifFormat
:"%Y-%m-%d", button
:"img_date"});
1261 // The following is removed, perhaps temporarily, because gcac reporting
1262 // no longer depends on gcac issues. -- Rod 2009-08-11
1263 /*********************************************************************
1264 // Custom code for IPPF. Try to make sure that a GCAC issue is linked to this
1265 // visit if it contains GCAC-related services.
1266 if ($gcac_related_visit) {
1267 $grow = sqlQuery("SELECT l.id, l.title, l.begdate, ie.pid " .
1268 "FROM lists AS l " .
1269 "LEFT JOIN issue_encounter AS ie ON ie.pid = l.pid AND " .
1270 "ie.encounter = '$inv_encounter' AND ie.list_id = l.id " .
1271 "WHERE l.pid = '$pid' AND " .
1272 "l.activity = 1 AND l.type = 'ippf_gcac' " .
1273 "ORDER BY ie.pid DESC, l.begdate DESC LIMIT 1");
1274 // Note that reverse-ordering by ie.pid is a trick for sorting
1275 // issues linked to the encounter (non-null values) first.
1276 if (empty($grow['pid'])) { // if there is no linked GCAC issue
1277 if (!empty($grow)) { // there is one that is not linked
1278 echo " if (confirm('" . xl('OK to link the GCAC issue dated') . " " .
1279 $grow['begdate'] . " " . xl('to this visit?') . "')) {\n";
1280 echo " $.getScript('link_issue_to_encounter.php?issue=" . $grow['id'] .
1281 "&thisenc=$inv_encounter');\n";
1284 echo " if (confirm('" . xl('Are you prepared to complete a new GCAC issue for this visit?') . "')) {\n";
1285 echo " dlgopen('summary/add_edit_issue.php?thisenc=$inv_encounter" .
1286 "&thistype=ippf_gcac', '_blank', 700, 600);\n";
1288 echo " $.getScript('link_issue_to_encounter.php?thisenc=$inv_encounter');\n";
1291 } // end if ($gcac_related_visit)
1292 *********************************************************************/
1294 if ($gcac_related_visit && !$gcac_service_provided) {
1295 // Skip this warning if the GCAC visit form is not allowed.
1296 $grow = sqlQuery("SELECT COUNT(*) AS count FROM list_options " .
1297 "WHERE list_id = 'lbfnames' AND option_id = 'LBFgcac'");
1298 if (!empty($grow['count'])) { // if gcac is used
1299 // Skip this warning if referral or abortion in TS.
1300 $grow = sqlQuery("SELECT COUNT(*) AS count FROM transactions " .
1301 "WHERE title = 'Referral' AND refer_date IS NOT NULL AND " .
1302 "refer_date = ? AND pid = ?", array($inv_date,$patient_id) );
1303 if (empty($grow['count'])) { // if there is no referral
1304 $grow = sqlQuery("SELECT COUNT(*) AS count FROM forms " .
1305 "WHERE pid = ? AND encounter = ? AND " .
1306 "deleted = 0 AND formdir = 'LBFgcac'", array($patient_id,$inv_encounter) );
1307 if (empty($grow['count'])) { // if there is no gcac form
1308 echo " alert('" . addslashes(xl('This visit will need a GCAC form, referral or procedure service.')) . "');\n";
1312 } // end if ($gcac_related_visit)