From af29af55f6222fd1a46108e0754d9f1680a1e4e5 Mon Sep 17 00:00:00 2001 From: teryhill Date: Sat, 3 Oct 2015 12:47:33 -0400 Subject: [PATCH] Patient Ledger, take 3. --- interface/main/left_nav.php | 1 + interface/patient_file/summary/demographics.php | 3 + interface/reports/pat_ledger.php | 701 ++++++++++++++++++++++++ library/globals.inc.php | 16 + version.php | 2 +- 5 files changed, 722 insertions(+), 1 deletion(-) create mode 100644 interface/reports/pat_ledger.php diff --git a/interface/main/left_nav.php b/interface/main/left_nav.php index e274fb151..11d426ae6 100644 --- a/interface/main/left_nav.php +++ b/interface/main/left_nav.php @@ -1554,6 +1554,7 @@ if (!empty($reg)) { + diff --git a/interface/patient_file/summary/demographics.php b/interface/patient_file/summary/demographics.php index 357a3fbbd..18e96f0a3 100644 --- a/interface/patient_file/summary/demographics.php +++ b/interface/patient_file/summary/demographics.php @@ -586,6 +586,9 @@ if ($GLOBALS['patient_id_category_name']) { | +| + + + * + * LICENSE: This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see ;. + * + * @package OpenEMR + * @author WMT + * @author Terry Hill + * @link http://www.open-emr.org + */ + +$sanitize_all_escapes=true; +$fake_register_globals=false; +require_once('../globals.php'); +require_once($GLOBALS['srcdir'].'/patient.inc'); +require_once($GLOBALS['srcdir'].'/acl.inc'); +require_once($GLOBALS['srcdir'].'/formatting.inc.php'); +require_once($GLOBALS['srcdir'].'/options.inc.php'); +require_once($GLOBALS['srcdir'].'/formdata.inc.php'); +require_once($GLOBALS['srcdir'].'/appointments.inc.php'); + +$enc_units = $total_units = 0; +$enc_chg = $total_chg = 0; +$enc_pmt = $total_pmt = 0; +$enc_adj = $total_adj = 0; +$enc_bal = $total_bal = 0; +$bgcolor = "#FFFFDD"; +$orow = 0; + +$pat_pid = $_GET['patient_id']; +$type_form = $_GET['form']; + +if (! acl_check('acct', 'rep')) die(xlt("Unauthorized access.")); + +function GetAllUnapplied($pat='',$from_dt='',$to_dt='') { + $all = array(); + if(!$pat) return($all); + $sql = "SELECT ar_session.*, ins.name, " . + "pat.lname, pat.fname, pat.mname, " . + "(SELECT SUM(ar_activity.pay_amount) FROM ar_activity WHERE " . + "ar_activity.session_id = ar_session.session_id) AS applied " . + "FROM ar_session " . + "LEFT JOIN insurance_companies AS ins on ar_session.payer_id = ins.id " . + "LEFT JOIN patient_data AS pat on ar_session.patient_id = pat.pid " . + "WHERE " . + "ar_session.created_time >= ? AND ar_session.created_time <= ? " . + "AND ar_session.patient_id=?"; + $result = sqlStatement($sql, array($from_dt, $to_dt, $pat)); + $iter = 0; + while($row = sqlFetchArray($result)) { + $all[$iter] = $row; + $iter++; + } + return($all); +} + +function User_Id_Look($thisField) { + if(!$thisField) return ''; + $ret = ''; + $rlist= sqlStatement("SELECT lname, fname, mname FROM users WHERE id=?",array($thisField)); + $rrow= sqlFetchArray($rlist); + if($rrow) { + $ret = $rrow{'lname'}.', '.$rrow{'fname'}.' '.$rrow{'mname'}; + } + return $ret; +} + +function List_Look($thisData, $thisList) { + if($thisList == 'occurrence') { + if(!$thisData || $thisData == '') return xl('Unknown or N/A'); + } + if($thisData == '') return ''; + $fres=sqlStatement("SELECT title FROM list_options WHERE list_id=? ". + "AND option_id=?", array($thisList, $thisData)); + if($fres) { + $rret=sqlFetchArray($fres); + $dispValue= xl_list_label($rret{'title'}); + if($thisList == 'occurrence' && $dispValue == '') { + $dispValue = xl('Unknown or N/A'); + } + } else { + $dispValue= xl('Not Found'); + } + return $dispValue; +} + +function GetAllCredits($enc = '', $pat='') { + $all = array(); + if(!$enc || !$pat) return($all); + $sql = "SELECT activity.*, session.*, ins.name FROM ar_activity AS ". + "activity LEFT JOIN ar_session AS session USING (session_id) ". + "LEFT JOIN insurance_companies AS ins ON session.payer_id = ". + "ins.id WHERE encounter=? AND pid=? ". + "ORDER BY sequence_no"; + $result = sqlStatement($sql, array($enc, $pat)); + $iter = 0; + while($row = sqlFetchArray($result)) { + $all[$iter] = $row; + $iter++; + } + return($all); +} +function PrintEncHeader($dt, $rsn, $dr) { + global $bgcolor, $orow; + $bgcolor = (($bgcolor == "#FFFFDD") ? "#FFDDDD" : "#FFFFDD"); + echo ""; + if(strlen($rsn) > 50) $rsn = substr($rsn,0,50).'...'; + echo "".xlt('Encounter Dt / Rsn'). ": ".text(substr($dt,0,10))." / ".text($rsn).""; + echo "" . xlt('Provider'). ": ".text(User_Id_Look($dr)).""; + echo "\n"; + $orow++; +} +function PrintEncFooter() { + global $enc_units, $enc_chg, $enc_pmt, $enc_adj, $enc_bal; + echo ""; + echo " "; + echo "". xlt('Encounter Balance').":"; + echo "".text($enc_units).""; + echo "".text(oeFormatMoney($enc_chg)).""; + echo "".text(oeFormatMoney($enc_pmt)).""; + echo "".text(oeFormatMoney($enc_adj)).""; + echo "".text(oeFormatMoney($enc_bal)).""; + echo "\n"; +} +function PrintCreditDetail($detail, $pat, $unassigned=false) { + global $enc_pmt, $total_pmt, $enc_adj, $total_adj, $enc_bal, $total_bal; + global $bgcolor, $orow, $enc_units, $enc_chg; + foreach($detail as $pmt) { + if($unassigned) { + if(($pmt['pay_total'] - $pmt['applied']) == 0) continue; + } + $bgcolor = (($bgcolor == "#FFFFDD") ? "#FFDDDD" : "#FFFFDD"); + $print = ""; + $print .= " "; + $method = List_Look($pmt['payment_method'],'payment_method'); + $desc = $pmt['description']; + $ref = $pmt['reference']; + if($unassigned) { + $memo = List_Look($pmt['adjustment_code'],'payment_adjustment_code'); + } else { + $memo = $pmt['memo']; + } + $description = $method; + if($ref) { + if($description) { $description .= ' - '; } + $description .= $ref; + } + if($desc) { + if($description) { $description .= ': '; } + $description .= $desc; + } + if($memo) { + if($description) { $description .= ' '; } + $description .= '['.$memo.']'; + } + $print .= "". + text($description)." "; + $payer = ($pmt['name'] == '') ? xl('Patient') : $pmt['name']; + if($unassigned) { + $pmt_date = substr($pmt['post_to_date'],0,10); + } else { + $pmt_date = substr($pmt['post_time'],0,10); + } + $print .= "". + text($pmt_date)." / ".text($payer).""; + $type = List_Look($pmt['payment_type'],'payment_type'); + $print .= "".text($type)." "; + if($unassigned) { + $pmt_amt = $pmt['pay_total'] - $pmt['applied']; + $uac_bal = oeFormatMoney($pmt_amt * -1); + $uac_appl = oeFormatMoney($pmt['applied']); + $uac_total = oeFormatMoney($pmt['pay_total']); + $pmt_amt = $pmt['pay_total']; + $total_pmt = $total_pmt - $uac_bal; + } else { + $uac_total = ''; + $uac_bal = ''; + $uac_appl = ''; + $pmt_amt = $pmt['pay_amount']; + $adj_amt = $pmt['adj_amount']; + $enc_pmt = $enc_pmt + $pmt['pay_amount']; + $total_pmt = $total_pmt + $pmt['pay_amount']; + $enc_adj = $enc_adj + $pmt['adj_amount']; + $total_adj = $total_adj + $pmt['adj_amount']; + } + $print_pmt = ''; + if($pmt_amt != 0) $print_pmt = oeFormatMoney($pmt_amt); + $print_adj = ''; + if($adj_amt != 0) $print_adj = oeFormatMoney($adj_amt); + $print .= "".text($uac_appl)." "; + $print .= "".text($print_pmt)." "; + $print .= "".text($print_adj)." "; + $print .= "".text($uac_bal)." "; + $print .= "\n"; + echo $print; + if($pmt['follow_up_note'] != '') { + $bgcolor = (($bgcolor == "#FFFFDD") ? "#FFDDDD" : "#FFFFDD"); + $print = ""; + $print .= " "; + $print .= "". xlt('Follow Up Note') .": "; + $print .= text($pmt['follow_up_note']); + $print .= "\n"; + echo $print; + } + if($unassigned) { + $total_bal = $total_bal + $uac_bal; + } else { + $enc_bal = $enc_bal - $pmt_amt - $adj_amt; + $total_bal = $total_bal - $pmt_amt - $adj_amt; + } + $orow++; + } + $bgcolor = (($bgcolor == "#FFFFDD") ? "#FFDDDD" : "#FFFFDD"); +} +if(!isset($_REQUEST['form_from_date'])) { $_REQUEST['form_from_date'] = ''; } +if(!isset($_REQUEST['form_to_date'])) { $_REQUEST['form_to_date'] = ''; } +if(!isset($_REQUEST['form_facility'])) { $_REQUEST['form_facility'] = ''; } +if(!isset($_REQUEST['form_provider'])) { $_REQUEST['form_provider'] = ''; } +if($type_form=='0') { + if(!isset($_REQUEST['form_patient'])) { $_REQUEST['form_patient'] = ''; } + if(!isset($_REQUEST['form_pid'])) { $_REQUEST['form_pid'] = ''; } +} +else +{ + if(!isset($_REQUEST['form_patient'])) { $_REQUEST['form_patient'] = $pat_pid; } + if(!isset($_REQUEST['form_pid'])) { $_REQUEST['form_pid'] = $pat_pid; } +} +if(!isset($_REQUEST['form_csvexport'])) { $_REQUEST['form_csvexport'] = ''; } +if(!isset($_REQUEST['form_refresh'])) { $_REQUEST['form_refresh'] = ''; } +if(!isset($_REQUEST['$form_dob'])) { $_REQUEST['$form_dob'] = ''; } + +if (substr($GLOBALS['ledger_begin_date'],0,1) == 'Y') { + $ledger_time = substr($GLOBALS['ledger_begin_date'],1,1); + $last_year = mktime(0,0,0,date('m'),date('d'),date('Y')-$ledger_time); +} +elseif (substr($GLOBALS['ledger_begin_date'],0,1) == 'M') { + $ledger_time = substr($GLOBALS['ledger_begin_date'],1,1); + $last_year = mktime(0,0,0,date('m')-$ledger_time ,date('d'),date('Y')); +} +elseif (substr($GLOBALS['ledger_begin_date'],0,1) == 'D') { + $ledger_time = substr($GLOBALS['ledger_begin_date'],1,1); + $last_year = mktime(0,0,0,date('m') ,date('d')-$ledger_time,date('Y')); +} + +$form_from_date = date('Y-m-d', $last_year); +if($_REQUEST['form_from_date']) { + $form_from_date = fixDate($_REQUEST['form_from_date'], $last_year); +} +$form_to_date = fixDate($_REQUEST['form_to_date'] , date('Y-m-d')); +$form_facility = $_REQUEST['form_facility']; +$form_provider = $_REQUEST['form_provider']; +$form_patient = $_REQUEST['form_patient']; +$form_pid = $_REQUEST['form_pid']; +$form_dob = $_REQUEST['form_dob']; + +if ($_REQUEST['form_csvexport']) { + header("Pragma: public"); + header("Expires: 0"); + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); + header("Content-Type: application/force-download"); + header("Content-Disposition: attachment; filename=svc_financial_report_".attr($form_from_date)."--".attr($form_to_date).".csv"); + header("Content-Description: File Transfer"); +} else { +?> + + + + + + + + + + + + + +<?php echo xlt('Patient Ledger by Date') ?> + + + + + + + - + + + +
+
+ + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + +
+ : + + + :\n"; + echo "
+ :     + + [?] + + : + + + [?] + :   + ' onclick='sel_patient()' title='' /> + + + + + + +
+
+
+ + + + +
+ +
+
+
+ += ? AND fe.date <= ? AND fe.pid = ? "; + array_push($sqlBindArray,$from_date,$to_date,$form_pid); + if ($form_facility) { + $query .= "AND fe.facility_id = ? "; + array_push($sqlBindArray,$form_facility); + } + if ($form_provider) { + $query .= "AND b.provider_id = ? "; + array_push($sqlBindArray,$form_provider); + } + $query .= "AND c.ct_proc = '1' "; + $query .= "AND activity > 0 ORDER BY fe.date, fe.id "; + $res = sqlStatement($query,$sqlBindArray); + + if ($_REQUEST['form_csvexport']) { + // CSV headers: + if (true) { + echo '"Code/Enc Dt",'; + echo '"Description",'; + echo '"Billed/Who",'; + echo '"Type/Units",'; + echo '"Chg/Pmt Amount",'."\n"; + } + } else { + if(!$form_facility) $form_facility = '3'; + $facility = sqlQuery("SELECT * FROM facility WHERE id=?", array($form_facility)); + $patient = sqlQuery("SELECT * from patient_data WHERE pid=?", array($form_patient)); +?> +
+ + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + +
: + : + : + : +
+
+
+ + + + + + + + + + + + + + + + + + + + + + 0) { + if(!$hdr_printed) { + PrintEncHeader($prev_row{'date'}, + $prev_row{'reason'}, $prev_row{'provider_id'}); + } + PrintCreditDetail($credits, $form_pid); + } + if($hdr_printed) PrintEncFooter(); + $hdr_printed = false; + } + $enc_units = $enc_chg = $enc_pmt = $enc_adj = $enc_bal = 0; + } + if($erow{'id'}) { + // Now print an encounter heading line - + if(!$hdr_printed) { + PrintEncHeader($erow{'date'}, + $erow{'reason'}, $erow{'provider_id'}); + $hdr_printed = true; + } + + $code_desc = $erow['code_text']; + if(strlen($code_desc) > 50) $code_desc = substr($code_desc,0,50).'...'; + $bgcolor = (($bgcolor == "#FFFFDD") ? "#FFDDDD" : "#FFFFDD"); + $print = ""; + $print .= ""; + $print .= ""; + $who = ($erow['name'] == '') ? xl('Self') : $erow['name']; + $bill = substr($erow['bill_date'],0,10); + if($bill == '') { $bill = 'unbilled'; } + $print .= ""; + $print .= ""; + $print .= ""; + $print .= ""; + $print .= "\n"; + + $total_units += $erow['units']; + $total_chg += $erow['fee']; + $total_bal += $erow['fee']; + $enc_units += $erow['units']; + $enc_chg += $erow['fee']; + $enc_bal += $erow['fee']; + $orow++; + + if ($_REQUEST['form_csvexport']) { + echo $csv; + } else { + echo $print; + } + } + $prev_encounter_id = $erow{'encounter'}; + $prev_row = $erow; + } + if($prev_encounter_id != -1) { + $credits = GetAllCredits($prev_encounter_id, $form_pid); + if(count($credits) > 0) { + if(!$hdr_printed) { + PrintEncHeader($prev_row{'date'}, + $prev_row{'reason'}, $prev_row{'provider_id'}); + } + PrintCreditDetail($credits, $form_pid); + } + if($hdr_printed) PrintEncFooter(); + } + // This is the end of the encounter/charge loop - + $uac = GetAllUnapplied($form_pid,$from_date,$to_date); + if(count($uac) > 0) { + if($orow) { + $bgcolor = (($bgcolor == "#FFFFDD") ? "#FFDDDD" : "#FFFFDD"); + echo "\n"; + } + PrintCreditDetail($uac, $form_pid, true); + } + if (!$_REQUEST['form_csvexport'] && $orow) { + echo "\n"; + echo " "; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + echo " \n"; + ?> +
/         +                
                     +              
".text($erow['code'])."".text($code_desc)."".text($bill)." / ".text($who)."". text($erow['units'])."". text(oeFormatMoney($erow['fee']))."   
 
 " . xlt("Grand Total") ."". text($total_units) ."  ". text(oeFormatMoney($total_chg)) ." ". text(oeFormatMoney($total_pmt)) ." ". text(oeFormatMoney($total_adj)) ." ". text(oeFormatMoney($total_bal)) . " 
+ \n"; +} +if (! $_REQUEST['form_csvexport']) { + if ( $_REQUEST['form_refresh'] && $orow <= 0) { + echo ""; + echo xlt('No matches found. Try search again.'); + echo ""; + echo ''; + echo ''; + } + +if (!$_REQUEST['form_refresh'] && !$_REQUEST['form_csvexport']) { ?> +
+ +
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/library/globals.inc.php b/library/globals.inc.php index c6bf1429f..7b47df084 100644 --- a/library/globals.inc.php +++ b/library/globals.inc.php @@ -91,6 +91,7 @@ else { // List of user specific tabs and globals $USER_SPECIFIC_TABS = array('Appearance', 'Locale', + 'Features', 'Calendar', 'Connectors'); $USER_SPECIFIC_GLOBALS = array('default_top_pane', @@ -103,6 +104,7 @@ $USER_SPECIFIC_GLOBALS = array('default_top_pane', 'us_weight_format', 'date_display_format', 'time_display_format', + 'ledger_begin_date', 'calendar_view_type', 'event_color', 'pat_trkr_timer', @@ -753,6 +755,20 @@ $GLOBALS_METADATA = array( xl('This specifies the Printing of the Custom End of Day Report grouped Provider or allow the Printing of Totals Only') ), + 'ledger_begin_date' => array( + xl('Beginning Date for Ledger Report'), + array( + 'Y1' => xl('One Year Ago'), + 'Y2' => xl('Two Years Ago'), + 'M6' => xl('Six Months Ago'), + 'M3' => xl('Three Months Ago'), + 'M1' => xl('One Month Ago'), + 'D1' => xl('One Day Ago'), + ), + 'Y1', // default = One Year + xl('This is the Beginning date for the Ledger Report.') + ), + ), // E-Sign Tab // diff --git a/version.php b/version.php index beceaa676..c05f9ccb5 100644 --- a/version.php +++ b/version.php @@ -17,7 +17,7 @@ $v_realpatch = '0'; // is a database change in the course of development. It is used // internally to determine when a database upgrade is needed. // -$v_database = 138; +$v_database = 139; // Access control version identifier, this is to be incremented whenever there // is a access control change in the course of development. It is used -- 2.11.4.GIT