6 * @link http://www.open-emr.org
7 * @author Jerry Padgett <sjpadgett@gmail.com>
8 * @copyright Copyright (c) 2017 Jerry Padgett <sjpadgett@gmail.com>
9 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
12 require_once(dirname(__FILE__
) . "/invoice_summary.inc.php");
14 use OpenEMR\Billing\Claim
;
16 function x12date($frmdate)
18 return ('20' . substr($frmdate, 4, 2) . substr($frmdate, 0, 2) . substr($frmdate, 2, 2));
22 function generate_x12_837I($pid, $encounter, &$log, $ub04id)
26 $claim = new Claim($pid, $encounter);
29 $log .= "Generating 837I claim $pid-$encounter for " .
30 $claim->patientFirstName() . ' ' .
31 $claim->patientMiddleName() . ' ' .
32 $claim->patientLastName() . ' on ' .
33 date('Y-m-d H:i', $today) . ".\n";
35 "*" . $claim->x12gsisa01() .
36 "*" . $claim->x12gsisa02() .
37 "*" . $claim->x12gsisa03() .
38 "*" . $claim->x12gsisa04() .
39 "*" . $claim->x12gsisa05() .
40 "*" . $claim->x12gssenderid() .
41 "*" . $claim->x12gsisa07() .
42 "*" . $claim->x12gsreceiverid() .
43 // date of transmission "*030911" .
44 "*" . date('Ymd', $today) .
45 //Time of transmission "*1630" .
46 "*" . date('Hi', $today) .
50 "*" . $claim->x12gsisa14() .
51 "*" . $claim->x12gsisa15() .
56 "*" . $claim->x12gsgs02() .
57 "*" . trim($claim->x12gs03()) .
58 "*" . date('Ymd', $today) .
59 "*" . date('Hi', $today) .
62 // "*" . $claim->x12gsversionstring() .
69 // "*" . $claim->x12gsversionstring() .
74 "*" . "0019" . // 0019 is required here
75 "*" . "00" . // 00 = original transmission
76 "*" . "0123" . // reference identification
77 "*" . date('Ymd', $today) . // transaction creation date
78 "*" . date('Hi', $today) . // transaction creation time
79 ($encounter_claim ?
"*RP" : "*CH") . // RP = reporting, CH = chargeable
83 //Field length is limited to 35. See nucc dataset page 63 www.nucc.org
84 $billingFacilityName = substr($claim->billingFacilityName(), 0, 60);
85 if ($billingFacilityName == '') {
86 $log .= "*** billing facility name in 1000A loop is empty\n";
88 $out .= "NM1" . // Loop 1000A Submitter stays in the 837I
91 "*" . $billingFacilityName .
98 $out .= "*" . $claim->billingFacilityETIN();
104 "*" . $claim->billingContactName() .
106 "*" . $claim->billingContactPhone();
111 $out .= "NM1" . // Loop 1000B Receiver stays in the 837I
114 "*" . $claim->clearingHouseName() .
120 "*" . $claim->clearingHouseETIN() .
125 $out .= "HL" . // Loop 2000A Billing/Pay-To Provider HL Loop
129 "*" . "1" . // 1 indicates there are child segments
131 $HLBillingPayToProvider = $HLcount++
;
132 // Situational PRV segment (for provider taxonomy code) omitted here.
133 // Situational CUR segment (foreign currency information) omitted here.
135 //Field length is limited to 35. See nucc dataset page 63 www.nucc.org
136 $billingFacilityName = substr($claim->billingFacilityName(), 0, 60);
137 $out .= "NM1" . // Loop 2010AA Billing Provider stays in the 837I
140 "*" . $billingFacilityName .
145 if ($claim->billingFacilityNPI()) {
146 $out .= "*XX*" . $claim->billingFacilityNPI();
148 $log .= "*** Billing facility has no NPI.\n";
154 "*" . $claim->billingFacilityStreet() .
158 "*" . $claim->billingFacilityCity() .
159 "*" . $claim->billingFacilityState() .
160 "*" . stripZipCode($claim->billingFacilityZip()) .
162 if ($claim->billingFacilityNPI() && $claim->billingFacilityETIN()) {
165 if ($claim->federalIdType()) {
166 $out .= "*" . $claim->federalIdType();
168 $out .= "*EI"; // For dealing with the situation before adding TaxId type In facility.
170 $out .= "*" . $claim->billingFacilityETIN() . "~\n";
172 $log .= "*** No billing facility NPI and/or ETIN.\n";
174 if ($claim->providerNumberType() && $claim->providerNumber() && !$claim->billingFacilityNPI()) {
177 "*" . $claim->providerNumberType() .
178 "*" . $claim->providerNumber() .
180 } else if ($claim->providerNumber() && !$claim->providerNumberType()) {
181 $log .= "*** Payer-specific provider insurance number is present but has no type assigned.\n";
183 // Situational PER*1C segment.
187 "*" . $claim->billingContactName() .
189 "*" . $claim->billingContactPhone();
192 // This is also excluded in the 837I
193 // Loop 2010AC Pay-To Plan Name omitted. Includes:
194 // NM1*PE, N3, N4, REF*2U, REF*EI
195 $PatientHL = $claim->isSelfOfInsured() ?
0 : 1;
196 $HLSubscriber = $HLcount++
;
200 $out .= "HL" . // Loop 2000B Subscriber HL Loop
202 "*$HLBillingPayToProvider" .
206 if (!$claim->payerSequence()) {
207 $log .= "*** Error: Insurance information is missing!\n";
211 //SBR01 is either a P or S SBR02 for care is always 18 "patient" SBR09 is always MA
212 $out .= "SBR" . // Subscriber Information
213 "*" . $claim->payerSequence() .
214 "*" . ($claim->isSelfOfInsured() ?
'18' : '') .
215 "*" . $claim->groupNumber() .
216 "*" . (($claim->groupNumber()) ?
'' : $claim->groupName()) .
217 "*" . $claim->insuredTypeCode() . // applies for secondary medicare
221 "*" . $claim->claimType() . // Zirmed replaces this
223 // 2000C Segment PAT omitted.
225 $out .= "NM1" . // Loop 2010BA Subscriber same in 837I
227 "*" . "1" . // 1 = person, 2 = non-person
228 "*" . $claim->insuredLastName() .
229 "*" . $claim->insuredFirstName() .
230 "*" . $claim->insuredMiddleName() .
234 // "MI" = Member Identification Number
235 // "II" = Standard Unique Health Identifier, "Required if the
236 // HIPAA Individual Patient Identifier is mandated use."
237 // Here we presume that is not true yet.
238 "*" . $claim->policyNumber() .
240 // For 5010, further subscriber info is sent only if they are the patient.
241 if ($claim->isSelfOfInsured()) {
244 "*" . $claim->insuredStreet() .
248 "*" . $claim->insuredCity() .
249 "*" . $claim->insuredState() .
250 "*" . stripZipCode($claim->insuredZip()) .
255 "*" . $claim->insuredDOB() .
256 "*" . $claim->insuredSex() .
259 // Segment REF*SY (Subscriber Secondary Identification) omitted.
260 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
261 // Segment PER*IC (Property and Casualty Subscriber Contact Information) omitted.
263 $payerName = substr($claim->payerName(), 0, 60);
264 $out .= "NM1" . // Loop 2010BB Payer
273 "*" . ($encounter_claim ?
$claim->payerAltID() : $claim->payerID()) .
275 if (!$claim->payerID()) {
276 $log .= "*** CMS ID is missing for payer '" . $claim->payerName() . "'.\n";
281 "*" . $claim->payerStreet() .
285 "*" . $claim->payerCity() .
286 "*" . $claim->payerState() .
287 "*" . stripZipCode($claim->payerZip()) .
290 // Segment REF (Payer Secondary Identification) omitted.
291 // Segment REF (Billing Provider Secondary Identification) omitted.
294 if (! $claim->isSelfOfInsured()) {
296 $out .= "HL" . // Loop 2000C Patient Information
305 "*" . $claim->insuredRelationship() .
308 $out .= "NM1" . // Loop 2010CA Patient may need this elsed in to the loop 2000C
311 "*" . $claim->patientLastName() .
312 "*" . $claim->patientFirstName();
313 if ($claim->patientMiddleName() !== '') {
314 $out .= "*" . $claim->patientMiddleName();
319 "*" . $claim->patientStreet() .
323 "*" . $claim->patientCity() .
324 "*" . $claim->patientState() .
325 "*" . stripZipCode($claim->patientZip()) .
330 "*" . $claim->patientDOB() .
331 "*" . $claim->patientSex() .
333 // Segment REF*Y4 (Property and Casualty Claim Number) omitted.
334 // Segment REF (Property and Casualty Patient Identifier) omitted.
335 // Segment PER (Property and Casualty Patient Contact Information) omitted.
336 } // end of patient different from insured
337 $proccount = $claim->procCount();
338 $clm_total_charges = 0;
339 for ($prockey = 0; $prockey < $proccount; ++
$prockey) {
340 $clm_total_charges +
= $claim->cptCharges($prockey);
342 if (!$clm_total_charges) {
343 $log .= "*** This claim has no charges!\n";
346 $out .= "CLM" . // Loop 2300 Claim
347 "*" . $pid . "-" . $encounter .
348 "*" . sprintf("%.2f", $clm_total_charges) . // Zirmed computes and replaces this
351 // Service location this need to be bill type from ub form type_of_bill
352 if (strlen($ub04id[7]) >= 3) {
353 $out .= "*" . substr($ub04id[7], 1, 1) . ":" . substr($ub04id[7], 2, 1) . ":" . substr($ub04id[7], 3, 1);
358 "*" . ($claim->billingFacilityAssignment() ?
'Y' : 'N') .
364 $out .= "DTP" . // Loop 2300
372 // DTP 434 RD8 (Statment from OR to date)
377 $tmp = x12date($ub04id[13]);
378 $tmp1 = x12date($ub04id[14]);
379 $out .= "DTP" . // Loop 2300
380 "*434" . "*" . "RD8" . "*" . $tmp . '-' . $tmp1 . "~\n";
385 $tmp = x12date($ub04id[25]);
386 $out .= "DTP" . // Loop 2300
387 "*435" . "*" . "DT" . "*" . $tmp . $ub04id[26] . "~\n";
390 if (strlen(trim($ub04id[13])) == 0) {
391 $log .= "*** Error: No Admission Date Entered!\n";
394 // Repricer Received Date
395 // DTP 050 D8 (Admission Date and Hour from form)
397 // Institutional Claim Code
398 // CL1 (Admission Type Code) (Admission Source Code) (Patient Status Code)
400 if ($ub04id[27] != "014X") { // Type of bill
402 $out .= "CL1" . // Loop 2300
403 "*" . $ub04id[27] . "*" . $ub04id[28] . "*" . $ub04id[30] . "~\n";
406 // Segment PWK (Claim Supplemental Information) omitted.
408 // Segment CN1 (Contract Information) omitted.
410 // Patient Estimated Amount Due
413 // $patientpaid = $claim->patientPaidAmount();
414 // if ($patientpaid != 0) {
416 // $out .= "AMT" . // Patient paid amount. Page 190/220.
418 // "*" . $patientpaid .
422 // Segment REF*4N (Service Authorization Exception Code) omitted.
423 // Segment REF*9F (Referral Number) omitted.
425 // Prior Authorization
427 if ($claim->priorAuth()) {
429 $out .= "REF" . // Prior Authorization Number
430 "*G1" . "*" . $claim->priorAuth() . "~\n";
433 // Segment REF*F8 (Payer Claim Control Number) omitted.
435 // This may be needed for the UB04 Claim if so change the 'MB' to 'MA'
436 // if ($claim->cliaCode() && ($CMS_5010 || $claim->claimType() === 'MB')) {
437 // Required by Medicare when in-house labs are done.
439 // $out .= "REF" . // Clinical Laboratory Improvement Amendment Number
441 // "*" . $claim->cliaCode() .
445 // Segment REF*9A (Repriced Claim Number) omitted.
446 // Segment REF*9C (Adjusted Repriced Claim Number) omitted.
447 // Segment REF*LX (Investigational Device Exemption Number) omitted.
448 // Segment REF*S9 (Claim Identifier for Transmission Intermediaries) omitted.
449 // Segment REF*LU (Auto Accident State) omitted.
450 // Segment REF*EA (Medical Record Number) omitted.
451 // Segment REF*P4 (Demonstration Project Identifier) omitted.
452 // Segment REF*G4 (Peer Review Organization PRO Approval Number) omitted.
453 // Segment K3 (File Information) omitted.
455 if ($claim->additionalNotes()) {
457 // Has a list of valid codes. Required when PROVIDER deems necessary
460 // Check to verify I am getting this information on the ub04 form
463 $out .= "NTE" . // comments box 19
464 "*" . "ADD" . "*" . $claim->additionalNotes() . "~\n";
467 // Segment CRC (EPSDT Referral) omitted.
468 // Diagnoses, up to $max_per_seg per HI segment. Check this
470 $da = $claim->diagArray();
471 $diag_type_code = 'ABK'; // ICD10
473 foreach ($da as $diag) {
477 if ($tmp %
$max_per_seg == 0) {
482 $out .= "HI"; // Health Diagnosis Codes
484 $out .= "*" . $diag_type_code . ":" . $diag;
485 if ($claim->diagtype
== "ICD9") {
486 $diag_type_code = 'BF';
488 $diag_type_code = 'ABF';
497 // Segment HI*BI (Occurrence Span Information).
498 // HI BI (Occurrence Span Code 1) RD8 (Occurrence Span Code Associated Date)
501 $diag_type_code = 'BI';
504 for ($i = 0; $i <= 3;) {
505 if ($tmp %
$max_per_seg == 0) {
510 $out .= "HI"; // Health Diagnosis Codes
513 $out .= "*" . $diag_type_code . ":" . $ub04id[$os ++
] . ":" . x12date($ub04id[$os ++
]) . ":" . x12date($ub04id[$os ++
]);
514 $diag_type_code = 'BI';
527 // Segment HI*BH (Occurrence Information).
528 // HI BH (Occurrence Code 1) D8 (Occurrence Code Associated Date)
532 $diag_type_code = 'BH';
535 for ($i = 0; $i <= 7;) {
536 if ($tmp %
$max_per_seg == 0) {
541 $out .= "HI"; // Health Diagnosis Codes
544 $out .= "*" . $diag_type_code . ":" . $ub04id[$os] . ":D8" . ":" . x12date($ub04id[$os ++
]);
545 $diag_type_code = 'BH';
558 // Segment HI*BE (Value Information).
559 // HI BE (Value Code 1) *.* (Value Code Amount)
563 $diag_type_code = 'BE';
566 for ($i = 0; $i <= 11;) {
567 if ($tmp %
$max_per_seg == 0) {
572 $out .= "HI"; // Health Diagnosis Codes
576 $out .= "*" . $diag_type_code . ":" . $ub04id[$os ++
] . ":" . ":" . x12date($ub04id[$os ++
]);
577 $diag_type_code = 'BE';
588 // Segment HI*BG (Condition Information).
589 // HI BG (Condition Code 1)
593 $diag_type_code = 'BG';
596 for ($i = 0; $i <= 10;) {
597 if ($tmp %
$max_per_seg == 0) {
602 $out .= "HI"; // Health Diagnosis Codes
606 $out .= "*" . $diag_type_code . ":" . $ub04id[$os ++
];
607 $diag_type_code = 'BG';
619 // Segment HI*TC (Treatment Code Information).
620 // HI TC (Treatment Code 1)
621 /* 63a. TREATMENT AUTHORIZATION CODES - PRIMARY PLAN */
624 $diag_type_code = 'TC';
627 for ($i = 0; $i <= 2;) {
628 if ($tmp %
$max_per_seg == 0) {
633 $out .= "HI"; // Health Diagnosis Codes
637 $out .= "*" . $diag_type_code . ":" . $ub04id[319];
638 $diag_type_code = 'TC';
642 $out .= "*" . $diag_type_code . ":" . $ub04id[322];
643 $diag_type_code = 'TC';
648 $out .= "*" . $diag_type_code . ":" . $ub04id[325];
649 $diag_type_code = 'TC';
661 // Segment HCP (Claim Pricing/Repricing Information) omitted.
663 // This needs to allow Attending Physician 2310A, Operating Physician Name 2310B, Other Operating Physician Name 2310C
664 // and Rendering Provider Name (Rendering Provider Name is futher down)
668 // Loop 2310A Attending Physician
669 $out .= "NM1" . "*71" . "*1" . "*" . $ub04id[388] . "*" . $ub04id[389] . "*" . "*";
670 if ($ub04id[379]) { // NPI
671 $out .= "*" . "XX" . "*" . $ub04id[379];
674 $log .= "*** Attending Physician has no NPI.\n";
680 $out .= "REF" . // Attending Physician Secondary Identification
681 "*" . $ub04id[380] . "*" . $ub04id[381] . "~\n";
690 $out .= "NM1" . // Loop 2310B operating Physician
691 "*72" . "*1" . "*" . $ub04id[400] . "*" . $ub04id[400] . "*" . "*";
693 $out .= "*" . "XX" . "*" . $ub04id[390];
696 $log .= "*** Operating Physician has no NPI qualifier.\n";
702 $out .= "REF" . // operating Physician Secondary Identification
703 "*" . $claim->$ub04id[391] . "*" . $ub04id[392] . "~\n";
712 $out .= "NM1" . // Loop 2310C other operating Physician
713 "*73" . "*1" . "*" . $ub04id[413] . "*" . $ub04id[414] . "*" . "*";
715 $out .= "*" . $ub04id[405] . "*" . $ub04id[406];
718 $log .= "*** Other Operating Physician has no NPI.\n";
724 $out .= "REF" . // other operating Physician Secondary Identification
725 "*" . $ub04id[407] . "*" . $ub04id[408] . "~\n";
731 $out .= "NM1" . // Loop 2310C other operating Physician
732 "*73" . "*1" . "*" . $ub04id[427] . "*" . $ub04id[428] . "*" . "*";
734 $out .= "*" . $ub04id[419] . "*" . $ub04id[420];
737 $log .= "*** Other Operating Physician has no NPI.\n";
743 $out .= "REF" . // other operating Physician Secondary Identification
744 "*" . $ub04id[422] . "*" . $ub04id[421] . "~\n";
748 * Per the implementation guide lines, only include this information if it is different
749 * than the Loop 2010AA information
751 if ($claim->providerNPIValid() && $claim->billingFacilityNPI() !== $claim->providerNPI()) {
753 $out .= "NM1" . // Loop 2310D Rendering Provider
754 "*82" . "*1" . "*" . $claim->providerLastName() . "*" . $claim->providerFirstName() . "*" . $claim->providerMiddleName() . "*" . "*";
755 if ($claim->providerNPI()) {
756 $out .= "*XX" . "*" . $claim->providerNPI();
758 $log .= "*** Rendering provider has no NPI.\n";
764 // This loop can only get skipped if we are generating a 5010 claim
765 if (! ($claim->providerNPIValid())) {
766 //If the loop was skipped because the provider NPI was invalid, generate a warning for the log.
767 $log .= "*** Skipping 2310B because " . $claim->providerLastName() . "," . $claim->providerFirstName() . " has invalid NPI.\n";
770 * Skipping this segment because the providerNPI and the billingFacilityNPI are identical
771 * is a normal condition, so no need to warn.
775 // 5010 spec says nothing here if NPI was specified.
777 if (! $claim->providerNPI() && in_array($claim->providerNumberType(), array('0B', '1G', 'G2', 'LU'))) {
778 if ($claim->providerNumber()) {
780 $out .= "REF" . "*" . $claim->providerNumberType() . "*" . $claim->providerNumber() . "~\n";
784 // Loop 2310D is omitted in the case of home visits (POS=12).
785 if ($claim->facilityPOS() != 12 && ($claim->facilityNPI() != $claim->billingFacilityNPI())) {
788 // Service Facility Name
790 $out .= "NM1" . // Loop 2310E Service Location
792 $facilityName = substr($claim->facilityName(), 0, 60);
793 if ($claim->facilityName() ||
$claim->facilityNPI() ||
$claim->facilityETIN()) {
794 $out .= "*" . $facilityName;
796 if ($claim->facilityNPI() ||
$claim->facilityETIN()) {
797 $out .= "*" . "*" . "*" . "*";
798 if ($claim->facilityNPI()) {
799 $out .= "*XX*" . $claim->facilityNPI();
801 $log .= "*** Service location has no NPI.\n";
805 if ($claim->facilityStreet()) {
807 $out .= "N3" . "*" . $claim->facilityStreet() . "~\n";
809 if ($claim->facilityState()) {
811 $out .= "N4" . "*" . $claim->facilityCity() . "*" . $claim->facilityState() . "*" . stripZipCode($claim->facilityZip()) . "~\n";
815 // Segment REF (Service Facility Location Secondary Identification) omitted.
816 // Segment PER (Service Facility Contact Information) omitted.
818 // Loop 2310F Referring Provider
820 if ($claim->referrerLastName()) {
821 // Medicare requires referring provider's name and UPIN.
824 $out .= "NM1" . // Loop 2310F Referring Provider this needs to change position
825 "*DN" . "*1" . "*" . $claim->referrerLastName() . "*" . $claim->referrerFirstName() . "*" . $claim->referrerMiddleName() . "*" . "*";
826 if ($claim->referrerNPI()) {
827 $out .= "*XX" . "*" . $claim->referrerNPI();
829 $log .= "*** Referrer has no NPI.\n";
834 // Loop 2310E, Supervising Provider
837 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
838 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
840 $prev_pt_resp = $clm_total_charges; // for computation below
842 // Loops 2320 and 2330*, other subscriber/payer information.
843 // Remember that insurance index 0 is always for the payer being billed
844 // by this claim, and 1 and above are always for the "other" payers.
846 for ($ins = 1; $ins < $claim->payerCount(); ++
$ins) {
847 $tmp1 = $claim->claimType($ins);
848 $tmp2 = 'C1'; // Here a kludge. See page 321.
849 if ($tmp1 === 'CI') {
852 if ($tmp1 === 'AM') {
855 if ($tmp1 === 'HM') {
858 if ($tmp1 === 'MB') {
861 if ($tmp1 === 'MA') {
864 if ($tmp1 === 'MC') {
867 if ($tmp1 === '09') {
872 $out .= "SBR" . // Loop 2320, Subscriber Information - page 297/318
873 "*" . $claim->payerSequence($ins) .
874 "*" . $claim->insuredRelationship($ins) .
875 "*" . $claim->groupNumber($ins) .
876 "*" . (($claim->groupNumber($ins)) ?
'' : $claim->groupName($ins)) .
877 "*" . ($claim->insuredTypeCode($ins) ?
$claim->insuredTypeCode($ins) : $tmp2) .
881 "*" . $claim->claimType($ins) .
884 // Things that apply only to previous payers, not future payers.
886 if ($claim->payerSequence($ins) < $claim->payerSequence()) {
887 // Generate claim-level adjustments.
888 $aarr = $claim->payerAdjustments($ins);
889 foreach ($aarr as $a) {
891 $out .= "CAS" . // Previous payer's claim-level adjustments. Page 301/323.
892 "*" . $a[1] . "*" . $a[2] . "*" . $a[3] . "~\n";
895 $payerpaid = $claim->payerTotals($ins);
897 $out .= "AMT" . // Previous payer's paid amount. Page 307/332.
898 "*D" . "*" . $payerpaid[1] . "~\n";
900 // Segment AMT*A8 (COB Total Non-Covered Amount) omitted.
901 // Segment AMT*EAF (Remaining Patient Liability) omitted.
902 } // End of things that apply only to previous payers.
905 $out .= "OI" . // Other Insurance Coverage Information. Page 310/344.
906 "*" . "*" . "*" . ($claim->billingFacilityAssignment($ins) ?
'Y' : 'N') .
907 // For this next item, the 5010 example in the spec does not match its
908 // description. So this might be wrong.
915 // Segment MOA (Medicare Outpatient Adjudication) omitted.
917 $out .= "NM1" . // Loop 2330A Subscriber info for other insco. Page 315/350.
920 "*" . $claim->insuredLastName($ins) .
921 "*" . $claim->insuredFirstName($ins) .
922 "*" . $claim->insuredMiddleName($ins) .
926 "*" . $claim->policyNumber($ins) .
931 "*" . $claim->insuredStreet($ins) .
936 "*" . $claim->insuredCity($ins) .
937 "*" . $claim->insuredState($ins) .
938 "*" . stripZipCode($claim->insuredZip($ins)) .
941 // Segment REF (Other Subscriber Secondary Identification) omitted.
943 $payerName = substr($claim->payerName($ins), 0, 60);
944 $out .= "NM1" . // Loop 2330B Payer info for other insco. Page 322/359.
953 "*" . $claim->payerID($ins) .
956 if (!$claim->payerID($ins)) {
957 $log .= "*** CMS ID is missing for payer '" . $claim->payerName($ins) . "'.\n";
962 "*" . $claim->payerStreet($ins) .
967 "*" . $claim->payerCity($ins) .
968 "*" . $claim->payerState($ins) .
969 "*" . stripZipCode($claim->payerZip($ins)) .
972 // Segment DTP*573 (Claim Check or Remittance Date) omitted.
973 // Segment REF (Other Payer Secondary Identifier) omitted.
974 // Segment REF*G1 (Other Payer Prior Authorization Number) omitted.
975 // Segment REF*9F (Other Payer Referral Number) omitted.
976 // Segment REF*T4 (Other Payer Claim Adjustment Indicator) omitted.
977 // Segment REF*F8 (Other Payer Claim Control Number) omitted.
978 // 2330C-I loops Omitted
979 } // End loops 2320/2330*.
983 // Procedure loop starts here.
986 for ($tlh = 0; $tlh < $proccount; ++
$tlh) {
987 $tmp = $claim->procs
[$tlh][code_text
];
989 if ($claim->procs
[$tlh][code_type
] == 'HCPCS') {
994 $getrevcd = $claim->cptCode($tlh);
995 $sql = "SELECT * FROM codes WHERE code_type = ? and code = ? ORDER BY revenue_code DESC";
996 $revcode[$tlh] = sqlQuery($sql, array(
1003 for ($prockey = 0; $prockey < $proccount; ++
$prockey) {
1004 $os = 99 +
($loopcount * 8); // Form revenue code offset
1005 $dosos = 102 +
($loopcount * 8); // Procedure date of service form start offset-add 8 for loop
1009 $out .= "LX" . // Loop 2400 LX Service Line. Page 398.
1010 "*" . "$loopcount" . "~\n";
1014 // Revenue code from form
1016 $tmp = $ub04id[$os]; //$revcode[$prockey][revenue_code];
1018 $log .= "*** Error: Missing Revenue Code for " . $claim->cptKey($prockey) . "!\n";
1020 // Institutional Service Line.
1022 $out .= "SV2" . "*" . $tmp . // revenue code
1024 "*" . "HC:" . $claim->cptKey($prockey) . "*" . sprintf('%.2f', $claim->cptCharges($prockey)) . "*UN" . "*" . $claim->cptUnits($prockey) . "*" . "*" . "*";
1028 if (! $claim->cptCharges($prockey)) {
1029 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no charges!\n";
1032 // Segment SV5 (Durable Medical Equipment Service) omitted.
1033 // Segment PWK (Line Supplemental Information) omitted.
1034 // Segment PWK (Durable Medical Equipment Certificate of Medical Necessity Indicator) omitted.
1035 // Segment CR1 (Ambulance Transport Information) omitted.
1036 // Segment CR3 (Durable Medical Equipment Certification) omitted.
1037 // Segment CRC (Ambulance Certification) omitted.
1038 // Segment CRC (Hospice Employee Indicator) omitted.
1039 // Segment CRC (Condition Indicator / Durable Medical Equipment) omitted.
1043 $out .= "DTP" . // Date of Service. Needs to be when service preformed.
1044 "*" . "472" . "*" . "D8" . "*" . $ub04id[$dosos] . "~\n"; //$claim->serviceDate()
1046 $testnote = rtrim($claim->cptNotecodes($prockey));
1047 if (! empty($testnote)) {
1049 $out .= "NTE" . // Explain Unusual Circumstances.
1050 "*ADD" . "*" . $claim->cptNotecodes($prockey) . "~\n";
1053 // Segment DTP*471 (Prescription Date) omitted.
1054 // Segment DTP*607 (Revision/Recertification Date) omitted.
1055 // Segment DTP*463 (Begin Therapy Date) omitted.
1056 // Segment DTP*461 (Last Certification Date) omitted.
1057 // Segment DTP*304 (Last Seen Date) omitted.
1058 // Segment DTP (Test Date) omitted.
1059 // Segment DTP*011 (Shipped Date) omitted.
1060 // Segment DTP*455 (Last X-Ray Date) omitted.
1061 // Segment DTP*454 (Initial Treatment Date) omitted.
1062 // Segment QTY (Ambulance Patient Count) omitted.
1063 // Segment QTY (Obstetric Anesthesia Additional Units) omitted.
1064 // Segment MEA (Test Result) omitted.
1065 // Segment CN1 (Contract Information) omitted.
1066 // Segment REF*9B (Repriced Line Item Reference Number) omitted.
1067 // Segment REF*9D (Adjusted Repriced Line Item Reference Number) omitted.
1068 // Segment REF*G1 (Prior Authorization) omitted.
1069 // Segment REF*6R (Line Item Control Number) omitted.
1070 // (Really oughta have this for robust 835 posting!)
1071 // Segment REF*EW (Mammography Certification Number) omitted.
1072 // Segment REF*X4 (CLIA Number) omitted.
1073 // Segment REF*F4 (Referring CLIA Facility Identification) omitted.
1074 // Segment REF*BT (Immunization Batch Number) omitted.
1075 // Segment REF*9F (Referral Number) omitted.
1076 // Segment AMT*GT (Sales Tax Amount) omitted.
1077 // Segment AMT*F4 (Postage Claimed Amount) omitted.
1078 // Segment K3 (File Information) omitted.
1079 // Segment NTE (Line Note) omitted.
1080 // Segment NTE (Third Party Organization Notes) omitted.
1081 // Segment PS1 (Purchased Service Information) omitted.
1082 // Segment HCP (Line Pricing/Repricing Information) omitted.
1084 // Loop 2410, Drug Information. Medicaid insurers seem to want this
1085 // with HCPCS codes.
1087 $ndc = $claim->cptNDCID($prockey);
1091 $out .= "LIN" . // Drug Identification. Page 500+ (Addendum pg 71).
1092 "*" . // Per addendum, LIN01 is not used.
1097 if (!preg_match('/^\d\d\d\d\d-\d\d\d\d-\d\d$/', $ndc, $tmp) && !preg_match('/^\d{11}$/', $ndc)) {
1098 $log .= "*** NDC code '$ndc' has invalid format!\n";
1102 $out .= "CTP" . // Drug Pricing. Page 500+ (Addendum pg 74).
1106 "*" . $claim->cptNDCQuantity($prockey) .
1107 "*" . $claim->cptNDCUOM($prockey) .
1108 // Note: 5010 documents "ME" (Milligrams) as an additional unit of measure.
1112 // Segment REF (Prescription or Compound Drug Association Number) omitted.
1114 // Loop 2420A, Rendering Provider (service-specific). (Operating Physician Name for 837I)
1115 // Used if the rendering provider for this service line is different
1116 // from that in loop 2310B.
1118 if ($claim->providerNPI() != $claim->providerNPI($prockey)) {
1120 $out .= "NM1" . // Loop 2310B Rendering Provider
1123 "*" . $claim->providerLastName($prockey) .
1124 "*" . $claim->providerFirstName($prockey) .
1125 "*" . $claim->providerMiddleName($prockey) .
1128 if ($claim->providerNPI($prockey)) {
1131 "*" . $claim->providerNPI($prockey);
1133 $log .= "*** Rendering provider has no NPI.\n";
1137 if ($claim->providerTaxonomy($prockey)) {
1140 "*" . "PE" . // PErforming provider
1142 "*" . $claim->providerTaxonomy($prockey) .
1146 // Segment PRV*PE (Rendering Provider Specialty Information) omitted.
1147 // Segment REF (Rendering Provider Secondary Identification) omitted.
1148 // Segment NM1 (Purchased Service Provider Name) omitted.
1149 // Segment REF (Purchased Service Provider Secondary Identification) omitted.
1150 // Segment NM1,N3,N4 (Service Facility Location) omitted.
1151 // Segment REF (Service Facility Location Secondary Identification) omitted.
1152 // Segment NM1 (Supervising Provider Name) omitted.
1153 // Segment REF (Supervising Provider Secondary Identification) omitted.
1154 // Segment NM1,N3,N4 (Ordering Provider) omitted.
1155 // Segment REF (Ordering Provider Secondary Identification) omitted.
1156 // Segment PER (Ordering Provider Contact Information) omitted.
1157 // Segment NM1 (Referring Provider Name) omitted.
1158 // Segment REF (Referring Provider Secondary Identification) omitted.
1159 // Segments NM1*PW, N3, N4 (Ambulance Pick-Up Location) omitted.
1160 // Segments NM1*45, N3, N4 (Ambulance Drop-Off Location) omitted.
1162 // REF*1C is required here for the Medicare provider number if NPI was
1163 // specified in NM109. Not sure if other payers require anything here.
1164 if ($claim->providerNumberType($prockey) == "G2") {
1165 ++
$edicount; $out .= "REF" . "*" . $claim->providerNumberType($prockey) .
1166 "*" . $claim->providerNumber($prockey) . "~\n";
1168 } // provider exception
1170 // Loop 2430, adjudication by previous payers.
1172 for ($ins = 1; $ins < $claim->payerCount(); ++
$ins) {
1173 if ($claim->payerSequence($ins) > $claim->payerSequence()) {
1174 continue; // payer is future, not previous
1177 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($prockey));
1178 $aarr = $claim->payerAdjustments($ins, $claim->cptKey($prockey));
1180 if ($payerpaid[1] == 0 && ! count($aarr)) {
1181 $log .= "*** Procedure '" . $claim->cptKey($prockey) . "' has no payments or adjustments from previous payer!\n";
1186 $out .= "SVD" . // Service line adjudication. Page 554.
1187 "*" . $claim->payerID($ins) . "*" . $payerpaid[1] . "*HC:" . $claim->cptKey($prockey) . "*" . "*" . $claim->cptUnits($prockey) . "~\n";
1189 $tmpdate = $payerpaid[0];
1190 foreach ($aarr as $a) {
1192 $out .= "CAS" . // Previous payer's line level adjustments. Page 558.
1193 "*" . $a[1] . "*" . $a[2] . "*" . $a[3] . "~\n";
1201 $out .= "DTP" . // Previous payer's line adjustment date. Page 493/566.
1202 "*573" . "*D8" . "*$tmpdate" . "~\n";
1205 // Segment AMT*EAF (Remaining Patient Liability) omitted.
1206 // Segment LQ (Form Identification Code) omitted.
1207 // Segment FRM (Supporting Documentation) omitted.
1209 } // end this procedure
1212 $out .= "SE" . // SE Trailer
1213 "*$edicount" . "*0021" . "~\n";
1215 $out .= "GE" . // GE Trailer
1216 "*1" . "*1" . "~\n";
1218 $out .= "IEA" . // IEA Trailer
1219 "*1" . "*000000001" . "~\n";
1221 // Remove any trailing empty fields (delimiters) from each segment.
1222 $out = preg_replace('/\*+~/', '~', $out);