Some requested security fixes.
[openemr.git] / library / sl_eob.inc.php
blobf47533f26c0741d546c9dc0bc4924eae53af20a7
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 include_once("patient.inc");
10 include_once("billing.inc");
12 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] !== 2) {
13 include_once("sql-ledger.inc");
14 include_once("invoice_summary.inc.php");
17 $chart_id_cash = 0;
18 $chart_id_ar = 0;
19 $chart_id_income = 0;
20 $services_id = 0;
22 function slInitialize() {
23 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2) return;
25 global $chart_id_cash, $chart_id_ar, $chart_id_income, $services_id;
26 global $sl_cash_acc, $sl_ar_acc, $sl_income_acc, $sl_services_id;
28 SLConnect();
30 $chart_id_cash = SLQueryValue("select id from chart where accno = '$sl_cash_acc'");
31 if ($sl_err) die($sl_err);
32 if (! $chart_id_cash) die(xl("There is no COA entry for cash account ") . "'$sl_cash_acc'");
34 $chart_id_ar = SLQueryValue("select id from chart where accno = '$sl_ar_acc'");
35 if ($sl_err) die($sl_err);
36 if (! $chart_id_ar) die(xl("There is no COA entry for AR account ") . "'$sl_ar_acc'");
38 $chart_id_income = SLQueryValue("select id from chart where accno = '$sl_income_acc'");
39 if ($sl_err) die($sl_err);
40 if (! $chart_id_income) die(xl("There is no COA entry for income account ") . "'$sl_income_acc'");
42 $services_id = SLQueryValue("select id from parts where partnumber = '$sl_services_id'");
43 if ($sl_err) die($sl_err);
44 if (! $services_id) die(xl("There is no parts entry for services ID ") . "'$sl_services_id'");
47 function slTerminate() {
48 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2) return;
49 SLClose();
52 // Try to figure out our invoice number (pid.encounter) from the
53 // claim ID and other stuff in the ERA. This should be straightforward
54 // except that some payers mangle the claim ID that we give them.
56 function slInvoiceNumber(&$out) {
57 $invnumber = $out['our_claim_id'];
58 $atmp = preg_split('/[ -]/', $invnumber);
59 $acount = count($atmp);
61 $pid = 0;
62 $encounter = 0;
63 if ($acount == 2) {
64 $pid = $atmp[0];
65 $encounter = $atmp[1];
67 else if ($acount == 3) {
68 $pid = $atmp[0];
69 $brow = sqlQuery("SELECT encounter FROM billing WHERE " .
70 "pid = '$pid' AND encounter = '" . $atmp[1] . "' AND activity = 1");
72 $encounter = $brow['encounter'];
74 else if ($acount == 1) {
75 $pres = sqlStatement("SELECT pid FROM patient_data WHERE " .
76 "lname LIKE '" . addslashes($out['patient_lname']) . "' AND " .
77 "fname LIKE '" . addslashes($out['patient_fname']) . "' " .
78 "ORDER BY pid DESC");
79 while ($prow = sqlFetchArray($pres)) {
80 if (strpos($invnumber, $prow['pid']) === 0) {
81 $pid = $prow['pid'];
82 $encounter = substr($invnumber, strlen($pid));
83 break;
88 if ($pid && $encounter) $invnumber = "$pid.$encounter";
89 return array($pid, $encounter, $invnumber);
92 // Insert a row into the acc_trans table.
93 // This should never be called if SQL-Ledger is not used.
95 function slAddTransaction($invid, $chartid, $amount, $date, $source, $memo, $insplan, $debug) {
96 global $sl_err;
97 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2)
98 die("Internal error calling slAddTransaction()");
99 $date = fixDate($date);
100 $query = "INSERT INTO acc_trans ( " .
101 "trans_id, " .
102 "chart_id, " .
103 "amount, " .
104 "transdate, " .
105 "source, " .
106 "project_id, " .
107 "memo " .
108 ") VALUES ( " .
109 "$invid, " . // trans_id
110 "$chartid, " . // chart_id
111 "$amount, " . // amount
112 "'$date', " . // transdate
113 "'$source', " . // source
114 "$insplan, " . // project_id
115 "'$memo' " . // memo
116 ")";
117 if ($debug) {
118 echo $query . "<br>\n";
119 } else {
120 SLQuery($query);
121 if ($sl_err) die($sl_err);
125 // Insert a row into the invoice table.
126 // This should never be called if SQL-Ledger is not used.
128 function slAddLineItem($invid, $serialnumber, $amount, $units, $insplan, $description, $debug) {
129 global $sl_err, $services_id;
130 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2)
131 die("Internal error calling slAddLineItem()");
132 $units = max(1, intval($units));
133 $price = $amount / $units;
134 $tmp = sprintf("%01.2f", $price);
135 if (abs($price - $tmp) < 0.000001) $price = $tmp;
136 $query = "INSERT INTO invoice ( " .
137 "trans_id, " .
138 "parts_id, " .
139 "description, " .
140 "qty, " .
141 "allocated, " .
142 "sellprice, " .
143 "fxsellprice, " .
144 "discount, " .
145 "unit, " .
146 "project_id, " .
147 "serialnumber " .
148 ") VALUES ( " .
149 "$invid, " . // trans_id
150 "$services_id, " . // parts_id
151 "'$description', " . // description
152 "$units, " . // qty
153 "0, " . // allocated
154 "$price, " . // sellprice
155 "$price, " . // fxsellprice
156 "0, " . // discount
157 "'', " . // unit
158 "$insplan, " . // project_id
159 "'$serialnumber'" . // serialnumber
160 ")";
161 if ($debug) {
162 echo $query . "<br>\n";
163 } else {
164 SLQuery($query);
165 if ($sl_err) die($sl_err);
169 // Update totals and payment date in the invoice header. Dollar amounts are
170 // stored as double precision floats so we have to be careful about rounding.
171 // This should never be called if SQL-Ledger is not used.
173 function slUpdateAR($invid, $amount, $paid = 0, $paydate = "", $debug) {
174 global $sl_err;
175 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2)
176 die("Internal error calling slUpdateAR()");
177 $paydate = fixDate($paydate);
178 $query = "UPDATE ar SET amount = round(CAST (amount AS numeric) + $amount, 2), " .
179 "netamount = round(CAST (netamount AS numeric) + $amount, 2)";
180 if ($paid) $query .= ", paid = round(CAST (paid AS numeric) + $paid, 2), datepaid = '$paydate'";
181 $query .= " WHERE id = $invid";
182 if ($debug) {
183 echo $query . "<br>\n";
184 } else {
185 SLQuery($query);
186 if ($sl_err) die($sl_err);
190 // This gets a posting session ID. If the payer ID is not 0 and a matching
191 // session already exists, then its ID is returned. Otherwise a new session
192 // is created.
194 function arGetSession($payer_id, $reference, $check_date, $deposit_date='', $pay_total=0) {
195 if (empty($deposit_date)) $deposit_date = $check_date;
196 if ($payer_id) {
197 $row = sqlQuery("SELECT session_id FROM ar_session WHERE " .
198 "payer_id = '$payer_id' AND reference = '$reference' AND " .
199 "check_date = '$check_date' AND deposit_date = '$deposit_date' " .
200 "ORDER BY session_id DESC LIMIT 1");
201 if (!empty($row['session_id'])) return $row['session_id'];
203 return sqlInsert("INSERT INTO ar_session ( " .
204 "payer_id, user_id, reference, check_date, deposit_date, pay_total " .
205 ") VALUES ( " .
206 "'$payer_id', " .
207 "'" . $_SESSION['authUserID'] . "', " .
208 "'$reference', " .
209 "'$check_date', " .
210 "'$deposit_date', " .
211 "'$pay_total' " .
212 ")");
215 // Post a payment, SQL-Ledger style.
217 function slPostPayment($trans_id, $thispay, $thisdate, $thissrc, $code, $thisins, $debug) {
218 global $chart_id_cash, $chart_id_ar;
219 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2)
220 die("Internal error calling slPostPayment()");
221 // Post a payment: add to ar, subtract from cash.
222 slAddTransaction($trans_id, $chart_id_ar , $thispay , $thisdate, $thissrc, $code, $thisins, $debug);
223 slAddTransaction($trans_id, $chart_id_cash, 0 - $thispay, $thisdate, $thissrc, $code, $thisins, $debug);
224 slUpdateAR($trans_id, 0, $thispay, $thisdate, $debug);
226 //writing the check details to Session Table on ERA proxcessing
227 function arPostSession($payer_id,$check_number,$check_date,$pay_total,$post_to_date,$deposit_date,$debug) {
228 $query = "INSERT INTO ar_session( " .
229 "payer_id,user_id,closed,reference,check_date,pay_total,post_to_date,deposit_date,patient_id,payment_type,adjustment_code,payment_method " .
230 ") VALUES ( " .
231 "'$payer_id'," .
232 $_SESSION['authUserID']."," .
233 "0," .
234 "'ePay - $check_number'," .
235 "'$check_date', " .
236 "$pay_total, " .
237 "'$post_to_date','$deposit_date', " .
238 "0,'insurance','insurance_payment','electronic'" .
239 ")";
240 if ($debug) {
241 echo $query . "<br>\n";
242 } else {
243 $sessionId=sqlInsert($query);
244 return $sessionId;
248 // Post a payment, new style.
250 function arPostPayment($patient_id, $encounter_id, $session_id, $amount, $code, $payer_type, $memo, $debug, $time='', $codetype='') {
251 $codeonly = $code;
252 $modifier = '';
253 $tmp = strpos($code, ':');
254 if ($tmp) {
255 $codeonly = substr($code, 0, $tmp);
256 $modifier = substr($code, $tmp+1);
258 if (empty($time)) $time = date('Y-m-d H:i:s');
259 $query = "INSERT INTO ar_activity ( " .
260 "pid, encounter, code_type, code, modifier, payer_type, post_time, post_user, " .
261 "session_id, memo, pay_amount " .
262 ") VALUES ( " .
263 "'$patient_id', " .
264 "'$encounter_id', " .
265 "'$codetype', " .
266 "'$codeonly', " .
267 "'$modifier', " .
268 "'$payer_type', " .
269 "'$time', " .
270 "'" . $_SESSION['authUserID'] . "', " .
271 "'$session_id', " .
272 "'$memo', " .
273 "'$amount' " .
274 ")";
275 sqlStatement($query);
276 return;
279 // Post a charge. This is called only from sl_eob_process.php where
280 // automated remittance processing can create a new service item.
281 // Here we add it as an unauthorized item to the billing table.
283 function arPostCharge($patient_id, $encounter_id, $session_id, $amount, $units, $thisdate, $code, $description, $debug, $codetype='') {
284 /*****************************************************************
285 // Select an existing billing item as a template.
286 $row= sqlQuery("SELECT * FROM billing WHERE " .
287 "pid = '$patient_id' AND encounter = '$encounter_id' AND " .
288 "code_type = 'CPT4' AND activity = 1 " .
289 "ORDER BY id DESC LIMIT 1");
290 $this_authorized = 0;
291 $this_provider = 0;
292 if (!empty($row)) {
293 $this_authorized = $row['authorized'];
294 $this_provider = $row['provider_id'];
296 *****************************************************************/
298 if (empty($codetype)) {
299 // default to CPT4 if empty, which is consistent with previous functionality.
300 $codetype="CPT4";
302 $codeonly = $code;
303 $modifier = '';
304 $tmp = strpos($code, ':');
305 if ($tmp) {
306 $codeonly = substr($code, 0, $tmp);
307 $modifier = substr($code, $tmp+1);
310 addBilling($encounter_id,
311 $codetype,
312 $codeonly,
313 $description,
314 $patient_id,
317 $modifier,
318 $units,
319 $amount,
321 '');
324 // See comments above.
325 // In the SQL-Ledger case this service item is added only to SL and
326 // not to the billing table.
328 function slPostCharge($trans_id, $thisamt, $thisunits, $thisdate, $code, $thisins, $description, $debug) {
329 global $chart_id_income, $chart_id_ar;
330 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2)
331 die("Internal error calling slPostCharge()");
332 // Post an adjustment: add negative invoice item, add to ar, subtract from income
333 slAddLineItem($trans_id, $code, $thisamt, $thisunits, $thisins, $description, $debug);
334 if ($thisamt) {
335 slAddTransaction($trans_id, $chart_id_ar , 0 - $thisamt, $thisdate, $description, $code, $thisins, $debug);
336 slAddTransaction($trans_id, $chart_id_income, $thisamt , $thisdate, $description, $code, $thisins, $debug);
337 slUpdateAR($trans_id, $thisamt, 0, '', $debug);
341 // Post an adjustment, SQL-Ledger style.
343 function slPostAdjustment($trans_id, $thisadj, $thisdate, $thissrc, $code, $thisins, $reason, $debug) {
344 global $chart_id_income, $chart_id_ar;
345 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2)
346 die("Internal error calling slPostAdjustment()");
347 // Post an adjustment: add negative invoice item, add to ar, subtract from income
348 $adjdate = fixDate($thisdate);
349 $description = "Adjustment $adjdate $reason";
350 slAddLineItem($trans_id, $code, 0 - $thisadj, 1, $thisins, $description, $debug);
351 if ($thisadj) {
352 slAddTransaction($trans_id, $chart_id_ar, $thisadj, $thisdate, "InvAdj $thissrc", $code, $thisins, $debug);
353 slAddTransaction($trans_id, $chart_id_income, 0 - $thisadj, $thisdate, "InvAdj $thissrc", $code, $thisins, $debug);
354 slUpdateAR($trans_id, 0 - $thisadj, 0, '', $debug);
358 // Post an adjustment, new style.
360 function arPostAdjustment($patient_id, $encounter_id, $session_id, $amount, $code, $payer_type, $reason, $debug, $time='', $codetype='') {
361 $codeonly = $code;
362 $modifier = '';
363 $tmp = strpos($code, ':');
364 if ($tmp) {
365 $codeonly = substr($code, 0, $tmp);
366 $modifier = substr($code, $tmp+1);
368 if (empty($time)) $time = date('Y-m-d H:i:s');
369 $query = "INSERT INTO ar_activity ( " .
370 "pid, encounter, code_type, code, modifier, payer_type, post_user, post_time, " .
371 "session_id, memo, adj_amount " .
372 ") VALUES ( " .
373 "'$patient_id', " .
374 "'$encounter_id', " .
375 "'$codetype', " .
376 "'$codeonly', " .
377 "'$modifier', " .
378 "'$payer_type', " .
379 "'" . $_SESSION['authUserID'] . "', " .
380 "'$time', " .
381 "'$session_id', " .
382 "'$reason', " .
383 "'$amount' " .
384 ")";
385 sqlStatement($query);
386 return;
389 function arGetPayerID($patient_id, $date_of_service, $payer_type) {
390 if ($payer_type < 1 || $payer_type > 3) return 0;
391 $tmp = array(1 => 'primary', 2 => 'secondary', 3 => 'tertiary');
392 $value = $tmp[$payer_type];
393 $query = "SELECT provider FROM insurance_data WHERE " .
394 "pid = ? AND type = ? AND date <= ? " .
395 "ORDER BY date DESC LIMIT 1";
396 $nprow = sqlQuery($query, array($patient_id,$value,$date_of_service) );
397 if (empty($nprow)) return 0;
398 return $nprow['provider'];
401 // Make this invoice re-billable, new style.
403 function arSetupSecondary($patient_id, $encounter_id, $debug,$crossover=0) {
404 if ($crossover==1) {
405 //if claim forwarded setting a new status
406 $status=6;
408 } else {
410 $status=1;
413 // Determine the next insurance level to be billed.
414 $ferow = sqlQuery("SELECT date, last_level_billed " .
415 "FROM form_encounter WHERE " .
416 "pid = '$patient_id' AND encounter = '$encounter_id'");
417 $date_of_service = substr($ferow['date'], 0, 10);
418 $new_payer_type = 0 + $ferow['last_level_billed'];
419 if ($new_payer_type < 3 && !empty($ferow['last_level_billed']) || $new_payer_type == 0)
420 ++$new_payer_type;
422 $new_payer_id = arGetPayerID($patient_id, $date_of_service, $new_payer_type);
424 if ($new_payer_id) {
425 // Queue up the claim.
426 if (!$debug)
427 updateClaim(true, $patient_id, $encounter_id, $new_payer_id, $new_payer_type,$status, 5, '', 'hcfa','',$crossover);
429 else {
430 // Just reopen the claim.
431 if (!$debug)
432 updateClaim(true, $patient_id, $encounter_id, -1, -1, $status, 0, '','','',$crossover);
435 return xl("Encounter ") . $encounter . xl(" is ready for re-billing.");
438 // Make this invoice re-billable, SQL-Ledger style.
440 function slSetupSecondary($invid, $debug) {
441 global $sl_err, $GLOBALS, $code_types;
443 if ($GLOBALS['oer_config']['ws_accounting']['enabled'] === 2)
444 die("Internal error calling slSetupSecondary()");
446 $info_msg = '';
448 // Get some needed items from the SQL-Ledger invoice.
449 $arres = SLQuery("select invnumber, transdate, customer_id, employee_id, " .
450 "shipvia from ar where ar.id = $invid");
451 if ($sl_err) die($sl_err);
452 $arrow = SLGetRow($arres, 0);
453 if (! $arrow) die(xl('There is no match for invoice id') . ' = ' . "$trans_id.");
454 $customer_id = $arrow['customer_id'];
455 $date_of_service = $arrow['transdate'];
456 list($trash, $encounter) = explode(".", $arrow['invnumber']);
458 // Get the OpenEMR PID corresponding to the customer.
459 $pdrow = sqlQuery("SELECT patient_data.pid " .
460 "FROM integration_mapping, patient_data WHERE " .
461 "integration_mapping.foreign_id = $customer_id AND " .
462 "integration_mapping.foreign_table = 'customer' AND " .
463 "patient_data.id = integration_mapping.local_id");
464 $pid = $pdrow['pid'];
465 if (! $pid) die(xl("Cannot find patient from SQL-Ledger customer id") . " = $customer_id.");
467 // Determine the ID of the next insurance company (if any) to be billed.
468 $new_payer_id = -1;
469 $new_payer_type = -1;
470 $insdone = strtolower($arrow['shipvia']);
471 foreach (array('ins1' => 'primary', 'ins2' => 'secondary', 'ins3' => 'tertiary') as $key => $value) {
472 if (strpos($insdone, $key) === false) {
473 $nprow = sqlQuery("SELECT provider FROM insurance_data WHERE " .
474 "pid = '$pid' AND type = '$value' AND date <= '$date_of_service' " .
475 "ORDER BY date DESC LIMIT 1");
476 if (!empty($nprow['provider'])) {
477 $new_payer_id = $nprow['provider'];
478 $new_payer_type = substr($key, 3);
480 break;
484 // Find out if the encounter exists.
485 $ferow = sqlQuery("SELECT pid FROM form_encounter WHERE " .
486 "encounter = $encounter");
487 $encounter_pid = $ferow['pid'];
489 // If it exists, just update the billing items.
490 if ($encounter_pid) {
491 if ($encounter_pid != $pid)
492 die(xl("Expected form_encounter.pid to be ") . $pid . ', ' . xl(' but was ') . $encounter_pid);
494 // If there's a payer ID queue it up, otherwise just reopen it.
495 if ($new_payer_id > 0) {
496 // TBD: implement a default bill_process and target in config.php,
497 // it should not really be hard-coded here.
498 if (!$debug)
499 updateClaim(true, $pid, $encounter, $new_payer_id, $new_payer_type, 1, 5, '', 'hcfa');
500 } else {
501 if (!$debug)
502 updateClaim(true, $pid, $encounter, -1, -1, 1, 0, '');
505 $info_msg = xl("Encounter ") . $encounter . xl(" is ready for re-billing.");
506 return;
509 // If we get here then the encounter does not already exist. This should
510 // only happen if A/R was converted from an earlier system. In this case
511 // the encounter ID should be the date of service, and we will create the
512 // encounter.
514 // If it does not exist then it better be (or start with) a date.
515 if (! preg_match("/^20\d\d\d\d\d\d/", $encounter))
516 die(xl("Internal error: encounter '") . $encounter . xl("' should exist but does not."));
518 $employee_id = $arrow['employee_id'];
520 // Get the OpenEMR provider info corresponding to the SQL-Ledger salesman.
521 $drrow = sqlQuery("SELECT users.id, users.username, users.facility_id " .
522 "FROM integration_mapping, users WHERE " .
523 "integration_mapping.foreign_id = $employee_id AND " .
524 "integration_mapping.foreign_table = 'salesman' AND " .
525 "users.id = integration_mapping.local_id");
526 $provider_id = $drrow['id'];
527 if (! $provider_id) die(xl("Cannot find provider from SQL-Ledger employee = ") . $employee_id );
529 if (! $date_of_service) die(xl("Invoice has no date!"));
531 // Generate a new encounter number.
532 $conn = $GLOBALS['adodb']['db'];
533 $new_encounter = $conn->GenID("sequences");
535 // Create the "new encounter".
536 $encounter_id = 0;
537 $query = "INSERT INTO form_encounter ( " .
538 "date, reason, facility_id, pid, encounter, onset_date, provider_id " .
539 ") VALUES ( " .
540 "'$date_of_service', " .
541 "'" . xl('Imported from Accounting') . "', " .
542 "'" . addslashes($drrow['facility_id']) . "', " .
543 "$pid, " .
544 "$new_encounter, " .
545 "'$date_of_service', " .
546 "'$provider_id' " .
547 ")";
548 if ($debug) {
549 echo $query . "<br>\n";
550 echo xl("Call to addForm() goes here.<br>") . "\n";
551 } else {
552 $encounter_id = idSqlStatement($query);
553 if (! $encounter_id) die(xl("Insert failed: ") . $query);
554 addForm($new_encounter, xl("New Patient Encounter"), $encounter_id,
555 "newpatient", $pid, 1, $date_of_service);
556 $info_msg = xl("Encounter ") . $new_encounter . xl(" has been created. ");
559 // For each invoice line item with a billing code we will insert
560 // a billing row with payer_id set to -1. Order the line items
561 // chronologically so that each procedure code will be followed by
562 // its associated icd9 code.
564 $inres = SLQuery("SELECT * FROM invoice WHERE trans_id = $invid " .
565 "ORDER BY id");
566 if ($sl_err) die($sl_err);
568 // When nonzero, this will be the ID of a billing row that needs to
569 // have its justify field set.
570 $proc_ins_id = 0;
572 for ($irow = 0; $irow < SLRowCount($inres); ++$irow) {
573 $row = SLGetRow($inres, $irow);
574 $amount = sprintf('%01.2f', $row['sellprice'] * $row['qty']);
576 // Extract the billing code.
577 $code = xl("Unknown");
578 if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['serialnumber'], $matches)) {
579 $code = strtoupper($matches[1]);
581 else if (preg_match("/([A-Za-z0-9]\d\d\S*)/", $row['description'], $matches)) {
582 $code = strtoupper($matches[1]);
585 list($code, $modifier) = explode("-", $code);
587 // Set the billing code type and description.
588 $code_type = "";
589 $code_text = "";
591 foreach ($code_types as $key => $value) {
592 if (preg_match("/$key/", $row['serialnumber'])) {
593 $code_type = $key;
594 if (!$value['diag']) {
595 $code_text = xl("Procedure") . " $code";
596 } else {
597 $code_text = xl("Diagnosis") . " $code";
598 if ($proc_ins_id) {
599 $query = "UPDATE billing SET justify = '$code' WHERE id = $proc_ins_id";
600 if ($debug) {
601 echo $query . "<br>\n";
602 } else {
603 sqlQuery($query);
605 $proc_ins_id = 0;
608 break;
612 // Skip adjustments.
613 if (! $code_type) continue;
615 // Insert the billing item. If this for a procedure code then save
616 // the row ID so that we can update the "justify" field with the ICD9
617 // code, which should come next in the loop.
619 $query = "INSERT INTO billing ( " .
620 "date, code_type, code, pid, provider_id, user, groupname, authorized, " .
621 "encounter, code_text, activity, payer_id, billed, bill_process, " .
622 "bill_date, modifier, units, fee, justify, target " .
623 ") VALUES ( " .
624 "NOW(), " .
625 "'$code_type', " .
626 "'$code', " .
627 "$pid, " .
628 "0, " . // was $provider_id but that is now in form_encounter
629 "'" . $_SESSION['authId'] . "', " .
630 "'" . $_SESSION['authProvider'] . "', " .
631 "1, " .
632 "$new_encounter, " .
633 "'$code_text', " .
634 "1, " .
635 "$new_payer_id, " .
636 ($new_payer_id > 0 ? "1, " : "0, ") .
637 ($new_payer_id > 0 ? "5, " : "0, ") .
638 ($new_payer_id > 0 ? "NOW(), " : "NULL, ") .
639 "'$modifier', " .
640 "0, " .
641 "$amount, " .
642 "'', " .
643 ($new_payer_id > 0 ? "'hcfa' " : "NULL ") .
644 ")";
645 if ($debug) {
646 echo $query . "<br>\n";
647 } else {
648 $proc_ins_id = idSqlStatement($query);
649 if ($code_types[$code_type]['diag'])
650 $proc_ins_id = 0;
654 // Finally, change this invoice number to contain the new encounter number.
656 $new_invnumber = "$pid.$new_encounter";
657 $query = "UPDATE ar SET invnumber = '$new_invnumber' WHERE id = $invid";
658 if ($debug) {
659 echo $query . "<br>\n";
660 } else {
661 SLQuery($query);
662 if ($sl_err) die($sl_err);
663 $info_msg .= xl("This invoice number has been changed to ") . $new_invnumber;
666 return $info_msg;