preparing for 5.0.1 release in several weeks (#1509)
[openemr.git] / library / edihistory / edih_csv_parse.php
blob6af240edb7242d2e96271dcd91584f45c63c8316
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)
44 if (strlen($strdate) == 6) {
45 $gtdt = getdate();
46 $cy = (string)$gtdt['year'];
47 $dt1 = substr($cy, 0, 2) . $strdate;
48 } elseif (strpos($strdate, '-') >= 6) {
49 $dt1 = substr($strdate, 0, strpos($strdate, '-') - 1);
50 } elseif (strlen($strdate) == 8) {
51 $dt1 = $strdate;
52 } else {
53 // bad argument
54 csv_edihist_log('edih_parse_date: invalid argument '.$strdate);
55 return false;
59 return substr($dt1, 0, 4) . '-' . substr($dt1, 4, 2) . '-' . substr($dt1, 6, 2);
62 /** remittance 835 files
64 * Each payment trace number (Control) gets a row in the csv file record.
65 * Each claim payment transaction gets a row in the csv claim record
66 * <pre>
68 * $array
69 * [$icn]['type']
70 * [$icn]['file'][$i] => array keys match csv_table_head() output
71 * [$icn]['claim'][$i] => array keys match csv_table_head() output
73 * </pre>
75 * @uses csv_file_type()
76 * @uses edih_parse_date()
77 * @uses edih_x12_transaction()
78 * @uses edih_get_segment()
79 * @param object edih_x12_obj
80 * @return array
82 function edih_835_csv_data($obj835)
85 $ret_ar = array();
87 $seg_ar = $obj835->edih_segments();
88 $env_ar = $obj835->edih_envelopes();
89 $de = $obj835->edih_delimiters()['e'];
90 $fn = $obj835->edih_filename();
91 //$tp = $obj835->edih_type();
93 // since 835 "files" table uses transaction trace as the "Control"
94 // we must assemble the 'files' array in the ST loop
95 // ['ISA'][$icn]
96 foreach ($env_ar['ISA'] as $icn => $isa) {
98 $ret_ar[$icn]['claim'] = array();
99 $ret_ar[$icn]['file'] = array();
101 $gsdate = '';
102 $trace = '';
104 if (array_key_exists('GS', $env_ar)) {
105 // for unlikely case of 'mixed' GS types in file
106 foreach ($env_ar['GS'] as $gs) {
107 if ($gs['icn'] == $icn) {
108 $ft = $gs['type'];
109 $gsdate = $gs['date'];
110 $payer_id = $gs['srcid']; // from TRN03
111 break;
116 $ret_ar[$icn]['type'] = csv_file_type($ft);
117 $gsdate = ($gsdate) ? $gsdate : edih_parse_date($isa['date']);
119 $fdx = count($ret_ar[$icn]['file']);
121 // ['ST'][$stky]=>['start']['count']['stn']['gsn']['icn']['type']['trace']['acct']
122 // ['ST'][$stky]['acct'][i]=>pid-enc$$ret_ar[$icn]['claim'][$cdx]['SvcDate'] =
123 foreach ($env_ar['ST'] as $st) {
124 if ($st['icn'] != $icn) {
125 continue;
128 // the "files" table has a row for each payment trace
130 if ($trace != $st['trace']) {
131 $fdx = count($ret_ar[$icn]['file']);
133 $ret_ar[$icn]['file'][$fdx]['Date'] = $gsdate;
134 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
135 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
136 $ret_ar[$icn]['file'][$fdx]['Trace'] = $st['trace'];
137 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = (string)count($st['acct']);
138 $ret_ar[$icn]['file'][$fdx]['Denied'] = 0;
139 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_id;
141 $trace = $st['trace'];
145 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
146 $stacct = array_values(array_unique($st['acct']));
147 $clmct = count($stacct);
148 $payer = '';
149 $denied = 0;
151 $n1pr = $obj835->edih_get_segment('N1', 'N1'.$de.'PR'.$de, $stsegs);
152 $payer = '';
153 if ($n1pr) {
154 foreach ($n1pr as $n1) {
155 $sar = explode($de, $n1);
156 $payer = (isset($sar[2])) ? $sar[2] : '';
159 if ($payer) {
160 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer;
162 } // end if ($n1pr)
165 for ($i=0; $i<$clmct; $i++) {
166 $clpsegs = $obj835->edih_x12_transaction($stacct[$i], $st['stn']);
167 if (!is_array($clpsegs) || !count($clpsegs)) {
169 csv_edihist_log('edih_835_csv_data: no segments for account '.$st['acct'][$i]);
170 continue;
174 foreach ($clpsegs as $trans) {
176 $cdx = count($ret_ar[$icn]['claim']);
177 foreach ($trans as $seg) {
179 if (strncmp($seg, 'CLP'.$de, 4) === 0) {
180 $sar = explode($de, $seg);
182 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = (isset($sar[1])) ? $sar[1] : '';
183 $ret_ar[$icn]['claim'][$cdx]['Status'] = (isset($sar[2])) ? $sar[2] : '';
184 $ret_ar[$icn]['claim'][$cdx]['Pmt'] = (isset($sar[4])) ? sprintf("%01.02f", $sar[4]) : '';
185 $ret_ar[$icn]['claim'][$cdx]['PtResp'] = ( isset($sar[5]) ) ? sprintf("%01.02f", $sar[5]) : '';
186 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = ( isset($sar[7]) ) ? trim($sar[7]) : '';
187 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
188 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $st['trace'];
189 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $payer;
190 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
191 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
193 if ($sar[2]=='4' || $sar[2]=='22' || $sar[2]=='23') {
194 $denied++;
197 $loopid = "2100";
198 continue;
202 if (strncmp($seg, 'NM1'.$de.'QC'.$de, 7) === 0) {
203 $sar = explode($de, $seg);
204 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', '.$sar[5]: "";
205 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3].', '.$sar[4].$midn;
206 continue;
209 if (strncmp($seg, 'DTM'.$de.'232'.$de, 8) === 0) {
210 $sar = explode($de, $seg);
211 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[2];
212 continue;
215 if (strncmp($seg, 'DTM'.$de.'472'.$de, 8) === 0) {
216 $sar = explode($de, $seg);
217 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[2];
218 continue;
220 } // end foreach($trans as $seg)
221 } // end foreach($clpsegs as $trans) {
222 } // end for($i=0; $i<$clmct; $i++)
223 // get denied count
224 $ret_ar[$icn]['file'][$fdx]['Denied'] = ($denied) ? $denied : '0';
226 } // end foreach($env_ar['ST'] as $st)
227 } // end foreach($env_ar['ISA'] as $icn => $isa)
229 return $ret_ar;
234 * Parse csv data from 837 files
235 * Note that this can return false provider values for extensive claims
236 * since loops are not tracked and 837 claims can have numerous
237 * providers, but probably not an issue for OpenEMR
239 * @param object edih_x12_ file object
240 * @return array data to write csv file and csv clain table rows
242 function edih_837_csv_data($obj837)
245 $ret_ar = array();
247 $seg_ar = $obj837->edih_segments();
248 $env_ar = $obj837->edih_envelopes();
249 $de = $obj837->edih_delimiters()['e'];
250 $fn = $obj837->edih_filename();
251 //$ft = csv_file_type( $obj837->edih_type() );
253 if (!isset($env_ar['ST'])) {
254 csv_edihist_log('edih_837_csv_data: envelope error');
255 return $ret_ar;
258 //['file'] = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12_partner');
259 //['claim'] =
260 // array('PtName', 'SvcDate', 'CLM01', 'InsLevel', 'Control', 'File_837', 'Fee', 'PtPaid', 'Provider' );
262 foreach ($env_ar['ISA'] as $icn => $isa) {
264 $ret_ar[$icn]['claim'] = array();
265 $ret_ar[$icn]['file'] = array();
266 //$ret_ar[$icn]['type'] = $ft;
267 foreach ($env_ar['GS'] as $gs) {
268 if ($gs['icn'] == $icn) {
269 $ret_ar[$icn]['type'] = csv_file_type($gs['type']);
270 $gsdate = $gs['date'];
271 break;
276 $fdx = count($ret_ar[$icn]['file']);
278 $ret_ar[$icn]['file'][$fdx]['Date'] = (string)$gsdate;
279 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
280 // if GS06 were unique, it could be used as the 'Control'
281 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
282 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = (string)$isa['receiver'];
284 $clm_ct = 0;
286 foreach ($env_ar['ST'] as $st) {
287 // claims should be in the correct ISA envelope
288 if ($st['icn'] != $icn) {
289 continue;
293 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
294 $stacct = array_values(array_unique($st['acct']));
295 $clmct = count($stacct);
296 // $st['icn'] is the ISA control number for the ISA envelope containing the ST--SE
297 $date = $env_ar['ISA'][$st['icn']]['date'];
298 $stn = $st['stn'];
299 for ($i=0; $i<$clmct; $i++) {
300 //echo '=== ACCT '.$stacct[$i].' '.$st['stn'].'<br />'.PHP_EOL;
301 $asegs = $obj837->edih_x12_transaction($stacct[$i], $st['stn']);
302 if (!is_array($asegs) || !count($asegs)) {
303 csv_edihist_log('edih_837_csv_data: no segments for account '.$st['acct'][$i]);
304 continue;
307 foreach ($asegs as $trans) {
309 //array('PtName'=>0, 'SvcDate'=>1, 'CLM01'=>2, 'InsLevel'=>3, 'Control'=>4, 'FileName'=>5, 'Fee'=>6, 'PtPaid'=>7, 'Provider'=>8 );
311 //'f837': $hdr = array('PtName', 'SvcDate', 'CLM01', 'InsLevel', 'Control', 'FileName', 'Fee', 'PtPaid', 'Provider' )
312 foreach ($trans as $seg) {
313 if (strncmp($seg, 'BHT'.$de, 4) === 0) {
314 $cdx = count($ret_ar[$icn]['claim']);
315 $sar = explode($de, $seg);
316 $bht03 = $sar[3];
317 $hl = '';
318 $clm_ct++;
320 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
321 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
322 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = '';
323 $ret_ar[$icn]['claim'][$cdx]['InsLevel'] = '';
325 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = (strlen($bht03) == 13) ? $bht03 : sprintf("%s%04d", $st['icn'], $st['stn']);
326 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
328 $ret_ar[$icn]['claim'][$cdx]['Fee'] = '0';
329 $ret_ar[$icn]['claim'][$cdx]['PtPaid'] = '0';
330 $ret_ar[$icn]['claim'][$cdx]['Provider'] = '';
333 if (strncmp($seg, 'HL'.$de, 3) === 0) {
334 $sar = explode($de, $seg);
335 $hl = $sar[3];
336 continue;
339 if (intval($hl) == 20) {
340 if (strncmp($seg, 'NM1'.$de, 4) === 0) {
341 $sar = explode($de, $seg);
342 if ($sar[2] == '82' || $sar[2] == '85') {
343 $ret_ar[$icn]['claim'][$cdx]['Provider'] = $sar[9];
346 continue;
348 } // end if $hl == '20'
350 if (intval($hl) >= 22) {
351 if (strncmp($seg, 'SBR'.$de, 4) === 0) {
352 $sar = explode($de, $seg);
353 $ret_ar[$icn]['claim'][$cdx]['InsLevel'] = $sar[1];
356 if (strncmp($seg, 'CLM'.$de, 4) === 0) {
357 $sar = explode($de, $seg);
358 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[1];
359 $ret_ar[$icn]['claim'][$cdx]['Fee'] = $sar[2];
360 continue;
363 if (strncmp($seg, 'AMT'.$de.'F5'.$de, 7) === 0) {
364 $sar = explode($de, $seg);
365 $ret_ar[$icn]['claim'][$cdx]['PtPaid'] = $sar[2];
366 continue;
369 if (strncmp($seg, 'NM1'.$de, 4) === 0) {
370 $sar = explode($de, $seg);
371 if (strpos('|IL|QC', $sar[1])) {
372 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', '.$sar[5]: '';
373 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3].', '.$sar[4].$midn;
374 continue;
377 if ($sar[1] == '82') {
378 $ret_ar[$icn]['claim'][$cdx]['Provider'] = $sar[9];
379 continue;
383 if (strncmp($seg, 'DTP'.$de.'472'.$de, 8) === 0) {
384 $sar = explode($de, $seg);
385 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[3];
386 continue;
388 } // end if $hl >= '22'
389 } // end foreach($trans as $seg)
390 } // end foreach($asegs as $trans)
391 } // end for($i=0; $i<$clmct; $i++)
392 } // end foreach($obj837->envelopes['ST'] as $st)
393 // claim count
394 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = (string)$clm_ct;
395 } // end foreach($env_ar['ISA'] as $icn => $isa)
397 return $ret_ar;
401 * extract csv table row data for x12 277 files
403 * @param object edih_x12_file object of type 276/277
404 * @return array
406 function edih_277_csv_data($obj277)
409 $ret_ar = array();
411 $seg_ar = $obj277->edih_segments();
412 $env_ar = $obj277->edih_envelopes();
413 $de = $obj277->edih_delimiters()['e'];
414 $fn = $obj277->edih_filename();
415 $tp = $obj277->edih_type();
416 // 'HN' 277 'HR' 276 )
417 $env_ar = $obj277->edih_envelopes();
419 if (!isset($env_ar['ST'])) {
420 csv_edihist_log('edih_277_csv_data: envelope error');
421 return $ret_ar;
424 if (!isset($env_ar['GS'])) {
425 csv_edihist_log('edih_277_csv_data: envelope error');
426 return $ret_ar;
430 foreach ($env_ar['ISA'] as $icn => $isa) {
432 $ret_ar[$icn]['claim'] = array();
433 $ret_ar[$icn]['file'] = array();
435 $rspdate = $isa['date'];
436 foreach ($env_ar['GS'] as $gs) {
437 if ($gs['icn'] == $icn) {
438 $ret_ar[$icn]['type'] = csv_file_type($gs['type']);
439 $rspdate = $gs['date'];
440 break;
444 //$ret_ar[$icn]['type'] = csv_file_type($ft);
446 $fdx = count($ret_ar[$icn]['file']);
447 //['f277']['file'] = array('Date', 'FileName', 'Control', 'Accept', 'AccAmt', 'Reject', 'RejAmt');
448 //'f276': $hdr = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12Partner');
449 $ret_ar[$icn]['file'][$fdx]['Date'] = $rspdate;
450 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
451 // could be GS06 for 276 if it were unique
452 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
453 if ($tp == 'HN') {
454 $ret_ar[$icn]['file'][$fdx]['Accept'] = 0;
455 $ret_ar[$icn]['file'][$fdx]['Reject'] = 0;
456 $ret_ar[$icn]['file'][$fdx]['AccAmt'] = 0;
457 $ret_ar[$icn]['file'][$fdx]['RejAmt'] = 0;
458 } else {
459 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = 0;
460 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = $isa['receiver'];
464 $clmct = 0;
466 //['ST'][$stky]=>['start']['count']['stn']['gsn']['icn']['type']['trace']['acct']
467 // ['ST'][$stky]['acct'][i]=>pid-enc
468 //'f277': $hdr = array('PtName', 'SvcDate', 'CLM01', 'Status', 'BHT03', 'FileName', 'Payer', 'Trace');
469 foreach ($env_ar['ST'] as $st) {
471 if ($st['icn'] != $icn) {
472 continue;
476 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
477 $stacct = array_values(array_unique($st['bht03']));
478 $clmct += count($stacct);
479 $st_icn = $st['icn']; // same value as $obj277->envelopes['ISA']['icn']
480 $stn = $st['stn'];
482 if ($tp == 'HR') {
483 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = $clmct;
487 //for($i=0; $i<$clmct; $i++) {
488 for ($i=0; $i<count($stacct); $i++) {
490 $asegs = $obj277->edih_x12_transaction($stacct[$i]);
492 foreach ($asegs as $trans) {
494 foreach ($trans as $seg) {
496 if (strncmp($seg, 'BHT'.$de, 4) === 0) {
497 $cdx = count($ret_ar[$icn]['claim']);
499 $sar = explode($de, $seg);
500 if ($sar[2] != '08') {
501 csv_edihist_log('Claim Status BHT purpose code: '.$sar[2].' in ST '.$st['stn'].' in file '.$fn);
504 $trns_tp = (isset($sar[6]) && $sar[6]) ? $sar[6] : '';
505 if ($trns_tp == 'TH') {
506 $bht_id = 'ack'; // 277CA
507 } elseif ($trns_tp == 'DG') {
508 $bht_id = 'rsp'; // 277
509 } else {
510 $bht_id = 'sub'; // 276
514 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
515 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
516 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = '';
518 if ($tp == 'HN') {
519 // 277
520 $ret_ar[$icn]['claim'][$cdx]['Status'] = '';
521 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = $sar[3];
522 } elseif ($tp == 'HR') {
523 //276
524 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = '';
525 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = sprintf("%s%04d", $st_icn, $stn);
530 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
532 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
533 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = '';
534 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
535 continue;
539 if (strncmp($seg, 'HL'.$de, 3) === 0) {
540 $sar = explode($de, $seg);
541 $hl = (string)$sar[3];
545 if ($hl == '20') {
546 // information source
547 if (strncmp($seg, 'NM1'.$de, 4) === 0) {
548 $sar = explode($de, $seg);
549 $ret_ar[$icn]['claim'][$cdx]['Payer'] = ($sar[1]=='PR' || $sar[1]=='AY') ? $sar[3] : '';
550 continue;
555 if ($hl == '21') {
556 // information source or receiver level rejection
557 // -- user should view the transaction
558 // -- don't include in csv data so Trace only refers to 276
559 //if ( strncmp($seg, 'TRN'.$de, 4) === 0) {
560 //$sar = explode($de, $seg);
561 //$ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
563 if (strncmp($seg, 'STC'.$de, 4) === 0) {
564 $sar = explode($de, $seg);
565 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
568 if (strncmp($seg, 'QTY'.$de, 4) === 0) {
569 $sar = explode($de, $seg);
570 if ($sar[1] == '90') {
571 $ret_ar[$icn]['file'][$fdx]['Accept'] += $sar[2];
574 if ($sar[1] == 'AA') {
575 $ret_ar[$icn]['file'][$fdx]['Reject'] += $sar[2];
579 if (strncmp($seg, 'AMT'.$de, 4) === 0) {
580 $sar = explode($de, $seg);
581 if ($sar[1] == 'YU') {
582 $ret_ar[$icn]['file'][$fdx]['AccAmt'] += $sar[2];
585 if ($sar[1] == 'YY') {
586 $ret_ar[$icn]['file'][$fdx]['RejAmt'] += $sar[2];
590 continue;
594 if ($hl == '19') {
595 // provider level rejection
596 // -- user should view the transaction
597 // -- don't include in csv data so Trace only refers to 276
598 //if ( strncmp($seg, 'TRN'.$de, 4) === 0) {
599 //$sar = explode($de, $seg);
600 //$ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
602 if (strncmp($seg, 'STC'.$de, 4) === 0) {
603 $sar = explode($de, $seg);
604 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
607 continue;
611 if ($hl == '22' || $hl == '23') {
612 // subscriber or dependent
613 if (strncmp($seg, 'NM1'.$de, 4) === 0) {
614 $sar = explode($de, $seg);
615 if ($sar[1] == 'IL' || $sar[1] == 'QC') {
616 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', '.$sar[5]: "";
617 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3].', '.$sar[4].$midn;
618 //if (isset($sar[8]) && $sar[8] == 'MI') {
619 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = (isset($sar[9])) ? $sar[9] : '';
623 continue;
626 // in response to 276, this is the reference given in TRN02
627 if (strncmp($seg, 'TRN'.$de.'2'.$de, 4) === 0) {
628 $sar = explode($de, $seg);
629 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
630 continue;
633 // REF*EJ* will give the payer assigned claim number
634 // not used much in 277CA files
635 if (strncmp($seg, 'REF'.$de.'EJ'.$de, 7) === 0) {
636 $sar = explode($de, $seg);
637 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[2];
638 continue;
641 if (strncmp($seg, 'REF'.$de.'1K'.$de, 7) === 0) {
642 // hopefully OpenEMR will include the claim number in 276
643 if ($tp == 'HR') {
644 $sar = explode($de, $seg);
645 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = $sar[2];
648 continue;
651 // REF*D9*(Claim number)~
653 if (strncmp($seg, 'STC'.$de, 4) === 0) {
654 // STC is only present in 277
655 $sar = explode($de, $seg);
656 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
657 continue;
660 continue;
663 if ($hl == 'PT') {
664 // 277CA
665 if (strncmp($seg, 'NM1'.$de, 4) === 0) {
666 $sar = explode($de, $seg);
667 if ($sar[1] == 'IL' || $sar[1] == 'QC') {
668 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', '.$sar[5]: "";
669 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3].', '.$sar[4].$midn;
670 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = (isset($sar[9])) ? $sar[9] : '';
673 continue;
676 if (strncmp($seg, 'TRN'.$de.'2'.$de, 6) === 0) {
677 $sar = explode($de, $seg);
678 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[2];
679 continue;
682 if (strncmp($seg, 'STC'.$de, 4) === 0) {
683 $sar = explode($de, $seg);
684 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
685 continue;
688 //if ( strncmp($seg, 'REF'.$de.'1K'.$de, 7) === 0) {
689 //$sar = explode($de, $seg);
690 //$ret_ar[$icn]['claim'][$cdx]['ClaimID'] = $sar[2];
691 //continue;
693 if (strncmp($seg, 'DTP'.$de.'472'.$de, 8) === 0) {
694 $sar = explode($de, $seg);
695 // D8-CCYYMMDD RD8-CCYYMMDD-CCYYMMDD only take initial date
696 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = substr($sar[3], 0, 8);
697 continue;
700 } // end foreach($trans as $seg)
701 } // end foreach($asegs as $trans)
702 } // end for($i=0; $i<$clmct; $i++)
703 }// end foreach($obj277->envelopes['ST'] as $st)
704 } // end foreach($env_ar['ISA'] as $icn => $isa)
706 return $ret_ar;
710 * parse an x12 278 file into data rows for csv tables
712 * @param object x12_file_object
713 * @return array
715 function edih_278_csv_data($obj278)
718 // f278 file = array('Date', 'FileName', 'Control', 'TrnCount', 'Auth', 'Payer');
719 // f278 claim = array('PtName', 'FileDate', 'Trace', 'Status' 'BHT03', 'FileName', 'Auth', 'Payer');
721 $ret_ar = array();
723 $de = $obj278->edih_delimiters()['e'];
724 $ds = $obj278->edih_delimiters()['s'];
725 $fn = $obj278->edih_filename();
726 $seg_ar = $obj278->edih_segments();
727 $env_ar = $obj278->edih_envelopes();
728 $ft = csv_file_type($obj278->edih_type());
730 // $ft: 'HI'=>'278'
731 if (!isset($env_ar['ST'])) {
732 csv_edihist_log('edih_278_csv_data: envelope error '.$fn);
733 return false;
737 if (!isset($env_ar['GS'])) {
738 csv_edihist_log('edih_278_csv_data: envelope error '.$fn);
739 return $ret_ar;
743 foreach ($env_ar['ISA'] as $icn => $isa) {
744 // array('Date', 'FileName', 'Control', 'ta1ctrl', 'RejCt');
745 $ret_ar[$icn]['type'] = $ft;
746 $ret_ar[$icn]['claim'] = array();
747 $ret_ar[$icn]['file'] = array();
748 $rspdate = $isa['date'];
750 foreach ($env_ar['GS'] as $gs) {
751 if ($gs['icn'] == $icn) {
752 $rspdate = $gs['date'];
753 break;
757 foreach ($env_ar['ST'] as $st) {
759 if ($st['icn'] != $icn) {
760 continue;
764 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
765 $loopid = '0';
766 $hl = 0;
767 //$isasender = $env_ar['ISA'][$st['icn']]['sender'];
768 //$isadate = $env_ar['ISA'][$st['icn']]['date'];
769 $isaicn = $st['icn'];
770 $has_le = false;
772 // for "claim" array
774 foreach ($stsegs as $seg) {
776 if (strncmp($seg, 'BHT'.$de, 4) === 0) {
777 // new transaction
778 // bht01 0007 --> Src, Rcv, Sbr, Dep, Event, Services
779 $rqst = '';
780 $status = 'A';
781 $cdx = count($ret_ar[$icn]['claim']);
783 $sar = explode($de, $seg);
784 if (isset($sar[2])) {
785 if ($sar[2] == '01') {
786 $rqst = 'Cancel';
789 if ($sar[2] == '13') {
790 $rqst = 'Req';
793 if ($sar[2] == '11') {
794 $rqst = 'Rsp';
797 if ($sar[2] == '36') {
798 $rqst = 'Reply';
802 $loopid = 0;
804 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
805 $ret_ar[$icn]['claim'][$cdx]['FileDate'] = $rspdate;
806 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
807 $ret_ar[$icn]['claim'][$cdx]['Status'] = '';
808 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = $sar[3]; //bht03 = $sar[3];
809 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
810 $ret_ar[$icn]['claim'][$cdx]['Auth'] = $rqst;
811 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
813 continue;
817 if (strncmp($seg, 'HL'.$de, 3) === 0) {
818 $sar = explode($de, $seg);
819 $hl = $sar[1];
820 $hlpc = $sar[2]; // parent code
821 $hllc = $sar[3];
822 $hlcc = (isset($sar[4])) ? $sar[4] : ''; // child code
823 if ($sar[3] == '20') { // level code
824 $loopid = '2000A'; // info source (payer)
825 } elseif ($sar[3] == '21') {
826 $loopid = '2000B'; // info receiver (clinic)
827 } elseif ($sar[3] == '22') {
828 $loopid = '2000C'; // subscriber
829 } elseif ($sar[3] == '23') {
830 $loopid = '2000D'; // dependent
831 } elseif ($sar[3] == 'EV') {
832 $loopid = '2000E'; // patient event
833 } elseif ($sar[3] == 'SS') {
834 $loopid = '2000F'; // service
835 } else {
836 //debug
837 csv_edihist_log('HL has no level '.$seg.' in '.$fn);
840 continue;
844 if (strncmp($seg, 'NM1'.$de, 4) === 0) {
845 $sar = explode($de, $seg);
846 $nm101 = $sar[1];
847 $nm103 = $sar[3];
848 $nm103 = ($sar[4]) ? $nm103.', '.$sar[4] : $nm103;
849 $nm103 = ($sar[5]) ? $nm103.' '.$sar[5] : $nm103;
850 if ($loopid == '2000A') {
851 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $nm103; //
852 $payer_name = $nm103;
853 } elseif ($loopid == '2000C') {
854 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm103; //$ptname = $nm1;
855 $loopid = '2010C';
856 } elseif ($loopid == '2000D') {
857 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm103; //$ptname = $nm1;
858 $loopid = '2010D';
859 } elseif (strpos('|2000E', $loopid)) {
860 $loopid = '2000E';
861 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010EA' : $loopid;
862 $loopid = (strpos('|45|FS|ND|PW|R3', $nm101) ) ? '2010EB' : $loopid;
863 $loopid = ($nm101 == 'L5') ? '2010EC' : $loopid;
864 } elseif ($loopid == '2000F') {
865 $loopid = '2000F';
866 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010FA' : $loopid;
869 continue;
872 // for 278 eligibility response (invalid data in 278 request)
873 if (strncmp($seg, 'AAA'.$de, 4) === 0) {
874 $sar = explode($de, $seg);
875 $status = 'R';
876 $rej_ct++;
877 $aaa_code = $sar[3];
878 $rsp_code = $sar[4];
879 if ($loopid == '2000A') {
880 $status .= ' Src '.$aaa_code;
881 } elseif ($loopid == '2000B') {
882 $status .= ' Rcv '.$aaa_code;
883 } elseif ($loopid == '2000C') {
884 $status .= ' Sbr '.$aaa_code;
885 } elseif ($loopid == '2000D') {
886 $status .= ' Dep '.$aaa_code;
887 } elseif ($loopid == '2000E') {
888 $status .= ' Pt '.$aaa_code;
889 } elseif ($loopid == '2000F') {
890 $status .= ' Svc '.$aaa_code;
891 } elseif ($loopid == '2010FA') {
892 $status .= ' Prv '.$aaa_code;
893 } elseif ($loopid == '2010EA') {
894 $status .= ' Svc '.$aaa_code;
895 } elseif ($loopid == '2010EC') {
896 $status .= ' Tpt '.$aaa_code;
900 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
902 continue;
906 // for 278 tracking
907 // this assumes OpenEMR will include a TRN segment in requests
908 if (strncmp($seg, 'TRN'.$de, 4) === 0) {
909 $sar = explode($de, $seg);
910 if ($rqst == 'Req') {
911 if (isset($sar[1]) && $sar[1] == '1') {
912 $ret_ar[$icn]['claim'][$cdx]['Trace'] = (isset($sar[2])) ? $sar[2] : '';
914 } else {
915 if (isset($sar[1]) && $sar[1] == '2') {
916 $ret_ar[$icn]['claim'][$cdx]['Trace'] = (isset($sar[2])) ? $sar[2] : '';
920 } // end foreach($stsegs as $seg)
922 } // endforeach($env_ar['ST'] as $st
923 $fdx = count($ret_ar[$icn]['file']);
925 $ret_ar[$icn]['file'][$fdx]['Date'] = $rspdate;
926 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
927 // could be GS06 for 278 request type
928 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
929 $ret_ar[$icn]['file'][$fdx]['TrnCount'] = $cdx;
930 $ret_ar[$icn]['file'][$fdx]['Auth'] = $rqst;
931 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_name;
933 } // endforeach($env_ar['ISA'] as $icn=>$isa)
935 return $ret_ar;
940 * Obtain claim information from batch 837|270|276|278 file to match 997/999 response
941 * Note, we assume each batch ST envelope contains a single transaction.
942 * Manual inspection is required if more than one transaction in an ST block,
944 * The 997/999 parse script creates a BHT03 reference by concatenating the
945 * response ISA13 (in TA1 segment) and the ST02 from the AK2 segment
946 * return array ['pt_name'] ['clm01'] ['svcdate'] ['batch_name'] ['stn']
948 * @uses csv_file_type()
949 * @uses csv_search_record()
951 * @param string concatenate ISA13 and ST02 for source file
952 * @param string type of source file
953 * @return array
955 function edih_rsp_st_match($rsp_trace, $file_type)
958 $info_ar = array();
960 if (strlen($rsp_trace) == 13) {
961 $bticn = substr($rsp_trace, 0, 9);
962 $stn = substr($rsp_trace, -4);
963 $btsrch = $rsp_trace;
964 } else {
965 // debug
966 csv_edihist_log('edih_rsp_st_match() invalid trace argument '.$rsp_trace);
967 return $info_ar;
971 $ft = csv_file_type($file_type);
973 if (strpos('|f837|f276|f270|f278', $ft) === false) {
974 // debug
975 csv_edihist_log('edih_rsp_st_match: file type '.$ft.' not in |f837|f276|f270|278');
976 return $info_ar;
980 $batch_srch = csv_search_record($ft, 'claim', array('s_val'=>$rsp_trace, 's_col'=>4, 'r_cols'=>'All'), '1');
981 if (is_array($batch_srch) && count($batch_srch[0])) {
982 $info_ar['pt_name'] = $batch_srch[0][0]; // $batch_srch['PtName'];
983 $info_ar['clm01'] = ($rtp == 'f837') ? $batch_srch[0][2] : $batch_srch[0][4]; // $batch_srch['CLM01'] : $batch_srch['BHT03'];
984 $info_ar['svcdate'] = $batch_srch[0][1]; // ($rtp == 'f270') ? $batch_srch['ReqDate'] : $batch_srch['SvcDate'];
985 $info_ar['batch_name'] = $batch_srch[0][5]; // $batch_srch['FileName'];
989 return $info_ar;
993 /** Extract csv file data rows from 997/999 files
995 * <pre> Creates array
996 * ['claim'][$i] = array('PtName', 'SvcDate', 'CLM01', 'Status', 'ak_num', 'File_997', 'Control', 'err_seg');
997 * ['file'][$i] = array('Date', 'FileName', 'Control', 'TA1ctrl', 'RejCt');
998 * </pre>
1000 * @uses edih_x12_file() edi HC file class
1001 * @uses edih_997_837_st_match()
1002 * @param object edih_x12_file object of type 999/997
1003 * @return array
1005 function edih_997_csv_data($obj997)
1008 $ret_ar = array();
1010 $de = $obj997->edih_delimiters()['e'];
1011 $ds = $obj997->edih_delimiters()['s'];
1012 $fn = $obj997->edih_filename();
1013 $seg_ar = $obj997->edih_segments();
1014 $env_ar = $obj997->edih_envelopes();
1016 if (!isset($env_ar['ST'])) {
1017 csv_edihist_log('edih_997_csv_data: envelope error');
1018 return $ret_ar;
1021 if (!isset($env_ar['GS'])) {
1022 csv_edihist_log('edih_997_csv_data: envelope error');
1023 return $ret_ar;
1026 foreach ($env_ar['ISA'] as $icn => $isa) {
1028 $ret_ar[$icn]['claim'] = array();
1029 $ret_ar[$icn]['file'] = array();
1031 foreach ($env_ar['GS'] as $gs) {
1032 if ($gs['icn'] == $icn) {
1033 $ret_ar[$icn]['type'] = csv_file_type($gs['type']);
1034 $rspdate = $gs['date'];
1035 break;
1040 $fdx = count($ret_ar[$icn]['file']);
1042 $ret_ar[$icn]['file'][$fdx]['Date'] = ($rspdate) ? $rspdate : $isa['date'];
1043 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
1044 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
1046 $rej_ct = 0;
1047 // CTX segment identifiers
1048 $trans_id = array('837'=>'CLM01', '270'=>'TRN02', '276'=>'TRN02');
1050 //['f997']['claim'] = array('PtName', 'RspDate', 'CLM01', 'Status', 'ak_num', 'File_997', 'Control', 'err_seg');
1051 foreach ($env_ar['ST'] as $st) {
1053 if ($st['icn'] != $icn) {
1054 continue;
1058 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
1059 $loopid = '0';
1060 //$isasender = $env_ar['ISA'][$st['icn']]['sender'];
1061 $isadate = $env_ar['ISA'][$st['icn']]['date'];
1062 $isaicn = $st['icn'];
1063 // match 997/999 response to sent file ISA control
1064 $ret_ar[$icn]['file'][$fdx]['Trace'] = ($st['trace']) ? $st['trace'] : '';
1065 $bticn = ($st['trace']) ? $st['trace'] : '';
1066 if (!$st['trace']) {
1068 csv_edihist_log('edih_997_csv_data: no trace to submitted file! '.$fn);
1071 //RspType
1072 foreach ($stsegs as $seg) {
1074 if (strncmp($seg, 'AK1'.$de, 4) === 0) {
1075 $sar = explode($de, $seg);
1077 $loopid = '2000';
1078 $rsptype = csv_file_type($sar[1]);
1079 // AK102 could be the 'trace' value if it were unique
1080 $rspgsn = $sar[2];
1082 continue;
1085 if (strncmp($seg, 'AK2'.$de, 4) === 0) {
1086 $sar = explode($de, $seg);
1087 $rspsttype = csv_file_type($sar[1]);
1088 $rspstn = (string)$sar[2];
1089 $bht03syn = sprintf("%s%04d", $isaicn, $rspstn);
1090 $iserr = false;
1091 $err_seg = '';
1092 $have_pt = false;
1093 $ptname = '';
1094 $svcdate = '';
1095 continue;
1098 if (strncmp($seg, 'IK3'.$de, 4) === 0 || strncmp($seg, 'AK3'.$de, 4) === 0) {
1099 // >> try err_seg = str_replace($de, '*', $seg)
1100 $sar = explode($de, $seg);
1101 $iserr = true;
1102 $loopid = '2100';
1103 $ctx_ct = 0;
1105 $err_seg .= ($err_seg) ? '' : $bht03syn.'*IK3*'; // ISA13+ST02 * invalid segment ID
1106 $err_seg .= (isset($sar[1])) ? '*'.$sar[1] : '*';
1107 $err_seg .= (isset($sar[2])) ? '*'.$sar[2] : '*'; // segment position
1108 //$err_seg .= (isset($sar[3])) ? '*'.$sar[3] : '*'; // loop, first 4 characters
1109 //$err_seg .= (isset($sar[4])) ? '*'.$sar[4] : '*'; // error code
1110 //$err_seg .= '*'.;
1111 // example IK3*NM1*16*2010*8~ |IK3*SegID*SegNum*Loop*ErrCode*$bht03syn
1112 // locate segment (#16 in ST-SE envelope)
1113 // ['err_seg'] = '|IK3*segID*segpos*loop*errcode*bht03syn|CTX-IK3*transID*segID*segpos*elempos
1114 // |IK4*elempos*errcode*elem*CTX-IK4*segID*segpos*elempos'
1116 // ///// retrieve original submitted claim
1117 if (!$have_pt) {
1119 $pt_info = edih_rsp_st_match($bht03syn, $rspsttype);
1120 //return array ['pt_name']['svcdate']['clm01']['batch_name'];
1121 if ($pt_info) {
1122 $ptname = (isset($pt_info['pt_name']) && strlen($pt_info['pt_name'])) ? $pt_info['pt_name'] : 'Unknown';
1123 $have_pt = true;
1124 } else {
1125 $ptname = 'Unknown';
1129 // /////////////////////////
1130 continue;
1134 //if ( strncmp($seg, 'IK4'.$de, 4) === 0 || strncmp($seg, 'AK4'.$de, 4) === 0 ) {
1135 //// data element error
1136 //$sar = explode($de, $seg);
1137 //$loopid == '2110';
1138 //$iserr = true;
1140 //$ctx_ct = 0;
1141 //$err_seg .= ($err_seg) ? '|IK4' : '';
1142 //$err_seg .= (isset($sar[1])) ? '*'.$sar[1] : '*';
1143 //$err_seg .= (isset($sar[2])) ? '*'.$sar[2] : '*';
1144 ////$err_seg .= (isset($sar[3])) ? '*'.$sar[3] : '*';
1145 ////$err_seg .= (isset($sar[4])) ? '*'.$sar[4] : '*';
1146 //// |IK4|elempos|errcode|elem
1147 //continue;
1150 //if ( strncmp($seg, 'CTX'.$de, 4) === 0 ) {
1151 //$sar = explode($de, $seg);
1152 //$ctx_ct++;
1153 //if ($loopid == '2100') {
1154 //$err_seg .= '|CTX-IK3';
1156 //if ($loopid == '2110') {
1157 //$err_seg .= '|CTX-IK4';
1159 //// CTX segment identifiers $trans_id['837'] ['270'] ['276']
1160 //if ( isset($trans_id[$rsptype]) && strpos($seg, $trans_id[$rsptype]) ) {
1161 //$err_seg .= (isset($sar[1]) && $sar[1]) ? '*'.$sar[1] : '';
1164 //if(strncmp($sar[1], 'SITUA', 5) === 0 ) {
1165 //// SITUATIONAL TRIGGER
1166 //$err_seg .= (isset($sar[2]) && $sar[2]) ? '*'.$sar[2] : '*';
1167 //$err_seg .= (isset($sar[3]) && $sar[3]) ? '*'.$sar[3] : '*';
1168 //$err_seg .= (isset($sar[5]) && $sar[5]) ? '*'.$sar[5] : '*';
1169 //// |CTX-IK3*segID*segPos*loopLS*elemPos:compositePos:repPos
1170 //} elseif ($ctx_ct > 1) {
1171 //$err_seg .= '*'.$sar[2];
1172 //if (!$have_pt) {
1173 //$p1 = strpos($sar[1],$ds);
1174 //$p2 = ($p1) ? strlen($sar[1])-$p1-1 : strlen($sar[1]);
1175 //$ret_ar[$icn]['claim'][$cdx]['CLM01'] = substr($sar[1], -$p2);
1179 //continue;
1182 if (strncmp($seg, 'AK5'.$de, 4) === 0 || strncmp($seg, 'IK5'.$de, 4) === 0) {
1183 // only store claims entries if there is an error
1184 $sar = explode($de, $seg);
1185 if ($sar[1] == 'A') {
1186 continue;
1187 } else {
1188 $rej_ct++;
1190 $cdx = count($ret_ar[$icn]['claim']);
1191 //array('PtName', 'RspDate', 'Trace', 'Status', 'Control', 'FileName', 'RspType', 'err_seg');
1192 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $ptname;
1193 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $svcdate;
1195 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $bht03syn;
1196 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
1197 $ret_ar[$icn]['claim'][$cdx]['Control'] = $icn;
1198 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
1199 $ret_ar[$icn]['claim'][$cdx]['RspType'] = $rspsttype;
1201 $ret_ar[$icn]['claim'][$cdx]['err_seg'] = $err_seg;
1203 // AK502 = Code indicating implementation error found based on the syntax editing of a transaction set
1208 } // end foreach($env_ar['ST'] as $st)
1209 $ret_ar[$icn]['file'][$fdx]['RejCt'] = $rej_ct;
1210 $ret_ar[$icn]['file'][$fdx]['RspType'] = $rsptype;
1211 } // end foreach($env_ar['ISA'] as $icn => $isa)
1215 return $ret_ar;
1220 * parse an x12 270/271 file into data rows for csv tables
1222 * @param object x12_file_object
1223 * @return array
1225 function edih_271_csv_data($obj270)
1227 //'f270 claim = array('PtName', 'ReqDate', 'PtAcct', 'InsLevel', 'BHT03', 'FileName', 'Payer');
1228 //'f270 file = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12_partner');
1229 //'f271 file = array('Date', 'FileName', 'Control', 'Claim_ct', 'Denied', 'Payer');
1230 //'f271 claim = array('PtName', 'RspDate', 'Trace', 'Status', 'BHT03', 'FileName', 'Payer');
1232 $ret_ar = array();
1234 $de = $obj270->edih_delimiters()['e'];
1235 $ds = $obj270->edih_delimiters()['s'];
1236 $fn = $obj270->edih_filename();
1237 $seg_ar = $obj270->edih_segments();
1238 $env_ar = $obj270->edih_envelopes();
1239 $ft = csv_file_type($obj270->edih_type());
1241 // $rsptype = array('HS'=>'270', 'HB'=>'271', 'HC'=>'837', 'HR'=>'276', 'HI'=>'278');
1242 if (!isset($env_ar['ST'])) {
1243 csv_edihist_log('edih_271_csv_data: envelope error '.$fn);
1244 return $ret_ar;
1248 if (!isset($env_ar['GS'])) {
1249 csv_edihist_log('edih_271_csv_data: envelope error');
1250 return $ret_ar;
1254 foreach ($env_ar['ISA'] as $icn => $isa) {
1255 // array('Date', 'FileName', 'Control', 'ta1ctrl', 'RejCt');
1256 $ret_ar[$icn]['type'] = $ft;
1257 $ret_ar[$icn]['claim'] = array();
1258 $ret_ar[$icn]['file'] = array();
1259 $rspdate = $isa['date'];
1260 $x12ptnr = $isa['receiver'];
1262 foreach ($env_ar['GS'] as $gs) {
1263 if ($gs['icn'] == $icn) {
1264 $gsdate = $gs['date'];
1265 break;
1269 foreach ($env_ar['ST'] as $st) {
1271 if ($st['icn'] != $icn) {
1272 continue;
1276 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
1277 $loopid = '0';
1278 $hl = 0;
1280 $isaicn = $st['icn'];
1281 $stn = $st['stn'];
1282 $has_le = false;
1284 // for "claim" array
1285 // 'f270' array('PtName', 'ReqDate', 'Trace', 'InsBnft', 'BHT03', 'FileName', 'Payer'); break;
1286 // 'f271'array('PtName', 'RspDate', 'Trace', 'Status', 'BHT03', 'FileName', 'Payer'); break;
1288 foreach ($stsegs as $seg) {
1290 if (strncmp($seg, 'BHT'.$de, 4) === 0) {
1291 // new transaction
1292 $cdx = (isset($ret_ar[$icn]['claim']) ) ? count($ret_ar[$icn]['claim']) : 0;
1294 $sar = explode($de, $seg);
1296 $isrqst = (isset($sar[2]) && $sar[2] == '13') ? true : false;
1297 $isrsp = (isset($sar[2]) && $sar[2] == '11') ? true : false;
1298 $loopid = 0;
1299 $bnfteq = '';
1300 $rej_ct = 0;
1302 $dtkey = ($ft == 'f271') ? 'RspDate' : 'ReqDate';
1304 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
1305 $ret_ar[$icn]['claim'][$cdx][$dtkey] = $gsdate;
1306 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
1307 if ($isrsp || $ft == 'f271') {
1308 $ret_ar[$icn]['claim'][$cdx]['Status'] = 'A'; // 271
1309 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = (isset($sar[3])) ? $sar[3] : ''; //bht03 = $sar[3];
1310 } else {
1311 $ret_ar[$icn]['claim'][$cdx]['InsBnft'] = ''; // 270
1312 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = sprintf("%s%04d", $isaicn, $stn);
1315 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
1316 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
1318 continue;
1322 if (strncmp($seg, 'HL'.$de, 3) === 0) {
1323 $sar = explode($de, $seg);
1324 $hl = $sar[1];
1325 $hlpc = $sar[2]; // parent code
1326 $hllc = $sar[3];
1327 $hlcc = (isset($sar[4])) ? $sar[4] : ''; // child code
1328 if ($sar[3] == '20') { // level code
1329 $loopid = '2000A'; // info source (payer)
1330 } elseif ($sar[3] == '21') {
1331 $loopid = '2000B'; // info receiver (clinic)
1332 } elseif ($sar[3] == '22') {
1333 $loopid = '2000C'; // subscriber
1334 } elseif ($sar[3] == '23') {
1335 $loopid = '2000D'; // dependent
1336 } else {
1337 //debug
1338 csv_edihist_log('HL has no level '.$seg.' in '.$fn);
1341 continue;
1345 if (strncmp($seg, 'NM1'.$de, 4) === 0) {
1346 $sar = explode($de, $seg);
1347 $nm1 = $sar[3];
1348 $nm1 = ($sar[4]) ? $nm1.', '.$sar[4] : $nm1;
1349 $nm1 = ($sar[5]) ? $nm1.' '.$sar[5] : $nm1;
1350 if ($loopid == '2000A') {
1351 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $nm1; //
1352 $payer_name = $nm1;
1353 } elseif ($loopid == '2000C' || $loopid == '2000D') {
1354 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm1; //$ptname = $nm1;
1357 continue;
1360 // for 271 eligibility response (invalid data in 270 request)
1361 if (strncmp($seg, 'AAA'.$de, 4) === 0) {
1362 $sar = explode($de, $seg);
1363 $status = 'R';
1364 $rej_ct++;
1365 $aaa_code = $sar[3];
1366 $rsp_code = $sar[4];
1367 if ($loopid == '2000A') {
1368 $status = $status.' Src '.$aaa_code;
1369 } elseif ($loopid == '2000B') {
1370 $status = $status.' Rcv '.$aaa_code;
1371 } elseif ($loopid == '2000C') {
1372 $status = $status.' Sbr '.$aaa_code;
1373 } elseif ($loopid == '2000D') {
1374 $status = $status.' Dep '.$aaa_code;
1378 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
1380 continue;
1384 // for 270 eligibility request
1385 if (strncmp($seg, 'EQ'.$de, 3) === 0) {
1386 if (strlen((string)$sar[1])) {
1387 $bnfteq .= ($bnfteq) ? '|'.$sar[1] : $sar[1];
1388 } elseif (strlen((string)$sar[2])) {
1389 $bnfteq .= ($bnfteq) ? '|'.$sar[2] : $sar[2];
1390 } else {
1391 csv_edihist_log('Invalid EQ segment, missing benefit type in '.$fn);
1392 continue;
1395 $ret_ar[$icn]['claim'][$cdx]['InsBnft'] = $bnfteq;
1396 continue;
1399 // overridden by REF*EJ* (not)
1400 if (strncmp($seg, 'TRN'.$de, 4) === 0) {
1401 if ($loopid = '2000C' || $loopid == '2000D') {
1402 $sar = explode($de, $seg);
1403 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2]; //$ptacct = $sar[2];
1407 continue;
1410 // for 271 eligibility response
1411 if (strncmp($seg, 'EB'.$de, 3) === 0) {
1412 $status = ( isset($status) ) ? $status : '';
1414 if (strpos($ret_ar[$icn]['claim'][$cdx]['Status'], 'tive')) {
1415 continue;
1419 $sar = explode($de, $seg);
1421 if (isset($sar[2])) {
1422 if ($sar[2] == '6' || $sar[2] == '7' || $sar[2] == '8') {
1423 $status = 'Inactive';
1424 } elseif ($sar[2] == 'I') {
1425 $status = 'Non-Covered';
1426 $rej_ct++;
1427 } elseif ($sar[2] == 'E') {
1428 $status = 'Exclusions';
1429 $rej_ct++;
1430 } elseif ($sar[2] == 'N') {
1431 $status = 'Restricted';
1432 $rej_ct++;
1433 } elseif ($sar[2] == 'V') {
1434 $status = 'Unknown';
1435 $rej_ct++;
1436 } elseif ($sar[2] == 'T') {
1437 $status = 'Card Lost';
1438 $rej_ct++;
1439 } elseif ($sar[2] == 'U') {
1440 $status = 'Contact';
1441 $rej_ct++;
1442 } elseif ($sar[2] == '1') {
1443 $status = 'Active';
1444 } elseif ($sar[2] == '2' || $sar[2] == '3' || $sar[2] == '4') {
1445 $status = 'Active Cap';
1450 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
1452 continue;
1456 if (strncmp($seg, 'DTP'.$de, 4) === 0) {
1457 $sar = explode($de, $seg);
1458 $dtp03 = (isset($sar[2]) && $sar[2] == 'D8') ? $sar[3] : substr($sar[3], 0, 8);
1459 if ($isrsp) {
1460 if ($loopid == '2100C' || $loopid == '2110C') {
1461 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $dtp03;
1462 } elseif ($loopid == '2100D' || $loopid == '2110D') {
1463 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $dtp03;
1465 } else {
1466 if ($loopid == '2100C' || $loopid == '2110C') {
1467 $ret_ar[$icn]['claim'][$cdx]['ReqDate'] = $dtp03;
1468 } elseif ($loopid == '2100D' || $loopid == '2110D') {
1469 $ret_ar[$icn]['claim'][$cdx]['ReqDate'] = $dtp03;
1474 continue;
1479 if (strncmp($seg, 'REF'.$de.'EJ'.$de, 7) === 0 ) {
1480 // patient account -- replaces or replaced by TRN02
1481 $sar = explode($de, $seg);
1482 $ret_ar[$icn]['claim'][$cdx]['PtAcct'] = $sar[2]; //$ptacct = $sar[2];
1484 continue;
1488 } // end foreach($stsegs as $seg)
1490 } // endforeach($env_ar['ST'] as $st
1491 // file: 'f271': array('Date', 'FileName', 'Control', 'Claim_ct', 'Reject', 'Payer')
1492 $fdx = count($ret_ar[$icn]['file']);
1493 //'f270': $hdr = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12Partner');
1494 $ret_ar[$icn]['file'][$fdx]['Date'] = $gsdate;
1495 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
1496 // for 270 type, could use GSO6 if it were unique
1497 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
1498 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = $cdx;
1499 if ($isrsp || $ft == 'f271') {
1500 $ret_ar[$icn]['file'][$fdx]['Reject'] = $rej_ct;
1501 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_name;
1502 } else {
1503 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = $x12ptnr;
1507 } // endforeach($env_ar['ISA'] as $icn=>$isa)
1509 return $ret_ar;
1513 * this function opens the x12 file in the object and routes
1514 * the object to the parsing function according to the x12 type
1515 * csvdata array design:
1516 * [$icn]['claims'][i] [$icn]['files'][i] [$icn]['type']
1518 * @uses edih_835_csv_data()
1519 * @uses edih_837_csv_data()
1520 * @uses edih_277_csv_data()
1521 * @uses edih_271_csv_data()
1522 * @uses edih_278_csv_data()
1523 * @uses edih_997_csv_data()
1525 * @param string path to file
1526 * @return array data for csv table records
1528 function edih_parse_select($file_path)
1530 $csvdata = array();
1531 // csvdata array design:
1532 // $csvdata[$icn]['claims'][i] [$icn]['files'][i] [$icn]['type']
1534 $x12_obj = csv_check_x12_obj($file_path);
1535 //$x12_obj = new edih_x12_file($file_path);
1536 if ($x12_obj instanceof edih_x12_file) {
1537 $ft = $x12_obj->edih_type();
1538 } else {
1539 csv_edihist_log('edih_parse_select: error in file path');
1540 return $csvdata;
1543 //'HB'=>'271', 'HS'=>'270', 'HR'=>'276', 'HI'=>'278',
1544 //'HN'=>'277', 'HP'=>'835', 'FA'=>'999', 'HC'=>'837'
1546 if ($ft == 'HP') {
1547 $csvdata = edih_835_csv_data($x12_obj);
1548 } elseif ($ft == 'HC') {
1549 $csvdata = edih_837_csv_data($x12_obj);
1550 } elseif ($ft == 'HN' || $ft == 'HR') {
1551 $csvdata = edih_277_csv_data($x12_obj);
1552 } elseif ($ft == 'FA') {
1553 $csvdata = edih_997_csv_data($x12_obj);
1554 } elseif ($ft == 'HB' || $ft == 'HS') {
1555 $csvdata = edih_271_csv_data($x12_obj);
1556 } elseif ($ft == 'HI') {
1557 $csvdata = edih_278_csv_data($x12_obj);
1558 } else {
1559 // debug
1560 csv_edihist_log('edih_parse_select(): unsupported file type '.$ft.' name: '.basename($file_path));
1564 return $csvdata;