support for "encounter claims" and x12 partner form expansion
[openemr.git] / library / gen_x12_837.inc.php
blobf0c636c1e38ae6b9f65b8803a8489c1b47be15a6
1 <?php
2 // Copyright (C) 2007-2009 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 $log .= "Generating claim $pid-$encounter for " .
19 $claim->patientFirstName() . ' ' .
20 $claim->patientMiddleName() . ' ' .
21 $claim->patientLastName() . ' on ' .
22 date('Y-m-d H:i', $today) . ".\n";
24 $out .= "ISA" .
25 "*00" .
26 "* " .
27 "*00" .
28 "* " .
29 "*" . $claim->x12gsisa05() .
30 "*" . $claim->x12gssenderid() .
31 "*" . $claim->x12gsisa07() .
32 "*" . $claim->x12gsreceiverid() .
33 "*030911" .
34 "*1630" .
35 "*U" .
36 "*00401" .
37 "*000000001" .
38 "*" . $claim->x12gsisa14() .
39 "*" . $claim->x12gsisa15() .
40 "*:" .
41 "~\n";
43 $out .= "GS" .
44 "*HC" .
45 "*" . $claim->x12gsgs02() .
46 "*" . trim($claim->x12gsreceiverid()) .
47 "*" . date('Ymd', $today) .
48 "*" . date('Hi', $today) .
49 "*1" .
50 "*X" .
51 "*" . $claim->x12gsversionstring() .
52 "~\n";
54 ++$edicount;
55 $out .= "ST" .
56 "*837" .
57 "*0021" .
58 "~\n";
60 ++$edicount;
61 $out .= "BHT" .
62 "*0019" .
63 "*00" .
64 "*0123" .
65 "*" . date('Ymd', $today) .
66 "*1023" .
67 "*CH" .
68 "~\n";
70 ++$edicount;
71 $out .= "REF" .
72 "*87" .
73 "*" . $claim->x12gsversionstring() .
74 "~\n";
76 ++$edicount;
77 $out .= "NM1" . // Loop 1000A Submitter
78 "*41" .
79 "*2" .
80 "*" . $claim->billingFacilityName() .
81 "*" .
82 "*" .
83 "*" .
84 "*" .
85 "*46" .
86 "*" . $claim->billingFacilityETIN() .
87 "~\n";
89 ++$edicount;
90 $out .= "PER" .
91 "*IC" .
92 "*" . $claim->billingContactName() .
93 "*TE" .
94 "*" . $claim->billingContactPhone();
95 if ($claim->x12gsper06()) {
96 $out .= "*ED*" . $claim->x12gsper06();
98 $out .= "~\n";
100 ++$edicount;
101 $out .= "NM1" . // Loop 1000B Receiver
102 "*40" .
103 "*2" .
104 "*" . $claim->clearingHouseName() .
105 "*" .
106 "*" .
107 "*" .
108 "*" .
109 "*46" .
110 "*" . $claim->clearingHouseETIN() .
111 "~\n";
113 $HLcount = 1;
115 ++$edicount;
116 $out .= "HL" . // Loop 2000A Billing/Pay-To Provider HL Loop
117 "*$HLcount" .
118 "*" .
119 "*20" .
120 "*1" .
121 "~\n";
123 $HLBillingPayToProvider = $HLcount++;
125 ++$edicount;
126 $out .= "NM1" . // Loop 2010AA Billing Provider
127 "*85" .
128 "*2" .
129 "*" . $claim->billingFacilityName() .
130 "*" .
131 "*" .
132 "*" .
133 "*";
134 if ($claim->billingFacilityNPI()) {
135 $out .= "*XX*" . $claim->billingFacilityNPI();
136 } else {
137 $log .= "*** Billing facility has no NPI.\n";
138 $out .= "*24*" . $claim->billingFacilityETIN();
140 $out .= "~\n";
142 ++$edicount;
143 $out .= "N3" .
144 "*" . $claim->billingFacilityStreet() .
145 "~\n";
147 ++$edicount;
148 $out .= "N4" .
149 "*" . $claim->billingFacilityCity() .
150 "*" . $claim->billingFacilityState() .
151 "*" . $claim->billingFacilityZip() .
152 "~\n";
154 // Add a REF*EI*<ein> segment if NPI was specified in the NM1 above.
155 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
156 ++$edicount;
157 $out .= "REF" .
158 "*EI" .
159 "*" . $claim->billingFacilityETIN() .
160 "~\n";
163 if ($claim->providerNumberType() && $claim->providerNumber()) {
164 ++$edicount;
165 $out .= "REF" .
166 "*" . $claim->providerNumberType() .
167 "*" . $claim->providerNumber() .
168 "~\n";
170 else if ($claim->providerNumber()) {
171 $log .= "*** Payer-specific provider insurance number is present but has no type assigned.\n";
174 ++$edicount;
175 $out .= "NM1" . // Loop 2010AB Pay-To Provider
176 "*87" .
177 "*2" .
178 "*" . $claim->billingFacilityName() .
179 "*" .
180 "*" .
181 "*" .
182 "*";
183 if ($claim->billingFacilityNPI())
184 $out .= "*XX*" . $claim->billingFacilityNPI();
185 else
186 $out .= "*24*" . $claim->billingFacilityETIN();
187 $out .= "~\n";
189 ++$edicount;
190 $out .= "N3" .
191 "*" . $claim->billingFacilityStreet() .
192 "~\n";
194 ++$edicount;
195 $out .= "N4" .
196 "*" . $claim->billingFacilityCity() .
197 "*" . $claim->billingFacilityState() .
198 "*" . $claim->billingFacilityZip() .
199 "~\n";
201 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
202 ++$edicount;
203 $out .= "REF" .
204 "*EI" .
205 "*" . $claim->billingFacilityETIN() .
206 "~\n";
209 $PatientHL = 0;
211 ++$edicount;
212 $out .= "HL" . // Loop 2000B Subscriber HL Loop
213 "*$HLcount" .
214 "*$HLBillingPayToProvider" .
215 "*22" .
216 "*$PatientHL" .
217 "~\n";
219 $HLSubscriber = $HLcount++;
221 if (!$claim->payerSequence()) {
222 $log .= "*** Error: Insurance information is missing!\n";
224 ++$edicount;
225 $out .= "SBR" . // Subscriber Information
226 "*" . $claim->payerSequence() .
227 "*" . $claim->insuredRelationship() .
228 "*" . $claim->groupNumber() .
229 "*" . $claim->groupName() .
230 "*" . $claim->insuredTypeCode() . // applies for secondary medicare
231 "*" .
232 "*" .
233 "*" .
234 "*" . $claim->claimType() . // Zirmed replaces this
235 "~\n";
237 ++$edicount;
238 $out .= "NM1" . // Loop 2010BA Subscriber
239 "*IL" .
240 "*1" .
241 "*" . $claim->insuredLastName() .
242 "*" . $claim->insuredFirstName() .
243 "*" . $claim->insuredMiddleName() .
244 "*" .
245 "*" .
246 "*MI" .
247 "*" . $claim->policyNumber() .
248 "~\n";
250 ++$edicount;
251 $out .= "N3" .
252 "*" . $claim->insuredStreet() .
253 "~\n";
255 ++$edicount;
256 $out .= "N4" .
257 "*" . $claim->insuredCity() .
258 "*" . $claim->insuredState() .
259 "*" . $claim->insuredZip() .
260 "~\n";
262 ++$edicount;
263 $out .= "DMG" .
264 "*D8" .
265 "*" . $claim->insuredDOB() .
266 "*" . $claim->insuredSex() .
267 "~\n";
269 ++$edicount;
270 $out .= "NM1" . // Loop 2010BB Payer
271 "*PR" .
272 "*2" .
273 "*" . $claim->payerName() .
274 "*" .
275 "*" .
276 "*" .
277 "*" .
278 "*PI" .
279 // Zirmed ignores this if using payer name matching:
280 "*" . ($encounter_claim ? $claim->payerAltID() : $claim->payerID()) .
281 "~\n";
283 // if (!$claim->payerID()) {
284 // $log .= "*** CMS ID is missing for payer '" . $claim->payerName() . "'.\n";
285 // }
287 ++$edicount;
288 $out .= "N3" .
289 "*" . $claim->payerStreet() .
290 "~\n";
292 ++$edicount;
293 $out .= "N4" .
294 "*" . $claim->payerCity() .
295 "*" . $claim->payerState() .
296 "*" . $claim->payerZip() .
297 "~\n";
299 if (! $claim->isSelfOfInsured()) {
300 ++$edicount;
301 $out .= "HL" . // Loop 2000C Patient Information
302 "*$HLcount" .
303 "*$HLSubscriber" .
304 "*23" .
305 "*0" .
306 "~\n";
308 $HLcount++;
310 ++$edicount;
311 $out .= "PAT" .
312 "*" . $claim->insuredRelationship() .
313 "~\n";
315 ++$edicount;
316 $out .= "NM1" . // Loop 2010CA Patient
317 "*QC" .
318 "*1" .
319 "*" . $claim->patientLastName() .
320 "*" . $claim->patientFirstName() .
321 "*" . $claim->patientMiddleName() .
322 "~\n";
324 ++$edicount;
325 $out .= "N3" .
326 "*" . $claim->patientStreet() .
327 "~\n";
329 ++$edicount;
330 $out .= "N4" .
331 "*" . $claim->patientCity() .
332 "*" . $claim->patientState() .
333 "*" . $claim->patientZip() .
334 "~\n";
336 ++$edicount;
337 $out .= "DMG" .
338 "*D8" .
339 "*" . $claim->patientDOB() .
340 "*" . $claim->patientSex() .
341 "~\n";
342 } // end of patient different from insured
344 $proccount = $claim->procCount();
346 $clm_total_charges = 0;
347 for ($prockey = 0; $prockey < $proccount; ++$prockey) {
348 $clm_total_charges += $claim->cptCharges($prockey);
351 if (!$clm_total_charges) {
352 $log .= "*** This claim has no charges!\n";
355 ++$edicount;
356 $out .= "CLM" . // Loop 2300 Claim
357 "*$pid-$encounter" .
358 "*" . sprintf("%.2f",$clm_total_charges) . // Zirmed computes and replaces this
359 "*" .
360 "*" .
361 "*" . $claim->facilityPOS() . "::" . $claim->frequencyTypeCode() .
362 "*Y" .
363 "*A" .
364 "*" . ($claim->billingFacilityAssignment() ? 'Y' : 'N') .
365 "*Y" .
366 "*C" .
367 "~\n";
369 ++$edicount;
370 $out .= "DTP" . // Date of Onset
371 "*431" .
372 "*D8" .
373 "*" . $claim->onsetDate() .
374 "~\n";
376 if (strcmp($claim->facilityPOS(),'21') == 0) {
377 ++$edicount;
378 $out .= "DTP" . // Date of Hospitalization
379 "*435" .
380 "*D8" .
381 "*" . $claim->onsetDate() .
382 "~\n";
385 $patientpaid = $claim->patientPaidAmount();
386 if ($patientpaid != 0) {
387 ++$edicount;
388 $out .= "AMT" . // Patient paid amount. Page 220.
389 "*F5" .
390 "*" . $patientpaid .
391 "~\n";
394 if ($claim->priorAuth()) {
395 ++$edicount;
396 $out .= "REF" . // Prior Authorization Number
397 "*G1" .
398 "*" . $claim->priorAuth() .
399 "~\n";
402 if ($claim->cliaCode()) {
403 // Required by Medicare when in-house labs are done.
404 ++$edicount;
405 $out .= "REF" . // Clinical Laboratory Improvement Amendment Number
406 "*X4" .
407 "*" . $claim->cliaCode() .
408 "~\n";
411 // Note: This would be the place to implement the NTE segment for loop 2300.
413 // Diagnoses, up to 8 per HI segment.
414 $da = $claim->diagArray();
415 $diag_type_code = 'BK';
416 $tmp = 0;
417 foreach ($da as $diag) {
418 if ($tmp % 8 == 0) {
419 if ($tmp) $out .= "~\n";
420 ++$edicount;
421 $out .= "HI"; // Health Diagnosis Codes
423 $out .= "*$diag_type_code:" . $diag;
424 $diag_type_code = 'BF';
425 ++$tmp;
427 if ($tmp) $out .= "~\n";
429 if ($claim->referrerLastName()) {
430 // Medicare requires referring provider's name and UPIN.
431 ++$edicount;
432 $out .= "NM1" . // Loop 2310A Referring Provider
433 "*DN" .
434 "*1" .
435 "*" . $claim->referrerLastName() .
436 "*" . $claim->referrerFirstName() .
437 "*" . $claim->referrerMiddleName() .
438 "*" .
439 "*";
440 if ($claim->referrerNPI()) { $out .=
441 "*XX" .
442 "*" . $claim->referrerNPI();
443 } else { $out .=
444 "*34" .
445 "*" . $claim->referrerSSN();
447 $out .= "~\n";
449 if ($claim->referrerTaxonomy()) {
450 ++$edicount;
451 $out .= "PRV" .
452 "*RF" . // ReFerring provider
453 "*ZZ" .
454 "*" . $claim->referrerTaxonomy() .
455 "~\n";
458 if ($claim->referrerUPIN()) {
459 ++$edicount;
460 $out .= "REF" . // Referring Provider Secondary Identification
461 "*1G" .
462 "*" . $claim->referrerUPIN() .
463 "~\n";
467 ++$edicount;
468 $out .= "NM1" . // Loop 2310B Rendering Provider
469 "*82" .
470 "*1" .
471 "*" . $claim->providerLastName() .
472 "*" . $claim->providerFirstName() .
473 "*" . $claim->providerMiddleName() .
474 "*" .
475 "*";
476 if ($claim->providerNPI()) { $out .=
477 "*XX" .
478 "*" . $claim->providerNPI();
479 } else { $out .=
480 "*34" .
481 "*" . $claim->providerSSN();
482 $log .= "*** Rendering provider has no NPI.\n";
484 $out .= "~\n";
486 if ($claim->providerTaxonomy()) {
487 ++$edicount;
488 $out .= "PRV" .
489 "*PE" . // PErforming provider
490 "*ZZ" .
491 "*" . $claim->providerTaxonomy() .
492 "~\n";
495 // REF*1C is required here for the Medicare provider number if NPI was
496 // specified in NM109. Not sure if other payers require anything here.
497 if ($claim->providerNumber()) {
498 ++$edicount;
499 $out .= "REF" .
500 "*" . $claim->providerNumberType() .
501 "*" . $claim->providerNumber() .
502 "~\n";
505 // Loop 2310D is omitted in the case of home visits (POS=12).
506 if ($claim->facilityPOS() != 12) {
507 ++$edicount;
508 $out .= "NM1" . // Loop 2310D Service Location
509 "*77" .
510 "*2";
511 if ($claim->facilityName() || $claim->facilityNPI() || $claim->facilityETIN()) { $out .=
512 "*" . $claim->facilityName();
514 if ($claim->facilityNPI() || $claim->facilityETIN()) { $out .=
515 "*" .
516 "*" .
517 "*" .
518 "*";
519 if ($claim->facilityNPI()) { $out .=
520 "*XX*" . $claim->facilityNPI();
521 } else { $out .=
522 "*24*" . $claim->facilityETIN();
523 $log .= "*** Service location has no NPI.\n";
526 $out .= "~\n";
527 if ($claim->facilityStreet()) {
528 ++$edicount;
529 $out .= "N3" .
530 "*" . $claim->facilityStreet() .
531 "~\n";
533 if ($claim->facilityState()) {
534 ++$edicount;
535 $out .= "N4" .
536 "*" . $claim->facilityCity() .
537 "*" . $claim->facilityState() .
538 "*" . $claim->facilityZip() .
539 "~\n";
543 // Loop 2310E, Supervising Provider
545 if ($claim->supervisorLastName()) {
546 ++$edicount;
547 $out .= "NM1" .
548 "*DQ" . // Supervising Physician
549 "*1" . // Person
550 "*" . $claim->supervisorLastName() .
551 "*" . $claim->supervisorFirstName() .
552 "*" . $claim->supervisorMiddleName() .
553 "*" . // NM106 not used
554 "*"; // Name Suffix
555 if ($claim->supervisorNPI()) { $out .=
556 "*XX" .
557 "*" . $claim->supervisorNPI();
558 } else { $out .=
559 "*34" .
560 "*" . $claim->supervisorSSN();
562 $out .= "~\n";
564 if ($claim->supervisorNumber()) {
565 ++$edicount;
566 $out .= "REF" .
567 "*" . $claim->supervisorNumberType() .
568 "*" . $claim->supervisorNumber() .
569 "~\n";
573 $prev_pt_resp = $clm_total_charges; // for computation below
575 // Loops 2320 and 2330*, other subscriber/payer information.
577 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
579 $tmp1 = $claim->claimType($ins);
580 $tmp2 = 'C1'; // Here a kludge. See page 321.
581 if ($tmp1 === 'CI') $tmp2 = 'C1';
582 if ($tmp1 === 'AM') $tmp2 = 'AP';
583 if ($tmp1 === 'HM') $tmp2 = 'HM';
584 if ($tmp1 === 'MB') $tmp2 = 'MB';
585 if ($tmp1 === 'MC') $tmp2 = 'MC';
586 if ($tmp1 === '09') $tmp2 = 'PP';
587 ++$edicount;
588 $out .= "SBR" . // Loop 2320, Subscriber Information - page 318
589 "*" . $claim->payerSequence($ins) .
590 "*" . $claim->insuredRelationship($ins) .
591 "*" . $claim->groupNumber($ins) .
592 "*" . $claim->groupName($ins) .
593 "*" . $tmp2 .
594 "*" .
595 "*" .
596 "*" .
597 "*" . $claim->claimType($ins) .
598 "~\n";
600 // Things that apply only to previous payers, not future payers.
602 if ($claim->payerSequence($ins) < $claim->payerSequence()) {
604 // Generate claim-level adjustments.
605 $aarr = $claim->payerAdjustments($ins);
606 foreach ($aarr as $a) {
607 ++$edicount;
608 $out .= "CAS" . // Previous payer's claim-level adjustments. Page 323.
609 "*" . $a[1] .
610 "*" . $a[2] .
611 "*" . $a[3] .
612 "~\n";
615 $payerpaid = $claim->payerTotals($ins);
616 ++$edicount;
617 $out .= "AMT" . // Previous payer's paid amount. Page 332.
618 "*D" .
619 "*" . $payerpaid[1] .
620 "~\n";
622 // Patient responsibility amount as of this previous payer.
623 $prev_pt_resp -= $payerpaid[1]; // reduce by payments
624 $prev_pt_resp -= $payerpaid[2]; // reduce by adjustments
626 ++$edicount;
627 $out .= "AMT" . // Allowed amount per previous payer. Page 334.
628 "*B6" .
629 "*" . sprintf('%.2f', $payerpaid[1] + $prev_pt_resp) .
630 "~\n";
632 ++$edicount;
633 $out .= "AMT" . // Patient responsibility amount per previous payer. Page 335.
634 "*F2" .
635 "*" . sprintf('%.2f', $prev_pt_resp) .
636 "~\n";
638 } // End of things that apply only to previous payers.
640 ++$edicount;
641 $out .= "DMG" . // Other subscriber demographic information. Page 342.
642 "*D8" .
643 "*" . $claim->insuredDOB($ins) .
644 "*" . $claim->insuredSex($ins) .
645 "~\n";
647 ++$edicount;
648 $out .= "OI" . // Other Insurance Coverage Information. Page 344.
649 "*" .
650 "*" .
651 "*Y" .
652 "*B" .
653 "*" .
654 "*Y" .
655 "~\n";
657 ++$edicount;
658 $out .= "NM1" . // Loop 2330A Subscriber info for other insco. Page 350.
659 "*IL" .
660 "*1" .
661 "*" . $claim->insuredLastName($ins) .
662 "*" . $claim->insuredFirstName($ins) .
663 "*" . $claim->insuredMiddleName($ins) .
664 "*" .
665 "*" .
666 "*MI" .
667 "*" . $claim->policyNumber($ins) .
668 "~\n";
670 ++$edicount;
671 $out .= "N3" .
672 "*" . $claim->insuredStreet($ins) .
673 "~\n";
675 ++$edicount;
676 $out .= "N4" .
677 "*" . $claim->insuredCity($ins) .
678 "*" . $claim->insuredState($ins) .
679 "*" . $claim->insuredZip($ins) .
680 "~\n";
682 ++$edicount;
683 $out .= "NM1" . // Loop 2330B Payer info for other insco. Page 359.
684 "*PR" .
685 "*2" .
686 "*" . $claim->payerName($ins) .
687 "*" .
688 "*" .
689 "*" .
690 "*" .
691 "*PI" .
692 "*" . $claim->payerID($ins) .
693 "~\n";
695 // if (!$claim->payerID($ins)) {
696 // $log .= "*** CMS ID is missing for payer '" . $claim->payerName($ins) . "'.\n";
697 // }
699 // Payer address (N3 and N4) are added below so that Gateway EDI can
700 // auto-generate secondary claims. These do NOT appear in my copy of
701 // the spec! -- Rod 2008-06-12
703 if (trim($claim->x12gsreceiverid()) == '431420764') { // if Gateway EDI
704 ++$edicount;
705 $out .= "N3" .
706 "*" . $claim->payerStreet($ins) .
707 "~\n";
709 ++$edicount;
710 $out .= "N4" .
711 "*" . $claim->payerCity($ins) .
712 "*" . $claim->payerState($ins) .
713 "*" . $claim->payerZip($ins) .
714 "~\n";
715 } // end Gateway EDI
717 } // End loops 2320/2330*.
719 $loopcount = 0;
721 // Procedure loop starts here.
723 for ($prockey = 0; $prockey < $proccount; ++$prockey) {
724 ++$loopcount;
726 ++$edicount;
727 $out .= "LX" . // Loop 2400 LX Service Line. Page 398.
728 "*$loopcount" .
729 "~\n";
731 ++$edicount;
732 $out .= "SV1" . // Professional Service. Page 400.
733 "*HC:" . $claim->cptKey($prockey) .
734 "*" . sprintf('%.2f', $claim->cptCharges($prockey)) .
735 "*UN" .
736 "*" . $claim->cptUnits($prockey) .
737 "*" .
738 "*" .
739 "*";
740 $dia = $claim->diagIndexArray($prockey);
741 $i = 0;
742 foreach ($dia as $dindex) {
743 if ($i) $out .= ':';
744 $out .= $dindex;
745 if (++$i >= 4) break;
747 $out .= "~\n";
749 if (!$claim->cptCharges($prockey)) {
750 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no charges!\n";
753 if (empty($dia)) {
754 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' is not justified!\n";
757 ++$edicount;
758 $out .= "DTP" . // Date of Service. Page 435.
759 "*472" .
760 "*D8" .
761 "*" . $claim->serviceDate() .
762 "~\n";
764 // Loop 2410, Drug Information. Medicaid insurers seem to want this
765 // with HCPCS codes.
767 $ndc = $claim->cptNDCID($prockey);
768 if ($ndc) {
769 ++$edicount;
770 $out .= "LIN" . // Drug Identification. Page 500+ (Addendum pg 71).
771 "*" . // Per addendum, LIN01 is not used.
772 "*N4" .
773 "*" . $ndc .
774 "~\n";
776 if (!preg_match('/^\d\d\d\d\d-\d\d\d\d-\d\d$/', $ndc, $tmp)) {
777 $log .= "*** NDC code '$ndc' has invalid format!\n";
780 ++$edicount;
781 $tmpunits = $claim->cptNDCQuantity($prockey) * $claim->cptUnits($prockey);
782 if (!$tmpunits) $tmpunits = 1;
783 $out .= "CTP" . // Drug Pricing. Page 500+ (Addendum pg 74).
784 "*" .
785 "*" .
786 "*" . sprintf('%.2f', $claim->cptCharges($prockey) / $tmpunits) .
787 "*" . $claim->cptNDCQuantity($prockey) .
788 "*" . $claim->cptNDCUOM($prockey) .
789 "~\n";
792 // Loop 2420A, Rendering Provider (service-specific).
793 // Used if the rendering provider for this service line is different
794 // from that in loop 2310B.
796 if ($claim->providerNPI() != $claim->providerNPI($prockey)) {
797 ++$edicount;
798 $out .= "NM1" . // Loop 2310B Rendering Provider
799 "*82" .
800 "*1" .
801 "*" . $claim->providerLastName($prockey) .
802 "*" . $claim->providerFirstName($prockey) .
803 "*" . $claim->providerMiddleName($prockey) .
804 "*" .
805 "*";
806 if ($claim->providerNPI($prockey)) { $out .=
807 "*XX" .
808 "*" . $claim->providerNPI($prockey);
809 } else { $out .=
810 "*34" .
811 "*" . $claim->providerSSN($prockey);
812 $log .= "*** Rendering provider has no NPI.\n";
814 $out .= "~\n";
816 if ($claim->providerTaxonomy($prockey)) {
817 ++$edicount;
818 $out .= "PRV" .
819 "*PE" . // PErforming provider
820 "*ZZ" .
821 "*" . $claim->providerTaxonomy($prockey) .
822 "~\n";
825 // REF*1C is required here for the Medicare provider number if NPI was
826 // specified in NM109. Not sure if other payers require anything here.
827 if ($claim->providerNumber($prockey)) {
828 ++$edicount;
829 $out .= "REF" .
830 "*" . $claim->providerNumberType($prockey) .
831 "*" . $claim->providerNumber($prockey) .
832 "~\n";
836 // Loop 2430, adjudication by previous payers.
838 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
839 if ($claim->payerSequence($ins) > $claim->payerSequence())
840 continue; // payer is future, not previous
842 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
843 $aarr = $claim->payerAdjustments($ins, $claim->cptKey($prockey));
845 if ($payerpaid[1] == 0 && !count($aarr)) {
846 $log .= "*** Procedure '" . $claim->cptKey($prockey) .
847 "' has no payments or adjustments from previous payer!\n";
848 continue;
851 ++$edicount;
852 $out .= "SVD" . // Service line adjudication. Page 554.
853 "*" . $claim->payerID($ins) .
854 "*" . $payerpaid[1] .
855 "*HC:" . $claim->cptKey($prockey) .
856 "*" .
857 "*" . $claim->cptUnits($prockey) .
858 "~\n";
860 $tmpdate = $payerpaid[0];
861 foreach ($aarr as $a) {
862 ++$edicount;
863 $out .= "CAS" . // Previous payer's line level adjustments. Page 558.
864 "*" . $a[1] .
865 "*" . $a[2] .
866 "*" . $a[3] .
867 "~\n";
868 if (!$tmpdate) $tmpdate = $a[0];
871 if ($tmpdate) {
872 ++$edicount;
873 $out .= "DTP" . // Previous payer's line adjustment date. Page 566.
874 "*573" .
875 "*D8" .
876 "*$tmpdate" .
877 "~\n";
879 } // end loop 2430
880 } // end this procedure
882 ++$edicount;
883 $out .= "SE" . // SE Trailer
884 "*$edicount" .
885 "*0021" .
886 "~\n";
888 $out .= "GE" . // GE Trailer
889 "*1" .
890 "*1" .
891 "~\n";
893 $out .= "IEA" . // IEA Trailer
894 "*1" .
895 "*000000001" .
896 "~\n";
898 $log .= "\n";
899 return $out;