EOL standardization fixes
[openemr.git] / library / gen_x12_837.inc.php
blobf83a98a56d865d92d15352767b42492a6b88d914
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 ($encounter_claim ? "*RP" : "*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 if($claim->federalIdType()){
159 $out .= "*" . $claim->federalIdType();
161 else{
162 $out .= "*EI";//For dealing with the situation before adding selection for TaxId type In facility ie default to EIN.
164 $out .= "*" . $claim->billingFacilityETIN() .
165 "~\n";
168 if ($claim->providerNumberType() && $claim->providerNumber()) {
169 ++$edicount;
170 $out .= "REF" .
171 "*" . $claim->providerNumberType() .
172 "*" . $claim->providerNumber() .
173 "~\n";
175 else if ($claim->providerNumber()) {
176 $log .= "*** Payer-specific provider insurance number is present but has no type assigned.\n";
179 ++$edicount;
180 $out .= "NM1" . // Loop 2010AB Pay-To Provider
181 "*87" .
182 "*2" .
183 "*" . $claim->billingFacilityName() .
184 "*" .
185 "*" .
186 "*" .
187 "*";
188 if ($claim->billingFacilityNPI())
189 $out .= "*XX*" . $claim->billingFacilityNPI();
190 else
191 $out .= "*24*" . $claim->billingFacilityETIN();
192 $out .= "~\n";
194 ++$edicount;
195 $out .= "N3" .
196 "*" . $claim->billingFacilityStreet() .
197 "~\n";
199 ++$edicount;
200 $out .= "N4" .
201 "*" . $claim->billingFacilityCity() .
202 "*" . $claim->billingFacilityState() .
203 "*" . $claim->billingFacilityZip() .
204 "~\n";
206 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
207 ++$edicount;
208 $out .= "REF" .
209 "*EI" .
210 "*" . $claim->billingFacilityETIN() .
211 "~\n";
214 $PatientHL = 0;
216 ++$edicount;
217 $out .= "HL" . // Loop 2000B Subscriber HL Loop
218 "*$HLcount" .
219 "*$HLBillingPayToProvider" .
220 "*22" .
221 "*$PatientHL" .
222 "~\n";
224 $HLSubscriber = $HLcount++;
226 if (!$claim->payerSequence()) {
227 $log .= "*** Error: Insurance information is missing!\n";
229 ++$edicount;
230 $out .= "SBR" . // Subscriber Information
231 "*" . $claim->payerSequence() .
232 "*" . $claim->insuredRelationship() .
233 "*" . $claim->groupNumber() .
234 "*" . $claim->groupName() .
235 "*" . $claim->insuredTypeCode() . // applies for secondary medicare
236 "*" .
237 "*" .
238 "*" .
239 "*" . $claim->claimType() . // Zirmed replaces this
240 "~\n";
242 ++$edicount;
243 $out .= "NM1" . // Loop 2010BA Subscriber
244 "*IL" .
245 "*1" .
246 "*" . $claim->insuredLastName() .
247 "*" . $claim->insuredFirstName() .
248 "*" . $claim->insuredMiddleName() .
249 "*" .
250 "*" .
251 "*MI" .
252 "*" . $claim->policyNumber() .
253 "~\n";
255 ++$edicount;
256 $out .= "N3" .
257 "*" . $claim->insuredStreet() .
258 "~\n";
260 ++$edicount;
261 $out .= "N4" .
262 "*" . $claim->insuredCity() .
263 "*" . $claim->insuredState() .
264 "*" . $claim->insuredZip() .
265 "~\n";
267 ++$edicount;
268 $out .= "DMG" .
269 "*D8" .
270 "*" . $claim->insuredDOB() .
271 "*" . $claim->insuredSex() .
272 "~\n";
274 ++$edicount;
275 $out .= "NM1" . // Loop 2010BB Payer
276 "*PR" .
277 "*2" .
278 "*" . $claim->payerName() .
279 "*" .
280 "*" .
281 "*" .
282 "*" .
283 "*PI" .
284 // Zirmed ignores this if using payer name matching:
285 "*" . ($encounter_claim ? $claim->payerAltID() : $claim->payerID()) .
286 "~\n";
288 // if (!$claim->payerID()) {
289 // $log .= "*** CMS ID is missing for payer '" . $claim->payerName() . "'.\n";
290 // }
292 ++$edicount;
293 $out .= "N3" .
294 "*" . $claim->payerStreet() .
295 "~\n";
297 ++$edicount;
298 $out .= "N4" .
299 "*" . $claim->payerCity() .
300 "*" . $claim->payerState() .
301 "*" . $claim->payerZip() .
302 "~\n";
304 if (! $claim->isSelfOfInsured()) {
305 ++$edicount;
306 $out .= "HL" . // Loop 2000C Patient Information
307 "*$HLcount" .
308 "*$HLSubscriber" .
309 "*23" .
310 "*0" .
311 "~\n";
313 $HLcount++;
315 ++$edicount;
316 $out .= "PAT" .
317 "*" . $claim->insuredRelationship() .
318 "~\n";
320 ++$edicount;
321 $out .= "NM1" . // Loop 2010CA Patient
322 "*QC" .
323 "*1" .
324 "*" . $claim->patientLastName() .
325 "*" . $claim->patientFirstName() .
326 "*" . $claim->patientMiddleName() .
327 "~\n";
329 ++$edicount;
330 $out .= "N3" .
331 "*" . $claim->patientStreet() .
332 "~\n";
334 ++$edicount;
335 $out .= "N4" .
336 "*" . $claim->patientCity() .
337 "*" . $claim->patientState() .
338 "*" . $claim->patientZip() .
339 "~\n";
341 ++$edicount;
342 $out .= "DMG" .
343 "*D8" .
344 "*" . $claim->patientDOB() .
345 "*" . $claim->patientSex() .
346 "~\n";
347 } // end of patient different from insured
349 $proccount = $claim->procCount();
351 $clm_total_charges = 0;
352 for ($prockey = 0; $prockey < $proccount; ++$prockey) {
353 $clm_total_charges += $claim->cptCharges($prockey);
356 if (!$clm_total_charges) {
357 $log .= "*** This claim has no charges!\n";
360 ++$edicount;
361 $out .= "CLM" . // Loop 2300 Claim
362 "*$pid-$encounter" .
363 "*" . sprintf("%.2f",$clm_total_charges) . // Zirmed computes and replaces this
364 "*" .
365 "*" .
366 "*" . $claim->facilityPOS() . "::" . $claim->frequencyTypeCode() .
367 "*Y" .
368 "*A" .
369 "*" . ($claim->billingFacilityAssignment() ? 'Y' : 'N') .
370 "*Y" .
371 "*C" .
372 "~\n";
374 ++$edicount;
375 $out .= "DTP" . // Date of Onset
376 "*431" .
377 "*D8" .
378 "*" . $claim->onsetDate() .
379 "~\n";
381 if (strcmp($claim->facilityPOS(),'21') == 0) {
382 ++$edicount;
383 $out .= "DTP" . // Date of Hospitalization
384 "*435" .
385 "*D8" .
386 "*" . $claim->onsetDate() .
387 "~\n";
390 $patientpaid = $claim->patientPaidAmount();
391 if ($patientpaid != 0) {
392 ++$edicount;
393 $out .= "AMT" . // Patient paid amount. Page 220.
394 "*F5" .
395 "*" . $patientpaid .
396 "~\n";
399 if ($claim->priorAuth()) {
400 ++$edicount;
401 $out .= "REF" . // Prior Authorization Number
402 "*G1" .
403 "*" . $claim->priorAuth() .
404 "~\n";
407 if ($claim->cliaCode()) {
408 // Required by Medicare when in-house labs are done.
409 ++$edicount;
410 $out .= "REF" . // Clinical Laboratory Improvement Amendment Number
411 "*X4" .
412 "*" . $claim->cliaCode() .
413 "~\n";
416 // Note: This would be the place to implement the NTE segment for loop 2300.
418 // Diagnoses, up to 8 per HI segment.
419 $da = $claim->diagArray();
420 $diag_type_code = 'BK';
421 $tmp = 0;
422 foreach ($da as $diag) {
423 if ($tmp % 8 == 0) {
424 if ($tmp) $out .= "~\n";
425 ++$edicount;
426 $out .= "HI"; // Health Diagnosis Codes
428 $out .= "*$diag_type_code:" . $diag;
429 $diag_type_code = 'BF';
430 ++$tmp;
432 if ($tmp) $out .= "~\n";
434 if ($claim->referrerLastName()) {
435 // Medicare requires referring provider's name and UPIN.
436 ++$edicount;
437 $out .= "NM1" . // Loop 2310A Referring Provider
438 "*DN" .
439 "*1" .
440 "*" . $claim->referrerLastName() .
441 "*" . $claim->referrerFirstName() .
442 "*" . $claim->referrerMiddleName() .
443 "*" .
444 "*";
445 if ($claim->referrerNPI()) { $out .=
446 "*XX" .
447 "*" . $claim->referrerNPI();
448 } else { $out .=
449 "*34" .
450 "*" . $claim->referrerSSN();
452 $out .= "~\n";
454 if ($claim->referrerTaxonomy()) {
455 ++$edicount;
456 $out .= "PRV" .
457 "*RF" . // ReFerring provider
458 "*ZZ" .
459 "*" . $claim->referrerTaxonomy() .
460 "~\n";
463 if ($claim->referrerUPIN()) {
464 ++$edicount;
465 $out .= "REF" . // Referring Provider Secondary Identification
466 "*1G" .
467 "*" . $claim->referrerUPIN() .
468 "~\n";
472 ++$edicount;
473 $out .= "NM1" . // Loop 2310B Rendering Provider
474 "*82" .
475 "*1" .
476 "*" . $claim->providerLastName() .
477 "*" . $claim->providerFirstName() .
478 "*" . $claim->providerMiddleName() .
479 "*" .
480 "*";
481 if ($claim->providerNPI()) { $out .=
482 "*XX" .
483 "*" . $claim->providerNPI();
484 } else { $out .=
485 "*34" .
486 "*" . $claim->providerSSN();
487 $log .= "*** Rendering provider has no NPI.\n";
489 $out .= "~\n";
491 if ($claim->providerTaxonomy()) {
492 ++$edicount;
493 $out .= "PRV" .
494 "*PE" . // PErforming provider
495 "*ZZ" .
496 "*" . $claim->providerTaxonomy() .
497 "~\n";
500 // REF*1C is required here for the Medicare provider number if NPI was
501 // specified in NM109. Not sure if other payers require anything here.
502 if ($claim->providerNumber()) {
503 ++$edicount;
504 $out .= "REF" .
505 "*" . $claim->providerNumberType() .
506 "*" . $claim->providerNumber() .
507 "~\n";
510 // Loop 2310D is omitted in the case of home visits (POS=12).
511 if ($claim->facilityPOS() != 12) {
512 ++$edicount;
513 $out .= "NM1" . // Loop 2310D Service Location
514 "*77" .
515 "*2";
516 if ($claim->facilityName() || $claim->facilityNPI() || $claim->facilityETIN()) { $out .=
517 "*" . $claim->facilityName();
519 if ($claim->facilityNPI() || $claim->facilityETIN()) { $out .=
520 "*" .
521 "*" .
522 "*" .
523 "*";
524 if ($claim->facilityNPI()) { $out .=
525 "*XX*" . $claim->facilityNPI();
526 } else { $out .=
527 "*24*" . $claim->facilityETIN();
528 $log .= "*** Service location has no NPI.\n";
531 $out .= "~\n";
532 if ($claim->facilityStreet()) {
533 ++$edicount;
534 $out .= "N3" .
535 "*" . $claim->facilityStreet() .
536 "~\n";
538 if ($claim->facilityState()) {
539 ++$edicount;
540 $out .= "N4" .
541 "*" . $claim->facilityCity() .
542 "*" . $claim->facilityState() .
543 "*" . $claim->facilityZip() .
544 "~\n";
548 // Loop 2310E, Supervising Provider
550 if ($claim->supervisorLastName()) {
551 ++$edicount;
552 $out .= "NM1" .
553 "*DQ" . // Supervising Physician
554 "*1" . // Person
555 "*" . $claim->supervisorLastName() .
556 "*" . $claim->supervisorFirstName() .
557 "*" . $claim->supervisorMiddleName() .
558 "*" . // NM106 not used
559 "*"; // Name Suffix
560 if ($claim->supervisorNPI()) { $out .=
561 "*XX" .
562 "*" . $claim->supervisorNPI();
563 } else { $out .=
564 "*34" .
565 "*" . $claim->supervisorSSN();
567 $out .= "~\n";
569 if ($claim->supervisorNumber()) {
570 ++$edicount;
571 $out .= "REF" .
572 "*" . $claim->supervisorNumberType() .
573 "*" . $claim->supervisorNumber() .
574 "~\n";
578 $prev_pt_resp = $clm_total_charges; // for computation below
580 // Loops 2320 and 2330*, other subscriber/payer information.
582 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
584 $tmp1 = $claim->claimType($ins);
585 $tmp2 = 'C1'; // Here a kludge. See page 321.
586 if ($tmp1 === 'CI') $tmp2 = 'C1';
587 if ($tmp1 === 'AM') $tmp2 = 'AP';
588 if ($tmp1 === 'HM') $tmp2 = 'HM';
589 if ($tmp1 === 'MB') $tmp2 = 'MB';
590 if ($tmp1 === 'MC') $tmp2 = 'MC';
591 if ($tmp1 === '09') $tmp2 = 'PP';
592 ++$edicount;
593 $out .= "SBR" . // Loop 2320, Subscriber Information - page 318
594 "*" . $claim->payerSequence($ins) .
595 "*" . $claim->insuredRelationship($ins) .
596 "*" . $claim->groupNumber($ins) .
597 "*" . $claim->groupName($ins) .
598 "*" . $tmp2 .
599 "*" .
600 "*" .
601 "*" .
602 "*" . $claim->claimType($ins) .
603 "~\n";
605 // Things that apply only to previous payers, not future payers.
607 if ($claim->payerSequence($ins) < $claim->payerSequence()) {
609 // Generate claim-level adjustments.
610 $aarr = $claim->payerAdjustments($ins);
611 foreach ($aarr as $a) {
612 ++$edicount;
613 $out .= "CAS" . // Previous payer's claim-level adjustments. Page 323.
614 "*" . $a[1] .
615 "*" . $a[2] .
616 "*" . $a[3] .
617 "~\n";
620 $payerpaid = $claim->payerTotals($ins);
621 ++$edicount;
622 $out .= "AMT" . // Previous payer's paid amount. Page 332.
623 "*D" .
624 "*" . $payerpaid[1] .
625 "~\n";
627 // Patient responsibility amount as of this previous payer.
628 $prev_pt_resp -= $payerpaid[1]; // reduce by payments
629 $prev_pt_resp -= $payerpaid[2]; // reduce by adjustments
631 ++$edicount;
632 $out .= "AMT" . // Allowed amount per previous payer. Page 334.
633 "*B6" .
634 "*" . sprintf('%.2f', $payerpaid[1] + $prev_pt_resp) .
635 "~\n";
637 ++$edicount;
638 $out .= "AMT" . // Patient responsibility amount per previous payer. Page 335.
639 "*F2" .
640 "*" . sprintf('%.2f', $prev_pt_resp) .
641 "~\n";
643 } // End of things that apply only to previous payers.
645 ++$edicount;
646 $out .= "DMG" . // Other subscriber demographic information. Page 342.
647 "*D8" .
648 "*" . $claim->insuredDOB($ins) .
649 "*" . $claim->insuredSex($ins) .
650 "~\n";
652 ++$edicount;
653 $out .= "OI" . // Other Insurance Coverage Information. Page 344.
654 "*" .
655 "*" .
656 "*Y" .
657 "*B" .
658 "*" .
659 "*Y" .
660 "~\n";
662 ++$edicount;
663 $out .= "NM1" . // Loop 2330A Subscriber info for other insco. Page 350.
664 "*IL" .
665 "*1" .
666 "*" . $claim->insuredLastName($ins) .
667 "*" . $claim->insuredFirstName($ins) .
668 "*" . $claim->insuredMiddleName($ins) .
669 "*" .
670 "*" .
671 "*MI" .
672 "*" . $claim->policyNumber($ins) .
673 "~\n";
675 ++$edicount;
676 $out .= "N3" .
677 "*" . $claim->insuredStreet($ins) .
678 "~\n";
680 ++$edicount;
681 $out .= "N4" .
682 "*" . $claim->insuredCity($ins) .
683 "*" . $claim->insuredState($ins) .
684 "*" . $claim->insuredZip($ins) .
685 "~\n";
687 ++$edicount;
688 $out .= "NM1" . // Loop 2330B Payer info for other insco. Page 359.
689 "*PR" .
690 "*2" .
691 "*" . $claim->payerName($ins) .
692 "*" .
693 "*" .
694 "*" .
695 "*" .
696 "*PI" .
697 "*" . $claim->payerID($ins) .
698 "~\n";
700 // if (!$claim->payerID($ins)) {
701 // $log .= "*** CMS ID is missing for payer '" . $claim->payerName($ins) . "'.\n";
702 // }
704 // Payer address (N3 and N4) are added below so that Gateway EDI can
705 // auto-generate secondary claims. These do NOT appear in my copy of
706 // the spec! -- Rod 2008-06-12
708 if (trim($claim->x12gsreceiverid()) == '431420764') { // if Gateway EDI
709 ++$edicount;
710 $out .= "N3" .
711 "*" . $claim->payerStreet($ins) .
712 "~\n";
714 ++$edicount;
715 $out .= "N4" .
716 "*" . $claim->payerCity($ins) .
717 "*" . $claim->payerState($ins) .
718 "*" . $claim->payerZip($ins) .
719 "~\n";
720 } // end Gateway EDI
722 } // End loops 2320/2330*.
724 $loopcount = 0;
726 // Procedure loop starts here.
728 for ($prockey = 0; $prockey < $proccount; ++$prockey) {
729 ++$loopcount;
731 ++$edicount;
732 $out .= "LX" . // Loop 2400 LX Service Line. Page 398.
733 "*$loopcount" .
734 "~\n";
736 ++$edicount;
737 $out .= "SV1" . // Professional Service. Page 400.
738 "*HC:" . $claim->cptKey($prockey) .
739 "*" . sprintf('%.2f', $claim->cptCharges($prockey)) .
740 "*UN" .
741 "*" . $claim->cptUnits($prockey) .
742 "*" .
743 "*" .
744 "*";
745 $dia = $claim->diagIndexArray($prockey);
746 $i = 0;
747 foreach ($dia as $dindex) {
748 if ($i) $out .= ':';
749 $out .= $dindex;
750 if (++$i >= 4) break;
752 $out .= "~\n";
754 if (!$claim->cptCharges($prockey)) {
755 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no charges!\n";
758 if (empty($dia)) {
759 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' is not justified!\n";
762 ++$edicount;
763 $out .= "DTP" . // Date of Service. Page 435.
764 "*472" .
765 "*D8" .
766 "*" . $claim->serviceDate() .
767 "~\n";
769 // AMT*AAE segment for Approved Amount from previous payer.
770 // Medicare secondaries seem to require this.
772 for ($ins = $claim->payerCount() - 1; $ins > 0; --$ins) {
773 if ($claim->payerSequence($ins) > $claim->payerSequence())
774 continue; // payer is future, not previous
775 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
776 ++$edicount;
777 $out .= "AMT" . // Approved amount per previous payer. Page 485.
778 "*AAE" .
779 "*" . sprintf('%.2f', $claim->cptCharges($prockey) - $payerpaid[2]) .
780 "~\n";
781 break;
784 // Loop 2410, Drug Information. Medicaid insurers seem to want this
785 // with HCPCS codes.
787 $ndc = $claim->cptNDCID($prockey);
788 if ($ndc) {
789 ++$edicount;
790 $out .= "LIN" . // Drug Identification. Page 500+ (Addendum pg 71).
791 "*" . // Per addendum, LIN01 is not used.
792 "*N4" .
793 "*" . $ndc .
794 "~\n";
796 if (!preg_match('/^\d\d\d\d\d-\d\d\d\d-\d\d$/', $ndc, $tmp)) {
797 $log .= "*** NDC code '$ndc' has invalid format!\n";
800 ++$edicount;
801 $tmpunits = $claim->cptNDCQuantity($prockey) * $claim->cptUnits($prockey);
802 if (!$tmpunits) $tmpunits = 1;
803 $out .= "CTP" . // Drug Pricing. Page 500+ (Addendum pg 74).
804 "*" .
805 "*" .
806 "*" . sprintf('%.2f', $claim->cptCharges($prockey) / $tmpunits) .
807 "*" . $claim->cptNDCQuantity($prockey) .
808 "*" . $claim->cptNDCUOM($prockey) .
809 "~\n";
812 // Loop 2420A, Rendering Provider (service-specific).
813 // Used if the rendering provider for this service line is different
814 // from that in loop 2310B.
816 if ($claim->providerNPI() != $claim->providerNPI($prockey)) {
817 ++$edicount;
818 $out .= "NM1" . // Loop 2310B Rendering Provider
819 "*82" .
820 "*1" .
821 "*" . $claim->providerLastName($prockey) .
822 "*" . $claim->providerFirstName($prockey) .
823 "*" . $claim->providerMiddleName($prockey) .
824 "*" .
825 "*";
826 if ($claim->providerNPI($prockey)) { $out .=
827 "*XX" .
828 "*" . $claim->providerNPI($prockey);
829 } else { $out .=
830 "*34" .
831 "*" . $claim->providerSSN($prockey);
832 $log .= "*** Rendering provider has no NPI.\n";
834 $out .= "~\n";
836 if ($claim->providerTaxonomy($prockey)) {
837 ++$edicount;
838 $out .= "PRV" .
839 "*PE" . // PErforming provider
840 "*ZZ" .
841 "*" . $claim->providerTaxonomy($prockey) .
842 "~\n";
845 // REF*1C is required here for the Medicare provider number if NPI was
846 // specified in NM109. Not sure if other payers require anything here.
847 if ($claim->providerNumber($prockey)) {
848 ++$edicount;
849 $out .= "REF" .
850 "*" . $claim->providerNumberType($prockey) .
851 "*" . $claim->providerNumber($prockey) .
852 "~\n";
856 // Loop 2430, adjudication by previous payers.
858 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
859 if ($claim->payerSequence($ins) > $claim->payerSequence())
860 continue; // payer is future, not previous
862 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
863 $aarr = $claim->payerAdjustments($ins, $claim->cptKey($prockey));
865 if ($payerpaid[1] == 0 && !count($aarr)) {
866 $log .= "*** Procedure '" . $claim->cptKey($prockey) .
867 "' has no payments or adjustments from previous payer!\n";
868 continue;
871 ++$edicount;
872 $out .= "SVD" . // Service line adjudication. Page 554.
873 "*" . $claim->payerID($ins) .
874 "*" . $payerpaid[1] .
875 "*HC:" . $claim->cptKey($prockey) .
876 "*" .
877 "*" . $claim->cptUnits($prockey) .
878 "~\n";
880 $tmpdate = $payerpaid[0];
881 foreach ($aarr as $a) {
882 ++$edicount;
883 $out .= "CAS" . // Previous payer's line level adjustments. Page 558.
884 "*" . $a[1] .
885 "*" . $a[2] .
886 "*" . $a[3] .
887 "~\n";
888 if (!$tmpdate) $tmpdate = $a[0];
891 if ($tmpdate) {
892 ++$edicount;
893 $out .= "DTP" . // Previous payer's line adjustment date. Page 566.
894 "*573" .
895 "*D8" .
896 "*$tmpdate" .
897 "~\n";
899 } // end loop 2430
900 } // end this procedure
902 ++$edicount;
903 $out .= "SE" . // SE Trailer
904 "*$edicount" .
905 "*0021" .
906 "~\n";
908 $out .= "GE" . // GE Trailer
909 "*1" .
910 "*1" .
911 "~\n";
913 $out .= "IEA" . // IEA Trailer
914 "*1" .
915 "*000000001" .
916 "~\n";
918 $log .= "\n";
919 return $out;