preparing for 5.0.1 release in several weeks (#1509)
[openemr.git] / library / edihistory / edih_segments.php
blobed2036dbf968920953de7e8fc287d60d1668dae6
1 <?php
2 /*
3 * edih_segments.php
4 *
5 * Copyright 2016 Kevin McCormick <kevin@kt61p>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
22 * @author Kevin McCormick
23 * @link: http://www.open-emr.org
24 * @package OpenEMR
25 * @subpackage ediHistory
29 /**
30 * increment loop values ($lpval is a reference)
32 * @param $lptest the prospective loop value
33 * @param &$lpval the present loop value -- reassigned here
34 * @return integer value from strcmp()
36 function edih_change_loop($lptest, &$lpval)
38 // strcmp($str1,$str2) Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.
39 if (strcmp($lptest, $lpval) > 0) {
40 //echo "$lptest greater than $lpval" .PHP_EOL;
41 $lpval = $lptest;
44 return strcmp($lptest, $lpval);
47 /**
48 * format segments for display of x12 edi files
50 * @param array $segments
51 * @param string $delimiter
52 * return string
54 function edih_segments_text($segments, $delimiter)
57 $str_html = '';
59 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
60 // debug
61 csv_edihist_log('edih_generic_text: invalid argument');
62 $str_html = "Invalid arguments for view of x12 file text<br>";
63 return $str_html;
67 $de = $delimiter;
68 $loopid = " -- ";
69 $idx = 0;
71 foreach ($segments as $key => $seg) {
72 $idx++;
74 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
78 return $str_html;
81 /**
82 * identify loops and format segments for display
83 * of 837 (professional claim) type x12 edi files
85 * @param array $segments
86 * @param string $delimiter
87 * return string
89 function edih_837_text($segments, $delimiter, $err_seg = '')
92 $str_html = '';
93 $err_ar = array();
95 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
96 // debug
97 csv_edihist_log('edih_837_text: invalid argument');
98 $str_html .= "Invalid arguments for view of x12 file text<br>";
99 return $str_html;
102 // to highlight identified errors listed in 999/997 ack
103 if ($err_seg) {
104 $er = edih_errseg_parse($err_seg);
105 $erstn = (isset($er['trace'])) ? substr($er['trace'], -4) : '';
106 $erseg = (isset($er['err'])) ? $er['err'] : array();
107 } else {
108 $erstn = '';
109 $erseg = array();
113 $de = $delimiter;
114 $loopid = "0";
115 $idx = 0;
116 $stkey = 0;
117 $segnum = 0;
118 $stsegct = 0;
119 $bterr = 'btseg';
121 foreach ($segments as $key => $seg) {
122 $idx++;
123 $title = '';
124 $stsegct++;
125 $bterr = 'btseg';
127 if ($erstn && ($erstn == $stn)) {
128 $bterr = (in_array($stsegct, $erseg)) ? 'bterr' : 'btseg';
132 if (strncmp('ST'.$de, $seg, 3) === 0) {
133 $loopid = 'Header';
134 $stkey = (int)$key;
135 $stsegct = 1;
136 $stn = explode($de, $seg)[2];
137 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
138 continue;
142 if (strncmp('BHT'.$de, $seg, 4) === 0) {
143 $loopid = 'Begin';
144 $stsegct = 2;
145 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
146 continue;
150 if (strncmp('HL'.$de, $seg, 3) === 0) {
151 $sar = explode($de, $seg);
152 if ($sar[3] == '20') { // level code
153 $loopid = '2000A'; // billing provider (clinic)
154 } elseif ($sar[3] == '22') {
155 $loopid = '2000B'; // subscriber
156 } elseif ($sar[3] == '23' || $sar[3] == 'PT') {
157 $loopid = '2000C'; // dependent
158 $has_eb = false;
159 } else {
160 //debug
161 csv_edihist_log('edih_837_text: HL has no level '.$seg);
165 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
166 continue;
170 if (strncmp('CLM'.$de, $seg, 4) === 0) {
171 $loopid = '2300';
172 $title = 'Claim';
173 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
174 $title = '';
175 continue;
179 if (strncmp('SBR'.$de, $seg, 4) === 0) {
180 if ($loopid == '2000B') {
181 $title = 'Subscriber';
182 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
183 } else {
184 $title = 'Other Subscriber';
185 $loopid = '2320';
186 $str_html .= "<tr><td class='btloop' title='$title'> -- </td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
189 $title = '';
190 continue;
194 if (strncmp('LX'.$de, $seg, 3) === 0) {
195 $loopid = '2400';
196 $title = 'Svc Line Number';
197 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
198 $title = '';
199 continue;
203 if (strncmp('LIN'.$de, $seg, 4) === 0) {
204 $loopid = '2410';
205 $title = 'Drug ID';
206 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
207 $title = '';
208 continue;
212 if (strncmp('SVD'.$de, $seg, 4) === 0) {
213 $loopid = '2430';
214 $title = 'Line Adjudication';
215 $str_html .= "<tr></tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
216 $title = '';
217 continue;
221 if (strncmp('NM1'.$de, $seg, 4) === 0) {
222 $sar = explode($de, $seg);
223 $nm101 = ( isset($sar[1]) ) ? $sar[1] : '';
224 if ($loopid == 'Begin' || strcmp(substr($loopid, 0, 4), '2320') < 0) {
225 if ($nm101 == '41') {
226 $loopid = '1000A';
227 $title = 'Submitter';
228 } elseif ($nm101 == '40') {
229 $loopid = '1000B';
230 $title = 'Receiver';
231 } elseif ($nm101 == '85') {
232 $loopid = '2010AA';
233 $title = 'Billing';
234 } elseif ($nm101 == '87') {
235 $loopid = '2010AB';
236 $title = 'Pay to';
237 } elseif ($nm101 == 'PE') {
238 $loopid = '2010AC';
239 $title = 'Pay to Plan';
240 } elseif ($nm101 == 'IL') {
241 $loopid = '2010BA';
242 $title = 'Subscriber';
243 } elseif ($nm101 == 'PR') {
244 $loopid = '2010BB';
245 $title = 'Payer';
246 } elseif ($nm101 == 'QC') {
247 $loopid = '2010CA';
248 $title = 'Patient';
249 } elseif ($nm101 == 'DN') {
250 $loopid = '2310A';
251 $title = 'Referring Provider';
252 } elseif ($nm101 == 'P3') {
253 $loopid = '2310A';
254 $title = 'Primary Care Provider';
255 } elseif ($nm101 == '82') {
256 $loopid = '2310B';
257 $title = 'Rendering Provider';
258 } elseif ($nm101 == '77') {
259 $loopid = '2310C';
260 $title = 'Service Facility';
261 } elseif ($nm101 == 'DQ') {
262 $loopid = '2310D';
263 $title = 'Supervising Provider';
264 } elseif ($nm101 == 'PW') {
265 $loopid = '2310E';
266 $title = 'Ambulance pickup';
267 } elseif ($nm101 == '45') {
268 $loopid = '2310F';
269 $title = 'Ambulance dropoff';
271 } elseif (strcmp(substr($loopid, 0, 4), '2400') < 0) {
272 if ($nm101 == 'IL') {
273 $loopid = '2330A';
274 $title = 'Other Subscriber';
275 } elseif ($nm101 == 'PR') {
276 $loopid = '2330B';
277 $title = 'Other Payer';
278 } elseif ($nm101 == 'PR') {
279 $loopid = '2330C';
280 $title = 'Other Referring Provider';
281 } elseif ($nm101 == '82') {
282 $loopid = '2330D';
283 $title = 'Other Rendering Provider';
284 } elseif ($nm101 == '77') {
285 $loopid = '2330E';
286 $title = 'Other Svc Facility';
287 } elseif ($nm101 == 'DQ') {
288 $loopid = '2330F';
289 $title = 'Other Supervising Provider';
290 } elseif ($nm101 == '85') {
291 $loopid = '2330G';
292 $title = 'Other Billing Provider';
294 } else {
295 if ($nm101 == '82') {
296 $loopid = '2420A';
297 $title = 'Rendering Provider';
298 } elseif ($nm101 == 'QB') {
299 $loopid = '2420B';
300 $title = 'Purchased Svc Provider';
301 } elseif ($nm101 == '77') {
302 $loopid = '2420C';
303 $title = 'Service Facility';
304 } elseif ($nm101 == 'DQ') {
305 $loopid = '2420D';
306 $title = 'Supervising Provider';
307 } elseif ($nm101 == 'DK') {
308 $loopid = '2420E';
309 $title = 'Ordering Provider';
310 } elseif ($nm101 == 'DN') {
311 $loopid = '2420F';
312 $title = 'Referring Provider';
313 } elseif ($nm101 == 'P3') {
314 $loopid = '2420F';
315 $title = 'Primary Care Provider';
316 } elseif ($nm101 == 'PW') {
317 $loopid = '2420G';
318 $title = 'Ambulance pickup';
319 } elseif ($nm101 == '45') {
320 $loopid = '2420H';
321 $title = 'Ambulance dropoff';
326 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
327 $title='';
328 continue;
332 if (strncmp('SE'.$de, $seg, 3) === 0) {
333 $loopid = 'Trailer';
334 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
335 $title = '';
336 continue;
339 // for all the segments that do not begin loops
340 $str_html .= "<tr><td class='btloop' title='$title'> -- </td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
345 return $str_html;
349 * identify loops and format segments for display
350 * of 270/271 (eligibility) type x12 edi files
352 * @param array $segments
353 * @param string $delimiter
354 * return string
356 function edih_271_text($segments, $delimiter, $err_seg = '')
359 $str_html = '';
361 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
362 // debug
363 csv_edihist_log('edih_271_text: invalid argument');
364 $str_html .= "Invalid arguments for view of x12 file text<br>";
365 return $str_html;
369 $de = $delimiter;
370 $prevseg = '';
371 $loopid = "0";
372 $lx_ct = 0;
373 $hasst = false;
374 $idx = 0;
375 $stsegct = 0;
377 // to highlight identified errors listed in 999/997 ack (for 270)
378 if ($err_seg) {
379 $er = edih_errseg_parse($err_seg);
380 $erstn = (isset($er['trace'])) ? substr($er['trace'], -4) : '';
381 $erseg = (isset($er['err'])) ? $er['err'] : array();
382 } else {
383 $erstn = '';
384 $erseg = array();
388 if ($err_seg) {
389 $er = edih_errseg_parse($err_seg);
390 if (is_array($er) && count($er)) {
391 $err_ar = $er;
396 foreach ($segments as $key => $seg) {
397 $sar = array();
398 $idx++;
399 $stsegct++;
400 $bterr = 'btseg';
402 if ($erstn && ($erstn == $stn)) {
403 $bterr = (in_array($stsegct, $erseg)) ? 'bterr' : 'btseg';
407 if (strncmp('ST'.$de, $seg, 3) === 0) {
408 $sar = explode($de, $seg);
409 $loopid = 'Header';
410 $hasst = true;
411 $stsegct = 1;
412 $sttp = (isset($seg[1])) ? $seg[1] : '';
413 $stn = (isset($seg[2])) ? $seg[2] : '';
414 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
415 continue;
419 if (strncmp('BHT'.$de, $seg, 4) === 0) {
420 $loopid = 'Begin';
421 // 2nd seg in transaction, ST may not be included if segments are transaction slice
422 if ($stsegct < 2) {
423 $stsegct = 2;
426 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
427 continue;
431 if (strncmp('HL'.$de, $seg, 3) === 0) {
432 $sar = explode($de, $seg);
433 if ($sar[3] == '20') { // level code
434 $loopid = '2000A'; // info source (payer)
435 } elseif ($sar[3] == '21') {
436 $loopid = '2000B'; // info receiver (clinic)
437 } elseif ($sar[3] == '22') {
438 $loopid = '2000C'; // subscriber
439 $has_eb = false;
440 } elseif ($sar[3] == '23') {
441 $loopid = '2000D'; // dependent
442 $has_eb = false;
443 } else {
444 //debug
445 csv_edihist_log('edih_271_text: HL has no level '.$seg);
449 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
450 $prevseg = 'HL'.$de;
451 continue;
455 if (strncmp('NM1'.$de, $seg, 4) === 0) {
456 if (strncmp('NM1'.$de, $prevseg, 4) === 0) {
457 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
458 continue;
461 switch ((string)$loopid) {
462 case '2000A':
463 $loopid = '2100A';
464 break; // edih_change_loop($lptest, &$lpval)
465 case '2000B':
466 $loopid = '2100B';
467 break;
468 case '2000C':
469 $loopid = '2100C';
470 break;
471 case '2000D':
472 $loopid = '2100D';
473 break;
474 default:
475 $loopid = $loopid;
478 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
479 $prevseg = 'NM1'.$de;
480 continue;
484 if (strncmp('EB'.$de, $seg, 3) === 0 || strncmp('EQ'.$de, $seg, 3) === 0) {
485 // EB* segment is in 271 type, EQ* is corresponding segment in 270 type
486 if (strncmp($seg, $prevseg, 3) === 0) {
487 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
488 $prevseg = substr($seg, 0, 3);
489 continue;
492 if ($loopid = '2100C' || $loopid = '2115C' || $loopid = '2120C') {
493 $loopid = '2110C';
494 } elseif ($loopid = '2100D' || $loopid = '2115D' || $loopid = '2120D') {
495 $loopid = '2110D';
498 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
499 $prevseg = substr($seg, 0, 3);
500 $has_eb = (strncmp('EB'.$de, $seg, 3) === 0);
501 $has_iii = false;
502 continue;
506 if (strncmp('III'.$de, $seg, 4) === 0 && $has_eb) {
507 // the III segment begins a loop in 271 type, but not in 270
508 if ($loopid = '2110C') {
509 $loopid = '2115C';
512 if ($loopid = '2100D') {
513 $loopid = '2115D';
516 if ($has_iii) {
517 $str_html .= "<tr><td class='btloop'></td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
518 } else {
519 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
520 $has_iii = true;
523 $prevseg = substr($seg, 0, 4);
524 continue;
528 if (strncmp('LS'.$de, $seg, 3) === 0) {
529 if ($loopid = '2110C' || $loopid = '2115C') {
530 $loopid = '2120C';
531 } elseif ($loopid = '2110D' || $loopid = '2115D') {
532 $loopid = '2120D';
535 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
536 continue;
540 if (strncmp('SE'.$de, $seg, 3) === 0) {
541 $str_html .= "<tr><td class='btloop'>Trailer</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
542 $loopid = '0';
543 continue;
546 // for all the segments that do not begin loops
547 $prevseg = substr($seg, 0, strpos($seg, $de)+1);
548 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
553 return $str_html;
557 function edih_835_text($segments, $delimiter, $err_seg = '')
560 $str_html = '';
561 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
562 //debug
563 csv_edihist_log('edih_835_text: invalid segments');
564 $str_html .= "Invalid arguments for view of x12 file text<br>";
565 return $str_html;
569 $de = $delimiter;
570 $prevseg = '';
571 $loopid = "0";
572 $lx_ct = 0;
573 $idx = 0;
575 foreach ($segments as $key => $seg) {
576 //$idx++;
578 if (strncmp('ST'.$de, $seg, 3) === 0) {
579 $loopid = 'Header';
580 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
581 continue;
585 if (strncmp('N1'.$de, $seg, 3) === 0) {
586 $sar = explode($de, $seg);
587 if ($sar[1] == 'PR') {
588 $loopid = '1000A';
589 } elseif ($sar[1] == 'PE') {
590 $loopid = '1000B';
593 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
594 $prevseg = 'N1'.$de;
595 continue;
599 if (strncmp('LX'.$de, $seg, 3) === 0) {
600 $loopid = '2000';
601 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
602 $prevseg = 'LX'.$de;
603 continue;
607 if (strncmp('TS3'.$de, $seg, 4) === 0) {
608 if ($loopid == '2000') {
609 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
610 } else {
611 $loopid = '2000';
612 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
615 $prevseg = 'TS3'.$de;
616 continue;
620 if (strncmp('CLP'.$de, $seg, 4) === 0) {
621 $loopid = '2100';
622 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
623 $prevseg = 'CLP'.$de;
624 continue;
628 if (strncmp('SVC'.$de, $seg, 4) === 0) {
629 $loopid = '2110';
630 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
631 $prevseg = 'SVC'.$de;
632 continue;
636 if (strncmp('PLB'.$de, $seg, 4) === 0) {
637 $loopid = 'Adjust';
638 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
639 $prevseg = 'PLB'.$de;
640 continue;
644 if (strncmp('SE'.$de, $seg, 3) === 0) {
645 $loopid = 'Trailer';
646 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
647 $prevseg = 'SE'.$de;
648 continue;
651 // for all the segments that do not begin loops
652 $prevseg = substr($seg, 0, 3);
653 $prevseg .= $de;
654 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
659 return $str_html;
664 * identify loops and format segments for display
665 * of 277 (claim status) type x12 edi files
667 * @param array $segments
668 * @param string $delimiter
669 * return string
671 function edih_277_text($segments, $delimiter, $stpos = '')
674 $str_html = '';
675 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
676 //debug
677 csv_edihist_log('edih_277_text: invlid segments');
678 $str_html .= "Invalid arguments for view of x12 file text<br>";
679 return $str_html;
683 // to highlight identified errors listed in 999/997 ack (for 276)
684 //if ($err_seg) {
685 //$er = edih_errseg_parse($err_seg);
686 //$erstn = (isset($er['trace'])) ? substr($er['trace'], -4) : '';
687 //$erseg = (isset($er['err'])) ? $er['err'] : array();
688 //} else {
689 //$erstn = '';
690 //$erseg = array();
693 $de = $delimiter;
694 $prevseg = '';
695 $loopid = "0";
696 $lx_ct = 0;
697 $stsegct = 0;
698 //$idx = 0;
700 foreach ($segments as $idx => $seg) {
701 //$idx++;
702 $stsegct++;
703 $key = ($stpos) ? $idx - $stpos : $idx;
704 // if 276 transactions are parsed, 999 errors may be present
705 //if ($erstn && ($erstn == $stn)) {
706 //$bterr = (in_array($stsegct, $erseg)) ? 'bterr' : 'btseg';
709 if (strncmp('ST'.$de, $seg, 3) === 0) {
710 $loopid = 'Header';
711 $stsegct = 1;
712 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
713 continue;
717 if (strncmp('BHT'.$de, $seg, 4) === 0) {
718 $loopid = 'Begin';
719 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
720 continue;
724 if (strncmp('HL'.$de, $seg, 3) === 0) {
725 $sar = explode($de, $seg);
726 if ($sar[3] == '20') { // level code
727 $loopid = '2000A'; // info source (payer)
728 } elseif ($sar[3] == '21') {
729 $loopid = '2000B'; // info receiver (clinic)
730 } elseif ($sar[3] == '19') {
731 $loopid = '2000C'; // provider
732 } elseif ($sar[3] == '22' || $sar[3] == 'PT') {
733 $loopid = '2000D'; // subscriber
734 } elseif ($sar[3] == '23') {
735 $loopid = '2000E'; // dependent
736 } else {
737 //debug
738 csv_edihist_log('edih_277_text: HL has no level '.$seg);
742 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
743 $prevseg = 'HL'.$de;
744 continue;
749 if (strncmp('NM1'.$de, $seg, 4) === 0) {
750 if (strncmp('NM1'.$de, $prevseg, 4) === 0) {
751 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
752 continue;
755 switch ((string)$loopid) {
756 case '2000A':
757 $loopid = '2100A';
758 break; // edih_change_loop($lptest, &$lpval)
759 case '2000B':
760 $loopid = '2100B';
761 break;
762 case '2000C':
763 $loopid = '2100C';
764 break;
765 case '2000D':
766 $loopid = '2100D';
767 break;
768 case '2000E':
769 $loopid = '2100E';
770 break;
773 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
774 $prevseg = 'NM1';
775 continue;
779 if (strncmp('TRN'.$de, $seg, 4) === 0) {
780 if (strncmp('TRN'.$de, $prevseg, 4) === 0) {
781 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
782 continue;
785 switch ((string)$loopid) {
786 case '2100A':
787 $loopid = '2200A';
788 break;
789 case '2100B':
790 $loopid = '2200B';
791 break;
792 case '2100C':
793 $loopid = '2200C';
794 break;
795 case '2100D':
796 $loopid = '2200D';
797 break;
798 case '2100E':
799 $loopid = '2200E';
800 break;
803 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
804 $prevseg = 'TRN';
805 continue;
809 if (strncmp('SVC'.$de, $seg, 4) === 0) {
810 if (strncmp('SVC'.$de, $prevseg, 4) === 0) {
811 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
812 continue;
815 switch ((string)$loopid) {
816 case '2200D':
817 $loopid = '2220D';
818 break;
819 case '2200E':
820 $loopid = '2220E';
821 break;
824 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
825 $prevseg = 'SVC';
826 continue;
830 if (strncmp('SE'.$de, $seg, 3) === 0) {
831 $loopid = 'Trailer';
832 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
833 $prevseg = 'SE';
834 continue;
837 // for all the segments that do not begin loops
838 $prevseg = substr($seg, 0, 3);
839 $prevseg .= $de;
840 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
844 return $str_html;
848 * identify loops and format segments for display
849 * of 278 (authorization) type x12 edi files
851 * @param array $segments
852 * @param string $delimiter
853 * return string
855 function edih_278_text($segments, $delimiter, $err_seg = '')
858 $str_html = '';
860 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
861 // debug
862 csv_edihist_log('edih_278_text(): invalid argument');
863 $str_html .= "Invalid arguments for view of x12 file text<br>";
864 return $str_html;
868 $de = $delimiter;
869 $prevseg = '';
870 $loopid = "0";
871 $lx_ct = 0;
872 $hasst = false;
873 $err_ar = array();
874 $idx = 0;
875 $stsegct =0;
877 // to highlight identified errors listed in 999/997 ack
878 if ($err_seg) {
879 $er = edih_errseg_parse($err_seg);
880 $erstn = (isset($er['trace'])) ? substr($er['trace'], -4) : '';
881 $erseg = (isset($er['err'])) ? $er['err'] : array();
882 } else {
883 $erstn = '';
884 $erseg = array();
888 foreach ($segments as $key => $seg) {
889 $idx++;
890 $stsegct++;
891 $title = '';
892 $bterr = 'btseg';
894 if ($erstn && ($erstn == $stn)) {
895 $bterr = (in_array($stsegct, $erseg)) ? 'bterr' : 'btseg';
899 if (strncmp('ST'.$de, $seg, 3) === 0) {
900 $loopid = 'Header';
901 $hasst = true;
902 $stsegct = 1;
903 $stn = explode($de, $seg)[2];
904 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
905 continue;
909 if (strncmp('BHT'.$de, $seg, 4) === 0) {
910 $loopid = 'Begin';
911 // 2nd seg in transaction, ST may not be included if segments are transaction slice
912 if ($stsegct < 2) {
913 $stsegct = 2;
916 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
917 continue;
921 if (strncmp($seg, 'HL'.$de, 3) === 0) {
922 $sar = explode($de, $seg);
923 $hl = $sar[1];
924 $hlpc = $sar[2]; // parent code
925 $hllc = $sar[3];
926 $hlcc = (isset($sar[4])) ? $sar[4] : ''; // child code
927 if ($sar[3] == '20') { // level code
928 $loopid = '2000A'; // info source (payer)
929 $title = 'Info Source';
930 } elseif ($sar[3] == '21') {
931 $loopid = '2000B'; // info receiver (clinic)
932 $title = 'Info Receiver';
933 } elseif ($sar[3] == '22') {
934 $loopid = '2000C'; // subscriber
935 $title = 'Subscriber';
936 } elseif ($sar[3] == '23') {
937 $loopid = '2000D'; // dependent
938 $title = 'Dependent';
939 } elseif ($sar[3] == 'EV') {
940 $loopid = '2000E'; // patient event
941 $title = 'Patient Event';
942 } elseif ($sar[3] == 'SS') {
943 $loopid = '2000F'; // service
944 $title = 'Service';
945 } else {
946 //debug
947 csv_edihist_log('edih_278_text: HL has no level '.$seg);
951 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
952 $prevseg = 'HL';
953 continue;
957 if (strncmp($seg, 'NM1'.$de, 4) === 0) {
958 $sar = explode($de, $seg);
959 $nm101 = $sar[1];
960 if ($loopid == '2000A') {
961 $loopid == '2010A'; // Source
962 } elseif ($loopid == '2000B') {
963 $loopid = '2010B'; // Receiver
964 } elseif ($loopid == '2000C') {
965 $loopid = '2010C'; // Subscriber
966 } elseif ($loopid == '2000D') {
967 $loopid = '2010D'; // Dependent
968 } elseif ($loopid == '2000E' || strpos($loopid, '010E')) { // Patient Event
969 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010EA' : $loopid;
970 $loopid = (strpos('|45|FS|ND|PW|R3', $nm101) ) ? '2010EB' : $loopid;
971 $loopid = ($nm101 == 'L5') ? '2010EC' : $loopid;
972 } elseif ($loopid == '2000F' || strpos($loopid, '010F')) { // Service
973 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010FA' : $loopid;
977 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
978 $prevseg = 'NM1';
979 continue;
983 if (strncmp('SE'.$de, $seg, 3) === 0) {
984 $str_html .= "<tr><td class='btloop'>Trailer</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
985 $loopid = '0';
986 $prevseg = 'SE';
987 continue;
990 // for all the segments that do not begin loops
991 $prevseg = substr($seg, 0, strpos($seg, $de));
992 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
997 return $str_html;
1001 * identify loops and format segments for display
1002 * of 997/999 (acknowledgement) type x12 edi files
1004 * @param array $segments
1005 * @param string $delimiter
1006 * return string
1008 function edih_997_text($segments, $delimiter)
1011 $str_html = '';
1012 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
1013 //debug
1014 csv_edihist_log('edih_997_text(): invalid segments');
1015 return $str_html;
1019 $de = $delimiter;
1020 $loopid = "0";
1022 //echo 'edih_997_text() foreach segment count: '.count($segments).PHP_EOL;
1024 foreach ($segments as $key => $seg) {
1026 //echo var_dump($seg).PHP_EOL;
1028 if (strncmp('TA1'.$de, $seg, 4) === 0) {
1029 $sar = explode($de, $seg);
1030 $rspicn = $sar[1];
1031 $loopid = 'ACK'; // not official
1032 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
1033 unset($sar);
1034 $loopid = ''; // reset loop for subsequent segments
1035 continue;
1039 if (strncmp('ST'.$de, $seg, 3) === 0) {
1040 $loopid = 'Header';
1041 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
1042 continue;
1046 if (strncmp('AK1'.$de, $seg, 4) === 0) {
1047 $sar = explode($de, $seg);
1048 $rsptp = csv_file_type($sar[1]);
1049 if ($rspicn && $rsptp) {
1050 $rspfile = csv_file_by_controlnum($rsptp, $rspicn);
1053 $title = ($rspfile) ? 'response to '.$rspfile : '';
1054 $loopid = '2000';
1055 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td title='$title' class='btseg'>$seg</td></tr>" .PHP_EOL;
1056 unset($sar);
1057 continue;
1061 if (strncmp('AK2'.$de, $seg, 4) === 0) {
1062 $loopid = 'AK2';
1063 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
1064 continue;
1068 if (strncmp('IK3'.$de, $seg, 4) === 0 || strncmp('AK3'.$de, $seg, 4) === 0) {
1069 $loopid = '2100';
1070 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
1071 continue;
1075 if (strncmp('IK4'.$de, $seg, 4) === 0 || strncmp('AK4'.$de, $seg, 4) === 0) {
1076 $loopid = '2110';
1077 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
1078 continue;
1082 if (strncmp('SE'.$de, $seg, 3) === 0) {
1083 $loopid = 'Trailer';
1084 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
1085 continue;
1088 // for all the segments that do not begin loops ;
1089 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
1093 return $str_html;
1097 * Display of x12 edi transaction listing or all segments in the files.
1098 * When using $err_info, you must use the filepath of the submitted file
1100 * @param string $filepath path to desired file
1101 * @param string $filetype used when filepath is just filename
1102 * @param string optional $claimid CLM01, or BHT03 to identify a transaction or a trace value
1103 * @param bool false: $claimid is pt transaction, true: $claimid is trace from 835 or 999
1104 * @param string optional $err_info the prepared error info from a 997/999 response
1105 * @return string html for display of file segments
1107 function edih_display_text($filepath, $filetype = '', $claimid = '', $trace = false, $err_info = '')
1110 $str_html = '';
1111 $de = '';
1112 $segments = '';
1113 $stsegkey = '';
1114 $ft = ($filetype) ? $filetype : '';
1115 $errs = ( strlen($err_info) ) ? $err_info : '';
1116 $bht03 = '';
1118 // verify x12 file
1119 $x12obj = csv_check_x12_obj($filepath, $ft);
1121 if ($x12obj && 'edih_x12_file' == get_class($x12obj)) {
1122 $ftype = $x12obj->edih_type();
1123 $ft = csv_file_type($ftype);
1124 $delims = $x12obj->edih_delimiters();
1125 $de = $delims['e'];
1126 $fn = $x12obj->edih_filename();
1127 $segs_ar = $x12obj->edih_segments();
1128 $env_ar = $x12obj->edih_envelopes();
1129 if (!$de || strlen($de) != 1) {
1130 // error in object
1131 // debug
1132 $str_html = 'edih_display_text(): error in delimiters<br />'.PHP_EOL;
1133 $str_html .= $x12obj->edih_message().PHP_EOL;
1134 return $str_html;
1137 if (!is_array($segs_ar) || !count($segs_ar)) {
1138 // unknown error
1139 $str_html = "<p>unknown error retrieving segments for $fn</p>".PHP_EOL;
1140 $str_html .= $x12obj->edih_message().PHP_EOL;
1141 return $str_html;
1143 } else {
1144 //debug
1145 csv_edihist_log('edih_transaction_text(): invalid path '.$filepath);
1146 $str_html = 'edih_display_text(): error accessing file<br />'.PHP_EOL;
1147 return $str_html;
1151 if ($claimid) {
1152 // claimid can be for transaction, payment, or error response
1153 if ($trace && array_key_exists($claimid, $env_ar['ISA'])) {
1154 $arg_ar = array('ISA13'=>$claimid, 'keys'=>true);
1155 $segments = $x12obj->edih_x12_slice($arg_ar);
1156 } else {
1157 // claimid alone can be clm01 or bht03, if trace=true, expect trn02 for claimid
1158 foreach ($env_ar['ST'] as $st) {
1159 if ($trace && $claimid == $st['trace']) {
1160 $arg_ar = array('ISA13'=>$st['icn'], 'GS06'=>$st['gsn'], 'trace'=>$claimid, 'keys'=>true);
1161 $segments = $x12obj->edih_x12_slice($arg_ar);
1162 break;
1163 } elseif (in_array($claimid, $st['acct'])) {
1164 if ($errs) {
1165 $arg_ar = array('ST02'=>$st['stn'], 'ISA13'=>$st['icn'], 'GS06'=>$st['gsn'], 'keys'=>true);
1166 $segments = $x12obj->edih_x12_slice($arg_ar);
1167 } else {
1168 // request for individual transaction segments
1169 $segments = $x12obj->edih_x12_transaction($claimid);
1172 break;
1173 } elseif (in_array($claimid, $st['bht03'])) {
1174 // also possible that bht03 number is given for claimid
1175 // this will likely be a 27x
1176 if ($errs) {
1177 $arg_ar = array('ST02'=>$st['stn'], 'ISA13'=>$st['icn'], 'GS06'=>$st['gsn'], 'keys'=>true);
1178 $segments = $x12obj->edih_x12_slice($arg_ar);
1179 } else {
1180 $segments = $x12obj->edih_x12_transaction($claimid);
1183 $bht03 = $claimid;
1184 break;
1188 } else {
1189 $segments = $segs_ar;
1193 // now check if we have segments
1194 if (empty($segments) || !count($segments)) {
1195 if ($claimid) {
1196 $str_html = "<p>error: transaction $claimid not found in $fn</p>".PHP_EOL;
1197 $str_html .= $x12obj->edih_message().PHP_EOL;
1198 return $str_html;
1199 } else {
1200 // unknown error
1201 $str_html = "<p>unknown error retrieving segments for $fn</p>".PHP_EOL;
1202 $str_html .= $x12obj->edih_message().PHP_EOL;
1203 return $str_html;
1207 // if the segments are from a slice or transaction
1208 // a multidimensional array segs[i][j] must be flattened
1209 $ar_sngl = csv_singlerecord_test($segments);
1210 // false when segments are a transaction or trace only
1211 if (!$ar_sngl) {
1213 // append segments to single array
1214 // keys should not duplicate since all segments
1215 // are from the same x12 file
1216 $trnsegs = array();
1217 for ($i=0; $i<count($segments); $i++) {
1218 $trnsegs = array_merge($trnsegs, $segments[$i]);
1221 $segments = $trnsegs;
1222 unset($trnsegs);
1226 $capstr = '';
1227 $tbl_id = ($claimid) ? $claimid : $fn;
1229 //'HB'=>'271', 'HS'=>'270', 'HR'=>'276', 'HI'=>'278','HN'=>'277', 'HP'=>'835', 'FA'=>'999', 'HC'=>'837');
1230 switch ((string)$ftype) {
1231 case 'HC':
1232 $capstr = "Claim "; //$cls = "txt837";
1233 $trn_html = edih_837_text($segments, $de, $errs);
1234 break;
1235 case 'HP':
1236 $capstr = "Payment "; //$cls = "txt835";
1237 $trn_html = edih_835_text($segments, $de);
1238 break;
1239 case 'HR':
1240 $capstr = "Status Query "; //$cls = "txt276";
1241 $trn_html = edih_277_text($segments, $de, $errs);
1242 break;
1243 case 'HN':
1244 $capstr = "Claim Status "; //$cls = "txt277";
1245 $trn_html = edih_277_text($segments, $de, $stsegkey);
1246 break;
1247 case 'HS':
1248 $capstr = "Eligibility Query "; //$cls = "txt270";
1249 $trn_html = edih_271_text($segments, $de, $errs);
1250 break;
1251 case 'HB':
1252 $capstr = "Eligibility Report "; //$cls = "txt271";
1253 $trn_html = edih_271_text($segments, $de);
1254 break;
1255 case 'HI':
1256 $capstr = "Authorization "; //$cls = "txt278";
1257 $trn_html = edih_278_text($segments, $de, $errs);
1258 break;
1259 case 'FA':
1260 $capstr = "Batch Acknowledgment "; //$cls = "txt997";
1261 $trn_html = edih_997_text($segments, $de);
1262 break;
1263 default:
1264 $capstr = "x12 $ftype "; //$cls = "txt_x12";
1265 $trn_html = edih_segments_text($segments, $de);
1266 break;
1270 $capstr .= ($claimid) ? " <em>ID:</em> $claimid" : "";
1272 $str_html .= "<table id=$tbl_id cols=3 class='segtxt'><caption>$capstr</caption>".PHP_EOL;
1273 $str_html .= "<thead>".PHP_EOL;
1274 $str_html .= "<tr><th class='btloop'>Loop</th><th class='btloop'>Num</th>";
1275 $str_html .= "<th class='segtxt'>Segment (<em>File:</em> $fn)</th></tr>".PHP_EOL;
1276 $str_html .= "</thead>".PHP_EOL."<tbody>".PHP_EOL;
1278 $str_html .= $trn_html;
1280 $str_html .= "</tbody></table>".PHP_EOL;
1282 return $str_html;