Remove any trailing delimiters from each X12 claim segment.
[openemr.git] / library / gen_x12_837.inc.php
blob5a0c388026f3478d4fe240712a6b4bc27ed9c984
1 <?php
2 // Copyright (C) 2007-2011 Rod Roark <rod@sunsetsystems.com>
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 require_once("Claim.class.php");
11 function gen_x12_837($pid, $encounter, &$log, $encounter_claim=false) {
13 $today = time();
14 $out = '';
15 $claim = new Claim($pid, $encounter);
16 $edicount = 0;
18 // This is true for the 5010 standard, false for 4010.
19 // x12gsversionstring() should be "005010X222A1" or "004010X098A1".
20 $CMS_5010 = strpos($claim->x12gsversionstring(), '5010') !== false;
22 $log .= "Generating claim $pid-$encounter for " .
23 $claim->patientFirstName() . ' ' .
24 $claim->patientMiddleName() . ' ' .
25 $claim->patientLastName() . ' on ' .
26 date('Y-m-d H:i', $today) . ".\n";
28 $out .= "ISA" .
29 "*00" .
30 "* " .
31 "*00" .
32 "* " .
33 "*" . $claim->x12gsisa05() .
34 "*" . $claim->x12gssenderid() .
35 "*" . $claim->x12gsisa07() .
36 "*" . $claim->x12gsreceiverid() .
37 "*030911" .
38 "*1630" .
39 "*" . ($CMS_5010 ? "^" : "U" ) .
40 "*" . ($CMS_5010 ? "00501" : "00401") .
41 "*000000001" .
42 "*" . $claim->x12gsisa14() .
43 "*" . $claim->x12gsisa15() .
44 "*:" .
45 "~\n";
47 $out .= "GS" .
48 "*HC" .
49 "*" . $claim->x12gsgs02() .
50 "*" . trim($claim->x12gsreceiverid()) .
51 "*" . date('Ymd', $today) .
52 "*" . date('Hi', $today) .
53 "*1" .
54 "*X" .
55 "*" . $claim->x12gsversionstring() .
56 "~\n";
58 ++$edicount;
59 $out .= "ST" .
60 "*837" .
61 "*0021" .
62 // Spec says the following is optional, so should be able to leave it out.
63 ($CMS_5010 ? ("*" . $claim->x12gsversionstring()) : "") .
64 "~\n";
66 ++$edicount;
67 $out .= "BHT" .
68 "*0019" . // 0019 is required here
69 "*00" . // 00 = original transmission
70 "*0123" . // reference identification
71 "*" . date('Ymd', $today) . // transaction creation date
72 "*" . date('Hi', $today) . // transaction creation time
73 ($encounter_claim ? "*RP" : "*CH") . // RP = reporting, CH = chargeable
74 "~\n";
76 if (!$CMS_5010) {
77 // This segment was deleted for 5010.
78 ++$edicount;
79 $out .= "REF" .
80 "*87" .
81 "*" . $claim->x12gsversionstring() .
82 "~\n";
85 ++$edicount;
86 //Field length is limited to 35. See nucc dataset page 63 www.nucc.org
87 $billingFacilityName = substr($claim->billingFacilityName(), 0, $CMS_5010 ? 60 : 35);
88 $out .= "NM1" . // Loop 1000A Submitter
89 "*41" .
90 "*2" .
91 "*" . $billingFacilityName .
92 "*" .
93 "*" .
94 "*" .
95 "*" .
96 "*46";
97 if (trim($claim->x12gsreceiverid()) == '470819582') { // if ECLAIMS EDI
98 $out .= "*" . $claim->clearingHouseETIN();
99 } else {
100 $out .= "*" . $claim->billingFacilityETIN();
102 $out .= "~\n";
104 ++$edicount;
105 $out .= "PER" .
106 "*IC" .
107 "*" . $claim->billingContactName() .
108 "*TE" .
109 "*" . $claim->billingContactPhone();
110 if (!$CMS_5010 && $claim->x12gsper06()) {
111 $out .= "*ED*" . $claim->x12gsper06();
113 $out .= "~\n";
115 ++$edicount;
116 $out .= "NM1" . // Loop 1000B Receiver
117 "*40" .
118 "*2" .
119 "*" . $claim->clearingHouseName() .
120 "*" .
121 "*" .
122 "*" .
123 "*" .
124 "*46" .
125 "*" . $claim->clearingHouseETIN() .
126 "~\n";
128 $HLcount = 1;
130 ++$edicount;
131 $out .= "HL" . // Loop 2000A Billing/Pay-To Provider HL Loop
132 "*$HLcount" .
133 "*" .
134 "*20" .
135 "*1" . // 1 indicates there are child segments
136 "~\n";
138 $HLBillingPayToProvider = $HLcount++;
140 // Situational PRV segment (for provider taxonomy code) omitted here.
141 // Situational CUR segment (foreign currency information) omitted here.
143 ++$edicount;
144 //Field length is limited to 35. See nucc dataset page 63 www.nucc.org
145 $billingFacilityName = substr($claim->billingFacilityName(), 0, $CMS_5010 ? 60 : 35);
146 $out .= "NM1" . // Loop 2010AA Billing Provider
147 "*85" .
148 "*2" .
149 "*" . $billingFacilityName .
150 "*" .
151 "*" .
152 "*" .
153 "*";
154 if ($claim->billingFacilityNPI()) {
155 $out .= "*XX*" . $claim->billingFacilityNPI();
157 else {
158 $log .= "*** Billing facility has no NPI.\n";
159 if ($CMS_5010) {
160 $out .= "*XX*";
162 else {
163 $out .= "*24*" . $claim->billingFacilityETIN();
166 $out .= "~\n";
168 ++$edicount;
169 $out .= "N3" .
170 "*" . $claim->billingFacilityStreet() .
171 "~\n";
173 ++$edicount;
174 $out .= "N4" .
175 "*" . $claim->billingFacilityCity() .
176 "*" . $claim->billingFacilityState() .
177 "*" . $claim->billingFacilityZip() .
178 "~\n";
180 if ($CMS_5010 || ($claim->billingFacilityNPI() && $claim->billingFacilityETIN())) {
181 ++$edicount;
182 $out .= "REF" ;
183 if($claim->federalIdType()){
184 $out .= "*" . $claim->federalIdType();
186 else{
187 $out .= "*EI"; // For dealing with the situation before adding TaxId type In facility.
189 $out .= "*" . $claim->billingFacilityETIN() .
190 "~\n";
193 if ($claim->providerNumberType() && $claim->providerNumber() &&
194 !($CMS_5010 && $claim->billingFacilityNPI()))
196 ++$edicount;
197 $out .= "REF" .
198 "*" . $claim->providerNumberType() .
199 "*" . $claim->providerNumber() .
200 "~\n";
202 else if ($claim->providerNumber() && !$claim->providerNumberType()) {
203 $log .= "*** Payer-specific provider insurance number is present but has no type assigned.\n";
206 // Situational PER*1C segment omitted.
208 // Pay-To Address defaults to billing provider and is no longer required in 5010.
209 if (!$CMS_5010) {
210 ++$edicount;
211 // Field length is limited to 35. See nucc dataset page 63 www.nucc.org
212 $billingFacilityName = substr($claim->billingFacilityName(), 0, $CMS_5010 ? 60 : 35);
213 $out .= "NM1" . // Loop 2010AB Pay-To Provider
214 "*87" .
215 "*2" .
216 "*" . $billingFacilityName .
217 "*" .
218 "*" .
219 "*" .
220 "*";
221 if ($claim->billingFacilityNPI())
222 $out .= "*XX*" . $claim->billingFacilityNPI();
223 else
224 $out .= "*24*" . $claim->billingFacilityETIN();
225 $out .= "~\n";
227 ++$edicount;
228 $out .= "N3" .
229 "*" . $claim->billingFacilityStreet() .
230 "~\n";
232 ++$edicount;
233 $out .= "N4" .
234 "*" . $claim->billingFacilityCity() .
235 "*" . $claim->billingFacilityState() .
236 "*" . $claim->billingFacilityZip() .
237 "~\n";
239 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
240 ++$edicount;
241 $out .= "REF" .
242 "*EI" .
243 "*" . $claim->billingFacilityETIN() .
244 "~\n";
248 // Loop 2010AC Pay-To Plan Name omitted. Includes:
249 // NM1*PE, N3, N4, REF*2U, REF*EI
251 $PatientHL = $claim->isSelfOfInsured() ? 0 : 1;
252 $HLSubscriber = $HLcount++;
254 ++$edicount;
255 $out .= "HL" . // Loop 2000B Subscriber HL Loop
256 "*$HLSubscriber" .
257 "*$HLBillingPayToProvider" .
258 "*22" .
259 "*$PatientHL" .
260 "~\n";
262 if (!$claim->payerSequence()) {
263 $log .= "*** Error: Insurance information is missing!\n";
266 ++$edicount;
267 $out .= "SBR" . // Subscriber Information
268 "*" . $claim->payerSequence() .
269 "*" . ($claim->isSelfOfInsured() ? '18' : '') .
270 "*" . $claim->groupNumber() .
271 "*" . (($CMS_5010 && $claim->groupNumber()) ? '' : $claim->groupName()) .
272 "*" . $claim->insuredTypeCode() . // applies for secondary medicare
273 "*" .
274 "*" .
275 "*" .
276 "*" . $claim->claimType() . // Zirmed replaces this
277 "~\n";
279 // Segment PAT omitted.
281 ++$edicount;
282 $out .= "NM1" . // Loop 2010BA Subscriber
283 "*IL" .
284 "*1" . // 1 = person, 2 = non-person
285 "*" . $claim->insuredLastName() .
286 "*" . $claim->insuredFirstName() .
287 "*" . $claim->insuredMiddleName() .
288 "*" .
289 "*" . // Name Suffix
290 "*MI" .
291 // "MI" = Member Identification Number
292 // "II" = Standard Unique Health Identifier, "Required if the
293 // HIPAA Individual Patient Identifier is mandated use."
294 // Here we presume that is not true yet.
295 "*" . $claim->policyNumber() .
296 "~\n";
298 // For 5010, further subscriber info is sent only if they are the patient.
299 if (!$CMS_5010 || $claim->isSelfOfInsured()) {
300 ++$edicount;
301 $out .= "N3" .
302 "*" . $claim->insuredStreet() .
303 "~\n";
305 ++$edicount;
306 $out .= "N4" .
307 "*" . $claim->insuredCity() .
308 "*" . $claim->insuredState() .
309 "*" . $claim->insuredZip() .
310 "~\n";
312 ++$edicount;
313 $out .= "DMG" .
314 "*D8" .
315 "*" . $claim->insuredDOB() .
316 "*" . $claim->insuredSex() .
317 "~\n";
320 // Segment REF*SY (Subscriber Secondary Identification) omitted.
321 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
322 // Segment PER*IC (Property and Casualty Subscriber Contact Information) omitted.
324 ++$edicount;
325 //Field length is limited to 35. See nucc dataset page 81 www.nucc.org
326 $payerName = substr($claim->payerName(), 0, $CMS_5010 ? 60 : 35);
327 $out .= "NM1" . // Loop 2010BB Payer
328 "*PR" .
329 "*2" .
330 "*" . $payerName .
331 "*" .
332 "*" .
333 "*" .
334 "*" .
335 // The 5010 spec says:
336 // "On or after the mandated implementation date for the HIPAA
337 // National Plan Identifier (National Plan ID), XV must be sent.
338 // Prior to the mandated implementation date and prior to any phase-
339 // in period identified by Federal regulation, PI must be sent."
340 // *************** Anybody know what that date is? ***************
341 "*PI" .
342 // Zirmed ignores this if using payer name matching:
343 "*" . ($encounter_claim ? $claim->payerAltID() : $claim->payerID()) .
344 "~\n";
346 // if (!$claim->payerID()) {
347 // $log .= "*** CMS ID is missing for payer '" . $claim->payerName() . "'.\n";
348 // }
350 if (true) { // !$CMS_5010
351 // The 5010 spec says:
352 // "Required when the payer address is available and the submitter intends
353 // for the claim to be printed on paper at the next EDI location (for example, a
354 // clearinghouse). If not required by this implementation guide, do not send."
356 ++$edicount;
357 $out .= "N3" .
358 "*" . $claim->payerStreet() .
359 "~\n";
361 ++$edicount;
362 $out .= "N4" .
363 "*" . $claim->payerCity() .
364 "*" . $claim->payerState() .
365 "*" . $claim->payerZip() .
366 "~\n";
369 // Segment REF (Payer Secondary Identification) omitted.
370 // Segment REF (Billing Provider Secondary Identification) omitted.
372 if (! $claim->isSelfOfInsured()) {
373 ++$edicount;
374 $out .= "HL" . // Loop 2000C Patient Information
375 "*$HLcount" .
376 "*$HLSubscriber" .
377 "*23" .
378 "*0" .
379 "~\n";
381 $HLcount++;
383 ++$edicount;
384 $out .= "PAT" .
385 "*" . $claim->insuredRelationship() .
386 "~\n";
388 ++$edicount;
389 $out .= "NM1" . // Loop 2010CA Patient
390 "*QC" .
391 "*1" .
392 "*" . $claim->patientLastName() .
393 "*" . $claim->patientFirstName() .
394 "*" . $claim->patientMiddleName() .
395 "~\n";
397 ++$edicount;
398 $out .= "N3" .
399 "*" . $claim->patientStreet() .
400 "~\n";
402 ++$edicount;
403 $out .= "N4" .
404 "*" . $claim->patientCity() .
405 "*" . $claim->patientState() .
406 "*" . $claim->patientZip() .
407 "~\n";
409 ++$edicount;
410 $out .= "DMG" .
411 "*D8" .
412 "*" . $claim->patientDOB() .
413 "*" . $claim->patientSex() .
414 "~\n";
416 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
417 // Segment REF (Property and Casualty Patient Identifier) omitted.
418 // Segment PER (Property and Casualty Patient Contact Information) omitted.
420 } // end of patient different from insured
422 $proccount = $claim->procCount();
424 $clm_total_charges = 0;
425 for ($prockey = 0; $prockey < $proccount; ++$prockey) {
426 $clm_total_charges += $claim->cptCharges($prockey);
429 if (!$clm_total_charges) {
430 $log .= "*** This claim has no charges!\n";
433 ++$edicount;
434 $out .= "CLM" . // Loop 2300 Claim
435 "*$pid-$encounter" .
436 "*" . sprintf("%.2f",$clm_total_charges) . // Zirmed computes and replaces this
437 "*" .
438 "*" .
439 "*" . sprintf('%02d', $claim->facilityPOS()) . ":" .
440 ($CMS_5010 ? "B" : "") . ":" .
441 $claim->frequencyTypeCode() . // Changed to correct single digit output
442 "*Y" .
443 "*A" .
444 "*" . ($claim->billingFacilityAssignment() ? 'Y' : 'N') .
445 "*Y" .
446 ($CMS_5010 ? "" : "*C") .
447 "~\n";
449 if ($claim->onsetDate()) {
450 ++$edicount;
451 $out .= "DTP" . // Date of Onset
452 "*431" .
453 "*D8" .
454 "*" . $claim->onsetDate() .
455 "~\n";
458 if ($claim->dateInitialTreatment()) {
459 ++$edicount;
460 $out .= "DTP" . // Date of Initial Treatment
461 "*454" .
462 "*D8" .
463 "*" . $claim->dateInitialTreatment() .
464 "~\n";
467 // Segment DTP*304 (Last Seen Date) omitted.
468 // Segment DTP*453 (Acute Manifestation Date) omitted.
469 // Segment DTP*439 (Accident Date) omitted.
470 // Segment DTP*484 (Last Menstrual Period Date) omitted.
471 // Segment DTP*455 (Last X-Ray Date) omitted.
472 // Segment DTP*471 (Hearing and Vision Prescription Date) omitted.
473 // Segments DTP (Disability Dates) omitted.
474 // Segment DTP*297 (Last Worked Date) omitted.
475 // Segment DTP*296 (Authorized Return to Work Date) omitted.
477 if (strcmp($claim->facilityPOS(),'21') == 0) {
478 ++$edicount;
479 $out .= "DTP" . // Date of Hospitalization
480 "*435" .
481 "*D8" .
482 "*" . $claim->onsetDate() .
483 "~\n";
486 // Segment DTP*096 (Discharge Date) omitted.
487 // Segments DTP (Assumed and Relinquished Care Dates) omitted.
488 // Segment DTP*444 (Property and Casualty Date of First Contact) omitted.
489 // Segment DTP*050 (Repricer Received Date) omitted.
490 // Segment PWK (Claim Supplemental Information) omitted.
491 // Segment CN1 (Contract Information) omitted.
493 $patientpaid = $claim->patientPaidAmount();
494 if ($patientpaid != 0) {
495 ++$edicount;
496 $out .= "AMT" . // Patient paid amount. Page 190/220.
497 "*F5" .
498 "*" . $patientpaid .
499 "~\n";
502 // Segment REF*4N (Service Authorization Exception Code) omitted.
503 // Segment REF*F5 (Mandatory Medicare Crossover Indicator) omitted.
504 // Segment REF*EW (Mammography Certification Number) omitted.
505 // Segment REF*9F (Referral Number) omitted.
507 if ($claim->priorAuth()) {
508 ++$edicount;
509 $out .= "REF" . // Prior Authorization Number
510 "*G1" .
511 "*" . $claim->priorAuth() .
512 "~\n";
515 // Segment REF*F8 (Payer Claim Control Number) omitted.
517 if ($claim->cliaCode() && ($CMS_5010 || $claim->claimType() === 'MB')) {
518 // Required by Medicare when in-house labs are done.
519 ++$edicount;
520 $out .= "REF" . // Clinical Laboratory Improvement Amendment Number
521 "*X4" .
522 "*" . $claim->cliaCode() .
523 "~\n";
526 // Segment REF*9A (Repriced Claim Number) omitted.
527 // Segment REF*9C (Adjusted Repriced Claim Number) omitted.
528 // Segment REF*LX (Investigational Device Exemption Number) omitted.
529 // Segment REF*D9 (Claim Identifier for Transmission Intermediaries) omitted.
530 // Segment REF*EA (Medical Record Number) omitted.
531 // Segment REF*P4 (Demonstration Project Identifier) omitted.
532 // Segment REF*1J (Care Plan Oversight) omitted.
533 // Segment K3 (File Information) omitted.
535 if ($claim->additionalNotes()) {
536 // Claim note.
537 ++$edicount;
538 $out .= "NTE" . // comments box 19
539 "*" . ($CMS_5010 ? "ADD" : "") .
540 "*" . $claim->additionalNotes() .
541 "~\n";
544 // Segment CR1 (Ambulance Transport Information) omitted.
545 // Segment CR2 (Spinal Manipulation Service Information) omitted.
546 // Segment CRC (Ambulance Certification) omitted.
547 // Segment CRC (Patient Condition Information: Vision) omitted.
548 // Segment CRC (Homebound Indicator) omitted.
549 // Segment CRC (EPSDT Referral) omitted.
551 // Diagnoses, up to $max_per_seg per HI segment.
552 $max_per_seg = $CMS_5010 ? 12 : 8;
553 $da = $claim->diagArray();
554 $diag_type_code = 'BK';
555 $tmp = 0;
556 foreach ($da as $diag) {
557 if ($tmp % $max_per_seg == 0) {
558 if ($tmp) $out .= "~\n";
559 ++$edicount;
560 $out .= "HI"; // Health Diagnosis Codes
562 $out .= "*$diag_type_code:" . $diag;
563 $diag_type_code = 'BF';
564 ++$tmp;
566 if ($tmp) $out .= "~\n";
568 // Segment HI*BP (Anesthesia Related Procedure) omitted.
569 // Segment HI*BG (Condition Information) omitted.
570 // Segment HCP (Claim Pricing/Repricing Information) omitted.
572 if ($claim->referrerLastName()) {
573 // Medicare requires referring provider's name and UPIN.
574 ++$edicount;
575 $out .= "NM1" . // Loop 2310A Referring Provider
576 "*DN" .
577 "*1" .
578 "*" . $claim->referrerLastName() .
579 "*" . $claim->referrerFirstName() .
580 "*" . $claim->referrerMiddleName() .
581 "*" .
582 "*";
583 if ($CMS_5010 || $claim->referrerNPI()) { $out .=
584 "*XX" .
585 "*" . $claim->referrerNPI();
586 } else { $out .=
587 "*34" . // not allowed for 5010
588 "*" . $claim->referrerSSN();
590 $out .= "~\n";
592 if (!$CMS_5010 && $claim->referrerTaxonomy()) {
593 ++$edicount;
594 $out .= "PRV" .
595 "*RF" . // ReFerring provider
596 "*ZZ" .
597 "*" . $claim->referrerTaxonomy() .
598 "~\n";
601 if (!CMS_5010 && $claim->referrerUPIN()) {
602 ++$edicount;
603 $out .= "REF" . // Referring Provider Secondary Identification
604 "*1G" .
605 "*" . $claim->referrerUPIN() .
606 "~\n";
610 ++$edicount;
611 $out .= "NM1" . // Loop 2310B Rendering Provider
612 "*82" .
613 "*1" .
614 "*" . $claim->providerLastName() .
615 "*" . $claim->providerFirstName() .
616 "*" . $claim->providerMiddleName() .
617 "*" .
618 "*";
619 if ($CMS_5010 || $claim->providerNPI()) { $out .=
620 "*XX" .
621 "*" . $claim->providerNPI();
622 } else { $out .=
623 "*34" . // not allowed for 5010
624 "*" . $claim->providerSSN();
625 $log .= "*** Rendering provider has no NPI.\n";
627 $out .= "~\n";
629 if ($claim->providerTaxonomy()) {
630 ++$edicount;
631 $out .= "PRV" .
632 "*PE" . // PErforming provider
633 "*" . ($CMS_5010 ? "PXC" : "ZZ") .
634 "*" . $claim->providerTaxonomy() .
635 "~\n";
638 // 4010: REF*1C is required here for the Medicare provider number if NPI was
639 // specified in NM109. Not sure if other payers require anything here.
640 // --- apparently ECLAIMS, INC wants the data in 2010 but NOT in 2310B - tony@mi-squared.com
642 // 5010 spec says nothing here if NPI was specified.
644 if (($CMS_5010 && !$claim->providerNPI() && in_array($claim->providerNumberType(), array('0B','1G','G2','LU')))
645 || (!$CMS_5010 && trim($claim->x12gsreceiverid()) != '470819582')) // if NOT ECLAIMS EDI
647 if ($claim->providerNumber()) {
648 ++$edicount;
649 $out .= "REF" .
650 "*" . $claim->providerNumberType() .
651 "*" . $claim->providerNumber() .
652 "~\n";
656 // Loop 2310D is omitted in the case of home visits (POS=12).
657 if ($claim->facilityPOS() != 12 &&
658 (!$CMS_5010 || $claim->facilityNPI() != $claim->billingFacilityNPI()))
660 ++$edicount;
661 $out .= "NM1" . // Loop 2310D Service Location
662 "*77" .
663 "*2";
664 //Field length is limited to 35. See nucc dataset page 77 www.nucc.org
665 $facilityName = substr($claim->facilityName(), 0, $CMS_5010 ? 60 : 35);
666 if ($claim->facilityName() || $claim->facilityNPI() || $claim->facilityETIN()) { $out .=
667 "*" . $facilityName;
669 if ($claim->facilityNPI() || $claim->facilityETIN()) { $out .=
670 "*" .
671 "*" .
672 "*" .
673 "*";
674 if ($CMS_5010 || $claim->facilityNPI()) { $out .=
675 "*XX*" . $claim->facilityNPI();
676 } else { $out .=
677 "*24*" . $claim->facilityETIN();
679 if (!$claim->facilityNPI()) {
680 $log .= "*** Service location has no NPI.\n";
683 $out .= "~\n";
684 if ($claim->facilityStreet()) {
685 ++$edicount;
686 $out .= "N3" .
687 "*" . $claim->facilityStreet() .
688 "~\n";
690 if ($claim->facilityState()) {
691 ++$edicount;
692 $out .= "N4" .
693 "*" . $claim->facilityCity() .
694 "*" . $claim->facilityState() .
695 "*" . $claim->facilityZip() .
696 "~\n";
700 // Segment REF (Service Facility Location Secondary Identification) omitted.
701 // Segment PER (Service Facility Contact Information) omitted.
703 // Loop 2310E, Supervising Provider
705 if ($claim->supervisorLastName()) {
706 ++$edicount;
707 $out .= "NM1" .
708 "*DQ" . // Supervising Physician
709 "*1" . // Person
710 "*" . $claim->supervisorLastName() .
711 "*" . $claim->supervisorFirstName() .
712 "*" . $claim->supervisorMiddleName() .
713 "*" . // NM106 not used
714 "*"; // Name Suffix
715 if ($CMS_5010 || $claim->supervisorNPI()) { $out .=
716 "*XX" .
717 "*" . $claim->supervisorNPI();
718 } else { $out .=
719 "*34" .
720 "*" . $claim->supervisorSSN();
722 if (!$claim->supervisorNPI()) {
723 $log .= "*** Supervising Provider has no NPI.\n";
725 $out .= "~\n";
727 if ($claim->supervisorNumber()) {
728 ++$edicount;
729 $out .= "REF" .
730 "*" . $claim->supervisorNumberType() .
731 "*" . $claim->supervisorNumber() .
732 "~\n";
736 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
737 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
739 $prev_pt_resp = $clm_total_charges; // for computation below
741 // Loops 2320 and 2330*, other subscriber/payer information.
742 // Remember that insurance index 0 is always for the payer being billed
743 // by this claim, and 1 and above are always for the "other" payers.
745 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
747 $tmp1 = $claim->claimType($ins);
748 $tmp2 = 'C1'; // Here a kludge. See page 321.
749 if ($tmp1 === 'CI') $tmp2 = 'C1';
750 if ($tmp1 === 'AM') $tmp2 = 'AP';
751 if ($tmp1 === 'HM') $tmp2 = 'HM';
752 if ($tmp1 === 'MB') $tmp2 = 'MB';
753 if ($tmp1 === 'MC') $tmp2 = 'MC';
754 if ($tmp1 === '09') $tmp2 = 'PP';
755 ++$edicount;
756 $out .= "SBR" . // Loop 2320, Subscriber Information - page 297/318
757 "*" . $claim->payerSequence($ins) .
758 "*" . $claim->insuredRelationship($ins) .
759 "*" . $claim->groupNumber($ins) .
760 "*" . (($CMS_5010 && $claim->groupNumber($ins)) ? '' : $claim->groupName($ins)) .
761 "*" . ($CMS_5010 ? $claim->insuredTypeCode($ins) : $tmp2) .
762 "*" .
763 "*" .
764 "*" .
765 "*" . $claim->claimType($ins) .
766 "~\n";
768 // Things that apply only to previous payers, not future payers.
770 if ($claim->payerSequence($ins) < $claim->payerSequence()) {
772 // Generate claim-level adjustments.
773 $aarr = $claim->payerAdjustments($ins);
774 foreach ($aarr as $a) {
775 ++$edicount;
776 $out .= "CAS" . // Previous payer's claim-level adjustments. Page 301/323.
777 "*" . $a[1] .
778 "*" . $a[2] .
779 "*" . $a[3] .
780 "~\n";
783 $payerpaid = $claim->payerTotals($ins);
784 ++$edicount;
785 $out .= "AMT" . // Previous payer's paid amount. Page 307/332.
786 "*D" .
787 "*" . $payerpaid[1] .
788 "~\n";
790 // Segment AMT*A8 (COB Total Non-Covered Amount) omitted.
791 // Segment AMT*EAF (Remaining Patient Liability) omitted.
793 if (!$CMS_5010) {
794 // Patient responsibility amount as of this previous payer.
795 $prev_pt_resp -= $payerpaid[1]; // reduce by payments
796 $prev_pt_resp -= $payerpaid[2]; // reduce by adjustments
798 ++$edicount;
799 $out .= "AMT" . // Allowed amount per previous payer. Page 334.
800 "*B6" .
801 "*" . sprintf('%.2f', $payerpaid[1] + $prev_pt_resp) .
802 "~\n";
804 ++$edicount;
805 $out .= "AMT" . // Patient responsibility amount per previous payer. Page 335.
806 "*F2" .
807 "*" . sprintf('%.2f', $prev_pt_resp) .
808 "~\n";
810 } // End of things that apply only to previous payers.
812 if (!$CMS_5010) {
813 ++$edicount;
814 $out .= "DMG" . // Other subscriber demographic information. Page 342.
815 "*D8" .
816 "*" . $claim->insuredDOB($ins) .
817 "*" . $claim->insuredSex($ins) .
818 "~\n";
821 ++$edicount;
822 $out .= "OI" . // Other Insurance Coverage Information. Page 310/344.
823 "*" .
824 "*" .
825 "*" . ($claim->billingFacilityAssignment($ins) ? 'Y' : 'N') .
826 // For this next item, the 5010 example in the spec does not match its
827 // description. So this might be wrong.
828 "*" . ($CMS_5010 ? '' : 'B') .
829 "*" .
830 "*Y" .
831 "~\n";
833 // Segment MOA (Medicare Outpatient Adjudication) omitted.
835 ++$edicount;
836 $out .= "NM1" . // Loop 2330A Subscriber info for other insco. Page 315/350.
837 "*IL" .
838 "*1" .
839 "*" . $claim->insuredLastName($ins) .
840 "*" . $claim->insuredFirstName($ins) .
841 "*" . $claim->insuredMiddleName($ins) .
842 "*" .
843 "*" .
844 "*MI" .
845 "*" . $claim->policyNumber($ins) .
846 "~\n";
848 ++$edicount;
849 $out .= "N3" .
850 "*" . $claim->insuredStreet($ins) .
851 "~\n";
853 ++$edicount;
854 $out .= "N4" .
855 "*" . $claim->insuredCity($ins) .
856 "*" . $claim->insuredState($ins) .
857 "*" . $claim->insuredZip($ins) .
858 "~\n";
860 // Segment REF (Other Subscriber Secondary Identification) omitted.
862 ++$edicount;
863 //Field length is limited to 35. See nucc dataset page 81 www.nucc.org
864 $payerName = substr($claim->payerName($ins), 0, $CMS_5010 ? 60 : 35);
865 $out .= "NM1" . // Loop 2330B Payer info for other insco. Page 322/359.
866 "*PR" .
867 "*2" .
868 "*" . $payerName .
869 "*" .
870 "*" .
871 "*" .
872 "*" .
873 "*PI" .
874 "*" . $claim->payerID($ins) .
875 "~\n";
877 // if (!$claim->payerID($ins)) {
878 // $log .= "*** CMS ID is missing for payer '" . $claim->payerName($ins) . "'.\n";
879 // }
881 // Payer address (N3 and N4) are added below so that Gateway EDI can
882 // auto-generate secondary claims. These do NOT appear in my copy of
883 // the spec! -- Rod 2008-06-12
885 if ($CMS_5010 || trim($claim->x12gsreceiverid()) == '431420764') { // if Gateway EDI
886 ++$edicount;
887 $out .= "N3" .
888 "*" . $claim->payerStreet($ins) .
889 "~\n";
891 ++$edicount;
892 $out .= "N4" .
893 "*" . $claim->payerCity($ins) .
894 "*" . $claim->payerState($ins) .
895 "*" . $claim->payerZip($ins) .
896 "~\n";
897 } // end Gateway EDI
899 // Segment DTP*573 (Claim Check or Remittance Date) omitted.
900 // Segment REF (Other Payer Secondary Identifier) omitted.
901 // Segment REF*G1 (Other Payer Prior Authorization Number) omitted.
902 // Segment REF*9F (Other Payer Referral Number) omitted.
903 // Segment REF*T4 (Other Payer Claim Adjustment Indicator) omitted.
904 // Segment REF*F8 (Other Payer Claim Control Number) omitted.
905 // Segment NM1 (Other Payer Referring Provider) omitted.
906 // Segment REF (Other Payer Referring Provider Secondary Identification) omitted.
907 // Segment NM1 (Other Payer Rendering Provider) omitted.
908 // Segment REF (Other Payer Rendering Provider Secondary Identification) omitted.
909 // Segment NM1 (Other Payer Service Facility Location) omitted.
910 // Segment REF (Other Payer Service Facility Location Secondary Identification) omitted.
911 // Segment NM1 (Other Payer Supervising Provider) omitted.
912 // Segment REF (Other Payer Supervising Provider Secondary Identification) omitted.
913 // Segment NM1 (Other Payer Billing Provider) omitted.
914 // Segment REF (Other Payer Billing Provider Secondary Identification) omitted.
916 } // End loops 2320/2330*.
918 $loopcount = 0;
920 // Procedure loop starts here.
922 for ($prockey = 0; $prockey < $proccount; ++$prockey) {
923 ++$loopcount;
925 ++$edicount;
926 $out .= "LX" . // Loop 2400 LX Service Line. Page 398.
927 "*$loopcount" .
928 "~\n";
930 ++$edicount;
931 $out .= "SV1" . // Professional Service. Page 400.
932 "*HC:" . $claim->cptKey($prockey) .
933 "*" . sprintf('%.2f', $claim->cptCharges($prockey)) .
934 "*UN" .
935 "*" . $claim->cptUnits($prockey) .
936 "*" .
937 "*" .
938 "*";
939 $dia = $claim->diagIndexArray($prockey);
940 $i = 0;
941 foreach ($dia as $dindex) {
942 if ($i) $out .= ':';
943 $out .= $dindex;
944 if (++$i >= 4) break;
946 $out .= "~\n";
948 if (!$claim->cptCharges($prockey)) {
949 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no charges!\n";
952 if (empty($dia)) {
953 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' is not justified!\n";
956 // Segment SV5 (Durable Medical Equipment Service) omitted.
957 // Segment PWK (Line Supplemental Information) omitted.
958 // Segment PWK (Durable Medical Equipment Certificate of Medical Necessity Indicator) omitted.
959 // Segment CR1 (Ambulance Transport Information) omitted.
960 // Segment CR3 (Durable Medical Equipment Certification) omitted.
961 // Segment CRC (Ambulance Certification) omitted.
962 // Segment CRC (Hospice Employee Indicator) omitted.
963 // Segment CRC (Condition Indicator / Durable Medical Equipment) omitted.
965 ++$edicount;
966 $out .= "DTP" . // Date of Service. Page 435.
967 "*472" .
968 "*D8" .
969 "*" . $claim->serviceDate() .
970 "~\n";
972 $testnote = rtrim($claim->cptNotecodes($prockey));
973 if (!empty($testnote)) {
974 ++$edicount;
975 $out .= "NTE" . // Explain Unusual Circumstances.
976 "*ADD" .
977 "*" . $claim->cptNotecodes($prockey) .
978 "~\n";
981 // Segment DTP*471 (Prescription Date) omitted.
982 // Segment DTP*607 (Revision/Recertification Date) omitted.
983 // Segment DTP*463 (Begin Therapy Date) omitted.
984 // Segment DTP*461 (Last Certification Date) omitted.
985 // Segment DTP*304 (Last Seen Date) omitted.
986 // Segment DTP (Test Date) omitted.
987 // Segment DTP*011 (Shipped Date) omitted.
988 // Segment DTP*455 (Last X-Ray Date) omitted.
989 // Segment DTP*454 (Initial Treatment Date) omitted.
990 // Segment QTY (Ambulance Patient Count) omitted.
991 // Segment QTY (Obstetric Anesthesia Additional Units) omitted.
992 // Segment MEA (Test Result) omitted.
993 // Segment CN1 (Contract Information) omitted.
994 // Segment REF*9B (Repriced Line Item Reference Number) omitted.
995 // Segment REF*9D (Adjusted Repriced Line Item Reference Number) omitted.
996 // Segment REF*G1 (Prior Authorization) omitted.
997 // Segment REF*6R (Line Item Control Number) omitted.
998 // (Really oughta have this for robust 835 posting!)
999 // Segment REF*EW (Mammography Certification Number) omitted.
1000 // Segment REF*X4 (CLIA Number) omitted.
1001 // Segment REF*F4 (Referring CLIA Facility Identification) omitted.
1002 // Segment REF*BT (Immunization Batch Number) omitted.
1003 // Segment REF*9F (Referral Number) omitted.
1004 // Segment AMT*T (Sales Tax Amount) omitted.
1005 // Segment AMT*F4 (Postage Claimed Amount) omitted.
1006 // Segment K3 (File Information) omitted.
1007 // Segment NTE (Line Note) omitted.
1008 // Segment NTE (Third Party Organization Notes) omitted.
1009 // Segment PS1 (Purchased Service Information) omitted.
1010 // Segment HCP (Line Pricing/Repricing Information) omitted.
1012 if (!$CMS_5010) {
1013 // This segment was deleted for 5010.
1015 // AMT*AAE segment for Approved Amount from previous payer.
1016 // Medicare secondaries seem to require this.
1018 for ($ins = $claim->payerCount() - 1; $ins > 0; --$ins) {
1019 if ($claim->payerSequence($ins) > $claim->payerSequence())
1020 continue; // payer is future, not previous
1021 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
1022 ++$edicount;
1023 $out .= "AMT" . // Approved amount per previous payer. Page 485.
1024 "*AAE" .
1025 "*" . sprintf('%.2f', $claim->cptCharges($prockey) - $payerpaid[2]) .
1026 "~\n";
1027 break;
1031 // Loop 2410, Drug Information. Medicaid insurers seem to want this
1032 // with HCPCS codes.
1034 $ndc = $claim->cptNDCID($prockey);
1035 if ($ndc) {
1036 ++$edicount;
1037 $out .= "LIN" . // Drug Identification. Page 500+ (Addendum pg 71).
1038 "*" . // Per addendum, LIN01 is not used.
1039 "*N4" .
1040 "*" . $ndc .
1041 "~\n";
1043 if (!preg_match('/^\d\d\d\d\d-\d\d\d\d-\d\d$/', $ndc, $tmp) && !preg_match('/^\d{11}$/', $ndc)) {
1044 $log .= "*** NDC code '$ndc' has invalid format!\n";
1047 ++$edicount;
1048 $tmpunits = $claim->cptNDCQuantity($prockey) * $claim->cptUnits($prockey);
1049 if (!$tmpunits) $tmpunits = 1;
1050 $out .= "CTP" . // Drug Pricing. Page 500+ (Addendum pg 74).
1051 "*" .
1052 "*" .
1053 "*" . ($CMS_5010 ? '' : sprintf('%.2f', $claim->cptCharges($prockey) / $tmpunits)) .
1054 "*" . $claim->cptNDCQuantity($prockey) .
1055 "*" . $claim->cptNDCUOM($prockey) .
1056 // Note: 5010 documents "ME" (Milligrams) as an additional unit of measure.
1057 "~\n";
1060 // Segment REF (Prescription or Compound Drug Association Number) omitted.
1062 // Loop 2420A, Rendering Provider (service-specific).
1063 // Used if the rendering provider for this service line is different
1064 // from that in loop 2310B.
1066 if ($claim->providerNPI() != $claim->providerNPI($prockey)) {
1067 ++$edicount;
1068 $out .= "NM1" . // Loop 2310B Rendering Provider
1069 "*82" .
1070 "*1" .
1071 "*" . $claim->providerLastName($prockey) .
1072 "*" . $claim->providerFirstName($prockey) .
1073 "*" . $claim->providerMiddleName($prockey) .
1074 "*" .
1075 "*";
1076 if ($CMS_5010 || $claim->providerNPI($prockey)) { $out .=
1077 "*XX" .
1078 "*" . $claim->providerNPI($prockey);
1079 } else { $out .=
1080 "*34" . // Not allowed for 5010
1081 "*" . $claim->providerSSN($prockey);
1083 if (!$claim->providerNPI($prockey)) {
1084 $log .= "*** Rendering provider has no NPI.\n";
1086 $out .= "~\n";
1088 if ($claim->providerTaxonomy($prockey)) {
1089 ++$edicount;
1090 $out .= "PRV" .
1091 "*PE" . // PErforming provider
1092 "*" . ($CMS_5010 ? "PXC" : "ZZ") .
1093 "*" . $claim->providerTaxonomy($prockey) .
1094 "~\n";
1097 // Segment PRV*PE (Rendering Provider Specialty Information) omitted.
1098 // Segment REF (Rendering Provider Secondary Identification) omitted.
1099 // Segment NM1 (Purchased Service Provider Name) omitted.
1100 // Segment REF (Purchased Service Provider Secondary Identification) omitted.
1101 // Segment NM1,N3,N4 (Service Facility Location) omitted.
1102 // Segment REF (Service Facility Location Secondary Identification) omitted.
1103 // Segment NM1 (Supervising Provider Name) omitted.
1104 // Segment REF (Supervising Provider Secondary Identification) omitted.
1105 // Segment NM1,N3,N4 (Ordering Provider) omitted.
1106 // Segment REF (Ordering Provider Secondary Identification) omitted.
1107 // Segment PER (Ordering Provider Contact Information) omitted.
1108 // Segment NM1 (Referring Provider Name) omitted.
1109 // Segment REF (Referring Provider Secondary Identification) omitted.
1110 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
1111 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
1113 // REF*1C is required here for the Medicare provider number if NPI was
1114 // specified in NM109. Not sure if other payers require anything here.
1115 if (!$CMS_5010 && $claim->providerNumber($prockey)) {
1116 ++$edicount;
1117 $out .= "REF" .
1118 "*" . $claim->providerNumberType($prockey) .
1119 // Note: 5010 documents that type 1D (Medicaid) is changed to G2.
1120 "*" . $claim->providerNumber($prockey) .
1121 "~\n";
1125 // Loop 2430, adjudication by previous payers.
1127 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
1128 if ($claim->payerSequence($ins) > $claim->payerSequence())
1129 continue; // payer is future, not previous
1131 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
1132 $aarr = $claim->payerAdjustments($ins, $claim->cptKey($prockey));
1134 if ($payerpaid[1] == 0 && !count($aarr)) {
1135 $log .= "*** Procedure '" . $claim->cptKey($prockey) .
1136 "' has no payments or adjustments from previous payer!\n";
1137 continue;
1140 ++$edicount;
1141 $out .= "SVD" . // Service line adjudication. Page 554.
1142 "*" . $claim->payerID($ins) .
1143 "*" . $payerpaid[1] .
1144 "*HC:" . $claim->cptKey($prockey) .
1145 "*" .
1146 "*" . $claim->cptUnits($prockey) .
1147 "~\n";
1149 $tmpdate = $payerpaid[0];
1150 foreach ($aarr as $a) {
1151 ++$edicount;
1152 $out .= "CAS" . // Previous payer's line level adjustments. Page 558.
1153 "*" . $a[1] .
1154 "*" . $a[2] .
1155 "*" . $a[3] .
1156 "~\n";
1157 if (!$tmpdate) $tmpdate = $a[0];
1159 // WTH is this??
1160 /*************************************************************
1161 if ( isset($a[4]) &&
1162 $a[4] != null ) {
1163 $out .= "CAS02" . // Previous payer's adjustment reason
1164 "*" . $a[4] .
1165 "~\n";
1167 *************************************************************/
1170 if ($tmpdate) {
1171 ++$edicount;
1172 $out .= "DTP" . // Previous payer's line adjustment date. Page 493/566.
1173 "*573" .
1174 "*D8" .
1175 "*$tmpdate" .
1176 "~\n";
1179 // Segment AMT*EAF (Remaining Patient Liability) omitted.
1180 // Segment LQ (Form Identification Code) omitted.
1181 // Segment FRM (Supporting Documentation) omitted.
1183 } // end loop 2430
1184 } // end this procedure
1186 ++$edicount;
1187 $out .= "SE" . // SE Trailer
1188 "*$edicount" .
1189 "*0021" .
1190 "~\n";
1192 $out .= "GE" . // GE Trailer
1193 "*1" .
1194 "*1" .
1195 "~\n";
1197 $out .= "IEA" . // IEA Trailer
1198 "*1" .
1199 "*000000001" .
1200 "~\n";
1202 // Remove any trailing empty fields (delimiters) from each segment.
1203 $out = preg_replace('/\*+~/', '~', $out);
1205 $log .= "\n";
1206 return $out;