* @author Jerry Padgett * @author Brady Miller * @copyright Copyright (c) 2006-2020 Rod Roark * @copyright Copyright (c) 2016-2019 Jerry Padgett * @copyright Copyright (c) 2019 Brady Miller * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ // Will start the (patient) portal OpenEMR session/cookie. require_once(__DIR__ . "/../src/Common/Session/SessionUtil.php"); OpenEMR\Common\Session\SessionUtil::portalSessionStart(); $isPortal = false; if (isset($_SESSION['pid']) && isset($_SESSION['patient_portal_onsite_two'])) { $pid = $_SESSION['pid']; $ignoreAuth_onsite_portal = true; $isPortal = true; require_once(__DIR__ . "/../interface/globals.php"); } else { OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy(); $ignoreAuth = false; require_once(__DIR__ . "/../interface/globals.php"); if (!isset($_SESSION['authUserID'])) { $landingpage = "index.php"; header('Location: ' . $landingpage); exit(); } } require_once(__DIR__ . "/lib/appsql.class.php"); require_once("$srcdir/patient.inc"); require_once("$srcdir/payment.inc.php"); require_once("$srcdir/forms.inc"); require_once("../custom/code_types.inc.php"); require_once("$srcdir/options.inc.php"); require_once("$srcdir/encounter_events.inc.php"); use OpenEMR\Billing\BillingUtilities; use OpenEMR\Common\Crypto\CryptoGen; use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\PaymentProcessing\Sphere\SpherePayment; $cryptoGen = new CryptoGen(); $appsql = new ApplicationTable(); $pid = isset($_REQUEST['pid']) ? $_REQUEST['pid'] : $pid; $pid = $_REQUEST['hidden_patient_code'] > 0 ? $_REQUEST['hidden_patient_code'] : $pid; $recid = isset($_REQUEST['recid']) ? (int) $_REQUEST['recid'] : 0; $adminUser = ''; $portalPatient = ''; $query = "SELECT pao.portal_username as recip_id, Concat_Ws(' ', patient_data.fname, patient_data.lname) as username FROM patient_data " . "LEFT JOIN patient_access_onsite pao ON pao.pid = patient_data.pid " . "WHERE patient_data.pid = ? AND pao.portal_pwd_status = 1"; $portalPatient = sqlQueryNoLog($query, $pid); if ($_SESSION['authUserID']) { $query = "SELECT users.username as recip_id, users.authorized as dash, CONCAT(users.fname,' ',users.lname) as username " . "FROM users WHERE id = ?"; $adminUser = sqlQueryNoLog($query, $_SESSION['authUserID']); } if ($recid) { $edata = $appsql->getPortalAuditRec($recid); } else { $edata = $appsql->getPortalAudit($pid, 'review', 'payment'); } $ccdata = array(); $invdata = array(); if ($edata) { $ccdata = json_decode($cryptoGen->decryptStandard($edata['checksum']), true); $invdata = json_decode($edata['table_args'], true); echo ""; } function bucks($amount) { if ($amount) { $amount = oeFormatMoney($amount); return $amount; } return ''; } function rawbucks($amount) { if ($amount) { $amount = sprintf("%.2f", $amount); return $amount; } return ''; } // Display a row of data for an encounter. // $var_index = 0; $sum_charges = $sum_ptpaid = $sum_inspaid = $sum_duept = $sum_copay = $sum_patcopay = $sum_balance = 0; function echoLine($iname, $date, $charges, $ptpaid, $inspaid, $duept, $encounter = 0, $copay = 0, $patcopay = 0) { global $sum_charges, $sum_ptpaid, $sum_inspaid, $sum_duept, $sum_copay, $sum_patcopay, $sum_balance; global $var_index; $var_index++; $balance = bucks($charges - $ptpaid - $inspaid); $balance = (round($duept, 2) != 0) ? 0 : $balance; // if balance is due from patient, then insurance balance is displayed as zero $encounter = $encounter ? $encounter : ''; echo " \n"; echo " " . text(oeFormatShortDate($date)) . "\n"; echo " " . text($encounter) . "\n"; echo " " . text(bucks($charges)) . "\n"; echo " " . text(bucks($inspaid * -1)) . "\n"; echo " " . text(bucks($ptpaid * -1)) . "\n"; echo " " . text(bucks($patcopay)) . "\n"; echo " " . text(bucks($copay)) . "\n"; echo " " . text(bucks($balance)) . "\n"; echo " " . text(bucks(round($duept, 2) * 1)) . "\n"; echo " \n"; echo " \n"; $sum_charges += (float)$charges * 1; $sum_ptpaid += (float)$ptpaid * -1; $sum_inspaid += (float)$inspaid * -1; $sum_duept += (float)$duept * 1; $sum_patcopay += (float)$patcopay * 1; $sum_copay += (float)$copay * 1; $sum_balance += (float)$balance * 1; } // We use this to put dashes, colons, etc. back into a timestamp. // function decorateString($fmt, $str) { $res = ''; while ($fmt) { $fc = substr($fmt, 0, 1); $fmt = substr($fmt, 1); if ($fc == '.') { $res .= substr($str, 0, 1); $str = substr($str, 1); } else { $res .= $fc; } } return $res; } // Compute taxes from a tax rate string and a possibly taxable amount. // function calcTaxes($row, $amount) { $total = 0; if (empty($row['taxrates'])) { return $total; } $arates = explode(':', $row['taxrates']); if (empty($arates)) { return $total; } foreach ($arates as $value) { if (empty($value)) { continue; } $trow = sqlQuery("SELECT option_value FROM list_options WHERE " . "list_id = 'taxrate' AND option_id = ? LIMIT 1", array($value )); if (empty($trow['option_value'])) { echo "\n"; continue; } $tax = sprintf("%01.2f", $amount * $trow['option_value']); // echo "\n"; $total += $tax; } return $total; } $now = time(); $today = date('Y-m-d', $now); $timestamp = date('Y-m-d H:i:s', $now); $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 )); $alertmsg = ''; // anything here pops up in an alert box // If the Save button was clicked... if ($_POST['form_save']) { $form_pid = $_POST['form_pid']; $form_method = trim($_POST['form_method']); $form_source = trim($_POST['form_source']); $patdata = getPatientData($form_pid, 'fname,mname,lname,pubpid'); $NameNew = $patdata['fname'] . " " . $patdata['lname'] . " " . $patdata['mname']; if ($_REQUEST['radio_type_of_payment'] == 'pre_payment') { $payment_id = sqlInsert( "insert into ar_session set " . "payer_id = ?" . ", patient_id = ?" . ", user_id = ?" . ", closed = ?" . ", reference = ?" . ", check_date = now() , deposit_date = now() " . ", pay_total = ?" . ", payment_type = 'patient'" . ", description = ?" . ", adjustment_code = 'pre_payment'" . ", post_to_date = now() " . ", payment_method = ?", array(0, $form_pid, $_SESSION['authUserID'], 0, $form_source, $_REQUEST['form_prepayment'], $NameNew, $form_method) ); frontPayment($form_pid, 0, $form_method, $form_source, $_REQUEST['form_prepayment'], 0, $timestamp);//insertion to 'payments' table. } if ($_POST['form_upay'] && $_REQUEST['radio_type_of_payment'] != 'pre_payment') { foreach ($_POST['form_upay'] as $enc => $payment) { if ($amount = (float)$payment) { $zero_enc = $enc; //---------------------------------------------------------------------------------------------------- //Fetching the existing code and modifier $ResultSearchNew = sqlStatement( "SELECT * FROM billing LEFT JOIN code_types ON billing.code_type=code_types.ct_key " . "WHERE code_types.ct_fee=1 AND billing.activity!=0 AND billing.pid =? AND encounter=? ORDER BY billing.code,billing.modifier", array($form_pid, $enc) ); if ($RowSearch = sqlFetchArray($ResultSearchNew)) { $Codetype = $RowSearch['code_type']; $Code = $RowSearch['code']; $Modifier = $RowSearch['modifier']; } else { $Codetype = ''; $Code = ''; $Modifier = ''; } //---------------------------------------------------------------------------------------------------- if ($_REQUEST['radio_type_of_payment'] == 'copay') {//copay saving to ar_session and ar_activity tables $session_id = sqlInsert( "INSERT INTO ar_session (payer_id,user_id,reference,check_date,deposit_date,pay_total," . " global_amount,payment_type,description,patient_id,payment_method,adjustment_code,post_to_date) " . " VALUES ('0',?,?,now(),now(),?,'','patient','COPAY',?,?,'patient_payment',now())", array($_SESSION['authUserID'], $form_source, $amount, $form_pid, $form_method) ); sqlBeginTrans(); $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc)); $insrt_id = sqlInsert( "INSERT INTO ar_activity (pid,encounter,sequence_no,code_type,code,modifier,payer_type,post_time,post_user,session_id,pay_amount,account_code)" . " VALUES (?,?,?,?,?,?,0,now(),?,?,?,'PCP')", array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, $_SESSION['authUserID'], $session_id, $amount) ); sqlCommitTrans(); frontPayment($form_pid, $enc, $form_method, $form_source, $amount, 0, $timestamp);//insertion to 'payments' table. } 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. if ($_REQUEST['radio_type_of_payment'] == 'cash') { sqlStatement( "update form_encounter set last_level_closed=? where encounter=? and pid=? ", array(4, $enc, $form_pid) ); sqlStatement( "update billing set billed=? where encounter=? and pid=?", array(1, $enc, $form_pid) ); } $adjustment_code = 'patient_payment'; $payment_id = sqlInsert( "insert into ar_session set " . "payer_id = ?" . ", patient_id = ?" . ", user_id = ?" . ", closed = ?" . ", reference = ?" . ", check_date = now() , deposit_date = now() " . ", pay_total = ?" . ", payment_type = 'patient'" . ", description = ?" . ", adjustment_code = ?" . ", post_to_date = now() " . ", payment_method = ?", array(0, $form_pid, $_SESSION['authUserID'], 0, $form_source, $amount, $NameNew, $adjustment_code, $form_method) ); //-------------------------------------------------------------------------------------------------------------------- frontPayment($form_pid, $enc, $form_method, $form_source, 0, $amount, $timestamp);//insertion to 'payments' table. //-------------------------------------------------------------------------------------------------------------------- $resMoneyGot = sqlStatement( "SELECT sum(pay_amount) as PatientPay FROM ar_activity where deleted IS NULL AND pid =? and " . "encounter =? and payer_type=0 and account_code='PCP'", array($form_pid, $enc) );//new fees screen copay gives account_code='PCP' $rowMoneyGot = sqlFetchArray($resMoneyGot); $Copay = $rowMoneyGot['PatientPay']; //-------------------------------------------------------------------------------------------------------------------- //Looping the existing code and modifier $ResultSearchNew = sqlStatement( "SELECT * FROM billing LEFT JOIN code_types ON billing.code_type=code_types.ct_key WHERE code_types.ct_fee=1 " . "AND billing.activity!=0 AND billing.pid =? AND encounter=? ORDER BY billing.code,billing.modifier", array($form_pid, $enc) ); while ($RowSearch = sqlFetchArray($ResultSearchNew)) { $Codetype = $RowSearch['code_type']; $Code = $RowSearch['code']; $Modifier = $RowSearch['modifier']; $Fee = $RowSearch['fee']; $resMoneyGot = sqlStatement( "SELECT sum(pay_amount) as MoneyGot FROM ar_activity where deleted IS NULL AND pid = ? " . "and code_type=? and code=? and modifier=? and encounter =? and !(payer_type=0 and account_code='PCP')", array($form_pid, $Codetype, $Code, $Modifier, $enc) ); //new fees screen copay gives account_code='PCP' $rowMoneyGot = sqlFetchArray($resMoneyGot); $MoneyGot = $rowMoneyGot['MoneyGot']; $resMoneyAdjusted = sqlStatement( "SELECT sum(adj_amount) as MoneyAdjusted FROM ar_activity where deleted IS NULL AND " . "pid =? and code_type=? and code=? and modifier=? and encounter =?", array($form_pid, $Codetype, $Code, $Modifier, $enc) ); $rowMoneyAdjusted = sqlFetchArray($resMoneyAdjusted); $MoneyAdjusted = $rowMoneyAdjusted['MoneyAdjusted']; $Remainder = $Fee - $Copay - $MoneyGot - $MoneyAdjusted; $Copay = 0; if (round($Remainder, 2) != 0 && $amount != 0) { if ($amount - $Remainder >= 0) { $insert_value = $Remainder; $amount = $amount - $Remainder; } else { $insert_value = $amount; $amount = 0; } sqlBeginTrans(); $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc)); sqlStatement( "insert into ar_activity set " . "pid = ?" . ", encounter = ?" . ", sequence_no = ?" . ", code_type = ?" . ", code = ?" . ", modifier = ?" . ", payer_type = ?" . ", post_time = now() " . ", post_user = ?" . ", session_id = ?" . ", pay_amount = ?" . ", adj_amount = ?" . ", account_code = 'PP'", array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, 0, $_SESSION['authUserID'], $payment_id, $insert_value, 0) ); sqlCommitTrans(); }//if }//while if ($amount != 0) {//if any excess is there. sqlBeginTrans(); $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($form_pid, $enc)); sqlStatement( "insert into ar_activity set " . "pid = ?" . ", encounter = ?" . ", sequence_no = ?" . ", code_type = ?" . ", code = ?" . ", modifier = ?" . ", payer_type = ?" . ", post_time = now() " . ", post_user = ?" . ", session_id = ?" . ", pay_amount = ?" . ", adj_amount = ?" . ", account_code = 'PP'", array($form_pid, $enc, $sequence_no['increment'], $Codetype, $Code, $Modifier, 0, $_SESSION['authUserID'], $payment_id, $amount, 0) ); sqlCommitTrans(); } //-------------------------------------------------------------------------------------------------------------------- }//invoice_balance }//if ($amount = 0 + $payment) }//foreach }//if ($_POST['form_upay']) }//if ($_POST['form_save']) if ($_POST['form_save'] || $_REQUEST['receipt']) { if ($_REQUEST['receipt']) { $form_pid = $_GET['patient']; $timestamp = decorateString('....-..-.. ..:..:..', $_GET['time']); } // Get details for what we guess is the primary facility. $frow = sqlQuery("SELECT * FROM facility " . "ORDER BY billing_location DESC, accepts_assignment DESC, id LIMIT 1"); // Get the patient's name and chart number. $patdata = getPatientData($form_pid, 'fname,mname,lname,pubpid'); // Re-fetch payment info. $payrow = sqlQuery("SELECT " . "SUM(amount1) AS amount1, " . "SUM(amount2) AS amount2, " . "MAX(method) AS method, " . "MAX(source) AS source, " . "MAX(dtime) AS dtime, " . // "MAX(user) AS user " . "MAX(user) AS user, " . "MAX(encounter) as encounter " . "FROM payments WHERE " . "pid = ? AND dtime = ?", array($form_pid, $timestamp )); // Create key for deleting, just in case. $ref_id = ($_REQUEST['radio_type_of_payment'] == 'copay') ? $session_id : $payment_id; $payment_key = $form_pid . '.' . preg_replace('/[^0-9]/', '', $timestamp) . '.' . $ref_id; // get facility from encounter $tmprow = sqlQuery("SELECT facility_id FROM form_encounter WHERE encounter = ?", array($payrow['encounter'])); $frow = sqlQuery("SELECT * FROM facility " . " WHERE id = ?", array($tmprow['facility_id'] )); // Now proceed with printing the receipt. ?> <?php echo xlt('Receipt for Payment'); ?> '; ?>




:
:
: '1', 'list_id' => 'payment_method'), $payrow['method']); ?>
:
:
:
:
<?php echo xlt('Record Payment'); ?>
'/> '; } else { $hide = 'hidden'; echo ''; } ?>
 
 :  
:
: ' />
:
$brow['encounter'], 'date' => $brow['encdate'], 'last_level_closed' => $brow['last_level_closed'], 'charges' => 0, 'payments' => 0, 'reason' => $brow['reason'] ); } if ($brow['code_type'] === 'COPAY') { // $encs[$key]['payments'] -= $brow['fee']; } else { $encs[$key]['charges'] += $brow['fee']; // Add taxes. $sql_array = array(); $query = "SELECT taxrates FROM codes WHERE " . "code_type = ? AND " . "code = ? AND "; array_push($sql_array, $code_types[$brow['code_type']]['id'], $brow['code']); if ($brow['modifier']) { $query .= "modifier = ?"; array_push($sql_array, $brow['modifier']); } else { $query .= "(modifier IS NULL OR modifier = '')"; } $query .= " LIMIT 1"; $trow = sqlQuery($query, $sql_array); $encs[$key]['charges'] += calcTaxes($trow, $brow['fee']); } } // Do the same for unbilled product sales. // $query = "SELECT fe.encounter, fe.reason, s.drug_id, s.fee, " . "LEFT(fe.date, 10) AS encdate,fe.last_level_closed " . "FROM form_encounter AS fe left join drug_sales AS s " . "on s.pid = ? AND s.fee != 0 " . "AND fe.pid = s.pid AND fe.encounter = s.encounter " . "where fe.pid = ? " . "ORDER BY s.encounter"; $dres = sqlStatement($query, array($pid, $pid)); // while ($drow = sqlFetchArray($dres)) { $key = (int)$drow['encounter']; if (empty($encs[$key])) { $encs[$key] = array( 'encounter' => $drow['encounter'], 'date' => $drow['encdate'], 'last_level_closed' => $drow['last_level_closed'], 'charges' => 0, 'payments' => 0 ); } $encs[$key]['charges'] += $drow['fee']; // Add taxes. $trow = sqlQuery( "SELECT taxrates FROM drug_templates WHERE drug_id = ? " . "ORDER BY selector LIMIT 1", array($drow['drug_id']) ); $encs[$key]['charges'] += calcTaxes($trow, $drow['fee']); } ksort($encs, SORT_NUMERIC); foreach ($encs as $key => $value) { $enc = $value['encounter']; $reason = $value['reason']; $dispdate = $value['date']; $inscopay = BillingUtilities::getCopay($pid, $dispdate); $patcopay = BillingUtilities::getPatientCopay($pid, $enc); // Insurance Payment // $drow = sqlQuery( "SELECT SUM(pay_amount) AS payments, " . "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " . "deleted IS NULL AND pid = ? and encounter = ? AND " . "payer_type != 0 AND account_code != 'PCP'", array($pid, $enc) ); $dpayment = $drow['payments']; $dadjustment = $drow['adjustments']; // Patient Payment // $drow = sqlQuery( "SELECT SUM(pay_amount) AS payments, SUM(adj_amount) AS adjustments " . "FROM ar_activity WHERE deleted IS NULL AND pid = ? and encounter = ? and " . "payer_type = 0 and account_code != 'PCP'", array($pid, $enc) ); $dpayment_pat = $drow['payments']; // NumberOfInsurance // $ResultNumberOfInsurance = sqlStatement( "SELECT COUNT( DISTINCT TYPE ) NumberOfInsurance FROM insurance_data where pid = ? and provider>0 ", array($pid) ); $RowNumberOfInsurance = sqlFetchArray($ResultNumberOfInsurance); $NumberOfInsurance = $RowNumberOfInsurance['NumberOfInsurance'] * 1; $duept = 0; if ((($NumberOfInsurance == 0 || $value['last_level_closed'] == 4 || $NumberOfInsurance == $value['last_level_closed']))) { // Patient balance $brow = sqlQuery("SELECT SUM(fee) AS amount FROM billing WHERE " . "pid = ? and encounter = ? AND activity = 1", array($pid, $enc )); $srow = sqlQuery("SELECT SUM(fee) AS amount FROM drug_sales WHERE " . "pid = ? and encounter = ? ", array($pid, $enc )); $drow = sqlQuery( "SELECT SUM(pay_amount) AS payments, SUM(adj_amount) AS adjustments " . "FROM ar_activity WHERE deleted IS NULL AND pid = ? and encounter = ? ", array($pid, $enc) ); $duept = $brow['amount'] + $srow['amount'] - $drow['payments'] - $drow['adjustments']; } echoLine("form_upay[$enc]", $dispdate, $value['charges'], $dpayment_pat, ($dpayment + $dadjustment), $duept, ($enc . ': ' . $reason), $inscopay, $patcopay); } // Continue with display of the data entry form. ?>
'; if (!isset($_SESSION['authUserID'])) { echo '
' . xlt("Payment Information") . ' ' . xlt("Pending Auth since") . ': ' . text($edata["date"]) . '
'; } else { echo '
' . xlt("Audit Payment") . ' ' . xlt("Pending since") . ': ' . text($edata["date"]) . '' . '
'; } } else { echo '
' . xlt("Pay Invoice") . ''; } } else { echo '

' . xlt("Locked Payment Pending") . '

'; } } else { echo ""; } ?>
renderSphereJs(); } ?>