7 * @link https://www.open-emr.org
8 * @author Jerry Padgett <sjpadgett@gmail.com>
9 * @copyright Copyright (c) 2017 Jerry Padgett <sjpadgett@gmail.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 namespace OpenEMR\Billing
;
15 use OpenEMR\Billing\Claim
;
19 public function x12Date($frmdate)
21 return ('20' . substr($frmdate, 4, 2) . substr($frmdate, 0, 2) . substr($frmdate, 2, 2));
24 public $ub04id = array();
26 public function generateX12837I($pid, $encounter, &$log, $ub04id)
30 $claim = new Claim($pid, $encounter);
33 $log .= "Generating 837I claim $pid-$encounter for " .
34 $claim->patientFirstName() . ' ' .
35 $claim->patientMiddleName() . ' ' .
36 $claim->patientLastName() . ' on ' .
37 date('Y-m-d H:i', $today) . ".\n";
39 "*" . $claim->x12gsisa01() .
40 "*" . $claim->x12gsisa02() .
41 "*" . $claim->x12gsisa03() .
42 "*" . $claim->x12gsisa04() .
43 "*" . $claim->x12gsisa05() .
44 "*" . $claim->x12_sender_id() .
45 "*" . $claim->x12gsisa07() .
46 "*" . $claim->x12gsreceiverid() .
47 // date of transmission "*030911" .
48 "*" . date('Ymd', $today) .
49 //Time of transmission "*1630" .
50 "*" . date('Hi', $today) .
54 "*" . $claim->x12gsisa14() .
55 "*" . $claim->x12gsisa15() .
60 "*" . $claim->x12gsgs02() .
61 "*" . trim($claim->x12gs03()) .
62 "*" . date('Ymd', $today) .
63 "*" . date('Hi', $today) .
66 // "*" . $claim->x12gsversionstring() .
67 "*" . "005010X223A2" .
73 // "*" . $claim->x12gsversionstring() .
74 "*" . "005010X223A2" .
78 "*" . "0019" . // 0019 is required here
79 "*" . "00" . // 00 = original transmission
80 "*" . "0123" . // reference identification
81 "*" . date('Ymd', $today) . // transaction creation date
82 "*" . date('Hi', $today) . // transaction creation time
83 ($encounter_claim ?
"*RP" : "*CH") . // RP = reporting, CH = chargeable
87 //Field length is limited to 35. See nucc dataset page 63 www.nucc.org
88 $billingFacilityName = substr($claim->billingFacilityName(), 0, 60);
89 if ($billingFacilityName == '') {
90 $log .= "*** billing facility name in 1000A loop is empty\n";
92 $out .= "NM1" . // Loop 1000A Submitter stays in the 837I
95 "*" . $billingFacilityName .
102 $out .= "*" . $claim->billingFacilityETIN();
108 "*" . $claim->billingContactName() .
110 "*" . $claim->billingContactPhone();
115 $out .= "NM1" . // Loop 1000B Receiver stays in the 837I
118 "*" . $claim->clearingHouseName() .
124 "*" . $claim->clearingHouseETIN() .
129 $out .= "HL" . // Loop 2000A Billing/Pay-To Provider HL Loop
133 "*" . "1" . // 1 indicates there are child segments
135 $HLBillingPayToProvider = $HLcount++
;
136 // Situational PRV segment (for provider taxonomy code) omitted here.
137 // Situational CUR segment (foreign currency information) omitted here.
139 //Field length is limited to 35. See nucc dataset page 63 www.nucc.org
140 $billingFacilityName = substr($claim->billingFacilityName(), 0, 60);
141 $out .= "NM1" . // Loop 2010AA Billing Provider stays in the 837I
144 "*" . $billingFacilityName .
149 if ($claim->billingFacilityNPI()) {
150 $out .= "*XX*" . $claim->billingFacilityNPI();
152 $log .= "*** Billing facility has no NPI.\n";
158 "*" . $claim->billingFacilityStreet() .
162 "*" . $claim->billingFacilityCity() .
163 "*" . $claim->billingFacilityState() .
164 "*" . $claim->x12Zip($claim->billingFacilityZip()) .
166 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
169 if ($claim->federalIdType()) {
170 $out .= "*" . $claim->federalIdType();
172 $out .= "*EI"; // For dealing with the situation before adding TaxId type In facility.
174 $out .= "*" . $claim->billingFacilityETIN() . "~\n";
176 $log .= "*** No billing facility NPI and/or ETIN.\n";
178 if ($claim->providerNumberType() && $claim->providerNumber() && !$claim->billingFacilityNPI()) {
181 "*" . $claim->providerNumberType() .
182 "*" . $claim->providerNumber() .
184 } elseif ($claim->providerNumber() && !$claim->providerNumberType()) {
185 $log .= "*** Payer-specific provider insurance number is present but has no type assigned.\n";
187 // Situational PER*1C segment.
191 "*" . $claim->billingContactName() .
193 "*" . $claim->billingContactPhone();
196 // This is also excluded in the 837I
197 // Loop 2010AC Pay-To Plan Name omitted. Includes:
198 // NM1*PE, N3, N4, REF*2U, REF*EI
199 $PatientHL = $claim->isSelfOfInsured() ?
0 : 1;
200 $HLSubscriber = $HLcount++
;
204 $out .= "HL" . // Loop 2000B Subscriber HL Loop
206 "*$HLBillingPayToProvider" .
210 if (!$claim->payerSequence()) {
211 $log .= "*** Error: Insurance information is missing!\n";
215 //SBR01 is either a P or S SBR02 for care is always 18 "patient" SBR09 is always MA
216 $out .= "SBR" . // Subscriber Information
217 "*" . $claim->payerSequence() .
218 "*" . ($claim->isSelfOfInsured() ?
'18' : '') .
219 "*" . $claim->groupNumber() .
220 "*" . (($claim->groupNumber()) ?
'' : $claim->groupName()) .
221 "*" . $claim->insuredTypeCode() . // applies for secondary medicare
225 "*" . $claim->claimType() . // Zirmed replaces this
227 // 2000C Segment PAT omitted.
229 $out .= "NM1" . // Loop 2010BA Subscriber same in 837I
231 "*" . "1" . // 1 = person, 2 = non-person
232 "*" . $claim->insuredLastName() .
233 "*" . $claim->insuredFirstName() .
234 "*" . $claim->insuredMiddleName() .
238 // "MI" = Member Identification Number
239 // "II" = Standard Unique Health Identifier, "Required if the
240 // HIPAA Individual Patient Identifier is mandated use."
241 // Here we presume that is not true yet.
242 "*" . $claim->policyNumber() .
244 // For 5010, further subscriber info is sent only if they are the patient.
245 if ($claim->isSelfOfInsured()) {
248 "*" . $claim->insuredStreet() .
252 "*" . $claim->insuredCity() .
253 "*" . $claim->insuredState() .
254 "*" . $claim->x12Zip($claim->insuredZip()) .
259 "*" . $claim->insuredDOB() .
260 "*" . $claim->insuredSex() .
263 // Segment REF*SY (Subscriber Secondary Identification) omitted.
264 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
265 // Segment PER*IC (Property and Casualty Subscriber Contact Information) omitted.
267 $payerName = substr($claim->payerName(), 0, 60);
268 $out .= "NM1" . // Loop 2010BB Payer
277 "*" . ($encounter_claim ?
$claim->payerAltID() : $claim->payerID()) .
279 if (!$claim->payerID()) {
280 $log .= "*** Payer ID is missing for payer '" . $claim->payerName() . "'.\n";
285 "*" . $claim->payerStreet() .
289 "*" . $claim->payerCity() .
290 "*" . $claim->payerState() .
291 "*" . $claim->x12Zip($claim->payerZip()) .
294 // Segment REF (Payer Secondary Identification) omitted.
295 // Segment REF (Billing Provider Secondary Identification) omitted.
298 if (!$claim->isSelfOfInsured()) {
300 $out .= "HL" . // Loop 2000C Patient Information
309 "*" . $claim->insuredRelationship() .
312 $out .= "NM1" . // Loop 2010CA Patient may need this elsed in to the loop 2000C
315 "*" . $claim->patientLastName() .
316 "*" . $claim->patientFirstName();
317 if ($claim->patientMiddleName() !== '') {
318 $out .= "*" . $claim->patientMiddleName();
323 "*" . $claim->patientStreet() .
327 "*" . $claim->patientCity() .
328 "*" . $claim->patientState() .
329 "*" . $claim->x12Zip($claim->patientZip()) .
334 "*" . $claim->patientDOB() .
335 "*" . $claim->patientSex() .
337 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
338 // Segment REF (Property and Casualty Patient Identifier) omitted.
339 // Segment PER (Property and Casualty Patient Contact Information) omitted.
340 } // end of patient different from insured
341 $proccount = $claim->procCount();
342 $clm_total_charges = 0;
343 for ($prockey = 0; $prockey < $proccount; ++
$prockey) {
344 $clm_total_charges +
= $claim->cptCharges($prockey);
346 if (!$clm_total_charges) {
347 $log .= "*** This claim has no charges!\n";
350 $out .= "CLM" . // Loop 2300 Claim
351 "*" . $pid . "-" . $encounter .
352 "*" . sprintf("%.2f", $clm_total_charges) . // Zirmed computes and replaces this
355 // Service location this need to be bill type from ub form type_of_bill
356 if (strlen($ub04id[7]) >= 3) {
357 $out .= "*" . substr($ub04id[7], 1, 1) . ":" . substr($ub04id[7], 2, 1) . ":" . substr($ub04id[7], 3, 1);
362 "*" . ($claim->billingFacilityAssignment() ?
'Y' : 'N') .
368 $out .= "DTP" . // Loop 2300
376 // DTP 434 RD8 (Statment from OR to date)
381 $tmp = self
::x12Date($ub04id[13]);
382 $tmp1 = self
::x12Date($ub04id[14]);
383 $out .= "DTP" . // Loop 2300
384 "*434" . "*" . "RD8" . "*" . $tmp . '-' . $tmp1 . "~\n";
389 $tmp = self
::x12Date($ub04id[25]);
390 $out .= "DTP" . // Loop 2300
391 "*435" . "*" . "DT" . "*" . $tmp . $ub04id[26] . "~\n";
394 if (strlen(trim($ub04id[13])) == 0) {
395 $log .= "*** Error: No Admission Date Entered!\n";
398 // Repricer Received Date
399 // DTP 050 D8 (Admission Date and Hour from form)
401 // Institutional Claim Code
402 // CL1 (Admission Type Code) (Admission Source Code) (Patient Status Code)
404 if ($ub04id[27] != "014X") { // Type of bill
406 $out .= "CL1" . // Loop 2300
407 "*" . $ub04id[27] . "*" . $ub04id[28] . "*" . $ub04id[30] . "~\n";
410 // Segment PWK (Claim Supplemental Information) omitted.
412 // Segment CN1 (Contract Information) omitted.
414 // Patient Estimated Amount Due
417 // $patientpaid = $claim->patientPaidAmount();
418 // if ($patientpaid != 0) {
420 // $out .= "AMT" . // Patient paid amount. Page 190/220.
422 // "*" . $patientpaid .
426 // Segment REF*4N (Service Authorization Exception Code) omitted.
427 // Segment REF*9F (Referral Number) omitted.
429 // Prior Authorization
431 if ($claim->priorAuth()) {
433 $out .= "REF" . // Prior Authorization Number
434 "*G1" . "*" . $claim->priorAuth() . "~\n";
437 // Segment REF*F8 (Payer Claim Control Number) omitted.
439 // This may be needed for the UB04 Claim if so change the 'MB' to 'MA'
440 // if ($claim->cliaCode() && ($CMS_5010 || $claim->claimType() === 'MB')) {
441 // Required by Medicare when in-house labs are done.
443 // $out .= "REF" . // Clinical Laboratory Improvement Amendment Number
445 // "*" . $claim->cliaCode() .
449 // Segment REF*9A (Repriced Claim Number) omitted.
450 // Segment REF*9C (Adjusted Repriced Claim Number) omitted.
451 // Segment REF*LX (Investigational Device Exemption Number) omitted.
452 // Segment REF*S9 (Claim Identifier for Transmission Intermediaries) omitted.
453 // Segment REF*LU (Auto Accident State) omitted.
454 // Segment REF*EA (Medical Record Number) omitted.
455 // Segment REF*P4 (Demonstration Project Identifier) omitted.
456 // Segment REF*G4 (Peer Review Organization PRO Approval Number) omitted.
457 // Segment K3 (File Information) omitted.
459 if ($claim->additionalNotes()) {
461 // Has a list of valid codes. Required when PROVIDER deems necessary
464 // Check to verify I am getting this information on the ub04 form
467 $out .= "NTE" . // comments box 19
468 "*" . "ADD" . "*" . $claim->additionalNotes() . "~\n";
471 // Segment CRC (EPSDT Referral) omitted.
472 // Diagnoses, up to $max_per_seg per HI segment. Check this
474 $da = $claim->diagArray();
475 $diag_type_code = 'ABK'; // ICD10
477 foreach ($da as $diag) {
481 if ($tmp %
$max_per_seg == 0) {
486 $out .= "HI"; // Health Diagnosis Codes
488 $out .= "*" . $diag_type_code . ":" . $diag;
489 if ($claim->diagtype
== "ICD9") {
490 $diag_type_code = 'BF';
492 $diag_type_code = 'ABF';
501 // Segment HI*BI (Occurrence Span Information).
502 // HI BI (Occurrence Span Code 1) RD8 (Occurrence Span Code Associated Date)
505 $diag_type_code = 'BI';
508 for ($i = 0; $i <= 3;) {
509 if ($tmp %
$max_per_seg == 0) {
514 $out .= "HI"; // Health Diagnosis Codes
517 $out .= "*" . $diag_type_code . ":" . $ub04id[$os++
] . ":" . self
::x12Date($ub04id[$os++
]) . ":" . self
::x12Date($ub04id[$os++
]);
518 $diag_type_code = 'BI';
531 // Segment HI*BH (Occurrence Information).
532 // HI BH (Occurrence Code 1) D8 (Occurrence Code Associated Date)
536 $diag_type_code = 'BH';
539 for ($i = 0; $i <= 7;) {
540 if ($tmp %
$max_per_seg == 0) {
545 $out .= "HI"; // Health Diagnosis Codes
548 $out .= "*" . $diag_type_code . ":" . $ub04id[$os] . ":D8" . ":" . self
::x12Date($ub04id[$os++
]);
549 $diag_type_code = 'BH';
562 // Segment HI*BE (Value Information).
563 // HI BE (Value Code 1) *.* (Value Code Amount)
567 $diag_type_code = 'BE';
570 for ($i = 0; $i <= 11;) {
571 if ($tmp %
$max_per_seg == 0) {
576 $out .= "HI"; // Health Diagnosis Codes
580 $out .= "*" . $diag_type_code . ":" . $ub04id[$os++
] . ":" . ":" . self
::x12Date($ub04id[$os++
]);
581 $diag_type_code = 'BE';
592 // Segment HI*BG (Condition Information).
593 // HI BG (Condition Code 1)
597 $diag_type_code = 'BG';
600 for ($i = 0; $i <= 10;) {
601 if ($tmp %
$max_per_seg == 0) {
606 $out .= "HI"; // Health Diagnosis Codes
610 $out .= "*" . $diag_type_code . ":" . $ub04id[$os++
];
611 $diag_type_code = 'BG';
623 // Segment HI*TC (Treatment Code Information).
624 // HI TC (Treatment Code 1)
625 /* 63a. TREATMENT AUTHORIZATION CODES - PRIMARY PLAN */
628 $diag_type_code = 'TC';
631 for ($i = 0; $i <= 2;) {
632 if ($tmp %
$max_per_seg == 0) {
637 $out .= "HI"; // Health Diagnosis Codes
641 $out .= "*" . $diag_type_code . ":" . $ub04id[319];
642 $diag_type_code = 'TC';
646 $out .= "*" . $diag_type_code . ":" . $ub04id[322];
647 $diag_type_code = 'TC';
652 $out .= "*" . $diag_type_code . ":" . $ub04id[325];
653 $diag_type_code = 'TC';
665 // Segment HCP (Claim Pricing/Repricing Information) omitted.
667 // This needs to allow Attending Physician 2310A, Operating Physician Name 2310B, Other Operating Physician Name 2310C
668 // and Rendering Provider Name (Rendering Provider Name is futher down)
672 // Loop 2310A Attending Physician
673 $out .= "NM1" . "*71" . "*1" . "*" . $ub04id[388] . "*" . $ub04id[389] . "*" . "*";
674 if ($ub04id[379]) { // NPI
675 $out .= "*" . "XX" . "*" . $ub04id[379];
678 $log .= "*** Attending Physician has no NPI.\n";
684 $out .= "REF" . // Attending Physician Secondary Identification
685 "*" . $ub04id[380] . "*" . $ub04id[381] . "~\n";
694 $out .= "NM1" . // Loop 2310B operating Physician
695 "*72" . "*1" . "*" . $ub04id[400] . "*" . $ub04id[400] . "*" . "*";
697 $out .= "*" . "XX" . "*" . $ub04id[390];
700 $log .= "*** Operating Physician has no NPI qualifier.\n";
706 $out .= "REF" . // operating Physician Secondary Identification
707 "*" . $claim->$ub04id[391] . "*" . $ub04id[392] . "~\n";
716 $out .= "NM1" . // Loop 2310C other operating Physician
717 "*73" . "*1" . "*" . $ub04id[413] . "*" . $ub04id[414] . "*" . "*";
719 $out .= "*" . $ub04id[405] . "*" . $ub04id[406];
722 $log .= "*** Other Operating Physician has no NPI.\n";
728 $out .= "REF" . // other operating Physician Secondary Identification
729 "*" . $ub04id[407] . "*" . $ub04id[408] . "~\n";
735 $out .= "NM1" . // Loop 2310C other operating Physician
736 "*73" . "*1" . "*" . $ub04id[427] . "*" . $ub04id[428] . "*" . "*";
738 $out .= "*" . $ub04id[419] . "*" . $ub04id[420];
741 $log .= "*** Other Operating Physician has no NPI.\n";
747 $out .= "REF" . // other operating Physician Secondary Identification
748 "*" . $ub04id[422] . "*" . $ub04id[421] . "~\n";
752 * Per the implementation guide lines, only include this information if it is different
753 * than the Loop 2010AA information
755 if ($claim->providerNPIValid() && $claim->billingFacilityNPI() !== $claim->providerNPI()) {
757 $out .= "NM1" . // Loop 2310D Rendering Provider
758 "*82" . "*1" . "*" . $claim->providerLastName() . "*" . $claim->providerFirstName() . "*" . $claim->providerMiddleName() . "*" . "*";
759 if ($claim->providerNPI()) {
760 $out .= "*XX" . "*" . $claim->providerNPI();
762 $log .= "*** Rendering provider has no NPI.\n";
768 // This loop can only get skipped if we are generating a 5010 claim
769 if (!($claim->providerNPIValid())) {
770 //If the loop was skipped because the provider NPI was invalid, generate a warning for the log.
771 $log .= "*** Skipping 2310B because " . $claim->providerLastName() . "," . $claim->providerFirstName() . " has invalid NPI.\n";
774 * Skipping this segment because the providerNPI and the billingFacilityNPI are identical
775 * is a normal condition, so no need to warn.
779 // 5010 spec says nothing here if NPI was specified.
781 if (!$claim->providerNPI() && in_array($claim->providerNumberType(), array('0B', '1G', 'G2', 'LU'))) {
782 if ($claim->providerNumber()) {
784 $out .= "REF" . "*" . $claim->providerNumberType() . "*" . $claim->providerNumber() . "~\n";
788 // Loop 2310D is omitted in the case of home visits (POS=12).
789 if ($claim->facilityPOS() != 12 && ($claim->facilityNPI() != $claim->billingFacilityNPI())) {
792 // Service Facility Name
794 $out .= "NM1" . // Loop 2310E Service Location
796 $facilityName = substr($claim->facilityName(), 0, 60);
797 if ($claim->facilityName() ||
$claim->facilityNPI() ||
$claim->facilityETIN()) {
798 $out .= "*" . $facilityName;
800 if ($claim->facilityNPI() ||
$claim->facilityETIN()) {
801 $out .= "*" . "*" . "*" . "*";
802 if ($claim->facilityNPI()) {
803 $out .= "*XX*" . $claim->facilityNPI();
805 $log .= "*** Service location has no NPI.\n";
809 if ($claim->facilityStreet()) {
811 $out .= "N3" . "*" . $claim->facilityStreet() . "~\n";
813 if ($claim->facilityState()) {
815 $out .= "N4" . "*" . $claim->facilityCity() . "*" . $claim->facilityState() . "*" . $claim->x12Zip($claim->facilityZip()) . "~\n";
819 // Segment REF (Service Facility Location Secondary Identification) omitted.
820 // Segment PER (Service Facility Contact Information) omitted.
822 // Loop 2310F Referring Provider
824 if ($claim->referrerLastName()) {
825 // Medicare requires referring provider's name and UPIN.
828 $out .= "NM1" . // Loop 2310F Referring Provider this needs to change position
829 "*DN" . "*1" . "*" . $claim->referrerLastName() . "*" . $claim->referrerFirstName() . "*" . $claim->referrerMiddleName() . "*" . "*";
830 if ($claim->referrerNPI()) {
831 $out .= "*XX" . "*" . $claim->referrerNPI();
833 $log .= "*** Referrer has no NPI.\n";
838 // Loop 2310E, Supervising Provider
841 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
842 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
844 $prev_pt_resp = $clm_total_charges; // for computation below
846 // Loops 2320 and 2330*, other subscriber/payer information.
847 // Remember that insurance index 0 is always for the payer being billed
848 // by this claim, and 1 and above are always for the "other" payers.
850 for ($ins = 1; $ins < $claim->payerCount(); ++
$ins) {
851 $tmp1 = $claim->claimType($ins);
852 $tmp2 = 'C1'; // Here a kludge. See page 321.
853 if ($tmp1 === 'CI') {
856 if ($tmp1 === 'AM') {
859 if ($tmp1 === 'HM') {
862 if ($tmp1 === 'MB') {
865 if ($tmp1 === 'MA') {
868 if ($tmp1 === 'MC') {
871 if ($tmp1 === '09') {
876 $out .= "SBR" . // Loop 2320, Subscriber Information - page 297/318
877 "*" . $claim->payerSequence($ins) .
878 "*" . $claim->insuredRelationship($ins) .
879 "*" . $claim->groupNumber($ins) .
880 "*" . (($claim->groupNumber($ins)) ?
'' : $claim->groupName($ins)) .
881 "*" . ($claim->insuredTypeCode($ins) ?
$claim->insuredTypeCode($ins) : $tmp2) .
885 "*" . $claim->claimType($ins) .
888 // Things that apply only to previous payers, not future payers.
890 if ($claim->payerSequence($ins) < $claim->payerSequence()) {
891 // Generate claim-level adjustments.
892 $aarr = $claim->payerAdjustments($ins);
893 foreach ($aarr as $a) {
895 $out .= "CAS" . // Previous payer's claim-level adjustments. Page 301/323.
896 "*" . $a[1] . "*" . $a[2] . "*" . $a[3] . "~\n";
899 $payerpaid = $claim->payerTotals($ins);
901 $out .= "AMT" . // Previous payer's paid amount. Page 307/332.
902 "*D" . "*" . $payerpaid[1] . "~\n";
904 // Segment AMT*A8 (COB Total Non-Covered Amount) omitted.
905 // Segment AMT*EAF (Remaining Patient Liability) omitted.
906 } // End of things that apply only to previous payers.
909 $out .= "OI" . // Other Insurance Coverage Information. Page 310/344.
910 "*" . "*" . "*" . ($claim->billingFacilityAssignment($ins) ?
'Y' : 'N') .
911 // For this next item, the 5010 example in the spec does not match its
912 // description. So this might be wrong.
919 // Segment MOA (Medicare Outpatient Adjudication) omitted.
921 $out .= "NM1" . // Loop 2330A Subscriber info for other insco. Page 315/350.
924 "*" . $claim->insuredLastName($ins) .
925 "*" . $claim->insuredFirstName($ins) .
926 "*" . $claim->insuredMiddleName($ins) .
930 "*" . $claim->policyNumber($ins) .
935 "*" . $claim->insuredStreet($ins) .
940 "*" . $claim->insuredCity($ins) .
941 "*" . $claim->insuredState($ins) .
942 "*" . $claim->x12Zip($claim->insuredZip($ins)) .
945 // Segment REF (Other Subscriber Secondary Identification) omitted.
947 $payerName = substr($claim->payerName($ins), 0, 60);
948 $out .= "NM1" . // Loop 2330B Payer info for other insco. Page 322/359.
957 "*" . $claim->payerID($ins) .
960 if (!$claim->payerID($ins)) {
961 $log .= "*** Payer ID is missing for payer '" . $claim->payerName($ins) . "'.\n";
966 "*" . $claim->payerStreet($ins) .
971 "*" . $claim->payerCity($ins) .
972 "*" . $claim->payerState($ins) .
973 "*" . $claim->x12Zip($claim->payerZip($ins)) .
976 // Segment DTP*573 (Claim Check or Remittance Date) omitted.
977 // Segment REF (Other Payer Secondary Identifier) omitted.
978 // Segment REF*G1 (Other Payer Prior Authorization Number) omitted.
979 // Segment REF*9F (Other Payer Referral Number) omitted.
980 // Segment REF*T4 (Other Payer Claim Adjustment Indicator) omitted.
981 // Segment REF*F8 (Other Payer Claim Control Number) omitted.
982 // 2330C-I loops Omitted
983 } // End loops 2320/2330*.
987 // Procedure loop starts here.
990 for ($tlh = 0; $tlh < $proccount; ++
$tlh) {
991 $tmp = $claim->procs
[$tlh][code_text
];
993 if ($claim->procs
[$tlh][code_type
] == 'HCPCS') {
998 $getrevcd = $claim->cptCode($tlh);
999 $sql = "SELECT * FROM codes WHERE code_type = ? and code = ? ORDER BY revenue_code DESC";
1000 $revcode[$tlh] = sqlQuery($sql, array(
1007 for ($prockey = 0; $prockey < $proccount; ++
$prockey) {
1008 $os = 99 +
($loopcount * 8); // Form revenue code offset
1009 $dosos = 102 +
($loopcount * 8); // Procedure date of service form start offset-add 8 for loop
1013 $out .= "LX" . // Loop 2400 LX Service Line. Page 398.
1014 "*" . "$loopcount" . "~\n";
1018 // Revenue code from form
1020 $tmp = $ub04id[$os]; //$revcode[$prockey][revenue_code];
1022 $log .= "*** Error: Missing Revenue Code for " . $claim->cptKey($prockey) . "!\n";
1024 // Institutional Service Line.
1026 $out .= "SV2" . "*" . $tmp . // revenue code
1028 "*" . "HC:" . $claim->cptKey($prockey) . "*" . sprintf('%.2f', $claim->cptCharges($prockey)) . "*UN" . "*" . $claim->cptUnits($prockey) . "*" . "*" . "*";
1032 if (!$claim->cptCharges($prockey)) {
1033 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no charges!\n";
1036 // Segment SV5 (Durable Medical Equipment Service) omitted.
1037 // Segment PWK (Line Supplemental Information) omitted.
1038 // Segment PWK (Durable Medical Equipment Certificate of Medical Necessity Indicator) omitted.
1039 // Segment CR1 (Ambulance Transport Information) omitted.
1040 // Segment CR3 (Durable Medical Equipment Certification) omitted.
1041 // Segment CRC (Ambulance Certification) omitted.
1042 // Segment CRC (Hospice Employee Indicator) omitted.
1043 // Segment CRC (Condition Indicator / Durable Medical Equipment) omitted.
1047 $out .= "DTP" . // Date of Service. Needs to be when service preformed.
1048 "*" . "472" . "*" . "D8" . "*" . $ub04id[$dosos] . "~\n"; //$claim->serviceDate()
1050 $testnote = rtrim($claim->cptNotecodes($prockey));
1051 if (!empty($testnote)) {
1053 $out .= "NTE" . // Explain Unusual Circumstances.
1054 "*ADD" . "*" . $claim->cptNotecodes($prockey) . "~\n";
1057 // Segment DTP*471 (Prescription Date) omitted.
1058 // Segment DTP*607 (Revision/Recertification Date) omitted.
1059 // Segment DTP*463 (Begin Therapy Date) omitted.
1060 // Segment DTP*461 (Last Certification Date) omitted.
1061 // Segment DTP*304 (Last Seen Date) omitted.
1062 // Segment DTP (Test Date) omitted.
1063 // Segment DTP*011 (Shipped Date) omitted.
1064 // Segment DTP*455 (Last X-Ray Date) omitted.
1065 // Segment DTP*454 (Initial Treatment Date) omitted.
1066 // Segment QTY (Ambulance Patient Count) omitted.
1067 // Segment QTY (Obstetric Anesthesia Additional Units) omitted.
1068 // Segment MEA (Test Result) omitted.
1069 // Segment CN1 (Contract Information) omitted.
1070 // Segment REF*9B (Repriced Line Item Reference Number) omitted.
1071 // Segment REF*9D (Adjusted Repriced Line Item Reference Number) omitted.
1072 // Segment REF*G1 (Prior Authorization) omitted.
1073 // Segment REF*6R (Line Item Control Number) omitted.
1074 // (Really oughta have this for robust 835 posting!)
1075 // Segment REF*EW (Mammography Certification Number) omitted.
1076 // Segment REF*X4 (CLIA Number) omitted.
1077 // Segment REF*F4 (Referring CLIA Facility Identification) omitted.
1078 // Segment REF*BT (Immunization Batch Number) omitted.
1079 // Segment REF*9F (Referral Number) omitted.
1080 // Segment AMT*GT (Sales Tax Amount) omitted.
1081 // Segment AMT*F4 (Postage Claimed Amount) omitted.
1082 // Segment K3 (File Information) omitted.
1083 // Segment NTE (Line Note) omitted.
1084 // Segment NTE (Third Party Organization Notes) omitted.
1085 // Segment PS1 (Purchased Service Information) omitted.
1086 // Segment HCP (Line Pricing/Repricing Information) omitted.
1088 // Loop 2410, Drug Information. Medicaid insurers seem to want this
1089 // with HCPCS codes.
1091 $ndc = $claim->cptNDCID($prockey);
1095 $out .= "LIN" . // Drug Identification. Page 500+ (Addendum pg 71).
1096 "*" . // Per addendum, LIN01 is not used.
1101 if (!preg_match('/^\d\d\d\d\d-\d\d\d\d-\d\d$/', $ndc, $tmp) && !preg_match('/^\d{11}$/', $ndc)) {
1102 $log .= "*** NDC code '$ndc' has invalid format!\n";
1106 $out .= "CTP" . // Drug Pricing. Page 500+ (Addendum pg 74).
1110 "*" . $claim->cptNDCQuantity($prockey) .
1111 "*" . $claim->cptNDCUOM($prockey) .
1112 // Note: 5010 documents "ME" (Milligrams) as an additional unit of measure.
1116 // Segment REF (Prescription or Compound Drug Association Number) omitted.
1118 // Loop 2420A, Rendering Provider (service-specific). (Operating Physician Name for 837I)
1119 // Used if the rendering provider for this service line is different
1120 // from that in loop 2310B.
1122 if ($claim->providerNPI() != $claim->providerNPI($prockey)) {
1124 $out .= "NM1" . // Loop 2310B Rendering Provider
1127 "*" . $claim->providerLastName($prockey) .
1128 "*" . $claim->providerFirstName($prockey) .
1129 "*" . $claim->providerMiddleName($prockey) .
1132 if ($claim->providerNPI($prockey)) {
1135 "*" . $claim->providerNPI($prockey);
1137 $log .= "*** Rendering provider has no NPI.\n";
1141 if ($claim->providerTaxonomy($prockey)) {
1144 "*" . "PE" . // PErforming provider
1146 "*" . $claim->providerTaxonomy($prockey) .
1150 // Segment PRV*PE (Rendering Provider Specialty Information) omitted.
1151 // Segment REF (Rendering Provider Secondary Identification) omitted.
1152 // Segment NM1 (Purchased Service Provider Name) omitted.
1153 // Segment REF (Purchased Service Provider Secondary Identification) omitted.
1154 // Segment NM1,N3,N4 (Service Facility Location) omitted.
1155 // Segment REF (Service Facility Location Secondary Identification) omitted.
1156 // Segment NM1 (Supervising Provider Name) omitted.
1157 // Segment REF (Supervising Provider Secondary Identification) omitted.
1158 // Segment NM1,N3,N4 (Ordering Provider) omitted.
1159 // Segment REF (Ordering Provider Secondary Identification) omitted.
1160 // Segment PER (Ordering Provider Contact Information) omitted.
1161 // Segment NM1 (Referring Provider Name) omitted.
1162 // Segment REF (Referring Provider Secondary Identification) omitted.
1163 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
1164 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
1166 // REF*1C is required here for the Medicare provider number if NPI was
1167 // specified in NM109. Not sure if other payers require anything here.
1168 if ($claim->providerNumberType($prockey) == "G2") {
1170 $out .= "REF" . "*" . $claim->providerNumberType($prockey) .
1171 "*" . $claim->providerNumber($prockey) . "~\n";
1173 } // provider exception
1175 // Loop 2430, adjudication by previous payers.
1177 for ($ins = 1; $ins < $claim->payerCount(); ++
$ins) {
1178 if ($claim->payerSequence($ins) > $claim->payerSequence()) {
1179 continue; // payer is future, not previous
1182 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
1183 $aarr = $claim->payerAdjustments($ins, $claim->cptKey($prockey));
1185 if ($payerpaid[1] == 0 && !count($aarr)) {
1186 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no payments or adjustments from previous payer!\n";
1191 $out .= "SVD" . // Service line adjudication. Page 554.
1192 "*" . $claim->payerID($ins) . "*" . $payerpaid[1] . "*HC:" . $claim->cptKey($prockey) . "*" . "*" . $claim->cptUnits($prockey) . "~\n";
1194 $tmpdate = $payerpaid[0];
1195 foreach ($aarr as $a) {
1197 $out .= "CAS" . // Previous payer's line level adjustments. Page 558.
1198 "*" . $a[1] . "*" . $a[2] . "*" . $a[3] . "~\n";
1206 $out .= "DTP" . // Previous payer's line adjustment date. Page 493/566.
1207 "*573" . "*D8" . "*$tmpdate" . "~\n";
1210 // Segment AMT*EAF (Remaining Patient Liability) omitted.
1211 // Segment LQ (Form Identification Code) omitted.
1212 // Segment FRM (Supporting Documentation) omitted.
1214 } // end this procedure
1217 $out .= "SE" . // SE Trailer
1218 "*$edicount" . "*0021" . "~\n";
1220 $out .= "GE" . // GE Trailer
1221 "*1" . "*1" . "~\n";
1223 $out .= "IEA" . // IEA Trailer
1224 "*1" . "*000000001" . "~\n";
1226 // Remove any trailing empty fields (delimiters) from each segment.
1227 $out = preg_replace('/\*+~/', '~', $out);