You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
472 lines
20 KiB
472 lines
20 KiB
2 years ago
|
<?php
|
||
|
|
||
|
/**
|
||
|
* main file for the 270 batch creation.
|
||
|
* This report is the batch report required for batch eligibility verification.
|
||
|
*
|
||
|
* This program creates the batch for the x12 270 eligibility file
|
||
|
*
|
||
|
* @package OpenEMR
|
||
|
* @link http://www.open-emr.org
|
||
|
* @author Terry Hill <terry@lilysystems.com>
|
||
|
* @author Brady Miller <brady.g.miller@gmail.com>
|
||
|
* @author Jerry Padgett <sjpadgett@gmail.com>
|
||
|
* @author Stephen Waite <stephen.waite@cmsvt.com>
|
||
|
* @copyright Copyright (c) 2010 MMF Systems, Inc
|
||
|
* @copyright Copyright (c) 2016 Terry Hill <terry@lillysystems.com>
|
||
|
* @copyright Copyright (c) 2017 Brady Miller <brady.g.miller@gmail.com>
|
||
|
* @copyright Copyright (c) 2019-2020 Jerry Padgett <sjpadgett@gmail.com>
|
||
|
* @copyright Copyright (c) 2019-2020 Stephen Waite <stephen.waite@cmsvt.com>
|
||
|
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
|
||
|
*/
|
||
|
|
||
|
require_once("../globals.php");
|
||
|
require_once("$srcdir/forms.inc");
|
||
|
require_once("$srcdir/patient.inc");
|
||
|
require_once "$srcdir/options.inc.php";
|
||
|
require_once("$srcdir/calendar.inc");
|
||
|
require_once("$srcdir/appointments.inc.php");
|
||
|
|
||
|
use OpenEMR\Billing\EDI270;
|
||
|
use OpenEMR\Common\Csrf\CsrfUtils;
|
||
|
use OpenEMR\Core\Header;
|
||
|
|
||
|
if (!empty($_POST)) {
|
||
|
if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
|
||
|
CsrfUtils::csrfNotVerified();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Element data seperator
|
||
|
$eleDataSep = "*";
|
||
|
// Segment Terminator
|
||
|
$segTer = "~";
|
||
|
// Component Element seperator
|
||
|
$compEleSep = ":";
|
||
|
|
||
|
// filter conditions for the report and batch creation
|
||
|
|
||
|
$from_date = (isset($_POST['form_from_date'])) ? DateToYYYYMMDD($_POST['form_from_date']) : date('Y-m-d');
|
||
|
$to_date = (isset($_POST['form_to_date'])) ? DateToYYYYMMDD($_POST['form_to_date']) : date('Y-m-d');
|
||
|
$form_facility = (!empty($_POST['form_facility'])) ? $_POST['form_facility'] : '';
|
||
|
$form_provider = (!empty($_POST['form_users'])) ? $_POST['form_users'] : '';
|
||
|
$exclude_policy = (!empty($_POST['removedrows'])) ? $_POST['removedrows'] : '';
|
||
|
$x12_partner = (!empty($_POST['form_x12'])) ? $_POST['form_x12'] : '';
|
||
|
$X12info = EDI270::getX12Partner($x12_partner);
|
||
|
|
||
|
// grab appointments, sort by date and make unique to first upcoming appt by pid.
|
||
|
$appts = fetchAppointments($from_date, $to_date);
|
||
|
$appts = sortAppointments($appts);
|
||
|
$appts = unique_by_key($appts, 'pid');
|
||
|
$ids = [];
|
||
|
foreach ($appts as $eid) {
|
||
|
$ids[] = $eid['pc_eid'];
|
||
|
}
|
||
|
//Set up the sql variable binding array (this prevents sql-injection attacks)
|
||
|
$sqlBindArray = array();
|
||
|
|
||
|
$ids = count($ids) > 0 ? implode(',', $ids) : "'0'";
|
||
|
$where = "e.pc_eid in($ids) ";
|
||
|
|
||
|
if ($form_facility != "") {
|
||
|
$where .= " AND f.id = ? ";
|
||
|
array_push($sqlBindArray, $form_facility);
|
||
|
}
|
||
|
|
||
|
if ($form_provider != "") {
|
||
|
$where .= " AND d.id = ? ";
|
||
|
array_push($sqlBindArray, $form_provider);
|
||
|
}
|
||
|
|
||
|
if ($exclude_policy != "") {
|
||
|
$arrayExplode = explode(",", $exclude_policy);
|
||
|
$excludePlacemakers = "";
|
||
|
$firstFlag = true;
|
||
|
foreach ($arrayExplode as $processExclude) {
|
||
|
// grab the string between the _ character and the ending ' character (and then drop these characters)
|
||
|
$processExclude = strstr($processExclude, '_');
|
||
|
$processExclude = substr($processExclude, 1, strlen($processExclude) - 2);
|
||
|
array_push($sqlBindArray, $processExclude);
|
||
|
if ($firstFlag) {
|
||
|
$excludePlacemakers = "?";
|
||
|
$firstFlag = false;
|
||
|
} else {
|
||
|
$excludePlacemakers .= ",?";
|
||
|
}
|
||
|
}
|
||
|
$where .= " AND i.policy_number NOT IN ($excludePlacemakers)";
|
||
|
}
|
||
|
$where .= " AND (i.policy_number is NOT NULL AND i.policy_number != '')";
|
||
|
$where .= " GROUP BY p.pid ORDER BY c.name";
|
||
|
$query = sprintf("SELECT e.pc_facility,
|
||
|
e.pc_eid,
|
||
|
p.lname,
|
||
|
p.fname,
|
||
|
p.mname,
|
||
|
DATE_FORMAT(p.dob, '%%Y%%m%%d') as dob,
|
||
|
p.ss,
|
||
|
p.sex,
|
||
|
p.pid,
|
||
|
p.pubpid,
|
||
|
i.subscriber_ss,
|
||
|
i.policy_number,
|
||
|
i.provider as payer_id,
|
||
|
i.subscriber_relationship,
|
||
|
i.subscriber_lname,
|
||
|
i.subscriber_fname,
|
||
|
i.subscriber_mname,
|
||
|
DATE_FORMAT(i.subscriber_dob, '%%Y%%m%%d') as subscriber_dob,
|
||
|
i.policy_number,
|
||
|
i.subscriber_sex,
|
||
|
DATE_FORMAT(i.date,'%%Y%%m%%d') as date,
|
||
|
d.lname as provider_lname,
|
||
|
d.fname as provider_fname,
|
||
|
d.npi as provider_npi,
|
||
|
d.upin as provider_pin,
|
||
|
f.federal_ein as federal_ein,
|
||
|
f.facility_npi as facility_npi,
|
||
|
f.name as facility_name,
|
||
|
c.cms_id as cms_id,
|
||
|
c.eligibility_id as eligibility_id,
|
||
|
c.name as payer_name
|
||
|
FROM openemr_postcalendar_events AS e
|
||
|
LEFT JOIN users AS d on (e.pc_aid is not null and e.pc_aid = d.id)
|
||
|
LEFT JOIN facility AS f on (f.id = e.pc_facility)
|
||
|
LEFT JOIN patient_data AS p ON p.pid = e.pc_pid
|
||
|
LEFT JOIN insurance_data AS i ON (i.id =(SELECT id FROM insurance_data AS i WHERE pid = p.pid AND type = 'primary' ORDER BY date DESC LIMIT 1))
|
||
|
LEFT JOIN insurance_companies as c ON (c.id = i.provider)
|
||
|
WHERE %s ", $where);
|
||
|
|
||
|
// Run the query
|
||
|
$rslt = sqlStatement($query, $sqlBindArray);
|
||
|
$res = [];
|
||
|
while ($row = sqlFetchArray($rslt)) {
|
||
|
foreach ($appts as $tmp) {
|
||
|
if ((int)$tmp['pc_eid'] === (int)$row['pc_eid']) {
|
||
|
$row['pc_eventDate'] = date("Ymd", strtotime($tmp['pc_eventDate']));
|
||
|
}
|
||
|
}
|
||
|
$res[] = $row;
|
||
|
}
|
||
|
// Get the facilities information
|
||
|
$facilities = getUserFacilities($_SESSION['authUserID']);
|
||
|
|
||
|
// Get the Providers information
|
||
|
$providers = EDI270::getUsernames();
|
||
|
|
||
|
//Get the x12 partners information
|
||
|
$clearinghouses = EDI270::getX12Partner();
|
||
|
|
||
|
if (isset($_POST['form_xmit']) && !empty($_POST['form_xmit']) && $res) {
|
||
|
$eFlag = !$GLOBALS['disable_eligibility_log'];
|
||
|
// make the batch request
|
||
|
$log = EDI270::requestRealTimeEligible($res, $X12info, $segTer, $compEleSep, $eFlag);
|
||
|
$e = strpos($log, "Error:");
|
||
|
if ($e !== false) {
|
||
|
$log = text(xlt("One or more transactions failed") .
|
||
|
"\n" . $log . "\n");
|
||
|
}
|
||
|
if ($eFlag) {
|
||
|
$fn = sprintf(
|
||
|
'elig-log_%s_%s.txt',
|
||
|
strtolower(str_replace(' ', '', $X12info['name'])),
|
||
|
date("Y-m-d:H:i:s")
|
||
|
);
|
||
|
$log = str_replace('~', "~\r", $log);
|
||
|
while (@ob_end_flush()) {
|
||
|
}
|
||
|
header('Content-Type: text/plain');
|
||
|
header("Content-Length: " . strlen($log));
|
||
|
header('Content-Disposition: attachment; filename="' . $fn . '"');
|
||
|
ob_start();
|
||
|
echo $log;
|
||
|
exit();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isset($_POST['form_savefile']) && !empty($_POST['form_savefile']) && $res) {
|
||
|
header('Content-Type: text/plain');
|
||
|
header(sprintf(
|
||
|
'Content-Disposition: attachment; filename="batch-elig-270.%s.%s.txt"',
|
||
|
strtolower(str_replace(' ', '', $X12info['name'])),
|
||
|
date("Y-m-d:H:i:s")
|
||
|
));
|
||
|
EDI270::printElig($res, $X12info, $segTer, $compEleSep);
|
||
|
exit;
|
||
|
}
|
||
|
|
||
|
// unique multidimensional array by key
|
||
|
function unique_by_key($source, $key)
|
||
|
{
|
||
|
$i = 0;
|
||
|
$rtn_array = array();
|
||
|
$key_array = array();
|
||
|
|
||
|
foreach ($source as $val) {
|
||
|
if (!in_array($val[$key], $key_array)) {
|
||
|
$key_array[$i] = $val[$key];
|
||
|
$rtn_array[$i] = $val;
|
||
|
}
|
||
|
$i++;
|
||
|
}
|
||
|
return $rtn_array;
|
||
|
}
|
||
|
?>
|
||
|
|
||
|
<html>
|
||
|
|
||
|
<head>
|
||
|
|
||
|
<title><?php echo xlt('Eligibility 270 Inquiry Batch'); ?></title>
|
||
|
|
||
|
<?php Header::setupHeader('datetime-picker'); ?>
|
||
|
|
||
|
<style>
|
||
|
|
||
|
/* specifically include & exclude from printing */
|
||
|
@media print {
|
||
|
#report_parameters {
|
||
|
visibility: hidden;
|
||
|
display: none;
|
||
|
}
|
||
|
#report_parameters_daterange {
|
||
|
visibility: visible;
|
||
|
display: inline;
|
||
|
}
|
||
|
#report_results table {
|
||
|
margin-top: 0px;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* specifically exclude some from the screen */
|
||
|
@media screen {
|
||
|
#report_parameters_daterange {
|
||
|
visibility: hidden;
|
||
|
display: none;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
</style>
|
||
|
|
||
|
<script>
|
||
|
|
||
|
var stringDelete = <?php echo xlj('Do you want to remove this record?'); ?>;
|
||
|
var stringBatch = <?php echo xlj('Please select X12 partner, required to create the 270 batch'); ?>;
|
||
|
|
||
|
// for form refresh
|
||
|
|
||
|
function refreshme() {
|
||
|
document.forms[0].submit();
|
||
|
}
|
||
|
|
||
|
// To delete the row from the reports section
|
||
|
function deletetherow(id){
|
||
|
var suredelete = confirm(stringDelete);
|
||
|
if(suredelete == true){
|
||
|
document.getElementById('PR'+id).style.display="none";
|
||
|
if(document.getElementById('removedrows').value == ""){
|
||
|
document.getElementById('removedrows').value = "'" + id + "'";
|
||
|
}else{
|
||
|
document.getElementById('removedrows').value = document.getElementById('removedrows').value + ",'" + id + "'";
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// To validate the batch file generation - for the required field [clearing house/x12 partner]
|
||
|
function validate_batch(eFlag) {
|
||
|
if (document.getElementById('form_x12').value == '') {
|
||
|
alert(stringBatch);
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
if (eFlag === true) {
|
||
|
document.getElementById('form_xmit').value = "true";
|
||
|
} else {
|
||
|
document.getElementById('form_savefile').value = "true";
|
||
|
}
|
||
|
|
||
|
document.theform.submit();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// To Clear the hidden input field
|
||
|
|
||
|
function validate_policy()
|
||
|
{
|
||
|
document.getElementById('removedrows').value = "";
|
||
|
document.getElementById('form_savefile').value = "";
|
||
|
document.getElementById('form_xmit').value = "";
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// To toggle the clearing house empty validation message
|
||
|
function toggleMessage(id,x12){
|
||
|
|
||
|
var spanstyle = String();
|
||
|
|
||
|
spanstyle = document.getElementById(id).style.visibility;
|
||
|
selectoption = document.getElementById(x12).value;
|
||
|
|
||
|
if(selectoption != '')
|
||
|
{
|
||
|
document.getElementById(id).style.visibility = "hidden";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
document.getElementById(id).style.visibility = "visible";
|
||
|
document.getElementById(id).style.display = "inline";
|
||
|
}
|
||
|
return true;
|
||
|
|
||
|
}
|
||
|
|
||
|
$(function () {
|
||
|
$('.datepicker').datetimepicker({
|
||
|
<?php $datetimepicker_timepicker = false; ?>
|
||
|
<?php $datetimepicker_showseconds = false; ?>
|
||
|
<?php $datetimepicker_formatInput = true; ?>
|
||
|
<?php require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?>
|
||
|
<?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
|
||
|
});
|
||
|
});
|
||
|
|
||
|
</script>
|
||
|
|
||
|
</head>
|
||
|
<body class="body_top">
|
||
|
|
||
|
<!-- Required for the popup date selectors -->
|
||
|
<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
|
||
|
|
||
|
<span class='title'><?php echo xlt('Report'); ?> - <?php echo xlt('Eligibility 270 Inquiry Batch'); ?></span>
|
||
|
|
||
|
<div id="report_parameters_daterange">
|
||
|
<?php echo text(oeFormatShortDate($from_date)) . " " . xlt('to{{Range}}') . " " . text(oeFormatShortDate($to_date)); ?>
|
||
|
</div>
|
||
|
|
||
|
<form method='post' name='theform' id='theform' action='edi_270.php' onsubmit="return top.restoreSession()">
|
||
|
<input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
|
||
|
<input type="hidden" name="removedrows" id="removedrows" value="">
|
||
|
<div id="report_parameters">
|
||
|
<table>
|
||
|
<tr>
|
||
|
<td width='550px'>
|
||
|
<div style='float:left'>
|
||
|
<table class='text'>
|
||
|
<tr>
|
||
|
<td class='col-form-label'>
|
||
|
<?php echo xlt('From'); ?>:
|
||
|
</td>
|
||
|
<td>
|
||
|
<input type='text' class='datepicker form-control' name='form_from_date' id="form_from_date" size='10' value='<?php echo attr(oeFormatShortDate($from_date)); ?>'>
|
||
|
</td>
|
||
|
<td class='col-form-label'>
|
||
|
<?php echo xlt('To{{Range}}'); ?>:
|
||
|
</td>
|
||
|
<td>
|
||
|
<input type='text' class='datepicker form-control' name='form_to_date' id="form_to_date" size='10' value='<?php echo attr(oeFormatShortDate($to_date)); ?>'>
|
||
|
</td>
|
||
|
<td> </td>
|
||
|
</tr>
|
||
|
|
||
|
<tr>
|
||
|
<td class='col-form-label'>
|
||
|
<?php echo xlt('Facility'); ?>:
|
||
|
</td>
|
||
|
<td>
|
||
|
<?php dropdown_facility($form_facility, 'form_facility', false); ?>
|
||
|
</td>
|
||
|
<td class='col-form-label'>
|
||
|
<?php echo xlt('Provider'); ?>:
|
||
|
</td>
|
||
|
<td>
|
||
|
<select name='form_users' class='form-control' onchange='form.submit();'>
|
||
|
<option value=''>-- <?php echo xlt('All'); ?> --</option>
|
||
|
<?php foreach ($providers as $user) : ?>
|
||
|
<option value='<?php echo attr($user['id']); ?>'
|
||
|
<?php echo $form_provider == $user['id'] ? " selected " : null; ?>
|
||
|
><?php echo text($user['fname'] . " " . $user['lname']); ?></option>
|
||
|
<?php endforeach; ?>
|
||
|
</select>
|
||
|
</td>
|
||
|
<td>
|
||
|
</td>
|
||
|
</tr>
|
||
|
|
||
|
<tr>
|
||
|
<td class='col-form-label'>
|
||
|
<?php echo xlt('X12 Partner'); ?>:
|
||
|
</td>
|
||
|
<td colspan='5'>
|
||
|
<select name='form_x12' id='form_x12' class='form-control' onchange='return toggleMessage("emptyVald","form_x12");'>
|
||
|
<option value=''>--<?php echo xlt('select'); ?>--</option>
|
||
|
<?php
|
||
|
if (isset($clearinghouses) && !empty($clearinghouses)) {
|
||
|
foreach ($clearinghouses as $clearinghouse) {
|
||
|
if (!empty($clearinghouse['id'])) {
|
||
|
echo "<option value='" . attr($clearinghouse['id']) . "'" .
|
||
|
(!empty($X12info['id']) && ($clearinghouse['id'] == $X12info['id']) ? " selected " : '') . ">" . text($clearinghouse['name']) . "</option>";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
?>
|
||
|
</select>
|
||
|
<span id='emptyVald' class='text-danger' style='font-size:12px;visibility: <?php echo (!empty($X12info['id'])) ? "hidden" : ""; ?>'> *
|
||
|
<?php echo xlt('Clearing house info required for EDI 270 batch creation.'); ?></span>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</div>
|
||
|
</td>
|
||
|
<td align='left' valign='middle' height="100%">
|
||
|
<table style='border-left:1px solid; width:100%; height:100%' >
|
||
|
<tr>
|
||
|
<td>
|
||
|
<div class="text-center">
|
||
|
<div class="btn-group" role="group">
|
||
|
<a href='#' class='btn btn-secondary btn-refresh' onclick='validate_policy(); $("#theform").submit();'>
|
||
|
<?php echo xlt('Refresh'); ?>
|
||
|
</a>
|
||
|
<a href='#' class='btn btn-secondary btn-transmit' onclick='return validate_batch(false);'>
|
||
|
<?php echo xlt('Create batch'); ?>
|
||
|
<input type='hidden' name='form_savefile' id='form_savefile' value=''></input>
|
||
|
|
||
|
<?php if ($GLOBALS['enable_oa']) {
|
||
|
echo "<a href='#' class='btn btn-secondary btn-transmit' onclick='return validate_batch(true);'>" . xlt('Request Eligibility') . "</a>\n";
|
||
|
}
|
||
|
?>
|
||
|
<input type='hidden' name='form_xmit' id='form_xmit' value=''></input>
|
||
|
</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</div>
|
||
|
<div class='text'>
|
||
|
<?php echo xlt('Please choose date range criteria above, and click Refresh to view results.'); ?>
|
||
|
</div>
|
||
|
|
||
|
</form>
|
||
|
|
||
|
<?php
|
||
|
if ($res) {
|
||
|
EDI270::showElig($res, $X12info, $segTer, $compEleSep);
|
||
|
}
|
||
|
?>
|
||
|
</body>
|
||
|
|
||
|
<script>
|
||
|
<?php
|
||
|
if (!empty($alertmsg)) {
|
||
|
echo " alert(" . js_escape($alertmsg) . ");\n";
|
||
|
} ?>
|
||
|
</script>
|
||
|
|
||
|
</html>
|