CCDA server fixups (#4356)
[openemr.git] / src / Billing / Hcfa1500.php
blobdf76180b14ad5a96217636f0d596d7cde94c0fd0
1 <?php
3 /* Hcfa1500 Class
5 * This program creates the HCFA 1500 claim form.
7 * @package OpenEMR
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Stephen Waite <stephen.waite@cmsvt.com>
10 * @copyright Copyright (c) 2011 Rod Roark <rod@sunsetsystems.com>
11 * @copyright Copyright (C) 2018 Stephen Waite <stephen.waite@cmsvt.com>
12 * @link https://www.open-emr.org
13 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
16 namespace OpenEMR\Billing;
18 use OpenEMR\Billing\Claim;
19 use OpenEMR\Billing\HCFAInfo;
21 class Hcfa1500
23 protected $hcfa_curr_line;
24 protected $hcfa_curr_col;
25 protected $hcfa_data;
26 protected $hcfa_proc_index;
27 /**
28 * Hcfa1500 constructor.
29 * @param int $hcfa_curr_line
30 * @param int $hcfa_curr_col
31 * @param type $hcfa_data
32 * @param int $hcfa_proc_index
34 public function __construct()
36 $this->hcfa_curr_line = 1;
37 $this->hcfa_curr_col = 1;
38 $this->hcfa_data = '';
39 $this->hcfa_proc_index = 0;
42 /**
43 * take the data element and place it at the correct coordinates on the page
45 * @global int $hcfa_curr_line
46 * @global int $hcfa_curr_col
47 * @global type $hcfa_data
48 * @param type $line
49 * @param type $col
50 * @param type $maxlen
51 * @param type $data
52 * @param type $strip regular expression for what to strip from the data. period and has are the defaults
53 * 02/12 version needs to include periods in the diagnoses hence the need to override
55 private function putHcfa($line, $col, $maxlen, $data, $strip = '/[.#]/')
57 if ($line < $this->hcfa_curr_line) {
58 die("Data item at ($line, $col) precedes current line $this->hcfa_curr_line and $data");
61 while ($this->hcfa_curr_line < $line) {
62 $this->hcfa_data .= "\n";
63 ++$this->hcfa_curr_line;
64 $this->hcfa_curr_col = 1;
67 if ($col < $this->hcfa_curr_col) {
68 die("Data item at ($line, $col) precedes current column.");
71 while ($this->hcfa_curr_col < $col) {
72 $this->hcfa_data .= " ";
73 ++$this->hcfa_curr_col;
76 $data = preg_replace($strip, '', strtoupper($data));
77 $len = min(strlen($data), $maxlen);
78 $this->hcfa_data .= substr($data, 0, $len);
79 $this->hcfa_curr_col += $len;
82 /**
83 * Process the diagnoses for a given claim. log any errors
85 * @param type $claim
86 * @param string $log
88 private function processDiagnoses0212($claim, &$log)
90 $hcfa_entries = array();
91 $diags = $claim->diagArray(false);
92 if ($claim->diagtype == 'ICD10') {
93 $icd_indicator = '0';
94 } else {
95 $icd_indicator = '9';
98 $hcfa_entries[] = new HCFAInfo(37, 42, 1, $icd_indicator);
100 // Box 22. Medicaid Resubmission Code and Original Ref. No.
101 $hcfa_entries[] = new HCFAInfo(38, 50, 10, $claim->medicaidResubmissionCode());
102 $hcfa_entries[] = new HCFAInfo(38, 62, 15, $claim->medicaidOriginalReference());
104 // Box 23. Prior Authorization Number
105 $hcfa_entries[] = new HCFAInfo(40, 50, 28, $claim->priorAuth());
107 $diag_count = 0;
108 foreach ($diags as $diag) {
109 if ($diag_count < 12) {
110 $this->addDiagnosis($hcfa_entries, $diag_count, $diag);
111 } else {
112 $log .= "***Too many diagnoses " . ($diag_count + 1) . ":" . $diag;
115 $diag_count++;
117 // Sort the entries to put them in the page base sequence.
118 usort($hcfa_entries, array('OpenEMR\Billing\HCFAInfo', 'cmpHcfaInfo'));
120 foreach ($hcfa_entries as $hcfa_entry) {
121 $this->putHcfa(
122 $hcfa_entry->getRow(),
123 $hcfa_entry->getColumn(),
124 $hcfa_entry->getWidth(),
125 $hcfa_entry->getInfo(),
126 '/#/'
131 * calculate where on the form a given diagnosis belongs and add it to the entries
133 * @param array $hcfa_entries
134 * @param type $number
135 * @param type $diag
137 private function addDiagnosis(&$hcfa_entries, $number, $diag)
140 * The diagnoses go across the page.
141 * Positioned
142 * A B C D
143 * E F G H
144 * I J K L
146 $column_num = ($number % 4);
147 $row_num = (int)($number / 4);
149 // First column is at location 3, each column is 13 wide
150 $col_pos = 3 + 13 * $column_num;
152 // First diagnosis row is 38
153 $strip = '/[.#]/';
154 $diag = preg_replace($strip, '', strtoupper($diag));
155 $row_pos = 38 + $row_num;
156 $hcfa_entries[] = new HCFAInfo($row_pos, $col_pos, 8, $diag);
159 public function genHcfa1500($pid, $encounter, &$log)
161 $this->hcfa_data = '';
162 $this->hcfa_proc_index = 0;
164 $today = time();
166 $claim = new Claim($pid, $encounter);
168 $log .= "Generating HCFA claim $pid-$encounter for " .
169 $claim->patientFirstName() . ' ' .
170 $claim->patientMiddleName() . ' ' .
171 $claim->patientLastName() . ' on ' .
172 date('Y-m-d H:i', $today) . ".\n";
174 while ($this->hcfa_proc_index < $claim->procCount()) {
175 if ($this->hcfa_proc_index) {
176 $this->hcfa_data .= "\014"; // append form feed for new page
179 $this->genHcfa1500Page($pid, $encounter, $log, $claim);
182 $log .= "\n";
183 return $this->hcfa_data;
186 private function genHcfa1500Page($pid, $encounter, &$log, $claim)
189 $this->hcfa_curr_line = 1;
190 $this->hcfa_curr_col = 1;
192 // According to:
193 // https://www.ngsmedicare.com/NGSMedicare/PartB/EducationandSupport/ToolsandMaterials/CMS_ClaimFormInst.aspx
194 // Medicare interprets sections 9 and 11 of the claim form in its own
195 // special way. This flag tells us to do that. However I'm not 100%
196 // sure that it applies nationwide, and if you find that it is not right
197 // for you then set it to false. -- Rod 2009-03-26
198 $new_medicare_logic = $claim->claimType() == 'MB';
200 // Payer name, attn, street.
201 $this->putHcfa(2, 41, 31, $claim->payerName());
202 $this->putHcfa(3, 41, 31, $claim->payerAttn());
203 $this->putHcfa(4, 41, 31, $claim->payerStreet());
205 // Payer city, state, zip.
206 $tmp = $claim->payerCity() ? ($claim->payerCity() . ', ') : '';
207 $this->putHcfa(5, 41, 31, $tmp . $claim->payerState() . ' ' . $claim->payerZip());
209 // Box 1. Insurance Type
210 // claimTypeRaw() gets the integer value from insurance_companies.ins_type_code.
211 // Previous version of this code called claimType() which maps ins_type_code to
212 // a 2-character code and that was not specific enough.
213 $ct = $claim->claimTypeRaw();
214 $tmpcol = 45; // Other
215 if ($ct == 2) {
216 $tmpcol = 1; // Medicare
217 } elseif ($ct == 3) {
218 $tmpcol = 8; // Medicaid
219 } elseif ($ct == 5) {
220 $tmpcol = 15; // TriCare (formerly CHAMPUS)
221 } elseif ($ct == 4) {
222 $tmpcol = 24; // Champus VA
223 } elseif ($ct == 6) {
224 $tmpcol = 31; // Group Health Plan (only BCBS?)
225 } elseif ($ct == 7) {
226 $tmpcol = 39; // FECA
229 $this->putHcfa(8, $tmpcol, 1, 'X');
231 // Box 1a. Insured's ID Number
232 $this->putHcfa(8, 50, 17, $claim->policyNumber());
234 // Box 2. Patient's Name
235 $tmp = $claim->patientLastName() . ', ' . $claim->patientFirstName();
236 if ($claim->patientMiddleName()) {
237 $tmp .= ', ' . substr($claim->patientMiddleName(), 0, 1);
240 $this->putHcfa(10, 1, 28, $tmp);
242 // Box 3. Patient's Birth Date and Sex
243 $tmp = $claim->patientDOB();
244 $this->putHcfa(10, 31, 2, substr($tmp, 4, 2));
245 $this->putHcfa(10, 34, 2, substr($tmp, 6, 2));
246 $this->putHcfa(10, 37, 4, substr($tmp, 0, 4));
247 $this->putHcfa(10, $claim->patientSex() == 'M' ? 42 : 47, 1, 'X');
249 // Box 4. Insured's Name
250 $tmp = $claim->insuredLastName() . ', ' . $claim->insuredFirstName();
251 if ($claim->insuredMiddleName()) {
252 $tmp .= ', ' . substr($claim->insuredMiddleName(), 0, 1);
255 $this->putHcfa(10, 50, 28, $tmp);
257 // Box 5. Patient's Address
258 $this->putHcfa(12, 1, 28, $claim->patientStreet());
260 // Box 6. Patient Relationship to Insured
261 $tmp = $claim->insuredRelationship();
262 $tmpcol = 47; // Other
263 if ($tmp === '18') {
264 $tmpcol = 33; // self
265 } elseif ($tmp === '01') {
266 $tmpcol = 38; // spouse
267 } elseif ($tmp === '19') {
268 $tmpcol = 42; // child
271 $this->putHcfa(12, $tmpcol, 1, 'X');
273 // Box 7. Insured's Address
274 $this->putHcfa(12, 50, 28, $claim->insuredStreet());
276 // Box 5 continued. Patient's City and State
277 $this->putHcfa(14, 1, 20, $claim->patientCity());
278 $this->putHcfa(14, 26, 2, $claim->patientState());
280 // Box 8. Reserved for NUCC Use in 02/12
282 // Box 7 continued. Insured's City and State
283 $this->putHcfa(14, 50, 20, $claim->insuredCity());
284 $this->putHcfa(14, 74, 2, $claim->insuredState());
286 // Box 5 continued. Patient's Zip Code and Telephone
287 $this->putHcfa(16, 1, 10, $claim->patientZip());
288 $tmp = $claim->patientPhone();
289 $this->putHcfa(16, 15, 3, substr($tmp, 0, 3));
290 $this->putHcfa(16, 19, 7, substr($tmp, 3));
292 // Box 7 continued. Insured's Zip Code and Telephone
293 $this->putHcfa(16, 50, 10, $claim->insuredZip());
294 $tmp = $claim->insuredPhone();
295 $this->putHcfa(16, 65, 3, substr($tmp, 0, 3));
296 $this->putHcfa(16, 69, 7, substr($tmp, 3));
298 // Box 9. Other Insured's Name
299 if ($new_medicare_logic) {
300 // TBD: Medigap stuff? How do we know if this is a Medigap transfer?
301 } else {
302 if ($claim->payerCount() > 1) {
303 $tmp = $claim->insuredLastName(1) . ', ' . $claim->insuredFirstName(1);
304 if ($claim->insuredMiddleName(1)) {
305 $tmp .= ', ' . substr($claim->insuredMiddleName(1), 0, 1);
308 $this->putHcfa(18, 1, 28, $tmp);
312 // Box 11. Insured's Group Number
313 if ($new_medicare_logic) {
314 // If this is Medicare secondary then we need the primary's policy number
315 // here, otherwise the word "NONE".
316 $tmp = $claim->payerSequence() == 'P' ? 'NONE' : $claim->policyNumber(1);
317 } else {
318 $tmp = $claim->groupNumber();
321 $this->putHcfa(18, 50, 30, $tmp);
323 // Box 9a. Other Insured's Policy or Group Number
324 if ($new_medicare_logic) {
325 // TBD: Medigap stuff?
326 } else {
327 if ($claim->payerCount() > 1) {
328 $this->putHcfa(20, 1, 28, $claim->policyNumber(1));
332 // Box 10a. Employment Related
333 $this->putHcfa(20, $claim->isRelatedEmployment() ? 35 : 41, 1, 'X');
335 // Box 11a. Insured's Birth Date and Sex
336 if ($new_medicare_logic) {
337 $tmpdob = $tmpsex = '';
338 if ($claim->payerSequence() != 'P') {
339 $tmpdob = $claim->insuredDOB(1);
340 $tmpsex = $claim->insuredSex(1);
342 } else {
343 $tmpdob = $claim->insuredDOB();
344 $tmpsex = $claim->insuredSex();
347 if ($tmpdob) {
348 $this->putHcfa(20, 53, 2, substr($tmpdob, 4, 2));
349 $this->putHcfa(20, 56, 2, substr($tmpdob, 6, 2));
350 $this->putHcfa(20, 59, 4, substr($tmpdob, 0, 4));
353 if ($tmpsex) {
354 $this->putHcfa(20, $tmpsex == 'M' ? 68 : 75, 1, 'X');
357 // Box 9b. Reserved for NUCC Use in 02/12
359 // Box 10b. Auto Accident
360 $this->putHcfa(22, $claim->isRelatedAuto() ? 35 : 41, 1, 'X');
361 if ($claim->isRelatedAuto()) {
362 $this->putHcfa(22, 45, 2, $claim->autoAccidentState());
365 // Box 11b. Insured's Employer/School Name
366 if ($new_medicare_logic) {
367 $tmp = $claim->payerSequence() == 'P' ? '' : $claim->groupName(1);
368 } else {
369 $tmp = $claim->groupName();
372 $this->putHcfa(22, 50, 30, $tmp);
374 // Box 9c. Reserved for NUCC Use in 02/12
376 // Box 10c. Other Accident
377 $this->putHcfa(24, $claim->isRelatedOther() ? 35 : 41, 1, 'X');
379 // Box 11c. Insurance Plan Name or Program Name
380 if ($new_medicare_logic) {
381 $tmp = '';
382 if ($claim->payerSequence() != 'P') {
383 $tmp = $claim->planName(1);
384 if (!$tmp) {
385 $tmp = $claim->payerName(1);
388 } else {
389 $tmp = $claim->planName();
392 $this->putHcfa(24, 50, 30, $tmp);
394 // Box 9d. Other Insurance Plan Name or Program Name
395 if ($new_medicare_logic) {
396 // TBD: Medigap stuff?
397 } else {
398 if ($claim->payerCount() > 1) {
399 $this->putHcfa(26, 1, 28, $claim->planName(1));
403 // Box 10d. Claim Codes medicaid_referral_code
405 if ($claim->epsdtFlag()) {
406 $this->putHcfa(26, 34, 2, $claim->medicaidReferralCode());
409 // Box 11d. Is There Another Health Benefit Plan
411 if (!$new_medicare_logic) {
412 $this->putHcfa(26, $claim->payerCount() > 1 ? 52 : 57, 1, 'X');
415 // Box 12. Patient's or Authorized Person's Signature
416 $this->putHcfa(29, 7, 17, 'Signature on File');
417 // Note: Date does not apply unless the person physically signs the form.
419 // Box 13. Insured's or Authorized Person's Signature
420 $this->putHcfa(29, 55, 17, 'Signature on File');
422 // Box 14. Date of Current Illness/Injury/Pregnancy
423 // this will cause onsetDate in Encounter summary to override misc billing so not perfect yet but fine for now
424 $tmp = ($claim->onsetDate()) ? $claim->onsetDate() : $claim->miscOnsetDate();
425 if (!empty($tmp)) {
426 $this->putHcfa(32, 2, 2, substr($tmp, 4, 2));
427 $this->putHcfa(32, 5, 2, substr($tmp, 6, 2));
428 $this->putHcfa(32, 8, 4, substr($tmp, 0, 4));
429 // Include Box 14 Qualifier
430 $this->putHcfa(32, 16, 3, $claim->box14Qualifier());
433 // Box 15. First Date of Same or Similar Illness, if applicable
434 $tmp = $claim->dateInitialTreatment();
435 if (!empty($tmp)) {
436 // Only include the Box 15 qualifier if using version 02/12 and there is a Box 15 date.
437 $this->putHcfa(32, 31, 3, $claim->box15Qualifier());
440 $this->putHcfa(32, 37, 2, substr($tmp, 4, 2));
441 $this->putHcfa(32, 40, 2, substr($tmp, 6, 2));
442 $this->putHcfa(32, 43, 4, substr($tmp, 0, 4));
444 // Box 16. Dates Patient Unable to Work in Current Occupation
445 if ($claim->isUnableToWork()) {
446 $tmp = $claim->offWorkFrom();
447 $this->putHcfa(32, 54, 2, substr($tmp, 4, 2));
448 $this->putHcfa(32, 57, 2, substr($tmp, 6, 2));
449 $this->putHcfa(32, 60, 4, substr($tmp, 0, 4));
450 $tmp = $claim->offWorkTo();
451 $this->putHcfa(32, 68, 2, substr($tmp, 4, 2));
452 $this->putHcfa(32, 71, 2, substr($tmp, 6, 2));
453 $this->putHcfa(32, 74, 4, substr($tmp, 0, 4));
456 // Referring provider stuff. Reports are that for primary care providers,
457 // Medicare forbids an entry here and other payers require one.
458 // There is still confusion over this.
459 if (
460 $claim->referrerLastName() || $claim->billingProviderLastName() &&
461 (empty($GLOBALS['MedicareReferrerIsRenderer']) || $claim->claimType() != 'MB')
463 // Box 17a. Referring Provider Alternate Identifier
464 // Commented this out because UPINs are obsolete, leaving the code as an
465 // example in case some other identifier needs to be supported.
466 /*****************************************************************
467 * if ($claim->referrerUPIN() && $claim->claimType() != 'MB') {
468 * $this->putHcfa(33, 30, 2, '1G');
469 * $this->putHcfa(33, 33, 15, $claim->referrerUPIN());
471 *****************************************************************/
472 if ($claim->claimType() == 'MC') {
473 $this->putHcfa(33, 30, 2, 'ZZ');
474 $this->putHcfa(33, 33, 14, $claim->referrerTaxonomy());
477 // Box 17. Name of Referring Provider or Other Source
478 if (strlen($claim->billingProviderLastName()) != 0) {
479 $tmp2 = $claim->billingProviderLastName() . ', ' . $claim->billingProviderFirstName();
480 if ($claim->billingProviderMiddleName()) {
481 $tmp2 .= ', ' . substr($claim->billingProviderMiddleName(), 0, 1);
484 $this->putHcfa(34, 1, 3, $claim->billing_options['provider_qualifier_code']);
485 $this->putHcfa(34, 4, 25, $tmp2);
486 if ($claim->billingProviderNPI()) {
487 $this->putHcfa(34, 33, 15, $claim->billingProviderNPI());
489 } else {
490 $tmp = $claim->referrerLastName() . ', ' . $claim->referrerFirstName();
491 if ($claim->referrerMiddleName()) {
492 $tmp .= ', ' . substr($claim->referrerMiddleName(), 0, 1);
495 $this->putHcfa(34, 1, 3, 'DN');
496 $this->putHcfa(34, 4, 25, $tmp);
497 if ($claim->referrerNPI()) {
498 $this->putHcfa(34, 33, 15, $claim->referrerNPI());
503 // Box 18. Hospitalization Dates Related to Current Services
504 if ($claim->isHospitalized()) {
505 $tmp = $claim->hospitalizedFrom();
506 $this->putHcfa(34, 54, 2, substr($tmp, 4, 2));
507 $this->putHcfa(34, 57, 2, substr($tmp, 6, 2));
508 $this->putHcfa(34, 60, 4, substr($tmp, 0, 4));
509 $tmp = $claim->hospitalizedTo();
510 $this->putHcfa(34, 68, 2, substr($tmp, 4, 2));
511 $this->putHcfa(34, 71, 2, substr($tmp, 6, 2));
512 $this->putHcfa(34, 74, 4, substr($tmp, 0, 4));
515 // Box 19. Reserved for Local Use
516 $this->putHcfa(36, 1, 48, $claim->additionalNotes());
518 // Box 20. Outside Lab
519 $this->putHcfa(36, $claim->isOutsideLab() ? 52 : 57, 1, 'X');
520 if ($claim->isOutsideLab()) {
521 // Note here that $this->putHcfa strips the decimal point, as required.
522 // We right-justify this amount (ending in col. 69).
523 $this->putHcfa(36, 63, 8, sprintf('%8s', $claim->outsideLabAmount()));
526 // Box 21. Diagnoses
527 $this->processDiagnoses0212($claim, $log);
529 $proccount = $claim->procCount(); // number of procedures
531 // Charges, adjustments and payments are accumulated by line item so that
532 // each page of a multi-page claim will stand alone. Payments include the
533 // co-pay for the first page only.
534 $clm_total_charges = 0;
535 $clm_amount_adjusted = 0;
536 $clm_amount_paid = $this->hcfa_proc_index ? 0 : $claim->patientPaidAmount();
538 // Procedure loop starts here.
539 for ($svccount = 0; $svccount < 6 && $this->hcfa_proc_index < $proccount; ++$this->hcfa_proc_index) {
540 $dia = $claim->diagIndexArray($this->hcfa_proc_index);
542 if (!$claim->cptCharges($this->hcfa_proc_index)) {
543 $log .= "*** Procedure '" . $claim->cptKey($this->hcfa_proc_index) .
544 "' has no charges!\n";
547 if (empty($dia)) {
548 $log .= "*** Procedure '" . $claim->cptKey($this->hcfa_proc_index) .
549 "' is not justified!\n";
552 $clm_total_charges += floatval($claim->cptCharges($this->hcfa_proc_index));
554 // Compute prior payments and "hard" adjustments.
555 for ($ins = 1; $ins < $claim->payerCount(); ++$ins) {
556 if ($claim->payerSequence($ins) > $claim->payerSequence()) {
557 continue; // skip future payers
560 $payerpaid = $claim->payerTotals($ins, $claim->cptKey($this->hcfa_proc_index));
561 $clm_amount_paid += $payerpaid[1];
562 $clm_amount_adjusted += $payerpaid[2];
565 ++$svccount;
566 $lino = $svccount * 2 + 41;
568 // Drug Information. Medicaid insurers want this with HCPCS codes.
570 $ndc = $claim->cptNDCID($this->hcfa_proc_index);
571 if ($ndc) {
572 if (preg_match('/^(\d\d\d\d\d)-(\d\d\d\d)-(\d\d)$/', $ndc, $tmp)) {
573 $ndc = $tmp[1] . $tmp[2] . $tmp[3];
574 } elseif (preg_match('/^\d{11}$/', $ndc)) {
575 } else {
576 $log .= "*** NDC code '$ndc' has invalid format!\n";
579 $this->putHcfa($lino, 1, 50, "N4$ndc " . $claim->cptNDCUOM($this->hcfa_proc_index) .
580 $claim->cptNDCQuantity($this->hcfa_proc_index));
583 //Note Codes.
584 $this->putHcfa($lino, 25, 7, $claim->cptNotecodes($this->hcfa_proc_index));
586 // 24i and 24j Top. ID Qualifier and Rendering Provider ID
587 if ($claim->supervisorNumber()) {
588 // If there is a supervising provider and that person has a
589 // payer-specific provider number, then we assume that the SP
590 // must be identified on the claim and this is how we do it
591 // (but the NPI of the actual rendering provider appears below).
592 // BCBS of TN indicated they want it this way. YMMV. -- Rod
593 $this->putHcfa($lino, 65, 2, $claim->supervisorNumberType());
594 $this->putHcfa($lino, 68, 10, $claim->supervisorNumber());
595 } elseif ($claim->providerNumber($this->hcfa_proc_index)) {
596 $this->putHcfa($lino, 65, 2, $claim->providerNumberType($this->hcfa_proc_index));
597 $this->putHcfa($lino, 68, 10, $claim->providerNumber($this->hcfa_proc_index));
598 } elseif ($claim->claimType() == 'MC') {
599 $this->putHcfa($lino, 65, 2, 'ZZ');
600 $this->putHcfa($lino, 68, 14, $claim->providerTaxonomy());
603 ++$lino;
605 // 24a. Date of Service
606 $tmp = $claim->serviceDate();
607 $this->putHcfa($lino, 1, 2, substr($tmp, 4, 2));
608 $this->putHcfa($lino, 4, 2, substr($tmp, 6, 2));
609 $this->putHcfa($lino, 7, 2, substr($tmp, 2, 2));
610 $this->putHcfa($lino, 10, 2, substr($tmp, 4, 2));
611 $this->putHcfa($lino, 13, 2, substr($tmp, 6, 2));
612 $this->putHcfa($lino, 16, 2, substr($tmp, 2, 2));
614 // 24b. Place of Service
615 $this->putHcfa($lino, 19, 2, $claim->facilityPOS());
617 // 24c. EMG
618 // Not currently supported.
620 // 24d. Procedures, Services or Supplies
621 $this->putHcfa($lino, 25, 7, $claim->cptCode($this->hcfa_proc_index));
622 // replace colon with space for printing
623 $this->putHcfa($lino, 33, 12, str_replace(':', ' ', $claim->cptModifier($this->hcfa_proc_index)));
625 // 24e. Diagnosis Pointer
626 $tmp = '';
627 foreach ($claim->diagIndexArray($this->hcfa_proc_index) as $value) {
628 $value = chr($value + 64);
629 $tmp .= $value;
632 $this->putHcfa($lino, 45, 4, $tmp);
634 // 24f. Charges
635 $this->putHcfa($lino, 50, 8, str_replace(
636 '.',
637 ' ',
638 sprintf('%8.2f', $claim->cptCharges($this->hcfa_proc_index))
641 // 24g. Days or Units
642 $this->putHcfa($lino, 59, 3, $claim->cptUnits($this->hcfa_proc_index));
644 // 24h. EPSDT Family Plan
646 if ($claim->epsdtFlag()) {
647 $this->putHcfa($lino, 63, 2, '03');
650 // 24j. Rendering Provider NPI
651 $this->putHcfa($lino, 68, 10, $claim->providerNPI($this->hcfa_proc_index));
654 // 25. Federal Tax ID Number
655 $this->putHcfa(56, 1, 15, $claim->billingFacilityETIN());
656 if ($claim->federalIdType() == 'SY') {
657 $this->putHcfa(56, 17, 1, 'X'); // The SSN checkbox
658 } else {
659 $this->putHcfa(56, 19, 1, 'X'); // The EIN checkbox
662 // 26. Patient's Account No.
663 // Instructions say hyphens are not allowed.
664 $this->putHcfa(56, 23, 15, "$pid-$encounter");
666 // 27. Accept Assignment
667 $this->putHcfa(56, $claim->billingFacilityAssignment() ? 38 : 43, 1, 'X');
669 // 28. Total Charge
670 $this->putHcfa(56, 52, 8, str_replace('.', ' ', sprintf('%8.2f', $clm_total_charges)));
671 if (!$clm_total_charges) {
672 $log .= "*** This claim has no charges!\n";
675 // 29. Amount Paid
676 $this->putHcfa(56, 62, 8, str_replace('.', ' ', sprintf('%8.2f', $clm_amount_paid)));
678 // 30. Reserved for NUCC use.
680 // 33. Billing Provider: Phone Number
681 $tmp = $claim->billingContactPhone();
682 $this->putHcfa(57, 66, 3, substr($tmp, 0, 3));
683 $this->putHcfa(57, 70, 3, substr($tmp, 3)); // slight adjustment for better look smw 030315
684 $this->putHcfa(57, 73, 1, '-');
685 $this->putHcfa(57, 74, 4, substr($tmp, 6));
687 // 32. Service Facility Location Information: Name
688 $this->putHcfa(58, 23, 25, $claim->facilityName());
690 // 33. Billing Provider: Name
691 if ($claim->federalIdType() == "SY") { // check entity type for NM*102 1 == person, 2 == non-person entity
692 $firstName = $claim->providerFirstName();
693 $lastName = $claim->providerLastName();
694 $middleName = $claim->providerMiddleName();
695 $suffixName = $claim->providerSuffixName();
696 $billingProviderName = $lastName . ", " . $firstName . ", " . $middleName . ", " . $suffixName;
697 $this->putHcfa(58, 50, 25, $billingProviderName);
698 } else {
699 $this->putHcfa(58, 50, 25, $claim->billingFacilityName());
702 // 32. Service Facility Location Information: Street
703 $this->putHcfa(59, 23, 25, $claim->facilityStreet());
705 // 33. Billing Provider: Name
706 $this->putHcfa(59, 50, 25, $claim->billingFacilityStreet());
708 // 31. Signature of Physician or Supplier
710 if ($GLOBALS['cms_1500_box_31_format'] == 0) {
711 $this->putHcfa(60, 1, 20, 'Signature on File');
712 } elseif ($GLOBALS['cms_1500_box_31_format'] == 1) {
713 $this->putHcfa(60, 1, 22, $claim->providerFirstName() . " " . $claim->providerLastName());
716 // 32. Service Facility Location Information: City State Zip
717 $tmp = $claim->facilityCity() ? ($claim->facilityCity() . ' ') : '';
718 $this->putHcfa(60, 23, 27, $tmp . $claim->facilityState() . ' ' .
719 $claim->facilityZip());
721 // 33. Billing Provider: City State Zip
722 $tmp = $claim->billingFacilityCity() ? ($claim->billingFacilityCity() . ' ') : '';
723 $this->putHcfa(60, 50, 27, $tmp . $claim->billingFacilityState() . ' ' .
724 $claim->billingFacilityZip());
726 // 31. Signature of Physician or Supplier: Date
727 if ($GLOBALS['cms_1500_box_31_date'] > 0) {
728 if ($GLOBALS['cms_1500_box_31_date'] == 1) {
729 $date_of_service = $claim->serviceDate();
730 $MDY = substr($date_of_service, 4, 2) .
731 " " . substr($date_of_service, 6, 2) .
732 " " . substr($date_of_service, 2, 2);
733 } elseif ($GLOBALS['cms_1500_box_31_date'] == 2) {
734 $MDY = date("m/d/y");
737 $this->putHcfa(61, 6, 10, $MDY);
740 // 32a. Service Facility NPI
741 $this->putHcfa(61, 23, 10, $claim->facilityNPI());
743 // 32b. Service Facility Other ID
744 // Note that Medicare does NOT want this any more.
745 if ($claim->providerGroupNumber()) {
746 $this->putHcfa(61, 36, 2, $claim->providerNumberType());
747 $this->putHcfa(61, 38, 11, $claim->providerGroupNumber());
750 // 33a. Billing Facility NPI
751 $this->putHcfa(61, 50, 10, $claim->billingFacilityNPI());
753 // 33b. Billing Facility Other ID
754 // Note that Medicare does NOT want this any more.
755 if ($claim->claimType() == 'MC') {
756 $this->putHcfa(61, 63, 2, 'ZZ');
757 $this->putHcfa(61, 65, 14, $claim->providerTaxonomy());
758 } elseif ($claim->providerGroupNumber() && $claim->claimType() != 'MB') {
759 $this->putHcfa(61, 63, 2, $claim->providerNumberType());
760 $this->putHcfa(61, 65, 14, $claim->providerGroupNumber());
763 // Put an extra line here for compatibility with old hcfa text generated form
764 $this->putHcfa(62, 1, 1, ' ');
765 // put a couple more in so that multiple claims correctly print through the text file download
766 $this->putHcfa(63, 1, 1, ' ');
767 $this->putHcfa(64, 1, 1, ' ');
768 return;