4 * Patient Flow Board (Patient Tracker) (Report Based on the appointment report)
6 * This program used to select and print the information captured in the Patient Flow Board program,
7 * allowing the user to select and print the desired information.
10 * @link http://www.open-emr.org
11 * @author Terry Hill <terry@lilysystems.com>
12 * @author Brady Miller <brady.g.miller@gmail.com>
13 * @copyright Copyright (c) 2015 Terry Hill <terry@lillysystems.com>
14 * @copyright Copyright (c) 2017-2018 Brady Miller <brady.g.miller@gmail.com>
15 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
18 require_once("../globals.php");
19 require_once("../../library/patient.inc.php");
20 require_once "$srcdir/options.inc.php";
21 require_once "$srcdir/appointments.inc.php";
22 require_once("$srcdir/patient_tracker.inc.php");
24 use OpenEMR\Common\Csrf\CsrfUtils
;
25 use OpenEMR\Core\Header
;
28 if (!CsrfUtils
::verifyCsrfToken($_POST["csrf_token_form"])) {
29 CsrfUtils
::csrfNotVerified();
33 $patient = $_POST['patient'] ??
null;
35 if ($patient && !isset($_POST['form_from_date'])) {
36 // If a specific patient, default to 2 years ago.
38 $from_date = date("$tmp-m-d");
39 $to_date = date('Y-m-d');
41 $from_date = isset($_POST['form_from_date']) ?
DateToYYYYMMDD($_POST['form_from_date']) : date('Y-m-d');
42 $to_date = isset($_POST['form_to_date']) ?
DateToYYYYMMDD($_POST['form_to_date']) : date('Y-m-d');
45 # check box information
46 $chk_show_details = false;
47 if (!empty($_POST['show_details'])) {
48 $chk_show_details = true;
51 $chk_show_drug_screens = false;
52 if (!empty($_POST['show_drug_screens'])) {
53 $chk_show_drug_screens = true;
56 $chk_show_completed_drug_screens = false;
57 if (!empty($_POST['show_completed_drug_screens'])) {
58 $chk_show_completed_drug_screens = true;
61 # end check box information
63 $provider = $_POST['form_provider'] ??
null;
64 $facility = $_POST['form_facility'] ??
null; #(CHEMED) facility filter
65 $form_orderby = (!empty($_POST['form_orderby']) && getComparisonOrder($_POST['form_orderby'])) ?
$_POST['form_orderby'] : 'date';
66 if (!empty($_POST["form_patient"])) {
67 $form_patient = isset($_POST['form_patient']) ?
$_POST['form_patient'] : '';
70 $form_pid = isset($_POST['form_pid']) ?
$_POST['form_pid'] : '';
71 if (empty($form_patient)) {
79 <title
><?php
echo xlt('Patient Flow Board Report'); ?
></title
>
81 <?php Header
::setupHeader(['datetime-picker', 'report-helper']); ?
>
85 var win
= top
.printLogSetup ? top
: opener
.top
;
86 win
.printLogSetup(document
.getElementById('printbutton'));
88 $
('.datepicker').datetimepicker({
89 <?php
$datetimepicker_timepicker = false; ?
>
90 <?php
$datetimepicker_showseconds = false; ?
>
91 <?php
$datetimepicker_formatInput = true; ?
>
92 <?php
require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?
>
93 <?php
// can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
97 function dosort(orderby
) {
98 var f
= document
.forms
[0];
99 f
.form_orderby
.value
= orderby
;
104 // CapMinds :: invokes find-patient popup.
105 function sel_patient() {
106 dlgopen('../main/calendar/find_patient_popup.php?pflag=0', '_blank', 500, 400);
109 // CapMinds :: callback by the find-patient popup.
110 function setpatient(pid
, lname
, fname
, dob
) {
111 var f
= document
.theform
;
112 f
.form_patient
.value
= lname +
', ' + fname
;
113 f
.form_pid
.value
= pid
;
118 /* specifically include & exclude from printing */
124 #report_parameters_daterange {
128 #report_results table {
133 /* specifically exclude some from the screen */
135 #report_parameters_daterange {
143 <body
class="body_top">
145 <!-- Required
for the popup date selectors
-->
147 style
="position: absolute; visibility: hidden; z-index: 1000;"></div
>
148 <?php
if ($GLOBALS['drug_screen']) { #setting the title of the page based o if drug screening is enabled ?>
149 <span
class='title'><?php
echo xlt('Patient Flow Board'); ?
> - <?php
echo xlt('Drug Screen Report'); ?
></span
>
151 <span
class='title'><?php
echo xlt('Patient Flow Board Report'); ?
></span
>
155 <div id
="report_parameters_daterange"><?php
echo text(oeFormatShortDate($from_date)) . " " . xlt('to{{Range}}') . " " . text(oeFormatShortDate($to_date)); #sets date range for calendars ?>
158 <form method
='post' name
='theform' id
='theform' action
='patient_flow_board_report.php' onsubmit
='return top.restoreSession()'>
159 <input type
="hidden" name
="csrf_token_form" value
="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
161 <div id
="report_parameters">
166 <div style
='float: left'>
170 <td
class='col-form-label'><?php
echo xlt('Facility'); ?
>:</td
>
171 <td
><?php
dropdown_facility($facility, 'form_facility'); ?
>
173 <td
class='col-form-label'><?php
echo xlt('Provider'); ?
>:</td
>
176 # Build a drop-down list of providers.
179 $query = "SELECT id, lname, fname FROM users WHERE " .
180 "authorized = 1 ORDER BY lname, fname"; #(CHEMED) facility filter
182 $ures = sqlStatement($query);
184 echo " <select name='form_provider' class='form-control'>\n";
185 echo " <option value=''>-- " . xlt('All') . " --\n";
187 while ($urow = sqlFetchArray($ures)) {
188 $provid = $urow['id'];
189 echo " <option value='" . attr($provid) . "'";
190 if (!empty($_POST['form_provider']) && ($provid == $_POST['form_provider'])) {
194 echo ">" . text($urow['lname']) . ", " . text($urow['fname']) . "\n";
204 <td
class='col-form-label'><?php
echo xlt('From'); ?
>:</td
>
205 <td
><input type
='text' name
='form_from_date' id
="form_from_date" class='datepicker form-control' size
='10' value
='<?php echo attr(oeFormatShortDate($from_date)); ?>'>
207 <td
class='col-form-label'><?php
echo xlt('To{{Range}}'); ?
>:</td
>
208 <td
><input type
='text' name
='form_to_date' id
="form_to_date" class='datepicker form-control' size
='10' value
='<?php echo attr(oeFormatShortDate($to_date)); ?>'>
213 <td
class='col-form-label'><?php
echo xlt('Status'); # status code drop down creation ?>:</td>
214 <td
><?php
generate_form_field(array('data_type' => 1,'field_id' => 'apptstatus','list_id' => 'apptstat','empty_title' => 'All'), ($_POST['form_apptstatus'] ??
''));?
></td
>
215 <td
><?php
echo xlt('Category') #category drop down creation ?>:</td>
217 <select id
="form_apptcat" name
="form_apptcat" class="form-control">
219 $categories = fetchAppointmentCategories();
220 echo "<option value='ALL'>" . xlt("All") . "</option>";
221 while ($cat = sqlFetchArray($categories)) {
222 echo "<option value='" . attr($cat['id']) . "'";
223 if (!empty($_POST['form_apptcat']) && ($cat['id'] == $_POST['form_apptcat'])) {
224 echo " selected='true' ";
227 echo ">" . text(xl_appt_category($cat['category'])) . "</option>";
235  
; 
;<span
class='text'><?php
echo xlt('Patient'); ?
>: </span
>
238 <input type
='text' size
='20' name
='form_patient' class='form-control' style
='cursor:pointer' value
='<?php echo (!empty($form_patient)) ? attr($form_patient) : xla('Click To Select
'); ?>' onclick
='sel_patient()' title
='<?php echo xla('Click to select patient
'); ?>' />
239 <input type
='hidden' name
='form_pid' value
='<?php echo attr($form_pid); ?>' />
243 <div
class="checkbox">
244 <label
><input type
="checkbox" name
="show_details" id
="show_details" <?php
echo ($chk_show_details) ?
"checked" : ""; ?
>> 
;<?php
echo xlt('Show Details'); ?
></label
>
251 <?php
if ($GLOBALS['drug_screen']) { ?
>
253 <?php
# these two selects will are for the drug screen entries the Show Selected for Drug Screens will show all
254 # that have a yes for selected. If you just check the Show Status of Drug Screens all drug screens will be displayed
255 # if both are selected then only completed drug screens will be displayed. ?>
257 <div
class="checkbox">
258 <label
><input type
="checkbox" name
="show_drug_screens" id
="show_drug_screens" <?php
echo ($chk_show_drug_screens) ?
"checked" : ""; ?
>> 
;<?php
echo xlt('Show Selected for Drug Screens'); ?
></label
>
262 <div
class="checkbox">
263 <label
><input type
="checkbox" name
="show_completed_drug_screens" id
="show_completed_drug_screens" <?php
echo ($chk_show_completed_drug_screens) ?
"checked" : ""; ?
>> 
;<?php
echo xlt('Show Status of Drug Screens'); ?
></label
>
274 <td
class='h-100' align
='left' valign
='middle'>
275 <table
class='w-100 h-100' style
='border-left: 1px solid;'>
278 <div
class="text-center">
279 <div
class="btn-group" role
="group">
280 <a href
='#' class='btn btn-secondary btn-save' onclick
='$("#form_refresh").attr("value","true"); $("#theform").submit();'>
281 <?php
echo xlt('Submit'); ?
>
283 <?php
if (!empty($_POST['form_refresh']) ||
!empty($_POST['form_orderby'])) { ?
>
284 <a href
='#' class='btn btn-secondary btn-print' id
='printbutton'>
285 <?php
echo xlt('Print'); ?
>
292 <tr
> 
; 
;<?php
echo xlt('Most column headers can be clicked to change sort order') ?
></tr
>
299 <!-- end of search parameters
--> <?php
300 if (!empty($_POST['form_refresh']) ||
!empty($_POST['form_orderby'])) {
302 <div id
="report_results">
303 <table
class='table'>
304 <thead
class='thead-light'>
305 <?php
if (!$chk_show_drug_screens && !$chk_show_completed_drug_screens) { # the first part of this block is for the Patient Flow Board report ?>
306 <th
><a href
="nojs.php" onclick
="return dosort('doctor')"
307 <?php
echo ($form_orderby == "doctor") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Provider'); ?
>
310 <th
><a href
="nojs.php" onclick
="return dosort('date')" <?php
echo ($form_orderby == "date") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Date'); ?
></a
>
313 <th
><a href
="nojs.php" onclick
="return dosort('time')"
314 <?php
echo ($form_orderby == "time") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Time'); ?
></a
>
317 <th
><a href
="nojs.php" onclick
="return dosort('patient')"
318 <?php
echo ($form_orderby == "patient") ?
" style=\"color: var(--success)\"" : ""; ?
>> 
; 
; 
;<?php
echo xlt('Patient'); ?
></a
>
321 <th
><a href
="nojs.php" onclick
="return dosort('pubpid')"
322 <?php
echo ($form_orderby == "pubpid") ?
" style=\"color: var(--success)\"" : ""; ?
>> 
;<?php
echo xlt('ID'); ?
></a
>
325 <th
><a href
="nojs.php" onclick
="return dosort('type')"
326 <?php
echo ($form_orderby == "type") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Type'); ?
></a
>
329 <?php
if ($chk_show_details) { ?
>
330 <th
><a href
="nojs.php" onclick
="return dosort('trackerstatus')"
331 <?php
echo ($form_orderby == "trackerstatus") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Status'); ?
></a
>
334 <th
><a href
="nojs.php" onclick
="return dosort('trackerstatus')"
335 <?php
echo ($form_orderby == "trackerstatus") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Final Status'); ?
></a
>
341 if ($chk_show_details) { # not sure if Sorting by Arrive Time is useful
342 echo xlt('Start Time');
344 echo xlt('Arrive Time');
348 if ($chk_show_details) { # not sure if Sorting by Discharge Time is useful
349 echo xlt('End Time');
351 echo xlt('Discharge Time');
354 <th
><?php
echo xlt('Total Time'); # not adding Sorting by Total Time yet but can see that it might be useful ?></th>
356 <?php
} else { # this section is for the drug screen report ?>
357 <th
><a href
="nojs.php" onclick
="return dosort('doctor')"
358 <?php
echo ($form_orderby == "doctor") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Provider'); ?
>
361 <th
><a href
="nojs.php" onclick
="return dosort('date')"
362 <?php
echo ($form_orderby == "date") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Date'); ?
></a
>
365 <th
><a href
="nojs.php" onclick
="return dosort('time')"
366 <?php
echo ($form_orderby == "time") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Time'); ?
></a
>
369 <th
><a href
="nojs.php" onclick
="return dosort('patient')"
370 <?php
echo ($form_orderby == "patient") ?
" style=\"color: var(--success)\"" : ""; ?
>> 
; 
; 
; 
;<?php
echo xlt('Patient'); ?
></a
>
373 <?php
if (!$chk_show_completed_drug_screens) { ?
>
374 <th
><a href
="nojs.php" onclick
="return dosort('pubpid')"
375 <?php
echo ($form_orderby == "pubpid") ?
" style=\"color: var(--success)\"" : ""; ?
>> 
;<?php
echo xlt('ID'); ?
></a
>
378 <th
><a href
="nojs.php" onclick
="return dosort('pubpid')"
379 <?php
echo ($form_orderby == "pubpid") ?
" style=\"color: var(--success)\"" : ""; ?
>> 
;<?php
echo xlt('ID'); ?
></a
>
383 <th
><?php
echo xlt('Drug Screen'); # not sure if Sorting by Drug Screen is useful ?></th>
385 <?php
if (!$chk_show_completed_drug_screens) { ?
>
388 <th
><a href
="nojs.php" onclick
="return dosort('completed')"
389 <?php
echo ($form_orderby == "completed") ?
" style=\"color: var(--success)\"" : ""; ?
>><?php
echo xlt('Completed'); ?
></a
>
393 <th
></th
><th
></th
><th
></th
>
398 <!-- added
for better
print-ability
-->
402 #Appointment Status Checking
403 $form_apptstatus = $_POST['form_apptstatus'];
404 $form_apptcat = null;
405 if (isset($_POST['form_apptcat'])) {
406 if ($form_apptcat != "ALL") {
407 $form_apptcat = intval($_POST['form_apptcat']);
411 #Without provider and facility data checking
412 $with_out_provider = null;
413 $with_out_facility = null;
415 # get the appointments also set the trackerboard flag to true (last entry in the fetchAppointments call so we get the tracker stuff)
416 $appointments = fetchAppointments($from_date, $to_date, $patient, $provider, $facility, $form_apptstatus, $with_out_provider, $with_out_facility, $form_apptcat, true);
417 # sort the appointments by the appointment time
418 $appointments = sortAppointments($appointments, $form_orderby);
419 # $j is used to count the number of patients that match the selected criteria.
421 //print_r2($appointments);
422 foreach ($appointments as $appointment) {
423 $patient_id = $appointment['pid'];
424 $tracker_id = $appointment['pt_tracker_id'];
425 $last_seq = $appointment['lastseq'];
426 $docname = $appointment['ulname'] . ', ' . $appointment['ufname'] . ' ' . $appointment['umname'];
427 # only get items with a tracker id.
428 if ($tracker_id == '') {
432 # only get the drug screens that are set to yes.
433 if ($chk_show_drug_screens == 1) {
434 if ($appointment['random_drug_test'] != '1') {
439 #if a patient id is entered just get that patient.
440 if (strlen($form_pid) != 0) {
441 if ($appointment['pid'] != $form_pid) {
450 # getting arrive time and end time from the elements file.
451 if ($tracker_id != 0) {
452 $newarrive = collect_checkin($tracker_id);
453 $newend = collect_checkout($tracker_id);
456 if ($newend != '' && $newarrive != '') {
460 $tracker_status = $appointment['status'];
461 # get the time interval for the entire visit. to display seconds add last option of true.
462 # get_Tracker_Time_Interval($newarrive, $newend, true)
463 $timecheck2 = get_Tracker_Time_Interval($newarrive, $newend);
464 # Get the tracker elements.
465 $tracker_elements = collect_Tracker_Elements($tracker_id);
466 # $j is incremented for a patient that made it for display.
470 <tr bgcolor
='<?php echo attr($bgcolor ?? ''); ?>'>
472 if (!$chk_show_drug_screens && !$chk_show_completed_drug_screens) { # the first part of this block is for the Patient Flow Board report ?>
473 <td
class="detail"> 
;<?php
echo text(($docname == $lastdocname) ?
"" : $docname) ?
>
476 <td
class="detail"><?php
echo text(oeFormatShortDate($appointment['pc_eventDate'])) ?
>
479 <td
class="detail"><?php
echo text(oeFormatTime($appointment['pc_startTime'])) ?
>
482 <td
class="detail"> 
;<?php
echo text($appointment['fname'] . " " . $appointment['lname']) ?
>
485 <td
class="detail"> 
;<?php
echo text($appointment['pubpid']) ?
>
488 <td
class="detail"> 
;<?php
echo text(xl_appt_category($appointment['pc_catname'])) ?
>
494 if ($chk_show_details) {
495 if ($no_visit != 1) {
496 echo xlt('Complete Visit Time');
499 if ($tracker_status != "") {
500 echo text(getListItemTitle('apptstat', $tracker_status));
506 <td
class="detail"> 
;<?php
echo text(substr($newarrive, 11)) ?
>
509 <td
class="detail"> 
;<?php
echo text(substr($newend, 11)) ?
>
512 <?php
if ($no_visit != 1) { ?
>
513 <td
class="detail"> 
;<?php
echo text($timecheck2) ?
></td
>
515 <td
class="detail"> 
;</td
>
518 if ($chk_show_details) { # lets show the detail lines
521 for ($x = 1; $x <= $last_seq; $x++
) {
523 <tr valign
='top' class="detail" >
524 <td colspan
="6" class="detail" align
='left'>
527 # get the verbiage for the status code
528 $track_stat = $tracker_elements[$i]['status'];
529 # Get Interval alert time and status color.
530 $colorevents = (collectApptStatusSettings($track_stat));
532 $alert_color = $colorevents['color'];
533 $alert_time = $colorevents['time_alert'];
534 if (is_checkin($track_stat) ||
is_checkout($track_stat)) { #bold the check in and check out times in this block.
536 <td
class="detail font-weight-bold">
543 echo text(getListItemTitle("apptstat", $track_stat));
547 if (is_checkin($track_stat) ||
is_checkout($track_stat)) { #bold the check in and check out times in this block.
549 <td
class="detail"><b
> 
;<?php
echo text(substr($tracker_elements[$i]['start_datetime'], 11)); ?
></b
></td
>
552 <td
class="detail"> 
;<?php
echo text(substr($tracker_elements[$i]['start_datetime'], 11)); ?
></td
>
553 <?php
# figure out the next time of the status
557 if ($k < $last_seq) {
558 # get the start time of the next status to determine the total time in this status
559 $start_tracker_time = $tracker_elements[$i]['start_datetime'];
560 $next_tracker_time = $tracker_elements[$k]['start_datetime'];
562 # since this is the last status the start and end are equal
563 $start_tracker_time = $tracker_elements[$i]['start_datetime'];
564 $next_tracker_time = $tracker_elements[$i]['start_datetime'];
567 if (is_checkin($track_stat) ||
is_checkout($track_stat)) { #bold the check in and check out times in this block. ?>
568 <td
class="detail font-weight-bold"> 
;<?php
echo text(substr($next_tracker_time, 11)) ?
></td
><?php
570 <td
class="detail"> 
;<?php
echo text(substr($next_tracker_time, 11)) ?
></td
>
571 <?php
# compute the total time of the status
574 $tracker_time = get_Tracker_Time_Interval($start_tracker_time, $next_tracker_time);
575 # add code to alert if over time interval for status
576 $timecheck = round(abs(strtotime($start_tracker_time) - strtotime($next_tracker_time)) / 60, 0);
577 if ($timecheck > $alert_time && ($alert_time != '0')) {
578 if (is_checkin($track_stat) ||
is_checkout($track_stat)) { #bold the check in and check out times in this block. ?>
579 <td
class="detail font-weight-bold" bgcolor
='<?php echo attr($alert_color) ?>'> 
;<?php
echo text($tracker_time); ?
></td
><?php
581 <td
class="detail" bgcolor
='<?php echo attr($alert_color) ?>'> 
;<?php
echo text($tracker_time); ?
></td
><?php
584 if (is_checkin($track_stat) ||
is_checkout($track_stat)) { #bold the check in and check out times in this block. ?>
585 <td
class="detail font-weight-bold"> 
;<?php
echo text($tracker_time); ?
></td
><?php
587 <td
class="detail"> 
;<?php
echo text($tracker_time); ?
></td
><?php
599 } else { # this section is for the drug screen report ?>
600 <td
class="detail"> 
;<?php
echo ($docname == $lastdocname) ?
"" : text($docname); ?
>
603 <td
class="detail"><?php
echo text(oeFormatShortDate($appointment['pc_eventDate'])) ?
>
606 <td
class="detail"><?php
echo text(oeFormatTime($appointment['pc_startTime'])) ?
>
609 <td
class="detail"> 
;<?php
echo text($appointment['fname'] . " " . $appointment['lname']) ?
>
612 <td
class="detail"> 
;<?php
echo text($appointment['pubpid']) ?
></td
>
614 <td
class="detail"> 
; 
; 
; 
; 
; 
;<?php
echo ($appointment['random_drug_test'] == '1') ?
xlt('Yes') : xlt('No'); ?
></td
>
616 <?php
if ($chk_show_completed_drug_screens) { ?
>
617 <td
class="detail"> 
; 
; 
; 
; 
; 
;<?php
echo ($appointment['drug_screen_completed'] == '1') ?
xlt('Yes') : xlt('No'); ?
></td
>
619 <td
class="detail"> 
; </td
>
622 <?php
# these last items are used to complete the screen ?>
623 <td
class="detail"> 
;</td
>
625 <td
class="detail"> 
;</td
>
627 <td
class="detail"> 
;</td
>
632 $lastdocname = $docname;
636 <?php
if (!$chk_show_drug_screens && !$chk_show_completed_drug_screens) { # is it Patient Flow Board or Drug screen ?>
637 <td colspan
="10" align
="left"><?php
echo xlt('Total number of Patient Flow Board entries'); ?
> 
;<?php
echo text($j);?
> 
;<?php
echo xlt('Patients'); ?
></td
>
639 <td colspan
="10" align
="left"><?php
echo xlt('Total number of Drug Screen entries'); ?
> 
;<?php
echo text($j);?
> 
;<?php
echo xlt('Patients'); ?
></td
>
645 <!-- end of search results
-->
647 <div
class='text'><?php
echo xlt('Please input search criteria above, and click Submit to view results.'); ?
>
650 <input type
="hidden" name
="form_orderby" value
="<?php echo attr($form_orderby) ?>" /> <input type
="hidden" name
="patient" value
="<?php echo attr($patient) ?>" />
651 <input type
='hidden' name
='form_refresh' id
='form_refresh' value
='' />