EDI history module, version 2.(take 3)
[openemr.git] / library / edihistory / edih_segments.php
blob1d2bb616ed567f1bd275f8eea3ad5b7df229d762
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()
35 */
36 function edih_change_loop($lptest, &$lpval) {
37 // strcmp($str1,$str2) Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.
38 if ( strcmp($lptest, $lpval) > 0) {
39 //echo "$lptest greater than $lpval" .PHP_EOL;
40 $lpval = $lptest;
42 return strcmp($lptest, $lpval);
45 /**
46 * format segments for display of x12 edi files
48 * @param array $segments
49 * @param string $delimiter
50 * return string
52 function edih_segments_text($segments, $delimiter) {
54 $str_html = '';
56 if ( !is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
57 // debug
58 csv_edihist_log('edih_generic_text: invalid argument');
59 $str_html = "Invalid arguments for view of x12 file text<br>";
60 return $str_html;
63 $de = $delimiter;
64 $loopid = " -- ";
65 $idx = 0;
67 foreach ($segments as $key=>$seg) {
68 $idx++;
70 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
73 return $str_html;
76 /**
77 * identify loops and format segments for display
78 * of 837 (professional claim) type x12 edi files
80 * @param array $segments
81 * @param string $delimiter
82 * return string
84 function edih_837_text($segments, $delimiter, $err_seg = '') {
86 $str_html = '';
87 $err_ar = array();
89 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
90 // debug
91 csv_edihist_log('edih_837_text: invalid argument');
92 $str_html .= "Invalid arguments for view of x12 file text<br>";
93 return $str_html;
95 // to highlight identified errors listed in 999/997 ack
96 if ($err_seg) {
97 $er = edih_errseg_parse($err_seg);
98 $erstn = (isset($er['trace'])) ? substr($er['trace'], -4) : '';
99 $erseg = (isset($er['err'])) ? $er['err'] : array();
100 } else {
101 $erstn = '';
102 $erseg = array();
105 $de = $delimiter;
106 $loopid = "0";
107 $idx = 0;
108 $stkey = 0;
109 $segnum = 0;
110 $stsegct = 0;
111 $bterr = 'btseg';
113 foreach ($segments as $key=>$seg) {
114 $idx++;
115 $title = '';
116 $stsegct++;
117 $bterr = 'btseg';
119 if ($erstn && ($erstn == $stn)) {
120 $bterr = (in_array($stsegct, $erseg)) ? 'bterr' : 'btseg';
123 if ( strncmp('ST'.$de, $seg, 3) === 0 ) {
124 $loopid = 'Header';
125 $stkey = (int)$key;
126 $stsegct = 1;
127 $stn = explode($de, $seg)[2];
128 $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;
129 continue;
132 if ( strncmp('BHT'.$de, $seg, 4) === 0 ) {
133 $loopid = 'Begin';
134 $stsegct = 2;
135 $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;
136 continue;
139 if ( strncmp('HL'.$de, $seg, 3) === 0 ) {
140 $sar = explode($de, $seg);
141 if ($sar[3] == '20') { // level code
142 $loopid = '2000A'; // billing provider (clinic)
143 } elseif ($sar[3] == '22') {
144 $loopid = '2000B'; // subscriber
145 } elseif ($sar[3] == '23' || $sar[3] == 'PT') {
146 $loopid = '2000C'; // dependent
147 $has_eb = false;
148 } else {
149 //debug
150 csv_edihist_log('edih_837_text: HL has no level '.$seg);
153 $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;
154 continue;
157 if ( strncmp('CLM'.$de, $seg, 4) === 0 ) {
158 $loopid = '2300'; $title = 'Claim';
159 $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;
160 $title = '';
161 continue;
164 if ( strncmp('SBR'.$de, $seg, 4) === 0 ) {
165 if ($loopid == '2000B') {
166 $title = 'Subscriber';
167 $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;
168 } else {
169 $title = 'Other Subscriber';
170 $loopid = '2320';
171 $str_html .= "<tr><td class='btloop' title='$title'> -- </td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
173 $title = '';
174 continue;
177 if ( strncmp('LX'.$de, $seg, 3) === 0 ) {
178 $loopid = '2400'; $title = 'Svc Line Number';
179 $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;
180 $title = '';
181 continue;
184 if ( strncmp('LIN'.$de, $seg, 4) === 0 ) {
185 $loopid = '2410'; $title = 'Drug ID';
186 $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;
187 $title = '';
188 continue;
191 if ( strncmp('SVD'.$de, $seg, 4) === 0 ) {
192 $loopid = '2430'; $title = 'Line Adjudication';
193 $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;
194 $title = '';
195 continue;
198 if ( strncmp('NM1'.$de, $seg, 4) === 0 ) {
199 $sar = explode($de, $seg);
200 $nm101 = ( isset($sar[1]) ) ? $sar[1] : '';
201 if ( $loopid == 'Begin' || strcmp(substr($loopid,0,4), '2320') < 0 ) {
202 if ($nm101 == '41') {
203 $loopid = '1000A'; $title = 'Submitter';
204 } elseif ($nm101 == '40') {
205 $loopid = '1000B'; $title = 'Receiver';
206 } elseif ($nm101 == '85') {
207 $loopid = '2010AA'; $title = 'Billing';
208 } elseif ($nm101 == '87') {
209 $loopid = '2010AB'; $title = 'Pay to';
210 } elseif ($nm101 == 'PE') {
211 $loopid = '2010AC'; $title = 'Pay to Plan';
212 } elseif ($nm101 == 'IL') {
213 $loopid = '2010BA'; $title = 'Subscriber';
214 } elseif ($nm101 == 'PR') {
215 $loopid = '2010BB'; $title = 'Payer';
216 } elseif ($nm101 == 'QC') {
217 $loopid = '2010CA'; $title = 'Patient';
218 } elseif ($nm101 == 'DN') {
219 $loopid = '2310A'; $title = 'Referring Provider';
220 } elseif ($nm101 == 'P3') {
221 $loopid = '2310A'; $title = 'Primary Care Provider';
222 } elseif ($nm101 == '82') {
223 $loopid = '2310B'; $title = 'Rendering Provider';
224 } elseif ($nm101 == '77') {
225 $loopid = '2310C'; $title = 'Service Facility';
226 } elseif ($nm101 == 'DQ') {
227 $loopid = '2310D'; $title = 'Supervising Provider';
228 } elseif ($nm101 == 'PW') {
229 $loopid = '2310E'; $title = 'Ambulance pickup';
230 } elseif ($nm101 == '45') {
231 $loopid = '2310F'; $title = 'Ambulance dropoff';
233 } elseif ( strcmp(substr($loopid,0,4), '2400') < 0 ) {
234 if ($nm101 == 'IL') {
235 $loopid = '2330A'; $title = 'Other Subscriber';
236 } elseif ($nm101 == 'PR') {
237 $loopid = '2330B'; $title = 'Other Payer';
238 } elseif ($nm101 == 'PR') {
239 $loopid = '2330C'; $title = 'Other Referring Provider';
240 } elseif ($nm101 == '82') {
241 $loopid = '2330D'; $title = 'Other Rendering Provider';
242 } elseif ($nm101 == '77') {
243 $loopid = '2330E'; $title = 'Other Svc Facility';
244 } elseif ($nm101 == 'DQ') {
245 $loopid = '2330F'; $title = 'Other Supervising Provider';
246 } elseif ($nm101 == '85') {
247 $loopid = '2330G'; $title = 'Other Billing Provider';
249 } else {
250 if ($nm101 == '82') {
251 $loopid = '2420A'; $title = 'Rendering Provider';
252 } elseif ($nm101 == 'QB') {
253 $loopid = '2420B'; $title = 'Purchased Svc Provider';
254 } elseif ($nm101 == '77') {
255 $loopid = '2420C'; $title = 'Service Facility';
256 } elseif ($nm101 == 'DQ') {
257 $loopid = '2420D'; $title = 'Supervising Provider';
258 } elseif ($nm101 == 'DK') {
259 $loopid = '2420E'; $title = 'Ordering Provider';
260 } elseif ($nm101 == 'DN') {
261 $loopid = '2420F'; $title = 'Referring Provider';
262 } elseif ($nm101 == 'P3') {
263 $loopid = '2420F'; $title = 'Primary Care Provider';
264 } elseif ($nm101 == 'PW') {
265 $loopid = '2420G'; $title = 'Ambulance pickup';
266 } elseif ($nm101 == '45') {
267 $loopid = '2420H'; $title = 'Ambulance dropoff';
271 $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;
272 $title='';
273 continue;
276 if ( strncmp('SE'.$de, $seg, 3) === 0 ) {
277 $loopid = 'Trailer';
278 $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;
279 $title = '';
280 continue;
282 // for all the segments that do not begin loops
283 $str_html .= "<tr><td class='btloop' title='$title'> -- </td><td class='btnum' title='$key'>$stsegct</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
287 return $str_html;
291 * identify loops and format segments for display
292 * of 270/271 (eligibility) type x12 edi files
294 * @param array $segments
295 * @param string $delimiter
296 * return string
298 function edih_271_text($segments, $delimiter, $err_seg = '') {
300 $str_html = '';
302 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
303 // debug
304 csv_edihist_log('edih_271_text: invalid argument');
305 $str_html .= "Invalid arguments for view of x12 file text<br>";
306 return $str_html;
309 $de = $delimiter;
310 $prevseg = '';
311 $loopid = "0";
312 $lx_ct = 0;
313 $hasst = false;
314 $idx = 0;
315 $stsegct = 0;
317 // to highlight identified errors listed in 999/997 ack (for 270)
318 if ($err_seg) {
319 $er = edih_errseg_parse($err_seg);
320 $erstn = (isset($er['trace'])) ? substr($er['trace'], -4) : '';
321 $erseg = (isset($er['err'])) ? $er['err'] : array();
322 } else {
323 $erstn = '';
324 $erseg = array();
327 if ($err_seg) {
328 $er = edih_errseg_parse($err_seg);
329 if ( is_array($er) && count($er)) {
330 $err_ar = $er;
334 foreach ($segments as $key=>$seg) {
335 $sar = array();
336 $idx++;
337 $stsegct++;
338 $bterr = 'btseg';
340 if ($erstn && ($erstn == $stn)) {
341 $bterr = (in_array($stsegct, $erseg)) ? 'bterr' : 'btseg';
344 if ( strncmp('ST'.$de, $seg, 3) === 0 ) {
345 $sar = explode($de, $seg);
346 $loopid = 'Header';
347 $hasst = true;
348 $stsegct = 1;
349 $sttp = (isset($seg[1])) ? $seg[1] : '';
350 $stn = (isset($seg[2])) ? $seg[2] : '';
351 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
352 continue;
355 if ( strncmp('BHT'.$de, $seg, 4) === 0 ) {
356 $loopid = 'Begin';
357 // 2nd seg in transaction, ST may not be included if segments are transaction slice
358 if ( $stsegct < 2) { $stsegct = 2; }
359 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
360 continue;
363 if ( strncmp('HL'.$de, $seg, 3) === 0 ) {
364 $sar = explode($de, $seg);
365 if ($sar[3] == '20') { // level code
366 $loopid = '2000A'; // info source (payer)
367 } elseif ($sar[3] == '21') {
368 $loopid = '2000B'; // info receiver (clinic)
369 } elseif ($sar[3] == '22') {
370 $loopid = '2000C'; // subscriber
371 $has_eb = false;
372 } elseif ($sar[3] == '23') {
373 $loopid = '2000D'; // dependent
374 $has_eb = false;
375 } else {
376 //debug
377 csv_edihist_log('edih_271_text: HL has no level '.$seg);
380 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
381 $prevseg = 'HL'.$de;
382 continue;
385 if ( strncmp('NM1'.$de, $seg, 4) === 0 ) {
386 if (strncmp('NM1'.$de, $prevseg, 4) === 0 ) {
387 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
388 continue;
390 switch((string)$loopid) {
391 case '2000A': $loopid = '2100A'; break; // edih_change_loop($lptest, &$lpval)
392 case '2000B': $loopid = '2100B'; break;
393 case '2000C': $loopid = '2100C'; break;
394 case '2000D': $loopid = '2100D'; break;
395 default: $loopid = $loopid;
397 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
398 $prevseg = 'NM1'.$de;
399 continue;
402 if ( strncmp('EB'.$de, $seg, 3) === 0 || strncmp('EQ'.$de, $seg, 3) === 0 ) {
403 // EB* segment is in 271 type, EQ* is corresponding segment in 270 type
404 if ( strncmp($seg, $prevseg, 3) === 0 ) {
405 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
406 $prevseg = substr($seg, 0, 3);
407 continue;
409 if ($loopid = '2100C' || $loopid = '2115C' || $loopid = '2120C') {
410 $loopid = '2110C';
411 } elseif ($loopid = '2100D' || $loopid = '2115D' || $loopid = '2120D') {
412 $loopid = '2110D';
414 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
415 $prevseg = substr($seg, 0, 3);
416 $has_eb = (strncmp('EB'.$de, $seg, 3) === 0);
417 $has_iii = false;
418 continue;
421 if ( strncmp('III'.$de, $seg, 4) === 0 && $has_eb) {
422 // the III segment begins a loop in 271 type, but not in 270
423 if ($loopid = '2110C') { $loopid = '2115C'; }
424 if ($loopid = '2100D') { $loopid = '2115D'; }
425 if ($has_iii) {
426 $str_html .= "<tr><td class='btloop'></td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
427 } else {
428 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
429 $has_iii = true;
431 $prevseg = substr($seg, 0, 4);
432 continue;
435 if ( strncmp('LS'.$de, $seg, 3) === 0 ) {
436 if ($loopid = '2110C' || $loopid = '2115C') {
437 $loopid = '2120C';
438 } elseif ($loopid = '2110D' || $loopid = '2115D') {
439 $loopid = '2120D';
441 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
442 continue;
445 if ( strncmp('SE'.$de, $seg, 3) === 0 ) {
446 $str_html .= "<tr><td class='btloop'>Trailer</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
447 $loopid = '0';
448 continue;
450 // for all the segments that do not begin loops
451 $prevseg = substr($seg, 0, strpos($seg,$de)+1);
452 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
456 return $str_html;
460 function edih_835_text($segments, $delimiter, $err_seg='') {
462 $str_html = '';
463 if ( !is_array($segments) || !count($segments) || strlen($delimiter) != 1 ) {
464 //debug
465 csv_edihist_log('edih_835_text: invalid segments');
466 $str_html .= "Invalid arguments for view of x12 file text<br>";
467 return $str_html;
470 $de = $delimiter;
471 $prevseg = '';
472 $loopid = "0";
473 $lx_ct = 0;
474 $idx = 0;
476 foreach($segments as $key=>$seg) {
477 //$idx++;
479 if ( strncmp('ST'.$de, $seg, 3) === 0 ) {
480 $loopid = 'Header';
481 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
482 continue;
485 if ( strncmp('N1'.$de, $seg, 3) === 0 ) {
486 $sar = explode($de, $seg);
487 if ($sar[1] == 'PR') {
488 $loopid = '1000A';
489 } elseif ($sar[1] == 'PE') {
490 $loopid = '1000B';
492 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
493 $prevseg = 'N1'.$de;
494 continue;
497 if ( strncmp('LX'.$de, $seg, 3) === 0 ) {
498 $loopid = '2000';
499 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
500 $prevseg = 'LX'.$de;
501 continue;
504 if ( strncmp('TS3'.$de, $seg, 4) === 0 ) {
505 if ($loopid == '2000') {
506 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
507 } else {
508 $loopid = '2000';
509 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
511 $prevseg = 'TS3'.$de;
512 continue;
515 if ( strncmp('CLP'.$de, $seg, 4) === 0 ) {
516 $loopid = '2100';
517 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
518 $prevseg = 'CLP'.$de;
519 continue;
522 if ( strncmp('SVC'.$de, $seg, 4) === 0 ) {
523 $loopid = '2110';
524 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
525 $prevseg = 'SVC'.$de;
526 continue;
529 if ( strncmp('PLB'.$de, $seg, 4) === 0 ) {
530 $loopid = 'Adjust';
531 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
532 $prevseg = 'PLB'.$de;
533 continue;
536 if ( strncmp('SE'.$de, $seg, 3) === 0 ) {
537 $loopid = 'Trailer';
538 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
539 $prevseg = 'SE'.$de;
540 continue;
542 // for all the segments that do not begin loops
543 $prevseg = substr($seg, 0, 3);
544 $prevseg .= $de;
545 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
549 return $str_html;
554 * identify loops and format segments for display
555 * of 277 (claim status) type x12 edi files
557 * @param array $segments
558 * @param string $delimiter
559 * return string
561 function edih_277_text($segments, $delimiter, $stpos='') {
563 $str_html = '';
564 if ( !is_array($segments) || !count($segments) || strlen($delimiter) != 1 ) {
565 //debug
566 csv_edihist_log('edih_277_text: invlid segments');
567 $str_html .= "Invalid arguments for view of x12 file text<br>";
568 return $str_html;
571 // to highlight identified errors listed in 999/997 ack (for 276)
572 //if ($err_seg) {
573 //$er = edih_errseg_parse($err_seg);
574 //$erstn = (isset($er['trace'])) ? substr($er['trace'], -4) : '';
575 //$erseg = (isset($er['err'])) ? $er['err'] : array();
576 //} else {
577 //$erstn = '';
578 //$erseg = array();
581 $de = $delimiter;
582 $prevseg = '';
583 $loopid = "0";
584 $lx_ct = 0;
585 $stsegct = 0;
586 //$idx = 0;
588 foreach($segments as $idx=>$seg) {
589 //$idx++;
590 $stsegct++;
591 $key = ($stpos) ? $idx - $stpos : $idx;
592 // if 276 transactions are parsed, 999 errors may be present
593 //if ($erstn && ($erstn == $stn)) {
594 //$bterr = (in_array($stsegct, $erseg)) ? 'bterr' : 'btseg';
595 //}
597 if ( strncmp('ST'.$de, $seg, 3) === 0 ) {
598 $loopid = 'Header';
599 $stsegct = 1;
600 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
601 continue;
604 if ( strncmp('BHT'.$de, $seg, 4) === 0 ) {
605 $loopid = 'Begin';
606 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
607 continue;
610 if ( strncmp('HL'.$de, $seg, 3) === 0 ) {
611 $sar = explode($de, $seg);
612 if ($sar[3] == '20') { // level code
613 $loopid = '2000A'; // info source (payer)
614 } elseif ($sar[3] == '21') {
615 $loopid = '2000B'; // info receiver (clinic)
616 } elseif ($sar[3] == '19') {
617 $loopid = '2000C'; // provider
618 } elseif ($sar[3] == '22' || $sar[3] == 'PT') {
619 $loopid = '2000D'; // subscriber
620 } elseif ($sar[3] == '23') {
621 $loopid = '2000E'; // dependent
622 } else {
623 //debug
624 csv_edihist_log('edih_277_text: HL has no level '.$seg);
627 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
628 $prevseg = 'HL'.$de;
629 continue;
633 if ( strncmp('NM1'.$de, $seg, 4) === 0 ) {
634 if (strncmp('NM1'.$de, $prevseg, 4) === 0 ) {
635 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
636 continue;
638 switch((string)$loopid) {
639 case '2000A': $loopid = '2100A'; break; // edih_change_loop($lptest, &$lpval)
640 case '2000B': $loopid = '2100B'; break;
641 case '2000C': $loopid = '2100C'; break;
642 case '2000D': $loopid = '2100D'; break;
643 case '2000E': $loopid = '2100E'; break;
645 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
646 $prevseg = 'NM1';
647 continue;
650 if ( strncmp('TRN'.$de, $seg, 4) === 0 ) {
651 if (strncmp('TRN'.$de, $prevseg, 4) === 0 ) {
652 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
653 continue;
655 switch((string)$loopid) {
656 case '2100A': $loopid = '2200A'; break;
657 case '2100B': $loopid = '2200B'; break;
658 case '2100C': $loopid = '2200C'; break;
659 case '2100D': $loopid = '2200D'; break;
660 case '2100E': $loopid = '2200E'; break;
662 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
663 $prevseg = 'TRN';
664 continue;
667 if ( strncmp('SVC'.$de, $seg, 4) === 0 ) {
668 if (strncmp('SVC'.$de, $prevseg, 4) === 0 ) {
669 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
670 continue;
672 switch((string)$loopid) {
673 case '2200D': $loopid = '2220D'; break;
674 case '2200E': $loopid = '2220E'; break;
676 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
677 $prevseg = 'SVC';
678 continue;
681 if ( strncmp('SE'.$de, $seg, 3) === 0 ) {
682 $loopid = 'Trailer';
683 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
684 $prevseg = 'SE';
685 continue;
687 // for all the segments that do not begin loops
688 $prevseg = substr($seg, 0, 3);
689 $prevseg .= $de;
690 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
693 return $str_html;
697 * identify loops and format segments for display
698 * of 278 (authorization) type x12 edi files
700 * @param array $segments
701 * @param string $delimiter
702 * return string
704 function edih_278_text($segments, $delimiter, $err_seg = '') {
706 $str_html = '';
708 if (!is_array($segments) || !count($segments) || strlen($delimiter) != 1) {
709 // debug
710 csv_edihist_log('edih_278_text(): invalid argument');
711 $str_html .= "Invalid arguments for view of x12 file text<br>";
712 return $str_html;
715 $de = $delimiter;
716 $prevseg = '';
717 $loopid = "0";
718 $lx_ct = 0;
719 $hasst = false;
720 $err_ar = array();
721 $idx = 0;
722 $stsegct =0;
724 // to highlight identified errors listed in 999/997 ack
725 if ($err_seg) {
726 $er = edih_errseg_parse($err_seg);
727 $erstn = (isset($er['trace'])) ? substr($er['trace'], -4) : '';
728 $erseg = (isset($er['err'])) ? $er['err'] : array();
729 } else {
730 $erstn = '';
731 $erseg = array();
734 foreach ($segments as $key=>$seg) {
735 $idx++;
736 $stsegct++;
737 $title = '';
738 $bterr = 'btseg';
740 if ($erstn && ($erstn == $stn)) {
741 $bterr = (in_array($stsegct, $erseg)) ? 'bterr' : 'btseg';
744 if ( strncmp('ST'.$de, $seg, 3) === 0 ) {
745 $loopid = 'Header';
746 $hasst = true;
747 $stsegct = 1;
748 $stn = explode($de, $seg)[2];
749 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
750 continue;
753 if ( strncmp('BHT'.$de, $seg, 4) === 0 ) {
754 $loopid = 'Begin';
755 // 2nd seg in transaction, ST may not be included if segments are transaction slice
756 if ( $stsegct < 2) { $stsegct = 2; }
757 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
758 continue;
761 if (strncmp($seg, 'HL'.$de, 3) === 0 ) {
762 $sar = explode($de, $seg);
763 $hl = $sar[1];
764 $hlpc = $sar[2]; // parent code
765 $hllc = $sar[3];
766 $hlcc = (isset($sar[4])) ? $sar[4] : ''; // child code
767 if ($sar[3] == '20') { // level code
768 $loopid = '2000A'; // info source (payer)
769 $title = 'Info Source';
770 } elseif ($sar[3] == '21') {
771 $loopid = '2000B'; // info receiver (clinic)
772 $title = 'Info Receiver';
773 } elseif ($sar[3] == '22') {
774 $loopid = '2000C'; // subscriber
775 $title = 'Subscriber';
776 } elseif ($sar[3] == '23') {
777 $loopid = '2000D'; // dependent
778 $title = 'Dependent';
779 } elseif ($sar[3] == 'EV') {
780 $loopid = '2000E'; // patient event
781 $title = 'Patient Event';
782 } elseif ($sar[3] == 'SS') {
783 $loopid = '2000F'; // service
784 $title = 'Service';
785 } else {
786 //debug
787 csv_edihist_log('edih_278_text: HL has no level '.$seg);
790 $str_html .= "<tr><td class='btloop' title='$title'>$loopid</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
791 $prevseg = 'HL';
792 continue;
795 if (strncmp($seg, 'NM1'.$de, 4) === 0 ) {
796 $sar = explode($de, $seg);
797 $nm101 = $sar[1];
798 if ($loopid == '2000A') {
799 $loopid == '2010A'; // Source
800 } elseif ( $loopid == '2000B' ) {
801 $loopid = '2010B'; // Receiver
802 } elseif ( $loopid == '2000C' ) {
803 $loopid = '2010C'; // Subscriber
804 } elseif ( $loopid == '2000D') {
805 $loopid = '2010D'; // Dependent
806 } elseif ( $loopid == '2000E' || strpos($loopid, '010E') ) { // Patient Event
807 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010EA' : $loopid;
808 $loopid = (strpos('|45|FS|ND|PW|R3', $nm101) ) ? '2010EB' : $loopid;
809 $loopid = ($nm101 == 'L5') ? '2010EC' : $loopid;
810 } elseif ( $loopid == '2000F' || strpos($loopid, '010F') ) { // Service
811 $loopid = (strpos('|71|72|73|77|AAJ|DD|DK|DN|FA|G3|P3|QB|QV|SJ', $nm101) ) ? '2010FA' : $loopid;
814 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
815 $prevseg = 'NM1';
816 continue;
819 if ( strncmp('SE'.$de, $seg, 3) === 0 ) {
820 $str_html .= "<tr><td class='btloop'>Trailer</td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
821 $loopid = '0';
822 $prevseg = 'SE';
823 continue;
825 // for all the segments that do not begin loops
826 $prevseg = substr($seg, 0, strpos($seg,$de));
827 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='$bterr'>$seg</td></tr>" .PHP_EOL;
831 return $str_html;
835 * identify loops and format segments for display
836 * of 997/999 (acknowledgement) type x12 edi files
838 * @param array $segments
839 * @param string $delimiter
840 * return string
842 function edih_997_text($segments, $delimiter) {
844 $str_html = '';
845 if ( !is_array($segments) || !count($segments) || strlen($delimiter) != 1 ) {
846 //debug
847 csv_edihist_log('edih_997_text(): invalid segments');
848 return $str_html;
851 $de = $delimiter;
852 $loopid = "0";
854 //echo 'edih_997_text() foreach segment count: '.count($segments).PHP_EOL;
856 foreach($segments as $key=>$seg) {
858 //echo var_dump($seg).PHP_EOL;
860 if ( strncmp('TA1'.$de, $seg, 4) === 0 ) {
861 $sar = explode($de, $seg);
862 $rspicn = $sar[1];
863 $loopid = 'ACK'; // not official
864 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
865 unset($sar);
866 $loopid = ''; // reset loop for subsequent segments
867 continue;
870 if ( strncmp('ST'.$de, $seg, 3) === 0 ) {
871 $loopid = 'Header';
872 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
873 continue;
876 if ( strncmp('AK1'.$de, $seg, 4) === 0 ) {
877 $sar = explode($de, $seg);
878 $rsptp = csv_file_type($sar[1]);
879 if ($rspicn && $rsptp) {
880 $rspfile = csv_file_by_controlnum($rsptp, $rspicn);
882 $title = ($rspfile) ? 'response to '.$rspfile : '';
883 $loopid = '2000';
884 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td title='$title' class='btseg'>$seg</td></tr>" .PHP_EOL;
885 unset($sar);
886 continue;
889 if ( strncmp('AK2'.$de, $seg, 4) === 0 ) {
890 $loopid = 'AK2';
891 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
892 continue;
895 if ( strncmp('IK3'.$de, $seg, 4) === 0 || strncmp('AK3'.$de, $seg, 4) === 0 ) {
896 $loopid = '2100';
897 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
898 continue;
901 if ( strncmp('IK4'.$de, $seg, 4) === 0 || strncmp('AK4'.$de, $seg, 4) === 0 ) {
902 $loopid = '2110';
903 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
904 continue;
907 if ( strncmp('SE'.$de, $seg, 3) === 0 ) {
908 $loopid = 'Trailer';
909 $str_html .= "<tr><td class='btloop'>$loopid</td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
910 continue;
912 // for all the segments that do not begin loops ;
913 $str_html .= "<tr><td class='btloop'> -- </td><td class='btnum'>$key</td><td class='btseg'>$seg</td></tr>" .PHP_EOL;
916 return $str_html;
920 * Display of x12 edi transaction listing or all segments in the files.
921 * When using $err_info, you must use the filepath of the submitted file
923 * @param string $filepath path to desired file
924 * @param string $filetype used when filepath is just filename
925 * @param string optional $claimid CLM01, or BHT03 to identify a transaction or a trace value
926 * @param bool false: $claimid is pt transaction, true: $claimid is trace from 835 or 999
927 * @param string optional $err_info the prepared error info from a 997/999 response
928 * @return string html for display of file segments
930 function edih_display_text($filepath, $filetype='', $claimid='', $trace=false, $err_info='') {
932 $str_html = '';
933 $de = '';
934 $segments = '';
935 $stsegkey = '';
936 $ft = ($filetype) ? $filetype : '';
937 $errs = ( strlen($err_info) ) ? $err_info : '';
938 $bht03 = '';
940 // verify x12 file
941 $x12obj = csv_check_x12_obj($filepath, $ft);
943 if ($x12obj && 'edih_x12_file' == get_class($x12obj) ) {
944 $ftype = $x12obj->edih_type();
945 $ft = csv_file_type($ftype);
946 $delims = $x12obj->edih_delimiters();
947 $de = $delims['e'];
948 $fn = $x12obj->edih_filename();
949 $segs_ar = $x12obj->edih_segments();
950 $env_ar = $x12obj->edih_envelopes();
951 if (!$de || strlen($de) != 1 ) {
952 // error in object
953 // debug
954 $str_html = 'edih_display_text(): error in delimiters<br />'.PHP_EOL;
955 $str_html .= $x12obj->edih_message().PHP_EOL;
956 return $str_html;
958 if ( !is_array($segs_ar) || !count($segs_ar) ) {
959 // unknown error
960 $str_html = "<p>unknown error retrieving segments for $fn</p>".PHP_EOL;
961 $str_html .= $x12obj->edih_message().PHP_EOL;
962 return $str_html;
964 } else {
965 //debug
966 csv_edihist_log('edih_transaction_text(): invalid path '.$filepath);
967 $str_html = 'edih_display_text(): error accessing file<br />'.PHP_EOL;
968 return $str_html;
971 if ($claimid) {
972 // claimid can be for transaction, payment, or error response
973 if ($trace && array_key_exists($claimid, $env_ar['ISA'])) {
974 $arg_ar = array('ISA13'=>$claimid, 'keys'=>true);
975 $segments = $x12obj->edih_x12_slice($arg_ar);
976 } else {
977 // claimid alone can be clm01 or bht03, if trace=true, expect trn02 for claimid
978 foreach($env_ar['ST'] as $st) {
980 if ($trace && $claimid == $st['trace']) {
981 $arg_ar = array('ISA13'=>$st['icn'], 'GS06'=>$st['gsn'], 'trace'=>$claimid, 'keys'=>true);
982 $segments = $x12obj->edih_x12_slice($arg_ar);
983 break;
985 } elseif ( in_array($claimid, $st['acct']) ) {
986 if ($errs) {
987 $arg_ar = array('ST02'=>$st['stn'], 'ISA13'=>$st['icn'], 'GS06'=>$st['gsn'], 'keys'=>true);
988 $segments = $x12obj->edih_x12_slice($arg_ar);
989 } else {
990 // request for individual transaction segments
991 $segments = $x12obj->edih_x12_transaction($claimid);
993 break;
994 } elseif ( in_array($claimid, $st['bht03']) ) {
995 // also possible that bht03 number is given for claimid
996 // this will likely be a 27x
997 if ($errs) {
998 $arg_ar = array('ST02'=>$st['stn'], 'ISA13'=>$st['icn'], 'GS06'=>$st['gsn'], 'keys'=>true);
999 $segments = $x12obj->edih_x12_slice($arg_ar);
1000 } else {
1001 $segments = $x12obj->edih_x12_transaction($claimid);
1003 $bht03 = $claimid;
1004 break;
1008 } else {
1009 $segments = $segs_ar;
1012 // now check if we have segments
1013 if ( empty($segments) || !count($segments) ) {
1014 if ($claimid) {
1015 $str_html = "<p>error: transaction $claimid not found in $fn</p>".PHP_EOL;
1016 $str_html .= $x12obj->edih_message().PHP_EOL;
1017 return $str_html;
1018 } else {
1019 // unknown error
1020 $str_html = "<p>unknown error retrieving segments for $fn</p>".PHP_EOL;
1021 $str_html .= $x12obj->edih_message().PHP_EOL;
1022 return $str_html;
1025 // if the segments are from a slice or transaction
1026 // a multidimensional array segs[i][j] must be flattened
1027 $ar_sngl = csv_singlerecord_test ( $segments );
1028 // false when segments are a transaction or trace only
1029 if (!$ar_sngl) {
1031 // append segments to single array
1032 // keys should not duplicate since all segments
1033 // are from the same x12 file
1034 $trnsegs = array();
1035 for ($i=0; $i<count($segments); $i++) {
1036 $trnsegs = array_merge($trnsegs, $segments[$i]);
1038 $segments = $trnsegs;
1039 unset($trnsegs);
1042 $capstr = '';
1043 $tbl_id = ($claimid) ? $claimid : $fn;
1045 //'HB'=>'271', 'HS'=>'270', 'HR'=>'276', 'HI'=>'278','HN'=>'277', 'HP'=>'835', 'FA'=>'999', 'HC'=>'837');
1046 switch((string)$ftype) {
1047 case 'HC':
1048 $capstr = "Claim "; //$cls = "txt837";
1049 $trn_html = edih_837_text($segments, $de, $errs);
1050 break;
1051 case 'HP':
1052 $capstr = "Payment "; //$cls = "txt835";
1053 $trn_html = edih_835_text($segments, $de);
1054 break;
1055 case 'HR':
1056 $capstr = "Status Query "; //$cls = "txt276";
1057 $trn_html = edih_277_text($segments, $de, $errs);
1058 break;
1059 case 'HN':
1060 $capstr = "Claim Status "; //$cls = "txt277";
1061 $trn_html = edih_277_text($segments, $de, $stsegkey);
1062 break;
1063 case 'HS':
1064 $capstr = "Eligibility Query "; //$cls = "txt270";
1065 $trn_html = edih_271_text($segments, $de, $errs);
1066 break;
1067 case 'HB':
1068 $capstr = "Eligibility Report "; //$cls = "txt271";
1069 $trn_html = edih_271_text( $segments, $de);
1070 break;
1071 case 'HI':
1072 $capstr = "Authorization "; //$cls = "txt278";
1073 $trn_html = edih_278_text( $segments, $de, $errs);
1074 break;
1075 case 'FA':
1076 $capstr = "Batch Acknowledgment "; //$cls = "txt997";
1077 $trn_html = edih_997_text( $segments, $de);
1078 break;
1079 default:
1080 $capstr = "x12 $ftype "; //$cls = "txt_x12";
1081 $trn_html = edih_segments_text($segments, $de);
1082 break;
1085 $capstr .= ($claimid) ? " <em>ID:</em> $claimid" : "";
1087 $str_html .= "<table id=$tbl_id cols=3 class='segtxt'><caption>$capstr</caption>".PHP_EOL;
1088 $str_html .= "<thead>".PHP_EOL;
1089 $str_html .= "<tr><th class='btloop'>Loop</th><th class='btloop'>Num</th>";
1090 $str_html .= "<th class='segtxt'>Segment (<em>File:</em> $fn)</th></tr>".PHP_EOL;
1091 $str_html .= "</thead>".PHP_EOL."<tbody>".PHP_EOL;
1093 $str_html .= $trn_html;
1095 $str_html .= "</tbody></table>".PHP_EOL;
1097 return $str_html;