2 // Copyright (C) 2007 Rod Roark <rod@sunsetsystems.com>
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
10 // TBD: Write log messages for the "view log" screen.
13 require_once("Claim.class.php");
15 function gen_x12_837($pid, $encounter) {
19 $claim = new Claim($pid, $encounter);
28 "*" . strtoupper($claim->x12gssenderid()) .
30 "*" . strtoupper($claim->x12gsreceiverid()) .
43 "*" . strtoupper($claim->x12gssenderid()) .
44 "*" . strtoupper($claim->x12gsreceiverid()) .
45 "*" . date('Ymd', $today) .
46 "*" . date('Hi', $today) .
49 "*" . strtoupper($claim->x12gsversionstring()) .
63 "*" . date('Ymd', $today) .
71 "*" . strtoupper($claim->x12gsversionstring()) .
75 $out .= "NM1" . // Loop 1000A Submitter
78 "*" . strtoupper($claim->billingFacilityName()) .
84 "*" . strtoupper($claim->billingFacilityETIN()) .
90 "*" . strtoupper($claim->billingContactName()) .
92 "*" . $claim->billingContactPhone() .
96 $out .= "NM1" . // Loop 1000B Receiver
99 "*" . strtoupper($claim->clearingHouseName()) .
105 "*" . strtoupper($claim->clearingHouseETIN()) .
111 $out .= "HL" . // Loop 2000A Billing/Pay-To Provider HL Loop
118 $HLBillingPayToProvider = $HLcount++
;
121 $out .= "NM1" . // Loop 2010AA Billing Provider
124 "*" . strtoupper($claim->billingFacilityName()) .
129 if ($claim->billingFacilityNPI())
130 $out .= "*XX*" . $claim->billingFacilityNPI();
132 $out .= "*24*" . $claim->billingFacilityETIN();
137 "*" . strtoupper($claim->billingFacilityStreet()) .
142 "*" . strtoupper($claim->billingFacilityCity()) .
143 "*" . strtoupper($claim->billingFacilityState()) .
144 "*" . strtoupper($claim->billingFacilityZip()) .
147 // Add a REF*EI*<ein> segment if NPI was specified in the NM1 above.
149 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
153 "*" . $claim->billingFacilityETIN() .
159 "*" . $claim->providerNumberType() .
160 "*" . $claim->providerNumber() .
164 $out .= "NM1" . // Loop 2010AB Pay-To Provider
167 "*" . strtoupper($claim->billingFacilityName()) .
172 if ($claim->billingFacilityNPI())
173 $out .= "*XX*" . $claim->billingFacilityNPI();
175 $out .= "*24*" . $claim->billingFacilityETIN();
180 "*" . strtoupper($claim->billingFacilityStreet()) .
185 "*" . strtoupper($claim->billingFacilityCity()) .
186 "*" . strtoupper($claim->billingFacilityState()) .
187 "*" . strtoupper($claim->billingFacilityZip()) .
190 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
194 "*" . $claim->billingFacilityETIN() .
201 $out .= "HL" . // Loop 2000B Subscriber HL Loop
203 "*$HLBillingPayToProvider" .
208 $HLSubscriber = $HLcount++
;
211 $out .= "SBR" . // Subscriber Information
212 "*" . strtoupper($claim->payerSequence()) .
213 "*" . strtoupper($claim->insuredRelationship()) .
214 "*" . strtoupper($claim->groupNumber()) .
215 "*" . strtoupper($claim->groupName()) .
220 "*" . $claim->claimType() .
224 $out .= "NM1" . // Loop 2010BA Subscriber
227 "*" . strtoupper($claim->insuredLastName()) .
228 "*" . strtoupper($claim->insuredFirstName()) .
229 "*" . strtoupper($claim->insuredMiddleName()) .
233 "*" . $claim->policyNumber() .
238 "*" . strtoupper($claim->insuredStreet()) .
243 "*" . strtoupper($claim->insuredCity()) .
244 "*" . strtoupper($claim->insuredState()) .
245 "*" . strtoupper($claim->insuredZip()) .
251 "*" . $claim->insuredDOB() .
252 "*" . $claim->insuredSex() .
256 $out .= "NM1" . // Loop 2010BB Payer
259 "*" . strtoupper($claim->payerName()) .
265 "*" . $claim->payerID() .
270 "*" . strtoupper($claim->payerStreet()) .
275 "*" . strtoupper($claim->payerCity()) .
276 "*" . strtoupper($claim->payerState()) .
277 "*" . strtoupper($claim->payerZip()) .
280 if (! $claim->isSelfOfInsured()) {
282 $out .= "HL" . // Loop 2000C Patient Information
293 "*" . $claim->insuredRelationship() .
297 $out .= "NM1" . // Loop 2010CA Patient
300 "*" . strtoupper($claim->patientLastName()) .
301 "*" . strtoupper($claim->patientFirstName()) .
302 "*" . strtoupper($claim->patientMiddleName()) .
307 "*" . strtoupper($claim->patientStreet()) .
312 "*" . strtoupper($claim->patientCity()) .
313 "*" . strtoupper($claim->patientState()) .
314 "*" . strtoupper($claim->patientZip()) .
320 "*" . $claim->patientDOB() .
321 "*" . $claim->patientSex() .
323 } // end of patient different from insured
325 $proccount = $claim->procCount();
327 $clm_total_charges = 0;
328 for ($prockey = 0; $prockey < $proccount; ++
$prockey) {
329 $clm_total_charges +
= $claim->cptCharges($prockey);
333 $out .= "CLM" . // Loop 2300 Claim
335 "*" . sprintf("%.2f",$clm_total_charges) .
338 "*" . $claim->facilityPOS() . "::1" .
347 $out .= "DTP" . // Date of Onset
350 "*" . $claim->onsetDate() .
353 if ($claim->facilityPOS() == '21') {
355 $out .= "DTP" . // Date of Hospitalization
358 "*" . $claim->onsetDate() .
362 $patientpaid = $claim->patientPaidAmount();
363 if ($patientpaid != 0) {
365 $out .= "AMT" . // Patient paid amount. Page 220.
371 if ($claim->priorAuth()) {
373 $out .= "REF" . // Prior Authorization Number
375 "*" . $claim->priorAuth() .
379 if ($claim->cliaCode()) {
380 // Required by Medicare when in-house labs are done.
382 $out .= "REF" . // Clinical Laboratory Improvement Amendment Number
384 "*" . $claim->cliaCode() .
388 $da = $claim->diagArray();
390 $out .= "HI"; // Health Diagnosis Codes
391 $diag_type_code = 'BK';
392 foreach ($da as $diag) {
393 $out .= "*$diag_type_code:" . $diag;
394 $diag_type_code = 'BF';
398 if ($claim->referrerLastName()) {
399 // Medicare requires referring provider's name and UPIN.
401 $out .= "NM1" . // Loop 2310A Referring Provider
404 "*" . strtoupper($claim->referrerLastName()) .
405 "*" . strtoupper($claim->referrerFirstName()) .
406 "*" . strtoupper($claim->referrerMiddleName()) .
409 if ($claim->referrerNPI()) { $out .=
411 "*" . $claim->referrerNPI();
414 "*" . $claim->referrerSSN();
419 $out .= "REF" . // Referring Provider Secondary Identification
421 "*" . strtoupper($claim->referrerUPIN()) .
426 $out .= "NM1" . // Loop 2310B Rendering Provider
429 "*" . strtoupper($claim->providerLastName()) .
430 "*" . strtoupper($claim->providerFirstName()) .
431 "*" . strtoupper($claim->providerMiddleName()) .
434 if ($claim->providerNPI()) { $out .=
436 "*" . $claim->providerNPI();
439 "*" . $claim->providerSSN();
444 $out .= "PRV" . // Rendering Provider Information
451 $out .= "NM1" . // Loop 2310B Service Location
454 "*" . strtoupper($claim->facilityName()) .
459 if ($claim->facilityNPI()) { $out .=
460 "*XX*" . $claim->facilityNPI();
462 "*24*" . $claim->facilityETIN();
468 "*" . strtoupper($claim->facilityStreet()) .
473 "*" . strtoupper($claim->facilityCity()) .
474 "*" . strtoupper($claim->facilityState()) .
475 "*" . strtoupper($claim->facilityZip()) .
478 // Loops 2320 and 2330*, other subscriber/payer information.
480 for ($ins = 1; $ins < $claim->payerCount(); ++
$ins) {
483 $out .= "SBR" . // Loop 2320, Subscriber Information - page 318
484 "*" . strtoupper($claim->payerSequence($ins)) .
485 "*" . strtoupper($claim->insuredRelationship($ins)) .
486 "*" . strtoupper($claim->groupNumber($ins)) .
487 "*" . strtoupper($claim->groupName($ins)) .
492 "*" . $claim->claimType($ins) .
495 // Things that apply only to previous payers, not future payers.
497 if ($claim->payerSequence($ins) < $claim->payerSequence()) {
499 // Generate claim-level adjustments.
500 $aarr = $claim->payerAdjustments($ins);
501 foreach ($aarr as $a) {
503 $out .= "CAS" . // Previous payer's claim-level adjustments. Page 323.
510 $payerpaid = $claim->payerPaidAmount($ins);
512 $out .= "AMT" . // Previous payer's paid amount. Page 332.
518 $out .= "AMT" . // Patient responsibility amount per previous payer. Page 335.
520 "*" . sprintf('%.2f', $claim->invoiceTotal() - $payerpaid) .
523 } // End of things that apply only to previous payers.
526 $out .= "OI" . // Other Insurance Coverage Information. Page 344.
536 $out .= "NM1" . // Loop 2330A Subscriber info for other insco. Page 350.
539 "*" . strtoupper($claim->insuredLastName($ins)) .
540 "*" . strtoupper($claim->insuredFirstName($ins)) .
541 "*" . strtoupper($claim->insuredMiddleName($ins)) .
545 "*" . $claim->policyNumber($ins) .
549 $out .= "NM1" . // Loop 2330B Payer info for other insco. Page 359.
552 "*" . strtoupper($claim->payerName($ins)) .
558 "*" . $claim->payerID($ins) .
561 } // End loops 2320/2330*.
565 // Procedure loop starts here.
567 for ($prockey = 0; $prockey < $proccount; ++
$prockey) {
571 $out .= "LX" . // Loop 2400 LX Service Line. Page 398.
576 $out .= "SV1" . // Professional Service. Page 400.
577 "*HC:" . strtoupper($claim->cptCode($prockey));
578 if ($claim->cptModifier($prockey)) { $out .=
579 ":" . strtoupper($claim->cptModifier($prockey));
582 "*" . sprintf('%.2f', $claim->cptCharges($prockey)) .
584 "*" . $claim->cptUnits($prockey) .
587 "*" . $claim->diagIndex($prockey) .
591 $out .= "DTP" . // Date of Service. Page 435.
594 "*" . $claim->serviceDate() .
597 // Loop 2410, Drug Information. Medicaid insurers seem to want this
600 if ($claim->cptNDCID($prockey))
602 $out .= "LIN" . // Drug Identification. Page 500+ (Addendum pg 71).
605 "*" . $claim->cptNDCID($prockey) .
609 $out .= "CTP" . // Drug Pricing. Page 500+ (Addendum pg 74).
612 "*0" . // dummy price, required by HIPAA
613 "*" . $claim->cptNDCQuantity($prockey) .
614 "*" . $claim->cptNDCUOM($prockey) .
618 // Loop 2430, adjudication by previous payers.
620 for ($ins = 1; $ins < $claim->payerCount(); ++
$ins) {
621 if ($claim->payerSequence($ins) > $claim->payerSequence())
622 continue; // payer is future, not previous
625 $out .= "SVD" . // Service line adjudication. Page 554.
626 "*" . $claim->payerID($ins) .
627 "*" . $claim->payerPaidAmount($ins, $claim->cptCode($prockey)) .
628 "*HC:" . strtoupper($claim->cptCode($prockey));
629 if ($claim->cptModifier($prockey)) $out .=
630 ":" . strtoupper($claim->cptModifier($prockey));
633 "*" . $claim->cptUnits($prockey) .
636 $aarr = $claim->payerAdjustments($ins, $claim->cptCode($prockey));
638 foreach ($aarr as $a) {
640 $out .= "CAS" . // Previous payer's line level adjustments. Page 558.
650 $out .= "DTP" . // Previous payer's line adjustment date. Page 566.
657 } // end this procedure
660 $out .= "SE" . // SE Trailer
665 $out .= "GE" . // GE Trailer
670 $out .= "IEA" . // IEA Trailer