Esempio n. 1
0
function era_callback(&$out)
{
    global $encount, $debug, $claim_status_codes, $adjustment_reasons, $remark_codes;
    global $invoice_total, $last_code, $paydate, $INTEGRATED_AR;
    global $InsertionId;
    //last inserted ID of
    // Some heading information.
    $chk_123 = $out['check_number'];
    $chk_123 = str_replace(' ', '_', $chk_123);
    if (isset($_REQUEST['chk' . $chk_123])) {
        if ($encount == 0) {
            writeMessageLine('#ffffff', 'infdetail', "Payer: " . htmlspecialchars($out['payer_name'], ENT_QUOTES));
            if ($debug) {
                writeMessageLine('#ffffff', 'infdetail', "WITHOUT UPDATE is selected; no changes will be applied.");
            }
        }
        $last_code = '';
        $invoice_total = 0.0;
        $bgcolor = ++$encount & 1 ? "#ddddff" : "#ffdddd";
        list($pid, $encounter, $invnumber) = slInvoiceNumber($out);
        // Get details, if we have them, for the invoice.
        $inverror = true;
        $codes = array();
        if ($pid && $encounter) {
            // Get invoice data into $arrow or $ferow.
            if ($INTEGRATED_AR) {
                $ferow = sqlQuery("SELECT e.*, p.fname, p.mname, p.lname " . "FROM form_encounter AS e, patient_data AS p WHERE " . "e.pid = '{$pid}' AND e.encounter = '{$encounter}' AND " . "p.pid = e.pid");
                if (empty($ferow)) {
                    $pid = $encounter = 0;
                    $invnumber = $out['our_claim_id'];
                } else {
                    $inverror = false;
                    $codes = ar_get_invoice_summary($pid, $encounter, true);
                    // $svcdate = substr($ferow['date'], 0, 10);
                }
            } else {
                $arres = SLQuery("SELECT ar.id, ar.notes, ar.shipvia, customer.name " . "FROM ar, customer WHERE ar.invnumber = '{$invnumber}' AND " . "customer.id = ar.customer_id");
                if ($sl_err) {
                    die($sl_err);
                }
                $arrow = SLGetRow($arres, 0);
                if ($arrow) {
                    $inverror = false;
                    $codes = get_invoice_summary($arrow['id'], true);
                } else {
                    // oops, no such invoice
                    $pid = $encounter = 0;
                    $invnumber = $out['our_claim_id'];
                }
            }
            // end not internal a/r
        }
        // 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';
        }
        $primary = $inslabel == 'Ins1';
        writeMessageLine($bgcolor, 'infdetail', "Claim status {$csc}: " . $claim_status_codes[$csc]);
        // Show an error message if the claim is missing or already posted.
        if ($inverror) {
            writeMessageLine($bgcolor, 'errdetail', "The following claim is not in our database");
        } else {
            // 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 ($csc == '4') {
            //Denial case, code is stored in the claims table for display in the billing manager screen with reason explained.
            $inverror = true;
            if (!$debug) {
                if ($pid && $encounter) {
                    $code_value = '';
                    foreach ($out['svc'] as $svc) {
                        foreach ($svc['adj'] as $adj) {
                            //Per code and modifier the reason will be showed in the billing manager.
                            $code_value .= $svc['code'] . '_' . $svc['mod'] . '_' . $adj['group_code'] . '_' . $adj['reason_code'] . ',';
                        }
                    }
                    $code_value = substr($code_value, 0, -1);
                    //We store the reason code to display it with description in the billing manager screen.
                    //process_file is used as for the denial case file name will not be there, and extra field(to store reason) can be avoided.
                    updateClaim(true, $pid, $encounter, $_REQUEST['InsId'], substr($inslabel, 3), 7, 0, $code_value);
                }
            }
            writeMessageLine($bgcolor, 'errdetail', "Not posting adjustments for denied claims, please follow up manually!");
        } else {
            if ($csc == '22') {
                $inverror = true;
                writeMessageLine($bgcolor, 'errdetail', "Payment reversals are not automated, please enter manually!");
            }
        }
        if ($out['warnings']) {
            writeMessageLine($bgcolor, 'infdetail', nl2br(rtrim($out['warnings'])));
        }
        // Simplify some claim attributes for cleaner code.
        $service_date = parse_date($out['dos']);
        $check_date = $paydate ? $paydate : parse_date($out['check_date']);
        $production_date = $paydate ? $paydate : parse_date($out['production_date']);
        if ($INTEGRATED_AR) {
            $insurance_id = arGetPayerID($pid, $service_date, substr($inslabel, 3));
            if (empty($ferow['lname'])) {
                $patient_name = $out['patient_fname'] . ' ' . $out['patient_lname'];
            } else {
                $patient_name = $ferow['fname'] . ' ' . $ferow['lname'];
            }
        } else {
            $insurance_id = 0;
            foreach ($codes as $cdata) {
                if ($cdata['ins']) {
                    $insurance_id = $cdata['ins'];
                    break;
                }
            }
            $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) {
            // Treat a modifier in the remit data as part of the procedure key.
            // This key will then make its way into SQL-Ledger.
            $codekey = $svc['code'];
            if ($svc['mod']) {
                $codekey .= ':' . $svc['mod'];
            }
            $prev = $codes[$codekey];
            $codetype = '';
            //will hold code type, if exists
            // This reports detail lines already on file for this service item.
            if ($prev) {
                $codetype = $codes[$codekey]['code_type'];
                //store code type
                writeOldDetail($prev, $patient_name, $invnumber, $service_date, $codekey, $bgcolor);
                // Check for sanity in amount charged.
                $prevchg = sprintf("%.2f", $prev['chg'] + $prev['adj']);
                if ($prevchg != abs($svc['chg'])) {
                    writeMessageLine($bgcolor, 'errdetail', "EOB charge amount " . $svc['chg'] . " for this code does not match our invoice");
                    $error = true;
                }
                // Check for already-existing primary remittance activity.
                // Removed this check because it was not allowing for copays manually
                // entered into the invoice under a non-copay billing code.
                /****
                   if ((sprintf("%.2f",$prev['chg']) != sprintf("%.2f",$prev['bal']) ||
                       $prev['adj'] != 0) && $primary)
                   {
                       writeMessageLine($bgcolor, 'errdetail',
                           "This service item already has primary payments and/or adjustments!");
                       $error = true;
                   }
                   ****/
                unset($codes[$codekey]);
            } else {
                // This is not an error. If we are not in error mode and not debugging,
                // 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:{$codekey} Added by {$inslabel} {$production_date}";
                if (!$error && !$debug) {
                    if ($INTEGRATED_AR) {
                        arPostCharge($pid, $encounter, 0, $svc['chg'], 1, $service_date, $codekey, $description, $debug, '', $codetype);
                    } else {
                        slPostCharge($arrow['id'], $svc['chg'], 1, $service_date, $codekey, $insurance_id, $description, $debug);
                    }
                    $invoice_total += $svc['chg'];
                }
                $class = $error ? 'errdetail' : 'newdetail';
                writeDetailLine($bgcolor, $class, $patient_name, $invnumber, $codekey, $production_date, $description, $svc['chg'], $error ? '' : $invoice_total);
            }
            $class = $error ? 'errdetail' : 'newdetail';
            // Report Allowed Amount.
            if ($svc['allowed']) {
                // A problem here is that some payers will include an adjustment
                // reflecting the allowed amount, others not.  So here we need to
                // check if the adjustment exists, and if not then create it.  We
                // assume that any nonzero CO (Contractual Obligation) or PI
                // (Payer Initiated) adjustment is good enough.
                $contract_adj = sprintf("%.2f", $svc['chg'] - $svc['allowed']);
                foreach ($svc['adj'] as $adj) {
                    if (($adj['group_code'] == 'CO' || $adj['group_code'] == 'PI') && $adj['amount'] != 0) {
                        $contract_adj = 0;
                    }
                }
                if ($contract_adj > 0) {
                    $svc['adj'][] = array('group_code' => 'CO', 'reason_code' => 'A2', 'amount' => $contract_adj);
                }
                writeMessageLine($bgcolor, 'infdetail', 'Allowed amount is ' . sprintf("%.2f", $svc['allowed']));
            }
            // Report miscellaneous remarks.
            if ($svc['remark']) {
                $rmk = $svc['remark'];
                writeMessageLine($bgcolor, 'infdetail', "{$rmk}: " . $remark_codes[$rmk]);
            }
            // Post and report the payment for this service item from the ERA.
            // By the way a 'Claim' level payment is probably going to be negative,
            // i.e. a payment reversal.
            if ($svc['paid']) {
                if (!$error && !$debug) {
                    if ($INTEGRATED_AR) {
                        arPostPayment($pid, $encounter, $InsertionId[$out['check_number']], $svc['paid'], $codekey, substr($inslabel, 3), $out['check_number'], $debug, '', $codetype);
                    } else {
                        slPostPayment($arrow['id'], $svc['paid'], $check_date, "{$inslabel}/" . $out['check_number'], $codekey, $insurance_id, $debug);
                    }
                    $invoice_total -= $svc['paid'];
                }
                $description = "{$inslabel}/" . $out['check_number'] . ' payment';
                if ($svc['paid'] < 0) {
                    $description .= ' reversal';
                }
                writeDetailLine($bgcolor, $class, $patient_name, $invnumber, $codekey, $check_date, $description, 0 - $svc['paid'], $error ? '' : $invoice_total);
            }
            // Post and report adjustments from this ERA.  Posted adjustment reasons
            // must be 25 characters or less in order to fit on patient statements.
            foreach ($svc['adj'] as $adj) {
                $description = $adj['reason_code'] . ': ' . $adjustment_reasons[$adj['reason_code']];
                if ($adj['group_code'] == 'PR' || !$primary) {
                    // Group code PR is Patient Responsibility.  Enter these as zero
                    // adjustments to retain the note without crediting the claim.
                    if ($primary) {
                        /****
                                       $reason = 'Pt resp: '; // Reasons should be 25 chars or less.
                                       if ($adj['reason_code'] == '1') $reason = 'To deductible: ';
                                       else if ($adj['reason_code'] == '2') $reason = 'Coinsurance: ';
                                       else if ($adj['reason_code'] == '3') $reason = 'Co-pay: ';
                           ****/
                        $reason = "{$inslabel} ptresp: ";
                        // Reasons should be 25 chars or less.
                        if ($adj['reason_code'] == '1') {
                            $reason = "{$inslabel} dedbl: ";
                        } else {
                            if ($adj['reason_code'] == '2') {
                                $reason = "{$inslabel} coins: ";
                            } else {
                                if ($adj['reason_code'] == '3') {
                                    $reason = "{$inslabel} copay: ";
                                }
                            }
                        }
                    } else {
                        $reason = "{$inslabel} note " . $adj['reason_code'] . ': ';
                        /****
                                       $reason .= sprintf("%.2f", $adj['amount']);
                           ****/
                    }
                    $reason .= sprintf("%.2f", $adj['amount']);
                    // Post a zero-dollar adjustment just to save it as a comment.
                    if (!$error && !$debug) {
                        if ($INTEGRATED_AR) {
                            arPostAdjustment($pid, $encounter, $InsertionId[$out['check_number']], 0, $codekey, substr($inslabel, 3), $reason, $debug, '', $codetype);
                        } else {
                            slPostAdjustment($arrow['id'], 0, $production_date, $out['check_number'], $codekey, $insurance_id, $reason, $debug);
                        }
                    }
                    writeMessageLine($bgcolor, $class, $description . ' ' . sprintf("%.2f", $adj['amount']));
                } else {
                    if (!$error && !$debug) {
                        if ($INTEGRATED_AR) {
                            arPostAdjustment($pid, $encounter, $InsertionId[$out['check_number']], $adj['amount'], $codekey, substr($inslabel, 3), "Adjust code " . $adj['reason_code'], $debug, '', $codetype);
                        } else {
                            slPostAdjustment($arrow['id'], $adj['amount'], $production_date, $out['check_number'], $codekey, $insurance_id, "{$inslabel} adjust code " . $adj['reason_code'], $debug);
                        }
                        $invoice_total -= $adj['amount'];
                    }
                    writeDetailLine($bgcolor, $class, $patient_name, $invnumber, $codekey, $production_date, $description, 0 - $adj['amount'], $error ? '' : $invoice_total);
                }
            }
        }
        // End of service item
        // Report any existing service items not mentioned in the ERA, and
        // determine if any of them are still missing an insurance response
        // (if so, then insurance is not yet done with the claim).
        $insurance_done = true;
        foreach ($codes as $code => $prev) {
            // writeOldDetail($prev, $arrow['name'], $invnumber, $service_date, $code, $bgcolor);
            writeOldDetail($prev, $patient_name, $invnumber, $service_date, $code, $bgcolor);
            $got_response = false;
            foreach ($prev['dtl'] as $ddata) {
                if ($ddata['pmt'] || $ddata['rsn']) {
                    $got_response = true;
                }
            }
            if (!$got_response) {
                $insurance_done = false;
            }
        }
        // Cleanup: If all is well, mark Ins<x> done and check for secondary billing.
        if (!$error && !$debug && $insurance_done) {
            if ($INTEGRATED_AR) {
                $level_done = 0 + substr($inslabel, 3);
                if ($out['crossover'] == 1) {
                    //Automatic forward case.So need not again bill from the billing manager screen.
                    sqlStatement("UPDATE form_encounter " . "SET last_level_closed = {$level_done},last_level_billed=" . $level_done . " WHERE " . "pid = '{$pid}' AND encounter = '{$encounter}'");
                    writeMessageLine($bgcolor, 'infdetail', 'This claim is processed by Insurance ' . $level_done . ' and automatically forwarded to Insurance ' . ($level_done + 1) . ' for processing. ');
                } else {
                    "UPDATE form_encounter " . "SET last_level_closed = {$level_done} WHERE " . "pid = '{$pid}' AND encounter = '{$encounter}'";
                }
                // Check for secondary insurance.
                if ($primary && arGetPayerID($pid, $service_date, 2)) {
                    arSetupSecondary($pid, $encounter, $debug, $out['crossover']);
                    if ($out['crossover'] != 1) {
                        writeMessageLine($bgcolor, 'infdetail', 'This claim is now re-queued for secondary paper billing');
                    }
                }
            } else {
                $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 ($primary && strpos($insgot, 'ins2') !== false) {
                    slSetupSecondary($arrow['id'], $debug);
                    if ($out['crossover'] != 1) {
                        writeMessageLine($bgcolor, 'infdetail', 'This claim is now re-queued for secondary paper billing');
                    }
                }
            }
        }
    }
}
Esempio n. 2
0
function slSetupSecondary($invid, $debug)
{
    global $sl_err, $GLOBALS;
    if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2) {
        die("Internal error calling slSetupSecondary()");
    }
    $info_msg = '';
    // Get some needed items from the SQL-Ledger invoice.
    $arres = SLQuery("select invnumber, transdate, customer_id, employee_id, " . "shipvia from ar where ar.id = {$invid}");
    if ($sl_err) {
        die($sl_err);
    }
    $arrow = SLGetRow($arres, 0);
    if (!$arrow) {
        die(xl('There is no match for invoice id') . ' = ' . "{$trans_id}.");
    }
    $customer_id = $arrow['customer_id'];
    $date_of_service = $arrow['transdate'];
    list($trash, $encounter) = explode(".", $arrow['invnumber']);
    // Get the OpenEMR PID corresponding to the customer.
    $pdrow = sqlQuery("SELECT patient_data.pid " . "FROM integration_mapping, patient_data WHERE " . "integration_mapping.foreign_id = {$customer_id} AND " . "integration_mapping.foreign_table = 'customer' AND " . "patient_data.id = integration_mapping.local_id");
    $pid = $pdrow['pid'];
    if (!$pid) {
        die(xl("Cannot find patient from SQL-Ledger customer id") . " = {$customer_id}.");
    }
    // Determine the ID of the next insurance company (if any) to be billed.
    $new_payer_id = -1;
    $new_payer_type = -1;
    $insdone = strtolower($arrow['shipvia']);
    foreach (array('ins1' => 'primary', 'ins2' => 'secondary', 'ins3' => 'tertiary') as $key => $value) {
        if (strpos($insdone, $key) === false) {
            $nprow = sqlQuery("SELECT provider FROM insurance_data WHERE " . "pid = '{$pid}' AND type = '{$value}' AND date <= '{$date_of_service}' " . "ORDER BY date DESC LIMIT 1");
            if (!empty($nprow['provider'])) {
                $new_payer_id = $nprow['provider'];
                $new_payer_type = substr($key, 3);
            }
            break;
        }
    }
    // Find out if the encounter exists.
    $ferow = sqlQuery("SELECT pid FROM form_encounter WHERE " . "encounter = {$encounter}");
    $encounter_pid = $ferow['pid'];
    // If it exists, just update the billing items.
    if ($encounter_pid) {
        if ($encounter_pid != $pid) {
            die(xl("Expected form_encounter.pid to be ") . $pid . ', ' . xl(' but was ') . $encounter_pid);
        }
        // If there's a payer ID queue it up, otherwise just reopen it.
        if ($new_payer_id > 0) {
            // TBD: implement a default bill_process and target in config.php,
            // it should not really be hard-coded here.
            if (!$debug) {
                updateClaim(true, $pid, $encounter, $new_payer_id, $new_payer_type, 1, 5, '', 'hcfa');
            }
        } else {
            if (!$debug) {
                updateClaim(true, $pid, $encounter, -1, -1, 1, 0, '');
            }
        }
        $info_msg = xl("Encounter ") . $encounter . xl(" is ready for re-billing.");
        return;
    }
    // If we get here then the encounter does not already exist.  This should
    // only happen if A/R was converted from an earlier system.  In this case
    // the encounter ID should be the date of service, and we will create the
    // encounter.
    // If it does not exist then it better be (or start with) a date.
    if (!preg_match("/^20\\d\\d\\d\\d\\d\\d/", $encounter)) {
        die(xl("Internal error: encounter '") . $encounter . xl("' should exist but does not."));
    }
    $employee_id = $arrow['employee_id'];
    // Get the OpenEMR provider info corresponding to the SQL-Ledger salesman.
    $drrow = sqlQuery("SELECT users.id, users.username, users.facility_id " . "FROM integration_mapping, users WHERE " . "integration_mapping.foreign_id = {$employee_id} AND " . "integration_mapping.foreign_table = 'salesman' AND " . "users.id = integration_mapping.local_id");
    $provider_id = $drrow['id'];
    if (!$provider_id) {
        die(xl("Cannot find provider from SQL-Ledger employee = ") . $employee_id);
    }
    if (!$date_of_service) {
        die(xl("Invoice has no date!"));
    }
    // Generate a new encounter number.
    $conn = $GLOBALS['adodb']['db'];
    $new_encounter = $conn->GenID("sequences");
    // Create the "new encounter".
    $encounter_id = 0;
    $query = "INSERT INTO form_encounter ( " . "date, reason, facility_id, pid, encounter, onset_date, provider_id " . ") VALUES ( " . "'{$date_of_service}', " . "'" . xl('Imported from Accounting') . "', " . "'" . addslashes($drrow['facility_id']) . "', " . "{$pid}, " . "{$new_encounter}, " . "'{$date_of_service}', " . "'{$provider_id}' " . ")";
    if ($debug) {
        echo $query . "<br>\n";
        echo xl("Call to addForm() goes here.<br>") . "\n";
    } else {
        $encounter_id = idSqlStatement($query);
        if (!$encounter_id) {
            die(xl("Insert failed: ") . $query);
        }
        addForm($new_encounter, xl("New Patient Encounter"), $encounter_id, "newpatient", $pid, 1, $date_of_service);
        $info_msg = xl("Encounter ") . $new_encounter . xl(" has been created. ");
    }
    // For each invoice line item with a billing code we will insert
    // a billing row with payer_id set to -1.  Order the line items
    // chronologically so that each procedure code will be followed by
    // its associated icd9 code.
    $inres = SLQuery("SELECT * FROM invoice WHERE trans_id = {$invid} " . "ORDER BY id");
    if ($sl_err) {
        die($sl_err);
    }
    // When nonzero, this will be the ID of a billing row that needs to
    // have its justify field set.
    $proc_ins_id = 0;
    for ($irow = 0; $irow < SLRowCount($inres); ++$irow) {
        $row = SLGetRow($inres, $irow);
        $amount = sprintf('%01.2f', $row['sellprice'] * $row['qty']);
        // Extract the billing code.
        $code = xl("Unknown");
        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)) {
                $code = strtoupper($matches[1]);
            }
        }
        list($code, $modifier) = explode("-", $code);
        // Set the billing code type and description.
        $code_type = "";
        $code_text = "";
        foreach ($code_types as $key => $value) {
            if (preg_match("/{$key}/", $row['serialnumber'])) {
                $code_type = $key;
                if ($value['fee']) {
                    $code_text = xl("Procedure") . " {$code}";
                } else {
                    $code_text = xl("Diagnosis") . " {$code}";
                    if ($proc_ins_id) {
                        $query = "UPDATE billing SET justify = '{$code}' WHERE id = {$proc_ins_id}";
                        if ($debug) {
                            echo $query . "<br>\n";
                        } else {
                            sqlQuery($query);
                        }
                        $proc_ins_id = 0;
                    }
                }
                break;
            }
        }
        // Skip adjustments.
        if (!$code_type) {
            continue;
        }
        // Insert the billing item.  If this for a procedure code then save
        // the row ID so that we can update the "justify" field with the ICD9
        // code, which should come next in the loop.
        //
        $query = "INSERT INTO billing ( " . "date, code_type, code, pid, provider_id, user, groupname, authorized, " . "encounter, code_text, activity, payer_id, billed, bill_process, " . "bill_date, modifier, units, fee, justify, target " . ") VALUES ( " . "NOW(), " . "'{$code_type}', " . "'{$code}', " . "{$pid}, " . "0, " . "'" . $_SESSION['authId'] . "', " . "'" . $_SESSION['authProvider'] . "', " . "1, " . "{$new_encounter}, " . "'{$code_text}', " . "1, " . "{$new_payer_id}, " . ($new_payer_id > 0 ? "1, " : "0, ") . ($new_payer_id > 0 ? "5, " : "0, ") . ($new_payer_id > 0 ? "NOW(), " : "NULL, ") . "'{$modifier}', " . "0, " . "{$amount}, " . "'', " . ($new_payer_id > 0 ? "'hcfa' " : "NULL ") . ")";
        if ($debug) {
            echo $query . "<br>\n";
        } else {
            $proc_ins_id = idSqlStatement($query);
            if ($code_type != "CPT4" && $code_type != "HCPCS") {
                $proc_ins_id = 0;
            }
        }
    }
    // Finally, change this invoice number to contain the new encounter number.
    //
    $new_invnumber = "{$pid}.{$new_encounter}";
    $query = "UPDATE ar SET invnumber = '{$new_invnumber}' WHERE id = {$invid}";
    if ($debug) {
        echo $query . "<br>\n";
    } else {
        SLQuery($query);
        if ($sl_err) {
            die($sl_err);
        }
        $info_msg .= xl("This invoice number has been changed to ") . $new_invnumber;
    }
    return $info_msg;
}
Esempio n. 3
0
function process_form($ar)
{
    global $bill_info, $webserver_root, $bat_filename, $pdf;
    if (isset($ar['bn_x12']) || isset($ar['bn_x12_encounter']) || isset($ar['bn_process_hcfa']) || isset($ar['bn_hcfa_txt_file'])) {
        $hlog = fopen("{$webserver_root}/library/freeb/process_bills.log", 'w');
    }
    if (isset($ar['bn_external'])) {
        // Open external billing file for output.
        $be = new BillingExport();
    }
    $db = $GLOBALS['adodb']['db'];
    if (empty($ar['claims'])) {
        $ar['claims'] = array();
    }
    $claim_count = 0;
    foreach ($ar['claims'] as $claimid => $claim_array) {
        $ta = split("-", $claimid);
        $patient_id = $ta[0];
        $encounter = $ta[1];
        $payer_id = substr($claim_array['payer'], 1);
        $payer_type = substr($claim_array['payer'], 0, 1);
        $payer_type = $payer_type == 'T' ? 3 : $payer_type == 'S' ? 2 : 1;
        if (isset($claim_array['bill'])) {
            if (isset($ar['bn_external'])) {
                // Write external claim.
                $be->addClaim($patient_id, $encounter);
            } else {
                $sql = "SELECT x.processing_format from x12_partners as x where x.id =" . $db->qstr($claim_array['partner']);
                $result = $db->Execute($sql);
                $target = "x12";
                if ($result && !$result->EOF) {
                    $target = $result->fields['processing_format'];
                }
            }
            $tmp = 1;
            if (isset($ar['HiddenMarkAsCleared']) && $ar['HiddenMarkAsCleared'] == 'yes') {
                $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 2);
                // $sql .= " billed = 1, ";
            }
            if (isset($ar['bn_x12']) || isset($ar['bn_x12_encounter'])) {
                $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 1, 1, '', $target, $claim_array['partner']);
            } else {
                if (isset($ar['bn_process_hcfa']) || isset($ar['bn_hcfa_txt_file'])) {
                    $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 1, 1, '', 'hcfa');
                } else {
                    if (isset($ar['bn_mark'])) {
                        // $sql .= " billed = 1, ";
                        $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 2);
                    } else {
                        if (isset($ar['bn_reopen'])) {
                            $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 1, 0);
                        } else {
                            if (isset($ar['bn_external'])) {
                                // $sql .= " billed = 1, ";
                                $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 2);
                            }
                        }
                    }
                }
            }
            if (!$tmp) {
                die(xl("Claim ") . $claimid . xl(" update failed, not in database?"));
            } else {
                if (isset($ar['bn_mark'])) {
                    $bill_info[] = xl("Claim ") . $claimid . xl(" was marked as billed only.") . "\n";
                } else {
                    if (isset($ar['bn_reopen'])) {
                        $bill_info[] = xl("Claim ") . $claimid . xl(" has been re-opened.") . "\n";
                    } else {
                        if (isset($ar['bn_x12']) || isset($ar['bn_x12_encounter'])) {
                            $log = '';
                            $segs = explode("~\n", gen_x12_837($patient_id, $encounter, $log, isset($ar['bn_x12_encounter'])));
                            fwrite($hlog, $log);
                            append_claim($segs);
                            if (!updateClaim(false, $patient_id, $encounter, -1, -1, 2, 2, $bat_filename)) {
                                $bill_info[] = xl("Internal error: claim ") . $claimid . xl(" not found!") . "\n";
                            }
                        } else {
                            if (isset($ar['bn_process_hcfa'])) {
                                $log = '';
                                $lines = gen_hcfa_1500($patient_id, $encounter, $log);
                                fwrite($hlog, $log);
                                $alines = explode("\f", $lines);
                                // form feeds may separate pages
                                foreach ($alines as $tmplines) {
                                    if ($claim_count++) {
                                        $pdf->ezNewPage();
                                    }
                                    $pdf->ezSetY($pdf->ez['pageHeight'] - $pdf->ez['topMargin']);
                                    $pdf->ezText($tmplines, 12, array('justification' => 'left', 'leading' => 12));
                                }
                                if (!updateClaim(false, $patient_id, $encounter, -1, -1, 2, 2, $bat_filename)) {
                                    $bill_info[] = xl("Internal error: claim ") . $claimid . xl(" not found!") . "\n";
                                }
                            } else {
                                if (isset($ar['bn_hcfa_txt_file'])) {
                                    $log = '';
                                    $lines = gen_hcfa_1500($patient_id, $encounter, $log);
                                    fwrite($hlog, $log);
                                    $bat_content .= $lines;
                                    if (!updateClaim(false, $patient_id, $encounter, -1, -1, 2, 2, $bat_filename)) {
                                        $bill_info[] = xl("Internal error: claim ") . $claimid . xl(" not found!") . "\n";
                                    }
                                } else {
                                    $bill_info[] = xl("Claim ") . $claimid . xl(" was queued successfully.") . "\n";
                                }
                            }
                        }
                    }
                }
            }
        }
        // end if this claim has billing
    }
    // end foreach
    if (isset($ar['bn_x12']) || isset($ar['bn_x12_encounter'])) {
        append_claim_close();
        fclose($hlog);
        send_batch();
        exit;
    }
    if (isset($ar['bn_process_hcfa'])) {
        fclose($hlog);
        // If a writable edi directory exists (and it should), write the pdf to it.
        $fh = @fopen($GLOBALS['OE_SITE_DIR'] . "/edi/{$bat_filename}", 'a');
        if ($fh) {
            fwrite($fh, $pdf->ezOutput());
            fclose($fh);
        }
        // Send the PDF download.
        $pdf->ezStream(array('Content-Disposition' => $bat_filename));
        exit;
    }
    if (isset($ar['bn_hcfa_txt_file'])) {
        fclose($hlog);
        $fh = @fopen($GLOBALS['OE_SITE_DIR'] . "/edi/{$bat_filename}", 'a');
        if ($fh) {
            fwrite($fh, $bat_content);
            fclose($fh);
        }
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
        header("Content-Type: application/force-download");
        header("Content-Disposition: attachment; filename={$bat_filename}");
        header("Content-Description: File Transfer");
        header("Content-Length: " . strlen($bat_content));
        echo $bat_content;
        exit;
    }
    if (isset($ar['bn_external'])) {
        // Close external billing file.
        $be->close();
    }
}
Esempio n. 4
0
function arSetupSecondary($patient_id, $encounter_id, $debug, $crossover = 0)
{
    if ($crossover == 1) {
        //if claim forwarded setting a new status
        $status = 6;
    } else {
        $status = 1;
    }
    // Determine the next insurance level to be billed.
    $ferow = sqlQuery("SELECT date, last_level_billed " . "FROM form_encounter WHERE " . "pid = '{$patient_id}' AND encounter = '{$encounter_id}'");
    $date_of_service = substr($ferow['date'], 0, 10);
    $new_payer_type = 0 + $ferow['last_level_billed'];
    if ($new_payer_type < 3 && !empty($ferow['last_level_billed']) || $new_payer_type == 0) {
        ++$new_payer_type;
    }
    $new_payer_id = arGetPayerID($patient_id, $date_of_service, $new_payer_type);
    if ($new_payer_id) {
        // Queue up the claim.
        if (!$debug) {
            updateClaim(true, $patient_id, $encounter_id, $new_payer_id, $new_payer_type, $status, 5, '', 'hcfa', '', $crossover);
        }
    } else {
        // Just reopen the claim.
        if (!$debug) {
            updateClaim(true, $patient_id, $encounter_id, -1, -1, $status, 0, '', '', '', $crossover);
        }
    }
    return xl("Encounter ") . $encounter . xl(" is ready for re-billing.");
}
Esempio n. 5
0
                             }
                             SLQuery("DELETE FROM invoice WHERE trans_id = '{$trans_id}'");
                             if ($sl_err) {
                                 die($sl_err);
                             }
                             SLQuery("DELETE FROM ar WHERE id = '{$trans_id}'");
                             if ($sl_err) {
                                 die($sl_err);
                             }
                         } else {
                             $info_msg .= "Invoice '{$billing}' not found!";
                         }
                         SLClose();
                     }
                     sqlStatement("UPDATE drug_sales SET billed = 0 WHERE " . "pid = '{$patient_id}' AND encounter = '{$encounter_id}'");
                     updateClaim(true, $patient_id, $encounter_id, -1, -1, 1, 0, '');
                     // clears for rebilling
                 } else {
                     if ($transaction) {
                         if (!acl_check('admin', 'super')) {
                             die("Not authorized!");
                         }
                         row_delete("transactions", "id = '{$transaction}'");
                     } else {
                         die("Nothing was recognized to delete!");
                     }
                 }
             }
         }
     }
 }
Esempio n. 6
0
                    fwrite($ofh, fread($ifh, 8192));
                }
                fclose($ofh);
                fclose($ifh);
                // chmod($fconfig['copy_pdfs_to'] . $fbase, 0666);
            }
            if ($billkey['bill_process'] == 5) {
                //the bill was generated without an error now print it
                $estring = $fconfig['print_command'] . " -P " . $fconfig['printer_name'] . " " . $fconfig['printer_extras'] . " " . $fname;
                $rstring = exec(escapeshellcmd($estring));
            }
        }
    } else {
        $presult = "Code: " . $r->faultCode() . " Reason '" . $r->faultString() . "'<BR>";
        echo "Claim for PatientID: {$patient_id}, Encounter: {$billkey['key']} failed due to: \n " . basename("/" . $presult) . "\n";
        /****
        		$sql = "UPDATE billing set process_date = now(), bill_process = 3, process_file = '" .
        			mysql_real_escape_string(basename("/" . $presult)) .
        			"' where encounter = $encounter AND pid = '" . $patient_id . "'";
        		$results = $db->Execute($sql);
        		if (!$results) {
        			echo "There was an error with the database.\n";
        			echo $db->ErrorMsg() . "\n";
        		}
            ****/
        if (!updateClaim(false, $patient_id, $encounter, -1, -1, 3, basename("/" . $presult))) {
            echo "Internal error: failed to update claim {$patient_id}-{$encounter}\n";
        }
    }
}
echo "\n\n";