bug fix march continued (#1921)
[openemr.git] / interface / billing / sl_eob_process.php
blob07a90b1322f594b7e0ec5e24f9891b1f1c238f02
1 <?php
2 /**
3 * This processes X12 835 remittances and produces a report.
5 * @package OpenEMR
6 * @link http://www.open-emr.org
7 * @author Rod Roark <rod@sunsetsystems.com>
8 * @author Brady Miller <brady.g.miller@gmail.com>
9 * @copyright Copyright (c) 2006-2010 Rod Roark <rod@sunsetsystems.com>
10 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
11 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 // Buffer all output so we can archive it to a file.
16 ob_start();
18 require_once("../globals.php");
19 require_once("$srcdir/invoice_summary.inc.php");
20 require_once("$srcdir/sl_eob.inc.php");
21 require_once("$srcdir/parse_era.inc.php");
22 require_once("claim_status_codes.php");
23 require_once("adjustment_reason_codes.php");
24 require_once("remark_codes.php");
25 require_once("$srcdir/billing.inc");
27 $debug = $_GET['debug'] ? 1 : 0; // set to 1 for debugging mode
28 $paydate = parse_date($_GET['paydate']);
29 $encount = 0;
31 $last_ptname = '';
32 $last_invnumber = '';
33 $last_code = '';
34 $invoice_total = 0.00;
35 $InsertionId;//last inserted ID of
37 ///////////////////////// Assorted Functions /////////////////////////
39 function parse_date($date)
41 $date = substr(trim($date), 0, 10);
42 if (preg_match('/^(\d\d\d\d)\D*(\d\d)\D*(\d\d)$/', $date, $matches)) {
43 return $matches[1] . '-' . $matches[2] . '-' . $matches[3];
46 return '';
49 function writeMessageLine($bgcolor, $class, $description, $nl2br_process = "false")
51 $dline =
52 " <tr bgcolor='" . attr($bgcolor) . "'>\n" .
53 " <td class='" . attr($class) . "' colspan='4'>&nbsp;</td>\n";
54 if ($nl2br_process) {
55 $dline .= " <td class='" . attr($class) . "'>" . nl2br(text($description)) . "</td>\n";
56 } else {
57 $dline .= " <td class='" . attr($class) . "'>" . text($description) . "</td>\n";
59 $dline .=
60 " <td class='" . attr($class) . "' colspan='2'>&nbsp;</td>\n" .
61 " </tr>\n";
62 echo $dline;
65 function writeDetailLine(
66 $bgcolor,
67 $class,
68 $ptname,
69 $invnumber,
70 $code,
71 $date,
72 $description,
73 $amount,
74 $balance
75 ) {
77 global $last_ptname, $last_invnumber, $last_code;
78 if ($ptname == $last_ptname) {
79 $ptname = '&nbsp;';
80 } else {
81 $last_ptname = $ptname;
84 if ($invnumber == $last_invnumber) {
85 $invnumber = '&nbsp;';
86 } else {
87 $last_invnumber = $invnumber;
90 if ($code == $last_code) {
91 $code = '&nbsp;';
92 } else {
93 $last_code = $code;
96 if ($amount) {
97 $amount = sprintf("%.2f", $amount);
100 if ($balance) {
101 $balance = sprintf("%.2f", $balance);
104 $dline =
105 " <tr bgcolor='" . attr($bgcolor) . "'>\n" .
106 " <td class='" . attr($class) . "'>" . text($ptname) . "</td>\n" .
107 " <td class='" . attr($class) . "'>" . text($invnumber) . "</td>\n" .
108 " <td class='" . attr($class) . "'>" . text($code) . "</td>\n" .
109 " <td class='" . attr($class) . "'>" . text(oeFormatShortDate($date)) . "</td>\n" .
110 " <td class='" . attr($class) . "'>" . text($description) . "</td>\n" .
111 " <td class='" . attr($class) . "' align='right'>" . text(oeFormatMoney($amount)) . "</td>\n" .
112 " <td class='" . attr($class) . "' align='right'>" . text(oeFormatMoney($balance)) . "</td>\n" .
113 " </tr>\n";
114 echo $dline;
117 // This writes detail lines that were already in SQL-Ledger for a given
118 // charge item.
120 function writeOldDetail(&$prev, $ptname, $invnumber, $dos, $code, $bgcolor)
122 global $invoice_total;
123 // $prev['total'] = 0.00; // to accumulate total charges
124 ksort($prev['dtl']);
125 foreach ($prev['dtl'] as $dkey => $ddata) {
126 $ddate = substr($dkey, 0, 10);
127 $description = $ddata['src'] . $ddata['rsn'];
128 if ($ddate == ' ') { // this is the service item
129 $ddate = $dos;
130 $description = 'Service Item';
133 $amount = sprintf("%.2f", $ddata['chg'] - $ddata['pmt']);
134 $invoice_total = sprintf("%.2f", $invoice_total + $amount);
135 writeDetailLine(
136 $bgcolor,
137 'olddetail',
138 $ptname,
139 $invnumber,
140 $code,
141 $ddate,
142 $description,
143 $amount,
144 $invoice_total
149 // This is called back by parse_era() once per claim.
151 function era_callback_check(&$out)
153 global $InsertionId;//last inserted ID of
154 global $StringToEcho,$debug;
156 if ($_GET['original']=='original') {
157 $StringToEcho="<br/><br/><br/><br/><br/><br/>";
158 $StringToEcho.="<table border='1' cellpadding='0' cellspacing='0' width='750'>";
159 $StringToEcho.="<tr bgcolor='#cccccc'><td width='50'></td><td class='dehead' width='150' align='center'>" . xlt('Check Number') . "</td><td class='dehead' width='400' align='center'>" . xlt('Payee Name') . "</td><td class='dehead' width='150' align='center'>" . xlt('Check Amount') . "</td></tr>";
160 $WarningFlag=false;
161 for ($check_count=1; $check_count<=$out['check_count']; $check_count++) {
162 if ($check_count%2==1) {
163 $bgcolor='#ddddff';
164 } else {
165 $bgcolor='#ffdddd';
168 $rs=sqlQ("select reference from ar_session where reference=?", array($out['check_number'.$check_count]));
169 if (sqlNumRows($rs)>0) {
170 $bgcolor='#ff0000';
171 $WarningFlag=true;
174 $StringToEcho.="<tr bgcolor='" . attr($bgcolor) . "'>";
175 $StringToEcho.="<td><input type='checkbox' name='chk" . attr($out['check_number'.$check_count]) . "' value='" . attr($out['check_number'.$check_count]) . "'/></td>";
176 $StringToEcho.="<td>" . text($out['check_number'.$check_count]) . "</td>";
177 $StringToEcho.="<td>" . text($out['payee_name'.$check_count]) . "</td>";
178 $StringToEcho.="<td align='right'>" . text(number_format($out['check_amount'.$check_count], 2)) . "</td>";
179 $StringToEcho.="</tr>";
182 $StringToEcho.="<tr bgcolor='#cccccc'><td colspan='4' align='center'><input type='submit' name='CheckSubmit' value='Submit'/></td></tr>";
183 if ($WarningFlag==true) {
184 $StringToEcho.="<tr bgcolor='#ff0000'><td colspan='4' align='center'>" . xlt('Warning, Check Number already exist in the database') . "</td></tr>";
187 $StringToEcho.="</table>";
188 } else {
189 for ($check_count=1; $check_count<=$out['check_count']; $check_count++) {
190 $chk_num=$out['check_number'.$check_count];
191 $chk_num=str_replace(' ', '_', $chk_num);
192 if (isset($_REQUEST['chk'.$chk_num])) {
193 $check_date=$out['check_date'.$check_count]?$out['check_date'.$check_count]:$_REQUEST['paydate'];
194 $post_to_date=$_REQUEST['post_to_date']!=''?$_REQUEST['post_to_date']:date('Y-m-d');
195 $deposit_date=$_REQUEST['deposit_date']!=''?$_REQUEST['deposit_date']:date('Y-m-d');
196 $InsertionId[$out['check_number'.$check_count]]=arPostSession($_REQUEST['InsId'], $out['check_number'.$check_count], $out['check_date'.$check_count], $out['check_amount'.$check_count], $post_to_date, $deposit_date, $debug);
201 function era_callback(&$out)
203 global $encount, $debug, $claim_status_codes, $adjustment_reasons, $remark_codes;
204 global $invoice_total, $last_code, $paydate;
205 global $InsertionId;//last inserted ID of
208 // Some heading information.
209 $chk_123=$out['check_number'];
210 $chk_123=str_replace(' ', '_', $chk_123);
211 if (isset($_REQUEST['chk'.$chk_123])) {
212 if ($encount == 0) {
213 writeMessageLine(
214 '#ffffff',
215 'infdetail',
216 "Payer: " . $out['payer_name']
218 if ($debug) {
219 writeMessageLine(
220 '#ffffff',
221 'infdetail',
222 "WITHOUT UPDATE is selected; no changes will be applied."
227 $last_code = '';
228 $invoice_total = 0.00;
229 $bgcolor = (++$encount & 1) ? "#ddddff" : "#ffdddd";
230 list($pid, $encounter, $invnumber) = slInvoiceNumber($out);
232 // Get details, if we have them, for the invoice.
233 $inverror = true;
234 $codes = array();
235 if ($pid && $encounter) {
236 // Get invoice data into $arrow or $ferow.
237 $ferow = sqlQuery("SELECT e.*, p.fname, p.mname, p.lname " .
238 "FROM form_encounter AS e, patient_data AS p WHERE " .
239 "e.pid = ? AND e.encounter = ? AND ".
240 "p.pid = e.pid", array($pid, $encounter));
241 if (empty($ferow)) {
242 $pid = $encounter = 0;
243 $invnumber = $out['our_claim_id'];
244 } else {
245 $inverror = false;
246 $codes = ar_get_invoice_summary($pid, $encounter, true);
247 // $svcdate = substr($ferow['date'], 0, 10);
251 // Show the claim status.
252 $csc = $out['claim_status_code'];
253 $inslabel = 'Ins1';
254 if ($csc == '1' || $csc == '19') {
255 $inslabel = 'Ins1';
258 if ($csc == '2' || $csc == '20') {
259 $inslabel = 'Ins2';
262 if ($csc == '3' || $csc == '21') {
263 $inslabel = 'Ins3';
266 $primary = ($inslabel == 'Ins1');
267 writeMessageLine(
268 $bgcolor,
269 'infdetail',
270 "Claim status $csc: " . $claim_status_codes[$csc]
273 // Show an error message if the claim is missing or already posted.
274 if ($inverror) {
275 writeMessageLine(
276 $bgcolor,
277 'errdetail',
278 "The following claim is not in our database"
280 } else {
281 // Skip this test. Claims can get multiple CLPs from the same payer!
283 // $insdone = strtolower($arrow['shipvia']);
284 // if (strpos($insdone, 'ins1') !== false) {
285 // $inverror = true;
286 // writeMessageLine($bgcolor, 'errdetail',
287 // "Primary insurance EOB was already posted for the following claim");
288 // }
291 if ($csc == '4') {//Denial case, code is stored in the claims table for display in the billing manager screen with reason explained.
292 $inverror = true;
293 if (!$debug) {
294 if ($pid && $encounter) {
295 $code_value = '';
296 foreach ($out['svc'] as $svc) {
297 foreach ($svc['adj'] as $adj) {//Per code and modifier the reason will be showed in the billing manager.
298 $code_value .= $svc['code'].'_'.$svc['mod'].'_'.$adj['group_code'].'_'.$adj['reason_code'].',';
302 $code_value = substr($code_value, 0, -1);
303 //We store the reason code to display it with description in the billing manager screen.
304 //process_file is used as for the denial case file name will not be there, and extra field(to store reason) can be avoided.
305 updateClaim(true, $pid, $encounter, $_REQUEST['InsId'], substr($inslabel, 3), 7, 0, $code_value);
309 writeMessageLine(
310 $bgcolor,
311 'errdetail',
312 "Not posting adjustments for denied claims, please follow up manually!"
314 } else if ($csc == '22') {
315 $inverror = true;
316 writeMessageLine(
317 $bgcolor,
318 'errdetail',
319 "Payment reversals are not automated, please enter manually!"
323 if ($out['warnings']) {
324 writeMessageLine($bgcolor, 'infdetail', rtrim($out['warnings']), true);
327 // Simplify some claim attributes for cleaner code.
328 $service_date = parse_date($out['dos']);
329 $check_date = $paydate ? $paydate : parse_date($out['check_date']);
330 $production_date = $paydate ? $paydate : parse_date($out['production_date']);
332 $insurance_id = arGetPayerID($pid, $service_date, substr($inslabel, 3));
333 if (empty($ferow['lname'])) {
334 $patient_name = $out['patient_fname'] . ' ' . $out['patient_lname'];
335 } else {
336 $patient_name = $ferow['fname'] . ' ' . $ferow['lname'];
339 $error = $inverror;
341 // This loops once for each service item in this claim.
342 foreach ($out['svc'] as $svc) {
343 // Treat a modifier in the remit data as part of the procedure key.
344 // This key will then make its way into SQL-Ledger.
345 $codekey = $svc['code'];
346 if ($svc['mod']) {
347 $codekey .= ':' . $svc['mod'];
350 $prev = $codes[$codekey];
351 $codetype = ''; //will hold code type, if exists
353 // This reports detail lines already on file for this service item.
354 if ($prev) {
355 $codetype = $codes[$codekey]['code_type']; //store code type
356 writeOldDetail($prev, $patient_name, $invnumber, $service_date, $codekey, $bgcolor);
357 // Check for sanity in amount charged.
358 $prevchg = sprintf("%.2f", $prev['chg'] + $prev['adj']);
359 if ($prevchg != abs($svc['chg'])) {
360 writeMessageLine(
361 $bgcolor,
362 'errdetail',
363 "EOB charge amount " . $svc['chg'] . " for this code does not match our invoice"
365 $error = true;
368 // Check for already-existing primary remittance activity.
369 // Removed this check because it was not allowing for copays manually
370 // entered into the invoice under a non-copay billing code.
371 /****
372 if ((sprintf("%.2f",$prev['chg']) != sprintf("%.2f",$prev['bal']) ||
373 $prev['adj'] != 0) && $primary)
375 writeMessageLine($bgcolor, 'errdetail',
376 "This service item already has primary payments and/or adjustments!");
377 $error = true;
379 ****/
381 unset($codes[$codekey]);
382 } // If the service item is not in our database...
383 else {
384 // This is not an error. If we are not in error mode and not debugging,
385 // insert the service item into SL. Then display it (in green if it
386 // was inserted, or in red if we are in error mode).
387 $description = "CPT4:$codekey Added by $inslabel $production_date";
388 if (!$error && !$debug) {
389 arPostCharge(
390 $pid,
391 $encounter,
393 $svc['chg'],
395 $service_date,
396 $codekey,
397 $description,
398 $debug,
400 $codetype
402 $invoice_total += $svc['chg'];
405 $class = $error ? 'errdetail' : 'newdetail';
406 writeDetailLine(
407 $bgcolor,
408 $class,
409 $patient_name,
410 $invnumber,
411 $codekey,
412 $production_date,
413 $description,
414 $svc['chg'],
415 ($error ? '' : $invoice_total)
419 $class = $error ? 'errdetail' : 'newdetail';
421 // Report Allowed Amount.
422 if ($svc['allowed']) {
423 // A problem here is that some payers will include an adjustment
424 // reflecting the allowed amount, others not. So here we need to
425 // check if the adjustment exists, and if not then create it. We
426 // assume that any nonzero CO (Contractual Obligation) or PI
427 // (Payer Initiated) adjustment is good enough.
428 $contract_adj = sprintf("%.2f", $svc['chg'] - $svc['allowed']);
429 foreach ($svc['adj'] as $adj) {
430 if (($adj['group_code'] == 'CO' || $adj['group_code'] == 'PI') && $adj['amount'] != 0) {
431 $contract_adj = 0;
435 if ($contract_adj > 0) {
436 $svc['adj'][] = array('group_code' => 'CO', 'reason_code' => 'A2',
437 'amount' => $contract_adj);
440 writeMessageLine(
441 $bgcolor,
442 'infdetail',
443 'Allowed amount is ' . sprintf("%.2f", $svc['allowed'])
447 // Report miscellaneous remarks.
448 if ($svc['remark']) {
449 $rmk = $svc['remark'];
450 writeMessageLine($bgcolor, 'infdetail', "$rmk: " . $remark_codes[$rmk]);
453 // Post and report the payment for this service item from the ERA.
454 // By the way a 'Claim' level payment is probably going to be negative,
455 // i.e. a payment reversal.
456 if ($svc['paid']) {
457 if (!$error && !$debug) {
458 arPostPayment(
459 $pid,
460 $encounter,
461 $InsertionId[$out['check_number']],
462 $svc['paid'], //$InsertionId[$out['check_number']] gives the session id
463 $codekey,
464 substr($inslabel, 3),
465 $out['check_number'],
466 $debug,
468 $codetype
470 $invoice_total -= $svc['paid'];
473 $description = "$inslabel/" . $out['check_number'] . ' payment';
474 if ($svc['paid'] < 0) {
475 $description .= ' reversal';
478 writeDetailLine(
479 $bgcolor,
480 $class,
481 $patient_name,
482 $invnumber,
483 $codekey,
484 $check_date,
485 $description,
486 0 - $svc['paid'],
487 ($error ? '' : $invoice_total)
491 // Post and report adjustments from this ERA. Posted adjustment reasons
492 // must be 25 characters or less in order to fit on patient statements.
493 foreach ($svc['adj'] as $adj) {
494 $description = $adj['reason_code'] . ': ' . $adjustment_reasons[$adj['reason_code']];
495 if ($adj['group_code'] == 'PR' || !$primary) {
496 // Group code PR is Patient Responsibility. Enter these as zero
497 // adjustments to retain the note without crediting the claim.
498 if ($primary) {
499 /****
500 $reason = 'Pt resp: '; // Reasons should be 25 chars or less.
501 if ($adj['reason_code'] == '1') $reason = 'To deductible: ';
502 else if ($adj['reason_code'] == '2') $reason = 'Coinsurance: ';
503 else if ($adj['reason_code'] == '3') $reason = 'Co-pay: ';
504 ****/
505 $reason = "$inslabel ptresp: "; // Reasons should be 25 chars or less.
506 if ($adj['reason_code'] == '1') {
507 $reason = "$inslabel dedbl: ";
508 } else if ($adj['reason_code'] == '2') {
509 $reason = "$inslabel coins: ";
510 } else if ($adj['reason_code'] == '3') {
511 $reason = "$inslabel copay: ";
513 } // Non-primary insurance adjustments are garbage, either repeating
514 // the primary or are not adjustments at all. Report them as notes
515 // but do not post any amounts.
516 else {
517 $reason = "$inslabel note " . $adj['reason_code'] . ': ';
518 /****
519 $reason .= sprintf("%.2f", $adj['amount']);
520 ****/
523 $reason .= sprintf("%.2f", $adj['amount']);
524 // Post a zero-dollar adjustment just to save it as a comment.
525 if (!$error && !$debug) {
526 arPostAdjustment(
527 $pid,
528 $encounter,
529 $InsertionId[$out['check_number']],
531 $codekey, //$InsertionId[$out['check_number']] gives the session id
532 substr($inslabel, 3),
533 $reason,
534 $debug,
536 $codetype
540 writeMessageLine($bgcolor, $class, $description . ' ' .
541 sprintf("%.2f", $adj['amount']));
542 } // Other group codes for primary insurance are real adjustments.
543 else {
544 if (!$error && !$debug) {
545 arPostAdjustment(
546 $pid,
547 $encounter,
548 $InsertionId[$out['check_number']],
549 $adj['amount'], //$InsertionId[$out['check_number']] gives the session id
550 $codekey,
551 substr($inslabel, 3),
552 "Adjust code " . $adj['reason_code'],
553 $debug,
555 $codetype
557 $invoice_total -= $adj['amount'];
560 writeDetailLine(
561 $bgcolor,
562 $class,
563 $patient_name,
564 $invnumber,
565 $codekey,
566 $production_date,
567 $description,
568 0 - $adj['amount'],
569 ($error ? '' : $invoice_total)
573 } // End of service item
575 // Report any existing service items not mentioned in the ERA, and
576 // determine if any of them are still missing an insurance response
577 // (if so, then insurance is not yet done with the claim).
578 $insurance_done = true;
579 foreach ($codes as $code => $prev) {
580 // writeOldDetail($prev, $arrow['name'], $invnumber, $service_date, $code, $bgcolor);
581 writeOldDetail($prev, $patient_name, $invnumber, $service_date, $code, $bgcolor);
582 $got_response = false;
583 foreach ($prev['dtl'] as $ddata) {
584 if ($ddata['pmt'] || $ddata['rsn']) {
585 $got_response = true;
589 if (!$got_response) {
590 $insurance_done = false;
594 // Cleanup: If all is well, mark Ins<x> done and check for secondary billing.
595 if (!$error && !$debug && $insurance_done) {
596 $level_done = 0 + substr($inslabel, 3);
598 if ($out['crossover']==1) {//Automatic forward case.So need not again bill from the billing manager screen.
599 sqlStatement("UPDATE form_encounter " .
600 "SET last_level_closed = ?,last_level_billed=? WHERE " .
601 "pid = ? AND encounter = ?", array($level_done, $level_done, $pid, $encounter));
602 writeMessageLine(
603 $bgcolor,
604 'infdetail',
605 'This claim is processed by Insurance '.$level_done.' and automatically forwarded to Insurance '.($level_done+1) .' for processing. '
607 } else {
608 sqlStatement("UPDATE form_encounter " .
609 "SET last_level_closed = ? WHERE " .
610 "pid = ? AND encounter = ?", array($level_done, $pid, $encounter));
613 // Check for secondary insurance.
614 if ($primary && arGetPayerID($pid, $service_date, 2)) {
615 arSetupSecondary($pid, $encounter, $debug, $out['crossover']);
617 if ($out['crossover']<>1) {
618 writeMessageLine(
619 $bgcolor,
620 'infdetail',
621 'This claim is now re-queued for secondary paper billing'
629 /////////////////////////// End Functions ////////////////////////////
631 $info_msg = "";
633 if (!verifyCsrfToken($_GET["csrf_token_form"])) {
634 csrfNotVerified();
637 $eraname = $_GET['eraname'];
639 if (! $eraname) {
640 die(xlt("You cannot access this page directly."));
643 // Open the output file early so that in case it fails, we do not post a
644 // bunch of stuff without saving the report. Also be sure to retain any old
645 // report files. Do not save the report if this is a no-update situation.
647 if (!$debug) {
648 $nameprefix = $GLOBALS['OE_SITE_DIR'] . "/era/$eraname";
649 $namesuffix = '';
650 for ($i = 1; is_file("$nameprefix$namesuffix.html"); ++$i) {
651 $namesuffix = "_$i";
654 $fnreport = "$nameprefix$namesuffix.html";
655 $fhreport = fopen($fnreport, 'w');
656 if (!$fhreport) {
657 die(xlt("Cannot create") . " '" . text($fnreport) . "'");
662 <html>
663 <head>
664 <?php html_header_show();?>
665 <link rel=stylesheet href="<?php echo $css_header;?>" type="text/css">
666 <style type="text/css">
667 body { font-family:sans-serif; font-size:8pt; font-weight:normal }
668 .dehead { color:#000000; font-family:sans-serif; font-size:9pt; font-weight:bold }
669 .olddetail { color:#000000; font-family:sans-serif; font-size:9pt; font-weight:normal }
670 .newdetail { color:#00dd00; font-family:sans-serif; font-size:9pt; font-weight:normal }
671 .errdetail { color:#dd0000; font-family:sans-serif; font-size:9pt; font-weight:normal }
672 .infdetail { color:#0000ff; font-family:sans-serif; font-size:9pt; font-weight:normal }
673 </style>
674 <title><?php echo xlt('EOB Posting - Electronic Remittances')?></title>
675 <script language="JavaScript">
676 </script>
677 </head>
678 <body leftmargin='0' topmargin='0' marginwidth='0' marginheight='0'>
679 <form action="sl_eob_process.php" method="get" >
680 <input type="hidden" name="csrf_token_form" value="<?php echo attr(collectCsrfToken()); ?>" />
682 <center>
683 <?php
684 if ($_GET['original']=='original') {
685 $alertmsg = parse_era_for_check($GLOBALS['OE_SITE_DIR'] . "/era/$eraname.edi", 'era_callback');
686 echo $StringToEcho;
687 } else {
689 <table border='0' cellpadding='2' cellspacing='0' width='100%'>
691 <tr bgcolor="#cccccc">
692 <td class="dehead">
693 <?php echo xlt('Patient'); ?>
694 </td>
695 <td class="dehead">
696 <?php echo xlt('Invoice'); ?>
697 </td>
698 <td class="dehead">
699 <?php echo xlt('Code'); ?>
700 </td>
701 <td class="dehead">
702 <?php echo xlt('Date'); ?>
703 </td>
704 <td class="dehead">
705 <?php echo xlt('Description'); ?>
706 </td>
707 <td class="dehead" align="right">
708 <?php echo xlt('Amount'); ?>&nbsp;
709 </td>
710 <td class="dehead" align="right">
711 <?php echo xl('Balance'); ?>&nbsp;
712 </td>
713 </tr>
715 <?php
716 global $InsertionId;
718 $eraname=$_REQUEST['eraname'];
719 $alertmsg = parse_era_for_check($GLOBALS['OE_SITE_DIR'] . "/era/$eraname.edi");
720 $alertmsg = parse_era($GLOBALS['OE_SITE_DIR'] . "/era/$eraname.edi", 'era_callback');
721 if (!$debug) {
722 $StringIssue=xl("Total Distribution for following check number is not full").': ';
723 $StringPrint='No';
724 foreach ($InsertionId as $key => $value) {
725 $rs= sqlQ("select pay_total from ar_session where session_id=?", array($value));
726 $row=sqlFetchArray($rs);
727 $pay_total=$row['pay_total'];
728 $rs= sqlQ("select sum(pay_amount) sum_pay_amount from ar_activity where session_id=?", array($value));
729 $row=sqlFetchArray($rs);
730 $pay_amount=$row['sum_pay_amount'];
732 if (($pay_total-$pay_amount)<>0) {
733 $StringIssue.=$key.' ';
734 $StringPrint='Yes';
738 if ($StringPrint=='Yes') {
739 echo "<script>alert('" . addslashes($StringIssue) . "')</script>";
745 </table>
746 <?php
749 </center>
750 <script language="JavaScript">
751 <?php
752 if ($alertmsg) {
753 echo " alert('" . addslashes($alertmsg) . "');\n";
756 </script>
757 <input type="hidden" name="paydate" value="<?php echo attr(DateToYYYYMMDD($_REQUEST['paydate'])); ?>" />
758 <input type="hidden" name="post_to_date" value="<?php echo attr(DateToYYYYMMDD($_REQUEST['post_to_date'])); ?>" />
759 <input type="hidden" name="deposit_date" value="<?php echo attr(DateToYYYYMMDD($_REQUEST['deposit_date'])); ?>" />
760 <input type="hidden" name="debug" value="<?php echo attr($_REQUEST['debug']); ?>" />
761 <input type="hidden" name="InsId" value="<?php echo attr($_REQUEST['InsId']); ?>" />
762 <input type="hidden" name="eraname" value="<?php echo attr($eraname); ?>" />
763 </form>
764 </body>
765 </html>
766 <?php
767 // Save all of this script's output to a report file.
768 if (!$debug) {
769 fwrite($fhreport, ob_get_contents());
770 fclose($fhreport);
773 ob_end_flush();