4 function getBillingById ($id, $cols = "*")
6 return sqlQuery("select $cols from billing where id='$id' and activity=1 order by date DESC limit 0,1");
9 function getBillingByPid ($pid, $cols = "*")
11 return sqlQuery("select $cols from billing where pid ='$pid' and activity=1 order by date DESC limit 0,1");
14 function getBillingByEncounter ($pid,$encounter, $cols = "code_type, code, code_text")
16 $res = sqlStatement("select $cols from billing where encounter = ? and pid=? and activity=1 order by code_type, date ASC", array($encounter,$pid) );
19 for($iter=0; $row=sqlFetchArray($res); $iter++)
26 function addBilling($encounter_id, $code_type, $code, $code_text, $pid,
27 $authorized="0", $provider, $modifier="", $units="", $fee="0.00",
28 $ndc_info='', $justify='', $billed=0, $notecodes='', $pricelevel='')
30 $sql = "insert into billing (date, encounter, code_type, code, code_text, " .
31 "pid, authorized, user, groupname, activity, billed, provider_id, " .
32 "modifier, units, fee, ndc_info, justify, notecodes, pricelevel) values (" .
33 "NOW(), ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
34 return sqlInsert($sql, array($encounter_id,$code_type,$code,$code_text,$pid,$authorized,
35 $_SESSION['authId'],$_SESSION['authProvider'],$billed,$provider,$modifier,$units,$fee,
36 $ndc_info,$justify,$notecodes,$pricelevel));
39 function authorizeBilling($id, $authorized = "1")
41 sqlQuery("update billing set authorized = '$authorized' where id = '$id'");
44 function deleteBilling($id)
46 sqlStatement("update billing set activity = 0 where id = '$id'");
49 function clearBilling($id)
51 sqlStatement("update billing set justify = '' where id = '$id'");
54 // This function supports the Billing page (billing_process.php),
55 // and initiation of secondary processing (sl_eob.inc.php).
56 // It is called in the following situations:
58 // * billing_process.php sets bill_time, bill_process, payer and target on
59 // queueing a claim for processing. Create claims row.
60 // * billing_process.php sets claim status to 2, and payer, on marking a
61 // claim as billed without actually generating any billing. Create a
62 // claims row. In this case bill_process will remain at 0 and process_time
63 // and process_file will not be set.
64 // * billing_process.php sets bill_process, payer, target and x12 partner
65 // before calling gen_x12_837. Create a claims row.
66 // * billing_process.php sets claim status to 2 (billed), bill_process to 2,
67 // process_time and process_file after calling gen_x12_837. Claims row
69 // * billing_process.php sets claim status to 2 (billed) after creating
70 // an electronic batch (hcfa-only with recent changes). Claims
71 // row already exists.
72 // * EOB posting updates claim status to mark a payer as done. Claims row
74 // * EOB posting reopens an encounter for billing a secondary payer. Create
77 // $newversion should be passed to us to indicate if a new claims row
78 // is to be generated, otherwise one must already exist. The payer, if
79 // passed in for the latter case, must match the existing claim.
81 // Currently on the billing page the user can select any of the patient's
82 // payers. That logic will tailor the payer choices to the encounter date.
84 function updateClaim($newversion, $patient_id, $encounter_id, $payer_id=-1, $payer_type=-1,
85 $status=-1, $bill_process=-1, $process_file='', $target='', $partner_id=-1,$crossover=0)
88 $sql = "SELECT * FROM claims WHERE patient_id = '$patient_id' AND " .
89 "encounter_id = '$encounter_id' AND status > 0 AND status < 4 ";
90 if ($payer_id >= 0) $sql .= "AND payer_id = '$payer_id' ";
91 $sql .= "ORDER BY version DESC LIMIT 1";
92 $row = sqlQuery($sql);
94 if ($payer_id < 0) $payer_id = $row['payer_id'];
95 if ($status < 0) $status = $row['status'];
96 if ($bill_process < 0) $bill_process = $row['bill_process'];
97 if ($partner_id < 0) $partner_id = $row['x12_partner_id'];
98 if (!$process_file ) $process_file = $row['process_file'];
99 if (!$target ) $target = $row['target'];
104 if (empty($payer_id) || $payer_id < 0) $payer_id = 0;
106 if ($status==7) {//$status==7 is the claim denial case.
107 $claimset .= ", status = '$status'";
109 elseif ($status >= 0) {
110 $claimset .= ", status = '$status'";
112 $billset .= ", billed = 1";
113 if ($status == 2) $billset .= ", bill_date = NOW()";
115 $billset .= ", billed = 0";
118 if ($status==7) {//$status==7 is the claim denial case.
119 $billset .= ", bill_process = '$status'";
121 elseif ($bill_process >= 0) {
122 $claimset .= ", bill_process = '$bill_process'";
123 $billset .= ", bill_process = '$bill_process'";
125 if ($status==7) {//$status==7 is the claim denial case.
126 $claimset .= ", process_file = '$process_file'";//Denial reason code is stored here
128 elseif ($process_file) {
129 $claimset .= ", process_file = '$process_file', process_time = NOW()";
130 $billset .= ", process_file = '$process_file', process_date = NOW()";
133 $claimset .= ", target = '$target'";
134 $billset .= ", target = '$target'";
136 if ($payer_id >= 0) {
137 $claimset .= ", payer_id = '$payer_id', payer_type = '$payer_type'";
138 $billset .= ", payer_id = '$payer_id'";
140 if ($partner_id >= 0) {
141 $claimset .= ", x12_partner_id = '$partner_id'";
142 $billset .= ", x12_partner_id = '$partner_id'";
146 $billset = substr($billset, 2);
147 sqlStatement("UPDATE billing SET $billset WHERE " .
148 "encounter = '$encounter_id' AND pid='$patient_id' AND activity = 1");
151 // If a new claim version is requested, insert its row.
155 $payer_id = ($payer_id < 0) ? $row['payer_id'] : $payer_id;
156 $bill_process = ($bill_process < 0) ? $row['bill_process'] : $bill_process;
157 $process_file = ($process_file) ? $row['process_file'] : $process_file;
158 $target = ($target) ? $row['target'] : $target;
159 $partner_id = ($partner_id < 0) ? $row['x12_partner_id'] : $partner_id;
160 $sql = "INSERT INTO claims SET " .
161 "patient_id = '$patient_id', " .
162 "encounter_id = '$encounter_id', " .
163 "bill_time = UNIX_TIMESTAMP(NOW()), " .
164 "payer_id = '$payer_id', " .
165 "status = '$status', " .
166 "payer_type = '" . $row['payer_type'] . "', " .
167 "bill_process = '$bill_process', " .
168 "process_time = '" . $row['process_time'] . "', " .
169 "process_file = '$process_file', " .
170 "target = '$target', " .
171 "x12_partner_id = '$partner_id'";
174 $version = sqlQuery( "SELECT IFNULL(MAX(version),0) + 1 AS increment FROM claims WHERE patient_id = ? AND encounter_id = ?", array( $patient_id, $encounter_id ) );
177 $sql .= "INSERT INTO claims SET " .
178 "patient_id = $patient_id, " .
179 "encounter_id = $encounter_id, " .
180 "bill_time = NOW() $claimset ," .
181 "version = " . $version['increment'];
184 {//Claim automatic forward case.startTra
185 $sql= "INSERT INTO claims SET " .
186 "patient_id = $patient_id, " .
187 "encounter_id = $encounter_id, " .
188 "bill_time = NOW(), status=$status ," .
189 "version = " . $version['increment'];
195 // Otherwise update the existing claim row.
197 else if ($claimset) {
198 $claimset = substr($claimset, 2);
199 sqlStatement("UPDATE claims SET $claimset WHERE " .
200 "patient_id = '$patient_id' AND encounter_id = '$encounter_id' AND " .
201 // "payer_id = '" . $row['payer_id'] . "' AND " .
202 "version = '" . $row['version'] . "'");
205 // Whenever a claim is marked billed, update A/R accordingly.
208 if ($payer_type > 0) {
209 sqlStatement("UPDATE form_encounter SET " .
210 "last_level_billed = '$payer_type' WHERE " .
211 "pid = '$patient_id' AND encounter = '$encounter_id'");
218 // Determine if the encounter is billed. It is considered billed if it
219 // has at least one chargeable item, and all of them are billed.
221 function isEncounterBilled($pid, $encounter) {
222 $billed = -1; // no chargeable services yet
224 $bres = sqlStatement("SELECT " .
225 "billing.billed FROM billing, code_types WHERE " .
226 "billing.pid = ? AND " .
227 "billing.encounter = ? AND " .
228 "billing.activity = 1 AND " .
229 "code_types.ct_key = billing.code_type AND " .
230 "code_types.ct_fee = 1 " .
232 "SELECT billed FROM drug_sales WHERE " .
235 array($pid, $encounter, $pid, $encounter));
237 while ($brow = sqlFetchArray($bres)) {
238 if ($brow['billed'] == 0) {
242 if ($billed < 0) $billed = 1;
249 // Get the co-pay amount that is effective on the given date.
250 // Or if no insurance on that date, return -1.
252 function getCopay($patient_id, $encdate) {
253 $tmp = sqlQuery("SELECT provider, copay FROM insurance_data " .
254 "WHERE pid = '$patient_id' AND type = 'primary' " .
255 "AND date <= '$encdate' ORDER BY date DESC LIMIT 1");
256 if ($tmp['provider']) return sprintf('%01.2f', 0 + $tmp['copay']);
260 // Get the total co-pay amount paid by the patient for an encounter
261 function getPatientCopay($patient_id, $encounter) {
262 $resMoneyGot = sqlStatement("SELECT sum(pay_amount) as PatientPay FROM ar_activity where ".
263 "pid = ? and encounter = ? and payer_type=0 and account_code='PCP'",
264 array($patient_id,$encounter));
265 //new fees screen copay gives account_code='PCP'
266 $rowMoneyGot = sqlFetchArray($resMoneyGot);
267 $Copay=$rowMoneyGot['PatientPay'];
271 // Get the "next invoice reference number" from this user's pool of reference numbers.
273 function getInvoiceRefNumber() {
274 $trow = sqlQuery("SELECT lo.notes " .
275 "FROM users AS u, list_options AS lo " .
276 "WHERE u.username = ? AND " .
277 "lo.list_id = 'irnpool' AND lo.option_id = u.irnpool AND lo.activity = 1 LIMIT 1",
278 array($_SESSION['authUser']));
279 return empty($trow['notes']) ? '' : $trow['notes'];
282 // Increment the "next invoice reference number" of this user's pool.
283 // This identifies the "digits" portion of that number and adds 1 to it.
284 // If it contains more than one string of digits, the last is used.
286 function updateInvoiceRefNumber() {
287 $irnumber = getInvoiceRefNumber();
288 // Here "?" specifies a minimal match, to get the most digits possible:
289 if (preg_match('/^(.*?)(\d+)(\D*)$/', $irnumber, $matches)) {
290 $newdigs = sprintf('%0' . strlen($matches[2]) . 'd', $matches[2] + 1);
291 $newnumber = $matches[1] . $newdigs . $matches[3];
292 sqlStatement("UPDATE users AS u, list_options AS lo " .
293 "SET lo.notes = ? WHERE " .
294 "u.username = ? AND " .
295 "lo.list_id = 'irnpool' AND lo.option_id = u.irnpool",
296 array($newnumber, $_SESSION['authUser']));
301 // Common function for voiding a receipt or checkout. When voiding a checkout you can specify
302 // $time as a timestamp (yyyy-mm-dd hh:mm:ss) or 'all'; default is the last checkout.
304 function doVoid($patient_id, $encounter_id, $purge=false, $time='') {
305 $what_voided = $purge ? 'checkout' : 'receipt';
311 // Get last checkout timestamp.
312 $corow = sqlQuery("(SELECT bill_date FROM billing WHERE " .
313 "pid = ? AND encounter = ? AND activity = 1 AND bill_date IS NOT NULL) " .
315 "(SELECT bill_date FROM drug_sales WHERE " .
316 "pid = ? AND encounter = ? AND bill_date IS NOT NULL) " .
317 "ORDER BY bill_date DESC LIMIT 1",
318 array($patient_id, $encounter_id, $patient_id, $encounter_id));
319 if (!empty($corow['bill_date'])) {
320 $date_original = $corow['bill_date'];
323 else if ($time == 'all') {
324 $row = sqlQuery("SELECT SUM(pay_amount) AS payments, " .
325 "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " .
326 "pid = ? AND encounter = ?",
327 array($patient_id, $encounter_id));
328 $adjustments = $row['adjustments'];
329 $payments = $row['payments'];
332 $date_original = $time;
334 // Get its charges and adjustments.
335 if ($date_original) {
336 $row = sqlQuery("SELECT SUM(pay_amount) AS payments, " .
337 "SUM(adj_amount) AS adjustments FROM ar_activity WHERE " .
338 "pid = ? AND encounter = ? AND post_time = ?",
339 array($patient_id, $encounter_id, $date_original));
340 $adjustments = $row['adjustments'];
341 $payments = $row['payments'];
344 // Get old invoice reference number.
345 $encrow = sqlQuery("SELECT invoice_refno FROM form_encounter WHERE " .
346 "pid = ? AND encounter = ? LIMIT 1",
347 array($patient_id, $encounter_id));
348 $old_invoice_refno = $encrow['invoice_refno'];
350 $usingirnpools = getInvoiceRefNumber();
351 // If not (undoing a checkout or using IRN pools), nothing is done.
352 if ($purge || $usingirnpools) {
353 $query = "INSERT INTO voids SET " .
355 "encounter_id = ?, " .
356 "what_voided = ?, " .
357 "date_voided = NOW(), " .
362 $sqlarr = array($patient_id, $encounter_id, $what_voided, $_SESSION['authUserID'], $row['adjustments'],
363 $row['payments'], $old_invoice_refno);
364 if ($date_original) {
365 $query .= ", date_original = ?";
366 $sqlarr[] = $date_original;
368 sqlStatement($query, $sqlarr);
371 // Purge means delete adjustments and payments from the last checkout
372 // and re-open the visit.
373 if ($date_original) {
374 sqlStatement("DELETE FROM ar_activity WHERE " .
375 "pid = ? AND encounter = ? AND post_time = ?",
376 array($patient_id, $encounter_id, $date_original));
377 sqlStatement("UPDATE billing SET billed = 0, bill_date = NULL WHERE " .
378 "pid = ? AND encounter = ? AND activity = 1 AND " .
379 "bill_date IS NOT NULL AND bill_date = ?",
380 array($patient_id, $encounter_id, $date_original));
381 sqlStatement("update drug_sales SET billed = 0, bill_date = NULL WHERE " .
382 "pid = ? AND encounter = ? AND " .
383 "bill_date IS NOT NULL AND bill_date = ?",
384 array($patient_id, $encounter_id, $date_original));
387 if ($time == 'all') {
388 sqlStatement("DELETE FROM ar_activity WHERE " .
389 "pid = ? AND encounter = ?",
390 array($patient_id, $encounter_id));
392 sqlStatement("UPDATE billing SET billed = 0, bill_date = NULL WHERE " .
393 "pid = ? AND encounter = ? AND activity = 1",
394 array($patient_id, $encounter_id));
395 sqlStatement("update drug_sales SET billed = 0, bill_date = NULL WHERE " .
396 "pid = ? AND encounter = ?",
397 array($patient_id, $encounter_id));
399 sqlStatement("UPDATE form_encounter SET last_level_billed = 0, " .
400 "last_level_closed = 0, stmt_count = 0, last_stmt_date = NULL " .
401 "WHERE pid = ? AND encounter = ?",
402 array($patient_id, $encounter_id));
404 else if ($usingirnpools) {
405 // Non-purge means just assign a new invoice reference number.
406 $new_invoice_refno = add_escape_custom(updateInvoiceRefNumber());
407 sqlStatement("UPDATE form_encounter " .
408 "SET invoice_refno = ? " .
409 "WHERE pid = ? AND encounter = ?",
410 array($new_invoice_refno, $patient_id, $encounter_id));