Questionnaires and LForms (#7668)
[openemr.git] / library / edihistory / edih_csv_parse.php
blob56cd37d79eba1b501b613ba47c89584da270f117
1 <?php
3 /*
4 * edih_csv_parse.php
6 * Copyright 2016 Kevin McCormick Carrollton, Texas
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; version 3 or later. You should have
17 * received a copy of the GNU General Public License along with this program;
18 * if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * <http://opensource.org/licenses/gpl-license.php>
24 * @link: https://www.open-emr.org
25 * @package ediHistory
28 /* ========= notes
29 * EDI files may contain multiple ISA envelopes. Each ISA envelope is treated as a "file" here.
30 * The same file name may have one or more ISA control numbers
31 * The ISA control number is associated with each GS and ST envelope and each included transaction.
32 * Each transaction will also link to the ISA control number as a means of retrieving the file.
34 * The CSV data column headers are the array keys for each EDI file type.
37 /**
38 * Provide a more user-friendly date in csv tables
40 * @param string YYYYMMDD
41 * @return string YYYY-MM-DD
43 function edih_parse_date($strdate)
45 if (strlen($strdate) == 6) {
46 $gtdt = getdate();
47 $cy = (string)$gtdt['year'];
48 $dt1 = substr($cy, 0, 2) . $strdate;
49 } elseif (strpos($strdate, '-') >= 6) {
50 $dt1 = substr($strdate, 0, strpos($strdate, '-') - 1);
51 } elseif (strlen($strdate) == 8) {
52 $dt1 = $strdate;
53 } else {
54 // bad argument
55 csv_edihist_log('edih_parse_date: invalid argument ' . $strdate);
56 return false;
60 return substr($dt1, 0, 4) . '-' . substr($dt1, 4, 2) . '-' . substr($dt1, 6, 2);
63 /** remittance 835 files
65 * Each payment trace number (Control) gets a row in the csv file record.
66 * Each claim payment transaction gets a row in the csv claim record
67 * <pre>
69 * $array
70 * [$icn]['type']
71 * [$icn]['file'][$i] => array keys match csv_table_head() output
72 * [$icn]['claim'][$i] => array keys match csv_table_head() output
74 * </pre>
76 * @uses csv_file_type()
77 * @uses edih_parse_date()
78 * @uses edih_x12_transaction()
79 * @uses edih_get_segment()
80 * @param object edih_x12_obj
81 * @return array
83 function edih_835_csv_data($obj835)
86 $ret_ar = array();
88 $seg_ar = $obj835->edih_segments();
89 $env_ar = $obj835->edih_envelopes();
90 $de = $obj835->edih_delimiters()['e'];
91 $fn = $obj835->edih_filename();
92 //$tp = $obj835->edih_type();
94 // since 835 "files" table uses transaction trace as the "Control"
95 // we must assemble the 'files' array in the ST loop
96 // ['ISA'][$icn]
97 foreach ($env_ar['ISA'] as $icn => $isa) {
99 $ret_ar[$icn]['claim'] = array();
100 $ret_ar[$icn]['file'] = array();
102 $gsdate = '';
103 $trace = '';
105 if (array_key_exists('GS', $env_ar)) {
106 // for unlikely case of 'mixed' GS types in file
107 foreach ($env_ar['GS'] as $gs) {
108 if ($gs['icn'] == $icn) {
109 $ft = $gs['type'];
110 $gsdate = $gs['date'];
111 $payer_id = $gs['srcid']; // from TRN03
112 break;
117 $ret_ar[$icn]['type'] = csv_file_type($ft);
118 $gsdate = ($gsdate) ? $gsdate : edih_parse_date($isa['date']);
120 $fdx = count($ret_ar[$icn]['file']);
122 // ['ST'][$stky]=>['start']['count']['stn']['gsn']['icn']['type']['trace']['acct']
123 // ['ST'][$stky]['acct'][i]=>pid-enc$$ret_ar[$icn]['claim'][$cdx]['SvcDate'] =
124 foreach ($env_ar['ST'] as $st) {
125 if ($st['icn'] != $icn) {
126 continue;
129 // the "files" table has a row for each payment trace
131 if ($trace != $st['trace']) {
132 $fdx = count($ret_ar[$icn]['file']);
134 $ret_ar[$icn]['file'][$fdx]['Date'] = $gsdate;
135 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
136 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
137 $ret_ar[$icn]['file'][$fdx]['Trace'] = $st['trace'];
138 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = (string)count($st['acct']);
139 $ret_ar[$icn]['file'][$fdx]['Denied'] = 0;
140 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_id;
142 $trace = $st['trace'];
146 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
147 $stacct = array_values(array_unique($st['acct']));
148 $clmct = count($stacct);
149 $payer = '';
150 $denied = 0;
152 $n1pr = $obj835->edih_get_segment('N1', 'N1' . $de . 'PR' . $de, $stsegs);
153 $payer = '';
154 if ($n1pr) {
155 foreach ($n1pr as $n1) {
156 $sar = explode($de, $n1);
157 $payer = (isset($sar[2])) ? $sar[2] : '';
160 if ($payer) {
161 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer;
163 } // end if ($n1pr)
166 for ($i = 0; $i < $clmct; $i++) {
167 $clpsegs = $obj835->edih_x12_transaction($stacct[$i], $st['stn']);
168 if (!is_array($clpsegs) || !count($clpsegs)) {
170 csv_edihist_log('edih_835_csv_data: no segments for account ' . $st['acct'][$i]);
171 continue;
175 foreach ($clpsegs as $trans) {
177 $cdx = count($ret_ar[$icn]['claim']);
178 foreach ($trans as $seg) {
180 if (strncmp($seg, 'CLP' . $de, 4) === 0) {
181 $sar = explode($de, $seg);
183 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = (isset($sar[1])) ? $sar[1] : '';
184 $ret_ar[$icn]['claim'][$cdx]['Status'] = (isset($sar[2])) ? $sar[2] : '';
185 $ret_ar[$icn]['claim'][$cdx]['Pmt'] = (isset($sar[4])) ? sprintf("%01.02f", $sar[4]) : '';
186 $ret_ar[$icn]['claim'][$cdx]['PtResp'] = ( isset($sar[5]) ) ? sprintf("%01.02f", $sar[5]) : '';
187 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = ( isset($sar[7]) ) ? trim($sar[7]) : '';
188 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
189 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $st['trace'];
190 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $payer;
191 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
192 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
194 if ($sar[2] == '4' || $sar[2] == '22' || $sar[2] == '23') {
195 $denied++;
198 $loopid = "2100";
199 continue;
203 if (strncmp($seg, 'NM1' . $de . 'QC' . $de, 7) === 0) {
204 $sar = explode($de, $seg);
205 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', ' . $sar[5] : "";
206 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3] . ', ' . $sar[4] . $midn;
207 continue;
210 if (strncmp($seg, 'DTM' . $de . '232' . $de, 8) === 0) {
211 $sar = explode($de, $seg);
212 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[2];
213 continue;
216 if (strncmp($seg, 'DTM' . $de . '472' . $de, 8) === 0) {
217 $sar = explode($de, $seg);
218 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[2];
219 continue;
221 } // end foreach($trans as $seg)
222 } // end foreach($clpsegs as $trans) {
223 } // end for($i=0; $i<$clmct; $i++)
224 // get denied count
225 $ret_ar[$icn]['file'][$fdx]['Denied'] = ($denied) ? $denied : '0';
227 } // end foreach($env_ar['ST'] as $st)
228 } // end foreach($env_ar['ISA'] as $icn => $isa)
230 return $ret_ar;
235 * Parse csv data from 837 files
236 * Note that this can return false provider values for extensive claims
237 * since loops are not tracked and 837 claims can have numerous
238 * providers, but probably not an issue for OpenEMR
240 * @param object edih_x12_ file object
241 * @return array data to write csv file and csv clain table rows
243 function edih_837_csv_data($obj837)
246 $ret_ar = array();
248 $seg_ar = $obj837->edih_segments();
249 $env_ar = $obj837->edih_envelopes();
250 $de = $obj837->edih_delimiters()['e'];
251 $fn = $obj837->edih_filename();
252 //$ft = csv_file_type( $obj837->edih_type() );
254 if (!isset($env_ar['ST'])) {
255 csv_edihist_log('edih_837_csv_data: envelope error');
256 return $ret_ar;
259 //['file'] = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12_partner');
260 //['claim'] =
261 // array('PtName', 'SvcDate', 'CLM01', 'InsLevel', 'Control', 'File_837', 'Fee', 'PtPaid', 'Provider' );
263 foreach ($env_ar['ISA'] as $icn => $isa) {
265 $ret_ar[$icn]['claim'] = array();
266 $ret_ar[$icn]['file'] = array();
267 //$ret_ar[$icn]['type'] = $ft;
268 foreach ($env_ar['GS'] as $gs) {
269 if ($gs['icn'] == $icn) {
270 $ret_ar[$icn]['type'] = csv_file_type($gs['type']);
271 $gsdate = $gs['date'];
272 break;
277 $fdx = count($ret_ar[$icn]['file']);
279 $ret_ar[$icn]['file'][$fdx]['Date'] = (string)$gsdate;
280 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
281 // if GS06 were unique, it could be used as the 'Control'
282 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
283 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = (string)$isa['receiver'];
285 $clm_ct = 0;
287 foreach ($env_ar['ST'] as $st) {
288 // claims should be in the correct ISA envelope
289 if ($st['icn'] != $icn) {
290 continue;
294 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
295 $stacct = array_values(array_unique($st['acct']));
296 $clmct = count($stacct);
297 // $st['icn'] is the ISA control number for the ISA envelope containing the ST--SE
298 $date = $env_ar['ISA'][$st['icn']]['date'];
299 $stn = $st['stn'];
300 for ($i = 0; $i < $clmct; $i++) {
301 //echo '=== ACCT '.$stacct[$i].' '.$st['stn'].'<br />'.PHP_EOL;
302 $asegs = $obj837->edih_x12_transaction($stacct[$i], $st['stn']);
303 if (!is_array($asegs) || !count($asegs)) {
304 csv_edihist_log('edih_837_csv_data: no segments for account ' . $st['acct'][$i]);
305 continue;
308 foreach ($asegs as $trans) {
310 //array('PtName'=>0, 'SvcDate'=>1, 'CLM01'=>2, 'InsLevel'=>3, 'Control'=>4, 'FileName'=>5, 'Fee'=>6, 'PtPaid'=>7, 'Provider'=>8 );
312 //'f837': $hdr = array('PtName', 'SvcDate', 'CLM01', 'InsLevel', 'Control', 'FileName', 'Fee', 'PtPaid', 'Provider' )
313 foreach ($trans as $seg) {
314 if (strncmp($seg, 'BHT' . $de, 4) === 0) {
315 $cdx = count($ret_ar[$icn]['claim']);
316 $sar = explode($de, $seg);
317 $bht03 = $sar[3];
318 $hl = '';
319 $clm_ct++;
321 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
322 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
323 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = '';
324 $ret_ar[$icn]['claim'][$cdx]['InsLevel'] = '';
326 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = (strlen($bht03) == 13) ? $bht03 : sprintf("%s%04d", $st['icn'], $st['stn']);
327 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
329 $ret_ar[$icn]['claim'][$cdx]['Fee'] = '0';
330 $ret_ar[$icn]['claim'][$cdx]['PtPaid'] = '0';
331 $ret_ar[$icn]['claim'][$cdx]['Provider'] = '';
334 if (strncmp($seg, 'HL' . $de, 3) === 0) {
335 $sar = explode($de, $seg);
336 $hl = $sar[3];
337 continue;
340 if (intval($hl) == 20) {
341 if (strncmp($seg, 'NM1' . $de, 4) === 0) {
342 $sar = explode($de, $seg);
343 if ($sar[2] == '82' || $sar[2] == '85') {
344 $ret_ar[$icn]['claim'][$cdx]['Provider'] = $sar[9];
347 continue;
349 } // end if $hl == '20'
351 if (intval($hl) >= 22) {
352 if (strncmp($seg, 'SBR' . $de, 4) === 0) {
353 $sar = explode($de, $seg);
354 $ret_ar[$icn]['claim'][$cdx]['InsLevel'] = $sar[1];
357 if (strncmp($seg, 'CLM' . $de, 4) === 0) {
358 $sar = explode($de, $seg);
359 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[1];
360 $ret_ar[$icn]['claim'][$cdx]['Fee'] = $sar[2];
361 continue;
364 if (strncmp($seg, 'AMT' . $de . 'F5' . $de, 7) === 0) {
365 $sar = explode($de, $seg);
366 $ret_ar[$icn]['claim'][$cdx]['PtPaid'] = $sar[2];
367 continue;
370 if (strncmp($seg, 'NM1' . $de, 4) === 0) {
371 $sar = explode($de, $seg);
372 if (strpos('|IL|QC', $sar[1])) {
373 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', ' . $sar[5] : '';
374 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3] . ', ' . $sar[4] . $midn;
375 continue;
378 if ($sar[1] == '82') {
379 $ret_ar[$icn]['claim'][$cdx]['Provider'] = $sar[9];
380 continue;
384 if (strncmp($seg, 'DTP' . $de . '472' . $de, 8) === 0) {
385 $sar = explode($de, $seg);
386 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = $sar[3];
387 continue;
389 } // end if $hl >= '22'
390 } // end foreach($trans as $seg)
391 } // end foreach($asegs as $trans)
392 } // end for($i=0; $i<$clmct; $i++)
393 } // end foreach($obj837->envelopes['ST'] as $st)
394 // claim count
395 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = (string)$clm_ct;
396 } // end foreach($env_ar['ISA'] as $icn => $isa)
398 return $ret_ar;
402 * extract csv table row data for x12 277 files
404 * @param object edih_x12_file object of type 276/277
405 * @return array
407 function edih_277_csv_data($obj277)
410 $ret_ar = array();
412 $seg_ar = $obj277->edih_segments();
413 $env_ar = $obj277->edih_envelopes();
414 $de = $obj277->edih_delimiters()['e'];
415 $fn = $obj277->edih_filename();
416 $tp = $obj277->edih_type();
417 // 'HN' 277 'HR' 276 )
418 $env_ar = $obj277->edih_envelopes();
420 if (!isset($env_ar['ST'])) {
421 csv_edihist_log('edih_277_csv_data: envelope error');
422 return $ret_ar;
425 if (!isset($env_ar['GS'])) {
426 csv_edihist_log('edih_277_csv_data: envelope error');
427 return $ret_ar;
431 foreach ($env_ar['ISA'] as $icn => $isa) {
433 $ret_ar[$icn]['claim'] = array();
434 $ret_ar[$icn]['file'] = array();
436 $rspdate = $isa['date'];
437 foreach ($env_ar['GS'] as $gs) {
438 if ($gs['icn'] == $icn) {
439 $ret_ar[$icn]['type'] = csv_file_type($gs['type']);
440 $rspdate = $gs['date'];
441 break;
445 //$ret_ar[$icn]['type'] = csv_file_type($ft);
447 $fdx = count($ret_ar[$icn]['file']);
448 //['f277']['file'] = array('Date', 'FileName', 'Control', 'Accept', 'AccAmt', 'Reject', 'RejAmt');
449 //'f276': $hdr = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12Partner');
450 $ret_ar[$icn]['file'][$fdx]['Date'] = $rspdate;
451 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
452 // could be GS06 for 276 if it were unique
453 $ret_ar[$icn]['file'][$fdx]['Control'] = (string)$icn;
454 if ($tp == 'HN') {
455 $ret_ar[$icn]['file'][$fdx]['Accept'] = 0;
456 $ret_ar[$icn]['file'][$fdx]['Reject'] = 0;
457 $ret_ar[$icn]['file'][$fdx]['AccAmt'] = 0;
458 $ret_ar[$icn]['file'][$fdx]['RejAmt'] = 0;
459 } else {
460 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = 0;
461 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = $isa['receiver'];
465 $clmct = 0;
467 //['ST'][$stky]=>['start']['count']['stn']['gsn']['icn']['type']['trace']['acct']
468 // ['ST'][$stky]['acct'][i]=>pid-enc
469 //'f277': $hdr = array('PtName', 'SvcDate', 'CLM01', 'Status', 'BHT03', 'FileName', 'Payer', 'Trace');
470 foreach ($env_ar['ST'] as $st) {
472 if ($st['icn'] != $icn) {
473 continue;
477 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
478 $stacct = array_values(array_unique($st['bht03']));
479 $clmct += count($stacct);
480 $st_icn = $st['icn']; // same value as $obj277->envelopes['ISA']['icn']
481 $stn = $st['stn'];
483 if ($tp == 'HR') {
484 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = $clmct;
488 //for($i=0; $i<$clmct; $i++) {
489 for ($i = 0; $i < count($stacct); $i++) {
491 $asegs = $obj277->edih_x12_transaction($stacct[$i]);
493 foreach ($asegs as $trans) {
495 foreach ($trans as $seg) {
497 if (strncmp($seg, 'BHT' . $de, 4) === 0) {
498 $cdx = count($ret_ar[$icn]['claim']);
500 $sar = explode($de, $seg);
501 if ($sar[2] != '08') {
502 csv_edihist_log('Claim Status BHT purpose code: ' . $sar[2] . ' in ST ' . $st['stn'] . ' in file ' . $fn);
505 $trns_tp = (isset($sar[6]) && $sar[6]) ? $sar[6] : '';
506 if ($trns_tp == 'TH') {
507 $bht_id = 'ack'; // 277CA
508 } elseif ($trns_tp == 'DG') {
509 $bht_id = 'rsp'; // 277
510 } else {
511 $bht_id = 'sub'; // 276
515 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
516 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = '';
517 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = '';
519 if ($tp == 'HN') {
520 // 277
521 $ret_ar[$icn]['claim'][$cdx]['Status'] = '';
522 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = $sar[3];
523 } elseif ($tp == 'HR') {
524 //276
525 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = '';
526 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = sprintf("%s%04d", $st_icn, $stn);
531 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
533 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
534 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = '';
535 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
536 continue;
540 if (strncmp($seg, 'HL' . $de, 3) === 0) {
541 $sar = explode($de, $seg);
542 $hl = (string)$sar[3];
546 if ($hl == '20') {
547 // information source
548 if (strncmp($seg, 'NM1' . $de, 4) === 0) {
549 $sar = explode($de, $seg);
550 $ret_ar[$icn]['claim'][$cdx]['Payer'] = ($sar[1] == 'PR' || $sar[1] == 'AY') ? $sar[3] : '';
551 continue;
556 if ($hl == '21') {
557 // information source or receiver level rejection
558 // -- user should view the transaction
559 // -- don't include in csv data so Trace only refers to 276
560 //if ( strncmp($seg, 'TRN'.$de, 4) === 0) {
561 //$sar = explode($de, $seg);
562 //$ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
564 if (strncmp($seg, 'STC' . $de, 4) === 0) {
565 $sar = explode($de, $seg);
566 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
569 if (strncmp($seg, 'QTY' . $de, 4) === 0) {
570 $sar = explode($de, $seg);
571 if ($sar[1] == '90') {
572 $ret_ar[$icn]['file'][$fdx]['Accept'] += $sar[2];
575 if ($sar[1] == 'AA') {
576 $ret_ar[$icn]['file'][$fdx]['Reject'] += $sar[2];
580 if (strncmp($seg, 'AMT' . $de, 4) === 0) {
581 $sar = explode($de, $seg);
582 if ($sar[1] == 'YU') {
583 $ret_ar[$icn]['file'][$fdx]['AccAmt'] += $sar[2];
586 if ($sar[1] == 'YY') {
587 $ret_ar[$icn]['file'][$fdx]['RejAmt'] += $sar[2];
591 continue;
595 if ($hl == '19') {
596 // provider level rejection
597 // -- user should view the transaction
598 // -- don't include in csv data so Trace only refers to 276
599 //if ( strncmp($seg, 'TRN'.$de, 4) === 0) {
600 //$sar = explode($de, $seg);
601 //$ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
603 if (strncmp($seg, 'STC' . $de, 4) === 0) {
604 $sar = explode($de, $seg);
605 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
608 continue;
612 if ($hl == '22' || $hl == '23') {
613 // subscriber or dependent
614 if (strncmp($seg, 'NM1' . $de, 4) === 0) {
615 $sar = explode($de, $seg);
616 if ($sar[1] == 'IL' || $sar[1] == 'QC') {
617 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', ' . $sar[5] : "";
618 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3] . ', ' . $sar[4] . $midn;
619 //if (isset($sar[8]) && $sar[8] == 'MI') {
620 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = (isset($sar[9])) ? $sar[9] : '';
624 continue;
627 // in response to 276, this is the reference given in TRN02
628 if (strncmp($seg, 'TRN' . $de . '2' . $de, 4) === 0) {
629 $sar = explode($de, $seg);
630 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2];
631 continue;
634 // REF*EJ* will give the payer assigned claim number
635 // not used much in 277CA files
636 if (strncmp($seg, 'REF' . $de . 'EJ' . $de, 7) === 0) {
637 $sar = explode($de, $seg);
638 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[2];
639 continue;
642 if (strncmp($seg, 'REF' . $de . '1K' . $de, 7) === 0) {
643 // hopefully OpenEMR will include the claim number in 276
644 if ($tp == 'HR') {
645 $sar = explode($de, $seg);
646 $ret_ar[$icn]['claim'][$cdx]['ClaimID'] = $sar[2];
649 continue;
652 // REF*D9*(Claim number)~
654 if (strncmp($seg, 'STC' . $de, 4) === 0) {
655 // STC is only present in 277
656 $sar = explode($de, $seg);
657 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
658 continue;
661 continue;
664 if ($hl == 'PT') {
665 // 277CA
666 if (strncmp($seg, 'NM1' . $de, 4) === 0) {
667 $sar = explode($de, $seg);
668 if ($sar[1] == 'IL' || $sar[1] == 'QC') {
669 $midn = ( isset($sar[5]) && strlen($sar[5]) ) ? ', ' . $sar[5] : "";
670 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $sar[3] . ', ' . $sar[4] . $midn;
671 //$ret_ar[$icn]['claim'][$cdx]['Ins_ID'] = (isset($sar[9])) ? $sar[9] : '';
674 continue;
677 if (strncmp($seg, 'TRN' . $de . '2' . $de, 6) === 0) {
678 $sar = explode($de, $seg);
679 $ret_ar[$icn]['claim'][$cdx]['CLM01'] = $sar[2];
680 continue;
683 if (strncmp($seg, 'STC' . $de, 4) === 0) {
684 $sar = explode($de, $seg);
685 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
686 continue;
689 //if ( strncmp($seg, 'REF'.$de.'1K'.$de, 7) === 0) {
690 //$sar = explode($de, $seg);
691 //$ret_ar[$icn]['claim'][$cdx]['ClaimID'] = $sar[2];
692 //continue;
694 if (strncmp($seg, 'DTP' . $de . '472' . $de, 8) === 0) {
695 $sar = explode($de, $seg);
696 // D8-CCYYMMDD RD8-CCYYMMDD-CCYYMMDD only take initial date
697 $ret_ar[$icn]['claim'][$cdx]['SvcDate'] = substr($sar[3], 0, 8);
698 continue;
701 } // end foreach($trans as $seg)
702 } // end foreach($asegs as $trans)
703 } // end for($i=0; $i<$clmct; $i++)
704 }// end foreach($obj277->envelopes['ST'] as $st)
705 } // end foreach($env_ar['ISA'] as $icn => $isa)
707 return $ret_ar;
711 * parse an x12 278 file into data rows for csv tables
713 * @param object x12_file_object
714 * @return array
716 function edih_278_csv_data($obj278)
719 // f278 file = array('Date', 'FileName', 'Control', 'TrnCount', 'Auth', 'Payer');
720 // f278 claim = array('PtName', 'FileDate', 'Trace', 'Status' 'BHT03', 'FileName', 'Auth', 'Payer');
722 $ret_ar = array();
724 $de = $obj278->edih_delimiters()['e'];
725 $ds = $obj278->edih_delimiters()['s'];
726 $fn = $obj278->edih_filename();
727 $seg_ar = $obj278->edih_segments();
728 $env_ar = $obj278->edih_envelopes();
729 $ft = csv_file_type($obj278->edih_type());
731 // $ft: 'HI'=>'278'
732 if (!isset($env_ar['ST'])) {
733 csv_edihist_log('edih_278_csv_data: envelope error ' . $fn);
734 return false;
738 if (!isset($env_ar['GS'])) {
739 csv_edihist_log('edih_278_csv_data: envelope error ' . $fn);
740 return $ret_ar;
744 foreach ($env_ar['ISA'] as $icn => $isa) {
745 // array('Date', 'FileName', 'Control', 'ta1ctrl', 'RejCt');
746 $ret_ar[$icn]['type'] = $ft;
747 $ret_ar[$icn]['claim'] = array();
748 $ret_ar[$icn]['file'] = array();
749 $rspdate = $isa['date'];
751 foreach ($env_ar['GS'] as $gs) {
752 if ($gs['icn'] == $icn) {
753 $rspdate = $gs['date'];
754 break;
758 foreach ($env_ar['ST'] as $st) {
760 if ($st['icn'] != $icn) {
761 continue;
765 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
766 $loopid = '0';
767 $hl = 0;
768 //$isasender = $env_ar['ISA'][$st['icn']]['sender'];
769 //$isadate = $env_ar['ISA'][$st['icn']]['date'];
770 $isaicn = $st['icn'];
771 $has_le = false;
773 // for "claim" array
775 foreach ($stsegs as $seg) {
777 if (strncmp($seg, 'BHT' . $de, 4) === 0) {
778 // new transaction
779 // bht01 0007 --> Src, Rcv, Sbr, Dep, Event, Services
780 $rqst = '';
781 $status = 'A';
782 $cdx = count($ret_ar[$icn]['claim']);
784 $sar = explode($de, $seg);
785 if (isset($sar[2])) {
786 if ($sar[2] == '01') {
787 $rqst = 'Cancel';
790 if ($sar[2] == '13') {
791 $rqst = 'Req';
794 if ($sar[2] == '11') {
795 $rqst = 'Rsp';
798 if ($sar[2] == '36') {
799 $rqst = 'Reply';
803 $loopid = 0;
805 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
806 $ret_ar[$icn]['claim'][$cdx]['FileDate'] = $rspdate;
807 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
808 $ret_ar[$icn]['claim'][$cdx]['Status'] = '';
809 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = $sar[3]; //bht03 = $sar[3];
810 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
811 $ret_ar[$icn]['claim'][$cdx]['Auth'] = $rqst;
812 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
814 continue;
818 if (strncmp($seg, 'HL' . $de, 3) === 0) {
819 $sar = explode($de, $seg);
820 $hl = $sar[1];
821 $hlpc = $sar[2]; // parent code
822 $hllc = $sar[3];
823 $hlcc = (isset($sar[4])) ? $sar[4] : ''; // child code
824 if ($sar[3] == '20') { // level code
825 $loopid = '2000A'; // info source (payer)
826 } elseif ($sar[3] == '21') {
827 $loopid = '2000B'; // info receiver (clinic)
828 } elseif ($sar[3] == '22') {
829 $loopid = '2000C'; // subscriber
830 } elseif ($sar[3] == '23') {
831 $loopid = '2000D'; // dependent
832 } elseif ($sar[3] == 'EV') {
833 $loopid = '2000E'; // patient event
834 } elseif ($sar[3] == 'SS') {
835 $loopid = '2000F'; // service
836 } else {
837 //debug
838 csv_edihist_log('HL has no level ' . $seg . ' in ' . $fn);
841 continue;
845 if (strncmp($seg, 'NM1' . $de, 4) === 0) {
846 $sar = explode($de, $seg);
847 $nm101 = $sar[1];
848 $nm103 = $sar[3];
849 $nm103 = ($sar[4]) ? $nm103 . ', ' . $sar[4] : $nm103;
850 $nm103 = ($sar[5]) ? $nm103 . ' ' . $sar[5] : $nm103;
851 if ($loopid == '2000A') {
852 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $nm103; //
853 $payer_name = $nm103;
854 } elseif ($loopid == '2000C') {
855 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm103; //$ptname = $nm1;
856 $loopid = '2010C';
857 } elseif ($loopid == '2000D') {
858 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm103; //$ptname = $nm1;
859 $loopid = '2010D';
860 } elseif (strpos('|2000E', $loopid)) {
861 $loopid = '2000E';
862 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010EA' : $loopid;
863 $loopid = (strpos('|45|FS|ND|PW|R3', $nm101) ) ? '2010EB' : $loopid;
864 $loopid = ($nm101 == 'L5') ? '2010EC' : $loopid;
865 } elseif ($loopid == '2000F') {
866 $loopid = '2000F';
867 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010FA' : $loopid;
870 continue;
873 // for 278 eligibility response (invalid data in 278 request)
874 if (strncmp($seg, 'AAA' . $de, 4) === 0) {
875 $sar = explode($de, $seg);
876 $status = 'R';
877 $rej_ct++;
878 $aaa_code = $sar[3];
879 $rsp_code = $sar[4];
880 if ($loopid == '2000A') {
881 $status .= ' Src ' . $aaa_code;
882 } elseif ($loopid == '2000B') {
883 $status .= ' Rcv ' . $aaa_code;
884 } elseif ($loopid == '2000C') {
885 $status .= ' Sbr ' . $aaa_code;
886 } elseif ($loopid == '2000D') {
887 $status .= ' Dep ' . $aaa_code;
888 } elseif ($loopid == '2000E') {
889 $status .= ' Pt ' . $aaa_code;
890 } elseif ($loopid == '2000F') {
891 $status .= ' Svc ' . $aaa_code;
892 } elseif ($loopid == '2010FA') {
893 $status .= ' Prv ' . $aaa_code;
894 } elseif ($loopid == '2010EA') {
895 $status .= ' Svc ' . $aaa_code;
896 } elseif ($loopid == '2010EC') {
897 $status .= ' Tpt ' . $aaa_code;
901 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
903 continue;
907 // for 278 tracking
908 // this assumes OpenEMR will include a TRN segment in requests
909 if (strncmp($seg, 'TRN' . $de, 4) === 0) {
910 $sar = explode($de, $seg);
911 if ($rqst == 'Req') {
912 if (isset($sar[1]) && $sar[1] == '1') {
913 $ret_ar[$icn]['claim'][$cdx]['Trace'] = (isset($sar[2])) ? $sar[2] : '';
915 } else {
916 if (isset($sar[1]) && $sar[1] == '2') {
917 $ret_ar[$icn]['claim'][$cdx]['Trace'] = (isset($sar[2])) ? $sar[2] : '';
921 } // end foreach($stsegs as $seg)
923 } // endforeach($env_ar['ST'] as $st
924 $fdx = count($ret_ar[$icn]['file']);
926 $ret_ar[$icn]['file'][$fdx]['Date'] = $rspdate;
927 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
928 // could be GS06 for 278 request type
929 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
930 $ret_ar[$icn]['file'][$fdx]['TrnCount'] = $cdx;
931 $ret_ar[$icn]['file'][$fdx]['Auth'] = $rqst;
932 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_name;
934 } // endforeach($env_ar['ISA'] as $icn=>$isa)
936 return $ret_ar;
941 * Obtain claim information from batch 837|270|276|278 file to match 997/999 response
942 * Note, we assume each batch ST envelope contains a single transaction.
943 * Manual inspection is required if more than one transaction in an ST block,
945 * The 997/999 parse script creates a BHT03 reference by concatenating the
946 * response ISA13 (in TA1 segment) and the ST02 from the AK2 segment
947 * return array ['pt_name'] ['clm01'] ['svcdate'] ['batch_name'] ['stn']
949 * @uses csv_file_type()
950 * @uses csv_search_record()
952 * @param string concatenate ISA13 and ST02 for source file
953 * @param string type of source file
954 * @return array
956 function edih_rsp_st_match($rsp_trace, $file_type)
959 $info_ar = array();
961 if (strlen($rsp_trace) == 13) {
962 $bticn = substr($rsp_trace, 0, 9);
963 $stn = substr($rsp_trace, -4);
964 $btsrch = $rsp_trace;
965 } else {
966 // debug
967 csv_edihist_log('edih_rsp_st_match() invalid trace argument ' . $rsp_trace);
968 return $info_ar;
972 $ft = csv_file_type($file_type);
974 if (strpos('|f837|f276|f270|f278', $ft) === false) {
975 // debug
976 csv_edihist_log('edih_rsp_st_match: file type ' . $ft . ' not in |f837|f276|f270|278');
977 return $info_ar;
981 $batch_srch = csv_search_record($ft, 'claim', array('s_val' => $rsp_trace, 's_col' => 4, 'r_cols' => 'All'), '1');
982 if (is_array($batch_srch) && count($batch_srch[0])) {
983 $info_ar['pt_name'] = $batch_srch[0][0]; // $batch_srch['PtName'];
984 $info_ar['clm01'] = ($rtp == 'f837') ? $batch_srch[0][2] : $batch_srch[0][4]; // $batch_srch['CLM01'] : $batch_srch['BHT03'];
985 $info_ar['svcdate'] = $batch_srch[0][1]; // ($rtp == 'f270') ? $batch_srch['ReqDate'] : $batch_srch['SvcDate'];
986 $info_ar['batch_name'] = $batch_srch[0][5]; // $batch_srch['FileName'];
990 return $info_ar;
994 /** Extract csv file data rows from 997/999 files
996 * <pre> Creates array
997 * ['claim'][$i] = array('PtName', 'SvcDate', 'CLM01', 'Status', 'ak_num', 'File_997', 'Control', 'err_seg');
998 * ['file'][$i] = array('Date', 'FileName', 'Control', 'TA1ctrl', 'RejCt');
999 * </pre>
1001 * @uses edih_x12_file() edi HC file class
1002 * @uses edih_997_837_st_match()
1003 * @param object edih_x12_file object of type 999/997
1004 * @return array
1006 function edih_997_csv_data($obj997)
1009 $ret_ar = array();
1011 $de = $obj997->edih_delimiters()['e'];
1012 $ds = $obj997->edih_delimiters()['s'];
1013 $fn = $obj997->edih_filename();
1014 $seg_ar = $obj997->edih_segments();
1015 $env_ar = $obj997->edih_envelopes();
1017 if (!isset($env_ar['ST'])) {
1018 csv_edihist_log('edih_997_csv_data: envelope error');
1019 return $ret_ar;
1022 if (!isset($env_ar['GS'])) {
1023 csv_edihist_log('edih_997_csv_data: envelope error');
1024 return $ret_ar;
1027 foreach ($env_ar['ISA'] as $icn => $isa) {
1029 $ret_ar[$icn]['claim'] = array();
1030 $ret_ar[$icn]['file'] = array();
1032 foreach ($env_ar['GS'] as $gs) {
1033 if ($gs['icn'] == $icn) {
1034 $ret_ar[$icn]['type'] = csv_file_type($gs['type']);
1035 $rspdate = $gs['date'];
1036 break;
1041 $fdx = count($ret_ar[$icn]['file']);
1043 $ret_ar[$icn]['file'][$fdx]['Date'] = ($rspdate) ? $rspdate : $isa['date'];
1044 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
1045 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
1047 $rej_ct = 0;
1048 // CTX segment identifiers
1049 $trans_id = array('837' => 'CLM01', '270' => 'TRN02', '276' => 'TRN02');
1051 //['f997']['claim'] = array('PtName', 'RspDate', 'CLM01', 'Status', 'ak_num', 'File_997', 'Control', 'err_seg');
1052 foreach ($env_ar['ST'] as $st) {
1054 if ($st['icn'] != $icn) {
1055 continue;
1059 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
1060 $loopid = '0';
1061 //$isasender = $env_ar['ISA'][$st['icn']]['sender'];
1062 $isadate = $env_ar['ISA'][$st['icn']]['date'];
1063 $isaicn = $st['icn'];
1064 // match 997/999 response to sent file ISA control
1065 $ret_ar[$icn]['file'][$fdx]['Trace'] = ($st['trace']) ? $st['trace'] : '';
1066 $bticn = ($st['trace']) ? $st['trace'] : '';
1067 if (!$st['trace']) {
1069 csv_edihist_log('edih_997_csv_data: no trace to submitted file! ' . $fn);
1072 //RspType
1073 foreach ($stsegs as $seg) {
1075 if (strncmp($seg, 'AK1' . $de, 4) === 0) {
1076 $sar = explode($de, $seg);
1078 $loopid = '2000';
1079 $rsptype = csv_file_type($sar[1]);
1080 // AK102 could be the 'trace' value if it were unique
1081 $rspgsn = $sar[2];
1083 continue;
1086 if (strncmp($seg, 'AK2' . $de, 4) === 0) {
1087 $sar = explode($de, $seg);
1088 $rspsttype = csv_file_type($sar[1]);
1089 $rspstn = (string)$sar[2];
1090 $bht03syn = sprintf("%s%04d", $isaicn, $rspstn);
1091 $iserr = false;
1092 $err_seg = '';
1093 $have_pt = false;
1094 $ptname = '';
1095 $svcdate = '';
1096 continue;
1099 if (strncmp($seg, 'IK3' . $de, 4) === 0 || strncmp($seg, 'AK3' . $de, 4) === 0) {
1100 // >> try err_seg = str_replace($de, '*', $seg)
1101 $sar = explode($de, $seg);
1102 $iserr = true;
1103 $loopid = '2100';
1104 $ctx_ct = 0;
1106 $err_seg .= ($err_seg) ? '' : $bht03syn . '*IK3*'; // ISA13+ST02 * invalid segment ID
1107 $err_seg .= (isset($sar[1])) ? '*' . $sar[1] : '*';
1108 $err_seg .= (isset($sar[2])) ? '*' . $sar[2] : '*'; // segment position
1109 //$err_seg .= (isset($sar[3])) ? '*'.$sar[3] : '*'; // loop, first 4 characters
1110 //$err_seg .= (isset($sar[4])) ? '*'.$sar[4] : '*'; // error code
1111 //$err_seg .= '*'.;
1112 // example IK3*NM1*16*2010*8~ |IK3*SegID*SegNum*Loop*ErrCode*$bht03syn
1113 // locate segment (#16 in ST-SE envelope)
1114 // ['err_seg'] = '|IK3*segID*segpos*loop*errcode*bht03syn|CTX-IK3*transID*segID*segpos*elempos
1115 // |IK4*elempos*errcode*elem*CTX-IK4*segID*segpos*elempos'
1117 // ///// retrieve original submitted claim
1118 if (!$have_pt) {
1120 $pt_info = edih_rsp_st_match($bht03syn, $rspsttype);
1121 //return array ['pt_name']['svcdate']['clm01']['batch_name'];
1122 if ($pt_info) {
1123 $ptname = (isset($pt_info['pt_name']) && strlen($pt_info['pt_name'])) ? $pt_info['pt_name'] : 'Unknown';
1124 $have_pt = true;
1125 } else {
1126 $ptname = 'Unknown';
1130 // /////////////////////////
1131 continue;
1135 //if ( strncmp($seg, 'IK4'.$de, 4) === 0 || strncmp($seg, 'AK4'.$de, 4) === 0 ) {
1136 //// data element error
1137 //$sar = explode($de, $seg);
1138 //$loopid == '2110';
1139 //$iserr = true;
1141 //$ctx_ct = 0;
1142 //$err_seg .= ($err_seg) ? '|IK4' : '';
1143 //$err_seg .= (isset($sar[1])) ? '*'.$sar[1] : '*';
1144 //$err_seg .= (isset($sar[2])) ? '*'.$sar[2] : '*';
1145 ////$err_seg .= (isset($sar[3])) ? '*'.$sar[3] : '*';
1146 ////$err_seg .= (isset($sar[4])) ? '*'.$sar[4] : '*';
1147 //// |IK4|elempos|errcode|elem
1148 //continue;
1151 //if ( strncmp($seg, 'CTX'.$de, 4) === 0 ) {
1152 //$sar = explode($de, $seg);
1153 //$ctx_ct++;
1154 //if ($loopid == '2100') {
1155 //$err_seg .= '|CTX-IK3';
1157 //if ($loopid == '2110') {
1158 //$err_seg .= '|CTX-IK4';
1160 //// CTX segment identifiers $trans_id['837'] ['270'] ['276']
1161 //if ( isset($trans_id[$rsptype]) && strpos($seg, $trans_id[$rsptype]) ) {
1162 //$err_seg .= (isset($sar[1]) && $sar[1]) ? '*'.$sar[1] : '';
1165 //if(strncmp($sar[1], 'SITUA', 5) === 0 ) {
1166 //// SITUATIONAL TRIGGER
1167 //$err_seg .= (isset($sar[2]) && $sar[2]) ? '*'.$sar[2] : '*';
1168 //$err_seg .= (isset($sar[3]) && $sar[3]) ? '*'.$sar[3] : '*';
1169 //$err_seg .= (isset($sar[5]) && $sar[5]) ? '*'.$sar[5] : '*';
1170 //// |CTX-IK3*segID*segPos*loopLS*elemPos:compositePos:repPos
1171 //} elseif ($ctx_ct > 1) {
1172 //$err_seg .= '*'.$sar[2];
1173 //if (!$have_pt) {
1174 //$p1 = strpos($sar[1],$ds);
1175 //$p2 = ($p1) ? strlen($sar[1])-$p1-1 : strlen($sar[1]);
1176 //$ret_ar[$icn]['claim'][$cdx]['CLM01'] = substr($sar[1], -$p2);
1180 //continue;
1183 if (strncmp($seg, 'AK5' . $de, 4) === 0 || strncmp($seg, 'IK5' . $de, 4) === 0) {
1184 // only store claims entries if there is an error
1185 $sar = explode($de, $seg);
1186 if ($sar[1] == 'A') {
1187 continue;
1188 } else {
1189 $rej_ct++;
1191 $cdx = count($ret_ar[$icn]['claim']);
1192 //array('PtName', 'RspDate', 'Trace', 'Status', 'Control', 'FileName', 'RspType', 'err_seg');
1193 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $ptname;
1194 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $svcdate;
1196 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $bht03syn;
1197 $ret_ar[$icn]['claim'][$cdx]['Status'] = $sar[1];
1198 $ret_ar[$icn]['claim'][$cdx]['Control'] = $icn;
1199 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
1200 $ret_ar[$icn]['claim'][$cdx]['RspType'] = $rspsttype;
1202 $ret_ar[$icn]['claim'][$cdx]['err_seg'] = $err_seg;
1204 // AK502 = Code indicating implementation error found based on the syntax editing of a transaction set
1209 } // end foreach($env_ar['ST'] as $st)
1210 $ret_ar[$icn]['file'][$fdx]['RejCt'] = $rej_ct;
1211 $ret_ar[$icn]['file'][$fdx]['RspType'] = $rsptype;
1212 } // end foreach($env_ar['ISA'] as $icn => $isa)
1216 return $ret_ar;
1221 * parse an x12 270/271 file into data rows for csv tables
1223 * @param object x12_file_object
1224 * @return array
1226 function edih_271_csv_data($obj270)
1228 //'f270 claim = array('PtName', 'ReqDate', 'PtAcct', 'InsLevel', 'BHT03', 'FileName', 'Payer');
1229 //'f270 file = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12_partner');
1230 //'f271 file = array('Date', 'FileName', 'Control', 'Claim_ct', 'Denied', 'Payer');
1231 //'f271 claim = array('PtName', 'RspDate', 'Trace', 'Status', 'BHT03', 'FileName', 'Payer');
1233 $ret_ar = array();
1235 $de = $obj270->edih_delimiters()['e'];
1236 $ds = $obj270->edih_delimiters()['s'];
1237 $fn = $obj270->edih_filename();
1238 $seg_ar = $obj270->edih_segments();
1239 $env_ar = $obj270->edih_envelopes();
1240 $ft = csv_file_type($obj270->edih_type());
1242 // $rsptype = array('HS'=>'270', 'HB'=>'271', 'HC'=>'837', 'HR'=>'276', 'HI'=>'278');
1243 if (!isset($env_ar['ST'])) {
1244 csv_edihist_log('edih_271_csv_data: envelope error ' . $fn);
1245 return $ret_ar;
1249 if (!isset($env_ar['GS'])) {
1250 csv_edihist_log('edih_271_csv_data: envelope error');
1251 return $ret_ar;
1255 foreach ($env_ar['ISA'] as $icn => $isa) {
1256 // array('Date', 'FileName', 'Control', 'ta1ctrl', 'RejCt');
1257 $ret_ar[$icn]['type'] = $ft;
1258 $ret_ar[$icn]['claim'] = array();
1259 $ret_ar[$icn]['file'] = array();
1260 $rspdate = $isa['date'];
1261 $x12ptnr = $isa['receiver'];
1263 foreach ($env_ar['GS'] as $gs) {
1264 if ($gs['icn'] == $icn) {
1265 $gsdate = $gs['date'];
1266 break;
1270 foreach ($env_ar['ST'] as $st) {
1272 if ($st['icn'] != $icn) {
1273 continue;
1277 $stsegs = array_slice($seg_ar, $st['start'], $st['count']);
1278 $loopid = '0';
1279 $hl = 0;
1281 $isaicn = $st['icn'];
1282 $stn = $st['stn'];
1283 $has_le = false;
1285 // for "claim" array
1286 // 'f270' array('PtName', 'ReqDate', 'Trace', 'InsBnft', 'BHT03', 'FileName', 'Payer'); break;
1287 // 'f271'array('PtName', 'RspDate', 'Trace', 'Status', 'BHT03', 'FileName', 'Payer'); break;
1289 foreach ($stsegs as $seg) {
1291 if (strncmp($seg, 'BHT' . $de, 4) === 0) {
1292 // new transaction
1293 $cdx = (isset($ret_ar[$icn]['claim']) ) ? count($ret_ar[$icn]['claim']) : 0;
1295 $sar = explode($de, $seg);
1297 $isrqst = (isset($sar[2]) && $sar[2] == '13') ? true : false;
1298 $isrsp = (isset($sar[2]) && $sar[2] == '11') ? true : false;
1299 $loopid = 0;
1300 $bnfteq = '';
1301 $rej_ct = 0;
1303 $dtkey = ($ft == 'f271') ? 'RspDate' : 'ReqDate';
1305 $ret_ar[$icn]['claim'][$cdx]['PtName'] = '';
1306 $ret_ar[$icn]['claim'][$cdx][$dtkey] = $gsdate;
1307 $ret_ar[$icn]['claim'][$cdx]['Trace'] = '';
1308 if ($isrsp || $ft == 'f271') {
1309 $ret_ar[$icn]['claim'][$cdx]['Status'] = 'A'; // 271
1310 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = (isset($sar[3])) ? $sar[3] : ''; //bht03 = $sar[3];
1311 } else {
1312 $ret_ar[$icn]['claim'][$cdx]['InsBnft'] = ''; // 270
1313 $ret_ar[$icn]['claim'][$cdx]['BHT03'] = sprintf("%s%04d", $isaicn, $stn);
1316 $ret_ar[$icn]['claim'][$cdx]['FileName'] = $fn;
1317 $ret_ar[$icn]['claim'][$cdx]['Payer'] = '';
1319 continue;
1323 if (strncmp($seg, 'HL' . $de, 3) === 0) {
1324 $sar = explode($de, $seg);
1325 $hl = $sar[1];
1326 $hlpc = $sar[2]; // parent code
1327 $hllc = $sar[3];
1328 $hlcc = (isset($sar[4])) ? $sar[4] : ''; // child code
1329 if ($sar[3] == '20') { // level code
1330 $loopid = '2000A'; // info source (payer)
1331 } elseif ($sar[3] == '21') {
1332 $loopid = '2000B'; // info receiver (clinic)
1333 } elseif ($sar[3] == '22') {
1334 $loopid = '2000C'; // subscriber
1335 } elseif ($sar[3] == '23') {
1336 $loopid = '2000D'; // dependent
1337 } else {
1338 //debug
1339 csv_edihist_log('HL has no level ' . $seg . ' in ' . $fn);
1342 continue;
1346 if (strncmp($seg, 'NM1' . $de, 4) === 0) {
1347 $sar = explode($de, $seg);
1348 $nm1 = $sar[3];
1349 $nm1 = ($sar[4]) ? $nm1 . ', ' . $sar[4] : $nm1;
1350 $nm1 = ($sar[5]) ? $nm1 . ' ' . $sar[5] : $nm1;
1351 if ($loopid == '2000A') {
1352 $ret_ar[$icn]['claim'][$cdx]['Payer'] = $nm1; //
1353 $payer_name = $nm1;
1354 } elseif ($loopid == '2000C' || $loopid == '2000D') {
1355 $ret_ar[$icn]['claim'][$cdx]['PtName'] = $nm1; //$ptname = $nm1;
1358 continue;
1361 // for 271 eligibility response (invalid data in 270 request)
1362 if (strncmp($seg, 'AAA' . $de, 4) === 0) {
1363 $sar = explode($de, $seg);
1364 $status = 'R';
1365 $rej_ct++;
1366 $aaa_code = $sar[3];
1367 $rsp_code = $sar[4];
1368 if ($loopid == '2000A') {
1369 $status = $status . ' Src ' . $aaa_code;
1370 } elseif ($loopid == '2000B') {
1371 $status = $status . ' Rcv ' . $aaa_code;
1372 } elseif ($loopid == '2000C') {
1373 $status = $status . ' Sbr ' . $aaa_code;
1374 } elseif ($loopid == '2000D') {
1375 $status = $status . ' Dep ' . $aaa_code;
1379 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
1381 continue;
1385 // for 270 eligibility request
1386 if (strncmp($seg, 'EQ' . $de, 3) === 0) {
1387 if (strlen((string)$sar[1])) {
1388 $bnfteq .= ($bnfteq) ? '|' . $sar[1] : $sar[1];
1389 } elseif (strlen((string)$sar[2])) {
1390 $bnfteq .= ($bnfteq) ? '|' . $sar[2] : $sar[2];
1391 } else {
1392 csv_edihist_log('Invalid EQ segment, missing benefit type in ' . $fn);
1393 continue;
1396 $ret_ar[$icn]['claim'][$cdx]['InsBnft'] = $bnfteq;
1397 continue;
1400 // overridden by REF*EJ* (not)
1401 if (strncmp($seg, 'TRN' . $de, 4) === 0) {
1402 if ($loopid = '2000C' || $loopid == '2000D') {
1403 $sar = explode($de, $seg);
1404 $ret_ar[$icn]['claim'][$cdx]['Trace'] = $sar[2]; //$ptacct = $sar[2];
1408 continue;
1411 // for 271 eligibility response
1412 if (strncmp($seg, 'EB' . $de, 3) === 0) {
1413 $status = ( isset($status) ) ? $status : '';
1415 if (strpos($ret_ar[$icn]['claim'][$cdx]['Status'], 'tive')) {
1416 continue;
1420 $sar = explode($de, $seg);
1422 if (isset($sar[2])) {
1423 if ($sar[2] == '6' || $sar[2] == '7' || $sar[2] == '8') {
1424 $status = 'Inactive';
1425 } elseif ($sar[2] == 'I') {
1426 $status = 'Non-Covered';
1427 $rej_ct++;
1428 } elseif ($sar[2] == 'E') {
1429 $status = 'Exclusions';
1430 $rej_ct++;
1431 } elseif ($sar[2] == 'N') {
1432 $status = 'Restricted';
1433 $rej_ct++;
1434 } elseif ($sar[2] == 'V') {
1435 $status = 'Unknown';
1436 $rej_ct++;
1437 } elseif ($sar[2] == 'T') {
1438 $status = 'Card Lost';
1439 $rej_ct++;
1440 } elseif ($sar[2] == 'U') {
1441 $status = 'Contact';
1442 $rej_ct++;
1443 } elseif ($sar[2] == '1') {
1444 $status = 'Active';
1445 } elseif ($sar[2] == '2' || $sar[2] == '3' || $sar[2] == '4') {
1446 $status = 'Active Cap';
1451 $ret_ar[$icn]['claim'][$cdx]['Status'] = $status;
1453 continue;
1457 if (strncmp($seg, 'DTP' . $de, 4) === 0) {
1458 $sar = explode($de, $seg);
1459 $dtp03 = (isset($sar[2]) && $sar[2] == 'D8') ? $sar[3] : substr($sar[3], 0, 8);
1460 if ($isrsp) {
1461 if ($loopid == '2100C' || $loopid == '2110C') {
1462 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $dtp03;
1463 } elseif ($loopid == '2100D' || $loopid == '2110D') {
1464 $ret_ar[$icn]['claim'][$cdx]['RspDate'] = $dtp03;
1466 } else {
1467 if ($loopid == '2100C' || $loopid == '2110C') {
1468 $ret_ar[$icn]['claim'][$cdx]['ReqDate'] = $dtp03;
1469 } elseif ($loopid == '2100D' || $loopid == '2110D') {
1470 $ret_ar[$icn]['claim'][$cdx]['ReqDate'] = $dtp03;
1475 continue;
1480 if (strncmp($seg, 'REF'.$de.'EJ'.$de, 7) === 0 ) {
1481 // patient account -- replaces or replaced by TRN02
1482 $sar = explode($de, $seg);
1483 $ret_ar[$icn]['claim'][$cdx]['PtAcct'] = $sar[2]; //$ptacct = $sar[2];
1485 continue;
1489 } // end foreach($stsegs as $seg)
1491 } // endforeach($env_ar['ST'] as $st
1492 // file: 'f271': array('Date', 'FileName', 'Control', 'Claim_ct', 'Reject', 'Payer')
1493 $fdx = count($ret_ar[$icn]['file']);
1494 //'f270': $hdr = array('Date', 'FileName', 'Control', 'Claim_ct', 'x12Partner');
1495 $ret_ar[$icn]['file'][$fdx]['Date'] = $gsdate;
1496 $ret_ar[$icn]['file'][$fdx]['FileName'] = $fn;
1497 // for 270 type, could use GSO6 if it were unique
1498 $ret_ar[$icn]['file'][$fdx]['Control'] = $icn;
1499 $ret_ar[$icn]['file'][$fdx]['Claim_ct'] = $cdx;
1500 if ($isrsp || $ft == 'f271') {
1501 $ret_ar[$icn]['file'][$fdx]['Reject'] = $rej_ct;
1502 $ret_ar[$icn]['file'][$fdx]['Payer'] = $payer_name;
1503 } else {
1504 $ret_ar[$icn]['file'][$fdx]['x12Partner'] = $x12ptnr;
1508 } // endforeach($env_ar['ISA'] as $icn=>$isa)
1510 return $ret_ar;
1514 * this function opens the x12 file in the object and routes
1515 * the object to the parsing function according to the x12 type
1516 * csvdata array design:
1517 * [$icn]['claims'][i] [$icn]['files'][i] [$icn]['type']
1519 * @uses edih_835_csv_data()
1520 * @uses edih_837_csv_data()
1521 * @uses edih_277_csv_data()
1522 * @uses edih_271_csv_data()
1523 * @uses edih_278_csv_data()
1524 * @uses edih_997_csv_data()
1526 * @param string path to file
1527 * @return array data for csv table records
1529 function edih_parse_select($file_path)
1531 $csvdata = array();
1532 // csvdata array design:
1533 // $csvdata[$icn]['claims'][i] [$icn]['files'][i] [$icn]['type']
1535 $x12_obj = csv_check_x12_obj($file_path);
1536 //$x12_obj = new edih_x12_file($file_path);
1537 if ($x12_obj instanceof edih_x12_file) {
1538 $ft = $x12_obj->edih_type();
1539 } else {
1540 csv_edihist_log('edih_parse_select: error in file path');
1541 return $csvdata;
1544 //'HB'=>'271', 'HS'=>'270', 'HR'=>'276', 'HI'=>'278',
1545 //'HN'=>'277', 'HP'=>'835', 'FA'=>'999', 'HC'=>'837'
1547 if ($ft == 'HP') {
1548 $csvdata = edih_835_csv_data($x12_obj);
1549 } elseif ($ft == 'HC') {
1550 $csvdata = edih_837_csv_data($x12_obj);
1551 } elseif ($ft == 'HN' || $ft == 'HR') {
1552 $csvdata = edih_277_csv_data($x12_obj);
1553 } elseif ($ft == 'FA') {
1554 $csvdata = edih_997_csv_data($x12_obj);
1555 } elseif ($ft == 'HB' || $ft == 'HS') {
1556 $csvdata = edih_271_csv_data($x12_obj);
1557 } elseif ($ft == 'HI') {
1558 $csvdata = edih_278_csv_data($x12_obj);
1559 } else {
1560 // debug
1561 csv_edihist_log('edih_parse_select(): unsupported file type ' . $ft . ' name: ' . basename($file_path));
1565 return $csvdata;