Display fix: width in manila for demographics (#1909)
[openemr.git] / library / gen_x12_837.inc.php
blob1578fe9bec3592fc0f381d8a375478b6f5399724
1 <?php
2 /*
3 * This program creates a 5010 837P file
5 * @package OpenEMR
6 * @author Rod Roark <rod@sunsetsystems.com>
7 * @author Stephen Waite <stephen.waite@cmsvt.com>
8 * @copyright Copyright (c) 2009 Rod Roark <rod@sunsetsystems.com>
9 * @copyright Copyright (c) 2018 Stephen Waite <stephen.waite@cmsvt.com>
10 * @link https://github.com/openemr/openemr/tree/master
11 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
14 require_once(dirname(__FILE__) . "/invoice_summary.inc.php");
16 use OpenEMR\Billing\Claim;
18 function stripZipCode($zip)
20 $temp = preg_replace('/[-\s]*/', '', $zip);
21 if (strlen($temp) == 5) {
22 return $temp . "9999";
23 } else {
24 return $temp;
28 function gen_x12_837($pid, $encounter, &$log, $encounter_claim = false)
30 $today = time();
31 $out = '';
32 $claim = new Claim($pid, $encounter);
33 $edicount = 0;
34 $HLcount = 0;
36 $log .= "Generating claim $pid" . "-" . $encounter . " for " .
37 $claim->patientFirstName() . ' ' .
38 $claim->patientMiddleName() . ' ' .
39 $claim->patientLastName() . ' on ' .
40 date('Y-m-d H:i', $today) . ".\n";
42 $out .= "ISA" .
43 "*" . $claim->x12gsisa01() .
44 "*" . $claim->x12gsisa02() .
45 "*" . $claim->x12gsisa03() .
46 "*" . $claim->x12gsisa04() .
47 "*" . $claim->x12gsisa05() .
48 "*" . $claim->x12gssenderid() .
49 "*" . $claim->x12gsisa07() .
50 "*" . $claim->x12gsreceiverid() .
51 "*" . "030911" . // dummy data replace by billing_process.php
52 "*" . "1630" . // ditto
53 "*" . "^" .
54 "*" . "00501" .
55 "*" . "000000001" .
56 "*" . $claim->x12gsisa14() .
57 "*" . $claim->x12gsisa15() .
58 "*:" .
59 "~\n";
61 $out .= "GS" .
62 "*" . "HC" .
63 "*" . $claim->x12gsgs02() .
64 "*" . trim($claim->x12gs03()) .
65 "*" . date('Ymd', $today) .
66 "*" . date('Hi', $today) .
67 "*" . "1" .
68 "*" . "X" .
69 "*" . $claim->x12gsversionstring() .
70 "~\n";
72 ++$edicount;
73 $out .= "ST" .
74 "*" . "837" .
75 "*" . "0021" .
76 "*" . $claim->x12gsversionstring() .
77 "~\n";
79 ++$edicount;
80 $out .= "BHT" .
81 "*" . "0019" . // 0019 is required here
82 "*" . "00" . // 00 = original transmission
83 "*" . "0123" . // reference identification
84 "*" . date('Ymd', $today) . // transaction creation date
85 "*" . date('Hi', $today) . // transaction creation time
86 "*" . ($encounter_claim ? "RP" : "CH") . // RP = reporting, CH = chargeable
87 "~\n";
89 ++$edicount;
90 if ($claim->federalIdType() == "SY") { // check entity type for NM*102 1 == person, 2 == non-person entity
91 $firstName = $claim->providerFirstName();
92 $lastName = $claim->providerLastName();
93 $middleName = $claim->providerMiddleName();
94 $suffixName = $claim->providerSuffixName();
95 $out .= "NM1" . // Loop 1000A Submitter
96 "*" . "41" .
97 "*" . "1" .
98 "*" . $lastName .
99 "*" . $firstName .
100 "*" . $middleName .
101 "*" . // Name Prefix not used
102 "*" . $suffixName .
103 "*" . "46";
104 } else {
105 $billingFacilityName = substr($claim->billingFacilityName(), 0, 60);
106 if ($billingFacilityName == '') {
107 $log .= "*** billing facility name in 1000A loop is empty\n";
109 $out .= "NM1" .
110 "*" . "41" .
111 "*" . "2" .
112 "*" . $billingFacilityName .
113 "*" .
114 "*" .
115 "*" .
116 "*" .
117 "*" . "46";
119 $out .= "*" . $claim->billingFacilityETIN();
120 $out .= "~\n";
122 ++$edicount;
123 $out .= "PER" . // Loop 1000A, Submitter EDI contact information
124 "*" . "IC" .
125 "*" . $claim->billingContactName() .
126 "*" . "TE" .
127 "*" . $claim->billingContactPhone() .
128 "*" . "EM" .
129 "*" . $claim->billingContactEmail();
130 $out .= "~\n";
132 ++$edicount;
133 $out .= "NM1" . // Loop 1000B Receiver
134 "*" . "40" .
135 "*" . "2" .
136 "*" . $claim->clearingHouseName() .
137 "*" .
138 "*" .
139 "*" .
140 "*" .
141 "*" . "46" .
142 "*" . $claim->clearingHouseETIN() .
143 "~\n";
145 ++$HLcount;
146 ++$edicount;
147 $out .= "HL" . // Loop 2000A Billing/Pay-To Provider HL Loop
148 "*" . $HLcount .
149 "*" .
150 "*" . "20" .
151 "*" . "1" . // 1 indicates there are child segments
152 "~\n";
154 $HLBillingPayToProvider = $HLcount++;
156 // Situational PRV segment for provider taxonomy.
157 if ($claim->facilityTaxonomy()) {
158 ++$edicount;
159 $out .= "PRV" .
160 "*" . "BI" .
161 "*" . "PXC" .
162 "*" . $claim->facilityTaxonomy() .
163 "~\n";
166 // Situational CUR segment (foreign currency information) omitted here.
167 ++$edicount;
168 if ($claim->federalIdType() == "SY") { // check for entity type like in 1000A
169 $firstName = $claim->providerFirstName();
170 $lastName = $claim->providerLastName();
171 $middleName = $claim->providerMiddleName();
172 $out .= "NM1" .
173 "*" . "85" .
174 "*" . "1" .
175 "*" . $lastName .
176 "*" . $firstName .
177 "*" . $middleName .
178 "*" . // Name Prefix not used
179 "*";
180 } else {
181 $billingFacilityName = substr($claim->billingFacilityName(), 0, 60);
182 if ($billingFacilityName == '') {
183 $log .= "*** billing facility name in 2010A loop is empty\n";
185 $out .= "NM1" . // Loop 2010AA Billing Provider
186 "*" . "85" .
187 "*" . "2" .
188 "*" . $billingFacilityName .
189 "*" .
190 "*" .
191 "*" .
192 "*";
194 if ($claim->billingFacilityNPI()) {
195 $out .= "*XX*" . $claim->billingFacilityNPI();
196 } else {
197 $log .= "*** Billing facility has no NPI.\n";
199 $out .= "~\n";
201 ++$edicount;
202 $out .= "N3" .
203 "*" . $claim->billingFacilityStreet() .
204 "~\n";
206 ++$edicount;
207 $out .= "N4" .
208 "*" . $claim->billingFacilityCity() .
209 "*" . $claim->billingFacilityState() .
210 "*" . stripZipCode($claim->billingFacilityZip()) .
211 "~\n";
213 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
214 ++$edicount;
215 $out .= "REF";
216 if ($claim->federalIdType()) {
217 $out .= "*" . $claim->federalIdType();
218 } else {
219 $out .= "*EI"; // For dealing with the situation before adding TaxId type In facility.
221 $out .= "*" . $claim->billingFacilityETIN() . "~\n";
222 } else {
223 $log .= "*** No billing facility NPI and/or ETIN.\n";
225 if ($claim->providerNumberType() && $claim->providerNumber() && !$claim->billingFacilityNPI()) {
226 ++$edicount;
227 $out .= "REF" .
228 "*" . $claim->providerNumberType() .
229 "*" . $claim->providerNumber() .
230 "~\n";
231 } else if ($claim->providerNumber() && !$claim->providerNumberType()) {
232 $log .= "*** Payer-specific provider insurance number is present but has no type assigned.\n";
235 // Situational PER*1C segment omitted.
237 // Pay-To Address defaults to billing provider and is no longer required in 5010 but may be useful
238 if ($claim->facilityStreet() != $claim->billingFacilityStreet()) {
239 ++$edicount;
240 $billingFacilityName = substr($claim->billingFacilityName(), 0, 60);
241 $out .= "NM1" . // Loop 2010AB Pay-To Provider
242 "*" . "87" .
243 "*" . "2" .
244 "*" . $billingFacilityName .
245 "*" .
246 "*" .
247 "*" .
248 "*";
249 if ($claim->billingFacilityNPI()) {
250 $out .= "*XX*" . $claim->billingFacilityNPI();
252 $out .= "~\n";
254 ++$edicount;
255 $out .= "N3" .
256 "*" . $claim->billingFacilityStreet() .
257 "~\n";
259 ++$edicount;
260 $out .= "N4" .
261 "*" . $claim->billingFacilityCity() .
262 "*" . $claim->billingFacilityState() .
263 "*" . stripZipCode($claim->billingFacilityZip()) .
264 "~\n";
267 // Loop 2010AC Pay-To Plan Name omitted. Includes:
268 // NM1*PE, N3, N4, REF*2U, REF*EI
270 $PatientHL = $claim->isSelfOfInsured() ? 0 : 1;
271 $HLSubscriber = $HLcount++;
273 ++$edicount;
274 $out .= "HL" . // Loop 2000B Subscriber HL Loop
275 "*" . $HLSubscriber .
276 "*" . $HLBillingPayToProvider .
277 "*" . "22" .
278 "*" . $PatientHL .
279 "~\n";
281 if (!$claim->payerSequence()) {
282 $log .= "*** Error: Insurance information is missing!\n";
285 ++$edicount;
286 $out .= "SBR" . // Subscriber Information
287 "*" . $claim->payerSequence() .
288 "*" . ($claim->isSelfOfInsured() ? '18' : '') .
289 "*" . $claim->groupNumber() .
290 "*" . ($claim->groupNumber() ? '' : $claim->groupName()) . // if groupNumber no groupName
291 "*" . $claim->insuredTypeCode() . // applies for secondary medicare
292 "*" .
293 "*" .
294 "*" .
295 "*" . $claim->claimType() .
296 "~\n";
298 // Segment PAT omitted.
300 ++$edicount;
301 $out .= "NM1" . // Loop 2010BA Subscriber
302 "*" . "IL" .
303 "*" . "1" . // 1 = person, 2 = non-person
304 "*" . $claim->insuredLastName() .
305 "*" . $claim->insuredFirstName() .
306 "*" . $claim->insuredMiddleName() .
307 "*" .
308 "*" . // Name Suffix not used
309 "*" . "MI" .
310 // "MI" = Member Identification Number
311 // "II" = Standard Unique Health Identifier, "Required if the
312 // HIPAA Individual Patient Identifier is mandated use."
313 // Here we presume that is not true yet.
314 "*" . $claim->policyNumber() .
315 "~\n";
317 // For 5010, further subscriber info is sent only if they are the patient.
318 if ($claim->isSelfOfInsured()) {
319 ++$edicount;
320 $out .= "N3" .
321 "*" . $claim->insuredStreet() .
322 "~\n";
324 ++$edicount;
325 $out .= "N4" .
326 "*" . $claim->insuredCity() .
327 "*" . $claim->insuredState() .
328 "*" . stripZipCode($claim->insuredZip()) .
329 "~\n";
331 ++$edicount;
332 $out .= "DMG" .
333 "*" . "D8" .
334 "*" . $claim->insuredDOB() .
335 "*" . $claim->insuredSex() .
336 "~\n";
339 // Segment REF*SY (Subscriber Secondary Identification) omitted.
340 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
341 // Segment PER*IC (Property and Casualty Subscriber Contact Information) omitted.
343 ++$edicount;
344 $payerName = substr($claim->payerName(), 0, 60);
345 $out .= "NM1" . // Loop 2010BB Payer
346 "*" . "PR" .
347 "*" . "2" .
348 "*" . $payerName .
349 "*" .
350 "*" .
351 "*" .
352 "*" .
353 "*" . "PI" .
354 "*" . ($encounter_claim ? $claim->payerAltID() : $claim->payerID()) .
355 "~\n";
356 if (!$claim->payerID()) {
357 $log .= "*** CMS ID is missing for payer '" . $claim->payerName() . "'.\n";
360 ++$edicount;
361 $out .= "N3" .
362 "*" . $claim->payerStreet() .
363 "~\n";
365 ++$edicount;
366 $out .= "N4" .
367 "*" . $claim->payerCity() .
368 "*" . $claim->payerState() .
369 "*" . stripZipCode($claim->payerZip()) .
370 "~\n";
372 // Segment REF (Payer Secondary Identification) omitted.
373 // Segment REF (Billing Provider Secondary Identification) omitted.
375 if (!$claim->isSelfOfInsured()) {
376 ++$edicount;
377 $out .= "HL" . // Loop 2000C Patient Information
378 "*" . $HLcount .
379 "*" . $HLSubscriber .
380 "*" . "23" .
381 "*" . "0" .
382 "~\n";
384 $HLcount++;
385 ++$edicount;
386 $out .= "PAT" .
387 "*" . $claim->insuredRelationship() .
388 "~\n";
390 ++$edicount;
391 $out .= "NM1" . // Loop 2010CA Patient
392 "*" . "QC" .
393 "*" . "1" .
394 "*" . $claim->patientLastName() .
395 "*" . $claim->patientFirstName();
397 if ($claim->patientMiddleName() !== '') {
398 $out .= "*" . $claim->patientMiddleName();
401 $out .= "~\n";
403 ++$edicount;
404 $out .= "N3" .
405 "*" . $claim->patientStreet() .
406 "~\n";
408 ++$edicount;
409 $out .= "N4" .
410 "*" . $claim->patientCity() .
411 "*" . $claim->patientState() .
412 "*" . stripZipCode($claim->patientZip()) .
413 "~\n";
415 ++$edicount;
416 $out .= "DMG" .
417 "*" . "D8" .
418 "*" . $claim->patientDOB() .
419 "*" . $claim->patientSex() .
420 "~\n";
422 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
423 // Segment REF (Property and Casualty Patient Identifier) omitted.
424 // Segment PER (Property and Casualty Patient Contact Information) omitted.
425 } // end of patient different from insured
427 $proccount = $claim->procCount();
428 $clm_total_charges = 0;
429 for ($prockey = 0; $prockey < $proccount; ++$prockey) {
430 $clm_total_charges += $claim->cptCharges($prockey);
432 if (!$clm_total_charges) {
433 $log .= "*** This claim has no charges!\n";
436 ++$edicount;
437 $out .= "CLM" . // Loop 2300 Claim
438 "*" . $pid . "-" . $encounter .
439 "*" . sprintf("%.2f", $clm_total_charges) .
440 "*" .
441 "*" .
442 "*" . sprintf('%02d', $claim->facilityPOS()) . ":" . "B" . ":" . $claim->frequencyTypeCode() .
443 "*" . "Y" .
444 "*" . "A" .
445 "*" . ($claim->billingFacilityAssignment() ? 'Y' : 'N') .
446 "*" . "Y" .
447 "~\n";
449 // above is for historical use of encounter onset date, now in misc_billing_options
450 // Segment DTP*431 (Onset of Current Symptoms or Illness)
451 // Segment DTP*484 (Last Menstrual Period Date)
453 if ($claim->onsetDate() && ($claim->onsetDate() !== $claim->serviceDate()) && ($claim->onsetDateValid())) {
454 ++$edicount;
455 $out .= "DTP" . // Date of Onset
456 "*" . "431" .
457 "*" . "D8" .
458 "*" . $claim->onsetDate() .
459 "~\n";
460 } else if ($claim->miscOnsetDate() && ($claim->miscOnsetDate() !== $claim->serviceDate())
461 && ($claim->box14Qualifier()) && ($claim->miscOnsetDateValid())) {
462 ++$edicount;
463 $out .= "DTP" .
464 "*" . $claim->box14Qualifier() .
465 "*" . "D8" .
466 "*" . $claim->miscOnsetDate() .
467 "~\n";
470 // Segment DTP*304 (Last Seen Date)
471 // Segment DTP*453 (Acute Manifestation Date)
472 // Segment DTP*439 (Accident Date)
473 // Segment DTP*455 (Last X-Ray Date)
474 // Segment DTP*471 (Hearing and Vision Prescription Date)
475 // Segment DTP*314 (Disability) omitted.
476 // Segment DTP*360 (Initial Disability Period Start) omitted.
477 // Segment DTP*361 (Initial Disability Period End) omitted.
478 // Segment DTP*297 (Last Worked Date)
479 // Segment DTP*296 (Authorized Return to Work Date)
481 // Segment DTP*454 (Initial Treatment Date)
483 if ($claim->dateInitialTreatment() && ($claim->box15Qualifier()) && ($claim->dateInitialTreatmentValid())) {
484 ++$edicount;
485 $out .= "DTP" . // Date Last Seen
486 "*" . $claim->box15Qualifier() .
487 "*" . "D8" .
488 "*" . $claim->dateInitialTreatment() .
489 "~\n";
492 if (strcmp($claim->facilityPOS(), '21') == 0 && $claim->onsetDateValid()) {
493 ++$edicount;
494 $out .= "DTP" . // Date of Hospitalization
495 "*" . "435" .
496 "*" . "D8" .
497 "*" . $claim->onsetDate() .
498 "~\n";
501 // above is for historical use of encounter onset date, now in misc_billing_options
502 if (strcmp($claim->facilityPOS(), '21') == 0 && $claim->hospitalizedFromDateValid()) {
503 ++$edicount;
504 $out .= "DTP" . // Date of Admission
505 "*" . "435" .
506 "*" . "D8" .
507 "*" . $claim->hospitalizedFrom() .
508 "~\n";
511 // Segment DTP*096 (Discharge Date)
512 if (strcmp($claim->facilityPOS(), '21') == 0 && $claim->hospitalizedToDateValid()) {
513 ++$edicount;
514 $out .= "DTP" . // Date of Discharge
515 "*" . "96" .
516 "*" . "D8" .
517 "*" . $claim->hospitalizedTo() .
518 "~\n";
521 // Segments DTP (Assumed and Relinquished Care Dates) omitted.
522 // Segment DTP*444 (Property and Casualty Date of First Contact) omitted.
523 // Segment DTP*050 (Repricer Received Date) omitted.
524 // Segment PWK (Claim Supplemental Information) omitted.
525 // Segment CN1 (Contract Information) omitted.
527 $patientpaid = $claim->patientPaidAmount();
528 if ($patientpaid != 0) {
529 ++$edicount;
530 $out .= "AMT" . // Patient paid amount. Page 190/220.
531 "*" . "F5" .
532 "*" . $patientpaid .
533 "~\n";
536 // Segment REF*4N (Service Authorization Exception Code) omitted.
537 // Segment REF*F5 (Mandatory Medicare Crossover Indicator) omitted.
538 // Segment REF*EW (Mammography Certification Number) omitted.
539 // Segment REF*9F (Referral Number) omitted.
541 if ($claim->priorAuth()) {
542 ++$edicount;
543 $out .= "REF" . // Prior Authorization Number
544 "*" . "G1" .
545 "*" . $claim->priorAuth() .
546 "~\n";
549 // Segment REF*F8 Payer Claim Control Number for claim re-submission.icn_resubmission_number
550 if (trim($claim->billing_options['icn_resubmission_number']) > 3) {
551 ++$edicount;
552 error_log("Method 1: " . $claim->billing_options['icn_resubmission_number'], 0);
553 $out .= "REF" .
554 "*" . "F8" .
555 "*" . $claim->icnResubmissionNumber() .
556 "~\n";
559 if ($claim->cliaCode() && ($claim->claimType() === 'MB')) {
560 // Required by Medicare when in-house labs are done.
561 ++$edicount;
562 $out .= "REF" . // Clinical Laboratory Improvement Amendment Number
563 "*" . "X4" .
564 "*" . $claim->cliaCode() .
565 "~\n";
568 // Segment REF*9A (Repriced Claim Number) omitted.
569 // Segment REF*9C (Adjusted Repriced Claim Number) omitted.
570 // Segment REF*LX (Investigational Device Exemption Number) omitted.
571 // Segment REF*D9 (Claim Identifier for Transmission Intermediaries) omitted.
572 // Segment REF*EA (Medical Record Number) omitted.
573 // Segment REF*P4 (Demonstration Project Identifier) omitted.
574 // Segment REF*1J (Care Plan Oversight) omitted.
575 // Segment K3 (File Information) omitted.
576 if ($claim->additionalNotes()) {
577 // Claim note.
578 ++$edicount;
579 $out .= "NTE" . // comments box 19
580 "*" . "ADD" .
581 "*" . $claim->additionalNotes() .
582 "~\n";
585 // Segment CR1 (Ambulance Transport Information) omitted.
586 // Segment CR2 (Spinal Manipulation Service Information) omitted.
587 // Segment CRC (Ambulance Certification) omitted.
588 // Segment CRC (Patient Condition Information: Vision) omitted.
589 // Segment CRC (Homebound Indicator) omitted.
590 // Segment CRC (EPSDT Referral).
591 if ($claim->epsdtFlag()) {
592 ++$edicount;
593 $out .= "CRC" .
594 "*" . "ZZ" .
595 "*" . "Y" .
596 "*" . $claim->medicaidReferralCode() .
597 "~\n";
600 // Diagnoses, up to $max_per_seg per HI segment.
601 $max_per_seg = 12;
602 $da = $claim->diagArray();
603 if ($claim->diagtype == "ICD9") {
604 $diag_type_code = 'BK';
605 } else {
606 $diag_type_code = 'ABK';
608 $tmp = 0;
609 foreach ($da as $diag) {
610 if ($tmp % $max_per_seg == 0) {
611 if ($tmp) {
612 $out .= "~\n";
614 ++$edicount;
615 $out .= "HI"; // Health Diagnosis Codes
617 $out .= "*" . $diag_type_code . ":" . $diag;
618 if ($claim->diagtype == "ICD9") {
619 $diag_type_code = 'BF';
620 } else {
621 $diag_type_code = 'ABF';
623 ++$tmp;
626 if ($tmp) {
627 $out .= "~\n";
630 // Segment HI*BP (Anesthesia Related Procedure) omitted.
631 // Segment HI*BG (Condition Information) omitted.
632 // Segment HCP (Claim Pricing/Repricing Information) omitted.
633 if ($claim->referrerLastName()) {
634 // Medicare requires referring provider's name and UPIN.
635 ++$edicount;
636 $out .= "NM1" . // Loop 2310A Referring Provider
637 "*" . "DN" .
638 "*" . "1" .
639 "*" . $claim->referrerLastName() .
640 "*" . $claim->referrerFirstName() .
641 "*" . $claim->referrerMiddleName() .
642 "*" .
643 "*";
644 if ($claim->referrerNPI()) {
645 $out .=
646 "*" . "XX" .
647 "*" . $claim->referrerNPI();
648 } else {
649 $log .= "*** Referring provider has no NPI.\n";
651 $out .= "~\n";
654 // Per the implementation guide lines, only include this information if it is different
655 // than the Loop 2010AA information
656 if ($claim->providerNPIValid() && ($claim->billingFacilityNPI() !== $claim->providerNPI())) {
657 ++$edicount;
658 $out .= "NM1" . // Loop 2310B Rendering Provider
659 "*" . "82" .
660 "*" . "1" .
661 "*" . $claim->providerLastName() .
662 "*" . $claim->providerFirstName() .
663 "*" . $claim->providerMiddleName() .
664 "*" .
665 "*";
666 if ($claim->providerNPI()) {
667 $out .=
668 "*" . "XX" .
669 "*" . $claim->providerNPI();
670 } else {
671 $log .= "*** Rendering provider has no NPI.\n";
673 $out .= "~\n";
675 if ($claim->providerTaxonomy()) {
676 ++$edicount;
677 $out .= "PRV" .
678 "*" . "PE" . // Performing provider
679 "*" . "PXC" .
680 "*" . $claim->providerTaxonomy() .
681 "~\n";
682 } else {
683 $log .= "*** Performing provider has no taxonomy code.\n";
685 } else {
686 $log .= "*** Rendering provider is billing under a group.\n";
688 if (!$claim->providerNPIValid()) {
689 // If the loop was skipped because the provider NPI was invalid, generate a warning for the log.
690 $log .= "*** Skipping 2310B because " . $claim->providerLastName() . "," . $claim->providerFirstName() . " has invalid NPI.\n";
693 if (!$claim->providerNPI() && in_array($claim->providerNumberType(), array('0B', '1G', 'G2', 'LU'))) {
694 if ($claim->providerNumber()) {
695 ++$edicount;
696 $out .= "REF" .
697 "*" . $claim->providerNumberType() .
698 "*" . $claim->providerNumber() .
699 "~\n";
702 // End of Loop 2310B
704 // Loop 2310C is omitted in the case of home visits (POS=12).
705 if ($claim->facilityPOS() != 12 && ($claim->facilityNPI() != $claim->billingFacilityNPI())) {
706 ++$edicount;
707 $out .= "NM1" . // Loop 2310C Service Location
708 "*" . "77" .
709 "*" . "2";
710 $facilityName = substr($claim->facilityName(), 0, 60);
711 if ($claim->facilityName() || $claim->facilityNPI() || $claim->facilityETIN()) {
712 $out .=
713 "*" . $facilityName;
714 } else {
715 $log .= "*** Check for invalid facility name, NPI, and/or tax id.\n";
717 if ($claim->facilityNPI() || $claim->facilityETIN()) {
718 $out .=
719 "*" .
720 "*" .
721 "*" .
722 "*";
723 if ($claim->facilityNPI()) {
724 $out .=
725 "*" . "XX" . "*" . $claim->facilityNPI();
726 } else {
727 $out .=
728 "*" . "24" . "*" . $claim->facilityETIN();
730 if (!$claim->facilityNPI()) {
731 $log .= "*** Service location has no NPI.\n";
735 $out .= "~\n";
736 if ($claim->facilityStreet()) {
737 ++$edicount;
738 $out .= "N3" .
739 "*" . $claim->facilityStreet() .
740 "~\n";
743 if ($claim->facilityState()) {
744 ++$edicount;
745 $out .= "N4" .
746 "*" . $claim->facilityCity() .
747 "*" . $claim->facilityState() .
748 "*" . stripZipCode($claim->facilityZip()) .
749 "~\n";
752 // Segment REF (Service Facility Location Secondary Identification) omitted.
753 // Segment PER (Service Facility Contact Information) omitted.
755 // Loop 2310D, Supervising Provider
756 if (! empty($claim->supervisorLastName())) {
757 ++$edicount;
758 $out .= "NM1" .
759 "*" . "DQ" . // Supervising Physician
760 "*" . "1" . // Person
761 "*" . $claim->supervisorLastName() .
762 "*" . $claim->supervisorFirstName() .
763 "*" . $claim->supervisorMiddleName() .
764 "*" . // NM106 not used
765 "*"; // Name Suffix not used
766 if ($claim->supervisorNPI()) {
767 $out .=
768 "*" . "XX" .
769 "*" . $claim->supervisorNPI();
770 } else {
771 $log .= "*** Supervising Provider has no NPI.\n";
773 $out .= "~\n";
775 if ($claim->supervisorNumber()) {
776 ++$edicount;
777 $out .= "REF" .
778 "*" . $claim->supervisorNumberType() .
779 "*" . $claim->supervisorNumber() .
780 "~\n";
784 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
785 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
787 // Loops 2320 and 2330, other subscriber/payer information.
788 // Remember that insurance index 0 is always for the payer being billed
789 // by this claim, and 1 and above are always for the "other" payers.
791 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
792 $tmp1 = $claim->claimType($ins);
793 $tmp2 = 'C1'; // Here a kludge. See page 321.
794 if ($tmp1 === 'CI') {
795 $tmp2 = 'C1';
797 if ($tmp1 === 'AM') {
798 $tmp2 = 'AP';
800 if ($tmp1 === 'HM') {
801 $tmp2 = 'HM';
803 if ($tmp1 === 'MB') {
804 $tmp2 = 'MB';
806 if ($tmp1 === 'MC') {
807 $tmp2 = 'MC';
809 if ($tmp1 === '09') {
810 $tmp2 = 'PP';
813 ++$edicount;
814 $out .= "SBR" . // Loop 2320, Subscriber Information - page 297/318
815 "*" . $claim->payerSequence($ins) .
816 "*" . $claim->insuredRelationship($ins) .
817 "*" . $claim->groupNumber($ins) .
818 "*" . ($claim->groupNumber() ? '' : $claim->groupName()) .
819 "*" . $claim->insuredTypeCode($ins) .
820 "*" .
821 "*" .
822 "*" .
823 "*" . $claim->claimType($ins) .
824 "~\n";
826 // Things that apply only to previous payers, not future payers.
827 if ($claim->payerSequence($ins) < $claim->payerSequence()) {
828 // Generate claim-level adjustments.
829 $aarr = $claim->payerAdjustments($ins);
830 foreach ($aarr as $a) {
831 ++$edicount;
832 $out .= "CAS" . // Previous payer's claim-level adjustments. Page 301/323.
833 "*" . $a[1] .
834 "*" . $a[2] .
835 "*" . $a[3] .
836 "~\n";
839 $payerpaid = $claim->payerTotals($ins);
840 ++$edicount;
841 $out .= "AMT" . // Previous payer's paid amount. Page 307/332.
842 "*" . "D" .
843 "*" . $payerpaid[1] .
844 "~\n";
845 // Segment AMT*A8 (COB Total Non-Covered Amount) omitted.
846 // Segment AMT*EAF (Remaining Patient Liability) omitted.
847 } // End of things that apply only to previous payers.
849 ++$edicount;
850 $out .= "OI" . // Other Insurance Coverage Information. Page 310/344.
851 "*" .
852 "*" .
853 "*" . ($claim->billingFacilityAssignment($ins) ? 'Y' : 'N') .
854 // For this next item, the 5010 example in the spec does not match its
855 // description. So this might be wrong.
856 "*" .
857 "*" .
858 "*" .
859 "Y" .
860 "~\n";
862 // Segment MOA (Medicare Outpatient Adjudication) omitted.
863 ++$edicount;
864 $out .= "NM1" . // Loop 2330A Subscriber info for other insco. Page 315/350.
865 "*" . "IL" .
866 "*" . "1" .
867 "*" . $claim->insuredLastName($ins) .
868 "*" . $claim->insuredFirstName($ins) .
869 "*" . $claim->insuredMiddleName($ins) .
870 "*" .
871 "*" .
872 "*" . "MI" .
873 "*" . $claim->policyNumber($ins) .
874 "~\n";
876 ++$edicount;
877 $out .= "N3" .
878 "*" . $claim->insuredStreet($ins) .
879 "~\n";
881 ++$edicount;
882 $out .= "N4" .
883 "*" . $claim->insuredCity($ins) .
884 "*" . $claim->insuredState($ins) .
885 "*" . stripZipCode($claim->insuredZip($ins)) .
886 "~\n";
888 // Segment REF (Other Subscriber Secondary Identification) omitted.
889 ++$edicount;
890 $payerName = substr($claim->payerName($ins), 0, 60);
891 $out .= "NM1" . // Loop 2330B Payer info for other insco. Page 322/359.
892 "*" . "PR" .
893 "*" . "2" .
894 "*" . $payerName .
895 "*" .
896 "*" .
897 "*" .
898 "*" .
899 "*" . "PI" .
900 "*" . $claim->payerID($ins) .
901 "~\n";
903 if (!$claim->payerID($ins)) {
904 $log .= "*** CMS ID is missing for payer '" . $claim->payerName($ins) . "'.\n";
907 ++$edicount;
908 $out .= "N3" .
909 "*" . $claim->payerStreet($ins) .
910 "~\n";
912 ++$edicount;
913 $out .= "N4" .
914 "*" . $claim->payerCity($ins) .
915 "*" . $claim->payerState($ins) .
916 "*" . stripZipCode($claim->payerZip($ins)) .
917 "~\n";
918 // Segment DTP*573 (Claim Check or Remittance Date) omitted.
919 // Segment REF (Other Payer Secondary Identifier) omitted.
920 // Segment REF*G1 (Other Payer Prior Authorization Number) omitted.
921 // Segment REF*9F (Other Payer Referral Number) omitted.
922 // Segment REF*T4 (Other Payer Claim Adjustment Indicator) omitted.
923 // Segment REF*F8 (Other Payer Claim Control Number) omitted.
924 // Segment NM1 (Other Payer Referring Provider) omitted.
925 // Segment REF (Other Payer Referring Provider Secondary Identification) omitted.
926 // Segment NM1 (Other Payer Rendering Provider) omitted.
927 // Segment REF (Other Payer Rendering Provider Secondary Identification) omitted.
928 // Segment NM1 (Other Payer Service Facility Location) omitted.
929 // Segment REF (Other Payer Service Facility Location Secondary Identification) omitted.
930 // Segment NM1 (Other Payer Supervising Provider) omitted.
931 // Segment REF (Other Payer Supervising Provider Secondary Identification) omitted.
932 // Segment NM1 (Other Payer Billing Provider) omitted.
933 // Segment REF (Other Payer Billing Provider Secondary Identification) omitted.
934 } // End loops 2320/2330*.
936 $loopcount = 0;
938 // Loop 2400 Procedure Loop.
941 for ($prockey = 0; $prockey < $proccount; ++$prockey) {
942 ++$loopcount;
943 ++$edicount;
944 $out .= "LX" . // Segment LX, Service Line. Page 398.
945 "*" . $loopcount .
946 "~\n";
948 ++$edicount;
949 $out .= "SV1" . // Segment SV1, Professional Service. Page 400.
950 "*" . "HC:" . $claim->cptKey($prockey) .
951 "*" . sprintf('%.2f', $claim->cptCharges($prockey)) .
952 "*" . "UN" .
953 "*" . $claim->cptUnits($prockey) .
954 "*" .
955 "*" .
956 "*";
957 $dia = $claim->diagIndexArray($prockey);
958 $i = 0;
959 foreach ($dia as $dindex) {
960 if ($i) {
961 $out .= ':';
964 $out .= $dindex;
965 if (++$i >= 4) {
966 break;
970 # needed for epstd
971 if ($claim->epsdtFlag()) {
972 $out .= "*" .
973 "*" .
974 "*" .
975 "*" . "Y" .
976 "~\n";
977 } else {
978 $out .= "~\n";
981 if (!$claim->cptCharges($prockey)) {
982 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no charges!\n";
985 if (empty($dia)) {
986 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' is not justified!\n";
989 // Segment SV5 (Durable Medical Equipment Service) omitted.
990 // Segment PWK01 (Line Supplemental Information) omitted.
991 // Segment CR1 (Ambulance Transport Information) omitted.
992 // Segment CR3 (Durable Medical Equipment Certification) omitted.
993 // Segment CRC (Ambulance Certification) omitted.
994 // Segment CRC (Hospice Employee Indicator) omitted.
995 // Segment CRC (Condition Indicator / Durable Medical Equipment) omitted.
997 ++$edicount;
998 $out .= "DTP" . // Date of Service. Page 435.
999 "*" . "472" .
1000 "*" . "D8" .
1001 "*" . $claim->serviceDate() .
1002 "~\n";
1004 $testnote = rtrim($claim->cptNotecodes($prockey));
1005 if (!empty($testnote)) {
1006 ++$edicount;
1007 $out .= "NTE" . // Explain Unusual Circumstances.
1008 "*" . "ADD" .
1009 "*" . $claim->cptNotecodes($prockey) .
1010 "~\n";
1013 // Segment DTP*471 (Prescription Date) omitted.
1014 // Segment DTP*607 (Revision/Recertification Date) omitted.
1015 // Segment DTP*463 (Begin Therapy Date) omitted.
1016 // Segment DTP*461 (Last Certification Date) omitted.
1017 // Segment DTP*304 (Last Seen Date) omitted.
1018 // Segment DTP (Test Date) omitted.
1019 // Segment DTP*011 (Shipped Date) omitted.
1020 // Segment DTP*455 (Last X-Ray Date) omitted.
1021 // Segment DTP*454 (Initial Treatment Date) omitted.
1022 // Segment QTY (Ambulance Patient Count) omitted.
1023 // Segment QTY (Obstetric Anesthesia Additional Units) omitted.
1024 // Segment MEA (Test Result) omitted.
1025 // Segment CN1 (Contract Information) omitted.
1026 // Segment REF*9B (Repriced Line Item Reference Number) omitted.
1027 // Segment REF*9D (Adjusted Repriced Line Item Reference Number) omitted.
1028 // Segment REF*G1 (Prior Authorization) omitted.
1029 // Segment REF*6R (Line Item Control Number) omitted.
1030 // (Really oughta have this for robust 835 posting!)
1031 // Segment REF*EW (Mammography Certification Number) omitted.
1032 // Segment REF*X4 (CLIA Number) omitted.
1033 // Segment REF*F4 (Referring CLIA Facility Identification) omitted.
1034 // Segment REF*BT (Immunization Batch Number) omitted.
1035 // Segment REF*9F (Referral Number) omitted.
1036 // Segment AMT*T (Sales Tax Amount) omitted.
1037 // Segment AMT*F4 (Postage Claimed Amount) omitted.
1038 // Segment K3 (File Information) omitted.
1039 // Segment NTE (Line Note) omitted.
1040 // Segment NTE (Third Party Organization Notes) omitted.
1041 // Segment PS1 (Purchased Service Information) omitted.
1042 // Segment HCP (Line Pricing/Repricing Information) omitted.
1044 // Loop 2410, Drug Information. Medicaid insurers seem to want this
1045 // with HCPCS codes.
1047 $ndc = $claim->cptNDCID($prockey);
1049 if ($ndc) {
1050 ++$edicount;
1051 $out .= "LIN" . // Drug Identification. Page 500+ (Addendum pg 71).
1052 "*" . // Per addendum, LIN01 is not used.
1053 "*" . "N4" .
1054 "*" . $ndc .
1055 "~\n";
1057 if (!preg_match('/^\d\d\d\d\d-\d\d\d\d-\d\d$/', $ndc, $tmp) && !preg_match('/^\d{11}$/', $ndc)) {
1058 $log .= "*** NDC code '$ndc' has invalid format!\n";
1061 ++$edicount;
1062 $out .= "CTP" . // Drug Pricing. Page 500+ (Addendum pg 74).
1063 "*" .
1064 "*" .
1065 "*" .
1066 "*" . $claim->cptNDCQuantity($prockey) .
1067 "*" . $claim->cptNDCUOM($prockey) .
1068 // Note: 5010 documents "ME" (Milligrams) as an additional unit of measure.
1069 "~\n";
1071 // Segment REF (Prescription or Compound Drug Association Number) omitted.
1075 // Loop 2420A, Rendering Provider (service-specific).
1076 // Used if the rendering provider for this service line is different
1077 // from that in loop 2310B.
1079 if ($claim->providerNPI() != $claim->providerNPI($prockey)) {
1080 ++$edicount;
1081 $out .= "NM1" . // Loop 2420A Rendering Provider
1082 "*" . "82" .
1083 "*" . "1" .
1084 "*" . $claim->providerLastName($prockey) .
1085 "*" . $claim->providerFirstName($prockey) .
1086 "*" . $claim->providerMiddleName($prockey) .
1087 "*" .
1088 "*";
1089 if ($claim->providerNPI($prockey)) {
1090 $out .=
1091 "*" . "XX" .
1092 "*" . $claim->providerNPI($prockey);
1093 } else {
1094 $log .= "*** Rendering provider has no NPI.\n";
1096 $out .= "~\n";
1098 // Segment PRV*PE (Rendering Provider Specialty Information) .
1100 if ($claim->providerTaxonomy($prockey)) {
1101 ++$edicount;
1102 $out .= "PRV" .
1103 "*" . "PE" . // PErforming provider
1104 "*" . "PXC" .
1105 "*" . $claim->providerTaxonomy($prockey) .
1106 "~\n";
1109 // Segment REF (Rendering Provider Secondary Identification).
1110 // REF*1C is required here for the Medicare provider number if NPI was
1111 // specified in NM109. Not sure if other payers require anything here.
1113 if ($claim->providerNumberType($prockey) == "G2") {
1114 ++$edicount; $out .= "REF" . "*" . $claim->providerNumberType($prockey) .
1115 "*" . $claim->providerNumber($prockey) . "~\n";
1117 } // end provider exception
1119 // Segment NM1 (Loop 2420B Purchased Service Provider Name) omitted.
1120 // Segment REF (Loop 2420B Purchased Service Provider Secondary Identification) omitted.
1121 // Segment NM1,N3,N4 (Loop 2420C Service Facility Location) omitted.
1122 // Segment REF (Loop 2420C Service Facility Location Secondary Identification) omitted.
1123 // Segment NM1 (Loop 2420D Supervising Provider Name) omitted.
1124 // Segment REF (Loop 2420D Supervising Provider Secondary Identification) omitted.
1126 // Loop 2420E, Ordering Provider.
1127 // for Medicare DME claims esp @joe on chat.open-emr.org :)
1129 if ($claim->Box17Qualifier() == "DK" && ($claim->claimType() === 'MB')) {
1130 ++$edicount;
1131 $out .= "NM1" .
1132 "*" . $claim->Box17Qualifier() .
1133 "*" . "1" .
1134 "*" . $claim->billingProviderLastName() .
1135 "*" . $claim->billingProviderFirstName() .
1136 "*" . $claim->billingProviderMiddleName() .
1137 "*" .
1138 "*";
1139 if ($claim->billingProviderNPI()) {
1140 $out .=
1141 "*" . "XX" .
1142 "*" . $claim->billingProviderNPI();
1143 } else {
1144 $log .= "*** Ordering provider has no NPI.\n";
1146 $out .= "~\n";
1148 ++$edicount;
1149 $out .= "N3" .
1150 "*" . $claim->billingProviderStreet() .
1151 "*" . $claim->billingProviderStreetB() .
1152 "~\n";
1154 ++$edicount;
1155 $out .= "N4" .
1156 "*" . $claim->billingProviderCity() .
1157 "*" . $claim->billingProviderState() .
1158 "*" . stripZipCode($claim->billingProviderZip()) .
1159 "~\n";
1160 // Segment REF (Ordering Provider Secondary Identification) omitted.
1161 // Segment PER (Ordering Provider Contact Information) omitted.
1165 // Segment NM1 (Referring Provider Name) omitted.
1166 // Segment REF (Referring Provider Secondary Identification) omitted.
1167 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
1168 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
1170 // Loop 2430, adjudication by previous payers.
1173 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
1174 if ($claim->payerSequence($ins) > $claim->payerSequence()) {
1175 continue; // payer is future, not previous
1178 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
1179 $aarr = $claim->payerAdjustments($ins, $claim->cptKey($prockey));
1181 if ($payerpaid[1] == 0 && !count($aarr)) {
1182 $log .= "*** Procedure '" . $claim->cptKey($prockey) .
1183 "' has no payments or adjustments from previous payer!\n";
1184 continue;
1187 ++$edicount;
1188 $out .= "SVD" . // Service line adjudication. Page 554.
1189 "*" . $claim->payerID($ins) .
1190 "*" . $payerpaid[1] .
1191 "*" . "HC:" . $claim->cptKey($prockey) .
1192 "*" .
1193 "*" . $claim->cptUnits($prockey) .
1194 "~\n";
1196 $tmpdate = $payerpaid[0];
1197 foreach ($aarr as $a) {
1198 ++$edicount;
1199 $out .= "CAS" . // Previous payer's line level adjustments. Page 558.
1200 "*" . $a[1] .
1201 "*" . $a[2] .
1202 "*" . $a[3] .
1203 "~\n";
1204 if (!$tmpdate) {
1205 $tmpdate = $a[0];
1209 if ($tmpdate) {
1210 ++$edicount;
1211 $out .= "DTP" . // Previous payer's line adjustment date. Page 493/566.
1212 "*" . "573" .
1213 "*" . "D8" .
1214 "*" . $tmpdate .
1215 "~\n";
1218 // Segment AMT*EAF (Remaining Patient Liability) omitted.
1219 // Segment LQ (Form Identification Code) omitted.
1220 // Segment FRM (Supporting Documentation) omitted.
1221 } // end loop 2430
1222 } // end this procedure
1224 ++$edicount;
1225 $out .= "SE" . // SE Trailer
1226 "*" . $edicount .
1227 "*" . "0021" .
1228 "~\n";
1230 $out .= "GE" . // GE Trailer
1231 "*" . "1" .
1232 "*" . "1" .
1233 "~\n";
1235 $out .= "IEA" . // IEA Trailer
1236 "*" . "1" .
1237 "*" . "000000001" .
1238 "~\n";
1240 // Remove any trailing empty fields (delimiters) from each segment.
1241 $out = preg_replace('/\*+~/', '~', $out);
1243 $log .= "\n";
1244 return $out;