added days of week to reccurence widget (#286)
[openemr.git] / library / edihistory / edih_csv_parse.php
blob4cf060dae6e01f4e47e9084abb85ac3e566e587f
1 <?php
2 /*
3 * edih_csv_parse.php
5 * Copyright 2016 Kevin McCormick Carrollton, Texas
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 3 or later. You should have
16 * received a copy of the GNU General Public License along with this program;
17 * if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * <http://opensource.org/licenses/gpl-license.php>
23 * @link: http://www.open-emr.org
24 * @package ediHistory
27 /* ========= notes
28 * EDI files may contain multiple ISA envelopes. Each ISA envelope is treated as a "file" here.
29 * The same file name may have one or more ISA control numbers
30 * The ISA control number is associated with each GS and ST envelope and each included transaction.
31 * Each transaction will also link to the ISA control number as a means of retrieving the file.
33 * The CSV data column headers are the array keys for each EDI file type.
36 /**
37 * Provide a more user-friendly date in csv tables
39 * @param string YYYYMMDD
40 * @return string YYYY-MM-DD
42 function edih_parse_date($strdate) {
43 if (strlen($strdate) == 6) {
44 $gtdt = getdate();
45 $cy = (string)$gtdt['year'];
46 $dt1 = substr($cy, 0, 2) . $strdate;
47 } elseif (strpos($strdate, '-') >= 6) {
48 $dt1 = substr($strdate, 0, strpos($strdate, '-') - 1 );
49 } elseif (strlen($strdate) == 8) {
50 $dt1 = $strdate;
51 } else {
52 // bad argument
53 csv_edihist_log('edih_parse_date: invalid argument '.$strdate);
54 return false;
57 return substr($dt1, 0, 4) . '-' . substr($dt1, 4, 2) . '-' . substr($dt1, 6, 2);
60 /** remittance 835 files
62 * Each payment trace number (Control) gets a row in the csv file record.
63 * Each claim payment transaction gets a row in the csv claim record
64 * <pre>
66 * $array
67 * [$icn]['type']
68 * [$icn]['file'][$i] => array keys match csv_table_head() output
69 * [$icn]['claim'][$i] => array keys match csv_table_head() output
71 * </pre>
73 * @uses csv_file_type()
74 * @uses edih_parse_date()
75 * @uses edih_x12_transaction()
76 * @uses edih_get_segment()
77 * @param object edih_x12_obj
78 * @return array
80 function edih_835_csv_data($obj835) {
82 $ret_ar = array();
84 $seg_ar = $obj835->edih_segments();
85 $env_ar = $obj835->edih_envelopes();
86 $de = $obj835->edih_delimiters()['e'];
87 $fn = $obj835->edih_filename();
88 //$tp = $obj835->edih_type();
90 // since 835 "files" table uses transaction trace as the "Control"
91 // we must assemble the 'files' array in the ST loop
92 // ['ISA'][$icn]
93 foreach($env_ar['ISA'] as $icn => $isa) {
95 $ret_ar[$icn]['claim'] = array();
96 $ret_ar[$icn]['file'] = array();
98 $gsdate = '';
99 $trace = '';
101 if ( array_key_exists('GS', $env_ar) ) {
102 // for unlikely case of 'mixed' GS types in file
103 foreach($env_ar['GS'] as $gs) {
104 if ($gs['icn'] == $icn) {
105 $ft = $gs['type'];
106 $gsdate = $gs['date'];
107 $payer_id = $gs['srcid']; // from TRN03
108 break;
112 $ret_ar[$icn]['type'] = csv_file_type($ft);
113 $gsdate = ($gsdate) ? $gsdate : edih_parse_date($isa['date']);
115 $fdx = count($ret_ar[$icn]['file']);
117 // ['ST'][$stky]=>['start']['count']['stn']['gsn']['icn']['type']['trace']['acct']
118 // ['ST'][$stky]['acct'][i]=>pid-enc$$ret_ar[$icn]['claim'][$cdx]['SvcDate'] =
119 foreach($env_ar['ST'] as $st) {
120 if ($st['icn'] != $icn) { continue; }
121 // the "files" table has a row for each payment trace
123 if ($trace != $st['trace']) {
124 $fdx = count($ret_ar[$icn]['file']);
126 $ret_ar[$icn]['file'][$fdx]['Date'] = $gsdate;
127 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
128 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
129 $ret_ar[$icn]['file'][$fdx]['Trace'] = $st['trace'];
130 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = (string)count($st['acct']);
131 $ret_ar[$icn]['file'][$fdx]['Denied'] = 0;
132 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_id;
134 $trace = $st['trace'];
137 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
138 $stacct = array_values(array_unique($st['acct']));
139 $clmct = count($stacct);
140 $payer = '';
141 $denied = 0;
143 $n1pr = $obj835->edih_get_segment('N1', 'N1'.$de.'PR'.$de, $stsegs);
144 $payer = '';
145 if ($n1pr) {
146 foreach($n1pr as $n1) {
147 $sar = explode($de, $n1);
148 $payer = (isset($sar[2])) ? $sar[2] : '';
150 if ($payer) { $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer; }
151 } // end if ($n1pr)
154 for($i=0; $i<$clmct; $i++) {
155 $clpsegs = $obj835->edih_x12_transaction($stacct[$i], $st['stn']);
156 if ( !is_array($clpsegs) || !count($clpsegs) ) {
158 csv_edihist_log('edih_835_csv_data: no segments for account '.$st['acct'][$i]);
159 continue;
162 foreach($clpsegs as $trans) {
164 $cdx = count($ret_ar[$icn]['claim']);
165 foreach($trans as $seg) {
167 if (strncmp($seg, 'CLP'.$de, 4) === 0) {
168 $sar = explode($de, $seg);
170 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = (isset($sar[1])) ? $sar[1] : '';
171 $ret_ar[$icn]['claim'][$cdx]['Status'] = (isset($sar[2])) ? $sar[2] : '';
172 $ret_ar[$icn]['claim'][$cdx]['Pmt'] = (isset($sar[4])) ? sprintf("%01.02f", $sar[4]) : '';
173 $ret_ar[$icn]['claim'][$cdx]['PtResp'] = ( isset($sar[5]) ) ? sprintf("%01.02f", $sar[5]) : '';
174 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = ( isset($sar[7]) ) ? trim($sar[7]) : '';
175 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
176 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $st['trace'];
177 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $payer;
178 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
179 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
181 if($sar[2]=='4' || $sar[2]=='22' || $sar[2]=='23') { $denied++; }
182 $loopid = "2100";
183 continue;
186 if (strncmp($seg, 'NM1'.$de.'QC'.$de, 7) === 0) {
187 $sar = explode($de, $seg);
188 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', '.$sar[5]: "";
189 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3].', '.$sar[4].$midn;
190 continue;
192 if (strncmp($seg, 'DTM'.$de.'232'.$de, 8) === 0) {
193 $sar = explode($de, $seg);
194 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[2];
195 continue;
197 if (strncmp($seg, 'DTM'.$de.'472'.$de, 8) === 0) {
198 $sar = explode($de, $seg);
199 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[2];
200 continue;
202 } // end foreach($trans as $seg)
203 } // end foreach($clpsegs as $trans) {
204 } // end for($i=0; $i<$clmct; $i++)
205 // get denied count
206 $ret_ar[$icn]['file'][$fdx]['Denied'] = ($denied) ? $denied : '0';
208 } // end foreach($env_ar['ST'] as $st)
210 } // end foreach($env_ar['ISA'] as $icn => $isa)
212 return $ret_ar;
217 * Parse csv data from 837 files
218 * Note that this can return false provider values for extensive claims
219 * since loops are not tracked and 837 claims can have numerous
220 * providers, but probably not an issue for OpenEMR
222 * @param object edih_x12_ file object
223 * @return array data to write csv file and csv clain table rows
225 function edih_837_csv_data($obj837) {
227 $ret_ar = array();
229 $seg_ar = $obj837->edih_segments();
230 $env_ar = $obj837->edih_envelopes();
231 $de = $obj837->edih_delimiters()['e'];
232 $fn = $obj837->edih_filename();
233 //$ft = csv_file_type( $obj837->edih_type() );
235 if ( !isset($env_ar['ST']) ) {
236 csv_edihist_log('edih_837_csv_data: envelope error');
237 return $ret_ar;
239 //['file'] = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12_partner');
240 //['claim'] =
241 // array('PtName', 'SvcDate', 'CLM01', 'InsLevel', 'Control', 'File_837', 'Fee', 'PtPaid', 'Provider' );
243 foreach($env_ar['ISA'] as $icn => $isa) {
245 $ret_ar[$icn]['claim'] = array();
246 $ret_ar[$icn]['file'] = array();
247 //$ret_ar[$icn]['type'] = $ft;
248 foreach($env_ar['GS'] as $gs) {
249 if ($gs['icn'] == $icn) {
250 $ret_ar[$icn]['type'] = csv_file_type( $gs['type'] );
251 $gsdate = $gs['date'];
252 break;
256 $fdx = count($ret_ar[$icn]['file']);
258 $ret_ar[$icn]['file'][$fdx]['Date'] = (string)$gsdate;
259 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
260 // if GS06 were unique, it could be used as the 'Control'
261 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
262 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = (string)$isa['receiver'];
264 $clm_ct = 0;
266 foreach($env_ar['ST'] as $st) {
267 // claims should be in the correct ISA envelope
268 if ( $st['icn'] != $icn ) { continue; }
270 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
271 $stacct = array_values(array_unique($st['acct']));
272 $clmct = count($stacct);
273 // $st['icn'] is the ISA control number for the ISA envelope containing the ST--SE
274 $date = $env_ar['ISA'][$st['icn']]['date'];
275 $stn = $st['stn'];
276 for($i=0; $i<$clmct; $i++) {
277 //echo '=== ACCT '.$stacct[$i].' '.$st['stn'].'<br />'.PHP_EOL;
278 $asegs = $obj837->edih_x12_transaction($stacct[$i], $st['stn']);
279 if ( !is_array($asegs) || !count($asegs) ) {
280 csv_edihist_log('edih_837_csv_data: no segments for account '.$st['acct'][$i]);
281 continue;
283 foreach($asegs as $trans) {
285 //array('PtName'=>0, 'SvcDate'=>1, 'CLM01'=>2, 'InsLevel'=>3, 'Control'=>4, 'FileName'=>5, 'Fee'=>6, 'PtPaid'=>7, 'Provider'=>8 );
287 //'f837': $hdr = array('PtName', 'SvcDate', 'CLM01', 'InsLevel', 'Control', 'FileName', 'Fee', 'PtPaid', 'Provider' )
288 foreach($trans as $seg) {
289 if ( strncmp($seg, 'BHT'.$de, 4) === 0 ) {
290 $cdx = count($ret_ar[$icn]['claim']);
291 $sar = explode($de, $seg);
292 $bht03 = $sar[3];
293 $hl = '';
294 $clm_ct++;
296 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
297 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
298 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = '';
299 $ret_ar[$icn]['claim'][$cdx]['InsLevel'] = '';
301 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = (strlen($bht03) == 13) ? $bht03 : sprintf("%s%04d", $st['icn'], $st['stn']);
302 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
304 $ret_ar[$icn]['claim'][$cdx]['Fee'] = '0';
305 $ret_ar[$icn]['claim'][$cdx]['PtPaid'] = '0';
306 $ret_ar[$icn]['claim'][$cdx]['Provider'] = '';
308 if (strncmp($seg, 'HL'.$de, 3) === 0 ) {
309 $sar = explode($de, $seg);
310 $hl = $sar[3];
311 continue;
314 if ( intval($hl) == 20 ) {
315 if ( strncmp($seg, 'NM1'.$de, 4) === 0 ) {
316 $sar = explode($de, $seg);
317 if ($sar[2] == '82' || $sar[2] == '85') {
318 $ret_ar[$icn]['claim'][$cdx]['Provider'] = $sar[9];
320 continue;
322 } // end if $hl == '20'
324 if ( intval($hl) >= 22 ) {
325 if ( strncmp($seg, 'SBR'.$de, 4) === 0 ) {
326 $sar = explode($de, $seg);
327 $ret_ar[$icn]['claim'][$cdx]['InsLevel'] = $sar[1];
329 if ( strncmp($seg, 'CLM'.$de, 4) === 0 ) {
330 $sar = explode($de, $seg);
331 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[1];
332 $ret_ar[$icn]['claim'][$cdx]['Fee'] = $sar[2];
333 continue;
335 if ( strncmp($seg, 'AMT'.$de.'F5'.$de, 7) === 0 ) {
336 $sar = explode($de, $seg);
337 $ret_ar[$icn]['claim'][$cdx]['PtPaid'] = $sar[2];
338 continue;
340 if ( strncmp($seg, 'NM1'.$de, 4) === 0 ) {
341 $sar = explode($de, $seg);
342 if ( strpos('|IL|QC', $sar[1]) ) {
343 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', '.$sar[5]: '';
344 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3].', '.$sar[4].$midn;
345 continue;
347 if ( $sar[1] == '82') {
348 $ret_ar[$icn]['claim'][$cdx]['Provider'] = $sar[9];
349 continue;
352 if ( strncmp($seg, 'DTP'.$de.'472'.$de, 8) === 0 ) {
353 $sar = explode($de, $seg);
354 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[3];
355 continue;
357 } // end if $hl >= '22'
358 } // end foreach($trans as $seg)
359 } // end foreach($asegs as $trans)
360 } // end for($i=0; $i<$clmct; $i++)
361 } // end foreach($obj837->envelopes['ST'] as $st)
362 // claim count
363 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = (string)$clm_ct;
364 } // end foreach($env_ar['ISA'] as $icn => $isa)
366 return $ret_ar;
370 * extract csv table row data for x12 277 files
372 * @param object edih_x12_file object of type 276/277
373 * @return array
375 function edih_277_csv_data($obj277) {
377 $ret_ar = array();
379 $seg_ar = $obj277->edih_segments();
380 $env_ar = $obj277->edih_envelopes();
381 $de = $obj277->edih_delimiters()['e'];
382 $fn = $obj277->edih_filename();
383 $tp = $obj277->edih_type();
384 // 'HN' 277 'HR' 276 )
385 $env_ar = $obj277->edih_envelopes();
387 if ( !isset($env_ar['ST']) ) {
388 csv_edihist_log( 'edih_277_csv_data: envelope error');
389 return $ret_ar;
391 if ( !isset($env_ar['GS']) ) {
392 csv_edihist_log('edih_277_csv_data: envelope error');
393 return $ret_ar;
396 foreach($env_ar['ISA'] as $icn => $isa) {
398 $ret_ar[$icn]['claim'] = array();
399 $ret_ar[$icn]['file'] = array();
401 $rspdate = $isa['date'];
402 foreach($env_ar['GS'] as $gs) {
403 if ($gs['icn'] == $icn) {
404 $ret_ar[$icn]['type'] = csv_file_type($gs['type']);
405 $rspdate = $gs['date'];
406 break;
409 //$ret_ar[$icn]['type'] = csv_file_type($ft);
411 $fdx = count($ret_ar[$icn]['file']);
412 //['f277']['file'] = array('Date', 'FileName', 'Control', 'Accept', 'AccAmt', 'Reject', 'RejAmt');
413 //'f276': $hdr = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12Partner');
414 $ret_ar[$icn]['file'][$fdx]['Date'] = $rspdate;
415 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
416 // could be GS06 for 276 if it were unique
417 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
418 if ($tp == 'HN') {
419 $ret_ar[$icn]['file'][$fdx]['Accept'] = 0;
420 $ret_ar[$icn]['file'][$fdx]['Reject'] = 0;
421 $ret_ar[$icn]['file'][$fdx]['AccAmt'] = 0;
422 $ret_ar[$icn]['file'][$fdx]['RejAmt'] = 0;
423 } else {
424 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = 0;
425 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = $isa['receiver'];
428 $clmct = 0;
430 //['ST'][$stky]=>['start']['count']['stn']['gsn']['icn']['type']['trace']['acct']
431 // ['ST'][$stky]['acct'][i]=>pid-enc
432 //'f277': $hdr = array('PtName', 'SvcDate', 'CLM01', 'Status', 'BHT03', 'FileName', 'Payer', 'Trace');
433 foreach($env_ar['ST'] as $st) {
435 if ( $st['icn'] != $icn ) { continue; }
437 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
438 $stacct = array_values(array_unique($st['bht03']));
439 $clmct += count($stacct);
440 $st_icn = $st['icn']; // same value as $obj277->envelopes['ISA']['icn']
441 $stn = $st['stn'];
443 if ($tp == 'HR') { $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = $clmct; }
445 //for($i=0; $i<$clmct; $i++) {
446 for($i=0; $i<count($stacct); $i++) {
448 $asegs = $obj277->edih_x12_transaction($stacct[$i]);
450 foreach($asegs as $trans) {
452 foreach($trans as $seg) {
454 if ( strncmp($seg, 'BHT'.$de, 4) === 0) {
455 $cdx = count($ret_ar[$icn]['claim']);
457 $sar = explode($de, $seg);
458 if ( $sar[2] != '08' ) {
459 csv_edihist_log('Claim Status BHT purpose code: '.$sar[2].' in ST '.$st['stn'].' in file '.$fn);
461 $trns_tp = (isset($sar[6]) && $sar[6]) ? $sar[6] : '';
462 if ($trns_tp == 'TH') {
463 $bht_id = 'ack'; // 277CA
464 } elseif($trns_tp == 'DG') {
465 $bht_id = 'rsp'; // 277
466 } else {
467 $bht_id = 'sub'; // 276
470 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
471 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
472 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = '';
474 if ($tp == 'HN') {
475 // 277
476 $ret_ar[$icn]['claim'][$cdx]['Status'] = '';
477 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = $sar[3];
478 } elseif ($tp == 'HR') {
479 //276
480 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = '';
481 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = sprintf("%s%04d", $st_icn, $stn);
485 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
487 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
488 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = '';
489 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
490 continue;
493 if ( strncmp($seg, 'HL'.$de, 3) === 0) {
494 $sar = explode($de, $seg);
495 $hl = (string)$sar[3];
498 if ( $hl == '20' ) {
499 // information source
500 if ( strncmp($seg, 'NM1'.$de, 4) === 0) {
501 $sar = explode($de, $seg);
502 $ret_ar[$icn]['claim'][$cdx]['Payer'] = ($sar[1]=='PR' || $sar[1]=='AY') ? $sar[3] : '';
503 continue;
507 if ( $hl == '21' ) {
508 // information source or receiver level rejection
509 // -- user should view the transaction
510 // -- don't include in csv data so Trace only refers to 276
511 //if ( strncmp($seg, 'TRN'.$de, 4) === 0) {
512 //$sar = explode($de, $seg);
513 //$ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
515 if ( strncmp($seg, 'STC'.$de, 4) === 0) {
516 $sar = explode($de, $seg);
517 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
519 if ( strncmp($seg, 'QTY'.$de, 4) === 0) {
520 $sar = explode($de, $seg);
521 if ( $sar[1] == '90' ) { $ret_ar[$icn]['file'][$fdx]['Accept'] += $sar[2]; }
522 if ( $sar[1] == 'AA' ) { $ret_ar[$icn]['file'][$fdx]['Reject'] += $sar[2]; }
524 if ( strncmp($seg, 'AMT'.$de, 4) === 0) {
525 $sar = explode($de, $seg);
526 if ( $sar[1] == 'YU' ) { $ret_ar[$icn]['file'][$fdx]['AccAmt'] += $sar[2]; }
527 if ( $sar[1] == 'YY' ) { $ret_ar[$icn]['file'][$fdx]['RejAmt'] += $sar[2]; }
529 continue;
532 if ( $hl == '19' ) {
533 // provider level rejection
534 // -- user should view the transaction
535 // -- don't include in csv data so Trace only refers to 276
536 //if ( strncmp($seg, 'TRN'.$de, 4) === 0) {
537 //$sar = explode($de, $seg);
538 //$ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
540 if ( strncmp($seg, 'STC'.$de, 4) === 0) {
541 $sar = explode($de, $seg);
542 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
544 continue;
547 if ( $hl == '22' || $hl == '23' ) {
548 // subscriber or dependent
549 if ( strncmp($seg, 'NM1'.$de, 4) === 0) {
550 $sar = explode($de, $seg);
551 if ( $sar[1] == 'IL' || $sar[1] == 'QC' ) {
552 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', '.$sar[5]: "";
553 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3].', '.$sar[4].$midn;
554 //if (isset($sar[8]) && $sar[8] == 'MI') {
555 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = (isset($sar[9])) ? $sar[9] : '';
558 continue;
560 // in response to 276, this is the reference given in TRN02
561 if ( strncmp($seg, 'TRN'.$de.'2'.$de, 4) === 0) {
562 $sar = explode($de, $seg);
563 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
564 continue;
566 // REF*EJ* will give the payer assigned claim number
567 // not used much in 277CA files
568 if ( strncmp($seg, 'REF'.$de.'EJ'.$de, 7) === 0) {
569 $sar = explode($de, $seg);
570 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[2];
571 continue;
573 if ( strncmp($seg, 'REF'.$de.'1K'.$de, 7) === 0) {
574 // hopefully OpenEMR will include the claim number in 276
575 if ($tp == 'HR') {
576 $sar = explode($de, $seg);
577 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = $sar[2];
579 continue;
581 // REF*D9*(Claim number)~
583 if ( strncmp($seg, 'STC'.$de, 4) === 0) {
584 // STC is only present in 277
585 $sar = explode($de, $seg);
586 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
587 continue;
589 continue;
592 if ( $hl == 'PT' ) {
593 // 277CA
594 if ( strncmp($seg, 'NM1'.$de, 4) === 0) {
595 $sar = explode($de, $seg);
596 if ( $sar[1] == 'IL' || $sar[1] == 'QC' ) {
597 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', '.$sar[5]: "";
598 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3].', '.$sar[4].$midn;
599 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = (isset($sar[9])) ? $sar[9] : '';
601 continue;
603 if ( strncmp($seg, 'TRN'.$de.'2'.$de, 6) === 0) {
604 $sar = explode($de, $seg);
605 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[2];
606 continue;
609 if ( strncmp($seg, 'STC'.$de, 4) === 0) {
610 $sar = explode($de, $seg);
611 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
612 continue;
614 //if ( strncmp($seg, 'REF'.$de.'1K'.$de, 7) === 0) {
615 //$sar = explode($de, $seg);
616 //$ret_ar[$icn]['claim'][$cdx]['ClaimID'] = $sar[2];
617 //continue;
619 if ( strncmp($seg, 'DTP'.$de.'472'.$de, 8) === 0) {
620 $sar = explode($de, $seg);
621 // D8-CCYYMMDD RD8-CCYYMMDD-CCYYMMDD only take initial date
622 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = substr($sar[3],0,8);
623 continue;
626 } // end foreach($trans as $seg)
627 } // end foreach($asegs as $trans)
628 } // end for($i=0; $i<$clmct; $i++)
629 }// end foreach($obj277->envelopes['ST'] as $st)
630 } // end foreach($env_ar['ISA'] as $icn => $isa)
632 return $ret_ar;
636 * parse an x12 278 file into data rows for csv tables
638 * @param object x12_file_object
639 * @return array
641 function edih_278_csv_data($obj278) {
643 // f278 file = array('Date', 'FileName', 'Control', 'TrnCount', 'Auth', 'Payer');
644 // f278 claim = array('PtName', 'FileDate', 'Trace', 'Status' 'BHT03', 'FileName', 'Auth', 'Payer');
646 $ret_ar = array();
648 $de = $obj278->edih_delimiters()['e'];
649 $ds = $obj278->edih_delimiters()['s'];
650 $fn = $obj278->edih_filename();
651 $seg_ar = $obj278->edih_segments();
652 $env_ar = $obj278->edih_envelopes();
653 $ft = csv_file_type( $obj278->edih_type() );
655 // $ft: 'HI'=>'278'
656 if ( !isset($env_ar['ST']) ) {
657 csv_edihist_log('edih_278_csv_data: envelope error '.$fn);
658 return false;
661 if ( !isset($env_ar['GS']) ) {
662 csv_edihist_log('edih_278_csv_data: envelope error '.$fn);
663 return $ret_ar;
666 foreach($env_ar['ISA'] as $icn => $isa) {
667 // array('Date', 'FileName', 'Control', 'ta1ctrl', 'RejCt');
668 $ret_ar[$icn]['type'] = $ft;
669 $ret_ar[$icn]['claim'] = array();
670 $ret_ar[$icn]['file'] = array();
671 $rspdate = $isa['date'];
673 foreach($env_ar['GS'] as $gs) {
674 if ($gs['icn'] == $icn) {
675 $rspdate = $gs['date'];
676 break;
679 foreach($env_ar['ST'] as $st) {
681 if ( $st['icn'] != $icn ) { continue; }
683 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
684 $loopid = '0';
685 $hl = 0;
686 //$isasender = $env_ar['ISA'][$st['icn']]['sender'];
687 //$isadate = $env_ar['ISA'][$st['icn']]['date'];
688 $isaicn = $st['icn'];
689 $has_le = false;
691 // for "claim" array
693 foreach($stsegs as $seg) {
695 if (strncmp($seg, 'BHT'.$de, 4) === 0 ) {
696 // new transaction
697 // bht01 0007 --> Src, Rcv, Sbr, Dep, Event, Services
698 $rqst = '';
699 $status = 'A';
700 $cdx = count($ret_ar[$icn]['claim']);
702 $sar = explode($de, $seg);
703 if ( isset($sar[2]) ) {
704 if ($sar[2] == '01') { $rqst = 'Cancel'; }
705 if ($sar[2] == '13') { $rqst = 'Req'; }
706 if ($sar[2] == '11') { $rqst = 'Rsp'; }
707 if ($sar[2] == '36') { $rqst = 'Reply'; }
709 $loopid = 0;
711 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
712 $ret_ar[$icn]['claim'][$cdx]['FileDate'] = $rspdate;
713 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
714 $ret_ar[$icn]['claim'][$cdx]['Status'] = '';
715 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = $sar[3]; //bht03 = $sar[3];
716 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
717 $ret_ar[$icn]['claim'][$cdx]['Auth'] = $rqst;
718 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
720 continue;
723 if (strncmp($seg, 'HL'.$de, 3) === 0 ) {
724 $sar = explode($de, $seg);
725 $hl = $sar[1];
726 $hlpc = $sar[2]; // parent code
727 $hllc = $sar[3];
728 $hlcc = (isset($sar[4])) ? $sar[4] : ''; // child code
729 if ($sar[3] == '20') { // level code
730 $loopid = '2000A'; // info source (payer)
731 } elseif ($sar[3] == '21') {
732 $loopid = '2000B'; // info receiver (clinic)
733 } elseif ($sar[3] == '22') {
734 $loopid = '2000C'; // subscriber
735 } elseif ($sar[3] == '23') {
736 $loopid = '2000D'; // dependent
737 } elseif ($sar[3] == 'EV') {
738 $loopid = '2000E'; // patient event
739 } elseif ($sar[3] == 'SS') {
740 $loopid = '2000F'; // service
741 } else {
742 //debug
743 csv_edihist_log('HL has no level '.$seg.' in '.$fn);
745 continue;
748 if (strncmp($seg, 'NM1'.$de, 4) === 0 ) {
749 $sar = explode($de, $seg);
750 $nm101 = $sar[1];
751 $nm103 = $sar[3];
752 $nm103 = ($sar[4]) ? $nm103.', '.$sar[4] : $nm103;
753 $nm103 = ($sar[5]) ? $nm103.' '.$sar[5] : $nm103;
754 if ($loopid == '2000A') {
755 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $nm103; //
756 $payer_name = $nm103;
757 } elseif ( $loopid == '2000C' ) {
758 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm103; //$ptname = $nm1;
759 $loopid = '2010C';
760 } elseif ( $loopid == '2000D') {
761 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm103; //$ptname = $nm1;
762 $loopid = '2010D';
763 } elseif ( strpos( '|2000E',$loopid) ) {
764 $loopid = '2000E';
765 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010EA' : $loopid;
766 $loopid = (strpos('|45|FS|ND|PW|R3', $nm101) ) ? '2010EB' : $loopid;
767 $loopid = ($nm101 == 'L5') ? '2010EC' : $loopid;
768 } elseif ( $loopid == '2000F' ) {
769 $loopid = '2000F';
770 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010FA' : $loopid;
772 continue;
774 // for 278 eligibility response (invalid data in 278 request)
775 if (strncmp($seg, 'AAA'.$de, 4) === 0 ) {
776 $sar = explode($de, $seg);
777 $status = 'R';
778 $rej_ct++;
779 $aaa_code = $sar[3];
780 $rsp_code = $sar[4];
781 if ($loopid == '2000A') {
782 $status .= ' Src '.$aaa_code;
783 } elseif ($loopid == '2000B') {
784 $status .= ' Rcv '.$aaa_code;
785 } elseif ($loopid == '2000C') {
786 $status .= ' Sbr '.$aaa_code;
787 } elseif ($loopid == '2000D') {
788 $status .= ' Dep '.$aaa_code;
789 } elseif ($loopid == '2000E') {
790 $status .= ' Pt '.$aaa_code;
791 } elseif ($loopid == '2000F') {
792 $status .= ' Svc '.$aaa_code;
793 } elseif ($loopid == '2010FA') {
794 $status .= ' Prv '.$aaa_code;
795 } elseif ($loopid == '2010EA') {
796 $status .= ' Svc '.$aaa_code;
797 } elseif ($loopid == '2010EC') {
798 $status .= ' Tpt '.$aaa_code;
801 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
803 continue;
806 // for 278 tracking
807 // this assumes OpenEMR will include a TRN segment in requests
808 if (strncmp($seg, 'TRN'.$de, 4) === 0 ) {
809 $sar = explode($de, $seg);
810 if ($rqst == 'Req') {
811 if ( isset($sar[1]) && $sar[1] == '1') {
812 $ret_ar[$icn]['claim'][$cdx]['Trace'] = (isset($sar[2])) ? $sar[2] : '';
814 } else {
815 if ( isset($sar[1]) && $sar[1] == '2') {
816 $ret_ar[$icn]['claim'][$cdx]['Trace'] = (isset($sar[2])) ? $sar[2] : '';
821 } // end foreach($stsegs as $seg)
823 } // endforeach($env_ar['ST'] as $st
824 $fdx = count($ret_ar[$icn]['file']);
826 $ret_ar[$icn]['file'][$fdx]['Date'] = $rspdate;
827 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
828 // could be GS06 for 278 request type
829 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
830 $ret_ar[$icn]['file'][$fdx]['TrnCount'] = $cdx;
831 $ret_ar[$icn]['file'][$fdx]['Auth'] = $rqst;
832 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_name;
834 } // endforeach($env_ar['ISA'] as $icn=>$isa)
836 return $ret_ar;
840 /**
841 * Obtain claim information from batch 837|270|276|278 file to match 997/999 response
842 * Note, we assume each batch ST envelope contains a single transaction.
843 * Manual inspection is required if more than one transaction in an ST block,
845 * The 997/999 parse script creates a BHT03 reference by concatenating the
846 * response ISA13 (in TA1 segment) and the ST02 from the AK2 segment
847 * return array ['pt_name'] ['clm01'] ['svcdate'] ['batch_name'] ['stn']
849 * @uses csv_file_type()
850 * @uses csv_search_record()
852 * @param string concatenate ISA13 and ST02 for source file
853 * @param string type of source file
854 * @return array
856 function edih_rsp_st_match($rsp_trace, $file_type) {
858 $info_ar = array();
860 if ( strlen($rsp_trace) == 13 ) {
861 $bticn = substr($rsp_trace, 0, 9);
862 $stn = substr($rsp_trace, -4);
863 $btsrch = $rsp_trace;
864 } else {
865 // debug
866 csv_edihist_log('edih_rsp_st_match() invalid trace argument '.$rsp_trace);
867 return $info_ar;
870 $ft = csv_file_type($file_type);
872 if ( strpos('|f837|f276|f270|f278', $ft) === false ) {
873 // debug
874 csv_edihist_log('edih_rsp_st_match: file type '.$ft.' not in |f837|f276|f270|278');
875 return $info_ar;
878 $batch_srch = csv_search_record($ft, 'claim', array('s_val'=>$rsp_trace, 's_col'=>4, 'r_cols'=>'All'), '1' );
879 if (is_array($batch_srch) && count($batch_srch[0])) {
880 $info_ar['pt_name'] = $batch_srch[0][0]; // $batch_srch['PtName'];
881 $info_ar['clm01'] = ($rtp == 'f837') ? $batch_srch[0][2] : $batch_srch[0][4]; // $batch_srch['CLM01'] : $batch_srch['BHT03'];
882 $info_ar['svcdate'] = $batch_srch[0][1]; // ($rtp == 'f270') ? $batch_srch['ReqDate'] : $batch_srch['SvcDate'];
883 $info_ar['batch_name'] = $batch_srch[0][5]; // $batch_srch['FileName'];
886 return $info_ar;
890 /** Extract csv file data rows from 997/999 files
892 * <pre> Creates array
893 * ['claim'][$i] = array('PtName', 'SvcDate', 'CLM01', 'Status', 'ak_num', 'File_997', 'Control', 'err_seg');
894 * ['file'][$i] = array('Date', 'FileName', 'Control', 'TA1ctrl', 'RejCt');
895 * </pre>
897 * @uses edih_x12_file() edi HC file class
898 * @uses edih_997_837_st_match()
899 * @param object edih_x12_file object of type 999/997
900 * @return array
902 function edih_997_csv_data($obj997) {
904 $ret_ar = array();
906 $de = $obj997->edih_delimiters()['e'];
907 $ds = $obj997->edih_delimiters()['s'];
908 $fn = $obj997->edih_filename();
909 $seg_ar = $obj997->edih_segments();
910 $env_ar = $obj997->edih_envelopes();
912 if ( !isset($env_ar['ST']) ) {
913 csv_edihist_log('edih_997_csv_data: envelope error');
914 return $ret_ar;
916 if ( !isset($env_ar['GS']) ) {
917 csv_edihist_log('edih_997_csv_data: envelope error');
918 return $ret_ar;
920 foreach($env_ar['ISA'] as $icn => $isa) {
922 $ret_ar[$icn]['claim'] = array();
923 $ret_ar[$icn]['file'] = array();
925 foreach($env_ar['GS'] as $gs) {
926 if ($gs['icn'] == $icn) {
927 $ret_ar[$icn]['type'] = csv_file_type( $gs['type'] );
928 $rspdate = $gs['date'];
929 break;
933 $fdx = count($ret_ar[$icn]['file']);
935 $ret_ar[$icn]['file'][$fdx]['Date'] = ($rspdate) ? $rspdate : $isa['date'];
936 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
937 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
939 $rej_ct = 0;
940 // CTX segment identifiers
941 $trans_id = array('837'=>'CLM01', '270'=>'TRN02', '276'=>'TRN02');
943 //['f997']['claim'] = array('PtName', 'RspDate', 'CLM01', 'Status', 'ak_num', 'File_997', 'Control', 'err_seg');
944 foreach($env_ar['ST'] as $st) {
946 if ( $st['icn'] != $icn ) { continue; }
948 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
949 $loopid = '0';
950 //$isasender = $env_ar['ISA'][$st['icn']]['sender'];
951 $isadate = $env_ar['ISA'][$st['icn']]['date'];
952 $isaicn = $st['icn'];
953 // match 997/999 response to sent file ISA control
954 $ret_ar[$icn]['file'][$fdx]['Trace'] = ($st['trace']) ? $st['trace'] : '';
955 $bticn = ($st['trace']) ? $st['trace'] : '';
956 if ( !$st['trace'] ) {
958 csv_edihist_log('edih_997_csv_data: no trace to submitted file! '.$fn);
960 //RspType
961 foreach($stsegs as $seg) {
963 if ( strncmp($seg, 'AK1'.$de, 4) === 0 ) {
964 $sar = explode($de, $seg);
966 $loopid = '2000';
967 $rsptype = csv_file_type($sar[1]);
968 // AK102 could be the 'trace' value if it were unique
969 $rspgsn = $sar[2];
971 continue;
973 if ( strncmp($seg, 'AK2'.$de, 4) === 0 ) {
974 $sar = explode($de, $seg);
975 $rspsttype = csv_file_type($sar[1]);
976 $rspstn = (string)$sar[2];
977 $bht03syn = sprintf("%s%04d", $isaicn, $rspstn);
978 $iserr = false;
979 $err_seg = '';
980 $have_pt = false;
981 $ptname = '';
982 $svcdate = '';
983 continue;
985 if ( strncmp($seg, 'IK3'.$de, 4) === 0 || strncmp($seg, 'AK3'.$de, 4) === 0 ) {
986 // >> try err_seg = str_replace($de, '*', $seg)
987 $sar = explode($de, $seg);
988 $iserr = true;
989 $loopid = '2100';
990 $ctx_ct = 0;
992 $err_seg .= ($err_seg) ? '' : $bht03syn.'*IK3*'; // ISA13+ST02 * invalid segment ID
993 $err_seg .= (isset($sar[1])) ? '*'.$sar[1] : '*';
994 $err_seg .= (isset($sar[2])) ? '*'.$sar[2] : '*'; // segment position
995 //$err_seg .= (isset($sar[3])) ? '*'.$sar[3] : '*'; // loop, first 4 characters
996 //$err_seg .= (isset($sar[4])) ? '*'.$sar[4] : '*'; // error code
997 //$err_seg .= '*'.;
998 // example IK3*NM1*16*2010*8~ |IK3*SegID*SegNum*Loop*ErrCode*$bht03syn
999 // locate segment (#16 in ST-SE envelope)
1000 // ['err_seg'] = '|IK3*segID*segpos*loop*errcode*bht03syn|CTX-IK3*transID*segID*segpos*elempos
1001 // |IK4*elempos*errcode*elem*CTX-IK4*segID*segpos*elempos'
1003 // ///// retrieve original submitted claim
1004 if (!$have_pt) {
1006 $pt_info = edih_rsp_st_match($bht03syn, $rspsttype);
1007 //return array ['pt_name']['svcdate']['clm01']['batch_name'];
1008 if ( $pt_info ) {
1009 $ptname = (isset($pt_info['pt_name']) && strlen($pt_info['pt_name'])) ? $pt_info['pt_name'] : 'Unknown';
1010 $have_pt = true;
1011 } else {
1012 $ptname = 'Unknown';
1015 // /////////////////////////
1016 continue;
1019 //if ( strncmp($seg, 'IK4'.$de, 4) === 0 || strncmp($seg, 'AK4'.$de, 4) === 0 ) {
1020 //// data element error
1021 //$sar = explode($de, $seg);
1022 //$loopid == '2110';
1023 //$iserr = true;
1025 //$ctx_ct = 0;
1026 //$err_seg .= ($err_seg) ? '|IK4' : '';
1027 //$err_seg .= (isset($sar[1])) ? '*'.$sar[1] : '*';
1028 //$err_seg .= (isset($sar[2])) ? '*'.$sar[2] : '*';
1029 ////$err_seg .= (isset($sar[3])) ? '*'.$sar[3] : '*';
1030 ////$err_seg .= (isset($sar[4])) ? '*'.$sar[4] : '*';
1031 //// |IK4|elempos|errcode|elem
1032 //continue;
1035 //if ( strncmp($seg, 'CTX'.$de, 4) === 0 ) {
1036 //$sar = explode($de, $seg);
1037 //$ctx_ct++;
1038 //if ($loopid == '2100') {
1039 //$err_seg .= '|CTX-IK3';
1041 //if ($loopid == '2110') {
1042 //$err_seg .= '|CTX-IK4';
1044 //// CTX segment identifiers $trans_id['837'] ['270'] ['276']
1045 //if ( isset($trans_id[$rsptype]) && strpos($seg, $trans_id[$rsptype]) ) {
1046 //$err_seg .= (isset($sar[1]) && $sar[1]) ? '*'.$sar[1] : '';
1049 //if(strncmp($sar[1], 'SITUA', 5) === 0 ) {
1050 //// SITUATIONAL TRIGGER
1051 //$err_seg .= (isset($sar[2]) && $sar[2]) ? '*'.$sar[2] : '*';
1052 //$err_seg .= (isset($sar[3]) && $sar[3]) ? '*'.$sar[3] : '*';
1053 //$err_seg .= (isset($sar[5]) && $sar[5]) ? '*'.$sar[5] : '*';
1054 //// |CTX-IK3*segID*segPos*loopLS*elemPos:compositePos:repPos
1055 //} elseif ($ctx_ct > 1) {
1056 //$err_seg .= '*'.$sar[2];
1057 //if (!$have_pt) {
1058 //$p1 = strpos($sar[1],$ds);
1059 //$p2 = ($p1) ? strlen($sar[1])-$p1-1 : strlen($sar[1]);
1060 //$ret_ar[$icn]['claim'][$cdx]['CLM01'] = substr($sar[1], -$p2);
1064 //continue;
1067 if ( strncmp($seg, 'AK5'.$de, 4) === 0 || strncmp($seg, 'IK5'.$de, 4) === 0 ) {
1068 // only store claims entries if there is an error
1069 $sar = explode($de, $seg);
1070 if ($sar[1] == 'A') {
1071 continue;
1072 } else {
1073 $rej_ct++;
1075 $cdx = count($ret_ar[$icn]['claim']);
1076 //array('PtName', 'RspDate', 'Trace', 'Status', 'Control', 'FileName', 'RspType', 'err_seg');
1077 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $ptname;
1078 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $svcdate;
1080 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $bht03syn;
1081 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
1082 $ret_ar[$icn]['claim'][$cdx]['Control'] = $icn;
1083 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
1084 $ret_ar[$icn]['claim'][$cdx]['RspType'] = $rspsttype;
1086 $ret_ar[$icn]['claim'][$cdx]['err_seg'] = $err_seg;
1088 // AK502 = Code indicating implementation error found based on the syntax editing of a transaction set
1092 } // end foreach($env_ar['ST'] as $st)
1093 $ret_ar[$icn]['file'][$fdx]['RejCt'] = $rej_ct;
1094 $ret_ar[$icn]['file'][$fdx]['RspType'] = $rsptype;
1095 } // end foreach($env_ar['ISA'] as $icn => $isa)
1098 return $ret_ar;
1103 * parse an x12 270/271 file into data rows for csv tables
1105 * @param object x12_file_object
1106 * @return array
1108 function edih_271_csv_data($obj270) {
1109 //'f270 claim = array('PtName', 'ReqDate', 'PtAcct', 'InsLevel', 'BHT03', 'FileName', 'Payer');
1110 //'f270 file = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12_partner');
1111 //'f271 file = array('Date', 'FileName', 'Control', 'Claim_ct', 'Denied', 'Payer');
1112 //'f271 claim = array('PtName', 'RspDate', 'Trace', 'Status', 'BHT03', 'FileName', 'Payer');
1114 $ret_ar = array();
1116 $de = $obj270->edih_delimiters()['e'];
1117 $ds = $obj270->edih_delimiters()['s'];
1118 $fn = $obj270->edih_filename();
1119 $seg_ar = $obj270->edih_segments();
1120 $env_ar = $obj270->edih_envelopes();
1121 $ft = csv_file_type( $obj270->edih_type() );
1123 // $rsptype = array('HS'=>'270', 'HB'=>'271', 'HC'=>'837', 'HR'=>'276', 'HI'=>'278');
1124 if ( !isset($env_ar['ST']) ) {
1125 csv_edihist_log('edih_271_csv_data: envelope error '.$fn);
1126 return $ret_ar;
1129 if ( !isset($env_ar['GS']) ) {
1130 csv_edihist_log('edih_271_csv_data: envelope error');
1131 return $ret_ar;
1134 foreach($env_ar['ISA'] as $icn => $isa) {
1135 // array('Date', 'FileName', 'Control', 'ta1ctrl', 'RejCt');
1136 $ret_ar[$icn]['type'] = $ft;
1137 $ret_ar[$icn]['claim'] = array();
1138 $ret_ar[$icn]['file'] = array();
1139 $rspdate = $isa['date'];
1140 $x12ptnr = $isa['receiver'];
1142 foreach($env_ar['GS'] as $gs) {
1143 if ($gs['icn'] == $icn) {
1144 $gsdate = $gs['date'];
1145 break;
1148 foreach($env_ar['ST'] as $st) {
1150 if ( $st['icn'] != $icn ) { continue; }
1152 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
1153 $loopid = '0';
1154 $hl = 0;
1156 $isaicn = $st['icn'];
1157 $stn = $st['stn'];
1158 $has_le = false;
1160 // for "claim" array
1161 // 'f270' array('PtName', 'ReqDate', 'Trace', 'InsBnft', 'BHT03', 'FileName', 'Payer'); break;
1162 // 'f271'array('PtName', 'RspDate', 'Trace', 'Status', 'BHT03', 'FileName', 'Payer'); break;
1164 foreach($stsegs as $seg) {
1166 if (strncmp($seg, 'BHT'.$de, 4) === 0 ) {
1167 // new transaction
1168 $cdx = (isset($ret_ar[$icn]['claim']) ) ? count($ret_ar[$icn]['claim']) : 0;
1170 $sar = explode($de, $seg);
1172 $isrqst = (isset($sar[2]) && $sar[2] == '13') ? true : false;
1173 $isrsp = (isset($sar[2]) && $sar[2] == '11') ? true : false;
1174 $loopid = 0;
1175 $bnfteq = '';
1176 $rej_ct = 0;
1178 $dtkey = ($ft == 'f271') ? 'RspDate' : 'ReqDate';
1180 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
1181 $ret_ar[$icn]['claim'][$cdx][$dtkey] = $gsdate;
1182 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
1183 if ($isrsp || $ft == 'f271') {
1184 $ret_ar[$icn]['claim'][$cdx]['Status'] = 'A'; // 271
1185 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = (isset($sar[3])) ? $sar[3] : ''; //bht03 = $sar[3];
1186 } else {
1187 $ret_ar[$icn]['claim'][$cdx]['InsBnft'] = ''; // 270
1188 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = sprintf("%s%04d", $isaicn, $stn);
1190 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
1191 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
1193 continue;
1196 if (strncmp($seg, 'HL'.$de, 3) === 0 ) {
1197 $sar = explode($de, $seg);
1198 $hl = $sar[1];
1199 $hlpc = $sar[2]; // parent code
1200 $hllc = $sar[3];
1201 $hlcc = (isset($sar[4])) ? $sar[4] : ''; // child code
1202 if ($sar[3] == '20') { // level code
1203 $loopid = '2000A'; // info source (payer)
1204 } elseif ($sar[3] == '21') {
1205 $loopid = '2000B'; // info receiver (clinic)
1206 } elseif ($sar[3] == '22') {
1207 $loopid = '2000C'; // subscriber
1208 } elseif ($sar[3] == '23') {
1209 $loopid = '2000D'; // dependent
1210 } else {
1211 //debug
1212 csv_edihist_log('HL has no level '.$seg.' in '.$fn);
1214 continue;
1217 if (strncmp($seg, 'NM1'.$de, 4) === 0 ) {
1218 $sar = explode($de, $seg);
1219 $nm1 = $sar[3];
1220 $nm1 = ($sar[4]) ? $nm1.', '.$sar[4] : $nm1;
1221 $nm1 = ($sar[5]) ? $nm1.' '.$sar[5] : $nm1;
1222 if ($loopid == '2000A') {
1223 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $nm1; //
1224 $payer_name = $nm1;
1225 } elseif ($loopid == '2000C' || $loopid == '2000D') {
1226 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm1; //$ptname = $nm1;
1228 continue;
1230 // for 271 eligibility response (invalid data in 270 request)
1231 if (strncmp($seg, 'AAA'.$de, 4) === 0 ) {
1232 $sar = explode($de, $seg);
1233 $status = 'R';
1234 $rej_ct++;
1235 $aaa_code = $sar[3];
1236 $rsp_code = $sar[4];
1237 if ($loopid == '2000A') {
1238 $status = $status.' Src '.$aaa_code;
1239 } elseif ($loopid == '2000B') {
1240 $status = $status.' Rcv '.$aaa_code;
1241 } elseif ($loopid == '2000C') {
1242 $status = $status.' Sbr '.$aaa_code;
1243 } elseif ($loopid == '2000D') {
1244 $status = $status.' Dep '.$aaa_code;
1247 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
1249 continue;
1252 // for 270 eligibility request
1253 if (strncmp($seg, 'EQ'.$de, 3) === 0 ) {
1254 if ( strlen((string)$sar[1]) ) {
1255 $bnfteq .= ($bnfteq) ? '|'.$sar[1] : $sar[1];
1256 } elseif ( strlen((string)$sar[2]) ) {
1257 $bnfteq .= ($bnfteq) ? '|'.$sar[2] : $sar[2];
1258 } else {
1259 csv_edihist_log('Invalid EQ segment, missing benefit type in '.$fn);
1260 continue;
1262 $ret_ar[$icn]['claim'][$cdx]['InsBnft'] = $bnfteq;
1263 continue;
1265 // overridden by REF*EJ* (not)
1266 if (strncmp($seg, 'TRN'.$de, 4) === 0 ) {
1267 if ($loopid = '2000C' || $loopid == '2000D') {
1268 $sar = explode($de, $seg);
1269 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2]; //$ptacct = $sar[2];
1272 continue;
1274 // for 271 eligibility response
1275 if (strncmp($seg, 'EB'.$de, 3) === 0 ) {
1276 $status = ( isset($status) ) ? $status : '';
1278 if ( strpos($ret_ar[$icn]['claim'][$cdx]['Status'], 'tive') ) {
1279 continue;
1282 $sar = explode($de, $seg);
1284 if ( isset($sar[2]) ) {
1285 if ( $sar[2] == '6' || $sar[2] == '7' || $sar[2] == '8' ) {
1286 $status = 'Inactive';
1287 } elseif ($sar[2] == 'I') {
1288 $status = 'Non-Covered';
1289 $rej_ct++;
1290 } elseif ($sar[2] == 'E') {
1291 $status = 'Exclusions';
1292 $rej_ct++;
1293 } elseif ($sar[2] == 'N') {
1294 $status = 'Restricted';
1295 $rej_ct++;
1296 } elseif ($sar[2] == 'V') {
1297 $status = 'Unknown';
1298 $rej_ct++;
1299 } elseif ($sar[2] == 'T') {
1300 $status = 'Card Lost';
1301 $rej_ct++;
1302 } elseif ($sar[2] == 'U') {
1303 $status = 'Contact';
1304 $rej_ct++;
1305 } elseif ($sar[2] == '1') {
1306 $status = 'Active';
1307 } elseif ($sar[2] == '2' || $sar[2] == '3' || $sar[2] == '4') {
1308 $status = 'Active Cap';
1312 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
1314 continue;
1317 if (strncmp($seg, 'DTP'.$de, 4) === 0 ) {
1318 $sar = explode($de, $seg);
1319 $dtp03 = (isset($sar[2]) && $sar[2] == 'D8') ? $sar[3] : substr($sar[3], 0, 8);
1320 if ($isrsp) {
1321 if ($loopid == '2100C' || $loopid == '2110C') {
1322 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $dtp03;
1323 } elseif ($loopid == '2100D' || $loopid == '2110D') {
1324 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $dtp03;
1326 } else {
1327 if ($loopid == '2100C' || $loopid == '2110C') {
1328 $ret_ar[$icn]['claim'][$cdx]['ReqDate'] = $dtp03;
1329 } elseif ($loopid == '2100D' || $loopid == '2110D') {
1330 $ret_ar[$icn]['claim'][$cdx]['ReqDate'] = $dtp03;
1334 continue;
1338 if (strncmp($seg, 'REF'.$de.'EJ'.$de, 7) === 0 ) {
1339 // patient account -- replaces or replaced by TRN02
1340 $sar = explode($de, $seg);
1341 $ret_ar[$icn]['claim'][$cdx]['PtAcct'] = $sar[2]; //$ptacct = $sar[2];
1343 continue;
1347 } // end foreach($stsegs as $seg)
1349 } // endforeach($env_ar['ST'] as $st
1350 // file: 'f271': array('Date', 'FileName', 'Control', 'Claim_ct', 'Reject', 'Payer')
1351 $fdx = count($ret_ar[$icn]['file']);
1352 //'f270': $hdr = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12Partner');
1353 $ret_ar[$icn]['file'][$fdx]['Date'] = $gsdate;
1354 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
1355 // for 270 type, could use GSO6 if it were unique
1356 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
1357 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = $cdx;
1358 if ($isrsp || $ft == 'f271') {
1359 $ret_ar[$icn]['file'][$fdx]['Reject'] = $rej_ct;
1360 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_name;
1361 } else {
1362 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = $x12ptnr;
1365 } // endforeach($env_ar['ISA'] as $icn=>$isa)
1367 return $ret_ar;
1371 * this function opens the x12 file in the object and routes
1372 * the object to the parsing function according to the x12 type
1373 * csvdata array design:
1374 * [$icn]['claims'][i] [$icn]['files'][i] [$icn]['type']
1376 * @uses edih_835_csv_data()
1377 * @uses edih_837_csv_data()
1378 * @uses edih_277_csv_data()
1379 * @uses edih_271_csv_data()
1380 * @uses edih_278_csv_data()
1381 * @uses edih_997_csv_data()
1383 * @param string path to file
1384 * @return array data for csv table records
1386 function edih_parse_select($file_path) {
1387 $csvdata = array();
1388 // csvdata array design:
1389 // $csvdata[$icn]['claims'][i] [$icn]['files'][i] [$icn]['type']
1391 $x12_obj = csv_check_x12_obj($file_path);
1392 //$x12_obj = new edih_x12_file($file_path);
1393 if ($x12_obj instanceof edih_x12_file) {
1394 $ft = $x12_obj->edih_type();
1395 } else {
1396 csv_edihist_log('edih_parse_select: error in file path');
1397 return $csvdata;
1399 //'HB'=>'271', 'HS'=>'270', 'HR'=>'276', 'HI'=>'278',
1400 //'HN'=>'277', 'HP'=>'835', 'FA'=>'999', 'HC'=>'837'
1402 if ( $ft == 'HP' ) {
1403 $csvdata = edih_835_csv_data($x12_obj);
1404 } elseif ( $ft == 'HC' ) {
1405 $csvdata = edih_837_csv_data($x12_obj);
1406 } elseif ( $ft == 'HN' || $ft == 'HR' ) {
1407 $csvdata = edih_277_csv_data($x12_obj);
1408 } elseif ( $ft == 'FA') {
1409 $csvdata = edih_997_csv_data($x12_obj);
1410 } elseif ( $ft == 'HB' || $ft == 'HS') {
1411 $csvdata = edih_271_csv_data($x12_obj);
1412 } elseif ( $ft == 'HI') {
1413 $csvdata = edih_278_csv_data($x12_obj);
1414 } else {
1415 // debug
1416 csv_edihist_log( 'edih_parse_select(): unsupported file type '.$ft.' name: '.basename($file_path));
1419 return $csvdata;