quick minor path updates (#1968)
[openemr.git] / library / sl_eob.inc.php
blob5b3a821c671133b80d13ae72e0c5104320787b58
1 <?php
2 // Copyright (C) 2005-2009 Rod Roark <rod@sunsetsystems.com>
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 require_once("patient.inc");
10 require_once("billing.inc");
11 require_once("invoice_summary.inc.php");
13 $chart_id_cash = 0;
14 $chart_id_ar = 0;
15 $chart_id_income = 0;
16 $services_id = 0;
19 // Try to figure out our invoice number (pid.encounter) from the
20 // claim ID and other stuff in the ERA. This should be straightforward
21 // except that some payers mangle the claim ID that we give them.
23 function slInvoiceNumber(&$out)
25 $invnumber = $out['our_claim_id'];
26 $atmp = preg_split('/[ -]/', $invnumber);
27 $acount = count($atmp);
29 $pid = 0;
30 $encounter = 0;
31 if ($acount == 2) {
32 $pid = $atmp[0];
33 $encounter = $atmp[1];
34 } else if ($acount == 3) {
35 $pid = $atmp[0];
36 $brow = sqlQuery("SELECT encounter FROM billing WHERE " .
37 "pid = '$pid' AND encounter = ? AND activity = 1", array($atmp[1]));
39 $encounter = $brow['encounter'];
40 } else if ($acount == 1) {
41 $pres = sqlStatement("SELECT pid FROM patient_data WHERE " .
42 "lname LIKE ? AND " .
43 "fname LIKE ? " .
44 "ORDER BY pid DESC", array($out['patient_lname'], $out['patient_fname']));
45 while ($prow = sqlFetchArray($pres)) {
46 if (strpos($invnumber, $prow['pid']) === 0) {
47 $pid = $prow['pid'];
48 $encounter = substr($invnumber, strlen($pid));
49 break;
54 if ($pid && $encounter) {
55 $invnumber = "$pid.$encounter";
58 return array($pid, $encounter, $invnumber);
61 // This gets a posting session ID. If the payer ID is not 0 and a matching
62 // session already exists, then its ID is returned. Otherwise a new session
63 // is created.
65 function arGetSession($payer_id, $reference, $check_date, $deposit_date = '', $pay_total = 0)
67 if (empty($deposit_date)) {
68 $deposit_date = $check_date;
71 if ($payer_id) {
72 $row = sqlQuery("SELECT session_id FROM ar_session WHERE " .
73 "payer_id = ? AND reference = ? AND " .
74 "check_date = ? AND deposit_date = ? " .
75 "ORDER BY session_id DESC LIMIT 1", array($payer_id, $reference, $check_date, $deposit_date));
76 if (!empty($row['session_id'])) {
77 return $row['session_id'];
81 return sqlInsert("INSERT INTO ar_session ( " .
82 "payer_id, user_id, reference, check_date, deposit_date, pay_total " .
83 ") VALUES ( ?, ?, ?, ?, ?, ? )", array($payer_id, $_SESSION['authUserID'], $reference, $check_date, $deposit_date, $pay_total));
85 //writing the check details to Session Table on ERA proxcessing
86 function arPostSession($payer_id, $check_number, $check_date, $pay_total, $post_to_date, $deposit_date, $debug)
88 $query = "INSERT INTO ar_session( " .
89 "payer_id,user_id,closed,reference,check_date,pay_total,post_to_date,deposit_date,patient_id,payment_type,adjustment_code,payment_method " .
90 ") VALUES (?, ?, 0, ?, ?, ?, ? ,?, 0, 'insurance', 'insurance_payment', 'electronic')";
91 if ($debug) {
92 echo text($query) . "<br>\n";
93 } else {
94 $sessionId=sqlInsert($query, array($payer_id, $_SESSION['authUserID'], 'ePay - '.$check_number, $check_date, $pay_total, $post_to_date, $deposit_date));
95 return $sessionId;
99 // Post a payment, new style.
101 function arPostPayment($patient_id, $encounter_id, $session_id, $amount, $code, $payer_type, $memo, $debug, $time = '', $codetype = '')
103 $codeonly = $code;
104 $modifier = '';
105 $tmp = strpos($code, ':');
106 if ($tmp) {
107 $codeonly = substr($code, 0, $tmp);
108 $modifier = substr($code, $tmp+1);
111 if (empty($time)) {
112 $time = date('Y-m-d H:i:s');
115 sqlBeginTrans();
116 $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($patient_id, $encounter_id));
117 $query = "INSERT INTO ar_activity ( " .
118 "pid, encounter, sequence_no, code_type, code, modifier, payer_type, post_time, post_user, " .
119 "session_id, memo, pay_amount " .
120 ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
121 sqlStatement($query, array($patient_id, $encounter_id, $sequence_no['increment'], $codetype, $codeonly, $modifier, $payer_type, $time, $_SESSION['authUserID'], $session_id, $memo, $amount));
122 sqlCommitTrans();
123 return;
126 // Post a charge. This is called only from sl_eob_process.php where
127 // automated remittance processing can create a new service item.
128 // Here we add it as an unauthorized item to the billing table.
130 function arPostCharge($patient_id, $encounter_id, $session_id, $amount, $units, $thisdate, $code, $description, $debug, $codetype = '')
132 /*****************************************************************
133 // Select an existing billing item as a template.
134 $row= sqlQuery("SELECT * FROM billing WHERE " .
135 "pid = '$patient_id' AND encounter = '$encounter_id' AND " .
136 "code_type = 'CPT4' AND activity = 1 " .
137 "ORDER BY id DESC LIMIT 1");
138 $this_authorized = 0;
139 $this_provider = 0;
140 if (!empty($row)) {
141 $this_authorized = $row['authorized'];
142 $this_provider = $row['provider_id'];
144 *****************************************************************/
146 if (empty($codetype)) {
147 // default to CPT4 if empty, which is consistent with previous functionality.
148 $codetype="CPT4";
151 $codeonly = $code;
152 $modifier = '';
153 $tmp = strpos($code, ':');
154 if ($tmp) {
155 $codeonly = substr($code, 0, $tmp);
156 $modifier = substr($code, $tmp+1);
159 addBilling(
160 $encounter_id,
161 $codetype,
162 $codeonly,
163 $description,
164 $patient_id,
167 $modifier,
168 $units,
169 $amount,
175 // Post an adjustment, new style.
177 function arPostAdjustment($patient_id, $encounter_id, $session_id, $amount, $code, $payer_type, $reason, $debug, $time = '', $codetype = '')
179 $codeonly = $code;
180 $modifier = '';
181 $tmp = strpos($code, ':');
182 if ($tmp) {
183 $codeonly = substr($code, 0, $tmp);
184 $modifier = substr($code, $tmp+1);
187 if (empty($time)) {
188 $time = date('Y-m-d H:i:s');
191 sqlBeginTrans();
192 $sequence_no = sqlQuery("SELECT IFNULL(MAX(sequence_no),0) + 1 AS increment FROM ar_activity WHERE pid = ? AND encounter = ?", array($patient_id, $encounter_id));
193 $query = "INSERT INTO ar_activity ( " .
194 "pid, encounter, sequence_no, code_type, code, modifier, payer_type, post_user, post_time, " .
195 "session_id, memo, adj_amount " .
196 ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
197 sqlStatement($query, array($patient_id, $encounter_id, $sequence_no['increment'], $codetype, $codeonly, $modifier, $payer_type, $_SESSION['authUserID'], $time, $session_id, $reason, $amount));
198 sqlCommitTrans();
199 return;
202 function arGetPayerID($patient_id, $date_of_service, $payer_type)
204 if ($payer_type < 1 || $payer_type > 3) {
205 return 0;
208 $tmp = array(1 => 'primary', 2 => 'secondary', 3 => 'tertiary');
209 $value = $tmp[$payer_type];
210 $query = "SELECT provider FROM insurance_data WHERE " .
211 "pid = ? AND type = ? AND date <= ? " .
212 "ORDER BY date DESC LIMIT 1";
213 $nprow = sqlQuery($query, array($patient_id,$value,$date_of_service));
214 if (empty($nprow)) {
215 return 0;
218 return $nprow['provider'];
221 // Make this invoice re-billable, new style.
223 function arSetupSecondary($patient_id, $encounter_id, $debug, $crossover = 0)
225 if ($crossover==1) {
226 //if claim forwarded setting a new status
227 $status=6;
228 } else {
229 $status=1;
232 // Determine the next insurance level to be billed.
233 $ferow = sqlQuery("SELECT date, last_level_billed " .
234 "FROM form_encounter WHERE " .
235 "pid = ? AND encounter = ?", array($patient_id, $encounter_id));
236 $date_of_service = substr($ferow['date'], 0, 10);
237 $new_payer_type = 0 + $ferow['last_level_billed'];
238 if ($new_payer_type < 3 && !empty($ferow['last_level_billed']) || $new_payer_type == 0) {
239 ++$new_payer_type;
242 $new_payer_id = arGetPayerID($patient_id, $date_of_service, $new_payer_type);
244 if ($new_payer_id) {
245 // Queue up the claim.
246 if (!$debug) {
247 updateClaim(true, $patient_id, $encounter_id, $new_payer_id, $new_payer_type, $status, 5, '', 'hcfa', '', $crossover);
249 } else {
250 // Just reopen the claim.
251 if (!$debug) {
252 updateClaim(true, $patient_id, $encounter_id, -1, -1, $status, 0, '', '', '', $crossover);
256 return xl("Encounter ") . $encounter . xl(" is ready for re-billing.");