Skip to content

Commit

Permalink
various corrections and improvements to remit processing
Browse files Browse the repository at this point in the history
  • Loading branch information
sunsetsystems committed Sep 1, 2006
1 parent 6418e4e commit 5f17434
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 51 deletions.
24 changes: 22 additions & 2 deletions interface/billing/claim_status_codes.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
<?php

// See http:https://www.wpc-edi.com/codes
//
$claim_status_codes = array(
'1' => 'Processed as Primary',
'2' => 'Processed as Secondary',
'3' => 'Processed as Tertiary',
'4' => 'Denied',
'5' => 'Pended',
'11' => 'Received, but not in process',
'13' => 'Suspended',
'15' => 'Suspended - investigation with field',
'16' => 'Suspended - return with material',
'17' => 'Suspended - review pending',
'19' => 'Processed as Primary, Forwarded to Additional Payer(s)',
'20' => 'Processed as Secondary, Forwarded to Additional Payer(s)',
'21' => 'Processed as Tertiary, Forwarded to Additional Payer(s)',
'22' => 'Reversal of Previous Payment',
'23' => 'Not Our Claim, Forwarded to Additional Payer(s)',
'25' => 'Predetermination Pricing Only - No Payment',
'27' => 'Reviewed'

/****
// See http:https://www.wpc-edi.com/codes
//
'0' => 'Cannot provide further status electronically.',
'1' => 'For more detailed information, see remittance advice.',
'2' => 'More detailed information in letter.',
Expand Down Expand Up @@ -660,5 +679,6 @@
'667' => 'Real-Time requests not supported by the information holder, do not resubmit',
'668' => 'Missing Endodontics treatment history and prognosis',
'669' => 'Dental service narrative needed.'
****/
);
?>
90 changes: 70 additions & 20 deletions interface/billing/sl_eob_process.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ function writeOldDetail(&$prev, $ptname, $invnumber, $dos, $code, $bgcolor) {
//
function era_callback(&$out) {
global $encount, $debug, $claim_status_codes, $adjustment_reasons, $remark_codes;
global $invoice_total;
// print_r($out); // debugging
global $invoice_total, $last_code;

// Some heading information.
if ($encount == 0) {
Expand All @@ -116,6 +115,7 @@ function era_callback(&$out) {
}
}

$last_code = '';
$invoice_total = 0.00;
$bgcolor = (++$encount & 1) ? "#ddddff" : "#ffdddd";
list($pid, $encounter, $invnumber) = slInvoiceNumber($out);
Expand All @@ -139,8 +139,20 @@ function era_callback(&$out) {
}
}

$insurance_id = 0;
foreach ($codes as $cdata) {
if ($cdata['ins']) {
$insurance_id = $cdata['ins'];
break;
}
}

// Show the claim status.
$csc = $out['claim_status_code'];
$inslabel = 'Ins1';
if ($csc == '1' || $csc == '19') $inslabel = 'Ins1';
if ($csc == '2' || $csc == '20') $inslabel = 'Ins2';
if ($csc == '3' || $csc == '21') $inslabel = 'Ins3';
writeMessageLine($bgcolor, 'infdetail',
"Claim status $csc: " . $claim_status_codes[$csc]);

Expand All @@ -150,12 +162,14 @@ function era_callback(&$out) {
"The following claim is not in our database");
}
else {
$insdone = strtolower($arrow['shipvia']);
if (strpos($insdone, 'ins1') !== false) {
$inverror = true;
writeMessageLine($bgcolor, 'errdetail',
"Primary insurance EOB was already posted for the following claim");
}
// Skip this test. Claims can get multiple CLPs from the same payer!
//
// $insdone = strtolower($arrow['shipvia']);
// if (strpos($insdone, 'ins1') !== false) {
// $inverror = true;
// writeMessageLine($bgcolor, 'errdetail',
// "Primary insurance EOB was already posted for the following claim");
// }
}

if ($out['warnings']) {
Expand All @@ -169,9 +183,10 @@ function era_callback(&$out) {
$patient_name = $arrow['name'] ? $arrow['name'] :
($out['patient_fname'] . ' ' . $out['patient_lname']);

$error = $inverror;

// This loops once for each service item in this claim.
foreach ($out['svc'] as $svc) {
$error = $inverror;
$prev = $codes[$svc['code']];

// This reports detail lines already on file for this service item.
Expand All @@ -184,7 +199,14 @@ function era_callback(&$out) {
"EOB charge amount " . $svc['chg'] . " for this code does not match our invoice");
$error = true;
}

// Check for duplicate payment. Should not happen.
//
// This is not right. What we want to do is check if we have
// any payments or adjustments from this payer for this service item,
// and produce an error if so. The point is that a duplicated claim
// submission may not give the same results as the original.
/****
foreach ($prev['dtl'] as $dkey => $ddata) {
if (! $ddata['pmt']) continue;
$ddate = parse_date($dkey);
Expand All @@ -194,17 +216,43 @@ function era_callback(&$out) {
$error = true;
}
}
****/
// The following replaces the above.
if ((sprintf("%.2f",$prev['chg']) != sprintf("%.2f",$prev['bal']) ||
$prev['adj'] != 0) && $inslabel == 'Ins1')
{
writeMessageLine($bgcolor, 'errdetail',
"This service item already has payments and/or adjustments!");
$error = true;
}

unset($codes[$svc['code']]);
}

// Or if the service item is not in our database, show it in red for
// manual resolution. Probably what happened is that the billing was
// "corrected" in OpenEMR after the claim was generated... not good!
// If the service item is not in our database...
else {

/****
writeDetailLine($bgcolor, 'errdetail', $patient_name, $invnumber,
$svc['code'], $service_date, '*** UNMATCHED SERVICE ITEM ***',
$svc['chg'], '');
$error = true;
****/

// No, this is not an error. Instead, if we are not in error mode
// insert the service item into SL. Then display it (in green if it
// was inserted, or in red if we are in error mode).
$description = 'CPT4:' . $svc['code'] . " Added by $inslabel $production_date";
if (!$error && !$debug) {
slPostCharge($arrow['id'], $svc['chg'], $service_date, $svc['code'],
$insurance_id, $description, $debug);
$invoice_total += $svc['chg'];
}
$class = $error ? 'errdetail' : 'newdetail';
writeDetailLine($bgcolor, $class, $patient_name, $invnumber,
$svc['code'], $production_date, $description,
$svc['chg'], ($error ? '' : $invoice_total));

}

$class = $error ? 'errdetail' : 'newdetail';
Expand Down Expand Up @@ -239,11 +287,11 @@ function era_callback(&$out) {
if ($svc['paid']) {
if (!$error && !$debug) {
slPostPayment($arrow['id'], $svc['paid'], $check_date,
'Ins1/' . $out['check_number'], $svc['code'], $prev['ins'], $debug);
"$inslabel/" . $out['check_number'], $svc['code'], $insurance_id, $debug);
$invoice_total -= $svc['paid'];
}
writeDetailLine($bgcolor, $class, $patient_name, $invnumber,
$svc['code'], $check_date, 'Ins1/' . $out['check_number'] . ' payment',
$svc['code'], $check_date, "$inslabel/" . $out['check_number'] . ' payment',
0 - $svc['paid'], ($error ? '' : $invoice_total));
}

Expand All @@ -261,7 +309,7 @@ function era_callback(&$out) {
$reason .= sprintf("%.2f", $adj['amount']);
if (!$error && !$debug) {
slPostAdjustment($arrow['id'], 0, $production_date,
$out['check_number'], $svc['code'], $prev['ins'],
$out['check_number'], $svc['code'], $insurance_id,
$reason, $debug);
}
writeMessageLine($bgcolor, $class, $description . ' ' .
Expand All @@ -271,8 +319,8 @@ function era_callback(&$out) {
else {
if (!$error && !$debug) {
slPostAdjustment($arrow['id'], $adj['amount'], $production_date,
$out['check_number'], $svc['code'], $prev['ins'],
'Ins1 adjust code ' . $adj['reason_code'], $debug);
$out['check_number'], $svc['code'], $insurance_id,
"$inslabel adjust code " . $adj['reason_code'], $debug);
$invoice_total -= $adj['amount'];
}
writeDetailLine($bgcolor, $class, $patient_name, $invnumber,
Expand All @@ -290,13 +338,15 @@ function era_callback(&$out) {

// Cleanup: If all is well, mark Ins1 done and check for secondary billing.
if (!$error && !$debug) {
// Mark Ins1 done.
$query = "UPDATE ar SET shipvia = 'Done: Ins1' WHERE id = " . $arrow['id'];
$shipvia = 'Done: Ins1';
if ($inslabel != 'Ins1') $shipvia .= ',Ins2';
if ($inslabel == 'Ins3') $shipvia .= ',Ins3';
$query = "UPDATE ar SET shipvia = '$shipvia' WHERE id = " . $arrow['id'];
SLQuery($query);
if ($sl_err) die($sl_err);
// Check for secondary insurance.
$insgot = strtolower($arrow['notes']);
if (strpos($insgot, 'ins2') !== false) {
if ($inslabel == 'Ins1' && strpos($insgot, 'ins2') !== false) {
slSetupSecondary($arrow['id'], $debug);
writeMessageLine($bgcolor, 'infdetail',
'This claim is now re-queued for secondary paper billing');
Expand Down
7 changes: 5 additions & 2 deletions library/invoice_summary.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function get_invoice_summary($trans_id, $with_detail = false) {
// Request all line items with money or adjustment reasons belonging
// to the invoice.
$inres = SLQuery("SELECT * FROM invoice WHERE trans_id = $trans_id AND " .
"( sellprice != 0 OR description LIKE 'Adjustment%' )");
"( sellprice != 0 OR description LIKE 'Adjustment%' OR serialnumber = 'Claim' )");
if ($sl_err) die($sl_err);

// Add charges and adjustments for each procedure code into its total and balance.
Expand All @@ -76,7 +76,10 @@ function get_invoice_summary($trans_id, $with_detail = false) {
$ins_id = $row['project_id'];

$code = "Unknown";
if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['serialnumber'], $matches)) {
if ($row['serialnumber'] == 'Claim') {
$code = 'Claim';
}
else if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['serialnumber'], $matches)) {
$code = strtoupper($matches[1]);
}
else if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['description'], $matches)) {
Expand Down
Loading

0 comments on commit 5f17434

Please sign in to comment.