Merge branch 'master' of https://github.com/openemr/openemr into signer-templates
[openemr.git] / portal / portal_payment.php
blob0821b80fe1e3bacd412566d96d37b378b818a91c
1 <?php
2 /**
4 * namespace OnsitePortal
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Jerry Padgett <sjpadgett@gmail.com>
10 * @author Brady Miller <brady.g.miller@gmail.com>
11 * @copyright Copyright (c) 2006-2015 Rod Roark <rod@sunsetsystems.com>
12 * @copyright Copyright (c) 2016-2019 Jerry Padgett <sjpadgett@gmail.com>
13 * @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
17 // Will start the (patient) portal OpenEMR session/cookie.
18 require_once(dirname(__FILE__) . "/../src/Common/Session/SessionUtil.php");
19 OpenEMR\Common\Session\SessionUtil::portalSessionStart();
21 $isPortal = false;
22 if (isset($_SESSION['pid']) && isset($_SESSION['patient_portal_onsite_two'])) {
23 $pid = $_SESSION['pid'];
24 $ignoreAuth = true;
25 $isPortal = true;
26 require_once(dirname(__FILE__) . "/../interface/globals.php");
27 } else {
28 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
29 $ignoreAuth = false;
30 require_once(dirname(__FILE__) . "/../interface/globals.php");
31 if (!isset($_SESSION['authUserID'])) {
32 $landingpage = "index.php";
33 header('Location: ' . $landingpage);
34 exit();
38 require_once(dirname(__FILE__) . "/lib/appsql.class.php");
39 require_once("$srcdir/acl.inc");
40 require_once("$srcdir/patient.inc");
41 require_once("$srcdir/payment.inc.php");
42 require_once("$srcdir/forms.inc");
43 require_once("$srcdir/invoice_summary.inc.php");
44 require_once("../custom/code_types.inc.php");
45 require_once("$srcdir/options.inc.php");
46 require_once("$srcdir/encounter_events.inc.php");
48 use OpenEMR\Billing\BillingUtilities;
49 use OpenEMR\Common\Crypto\CryptoGen;
51 $cryptoGen = new CryptoGen();
53 $appsql = new ApplicationTable();
54 $pid = isset($_REQUEST['pid']) ? $_REQUEST['pid'] : $pid;
55 $pid = $_REQUEST['hidden_patient_code'] > 0 ? $_REQUEST['hidden_patient_code'] : $pid;
56 $recid = isset($_REQUEST['recid']) ? (int) $_REQUEST['recid'] : 0;
57 $adminUser = '';
58 $portalPatient = '';
60 $query = "SELECT pao.portal_username as recip_id, Concat_Ws(' ', patient_data.fname, patient_data.lname) as username FROM patient_data " .
61 "LEFT JOIN patient_access_onsite pao ON pao.pid = patient_data.pid " .
62 "WHERE patient_data.pid = ? AND pao.portal_pwd_status = 1";
63 $portalPatient = sqlQueryNoLog($query, $pid);
64 if ($_SESSION['authUserID']) {
65 $query = "SELECT users.username as recip_id, users.authorized as dash, CONCAT(users.fname,' ',users.lname) as username " .
66 "FROM users WHERE id = ?";
67 $adminUser = sqlQueryNoLog($query, $_SESSION['authUserID']);
70 if ($recid) {
71 $edata = $appsql->getPortalAuditRec($recid);
72 } else {
73 $edata = $appsql->getPortalAudit($pid, 'review', 'payment');
75 $ccdata = array();
76 $invdata = array();
77 if ($edata) {
78 $ccdata = json_decode($cryptoGen->decryptStandard($edata['checksum']), true);
79 $invdata = json_decode($edata['table_args'], true);
80 echo "<script type='text/javascript'>var jsondata='" . $edata['table_args'] . "';var ccdata='" . $edata['checksum'] . "'</script>";
83 function bucks($amount)
85 if ($amount) {
86 $amount = oeFormatMoney($amount);
87 return $amount;
90 return '';
93 function rawbucks($amount)
95 if ($amount) {
96 $amount = sprintf("%.2f", $amount);
97 return $amount;
100 return '';
103 // Display a row of data for an encounter.
105 $var_index = 0;
106 $sum_charges = $sum_ptpaid = $sum_inspaid = $sum_duept = $sum_copay = $sum_patcopay = $sum_balance = 0;
107 function echoLine($iname, $date, $charges, $ptpaid, $inspaid, $duept, $encounter = 0, $copay = 0, $patcopay = 0)
109 global $sum_charges, $sum_ptpaid, $sum_inspaid, $sum_duept, $sum_copay, $sum_patcopay, $sum_balance;
110 global $var_index;
111 $var_index++;
112 $balance = bucks($charges - $ptpaid - $inspaid);
113 $balance = (round($duept, 2) != 0) ? 0 : $balance; // if balance is due from patient, then insurance balance is displayed as zero
114 $encounter = $encounter ? $encounter : '';
115 echo " <tr id='tr_" . attr($var_index) . "' >\n";
116 echo " <td class='detail'>" . text(oeFormatShortDate($date)) . "</td>\n";
117 echo " <td class='detail' id='" . attr($date) . "' align='left'>" . text($encounter) . "</td>\n";
118 echo " <td class='detail' align='center' id='td_charges_$var_index' >" . text(bucks($charges)) . "</td>\n";
119 echo " <td class='detail' align='center' id='td_inspaid_$var_index' >" . text(bucks($inspaid * -1)) . "</td>\n";
120 echo " <td class='detail' align='center' id='td_ptpaid_$var_index' >" . text(bucks($ptpaid * -1)) . "</td>\n";
121 echo " <td class='detail' align='center' id='td_patient_copay_$var_index' >" . text(bucks($patcopay)) . "</td>\n";
122 echo " <td class='detail' align='center' id='td_copay_$var_index' >" . text(bucks($copay)) . "</td>\n";
123 echo " <td class='detail' align='center' id='balance_$var_index'>" . text(bucks($balance)) . "</td>\n";
124 echo " <td class='detail' align='center' id='duept_$var_index'>" . text(bucks(round($duept, 2) * 1)) . "</td>\n";
125 echo " <td class='detail' align='center'><input class='form-control' name='" . attr($iname) . "' id='paying_" . attr($var_index) .
126 "' " . " value='" . '' . "' onchange='coloring();calctotal()' autocomplete='off' " . "onkeyup='calctotal()'/></td>\n";
127 echo " </tr>\n";
129 $sum_charges += $charges * 1;
130 $sum_ptpaid += $ptpaid * -1;
131 $sum_inspaid += $inspaid * -1;
132 $sum_duept += $duept * 1;
133 $sum_patcopay += $patcopay * 1;
134 $sum_copay += $copay * 1;
135 $sum_balance += $balance * 1;
138 // We use this to put dashes, colons, etc. back into a timestamp.
140 function decorateString($fmt, $str)
142 $res = '';
143 while ($fmt) {
144 $fc = substr($fmt, 0, 1);
145 $fmt = substr($fmt, 1);
146 if ($fc == '.') {
147 $res .= substr($str, 0, 1);
148 $str = substr($str, 1);
149 } else {
150 $res .= $fc;
154 return $res;
157 // Compute taxes from a tax rate string and a possibly taxable amount.
159 function calcTaxes($row, $amount)
161 $total = 0;
162 if (empty($row['taxrates'])) {
163 return $total;
166 $arates = explode(':', $row['taxrates']);
167 if (empty($arates)) {
168 return $total;
171 foreach ($arates as $value) {
172 if (empty($value)) {
173 continue;
176 $trow = sqlQuery("SELECT option_value FROM list_options WHERE " . "list_id = 'taxrate' AND option_id = ? LIMIT 1", array($value
178 if (empty($trow['option_value'])) {
179 echo "<!-- Missing tax rate '" . text($value) . "'! -->\n";
180 continue;
183 $tax = sprintf("%01.2f", $amount * $trow['option_value']);
184 // echo "<!-- Rate = '$value', amount = '$amount', tax = '$tax' -->\n";
185 $total += $tax;
188 return $total;
191 $now = time();
192 $today = date('Y-m-d', $now);
193 $timestamp = date('Y-m-d H:i:s', $now);
195 $patdata = sqlQuery("SELECT " . "p.fname, p.mname, p.lname, p.postal_code, p.pubpid,p.pid, i.copay " . "FROM patient_data AS p " . "LEFT OUTER JOIN insurance_data AS i ON " . "i.pid = p.pid AND i.type = 'primary' " . "WHERE p.pid = ? ORDER BY i.date DESC LIMIT 1", array($pid
198 $alertmsg = ''; // anything here pops up in an alert box
200 // If the Save button was clicked...
201 if ($_POST['form_save']) {
202 $form_pid = $_POST['form_pid'];
203 $form_method = trim($_POST['form_method']);
204 $form_source = trim($_POST['form_source']);
205 $patdata = getPatientData($form_pid, 'fname,mname,lname,pubpid');
206 $NameNew = $patdata['fname'] . " " . $patdata['lname'] . " " . $patdata['mname'];
208 if ($_REQUEST['radio_type_of_payment'] == 'pre_payment') {
209 $payment_id = sqlInsert(
210 "insert into ar_session set " .
211 "payer_id = ?" .
212 ", patient_id = ?" .
213 ", user_id = ?" .
214 ", closed = ?" .
215 ", reference = ?" .
216 ", check_date = now() , deposit_date = now() " .
217 ", pay_total = ?" .
218 ", payment_type = 'patient'" .
219 ", description = ?" .
220 ", adjustment_code = 'pre_payment'" .
221 ", post_to_date = now() " .
222 ", payment_method = ?",
223 array(0, $form_pid, $_SESSION['authUserID'], 0, $form_source, $_REQUEST['form_prepayment'], $NameNew, $form_method)
226 frontPayment($form_pid, 0, $form_method, $form_source, $_REQUEST['form_prepayment'], 0, $timestamp);//insertion to 'payments' table.
229 if ($_POST['form_upay'] && $_REQUEST['radio_type_of_payment'] != 'pre_payment') {
230 foreach ($_POST['form_upay'] as $enc => $payment) {
231 if ($amount = 0 + $payment) {
232 $zero_enc = $enc;
234 //----------------------------------------------------------------------------------------------------
235 //Fetching the existing code and modifier
236 $ResultSearchNew = sqlStatement(
237 "SELECT * FROM billing LEFT JOIN code_types ON billing.code_type=code_types.ct_key ".
238 "WHERE code_types.ct_fee=1 AND billing.activity!=0 AND billing.pid =? AND encounter=? ORDER BY billing.code,billing.modifier",
239 array($form_pid, $enc)
241 if ($RowSearch = sqlFetchArray($ResultSearchNew)) {
242 $Codetype = $RowSearch['code_type'];
243 $Code = $RowSearch['code'];
244 $Modifier = $RowSearch['modifier'];
245 } else {
246 $Codetype = '';
247 $Code = '';
248 $Modifier = '';
251 //----------------------------------------------------------------------------------------------------
252 if ($_REQUEST['radio_type_of_payment'] == 'copay') {//copay saving to ar_session and ar_activity tables
253 $session_id = sqlInsert(
254 "INSERT INTO ar_session (payer_id,user_id,reference,check_date,deposit_date,pay_total," .
255 " global_amount,payment_type,description,patient_id,payment_method,adjustment_code,post_to_date) " .
256 " VALUES ('0',?,?,now(),now(),?,'','patient','COPAY',?,?,'patient_payment',now())",
257 array($_SESSION['authId'], $form_source, $amount, $form_pid, $form_method)
260 sqlBeginTrans();
261 $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc));
262 $insrt_id=sqlInsert(
263 "INSERT INTO ar_activity (pid,encounter,sequence_no,code_type,code,modifier,payer_type,post_time,post_user,session_id,pay_amount,account_code)".
264 " VALUES (?,?,?,?,?,?,0,now(),?,?,?,'PCP')",
265 array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, $_SESSION['authId'], $session_id, $amount)
267 sqlCommitTrans();
269 frontPayment($form_pid, $enc, $form_method, $form_source, $amount, 0, $timestamp);//insertion to 'payments' table.
272 if ($_REQUEST['radio_type_of_payment'] == 'invoice_balance' || $_REQUEST['radio_type_of_payment'] == 'cash') { //Payment by patient after insurance paid, cash patients similar to do not bill insurance in feesheet.
273 if ($_REQUEST['radio_type_of_payment'] == 'cash') {
274 sqlStatement(
275 "update form_encounter set last_level_closed=? where encounter=? and pid=? ",
276 array(4, $enc, $form_pid)
278 sqlStatement(
279 "update billing set billed=? where encounter=? and pid=?",
280 array(1, $enc, $form_pid)
284 $adjustment_code = 'patient_payment';
285 $payment_id = sqlInsert(
286 "insert into ar_session set " .
287 "payer_id = ?" .
288 ", patient_id = ?" .
289 ", user_id = ?" .
290 ", closed = ?" .
291 ", reference = ?" .
292 ", check_date = now() , deposit_date = now() " .
293 ", pay_total = ?" .
294 ", payment_type = 'patient'" .
295 ", description = ?" .
296 ", adjustment_code = ?" .
297 ", post_to_date = now() " .
298 ", payment_method = ?",
299 array(0, $form_pid, $_SESSION['authUserID'], 0, $form_source, $amount, $NameNew, $adjustment_code, $form_method)
302 //--------------------------------------------------------------------------------------------------------------------
304 frontPayment($form_pid, $enc, $form_method, $form_source, 0, $amount, $timestamp);//insertion to 'payments' table.
306 //--------------------------------------------------------------------------------------------------------------------
308 $resMoneyGot = sqlStatement(
309 "SELECT sum(pay_amount) as PatientPay FROM ar_activity where pid =? and " .
310 "encounter =? and payer_type=0 and account_code='PCP'",
311 array($form_pid, $enc)
312 );//new fees screen copay gives account_code='PCP'
313 $rowMoneyGot = sqlFetchArray($resMoneyGot);
314 $Copay = $rowMoneyGot['PatientPay'];
316 //--------------------------------------------------------------------------------------------------------------------
318 //Looping the existing code and modifier
319 $ResultSearchNew = sqlStatement(
320 "SELECT * FROM billing LEFT JOIN code_types ON billing.code_type=code_types.ct_key WHERE code_types.ct_fee=1 " .
321 "AND billing.activity!=0 AND billing.pid =? AND encounter=? ORDER BY billing.code,billing.modifier",
322 array($form_pid, $enc)
324 while ($RowSearch = sqlFetchArray($ResultSearchNew)) {
325 $Codetype = $RowSearch['code_type'];
326 $Code = $RowSearch['code'];
327 $Modifier = $RowSearch['modifier'];
328 $Fee = $RowSearch['fee'];
330 $resMoneyGot = sqlStatement(
331 "SELECT sum(pay_amount) as MoneyGot FROM ar_activity where pid =? " .
332 "and code_type=? and code=? and modifier=? and encounter =? and !(payer_type=0 and account_code='PCP')",
333 array($form_pid, $Codetype, $Code, $Modifier, $enc)
335 //new fees screen copay gives account_code='PCP'
336 $rowMoneyGot = sqlFetchArray($resMoneyGot);
337 $MoneyGot = $rowMoneyGot['MoneyGot'];
339 $resMoneyAdjusted = sqlStatement(
340 "SELECT sum(adj_amount) as MoneyAdjusted FROM ar_activity where " .
341 "pid =? and code_type=? and code=? and modifier=? and encounter =?",
342 array($form_pid, $Codetype, $Code, $Modifier, $enc)
344 $rowMoneyAdjusted = sqlFetchArray($resMoneyAdjusted);
345 $MoneyAdjusted = $rowMoneyAdjusted['MoneyAdjusted'];
347 $Remainder = $Fee - $Copay - $MoneyGot - $MoneyAdjusted;
348 $Copay = 0;
349 if (round($Remainder, 2) != 0 && $amount != 0) {
350 if ($amount - $Remainder >= 0) {
351 $insert_value = $Remainder;
352 $amount = $amount - $Remainder;
353 } else {
354 $insert_value = $amount;
355 $amount = 0;
358 sqlBeginTrans();
359 $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc));
360 sqlStatement(
361 "insert into ar_activity set " .
362 "pid = ?" .
363 ", encounter = ?" .
364 ", sequence_no = ?" .
365 ", code_type = ?" .
366 ", code = ?" .
367 ", modifier = ?" .
368 ", payer_type = ?" .
369 ", post_time = now() " .
370 ", post_user = ?" .
371 ", session_id = ?" .
372 ", pay_amount = ?" .
373 ", adj_amount = ?" .
374 ", account_code = 'PP'",
375 array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, 0, $_SESSION['authUserID'], $payment_id, $insert_value, 0)
377 sqlCommitTrans();
378 }//if
379 }//while
380 if ($amount!=0) {//if any excess is there.
381 sqlBeginTrans();
382 $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc));
383 sqlStatement(
384 "insert into ar_activity set " .
385 "pid = ?" .
386 ", encounter = ?" .
387 ", sequence_no = ?" .
388 ", code_type = ?" .
389 ", code = ?" .
390 ", modifier = ?" .
391 ", payer_type = ?" .
392 ", post_time = now() " .
393 ", post_user = ?" .
394 ", session_id = ?" .
395 ", pay_amount = ?" .
396 ", adj_amount = ?" .
397 ", account_code = 'PP'",
398 array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, 0, $_SESSION['authUserID'], $payment_id, $amount, 0)
400 sqlCommitTrans();
403 //--------------------------------------------------------------------------------------------------------------------
404 }//invoice_balance
405 }//if ($amount = 0 + $payment)
406 }//foreach
407 }//if ($_POST['form_upay'])
408 }//if ($_POST['form_save'])
410 if ($_POST['form_save'] || $_REQUEST['receipt']) {
411 if ($_REQUEST['receipt']) {
412 $form_pid = $_GET['patient'];
413 $timestamp = decorateString('....-..-.. ..:..:..', $_GET['time']);
416 // Get details for what we guess is the primary facility.
417 $frow = sqlQuery("SELECT * FROM facility " . "ORDER BY billing_location DESC, accepts_assignment DESC, id LIMIT 1");
419 // Get the patient's name and chart number.
420 $patdata = getPatientData($form_pid, 'fname,mname,lname,pubpid');
422 // Re-fetch payment info.
423 $payrow = sqlQuery("SELECT " . "SUM(amount1) AS amount1, " . "SUM(amount2) AS amount2, " . "MAX(method) AS method, " . "MAX(source) AS source, " . "MAX(dtime) AS dtime, " .
424 // "MAX(user) AS user " .
425 "MAX(user) AS user, " . "MAX(encounter) as encounter " . "FROM payments WHERE " . "pid = ? AND dtime = ?", array($form_pid, $timestamp
428 // Create key for deleting, just in case.
429 $ref_id = ($_REQUEST['radio_type_of_payment'] == 'copay') ? $session_id : $payment_id;
430 $payment_key = $form_pid . '.' . preg_replace('/[^0-9]/', '', $timestamp) . '.' . $ref_id;
432 // get facility from encounter
433 $tmprow = sqlQuery("SELECT facility_id FROM form_encounter WHERE encounter = ?", array($payrow['encounter']));
434 $frow = sqlQuery("SELECT * FROM facility " . " WHERE id = ?", array($tmprow['facility_id']
437 // Now proceed with printing the receipt.
440 <title><?php echo xlt('Receipt for Payment'); ?></title>
441 <script type="text/javascript" src="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery/dist/jquery.min.js"></script>
442 <script>
444 function goHome() {
445 window.location.replace("./patient/onsiteactivityviews");
448 function notifyPatient() {
449 let pid = <?php echo js_escape($pid); ?>;
450 let note = $('#pop_receipt').html();
451 let formURL = './messaging/handle_note.php';
452 let owner = <?php echo js_escape($adminUser['recip_id']); ?>;
453 let sn = <?php echo js_escape($adminUser['username']); ?>;
454 let rid = <?php echo js_escape($portalPatient['recip_id']); ?>;
455 let rn = <?php echo js_escape($portalPatient['username']); ?>;
456 $.ajax({
457 url: formURL,
458 type: "POST",
459 data: {
460 'task': 'add',
461 'owner': owner,
462 'pid': pid,
463 'inputBody': note,
464 'title': 'Bill/Collect',
465 'recipient_name': rn,
466 'recipient_id': rid,
467 'sender_id': owner,
468 'sender_name': sn
470 success: function (data, textStatus, jqXHR) {
471 alert('Receipt sent to patient via Messages.')
473 error: function (jqXHR, status, error) {
474 console.log(status + ": " + error);
478 </script>
479 <?php
480 ob_start();
481 echo '<htlm><head></head><body style="text-align: center; margin: auto;">';
483 <div id='pop_receipt' style='display: block'>
485 <h2><?php echo xlt('Receipt for Payment'); ?></h2>
486 <p><?php echo text($frow['name']) ?>
487 <br><?php echo text($frow['street']) ?>
488 <br><?php echo text($frow['city'] . ', ' . $frow['state']) . ' ' . text($frow['postal_code']) ?>
489 <br><?php echo text($frow['phone']) ?>
491 <div style="text-align: center; margin: auto;">
492 <table border='0' cellspacing='8'
493 style="text-align: center; margin: auto;">
494 <tr>
495 <td><?php echo xlt('Date'); ?>:</td>
496 <td><?php echo text(oeFormatSDFT(strtotime($payrow['dtime']))) ?></td>
497 </tr>
498 <tr>
499 <td><?php echo xlt('Patient'); ?>:</td>
500 <td><?php echo text($patdata['fname']) . " " . text($patdata['mname']) . " " . text($patdata['lname']) . " (" . text($patdata['pubpid']) . ")" ?></td>
501 </tr>
502 <tr>
503 <td><?php echo xlt('Paid Via'); ?>:</td>
504 <td><?php echo generate_display_field(array('data_type' => '1', 'list_id' => 'payment_method'), $payrow['method']); ?></td>
505 </tr>
506 <tr>
507 <td><?php echo xlt('Authorized Id'); ?>:</td>
508 <td><?php echo text($payrow['source']) ?></td>
509 </tr>
510 <tr>
511 <td><?php echo xlt('Amount for This Visit'); ?>:</td>
512 <td><?php echo text(oeFormatMoney($payrow['amount1'])) ?></td>
513 </tr>
514 <tr>
515 <td><?php echo xlt('Amount for Past Balance'); ?>:</td>
516 <td><?php echo text(oeFormatMoney($payrow['amount2'])) ?></td>
517 </tr>
518 <tr>
519 <td><?php echo xlt('Received By'); ?>:</td>
520 <td><?php echo text($payrow['user']) ?></td>
521 </tr>
522 </table>
523 </div>
524 </div>
525 <button class='btn btn-sm' type='button' onclick='goHome()' id='returnhome'><?php echo xla('Return Home'); ?></button>
526 <button class='btn btn-sm' type='button' onclick="notifyPatient()"><?php echo xla('Notify Patient'); ?></button>
527 </body></html>
528 <?php
529 ob_end_flush();
530 } else {
532 // Here we display the form for data entry.
535 <title><?php echo xlt('Record Payment'); ?></title>
536 <style type="text/css">
537 .dehead {
538 color: #000000;
539 font-weight: bold
541 .detail {
542 padding: 1px 1px;
543 color: #000000;
544 font-weight: normal
546 </style>
547 <script type="text/javascript" src="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery-creditcardvalidator/jquery.creditCardValidator.js"></script>
548 <script type="text/javascript" src="<?php echo $GLOBALS['webroot'] ?>/library/textformat.js?v=<?php echo $v_js_includes; ?>"></script>
549 <script type="text/javascript">
550 var chargeMsg = <?php $amsg = xl('Payment was successfully authorized and your card is charged.') . "\n" .
551 xl("You will be notified when your payment is applied for this invoice.") . "\n" .
552 xl('Until then you will continue to see payment details here.') . "\n" . xl('Thank You.');
553 echo json_encode($amsg);
555 var publicKey = <?php echo json_encode($cryptoGen->decryptStandard($GLOBALS['gateway_public_key'])); ?>;
556 var apiKey = <?php echo json_encode($cryptoGen->decryptStandard($GLOBALS['gateway_api_key'])); ?>;
558 function calctotal() {
559 var flag = 0;
560 var f = document.forms["invoiceForm"];
561 var total = 0;
562 for (var i = 0; i < f.elements.length; ++i) {
563 var elem = f.elements[i];
564 var ename = elem.name;
565 if (ename.indexOf('form_upay[') == 0 || ename.indexOf('form_bpay[') == 0) {
566 if (elem.value.length > 0) {
567 total += Number(elem.value);
568 if (total < 0) flag = 1;
572 f.form_paytotal.value = Number(total).toFixed(2);
573 if (flag) {
574 $('#invoiceForm')[0].reset();
575 alert(<?php echo xlj('Negative payments not accepted'); ?>)
577 return true;
580 function coloring() {
581 for (var i = 1; ; ++i) {
582 if (document.getElementById('paying_' + i)) {
583 paying = document.getElementById('paying_' + i).value * 1;
584 patient_balance = document.getElementById('duept_' + i).innerHTML * 1;
585 if (patient_balance > 0 && paying > 0) {
586 if (paying > patient_balance) {
587 document.getElementById('paying_' + i).style.background = '#FF0000';
589 else if (paying < patient_balance) {
590 document.getElementById('paying_' + i).style.background = '#99CC00';
592 else if (paying == patient_balance) {
593 document.getElementById('paying_' + i).style.background = '#ffffff';
596 else {
597 document.getElementById('paying_' + i).style.background = '#ffffff';
600 else {
601 break;
606 function CheckVisible(MakeBlank) {//Displays and hides the check number text box.
607 if (document.getElementById('form_method').options[document.getElementById('form_method').selectedIndex].value == 'check_payment' ||
608 document.getElementById('form_method').options[document.getElementById('form_method').selectedIndex].value == 'bank_draft') {
609 document.getElementById('check_number').disabled = false;
611 else {
612 document.getElementById('check_number').disabled = true;
616 function validate() {
617 var f = document.forms["invoiceForm"];
618 ok = -1;
619 //no checks taken here....
620 issue = 'no';
621 if (document.getElementById('radio_type_of_payment_self1').checked == false &&
622 document.getElementById('radio_type_of_payment1').checked == false
623 && document.getElementById('radio_type_of_payment2').checked == false
624 && document.getElementById('radio_type_of_payment4').checked == false) {
625 alert("<?php //echo addslashes( xl('Please Select Type Of Payment.')) ?>");
626 return false;
628 if (document.getElementById('radio_type_of_payment_self1').checked == true || document.getElementById('radio_type_of_payment1').checked == true) {
629 for (var i = 0; i < f.elements.length; ++i) {
630 var elem = f.elements[i];
631 var ename = elem.name;
632 if (ename.indexOf('form_upay[0') == 0) //Today is this text box.
634 if (elem.value * 1 > 0) {//A warning message, if the amount is posted with out encounter.
635 if (confirm(<?php echo xlj('Are you sure to post for today?'); ?>)) {
636 ok = 1;
638 else {
639 elem.focus();
640 return false;
643 break;
647 else if (document.getElementsByName('form_paytotal')[0].value <= 0)//total 0
649 alert(<?php echo xlj('Invalid Total!'); ?>)
650 return false;
652 if (ok == -1) {
653 if (confirm(<?php echo xlj('Payment Validated: Save?'); ?>)) {
654 return true;
656 else {
657 return false;
662 function cursor_pointer() {//Point the cursor to the latest encounter(Today)
663 var f = document.forms["invoiceForm"];
664 var total = 0;
665 for (var i = 0; i < f.elements.length; ++i) {
666 var elem = f.elements[i];
667 var ename = elem.name;
668 if (ename.indexOf('form_upay[') == 0) {
669 elem.focus();
670 break;
675 function make_it_hide_enc_pay() {
676 document.getElementById('td_head_insurance_payment').style.display = "none";
677 document.getElementById('td_head_patient_co_pay').style.display = "none";
678 document.getElementById('td_head_co_pay').style.display = "none";
679 document.getElementById('td_head_insurance_balance').style.display = "none";
680 for (var i = 1; ; ++i) {
681 var td_inspaid_elem = document.getElementById('td_inspaid_' + i)
682 var td_patient_copay_elem = document.getElementById('td_patient_copay_' + i)
683 var td_copay_elem = document.getElementById('td_copay_' + i)
684 var balance_elem = document.getElementById('balance_' + i)
685 if (td_inspaid_elem) {
686 td_inspaid_elem.style.display = "none";
687 td_patient_copay_elem.style.display = "none";
688 td_copay_elem.style.display = "none";
689 balance_elem.style.display = "none";
691 else {
692 break;
695 document.getElementById('td_total_4').style.display = "none";
696 document.getElementById('td_total_7').style.display = "none";
697 document.getElementById('td_total_8').style.display = "none";
698 document.getElementById('td_total_6').style.display = "none";
700 document.getElementById('table_display').width = "420px";
703 function make_visible() {
704 document.getElementById('td_head_rep_doc').style.display = "";
705 document.getElementById('td_head_description').style.display = "";
706 document.getElementById('td_head_total_charge').style.display = "none";
707 document.getElementById('td_head_insurance_payment').style.display = "none";
708 document.getElementById('td_head_patient_payment').style.display = "none";
709 document.getElementById('td_head_patient_co_pay').style.display = "none";
710 document.getElementById('td_head_co_pay').style.display = "none";
711 document.getElementById('td_head_insurance_balance').style.display = "none";
712 document.getElementById('td_head_patient_balance').style.display = "none";
713 for (var i = 1; ; ++i) {
714 var td_charges_elem = document.getElementById('td_charges_' + i)
715 var td_inspaid_elem = document.getElementById('td_inspaid_' + i)
716 var td_ptpaid_elem = document.getElementById('td_ptpaid_' + i)
717 var td_patient_copay_elem = document.getElementById('td_patient_copay_' + i)
718 var td_copay_elem = document.getElementById('td_copay_' + i)
719 var balance_elem = document.getElementById('balance_' + i)
720 var duept_elem = document.getElementById('duept_' + i)
721 if (td_charges_elem) {
722 td_charges_elem.style.display = "none";
723 td_inspaid_elem.style.display = "none";
724 td_ptpaid_elem.style.display = "none";
725 td_patient_copay_elem.style.display = "none";
726 td_copay_elem.style.display = "none";
727 balance_elem.style.display = "none";
728 duept_elem.style.display = "none";
730 else {
731 break;
734 document.getElementById('td_total_7').style.display = "";
735 document.getElementById('td_total_8').style.display = "";
736 document.getElementById('td_total_1').style.display = "none";
737 document.getElementById('td_total_2').style.display = "none";
738 document.getElementById('td_total_3').style.display = "none";
739 document.getElementById('td_total_4').style.display = "none";
740 document.getElementById('td_total_5').style.display = "none";
741 document.getElementById('td_total_6').style.display = "none";
743 document.getElementById('table_display').width = "505px";
746 function make_it_hide() {
747 document.getElementById('td_head_rep_doc').style.display = "none";
748 document.getElementById('td_head_description').style.display = "none";
749 document.getElementById('td_head_total_charge').style.display = "";
750 document.getElementById('td_head_insurance_payment').style.display = "";
751 document.getElementById('td_head_patient_payment').style.display = "";
752 document.getElementById('td_head_patient_co_pay').style.display = "";
753 document.getElementById('td_head_co_pay').style.display = "";
754 document.getElementById('td_head_insurance_balance').style.display = "";
755 document.getElementById('td_head_patient_balance').style.display = "";
756 for (var i = 1; ; ++i) {
757 var td_charges_elem = document.getElementById('td_charges_' + i)
758 var td_inspaid_elem = document.getElementById('td_inspaid_' + i)
759 var td_ptpaid_elem = document.getElementById('td_ptpaid_' + i)
760 var td_patient_copay_elem = document.getElementById('td_patient_copay_' + i)
761 var td_copay_elem = document.getElementById('td_copay_' + i)
762 var balance_elem = document.getElementById('balance_' + i)
763 var duept_elem = document.getElementById('duept_' + i)
764 if (td_charges_elem) {
765 td_charges_elem.style.display = "";
766 td_inspaid_elem.style.display = "";
767 td_ptpaid_elem.style.display = "";
768 td_patient_copay_elem.style.display = "";
769 td_copay_elem.style.display = "";
770 balance_elem.style.display = "";
771 duept_elem.style.display = "";
773 else {
774 break;
777 document.getElementById('td_total_1').style.display = "";
778 document.getElementById('td_total_2').style.display = "";
779 document.getElementById('td_total_3').style.display = "";
780 document.getElementById('td_total_4').style.display = "";
781 document.getElementById('td_total_5').style.display = "";
782 document.getElementById('td_total_6').style.display = "";
783 document.getElementById('td_total_7').style.display = "";
784 document.getElementById('td_total_8').style.display = "";
786 document.getElementById('table_display').width = "100%";
789 function make_visible_radio() {
790 document.getElementById('tr_radio1').style.display = "";
791 document.getElementById('tr_radio2').style.display = "none";
794 function make_hide_radio() {
795 document.getElementById('tr_radio1').style.display = "none";
796 document.getElementById('tr_radio2').style.display = "";
799 function make_visible_row() {
800 document.getElementById('table_display').style.display = "";
801 document.getElementById('table_display_prepayment').style.display = "none";
804 function make_hide_row() {
805 document.getElementById('table_display').style.display = "none";
806 document.getElementById('table_display_prepayment').style.display = "";
809 function make_self() {
810 make_visible_row();
811 make_it_hide();
812 make_it_hide_enc_pay();
813 document.getElementById('radio_type_of_payment_self1').checked = true;
814 cursor_pointer();
817 function make_insurance() {
818 make_visible_row();
819 make_it_hide();
820 cursor_pointer();
821 document.getElementById('radio_type_of_payment1').checked = true;
824 $('#paySubmit').click(function (e) {
825 e.preventDefault();e.stopPropagation();
826 $("#mode").val("portal-save");
827 let inv_values = JSON.stringify(getFormObj('invoiceForm'));
828 let extra_values = JSON.stringify(getFormObj('paymentForm'));
829 let extra = "&inv_values=" + encodeURIComponent(inv_values) + "&extra_values=" + encodeURIComponent(extra_values);
830 let flag = 0
831 let liburl = './lib/paylib.php';
832 $.ajax({
833 type: "POST",
834 url: liburl,
835 data: $("#invoiceForm").serialize() + extra,
836 beforeSend: function (xhr) {
837 if (validateCC() !== true) return false;
838 if ($('#cardCode').val() == "" || $('#cardHolderName').val() == "" || $('#expYear').val() == "" || $('#expMonth').val() == "") {
839 alert(<?php echo xlj('Invalid Credit Card Values: Please correct'); ?>)
840 return false;
842 if (validate() != true) {
843 flag = 1;
844 alert(<?php echo xlj('Validation error: Fix and resubmit. This popup info is preserved!'); ?>)
845 return false;
847 $("#openPayModal .close").click()
849 error: function (qXHR, textStatus, errorThrow) {
850 console.log("There was an error:" + errorThrow);
852 success: function (templateHtml, textStatus, jqXHR) {
853 let msg = <?php $amsg = xl('Payment successfully sent for review and posting to your account.') . "\n" .
854 xl("You will be notified when the payment transaction is confirmed.") . "\n" .
855 xl('Until then you will continue to see payment details here.') . "\n" . xl('Thank You.');
856 echo json_encode($amsg); // backward compatable 5.0.1
858 alert(msg);
859 window.location.reload(false);
862 if (flag) {
863 $("#openPayModal .close").click();
867 $('#openPayModal').on('show.bs.modal', function () {
868 let total = $("#form_paytotal").val();
869 if(Number(total) < 1) {
870 let error = <?php echo json_encode("Please enter a payment amount"); ?>;
871 alert(error);
872 return false;
874 $("#payTotal").text(total);
875 $("#paymentAmount").val(total);
878 $("#invoiceForm").on('submit', function (e) {
879 e.preventDefault();
880 let thisform = this;
881 $("#mode").val("review-save");
882 let inv_values = JSON.stringify(getFormObj('invoiceForm'));
883 let extra_values = JSON.stringify(getFormObj('paymentForm'));
884 let extra = "&inv_values=" + inv_values + "&extra_values=" + extra_values;
886 let flag = 0
887 let liburl = '<?php echo $GLOBALS["webroot"] ?>/portal/lib/paylib.php';
888 $.ajax({
889 type: "POST",
890 url: liburl,
891 data: $("#invoiceForm").serialize() + extra,
892 beforeSend: function (xhr) {
893 if (validate() != true) {
894 flag = 1;
895 alert(<?php echo xlj('Validation error: Fix and resubmit.'); ?>)
896 return false;
899 error: function (xhr, textStatus, error) {
900 alert(<?php echo xlj('There is a Post error'); ?>)
901 console.log("There was an error:" + textStatus);
902 return false;
904 success: function (templateHtml, textStatus, jqXHR) {
905 thisform.submit();
910 function getFormObj(formId) {
911 let formObj = {};
912 let inputs = $('#' + formId).serializeArray();
913 $.each(inputs, function (i, input) {
914 formObj[input.name] = input.value;
916 return formObj;
919 function formRepopulate(jsondata) {
920 let data = $.parseJSON(jsondata);
921 $.each(data, function (name, val) {
922 let $el = $('[name="' + name + '"]'),
923 type = $el.attr('type');
924 switch (type) {
925 case 'checkbox':
926 $el.prop('checked', true);
927 break;
928 case 'radio':
929 $el.filter('[value="' + val + '"]').prop('checked', true);
930 break;
931 default:
932 $el.val(val);
937 function getAuth() {
938 let authnum = document.getElementById("check_number").value;
939 authnum = prompt(<?php echo xlj('Please enter card comfirmation authorization'); ?>, authnum);
940 if (authnum != null) {
941 document.getElementById("check_number").value = authnum;
944 </script>
946 <body class="skin-blue" onunload='imclosing()' onLoad="cursor_pointer();"
947 style="text-align: center; margin: auto;">
949 <form id="invoiceForm" method='post' action='<?php echo $GLOBALS["webroot"] ?>/portal/portal_payment.php'>
950 <input type='hidden' name='form_pid' value='<?php echo attr($pid) ?>'/>
951 <input type='hidden' name='form_save' value='<?php echo xla('Invoice'); ?>'/>
952 <table>
953 <tr height="10">
954 <td colspan="3">&nbsp;</td>
955 </tr>
956 <tr>
957 <td colspan='3' align='center' class='text'>
958 <b><?php echo xlt('Accept Payment for'); ?>&nbsp;:&nbsp;&nbsp;<?php
959 echo text($patdata['fname']) . " " .
960 text($patdata['lname']) . " " .
961 text($patdata['mname']) . " (" .
962 text($patdata['pid']) . ")" ?></b>
963 <?php $NameNew = $patdata['fname'] . " " . $patdata['lname'] . " " . $patdata['mname']; ?>
964 </td>
965 </tr>
966 <tr height="15">
967 <td colspan='3'></td>
968 </tr>
969 <tr>
970 <td class='text'>
971 <?php echo xlt('Payment Method'); ?>:
972 </td>
973 <td colspan='2'><select name="form_method" id="form_method" class="form-control" onChange='CheckVisible("yes")'>
974 <?php
975 $query1112 = "SELECT * FROM list_options where list_id=? ORDER BY seq, title ";
976 $bres1112 = sqlStatement($query1112, array('payment_method'));
977 while ($brow1112 = sqlFetchArray($bres1112)) {
978 if ($brow1112['option_id'] != 'credit_card' || $brow1112['option_id'] == 'debit' || $brow1112['option_id'] == 'bank_draft') {
979 continue;
981 echo "<option value='" . attr($brow1112['option_id']) . "'>" .
982 text(xl_list_label($brow1112['title'])) . "</option>";
985 </select></td>
986 </tr>
987 <?php if (isset($_SESSION['authUserID'])) { ?>
988 <tr height="5">
989 <td colspan='3'></td>
990 </tr>
991 <tr>
992 <td class='text'>
993 <?php echo xlt('Authorized'); ?>:
994 </td>
995 <td colspan='2'>
996 <?php if ($ccdata['authCode'] && empty($payrow['source'])) {
997 $payrow['source'] = $ccdata['authCode'] . " : " .$ccdata['transId'];
1000 <input class="form-control input-sm" id='check_number' name='form_source' style='' value='<?php echo attr($payrow['source']) ?>'>
1001 </td>
1002 </tr>
1003 <?php } ?>
1004 <?php if (isset($_SESSION['authUserID'])) {
1005 $hide = '';
1006 echo '<tr height="5"><td colspan="3"></td></tr><tr">';
1007 } else {
1008 $hide = 'hidden';
1009 echo '<tr class="hidden">';
1012 <td class='text' valign="middle">
1013 <?php echo xlt('Patient Coverage'); ?>:
1014 </td>
1015 <td class='text' colspan="2">
1016 <input type="radio" name="radio_type_of_coverage" id="radio_type_of_coverage1"
1017 value="self" onClick="make_visible_radio();make_self();"/>
1018 <?php echo xlt('Self'); ?>
1019 <input type="radio" name="radio_type_of_coverage" id="radio_type_of_coverag2" value="insurance"
1020 checked="checked"
1021 onClick="make_hide_radio();make_insurance();"/>
1022 <?php echo xlt('Insurance'); ?>
1023 </td>
1024 </tr>
1025 <tr height="5">
1026 <td colspan='3'></td>
1027 </tr>
1028 <tr id="tr_radio1" style="display: none">
1029 <!-- For radio Insurance -->
1030 <td class='text' valign="top">
1031 <?php echo xlt('Payment against'); ?>:
1032 </td>
1033 <td class='text' colspan="2">
1034 <input type="radio" name="radio_type_of_payment" id="radio_type_of_payment_self1"
1035 value="cash" onClick="make_visible_row();make_it_hide_enc_pay();cursor_pointer();"/>
1036 <?php echo xlt('Encounter Payment'); ?>
1037 </td>
1038 </tr>
1039 <tr id="tr_radio2">
1040 <!-- For radio self -->
1041 <td class='text' valign="top"><?php echo xlt('Payment against'); ?>:</td>
1042 <td class='text' colspan="2">
1043 <input type="radio" name="radio_type_of_payment" id="radio_type_of_payment1" class="<?php echo $hide ? $hide : ''; ?>"
1044 value="copay" onClick="make_visible_row();cursor_pointer();"/><?php echo !$hide ? xlt('Co Pay') : ''; ?>
1045 <input type="radio" name="radio_type_of_payment" id="radio_type_of_payment2" checked="checked"
1046 value="invoice_balance" onClick="make_visible_row();"/><?php echo xlt('Invoice Balance'); ?>
1047 <input type="radio" name="radio_type_of_payment" id="radio_type_of_payment4" value="pre_payment"
1048 onClick="make_hide_row();"/><?php echo xlt('Pre Pay'); ?>
1049 </td>
1050 </tr>
1051 <tr height="15">
1052 <td colspan='3'></td>
1053 </tr>
1054 </table>
1055 <table width="20%" border="0" cellspacing="0" cellpadding="0" id="table_display_prepayment" style="margin-bottom: 10px; display: none">
1056 <tr>
1057 <td class='detail'><?php echo xlt('Pre Payment'); ?></td>
1058 <td><input class="form-control" type='text' name='form_prepayment' style=''/></td>
1059 </tr>
1060 </table>
1061 <table id="table_display" style="width: 100%; background: #eee;" class="table table-condensed table-striped table-bordered">
1062 <thead>
1063 </thead>
1064 <tbody>
1065 <tr bgcolor="#cccccc" id="tr_head">
1066 <td class="dehead" width="60">
1067 <?php echo xlt('DOS') ?>
1068 </td>
1069 <td class="dehead" width="120">
1070 <?php echo xlt('Visit Reason') ?>
1071 </td>
1072 <td class="dehead" align="center" width="70" id="td_head_total_charge">
1073 <?php echo xlt('Total Charge') ?>
1074 </td>
1075 <td class="dehead" align="center" width="70" id="td_head_rep_doc" style='display: none'>
1076 <?php echo xlt('Report/ Form') ?>
1077 </td>
1078 <td class="dehead" align="center" width="200" id="td_head_description" style='display: none'>
1079 <?php echo xlt('Description') ?>
1080 </td>
1081 <td class="dehead" align="center" width="70" id="td_head_insurance_payment">
1082 <?php echo xlt('Insurance Payment') ?>
1083 </td>
1084 <td class="dehead" align="center" width="70" id="td_head_patient_payment">
1085 <?php echo xlt('Patient Payment') ?>
1086 </td>
1087 <td class="dehead" align="center" width="55" id="td_head_patient_co_pay">
1088 <?php echo xlt('Co Pay Paid') ?>
1089 </td>
1090 <td class="dehead" align="center" width="55" id="td_head_co_pay">
1091 <?php echo xlt('Required Co Pay') ?>
1092 </td>
1093 <td class="dehead" align="center" width="70" id="td_head_insurance_balance">
1094 <?php echo xlt('Insurance Balance') ?>
1095 </td>
1096 <td class="dehead" align="center" width="70" id="td_head_patient_balance">
1097 <?php echo xlt('Patient Balance') ?>
1098 </td>
1099 <td class="dehead" align="center" width="50">
1100 <?php echo xlt('Paying') ?>
1101 </td>
1102 </tr>
1103 <?php
1104 $encs = array();
1105 // Get the unbilled service charges and payments by encounter for this patient.
1107 $query = "SELECT fe.encounter, fe.reason, b.code_type, b.code, b.modifier, b.fee, " .
1108 "LEFT(fe.date, 10) AS encdate ,fe.last_level_closed " . "FROM form_encounter AS fe left join billing AS b on " .
1109 "b.pid = ? AND b.activity = 1 AND " . "b.code_type != 'TAX' AND b.fee != 0 " . "AND fe.pid = b.pid AND fe.encounter = b.encounter " .
1110 "where fe.pid = ? " . "ORDER BY b.encounter";
1111 $bres = sqlStatement($query, array($pid, $pid));
1113 while ($brow = sqlFetchArray($bres)) {
1114 $key = 0 + $brow['encounter'];
1115 if (empty($encs[$key])) {
1116 $encs[$key] = array('encounter' => $brow['encounter'], 'date' => $brow['encdate'], 'last_level_closed' => $brow['last_level_closed'], 'charges' => 0, 'payments' => 0, 'reason' => $brow['reason']
1120 if ($brow['code_type'] === 'COPAY') {
1121 // $encs[$key]['payments'] -= $brow['fee'];
1122 } else {
1123 $encs[$key]['charges'] += $brow['fee'];
1124 // Add taxes.
1125 $sql_array = array();
1126 $query = "SELECT taxrates FROM codes WHERE " . "code_type = ? AND " . "code = ? AND ";
1127 array_push($sql_array, $code_types[$brow['code_type']]['id'], $brow['code']);
1128 if ($brow['modifier']) {
1129 $query .= "modifier = ?";
1130 array_push($sql_array, $brow['modifier']);
1131 } else {
1132 $query .= "(modifier IS NULL OR modifier = '')";
1135 $query .= " LIMIT 1";
1136 $trow = sqlQuery($query, $sql_array);
1137 $encs[$key]['charges'] += calcTaxes($trow, $brow['fee']);
1141 // Do the same for unbilled product sales.
1143 $query = "SELECT fe.encounter, fe.reason, s.drug_id, s.fee, " .
1144 "LEFT(fe.date, 10) AS encdate,fe.last_level_closed " .
1145 "FROM form_encounter AS fe left join drug_sales AS s " .
1146 "on s.pid = ? AND s.fee != 0 " .
1147 "AND fe.pid = s.pid AND fe.encounter = s.encounter " .
1148 "where fe.pid = ? " . "ORDER BY s.encounter";
1150 $dres = sqlStatement($query, array($pid, $pid));
1152 while ($drow = sqlFetchArray($dres)) {
1153 $key = 0 + $drow['encounter'];
1154 if (empty($encs[$key])) {
1155 $encs[$key] = array(
1156 'encounter' => $drow['encounter'], 'date' => $drow['encdate'],
1157 'last_level_closed' => $drow['last_level_closed'],
1158 'charges' => 0, 'payments' => 0
1162 $encs[$key]['charges'] += $drow['fee'];
1163 // Add taxes.
1164 $trow = sqlQuery(
1165 "SELECT taxrates FROM drug_templates WHERE drug_id = ? " .
1166 "ORDER BY selector LIMIT 1",
1167 array($drow['drug_id'])
1169 $encs[$key]['charges'] += calcTaxes($trow, $drow['fee']);
1172 ksort($encs, SORT_NUMERIC);
1174 foreach ($encs as $key => $value) {
1175 $enc = $value['encounter'];
1176 $reason = $value['reason'];
1177 $dispdate = $value['date'];
1179 $inscopay = BillingUtilities::getCopay($pid, $dispdate);
1180 $patcopay = BillingUtilities::getPatientCopay($pid, $enc);
1181 // Insurance Payment
1183 $drow = sqlQuery("SELECT SUM(pay_amount) AS payments, " . "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " . "pid = ? and encounter = ? and " . "payer_type != 0 and account_code!='PCP' ", array($pid, $enc
1185 $dpayment = $drow['payments'];
1186 $dadjustment = $drow['adjustments'];
1187 // Patient Payment
1189 $drow = sqlQuery(
1190 "SELECT SUM(pay_amount) AS payments, " . "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " . "pid = ? and encounter = ? and " . "payer_type = 0 and account_code!='PCP' ",
1191 array($pid, $enc)
1193 $dpayment_pat = $drow['payments'];
1195 // NumberOfInsurance
1197 $ResultNumberOfInsurance = sqlStatement(
1198 "SELECT COUNT( DISTINCT TYPE ) NumberOfInsurance FROM insurance_data where pid = ? and provider>0 ",
1199 array($pid)
1201 $RowNumberOfInsurance = sqlFetchArray($ResultNumberOfInsurance);
1202 $NumberOfInsurance = $RowNumberOfInsurance['NumberOfInsurance'] * 1;
1203 $duept = 0;
1204 if ((($NumberOfInsurance == 0 || $value['last_level_closed'] == 4 || $NumberOfInsurance == $value['last_level_closed']))) { // Patient balance
1205 $brow = sqlQuery("SELECT SUM(fee) AS amount FROM billing WHERE " . "pid = ? and encounter = ? AND activity = 1", array($pid, $enc
1207 $srow = sqlQuery("SELECT SUM(fee) AS amount FROM drug_sales WHERE " . "pid = ? and encounter = ? ", array($pid, $enc
1209 $drow = sqlQuery("SELECT SUM(pay_amount) AS payments, " . "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " . "pid = ? and encounter = ? ", array($pid, $enc
1211 $duept = $brow['amount'] + $srow['amount'] - $drow['payments'] - $drow['adjustments'];
1214 echoLine("form_upay[$enc]", $dispdate, $value['charges'], $dpayment_pat, ($dpayment + $dadjustment), $duept, ($enc . ': ' . $reason), $inscopay, $patcopay);
1217 // Continue with display of the data entry form.
1219 <tr>
1220 <td class="dehead" align="center"><?php echo xlt('Total'); ?></td>
1221 <td class="dehead" id='td_total_1' align="center"></td>
1222 <td class="dehead" id='td_total_2' align="center"><?php echo text(bucks($sum_charges)) ?></td>
1223 <td class="dehead" id='td_total_3' align="center"><?php echo text(bucks($sum_inspaid)) ?></td>
1224 <td class="dehead" id='td_total_4' align="center"><?php echo text(bucks($sum_ptpaid)) ?></td>
1225 <td class="dehead" id='td_total_5' align="center"><?php echo text(bucks($sum_patcopay)) ?></td>
1226 <td class="dehead" id='td_total_6' align="center"><?php echo text(bucks($sum_copay)) ?></td>
1227 <td class="dehead" id='td_total_7' align="center"><?php echo text(bucks($sum_balance)) ?></td>
1228 <td class="dehead" id='td_total_8' align="center"><?php echo text(bucks($sum_duept)) ?></td>
1229 <td class="dehead" align="center">
1230 <input class="form-control" name='form_paytotal' id='form_paytotal' value='' style='color:#3b9204;' readonly/>
1231 </td>
1232 </tr>
1233 </table>
1234 <?php
1235 if (isset($ccdata["cardHolderName"])) {
1236 echo '<div class="col-xs-5"><div class="panel panel-default height">';
1237 if (!isset($_SESSION['authUserID'])) {
1238 echo '<div class="panel-heading">' . xlt("Payment Information") .
1239 '<span style="color:#cc0000"><em> ' . xlt("Pending Auth since") . ': </em>' . text($edata["date"]) . '</span></div>';
1240 } else {
1241 echo '<div class="panel-heading">' . xlt("Audit Payment") .
1242 '<span style="color:#cc0000"><em> ' . xlt("Pending since") . ': </em>' . text($edata["date"]) . '</span>' .
1243 ' <button type="button" class="btn btn-warning btn-sm" onclick="getAuth()">' . xlt("Authorize") . '</button></div>';
1245 } else {
1246 echo '<div style="display:none" class="col-xs-6"><div class="panel panel-default height">' .
1247 '<div class="panel-heading">' . xlt("Payment Information") . ' </div>';
1250 <div class="panel-body">
1251 <strong><?php echo xlt('Card Name'); ?>: </strong><span id="cn"><?php echo text($ccdata["cc_type"]) ?></span><br>
1252 <strong><?php echo xlt('Name on Card'); ?>: </strong><span id="nc"><?php echo text($ccdata["cardHolderName"]) ?></span>
1253 <strong><?php echo xlt('Card Holder Zip'); ?>: </strong><span id="czip"><?php echo text($ccdata["zip"]) ?></span><br>
1254 <strong><?php echo xlt('Card Number'); ?>: </strong><span id="ccn">
1255 <?php
1256 if (isset($_SESSION['authUserID']) || isset($ccdata["transId"])) {
1257 echo text($ccdata["cardNumber"]) . "</span><br>";
1258 } else {
1259 echo "********** " . text(substr($ccdata["cardNumber"], -4)) . "</span><br>";
1262 <?php
1263 if (!isset($ccdata["transId"])) { ?>
1264 <strong><?php echo xlt('Exp Date'); ?>: </strong><span id="ed"><?php echo text($ccdata["month"]) . "/" . text($ccdata["year"]) ?></span>
1265 <strong><?php echo xlt('CVV'); ?>: </strong><span id="cvvpin"><?php echo text($ccdata["cardCode"]) ?></span><br>
1266 <?php } else { ?>
1267 <strong><?php echo xlt('Transaction Id'); ?>: </strong><span id="ed"><?php echo text($ccdata["transId"]) . "/" . text($ccdata["year"]) ?></span>
1268 <strong><?php echo xlt('Authorization'); ?>: </strong><span id="cvvpin"><?php echo text($ccdata["authCode"]) ?></span><br>
1269 <?php } ?>
1270 <strong><?php echo xlt('Charge Total'); ?>: </strong><span id="ct"><?php echo text($invdata["form_paytotal"]) ?></span><br>
1271 </div>
1272 </div>
1273 </div>
1274 <div>
1275 <?php
1276 if (!isset($_SESSION['authUserID'])) {
1277 if (!isset($ccdata["cardHolderName"])) {
1278 echo '<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#openPayModal">' . xlt("Pay Invoice") . '</button>';
1279 } else {
1280 echo '<h4><span class="bg-danger">' . xlt("Locked Payment Pending") . '</span></h4>';
1282 } else {
1283 echo "<button type='submit' class='btn btn-success' form='invoiceForm'>" . xlt('Post Payment') . "</button>";
1286 </div>
1287 <input type="hidden" name="hidden_patient_code" id="hidden_patient_code" value="<?php echo attr($pid); ?>"/>
1288 <input type='hidden' name='mode' id='mode' value=''/>
1289 </form>
1291 <script>
1292 if (typeof jsondata !== 'undefined') {
1293 formRepopulate(jsondata);
1295 calctotal();
1296 </script>
1297 <!-- credit payment modal -->
1298 <div id="openPayModal" class="modal fade" role="dialog">
1299 <div class="modal-dialog">
1300 <div class="modal-content">
1301 <div class="modal-header">
1302 <h4><?php echo xlt('Submit Payment for Authorization'); ?></h4>
1303 <!--<button type="button" class="close" data-dismiss="modal">&times;</button>-->
1304 </div>
1305 <div class="modal-body">
1306 <?php if ($GLOBALS['payment_gateway'] != 'Stripe') { ?>
1307 <form id='paymentForm' method='post' action='<?php echo $GLOBALS["webroot"] ?>/portal/lib/paylib.php'>
1308 <fieldset>
1309 <div class="form-group">
1310 <label label-default="label-default"
1311 class="control-label"><?php echo xlt('Name on Card'); ?></label>
1312 <div class="controls">
1313 <input name="cardHolderName" id="cardHolderName" type="text" class="form-control"
1314 pattern="\w+ \w+.*"
1315 title="<?php echo xla('Fill your first and last name'); ?>"
1316 value="<?php echo attr($patdata['fname']) . ' ' . attr($patdata['lname']) ?>"/>
1317 </div>
1318 </div>
1319 <div class="form-group">
1320 <label class="control-label"><?php echo xlt('Card Number'); ?></label>
1321 <div class="controls">
1322 <div class="row">
1323 <div class="col-sm-12">
1324 <input name="cardNumber" id="cardNumber" type="text"
1325 class="form-control inline col-sm-4"
1326 autocomplete="off" maxlength="19" pattern="\d"
1327 onchange="validateCC()"
1328 title="<?php echo xla('Card Number'); ?>" value=""/>&nbsp;&nbsp;
1329 <h4 name="cardtype" id="cardtype" style="display: inline-block; color:#cc0000;"><?php echo xlt('Validating') ?></h4>
1330 </div>
1331 </div>
1332 </div>
1333 </div>
1334 <div class="form-group">
1335 <label label-default="label-default"
1336 class="control-label"><?php echo xlt('Card Expiry Date and Card Holders Zip'); ?></label>
1337 <div class="controls">
1338 <div class="row">
1339 <div class="col-md-4">
1340 <select name="month" id="expMonth" class="form-control">
1341 <option value=""><?php echo xlt('Select Month'); ?></option>
1342 <option value="01"><?php echo xlt('January'); ?></option>
1343 <option value="02"><?php echo xlt('February'); ?></option>
1344 <option value="03"><?php echo xlt('March'); ?></option>
1345 <option value="04"><?php echo xlt('April'); ?></option>
1346 <option value="05"><?php echo xlt('May'); ?></option>
1347 <option value="06"><?php echo xlt('June'); ?></option>
1348 <option value="07"><?php echo xlt('July'); ?></option>
1349 <option value="08"><?php echo xlt('August'); ?></option>
1350 <option value="09"><?php echo xlt('September'); ?></option>
1351 <option value="10"><?php echo xlt('October'); ?></option>
1352 <option value="11"><?php echo xlt('November'); ?></option>
1353 <option value="12"><?php echo xlt('December'); ?></option>
1354 </select>
1355 </div>
1356 <div class="col-md-4">
1357 <select name="year" id="expYear" class="form-control">
1358 <option value=""><?php echo xlt('Select Year'); ?></option>
1359 <option value="2019">2019</option>
1360 <option value="2020">2020</option>
1361 <option value="2021">2021</option>
1362 <option value="2022">2022</option>
1363 <option value="2023">2023</option>
1364 <option value="2024">2024</option>
1365 <option value="2025">2025</option>
1366 <option value="2026">2026</option>
1367 <option value="2027">2027</option>
1368 <option value="2028">2028</option>
1369 </select>
1370 </div>
1371 <div class="col-md-4">
1372 <input name="zip" id="cczip" type="text" class="form-control"
1373 pattern="\d"
1374 title="<?php echo xla('Enter Your Zip'); ?>"
1375 placeholder="<?php echo xla('Card Holder Zip'); ?>"
1376 value="<?php echo attr($patdata['postal_code']) ?>"/>
1377 </div>
1378 </div>
1379 </div>
1380 </div>
1381 <div class="form-group">
1382 <label label-default="label-default" class="control-label"><?php echo xlt('Card CVV'); ?></label>
1383 <div class="controls">
1384 <div class="row">
1385 <div class="col-md-3">
1386 <input name="cardCode" id="cardCode" type="text" class="form-control"
1387 autocomplete="off" maxlength="4" onfocus="validateCC()"
1388 title="<?php echo xla('Three or four digits at back of your card'); ?>"
1389 value=""/>
1390 </div>
1391 <div class="col-md-3">
1392 <img src='./images/img_cvc.png' style='height: 40px; width: auto'>
1393 </div>
1394 <div class="col-md-6">
1395 <h4 style="display: inline-block;"><?php echo xlt('Payment Amount'); ?>:&nbsp;
1396 <strong><span id="payTotal"></span></strong></h4>
1397 </div>
1398 </div>
1399 </div>
1400 </div>
1401 <input type='hidden' name='pid' id='pid' value='<?php echo attr($pid) ?>'/>
1402 <input type='hidden' name='mode' id='mode' value=''/>
1403 <input type='hidden' name='cc_type' id='cc_type' value=''/>
1404 <input type='hidden' name='payment' id='paymentAmount' value=''/>
1405 <input type='hidden' name='invValues' id='invValues' value=''/>
1406 <input type="hidden" name="dataValue" id="dataValue" />
1407 <input type="hidden" name="dataDescriptor" id="dataDescriptor" />
1408 </fieldset>
1409 </form>
1410 <?php } else { ?>
1411 <form method="post" name="payment-form" id="payment-form">
1412 <fieldset>
1413 <div class="form-group">
1414 <label label-default="label-default"
1415 class="control-label"><?php echo xlt('Name on Card'); ?></label>
1416 <div class="controls">
1417 <input name="cardHolderName" id="cardHolderName" type="text"
1418 class="form-control"
1419 pattern="\w+ \w+.*"
1420 title="<?php echo xla('Fill your first and last name'); ?>"
1421 value="<?php echo attr($patdata['fname']) . ' ' . attr($patdata['lname']) ?>"/>
1422 </div>
1423 </div>
1424 <div class="form-row form-group">
1425 <label for="card-element"><?php echo xlt('Credit or Debit Card') ?></label>
1426 <div id="card-element"></div>
1427 <div id="card-errors" role="alert"></div>
1428 </div>
1429 <div class="col-md-6">
1430 <h4 style="display: inline-block;"><?php echo xlt('Payment Amount'); ?>:&nbsp;
1431 <strong><span id="payTotal"></span></strong></h4>
1432 </div>
1433 <input type='hidden' name='mode' id='mode' value=''/>
1434 <input type='hidden' name='cc_type' id='cc_type' value=''/>
1435 <input type='hidden' name='payment' id='paymentAmount' value=''/>
1436 <input type='hidden' name='invValues' id='invValues' value=''/>
1437 </fieldset>
1438 </form>
1439 <?php } ?>
1440 </div>
1441 <!-- Body -->
1442 <div class="modal-footer">
1443 <div class="button-group">
1444 <button type="button" class="btn btn-default" data-dismiss="modal"><?php echo xlt('Cancel'); ?></button>
1445 <?php
1446 if ($GLOBALS['payment_gateway'] == 'InHouse') { ?>
1447 <button id="paySubmit" class="btn btn-primary"><?php echo xlt('Send Payment'); ?></button>
1448 <?php } else if ($GLOBALS['payment_gateway'] == 'AuthorizeNet') { ?>
1449 <button id="payAurhorizeNet" class="btn btn-primary"
1450 onclick="sendPaymentDataToAnet(event)"><?php echo xlt('Pay Now'); ?></button>
1451 <?php }
1452 if ($GLOBALS['payment_gateway'] == 'Stripe') { ?>
1453 <button id="stripeSubmit" class="btn btn-primary"><?php echo xlt('Pay Now'); ?></button>
1454 <?php } ?>
1455 </div>
1456 </div>
1457 </div>
1458 </div>
1459 </div>
1460 <script type="text/javascript">
1461 var ccerr = <?php echo xlj('Invalid Credit Card Number'); ?>
1463 // In House CC number Validation
1464 $('#cardNumber').validateCreditCard(function (result) {
1465 var r = (result.card_type === null ? '' : result.card_type.name.toUpperCase())
1466 var v = (result.valid === true ? ' Valid Number' : ' Validating')
1467 if (result.valid === true) {
1468 document.getElementById("cardtype").style.color = "#00aa00";
1469 } else {
1470 document.getElementById("cardtype").style.color = "#aa0000";
1472 $('#cardtype').text(r + v);
1475 // In House CC Validation
1476 function validateCC() {
1477 var result = $('#cardNumber').validateCreditCard();
1478 var r = (result.card_type == null ? '' : result.card_type.name.toUpperCase())
1479 var v = (result.valid == true ? ' Valid Card Number' : ' Invalid Card Number')
1480 if (result.valid === true) {
1481 document.getElementById("cardtype").style.color = "#00aa00";
1482 } else {
1483 document.getElementById("cardtype").style.color = "#aa0000";
1485 $('#cardtype').text(r + v);
1486 $('#cc_type').val(r);
1487 if (!result.valid) {
1488 alert(ccerr);
1489 return false;
1491 else {
1492 return true;
1495 </script>
1497 <?php if ($GLOBALS['payment_gateway'] == 'AuthorizeNet') {
1498 // Include Authorize.Net dependency to tokenize card.
1499 // Will return a token to use for payment request keeping
1500 // credit info off the server.
1502 <script type="text/javascript">
1503 function sendPaymentDataToAnet(e) {
1504 e.preventDefault();
1505 const authData = {};
1506 authData.clientKey = publicKey;
1507 authData.apiLoginID = apiKey;
1509 const cardData = {};
1510 cardData.cardNumber = document.getElementById("cardNumber").value;
1511 cardData.month = document.getElementById("expMonth").value;
1512 cardData.year = document.getElementById("expYear").value;
1513 cardData.cardCode = document.getElementById("cardCode").value;
1514 cardData.fullName = document.getElementById("cardHolderName").value;
1515 cardData.zip = document.getElementById("cczip").value;
1517 const secureData = {};
1518 secureData.authData = authData;
1519 secureData.cardData = cardData;
1521 Accept.dispatchData(secureData, acceptResponseHandler);
1523 function acceptResponseHandler(response) {
1524 if (response.messages.resultCode === "Error") {
1525 let i = 0;
1526 let errorMsg = '';
1527 while (i < response.messages.message.length) {
1528 errorMsg = errorMsg + response.messages.message[i].code + ": " +response.messages.message[i].text;
1529 console.log(errorMsg);
1530 i = i + 1;
1532 alert(errorMsg);
1533 } else {
1534 paymentFormUpdate(response.opaqueData);
1539 function paymentFormUpdate(opaqueData) {
1540 // this is card tokenized
1541 document.getElementById("dataDescriptor").value = opaqueData.dataDescriptor;
1542 document.getElementById("dataValue").value = opaqueData.dataValue;
1543 let oForm = document.forms['paymentForm'];
1544 oForm.elements['mode'].value = "AuthorizeNet";
1545 let inv_values = JSON.stringify(getFormObj('invoiceForm'));
1546 document.getElementById("invValues").value = inv_values;
1548 // empty out the fields before submitting to server.
1549 document.getElementById("cardNumber").value = "";
1550 document.getElementById("expMonth").value = "";
1551 document.getElementById("expYear").value = "";
1552 document.getElementById("cardCode").value = "";
1554 // Submit payment to server
1555 fetch('./lib/paylib.php', {
1556 method: 'POST',
1557 body: new FormData(oForm)
1558 }).then(function(response) {
1559 if (!response.ok) {
1560 throw Error(response.statusText);
1562 return response.text();
1563 }).then(function(data) {
1564 if(data !== 'ok') {
1565 alert(data);
1566 return;
1568 alert(chargeMsg);
1569 window.location.reload(false);
1570 }).catch(function(error) {
1571 alert(error)
1574 </script>
1575 <?php } // end authorize.net ?>
1577 <?php if ($GLOBALS['payment_gateway'] == 'Stripe') { // Begin Include Stripe ?>
1578 <script type="text/javascript">
1579 const stripe = Stripe(publicKey);
1580 const elements = stripe.elements();// Custom styling can be passed to options when creating an Element.
1581 const style = {
1582 base: {
1583 color: '#32325d',
1584 lineHeight: '18px',
1585 fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
1586 fontSmoothing: 'antialiased',
1587 fontSize: '16px',
1588 '::placeholder': {
1589 color: '#aaa8a8'
1592 invalid: {
1593 color: '#fa755a',
1594 iconColor: '#fa755a'
1598 // Create an instance of the card Element.
1599 const card = elements.create('card', {style: style});
1600 // Add an instance of the card Element into the `card-element` <div>.
1601 card.mount('#card-element');
1602 // Handle real-time validation errors from the card Element.
1603 card.addEventListener('change', function (event) {
1604 let displayError = document.getElementById('card-errors');
1605 if (event.error) {
1606 displayError.textContent = event.error.message;
1607 } else {
1608 displayError.textContent = '';
1611 // Handle form submission.
1612 let form = document.getElementById('stripeSubmit');
1613 form.addEventListener('click', function (event) {
1614 event.preventDefault();
1615 stripe.createToken(card).then(function (result) {
1616 if (result.error) {
1617 // Inform the user if there was an error.
1618 let errorElement = document.getElementById('card-errors');
1619 errorElement.textContent = result.error.message;
1620 } else {
1621 // Send the token to server.
1622 stripeTokenHandler(result.token);
1626 // Submit the form with the token ID.
1627 function stripeTokenHandler(token) {
1628 // Insert the token ID into the form so it gets submitted to the server
1629 let oForm = document.forms['payment-form'];
1630 oForm.elements['mode'].value = "Stripe";
1632 let inv_values = JSON.stringify(getFormObj('invoiceForm'));
1633 document.getElementById("invValues").value = inv_values;
1635 let hiddenInput = document.createElement('input');
1636 hiddenInput.setAttribute('type', 'hidden');
1637 hiddenInput.setAttribute('name', 'stripeToken');
1638 hiddenInput.setAttribute('value', token.id);
1639 oForm.appendChild(hiddenInput);
1641 // Submit payment to server
1642 fetch('./lib/paylib.php', {
1643 method: 'POST',
1644 body: new FormData(oForm)
1645 }).then(function(response) {
1646 if (!response.ok) {
1647 throw Error(response.statusText);
1649 return response.text();
1650 }).then(function(data) {
1651 if(data !== 'ok') {
1652 alert(data);
1653 return;
1655 alert(chargeMsg);
1656 window.location.reload(false);
1657 }).catch(function(error) {
1658 alert(error)
1661 </script>
1662 <?php } ?>
1664 </body>
1665 <?php } // end else display ?>