6 * (TLH) Added payor,provider,fixed cvs download to included selected fields
7 * (TLH) Added ability to download selected invoices only or all for patient
10 * @link https://www.open-emr.org
11 * @author Rod Roark <rod@sunsetsystems.com>
12 * @author Terry Hill <terry@lillysystems.com>
13 * @author Brady Miller <brady.g.miller@gmail.com>
14 * @author Stephen Waite <stephen.waite@cmsvt.com>
15 * @author Sherwin Gaddis <sherwingaddis@gmail.com>
16 * @copyright Copyright (c) 2006-2020 Rod Roark <rod@sunsetsystems.com>
17 * @copyright Copyright (c) 2015 Terry Hill <terry@lillysystems.com>
18 * @copyright Copyright (c) 2017-2018 Brady Miller <brady.g.miller@gmail.com>
19 * @copyright Copyright (c) 2019 Stephen Waite <stephen.waite@cmsvt.com>
20 * @copyright Copyright (c) 2019 Sherwin Gaddis <sherwingaddis@gmail.com>
21 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
24 require_once("../globals.php");
25 require_once("../../library/patient.inc");
26 require_once "$srcdir/options.inc.php";
28 use OpenEMR\Billing\InvoiceSummary
;
29 use OpenEMR\Billing\SLEOB
;
30 use OpenEMR\Common\Csrf\CsrfUtils
;
31 use OpenEMR\Core\Header
;
32 use OpenEMR\Common\Acl\AclMain
;
35 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
36 CsrfUtils
::csrfNotVerified();
40 if (!AclMain
::aclCheckCore('acct', 'rep_a')) {
41 die(xl("Unauthorized access."));
46 $export_patient_count = 0;
49 $form_date = (isset($_POST['form_date'])) ?
DateToYYYYMMDD($_POST['form_date']) : "";
50 $form_to_date = (isset($_POST['form_to_date'])) ?
DateToYYYYMMDD($_POST['form_to_date']) : "";
51 $form_category = $_POST['form_category'] ??
null;
52 $is_ins_summary = $form_category == 'Ins Summary';
53 $is_due_ins = ($form_category == 'Due Ins') ||
$is_ins_summary;
54 $is_due_pt = $form_category == 'Due Pt';
55 $is_all = $form_category == 'All';
56 $is_ageby_lad = strpos(($_POST['form_ageby'] ??
''), 'Last') !== false;
57 $form_facility = $_POST['form_facility'] ??
null;
58 $form_provider = $_POST['form_provider'] ??
null;
59 $form_payer_id = $_POST['form_payer_id'] ??
null;
60 $form_page_y = $_POST['form_page_y'] ??
'';
61 $form_offset_y = $_POST['form_offset_y'] ??
'';
62 $form_y = $_POST['form_y'] ??
'';
64 if (!empty($_POST['form_refresh']) ||
!empty($_POST['form_export']) ||
!empty($_POST['form_csvexport'])) {
65 if ($is_ins_summary) {
68 $form_cb_pubpid = false;
69 $form_cb_adate = false;
70 $form_cb_policy = false;
71 $form_cb_phone = false;
72 $form_cb_city = false;
73 $form_cb_ins1 = false;
74 $form_cb_referrer = false;
75 $form_cb_idays = false;
78 $form_cb_ssn = (!empty($_POST['form_cb_ssn'])) ?
true : false;
79 $form_cb_dob = (!empty($_POST['form_cb_dob'])) ?
true : false;
80 $form_cb_pubpid = (!empty($_POST['form_cb_pubpid'])) ?
true : false;
81 $form_cb_adate = (!empty($_POST['form_cb_adate'])) ?
true : false;
82 $form_cb_policy = (!empty($_POST['form_cb_policy'])) ?
true : false;
83 $form_cb_phone = (!empty($_POST['form_cb_phone'])) ?
true : false;
84 $form_cb_city = (!empty($_POST['form_cb_city'])) ?
true : false;
85 $form_cb_ins1 = (!empty($_POST['form_cb_ins1'])) ?
true : false;
86 $form_cb_referrer = (!empty($_POST['form_cb_referrer'])) ?
true : false;
87 $form_cb_idays = (!empty($_POST['form_cb_idays'])) ?
true : false;
88 $form_cb_err = (!empty($_POST['form_cb_err'])) ?
true : false;
93 $form_cb_pubpid = false;
94 $form_cb_adate = false;
95 $form_cb_policy = false;
96 $form_cb_phone = true;
97 $form_cb_city = false;
98 $form_cb_ins1 = false;
99 $form_cb_referrer = false;
100 $form_cb_idays = false;
101 $form_cb_err = false;
104 $form_age_cols = (int) ($_POST['form_age_cols'] ??
null);
105 $form_age_inc = (int) ($_POST['form_age_inc'] ??
null);
106 if ($form_age_cols > 0 && $form_age_cols < 50) {
107 if ($form_age_inc <= 0) {
115 $initial_colspan = 1;
128 if ($form_cb_pubpid) {
132 if ($form_cb_policy) {
136 if ($form_cb_phone) {
148 if ($form_cb_referrer) {
152 if ($form_provider) {
156 if ($form_payer_id) {
160 $final_colspan = $form_cb_adate ?
6 : 5;
161 $form_cb_with_debt = (!empty($_POST['form_cb_with_debt'])) ?
true : false;
162 $grand_total_charges = 0;
163 $grand_total_adjustments = 0;
164 $grand_total_paid = 0;
165 $grand_total_agedbal = array();
166 for ($c = 0; $c < $form_age_cols; ++
$c) {
167 $grand_total_agedbal[$c] = 0;
171 function bucks($amount)
174 return oeFormatMoney($amount); // was printf("%.2f", $amount);
178 function endPatient($ptrow)
180 global $export_patient_count, $export_dollars, $bgcolor;
181 global $grand_total_charges, $grand_total_adjustments, $grand_total_paid;
182 global $grand_total_agedbal, $is_due_ins, $form_age_cols;
183 global $initial_colspan, $final_colspan, $form_cb_idays, $form_cb_err;
185 if (!$ptrow['pid']) {
189 $pt_balance = $ptrow['amount'] - $ptrow['paid'];
191 if ($_POST['form_export']) {
192 // This is a fixed-length format used by Transworld Systems. Your
193 // needs will surely be different, so consider this just an example.
195 echo "1896H"; // client number goes here
196 echo "000"; // filler
197 echo sprintf("%-30s", substr($ptrow['ptname'], 0, 30));
198 echo sprintf("%-30s", " ");
199 echo sprintf("%-30s", substr($ptrow['address1'], 0, 30));
200 echo sprintf("%-15s", substr($ptrow['city'], 0, 15));
201 echo sprintf("%-2s", substr($ptrow['state'], 0, 2));
202 echo sprintf("%-5s", $ptrow['zipcode'] ?
substr($ptrow['zipcode'], 0, 5) : '00000');
203 echo "1"; // service code
204 echo sprintf("%010.0f", $ptrow['pid']); // transmittal number = patient id
206 echo sprintf("%-15s", substr($ptrow['ss'], 0, 15));
207 echo substr($ptrow['dos'], 5, 2) . substr($ptrow['dos'], 8, 2) . substr($ptrow['dos'], 2, 2);
208 echo sprintf("%08.0f", $pt_balance * 100);
209 echo sprintf("%-9s\n", " ");
211 if (!$_POST['form_without']) {
212 sqlStatement("UPDATE patient_data SET " .
213 "billing_note = CONCAT('IN COLLECTIONS " . date("Y-m-d") . "', billing_note) " .
214 "WHERE pid = ? ", array($ptrow['pid']));
217 $export_patient_count +
= 1;
218 $export_dollars +
= $pt_balance;
219 } elseif ($_POST['form_csvexport']) {
220 $export_patient_count +
= 1;
221 $export_dollars +
= $pt_balance;
223 if ($ptrow['count'] > 1) {
224 echo " <tr bgcolor='" . attr($bgcolor) . "'>\n";
225 /***************************************************************
226 echo " <td class='detail' colspan='$initial_colspan'>";
227 echo " </td>\n";
228 echo " <td class='detotal' colspan='$final_colspan'> Total Patient Balance:</td>\n";
229 ***************************************************************/
230 echo " <td class='detotal' colspan='" . attr(($initial_colspan +
$final_colspan)) .
231 "'> " . xlt('Total Patient Balance') . ":</td>\n";
232 /**************************************************************/
233 if ($form_age_cols) {
234 for ($c = 0; $c < $form_age_cols; ++
$c) {
235 echo " <td class='detotal' align='left'> " .
236 text(oeFormatMoney($ptrow['agedbal'][$c])) . " </td>\n";
239 echo " <td class='detotal' align='left'> " .
240 text(oeFormatMoney($pt_balance)) . " </td>\n";
243 if ($form_cb_idays) {
244 echo " <td class='detail'> </td>\n";
247 echo " <td class='detail' colspan='2'> </td>\n";
249 echo " <td class='detail'> </td>\n";
256 $grand_total_charges +
= $ptrow['charges'];
257 $grand_total_adjustments +
= $ptrow['adjustments'];
258 $grand_total_paid +
= $ptrow['paid'];
259 for ($c = 0; $c < $form_age_cols; ++
$c) {
260 $grand_total_agedbal[$c] +
= ($ptrow['agedbal'][$c] ??
null);
264 function endInsurance($insrow)
266 global $export_patient_count, $export_dollars, $bgcolor;
267 global $grand_total_charges, $grand_total_adjustments, $grand_total_paid;
268 global $grand_total_agedbal, $is_due_ins, $form_age_cols;
269 global $initial_colspan, $form_cb_idays, $form_cb_err;
270 if (!$insrow['pid']) {
274 $ins_balance = $insrow['amount'] - $insrow['paid'];
275 if ($_POST['form_export'] ||
$_POST['form_csvexport']) {
276 // No exporting of insurance summaries.
277 $export_patient_count +
= 1;
278 $export_dollars +
= $ins_balance;
280 echo " <tr bgcolor='" . attr($bgcolor) . "'>\n";
281 echo " <td class='detail'>" . text($insrow['insname']) . "</td>\n";
282 echo " <td class='detotal' align='left'> " .
283 text(oeFormatMoney($insrow['charges'])) . " </td>\n";
284 echo " <td class='detotal' align='left'> " .
285 text(oeFormatMoney($insrow['adjustments'])) . " </td>\n";
286 echo " <td class='detotal' align='left'> " .
287 text(oeFormatMoney($insrow['paid'])) . " </td>\n";
288 if ($form_age_cols) {
289 for ($c = 0; $c < $form_age_cols; ++
$c) {
290 echo " <td class='detotal' align='left'> " .
291 text(oeFormatMoney($insrow['agedbal'][$c])) . " </td>\n";
294 echo " <td class='detotal' align='left'> " .
295 text(oeFormatMoney($ins_balance)) . " </td>\n";
301 $grand_total_charges +
= $insrow['charges'];
302 $grand_total_adjustments +
= $insrow['adjustments'];
303 $grand_total_paid +
= $insrow['paid'];
304 for ($c = 0; $c < $form_age_cols; ++
$c) {
305 $grand_total_agedbal[$c] +
= $insrow['agedbal'][$c];
309 function getInsName($payerid)
311 $tmp = sqlQuery("SELECT name FROM insurance_companies WHERE id = ? ", array($payerid));
315 // In the case of CSV export only, a download will be forced.
316 if (!empty($_POST['form_csvexport'])) {
317 header("Pragma: public");
318 header("Expires: 0");
319 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
320 header("Content-Type: application/force-download");
321 header("Content-Disposition: attachment; filename=collections_report.csv");
322 header("Content-Description: File Transfer");
328 <title
><?php
echo xlt('Collections Report')?
></title
>
330 <?php Header
::setupHeader(['datetime-picker', 'report-helper']); ?
>
338 #report_parameters_daterange {
347 /* specifically exclude some from the screen */
349 #report_parameters_daterange {
357 function reSubmit() {
358 $
("#form_refresh").attr("value","true");
359 $
("#form_csvexport").val("");
360 $
("#theform").submit();
362 // open dialog to edit an invoice w/o opening encounter.
363 function editInvoice(e
, id
) {
366 $
("#form_page_y").val(e
.pageY
);
367 $
("#form_offset_y").val(e
.offsetY
);
368 $
("#form_y").val(e
.y
);
369 let url
= './../billing/sl_eob_invoice.php?id=' +
encodeURIComponent(id
);
370 dlgopen(url
,'','modal-lg',750,false,'', {
376 let Y
= parseFloat($
("#form_page_y").val()) - parseFloat($
("#form_offset_y").val()) - parseFloat($
("#form_y").val());
377 $
("html, body").animate({scrollTop
: Y
}, 800);
381 oeFixedHeaderSetup(document
.getElementById('mymaintable'));
382 var win
= top
.printLogSetup ? top
: opener
.top
;
383 win
.printLogSetup(document
.getElementById('printbutton'));
385 $
('.datepicker').datetimepicker({
386 <?php
$datetimepicker_timepicker = false; ?
>
387 <?php
$datetimepicker_showseconds = false; ?
>
388 <?php
$datetimepicker_formatInput = true; ?
>
389 <?php
require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?
>
390 <?php
// can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
394 function checkAll(checked
) {
395 var f
= document
.forms
[0];
396 for (var i
= 0; i
< f
.elements
.length
; ++i
) {
397 var ename
= f
.elements
[i
].name
;
398 if (ename
.indexOf('form_cb[') == 0)
399 f
.elements
[i
].checked
= checked
;
406 <body
class="body_top">
408 <span
class='title'><?php
echo xlt('Report'); ?
> - <?php
echo xlt('Collections'); ?
></span
>
410 <form method
='post' action
='collections_report.php' enctype
='multipart/form-data' id
='theform' onsubmit
='return top.restoreSession()'>
411 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
413 <div id
="report_parameters">
415 <input type
='hidden' name
='form_refresh' id
='form_refresh' value
=''/>
416 <input type
='hidden' name
='form_export' id
='form_export' value
=''/>
417 <input type
='hidden' name
='form_csvexport' id
='form_csvexport' value
=''/>
418 <input type
='hidden' name
='form_page_y' id
='form_page_y' value
='<?php echo attr($form_page_y); ?>'/>
419 <input type
='hidden' name
='form_offset_y' id
='form_offset_y' value
='<?php echo attr($form_offset_y); ?>'/>
420 <input type
='hidden' name
='form_y' id
='form_y' value
='<?php echo attr($form_y); ?>'/>
425 <div style
='float:left'>
429 <td
class='col-form-label'>
432 <td
><?php
echo xlt('Displayed Columns') ?
>:</td
>
436 <label
><input type
='checkbox' name
='form_cb_ssn'<?php
echo ($form_cb_ssn) ?
' checked' : ''; ?
>>
437 <?php
echo xlt('SSN') ?
> 
;</label
>
440 <label
><input type
='checkbox' name
='form_cb_dob'<?php
echo ($form_cb_dob) ?
' checked' : ''; ?
>>
441 <?php
echo xlt('DOB') ?
> 
;</label
>
444 <label
><input type
='checkbox' name
='form_cb_pubpid'<?php
echo ($form_cb_pubpid) ?
' checked' : ''; ?
>>
445 <?php
echo xlt('ID') ?
> 
;</label
>
448 <label
><input type
='checkbox' name
='form_cb_policy'<?php
echo ($form_cb_policy) ?
' checked' : ''; ?
>>
449 <?php
echo xlt('Policy') ?
> 
;</label
>
452 <label
><input type
='checkbox' name
='form_cb_phone'<?php
echo ($form_cb_phone) ?
' checked' : ''; ?
>>
453 <?php
echo xlt('Phone') ?
> 
;</label
>
456 <label
><input type
='checkbox' name
='form_cb_city'<?php
echo ($form_cb_city) ?
' checked' : ''; ?
>>
457 <?php
echo xlt('City') ?
> 
;</label
>
462 <label
><input type
='checkbox' name
='form_cb_ins1'<?php
echo ($form_cb_ins1) ?
' checked' : ''; ?
>>
463 <?php
echo xlt('Primary Ins') ?
> 
;</label
>
466 <label
><input type
='checkbox' name
='form_cb_referrer'<?php
echo ($form_cb_referrer) ?
' checked' : ''; ?
>>
467 <?php
echo xlt('Referrer') ?
> 
;</label
>
470 <label
><input type
='checkbox' name
='form_cb_adate'<?php
echo ($form_cb_adate) ?
' checked' : ''; ?
>>
471 <?php
echo xlt('Act Date') ?
> 
;</label
>
474 <label
><input type
='checkbox' name
='form_cb_idays'<?php
echo ($form_cb_idays) ?
' checked' : ''; ?
>>
475 <?php
echo xlt('Inactive Days') ?
> 
;</label
>
478 <label
><input type
='checkbox' name
='form_cb_err'<?php
echo ($form_cb_err) ?
' checked' : ''; ?
>>
479 <?php
echo xlt('Errors') ?
></label
>
490 <td
class='col-form-label'>
491 <?php
echo xlt('Service Date'); ?
>:
494 <input type
='text' class='datepicker form-control' name
='form_date' id
="form_date" size
='10' value
='<?php echo attr(oeFormatShortDate($form_date)); ?>'>
496 <td
class='col-form-label'>
497 <?php
echo xlt('To{{Range}}'); ?
>:
500 <input type
='text' class='datepicker form-control' name
='form_to_date' id
="form_to_date" size
='10' value
='<?php echo attr(oeFormatShortDate($form_to_date)); ?>'>
503 <select name
='form_category' class='form-control'>
505 foreach (array('Open' => xl('Open'),'Due Pt' => xl('Due Pt'),'Due Ins' => xl('Due Ins'),'Ins Summary' => xl('Ins Summary'),'Credits' => xl('Credits'),'All' => xl('All')) as $key => $value) {
506 echo " <option value='" . attr($key) . "'";
507 if ($form_category == $key) {
511 echo ">" . text($value) . "</option>\n";
521 <td
class='col-form-label'>
522 <?php
echo xlt('Facility'); ?
>:
525 <?php
dropdown_facility($form_facility, 'form_facility', false); ?
>
528 <td
class='col-form-label'>
529 <?php
echo xlt('Payor'); ?
>:
532 <?php
# added dropdown for payors (TLH)
533 $insurancei = getInsuranceProviders();
534 echo " <select name='form_payer_id' class='form-control'>\n";
535 echo " <option value='0'>-- " . xlt('All') . " --</option>\n";
536 foreach ($insurancei as $iid => $iname) {
537 echo "<option value='" . attr($iid) . "'";
538 if (!empty($_POST['form_payer_id']) && ($iid == $_POST['form_payer_id'])) {
542 echo ">" . text($iname) . "</option>\n";
543 if (!empty($_POST['form_payer_id']) && ($iid == $_POST['form_payer_id'])) {
544 $ins_co_name = $iname;
554 <td
class='col-form-label'>
555 <?php
echo xlt('Age By') ?
>:
558 <select name
='form_ageby' class='form-control'>
560 foreach (array( 'Service Date' => xl('Service Date'), 'Last Activity Date' => xl('Last Activity Date')) as $key => $value) {
561 echo " <option value='" . attr($key) . "'";
562 if (!empty($_POST['form_ageby']) && ($_POST['form_ageby'] == $value)) {
566 echo ">" . text($value) . "</option>\n";
572 <td
class='col-form-label'>
573 <?php
echo xlt('Provider') ?
>:
576 <?php
# Build a drop-down list of providers.
579 $query = "SELECT id, lname, fname FROM users WHERE " .
580 "authorized = 1 ORDER BY lname, fname"; #(CHEMED) facility filter
582 $ures = sqlStatement($query);
584 echo " <select name='form_provider' class='form-control'>\n";
585 echo " <option value=''>-- " . xlt('All') . " --\n";
587 while ($urow = sqlFetchArray($ures)) {
588 $provid = $urow['id'];
589 echo " <option value='" . attr($provid) . "'";
590 if (!empty($_POST['form_provider']) && ($provid == $_POST['form_provider'])) {
594 echo ">" . text($urow['lname']) . ", " . text($urow['fname']) . "\n";
595 if (!empty($_POST['form_provider']) && ($provid == $_POST['form_provider'])) {
596 $provider_name = $urow['lname'] . ", " . $urow['fname'];
605 <td
class='col-form-label'>
606 <?php
echo xlt('Aging Columns') ?
>:
609 <input type
='text' name
='form_age_cols' class='form-control' size
='2' value
='<?php echo ($form_age_cols) ? attr($form_age_cols) : "3" ; ?>' />
611 <td
class='col-form-label'>
612 <?php
echo xlt('Days/Col') ?
>:
615 <input type
='text' name
='form_age_inc' class='form-control' size
='3' value
='<?php echo ($form_age_inc) ? attr($form_age_inc) : "30"; ?>' />
618 <div
class="checkbox">
619 <label
><input type
='checkbox' name
='form_cb_with_debt'<?php
echo ($form_cb_with_debt) ?
' checked' : ''; ?
>>
620 <?php
echo xlt('Patients with debt') ?
></label
>
634 <td align
='left' valign
='middle' height
="100%">
635 <table style
='border-left:1px solid; width:100%; height:100%' >
638 <div
class="text-center">
639 <div
class="btn-group" role
="group">
640 <a href
='#' class='btn btn-secondary btn-save' onclick
='$("#form_refresh").attr("value","true"); $("#form_csvexport").val(""); $("#theform").submit();'>
641 <?php
echo xlt('Submit'); ?
>
643 <?php
if (!empty($_POST['form_refresh'])) { ?
>
644 <a href
='#' class='btn btn-secondary btn-print' onclick
='window.print()'>
645 <?php
echo xlt('Print'); ?
>
660 } // end not form_csvexport
662 if (!empty($_POST['form_refresh']) ||
!empty($_POST['form_export']) ||
!empty($_POST['form_csvexport'])) {
666 if ($_POST['form_export'] ||
$_POST['form_csvexport']) {
668 foreach ($_POST['form_cb'] as $key => $value) {
669 list($key_newval['pid'], $key_newval['encounter']) = explode(".", $key);
670 $newkey = $key_newval['pid'];
671 $newencounter = $key_newval['encounter'];
672 # added this condition to handle the downloading of individual invoices (TLH)
673 if ($_POST['form_individual'] == 1) {
674 $where .= " OR f.encounter = ? ";
675 array_push($sqlArray, $newencounter);
677 $where .= " OR f.pid = ? ";
678 array_push($sqlArray, $newkey);
691 $where .= "f.date >= ? AND f.date <= ? ";
692 array_push($sqlArray, $form_date . ' 00:00:00', $form_to_date . ' 23:59:59');
694 $where .= "f.date >= ? AND f.date <= ? ";
695 array_push($sqlArray, $form_date . ' 00:00:00', $form_date . ' 23:59:59');
699 if ($form_facility) {
704 $where .= "f.facility_id = ? ";
705 array_push($sqlArray, $form_facility);
708 # added for filtering by provider (TLH)
709 if ($form_provider) {
714 $where .= "f.provider_id = ? ";
715 array_push($sqlArray, $form_provider);
722 # added provider from encounter to the query (TLH)
723 $query = "SELECT f.id, f.date, f.pid, CONCAT(w.lname, ', ', w.fname) AS provider_id, f.encounter, f.last_level_billed, " .
724 "f.last_level_closed, f.last_stmt_date, f.stmt_count, f.invoice_refno, " .
725 "p.fname, p.mname, p.lname, p.street, p.city, p.state, " .
726 "p.postal_code, p.phone_home, p.ss, p.billing_note, " .
727 "p.pubpid, p.DOB, CONCAT(u.lname, ', ', u.fname) AS referrer, " .
728 "( SELECT bill_date FROM billing AS b WHERE " .
729 "b.pid = f.pid AND b.encounter = f.encounter AND " .
730 "b.activity = 1 AND b.code_type != 'COPAY' LIMIT 1) AS billdate, " .
731 "( SELECT SUM(b.fee) FROM billing AS b WHERE " .
732 "b.pid = f.pid AND b.encounter = f.encounter AND " .
733 "b.activity = 1 AND b.code_type != 'COPAY' ) AS charges, " .
734 "( SELECT SUM(b.fee) FROM billing AS b WHERE " .
735 "b.pid = f.pid AND b.encounter = f.encounter AND " .
736 "b.activity = 1 AND b.code_type = 'COPAY' ) AS copays, " .
737 "( SELECT SUM(s.fee) FROM drug_sales AS s WHERE " .
738 "s.pid = f.pid AND s.encounter = f.encounter ) AS sales, " .
739 "( SELECT SUM(a.pay_amount) FROM ar_activity AS a WHERE " .
740 "a.pid = f.pid AND a.encounter = f.encounter AND a.deleted IS NULL) AS payments, " .
741 "( SELECT SUM(a.adj_amount) FROM ar_activity AS a WHERE " .
742 "a.pid = f.pid AND a.encounter = f.encounter AND a.deleted IS NULL) AS adjustments " .
743 "FROM form_encounter AS f " .
744 "JOIN patient_data AS p ON p.pid = f.pid " .
745 "LEFT OUTER JOIN users AS u ON u.id = p.ref_providerID " .
746 "LEFT OUTER JOIN users AS w ON w.id = f.provider_id " .
748 "ORDER BY f.pid, f.encounter";
750 $eres = sqlStatement($query, $sqlArray);
752 while ($erow = sqlFetchArray($eres)) {
753 $patient_id = $erow['pid'];
754 $encounter_id = $erow['encounter'];
755 $pt_balance = $erow['charges'] +
$erow['sales'] +
$erow['copays'] - $erow['payments'] - $erow['adjustments'];
756 $pt_balance = 0 +
sprintf("%.2f", $pt_balance); // yes this seems to be necessary
757 $svcdate = substr($erow['date'], 0, 10);
759 if ($form_cb_with_debt && $pt_balance <= 0) {
764 if ($_POST['form_refresh'] && ! $is_all) {
765 if ($pt_balance == 0) {
770 if ($form_category == 'Credits') {
771 if ($pt_balance > 0) {
776 // If we have not yet billed the patient, then compute $duncount as a
777 // negative count of the number of insurance plans for which we have not
778 // yet closed out insurance. Here we also compute $insname as the name of
779 // the insurance plan from which we are awaiting payment, and its sequence
780 // number $insposition (1-3).
781 $last_level_closed = $erow['last_level_closed'];
782 $duncount = $erow['stmt_count'];
787 for ($i = 1; $i <= 3; ++
$i) {
788 $tmp = SLEOB
::arGetPayerID($patient_id, $svcdate, $i);
795 $duncount = $last_level_closed - count($payerids);
797 if (!empty($payerids[$last_level_closed])) {
798 $insname = getInsName($payerids[$last_level_closed]);
799 $insposition = $last_level_closed +
1;
804 // Skip invoices not in the desired "Due..." category.
806 if ($is_due_ins && $duncount >= 0) {
809 if ($is_due_pt && $duncount < 0) {
814 // echo "<!-- " . $erow['encounter'] . ': ' . $erow['charges'] . ' + ' . $erow['sales'] . ' + ' . $erow['copays'] . ' - ' . $erow['payments'] . ' - ' . $erow['adjustments'] . " -->\n"; // debugging
816 // An invoice is due from the patient if money is owed and we are
817 // not waiting for insurance to pay.
818 $isduept = ($duncount >= 0) ?
" checked" : "";
822 $row['id'] = $erow['id'];
823 $row['invnumber'] = "$patient_id.$encounter_id";
824 $row['custid'] = $patient_id;
825 $row['name'] = $erow['fname'] . ' ' . $erow['lname'];
826 $row['address1'] = $erow['street'];
827 $row['city'] = $erow['city'];
828 $row['state'] = $erow['state'];
829 $row['zipcode'] = $erow['postal_code'];
830 $row['phone'] = $erow['phone_home'];
831 $row['duncount'] = $duncount;
832 $row['dos'] = $svcdate;
833 $row['ss'] = $erow['ss'];
834 $row['DOB'] = $erow['DOB'];
835 $row['pubpid'] = $erow['pubpid'];
836 $row['billnote'] = $erow['billing_note'];
837 $row['referrer'] = $erow['referrer'];
838 $row['provider'] = $erow['provider_id'];
839 $row['irnumber'] = $erow['invoice_refno'];
840 $row['billdate'] = $erow['billdate']; // use this for ins_due claim age date
842 // Also get the primary insurance company name whenever there is one.
844 if ($insposition == 1) {
845 $row['ins1'] = $insname;
847 if (empty($payerids)) {
848 $tmp = SLEOB
::arGetPayerID($patient_id, $svcdate, 1);
854 if (!empty($payerids)) {
855 $row['ins1'] = getInsName($payerids[0]);
859 // This computes the invoice's total original charges and adjustments,
860 // date of last activity, and determines if insurance has responded to
861 // all billing items.
862 $invlines = InvoiceSummary
::arGetInvoiceSummary($patient_id, $encounter_id, true);
864 // if ($encounter_id == 185) { // debugging
866 // print_r($invlines);
871 $row['adjustments'] = 0;
873 $ins_seems_done = true;
875 foreach ($invlines as $key => $value) {
876 $row['charges'] +
= $value['chg'] +
$value['adj'];
877 $row['adjustments'] +
= 0 - $value['adj'];
878 $row['paid'] +
= $value['chg'] - $value['bal'];
879 foreach ($value['dtl'] as $dkey => $dvalue) {
880 $dtldate = trim(substr($dkey, 0, 10));
881 if ($dtldate && $dtldate > $ladate) {
886 $lckey = strtolower($key);
887 if ($lckey == 'co-pay' ||
$lckey == 'claim') {
891 if (count($value['dtl']) <= 1) {
892 $ins_seems_done = false;
896 // Simulating ar.amount in SQL-Ledger which is charges with adjustments:
897 $row['amount'] = $row['charges'] +
$row['adjustments'];
899 $row['billing_errmsg'] = '';
900 if ($is_due_ins && $last_level_closed < 1 && $ins_seems_done) {
901 $row['billing_errmsg'] = 'Ins1 seems done';
902 } elseif ($last_level_closed >= 1 && !$ins_seems_done) {
903 $row['billing_errmsg'] = 'Ins1 seems not done';
906 // Calculate claim age date for due ins
908 $ladate = $row['billdate'];
911 $row['ladate'] = $ladate;
914 $row['inactive_days'] = "n/a";
916 // Compute number of days since last activity.
921 substr($ladate, 5, 2),
922 substr($ladate, 8, 2),
923 substr($ladate, 0, 4)
925 $row['inactive_days'] = floor((time() - $latime) / (60 * 60 * 24));
928 // Look up insurance policy number if we need it.
929 if ($form_cb_policy) {
930 $instype = ($insposition == 2) ?
'secondary' : (($insposition == 3) ?
'tertiary' : 'primary');
931 $insrow = sqlQuery("SELECT policy_number FROM insurance_data WHERE " .
932 "pid = ? AND type = ? AND (date <= ? OR date IS NULL) " .
933 "ORDER BY date DESC LIMIT 1", array($patient_id, $instype, $svcdate));
934 $row['policy'] = $insrow['policy_number'];
937 $ptname = $erow['lname'] . ", " . $erow['fname'];
938 if ($erow['mname']) {
939 $ptname .= " " . substr($erow['mname'], 0, 1);
946 $rows[$insname . '|' . $ptname . '|' . $encounter_id] = $row;
952 if ($_POST['form_export']) {
953 echo "<textarea rows='35' cols='100' readonly>";
954 } elseif ($_POST['form_csvexport']) {
955 # CSV headers added conditions if they are checked to display then export them (TLH)
957 echo csvEscape(xl('Insurance')) . ',';
958 echo csvEscape(xl('Name')) . ',';
960 echo csvEscape(xl('SSN')) . ',';
964 echo csvEscape(xl('DOB')) . ',';
967 if ($form_cb_pubpid) {
968 echo csvEscape(xl('Pubpid')) . ',';
971 if ($form_cb_policy) {
972 echo csvEscape(xl('Policy')) . ',';
975 if ($form_cb_phone) {
976 echo csvEscape(xl('Phone')) . ',';
980 echo csvEscape(xl('City')) . ',';
983 echo csvEscape(xl('Invoice')) . ',';
984 echo csvEscape(xl('DOS')) . ',';
985 echo csvEscape(xl('Referrer')) . ',';
986 echo csvEscape(xl('Provider')) . ',';
987 echo csvEscape(xl('Adjust')) . ',';
988 echo csvEscape(xl('Paid')) . ',';
989 echo csvEscape(xl('Balance')) . ',';
990 echo csvEscape(xl('IDays')) . ',';
992 echo csvEscape(xl('LADate')) . ',';
993 echo csvEscape(xl('Error')) . "\n";
995 echo csvEscape(xl('LADate')) . "\n";
1001 <div id
="report_results">
1002 <table
class='table' id
='mymaintable'>
1004 <thead
class='thead-light'>
1005 <?php
if ($is_due_ins) { ?
>
1006 <th
> 
;<?php
echo xlt('Insurance')?
></th
>
1008 <?php
if (!$is_ins_summary) { ?
>
1009 <th
> 
;<?php
echo xlt('Name')?
></th
>
1011 <?php
if ($form_cb_ssn) { ?
>
1012 <th
> 
;<?php
echo xlt('SSN')?
></th
>
1014 <?php
if ($form_cb_dob) { ?
>
1015 <th
> 
;<?php
echo xlt('DOB')?
></th
>
1017 <?php
if ($form_cb_pubpid) { ?
>
1018 <th
> 
;<?php
echo xlt('ID')?
></th
>
1020 <?php
if ($form_cb_policy) { ?
>
1021 <th
> 
;<?php
echo xlt('Policy')?
></th
>
1023 <?php
if ($form_cb_phone) { ?
>
1024 <th
> 
;<?php
echo xlt('Phone')?
></th
>
1026 <?php
if ($form_cb_city) { ?
>
1027 <th
> 
;<?php
echo xlt('City')?
></th
>
1029 <?php
if ($form_cb_ins1 ||
$form_payer_id) { ?
>
1030 <th
> 
;<?php
echo xlt('Primary Ins')?
></th
>
1032 <?php
if ($form_provider) { ?
>
1033 <th
> 
;<?php
echo xlt('Provider')?
></th
>
1035 <?php
if ($form_cb_referrer) { ?
>
1036 <th
> 
;<?php
echo xlt('Referrer')?
></th
>
1038 <?php
if (!$is_ins_summary) { ?
>
1039 <th
> 
;<?php
echo xlt('Invoice') ?
></th
>
1040 <th
> 
;<?php
echo xlt('Svc Date') ?
></th
>
1041 <?php
if ($form_cb_adate) { ?
>
1042 <th
> 
;<?php
echo xlt('Act Date')?
></th
>
1045 <th align
="right"><?php
echo xlt('Charge') ?
> 
;</th
>
1046 <th align
="right"><?php
echo xlt('Adjust') ?
> 
;</th
>
1047 <th align
="right"><?php
echo xlt('Paid') ?
> 
;</th
>
1049 // Generate aging headers if appropriate, else balance header.
1050 if ($form_age_cols) {
1051 for ($c = 0; $c < $form_age_cols;) {
1052 echo " <th class='dehead' align='left'>";
1053 echo $form_age_inc * $c;
1054 if (++
$c < $form_age_cols) {
1055 echo "-" . text(($form_age_inc * $c - 1));
1064 <th align
="right"><?php
echo xlt('Balance') ?
> 
;</th
>
1068 <?php
if ($form_cb_idays) { ?
>
1069 <th align
="right"><?php
echo xlt('IDays')?
> 
;</th
>
1071 <?php
if (!$is_ins_summary) { ?
>
1072 <th align
="center"><?php
echo xlt('Prv') ?
></th
>
1073 <th align
="center"><?php
echo xlt('Sel') ?
></th
>
1075 <?php
if ($form_cb_err) { ?
>
1076 <th
> 
;<?php
echo xlt('Error')?
></th
>
1083 $ptrow = array('insname' => '', 'pid' => 0);
1086 foreach ($rows as $key => $row) {
1087 list($insname, $ptname, $trash) = explode('|', $key);
1088 list($pid, $encounter) = explode(".", $row['invnumber']);
1089 if ($form_payer_id) {
1090 if ($ins_co_name <> $row['ins1']) {
1095 if ($is_ins_summary && $insname != $ptrow['insname']) {
1096 endInsurance($ptrow);
1097 $bgcolor = ((++
$orow & 1) ?
"#ffdddd" : "#ddddff");
1098 $ptrow = array('insname' => $insname, 'ptname' => $ptname, 'pid' => $pid, 'count' => 1);
1099 foreach ($row as $key => $value) {
1100 $ptrow[$key] = $value;
1103 $ptrow['agedbal'] = array();
1104 } elseif (!$is_ins_summary && ($insname != $ptrow['insname'] ||
$pid != $ptrow['pid'])) {
1105 // For the report, this will write the patient totals. For the
1106 // collections export this writes everything for the patient:
1108 $bgcolor = ((++
$orow & 1) ?
"#ffdddd" : "#ddddff");
1109 $ptrow = array('insname' => $insname, 'ptname' => $ptname, 'pid' => $pid, 'count' => 1);
1110 foreach ($row as $key => $value) {
1111 $ptrow[$key] = $value;
1114 $ptrow['agedbal'] = array();
1116 $ptrow['amount'] +
= $row['amount'];
1117 $ptrow['paid'] +
= $row['paid'];
1118 $ptrow['charges'] +
= $row['charges'];
1119 $ptrow['adjustments'] +
= $row['adjustments'];
1123 // Compute invoice balance and aging column number, and accumulate aging.
1124 $balance = $row['charges'] +
$row['adjustments'] - $row['paid'];
1125 if ($form_age_cols) {
1126 $agedate = $is_ageby_lad ?
$row['ladate'] : $row['dos'];
1131 substr($agedate, 5, 2),
1132 substr($agedate, 8, 2),
1133 substr($agedate, 0, 4)
1135 $days = floor((time() - $agetime) / (60 * 60 * 24));
1136 $agecolno = min($form_age_cols - 1, max(0, floor($days / $form_age_inc)));
1138 $ptrow['agedbal'][$agecolno] = $ptrow['agedbal'][$agecolno] ??
null;
1139 $ptrow['agedbal'][$agecolno] +
= $balance;
1142 if (!$is_ins_summary && !$_POST['form_export'] && !$_POST['form_csvexport']) {
1143 $in_collections = stristr($row['billnote'], 'IN COLLECTIONS') !== false;
1145 <tr bgcolor
='<?php echo attr($bgcolor) ?>'>
1147 if ($ptrow['count'] == 1) {
1149 echo " <td class='detail'> " . text($insname) . "</td>\n";
1152 echo " <td class='detail'> " . text($ptname) . "</td>\n";
1154 echo " <td class='detail'> " . text($row['ss']) . "</td>\n";
1158 echo " <td class='detail'> " . text(oeFormatShortDate($row['DOB'])) . "</td>\n";
1161 if ($form_cb_pubpid) {
1162 echo " <td class='detail'> " . text($row['pubpid']) . "</td>\n";
1165 if ($form_cb_policy) {
1166 echo " <td class='detail'> " . text($row['policy']) . "</td>\n";
1169 if ($form_cb_phone) {
1170 echo " <td class='detail'> " . text($row['phone']) . "</td>\n";
1173 if ($form_cb_city) {
1174 echo " <td class='detail'> " . text($row['city']) . "</td>\n";
1177 if ($form_cb_ins1 ||
$form_payer_id) {
1178 echo " <td class='detail'> " . text($row['ins1']) . "</td>\n";
1181 if ($form_provider) {
1182 echo " <td class='detail'> " . text($provider_name) . "</td>\n";
1185 if ($form_cb_referrer) {
1186 echo " <td class='detail'> " . text($row['referrer']) . "</td>\n";
1189 echo " <td class='detail' colspan='" . attr($initial_colspan) . "'>";
1190 echo " </td>\n";
1194  
;<a href
="#" onclick
="editInvoice(event,<?php echo attr_js($row['id']) ?>)">
1195 <?php
echo empty($row['irnumber']) ?
text($row['invnumber']) : text($row['irnumber']); ?
></a
>
1198  
;<?php
echo text(oeFormatShortDate($row['dos'])); ?
>
1200 <?php
if ($form_cb_adate) { ?
>
1202  
;<?php
echo text(oeFormatShortDate($row['ladate'])); ?
>
1205 <td
class="detail" align
="left">
1206 <?php
echo text(bucks($row['charges'])) ?
> 
;
1208 <td
class="detail" align
="left">
1209 <?php
echo text(bucks($row['adjustments'])) ?
> 
;
1211 <td
class="detail" align
="left">
1212 <?php
echo text(bucks($row['paid'])) ?
> 
;
1215 if ($form_age_cols) {
1216 for ($c = 0; $c < $form_age_cols; ++
$c) {
1217 echo " <td class='detail' align='left'>";
1218 if ($c == $agecolno) {
1219 echo text(bucks($balance));
1222 echo " </td>\n";
1226 <td
class="detail" align
="left"><?php
echo text(bucks($balance)); ?
> 
;</td
>
1231 if ($form_cb_idays) {
1232 echo " <td class='detail' align='right'>";
1233 echo text($row['inactive_days']) . " </td>\n";
1236 <td
class="detail" align
="center">
1237 <?php
echo $row['duncount'] ?
text($row['duncount']) : " " ?
>
1239 <td
class="detail" align
="center">
1241 if ($in_collections) {
1242 echo " <span class='font-weight-bold text-danger'>IC</span>\n";
1244 echo " <input type='checkbox' name='form_cb[" . attr($row['invnumber']) . "]' />\n";
1250 echo " <td class='detail'> ";
1251 echo text($row['billing_errmsg']) . "</td>\n";
1256 } elseif ($_POST['form_csvexport']) { // end not export and not insurance summary
1257 // The CSV detail line is written here added conditions for checked items (TLH).
1258 // Added zero balances for a complete spreadsheet view
1259 $balance = $row['charges'] +
$row['adjustments'] - $row['paid'];
1260 if ($balance > 0 ||
$_POST['form_zero_balances']) {
1261 echo csvEscape($row['ins1']) . ','; // insname
1262 echo csvEscape($ptname) . ',';
1264 echo csvEscape($row['ss']) . ',';
1268 echo csvEscape(oeFormatShortDate($row['DOB'])) . ',';
1271 if ($form_cb_pubpid) {
1272 echo csvEscape($row['pubpid']) . ',';
1275 if ($form_cb_policy) {
1276 echo csvEscape($row['policy']) . ',';
1279 if ($form_cb_phone) {
1280 echo csvEscape($row['phone']) . ',';
1283 if ($form_cb_city) {
1284 echo csvEscape($row['city']) . ',';
1287 echo (empty($row['irnumber']) ?
csvEscape($row['invnumber']) : csvEscape($row['irnumber'])) . ',';
1288 echo csvEscape(oeFormatShortDate($row['dos'])) . ',';
1289 echo csvEscape($row['referrer']) . ',';
1290 echo csvEscape($row['provider']) . ',';
1291 echo csvEscape(oeFormatMoney($row['charges'])) . ',';
1292 echo csvEscape(oeFormatMoney($row['adjustments'])) . ',';
1293 echo csvEscape(oeFormatMoney($row['paid'])) . ',';
1294 echo csvEscape(oeFormatMoney($balance)) . ',';
1295 echo csvEscape($row['inactive_days']) . ',';
1297 echo csvEscape(oeFormatShortDate($row['ladate'])) . ',';
1298 echo csvEscape($row['billing_errmsg']) . "\n";
1300 echo csvEscape(oeFormatShortDate($row['ladate'])) . "\n";
1303 } // end $form_csvexport
1306 if ($is_ins_summary) {
1307 endInsurance($ptrow);
1312 if ($_POST['form_export']) {
1313 echo "</textarea>\n";
1314 $alertmsg .= "$export_patient_count patients with total of " .
1315 oeFormatMoney($export_dollars) . " have been exported ";
1316 if ($_POST['form_without']) {
1317 $alertmsg .= "but NOT flagged as in collections.";
1319 $alertmsg .= "AND flagged as in collections.";
1321 } elseif ($_POST['form_csvexport']) {
1322 // echo "</textarea>\n";
1323 // $alertmsg .= "$export_patient_count patients representing $" .
1324 // sprintf("%.2f", $export_dollars) . " have been exported.";
1326 echo " <tr class='bg-white'>\n";
1327 if ($is_ins_summary) {
1328 echo " <td class='dehead'> " . xlt('Report Totals') . ":</td>\n";
1330 echo " <td class='detail' colspan='" . attr($initial_colspan) . "'>\n";
1331 echo " </td>\n";
1332 echo " <td class='dehead' colspan='" . attr($final_colspan - 3) .
1333 "'> " . xlt('Report Totals') . ":</td>\n";
1336 echo " <td class='dehead' align='left'> " .
1337 text(oeFormatMoney($grand_total_charges)) . " </td>\n";
1338 echo " <td class='dehead' align='left'> " .
1339 text(oeFormatMoney($grand_total_adjustments)) . " </td>\n";
1340 echo " <td class='dehead' align='left'> " .
1341 text(oeFormatMoney($grand_total_paid)) . " </td>\n";
1342 if ($form_age_cols) {
1343 for ($c = 0; $c < $form_age_cols; ++
$c) {
1344 echo " <td class='dehead' align='left'>" .
1345 text(oeFormatMoney($grand_total_agedbal[$c])) . " </td>\n";
1348 echo " <td class='dehead' align='left'>" .
1349 text(oeFormatMoney($grand_total_charges +
1350 $grand_total_adjustments - $grand_total_paid)) . " </td>\n";
1353 if ($form_cb_idays) {
1354 echo " <td class='detail'> </td>\n";
1357 if (!$is_ins_summary) {
1358 echo " <td class='detail' colspan='2'> </td>\n";
1362 echo " <td class='detail'> </td>\n";
1369 } // end if form_refresh
1372 if (empty($_POST['form_csvexport'])) {
1373 if (empty($_POST['form_export'])) {
1376 <div style
='margin-top:5px'>
1377 <div
class="btn-group float-left" role
="group">
1378 <a href
='javascript:;' class='btn btn-secondary btn-save' onclick
='checkAll(true)'><?php
echo xlt('Select All'); ?
></a
>
1379 <a href
='javascript:;' class='btn btn-secondary btn-cancel' onclick
='checkAll(false)'><?php
echo xlt('Clear All'); ?
></a
>
1380 <a href
='javascript:;' class='btn btn-secondary btn-transmit' onclick
='$("#form_csvexport").attr("value","true"); $("#theform").submit();'>
1381 <?php
echo xlt('Export Selected as CSV'); ?
>
1383 <a href
='javascript:;' class='btn btn-secondary btn-transmit' onclick
='$("#form_export").attr("value","true"); $("#form_csvexport").val(""); $("#theform").submit();'>
1384 <?php
echo xlt('Export Selected to Collections'); ?
>
1388 <div style
='float:left'>
1389 <label
><input type
='checkbox' name
='form_zero_balances' value
='1' /> <?php
echo xlt('Export Zero Balances') ?
> 
; 
;</label
>
1392 <div style
='float:left'>
1393 <label
><input type
='checkbox' name
='form_individual' value
='1' /> <?php
echo xlt('Export Individual Invoices') ?
> 
; 
;</label
>
1396 <div style
='float:left'>
1397 <label
><input type
='checkbox' name
='form_without' value
='1' /> <?php
echo xlt('Without Update') ?
></label
>
1409 echo "alert(" . js_escape($alertmsg) . ");\n";
1416 } // end not form_csvexport