3 * csv_record_include.php
5 * Copyright 2012 Kevin McCormick
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 3 or later. You should have
15 * received a copy of the GNU General Public License along with this program;
16 * if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * <http://opensource.org/licenses/gpl-license.php>
20 * @author Kevin McCormick
21 * @link: http://www.open-emr.org
23 * @subpackage ediHistory
27 * The purpose of this file is to hold functions of general utility for
28 * my edi_claim_history project. It began as a php "class" but I am now
29 * thinking that instantiating the class is too much bother and probably
30 * a waste of memory, since the contents of the file have to be read into
34 * ******* important *********
35 * function csv_parameters($type="ALL")
36 * This function must have the correct values or nothing will work
37 * function csv_verify_file( $file_path, $type, $val_array=FALSE )
38 * critical for file verification and x12 parsing
39 * function (in ibr_uploads.php) ibr_upload_match_file($param_ar, $fidx, &$html_str)
40 * contains a regular expression that must be correct
42 * **************************
45 * The claim_history x12 files are batch (837) claim status (277 also TA1) and era (835)
46 * (Eligibility status files (271) would probably work in this scheme as well.)
47 * There are also Availity clearinghouse specific files .ibr, .ebr, .dpr (nothing for .dpr files)
51 * Each file type has a row in the array from csv_paramaters()
52 * type directory files_csv claims_csv column regex
54 * 1. Read the parameters array and choose the parameters using 'type'
55 * 2. Search the 'directory' for files matching the 'regex' regular expressions and
56 * compare the results to the files listed in the 'files_csv' files.csv record -- unmatched files are "new"
57 * 3. Each "new" x12 file should be read by csv_x12_segments -- returns array('path', 'delimiters', 'segments')
58 * ibr, ebr, ack -- basically Availity formats have their own read functions
59 * 4. Pass the array to various functions which parse for claims information
60 * 5. Write the results to files.csv or claims.csv and create html output for display
62 * 6. Other outputs as called for in ibr_history.php -- from user input from claim_history.html
65 * Key usability issue is the "new" files are in the users home directory -- downloaded there
66 * while the OpenEMR is on the server -- so there is a basic issue of access to the files
68 * The ibr_uploads.php script handles uploads of zip archives or multiple file uploads
70 * The csv data files are just php written .csv files, so anything different may cause errors
71 * You can open and edit them in OpenOffice, but you must save them in "original format"
73 * TO DO script to read 271 eligibility response files -- add type to csv_verfy_file, csv_parameters, csv_files_header, csv_setup
75 * TO_DO Some type of "find in files" search would be helpful for locating all references to a claim, patient, etc.
76 * [ grep -nHIrF 'findtext']
78 * TO_DO functions to zip old files, put them aside, and remove them from csv tables
82 // * a security measure to prevent direct web access to this file
84 // if (!defined('SITE_IN')) die('Direct access not allowed!');
87 * Log messages to the log file
89 * @param string $msg_str the log message
90 * @return int number of characters written
92 function csv_edihist_log ( $msg_str ) {
94 $logfile = csv_edih_basedir();
95 //$logfile = ($logfile) ? $logfile."/edi_history_log.txt" : $GLOBALS['OE_SITE_DIR']."/edi_history_log.txt";
96 $logfile = ($logfile) ?
$logfile."/edi_history_log.txt" : false;
98 echo "EDI History log file not available <br />";
102 if ( is_string($msg_str) ) {
103 $tm = date( 'Ymd:Hms' );
104 $tm .= " " . $msg_str . PHP_EOL
;
105 $fh = fopen( $logfile, 'a');
107 $rslt = fwrite($fh, $tm); // number of characters written
116 * read the edi_history_log.txt file into an
117 * html formatted ordered list
121 function csv_log_html() {
122 $html_str = "<div class=\"filetext\">".PHP_EOL
."<ol class='logview'>".PHP_EOL
;
123 $fp = csv_edih_basedir();
124 $fp = $fp."/edi_history_log.txt";
125 $fh = fopen( $fp, 'r');
127 while (($buffer = fgets($fh)) !== false) {
128 $html_str .= "<li>$buffer</li>".PHP_EOL
;
130 $html_str .= "</ol>".PHP_EOL
."</div>".PHP_EOL
;
132 $html_str .= "<p>Error: unexpected file ending error</p>".PHP_EOL
;
136 $html_str = "<p>Error: unable to open log file</p>".PHP_EOL
;
141 function csv_log_archive() {
145 $bdir = csv_edih_basedir();
146 $zname = $bdir.DIRECTORY_SEPARATOR
.$dte.'_edihistory_log.txt';
147 $logname = $bdir.DIRECTORY_SEPARATOR
.'edi_history_log.txt';
148 $archname = $bdir.DIRECTORY_SEPARATOR
.'edihistory_archive.zip';
150 $fs = filesize($logname);
151 if ($fs == false && $fs < 512) {
152 $str_out = "$tm error accessng log file.<br />".PHP_EOL
;
154 } elseif ($fs < 512) {
155 $str_out = "$tm log too small to archive.<br />".PHP_EOL
;
159 $zip = new ZipArchive
;
160 if ($zip->open($archname, ZIPARCHIVE
::CREATE | ZIPARCHIVE
::CHECKCONS
)!==TRUE) {
161 exit("cannot open <$archname>\n");
163 $a = $zip->addFile($logname, $zname);
166 $fh = fopen($logname, "w+b");
168 $tm = date('Ymd:Hms');
169 $rslt = fwrite($fh, "$tm log file archive created.".PHP_EOL
);
172 $str_out = "$tm log file archive created.<br />".PHP_EOL
;
174 $str_out = "$tm error in archive of log file.<br />".PHP_EOL
;
181 * open or save a user notes file
187 function csv_notes_file($content='', $open=true) {
190 //$fp = dirname(__FILE__) . "/edi_notes.txt";
191 $fp = csv_edih_basedir();
192 $fp = $fp."/edi_notes.txt";
193 if (! is_writable($fp) ) {
194 $fh = fopen( $fp, 'a+b');
198 // if contents were previously deleted by user and file is empty,
199 // the text 'empty' is put in content in save operation
200 $ftxt = file_get_contents($fp);
201 if ($ftxt === false) { echo "csv_notes_file: file error<br />".PHP_EOL
; }
202 if (substr($ftxt, 0, 5) == 'empty' && strlen($ftxt) == 5) {
203 $ftxt = '## '. date("F j, Y, g:i a");
205 $ftxt = '## '. date("F j, Y, g:i a");
208 } elseif (strlen($content)) {
209 //echo "csv_notes_file: we have content<br />".PHP_EOL;
210 if (preg_match('/[^\x20-\x7E\x0A\x0D]|(<\?)|(<%)|(<asp)|(<ASP)|(#!)|(\$\{)|(<scr)|(<SCR)/', $content, $matches, PREG_OFFSET_CAPTURE
)) {
211 $str_html .= "Filtered character in file content not accepted <br />" . PHP_EOL
;
212 $str_html .= " character: " . $matches[0][0] . " position: " . $matches[0][1] . "<br />" . PHP_EOL
;
215 //echo "csv_notes_file: we are trying to save in $fp<br />".PHP_EOL;
216 $saved = file_put_contents($fp, $content);
218 $str_html .= ($saved) ?
"Notes saved<br />" : "Save Error<br />";
221 $saved = file_put_contents($fp, $ftxt);
222 $str_html .= ($saved) ?
"No content in notes.<br />" : "Save Error with empty file<br />";
229 * set the base path for most file operations
231 * @return string|boolean
233 function csv_edih_basedir() {
234 //$GLOBALS['OE_SITE_DIR']
235 // should be something like /var/www/htdocs/openemr/sites/default
236 if (isset($GLOBALS['OE_SITE_DIR'])) {
237 return $GLOBALS['OE_SITE_DIR'].'/edi/history';
239 csv_edihist_log("csv_edih_basedir: failed to obtain OpenEMR Site directory");
245 * set the temporary directory used for uploads, etc.
249 function csv_edih_tmpdir() {
250 //define("IBR_UPLOAD_DIR", "/tmp/edihist");
251 $systmp = sys_get_temp_dir();
252 $systmp = stripcslashes($systmp);
253 return $systmp."/edihist";
258 * Initial setup function
260 * Create the directory tree and write the column headers into the csv files
261 * This function will accept a directory argument and it appends the value
262 * from IBR_HISTORY_DIR to the path. Then a directory for each type of file
263 * and the csv files are created under that.
265 * @uses csv_parameters()
266 * @uses csv_files_header()
268 * @param string &$out_str referenced, should be created in calling function
271 function csv_setup(&$out_str) {
275 //$basedir = dirname(__FILE__);
276 $edihist_dir = csv_edih_basedir();
278 $basedir = $GLOBALS['OE_SITE_DIR'].DIRECTORY_SEPARATOR
.'edi';
279 $csv_dir = $edihist_dir.DIRECTORY_SEPARATOR
.'csv';
280 $archive_dir = $edihist_dir.DIRECTORY_SEPARATOR
.'archive';
282 //csv_edihist_log("setup: failed to obtain OpenEMR Site directory");
283 $out_str .= "setup: failed to obtain OpenEMR Site directory <br />";
287 if (is_writable($basedir) ) {
289 $out_str .= "setup: directory $basedir <br />";
290 //csv_edihist_log("setup: directory $basedir");
295 if (!mkdir($edihist_dir, 0755, true)) {
296 //csv_edihist_log("Setup: Failed to create folder... $edihist_dir");
297 $out_str .= "Setup: Failed to create folder... $edihist_dir<br />".PHP_EOL
;
301 $p_ar = csv_parameters("ALL");
303 if (!mkdir($csv_dir, 0755, true) ) {
305 //csv_edihist_log("Setup: Failed to create csv folder...$csv_dir");
308 if (!mkdir($archive_dir, 0755, true) ) {
310 //csv_edihist_log("Setup: Failed to create archive folder...$archive_dir");
314 foreach ($p_ar as $key=>$val) {
315 // make the file storage subdirs; like /history/era /history/f997, etc.
316 $type_dir = $p_ar[$key]['directory'];
318 if (!is_dir($type_dir) && !mkdir($type_dir, 0755, false) ) {
319 //csv_edihist_log("Setup: failed to create storage directory $key");
320 $out_str .= "Setup: failed to create storage directory $key<br />".PHP_EOL
;
323 $out_str .= "created directory for $key<br />" .PHP_EOL
;
326 $hdr_f = csv_files_header($p_ar[$key]['type'], 'file');
327 $hdr_c = csv_files_header($p_ar[$key]['type'], 'claim');
329 $fpath = $p_ar[$key]['files_csv'];
330 $cpath = $p_ar[$key]['claims_csv'];
332 if (is_array($hdr_f) ) {
333 // create the files_type.csv files and insert header row
335 //csv_edihist_log("Creating file $fpath for $key");
336 $fh = fopen($fpath, 'x');
338 $chr = fputcsv($fh, $hdr_f);
339 $out_str .= ($chr) ?
"created $fpath <br />" .PHP_EOL
: "failed to create $fpath<br />" .PHP_EOL
;
340 $isOK = ($chr) ?
TRUE : FALSE;
344 //csv_edihist_log("Creating file failed for $key");
345 $out_str .= "Creating file failed for $key<br />" .PHP_EOL
;
350 //csv_edihist_log("Did not get header row for $key file");
351 $out_str .= "Did not get header row for $key file<br />".PHP_EOL
;
354 if (is_array($hdr_c) ) {
355 // // create the claims_type.csv files and insert header row
357 //csv_edihist_log("Creating file $cpath for $key");
358 $fh = fopen($cpath, 'x');
360 $chr = fputcsv($fh, $hdr_c);
361 $out_str .= ($chr) ?
"created $cpath <br />" .PHP_EOL
: "failed to write heading row for $cpath<br />" .PHP_EOL
;
362 $isOK = ($chr) ?
TRUE : FALSE;
366 //csv_edihist_log("Creating file failed for $key");
367 $out_str .= "Creating file failed for $key<br />" .PHP_EOL
;
373 //csv_edihist_log("Did not get header row for $key claims table");
374 $out_str .= "Did not get header row for $key claims table<br />".PHP_EOL
;
378 //$GLOBALS['OE_SITE_DIR']."/edi_history_log.txt";
379 //if (is_file($GLOBALS['OE_SITE_DIR']."/edi_history_log.txt")) {
380 // rename ($GLOBALS['OE_SITE_DIR']."/edi_history_log.txt", $edihist_dir."/edi_history_log.txt" );
384 $out_str .= "Setup failed: Can not create directories <br />" . PHP_EOL
;
392 * Empty all contents of tmp dir IBR_UPLOAD_DIR
397 function csv_clear_tmpdir() {
399 $edih_tmpdir = csv_edih_tmpdir();
400 $tmp_files = scandir($edih_tmpdir);
401 if (count($tmp_files)) {
402 foreach($tmp_files as $idx=>$tmpf) {
403 if ($tmpf == "." ||
$tmpf == "..") {
404 // can't delete . and ..
407 if (is_file($edih_tmpdir.DIRECTORY_SEPARATOR
.$tmpf) ) {
408 unlink($edih_tmpdir.DIRECTORY_SEPARATOR
.$tmpf);
409 unset($tmp_files[$idx]);
413 if (count($tmp_files) > 2) {
415 csv_edihist_log ( "tmp dir contents remain in $edih_tmpdir");
423 * The array that holds the various parameters used in dealing with files
425 * A key function since it holds the paths, columns, etc. This function relies on
426 * the IBR_HISTORY_DIR constant. Unfortunately, there is an issue with matching the type in
427 * the case of the values '997', '277', '999', etc, becasue these strings may be recast
428 * from strings to integers, so the 'type' originally supplied is lost.
429 * This introduces an inconsistency when the 'type' is used in comparison tests.
430 * The workaround is to say the "type" should have an 'f' prepended to the x12 type number.
431 * The 'datecolumn' and 'fncolumn' entries are used in csv_to_html() to filter by date
432 * or place links to files.
434 * @param string $type -- default = ALL or one of batch, ibr, ebr, dpr, f997, f277, era, ack, text
437 function csv_parameters($type="ALL") {
439 $edihist_dir = csv_edih_basedir(); // $GLOBALS['OE_SITES_BASE'].'/edi/history'
441 // the batch file directory is a special case - decision is to use OpenEMR batch files so users will not have to
442 // upload these. If they are accidentally uploaded, they will be matched and the extra copy will be discarded
443 // OpenEMR copies each batch file to sites/default/edi and this project never reads from or writes to that directory
444 // batch reg ex -- '/20[01][0-9]-[01][0-9]-[0-3][0-9]-[0-9]{4}-batch*\.txt/' '/\d{4}-\d{2}-\d{2}-batch*\.txt$/'
446 //$p_ar['csv'] = array("type"=>'csv', "directory"=>$edihist_dir.'/csv', "claims_csv"=>'ibr_parameters.csv',
447 // "files_csv"=>'', "column"=>'', "regex"=>'/\.csv$/');
449 $p_ar['batch'] = array("type"=>'batch', "directory"=>$GLOBALS['OE_SITE_DIR'].'/edi', "claims_csv"=>$edihist_dir."/csv/claims_batch.csv",
450 "files_csv"=>$edihist_dir."/csv/files_batch.csv", "datecolumn"=>'0', "fncolumn"=>'1', "regex"=>'/\-batch(.*)\.txt$/');
451 $p_ar['ta1'] = array("type"=>'ta1', "directory"=>$edihist_dir.'/f997', "claims_csv"=>'',
452 "files_csv"=>$edihist_dir.'/csv/files_997.csv', "datecolumn"=>'0', "fncolumn"=>'1', "regex"=>'/\.ta1$/i');
453 $p_ar['ack'] = array("type"=>'ack', "directory"=>$edihist_dir.'/f997', "claims_csv"=>'',
454 "files_csv"=>$edihist_dir.'/csv/files_997.csv', "datecolumn"=>'0', "fncolumn"=>'1', "regex"=>'/\.ack$/i');
455 $p_ar['f997'] = array("type"=>'f997', "directory"=>$edihist_dir.'/f997', "claims_csv"=>$edihist_dir.'/csv/claims_997.csv',
456 "files_csv"=>$edihist_dir.'/csv/files_997.csv', "datecolumn"=>'0', "fncolumn"=>'1', "regex"=>'/\.99[79]$/');
458 $p_ar['ibr'] = array("type"=>'ibr', "directory"=>$edihist_dir.'/ibr', "claims_csv"=>$edihist_dir.'/csv/claims_ibr.csv',
459 "files_csv"=>$edihist_dir.'/csv/files_ibr.csv', "datecolumn"=>'0', "fncolumn"=>'1', "regex"=>'/\.ibr$/');
460 $p_ar['ebr'] = array("type"=>'ebr', "directory"=>$edihist_dir.'/ebr', "claims_csv"=>$edihist_dir.'/csv/claims_ebr.csv',
461 "files_csv"=>$edihist_dir.'/csv/files_ebr.csv', "datecolumn"=>'0', "fncolumn"=>'1', "regex"=>'/\.ebr$/');
462 $p_ar['dpr'] = array("type"=>'dpr', "directory"=>$edihist_dir.'/dpr', "claims_csv"=>$edihist_dir.'/csv/claims_dpr.csv',
463 "files_csv"=>'', "datecolumn"=>'1', "fncolumn"=>'5', "regex"=>'/\.dpr$/');
464 $p_ar['f277'] = array("type"=>'f277', "directory"=>$edihist_dir.'/f277', "claims_csv"=>$edihist_dir.'/csv/claims_277.csv',
465 "files_csv"=>$edihist_dir.'/csv/files_277.csv', "datecolumn"=>'0', "fncolumn"=>'1', "regex"=>'/\.277([ei]br)?$/');
466 // OpenEMR stores era files, but the naming scheme is confusing, so we will just use our own directory for them
467 $p_ar['era'] = array("type"=>'era', "directory"=>$edihist_dir.'/era', "claims_csv"=>$edihist_dir.'/csv/claims_era.csv',
468 "files_csv"=>$edihist_dir.'/csv/files_era.csv', "datecolumn"=>'0', "fncolumn"=>'1', "regex"=>'/835[0-9]{5}\.835*|\.(era|ERA)$/');
469 $p_ar['text'] = array("type"=>'text', "directory"=>$edihist_dir.'/text', "claims_csv"=>'',
470 "files_csv"=>'', "column"=>'', "regex"=>'/\.(EB)|(IB)|(DP)|(AC)|(TA)|(99)|(97)T$/i');
472 $tp = strpos('|f837', (string)$type) ?
'batch' : $type;
473 $tp = strpos('|f999', (string)$type) ?
'f997' : $tp;
474 $tp = strpos('|f997', (string)$type) ?
'f997' : $tp;
475 $tp = strpos('|f835', (string)$type) ?
'era' : $tp;
476 $tp = strpos('|f277', (string)$type) ?
'f277' : $tp;
478 if ( array_key_exists($tp, $p_ar) ) {
486 * determine if a csv table has data for select dropdown
488 * @param string default 'json'
489 * @return array json if argument is 'json'
491 function csv_table_select_list($outtp='json') {
494 $edihist_dir = csv_edih_basedir(); // $GLOBALS['OE_SITE_DIR'].'/edi/history'
495 $thisdir = $edihist_dir.'/csv';
496 $tbllist = scandir($thisdir);
498 foreach($tbllist as $csvf) {
499 if ($csvf == "." ||
$csvf == ".." ) { continue; }
500 if (filesize($thisdir.DIRECTORY_SEPARATOR
.$csvf) < 90) { continue; }
501 if (substr($csvf, -1) == '~') { continue; }
502 $finfo = pathinfo($thisdir.DIRECTORY_SEPARATOR
.$csvf);
503 $fn = $finfo['filename'];
504 $tp = explode('_', $fn);
505 $optlist[$idx]['fname'] = $fn;
506 $optlist[$idx]['desc'] = $tp[1] .' '.$tp[0];
509 if ($outtp == 'json') {
510 return json_encode($optlist);
518 * List files in the directory for the given type
520 * Write an entry in the log if an file is in the directory
521 * that does not match the type.
523 * @uses csv_parameters()
524 * @param string $type a type from our list
527 function csv_dirfile_list ($type) {
528 // return false if location is not appropriate
529 // use regular expressions to select desired files from directory
530 if (! strpos("|era|f997|ibr|ebr|dpr|f277|batch|ack|ta1", $type) ) {
531 if ($type != 'text') {
532 // do not log text type, but do not search either
533 csv_edihist_log("csv_dirfile_list error: incorrect type $type");
537 $params = csv_parameters($type);
538 //$search_dir = dirname(__FILE__).$params['directory'].DIRECTORY_SEPARATOR;
539 $search_dir = $params['directory'].DIRECTORY_SEPARATOR
;
540 $typedir = basename($params['directory']);
541 $ext_re = $params['regex'];
544 if (is_dir($search_dir)) {
545 if ($dh = opendir($search_dir)) {
546 while (($file = readdir($dh)) !== false) {
547 if (is_file($search_dir.$file) ) {
548 if (preg_match($ext_re, $file) ) {
550 } elseif ($typedir == 'f997') {
551 $ext = substr($file, -3);
552 // no error, since ack|ta1 files are put there
553 if ($type == 'f997') {
554 if ($ext == 'ack' ||
$ext == 'ta1') { continue; }
555 } elseif ($type == 'ack') {
556 if (ext
== '999' || ext
== '997' ||
$ext == 'ta1') { continue; }
557 } elseif ($type == 'ta1') {
558 if (ext
== '999' || ext
== '997' ||
$ext == 'ack') { continue; }
561 csv_edihist_log("csv_dirfile_list: $type wrong type $file");
568 csv_edihist_log("csv_dirfile_list: Error: $typedir directory seems to be missing!");
576 * List files that are in the csv record
578 * @uses csv_parameters()
579 * @param string $type -- one of our types
582 function csv_processed_files_list ($type) {
585 if (! strpos("|era|f997|ibr|ebr|dpr|f277|batch|ack|ta1", $type) ) {
586 if ($type != 'text') {
587 csv_edihist_log("csv_processed_files_list error: incorrect type $type");
591 $processed_files = array();
592 $param = csv_parameters($type);
593 $csv_col = $param['fncolumn'];
594 if ($type == 'dpr') {
595 $csv_file = $param['claims_csv'];
598 $csv_file = $param['files_csv'];
602 if (($fh1 = fopen( $csv_file, "r" )) !== FALSE) {
603 while (($data = fgetcsv($fh1, 1024, ",")) !== FALSE) {
604 if ($idx) { $processed_files[] = $data[$csv_col]; }
605 // skip the header row
610 csv_edihist_log ("csv_list_processed_files: failed to access $csv_file" );
614 return $processed_files;
619 * Give an array of files in the storage directories that are not in the csv record
621 * @param string $type -- one of our types
624 function csv_newfile_list($type) {
626 //f277 f997 ack batch csv ebr era ibr text
627 if (! strpos("|era|f997|ibr|ebr|dpr|f277|batch|ack|ta1", $type) ) {
628 if ($type != 'text') {
629 csv_edihist_log("csv_newfile_list: incorrect type $type");
634 $dir_files = csv_dirfile_list ($type);
635 $csv_files = csv_processed_files_list ($type);
636 // $dir_files should come first in array_diff()
637 if (empty($dir_files)) {
638 // logic error -- fixed; if dir_files is empty, there are no files of that type
639 //$ar_new = $csv_files;
640 $ar_new = $dir_files;
642 $ar_new = array_diff($dir_files, $csv_files);
650 * Give the column headings for the csv files
652 * @param string $file_type -- one of our types batch|era|ibr|ebr|dpr|f277|f997, etc.
653 * @param string $csv_type -- one of 'file' or 'claim'
656 function csv_files_header($file_type, $csv_type) {
658 if (! strpos("|era|835|f997|999|ibr|ebr|dpr|f277|batch|837|ta1|ack", $file_type) ) {
659 csv_edihist_log("csv_files_header error: incorrect file type $file_type");
662 if (!strpos('|file|claim', $csv_type) ) {
663 csv_edihist_log("csv_files_header error: incorrect csv type $csv_type");
667 $ft = strpos('|277', $file_type) ?
'f277' : $file_type;
668 $ft = strpos('|835', $file_type) ?
'era' : $ft;
669 $ft = strpos('|837', $file_type) ?
'batch' : $ft;
670 $ft = strpos('|999|997|ack|ta1', $file_type) ?
'f997' : $ft;
672 $csv_hd_ar = array();
673 // actually, 'ack' and 'ta1' are probably redundant, since they are interpreted as 'f997'
674 $csv_hd_ar['ack']['file'] = array('Date', 'FileName', 'isa13', 'ta1ctrl', 'Code');
675 $csv_hd_ar['ebr']['file'] = array('Date', 'FileName', 'clrhsid', 'claim_ct', 'reject_ct', 'Batch');
676 $csv_hd_ar['ibr']['file'] = array('Date', 'FileName', 'clrhsid', 'claim_ct', 'reject_ct', 'Batch');
678 $csv_hd_ar['batch']['file'] = array('Date', 'FileName', 'Ctn_837', 'claim_ct', 'x12_partner');
679 $csv_hd_ar['ta1']['file'] = array('Date', 'FileName', 'Ctn_ta1', 'ta1ctrl', 'Code');
680 $csv_hd_ar['f997']['file'] = array('Date', 'FileName', 'Ctn_999', 'ta1ctrl', 'RejCt');
681 $csv_hd_ar['f277']['file'] = array('Date', 'FileName', 'Ctn_277', 'Accept', 'AccAmt', 'Reject', 'RejAmt');
682 $csv_hd_ar['era']['file'] = array('Date', 'FileName', 'Trace', 'claim_ct', 'Denied', 'Payer');
684 $csv_hd_ar['ebr']['claim'] = array('PtName','SvcDate', 'clm01', 'Status', 'Batch', 'FileName', 'Payer');
685 $csv_hd_ar['ibr']['claim'] = array('PtName','SvcDate', 'clm01', 'Status', 'Batch', 'FileName', 'Payer');
686 $csv_hd_ar['dpr']['claim'] = array('PtName','SvcDate', 'clm01', 'Status', 'Batch', 'FileName', 'Payer');
688 $csv_hd_ar['batch']['claim'] = array('PtName', 'SvcDate', 'clm01', 'InsLevel', 'Ctn_837', 'File_837', 'Fee', 'PtPaid', 'Provider' );
689 $csv_hd_ar['f997']['claim'] = array('PtName', 'SvcDate', 'clm01', 'Status', 'ak_num', 'File_997', 'Ctn_837', 'err_seg');
690 $csv_hd_ar['f277']['claim'] = array('PtName', 'SvcDate', 'clm01', 'Status', 'st_277', 'File_277', 'payer_name', 'claim_id', 'bht03_837');
691 $csv_hd_ar['era']['claim'] = array('PtName', 'SvcDate', 'clm01', 'Status', 'trace', 'File_835', 'claimID', 'Pmt', 'PtResp', 'Payer');
693 return $csv_hd_ar[$ft][$csv_type];
698 * Determine whether an array is multidimensional
701 * @return bool false if arrayis multidimensional
703 function csv_singlerecord_test ( $array ) {
704 // the two versions of count() are compared
705 // if the array has a sub-array, count recursive is greater
706 $is_sngl = count($array, COUNT_RECURSIVE
) == count( $array, COUNT_NORMAL
);
712 * A multidimensional array will be flattened to a single row.
714 * @param array $array array to be flattened
717 function csv_array_flatten($array) {
719 if (!is_array($array)) {return FALSE;}
721 foreach ($array as $key => $value) {
722 if (is_array($value)) {
723 $result = array_merge($result, csv_array_flatten($value));
725 $result[$key] = $value;
732 * Append rows to one of the csv record files.
734 * @uses csv_singlerecord_test()
735 * @uses csv_parameters()
736 * @uses csv_files_header()
737 * @param array $csv_data the data array, either file data or claim data
738 * @param string $file_type which of our file types to use
739 * @param string $csv_type either 'claim' or 'file'
740 * @return int number of characters written per fputcsv()
742 function csv_write_record($csv_data, $file_type, $csv_type) {
744 if (!is_array($csv_data)) { return FALSE;}
745 // use CSV_RECORD class to write ibr or ebr claims data to the csv file
746 // csv, batch, ibr, ebr, f997, or era
747 if (! strpos("|era|f997|ibr|ebr|dpr|f277|batch|ack", $file_type) ) {
748 csv_edihist_log("csv_write_record error: incorrect file type $file_type");
753 $ft = strpos("|835", $file_type) ?
'era' : $ft;
754 $ft = strpos("|837", $file_type) ?
'batch' : $ft;
755 $ft = strpos("|999|ack|ta1", $file_type) ?
'f997' : $ft;
757 $params = csv_parameters($ft);
759 if ($csv_type == "claim") {
760 $fp = $params['claims_csv'];
761 } elseif ($csv_type == "file") {
762 $fp = $params['files_csv'];
764 csv_edihist_log("csv_writedata_csv error: incorrect csv type $csv_type");
768 $fh = fopen( $fp, 'a');
769 // count characters written -- returned by fputcsv
771 // if we fail to open the file, return the result, expect FALSE
772 if (!$fh) { return FALSE; }
773 // test for a new file
774 if ( filesize($fp) === 0 ) {
775 $ar_h = csv_files_header($file_type, $csv_type);
777 if ($td === FALSE ||
$td === NULL ) {
778 // assume we have an empty file
779 // write header row if this is a new csv file
781 $indc +
= fputcsv ( $fh, $ar_h );
786 // test array for dimension counts
787 $is_sngl = csv_singlerecord_test($csv_data) ;
789 $indc +
= fputcsv ( $fh, $csv_data );
791 // multi-dimensional array -- we rely on array_flatten to
792 // assure us that the array depth is 1
793 foreach ($csv_data as $row) {
794 $wr = csv_array_flatten($row);
795 // $wr is false if $row is not an array
797 $indc +
= fputcsv ( $fh , $wr );
809 * Search a csv record file and return the row or values from selected columns
811 * This function requires that the $search_ar parameter be an array
812 * with keys ['s_val']['s_col']['r_cols'], and 'r_cols' is an array
813 * 's_val' is the search value, s_col is the column to check, r_cols is an array
814 * of column numbers from which values are returned. If r_cols is not an array,
815 * then the entire row will be returned. If the 'expect' parameter is 1, then
816 * the search will stop after the first success and return the result. Otherwise, the
817 * entire file will be searched.
818 * ex: csv_search_record('batch', 'claim', array('s_val'=>'20120115', 's_col'=>1, 'r_cols'=>array(0, 1, 2, 8)), "2" )
820 * @uses csv_parameters()
821 * @param string $file_type
822 * @param string $csv_type
823 * @param array $search_ar
824 * @param mixed $expect
827 function csv_search_record($file_type, $csv_type, $search_ar, $expect="1") {
829 if (! strpos("|era|f997|ibr|ebr|dpr|f277|batch|ack", $file_type) ) {
830 csv_edihist_log("csv_search_record: incorrect file type $file_type");
834 $params = csv_parameters($file_type);
836 if ($csv_type == "claim") {
837 $fp = $params['claims_csv'];
838 } elseif ($csv_type == "file") {
839 $fp = $params['files_csv'];
841 csv_edihist_log("csv_search_record: incorrect csv type $csv_type");
845 if (!is_array($search_ar) ||
array_keys($search_ar) != array('s_val', 's_col', 'r_cols')) {
846 csv_edihist_log("csv_search_record: invalid search criteria");
849 $sv = $search_ar['s_val'];
850 $sc = $search_ar['s_col'];
851 $rv = (is_array($search_ar['r_cols']) && count($search_ar['r_cols'])) ?
$search_ar['r_cols'] : 'all';
855 if (($fh1 = fopen($fp, "r")) !== FALSE) {
856 while (($data = fgetcsv($fh1)) !== FALSE) {
858 if ($data[$sc] == $sv) {
860 $ret_ar[$idx] = $data;
862 // now loop through the 'r_cols' array for data index
865 // make sure we don't access a non-existing index
866 if ($c >= $dct) { continue; }
868 $ret_ar[$idx][] = $data[$c];
872 if ($expect == '1') { break; }
877 csv_edihist_log("csv_search_record: failed to open $fp");
880 if (empty($ret_ar) ) {
888 * Search the 'claims' csv table for the patient control and find the associated file name
890 * In 'claims' csv tables, clm01 is position 2 number is pos 4, and filename is pos 5;
891 * except in ebr, ibr, and dpr files which have batch name in pos 4. See the
892 * csv files column headings for more information.
894 * @uses csv_parameters()
895 * @uses csv_pid_enctr_parse()
896 * @see csv_files_header()
897 * @param string patient control-- pid-encounter, pid, or encounter
898 * @param string filetype batch, era, f277, f997, ibr, ebr, dpr
899 * @param string search type encounter, pid, or ptctln
900 * @return array|bool [i](pid_encounter, number, filename) or false on error
902 function csv_file_with_pid_enctr ($ptctln, $filetype='batch', $srchtype='encounter' ) {
904 // return array of [i](pid_encounter, filename), there may be more than one file
907 csv_edihist_log("csv_file_with_pid_enctr: missing encounter data");
908 //return "invalid encounter data<br />" . PHP_EOL;
912 if (! strpos('|era|835|f997|999|ibr|ebr|dpr|f277|batch|837|ta1|ack', $filetype) ) {
913 csv_edihist_log("csv_file_with_pid_enctr: incorrect file type $filetype");
916 $params = csv_parameters($filetype);
917 //$fp = isset($params['claims_csv']) ? dirname(__FILE__).$params['claims_csv'] : false;
918 $fp = isset($params['claims_csv']) ?
$params['claims_csv'] : false;
920 csv_edihist_log("csv_file_with_pid_enctr: incorrect file type $filetype");
925 $enctr = trim($ptctln);
927 preg_match('/\D/', $enctr, $match2, PREG_OFFSET_CAPTURE
);
929 if (count($match2)) {
931 if ($srchtype != 'ptctln') {
932 $idar = csv_pid_enctr_parse($enctr);
933 if (is_array($idar) && count($idar)) {
934 $p = strval($idar['pid']);
936 $e = strval($idar['enctr']);
939 csv_edihist_log("csv_file_with_pid_enctr: error parsing pid_encounter $pid_enctr");
946 // no match from preg_match, so $enctr has no non-digit characer like '-'
947 if ($srchtype == 'ptctln') {
948 if (strlen($enctr) > IBR_ENCOUNTER_DIGIT_LENGTH
) {
949 $pe = substr($enctr, 0, strlen($enctr)-IBR_ENCOUNTER_DIGIT_LENGTH
) .'-'.substr($enctr, -IBR_ENCOUNTER_DIGIT_LENGTH
);
951 // no pid, so change search type to encounter only
952 $srchtype = 'encounter';
962 // in 'claims' csv tables, clm01 is position 2 and filename is position 5
963 if (($fh1 = fopen($fp, "r")) !== FALSE) {
964 if ($srchtype == 'encounter') {
965 while (($data = fgetcsv($fh1, 1024, ",")) !== FALSE) {
967 if (substr($data[2], -$elen) == $e) {
968 // since e=123 will match 1123 and 123
969 $peval = csv_pid_enctr_parse($data[2]);
970 if (is_array($peval) && count($peval)) {
971 if ($peval['enctr'] == $e) {
972 $ret_ar[] = array($data[2], $data[4], $data[5]);
977 } elseif ($srchtype == 'pid') {
978 while (($data = fgetcsv($fh1, 1024, ",")) !== FALSE) {
980 if (substr($data[2], 0, $plen) == $p) {
981 // since p=123 will match 1123 and 123
982 $peval = csv_pid_enctr_parse($data[2]);
983 if (is_array($peval) && count($peval)) {
984 if ($peval['pid'] == $p) {
985 $ret_ar[] = array($data[2], $data[4], $data[5]);
991 while (($data = fgetcsv($fh1, 1024, ",")) !== FALSE) {
993 if ($data[2] == $pe) {
994 $ret_ar[] = array($data[2], $data[4], $data[5]);
1000 csv_edihist_log("csv_file_with_pid_enctr: failed to open csv file ");
1007 * get the x12 file containing the control_num ISA13
1009 * The csv for x12 files 999, 277, 835, 837 has the control number in pos 2
1010 * and the filename in pos 1. This is a convenience function, since the actual
1011 * work is done by csv_search_record()
1013 * @uses csv_search_record()
1014 * @param string $control_num the interchange control number, isa13
1015 * @return string the file name
1017 function csv_file_by_controlnum($type, $control_num) {
1018 // get the batch file containing the control_num
1020 if (! strpos("|era|f997|f277|batch|ta1", $type) ) {
1021 csv_edihist_log("csv_file_by_controlnum: incorrect file type $type");
1024 // $search_ar should have keys ['s_val']['s_col'] array(['r_cols'][])
1025 // like "batch', 'claim, array(9, '0024', array(1, 2, 7))
1027 if ($type == 'era') {
1028 $ctln = trim(strval($control_num));
1030 $ctln = (strlen($control_num) >= 9) ?
substr($control_num, 0, 9) : trim(strval($control_num));
1032 $search = array('s_val'=>$ctln, 's_col'=>2, 'r_cols'=>array(1));
1033 $result = csv_search_record($type, 'file', $search, "1");
1034 if (is_array($result) && count($result[0]) == 1) {
1035 $fn = $result[0][0];
1041 * A function to try and assure the pid-encounter is correctly parsed
1043 * assume a format of pid-encounter, since that is sent in the OpenEMR x12 837
1044 * however, in case payer mangles the pid-encounter by dropping the separator,
1045 * check value and use IBR_ENCOUNTER_DIGIT_LENGTH constant
1047 * @param string $pid_enctr the value from element CPL01
1048 * return array array('pid' => $pid, 'enctr' => $enc)
1050 function csv_pid_enctr_parse( $pid_enctr ) {
1051 // evaluate the patient account field
1053 if (!$pid_enctr ||
!is_string($pid_enctr) ) {
1054 csv_edihist_log("csv_pid_enctr_parse: invalid argument");
1057 $pval = trim($pid_enctr);
1058 preg_match('/\D/', $pval, $match2, PREG_OFFSET_CAPTURE
);
1059 $inv_split = (count($match2)) ?
preg_split('/\D/', $pval, 2, PREG_SPLIT_NO_EMPTY
) : false;
1061 $pid = $inv_split[0];
1062 $enc = $inv_split[1];
1063 } elseif ( preg_match('/20[01]{1}[0-9]{1}(0[0-9]{1}|1[0-2]{1})[0-3]{1}[0-9]{1}/', $pval) ) {
1064 // encounter numbers can also be Ymd like 20110412
1068 $enc = (strlen($pval) >= IBR_ENCOUNTER_DIGIT_LENGTH
) ?
substr($pval, -IBR_ENCOUNTER_DIGIT_LENGTH
) : $pval;
1069 $pid = (strlen($pval) > IBR_ENCOUNTER_DIGIT_LENGTH
) ?
substr($pval, 0, (strlen($pval)-IBR_ENCOUNTER_DIGIT_LENGTH
)) : '';
1071 return array('pid' => $pid, 'enctr' => $enc);
1076 * This function is supposed to allow the downloading of a file.
1078 * Not used or tested -- do not use. Since the users cannot scan the directories,
1079 * the file to be downloaded would have to be selected from a csv table display
1080 * or some other listing produced by reading the directories.
1082 * @todo implement this function
1083 * @param string $filename
1084 * @return void --save file dialogue
1086 function csv_download_file( $filename ){
1087 // adapted from http://php.net/manual/en/function.header.php
1088 // phpnet at holodyn dot com 31-Jan-2011 01:01
1089 // Must be fresh start
1090 // ///////////////////// this function not used as of now and probably doesn't work
1091 //////////////////////////////////////////////////////////////////////////////////////
1092 // but a "view file" function will be made, probably as a separate page
1093 // links in csv file
1094 // <a href='edi_view_file.php?key=filename' target='_blank'>filename</a>
1095 // OpenEMR open log link: <a href='../../library/freeb/process_bills.log' target='_blank' class='link_submit' title=''>[View Log]</a>
1097 if( headers_sent() ) {
1098 csv_edihist_log("csv_download_file: error headers already sent");
1101 //FILTER_SANITIZE_URL
1102 //$filename = $_GET['dlkey'];
1104 $filename = filter_input(INPUT_GET
,'dlkey',FILTER_SANITIZE_STRING
);
1105 $fp = csv_check_filepath($filename);
1107 csv_edihist_log("csv_download_file: invalid filename for download $filename");
1108 //echo "csv_download_file: invalid filename for download $filename <br />" . PHP_EOL;
1109 return FALSE; // no -- httpd error code 504
1112 $file_html = csv_filetohtml($fp);
1115 $bn = basename($filename) . '.html';
1117 $host = $_SERVER['HTTP_HOST'];
1118 $uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
1119 header("Location: http://$host$uri/$extra");
1120 file_put_contents($host . $uri .DIRECTROY_SEPARATOR
. $bn, $file_html);
1121 $fsize = filesize($host . $uri .DIRECTROY_SEPARATOR
. $bn);
1125 csv_edihist_log("csv_download_file: file was not converted to html $filename");
1126 //echo "csv_download_file: file was not converted to html $filename <br />" . PHP_EOL;
1130 // Required for some browsers
1131 if(ini_get('zlib.output_compression'))
1132 ini_set('zlib.output_compression', 'Off');
1135 $ctype="application/pdf";
1137 header("Pragma: public"); // required
1138 header("Expires: 0");
1139 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
1140 header("Cache-Control: private",false); // required for certain browsers
1141 header("Content-Type: $ctype");
1142 header("Content-Disposition: attachment; filename=\"".basename($fp)."\";" );
1143 header("Content-Transfer-Encoding: binary");
1144 header("Content-Length: ".$fsize);
1155 * check the csv claims tables and return rows for a particular encounter
1157 * @uses csv_pid_enctr_parse()
1158 * @uses csv_file_with_pid_enctr()
1159 * @uses csv_table_select_list()
1160 * @uses csv_search_record()
1161 * @param string encounter number
1164 function csv_claim_history($encounter) {
1167 $enct = csv_pid_enctr_parse(strval($encounter));
1168 $e = ($enct) ?
$enct['enctr'] : false;
1172 return "invalid encounter value $encounter <br />".PHP_EOL
;
1174 // get complete pid-encounter from the batch claims record
1175 $efp = csv_file_with_pid_enctr($e);
1176 if (is_array($efp) && count($efp)) {
1179 csv_edihist_log("csv_claim_history: failed to locate $e in batch claims record");
1180 return "failed to locate $e in batch claims record";
1182 // use function csv_table_select_list() so that only
1183 // existing csv tables are queried
1184 $tbl2 = csv_table_select_list('array');
1186 if (is_array($tbl2) && count($tbl2) ) {
1187 foreach($tbl2 as $tbl) {
1188 $tp1 = explode(' ', $tbl['desc']);
1189 if ($tp1[1] == 'files') { continue; }
1190 if ($tp1[0] == '999' ||
$tp1[0] == '997' ||
$tp1[0] == '277') {
1193 } elseif ($tp1[0] == 'ibr' ||
$tp1[0] == 'ebr' ||
$tp1[0] == 'dpr') {
1195 $rtypes['prop'][] = $k;
1202 csv_edihist_log("csv_claim_history: failed to get csv table names");
1203 return "failed to get csv table names";
1206 $ch_html .= "<table class='clmhist' columns=4><caption>Encounter Record for $pe</caption>";
1207 $ch_html .= "<tbody>".PHP_EOL
;
1209 if (isset($rtypes['batch'])) {
1211 $srchar = array('s_val'=>$pe, 's_col'=>2, 'r_cols'=>'all');
1212 $btar = csv_search_record($tp, 'claim', $srchar, '2');
1214 $ch_html .= "<tr class='chhead'>".PHP_EOL
;
1215 $ch_html .= "<td>Name</td><td>SvcDate</td><td>CLM01</td><td>File</td>".PHP_EOL
;
1216 $ch_html .= "</tr>".PHP_EOL
;
1217 if (is_array($btar) && count($btar)) {
1218 foreach($btar as $ch) {
1219 $dt = substr($ch[1], 0, 4).'-'.substr($ch[1], 4, 2).'-'.substr($ch[1], 6, 2);
1220 //array('PtName', 'SvcDate', 'clm01', 'InsLevel', 'Ctn_837', 'File_837', 'Fee', 'PtPaid', 'Provider' );
1221 $ch_html .= "<tr class='chbatch'>".PHP_EOL
;
1223 $ch_html .= "<td>{$ch[0]}</td>".PHP_EOL
;
1224 $ch_html .= "<td>$dt</td>".PHP_EOL
;
1225 $ch_html .= "<td><a class='btclm' target='_blank' href='edi_history_main.php?fvbatch={$ch[5]}&btpid={$ch[2]}'>{$ch[2]}</a></td>".PHP_EOL
;
1226 $ch_html .= "<td title='{$ch[4]}'><a target='_blank' href='edi_history_main.php?fvkey={$ch[5]}'>{$ch[5]}</a></td>".PHP_EOL
;
1228 $ch_html .= "</tr>".PHP_EOL
;
1231 $ch_html .= "<tr class='chbatch'>".PHP_EOL
;
1232 $ch_html .= "<td colspan=4>Batch -- Nothing found for $pe in $tp record</td>".PHP_EOL
;
1233 $ch_html .= "</tr>".PHP_EOL
;
1237 if (isset($rtypes['f997'])) {
1239 $srchar = array('s_val'=>$pe, 's_col'=>2, 'r_cols'=>'all');
1240 $f997ar = csv_search_record($tp, 'claim', $srchar, '2');
1242 $ch_html .= "<tr class='chhead'>".PHP_EOL
;
1243 $ch_html .= "<td>Response</td><td>Status</td><td>File</td><td>Notes</td>".PHP_EOL
;
1244 $ch_html .= "</tr>".PHP_EOL
;
1245 if (is_array($f997ar) && count($f997ar)) {
1246 foreach($f997ar as $ch) {
1248 $msg = strlen($ch[7]) ?
$ch[7] : 'ST Number';
1249 //array('PtName', 'SvcDate', 'clm01', 'Status', 'ak_num', 'File_997', 'Ctn_837', 'err_seg');
1250 $ch_html .= "<tr class='chf997'>";
1251 $ch_html .= "<td>997/999</td>".PHP_EOL
;
1252 $ch_html .= "<td><a class='clmstatus' target='_blank' href='edi_history_main.php?fv997={$ch[5]}&aknum={$ch[4]}'>{$ch[3]}</a></td>".PHP_EOL
;
1253 $ch_html .= "<td><a target='_blank' href='edi_history_main.php?fvkey={$ch[5]}'>{$ch[5]}</a></td>".PHP_EOL
;
1254 $ch_html .= "<td title='$msg'>{$ch[6]} {$ch[4]}</td>".PHP_EOL
;
1255 $ch_html .= "</tr>".PHP_EOL
;
1258 $ch_html .= "<tr class='chf997'>";
1259 $ch_html .= "<td colspan=4>x12 999 -- Nothing found for $pe</td>".PHP_EOL
;
1260 $ch_html .= "</tr>".PHP_EOL
;
1264 if (isset($rtypes['f277'])) {
1267 $srchar = array('s_val'=>$pe, 's_col'=>2, 'r_cols'=>'all');
1268 $f277ar = csv_search_record($tp, 'claim', $srchar, '2');
1270 $ch_html .= "<tr class='chhead'>".PHP_EOL
;
1271 $ch_html .= "<td>Response</td><td>Status</td><td>File</td><td>ClaimID</td>".PHP_EOL
;
1272 $ch_html .= "</tr>".PHP_EOL
;
1273 if (is_array($f277ar) && count($f277ar)) {
1274 foreach($f277ar as $ch) {
1275 // array('PtName', 'SvcDate', 'clm01', 'Status', 'st_277', 'File_277', 'payer_name', 'claim_id', 'bht03_837');
1276 $ch_html .= "<tr class='chf277'>";
1278 $ch_html .= "<td>x12 277</td>".PHP_EOL
;
1279 $ch_html .= "<td><a class='clmstatus' target='_blank' href='edi_history_main.php?rspfile={$ch[5]}&pidenc={$ch[2]}&rspstnum={$ch[4]}'>{$ch[3]}</a></td>".PHP_EOL
;
1280 $ch_html .= "<td title='{$ch[5]}'><a target='_blank' href='edi_history_main.php?fvkey={$ch[5]}'>File</a></td>".PHP_EOL
;
1281 $ch_html .= "<td title='{$ch[6]}'>{$ch[7]}</td>".PHP_EOL
;
1283 $ch_html .= "</tr>".PHP_EOL
;
1286 $ch_html .= "<tr class='chf277'>";
1287 $ch_html .= "<td colspan=4>x12 277 -- Nothing found for $pe</td>".PHP_EOL
;
1288 $ch_html .= "</tr>".PHP_EOL
;
1292 if (is_array($rtypes['prop']) && count($rtypes['prop']) ) {
1293 foreach($rtypes['prop'] as $tp) {
1295 $rspnm = strtoupper($tp);
1296 $srchar = array('s_val'=>$pe, 's_col'=>2, 'r_cols'=>'all');
1297 $ibrar = csv_search_record($tp, 'claim', $srchar, '2');
1299 $ch_html .= "<tr class='chhead'>".PHP_EOL
;
1300 $ch_html .= "<td>Response</td><td>Status</td><td>File</td><td>Payer</td>".PHP_EOL
;
1301 $ch_html .= "</tr>".PHP_EOL
;
1302 if (is_array($ibrar) && count($ibrar)) {
1303 foreach($ibrar as $ch) {
1304 //array('PtName','SvcDate', 'clm01', 'Status', 'Batch', 'FileName', 'Payer');
1305 $ch_html .= "<tr class='ch$tp'>";
1307 $ch_html .= "<td>$rspnm</td>".PHP_EOL
;
1309 $ch_html .= "<td><a class='clmstatus' target='_blank' href='edi_history_main.php?dprfile={$ch[5]}&dprclm={$ch[2]}'>{$ch[3]}</a></td>".PHP_EOL
;
1311 $ch_html .= "<td><a class='clmstatus' target='_blank' href='edi_history_main.php?ebrfile={$ch[5]}&ebrclm={$ch[2]}&batchfile={$ch[4]}'>{$ch[3]}</a></td>".PHP_EOL
;
1313 $ch_html .= "<td title='{$ch[5]}'><a target='_blank' href='edi_history_main.php?fvkey={$ch[5]}'>File</a></td>".PHP_EOL
;
1314 $ch_html .= "<td>{$ch[6]}</td>".PHP_EOL
;
1316 $ch_html .= "</tr>".PHP_EOL
;
1319 $ch_html .= "<tr class='ch$tp'>";
1320 $ch_html .= "<td colspan=4>$rspnm -- Nothing found for $pe</td>".PHP_EOL
;
1321 $ch_html .= "</tr>".PHP_EOL
;
1326 if (isset($rtypes['era'])) {
1329 $srchar = array('s_val'=>$pe, 's_col'=>2, 'r_cols'=>'all');
1330 $eraar = csv_search_record($tp, 'claim', $srchar, '2');
1332 $ch_html .= "<tr class='chhead'>".PHP_EOL
;
1333 $ch_html .= "<td>Response</td><td>Status</td><td>Trace</td><td>Payer</td>".PHP_EOL
;
1334 $ch_html .= "</tr>".PHP_EOL
;
1335 if (is_array($eraar) && count($eraar)) {
1336 foreach($eraar as $ch) {
1338 $msg = $ch[6] .' '.$ch[7].' '.$ch[8];
1339 // array('PtName', 'SvcDate', 'clm01', 'Status', 'trace', 'File_835', 'claimID', 'Pmt', 'PtResp', 'Payer');
1340 $ch_html .= "<tr class='ch835'>";
1342 $ch_html .= "<td>x12 ERA</td>".PHP_EOL
;
1343 $ch_html .= "<td>{$ch[3]} <a class='clmstatus' target='_blank' href='edi_history_main.php?erafn={$ch[5]}&pidenc={$ch[2]}&summary=yes'>S</a> <a target='_blank' href='edi_history_main.php?erafn={$ch[5]}&pidenc={$ch[2]}&srchtp=encounter'>RA</a></td>".PHP_EOL
;
1344 $ch_html .= "<td><a target='_blank' href='edi_history_main.php?erafn={$ch[5]}&trace={$ch[4]}&srchtp=trace'>{$ch[4]}</a> <a target='_blank' href='edi_history_main.php?fvkey={$ch[5]}'>x12</a></td>".PHP_EOL
;
1345 $ch_html .= "<td title=$msg>{$ch[9]}</td>".PHP_EOL
;
1347 $ch_html .= "</tr>".PHP_EOL
;
1350 $ch_html .= "<tr class='ch835'>";
1351 $ch_html .= "<td colspan=4>x12 835 ERA -- Nothing found for $pe</td>".PHP_EOL
;
1352 $ch_html .= "</tr>".PHP_EOL
;
1356 // -- this is where a query on the payments datatable could be used to show if payment
1357 // has been received, even if no era file shows the payment.
1359 $ch_html .= "</tbody>".PHP_EOL
;
1360 $ch_html .= "</table>".PHP_EOL
;
1367 * Render one of our csv record files as an html table
1369 * This function determines the actual csv file from the file_type and the
1370 * csv_type. A percentage (default=100) of the csv file rows is selected
1371 * or the date field of each row is checked against the optional date parameters.
1373 * @uses csv_parameters()
1374 * @param string $file_type -- one of "|era|f997|ibr|ebr|dpr|f277|batch"
1375 * @param string $csv_type -- either "file" or "claim"
1376 * @param float $row_pct the percentage of the table to return (most recent)
1377 * @param string $datestart
1378 * @param string $dateend
1381 function csv_to_html($file_type, $csv_type, $row_pct = 1, $datestart='', $dateend='') {
1383 // read a csv file into an html table, using predefined stylesheet and javascript
1388 //echo "csv_to_html: $file_type $csv_type $row_pct $datestart $dateend <br />" .PHP_EOL;
1389 //<td><a class='btclm' target='_blank' href='edi_history_main.php?fvbatch={$val['batch']}&btpid={$val['pid']}'>{$val['pid']}</td>
1390 // <td><a class='clmstatus' target='_blank' href='edi_history_main.php?rspfile={$val['file_277']}&pidenc={$val['pid']}&rspstnum={$val['st_277']}'>{$val['status']}</td>
1392 if (! strpos("|era|f997|ibr|ebr|dpr|f277|batch|ack|ta1", $file_type) ) {
1393 csv_edihist_log("csv_to_html error: incorrect file type $file_type");
1394 $csv_html .= "csv_to_html error: incorrect file type $file_type <br />".PHP_EOL
;
1398 $params = csv_parameters($file_type);
1400 // csv tables date is given date or mtime in col 0 for file, date is service date in col 1 for claim
1401 $dtcol = ($csv_type == "file") ?
$params['datecolumn'] : '1';
1402 $fncol = ($csv_type == "file") ?
$params['fncolumn'] : '1';
1403 // but dpr files are only in the claims table, a special case
1404 if ($file_type == "dpr") { $fncol = $params['fncolumn']; }
1406 if ($csv_type == "claim") {
1407 //$fp = dirname(__FILE__).$params['claims_csv'];
1408 $fp = $params['claims_csv'];
1409 } elseif ($csv_type == "file") {
1410 //$fp = dirname(__FILE__).$params['files_csv'];
1411 $fp = $params['files_csv'];
1413 csv_edihist_log("csv_to_html error: incorrect csv type $csv_type");
1414 $csv_html .= "csv_to_html error: incorrect csv type $csv_type <br />".PHP_EOL
;
1417 // for using OpenEMR dynarch calendar, assume format of CCYY-MM-DD
1418 if (preg_match('/\d{4}-\d{2}-\d{2}/', $datestart) && preg_match('/\d{4}-\d{2}-\d{2}/', $dateend) ) {
1419 $ds = str_replace('-', '', $datestart);
1420 $de = str_replace('-', '', $dateend);
1421 if ( $de <= $ds) { $de = date("Ymd", time()); }
1425 /* comment datepicker format dates
1426 if (preg_match('/\d{2}\/\d{2}\/\d{4}/', $datestart) && preg_match('/\d{2}\/\d{2}\/\d{4}/', $dateend) ) {
1427 // we want a date range -- need a better regex
1428 // assume submit format /mm/dd/yyyy -- set in edih_view.php datepicker javascript
1429 $d1 = explode( "/", $datestart);
1430 $ds = $d1[2] . $d1[0] . $d1[1];
1431 $d1 = explode( "/", $dateend);
1432 $de = $d1[2] . $d1[0] . $d1[1];
1437 * end comment datepicker format dates
1440 $f_name = basename($fp);
1441 // open the file for read and read it into an array
1442 $fh = fopen($fp, "r");
1447 if ($fh !== FALSE) {
1448 while (($data = fgetcsv($fh, 1024, ",")) !== FALSE) {
1453 $isok = (substr($data[$dtcol], 0, 8) >= $ds) ?
TRUE : FALSE;
1454 $isok = (substr($data[$dtcol], 0, 8) > $de) ?
FALSE : $isok;
1456 if ($isok) { $csv_d[] = $data; }
1462 $csv_html .= "csv_to_html: failed to open $fp <br />".PHP_EOL
;
1466 // get the entire table
1467 if ($fh !== FALSE) {
1468 while (($data = fgetcsv($fh)) !== FALSE) {
1473 $csv_html .= "csv_to_html: failed to open $fp <br />".PHP_EOL
;
1478 $ln_ct = count($csv_d);
1479 // make sure row_pct is between 0 and 1
1480 if ($row_pct > 1 ||
$row_pct <= 0) { $row_pct = 1; }
1481 // only return the number of desired rows
1482 $rwct = (int)($ln_ct * $row_pct) +
1;
1483 $rwst = $ln_ct - $rwct;
1484 if ($rwst < 1) { $rwst = 1; $rwct = $ln_ct; }
1487 $csv_html .= "<h4>Table: $f_name Start Date: $datestart End Date: $dateend Rows: $rwct</h4>".PHP_EOL
;
1489 $csv_html .= "<h4>Table: $f_name Rows: $ln_ct Shown: $rwct</h4>".PHP_EOL
;
1492 $csv_html .= "<table id=\"csvTable\" class=\"csvDisplay\">".PHP_EOL
;
1493 // this is the body of the table
1495 if ($csv_type == 'file') {
1496 //['era']['file'] = array('Date', 'FileName', 'Trace', 'claim_ct', 'Denied', 'Payer');
1498 $csv_html .= '<thead>'.PHP_EOL
.'<tr>'.PHP_EOL
;
1499 foreach ($csv_d[0] as $h) { $csv_html .= "<th>$h</th>"; }
1500 $csv_html .= PHP_EOL
.'</tr>'.PHP_EOL
.'</thead>'.PHP_EOL
.'<tbody>'.PHP_EOL
;
1502 if ($file_type == 'era') {
1503 for ($i=$rwst; $i<$ln_ct; $i++
) {
1504 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1505 $csv_html .= "<tr class='{$bgc}'>".PHP_EOL
;
1506 foreach($csv_d[$i] as $idx=>$dta) {
1508 $csv_html .= "<td><a href='edi_history_main.php?fvkey=$dta' target='_blank'>$dta</a></td>".PHP_EOL
;
1509 } elseif ($idx == 2) {
1510 $fnm = $csv_d[$i][1];
1511 $csv_html .= "<td><a href='edi_history_main.php?erafn=$fnm&trace=$dta' target='_blank'>$dta</a></td>".PHP_EOL
;
1513 $csv_html .= "<td>$dta</td>".PHP_EOL
;
1516 $csv_html .= "</tr>".PHP_EOL
;
1518 } elseif ($file_type == 'f997') {
1520 // array('Date', 'FileName', 'Ctn_999', 'ta1ctrl', 'RejCt');
1521 for ($i=$rwst; $i<$ln_ct; $i++
) {
1522 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1523 $csv_html .= "<tr class=\"$bgc\">".PHP_EOL
;
1525 foreach($csv_d[$i] as $idx => $dta) {
1528 $ext = strtolower(substr($dta, -3));
1529 $csv_html .= "<td><a target=\"_blank\" href=\"edi_history_main.php?fvkey=$dta\">$dta</a> <a target=\"_blank\" href=\"edi_history_main.php?fvkey=$dta&readable=yes\">Text</a></td>".PHP_EOL
;
1530 } elseif ($idx == 3) {
1531 $csv_html .= "<td><a target=\"_blank\" href=\"edi_history_main.php?btctln=$dta\">$dta</a></td>".PHP_EOL
;
1532 } elseif ($idx == 4) {
1533 if ($ext == '999' ||
$ext == '997') {
1534 $csv_html .= "<td><a class=\"codeval\" target=\"_blank\" href=\"edi_history_main.php?fv997=$fnm&err997=$dta\">$dta</a></td>".PHP_EOL
;
1535 } elseif ($ext == 'ta1' ||
$ext == 'ack') {
1536 $csv_html .= "<td><a class=\"codeval\" target=\"_blank\" href=\"edi_history_main.php?ackfile=$fnm&ackcode=$dta\">$dta</a></td>".PHP_EOL
;
1538 $csv_html .= "<td>$dta</td>".PHP_EOL
;
1541 $csv_html .= "<td>$dta</td>".PHP_EOL
;
1544 $csv_html .= "</tr>".PHP_EOL
;
1546 } elseif ($file_type == 'ebr' ||
$file_type == 'ibr' ) {
1547 //['ibr']['file'] = array('Date', 'FileName', 'clrhsid', 'claim_ct', 'reject_ct', 'Batch');
1548 for ($i=$rwst; $i<$ln_ct; $i++
) {
1549 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1550 $fnm = $csv_d[$i][1];
1551 $btfile = $csv_d[$i][5];
1552 if (intval($csv_d[$i][4]) > 0) {
1553 $rejlink = "<td><a class=\"clmstatus\" target=\"_blank\" href=\"edi_history_main.php?ebrfile=$fnm&ebrclm=any\">{$csv_d[$i][4]}</a></td>";
1555 $rejlink = "<td>{$csv_d[$i][4]}</td>";
1558 $csv_html .= "<td>{$csv_d[$i][0]}</td>".PHP_EOL
;
1559 $csv_html .= "<td><a target=\"_blank\" href=\"edi_history_main.php?fvkey={$csv_d[$i][1]}\">{$csv_d[$i][1]}</a> <a target=\"_blank\" href=\"edi_history_main.php?fvkey={$csv_d[$i][1]}&readable=yes\">Text</a></td>".PHP_EOL
;
1560 $csv_html .= "<td>{$csv_d[$i][2]}</td>".PHP_EOL
;
1561 $csv_html .= "<td>{$csv_d[$i][3]}</td>".PHP_EOL
;
1562 $csv_html .= $rejlink.PHP_EOL
;
1563 $csv_html .= "<td><a target=\"_blank\" href=\"edi_history_main.php?fvkey=$btfile\">$btfile</a></td>".PHP_EOL
;
1565 $csv_html .= "</tr>".PHP_EOL
;
1569 // the generic case -- for 'file' type tables, the filename is in column 1, as set in the parameters array
1570 // see csv_parameters()
1571 // create header row here
1573 for ($i=$rwst; $i<$ln_ct; $i++
) {
1574 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1575 $csv_html .= "<tr class='{$bgc}'>";
1576 foreach($csv_d[$i] as $idx=>$dta) {
1577 if ($idx == $fncol) {
1578 $csv_html .= "<td><a href='edi_history_main.php?fvkey=$dta' target='_blank'>$dta</a></td>".PHP_EOL
;
1580 $csv_html .= "<td>$dta</td>".PHP_EOL
;
1583 $csv_html .= "</tr>".PHP_EOL
;
1586 } elseif ($csv_type == 'claim') {
1587 // a 'claim' type table $csv_type == 'claim' there is more variation
1588 if ($file_type == 'era') {
1589 // era csv_type is claim col 2 is pid, 3 encounter, 8 is trace
1590 //['era']['claim'] = array('PtName', 'SvcDate', 'clm01', 'Status', 'trace', 'File_835', 'claimID', 'Pmt', 'PtResp', 'Payer');
1591 //['era']['claim'] = array('PtName', 'SvcDate', 'clm01', 'Status', 'trace', 'File_835', 'claimID', 'Pmt', 'PtResp', 'Payer');
1592 $csv_html .= '<thead>'.PHP_EOL
.'<tr>'.PHP_EOL
;
1593 $csv_html .= '<th>Name</th><th>SvcDate</th><th>CLM01</th><th>Status</th><th>Trace</th><th>File</th><th>Payer</th>'.PHP_EOL
;
1594 $csv_html .= '</tr>'.PHP_EOL
.'</thead>'.PHP_EOL
.'<tbody>'.PHP_EOL
;
1595 for ($i=$rwst; $i<$ln_ct; $i++
) {
1596 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1597 $nm = $csv_d[$i][0];
1598 $dt = substr($csv_d[$i][1], 0, 4).'-'.substr($csv_d[$i][1], 4, 2).'-'.substr($csv_d[$i][1], 6, 2);
1599 $clm = $csv_d[$i][2];
1600 $sts = $csv_d[$i][3];
1601 $trc = $csv_d[$i][4];
1602 $fnm = $csv_d[$i][5];
1603 $clmid = $csv_d[$i][6];
1604 $msg = $csv_d[$i][6] .' '.$csv_d[$i][7].' '.$csv_d[$i][8];
1605 $pr = $csv_d[$i][9];
1606 $csv_html .= "<tr class='{$bgc}'>";
1608 $csv_html .= "<td>$nm</td>".PHP_EOL
;
1610 $csv_html .= "<td>$dt</td>".PHP_EOL
;
1612 $csv_html .= "<td><a class='btclm' target='_blank' href='edi_history_main.php?fvbatch=&btpid=$clm'>$clm</a></td>".PHP_EOL
;
1614 $csv_html .= "<td>$sts <a class='clmstatus' target='_blank' href='edi_history_main.php?erafn=$fnm&pidenc=$clm&summary=yes'>S</a> <a target='_blank' href='edi_history_main.php?erafn=$fnm&pidenc=$clm&srchtp=encounter'>RA</a></td>".PHP_EOL
;
1616 $csv_html .= "<td><a target='_blank' href='edi_history_main.php?erafn=$fnm&trace=$trc&srchtp=trace'>$trc</a></td>".PHP_EOL
;
1618 $csv_html .= "<td title=$fnm><a target='_blank' href='edi_history_main.php?fvkey=$fnm'>x12</a></td>".PHP_EOL
;
1620 $csv_html .= "<td title=$msg>$pr</td>".PHP_EOL
;
1622 $csv_html .= "</tr>".PHP_EOL
;
1624 } elseif ($file_type == 'dpr') {
1625 // dpr case, only file type is claim,
1626 //['dpr']['claim'] = array('PtName','SvcDate', 'clm01', 'Status', 'Batch', 'FileName', 'Payer');
1627 $csv_html .= '<thead>'.PHP_EOL
.'<tr>'.PHP_EOL
;
1628 $csv_html .= '<th>Name</th><th>SvcDate</th><th>CLM01</th><th>Status</th><th>Batch</th><th>File</th><th>Payer</th>'.PHP_EOL
;
1629 $csv_html .= '</tr>'.PHP_EOL
.'</thead>'.PHP_EOL
.'<tbody>'.PHP_EOL
;
1630 for ($i=$rwst; $i<$ln_ct; $i++
) {
1631 $dt = substr($csv_d[$i][1], 0, 4).'-'.substr($csv_d[$i][1], 4, 2).'-'.substr($csv_d[$i][1], 6, 2);
1632 $pidenc = $csv_d[$i][2];
1633 $btfile = $csv_d[$i][4];
1634 $fnm = $csv_d[$i][5];
1635 //$msg = $csv_d[$i][8];
1636 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1637 $csv_html .= "<tr class='{$bgc}'>";
1639 $csv_html .= "<td>{$csv_d[$i][0]}</td>".PHP_EOL
;
1641 $csv_html .= "<td>$dt</td>".PHP_EOL
;
1643 $csv_html .= "<td><a class='btclm' target='_blank' href='edi_history_main.php?fvbatch=$btfile&btpid=$pidenc'>$pidenc</a></td>".PHP_EOL
;
1645 $csv_html .= "<td><a class='clmstatus' target='_blank' href='edi_history_main.php?dprfile=$fnm&dprclm=$pidenc'>{$csv_d[$i][3]}</a></td>".PHP_EOL
;
1647 $csv_html .= "<td title=$btfile><a target='_blank'href='edi_history_main.php?fvkey=$btfile'>Batch</a></td>".PHP_EOL
;
1649 $csv_html .= "<td title=$fnm><a target='_blank'href='edi_history_main.php?fvkey=$fnm'>dpr File</a> <a target='_blank'href='edi_history_main.php?fvkey=$fnm&readable=yes'>Text</a></td>".PHP_EOL
;
1651 $csv_html .= "<td>{$csv_d[$i][6]}</td>".PHP_EOL
;
1653 $csv_html .= "</tr>".PHP_EOL
;
1656 } elseif ($file_type == 'ebr' ||
$file_type == 'ibr') {
1657 //array('PtName','SvcDate', 'clm01', 'Status', 'Batch', 'FileName', 'Payer');
1659 $csv_html .= '<thead>'.PHP_EOL
.'<tr>'.PHP_EOL
;
1660 $csv_html .= '<th>Name</th><th>SvcDate</th><th>CLM01</th><th>Status</th><th>Batch</th><th>File</th><th>Payer</th>'.PHP_EOL
;
1661 $csv_html .= '</tr>'.PHP_EOL
.'</thead>'.PHP_EOL
.'<tbody>'.PHP_EOL
;
1662 for ($i=$rwst; $i<$ln_ct; $i++
) {
1663 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1665 $dt = substr($csv_d[$i][1], 0, 4).'-'.substr($csv_d[$i][1], 4, 2).'-'.substr($csv_d[$i][1], 6, 2);
1666 $pidenc = $csv_d[$i][2];
1667 $btfile = $csv_d[$i][4];
1668 $fnm = $csv_d[$i][5];
1669 //$msg = $csv_d[$i][8];
1670 $csv_html .= "<tr class='{$bgc}'>";
1672 $csv_html .= "<td>{$csv_d[$i][0]}</td>".PHP_EOL
;
1674 $csv_html .= "<td>$dt</td>".PHP_EOL
;
1676 $csv_html .= "<td><a class='btclm' target='_blank' href='edi_history_main.php?fvbatch=$btfile&btpid=$pidenc'>$pidenc</a></td>".PHP_EOL
;
1678 $csv_html .= "<td><a class='clmstatus' target='_blank' href='edi_history_main.php?ebrfile=$fnm&ebrclm=$pidenc'>{$csv_d[$i][3]}</a></td>".PHP_EOL
;
1680 $csv_html .= "<td title=$btfile><a target='_blank' href='edi_history_main.php?fvkey=$btfile'>Batch</a></td>".PHP_EOL
;
1682 $csv_html .= "<td title=$fnm><a target='_blank'href='edi_history_main.php?fvkey=$fnm'>File</a> <a target='_blank'href='edi_history_main.php?fvkey=$fnm&readable=yes'>R</a></td>".PHP_EOL
;
1684 $csv_html .= "<td title=$msg>{$csv_d[$i][6]}</td>".PHP_EOL
;
1686 $csv_html .= "</tr>".PHP_EOL
;
1688 } elseif ($file_type == 'f997') {
1690 //['f997']['claim'] = array('PtName', 'SvcDate', 'clm01', 'Status', 'ak_num', 'File_997', 'Ctn_837', 'err_seg');
1691 $csv_html .= '<thead>'.PHP_EOL
.'<tr>'.PHP_EOL
;
1692 $csv_html .= '<th>Name</th><th>SvcDate</th><th>CLM01</th><th>Status</th><th>ST</th><th>File</th><th>Batch</th>'.PHP_EOL
;
1693 $csv_html .= '</tr>'.PHP_EOL
.'</thead>'.PHP_EOL
.'<tbody>'.PHP_EOL
;
1694 for ($i=$rwst; $i<$ln_ct; $i++
) {
1695 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1697 $dt = substr($csv_d[$i][1], 0, 4).'-'.substr($csv_d[$i][1], 4, 2).'-'.substr($csv_d[$i][1], 6, 2);
1698 $pidenc = $csv_d[$i][2];
1699 $akn = $csv_d[$i][4];
1700 $fnm = $csv_d[$i][5];
1701 $msg = strlen($csv_d[$i][7]) ?
$csv_d[$i][7] : 'ST Number';
1703 $csv_html .= "<tr class='{$bgc}'>";
1705 $csv_html .= "<td>{$csv_d[$i][0]}</td>".PHP_EOL
;
1707 $csv_html .= "<td>$dt</td>".PHP_EOL
;
1709 $csv_html .= "<td><a class='btclm' target='_blank' href='edi_history_main.php?fvbatch={$csv_d[$i][6]}&btpid=$pidenc'>$pidenc</a></td>".PHP_EOL
;
1711 $csv_html .= "<td><a class='clmstatus' target='_blank' href='edi_history_main.php?fv997=$fnm&aknum=$akn'>{$csv_d[$i][3]}</a></td>".PHP_EOL
;
1713 $csv_html .= "<td title='$msg'>$akn</td>".PHP_EOL
;
1715 $csv_html .= "<td><a target='_blank' href='edi_history_main.php?fvkey=$fnm'>$fnm</a></td>".PHP_EOL
;
1717 $csv_html .= "<td><a target='_blank' href='edi_history_main.php?btctln={$csv_d[$i][6]}'>{$csv_d[$i][6]}</a></td>".PHP_EOL
;
1719 $csv_html .= "</tr>".PHP_EOL
;
1721 } elseif ($file_type == 'f277') {
1723 //['f277']['claim'] = array('PtName', 'SvcDate', 'clm01', 'Status', 'st_277', 'File_277', 'payer_name', 'claim_id', 'bht03_837');
1724 $csv_html .= '<thead>'.PHP_EOL
.'<tr>'.PHP_EOL
;
1725 $csv_html .= '<th>Name</th><th>SvcDate</th><th>CLM01</th><th>Status</th><th>File</th><th>ClaimID</th><th>Batch</th>'.PHP_EOL
;
1726 $csv_html .= '</tr>'.PHP_EOL
.'</thead>'.PHP_EOL
.'<tbody>'.PHP_EOL
;
1727 for ($i=$rwst; $i<$ln_ct; $i++
) {
1728 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1729 $csv_html .= "<tr class='{$bgc}'>";
1731 $dt = substr($csv_d[$i][1], 0, 4).'-'.substr($csv_d[$i][1], 4, 2).'-'.substr($csv_d[$i][1], 6, 2);
1732 $btpid = $csv_d[$i][2];
1733 $f277file = $csv_d[$i][5];
1734 $clmid = $csv_d[$i][7];
1735 $bt_bht03 = $csv_d[$i][8];
1736 //$msg277 = (strlen($csv_d[$i][9])) ? $csv_d[$i][9] : '';
1738 $csv_html .= "<td>{$csv_d[$i][0]}</td>".PHP_EOL
;
1740 $csv_html .= "<td>$dt</td>".PHP_EOL
;
1742 $csv_html .= "<td><a class='btclm' target='_blank' href='edi_history_main.php?fvbatch=$bt_bht03&btpid=$btpid'>$btpid</a></td>".PHP_EOL
;
1744 $csv_html .= "<td><a class='clmstatus' target='_blank' href='edi_history_main.php?rspfile=$f277file&pidenc=$btpid&rspstnum={$csv_d[$i][4]}'>{$csv_d[$i][3]}</a></td>".PHP_EOL
;
1746 $csv_html .= "<td title='$f277file'><a target='_blank' href='edi_history_main.php?fvkey=$f277file'>File</a></td>".PHP_EOL
;
1748 $csv_html .= "<td>$clmid</td>".PHP_EOL
;
1750 $csv_html .= "<td title='$bt_bht03'><a target='_blank' href='edi_history_main.php?btctln=$bt_bht03'>Batch</a></td>".PHP_EOL
;
1752 $csv_html .= "</tr>".PHP_EOL
;
1754 } elseif ($file_type == 'batch') {
1756 //['batch']['claim'] = array('PtName', 'SvcDate', 'clm01', 'InsLevel', 'Ctn_837', 'File_837', 'Fee', 'PtPaid', 'Provider' );
1757 $csv_html .= '<thead>'.PHP_EOL
.'<tr>'.PHP_EOL
;
1758 $csv_html .= '<th>Name</th><th>SvcDate</th><th>CLM01</th><th>Ins</th><th>Fee/PtPd</th><th>File</th><th>Provider</th>'.PHP_EOL
;
1759 $csv_html .= '</tr>'.PHP_EOL
.'</thead>'.PHP_EOL
.'<tbody>'.PHP_EOL
;
1760 for ($i=$rwst; $i<$ln_ct; $i++
) {
1761 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1763 $dt = substr($csv_d[$i][1], 0, 4).'-'.substr($csv_d[$i][1], 4, 2).'-'.substr($csv_d[$i][1], 6, 2);
1764 $msg = $csv_d[$i][6].' ('.$csv_d[$i][7].')';
1765 $btfile = $csv_d[$i][5];
1767 $csv_html .= "<tr class='{$bgc}'>";
1769 $csv_html .= "<td>{$csv_d[$i][0]}</td>".PHP_EOL
;
1771 $csv_html .= "<td>$dt</td>".PHP_EOL
;
1773 $csv_html .= "<td><a class='btclm' target='_blank' href='edi_history_main.php?fvbatch=$btfile&btpid={$csv_d[$i][2]}'>{$csv_d[$i][2]}</a></td>".PHP_EOL
;
1775 $csv_html .= "<td>{$csv_d[$i][3]}</td>".PHP_EOL
;
1777 $csv_html .= "<td>$msg</td>".PHP_EOL
;
1779 $csv_html .= "<td><a target='_blank' href='edi_history_main.php?fvkey=$btfile'>$btfile</a></td>".PHP_EOL
;
1781 $csv_html .= "<td>{$csv_d[$i][8]}</td>".PHP_EOL
;
1783 $csv_html .= "</tr>".PHP_EOL
;
1787 $csv_html .= '<thead>'.PHP_EOL
.'<tr>';
1788 foreach ($csv_d[0] as $h) { $csv_html .= "<th>$h</th>"; }
1789 $csv_html .= '</tr>'.PHP_EOL
.'</thead>'.PHP_EOL
.'<tbody>'.PHP_EOL
;
1791 for ($i=$rwst; $i<$ln_ct; $i++
) {
1792 $bgc = ($i %
2 == 1 ) ?
'odd' : 'even';
1793 $csv_html .= "<tr class='{$bgc}'>";
1794 foreach($csv_d[$i] as $idx=>$dta) {
1795 $csv_html .= "<td>$dta</td>".PHP_EOL
;
1797 $csv_html .= "</tr>".PHP_EOL
;
1800 } // end body of the table
1801 //$csv_html .= "</tbody>".PHP_EOL."</table>".PHP_EOL."</div>".PHP_EOL;
1802 $csv_html .= "</tbody>".PHP_EOL
."</table>".PHP_EOL
;
1807 * Produce an html rendition of one of our files
1809 * this function accepts a file name array from uploads.php, one file only,
1810 * or a string file path as the filepath argument
1812 * @uses csv_check_filepath()
1813 * @uses csv_parameters()
1814 * @uses csv_x12_segments()
1815 * @param mixed $filepath string or array path to or name of one of our files
1816 * @return string html formatted
1818 function csv_filetohtml ($filepath) {
1820 if (is_array($filepath) && count($filepath) > 0) {
1821 $ftkey = array_keys($filepath);
1823 $ftestpath = $filepath[$type][0];
1824 $bn = basename($ftestpath);
1826 $bn = basename($filepath);
1827 $params = csv_parameters("ALL");
1829 foreach($params as $ky=>$val) {
1830 if ( !$params[$ky]['regex'] ) { continue; }
1831 if (!preg_match($params[$ky]['regex'], $bn) ) {
1834 $type = $params[$ky]['type'];
1835 //$ftestpath = dirname(__FILE__) . $params[$ky]['directory'].DIRECTORY_SEPARATOR.$bn;
1836 $ftestpath = $params[$ky]['directory'].DIRECTORY_SEPARATOR
.$bn;
1843 if (!isset($type) ) {
1844 csv_edihist_log("csv_filetohtml: failed to type $bn");
1845 $out_str = "csv_filetohtml: failed to classify $bn <br />". PHP_EOL
;
1849 $fp = csv_check_filepath($ftestpath, $type);
1851 csv_edihist_log("csv_filetohtml: could not get good path for $bn");
1852 $out_str = "csv_filetohtml: could not get good path for $bn <br />". PHP_EOL
;
1855 // different file types
1856 if (strpos("|batch|era|f277|f997|999|837|835|ta1", (string)$type) ) {
1858 $seg_ar = csv_x12_segments($fp, $type);
1859 if (is_array($seg_ar) && count($seg_ar['segments']) ) {
1860 $txt_ar = $seg_ar['segments'];
1861 $seg_d = $seg_ar['delimiters']['t'];
1864 csv_edihist_log("csv_filetohtml: did not get segments for $bn");
1865 $out_str = "csv_filetohtml: did not get segments for $bn <br />". PHP_EOL
;
1869 } elseif (strpos("|ibr|ebr|dpr|ack", $type) ) {
1870 // clearinghouse file types (newlines)
1871 $fh = fopen($fp, 'r');
1873 while (($buffer = fgets($fh, 1024)) !== false) {
1874 $txt_ar[] = $buffer;
1877 csv_edihist_log("csv_filetohtml: failed to open $bn <br />");
1882 csv_edihist_log("csv_filetohtml: did not get lines for $bn");
1883 $out_str = "csv_filetohtml: did not get lines for $bn <br />". PHP_EOL
;
1886 } elseif (strpos("|text", $type) ) {
1887 // clearinghouse readable versions
1888 $txt_ar = file_get_contents($fp);
1891 csv_edihist_log("csv_filetohtml: did not get contents for $bn");
1892 $out_str = "csv_filetohtml: did not get contents for $bn <br />". PHP_EOL
;
1897 csv_edihist_log("csv_filetohtml: $type was not matched for $bn");
1898 $out_str = "csv_filetohtml: $type was not matched for $bn <br />". PHP_EOL
;
1901 // we have navigated our checks and read the file
1904 // now prepare the html page
1906 // use an ordered list format for x12 and ebr/ibr, regular text for text type
1907 if ($fltp == "text") {
1908 $out_str .= "<h4>$bn</h4>
1909 <div class=\"filetext\">
1912 $out_str .= $txt_ar;
1915 } elseif ($fltp == 'x12') {
1916 $out_str .= "<h4>$bn</h4>
1917 <div class=\"filetext\">
1920 foreach($txt_ar as $line) {
1932 $out_str .= "<h4>$bn</h4>
1933 <div class=\"filetext\">
1936 foreach($txt_ar as $line) {
1958 * Check that the file path we are working with is a readable file.
1960 * If it is a file we have uploaded and we have only the file name
1961 * this function will type the file and find it in the uploaded files directories
1962 * and return the complete path.
1964 * @uses csv_parameters()
1965 * @param string $filename name of a file that is one of our types
1966 * @param string $type optional; one of our file types
1967 * @return string either an empty string or a readable filepath
1969 function csv_check_filepath($filename, $type = "ALL") {
1971 // if file is readable, just return it
1972 if ( is_file($filename) && is_readable($filename) ) {
1977 $fn = basename($filename);
1979 if ($type != "ALL") {
1980 $p = csv_parameters($type);
1981 if (is_array($p) && array_key_exists('type', $p) ) {
1983 $fp = $p['directory'].DIRECTORY_SEPARATOR
.$fn;
1984 if ( is_file($fp) && is_readable($fp) ) {
1988 csv_edihist_log("csv_check_filepath: invalid type $type");
1991 $p_ar = csv_parameters("ALL");
1992 foreach ($p_ar as $tp=>$par) {
1994 if ( !$p_ar[$tp]['regex'] ||
!preg_match($p_ar[$tp]['regex'], $fn) ) {
1998 $fp = $p_ar[$tp]['directory'].DIRECTORY_SEPARATOR
.$fn;
1999 if ( is_file($fp) && is_readable($fp) ) {
2011 * Verify readibility and check for some expected content.
2013 * @uses csv_check_filepath()
2014 * @param string $file_path full path to file
2015 * @param string $type one of our file types
2016 * @param bool $val_array optional; default is false, whether to return filepath only
2017 * or array(filepath, next_segment)
2018 * @return string|array string file path or array if valid, otherwise 'false'
2020 function csv_verify_file( $file_path, $type, $val_array=FALSE ) {
2021 // check whether $file_path actually leads to a plausible x12 file
2022 // and supply proper directory if needed
2023 $fp = csv_check_filepath($file_path, $type);
2025 // verify that the file is correct format by checking the first ST segment
2028 $type = strtolower($type);
2030 if ($type == "batch" ||
$type == "837") { $st_str = "ST*837"; $next_segment = "GS"; $slen = 250; }
2031 if ($type == "era" ||
$type == "835") { $st_str = "ST*835"; $next_segment = "GS"; $slen = 250; }
2032 if ($type == "997" ||
$type == "f997") { $st_str = "ST*997"; $next_segment = "TA1"; $slen = 250; }
2033 if ($type == "999" ||
$type == "f999") { $st_str = "ST*999"; $next_segment = "TA1"; $slen = 250; }
2034 if ($type == "277" ||
$type == "f277") { $st_str = "ST*277"; $next_segment = "GS"; $slen = 250; }
2035 if ($type == "271" ||
$type == "f271") { $st_str = "ST*271"; $next_segment = "GS"; $slen = 250; }
2036 if ($type == "ta1") { $st_str = "TA1*"; $next_segment = "TA1"; $slen = 200; }
2037 // note the ebr, ibr, dpr ack checks will not be valid for years < 2010 or > 2019
2038 if ($type == "ebr") { $st_str = "1|201"; $slen = 10; }
2039 if ($type == "ibr") { $st_str = "1|201"; $slen = 10; }
2040 if ($type == "dpr") { $st_str = "DPR|201"; $slen = 10; }
2041 if ($type == "ack") { $st_str = "1|201"; $slen = 10; }
2042 if ($type == "text") { $st_str = "Date Received"; $slen = 800; }
2043 // for proprietary file formats, if we have a list of clearinghouses,
2044 // the $st_str could be "Availity|Emdeon|ABC " etc. and name probably found in the first 100 characters
2045 // instead of Date Received, which I just guess will be standard and within the first 500 characters
2046 $f_str = file_get_contents($fp, FALSE, NULL, 0, $slen);
2047 $st_pos = strpos($f_str, $st_str);
2049 // special check for 997/999 types, since 999 may be type 997
2050 if (($type == "997" ||
$type == "f997") && preg_match('/\.999$/', $fp) ) {
2051 $st_pos = strpos($f_str, "ST*999");
2052 $next_segment = "TA1";
2054 //$f_str = file_get_contents($fp);
2055 //$st_pos = strpos(substr($f_str, 0, $slen), $st_str);
2056 if ( $st_pos === FALSE ) {
2057 // did not find the magic word
2058 csv_edihist_log ("csv_verify_file: Error, not a valid $type file: $file_path");
2059 //echo "ibr_era_check_path Error, not a valid $type file: $file_path <br />"
2061 $next_segment = FALSE;
2067 return array($fp, $next_segment);
2074 * Parse Availity ebr, ibr, or dpr file to an array
2076 * This function will return a multidimensional array that is indexed per line of the file
2077 * and another array of each field or element in the line. It uses the
2078 * constant IBR_DELIMITER as the element delimiter
2080 * @param string $file_path complete path to file
2081 * @return array multidimensional array
2083 function csv_ebr_filetoarray ($file_path ) {
2084 // read the ibr, ebr, dpr file into an array of arrays
2085 // since the file is multi-line, use fgets()
2087 $ext = substr($file_path, -3);
2088 $fp = csv_verify_file( $file_path, $ext);
2090 csv_edihist_log("csv_ebr_filetoarray: failed to verify $file_path");
2094 $fh = fopen($fp, 'r');
2096 while (($buffer = fgets($fh, 4096)) !== false) {
2097 $ar_ibr[] = explode ( IBR_DELIMITER
, trim($buffer) );
2101 csv_edihist_log( "csv_ebr_filetoarray Error: failed to read " . $file_path );
2109 * Parse an x12 segment text into an array.
2111 * @param string $sgmt_str -- a substring of all or part of a segment
2112 * @param string $seg_term -- segment delimiter default is "~"
2113 * @param string $elem_delim -- element delimiter default is "*"
2114 * @return array -- exploded $sgmt_str by $element_d
2116 function csv_x12_segment_to_array($sgmt_str, $seg_term = "~", $elem_delim = "*") {
2118 // allow for imprecise selecting of segment strings
2120 $slen = strlen($sgmt_str);
2121 if (!$slen) { return FALSE; }
2122 if (!strpos($sgmt_str, $elem_delim)) { return FALSE; }
2123 // find segment delimiters (up to two)
2124 $p1 = strpos($sgmt_str, $seg_term);
2125 $p2 = ($p1) ?
strpos($sgmt_str, $seg_term, $p1+
1 ) : FALSE;
2127 // assume we have just the segment text
2128 $seg1 = trim($sgmt_str);
2129 } elseif ($p1 && $p2 && ($p2 > $p1) && ($p2-$p1 < $slen) ) {
2130 // assume we have end of segment ~ segment ~ begining of next segment
2131 $seg1 = substr($sgmt_str, $p1+
1, $p2-$p1-1);
2132 } elseif ($p1 !== FALSE && $p1 == 0) {
2133 // assume we have ~segment
2134 $seg1 = substr($sgmt_str, $p1+
1);
2135 } elseif ($p1 !== FALSE && $p1+
1 == $slen ) {
2136 // assume we have segment~
2137 $seg1 = substr($sgmt_str, 0, $p1-1);
2138 } elseif ($p1 !== FALSE && $p1+
1 < $slen ) {
2139 // assume we have segment~ start of segment
2140 $seg1 = substr($sgmt_str, 0, $p1-1);
2142 // no conjecture matched, just use it
2143 $seg1 = trim($sgmt_str);
2146 $ar_seg = explode ($elem_delim, $seg1 );
2153 * Extract x12 delimiters from the ISA segment
2155 * There are obviously easier/faster ways of doing this, but I wanted to be able
2156 * to possibly extract these needed values from malformed or mishandled
2157 * files, so we go character by character. The array returned is empty on error, otherwise:
2159 * array('t'=>segment terminator, 'e'=>element delimiter,
2160 * 's'=>sub-element delimiter, 'r'=>repetition delimiter)
2163 * @param string $isa_str126 first 126 characters of x12 file
2164 * @param string $next_segid the segment ID immediately following ISA segment
2165 * @return mixed array or false on error
2167 function csv_x12_delimiters($isa_str126, $next_segid) {
2168 // this function reads the ISA segment and into the next segment of
2169 // an x12 file, to determine the delimiters,
2170 // ISA segment is 106 characters, 16 elements, so the $next_segid could be dispensed with
2172 if (substr($isa_str126, 0, 3) != "ISA") {
2173 // not the starting 126 characters
2174 csv_edihist_log("csv_x12_delimiters Error: isa_str126 does not begin with ISA");
2177 if (! strpos($isa_str126, $next_segid) ) {
2178 // not the starting 126 characters
2179 csv_edihist_log("csv_x12_delimiters Error: next_segment $next_segid not in isa_str126 ");
2182 // $ns_pos = strpos($isa_str126, $next_segid);
2183 // $elem_pos = strrpos (substr($isa_str126, 0, $ns_pos-1), $elem_delim);
2184 // $dstr = substr($isa_str126, $elem_pos, $ns_pos-1);
2188 $seg2_len = strlen($next_segid); // usually "GS" but could be "TA1" or whatever the specification says
2189 $rep_d = ""; // repetition delimiter ISA11 5010A1 - per Availity EDI guide
2191 $elem_delim = substr($isa_str126, 3, 1); // ISA*
2193 $chars = strlen($isa_str126);
2195 for ($i = 0; $i < $chars; $i++
) {
2196 if (strlen($s) >= 3 && substr($s, -$seg2_len) == $next_segid) { break; }
2197 $c = substr($isa_str126, $i, 1);
2198 if ($c == $elem_delim) {
2199 if ($delim_ct == 11) { $rep_d = substr($s, 1, 1); }
2205 // there are 16 elements in ISA segment
2206 if ($delim_ct > 16) {
2207 // incorrect $next_segid argument
2208 csv_edihist_log("csv_x12_delimiters: incorrect next_segment $next_segid does not follow ISA");
2212 if (strlen($s) >= 5) {
2213 $ret_ar["t"] = $s[2];
2214 $ret_ar["e"] = $s[0];
2215 $ret_ar["s"] = $s[1];
2216 $ret_ar["r"] = $rep_d;
2218 csv_edihist_log("csv_x12_delimiters: Invalid delimiters $s");
2224 * from php help: tleffler [AT] gmail [DOT] com 12-May-2011 08:55
2226 * Not used, but possibly interesting. Thought is to pass a file handle as an argument
2227 * @param mixed $possibleResource
2230 function isResource ($possibleResource) { return !is_null(@get_resource_type
($possibleResource)); }
2233 * Parse x12 file into array of segments.
2235 * This function relies on csv_x12_delimiters() to get the delimiters array
2236 * and on csv_verify_file() to supply the next_segment value.
2237 * There are some basic verifications and failures are noted in the log.
2239 * 'path'=>pathtofile
2240 * 'delimiters'=>array from x12_delimiters()
2241 * 'segments'=>segments[i]=>segment text
2242 * if $seg_array is true then segments[i]=>array of elements
2245 * @uses csv_x12_delimiters()
2246 * @uses csv_verify_file()
2247 * @param string $file_path the full path for the file
2248 * @param string $type one of batch|837|era|835|997|999|277|271
2249 * @param bool $seg_array whether each segment should be made into an array of elements
2250 * @return array|bool array['delimiters']['segments']['path'], or false on error
2252 function csv_x12_segments($file_path, $type, $seg_array = FALSE) {
2254 $fp_ar = csv_verify_file($file_path, $type, TRUE );
2256 if (!$fp_ar ||
!$fp_ar[0]) {
2257 csv_edihist_log ("csv_x12_segments: verification failed for $file_path");
2264 $next_segment = $fp_ar[1];
2265 $f_str = file_get_contents($fp);
2267 // verify $delimiters
2268 $delimiters = csv_x12_delimiters(substr($f_str,0,126), $next_segment);
2270 // here, expect $delimiters['t'] ['e'] ['s'] ['r']
2271 if (is_array($delimiters) && array_keys($delimiters) == array('t', 'e', 's', 'r') ) {
2273 $seg_d = $delimiters['t'];
2274 $elem_d = $delimiters['e'];
2275 $subelem_d = $delimiters['s'];
2276 $rep_d = $delimiters['r'];
2278 csv_edihist_log ("csv_x12_segments: invalid delimiters or delimiters wrong for $fp");
2282 // OK, now initialize variables
2283 $fn = basename($fp);
2285 $ar_seg['path'] = $fp;
2286 $ar_seg['delimiters'] = $delimiters;
2287 $ar_seg['segments'] = array();
2288 $seg_pos = 0; // position where segment begins
2289 $st_segs_ct = 0; // segments in ST-SE envelope
2290 $se_seg_ct = ""; // segment count from SE segment
2291 $isa_segs_ct = 0; // segments in ISA envelope
2292 $isa_ct = 0; // ISA envelope count
2293 $iea_ct = 0; // IEA count
2294 $trnset_seg_ct = 0; // segments by sum of isa segment count
2296 $isa_str = "ISA".$elem_d; // to reduce evaluations
2297 $iea_str = "IEA".$elem_d;
2298 $st_str = "ST".$elem_d;
2299 $se_str = "SE".$elem_d;
2305 // extract each segment from the file text
2306 $seg_end = strpos($f_str, $seg_d, $seg_pos);
2307 $moresegs = strpos($f_str, $seg_d, $seg_end+
1);
2309 $seg_text = substr($f_str, $seg_pos, $seg_end-$seg_pos);
2310 $seg_pos = $seg_end +
1;
2312 // we trim in case there are line or carriage returns
2313 $seg_text = trim($seg_text);
2315 // check for non ASCII basic characters. Note reg_ex '/[^\x20-\xFF]/' allows extended ASCII characters
2316 // this is partly file syntax and partly protection -- we don't want to process an imposter
2317 // We are mostly concerned with \x00 to \x19, the "control" characters, but apparently some are allowed
2319 if (preg_match_all('/[^\x20-\x7E]/', $seg_text, $matches)) {
2320 csv_edihist_log ("csv_x12_segments: Non-basic ASCII character in segment ($idx) in file $fn");
2321 // quit here? return false; -- actually files have probably been scanned before in upload.php
2322 // also x12 files have more allowed characters than these
2325 $ar_seg['segments'][] = explode($elem_d, $seg_text);
2327 $ar_seg['segments'][] = $seg_text;
2332 // some checks, if wanted
2333 if (substr($seg_text, 0, 4) == $isa_str) {
2334 $isa_seg = explode($elem_d, $seg_text);
2335 $isa_id = $isa_seg[13];
2341 if (substr($seg_text, 0, 3) == $st_str) {
2342 // $e = strpos($seg_text, $elem_d, 8); // ST*835* is 7 characters
2343 // $st02 = substr($seg_text, 7, $e-7);
2344 $st_ar = explode($elem_d, $seg_text);
2345 $st_num = $st_ar[2];
2349 if (substr($seg_text, 0, 3) == $se_str) {
2350 $se_ar = explode($elem_d, $seg_text);
2351 $se_seg_ct = $se_ar[1];
2352 $se_num = $se_ar[2];
2353 if ($se_num != $st_num) {
2354 csv_edihist_log ("csv_x12_segments: ST-SE number mismatch $st_num $se_num in $fn");
2356 if (intval($se_seg_ct) != $st_segs_ct) {
2357 csv_edihist_log ("csv_x12_segments: ST-SE segment count mismatch $st_segs_ct $se_seg_ct in $fn");
2361 if (substr($seg_text, 0, 4) == $iea_str) {
2362 $iea_seg = explode($elem_d, $seg_text);
2363 $iea_id = $iea_seg[2];
2366 if ($isa_id != $iea_id) {
2367 csv_edihist_log ("csv_x12_segments: ISA-IEA identifier mismatch set $iea_ct in $fn");
2369 if ($iea_ct == $isa_ct) {
2370 $trnset_seg_ct +
= $isa_segs_ct;
2371 if ($idx+
1 != $trnset_seg_ct ) { //
2372 csv_edihist_log ("csv_x12_segments: IEA segment count error ({idx+1}:$trnset_seg_ct set) $iea_ct in $fn");
2375 csv_edihist_log ("csv_x12_segments: ISA-IEA count mismatch set $isa_ct $iea_ct in $fn");