use locale for check date, deposit date (#2436)
[openemr.git] / library / edi.inc
blob9d703970d9574e7576ba508a87fb1c4968dbb7bb
1 <?php
2 /**
3  * Inc file for the 270 / 271 creation and uploading
4  *
5  * This program creates the segments for the x12 270 eligibility file
6  * It also allows the reading and storing of the x12 271 file
7  *
8  * @package   OpenEMR
9  * @link      http://www.open-emr.org
10  * @author    Terry Hill <terry@lilysystems.com>
11  * @author    Brady Miller <brady.g.miller@gmail.com>
12  * @author    Jerry Padgett <sjpadgett@gmail.com>
13  * @copyright Copyright (c) 2010 MMF Systems, Inc
14  * @copyright Copyright (c) 2016 Terry Hill <terry@lillysystems.com>
15  * @copyright Copyright (c) 2017 Brady Miller <brady.g.miller@gmail.com>
16  * @copyright Copyright (c) 2019 Jerry Padgett <sjpadgett@gmail.com>
17  * @license   https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
18  */
19 require_once("$srcdir/edihistory/codes/edih_271_code_class.php");
21 use OpenEMR\Common\Http\oeHttp;
22 use OpenEMR\Common\Utils\RandomGenUtils;
24 // @TODO global to become private var when this goes to a class.
26 global $X12info;
28 // SEGMENT FUNCTION START
30 // ISA Segment  - EDI-270 format
32 function create_ISA($row, $X12info, $segTer, $compEleSep)
34     $ISA     =  array();
35     $ISA[0] = "ISA"; // Interchange Control Header Segment ID
36     $ISA[1] = "00";  // Author Info Qualifier
37     $ISA[2] = str_pad("0000000", 10, " ");        // Author Information
38     $ISA[3] = "00"; //   Security Information Qualifier
39                     //   MEDI-CAL NOTE: For Leased-Line & Dial-Up use '01',
40                     //   for BATCH use '00'.
41                     //   '00' No Security Information Present
42                     //   (No Meaningful Information in I04)
43     $ISA[4] = str_pad("0000000000", 10, " ");         // Security Information
44     $ISA[5] = str_pad($X12info['x12_isa05'], 2, " ");              // Interchange ID Qualifier
45     $ISA[6] = str_pad($X12info['x12_sender_id'], 15, " ");      // INTERCHANGE SENDER ID
46     $ISA[7] = str_pad($X12info['x12_isa07'], 2, " ");              // Interchange ID Qualifier
47     $ISA[8] = str_pad($X12info['x12_receiver_id'], 15, " ");      // INTERCHANGE RECEIVER ID
48     $ISA[9] = str_pad(date('ymd'), 6, " ");       // Interchange Date (YYMMDD)
49     $ISA[10] = str_pad(date('Hi'), 4, " ");       // Interchange Time (HHMM)
50     $ISA[11] = "^";                                 // Interchange Control Standards Identifier
51     $ISA[12] = str_pad("00501", 5, " ");          // Interchange Control Version Number
52     $ISA[13] = str_pad("000000001", 9, " ");      // INTERCHANGE CONTROL NUMBER
53     $ISA[14] = str_pad($X12info['x12_isa14'], 1, " ");              // Acknowledgment Request [0= not requested, 1= requested]
54     $ISA[15] =  str_pad($X12info['x12_isa15'], 1, " ");                 // Usage Indicator [ P = Production Data, T = Test Data ]
55     $ISA['Created'] = implode('*', $ISA);       // Data Element Separator
56     $ISA['Created'] = $ISA['Created'] ."*";
57     $ISA['Created'] = $ISA ['Created'] . $compEleSep . $segTer;
59     return trim($ISA['Created']);
61 // GS Segment  - EDI-270 format
62 function create_GS($row, $X12info, $segTer, $compEleSep)
64     $GS    = array();
65     $GS[0] = "GS";                      // Functional Group Header Segment ID
66     $GS[1] = "HS";                      // Functional ID Code [ HS = Eligibility, Coverage or Benefit Inquiry (270) ]
67     $GS[2] =  $X12info['x12_sender_id'];              // Application Sender's ID
68     $GS[3] =  $X12info['x12_receiver_id'];              // Application Receiver's ID
69     $GS[4] = date('Ymd');               // Date [CCYYMMDD]
70     $GS[5] = date('His');               // Time [HHMM] Group Creation Time
71     $GS[6] = "2";                       // Group Control Number No zeros for 5010
72     $GS[7] = "X";                   // Responsible Agency Code Accredited Standards Committee X12 ]
73     $GS[8] = "005010X279A1";            // Version Release / Industry[ Identifier Code Query 005010X279A1
74     $GS['Created'] = implode('*', $GS);         // Data Element Separator
75     $GS['Created'] = $GS ['Created'] . $segTer;  // change the information in the tag or change the tag
76     return trim($GS['Created']);
78 // ST Segment  - EDI-270 format
79 function create_ST($row, $X12info, $segTer, $compEleSep)
81     $ST    =    array();
82     $ST[0] = "ST";                              // Transaction Set Header Segment ID
83     $ST[1] = "270";                                 // Transaction Set Identifier Code (Inquiry Request)
84     $ST[2] = "000000003";                       // Transaction Set Control Number - Must match SE's
85     $ST[3] = "005010X279A1";                    // Standard 005010X279A1 in $ST[3]
86     $ST['Created'] = implode('*', $ST);             // Data Element Separator
87     $ST['Created'] = $ST ['Created'] . $segTer;
88     return trim($ST['Created']);
90 // BHT Segment  - EDI-270 format
91 function create_BHT($row, $X12info, $segTer, $compEleSep)
93     $BHT    =   array();
94     $BHT[0] = "BHT";                        // Beginning of Hierarchical Transaction Segment ID
95     $BHT[1] = "0022";                       // Subscriber Structure Code
96     $BHT[2] = "13";                         // Purpose Code - This is a Request
97     $BHT[3] = "PROVTest600";                //  Submitter Transaction Identifier
98     // This information is required by the information Receiver when using Real Time transactions.
99     // For BATCH this can be used for optional information.
100     $BHT[4] = str_pad(date('Ymd'), 8, " ");           // Date Transaction Set Created
101     $BHT[5] = str_pad(date('Hi'), 4, " ");            // Time Transaction Set Created no space after and 1300 is plenty
102     $BHT['Created'] = implode('*', $BHT);           // Data Element Separator
103     $BHT['Created'] = $BHT ['Created'] . $segTer;
104     return trim($BHT['Created']);
106 // HL Segment  - EDI-270 format
107 function create_HL($row, $nHlCounter, $X12info, $segTer, $compEleSep)
109     $HL         = array();
110     $HL[0]      = "HL";             // Hierarchical Level Segment ID
111     $HL_LEN[0]  =  2;
112     $HL[1] = $nHlCounter;       // Hierarchical ID No.
113     if ($nHlCounter == 1) {
114         $HL[2] = "";
115         $HL[3] = 20;            // Description: Identifies the payor, maintainer, or source of the information.
116         $HL[4] = 1;                 // 1 Additional Subordinate HL Data Segment in This Hierarchical Structure.
117     } else if ($nHlCounter == 2) {
118         $HL[2] = 1;                 // Hierarchical Parent ID Number
119         $HL[3] = 21;            // Hierarchical Level Code. '21' Information Receiver
120         $HL[4] = 1;                 // 1 Additional Subordinate HL Data Segment in This Hierarchical Structure.
121     } else {
122         $HL[2] = 2;
123         $HL[3] = 22;            // Hierarchical Level Code.'22' Subscriber
124         $HL[4] = 0;                 // 0 no Additional Subordinate in the Hierarchical Structure.
125     }
126     $HL['Created'] = implode('*', $HL);         // Data Element Separator
127     $HL['Created'] = $HL ['Created'] . $segTer;
128     return trim($HL['Created']);
130 // NM1 Segment  - EDI-270 format
131 function create_NM1($row, $nm1Cast, $X12info, $segTer, $compEleSep)
133     $NM1        = array();
134     $NM1[0]         = "NM1";                    // Subscriber Name Segment ID
135     if ($nm1Cast == 'PR') {
136         $NM1[1] = "PR";                         // Entity ID Code - Payer [PR Payer]
137         $NM1[2] = "2";                      // Entity Type - Non-Person
138         $NM1[3] = $row["payer_name"];       // Organizational Name
139         $NM1[4] = "";                       // Data Element not required.
140         $NM1[5] = "";                       // Data Element not required.
141         $NM1[6] = "";                       // Data Element not required.
142         $NM1[7] = "";                       // Data Element not required.
143         $NM1[8] = $X12info['id_number'] ? $X12info['id_number'] : "46";  // 46 - Electronic Transmitter Identification Number (ETIN)
144         if ($GLOBALS['enable_oa']) {
145             $payerId = $row['eligibility_id'];
146         } else {
147             $payerId = $row['cms_id'];
148         }
149         $NM1[9] = $payerId; // Application Sender's ID
150     } else if ($nm1Cast == 'FA') {
151         $NM1[1] = "FA";                     // Entity ID Code - Facility [FA Facility]
152         $NM1[2] = "2";                      // Entity Type - Non-Person
153         $NM1[3] = $row['facility_name'];            // Organizational Name
154         $NM1[4] = "";           // Data Element not required.
155         $NM1[5] = "";           // Data Element not required.
156         $NM1[6] = "";                       // Data Element not required.
157         $NM1[7] = "";                       // Data Element not required.
158         $NM1[8] = "FI";
159         $NM1[9] = $row['facility_npi'];
160     } else if ($nm1Cast == '1P') {
161         $NM1[1] = "1P";                     // Entity ID Code - Provider
162         $NM1[2] = "2";                      // Entity Type - Non-Person
163         $NM1[3] = $row['facility_name'];   // Organizational Name
164         $NM1[4] = "";   // Data Element not required.
165         $NM1[5] = "";                       // Data Element not required.
166         $NM1[6] = "";                       // Data Element not required.
167         $NM1[7] = "";                       // Data Element not required.
168         $NM1[8] = "XX";
169         $NM1[9] = $row['provider_npi'];
170     } else if ($nm1Cast == 'IL') {
171         $NM1[1] = "IL";                         // Insured or Subscriber
172         $NM1[2] = "1";                      // Entity Type - Person
173         $NM1[3] = $row['lname'];                // last Name
174         $NM1[4] = $row['fname'];                // first Name
175         $NM1[5] = $row['mname'];                // middle Name
176         $NM1[6] = "";                       // data element
177         $NM1[7] = "";                       // data element
178         $NM1[8] = "MI";                     // Identification Code Qualifier
179         $NM1[9] = $row['policy_number'];    // Identification Code
180     }
181     $NM1['Created'] = implode('*', $NM1);               // Data Element Separator
182     $NM1['Created'] = $NM1['Created'] . $segTer;
183     return trim($NM1['Created']);
185 // REF Segment  - EDI-270 format
186 function create_REF($row, $ref, $X12info, $segTer, $compEleSep)
188     $REF    =   array();
189     $REF[0] = "REF";                            // Subscriber Additional Identification    does not want this for anything
190     if ($ref == '1P') {
191         $REF[1] = "4A";                         // Reference Identification Qualifier
192         $REF[2] = $row['provider_pin'];         // Provider Pin.
193     } else {
194         $REF[1] = "EJ";                         // 'EJ' for Patient Account Number     does not want this for patient
195         $REF[2] = $row['pid'];                  // Patient Account No.
196     }
197     $REF['Created'] = implode('*', $REF);  // Data Element Separator
198     $REF['Created'] = $REF['Created'] . $segTer;
199     return trim($REF['Created']);
201 // TRN Segment - EDI-270 format
202 function create_TRN($row, $tracno, $refiden, $X12info, $segTer, $compEleSep)
204     $TRN    =   array();
205     $TRN[0] = "TRN";                        // Subscriber Trace Number Segment ID
206     $TRN[1] = "1";                          // Trace Type Code ï¿½ Current Transaction Trace Numbers
207     $TRN[2] = $tracno;                      // Trace Number
208     $TRN[3] = "9000000000";                 // Originating Company ID ï¿½ must be 10 positions in length
209     $TRN[4] = $refiden;                     // Additional Entity Identifier (i.e. Subdivision)
210     $TRN['Created'] = implode('*', $TRN); // Data Element Separator
211     $TRN['Created'] = $TRN['Created'] . $segTer;
212     return trim($TRN['Created']);
214 // DMG Segment - EDI-270 format
215 function create_DMG($row, $X12info, $segTer, $compEleSep)
217     $DMG    =   array();
218     $DMG[0] = "DMG";                            // Date or Time or Period Segment ID
219     $DMG[1] = "D8";                             // Date Format Qualifier - (D8 means CCYYMMDD)
220     $DMG[2] = $row['dob'];                      // Subscriber's Birth date
221     $DMG[3] = strtoupper($row['sex'][0]);
222     $DMG['Created'] = implode('*', $DMG);  // Data Element Separator
223     $DMG['Created'] = $DMG['Created'] .  $segTer;
224     return trim($DMG['Created']);
226 // DTP Segment - EDI-270 format
227 function create_DTP($row, $qual, $X12info, $segTer, $compEleSep)
229     $DTP    =   array();
230     $DTP[0] = "DTP";                            // Date or Time or Period Segment ID
231     $DTP[1] = $qual;                            // Qualifier - Date of Service
232     $DTP[2] = "D8";                             // Date Format Qualifier - (D8 means CCYYMMDD)
233     if ($qual == '102') {
234         $DTP[3] = $row['date'];                 // Date
235     } else {
236         $DTP[3] = !empty($row['pc_eventDate']) && $row['pc_eventDate'] > '20010101' ? $row['pc_eventDate'] : date("Ymd");         // Date of Service
237     }
238     $DTP['Created'] = implode('*', $DTP);   // Data Element Separator
239     $DTP['Created'] = $DTP['Created'] .  $segTer;
240     return trim($DTP['Created']);
242 // EQ Segment - EDI-270 format
243 function create_EQ($row, $X12info, $segTer, $compEleSep)
245     $EQ         =   array();
246     $EQ[0]  = "EQ";                                     // Subscriber Eligibility or Benefit Inquiry Information
247     $EQ[1]  = "30";                                     // Service Type Code
248     $EQ['Created'] = implode('*', $EQ);                 // Data Element Separator
249     $EQ['Created'] = $EQ['Created'] . $segTer;
250     return trim($EQ['Created']);
252 // SE Segment - EDI-270 format
253 function create_SE($row, $segmentcount, $X12info, $segTer, $compEleSep)
255     $SE     =   array();
256     $SE[0] = "SE";                              // Transaction Set Trailer Segment ID
257     $SE[1] = $segmentcount;                     // Segment Count
258     $SE[2] = "000000003";                       // Transaction Set Control Number - Must match ST's
259     $SE['Created'] = implode('*', $SE);    // Data Element Separator
260     $SE['Created'] = $SE['Created'] . $segTer;
261     return trim($SE['Created']);
263 // GE Segment - EDI-270 format
264 function create_GE($row, $X12info, $segTer, $compEleSep)
266     $GE     =   array();
267     $GE[0]  = "GE";                          // Functional Group Trailer Segment ID
268     $GE[1]  = "1";                           // Number of included Transaction Sets
269     $GE[2]  = "2";                           // Group Control Number
270     $GE['Created'] = implode('*', $GE); // Data Element Separator
271     $GE['Created'] = $GE['Created'] . $segTer;
272     return trim($GE['Created']);
274 // IEA Segment - EDI-270 format
275 function create_IEA($row, $X12info, $segTer, $compEleSep)
277     $IEA    =   array();
278     $IEA[0] = "IEA";                        // Interchange Control Trailer Segment ID
279     $IEA[1] = "1";                          // Number of included Functional Groups
280     $IEA[2] = "000000001";                  // Interchange Control Number
281     $IEA['Created'] = implode('*', $IEA);
282     $IEA['Created'] = $IEA['Created'] .  $segTer;
283     return trim($IEA['Created']);
286 function translate_relationship($relationship)
288     switch ($relationship) {
289         case "spouse":
290             return "01";
291             break;
292         case "child":
293             return "19";
294             break;
295         case "self":
296         default:
297             return "S";
298     }
301 // EDI-270 Batch file Generation
302 function print_elig($res, $X12info, $segTer, $compEleSep)
304     $i=1;
305     $PATEDI    = "";
306     // For Header Segment
307     $nHlCounter = 1;
308     $rowCount   = 0;
309     $trcNo      = 1234501;
310     $refiden    = 5432101;
311     while ($row = sqlFetchArray($res)) {
312         if ($nHlCounter == 1) {
313             // create ISA
314             $PATEDI    = create_ISA($row, $X12info, $segTer, $compEleSep);
315             // create GS
316             $PATEDI   .= create_GS($row, $X12info, $segTer, $compEleSep);
317             // create ST
318             $PATEDI   .= create_ST($row, $X12info, $segTer, $compEleSep);
319             // create BHT
320             $PATEDI   .= create_BHT($row, $X12info, $segTer, $compEleSep);
321             // For Payer Segment
322             $PATEDI  .= create_HL($row, 1, $X12info, $segTer, $compEleSep);
323             $PATEDI  .= create_NM1($row, 'PR', $X12info, $segTer, $compEleSep);
324             // For Provider Segment
325             $PATEDI  .= create_HL($row, 2, $X12info, $segTer, $compEleSep);
326             $PATEDI  .= create_NM1($row, 'FA', $X12info, $segTer, $compEleSep);
327             $nHlCounter = $nHlCounter + 2;
328             $segmentcount = 6; // segement counts - start from ST
329         }
330         // For Subscriber Segment
331         $PATEDI  .= create_HL($row, $nHlCounter, $X12info, $segTer, $compEleSep);
332         $PATEDI  .= create_NM1($row, 'IL', $X12info, $segTer, $compEleSep);
333         // send pid so we get it back in 271
334         $PATEDI .= create_REF($row, 'EJ', '', $segTer, '');
335         $PATEDI .= create_DMG($row, $X12info, $segTer, $compEleSep);
336         $PATEDI .= create_DTP($row, '291', $X12info, $segTer, $compEleSep);
337         $PATEDI .= create_EQ($row, $X12info, $segTer, $compEleSep);
338         $segmentcount = $segmentcount + 6;
339         $nHlCounter = $nHlCounter + 1;
340         $rowCount = $rowCount + 1;
341         $trcNo = $trcNo + 1;
342         $refiden = $refiden + 1;
343         if ($rowCount == sqlNumRows($res)) {
344             $segmentcount = $segmentcount + 1;
345             $PATEDI   .= create_SE($row, $segmentcount, $X12info, $segTer, $compEleSep);
346             $PATEDI   .= create_GE($row, $X12info, $segTer, $compEleSep);
347             $PATEDI   .= create_IEA($row, $X12info, $segTer, $compEleSep);
348         }
349     }
350     echo $PATEDI;
353 function requestEligibleTransaction($pid = 0, $eFlag = false)
355     $query = "SELECT 
356             d.facility_id,
357             p.lname,
358             p.fname,
359             p.mname,
360             DATE_FORMAT(p.dob, '%Y%m%d') as dob,
361             p.ss,
362             p.sex,
363             p.pid,
364             p.pubpid,
365             p.providerID,
366             i.subscriber_ss,
367             i.policy_number,
368             i.provider as payer_id,
369             i.subscriber_relationship,
370             i.subscriber_lname,
371             i.subscriber_fname,
372             i.subscriber_mname,
373             DATE_FORMAT(i.subscriber_DOB, '%Y%m%d') as subscriber_dob,
374             i.policy_number,
375             i.subscriber_sex,
376             DATE_FORMAT(i.date, '%Y%m%d') as date,
377             d.lname as provider_lname,
378             d.fname as provider_fname,
379             d.npi as provider_npi,
380             d.upin as provider_pin,
381             f.federal_ein as federal_ein,
382             f.facility_npi as facility_npi,
383             f.name as facility_name,
384             c.cms_id as cms_id,
385             c.eligibility_id as eligibility_id,
386             c.x12_default_eligibility_id as partner,
387             c.name as payer_name
388         FROM patient_data AS p 
389         LEFT JOIN users AS d on (p.providerID = d.id)
390         LEFT JOIN facility AS f on (f.id = d.facility_id)
391         LEFT JOIN insurance_data AS i ON (i.id =(SELECT id FROM insurance_data AS i WHERE pid = p.pid AND type = 'primary' ORDER BY date DESC LIMIT 1))
392         LEFT JOIN insurance_companies as c ON (c.id = i.provider)
393         WHERE p.pid = ?";
394     $res = sqlStatement($query, array($pid));
396     $details = requestRealTimeEligible($res, '', "~", ':', true);
397     $isError = strpos($details, "Error:");
398     $isError = $isError !== false ? $isError : strpos($details, "AAA");
399     if ($isError !== false) {
400         $details = substr($details, $isError);
401         return "<div>" . nl2br(text($details)) . "</div>";
402     }
404     return true;
407 // EDI-270 RealTime Request & Response
408 // RealTime requires one transaction per request.
410 function requestRealTimeEligible($res, $X12info, $segTer, $compEleSep, $eFlag = false)
412     $rowCount = 0;
413     $totalCount = sqlNumRows($res);
414     $down_accum = $log = $error_accum = '';
415     while ($row = sqlFetchArray($res)) {
416         if (!$X12info) {
417             $X12info = getX12Partner($row['partner']);
418         }
419         if ($row['providerID'] === 0 || !$row['provider_npi']) {
420             $error_accum .= xlt("Error") . ": " . xlt("Provider Missing Add one in Choices") . "\n";
421         }
422         if (!$row['eligibility_id']) {
423             $error_accum .= xlt("Error") . ": " . xlt("Missing Insurance Payer Id") . "\n";
424         }
425         if (!$row['policy_number'] || !$row['subscriber_dob']) {
426             $error_accum .= xlt("Error") . ": " . xlt("Missing Subscriber Policy Number or DOB") . "\n";
427         }
428         if (!empty($error_accum)) {
429             return $error_accum;
430         }
431         // create ISA
432         $PATEDI = create_ISA($row, $X12info, $segTer, $compEleSep);
433         // create GS
434         $PATEDI .= create_GS($row, $X12info, $segTer, $compEleSep);
435         // create ST
436         $PATEDI .= create_ST($row, $X12info, $segTer, $compEleSep);
437         // create BHT
438         $PATEDI .= create_BHT($row, $X12info, $segTer, $compEleSep);
439         // For Payer Segment
440         $PATEDI .= create_HL($row, 1, $X12info, $segTer, $compEleSep);
441         $PATEDI .= create_NM1($row, 'PR', $X12info, $segTer, $compEleSep);
442         // For Provider Segment
443         $PATEDI .= create_HL($row, 2, $X12info, $segTer, $compEleSep);
444         //$PATEDI .= create_NM1($row, 'FA', $X12info, $segTer, $compEleSep); // unsure but this may have to be an option
445         $PATEDI .= create_NM1($row, '1P', $X12info, $segTer, $compEleSep);
446         // For Subscriber Segment
447         $PATEDI .= create_HL($row, 3, $X12info, $segTer, $compEleSep);
448         $PATEDI .= create_NM1($row, 'IL', $X12info, $segTer, $compEleSep);
449         // send pid so we get it back in 271
450         $PATEDI .= create_REF($row, 'EJ', '', $segTer, '');
451         $PATEDI .= create_DMG($row, $X12info, $segTer, $compEleSep);
452         // 2110
453         $PATEDI .= create_DTP($row, '291', $X12info, $segTer, $compEleSep);
454         $PATEDI .= create_EQ($row, $X12info, $segTer, $compEleSep);
455         // the end
456         $PATEDI .= create_SE($row, 13, $X12info, $segTer, $compEleSep);
457         $PATEDI .= create_GE($row, $X12info, $segTer, $compEleSep);
458         $PATEDI .= create_IEA($row, $X12info, $segTer, $compEleSep);
459         // make request
460         $result = requestEligibility($X12info['id'], $PATEDI);
461         $rowCount++;
462         $e = strpos($result, "Error:");
463         if ($e !== false) {
464             $error_accum = $result;
465         } else {
466             $down_accum .= $result . "\n"; // delimit for next new request
467         }
469         $log .= "*** 270 " . xlt("Request Message") . " $rowCount of $totalCount\n" . $PATEDI . "\n" . $error_accum . "\n"; // keep a log.
470         $error_accum = '';
471     }
472     // parse the 271 responses from 270 requests sent.
473     $process = parseEdi271($down_accum);
474     $log = xlt("List of ") . $rowCount .  " " . xlt("Requests Sent") . ":\n" . $log . "\n" . $process;
475     if ($eFlag) {
476         return $log;
477     }
479     return $rowCount;
481 // Report Generation
483 function show_elig($res, $X12info, $segTer, $compEleSep)
486     $i=0;
487     echo "      <div id='report_results'>
488     <table>
489         <thead>
490             <th style='width:12%;'>     ". htmlspecialchars(xl('Facility Name'), ENT_NOQUOTES) ."</th>
491             <th style='width:9%;'>      ". htmlspecialchars(xl('Facility NPI'), ENT_NOQUOTES) ."</th>
492             <th style='width:15%;'>     ". htmlspecialchars(xl('Insurance Comp'), ENT_NOQUOTES) ."</th>
493             <th style='width:8%;'>      ". htmlspecialchars(xl('Policy No'), ENT_NOQUOTES) ."</th>
494             <th style='width:16%;'>     ". htmlspecialchars(xl('Patient Name'), ENT_NOQUOTES) ."</th>
495             <th style='width:7%;'>      ". htmlspecialchars(xl('DOB'), ENT_NOQUOTES) ."</th>
496             <th style='width:6%;'>      ". htmlspecialchars(xl('Gender'), ENT_NOQUOTES) ."</th>
497             <th style='width:9%;'>      ". htmlspecialchars(xl('SSN'), ENT_NOQUOTES) ."</th>
498             <th style='width:2%;'>      &nbsp;                    </th>
499         </thead>
500         <tbody>
501                 ";
503     while ($row = sqlFetchArray($res)) {
504         $i= $i+1;
506         if ($i%2 == 0) {
507             $background = '#FFF';
508         } else {
509             $background = '#FFF';
510         }
512         $elig     = array();
513         $elig[0]  = $row['facility_name'];              // Inquiring Provider Name  calendadr
514         $elig[1]  = $row['facility_npi'];               // Inquiring Provider NPI
515         $elig[2]  = $row['payer_name'];                     // Payer Name  our insurance co name
516         $elig[3]  = $row['policy_number'];              // Subscriber ID
517         $elig[4]  = $row['subscriber_lname'];               // Subscriber Last Name
518         $elig[5]  = $row['subscriber_fname'];               // Subscriber First Name
519         $elig[6]  = $row['subscriber_mname'];               // Subscriber Middle Initial
520         $elig[7]  = $row['subscriber_dob'];                 // Subscriber Date of Birth
521         $elig[8]  = substr($row['subscriber_sex'], 0, 1);       // Subscriber Sex
522         $elig[9]  = $row['subscriber_ss'];              // Subscriber SSN
523         $elig[10] = translate_relationship($row['subscriber_relationship']);    // Pt Relationship to insured
524         $elig[11] = $row['lname'];                  // Dependent Last Name
525         $elig[12] = $row['fname'];                  // Dependent First Name
526         $elig[13] = $row['mname'];                  // Dependent Middle Initial
527         $elig[14] = $row['dob'];                    // Dependent Date of Birth
528         $elig[15] = substr($row['sex'], 0, 1);              // Dependent Sex
529         $elig[16] = $row['pc_eventDate'];               // Date of service
530         $elig[17] = "30";                       // Service Type
531         $elig[18] = $row['pubpid'];                     // Patient Account Number pubpid
533         echo "  <tr id='PR".$i."_". htmlspecialchars($row['policy_number'], ENT_QUOTES)."'>
534                                 <td class ='detail' style='width:12%;'>". htmlspecialchars($row['facility_name'], ENT_NOQUOTES) ."</td>
535                                 <td class ='detail' style='width:9%;'>".  htmlspecialchars($row['facility_npi'], ENT_NOQUOTES) ."</td>
536                                 <td class ='detail' style='width:15%;'>". htmlspecialchars($row['payer_name'], ENT_NOQUOTES) ."</td>
537                                 <td class ='detail' style='width:8%;'>".  htmlspecialchars($row['policy_number'], ENT_NOQUOTES) ."</td>
538                                 <td class ='detail' style='width:16%;'>". htmlspecialchars($row['subscriber_lname']." ".$row['subscriber_fname'], ENT_NOQUOTES) ."</td>
539                                 <td class ='detail' style='width:7%;'>".  htmlspecialchars($row['subscriber_dob'], ENT_NOQUOTES) ."</td>
540                                 <td class ='detail' style='width:6%;'>".  htmlspecialchars($row['subscriber_sex'], ENT_NOQUOTES) ."</td>
541                                 <td class ='detail' style='width:9%;'>".  htmlspecialchars($row['subscriber_ss'], ENT_NOQUOTES) ."</td>
542                                 <td class ='detail' style='width:2%;'>
543                                 <img src=\"" . $GLOBALS['images_static_relative'] . "/deleteBtn.png\" title=" .htmlspecialchars(xl('Delete Row'), ENT_QUOTES) . " style='cursor:pointer;cursor:hand;' onclick='deletetherow(\"" . $i."_". htmlspecialchars($row['policy_number'], ENT_QUOTES) . "\")'>
544                                 </td>
545                         </tr>
546                 ";
547         unset($elig);
548     }
550     if ($i==0) {
551         echo "  <tr>
552                                 <td class='norecord' colspan=9>
553                                         <div style='padding:5px;font-family:arial;font-size:13px;text-align:center;'>". htmlspecialchars(xl('No records found'), ENT_NOQUOTES) . "</div>
554                                 </td>
555                         </tr>   ";
556     }
557         echo "  </tbody>
558                         </table>";
561 // To Show Eligibility Verification data
562 function show_eligibility_information($pid, $flag = false)
564     $query =
565         "SELECT eligr.*, eligv.insurance_id, eligv.copay, insd.pid, insc.name, " .
566         "Date_Format(eligv.eligibility_check_date, '%W %M %e, %Y %h:%i %p') AS verificationDate " .
567         "FROM eligibility_verification eligv " .
568         "INNER JOIN benefit_eligibility eligr ON eligr.verification_id = eligv.verification_id " .
569         "INNER JOIN insurance_data insd ON insd.id = eligv.insurance_id " .
570         "INNER JOIN insurance_companies insc ON insc.id = insd.provider " .
571         "WHERE insd.pid = ? AND eligv.eligibility_check_date = " .
572         "(SELECT Max(eligibility_verification.eligibility_check_date) FROM eligibility_verification ".
573         "WHERE eligibility_verification.insurance_id = eligv.insurance_id)";
574     $result = sqlStatement($query, array($pid));
576     $showString = "<div class='row'>";
577     $col = 1;
578     $title = 1;
579     while ($benefit = sqlFetchArray($result)) {
580         if ($title) {
581             $title = 0;
582             $showString .= "<div class='col col-sm-12'>\n";
583             $showString .= "<b>" . xlt('Insurance Provider') . ":</b> " . (!empty($benefit['name']) ? text($benefit['name']) : xlt('n/a')) . "<br/>\n";
584             $showString .= "<b>" . xlt('Verified On') . ":</b> " . text($benefit['verificationDate']) . "<br/><br/>\n";
585             $showString .= "</div><br/>\n";
586         }
587         $benefit['start_date'] = strpos($benefit['start_date'], "0000") === false ? $benefit['start_date'] : '';
588         $benefit['end_date'] = strpos($benefit['end_date'], "0000") === false ? $benefit['end_date'] : '';
589         $color = "";
590         switch ($benefit['type']) {
591             case '1':
592                 $color = "darkred";
593                 break;
594             case 'A':
595                 $color = "blue";
596                 break;
597             case 'B':
598                 $color = "red";
599                 break;
600             case 'C':
601                 $color = "green";
602                 break;
603             case 'F':
604                 $color = "darkgreen";
605                 break;
606         }
607         $showString .= "\n<div class='col col-sm-6' >\n";
608         $showString .= !empty($benefit['benefit_type']) ? "<b style='color: $color'>" . xlt('Benefit Type') . ": " .  text($benefit['benefit_type']) . "</b><br />\n" : '';
609         $showString .= !empty($benefit['start_date']) ? "<b>" . xlt('Start Date') . ":</b> " . text(date("d/m/Y", strtotime($benefit['start_date']))) . "<br />\n" : '';
610         $showString .= !empty($benefit['end_date']) ? "<b>" . xlt('End Date') . ":</b> " . text(date("d/m/Y", strtotime($benefit['end_date']))) . "<br />\n" : '';
611         $showString .= !empty($benefit['coverage_level']) ? "<b>" . xlt('Coverage Level') . ":</b> " .text($benefit['coverage_level']) . "<br />\n" : '';
612         $showString .= !empty($benefit['coverage_type']) ? "<b>" . xlt('Coverage Type') . ":</b> " . text($benefit['coverage_type']) . "<br />\n" : '';
613         $showString .= !empty($benefit['plan_type']) ? "<b>" . xlt('Plan Type') . ":</b> " .  text($benefit['plan_type']) . "<br />\n" : '';
614         $showString .= !empty($benefit['plan_desc']) ? "<b>" . xlt('Plan Description') . ":</b> " .  text(text($benefit['plan_desc'])) . "<br />\n" : '';
615         $showString .= !empty($benefit['coverage_period']) ? "<b>" . xlt('Coverage Period') . ":</b> " . text($benefit['coverage_period']) . "<br />\n" : '';
616         $showString .= !empty($benefit['amount']) ? "<b>" . xlt('Amount') . ":</b> " . text($benefit['amount']) . "<br />\n" : '';
617         $showString .= !empty($benefit['percent']) ? "<b>" . xlt('Percentage') . ":</b> " . text($benefit['percent']) . "<br />\n" : '';
618         $showString .= !empty($benefit['network_ind']) ? "<b>" . xlt('Network Indicator') . ":</b> " . text($benefit['network_ind']) . "<br />\n" : '';
619         $showString .= !empty($benefit['message']) ? "<b>" . xlt('Message') . ":</b> " . text($benefit['message']) . "<br />\n" : '';
620         $showString .= "</div>";
622         if ($col === 2) {
623             $showString .= "</div>\n<br/><div class='row'>\n";
624             $col = 0;
625         }
626         $col++;
627     }
628     if ($col === 2) {
629         $showString .= "</div>";
630     }
631     if ($title === 1) {
632         $showString = "<br><span><b>" . xlt("Nothing To Report") . "</b></span><br>";
633     }
634     $showString .= "</div>\n";
635     echo $showString;
638 // For EDI 271
639 // Function to save the values in eligibility_verification table
640 function eligibility_verification_save($subscriber = [])
642     $verification_id = 0;
643     $insurance_id = 0;
644     $partner_id = $subscriber['isa_sender_id'];
645     $patient_id = $subscriber['pid'];
647     $query = "SELECT id, copay FROM insurance_data WHERE type = 'primary' and pid = ?";
648     $insId = sqlQuery($query, array($patient_id));
649     if ($insId !== false) {
650         $insurance_id = $insId['id'];
651         $copay = $insId['copay'];
652     }
654     $query = "SELECT verification_id FROM eligibility_verification WHERE insurance_id = ?";
655     $resId = sqlQuery($query, array($insurance_id));
656     if ($resId !== false) {
657         $verification_id = $resId['verification_id'];
658     }
660     if (!empty($insurance_id)) {
661         $sqlBindArray = array();
662         $query = "REPLACE INTO eligibility_verification SET verification_id = ?, insurance_id = ?, response_id = ?, eligibility_check_date = now(), create_date = now()";
663         array_push($sqlBindArray, $verification_id, $insurance_id, $partner_id);
665         $res = sqlInsert($query, $sqlBindArray);
666         if (!$verification_id) {
667             $verification_id = $res;
668         }
669     }
671     $query = "DELETE FROM `benefit_eligibility` WHERE `benefit_eligibility`.`verification_id` = ?";
672     $res = sqlStatement($query, array($verification_id));
674     foreach ($subscriber['benefits'] as $benefit) {
675         $bind = array(
676             $verification_id,
677             "A",
678             date('Y/m/d H:i'),
679             date('Y/m/d H:i'),
680             $benefit['type'],
681             $benefit['benefit_type'],
682             $benefit['start_date'],
683             $benefit['end_date'],
684             $benefit['coverage_level'],
685             $benefit['coverage_type'],
686             $benefit['plan_type'],
687             $benefit['plan_desc'],
688             $benefit['coverage_period'],
689             $benefit['amount'],
690             $benefit['percent'],
691             $benefit['network_ind'],
692             $benefit['message']
693         );
695         $query = "INSERT INTO `benefit_eligibility` " .
696             "(`verification_id`, `response_status`, `response_create_date`, `response_modify_date`, `type`, `benefit_type`, `start_date`, " .
697             "`end_date`, `coverage_level`, `coverage_type`, `plan_type`, `plan_description`, `coverage_period`, `amount`, `percent`, `network_ind`, `message`) " .
698             "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
699         $res = sqlStatement($query, $bind);
700     }
703 // return array of X12 partners
704 // if id return just that id
705 function getX12Partner($id = 0)
707     // @TODO move to class
708     global $X12info;
709     $id = (int)$id;
710     $returnval = [];
712     if ((int)$id > 0) {
713         $returnval = sqlQuery("select * from x12_partners WHERE id = ?", array($id));
714         $X12info = $returnval;
715     } else {
716         $rez = sqlStatement("select * from x12_partners");
717         for ($iter = 0; $row = sqlFetchArray($rez); $iter++) {
718             $returnval[$iter] = $row;
719         }
720     }
722     return $returnval;
725 // return array of provider usernames
726 function getUsernames()
728     $rez = sqlStatement("select distinct username, lname, fname,id from users " .
729         "where authorized = 1 and username != ''");
730     for ($iter = 0; $row = sqlFetchArray($rez); $iter++) {
731         $returnval[$iter] = $row;
732     }
734     return $returnval;
737 // return formated array
739 function arrFormated(&$item, $key)
741     $item = strstr($item, '_');
742     $item = substr($item, 1, strlen($item) - 1);
743     $item = "'" . $item;
746 function requestEligibility($partner = '', $x12_270 = '')
748     global $X12info;
749     if (((int)$X12info['id'] !== (int)$partner) && (int)$partner > 0) {
750         $X12info = getX12Partner($partner);
751     }
753     $payloadId = "3b8c13f5-11e2-43bf-bc47-737cca04f3fe"; // a default fallback
754     if (function_exists('openssl_random_pseudo_bytes') === true) {
755         $data = openssl_random_pseudo_bytes(16);
756         $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
757         $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
758         $payloadId = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
759     }
761     $boundary = RandomGenUtils::createUniqueToken(12);
762     $rt_passwrd = $X12info['x12_isa04'];
763     $rt_user = $X12info['x12_isa02'];
764     $sender_id = $X12info['x12_sender_id'];
765     $receiver_id = $X12info['x12_receiver_id'];
766     $now_date = date("Y-m-d\TH:i:s\Z");
767     $headers = array(
768         'Content-Type' => "multipart/form-data; boundary=$boundary",
769         'Host' => ' wsd.officeally.com'
770     );
772 // IMPORTANT: Do not change the format of $mime_body below.
773 // HTTP MIME Multipart is non-normative. LFs matter...
775     $mime_body = <<<MIMEBODY
776 --$boundary
777 Content-Disposition: form-data; name="ProcessingMode"
779 RealTime
780 --$boundary
781 Content-Disposition: form-data; name="TimeStamp"
783 $now_date
784 --$boundary
785 Content-Disposition: form-data; name="PayloadID"
787 $payloadId
788 --$boundary
789 Content-Disposition: form-data; name="CORERuleVersion"
791 2.2.0
792 --$boundary
793 Content-Disposition: form-data; name="ReceiverID"
795 $receiver_id
796 --$boundary
797 Content-Disposition: form-data; name="SenderID"
799 $sender_id
800 --$boundary
801 Content-Disposition: form-data; name="PayloadType"
803 X12_270_Request_005010X279A1
804 --$boundary
805 Content-Disposition: form-data; name="UserName"
807 $rt_user
808 --$boundary
809 Content-Disposition: form-data; name="Password"
811 $rt_passwrd
812 --$boundary
813 Content-Disposition: form-data; name="Payload"
815 $x12_270
816 --$boundary--
817 MIMEBODY;
818     // send the request
819     $response = oeHttp::bodyFormat('body')
820         //->setDebug('5000')/* @todo uncomment and set proxy port to debug eg Fiddler */
821         ->usingHeaders($headers)
822         ->post('https://wsd.officeally.com/TransactionSite/rtx.aspx', $mime_body); // @TODO put request urls in x12 partner's for versatility.
824     $formBody = $response->body();
825     $contentType = $response->header('Content-Type')[0];
826     $hContentLength = (int)$response->header('Content-Length')[0];
827     $cksum = ($hContentLength - strlen($formBody)) === 0 ? true : false; // validate content size
828     $formData = mimeParse($formBody, $contentType);
830     $errors = '';
831     if (!$cksum) {
832         $errors .= "Error:" . xlt("Request Content Fails Integrity Test");
833     }
834     if ($response->status() !== 200) {
835         $errors .= "\nError:" . xlt("Http Error") . ": " . $response->getReasonPhrase() .  " : " . $response->status();
836     }
837     if ($formData['ErrorCode'] != "Success") {
838         $errors .= "\nError:" . $formData['ErrorCode'] . "\n" . $formData['ErrorMessage'];
839     }
840     if ($errors) {
841         $errors .= $formData['Payload'] ? "\nError:" . $formData['Payload'] : '';
842         return $errors;
843     }
845     $x12_271 = $formData['Payload'];
847     return $x12_271;
850 function mimeParse($formBody = '', $contentType)
852     $mimeBody = preg_replace('~\r\n?~', "\r", $formBody);
853     list($contentType, $bound, $cs) = explode(";", trim($contentType)); // $contentType & $cs are throwaways
854     $bound = explode("=", trim($bound, ' '))[1];
855     $mimeFields = preg_split("/-+$bound/", $mimeBody);
856     array_pop($mimeFields);
857     $hold = $isMatches = [];
858     foreach ($mimeFields as $id => $field) {
859         if (empty($field)) {
860             continue;
861         }
862         preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $field, $isMatches);
863         if (preg_match('/^(.*)\[\]$/i', $isMatches[1], $hold)) {
864             $mimeData[$hold[1]][] = $isMatches[2];
865         } else {
866             $mimeData[$isMatches[1]] = $isMatches[2];
867         }
868     }
869     return $mimeData;
872 function getPatientMatch($fn, $ln, $sex, $dob)
874     $fn = "%" . $fn . "%";
875     $ln = "%" . $ln . "%";
876     $sex = "%" . $sex . "%";
877     $dob = date("Y-m-d", strtotime($dob));
878     $sql = "SELECT pid FROM patient_data WHERE fname LIKE ? && lname LIKE ? && sex LIKE ? && DOB LIKE ?";
879     $rtn = sqlQuery($sql, array($fn, $ln, $sex, $dob));
881     return $rtn['pid'] ? $rtn['pid'] : 0;
884 function parseEdi271($content)
887     $codes = new edih_271_codes('*', '^');
888     $target = $GLOBALS['edi_271_file_path'];
889     $log = "";
890     // not sure if want to save yet
891     $target = $target . time();
893     $responses = explode("\n", $content);
894     if (empty($responses)) {
895         $responses = $content;
896     }
898 // Loop through each 271. '\n' delims records in batch.
899     foreach ($responses as $new) {
900         if (empty($new)) {
901             continue;
902         }
903         $AAA = array();
904         $subscribers = array();
905         $benefits = array();
906         $in = array();
907         $in['pid'] = 0;
908         $loop = array();
909         $loop['id'] = 0;
910         $loop['parent'] = 0;
911         $loop['error'] = 1;
912         $trace = -1;
914         $segments = explode("~", $new);
916         if (count($segments) < 6) {
917             if (file_exists($target)) {
918                 unlink($target);
919             }
920             continue;
921         }
923         foreach ($segments as $segment) {
924             $elements = explode("*", $segment);
925             $ecnt = count($elements);
926             // sanitize
927             for ($i = 0; $i < $ecnt; $i++) {
928                 $elements[$i] = text(trim($elements[$i]));
929             }
930             // Switch Case for Segment
931             switch ($elements[0]) {
932                 case 'ISA':
933                     $loop[1] = $elements[2];
934                     $in['isa_sender_id'] = $elements[6];
935                     $in['isa_receiver_id'] = $elements[8];
936                     $in['isa_control_number'] = $elements[13];
937                     break;
939                 case 'HL':
940                     $loop['id'] = (int)$elements[1];
941                     $loop['parent'] = (int)$elements[2];
942                     $loop['error'] = (int)$elements[4];
943                     break;
945                 case 'NM1':
946                     if ($loop['id'] === 1) {//"PR" payer
947                         $in['payer_org'] = $elements[3];
948                         $in['payer_member_id'] = $elements[9];
949                     } elseif ($loop['id'] === 2) { //"1P" or "FA"
950                         $in['provider_org'] = $elements[3];
951                         $in['provider_member_id'] = $elements[9];
952                     } elseif ($elements[1] == "IL" || $loop['context'] == "TRN") { //"IL"
953                         $in['trace'] = $trace;
954                         $in['subscriber_lname'] = $elements[3];
955                         $in['subscriber_fname'] = $elements[4];
956                         $in['subscriber_mname'] = $elements[5];
957                         $in['subscriber_member_id'] = $elements[9];
958                         $in['verify_date'] = date('Y/m/d H:i:s');
959                     }
960                     $loop['context'] = $elements[0];
961                     break;
963                 case 'DMG':
964                     if ($elements[1] == "D8") {
965                         $in['subscriber_dob'] = $elements[2];
966                     }
967                     $in['subscriber_sex'] = $elements[3];
968                     $loop['context'] = $elements[0];
969                     // 2100A-C should be done so get our patient id.
970                     if (!(int)$in['pid']) {
971                         $in['pid'] = (int)getPatientMatch(
972                             $in['subscriber_fname'],
973                             $in['subscriber_lname'],
974                             $in['subscriber_sex'],
975                             $in['subscriber_dob']
976                         );
977                     }
978                     break;
980                 case 'TRN':
981                     if ($trace === -1) {
982                         $trace++;
983                         break; // subscriber not set yet
984                     }
985                     $trace++;
986                     if ($in['pid']) {
987                         $in['benefits'] = $benefits ? $benefits : [];
988                         array_push($subscribers, $in);
989                         $loop['context'] = $elements[0];
990                         $benefits = [];
991                     }
992                     break;
994                 case 'REF':
995                     if ($elements[1] == "EJ") {
996                         $in['pid'] = (int)$elements[2];
997                         if (!$in['pid']) {
998                             $in['pid'] = (int)getPatientMatch(
999                                 $in['subscriber_fname'],
1000                                 $in['subscriber_lname'],
1001                                 $in['subscriber_sex'],
1002                                 $in['subscriber_dob']
1003                             );
1004                         }
1005                     }
1006                     break;
1008                 case 'DTP':
1009                     if ($elements[2] == "D8") {
1010                         $loop['start_date'] = $elements[3] ? date("Y-m-d", strtotime($elements[3])) : '';
1011                         $loop['end_date'] = '';
1012                     } elseif ($elements[2] == "RD8") {
1013                         $tmp = explode('-', $elements[3]);
1014                         $loop['start_date'] = $tmp[0] ? date("Y-m-d", strtotime($tmp[0])) : '';
1015                         $loop['end_date'] = !empty($tmp[1]) ? date("Y-m-d", strtotime($tmp[1])) : '';
1016                     }
1017                     if ($loop['context'] == "EB") {
1018                         $bcnt = count($benefits) - 1;
1019                         $benefits[$bcnt]['start_date'] = $loop['start_date'];
1020                         $benefits[$bcnt]['end_date'] = $loop['end_date'];
1021                     }
1022                     break;
1024                 case 'EB':
1025                     $eb = array(
1026                         'type' => $elements[1],
1027                         'benefit_type' =>  $codes->get_271_code("EB01", $elements[1]) ?  $codes->get_271_code("EB01", $elements[1]) : $elements[1],
1028                         'start_date' => '',
1029                         'end_date' => '',
1030                         'coverage_level' => $elements[2] ?  $codes->get_271_code("EB02", $elements[2]) :$elements[2],
1031                         'coverage_type' => $elements[3] ?  $codes->get_271_code("EB03", $elements[3]) :$elements[3],
1032                         'plan_type' =>  $elements[4] ?  $codes->get_271_code("EB04", $elements[4]) : $elements[4],
1033                         'plan_description' => $elements[5],
1034                         'coverage_period' =>  $elements[6] ?  $codes->get_271_code("EB06", $elements[6]) : $elements[6],
1035                         'amount' => $elements[7] ? number_format($elements[7], 2, '.', '') : '',
1036                         'percent' => $elements[8],
1037                         'network_ind' => $elements[12] ?  $codes->get_271_code("EB12", $elements[12]) : $elements[12],
1038                         'message' => '' // any MSG segments that may be assoc with this EB.
1039                     );
1040                     $loop['context'] = "EB";
1041                     array_push($benefits, $eb);
1042                     break;
1044                 case 'AAA':
1045                     $error = array(
1046                         'request_ind' => $elements[1],
1047                         'reason_code' => $elements[3] . " : " .  $codes->get_271_code("AAA03", $elements[3]),
1048                         'follow_up' => $elements[4] . " : " .  $codes->get_271_code("AAA04", $elements[4])
1049                     );
1050                     array_push($AAA, $error);
1051                     break;
1053                 case 'MSG':
1054                     $bcnt = count($benefits) - 1;
1055                     if ($bcnt > -1) {
1056                         $benefits[$bcnt]['message'] = $benefits[$bcnt]['message'] ? $benefits[$bcnt]['message'] . ":" : '';
1057                         $benefits[$bcnt]['message'] .= $elements[1];
1058                     }
1059                     break;
1061                 case 'SE':
1062                     $in['benefits'] = $benefits ? $benefits : [];
1063                     if ($in['pid']) {
1064                         array_push($subscribers, $in);
1065                     }
1066                     $loop['context'] = $elements[0];
1067                     $benefits = [];
1068                     break;
1070                 case 'IEA':
1071                     // save
1072                     $elog = '';
1073                     if (count($subscribers) < 1) {
1074                         $elog = xlt("Error") . ": " . xlt("Unknown Transaction Error Maybe Subscriber Effective or DOB Dates");
1075                     }
1076                     foreach ($subscribers as $subscriber) {
1077                         eligibility_verification_save($subscriber);
1078                     }
1079                     break;
1080             }
1081         }
1082         // some debug logging
1083         if (!$GLOBALS['disable_eligibility_log']) {
1084             $log .= "*------------------- " . xlt("271 Returned") . " --------------------*\n" . $new . "\n" . (isset($AAA[0]) ? (xlt("AAA Segments") . ":\n" . print_r($AAA, true)) : "\n") . $elog;
1085             $log .= makeEligibilityReport($subscribers);
1086         }
1087     }
1090     return $log;
1093 function makeEligibilityReport($subscribers = [])
1095     $binfo = '';
1096     foreach ($subscribers as $subscriber) {
1097         $binfo .=
1098             xlt("Subscriber Member") . ": " . $subscriber['subscriber_fname'] . " " . $subscriber['subscriber_lname'] . " " . $subscriber['subscriber_mname'] .
1099             " " .xlt("Member Id") . ": " . $subscriber['subscriber_member_id'] . " ---*\n";
1100         $cnt = count($subscriber['benefits']);
1101         if ($cnt < 1) {
1102             $binfo .= "*** " . xlt("Nothing returned to report") . " ***\n";
1103         }
1104         foreach ($subscriber['benefits'] as $key => $benefits) {
1105             foreach ($benefits as $key => $benefit) {
1106                 if ($key == 'type') {
1107                     $binfo .= "\n";
1108                 }
1109                 if (empty($benefit) || $key == 'type') {
1110                     continue;
1111                 }
1112                 $binfo .= "\t" . ucwords(str_replace('_', ' ', $key)) . ": " . $benefit . "\n";
1113             }
1114         }
1115     }
1117     return $binfo;