Merge branch 'AE/groupFixes' of github.com:matrix-israel/openemr into AE/groupFixes
[openemr.git] / interface / billing / billing_process.php
blobcacd0cea9d7a2dbc850398d2cae592f717e3fa8c
1 <?php
2 /*
3 * Billing process Program
5 * This program process data for claims generation
7 * Copyright (C) 2016 Terry Hill <terry@lillysystems.com>
8 * Copyright (C) 2014 Brady Miller <brady.g.miller@gmail.com>
10 * LICENSE: This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 3
13 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see http://opensource.org/licenses/gpl-license.php.
21 * @package OpenEMR
22 * @author Terry Hill <terry@lilysystems.com>
23 * @author Brady Miller <brady.g.miller@gmail.com>
24 * @link http://www.open-emr.org
27 include_once("../globals.php");
28 include_once("$srcdir/patient.inc");
29 include_once("$srcdir/billrep.inc");
30 include_once("$srcdir/billing.inc");
31 include_once("$srcdir/gen_x12_837.inc.php");
32 include_once("$srcdir/gen_hcfa_1500.inc.php");
34 $EXPORT_INC = "$webserver_root/custom/BillingExport.php";
35 if (file_exists($EXPORT_INC)) {
36 include_once($EXPORT_INC);
37 $BILLING_EXPORT = true;
40 $bill_info = array();
42 $bat_type = ''; // will be edi or hcfa
43 $bat_sendid = '';
44 $bat_recvid = '';
45 $bat_content = '';
46 $bat_gscount = 0;
47 $bat_stcount = 0;
48 $bat_time = time();
49 $bat_hhmm = date('Hi' , $bat_time);
50 $bat_yymmdd = date('ymd', $bat_time);
51 $bat_yyyymmdd = date('Ymd', $bat_time);
52 // Minutes since 1/1/1970 00:00:00 GMT will be our interchange control number:
53 $bat_icn = sprintf('%09.0f', $bat_time/60);
54 $bat_filename = date("Y-m-d-Hi", $bat_time) . "-batch.";
55 $bat_filename .= (isset($_POST['bn_process_hcfa']) || isset($_POST['bn_process_hcfa_form'])) ? 'pdf' : 'txt';
57 if (isset($_POST['bn_process_hcfa']) || isset($_POST['bn_process_hcfa_form']) ) {
58 $pdf = new Cezpdf('LETTER');
59 $pdf->ezSetMargins(trim($_POST['top_margin'])+0,0,trim($_POST['left_margin'])+0,0);
60 $pdf->selectFont('Courier');
63 function append_claim(&$segs) {
64 global $bat_content, $bat_sendid, $bat_recvid, $bat_sender, $bat_stcount;
65 global $bat_gscount, $bat_yymmdd, $bat_yyyymmdd, $bat_hhmm, $bat_icn;
67 foreach ($segs as $seg) {
68 if (!$seg) continue;
69 $elems = explode('*', $seg);
70 if ($elems[0] == 'ISA') {
71 if (!$bat_content) {
72 $bat_sendid = trim($elems[6]);
73 $bat_recvid = trim($elems[8]);
74 $bat_sender = $GS02 ? $GS02 : $bat_sendid;
75 $bat_content = substr($seg, 0, 70) .
76 "$bat_yymmdd*$bat_hhmm*" . $elems[11] . "*" . $elems[12] . "*$bat_icn*" .
77 $elems[14] . "*" . $elems[15] . "*:~";
79 continue;
80 } else if (!$bat_content) {
81 die("Error:<br>\nInput must begin with 'ISA'; " .
82 "found '" . htmlentities($elems[0]) . "' instead");
84 if ($elems[0] == 'GS') {
85 if ($bat_gscount == 0) {
86 ++$bat_gscount;
87 $bat_content .= "GS*HC*" . $elems[2] . "*" . $elems[3] .
88 "*$bat_yyyymmdd*$bat_hhmm*1*X*" . $elems[8] . "~";
90 continue;
92 if ($elems[0] == 'ST') {
93 ++$bat_stcount;
94 $bat_content .= sprintf("ST*837*%04d", $bat_stcount);
95 if (!empty($elems[3])) $bat_content .= "*" . $elems[3];
96 $bat_content .= "~";
97 continue;
99 if ($elems[0] == 'SE') {
100 $bat_content .= sprintf("SE*%d*%04d~", $elems[1], $bat_stcount);
101 continue;
103 if ($elems[0] == 'GE' || $elems[0] == 'IEA') continue;
104 $bat_content .= $seg . '~';
108 function append_claim_close() {
109 global $bat_content, $bat_stcount, $bat_gscount, $bat_icn;
110 if ($bat_gscount) $bat_content .= "GE*$bat_stcount*1~";
111 $bat_content .= "IEA*$bat_gscount*$bat_icn~";
114 function send_batch() {
115 global $bat_content, $bat_filename, $webserver_root;
116 // If a writable edi directory exists, log the batch to it.
117 // I guarantee you'll be glad we did this. :-)
118 $fh = @fopen($GLOBALS['OE_SITE_DIR'] . "/edi/$bat_filename", 'a');
119 if ($fh) {
120 fwrite($fh, $bat_content);
121 fclose($fh);
123 header("Pragma: public");
124 header("Expires: 0");
125 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
126 header("Content-Type: application/force-download");
127 header("Content-Disposition: attachment; filename=$bat_filename");
128 header("Content-Description: File Transfer");
129 header("Content-Length: " . strlen($bat_content));
130 echo $bat_content;
133 process_form($_POST);
135 function process_form($ar) {
136 global $bill_info, $webserver_root, $bat_filename, $pdf;
138 if (isset($ar['bn_x12']) || isset($ar['bn_x12_encounter']) || isset($ar['bn_process_hcfa']) || isset($ar['bn_hcfa_txt_file']) || isset($ar['bn_process_hcfa_form'])) {
139 if ($GLOBALS['billing_log_option'] == 1) {
140 $hlog = fopen($GLOBALS['OE_SITE_DIR']. "/edi/process_bills.log", 'a');
142 else { // ($GLOBALS['billing_log_option'] == 2)
143 $hlog = fopen($GLOBALS['OE_SITE_DIR']. "/edi/process_bills.log", 'w');
147 if (isset($ar['bn_external'])) {
148 // Open external billing file for output.
149 $be = new BillingExport();
152 $db = $GLOBALS['adodb']['db'];
154 if (empty($ar['claims'])) {
155 $ar['claims'] = array();
157 $claim_count = 0;
158 foreach ($ar['claims'] as $claimid => $claim_array) {
160 $ta = explode("-",$claimid);
161 $patient_id = $ta[0];
162 $encounter = $ta[1];
163 $payer_id = substr($claim_array['payer'], 1);
164 $payer_type = substr($claim_array['payer'], 0, 1);
165 $payer_type = $payer_type == 'T' ? 3 : $payer_type == 'S' ? 2 : 1;
167 if (isset($claim_array['bill'])) {
169 if (isset($ar['bn_external'])) {
170 // Write external claim.
171 $be->addClaim($patient_id, $encounter);
173 else {
174 $sql = "SELECT x.processing_format from x12_partners as x where x.id =" .
175 $db->qstr($claim_array['partner']);
176 $result = $db->Execute($sql);
177 $target = "x12";
178 if ($result && !$result->EOF) {
179 $target = $result->fields['processing_format'];
183 $tmp = 1;
184 if (isset($ar['HiddenMarkAsCleared']) && $ar['HiddenMarkAsCleared']=='yes')
186 $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 2);// $sql .= " billed = 1, ";
188 if (isset($ar['bn_x12']) || isset($ar['bn_x12_encounter'])) {
189 $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 1, 1, '', $target, $claim_array['partner']);
190 } else if (isset($ar['bn_process_hcfa']) || isset($ar['bn_hcfa_txt_file']) || isset($ar['bn_process_hcfa_form'])) {
191 $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 1, 1, '', 'hcfa');
192 } else if (isset($ar['bn_mark'])) {
193 // $sql .= " billed = 1, ";
194 $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 2);
195 } else if (isset($ar['bn_reopen'])) {
196 $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 1, 0);
197 } else if (isset($ar['bn_external'])) {
198 // $sql .= " billed = 1, ";
199 $tmp = updateClaim(true, $patient_id, $encounter, $payer_id, $payer_type, 2);
202 if (!$tmp) {
203 die(xl("Claim ") . $claimid . xl(" update failed, not in database?"));
205 else {
206 if(isset($ar['bn_mark'])) {
207 $bill_info[] = xl("Claim ") . $claimid . xl(" was marked as billed only.") . "\n";
210 else if (isset($ar['bn_reopen'])) {
211 $bill_info[] = xl("Claim ") . $claimid . xl(" has been re-opened.") . "\n";
214 else if (isset($ar['bn_x12']) || isset($ar['bn_x12_encounter'])) {
215 $log = '';
216 $segs = explode("~\n", gen_x12_837($patient_id, $encounter, $log,
217 isset($ar['bn_x12_encounter'])));
218 fwrite($hlog, $log);
219 append_claim($segs);
220 if (!updateClaim(false, $patient_id, $encounter, -1, -1, 2, 2, $bat_filename)) {
221 $bill_info[] = xl("Internal error: claim ") . $claimid . xl(" not found!") . "\n";
226 else if (isset($ar['bn_process_hcfa'])) {
227 $log = '';
228 $lines = gen_hcfa_1500($patient_id, $encounter, $log);
229 fwrite($hlog, $log);
230 $alines = explode("\014", $lines); // form feeds may separate pages
231 foreach ($alines as $tmplines) {
232 if ($claim_count++) $pdf->ezNewPage();
233 $pdf->ezSetY($pdf->ez['pageHeight'] - $pdf->ez['topMargin']);
234 $pdf->ezText($tmplines, 12, array('justification' => 'left', 'leading' => 12));
236 if (!updateClaim(false, $patient_id, $encounter, -1, -1, 2, 2, $bat_filename)) {
237 $bill_info[] = xl("Internal error: claim ") . $claimid . xl(" not found!") . "\n";
240 else if (isset($ar['bn_process_hcfa_form'])) {
241 $log = '';
242 $lines = gen_hcfa_1500($patient_id, $encounter, $log);
243 $hcfa_image = $GLOBALS['images_static_absolute'] ."/cms1500.png";
244 fwrite($hlog, $log);
245 $alines = explode("\014", $lines); // form feeds may separate pages
246 foreach ($alines as $tmplines) {
247 if ($claim_count++) $pdf->ezNewPage();
248 $pdf->ezSetY($pdf->ez['pageHeight'] - $pdf->ez['topMargin']);
249 $pdf->addPngFromFile("$hcfa_image", 0,0,612,792);
250 $pdf->ezText($tmplines, 12, array('justification' => 'left', 'leading' => 12));
252 if (!updateClaim(false, $patient_id, $encounter, -1, -1, 2, 2, $bat_filename)) {
253 $bill_info[] = xl("Internal error: claim ") . $claimid . xl(" not found!") . "\n";
257 else if (isset($ar['bn_hcfa_txt_file'])) {
258 $log = '';
259 $lines = gen_hcfa_1500($patient_id, $encounter, $log);
260 fwrite($hlog, $log);
261 $bat_content .= $lines;
262 if (!updateClaim(false, $patient_id, $encounter, -1, -1, 2, 2, $bat_filename)) {
263 $bill_info[] = xl("Internal error: claim ") . $claimid . xl(" not found!") . "\n";
267 else {
268 $bill_info[] = xl("Claim ") . $claimid . xl(" was queued successfully.") . "\n";
273 } // end if this claim has billing
275 } // end foreach
277 if (isset($ar['bn_x12']) || isset($ar['bn_x12_encounter'])) {
278 append_claim_close();
279 fclose($hlog);
280 send_batch();
281 exit;
284 if (isset($ar['bn_process_hcfa'])) {
285 fclose($hlog);
286 // If a writable edi directory exists (and it should), write the pdf to it.
287 $fh = @fopen($GLOBALS['OE_SITE_DIR'] . "/edi/$bat_filename", 'a');
288 if ($fh) {
289 fwrite($fh, $pdf->ezOutput());
290 fclose($fh);
292 // Send the PDF download.
293 $pdf->ezStream(array('Content-Disposition' => $bat_filename));
294 exit;
296 if ( isset($ar['bn_process_hcfa_form']) ) {
297 fclose($hlog);
298 // If a writable edi directory exists (and it should), write the pdf to it.
299 $fh = @fopen($GLOBALS['OE_SITE_DIR'] . "/edi/$bat_filename", 'a');
300 if ($fh) {
301 fwrite($fh, $pdf->ezOutput());
302 fclose($fh);
304 // Send the PDF download.
305 header("Pragma: public");
306 header("Expires: 0");
307 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
308 header("Content-Type: application/force-download");
309 header("Content-Disposition: attachment; filename=$bat_filename");
310 header("Content-Description: File Transfer");
311 //header("Content-Length: " . strlen($bat_content));
312 echo $pdf->ezOutput();
314 exit;
317 if (isset($ar['bn_hcfa_txt_file'])) {
318 fclose($hlog);
319 $fh = @fopen($GLOBALS['OE_SITE_DIR'] . "/edi/$bat_filename", 'a');
320 if ($fh) {
321 fwrite($fh, $bat_content);
322 fclose($fh);
324 header("Pragma: public");
325 header("Expires: 0");
326 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
327 header("Content-Type: application/force-download");
328 header("Content-Disposition: attachment; filename=$bat_filename");
329 header("Content-Description: File Transfer");
330 header("Content-Length: " . strlen($bat_content));
331 echo $bat_content;
332 exit;
335 if (isset($ar['bn_external'])) {
336 // Close external billing file.
337 $be->close();
341 <html>
342 <head>
343 <?php if (function_exists(html_header_show)) html_header_show(); ?>
345 <link rel="stylesheet" href="<?php echo $css_header;?>" type="text/css">
346 <script type="text/javascript" src="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery-min-1-9-1/index.js"></script>
347 <script>
348 $(document).ready( function() {
349 $("#close-link").click( function() {
350 window.close();
353 </script>
355 </head>
356 <body class="body_top">
357 <br><p><h3><?php echo xlt('Billing queue results'); ?>:</h3><a href="#" id="close-link"><?php echo xlt('Close'); ?></a><ul>
358 <?php
359 foreach ($bill_info as $infoline) {
360 echo nl2br($infoline);
363 </ul></p>
364 </body>
365 </html>