2 // Copyright (C) 2006-2010 Rod Roark <rod@sunsetsystems.com>
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 // This is a report of receipts by payer or payment method.
11 // The payer option means an insurance company name or "Patient".
13 // The payment method option is most useful for sites using
14 // pos_checkout.php (e.g. weight loss clinics) because this plugs
15 // a payment method like Cash, Check, VISA, etc. into the "source"
16 // column of the SQL-Ledger acc_trans table or ar_session table.
18 require_once("../globals.php");
19 require_once("$srcdir/patient.inc");
20 require_once("$srcdir/sql-ledger.inc");
21 require_once("$srcdir/acl.inc");
22 require_once("$srcdir/formatting.inc.php");
23 require_once "$srcdir/options.inc.php";
24 require_once "$srcdir/formdata.inc.php";
25 require_once("../../custom/code_types.inc.php");
27 // This controls whether we show pt name, policy number and DOS.
32 function bucks($amount) {
33 if ($amount) echo oeFormatMoney($amount);
36 function thisLineItem($patient_id, $encounter_id, $memo, $transdate,
37 $rowmethod, $rowpayamount, $rowadjamount, $payer_type=0, $irnumber='')
39 global $form_report_by, $insarray, $grandpaytotal, $grandadjtotal;
41 if ($form_report_by != '1') { // reporting by method or check number
42 showLineItem($patient_id, $encounter_id, $memo, $transdate,
43 $rowmethod, $rowpayamount, $rowadjamount, $payer_type, $irnumber);
47 // Reporting by payer.
49 if ($_POST['form_details']) { // details are wanted
50 // Save everything for later sorting.
51 $insarray[] = array($patient_id, $encounter_id, $memo, $transdate,
52 $rowmethod, $rowpayamount, $rowadjamount, $payer_type, $irnumber);
54 else { // details not wanted
55 if (empty($insarray[$rowmethod])) $insarray[$rowmethod] = array(0, 0);
56 $insarray[$rowmethod][0] +
= $rowpayamount;
57 $insarray[$rowmethod][1] +
= $rowadjamount;
58 $grandpaytotal +
= $rowpayamount;
59 $grandadjtotal +
= $rowadjamount;
63 function showLineItem($patient_id, $encounter_id, $memo, $transdate,
64 $rowmethod, $rowpayamount, $rowadjamount, $payer_type=0, $irnumber='')
66 global $paymethod, $paymethodleft, $methodpaytotal, $methodadjtotal,
67 $grandpaytotal, $grandadjtotal, $showing_ppd;
69 if (! $rowmethod) $rowmethod = 'Unknown';
71 $invnumber = $irnumber ?
$irnumber : "$patient_id.$encounter_id";
73 if ($paymethod != $rowmethod) {
75 // Print method total.
78 <tr bgcolor
="#ddddff">
79 <td
class="detail" colspan
="<?php echo $showing_ppd ? 7 : 4; ?>">
80 <?php
echo xl('Total for ') . $paymethod ?
>
83 <?php
bucks($methodadjtotal) ?
>
86 <?php
bucks($methodpaytotal) ?
>
93 $paymethod = $rowmethod;
94 $paymethodleft = $paymethod;
97 if ($_POST['form_details']) {
102 <?php
echo $paymethodleft; $paymethodleft = " " ?
>
105 <?php
echo oeFormatShortDate($transdate) ?
>
108 <?php
echo $invnumber ?
>
113 $pferow = sqlQuery("SELECT p.fname, p.mname, p.lname, fe.date " .
114 "FROM patient_data AS p, form_encounter AS fe WHERE " .
115 "p.pid = '$patient_id' AND fe.pid = p.pid AND " .
116 "fe.encounter = '$encounter_id' LIMIT 1");
117 $dos = substr($pferow['date'], 0, 10);
119 echo " <td class='dehead'>\n";
120 echo " " . $pferow['lname'] . ", " . $pferow['fname'] . " " . $pferow['mname'];
123 echo " <td class='dehead'>\n";
125 $ptarr = array(1 => 'primary', 2 => 'secondary', 3 => 'tertiary');
126 $insrow = getInsuranceDataByDate($patient_id, $dos,
127 $ptarr[$payer_type], "policy_number");
128 echo " " . $insrow['policy_number'];
132 echo " <td class='dehead'>\n";
133 echo " " . oeFormatShortDate($dos) . "\n";
142 <?php
bucks($rowadjamount) ?
>
145 <?php
bucks($rowpayamount) ?
>
150 $methodpaytotal +
= $rowpayamount;
151 $grandpaytotal +
= $rowpayamount;
152 $methodadjtotal +
= $rowadjamount;
153 $grandadjtotal +
= $rowadjamount;
156 // This is called by usort() when reporting by payer with details.
157 // Sorts by payer/date/patient/encounter/memo.
158 function payerCmp($a, $b) {
159 foreach (array(4,3,0,1,2,7) as $i) {
160 if ($a[$i] < $b[$i]) return -1;
161 if ($a[$i] > $b[$i]) return 1;
166 if (! acl_check('acct', 'rep')) die(xl("Unauthorized access."));
168 $INTEGRATED_AR = $GLOBALS['oer_config']['ws_accounting']['enabled'] === 2;
170 if (!$INTEGRATED_AR) SLConnect();
172 $form_from_date = fixDate($_POST['form_from_date'], date('Y-m-d'));
173 $form_to_date = fixDate($_POST['form_to_date'] , date('Y-m-d'));
174 $form_use_edate = $_POST['form_use_edate'];
175 $form_facility = $_POST['form_facility'];
176 $form_report_by = $_POST['form_report_by'];
177 $form_proc_codefull = trim($_POST['form_proc_codefull']);
178 // Parse the code type and the code from <code_type>:<code>
179 $tmp_code_array = explode(':',$form_proc_codefull);
180 $form_proc_codetype = $tmp_code_array[0];
181 $form_proc_code = $tmp_code_array[1];
187 <?php
if (function_exists('html_header_show')) html_header_show(); ?
>
188 <style type
="text/css">
189 /* specifically include & exclude from printing */
195 #report_parameters_daterange {
204 /* specifically exclude some from the screen */
206 #report_parameters_daterange {
213 <script type
="text/javascript" src
="../../library/dialog.js"></script
>
214 <script language
="JavaScript">
215 // This is for callback by the find-code popup.
216 // Erases the current entry
217 function set_related(codetype
, code
, selector
, codedesc
) {
218 var f
= document
.forms
[0];
219 var s
= f
.form_proc_codefull
.value
;
221 s
= codetype +
':' + code
;
225 f
.form_proc_codefull
.value
= s
;
228 // This invokes the find-code popup.
229 function sel_procedure() {
230 dlgopen('../patient_file/encounter/find_code_popup.php?codetype=<?php echo attr(collect_codetypes("procedure","csv")) ?>', '_blank', 500, 400);
234 <title
><?
xl('Receipts Summary','e')?
></title
>
237 <body
class="body_top">
239 <span
class='title'><?php
xl('Report','e'); ?
> - <?php
xl('Receipts Summary','e'); ?
></span
>
241 <form method
='post' action
='receipts_by_method_report.php' id
='theform'>
243 <div id
="report_parameters">
245 <input type
='hidden' name
='form_refresh' id
='form_refresh' value
=''/>
250 <div style
='float:left'>
255 <?php
xl('Report by','e'); ?
>
259 echo " <select name='form_report_by'>\n";
260 foreach (array(1 => 'Payer', 2 => 'Payment Method', 3 => 'Check Number') as $key => $value) {
261 echo " <option value='$key'";
262 if ($key == $form_report_by) echo ' selected';
263 echo ">" . xl($value) . "</option>\n";
265 echo " </select> \n"; ?
>
269 <?php
dropdown_facility(strip_escape_custom($form_facility), 'form_facility', false); ?
>
273 <?php
if (!$GLOBALS['simplified_demographics']) echo ' ' . xl('Procedure/Service') . ':'; ?
>
276 <input type
='text' name
='form_proc_codefull' size
='12' value
='<?php echo $form_proc_codefull; ?>' onclick
='sel_procedure()'
277 title
='<?php xl('Click to select optional procedure code
','e
'); ?>'
278 <?php
if ($GLOBALS['simplified_demographics']) echo "style='display:none'"; ?
> />
280  
;<input type
='checkbox' name
='form_details' value
='1'<?php
if ($_POST['form_details']) echo " checked"; ?
> /><?
xl('Details','e')?
>
286 <select name
='form_use_edate'>
287 <option value
='0'><?php
xl('Payment Date','e'); ?
></option
>
288 <option value
='1'<?php
if ($form_use_edate) echo ' selected' ?
>><?php
xl('Invoice Date','e'); ?
></option
>
292 <input type
='text' name
='form_from_date' id
="form_from_date" size
='10' value
='<?php echo $form_from_date ?>'
293 onkeyup
='datekeyup(this,mypcc)' onblur
='dateblur(this,mypcc)' title
='yyyy-mm-dd'>
294 <img src
='../pic/show_calendar.gif' align
='absbottom' width
='24' height
='22'
295 id
='img_from_date' border
='0' alt
='[?]' style
='cursor:pointer'
296 title
='<?php xl('Click here to choose a date
','e
'); ?>'>
299 <?php
xl('To','e'); ?
>:
302 <input type
='text' name
='form_to_date' id
="form_to_date" size
='10' value
='<?php echo $form_to_date ?>'
303 onkeyup
='datekeyup(this,mypcc)' onblur
='dateblur(this,mypcc)' title
='yyyy-mm-dd'>
304 <img src
='../pic/show_calendar.gif' align
='absbottom' width
='24' height
='22'
305 id
='img_to_date' border
='0' alt
='[?]' style
='cursor:pointer'
306 title
='<?php xl('Click here to choose a date
','e
'); ?>'>
314 <td align
='left' valign
='middle' height
="100%">
315 <table style
='border-left:1px solid; width:100%; height:100%' >
318 <div style
='margin-left:15px'>
319 <a href
='#' class='css_button' onclick
='$("#form_refresh").attr("value","true"); $("#theform").submit();'>
321 <?php
xl('Submit','e'); ?
>
325 <?php
if ($_POST['form_refresh']) { ?
>
326 <a href
='#' class='css_button' onclick
='window.print()'>
328 <?php
xl('Print','e'); ?
>
340 </div
> <!-- end of parameters
-->
343 if ($_POST['form_refresh']) {
345 <div id
="report_results">
357 <?
xl('Invoice','e')?
>
359 <?php
if ($showing_ppd) { ?
>
361 <?
xl('Patient','e')?
>
371 <?
xl('Procedure','e')?
>
374 <?
xl('Adjustments','e')?
>
377 <?
xl('Payments','e')?
>
382 if (!$INTEGRATED_AR) {
383 $chart_id_cash = SLQueryValue("select id from chart where accno = '$sl_cash_acc'");
384 if ($sl_err) die($sl_err);
385 $chart_id_income = SLQueryValue("select id from chart where accno = '$sl_income_acc'");
386 if ($sl_err) die($sl_err);
389 if ($_POST['form_refresh']) {
390 $from_date = $form_from_date;
391 $to_date = $form_to_date;
400 if ($INTEGRATED_AR) {
402 // Get co-pays using the encounter date as the pay date. These will
403 // always be considered patient payments. Ignored if selecting by
406 if (!$form_proc_code ||
!$form_proc_codetype) {
407 $query = "SELECT b.fee, b.pid, b.encounter, b.code_type, " .
408 "fe.date, fe.facility_id, fe.invoice_refno " .
409 "FROM billing AS b " .
410 "JOIN form_encounter AS fe ON fe.pid = b.pid AND fe.encounter = b.encounter " .
411 "WHERE b.code_type = 'COPAY' AND b.activity = 1 AND b.fee != 0 AND " .
412 "fe.date >= '$from_date 00:00:00' AND fe.date <= '$to_date 23:59:59'";
413 // If a facility was specified.
414 if ($form_facility) $query .= " AND fe.facility_id = '$form_facility'";
415 $query .= " ORDER BY fe.date, b.pid, b.encounter, fe.id";
417 $res = sqlStatement($query);
418 while ($row = sqlFetchArray($res)) {
419 $rowmethod = $form_report_by == 1 ?
'Patient' : 'Co-Pay';
420 thisLineItem($row['pid'], $row['encounter'], $row['code_text'],
421 substr($row['date'], 0, 10), $rowmethod, 0 - $row['fee'], 0, 0, $row['invoice_refno']);
423 } // end if not form_proc_code
425 // Get all other payments and adjustments and their dates, corresponding
426 // payers and check reference data, and the encounter dates separately.
428 $query = "SELECT a.pid, a.encounter, a.post_time, a.pay_amount, " .
429 "a.adj_amount, a.memo, a.session_id, a.code, a.payer_type, fe.id, fe.date, " .
430 "fe.invoice_refno, s.deposit_date, s.payer_id, s.reference, i.name " .
431 "FROM ar_activity AS a " .
432 "JOIN form_encounter AS fe ON fe.pid = a.pid AND fe.encounter = a.encounter " .
433 "JOIN forms AS f ON f.pid = a.pid AND f.encounter = a.encounter AND f.formdir = 'newpatient' " .
434 "LEFT JOIN ar_session AS s ON s.session_id = a.session_id " .
435 "LEFT JOIN insurance_companies AS i ON i.id = s.payer_id " .
436 "WHERE ( a.pay_amount != 0 OR a.adj_amount != 0 )";
438 if ($form_use_edate) {
439 $query .= " AND fe.date >= '$from_date 00:00:00' AND fe.date <= '$to_date 23:59:59'";
441 $query .= " AND ( ( s.deposit_date IS NOT NULL AND " .
442 "s.deposit_date >= '$from_date' AND s.deposit_date <= '$to_date' ) OR " .
443 "( s.deposit_date IS NULL AND a.post_time >= '$from_date 00:00:00' AND " .
444 "a.post_time <= '$to_date 23:59:59' ) )";
446 // If a procedure code was specified.
447 if ($form_proc_code && $form_proc_codetype) {
448 // if a code_type is entered into the ar_activity table, then use it. If it is not entered in, then do not use it.
449 $query .= " AND ( a.code_type = '$form_proc_codetype' OR a.code_type = '' ) AND a.code LIKE '$form_proc_code%'";
451 // If a facility was specified.
452 if ($form_facility) $query .= " AND fe.facility_id = '$form_facility'";
454 if ($form_use_edate) {
455 $query .= " ORDER BY s.reference, fe.date, a.pid, a.encounter, fe.id";
457 $query .= " ORDER BY s.reference, s.deposit_date, a.post_time, a.pid, a.encounter, fe.id";
460 $res = sqlStatement($query);
461 while ($row = sqlFetchArray($res)) {
462 if ($form_use_edate) {
463 $thedate = substr($row['date'], 0, 10);
464 } else if (!empty($row['deposit_date'])) {
465 $thedate = $row['deposit_date'];
467 $thedate = substr($row['post_time'], 0, 10);
469 // Compute reporting key: insurance company name or payment method.
470 if ($form_report_by == '1') {
471 if (empty($row['payer_id'])) {
474 if (empty($row['name'])) $rowmethod = xl('Unnamed insurance company');
475 else $rowmethod = $row['name'];
479 if (empty($row['session_id'])) {
480 $rowmethod = trim($row['memo']);
482 $rowmethod = trim($row['reference']);
484 if ($form_report_by != '3') {
485 // Extract only the first word as the payment method because any
486 // following text will be some petty detail like a check number.
487 $rowmethod = substr($rowmethod, 0, strcspn($rowmethod, ' /'));
491 thisLineItem($row['pid'], $row['encounter'], $row['code'], $thedate,
492 $rowmethod, $row['pay_amount'], $row['adj_amount'], $row['payer_type'],
493 $row['invoice_refno']);
495 } // end $INTEGRATED_AR
497 $query = "SELECT acc_trans.amount, acc_trans.transdate, acc_trans.memo, " .
498 "replace(acc_trans.source, 'InvAdj ', '') AS source, " .
499 "acc_trans.chart_id, ar.invnumber, ar.employee_id, ar.notes " .
500 "FROM acc_trans, ar WHERE " .
501 "( acc_trans.chart_id = $chart_id_cash OR " .
502 "( acc_trans.chart_id = $chart_id_income AND " .
503 "acc_trans.source LIKE 'InvAdj %' ) ) AND " .
504 "ar.id = acc_trans.trans_id AND ";
505 if ($form_proc_code) {
506 $query .= "acc_trans.memo ILIKE '$form_proc_code%' AND ";
508 if ($form_use_edate) {
509 $query .= "ar.transdate >= '$from_date' AND " .
510 "ar.transdate <= '$to_date'";
512 $query .= "acc_trans.transdate >= '$from_date' AND " .
513 "acc_trans.transdate <= '$to_date'";
515 $query .= " ORDER BY source, acc_trans.transdate, ar.invnumber, acc_trans.memo";
517 // echo "<!-- $query -->\n";
519 $t_res = SLQuery($query);
520 if ($sl_err) die($sl_err);
522 for ($irow = 0; $irow < SLRowCount($t_res); ++
$irow) {
523 $row = SLGetRow($t_res, $irow);
524 list($patient_id, $encounter_id) = explode(".", $row['invnumber']);
526 // If a facility was specified then skip invoices whose encounters
527 // do not indicate that facility.
528 if ($form_facility) {
529 $tmp = sqlQuery("SELECT count(*) AS count FROM form_encounter WHERE " .
530 "pid = '$patient_id' AND encounter = '$encounter_id' AND " .
531 "facility_id = '$form_facility'");
532 if (empty($tmp['count'])) continue;
535 $rowpayamount = 0 - $row['amount'];
537 if ($row['chart_id'] == $chart_id_income) {
538 $rowadjamount = $rowpayamount;
542 // Compute reporting key: insurance company name or payment method.
543 $payer_type = 0; // will be 0=pt, 1=ins1, 2=ins2 or 3=ins3
544 if ($form_report_by == '1') {
546 $rowsrc = strtolower($row['source']);
547 $insgot = strtolower($row['notes']);
548 foreach (array('ins1', 'ins2', 'ins3') as $value) {
549 if (strpos($rowsrc, $value) !== false) {
550 $i = strpos($insgot, $value);
552 $j = strpos($insgot, "\n", $i);
553 if (!$j) $j = strlen($insgot);
554 $payer_type = 0 +
substr($value, 3);
555 $rowmethod = trim(substr($row['notes'], $i +
5, $j - $i - 5));
560 } // end reporting by payer
562 $rowmethod = trim($row['source']);
563 if ($form_report_by != '3') {
564 // Extract only the first word as the payment method because any
565 // following text will be some petty detail like a check number.
566 $rowmethod = substr($rowmethod, 0, strcspn($rowmethod, ' /'));
568 } // end reporting by method
570 thisLineItem($patient_id, $encounter_id, $row['memo'], $row['transdate'],
571 $rowmethod, $rowpayamount, $rowadjamount, $payer_type);
573 } // end not $INTEGRATED_AR
575 // Not payer summary.
576 if ($form_report_by != '1' ||
$_POST['form_details']) {
578 if ($form_report_by == '1') { // by payer with details
579 // Sort and dump saved info, and consolidate items with all key
580 // fields being the same.
581 usort($insarray, 'payerCmp');
583 foreach ($insarray as $a) {
584 if (empty($a[4])) $a[4] = xl('Patient');
590 foreach (array(4,3,0,1,2,7) as $i) if ($a[$i] != $b[$i]) $match = false;
595 showLineItem($b[0], $b[1], $b[2], $b[3], $b[4], $b[5], $b[6], $b[7], $b[8]);
601 showLineItem($b[0], $b[1], $b[2], $b[3], $b[4], $b[5], $b[6], $b[7], $b[8]);
603 } // end by payer with details
605 // Print last method total.
607 <tr bgcolor
="#ddddff">
608 <td
class="detail" colspan
="<?php echo $showing_ppd ? 7 : 4; ?>">
609 <?php
echo xl('Total for ') . $paymethod ?
>
612 <?php
bucks($methodadjtotal) ?
>
615 <?php
bucks($methodpaytotal) ?
>
621 // Payer summary: need to sort and then print it all.
624 foreach ($insarray as $key => $value) {
625 if (empty($key)) $key = xl('Patient');
627 <tr bgcolor
="#ddddff">
628 <td
class="detail" colspan
="<?php echo $showing_ppd ? 7 : 4; ?>">
632 <?php
bucks($value[1]); ?
>
635 <?php
bucks($value[0]); ?
>
640 } // end payer summary
642 <tr bgcolor
="#ffdddd">
643 <td
class="detail" colspan
="<?php echo $showing_ppd ? 7 : 4; ?>">
644 <?php
xl('Grand Total','e') ?
>
647 <?php
bucks($grandadjtotal) ?
>
650 <?php
bucks($grandpaytotal) ?
>
655 } // end form refresh
656 if (!$INTEGRATED_AR) SLClose();
663 <?php
echo xl('Please input search criteria above, and click Submit to view results.', 'e' ); ?
>
670 <!-- stuff
for the popup calendar
-->
671 <link rel
='stylesheet' href
='<?php echo $css_header ?>' type
='text/css'>
672 <style type
="text/css">@import
url(../../library
/dynarch_calendar
.css
);</style
>
673 <script type
="text/javascript" src
="../../library/dynarch_calendar.js"></script
>
674 <?php
include_once("{$GLOBALS['srcdir']}/dynarch_calendar_en.inc.php"); ?
>
675 <script type
="text/javascript" src
="../../library/dynarch_calendar_setup.js"></script
>
676 <script type
="text/javascript" src
="../../library/js/jquery.1.3.2.js"></script
>
677 <script language
="Javascript">
678 Calendar
.setup({inputField
:"form_from_date", ifFormat
:"%Y-%m-%d", button
:"img_from_date"});
679 Calendar
.setup({inputField
:"form_to_date", ifFormat
:"%Y-%m-%d", button
:"img_to_date"});