2 // Copyright (C) 2007-2011 Rod Roark <rod@sunsetsystems.com>
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");
10 function stripZipCode($zip)
12 return preg_replace('/[-\s]*/','',$zip);
14 function gen_x12_837($pid, $encounter, &$log, $encounter_claim=false) {
18 $claim = new Claim($pid, $encounter);
21 // This is true for the 5010 standard, false for 4010.
22 // x12gsversionstring() should be "005010X222A1" or "004010X098A1".
23 $CMS_5010 = strpos($claim->x12gsversionstring(), '5010') !== false;
25 $log .= "Generating claim $pid-$encounter for " .
26 $claim->patientFirstName() . ' ' .
27 $claim->patientMiddleName() . ' ' .
28 $claim->patientLastName() . ' on ' .
29 date('Y-m-d H:i', $today) . ".\n";
32 "*" . $claim->x12gsisa01() .
33 "*" . $claim->x12gsisa02() .
34 "*" . $claim->x12gsisa03() .
35 "*" . $claim->x12gsisa04() .
36 "*" . $claim->x12gsisa05() .
37 "*" . $claim->x12gssenderid() .
38 "*" . $claim->x12gsisa07() .
39 "*" . $claim->x12gsreceiverid() .
42 "*" . ($CMS_5010 ?
"^" : "U" ) .
43 "*" . ($CMS_5010 ?
"00501" : "00401") .
45 "*" . $claim->x12gsisa14() .
46 "*" . $claim->x12gsisa15() .
52 "*" . $claim->x12gsgs02() .
53 "*" . trim($claim->x12gs03()) .
54 "*" . date('Ymd', $today) .
55 "*" . date('Hi', $today) .
58 "*" . $claim->x12gsversionstring() .
65 // Spec says the following is optional, so should be able to leave it out.
66 ($CMS_5010 ?
("*" . $claim->x12gsversionstring()) : "") .
71 "*0019" . // 0019 is required here
72 "*00" . // 00 = original transmission
73 "*0123" . // reference identification
74 "*" . date('Ymd', $today) . // transaction creation date
75 "*" . date('Hi', $today) . // transaction creation time
76 ($encounter_claim ?
"*RP" : "*CH") . // RP = reporting, CH = chargeable
80 // This segment was deleted for 5010.
84 "*" . $claim->x12gsversionstring() .
90 if ($claim->federalIdType() == "SY") { // check entity type for NM*102 1 == person, 2 == non-person entity
91 $tempName = $claim->billingFacilityName();
92 $partsName = explode(' ', $tempName);// Loop 1000A submitter entity == person
93 $num_parts = count($partsName);
96 $firstName = $partsName[0];
98 $lastName = $partsName[1];
102 $firstName = $partsName[0];
103 $middleName = $partsName[1];
104 $lastName = $partsName[2];
108 $firstName = $partsName[0];
109 $middleName = $partsName[1];
110 $lastName = $partsName[2];
111 $suffixName = $partsName[3];
114 $log .= "*** submitter name in 1000A loop has more than 4 parts, may not be desirable\n";
115 $firstName = $partsName[0];
116 $middleName = $partsName[1];
117 $lastName = $partsName[2];
118 $suffixName = $partsName[3];
120 $out .= "NM1" . // Loop 1000A Submitter
126 "*" . // Name Prefix not used
127 "*" . // Name Suffix not used
129 } else { //Field length is limited to 35. See nucc dataset page 63 www.nucc.org
130 $billingFacilityName = substr($claim->billingFacilityName(), 0, $CMS_5010 ?
60 : 35);
131 if ($billingFacilityName == '') $log .= "*** billing facility name in 1000A loop is empty\n";
135 "*" . $billingFacilityName .
143 if (trim($claim->x12gsreceiverid()) == '470819582') { // if ECLAIMS EDI
144 $out .= "*" . $claim->clearingHouseETIN();
146 $out .= "*" . $claim->billingFacilityETIN();
153 "*" . $claim->billingContactName() .
155 "*" . $claim->billingContactPhone();
156 if (!$CMS_5010 && $claim->x12gsper06()) {
157 $out .= "*ED*" . $claim->x12gsper06();
162 $out .= "NM1" . // Loop 1000B Receiver
165 "*" . $claim->clearingHouseName() .
171 "*" . $claim->clearingHouseETIN() .
177 $out .= "HL" . // Loop 2000A Billing/Pay-To Provider HL Loop
181 "*1" . // 1 indicates there are child segments
184 $HLBillingPayToProvider = $HLcount++
;
186 // Situational PRV segment (for provider taxonomy code) omitted here.
187 // Situational CUR segment (foreign currency information) omitted here.
190 //Field length is limited to 35. See nucc dataset page 63 www.nucc.org
191 if ($claim->federalIdType() == "SY") { // check for entity type like in 1000A
192 $tempName = $claim->billingFacilityName();
193 $partsName = explode(' ', $tempName);// Loop 2010AA Billing Provider entity == person
194 $num_parts = count($partsName);
195 switch ($num_parts) {
197 $firstName = $partsName[0];
199 $lastName = $partsName[1];
203 $firstName = $partsName[0];
204 $middleName = $partsName[1];
205 $lastName = $partsName[2];
209 $firstName = $partsName[0];
210 $middleName = $partsName[1];
211 $lastName = $partsName[2];
212 $suffixName = $partsName[3];
215 $log .= "*** billing provider name in 2010AA loop has more than 4 parts, may not be desirable\n";
216 $firstName = $partsName[0];
217 $middleName = $partsName[1];
218 $lastName = $partsName[2];
219 $suffixName = $partsName[3];
227 "*" . // Name Prefix not used
231 $billingFacilityName = substr($claim->billingFacilityName(), 0, $CMS_5010 ?
60 : 35);
232 if ($billingFacilityName == '') $log .= "*** billing facility name in 2010A loop is empty\n";
233 $out .= "NM1" . // Loop 2010AA Billing Provider
236 "*" . $billingFacilityName .
242 if ($claim->billingFacilityNPI()) {
243 $out .= "*XX*" . $claim->billingFacilityNPI();
246 $log .= "*** Billing facility has no NPI.\n";
251 $out .= "*24*" . $claim->billingFacilityETIN();
258 "*" . $claim->billingFacilityStreet() .
263 "*" . $claim->billingFacilityCity() .
264 "*" . $claim->billingFacilityState() .
265 "*" . stripZipCode($claim->billingFacilityZip()) .
268 if ($CMS_5010 ||
($claim->billingFacilityNPI() && $claim->billingFacilityETIN())) {
271 if($claim->federalIdType()){
272 $out .= "*" . $claim->federalIdType();
275 $out .= "*EI"; // For dealing with the situation before adding TaxId type In facility.
277 $out .= "*" . $claim->billingFacilityETIN() .
281 if ($claim->providerNumberType() && $claim->providerNumber() &&
282 !($CMS_5010 && $claim->billingFacilityNPI()))
286 "*" . $claim->providerNumberType() .
287 "*" . $claim->providerNumber() .
290 else if ($claim->providerNumber() && !$claim->providerNumberType()) {
291 $log .= "*** Payer-specific provider insurance number is present but has no type assigned.\n";
294 // Situational PER*1C segment omitted.
296 // Pay-To Address defaults to billing provider and is no longer required in 5010.
299 // Field length is limited to 35. See nucc dataset page 63 www.nucc.org
300 $billingFacilityName = substr($claim->billingFacilityName(), 0, $CMS_5010 ?
60 : 35);
301 $out .= "NM1" . // Loop 2010AB Pay-To Provider
304 "*" . $billingFacilityName .
309 if ($claim->billingFacilityNPI())
310 $out .= "*XX*" . $claim->billingFacilityNPI();
312 $out .= "*24*" . $claim->billingFacilityETIN();
317 "*" . $claim->billingFacilityStreet() .
322 "*" . $claim->billingFacilityCity() .
323 "*" . $claim->billingFacilityState() .
324 "*" . stripZipCode($claim->billingFacilityZip()) .
327 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
331 "*" . $claim->billingFacilityETIN() .
336 // Loop 2010AC Pay-To Plan Name omitted. Includes:
337 // NM1*PE, N3, N4, REF*2U, REF*EI
339 $PatientHL = $claim->isSelfOfInsured() ?
0 : 1;
340 $HLSubscriber = $HLcount++
;
343 $out .= "HL" . // Loop 2000B Subscriber HL Loop
345 "*$HLBillingPayToProvider" .
350 if (!$claim->payerSequence()) {
351 $log .= "*** Error: Insurance information is missing!\n";
355 $out .= "SBR" . // Subscriber Information
356 "*" . $claim->payerSequence() .
357 "*" . ($claim->isSelfOfInsured() ?
'18' : '') .
358 "*" . $claim->groupNumber() .
359 "*" . (($CMS_5010 && $claim->groupNumber()) ?
'' : $claim->groupName()) .
360 "*" . $claim->insuredTypeCode() . // applies for secondary medicare
364 "*" . $claim->claimType() . // Zirmed replaces this
367 // Segment PAT omitted.
370 $out .= "NM1" . // Loop 2010BA Subscriber
372 "*1" . // 1 = person, 2 = non-person
373 "*" . $claim->insuredLastName() .
374 "*" . $claim->insuredFirstName() .
375 "*" . $claim->insuredMiddleName() .
379 // "MI" = Member Identification Number
380 // "II" = Standard Unique Health Identifier, "Required if the
381 // HIPAA Individual Patient Identifier is mandated use."
382 // Here we presume that is not true yet.
383 "*" . $claim->policyNumber() .
386 // For 5010, further subscriber info is sent only if they are the patient.
387 if (!$CMS_5010 ||
$claim->isSelfOfInsured()) {
390 "*" . $claim->insuredStreet() .
395 "*" . $claim->insuredCity() .
396 "*" . $claim->insuredState() .
397 "*" . stripZipCode($claim->insuredZip()) .
403 "*" . $claim->insuredDOB() .
404 "*" . $claim->insuredSex() .
408 // Segment REF*SY (Subscriber Secondary Identification) omitted.
409 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
410 // Segment PER*IC (Property and Casualty Subscriber Contact Information) omitted.
413 //Field length is limited to 35. See nucc dataset page 81 www.nucc.org
414 $payerName = substr($claim->payerName(), 0, $CMS_5010 ?
60 : 35);
415 $out .= "NM1" . // Loop 2010BB Payer
423 // The 5010 spec says:
424 // "On or after the mandated implementation date for the HIPAA
425 // National Plan Identifier (National Plan ID), XV must be sent.
426 // Prior to the mandated implementation date and prior to any phase-
427 // in period identified by Federal regulation, PI must be sent."
428 // *************** Anybody know what that date is? ***************
429 // August 2011 - Publish interim final rule
430 // October 1, 2012-March 31, 2013 - Enumeration
431 // April 1, 2013-September 30, 2013 - Testing
432 // October 1, 2013 - Implementation
435 // Zirmed ignores this if using payer name matching:
436 "*" . ($encounter_claim ?
$claim->payerAltID() : $claim->payerID()) .
439 // if (!$claim->payerID()) {
440 // $log .= "*** CMS ID is missing for payer '" . $claim->payerName() . "'.\n";
443 if (true) { // !$CMS_5010
444 // The 5010 spec says:
445 // "Required when the payer address is available and the submitter intends
446 // for the claim to be printed on paper at the next EDI location (for example, a
447 // clearinghouse). If not required by this implementation guide, do not send."
451 "*" . $claim->payerStreet() .
456 "*" . $claim->payerCity() .
457 "*" . $claim->payerState() .
458 "*" . stripZipCode($claim->payerZip()) .
462 // Segment REF (Payer Secondary Identification) omitted.
463 // Segment REF (Billing Provider Secondary Identification) omitted.
465 if (! $claim->isSelfOfInsured()) {
467 $out .= "HL" . // Loop 2000C Patient Information
478 "*" . $claim->insuredRelationship() .
482 $out .= "NM1" . // Loop 2010CA Patient
485 "*" . $claim->patientLastName() .
486 "*" . $claim->patientFirstName();
487 if ($claim->patientMiddleName() !== '') $out .= "*"
488 . $claim->patientMiddleName();
493 "*" . $claim->patientStreet() .
498 "*" . $claim->patientCity() .
499 "*" . $claim->patientState() .
500 "*" . stripZipCode($claim->patientZip()) .
506 "*" . $claim->patientDOB() .
507 "*" . $claim->patientSex() .
510 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
511 // Segment REF (Property and Casualty Patient Identifier) omitted.
512 // Segment PER (Property and Casualty Patient Contact Information) omitted.
514 } // end of patient different from insured
516 $proccount = $claim->procCount();
518 $clm_total_charges = 0;
519 for ($prockey = 0; $prockey < $proccount; ++
$prockey) {
520 $clm_total_charges +
= $claim->cptCharges($prockey);
523 if (!$clm_total_charges) {
524 $log .= "*** This claim has no charges!\n";
528 $out .= "CLM" . // Loop 2300 Claim
530 "*" . sprintf("%.2f",$clm_total_charges) . // Zirmed computes and replaces this
533 "*" . sprintf('%02d', $claim->facilityPOS()) . ":" .
534 ($CMS_5010 ?
"B" : "") . ":" .
535 $claim->frequencyTypeCode() . // Changed to correct single digit output
538 "*" . ($claim->billingFacilityAssignment() ?
'Y' : 'N') .
540 ($CMS_5010 ?
"" : "*C") .
543 if ($claim->onsetDate() &&
544 ($claim->onsetDate()!== $claim->serviceDate()) &&
545 ($claim->onsetDateValid())
548 $out .= "DTP" . // Date of Onset
551 "*" . $claim->onsetDate() .
555 if ($claim->dateInitialTreatment() && ($claim->onsetDateValid())) {
557 $out .= "DTP" . // Date of Initial Treatment
560 "*" . $claim->dateInitialTreatment() .
564 // Segment DTP*304 (Last Seen Date) omitted.
565 // Segment DTP*453 (Acute Manifestation Date) omitted.
566 // Segment DTP*439 (Accident Date) omitted.
567 // Segment DTP*484 (Last Menstrual Period Date) omitted.
568 // Segment DTP*455 (Last X-Ray Date) omitted.
569 // Segment DTP*471 (Hearing and Vision Prescription Date) omitted.
570 // Segments DTP (Disability Dates) omitted.
571 // Segment DTP*297 (Last Worked Date) omitted.
572 // Segment DTP*296 (Authorized Return to Work Date) omitted.
574 if (strcmp($claim->facilityPOS(),'21') == 0 && $claim->onsetDateValid() ) {
576 $out .= "DTP" . // Date of Hospitalization
579 "*" . $claim->onsetDate() .
583 // Segment DTP*096 (Discharge Date) omitted.
584 // Segments DTP (Assumed and Relinquished Care Dates) omitted.
585 // Segment DTP*444 (Property and Casualty Date of First Contact) omitted.
586 // Segment DTP*050 (Repricer Received Date) omitted.
587 // Segment PWK (Claim Supplemental Information) omitted.
588 // Segment CN1 (Contract Information) omitted.
590 $patientpaid = $claim->patientPaidAmount();
591 if ($patientpaid != 0) {
593 $out .= "AMT" . // Patient paid amount. Page 190/220.
599 // Segment REF*4N (Service Authorization Exception Code) omitted.
600 // Segment REF*F5 (Mandatory Medicare Crossover Indicator) omitted.
601 // Segment REF*EW (Mammography Certification Number) omitted.
602 // Segment REF*9F (Referral Number) omitted.
604 if ($claim->priorAuth()) {
606 $out .= "REF" . // Prior Authorization Number
608 "*" . $claim->priorAuth() .
612 // Segment REF*F8 (Payer Claim Control Number) omitted.
614 if ($claim->cliaCode() && ($CMS_5010 ||
$claim->claimType() === 'MB')) {
615 // Required by Medicare when in-house labs are done.
617 $out .= "REF" . // Clinical Laboratory Improvement Amendment Number
619 "*" . $claim->cliaCode() .
623 // Segment REF*9A (Repriced Claim Number) omitted.
624 // Segment REF*9C (Adjusted Repriced Claim Number) omitted.
625 // Segment REF*LX (Investigational Device Exemption Number) omitted.
626 // Segment REF*D9 (Claim Identifier for Transmission Intermediaries) omitted.
627 // Segment REF*EA (Medical Record Number) omitted.
628 // Segment REF*P4 (Demonstration Project Identifier) omitted.
629 // Segment REF*1J (Care Plan Oversight) omitted.
630 // Segment K3 (File Information) omitted.
632 if ($claim->additionalNotes()) {
635 $out .= "NTE" . // comments box 19
636 "*" . ($CMS_5010 ?
"ADD" : "") .
637 "*" . $claim->additionalNotes() .
641 // Segment CR1 (Ambulance Transport Information) omitted.
642 // Segment CR2 (Spinal Manipulation Service Information) omitted.
643 // Segment CRC (Ambulance Certification) omitted.
644 // Segment CRC (Patient Condition Information: Vision) omitted.
645 // Segment CRC (Homebound Indicator) omitted.
646 // Segment CRC (EPSDT Referral) omitted.
648 // Diagnoses, up to $max_per_seg per HI segment.
649 $max_per_seg = $CMS_5010 ?
12 : 8;
650 $da = $claim->diagArray();
651 if ($claim->diagtype
== "ICD9") {
652 $diag_type_code = 'BK';
656 $diag_type_code = 'ABK';
659 foreach ($da as $diag) {
660 if ($tmp %
$max_per_seg == 0) {
661 if ($tmp) $out .= "~\n";
663 $out .= "HI"; // Health Diagnosis Codes
665 $out .= "*$diag_type_code:" . $diag;
666 if ($claim->diagtype
== "ICD9") {
667 $diag_type_code = 'BF';
671 $diag_type_code = 'ABF';
675 if ($tmp) $out .= "~\n";
677 // Segment HI*BP (Anesthesia Related Procedure) omitted.
678 // Segment HI*BG (Condition Information) omitted.
679 // Segment HCP (Claim Pricing/Repricing Information) omitted.
681 if ($claim->referrerLastName()) {
682 // Medicare requires referring provider's name and UPIN.
684 $out .= "NM1" . // Loop 2310A Referring Provider
687 "*" . $claim->referrerLastName() .
688 "*" . $claim->referrerFirstName() .
689 "*" . $claim->referrerMiddleName() .
692 if ($CMS_5010 ||
$claim->referrerNPI()) { $out .=
694 "*" . $claim->referrerNPI();
696 "*34" . // not allowed for 5010
697 "*" . $claim->referrerSSN();
701 if (!$CMS_5010 && $claim->referrerTaxonomy()) {
704 "*RF" . // ReFerring provider
706 "*" . $claim->referrerTaxonomy() .
710 if (!CMS_5010
&& $claim->referrerUPIN()) {
712 $out .= "REF" . // Referring Provider Secondary Identification
714 "*" . $claim->referrerUPIN() .
720 /* Per the implementation guide lines, only include this information if it is different
721 * than the Loop 2010AA information
724 ($claim->providerNPIValid() &&
725 $claim->billingFacilityNPI() !== $claim->providerNPI() ))
728 $out .= "NM1" . // Loop 2310B Rendering Provider
731 "*" . $claim->providerLastName() .
732 "*" . $claim->providerFirstName() .
733 "*" . $claim->providerMiddleName() .
736 if ($CMS_5010 ||
$claim->providerNPI()) { $out .=
738 "*" . $claim->providerNPI();
740 "*34" . // not allowed for 5010
741 "*" . $claim->providerSSN();
742 $log .= "*** Rendering provider has no NPI.\n";
746 if ($claim->providerTaxonomy()) {
749 "*PE" . // PErforming provider
750 "*" . ($CMS_5010 ?
"PXC" : "ZZ") .
751 "*" . $claim->providerTaxonomy() .
758 // This loop can only get skipped if we are generating a 5010 claim
759 if(!($claim->providerNPIValid()))
761 /* If the loop was skipped because the provider NPI was invalid, generate
762 * a warning for the log.*/
763 $log.="*** Skipping 2310B because ".$claim->providerLastName() ."," . $claim->providerFirstName() . " has invalid NPI.\n";
765 /* Skipping this segment because the providerNPI and the billingFacilityNPI are identical
766 * is a normal condition, so no need to warn.
771 // 4010: REF*1C is required here for the Medicare provider number if NPI was
772 // specified in NM109. Not sure if other payers require anything here.
773 // --- apparently ECLAIMS, INC wants the data in 2010 but NOT in 2310B - tony@mi-squared.com
775 // 5010 spec says nothing here if NPI was specified.
777 if (($CMS_5010 && !$claim->providerNPI() && in_array($claim->providerNumberType(), array('0B','1G','G2','LU')))
778 ||
(!$CMS_5010 && trim($claim->x12gsreceiverid()) != '470819582')) // if NOT ECLAIMS EDI
780 if ($claim->providerNumber()) {
783 "*" . $claim->providerNumberType() .
784 "*" . $claim->providerNumber() .
789 // Loop 2310D is omitted in the case of home visits (POS=12).
790 if ($claim->facilityPOS() != 12 &&
791 (!$CMS_5010 ||
$claim->facilityNPI() != $claim->billingFacilityNPI()))
794 $out .= "NM1" . // Loop 2310D Service Location
797 //Field length is limited to 35. See nucc dataset page 77 www.nucc.org
798 $facilityName = substr($claim->facilityName(), 0, $CMS_5010 ?
60 : 35);
799 if ($claim->facilityName() ||
$claim->facilityNPI() ||
$claim->facilityETIN()) { $out .=
802 if ($claim->facilityNPI() ||
$claim->facilityETIN()) { $out .=
807 if ($CMS_5010 ||
$claim->facilityNPI()) { $out .=
808 "*XX*" . $claim->facilityNPI();
810 "*24*" . $claim->facilityETIN();
812 if (!$claim->facilityNPI()) {
813 $log .= "*** Service location has no NPI.\n";
817 if ($claim->facilityStreet()) {
820 "*" . $claim->facilityStreet() .
823 if ($claim->facilityState()) {
826 "*" . $claim->facilityCity() .
827 "*" . $claim->facilityState() .
828 "*" . stripZipCode($claim->facilityZip()) .
833 // Segment REF (Service Facility Location Secondary Identification) omitted.
834 // Segment PER (Service Facility Contact Information) omitted.
836 // Loop 2310E, Supervising Provider
838 if ($claim->supervisorLastName()) {
841 "*DQ" . // Supervising Physician
843 "*" . $claim->supervisorLastName() .
844 "*" . $claim->supervisorFirstName() .
845 "*" . $claim->supervisorMiddleName() .
846 "*" . // NM106 not used
848 if ($CMS_5010 ||
$claim->supervisorNPI()) { $out .=
850 "*" . $claim->supervisorNPI();
853 "*" . $claim->supervisorSSN();
855 if (!$claim->supervisorNPI()) {
856 $log .= "*** Supervising Provider has no NPI.\n";
860 if ($claim->supervisorNumber()) {
863 "*" . $claim->supervisorNumberType() .
864 "*" . $claim->supervisorNumber() .
869 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
870 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
872 $prev_pt_resp = $clm_total_charges; // for computation below
874 // Loops 2320 and 2330*, other subscriber/payer information.
875 // Remember that insurance index 0 is always for the payer being billed
876 // by this claim, and 1 and above are always for the "other" payers.
878 for ($ins = 1; $ins < $claim->payerCount(); ++
$ins) {
880 $tmp1 = $claim->claimType($ins);
881 $tmp2 = 'C1'; // Here a kludge. See page 321.
882 if ($tmp1 === 'CI') $tmp2 = 'C1';
883 if ($tmp1 === 'AM') $tmp2 = 'AP';
884 if ($tmp1 === 'HM') $tmp2 = 'HM';
885 if ($tmp1 === 'MB') $tmp2 = 'MB';
886 if ($tmp1 === 'MC') $tmp2 = 'MC';
887 if ($tmp1 === '09') $tmp2 = 'PP';
889 $out .= "SBR" . // Loop 2320, Subscriber Information - page 297/318
890 "*" . $claim->payerSequence($ins) .
891 "*" . $claim->insuredRelationship($ins) .
892 "*" . $claim->groupNumber($ins) .
893 "*" . (($CMS_5010 && $claim->groupNumber($ins)) ?
'' : $claim->groupName($ins)) .
894 "*" . ($CMS_5010 ?
$claim->insuredTypeCode($ins) : $tmp2) .
898 "*" . $claim->claimType($ins) .
901 // Things that apply only to previous payers, not future payers.
903 if ($claim->payerSequence($ins) < $claim->payerSequence()) {
905 // Generate claim-level adjustments.
906 $aarr = $claim->payerAdjustments($ins);
907 foreach ($aarr as $a) {
909 $out .= "CAS" . // Previous payer's claim-level adjustments. Page 301/323.
916 $payerpaid = $claim->payerTotals($ins);
918 $out .= "AMT" . // Previous payer's paid amount. Page 307/332.
920 "*" . $payerpaid[1] .
923 // Segment AMT*A8 (COB Total Non-Covered Amount) omitted.
924 // Segment AMT*EAF (Remaining Patient Liability) omitted.
927 // Patient responsibility amount as of this previous payer.
928 $prev_pt_resp -= $payerpaid[1]; // reduce by payments
929 $prev_pt_resp -= $payerpaid[2]; // reduce by adjustments
932 $out .= "AMT" . // Allowed amount per previous payer. Page 334.
934 "*" . sprintf('%.2f', $payerpaid[1] +
$prev_pt_resp) .
938 $out .= "AMT" . // Patient responsibility amount per previous payer. Page 335.
940 "*" . sprintf('%.2f', $prev_pt_resp) .
943 } // End of things that apply only to previous payers.
947 $out .= "DMG" . // Other subscriber demographic information. Page 342.
949 "*" . $claim->insuredDOB($ins) .
950 "*" . $claim->insuredSex($ins) .
955 $out .= "OI" . // Other Insurance Coverage Information. Page 310/344.
958 "*" . ($claim->billingFacilityAssignment($ins) ?
'Y' : 'N') .
959 // For this next item, the 5010 example in the spec does not match its
960 // description. So this might be wrong.
961 "*" . ($CMS_5010 ?
'' : 'B') .
966 // Segment MOA (Medicare Outpatient Adjudication) omitted.
969 $out .= "NM1" . // Loop 2330A Subscriber info for other insco. Page 315/350.
972 "*" . $claim->insuredLastName($ins) .
973 "*" . $claim->insuredFirstName($ins) .
974 "*" . $claim->insuredMiddleName($ins) .
978 "*" . $claim->policyNumber($ins) .
983 "*" . $claim->insuredStreet($ins) .
988 "*" . $claim->insuredCity($ins) .
989 "*" . $claim->insuredState($ins) .
990 "*" . stripZipCode($claim->insuredZip($ins)) .
993 // Segment REF (Other Subscriber Secondary Identification) omitted.
996 //Field length is limited to 35. See nucc dataset page 81 www.nucc.org
997 $payerName = substr($claim->payerName($ins), 0, $CMS_5010 ?
60 : 35);
998 $out .= "NM1" . // Loop 2330B Payer info for other insco. Page 322/359.
1007 "*" . $claim->payerID($ins) .
1010 // if (!$claim->payerID($ins)) {
1011 // $log .= "*** CMS ID is missing for payer '" . $claim->payerName($ins) . "'.\n";
1014 // Payer address (N3 and N4) are added below so that Gateway EDI can
1015 // auto-generate secondary claims. These do NOT appear in my copy of
1016 // the spec! -- Rod 2008-06-12
1018 if ($CMS_5010 ||
trim($claim->x12gsreceiverid()) == '431420764') { // if Gateway EDI
1021 "*" . $claim->payerStreet($ins) .
1026 "*" . $claim->payerCity($ins) .
1027 "*" . $claim->payerState($ins) .
1028 "*" . stripZipCode($claim->payerZip($ins)) .
1030 } // end Gateway EDI
1032 // Segment DTP*573 (Claim Check or Remittance Date) omitted.
1033 // Segment REF (Other Payer Secondary Identifier) omitted.
1034 // Segment REF*G1 (Other Payer Prior Authorization Number) omitted.
1035 // Segment REF*9F (Other Payer Referral Number) omitted.
1036 // Segment REF*T4 (Other Payer Claim Adjustment Indicator) omitted.
1037 // Segment REF*F8 (Other Payer Claim Control Number) omitted.
1038 // Segment NM1 (Other Payer Referring Provider) omitted.
1039 // Segment REF (Other Payer Referring Provider Secondary Identification) omitted.
1040 // Segment NM1 (Other Payer Rendering Provider) omitted.
1041 // Segment REF (Other Payer Rendering Provider Secondary Identification) omitted.
1042 // Segment NM1 (Other Payer Service Facility Location) omitted.
1043 // Segment REF (Other Payer Service Facility Location Secondary Identification) omitted.
1044 // Segment NM1 (Other Payer Supervising Provider) omitted.
1045 // Segment REF (Other Payer Supervising Provider Secondary Identification) omitted.
1046 // Segment NM1 (Other Payer Billing Provider) omitted.
1047 // Segment REF (Other Payer Billing Provider Secondary Identification) omitted.
1049 } // End loops 2320/2330*.
1053 // Procedure loop starts here.
1055 for ($prockey = 0; $prockey < $proccount; ++
$prockey) {
1059 $out .= "LX" . // Loop 2400 LX Service Line. Page 398.
1064 $out .= "SV1" . // Professional Service. Page 400.
1065 "*HC:" . $claim->cptKey($prockey) .
1066 "*" . sprintf('%.2f', $claim->cptCharges($prockey)) .
1068 "*" . $claim->cptUnits($prockey) .
1072 $dia = $claim->diagIndexArray($prockey);
1074 foreach ($dia as $dindex) {
1075 if ($i) $out .= ':';
1077 if (++
$i >= 4) break;
1081 if (!$claim->cptCharges($prockey)) {
1082 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no charges!\n";
1086 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' is not justified!\n";
1089 // Segment SV5 (Durable Medical Equipment Service) omitted.
1090 // Segment PWK (Line Supplemental Information) omitted.
1091 // Segment PWK (Durable Medical Equipment Certificate of Medical Necessity Indicator) omitted.
1092 // Segment CR1 (Ambulance Transport Information) omitted.
1093 // Segment CR3 (Durable Medical Equipment Certification) omitted.
1094 // Segment CRC (Ambulance Certification) omitted.
1095 // Segment CRC (Hospice Employee Indicator) omitted.
1096 // Segment CRC (Condition Indicator / Durable Medical Equipment) omitted.
1099 $out .= "DTP" . // Date of Service. Page 435.
1102 "*" . $claim->serviceDate() .
1105 $testnote = rtrim($claim->cptNotecodes($prockey));
1106 if (!empty($testnote)) {
1108 $out .= "NTE" . // Explain Unusual Circumstances.
1110 "*" . $claim->cptNotecodes($prockey) .
1114 // Segment DTP*471 (Prescription Date) omitted.
1115 // Segment DTP*607 (Revision/Recertification Date) omitted.
1116 // Segment DTP*463 (Begin Therapy Date) omitted.
1117 // Segment DTP*461 (Last Certification Date) omitted.
1118 // Segment DTP*304 (Last Seen Date) omitted.
1119 // Segment DTP (Test Date) omitted.
1120 // Segment DTP*011 (Shipped Date) omitted.
1121 // Segment DTP*455 (Last X-Ray Date) omitted.
1122 // Segment DTP*454 (Initial Treatment Date) omitted.
1123 // Segment QTY (Ambulance Patient Count) omitted.
1124 // Segment QTY (Obstetric Anesthesia Additional Units) omitted.
1125 // Segment MEA (Test Result) omitted.
1126 // Segment CN1 (Contract Information) omitted.
1127 // Segment REF*9B (Repriced Line Item Reference Number) omitted.
1128 // Segment REF*9D (Adjusted Repriced Line Item Reference Number) omitted.
1129 // Segment REF*G1 (Prior Authorization) omitted.
1130 // Segment REF*6R (Line Item Control Number) omitted.
1131 // (Really oughta have this for robust 835 posting!)
1132 // Segment REF*EW (Mammography Certification Number) omitted.
1133 // Segment REF*X4 (CLIA Number) omitted.
1134 // Segment REF*F4 (Referring CLIA Facility Identification) omitted.
1135 // Segment REF*BT (Immunization Batch Number) omitted.
1136 // Segment REF*9F (Referral Number) omitted.
1137 // Segment AMT*T (Sales Tax Amount) omitted.
1138 // Segment AMT*F4 (Postage Claimed Amount) omitted.
1139 // Segment K3 (File Information) omitted.
1140 // Segment NTE (Line Note) omitted.
1141 // Segment NTE (Third Party Organization Notes) omitted.
1142 // Segment PS1 (Purchased Service Information) omitted.
1143 // Segment HCP (Line Pricing/Repricing Information) omitted.
1146 // This segment was deleted for 5010.
1148 // AMT*AAE segment for Approved Amount from previous payer.
1149 // Medicare secondaries seem to require this.
1151 for ($ins = $claim->payerCount() - 1; $ins > 0; --$ins) {
1152 if ($claim->payerSequence($ins) > $claim->payerSequence())
1153 continue; // payer is future, not previous
1154 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
1156 $out .= "AMT" . // Approved amount per previous payer. Page 485.
1158 "*" . sprintf('%.2f', $claim->cptCharges($prockey) - $payerpaid[2]) .
1164 // Loop 2410, Drug Information. Medicaid insurers seem to want this
1165 // with HCPCS codes.
1167 $ndc = $claim->cptNDCID($prockey);
1170 $out .= "LIN" . // Drug Identification. Page 500+ (Addendum pg 71).
1171 "*" . // Per addendum, LIN01 is not used.
1176 if (!preg_match('/^\d\d\d\d\d-\d\d\d\d-\d\d$/', $ndc, $tmp) && !preg_match('/^\d{11}$/', $ndc)) {
1177 $log .= "*** NDC code '$ndc' has invalid format!\n";
1181 $tmpunits = $claim->cptNDCQuantity($prockey) * $claim->cptUnits($prockey);
1182 if (!$tmpunits) $tmpunits = 1;
1183 $out .= "CTP" . // Drug Pricing. Page 500+ (Addendum pg 74).
1186 "*" . ($CMS_5010 ?
'' : sprintf('%.2f', $claim->cptCharges($prockey) / $tmpunits)) .
1187 "*" . $claim->cptNDCQuantity($prockey) .
1188 "*" . $claim->cptNDCUOM($prockey) .
1189 // Note: 5010 documents "ME" (Milligrams) as an additional unit of measure.
1193 // Segment REF (Prescription or Compound Drug Association Number) omitted.
1195 // Loop 2420A, Rendering Provider (service-specific).
1196 // Used if the rendering provider for this service line is different
1197 // from that in loop 2310B.
1199 if ($claim->providerNPI() != $claim->providerNPI($prockey)) {
1201 $out .= "NM1" . // Loop 2310B Rendering Provider
1204 "*" . $claim->providerLastName($prockey) .
1205 "*" . $claim->providerFirstName($prockey) .
1206 "*" . $claim->providerMiddleName($prockey) .
1209 if ($CMS_5010 ||
$claim->providerNPI($prockey)) { $out .=
1211 "*" . $claim->providerNPI($prockey);
1213 "*34" . // Not allowed for 5010
1214 "*" . $claim->providerSSN($prockey);
1216 if (!$claim->providerNPI($prockey)) {
1217 $log .= "*** Rendering provider has no NPI.\n";
1221 if ($claim->providerTaxonomy($prockey)) {
1224 "*PE" . // PErforming provider
1225 "*" . ($CMS_5010 ?
"PXC" : "ZZ") .
1226 "*" . $claim->providerTaxonomy($prockey) .
1230 // Segment PRV*PE (Rendering Provider Specialty Information) omitted.
1231 // Segment REF (Rendering Provider Secondary Identification) omitted.
1232 // Segment NM1 (Purchased Service Provider Name) omitted.
1233 // Segment REF (Purchased Service Provider Secondary Identification) omitted.
1234 // Segment NM1,N3,N4 (Service Facility Location) omitted.
1235 // Segment REF (Service Facility Location Secondary Identification) omitted.
1236 // Segment NM1 (Supervising Provider Name) omitted.
1237 // Segment REF (Supervising Provider Secondary Identification) omitted.
1238 // Segment NM1,N3,N4 (Ordering Provider) omitted.
1239 // Segment REF (Ordering Provider Secondary Identification) omitted.
1240 // Segment PER (Ordering Provider Contact Information) omitted.
1241 // Segment NM1 (Referring Provider Name) omitted.
1242 // Segment REF (Referring Provider Secondary Identification) omitted.
1243 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
1244 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
1246 // REF*1C is required here for the Medicare provider number if NPI was
1247 // specified in NM109. Not sure if other payers require anything here.
1248 if (!$CMS_5010 && $claim->providerNumber($prockey)) {
1251 "*" . $claim->providerNumberType($prockey) .
1252 // Note: 5010 documents that type 1D (Medicaid) is changed to G2.
1253 "*" . $claim->providerNumber($prockey) .
1258 // Loop 2430, adjudication by previous payers.
1260 for ($ins = 1; $ins < $claim->payerCount(); ++
$ins) {
1261 if ($claim->payerSequence($ins) > $claim->payerSequence())
1262 continue; // payer is future, not previous
1264 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
1265 $aarr = $claim->payerAdjustments($ins, $claim->cptKey($prockey));
1267 if ($payerpaid[1] == 0 && !count($aarr)) {
1268 $log .= "*** Procedure '" . $claim->cptKey($prockey) .
1269 "' has no payments or adjustments from previous payer!\n";
1274 $out .= "SVD" . // Service line adjudication. Page 554.
1275 "*" . $claim->payerID($ins) .
1276 "*" . $payerpaid[1] .
1277 "*HC:" . $claim->cptKey($prockey) .
1279 "*" . $claim->cptUnits($prockey) .
1282 $tmpdate = $payerpaid[0];
1283 foreach ($aarr as $a) {
1285 $out .= "CAS" . // Previous payer's line level adjustments. Page 558.
1290 if (!$tmpdate) $tmpdate = $a[0];
1293 /*************************************************************
1294 if ( isset($a[4]) &&
1296 $out .= "CAS02" . // Previous payer's adjustment reason
1300 *************************************************************/
1305 $out .= "DTP" . // Previous payer's line adjustment date. Page 493/566.
1312 // Segment AMT*EAF (Remaining Patient Liability) omitted.
1313 // Segment LQ (Form Identification Code) omitted.
1314 // Segment FRM (Supporting Documentation) omitted.
1317 } // end this procedure
1320 $out .= "SE" . // SE Trailer
1325 $out .= "GE" . // GE Trailer
1330 $out .= "IEA" . // IEA Trailer
1335 // Remove any trailing empty fields (delimiters) from each segment.
1336 $out = preg_replace('/\*+~/', '~', $out);