migrated ubiquitous libraries to composer autoloader (#421)
[openemr.git] / interface / reports / receipts_by_method_report.php
blob43f94587ca6d1f74892bed8d08fa382cf7e2d191
1 <?php
2 // Copyright (C) 2006-2016 Rod Roark <rod@sunsetsystems.com>
3 //
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/acl.inc");
21 require_once("$srcdir/formatting.inc.php");
22 require_once "$srcdir/options.inc.php";
23 require_once("../../custom/code_types.inc.php");
25 // This controls whether we show pt name, policy number and DOS.
26 $showing_ppd = true;
28 $insarray = array();
30 function bucks($amount) {
31 if ($amount) echo oeFormatMoney($amount);
34 function thisLineItem($patient_id, $encounter_id, $memo, $transdate,
35 $rowmethod, $rowpayamount, $rowadjamount, $payer_type=0, $irnumber='')
37 global $form_report_by, $insarray, $grandpaytotal, $grandadjtotal;
39 if ($form_report_by != '1') { // reporting by method or check number
40 showLineItem($patient_id, $encounter_id, $memo, $transdate,
41 $rowmethod, $rowpayamount, $rowadjamount, $payer_type, $irnumber);
42 return;
45 // Reporting by payer.
47 if ($_POST['form_details']) { // details are wanted
48 // Save everything for later sorting.
49 $insarray[] = array($patient_id, $encounter_id, $memo, $transdate,
50 $rowmethod, $rowpayamount, $rowadjamount, $payer_type, $irnumber);
52 else { // details not wanted
53 if (empty($insarray[$rowmethod])) $insarray[$rowmethod] = array(0, 0);
54 $insarray[$rowmethod][0] += $rowpayamount;
55 $insarray[$rowmethod][1] += $rowadjamount;
56 $grandpaytotal += $rowpayamount;
57 $grandadjtotal += $rowadjamount;
61 function showLineItem($patient_id, $encounter_id, $memo, $transdate,
62 $rowmethod, $rowpayamount, $rowadjamount, $payer_type=0, $irnumber='')
64 global $paymethod, $paymethodleft, $methodpaytotal, $methodadjtotal,
65 $grandpaytotal, $grandadjtotal, $showing_ppd;
67 if (! $rowmethod) $rowmethod = 'Unknown';
69 $invnumber = $irnumber ? $irnumber : "$patient_id.$encounter_id";
71 if ($paymethod != $rowmethod) {
72 if ($paymethod) {
73 // Print method total.
76 <tr bgcolor="#ddddff">
77 <td class="detail" colspan="<?php echo $showing_ppd ? 7 : 4; ?>">
78 <?php echo xl('Total for ') . $paymethod ?>
79 </td>
80 <td align="right">
81 <?php bucks($methodadjtotal) ?>
82 </td>
83 <td align="right">
84 <?php bucks($methodpaytotal) ?>
85 </td>
86 </tr>
87 <?php
89 $methodpaytotal = 0;
90 $methodadjtotal = 0;
91 $paymethod = $rowmethod;
92 $paymethodleft = $paymethod;
95 if ($_POST['form_details']) {
98 <tr>
99 <td class="detail">
100 <?php echo $paymethodleft; $paymethodleft = "&nbsp;" ?>
101 </td>
102 <td>
103 <?php echo oeFormatShortDate($transdate) ?>
104 </td>
105 <td class="detail">
106 <?php echo $invnumber ?>
107 </td>
109 <?php
110 if ($showing_ppd) {
111 $pferow = sqlQuery("SELECT p.fname, p.mname, p.lname, fe.date " .
112 "FROM patient_data AS p, form_encounter AS fe WHERE " .
113 "p.pid = '$patient_id' AND fe.pid = p.pid AND " .
114 "fe.encounter = '$encounter_id' LIMIT 1");
115 $dos = substr($pferow['date'], 0, 10);
117 echo " <td class='dehead'>\n";
118 echo " " . $pferow['lname'] . ", " . $pferow['fname'] . " " . $pferow['mname'];
119 echo " </td>\n";
121 echo " <td class='dehead'>\n";
122 if ($payer_type) {
123 $ptarr = array(1 => 'primary', 2 => 'secondary', 3 => 'tertiary');
124 $insrow = getInsuranceDataByDate($patient_id, $dos,
125 $ptarr[$payer_type], "policy_number");
126 echo " " . $insrow['policy_number'];
128 echo " </td>\n";
130 echo " <td class='dehead'>\n";
131 echo " " . oeFormatShortDate($dos) . "\n";
132 echo " </td>\n";
136 <td>
137 <?php echo $memo ?>
138 </td>
139 <td align="right">
140 <?php bucks($rowadjamount) ?>
141 </td>
142 <td align="right">
143 <?php bucks($rowpayamount) ?>
144 </td>
145 </tr>
146 <?php
148 $methodpaytotal += $rowpayamount;
149 $grandpaytotal += $rowpayamount;
150 $methodadjtotal += $rowadjamount;
151 $grandadjtotal += $rowadjamount;
154 // This is called by usort() when reporting by payer with details.
155 // Sorts by payer/date/patient/encounter/memo.
156 function payerCmp($a, $b) {
157 foreach (array(4,3,0,1,2,7) as $i) {
158 if ($a[$i] < $b[$i]) return -1;
159 if ($a[$i] > $b[$i]) return 1;
161 return 0;
164 if (! acl_check('acct', 'rep')) die(xl("Unauthorized access."));
167 $form_from_date = fixDate($_POST['form_from_date'], date('Y-m-d'));
168 $form_to_date = fixDate($_POST['form_to_date'] , date('Y-m-d'));
169 $form_use_edate = $_POST['form_use_edate'];
170 $form_facility = $_POST['form_facility'];
171 $form_report_by = $_POST['form_report_by'];
172 $form_proc_codefull = trim($_POST['form_proc_codefull']);
173 // Parse the code type and the code from <code_type>:<code>
174 $tmp_code_array = explode(':',$form_proc_codefull);
175 $form_proc_codetype = $tmp_code_array[0];
176 $form_proc_code = $tmp_code_array[1];
179 <html>
180 <head>
182 <?php if (function_exists('html_header_show')) html_header_show(); ?>
183 <style type="text/css">
184 /* specifically include & exclude from printing */
185 @media print {
186 #report_parameters {
187 visibility: hidden;
188 display: none;
190 #report_parameters_daterange {
191 visibility: visible;
192 display: inline;
194 #report_results {
195 margin-top: 30px;
199 /* specifically exclude some from the screen */
200 @media screen {
201 #report_parameters_daterange {
202 visibility: hidden;
203 display: none;
207 table.mymaintable, table.mymaintable td {
208 border: 1px solid #aaaaaa;
209 border-collapse: collapse;
211 table.mymaintable td {
212 padding: 1pt 4pt 1pt 4pt;
214 </style>
216 <script type="text/javascript" src="../../library/dialog.js?v=<?php echo $v_js_includes; ?>"></script>
217 <script type="text/javascript" src="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery-min-1-9-1/index.js"></script>
218 <script type="text/javascript" src="../../library/js/report_helper.js?v=<?php echo $v_js_includes; ?>"></script>
220 <script language="JavaScript">
222 $(document).ready(function() {
223 oeFixedHeaderSetup(document.getElementById('mymaintable'));
224 var win = top.printLogSetup ? top : opener.top;
225 win.printLogSetup(document.getElementById('printbutton'));
228 // This is for callback by the find-code popup.
229 // Erases the current entry
230 function set_related(codetype, code, selector, codedesc) {
231 var f = document.forms[0];
232 var s = f.form_proc_codefull.value;
233 if (code) {
234 s = codetype + ':' + code;
235 } else {
236 s = '';
238 f.form_proc_codefull.value = s;
241 // This invokes the find-code popup.
242 function sel_procedure() {
243 dlgopen('../patient_file/encounter/find_code_popup.php?codetype=<?php echo attr(collect_codetypes("procedure","csv")) ?>', '_blank', 500, 400);
246 </script>
248 <title><?xl('Receipts Summary','e')?></title>
249 </head>
251 <body class="body_top">
253 <span class='title'><?php xl('Report','e'); ?> - <?php xl('Receipts Summary','e'); ?></span>
255 <form method='post' action='receipts_by_method_report.php' id='theform'>
257 <div id="report_parameters">
259 <input type='hidden' name='form_refresh' id='form_refresh' value=''/>
261 <table>
262 <tr>
263 <td width='630px'>
264 <div style='float:left'>
266 <table class='text'>
267 <tr>
268 <td class='label'>
269 <?php xl('Report by','e'); ?>
270 </td>
271 <td>
272 <?php
273 echo " <select name='form_report_by'>\n";
274 foreach (array(1 => 'Payer', 2 => 'Payment Method', 3 => 'Check Number') as $key => $value) {
275 echo " <option value='$key'";
276 if ($key == $form_report_by) echo ' selected';
277 echo ">" . xl($value) . "</option>\n";
279 echo " </select>&nbsp;\n"; ?>
280 </td>
282 <td>
283 <?php dropdown_facility(strip_escape_custom($form_facility), 'form_facility', false); ?>
284 </td>
286 <td>
287 <?php if (!$GLOBALS['simplified_demographics']) echo '&nbsp;' . xl('Procedure/Service') . ':'; ?>
288 </td>
289 <td>
290 <input type='text' name='form_proc_codefull' size='12' value='<?php echo $form_proc_codefull; ?>' onclick='sel_procedure()'
291 title='<?php xl('Click to select optional procedure code','e'); ?>'
292 <?php if ($GLOBALS['simplified_demographics']) echo "style='display:none'"; ?> />
293 <br>
294 &nbsp;<input type='checkbox' name='form_details' value='1'<?php if ($_POST['form_details']) echo " checked"; ?> /><?xl('Details','e')?>
295 </td>
296 </tr>
297 <tr>
298 <td>&nbsp;</td>
299 <td>
300 <select name='form_use_edate'>
301 <option value='0'><?php xl('Payment Date','e'); ?></option>
302 <option value='1'<?php if ($form_use_edate) echo ' selected' ?>><?php xl('Invoice Date','e'); ?></option>
303 </select>
304 </td>
305 <td>
306 <input type='text' name='form_from_date' id="form_from_date" size='10' value='<?php echo $form_from_date ?>'
307 onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)' title='yyyy-mm-dd'>
308 <img src='../pic/show_calendar.gif' align='absbottom' width='24' height='22'
309 id='img_from_date' border='0' alt='[?]' style='cursor:pointer'
310 title='<?php xl('Click here to choose a date','e'); ?>'>
311 </td>
312 <td class='label'>
313 <?php xl('To','e'); ?>:
314 </td>
315 <td>
316 <input type='text' name='form_to_date' id="form_to_date" size='10' value='<?php echo $form_to_date ?>'
317 onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)' title='yyyy-mm-dd'>
318 <img src='../pic/show_calendar.gif' align='absbottom' width='24' height='22'
319 id='img_to_date' border='0' alt='[?]' style='cursor:pointer'
320 title='<?php xl('Click here to choose a date','e'); ?>'>
321 </td>
322 </tr>
323 </table>
325 </div>
327 </td>
328 <td align='left' valign='middle' height="100%">
329 <table style='border-left:1px solid; width:100%; height:100%' >
330 <tr>
331 <td>
332 <div style='margin-left:15px'>
333 <a href='#' class='css_button' onclick='$("#form_refresh").attr("value","true"); $("#theform").submit();'>
334 <span>
335 <?php xl('Submit','e'); ?>
336 </span>
337 </a>
339 <?php if ($_POST['form_refresh']) { ?>
340 <a href='#' class='css_button' id='printbutton'>
341 <span>
342 <?php xl('Print','e'); ?>
343 </span>
344 </a>
345 <?php } ?>
346 </div>
347 </td>
348 </tr>
349 </table>
350 </td>
351 </tr>
352 </table>
354 </div> <!-- end of parameters -->
356 <?php
357 if ($_POST['form_refresh']) {
359 <div id="report_results">
361 <table width='98%' id='mymaintable' class='mymaintable'>
363 <thead>
364 <tr bgcolor="#dddddd">
365 <th>
366 <?php xl('Method','e') ?>
367 </th>
368 <th>
369 <?php xl('Date','e') ?>
370 </th>
371 <th>
372 <?php xl('Invoice','e') ?>
373 </th>
374 <?php if ($showing_ppd) { ?>
375 <th>
376 <?xl('Patient','e')?>
377 </th>
378 <th>
379 <?xl('Policy','e')?>
380 </th>
381 <th>
382 <?xl('DOS','e')?>
383 </th>
384 <?php } ?>
385 <th>
386 <?xl('Procedure','e')?>
387 </th>
388 <th align="right">
389 <?xl('Adjustments','e')?>
390 </th>
391 <th align="right">
392 <?xl('Payments','e')?>
393 </th>
394 </tr>
395 </thead>
396 <tbody>
397 <?php
399 if ($_POST['form_refresh']) {
400 $from_date = $form_from_date;
401 $to_date = $form_to_date;
403 $paymethod = "";
404 $paymethodleft = "";
405 $methodpaytotal = 0;
406 $grandpaytotal = 0;
407 $methodadjtotal = 0;
408 $grandadjtotal = 0;
411 // Get co-pays using the encounter date as the pay date. These will
412 // always be considered patient payments. Ignored if selecting by
413 // billing code.
415 if (!$form_proc_code || !$form_proc_codetype) {
416 $query = "SELECT b.fee, b.pid, b.encounter, b.code_type, " .
417 "fe.date, fe.facility_id, fe.invoice_refno " .
418 "FROM billing AS b " .
419 "JOIN form_encounter AS fe ON fe.pid = b.pid AND fe.encounter = b.encounter " .
420 "WHERE b.code_type = 'COPAY' AND b.activity = 1 AND b.fee != 0 AND " .
421 "fe.date >= '$from_date 00:00:00' AND fe.date <= '$to_date 23:59:59'";
422 // If a facility was specified.
423 if ($form_facility) $query .= " AND fe.facility_id = '$form_facility'";
424 $query .= " ORDER BY fe.date, b.pid, b.encounter, fe.id";
426 $res = sqlStatement($query);
427 while ($row = sqlFetchArray($res)) {
428 $rowmethod = $form_report_by == 1 ? 'Patient' : 'Co-Pay';
429 thisLineItem($row['pid'], $row['encounter'], $row['code_text'],
430 substr($row['date'], 0, 10), $rowmethod, 0 - $row['fee'], 0, 0, $row['invoice_refno']);
432 } // end if not form_proc_code
434 // Get all other payments and adjustments and their dates, corresponding
435 // payers and check reference data, and the encounter dates separately.
437 $query = "SELECT a.pid, a.encounter, a.post_time, a.pay_amount, " .
438 "a.adj_amount, a.memo, a.session_id, a.code, a.payer_type, fe.id, fe.date, " .
439 "fe.invoice_refno, s.deposit_date, s.payer_id, s.reference, i.name " .
440 "FROM ar_activity AS a " .
441 "JOIN form_encounter AS fe ON fe.pid = a.pid AND fe.encounter = a.encounter " .
442 "JOIN forms AS f ON f.pid = a.pid AND f.encounter = a.encounter AND f.formdir = 'newpatient' " .
443 "LEFT JOIN ar_session AS s ON s.session_id = a.session_id " .
444 "LEFT JOIN insurance_companies AS i ON i.id = s.payer_id " .
445 "WHERE ( a.pay_amount != 0 OR a.adj_amount != 0 )";
447 if ($form_use_edate) {
448 $query .= " AND fe.date >= '$from_date 00:00:00' AND fe.date <= '$to_date 23:59:59'";
449 } else {
450 $query .= " AND ( ( s.deposit_date IS NOT NULL AND " .
451 "s.deposit_date >= '$from_date' AND s.deposit_date <= '$to_date' ) OR " .
452 "( s.deposit_date IS NULL AND a.post_time >= '$from_date 00:00:00' AND " .
453 "a.post_time <= '$to_date 23:59:59' ) )";
455 // If a procedure code was specified.
456 if ($form_proc_code && $form_proc_codetype) {
457 // 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.
458 $query .= " AND ( a.code_type = '$form_proc_codetype' OR a.code_type = '' ) AND a.code LIKE '$form_proc_code%'";
460 // If a facility was specified.
461 if ($form_facility) $query .= " AND fe.facility_id = '$form_facility'";
463 if ($form_use_edate) {
464 $query .= " ORDER BY s.reference, fe.date, a.pid, a.encounter, fe.id";
465 } else {
466 $query .= " ORDER BY s.reference, s.deposit_date, a.post_time, a.pid, a.encounter, fe.id";
469 $res = sqlStatement($query);
470 while ($row = sqlFetchArray($res)) {
471 if ($form_use_edate) {
472 $thedate = substr($row['date'], 0, 10);
473 } else if (!empty($row['deposit_date'])) {
474 $thedate = $row['deposit_date'];
475 } else {
476 $thedate = substr($row['post_time'], 0, 10);
478 // Compute reporting key: insurance company name or payment method.
479 if ($form_report_by == '1') {
480 if (empty($row['payer_id'])) {
481 $rowmethod = '';
482 } else {
483 if (empty($row['name'])) $rowmethod = xl('Unnamed insurance company');
484 else $rowmethod = $row['name'];
487 else {
488 if (empty($row['session_id'])) {
489 $rowmethod = trim($row['memo']);
490 } else {
491 $rowmethod = trim($row['reference']);
493 if ($form_report_by != '3') {
494 // Extract only the first word as the payment method because any
495 // following text will be some petty detail like a check number.
496 $rowmethod = substr($rowmethod, 0, strcspn($rowmethod, ' /'));
500 thisLineItem($row['pid'], $row['encounter'], $row['code'], $thedate,
501 $rowmethod, $row['pay_amount'], $row['adj_amount'], $row['payer_type'],
502 $row['invoice_refno']);
505 // Not payer summary.
506 if ($form_report_by != '1' || $_POST['form_details']) {
508 if ($form_report_by == '1') { // by payer with details
509 // Sort and dump saved info, and consolidate items with all key
510 // fields being the same.
511 usort($insarray, 'payerCmp');
512 $b = array();
513 foreach ($insarray as $a) {
514 if (empty($a[4])) $a[4] = xl('Patient');
515 if (empty($b)) {
516 $b = $a;
518 else {
519 $match = true;
520 foreach (array(4,3,0,1,2,7) as $i) if ($a[$i] != $b[$i]) $match = false;
521 if ($match) {
522 $b[5] += $a[5];
523 $b[6] += $a[6];
524 } else {
525 showLineItem($b[0], $b[1], $b[2], $b[3], $b[4], $b[5], $b[6], $b[7], $b[8]);
526 $b = $a;
530 if (!empty($b)) {
531 showLineItem($b[0], $b[1], $b[2], $b[3], $b[4], $b[5], $b[6], $b[7], $b[8]);
533 } // end by payer with details
535 // Print last method total.
537 <tr bgcolor="#ddddff">
538 <td class="detail" colspan="<?php echo $showing_ppd ? 7 : 4; ?>">
539 <?php echo xl('Total for ') . $paymethod ?>
540 </td>
541 <td align="right">
542 <?php bucks($methodadjtotal) ?>
543 </td>
544 <td align="right">
545 <?php bucks($methodpaytotal) ?>
546 </td>
547 </tr>
548 <?php
551 // Payer summary: need to sort and then print it all.
552 else {
553 ksort($insarray);
554 foreach ($insarray as $key => $value) {
555 if (empty($key)) $key = xl('Patient');
557 <tr bgcolor="#ddddff">
558 <td class="detail" colspan="<?php echo $showing_ppd ? 7 : 4; ?>">
559 <?php echo $key; ?>
560 </td>
561 <td align="right">
562 <?php bucks($value[1]); ?>
563 </td>
564 <td align="right">
565 <?php bucks($value[0]); ?>
566 </td>
567 </tr>
568 <?php
569 } // end foreach
570 } // end payer summary
572 <tr bgcolor="#ffdddd">
573 <td class="detail" colspan="<?php echo $showing_ppd ? 7 : 4; ?>">
574 <?php xl('Grand Total','e') ?>
575 </td>
576 <td align="right">
577 <?php bucks($grandadjtotal) ?>
578 </td>
579 <td align="right">
580 <?php bucks($grandpaytotal) ?>
581 </td>
582 </tr>
584 <?php
585 } // end form refresh
588 </tbody>
589 </table>
590 </div>
591 <?php } else { ?>
592 <div class='text'>
593 <?php echo xl('Please input search criteria above, and click Submit to view results.', 'e' ); ?>
594 </div>
595 <?php } ?>
597 </form>
598 </body>
600 <!-- stuff for the popup calendar -->
601 <link rel='stylesheet' href='<?php echo $css_header ?>' type='text/css'>
602 <style type="text/css">@import url(../../library/dynarch_calendar.css);</style>
603 <script type="text/javascript" src="../../library/dynarch_calendar.js"></script>
604 <?php include_once("{$GLOBALS['srcdir']}/dynarch_calendar_en.inc.php"); ?>
605 <script type="text/javascript" src="../../library/dynarch_calendar_setup.js"></script>
606 <script language="Javascript">
607 Calendar.setup({inputField:"form_from_date", ifFormat:"%Y-%m-%d", button:"img_from_date"});
608 Calendar.setup({inputField:"form_to_date", ifFormat:"%Y-%m-%d", button:"img_to_date"});
609 </script>
611 </html>