예제 #1
0
function generate_receipt($patient_id, $encounter = 0)
{
    global $sl_err, $sl_cash_acc, $css_header, $details, $INTEGRATED_AR;
    // 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");
    $patdata = getPatientData($patient_id, 'fname,mname,lname,pubpid,street,city,state,postal_code,providerID');
    // Get the most recent invoice data or that for the specified encounter.
    //
    // Adding a provider check so that their info can be displayed on receipts
    if ($INTEGRATED_AR) {
        if ($encounter) {
            $ferow = sqlQuery("SELECT id, date, encounter, provider_id FROM form_encounter " . "WHERE pid = ? AND encounter = ?", array($patient_id, $encounter));
        } else {
            $ferow = sqlQuery("SELECT id, date, encounter, provider_id FROM form_encounter " . "WHERE pid = ? " . "ORDER BY id DESC LIMIT 1", array($patient_id));
        }
        if (empty($ferow)) {
            die(xlt("This patient has no activity."));
        }
        $trans_id = $ferow['id'];
        $encounter = $ferow['encounter'];
        $svcdate = substr($ferow['date'], 0, 10);
        if ($GLOBALS['receipts_by_provider']) {
            if (isset($ferow['provider_id'])) {
                $encprovider = $ferow['provider_id'];
            } else {
                if (isset($patdata['providerID'])) {
                    $encprovider = $patdata['providerID'];
                } else {
                    $encprovider = -1;
                }
            }
        }
        if ($encprovider) {
            $providerrow = sqlQuery("SELECT fname, mname, lname, title, street, streetb, " . "city, state, zip, phone, fax FROM users WHERE id = ?", array($encprovider));
        }
    } else {
        SLConnect();
        //
        $arres = SLQuery("SELECT * FROM ar WHERE " . "invnumber LIKE '{$patient_id}.%' " . "ORDER BY id DESC LIMIT 1");
        if ($sl_err) {
            die(text($sl_err));
        }
        if (!SLRowCount($arres)) {
            die(xlt("This patient has no activity."));
        }
        $arrow = SLGetRow($arres, 0);
        //
        $trans_id = $arrow['id'];
        //
        // Determine the date of service.  An 8-digit encounter number is
        // presumed to be a date of service imported during conversion or
        // associated with prescriptions only.  Otherwise look it up in the
        // form_encounter table.
        //
        $svcdate = "";
        list($trash, $encounter) = explode(".", $arrow['invnumber']);
        if (strlen($encounter) >= 8) {
            $svcdate = substr($encounter, 0, 4) . "-" . substr($encounter, 4, 2) . "-" . substr($encounter, 6, 2);
        } else {
            if ($encounter) {
                $tmp = sqlQuery("SELECT date FROM form_encounter WHERE " . "encounter = ?", array($encounter));
                $svcdate = substr($tmp['date'], 0, 10);
            }
        }
    }
    // end not $INTEGRATED_AR
    // Get invoice reference number.
    $encrow = sqlQuery("SELECT invoice_refno FROM form_encounter WHERE " . "pid = ? AND encounter = ? LIMIT 1", array($patient_id, $encounter));
    $invoice_refno = $encrow['invoice_refno'];
    ?>
<html>
<head>
<?php 
    html_header_show();
    ?>
<link rel='stylesheet' href='<?php 
    echo $css_header;
    ?>
' type='text/css'>
<title><?php 
    echo xlt('Receipt for Payment');
    ?>
</title>
<script type="text/javascript" src="../../library/dialog.js"></script>
<script language="JavaScript">

<?php 
    require $GLOBALS['srcdir'] . "/restoreSession.php";
    ?>

 // Process click on Print button.
 function printme() {
  var divstyle = document.getElementById('hideonprint').style;
  divstyle.display = 'none';
  window.print();
  return false;
 }

 // Process click on Delete button.
 function deleteme() {
  dlgopen('deleter.php?billing=<?php 
    echo attr("{$patient_id}.{$encounter}");
    ?>
', '_blank', 500, 450);
  return false;
 }

 // Called by the deleteme.php window on a successful delete.
 function imdeleted() {
  window.close();
 }

</script>
</head>
<body class="body_top">
<center>
<?php 
    if ($GLOBALS['receipts_by_provider'] && !empty($providerrow)) {
        printProviderHeader($providerrow);
    } else {
        printFacilityHeader($frow);
    }
    echo xlt("Receipt Generated") . ":" . text(date(' F j, Y'));
    if ($invoice_refno) {
        echo " " . xlt("Invoice Number") . ": " . text($invoice_refno) . " " . xlt("Service Date") . ": " . text($svcdate);
    }
    ?>
<br>&nbsp;
</b></p>
</center>
<p>
<?php 
    echo text($patdata['fname']) . ' ' . text($patdata['mname']) . ' ' . text($patdata['lname']);
    ?>
<br><?php 
    echo text($patdata['street']);
    ?>
<br><?php 
    echo text($patdata['city']) . ', ' . text($patdata['state']) . ' ' . text($patdata['postal_code']);
    ?>
<br>&nbsp;
</p>
<center>
<table cellpadding='5'>
 <tr>
  <td><b><?php 
    echo xlt('Date');
    ?>
</b></td>
  <td><b><?php 
    echo xlt('Description');
    ?>
</b></td>
  <td align='right'><b><?php 
    echo $details ? xlt('Price') : '&nbsp;';
    ?>
</b></td>
  <td align='right'><b><?php 
    echo $details ? xlt('Qty') : '&nbsp;';
    ?>
</b></td>
  <td align='right'><b><?php 
    echo xlt('Total');
    ?>
</b></td>
 </tr>

<?php 
    $charges = 0.0;
    if ($INTEGRATED_AR) {
        // Product sales
        $inres = sqlStatement("SELECT s.sale_id, s.sale_date, s.fee, " . "s.quantity, s.drug_id, d.name " . "FROM drug_sales AS s LEFT JOIN drugs AS d ON d.drug_id = s.drug_id " . "WHERE s.pid = ? AND s.encounter = ? " . "ORDER BY s.sale_id", array($patient_id, $encounter));
        while ($inrow = sqlFetchArray($inres)) {
            $charges += sprintf('%01.2f', $inrow['fee']);
            receiptDetailLine($inrow['sale_date'], $inrow['name'], $inrow['fee'], $inrow['quantity']);
        }
        // Service and tax items
        $inres = sqlStatement("SELECT * FROM billing WHERE " . "pid = ? AND encounter = ? AND " . "code_type != 'COPAY' AND activity = 1 " . "ORDER BY id", array($patient_id, $encounter));
        while ($inrow = sqlFetchArray($inres)) {
            $charges += sprintf('%01.2f', $inrow['fee']);
            receiptDetailLine($svcdate, $inrow['code_text'], $inrow['fee'], $inrow['units']);
        }
        // Adjustments.
        $inres = sqlStatement("SELECT " . "a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, " . "s.payer_id, s.reference, s.check_date, s.deposit_date " . "FROM ar_activity AS a " . "LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " . "a.pid = ? AND a.encounter = ? AND " . "a.adj_amount != 0 " . "ORDER BY s.check_date, a.sequence_no", array($patient_id, $encounter));
        while ($inrow = sqlFetchArray($inres)) {
            $charges -= sprintf('%01.2f', $inrow['adj_amount']);
            $payer = empty($inrow['payer_type']) ? 'Pt' : 'Ins' . $inrow['payer_type'];
            receiptDetailLine($svcdate, $payer . ' ' . $inrow['memo'], 0 - $inrow['adj_amount'], 1);
        }
    } else {
        // Request all line items with money belonging to the invoice.
        $inres = SLQuery("SELECT * FROM invoice WHERE " . "trans_id = {$trans_id} AND sellprice != 0 ORDER BY id");
        if ($sl_err) {
            die($sl_err);
        }
        for ($irow = 0; $irow < SLRowCount($inres); ++$irow) {
            $row = SLGetRow($inres, $irow);
            $amount = sprintf('%01.2f', $row['sellprice'] * $row['qty']);
            $charges += $amount;
            $desc = preg_replace('/^.{1,6}:/', '', $row['description']);
            receiptDetailLine($svcdate, $desc, $amount, $row['qty']);
        }
    }
    // end not $INTEGRATED_AR
    ?>

 <tr>
  <td colspan='5'>&nbsp;</td>
 </tr>
 <tr>
  <td><?php 
    echo text(oeFormatShortDate($svcdispdate));
    ?>
</td>
  <td><b><?php 
    echo xlt('Total Charges');
    ?>
</b></td>
  <td align='right'>&nbsp;</td>
  <td align='right'>&nbsp;</td>
  <td align='right'><?php 
    echo text(oeFormatMoney($charges, true));
    ?>
</td>
 </tr>
 <tr>
  <td colspan='5'>&nbsp;</td>
 </tr>

<?php 
    if ($INTEGRATED_AR) {
        // Get co-pays.
        $inres = sqlStatement("SELECT fee, code_text FROM billing WHERE " . "pid = ? AND encounter = ?  AND " . "code_type = 'COPAY' AND activity = 1 AND fee != 0 " . "ORDER BY id", array($patient_id, $encounter));
        while ($inrow = sqlFetchArray($inres)) {
            $charges += sprintf('%01.2f', $inrow['fee']);
            receiptPaymentLine($svcdate, 0 - $inrow['fee'], $inrow['code_text']);
        }
        // Get other payments.
        $inres = sqlStatement("SELECT " . "a.code, a.modifier, a.memo, a.payer_type, a.adj_amount, a.pay_amount, " . "s.payer_id, s.reference, s.check_date, s.deposit_date " . "FROM ar_activity AS a " . "LEFT JOIN ar_session AS s ON s.session_id = a.session_id WHERE " . "a.pid = ? AND a.encounter = ? AND " . "a.pay_amount != 0 " . "ORDER BY s.check_date, a.sequence_no", array($patient_id, $encounter));
        $payer = empty($inrow['payer_type']) ? 'Pt' : 'Ins' . $inrow['payer_type'];
        while ($inrow = sqlFetchArray($inres)) {
            $charges -= sprintf('%01.2f', $inrow['pay_amount']);
            receiptPaymentLine($svcdate, $inrow['pay_amount'], $payer . ' ' . $inrow['reference']);
        }
    } else {
        $chart_id_cash = SLQueryValue("select id from chart where accno = '{$sl_cash_acc}'");
        if ($sl_err) {
            die($sl_err);
        }
        if (!$chart_id_cash) {
            die("There is no COA entry for cash account '{$sl_cash_acc}'");
        }
        //
        // Request all cash entries belonging to the invoice.
        $atres = SLQuery("SELECT * FROM acc_trans WHERE " . "trans_id = {$trans_id} AND chart_id = {$chart_id_cash} ORDER BY transdate");
        if ($sl_err) {
            die($sl_err);
        }
        //
        for ($irow = 0; $irow < SLRowCount($atres); ++$irow) {
            $row = SLGetRow($atres, $irow);
            $amount = sprintf('%01.2f', $row['amount']);
            // negative
            $charges += $amount;
            $rowsource = $row['source'];
            if (strtolower($rowsource) == 'co-pay') {
                $rowsource = '';
            }
            receiptPaymentLine($row['transdate'], 0 - $amount, $rowsource);
        }
    }
    // end not $INTEGRATED_AR
    ?>
 <tr>
  <td colspan='5'>&nbsp;</td>
 </tr>
 <tr>
  <td>&nbsp;</td>
  <td><b><?php 
    echo xlt('Balance Due');
    ?>
</b></td>
  <td colspan='2'>&nbsp;</td>
  <td align='right'><?php 
    echo text(oeFormatMoney($charges, true));
    ?>
</td>
 </tr>
</table>
</center>
<div id='hideonprint'>
<p>
&nbsp;
<a href='#' onclick='return printme();'><?php 
    echo xlt('Print');
    ?>
</a>
<?php 
    if (acl_check('acct', 'disc')) {
        ?>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href='#' onclick='return deleteme();'><?php 
        echo xlt('Undo Checkout');
        ?>
</a>
<?php 
    }
    ?>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<?php 
    if ($details) {
        ?>
<a href='pos_checkout.php?details=0&ptid=<?php 
        echo attr($patient_id);
        ?>
&enc=<?php 
        echo attr($encounter);
        ?>
'><?php 
        echo xlt('Hide Details');
        ?>
</a>
<?php 
    } else {
        ?>
<a href='pos_checkout.php?details=1&ptid=<?php 
        echo attr($patient_id);
        ?>
&enc=<?php 
        echo attr($encounter);
        ?>
'><?php 
        echo xlt('Show Details');
        ?>
</a>
<?php 
    }
    ?>
</p>
</div>
</body>
</html>
<?php 
    if (!$INTEGRATED_AR) {
        SLClose();
    }
}
예제 #2
0
function responsible_party($trans_id)
{
    global $sl_err;
    $arres = SLQuery("select * from ar where id = {$trans_id}");
    if ($sl_err) {
        die($sl_err);
    }
    $arrow = SLGetRow($arres, 0);
    if (!$arrow) {
        die(xl("There is no match for invoice id = ") . $trans_id);
    }
    if ($arrow['paid'] >= $arrow['netamount']) {
        return -1;
    }
    $insgot = strtolower($arrow['notes']);
    $insdone = strtolower($arrow['shipvia']);
    for ($i = 1; $i <= 3; ++$i) {
        $lcvalue = "ins{$i}";
        if (strpos($insgot, $lcvalue) !== false && strpos($insdone, $lcvalue) === false) {
            return $i;
        }
    }
    return 0;
}
예제 #3
0
 // echo "<!-- $query -->\n"; // debugging
 $t_res = SLQuery($query);
 if ($sl_err) {
     die($sl_err);
 }
 $docname = "";
 $docnameleft = "";
 $main_docid = 0;
 $doctotal1 = 0;
 $grandtotal1 = 0;
 $doctotal2 = 0;
 $grandtotal2 = 0;
 $last_trans_id = 0;
 $skipping = false;
 for ($irow = 0; $irow < SLRowCount($t_res); ++$irow) {
     $row = SLGetRow($t_res, $irow);
     list($patient_id, $encounter_id) = explode(".", $row['invnumber']);
     // Under some conditions we may skip invoices that matched the SQL query.
     //
     if ($row['trans_id'] == $last_trans_id) {
         if ($skipping) {
             continue;
         }
         // same invoice and not skipping, do nothing.
     } else {
         // new invoice
         $skipping = false;
         // If a diagnosis code was given then skip any invoices without
         // that diagnosis.
         if ($form_icdcode) {
             if (!SLQueryValue("SELECT count(*) FROM invoice WHERE " . "invoice.trans_id = '" . $row['trans_id'] . "' AND " . "( invoice.description ILIKE 'ICD9:{$form_icdcode} %' OR " . "invoice.serialnumber ILIKE 'ICD9:{$form_icdcode}' )")) {
예제 #4
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');
                    }
                }
            }
        }
    }
}
예제 #5
0
         $duept = $brow['amount'] + $srow['amount'] - $drow['payments'] - $drow['adjustments'];
     }
     echoLine("form_upay[{$enc}]", $dispdate, $value['charges'], $dpayment_pat, $dpayment + $dadjustment, $duept, $enc, $inscopay, $patcopay);
 }
 // Now list previously billed visits.
 if ($INTEGRATED_AR) {
 } else {
     // Query for all open invoices.
     $query = "SELECT ar.id, ar.invnumber, ar.amount, ar.paid, " . "ar.intnotes, ar.notes, ar.shipvia, " . "(SELECT SUM(invoice.sellprice * invoice.qty) FROM invoice WHERE " . "invoice.trans_id = ar.id AND invoice.sellprice > 0) AS charges, " . "(SELECT SUM(invoice.sellprice * invoice.qty) FROM invoice WHERE " . "invoice.trans_id = ar.id AND invoice.sellprice < 0) AS adjustments, " . "(SELECT SUM(acc_trans.amount) FROM acc_trans WHERE " . "acc_trans.trans_id = ar.id AND acc_trans.chart_id = ? " . "AND acc_trans.source NOT LIKE 'Ins%') AS ptpayments " . "FROM ar WHERE ar.invnumber LIKE ? AND " . "ar.amount != ar.paid " . "ORDER BY ar.invnumber";
     $ires = SLQuery($query, array($chart_id_cash, $pid . "%"));
     if ($sl_err) {
         die($sl_err);
     }
     $num_invoices = SLRowCount($ires);
     for ($ix = 0; $ix < $num_invoices; ++$ix) {
         $irow = SLGetRow($ires, $ix);
         // Get encounter ID and date of service.
         list($patient_id, $enc) = explode(".", $irow['invnumber']);
         $tmp = sqlQuery("SELECT LEFT(date, 10) AS encdate FROM form_encounter " . "WHERE encounter = ?", array($enc));
         $svcdate = $tmp['encdate'];
         // Compute $duncount as in sl_eob_search.php to determine if
         // this invoice is at patient responsibility.
         $duncount = substr_count(strtolower($irow['intnotes']), "statement sent");
         if (!$duncount) {
             $insgot = strtolower($irow['notes']);
             $inseobs = strtolower($irow['shipvia']);
             foreach (array('ins1', 'ins2', 'ins3') as $value) {
                 if (strpos($insgot, $value) !== false && strpos($inseobs, $value) === false) {
                     --$duncount;
                 }
             }
예제 #6
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;
}
예제 #7
0
       $ferow = sqlQuery("SELECT e.*, p.fname, p.mname, p.lname " .
         "FROM form_encounter AS e, patient_data AS p WHERE " .
         "e.pid = '$patient_id' AND e.encounter = '$encounter_id' AND ".
         "p.pid = e.pid");
       if (empty($ferow)) die("There is no encounter $patient_id.$encounter_id.");
       $svcdate = substr($ferow['date'], 0, 10);
       *****************************************************************/
    // Get invoice charge details.
    $codes = ar_get_invoice_summary($patient_id, $encounter_id, true);
} else {
    // Get invoice data into $arrow.
    $arres = SLQuery("select ar.*, customer.name, employee.name as doctor " . "from ar, customer, employee where ar.id = {$trans_id} and " . "customer.id = ar.customer_id and employee.id = ar.employee_id");
    if ($sl_err) {
        die($sl_err);
    }
    $arrow = SLGetRow($arres, 0);
    if (!$arrow) {
        die(xl("There is no match for invoice id = ") . $trans_id);
    }
    //
    // Determine the date of service.  An 8-digit encounter number is
    // presumed to be a date of service imported during conversion.
    // Otherwise look it up in the form_encounter table.
    //
    $svcdate = "";
    list($patient_id, $encounter) = explode(".", $arrow['invnumber']);
    if (strlen($encounter) == 8) {
        $svcdate = substr($encounter, 0, 4) . "-" . substr($encounter, 4, 2) . "-" . substr($encounter, 6, 2);
    } else {
        if ($encounter) {
            $tmp = sqlQuery("SELECT date FROM form_encounter WHERE " . "encounter = {$encounter}");
예제 #8
0
 function loadPayerInfo(&$billrow)
 {
     global $sl_err;
     $encounter_date = substr($this->encounter['date'], 0, 10);
     // Create the $payers array.  This contains data for all insurances
     // with the current one always at index 0, and the others in payment
     // order starting at index 1.
     //
     $this->payers = array();
     $this->payers[0] = array();
     $query = "SELECT * FROM insurance_data WHERE " . "pid = '{$this->pid}' AND " . "date <= '{$encounter_date}' " . "ORDER BY type ASC, date DESC";
     $dres = sqlStatement($query);
     $prevtype = '';
     while ($drow = sqlFetchArray($dres)) {
         if (strcmp($prevtype, $drow['type']) == 0) {
             continue;
         }
         $prevtype = $drow['type'];
         // Very important to look at entries with a missing provider because
         // they indicate no insurance as of the given date.
         if (empty($drow['provider'])) {
             continue;
         }
         $ins = count($this->payers);
         if ($drow['provider'] == $billrow['payer_id'] && empty($this->payers[0]['data'])) {
             $ins = 0;
         }
         $crow = sqlQuery("SELECT * FROM insurance_companies WHERE " . "id = '" . $drow['provider'] . "'");
         $orow = new InsuranceCompany($drow['provider']);
         $this->payers[$ins] = array();
         $this->payers[$ins]['data'] = $drow;
         $this->payers[$ins]['company'] = $crow;
         $this->payers[$ins]['object'] = $orow;
     }
     // This kludge hands most cases of a rare ambiguous situation, where
     // the primary insurance company is the same as the secondary.  It seems
     // nobody planned for that!
     //
     for ($i = 1; $i < count($this->payers); ++$i) {
         if ($billrow['process_date'] && $this->payers[0]['data']['provider'] == $this->payers[$i]['data']['provider']) {
             $tmp = $this->payers[0];
             $this->payers[0] = $this->payers[$i];
             $this->payers[$i] = $tmp;
         }
     }
     $this->using_modifiers = true;
     // Get payment and adjustment details if there are any previous payers.
     //
     $this->invoice = array();
     if ($this->payerSequence() != 'P') {
         if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2) {
             $this->invoice = ar_get_invoice_summary($this->pid, $this->encounter_id, true);
         } else {
             if ($GLOBALS['oer_config']['ws_accounting']['enabled']) {
                 SLConnect();
                 $arres = SLQuery("select id from ar where invnumber = " . "'{$this->pid}.{$this->encounter_id}'");
                 if ($sl_err) {
                     die($sl_err);
                 }
                 $arrow = SLGetRow($arres, 0);
                 if ($arrow) {
                     $this->invoice = get_invoice_summary($arrow['id'], true);
                 }
                 SLClose();
             }
         }
         // Secondary claims might not have modifiers in SQL-Ledger data.
         // In that case, note that we should not try to match on them.
         $this->using_modifiers = false;
         foreach ($this->invoice as $key => $trash) {
             if (strpos($key, ':')) {
                 $this->using_modifiers = true;
             }
         }
     }
 }
예제 #9
0
            $arow = sqlQuery("SELECT SUM(fee) AS amount FROM billing WHERE " . "pid = '{$patient_id}' AND encounter = '{$encounter_id}' AND " . "activity = 1 AND code_type != 'COPAY'");
            $inv_amount += $arow['amount'];
            $arow = sqlQuery("SELECT SUM(fee) AS amount FROM billing WHERE " . "pid = '{$patient_id}' AND encounter = '{$encounter_id}' AND " . "activity = 1 AND code_type = 'COPAY'");
            $inv_paid = 0 - $arow['amount'];
            $arow = sqlQuery("SELECT SUM(pay_amount) AS pay, " . "sum(adj_amount) AS adj FROM ar_activity WHERE " . "pid = '{$patient_id}' AND encounter = '{$encounter_id}'");
            $inv_paid += $arow['pay'];
            $inv_amount -= $arow['adj'];
        } else {
            $ares = SLQuery("SELECT duedate, amount, paid FROM ar WHERE " . "ar.invnumber = '{$invnumber}'");
            if ($sl_err) {
                die($sl_err);
            }
            if (SLRowCount($ares) == 0) {
                continue;
            }
            $arow = SLGetRow($ares, 0);
            $inv_amount = $arow['amount'];
            $inv_paid = $arow['paid'];
            $inv_duedate = $arow['duedate'];
        }
        $total_amount += bucks($inv_amount);
        $total_paid += bucks($inv_paid);
        $bgcolor = $irow & 1 ? "#ffdddd" : "#ddddff";
        ?>
 <tr bgcolor='<?php 
        echo $bgcolor;
        ?>
'>
  <td class="detail">
   &nbsp;<?php 
        echo $row['lname'] . ', ' . $row['fname'] . ' ' . $row['mname'];
예제 #10
0
<br><br>
<span class='text'>
<?php 
SLConnect();
echo "<p>Be patient, this will take a while...</p>";
flush();
// This marker will eventually tell us which encounters have no
// matching invoice.
if (!$dry_run) {
    sqlStatement("UPDATE form_encounter SET last_level_billed = -1");
}
$invoice_count = 0;
$activity_count = 0;
$res = SLQuery("SELECT id, invnumber, transdate, shipvia, intnotes " . "FROM ar WHERE invnumber LIKE '%.%' ORDER BY id");
for ($irow = 0; $irow < SLRowCount($res); ++$irow) {
    $row = SLGetRow($res, $irow);
    list($pid, $encounter) = explode(".", $row['invnumber']);
    $tmp = sqlQuery("SELECT count(*) AS count FROM form_encounter WHERE " . "pid = '{$pid}' AND encounter = '{$encounter}'");
    if ($tmp['count'] == 0) {
        echo "SQL-Ledger invoice {$pid}.{$encounter} has no matching encounter " . "and is ignored. This will affect financial reports!<br />\n";
        continue;
    }
    $billing = array();
    $provider_id = 0;
    $last_biller = 0;
    $svcdate = $row['transdate'];
    if (!$dry_run) {
        // Delete any TAX rows from billing for encounters in SQL-Ledger.
        sqlStatement("UPDATE billing SET activity = 0 WHERE " . "pid = '{$pid}' AND encounter = '{$encounter}' AND " . "code_type = 'TAX'");
    }
    // Get all billing table items with money for this encounter, and