.inc files migration to .inc.php (#5897)
[openemr.git] / interface / patient_file / front_payment.php
blob58449ea657295b276921dfb0e1bdd3e3732bfd3f
1 <?php
3 /**
4 * Front payment gui.
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2006-2020 Rod Roark <rod@sunsetsystems.com>
11 * @copyright Copyright (c) 2017-2018 Brady Miller <brady.g.miller@gmail.com>
12 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 require_once("../globals.php");
16 require_once("$srcdir/patient.inc.php");
17 require_once("$srcdir/payment.inc.php");
18 require_once("$srcdir/forms.inc.php");
19 require_once("../../custom/code_types.inc.php");
20 require_once("$srcdir/options.inc.php");
21 require_once("$srcdir/encounter_events.inc.php");
23 use OpenEMR\Billing\BillingUtilities;
24 use OpenEMR\Common\Acl\AclMain;
25 use OpenEMR\Common\Csrf\CsrfUtils;
26 use OpenEMR\Common\Twig\TwigContainer;
27 use OpenEMR\Core\Header;
28 use OpenEMR\OeUI\OemrUI;
29 use OpenEMR\PaymentProcessing\Sphere\SpherePayment;
30 use OpenEMR\Services\FacilityService;
32 if (!empty($_REQUEST['receipt']) && empty($_POST['form_save'])) {
33 if (!AclMain::aclCheckCore('acct', 'bill') && !AclMain::aclCheckCore('acct', 'rep_a') && !AclMain::aclCheckCore('patients', 'rx')) {
34 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Receipt for Payment")]);
35 exit;
37 } else {
38 if (!AclMain::aclCheckCore('acct', 'bill', '', 'write')) {
39 if (!empty($_POST['form_save'])) {
40 $pageTitle = xl("Receipt for Payment");
41 } else {
42 $pageTitle = xl("Record Payment");
44 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => $pageTitle]);
45 exit;
49 $pid = (!empty($_REQUEST['hidden_patient_code']) && ($_REQUEST['hidden_patient_code'] > 0)) ? $_REQUEST['hidden_patient_code'] : $pid;
51 $facilityService = new FacilityService();
54 <!DOCTYPE html>
55 <html>
56 <head>
57 <?php Header::setupHeader(['opener']);?>
58 <?php if ($GLOBALS['payment_gateway'] == 'Stripe') { ?>
59 <script src="https://js.stripe.com/v3/"></script>
60 <?php } ?>
61 <?php if ($GLOBALS['payment_gateway'] == 'AuthorizeNet') {
62 // Must be loaded from their server
63 $script = "https://jstest.authorize.net/v1/Accept.js"; // test script
64 if ($GLOBALS['gateway_mode_production']) {
65 $script = "https://js.authorize.net/v1/Accept.js"; // Production script
66 } ?>
67 <script src=<?php echo $script; ?> charset="utf-8"></script>
68 <?php } ?>
69 <?php
70 // Format dollars for display.
72 function bucks($amount)
74 if ($amount) {
75 $amount = oeFormatMoney($amount);
76 return $amount;
78 return '';
81 function rawbucks($amount)
83 if ($amount) {
84 $amount = sprintf("%.2f", $amount);
85 return $amount;
87 return '';
90 // Display a row of data for an encounter.
92 $var_index = 0;
93 function echoLine($iname, $date, $charges, $ptpaid, $inspaid, $duept, $encounter = 0, $copay = 0, $patcopay = 0)
95 global $var_index;
96 $var_index++;
97 $balance = bucks($charges - $ptpaid - $inspaid);
98 $balance = (round($duept, 2) != 0) ? 0 : $balance;//if balance is due from patient, then insurance balance is displayed as zero
99 $encounter = $encounter ? $encounter : '';
100 echo " <tr id='tr_" . attr($var_index) . "' >\n";
101 echo " <td>" . text(oeFormatShortDate($date)) . "</td>\n";
102 echo " <td class='text-center' id='" . attr($date) . "'>" . text($encounter) . "</td>\n";
103 echo " <td class='text-center' id='td_charges_$var_index' >" . text(bucks($charges)) . "</td>\n";
104 echo " <td class='text-center' id='td_inspaid_$var_index' >" . text(bucks($inspaid * -1)) . "</td>\n";
105 echo " <td class='text-center' id='td_ptpaid_$var_index' >" . text(bucks($ptpaid * -1)) . "</td>\n";
106 echo " <td class='text-center' id='td_patient_copay_$var_index' >" . text(bucks($patcopay)) . "</td>\n";
107 echo " <td class='text-center' id='td_copay_$var_index' >" . text(bucks($copay)) . "</td>\n";
108 echo " <td class='text-center' id='balance_$var_index'>" . text(bucks($balance)) . "</td>\n";
109 echo " <td class='text-center' id='duept_$var_index'>" . text(bucks(round($duept, 2) * 1)) . "</td>\n";
110 echo " <td class='text-right'><input type='text' class='form-control' name='" . attr($iname) . "' id='paying_" . attr($var_index) . "' " .
111 " value='' onchange='coloring();calctotal()' autocomplete='off' " .
112 "onkeyup='calctotal()'/></td>\n";
113 echo " </tr>\n";
116 // We use this to put dashes, colons, etc. back into a timestamp.
118 function decorateString($fmt, $str)
120 $res = '';
121 while ($fmt) {
122 $fc = substr($fmt, 0, 1);
123 $fmt = substr($fmt, 1);
124 if ($fc == '.') {
125 $res .= substr($str, 0, 1);
126 $str = substr($str, 1);
127 } else {
128 $res .= $fc;
132 return $res;
135 // Compute taxes from a tax rate string and a possibly taxable amount.
137 function calcTaxes($row, $amount)
139 $total = 0;
140 if (empty($row['taxrates'])) {
141 return $total;
144 $arates = explode(':', $row['taxrates']);
145 if (empty($arates)) {
146 return $total;
149 foreach ($arates as $value) {
150 if (empty($value)) {
151 continue;
154 $trow = sqlQuery("SELECT option_value FROM list_options WHERE " .
155 "list_id = 'taxrate' AND option_id = ? AND activity = 1 LIMIT 1", array($value));
156 if (empty($trow['option_value'])) {
157 echo "<!-- Missing tax rate '" . text($value) . "'! -->\n";
158 continue;
161 $tax = sprintf("%01.2f", $amount * $trow['option_value']);
162 // echo "<!-- Rate = '$value', amount = '$amount', tax = '$tax' -->\n";
163 $total += $tax;
166 return $total;
169 $now = time();
170 $today = date('Y-m-d', $now);
171 $timestamp = date('Y-m-d H:i:s', $now);
173 $patdata = sqlQuery("SELECT " .
174 "p.fname, p.mname, p.lname, p.pubpid,p.pid, i.copay " .
175 "FROM patient_data AS p " .
176 "LEFT OUTER JOIN insurance_data AS i ON " .
177 "i.pid = p.pid AND i.type = 'primary' " .
178 "WHERE p.pid = ? ORDER BY i.date DESC LIMIT 1", array($pid));
180 $alertmsg = ''; // anything here pops up in an alert box
182 // If the Save button was clicked...
183 if (!empty($_POST['form_save'])) {
184 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
185 CsrfUtils::csrfNotVerified();
188 $form_pid = $_POST['form_pid'];
189 $form_method = trim($_POST['form_method']);
190 $form_source = trim($_POST['form_source']);
191 $patdata = getPatientData($form_pid, 'fname,mname,lname,pubpid');
192 $NameNew = $patdata['fname'] . " " . $patdata['lname'] . " " . $patdata['mname'];
194 if ($_REQUEST['radio_type_of_payment'] == 'pre_payment') {
195 $payment_id = sqlInsert(
196 "insert into ar_session set " .
197 "payer_id = ?" .
198 ", patient_id = ?" .
199 ", user_id = ?" .
200 ", closed = ?" .
201 ", reference = ?" .
202 ", check_date = now() , deposit_date = now() " .
203 ", pay_total = ?" .
204 ", payment_type = 'patient'" .
205 ", description = ?" .
206 ", adjustment_code = 'pre_payment'" .
207 ", post_to_date = now() " .
208 ", payment_method = ?",
209 array(0, $form_pid, $_SESSION['authUserID'], 0, $form_source, $_REQUEST['form_prepayment'], $NameNew, $form_method)
212 frontPayment($form_pid, 0, $form_method, $form_source, $_REQUEST['form_prepayment'], 0, $timestamp);//insertion to 'payments' table.
215 if ($_POST['form_upay'] && $_REQUEST['radio_type_of_payment'] != 'pre_payment') {
216 foreach ($_POST['form_upay'] as $enc => $payment) {
217 $payment = floatval($payment);
218 if ($amount = $payment) {
219 $zero_enc = $enc;
220 if ($_REQUEST['radio_type_of_payment'] == 'invoice_balance') {
221 if (!$enc) {
222 $enc = calendar_arrived($form_pid);
224 } else {
225 if (!$enc) {
226 $enc = calendar_arrived($form_pid);
230 //----------------------------------------------------------------------------------------------------
231 //Fetching the existing code and modifier
232 $ResultSearchNew = sqlStatement(
233 "SELECT * FROM billing LEFT JOIN code_types ON billing.code_type=code_types.ct_key " .
234 "WHERE code_types.ct_fee=1 AND billing.activity!=0 AND billing.pid =? AND encounter=? ORDER BY billing.code,billing.modifier",
235 array($form_pid, $enc)
237 if ($RowSearch = sqlFetchArray($ResultSearchNew)) {
238 $Codetype = $RowSearch['code_type'];
239 $Code = $RowSearch['code'];
240 $Modifier = $RowSearch['modifier'];
241 } else {
242 $Codetype = '';
243 $Code = '';
244 $Modifier = '';
247 //----------------------------------------------------------------------------------------------------
248 if ($_REQUEST['radio_type_of_payment'] == 'copay') {//copay saving to ar_session and ar_activity tables
249 $session_id = sqlInsert(
250 "INSERT INTO ar_session (payer_id,user_id,reference,check_date,deposit_date,pay_total," .
251 " global_amount,payment_type,description,patient_id,payment_method,adjustment_code,post_to_date) " .
252 " VALUES ('0',?,?,now(),now(),?,'','patient','COPAY',?,?,'patient_payment',now())",
253 array($_SESSION['authUserID'], $form_source, $amount, $form_pid, $form_method)
256 sqlBeginTrans();
257 $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc));
258 $insrt_id = sqlInsert(
259 "INSERT INTO ar_activity (pid,encounter,sequence_no,code_type,code,modifier,payer_type,post_time,post_user,session_id,pay_amount,account_code)" .
260 " VALUES (?,?,?,?,?,?,0,now(),?,?,?,'PCP')",
261 array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, $_SESSION['authUserID'], $session_id, $amount)
263 sqlCommitTrans();
265 frontPayment($form_pid, $enc, $form_method, $form_source, $amount, 0, $timestamp);//insertion to 'payments' table.
268 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.
269 if ($_REQUEST['radio_type_of_payment'] == 'cash') {
270 sqlStatement(
271 "update form_encounter set last_level_closed=? where encounter=? and pid=? ",
272 array(4, $enc, $form_pid)
274 sqlStatement(
275 "update billing set billed=? where encounter=? and pid=?",
276 array(1, $enc, $form_pid)
280 $adjustment_code = 'patient_payment';
281 $payment_id = sqlInsert(
282 "insert into ar_session set " .
283 "payer_id = ?" .
284 ", patient_id = ?" .
285 ", user_id = ?" .
286 ", closed = ?" .
287 ", reference = ?" .
288 ", check_date = now() , deposit_date = now() " .
289 ", pay_total = ?" .
290 ", payment_type = 'patient'" .
291 ", description = ?" .
292 ", adjustment_code = ?" .
293 ", post_to_date = now() " .
294 ", payment_method = ?",
295 array(0, $form_pid, $_SESSION['authUserID'], 0, $form_source, $amount, $NameNew, $adjustment_code, $form_method)
298 //--------------------------------------------------------------------------------------------------------------------
300 frontPayment($form_pid, $enc, $form_method, $form_source, 0, $amount, $timestamp);//insertion to 'payments' table.
302 //--------------------------------------------------------------------------------------------------------------------
304 $resMoneyGot = sqlStatement(
305 "SELECT sum(pay_amount) as PatientPay FROM ar_activity where pid =? and " .
306 "encounter = ? and payer_type = 0 and account_code = 'PCP' AND deleted IS NULL",
307 array($form_pid, $enc)
308 );//new fees screen copay gives account_code='PCP'
309 $rowMoneyGot = sqlFetchArray($resMoneyGot);
310 $Copay = $rowMoneyGot['PatientPay'];
312 //--------------------------------------------------------------------------------------------------------------------
314 //Looping the existing code and modifier
315 $ResultSearchNew = sqlStatement(
316 "SELECT * FROM billing LEFT JOIN code_types ON billing.code_type=code_types.ct_key WHERE code_types.ct_fee=1 " .
317 "AND billing.activity!=0 AND billing.pid =? AND encounter=? ORDER BY billing.code,billing.modifier",
318 array($form_pid, $enc)
320 while ($RowSearch = sqlFetchArray($ResultSearchNew)) {
321 $Codetype = $RowSearch['code_type'];
322 $Code = $RowSearch['code'];
323 $Modifier = $RowSearch['modifier'];
324 $Fee = $RowSearch['fee'];
326 $resMoneyGot = sqlStatement(
327 "SELECT sum(pay_amount) as MoneyGot FROM ar_activity where pid = ? AND deleted IS NULL " .
328 "and code_type=? and code=? and modifier=? and encounter =? and !(payer_type=0 and account_code='PCP')",
329 array($form_pid, $Codetype, $Code, $Modifier, $enc)
331 //new fees screen copay gives account_code='PCP'
332 $rowMoneyGot = sqlFetchArray($resMoneyGot);
333 $MoneyGot = $rowMoneyGot['MoneyGot'];
335 $resMoneyAdjusted = sqlStatement(
336 "SELECT sum(adj_amount) as MoneyAdjusted FROM ar_activity where " .
337 "pid = ? and code_type = ? and code = ? and modifier = ? and encounter = ? AND deleted IS NULL",
338 array($form_pid, $Codetype, $Code, $Modifier, $enc)
340 $rowMoneyAdjusted = sqlFetchArray($resMoneyAdjusted);
341 $MoneyAdjusted = $rowMoneyAdjusted['MoneyAdjusted'];
343 $Remainder = $Fee - $Copay - $MoneyGot - $MoneyAdjusted;
344 $Copay = 0;
345 if (round($Remainder, 2) != 0 && $amount != 0) {
346 if ($amount - $Remainder >= 0) {
347 $insert_value = $Remainder;
348 $amount = $amount - $Remainder;
349 } else {
350 $insert_value = $amount;
351 $amount = 0;
354 sqlBeginTrans();
355 $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc));
356 sqlStatement(
357 "insert into ar_activity set " .
358 "pid = ?" .
359 ", encounter = ?" .
360 ", sequence_no = ?" .
361 ", code_type = ?" .
362 ", code = ?" .
363 ", modifier = ?" .
364 ", payer_type = ?" .
365 ", post_time = now() " .
366 ", post_user = ?" .
367 ", session_id = ?" .
368 ", pay_amount = ?" .
369 ", adj_amount = ?" .
370 ", account_code = 'PP'",
371 array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, 0, $_SESSION['authUserID'], $payment_id, $insert_value, 0)
373 sqlCommitTrans();
374 }//if
375 }//while
376 if ($amount != 0) {//if any excess is there.
377 sqlBeginTrans();
378 $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc));
379 sqlStatement(
380 "insert into ar_activity set " .
381 "pid = ?" .
382 ", encounter = ?" .
383 ", sequence_no = ?" .
384 ", code_type = ?" .
385 ", code = ?" .
386 ", modifier = ?" .
387 ", payer_type = ?" .
388 ", post_time = now() " .
389 ", post_user = ?" .
390 ", session_id = ?" .
391 ", pay_amount = ?" .
392 ", adj_amount = ?" .
393 ", account_code = 'PP'",
394 array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, 0, $_SESSION['authUserID'], $payment_id, $amount, 0)
396 sqlCommitTrans();
399 //--------------------------------------------------------------------------------------------------------------------
400 }//invoice_balance
401 }//if ($amount = 0 + $payment)
402 }//foreach
403 }//if ($_POST['form_upay'])
404 }//if ($_POST['form_save'])
406 if (!empty($_POST['form_save']) || !empty($_REQUEST['receipt'])) {
407 if (!empty($_REQUEST['receipt'])) {
408 $form_pid = $_GET['patient'];
409 $timestamp = decorateString('....-..-.. ..:..:..', $_GET['time']);
412 // Get details for what we guess is the primary facility.
413 $frow = $facilityService->getPrimaryBusinessEntity(array("useLegacyImplementation" => true));
415 // Get the patient's name and chart number.
416 $patdata = getPatientData($form_pid, 'fname,mname,lname,pubpid');
418 // Re-fetch payment info.
419 $payrow = sqlQuery("SELECT " .
420 "SUM(amount1) AS amount1, " .
421 "SUM(amount2) AS amount2, " .
422 "MAX(method) AS method, " .
423 "MAX(source) AS source, " .
424 "MAX(dtime) AS dtime, " .
425 // "MAX(user) AS user " .
426 "MAX(user) AS user, " .
427 "MAX(encounter) as encounter " .
428 "FROM payments WHERE " .
429 "pid = ? AND dtime = ?", array($form_pid, $timestamp));
431 // Create key for deleting, just in case.
432 $ref_id = ($_REQUEST['radio_type_of_payment'] == 'copay') ? $session_id : $payment_id;
433 $payment_key = $form_pid . '.' . preg_replace('/[^0-9]/', '', $timestamp) . '.' . $ref_id;
435 if ($_REQUEST['radio_type_of_payment'] != 'pre_payment') {
436 // get facility from encounter
437 $tmprow = sqlQuery("SELECT `facility_id` FROM `form_encounter` WHERE `encounter` = ?", array($payrow['encounter']));
438 $frow = $facilityService->getById($tmprow['facility_id']);
439 } else {
440 // if pre_payment, then no encounter yet, so get main office address
441 $frow = $facilityService->getPrimaryBillingLocation();
444 // Now proceed with printing the receipt.
447 <title><?php echo xlt('Receipt for Payment'); ?></title>
448 <?php Header::setupHeader(); ?>
449 <script>
451 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
453 $(function () {
454 var win = top.printLogSetup ? top : opener.top;
455 win.printLogSetup(document.getElementById('printbutton'));
458 function closeHow(e) {
459 if (opener) {
460 dlgclose();
461 return;
463 top.activateTabByName('pat', true);
464 top.tabCloseByName(window.name);
467 // This is action to take before printing and is called from restoreSession.php.
468 function printlog_before_print() {
469 let divstyle = document.getElementById('hideonprint').style;
470 divstyle.display = 'none';
471 // currently exit is not hidden by default in case receipt print is not needed
472 // and left here for future option to force users to print via global etc..
473 // can still print later via reports.
474 divstyle = document.getElementById('showonprint').style;
475 divstyle.display = '';
478 // Process click on Delete button.
479 function deleteme() {
480 dlgopen('deleter.php?payment=' + <?php echo js_url($payment_key); ?> + '&csrf_token_form=' + <?php echo js_url(CsrfUtils::collectCsrfToken()); ?>, '_blank', 500, 450);
481 return false;
484 // Called by the deleteme.php window on a successful delete.
485 function imdeleted() {
486 if (opener) {
487 dlgclose(); // we're in reports/leftnav and callback reloads.
488 } else {
489 window.history.back(); // this is us full screen.
493 // Called to switch to the specified encounter having the specified DOS.
494 // This also closes the popup window.
495 function toencounter(enc, datestr, topframe) {
496 top.restoreSession();
497 top.goToEncounter(enc);
498 if (opener) dlgclose();
501 </script>
502 <style>
503 @media print {
504 #donebutton {
505 display: none;
508 </style>
509 </head>
510 <body>
511 <div class="container mt-3">
512 <div class="row">
513 <div class="col-12 text-center">
514 <h2><?php echo xlt('Receipt for Payment'); ?></h2>
516 <?php echo text($frow['name']) ?>
517 <br />
518 <?php echo text($frow['street']) ?>
519 <br />
520 <?php echo text($frow['city'] . ', ' . $frow['state']) . ' ' . text($frow['postal_code']) ?>
521 <br />
522 <?php echo text($frow['phone']) ?>
523 </p>
525 <div class="table-responsive">
526 <table class="table table-borderless">
527 <tr>
528 <td><?php echo xlt('Date'); ?>:</td>
529 <td><?php echo text(oeFormatSDFT(strtotime($payrow['dtime']))) ?></td>
530 </tr>
531 <tr>
532 <td><?php echo xlt('Patient'); ?>:</td>
533 <td><?php echo text($patdata['fname']) . " " . text($patdata['mname']) . " " .
534 text($patdata['lname']) . " (" . text($patdata['pubpid']) . ")" ?></td>
535 </tr>
536 <tr>
537 <td><?php echo xlt('How Paid'); ?>:</td>
538 <td><?php echo generate_display_field(array('data_type' => '1', 'list_id' => 'payment_method'), $payrow['method']); ?></td>
539 </tr>
540 <tr>
541 <td><?php echo xlt('Check or Reference Number'); ?>:</td>
542 <td><?php echo text($payrow['source']) ?></td>
543 </tr>
544 <tr>
545 <td><?php echo xlt('Amount for This Visit'); ?>:</td>
546 <td><?php echo text(oeFormatMoney($payrow['amount1'])) ?></td>
547 </tr>
548 <tr>
549 <td>
550 <?php
551 if ($_REQUEST['radio_type_of_payment'] == 'pre_payment') {
552 echo xlt('Pre-payment Amount');
553 } else {
554 echo xlt('Amount for Past Balance');
557 :</td>
558 <td><?php echo text(oeFormatMoney($payrow['amount2'])) ?></td>
559 </tr>
560 <tr>
561 <td><?php echo xlt('Received By'); ?>:</td>
562 <td><?php echo text($payrow['user']) ?></td>
563 </tr>
564 </table>
565 </div>
566 <div id='hideonprint'>
567 <button type="button" class="btn btn-primary btn-print" value='<?php echo xla('Print'); ?>' id='printbutton'>
568 <?php echo xlt('Print'); ?>
569 </button>
571 <?php
572 $todaysenc = todaysEncounterIf($pid);
573 if ($todaysenc && $todaysenc != $encounter) {
574 echo "&nbsp;<input type='button' class='btn btn-primary' " .
575 "value='" . xla('Open Today`s Visit') . "' " .
576 "onclick='toencounter(" . attr_js($todaysenc) . ", " . attr_js($today) . ", (opener ? opener.top : top))' />\n";
580 <?php if (AclMain::aclCheckCore('admin', 'super') || AclMain::aclCheckCore('acct', 'bill')) {
581 // allowing biller to delete payments ?>
582 <button type="button" class="btn btn-danger btn-delete" value='<?php echo xla('Delete'); ?>' onclick="deleteme()">
583 <?php echo xlt('Delete'); ?>
584 </button>
585 <?php } ?>
586 </div>
587 <div class='mt-3' id='showonprint'>
588 <button type="button" class="btn btn-secondary btn-cancel" value='<?php echo xla('Exit'); ?>' id='donebutton' onclick="closeHow(event)">
589 <?php echo xlt('Exit'); ?>
590 </button>
591 </div>
592 </div>
593 </div>
594 </div>
595 </body>
597 <?php
599 // End of receipt printing logic.
601 } else {
603 // Here we display the form for data entry.
606 <title><?php echo xlt('Record Payment'); ?></title>
608 <style>
609 #ajax_div_patient {
610 position: absolute;
611 z-index:10;
612 background-color: #FBFDD0;
613 border: 1px solid #ccc;
614 padding: 10px;
616 </style>
617 <!--Removed standard dependencies 12/29/17 as not needed any longer since moved to a tab/frame not popup.-->
619 <!-- supporting javascript code -->
620 <script>
621 var mypcc = '1';
622 </script>
623 <?php include_once("{$GLOBALS['srcdir']}/ajax/payment_ajax_jav.inc.php"); ?>
624 <script>
625 document.onclick=HideTheAjaxDivs;
626 </script>
628 <?php Header::setupAssets('topdialog'); ?>
630 <script src="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery-creditcardvalidator/jquery.creditCardValidator.js"></script>
632 <script>
633 var chargeMsg = <?php echo xlj('Payment was successfully authorized and charged. Thank You.'); ?>;
634 var publicKey = <?php echo json_encode($cryptoGen->decryptStandard($GLOBALS['gateway_public_key'])); ?>;
635 var apiKey = <?php echo json_encode($cryptoGen->decryptStandard($GLOBALS['gateway_api_key'])); ?>;
636 $(function() {
637 $('#openPayModal').on('show.bs.modal', function () {
638 let total = $("[name='form_paytotal']").val();
639 let prepay = $("#form_prepayment").val();
640 if (Number(total) < 1) {
641 if (Number(prepay) < 1) {
642 let error = <?php echo xlj("Please enter a payment amount"); ?>;
643 alert(error);
644 return false;
646 total = prepay;
648 $("#form_method").val('credit_card');
649 $("#payTotal").text(total);
650 $("#paymentAmount").val(total);
653 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
654 function closeHow(e) {
655 if (opener) {
656 dlgclose();
657 return;
659 top.activateTabByName('pat', true);
660 top.tabCloseByName(window.name);
662 function calctotal() {
663 var f = document.forms[0];
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 || ename.indexOf('form_bpay[') == 0) {
669 if (elem.value.length > 0) total += Number(elem.value);
672 f.form_paytotal.value = Number(total).toFixed(2);
673 return true;
676 function coloring() {
677 for (var i = 1; ; ++i) {
678 if (document.getElementById('paying_' + i)) {
679 paying = document.getElementById('paying_' + i).value * 1;
680 patient_balance = document.getElementById('duept_' + i).innerHTML * 1;
682 //balance=document.getElementById('balance_'+i).innerHTML*1;
683 if (patient_balance > 0 && paying > 0) {
684 if (paying > patient_balance) {
685 document.getElementById('paying_' + i).style.background = '#FF0000';
687 else if (paying < patient_balance) {
688 document.getElementById('paying_' + i).style.background = '#99CC00';
690 else if (paying == patient_balance) {
691 document.getElementById('paying_' + i).style.background = 'var(--white)';
693 } else {
694 document.getElementById('paying_' + i).style.background = 'var(--white)';
697 else {
698 break;
703 function CheckVisible(MakeBlank) { //Displays and hides the check number text box.
704 if (document.getElementById('form_method').options[document.getElementById(
705 'form_method').selectedIndex].value == 'check_payment' || document.getElementById(
706 'form_method').options[document.getElementById('form_method').selectedIndex]
707 .value == 'bank_draft') {
708 document.getElementById('check_number').disabled = false;
709 } else {
710 document.getElementById('check_number').disabled = true;
714 function validate(notSubmit = false) {
715 var f = document.forms[0];
716 let ok = -1;
717 top.restoreSession();
718 issue = 'no';
719 // prevent an empty form submission
720 let flgempty = true;
721 for (let i = 0; i < f.elements.length; ++i) {
722 let ename = f.elements[i].name;
723 if (f.elements[i].value == 'pre_payment' && f.elements[i].checked === true) {
724 if (Number(f.elements.namedItem("form_prepayment").value) !== 0) {
725 flgempty = false;
727 break;
729 if (ename.indexOf('form_upay[') === 0 || ename.indexOf('form_bpay[') === 0) {
730 if (Number(f.elements[i].value) !== 0) flgempty = false;
733 if (flgempty) {
734 alert(<?php echo xlj('A Payment is Required!. Please input a payment line item entry.'); ?>);
735 return false;
737 // continue validation.
738 if (((document.getElementById('form_method').options[document.getElementById('form_method').selectedIndex].value == 'check_payment' ||
739 document.getElementById('form_method').options[document.getElementById('form_method').selectedIndex].value == 'bank_draft') &&
740 document.getElementById('check_number').value == '')) {
741 alert(<?php echo xlj('Please Fill the Check or Reference Number'); ?>);
742 document.getElementById('check_number').focus();
743 return false;
745 if (document.getElementById('radio_type_of_payment_self1').checked == false &&
746 document.getElementById('radio_type_of_payment1').checked == false &&
747 document.getElementById('radio_type_of_payment2').checked == false &&
748 document.getElementById('radio_type_of_payment4').checked == false) {
749 alert(<?php echo xlj('Please Select Type Of Payment.'); ?>);
750 return false;
752 if (document.getElementById('radio_type_of_payment_self1').checked == true ||
753 document.getElementById('radio_type_of_payment1').checked == true) {
754 for (var i = 0; i < f.elements.length; ++i) {
755 var elem = f.elements[i];
756 var ename = elem.name;
757 if (ename.indexOf('form_upay[0') == 0) //Today is this text box.
759 if (elem.value * 1 > 0) {//A warning message, if the amount is posted with out encounter.
760 if (confirm(<?php echo xlj('If patient has appointment click OK to create encounter otherwise, cancel this and then create an encounter for today visit.'); ?>)) {
761 ok = 2;
762 } else {
763 elem.focus();
764 return false;
767 break;
772 if (document.getElementById('radio_type_of_payment1').checked == true){//CO-PAY
773 var total = 0;
774 for (var i = 0; i < f.elements.length; ++i) {
775 var elem = f.elements[i];
776 var ename = elem.name;
777 if (ename.indexOf('form_upay[0]') == 0) {//Today is this text box.
778 if (f.form_paytotal.value * 1 != elem.value * 1) {//Total CO-PAY is not posted against today
779 //A warning message, if the amount is posted against an old encounter.
780 if (confirm(<?php echo xlj('You are posting against an old encounter?'); ?>)) {
781 ok = 1;
782 } else {
783 elem.focus();
784 return false;
787 break;
790 }//Co Pay
791 else if (document.getElementById('radio_type_of_payment2').checked == true) {//Invoice Balance
792 for (var i = 0; i < f.elements.length; ++i) {
793 var elem = f.elements[i];
794 var ename = elem.name;
795 if (ename.indexOf('form_upay[0') == 0) {
796 if (elem.value * 1 > 0) {
797 alert(<?php echo xlj('Invoice Balance cannot be posted. No Encounter is created.'); ?>);
798 return false;
800 break;
804 if (notSubmit) {
805 return true;
807 if (ok === -1) {
808 if (confirm(<?php echo xlj('Would you like to save?'); ?>)) {
809 return true;
811 else {
812 return false;
815 return ok;
818 function cursor_pointer() { //Point the cursor to the latest encounter(Today)
819 var f = document.forms[0];
820 var total = 0;
821 for (var i = 0; i < f.elements.length; ++i) {
822 var elem = f.elements[i];
823 var ename = elem.name;
824 if (ename.indexOf('form_upay[') == 0) {
825 elem.focus();
826 break;
830 //=====================================================
831 function make_it_hide_enc_pay() {
832 document.getElementById('td_head_insurance_payment').style.display = "none";
833 document.getElementById('td_head_patient_co_pay').style.display = "none";
834 document.getElementById('td_head_co_pay').style.display = "none";
835 document.getElementById('td_head_insurance_balance').style.display = "none";
836 for (var i = 1; ; ++i) {
837 var td_inspaid_elem = document.getElementById('td_inspaid_' + i)
838 var td_patient_copay_elem = document.getElementById('td_patient_copay_' + i)
839 var td_copay_elem = document.getElementById('td_copay_' + i)
840 var balance_elem = document.getElementById('balance_' + i)
841 if (td_inspaid_elem) {
842 td_inspaid_elem.style.display = "none";
843 td_patient_copay_elem.style.display = "none";
844 td_copay_elem.style.display = "none";
845 balance_elem.style.display = "none";
846 } else {
847 break;
850 document.getElementById('td_total_4').style.display = "none";
851 document.getElementById('td_total_7').style.display = "none";
852 document.getElementById('td_total_8').style.display = "none";
853 document.getElementById('td_total_6').style.display = "none";
854 document.getElementById('table_display').width = "420px";
856 //=====================================================
857 function make_visible() {
858 document.getElementById('td_head_rep_doc').style.display = "";
859 document.getElementById('td_head_description').style.display = "";
860 document.getElementById('td_head_total_charge').style.display = "none";
861 document.getElementById('td_head_insurance_payment').style.display = "none";
862 document.getElementById('td_head_patient_payment').style.display = "none";
863 document.getElementById('td_head_patient_co_pay').style.display = "none";
864 document.getElementById('td_head_co_pay').style.display = "none";
865 document.getElementById('td_head_insurance_balance').style.display = "none";
866 document.getElementById('td_head_patient_balance').style.display = "none";
867 for (var i = 1; ; ++i) {
868 var td_charges_elem = document.getElementById('td_charges_' + i)
869 var td_inspaid_elem = document.getElementById('td_inspaid_' + i)
870 var td_ptpaid_elem = document.getElementById('td_ptpaid_' + i)
871 var td_patient_copay_elem = document.getElementById('td_patient_copay_' + i)
873 var td_copay_elem = document.getElementById('td_copay_' + i)
874 var balance_elem = document.getElementById('balance_' + i)
875 var duept_elem = document.getElementById('duept_' + i)
876 if (td_charges_elem) {
877 td_charges_elem.style.display = "none";
878 td_inspaid_elem.style.display = "none";
879 td_ptpaid_elem.style.display = "none";
880 td_patient_copay_elem.style.display = "none";
881 td_copay_elem.style.display = "none";
882 balance_elem.style.display = "none";
883 duept_elem.style.display = "none";
884 } else {
885 break;
888 document.getElementById('td_total_7').style.display = "";
889 document.getElementById('td_total_8').style.display = "";
890 document.getElementById('td_total_1').style.display = "none";
891 document.getElementById('td_total_2').style.display = "none";
892 document.getElementById('td_total_3').style.display = "none";
893 document.getElementById('td_total_4').style.display = "none";
894 document.getElementById('td_total_5').style.display = "none";
895 document.getElementById('td_total_6').style.display = "none";
896 document.getElementById('table_display').width = "505px";
899 function make_it_hide() {
900 document.getElementById('td_head_rep_doc').style.display = "none";
901 document.getElementById('td_head_description').style.display = "none";
902 document.getElementById('td_head_total_charge').style.display = "";
903 document.getElementById('td_head_insurance_payment').style.display = "";
904 document.getElementById('td_head_patient_payment').style.display = "";
905 document.getElementById('td_head_patient_co_pay').style.display = "";
906 document.getElementById('td_head_co_pay').style.display = "";
907 document.getElementById('td_head_insurance_balance').style.display = "";
908 document.getElementById('td_head_patient_balance').style.display = "";
909 for (var i = 1; ; ++i) {
910 var td_charges_elem = document.getElementById('td_charges_' + i)
911 var td_inspaid_elem = document.getElementById('td_inspaid_' + i)
912 var td_ptpaid_elem = document.getElementById('td_ptpaid_' + i)
913 var td_patient_copay_elem = document.getElementById('td_patient_copay_' + i)
915 var td_copay_elem = document.getElementById('td_copay_' + i)
916 var balance_elem = document.getElementById('balance_' + i)
917 var duept_elem = document.getElementById('duept_' + i)
918 if (td_charges_elem) {
919 td_charges_elem.style.display = "";
920 td_inspaid_elem.style.display = "";
921 td_ptpaid_elem.style.display = "";
922 td_patient_copay_elem.style.display = "";
923 td_copay_elem.style.display = "";
924 balance_elem.style.display = "";
925 duept_elem.style.display = "";
926 } else {
927 break;
930 document.getElementById('td_total_1').style.display = "";
931 document.getElementById('td_total_2').style.display = "";
932 document.getElementById('td_total_3').style.display = "";
933 document.getElementById('td_total_4').style.display = "";
934 document.getElementById('td_total_5').style.display = "";
935 document.getElementById('td_total_6').style.display = "";
936 document.getElementById('td_total_7').style.display = "";
937 document.getElementById('td_total_8').style.display = "";
938 document.getElementById('table_display').width = "635px";
941 function make_visible_radio() {
942 document.getElementById('tr_radio1').style.display = "";
943 document.getElementById('tr_radio2').style.display = "none";
946 function make_hide_radio() {
947 document.getElementById('tr_radio1').style.display = "none";
948 document.getElementById('tr_radio2').style.display = "";
951 function make_visible_row() {
952 document.getElementById('table_display').style.display = "";
953 document.getElementById('table_display_prepayment').style.display = "none";
956 function make_hide_row() {
957 document.getElementById('table_display').style.display = "none";
958 document.getElementById('table_display_prepayment').style.display = "";
961 function make_self() {
962 make_visible_row();
963 make_it_hide();
964 make_it_hide_enc_pay();
965 document.getElementById('radio_type_of_payment_self1').checked = true;
966 cursor_pointer();
969 function make_insurance() {
970 make_visible_row();
971 make_it_hide();
972 cursor_pointer();
973 document.getElementById('radio_type_of_payment1').checked = true;
975 </script>
977 <style>
978 @media (min-width: 992px) {
979 .modal-lg {
980 width: 1000px !Important;
983 </style>
984 <title><?php echo xlt('Record Payment'); ?></title>
985 <?php $NameNew = $patdata['fname'] . " " . $patdata['lname'] . " " . $patdata['mname']; ?>
986 <?php
987 $arrOeUiSettings = array(
988 'heading_title' => xl('Accept Payment'),
989 'include_patient_name' => true,// use only in appropriate pages
990 'expandable' => false,
991 'expandable_files' => array(),//all file names need suffix _xpd
992 'action' => "",//conceal, reveal, search, reset, link or back
993 'action_title' => "",
994 'action_href' => "",//only for actions - reset, link or back
995 'show_help_icon' => false,
996 'help_file_name' => ""
998 $oemr_ui = new OemrUI($arrOeUiSettings);
1000 </head>
1001 <body>
1002 <div class="container mt-3"><!--begin container div for form-->
1003 <div class="row">
1004 <div class="col-sm-12">
1005 <?php echo $oemr_ui->pageHeading() . "\r\n"; ?>
1006 </div>
1007 </div>
1008 <div class="row">
1009 <div class="col-sm-12">
1010 <form class="form form-vertical" method='post' action='front_payment.php<?php echo (!empty($payid)) ? "?payid=" . attr_url($payid) : ""; ?>' onsubmit='return validate();'>
1011 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
1012 <input name='form_pid' type='hidden' value='<?php echo attr($pid) ?>' />
1013 <fieldset>
1014 <legend><?php echo xlt('Payment'); ?></legend>
1015 <div class="col-12 oe-custom-line">
1016 <label class="control-label" for="form_method"><?php echo xlt('Payment Method'); ?>:</label>
1017 <select class="form-control" id="form_method" name="form_method" onchange='CheckVisible("yes")'>
1018 <?php
1019 $query1112 = "SELECT * FROM list_options where activity=1 AND list_id=? ORDER BY seq, title ";
1020 $bres1112 = sqlStatement($query1112, array('payment_method'));
1021 while ($brow1112 = sqlFetchArray($bres1112)) {
1022 if ($brow1112['option_id'] == 'electronic' || $brow1112['option_id'] == 'bank_draft') {
1023 continue;
1025 echo "<option value='" . attr($brow1112['option_id']) . "'>" . text(xl_list_label($brow1112['title'])) . "</option>";
1028 </select>
1029 </div>
1030 <div class="col-12 oe-custom-line">
1031 <label class="control-label" for="check_number"><?php echo xlt('Check or Reference Number'); ?>:</label>
1032 <div id="ajax_div_patient" style="display:none;"></div>
1033 <input type='text' id="check_number" name='form_source' class='form-control' value='<?php echo attr($payrow['source'] ?? ''); ?>' />
1034 </div>
1035 <div class="col-12 oe-custom-line">
1036 <label class="control-label" for="form_discount"><?php echo xla('Patient Coverage'); ?>:</label>
1037 <div class="pl-3">
1038 <label class="radio-inline">
1039 <input id="radio_type_of_coverage1" name="radio_type_of_coverage" onclick="make_visible_radio();make_self();" type="radio" value="self"><?php echo xlt('Self'); ?>
1040 </label>
1041 <label class="radio-inline">
1042 <input checked="checked" id="radio_type_of_coverag2" name="radio_type_of_coverage" onclick="make_hide_radio();make_insurance();" type="radio" value="insurance"><?php echo xlt('Insurance'); ?>
1043 </label>
1044 </div>
1045 </div>
1046 <div class="col-12 oe-custom-line">
1047 <label class="control-label" for=""><?php echo xlt('Payment against'); ?>:</label>
1048 <div id="tr_radio1" style="padding-left:15px; display:none"><!-- For radio Insurance -->
1049 <label class="radio-inline">
1050 <input id="radio_type_of_payment_self1" name="radio_type_of_payment" onclick="make_visible_row();make_it_hide_enc_pay();cursor_pointer();" type="radio" value="cash"><?php echo xlt('Encounter Payment'); ?>
1051 </label>
1052 </div>
1053 <div id="tr_radio2" style="padding-left:15px"><!-- For radio self -->
1054 <label class="radio-inline">
1055 <input checked="checked" id="radio_type_of_payment1" name="radio_type_of_payment" onclick="make_visible_row();cursor_pointer();" type="radio" value="copay"><?php echo xlt('Co Pay'); ?>
1056 </label>
1057 <label class="radio-inline">
1058 <input id="radio_type_of_payment2" name="radio_type_of_payment" onclick="make_visible_row();" type="radio" value="invoice_balance"><?php echo xlt('Invoice Balance'); ?><br />
1059 </label>
1060 <label class="radio-inline">
1061 <input id="radio_type_of_payment4" name="radio_type_of_payment" onclick="make_hide_row();" type="radio" value="pre_payment"><?php echo xlt('Pre Pay'); ?>
1062 </label>
1063 </div>
1064 </div>
1065 <div class="col-12 oe-custom-line">
1066 <div id="table_display_prepayment" style="display:none">
1067 <label class="control-label" for="form_prepayment"><?php echo xlt('Pre Payment'); ?>:</label>
1068 <input name='form_prepayment' id='form_prepayment'class='form-control' type='text' value ='' />
1069 </div>
1070 </div>
1071 </fieldset>
1072 <fieldset>
1073 <legend><?php echo xlt('Collect For'); ?></legend>
1074 <div class="table-responsive">
1075 <table class="table" id="table_display">
1076 <thead>
1077 <tr class="table-active" id="tr_head">
1078 <th class="font-weight-bold" width="70"><?php echo xlt('DOS'); ?></td>
1079 <th class="font-weight-bold" width="65"><?php echo xlt('Encounter'); ?></td>
1080 <th class="font-weight-bold text-center" id="td_head_total_charge" width="80"><?php echo xlt('Total Charge'); ?></td>
1081 <th class="font-weight-bold text-center" id="td_head_rep_doc" style='display:none' width="70"><?php echo xlt('Report/ Form'); ?></td>
1082 <th class="font-weight-bold text-center" id="td_head_description" style='display:none' width="200"><?php echo xlt('Description'); ?></td>
1083 <th class="font-weight-bold text-center" id="td_head_insurance_payment" width="80"><?php echo xlt('Insurance Payment'); ?></td>
1084 <th class="font-weight-bold text-center" id="td_head_patient_payment" width="80"><?php echo xlt('Patient Payment'); ?></td>
1085 <th class="font-weight-bold text-center" id="td_head_patient_co_pay" width="55"><?php echo xlt('Co Pay Paid'); ?></td>
1086 <th class="font-weight-bold text-center" id="td_head_co_pay" width="55"><?php echo xlt('Required Co Pay'); ?></td>
1087 <th class="font-weight-bold text-center" id="td_head_insurance_balance" width="80"><?php echo xlt('Insurance Balance'); ?></td>
1088 <th class="font-weight-bold text-center" id="td_head_patient_balance" width="80"><?php echo xlt('Patient Balance'); ?></td>
1089 <th class="font-weight-bold text-center" width="50"><?php echo xlt('Paying'); ?></th>
1090 </tr>
1091 </thead>
1092 <?php
1093 $encs = array();
1095 // Get the unbilled service charges and payments by encounter for this patient.
1097 $query = "SELECT fe.encounter, b.code_type, b.code, b.modifier, b.fee, " .
1098 "LEFT(fe.date, 10) AS encdate ,fe.last_level_closed " .
1099 "FROM form_encounter AS fe left join billing AS b on " .
1100 "b.pid = ? AND b.activity = 1 AND " . //AND b.billed = 0
1101 "b.code_type != 'TAX' AND b.fee != 0 " .
1102 "AND fe.pid = b.pid AND fe.encounter = b.encounter " .
1103 "where fe.pid = ? " .
1104 "ORDER BY b.encounter";
1105 $bres = sqlStatement($query, array($pid, $pid));
1107 while ($brow = sqlFetchArray($bres)) {
1108 $key = 0 - $brow['encounter'];
1109 if (empty($encs[$key])) {
1110 $encs[$key] = array(
1111 'encounter' => $brow['encounter'],
1112 'date' => $brow['encdate'],
1113 'last_level_closed' => $brow['last_level_closed'],
1114 'charges' => 0,
1115 'payments' => 0);
1118 if ($brow['code_type'] === 'COPAY') {
1119 //$encs[$key]['payments'] -= $brow['fee'];
1120 } else {
1121 $encs[$key]['charges'] += $brow['fee'];
1122 // Add taxes.
1123 $sql_array = array();
1124 $query = "SELECT taxrates FROM codes WHERE " .
1125 "code_type = ? AND " .
1126 "code = ? AND ";
1127 array_push($sql_array, ($code_types[$brow['code_type']]['id'] ?? null), $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, 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 " . //AND s.billed = 0
1147 "AND fe.pid = s.pid AND fe.encounter = s.encounter " .
1148 "where fe.pid = ? " .
1149 "ORDER BY s.encounter";
1151 $dres = sqlStatement($query, array($pid, $pid));
1153 while ($drow = sqlFetchArray($dres)) {
1154 $key = 0 - $drow['encounter'];
1155 if (empty($encs[$key])) {
1156 $encs[$key] = array(
1157 'encounter' => $drow['encounter'],
1158 'date' => $drow['encdate'],
1159 'last_level_closed' => $drow['last_level_closed'],
1160 'charges' => 0,
1161 'payments' => 0);
1164 $encs[$key]['charges'] += $drow['fee'];
1165 // Add taxes.
1166 $trow = sqlQuery("SELECT taxrates FROM drug_templates WHERE drug_id = ? " .
1167 "ORDER BY selector LIMIT 1", array($drow['drug_id']));
1168 $encs[$key]['charges'] += calcTaxes($trow, $drow['fee']);
1171 ksort($encs, SORT_NUMERIC);
1172 $gottoday = false;
1173 //Bringing on top the Today always
1174 foreach ($encs as $key => $value) {
1175 $dispdate = $value['date'];
1176 if (strcmp($dispdate, $today) == 0 && !$gottoday) {
1177 $gottoday = true;
1178 break;
1182 // If no billing was entered yet for today, then generate a line for
1183 // entering today's co-pay.
1185 if (!$gottoday) {
1186 echoLine("form_upay[0]", date("Y-m-d"), 0, 0, 0, 0 /*$duept*/);//No encounter yet defined.
1189 $gottoday = false;
1190 foreach ($encs as $key => $value) {
1191 $enc = $value['encounter'];
1192 $dispdate = $value['date'];
1193 if (strcmp($dispdate, $today) == 0 && !$gottoday) {
1194 $dispdate = date("Y-m-d");
1195 $gottoday = true;
1197 //------------------------------------------------------------------------------------
1198 $inscopay = BillingUtilities::getCopay($pid, $dispdate);
1199 $patcopay = BillingUtilities::getPatientCopay($pid, $enc);
1200 //Insurance Payment
1201 //-----------------
1202 $drow = sqlQuery(
1203 "SELECT SUM(pay_amount) AS payments, " .
1204 "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " .
1205 "deleted IS NULL AND pid = ? and encounter = ? and " .
1206 "payer_type != 0 and account_code!='PCP' ",
1207 array($pid, $enc)
1209 $dpayment = $drow['payments'];
1210 $dadjustment = $drow['adjustments'];
1211 //Patient Payment
1212 //---------------
1213 $drow = sqlQuery(
1214 "SELECT SUM(pay_amount) AS payments, " .
1215 "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " .
1216 "deleted IS NULL AND pid = ? and encounter = ? and " .
1217 "payer_type = 0 and account_code!='PCP' ",
1218 array($pid, $enc)
1220 $dpayment_pat = $drow['payments'];
1222 //------------------------------------------------------------------------------------
1223 //NumberOfInsurance
1224 $ResultNumberOfInsurance = sqlStatement("SELECT COUNT( DISTINCT TYPE ) NumberOfInsurance FROM insurance_data
1225 where pid = ? and provider>0 ", array($pid));
1226 $RowNumberOfInsurance = sqlFetchArray($ResultNumberOfInsurance);
1227 $NumberOfInsurance = $RowNumberOfInsurance['NumberOfInsurance'] * 1;
1228 //------------------------------------------------------------------------------------
1229 $duept = 0;
1230 if ((($NumberOfInsurance == 0 || $value['last_level_closed'] == 4 || $NumberOfInsurance == $value['last_level_closed']))) {//Patient balance
1231 $brow = sqlQuery("SELECT SUM(fee) AS amount FROM billing WHERE " .
1232 "pid = ? and encounter = ? AND activity = 1", array($pid, $enc));
1233 $srow = sqlQuery("SELECT SUM(fee) AS amount FROM drug_sales WHERE " .
1234 "pid = ? and encounter = ? ", array($pid, $enc));
1235 $drow = sqlQuery("SELECT SUM(pay_amount) AS payments, " .
1236 "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " .
1237 "deleted IS NULL AND pid = ? and encounter = ? ", array($pid, $enc));
1238 $duept = $brow['amount'] + $srow['amount'] - $drow['payments'] - $drow['adjustments'];
1241 echoLine(
1242 "form_upay[$enc]",
1243 $dispdate,
1244 $value['charges'],
1245 $dpayment_pat,
1246 ($dpayment + $dadjustment),
1247 $duept,
1248 $enc,
1249 $inscopay,
1250 $patcopay
1253 // Continue with display of the data entry form.
1256 <tr class="table-active">
1257 <td class="font-weight-bold" id='td_total_1'></td>
1258 <td class="font-weight-bold" id='td_total_2'></td>
1259 <td class="font-weight-bold" id='td_total_3'></td>
1260 <td class="font-weight-bold" id='td_total_4'></td>
1261 <td class="font-weight-bold" id='td_total_5'></td>
1262 <td class="font-weight-bold" id='td_total_6'></td>
1263 <td class="font-weight-bold" id='td_total_7'></td>
1264 <td class="font-weight-bold" id='td_total_8'></td>
1265 <td class="font-weight-bold text-right"><?php echo xlt('Total');?></td>
1266 <td class="font-weight-bold text-right">
1267 <input type='text' class='form-control text-success' name='form_paytotal' value='' readonly />
1268 </td>
1269 </tr>
1270 </table>
1271 </div>
1272 </fieldset>
1273 <div class="form-group">
1274 <div class="col-sm-12 text-left position-override">
1275 <div class="form-group" role="group">
1276 <button type='submit' class="btn btn-primary btn-save" name='form_save' value='<?php echo xla('Generate Invoice');?>'><?php echo xlt('Generate Invoice');?></button>
1277 <?php if (!empty($GLOBALS['cc_front_payments']) && $GLOBALS['payment_gateway'] != 'InHouse') {
1278 if ($GLOBALS['payment_gateway'] == 'Sphere') {
1279 echo SpherePayment::renderSphereHtml('clinic');
1280 } else {
1281 echo '<button type="button" class="btn btn-success btn-transmit mx-1" data-toggle="modal" data-target="#openPayModal">' . xlt("Credit Card Pay") . '</button>';
1282 if (!empty($GLOBALS['cc_stripe_terminal'])) {
1283 echo '<button type="button" class="btn btn-success btn-transmit mx-1" onclick="posDialog()">' . xlt("POS Payment") . '</button>';
1286 } ?>
1287 <button type='button' class="btn btn-secondary btn-cancel" value='<?php echo xla('Cancel'); ?>' onclick='closeHow(event)'><?php echo xlt('Cancel'); ?></button>
1288 <input type="hidden" name="hidden_patient_code" id="hidden_patient_code" value="<?php echo attr($pid);?>"/>
1289 <input type='hidden' name='ajax_mode' id='ajax_mode' value='' />
1290 <input type='hidden' name='mode' id='mode' value='' />
1291 </div>
1292 </div>
1293 </div>
1294 </form>
1295 </div>
1296 </div>
1297 <script>
1298 calctotal();
1299 </script>
1300 <!-- credit payment modal -->
1301 <div id="openPayModal" class="modal fade" role="dialog">
1302 <div class="modal-dialog">
1303 <div class="modal-content">
1304 <div class="modal-header">
1305 <h4><?php echo xlt('Submit Payment for Authorization'); ?></h4>
1306 </div>
1307 <div class="modal-body">
1308 <?php if ($GLOBALS['payment_gateway'] == 'AuthorizeNet') { ?>
1309 <form id='paymentForm' method='post' action='./front_payment_cc.php'>
1310 <fieldset>
1311 <div class="form-group">
1312 <label
1313 class="control-label"><?php echo xlt('Name on Card'); ?></label>
1314 <div class="controls">
1315 <input name="cardHolderName" id="cardHolderName" type="text" class="form-control"
1316 pattern="\w+ \w+.*"
1317 title="<?php echo xla('Fill your first and last name'); ?>"
1318 value="<?php echo attr($patdata['fname']) . ' ' . attr($patdata['lname']) ?>" />
1319 </div>
1320 </div>
1321 <div class="form-group">
1322 <div class="row">
1323 <div class="col-sm-6">
1324 <label class="control-label"><?php echo xlt('Card Number'); ?></label>
1325 <input name="cardNumber" id="cardNumber" type="text"
1326 class="form-control"
1327 autocomplete="off" maxlength="19" pattern="\d"
1328 onchange="validateCC()"
1329 title="<?php echo xla('Card Number'); ?>" value="" />&nbsp;&nbsp;
1330 </div>
1331 <span class="col-sm-6">
1332 <label class="control-label"><?php echo xlt('Entry Status'); ?></label>
1333 <h5 name="cardtype" id="cardtype" style="color:#cc0000;"><?php echo xlt('Validating') ?></h5>
1334 </span>
1335 </div>
1336 </div>
1337 <div class="form-group">
1338 <label
1339 class="control-label"><?php echo xlt('Card Expiry Date and Card Holders Zip'); ?></label>
1340 <div class="row">
1341 <div class="col-md-4">
1342 <select name="month" id="expMonth" class="form-control">
1343 <option value=""><?php echo xlt('Select Month'); ?></option>
1344 <option value="01"><?php echo xlt('January'); ?></option>
1345 <option value="02"><?php echo xlt('February'); ?></option>
1346 <option value="03"><?php echo xlt('March'); ?></option>
1347 <option value="04"><?php echo xlt('April'); ?></option>
1348 <option value="05"><?php echo xlt('May'); ?></option>
1349 <option value="06"><?php echo xlt('June'); ?></option>
1350 <option value="07"><?php echo xlt('July'); ?></option>
1351 <option value="08"><?php echo xlt('August'); ?></option>
1352 <option value="09"><?php echo xlt('September'); ?></option>
1353 <option value="10"><?php echo xlt('October'); ?></option>
1354 <option value="11"><?php echo xlt('November'); ?></option>
1355 <option value="12"><?php echo xlt('December'); ?></option>
1356 </select>
1357 </div>
1358 <div class="col-md-4">
1359 <select name="year" id="expYear" class="form-control">
1360 <option value=""><?php echo xlt('Select Year'); ?></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 <option value="2028">2029</option>
1370 <option value="2028">2030</option>
1371 </select>
1372 </div>
1373 <div class="col-md-4">
1374 <input name="zip" id="cczip" type="text" class="form-control"
1375 pattern="\d"
1376 title="<?php echo xla('Enter Your Zip'); ?>"
1377 placeholder="<?php echo xla('Card Holder Zip'); ?>"
1378 value="<?php echo attr($patdata['postal_code']) ?>" />
1379 </div>
1380 </div>
1381 </div>
1382 <div class="form-group">
1383 <label class="control-label"><?php echo xlt('Card CVV'); ?></label>
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='./../../portal/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 <input type='hidden' name='pid' id='pid' value='<?php echo attr($pid) ?>' />
1401 <input type='hidden' name='mode' id='mode' value='' />
1402 <input type='hidden' name='cc_type' id='cc_type' value='' />
1403 <input type='hidden' name='payment' id='paymentAmount' value='' />
1404 <input type='hidden' name='invValues' id='invValues' value='' />
1405 <input type="hidden" name="dataValue" id="dataValue" />
1406 <input type="hidden" name="dataDescriptor" id="dataDescriptor" />
1407 </fieldset>
1408 </form>
1409 <?php }
1410 if ($GLOBALS['payment_gateway'] == 'Stripe') { ?>
1411 <form class="form" method="post" name="payment-form" id="payment-form">
1412 <fieldset>
1413 <div class="form-group">
1414 <label for="cardHolderName" class="control-label"><?php echo xlt('Name on Card'); ?></label>
1415 <input name="cardHolderName" id="cardHolderName" type="text"
1416 class="form-control"
1417 pattern="\w+ \w+.*"
1418 title="<?php echo xla('Fill your first and last name'); ?>"
1419 value="<?php echo attr($patdata['fname']) . ' ' . attr($patdata['lname']) ?>" />
1420 </div>
1421 <div class="form-group">
1422 <label for="card-element"><?php echo xlt('Credit or Debit Card') ?></label>
1423 <div class="form-group" id="card-element"></div>
1424 <div class="text-danger" id="card-errors" role="alert"></div>
1425 </div>
1426 <div class="form-row">
1427 <?php echo xlt('Payment Amount'); ?>:&nbsp;<span id="payTotal"></span>
1428 </div>
1429 <input type='hidden' name='mode' id='mode' value='' />
1430 <input type='hidden' name='cc_type' id='cc_type' value='' />
1431 <input type='hidden' name='payment' id='paymentAmount' value='' />
1432 <input type='hidden' name='invValues' id='invValues' value='' />
1433 <input type='hidden' name='encs' id='encs' value='' />
1434 </fieldset>
1435 </form>
1436 <?php } ?>
1437 </div>
1438 <!-- Body -->
1439 <div class="modal-footer">
1440 <div class="button-group">
1441 <button type="button" class="btn btn-default" data-dismiss="modal"><?php echo xlt('Cancel'); ?></button>
1442 <?php
1443 if ($GLOBALS['payment_gateway'] == 'AuthorizeNet') { ?>
1444 <button id="payAurhorizeNet" class="btn btn-primary"
1445 onclick="sendPaymentDataToAnet(event)"><?php echo xlt('Pay Now'); ?></button>
1446 <?php }
1447 if ($GLOBALS['payment_gateway'] == 'Stripe') { ?>
1448 <button id="stripeSubmit" class="btn btn-primary"><?php echo xlt('Pay Now'); ?></button>
1449 <?php } ?>
1450 </div>
1451 </div>
1452 </div>
1453 </div>
1454 </div>
1456 <?php if ($GLOBALS['payment_gateway'] == 'AuthorizeNet') {
1457 // Include Authorize.Net dependency to tokenize card.
1458 // Will return a token to use for payment request keeping
1459 // credit info off the server.
1461 <script>
1462 var ccerr = <?php echo xlj('Invalid Credit Card Number'); ?>
1464 // In House CC number Validation
1465 $('#cardNumber').validateCreditCard(function (result) {
1466 var r = (result.card_type === null ? '' : result.card_type.name.toUpperCase())
1467 var v = (result.valid === true ? ' Valid Number' : ' Validating')
1468 if (result.valid === true) {
1469 document.getElementById("cardtype").style.color = "#00aa00";
1470 } else {
1471 document.getElementById("cardtype").style.color = "#aa0000";
1473 $('#cardtype').text(r + v);
1476 // Authorize.net
1477 function validateCC() {
1478 var result = $('#cardNumber').validateCreditCard();
1479 var r = (result.card_type == null ? '' : result.card_type.name.toUpperCase())
1480 var v = (result.valid === true ? ' Valid Card Number' : ' Invalid Card Number')
1481 if (result.valid === true) {
1482 document.getElementById("cardtype").style.color = "#00aa00";
1483 } else {
1484 document.getElementById("cardtype").style.color = "#aa0000";
1486 $('#cardtype').text(r + v);
1487 $('#cc_type').val(r);
1488 if (!result.valid) {
1489 alert(ccerr);
1490 return false;
1492 else {
1493 return true;
1497 function sendPaymentDataToAnet(e) {
1498 e.preventDefault();
1499 const authData = {};
1500 authData.clientKey = publicKey;
1501 authData.apiLoginID = apiKey;
1503 const cardData = {};
1504 cardData.cardNumber = document.getElementById("cardNumber").value;
1505 cardData.month = document.getElementById("expMonth").value;
1506 cardData.year = document.getElementById("expYear").value;
1507 cardData.cardCode = document.getElementById("cardCode").value;
1508 cardData.fullName = document.getElementById("cardHolderName").value;
1509 cardData.zip = document.getElementById("cczip").value;
1511 const secureData = {};
1512 secureData.authData = authData;
1513 secureData.cardData = cardData;
1515 Accept.dispatchData(secureData, acceptResponseHandler);
1517 function acceptResponseHandler(response) {
1518 if (response.messages.resultCode === "Error") {
1519 let i = 0;
1520 let errorMsg = '';
1521 while (i < response.messages.message.length) {
1522 errorMsg = errorMsg + response.messages.message[i].code + ": " +response.messages.message[i].text;
1523 console.log(errorMsg);
1524 i = i + 1;
1526 alert(errorMsg);
1527 } else {
1528 paymentFormUpdate(response.opaqueData);
1533 function paymentFormUpdate(opaqueData) {
1534 // this is card tokenized
1535 document.getElementById("dataDescriptor").value = opaqueData.dataDescriptor;
1536 document.getElementById("dataValue").value = opaqueData.dataValue;
1537 let oForm = document.forms['paymentForm'];
1538 oForm.elements['mode'].value = "AuthorizeNet";
1539 // empty out the fields before submitting to server.
1540 document.getElementById("cardNumber").value = "";
1541 document.getElementById("expMonth").value = "";
1542 document.getElementById("expYear").value = "";
1543 document.getElementById("cardCode").value = "";
1545 // Submit payment to server
1546 fetch('./front_payment_cc.php', {
1547 method: 'POST',
1548 body: new FormData(oForm)
1549 }).then((response) => {
1550 if (!response.ok) {
1551 throw Error(response.statusText);
1553 return response.json();
1554 }).then(function(data) {
1555 if(data.status !== 'ok') {
1556 alert(data);
1557 return;
1559 document.getElementById("check_number").value = data.authCode;
1560 alert(chargeMsg + "\n" + 'Auth: ' + data.authCode + ' TransId: ' + data.transId);
1561 $("[name='form_save']").click();
1562 }).catch(function(error) {
1563 alert(error)
1566 </script>
1567 <?php } // end authorize.net ?>
1569 <?php if ($GLOBALS['payment_gateway'] == 'Stripe') { // Begin Include Stripe ?>
1570 <script>
1571 // await validation function.
1572 const waitValidate = async (state = false) => {
1573 return await validate(state);
1575 const stripe = Stripe(publicKey);
1576 const elements = stripe.elements();
1577 const style = {
1578 base: {
1579 color: '#32325d',
1580 lineHeight: '1.2rem',
1581 fontSmoothing: 'antialiased',
1582 '::placeholder': {
1583 color: '#ccc'
1586 invalid: {
1587 color: '#f42c03',
1588 iconColor: '#ff0000'
1592 // Create an instance of the card Element.
1593 const card = elements.create('card', {style: style});
1594 // Add an instance of the card Element into the `card-element` <div>.
1595 card.mount('#card-element');
1596 // Handle real-time validation errors from the card Element.
1597 card.addEventListener('change', function (event) {
1598 let displayError = document.getElementById('card-errors');
1599 if (event.error) {
1600 displayError.textContent = event.error.message;
1601 } else {
1602 displayError.textContent = '';
1605 // Handle form submission.
1606 let form = document.getElementById('stripeSubmit');
1607 form.addEventListener('click', function (event) {
1608 event.preventDefault();
1609 stripe.createToken(card).then(function (result) {
1610 if (result.error) {
1611 // Inform the user if there was an error.
1612 let errorElement = document.getElementById('card-errors');
1613 errorElement.textContent = result.error.message;
1614 } else {
1615 // Send the token to server.
1616 stripeTokenHandler(result.token);
1621 // Submit the form with the token ID.
1622 function stripeTokenHandler(token) {
1623 // below for manual cc audit
1624 const encDates = (() => {
1625 let i = 0, c;
1626 let invDates = '';
1627 $('#table_display tbody tr').each(function () {
1628 if (this.className == 'table-active') {
1629 return false;
1631 if(i > 4) {
1632 return false; // breaks on max 5 encounters
1634 invDates += 'item' + ++i + ': ';
1635 c = 0;
1636 $(this).find('td').each(function() {
1637 if (++c < 3) {
1638 invDates += this.innerText + ' ';
1642 return invDates;
1643 })();
1644 // Insert the token ID into the form so it gets submitted to the server
1645 let oForm = document.forms['payment-form'];
1646 oForm.elements['mode'].value = "Stripe";
1647 oForm.elements['encs'].value = encDates;
1649 let hiddenInput = document.createElement('input');
1650 hiddenInput.setAttribute('type', 'hidden');
1651 hiddenInput.setAttribute('name', 'stripeToken');
1652 hiddenInput.setAttribute('value', token.id);
1653 oForm.appendChild(hiddenInput);
1655 // Submit payment to server
1656 fetch('./front_payment_cc.php', {
1657 method: 'POST',
1658 body: new FormData(oForm)
1659 }).then((response) => {
1660 if (!response.ok) {
1661 throw Error(response.statusText);
1663 return response.json();
1664 }).then(function (data) {
1665 if (data.status !== 'ok') {
1666 alert(data);
1667 return;
1669 document.getElementById("check_number").value = data.transId;
1670 alert(chargeMsg + "\n" + 'Auth: ' + data.authCode + ' TransId: ' + data.transId);
1671 $("[name='form_save']").click();
1672 }).catch(function (error) {
1673 alert(error.message);
1676 // terminal
1677 <?php if (!empty($GLOBALS['cc_stripe_terminal'])) { ?>
1678 // Dialog function for Stripe terminal payment.
1679 // Will post on successful credit payment.
1680 function posDialog() {
1681 // to pass validation check and saving a user having to click.
1682 $("#form_method").val('credit_card');
1683 // let's validate prior to collect payment from terminal
1684 // we'll use an await and validate promise to proceed.
1685 waitValidate(true).then((validateOk) => {
1686 // validation failed for some reason that user is aware
1687 // by alerts or a quite fail we'll handle.
1688 if (validateOk === false || typeof validateOk === 'undefined') {
1689 return false;
1691 // if 2 then need an encounter so credit is no no!
1692 // 1 would be posting against old encounter. will allow.
1693 if (validateOk === 2) {
1694 alert(xl("Must have an encounter to take credit card payment."));
1695 return true;
1697 let total = $("[name='form_paytotal']").val();
1698 let prepay = $("#form_prepayment").val();
1699 // just to be sure. validate() should catch...
1700 if (Number(total) < 1) {
1701 if (Number(prepay) < 1) {
1702 let error = xl("Please enter a payment amount");
1703 alert(error);
1704 return false;
1706 total = prepay;
1708 $("#payTotal").text(total);
1709 $("#paymentAmount").val(total);
1710 let title = xl("POS Payment");
1711 let url = "./front_payment_terminal.php?total=" + encodeURIComponent(total);
1712 dlgopen(url, 'terminal', 'modal-md', '550', '', title, {
1713 buttons: [
1714 {text: xl('Cancel'), close: false, id: "closeBtn", style: 'secondary btn-cancel'}
1719 <?php } ?>
1720 </script>
1721 <?php } ?>
1723 <?php
1724 if ($GLOBALS['payment_gateway'] == 'Sphere') {
1725 echo (new SpherePayment('clinic', $pid))->renderSphereJs();
1729 </div><!--end of container div of accept payment i.e the form-->
1730 <?php
1731 $oemr_ui->oeBelowContainerDiv();
1732 } // forms else close
1734 </body>
1735 </html>