incremented database counter for prior feature
[openemr.git] / interface / patient_tracker / patient_tracker.php
blob6e07e21337f485df3508441dfc8dea9b863c0d78
1 <?php
2 /**
3 * Patient Tracker (Patient Flow Board)
5 * This program displays the information entered in the Calendar program ,
6 * allowing the user to change status and view those changed here and in the Calendar
7 * Will allow the collection of length of time spent in each status
9 * Copyright (C) 2015 Terry Hill <terry@lillysystems.com>
11 * LICENSE: This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 3
14 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://opensource.org/licenses/gpl-license.php>;.
22 * @package OpenEMR
23 * @author Terry Hill <terry@lilysystems.com>
24 * @link http://www.open-emr.org
26 * Please help the overall project by sending changes you make to the author and to the OpenEMR community.
30 $fake_register_globals=false;
31 $sanitize_all_escapes=true;
33 require_once("../globals.php");
34 require_once("$srcdir/patient.inc");
35 require_once("$srcdir/formatting.inc.php");
36 require_once("$srcdir/options.inc.php");
37 require_once("$srcdir/patient_tracker.inc.php");
38 require_once("$srcdir/user.inc");
40 // mdsupport - user_settings prefix
41 $uspfx = substr(__FILE__, strlen($webserver_root)) . '.';
42 $setting_new_window = prevSetting($uspfx, 'setting_new_window', 'form_new_window', ' ');
44 #define variables, future enhancement allow changing the to_date and from_date
45 #to allow picking a date to review
47 if (!is_null($_POST['form_provider'])) {
48 $provider = $_POST['form_provider'];
50 else if ($_SESSION['userauthorized']) {
51 $provider = $_SESSION['authUserID'];
53 else {
54 $provider = null;
56 $facility = !is_null($_POST['form_facility']) ? $_POST['form_facility'] : null;
57 $form_apptstatus = !is_null($_POST['form_apptstatus']) ? $_POST['form_apptstatus'] : null;
58 $form_apptcat=null;
59 if(isset($_POST['form_apptcat']))
61 if($form_apptcat!="ALL")
63 $form_apptcat=intval($_POST['form_apptcat']);
67 $appointments = array();
68 $from_date = date("Y-m-d");
69 $to_date = date("Y-m-d");
70 $datetime = date("Y-m-d H:i:s");
72 # go get the information and process it
73 $appointments = fetch_Patient_Tracker_Events($from_date, $to_date, $provider, $facility, $form_apptstatus, $form_apptcat);
74 $appointments = sortAppointments( $appointments, 'time' );
76 //grouping of the count of every status
77 $appointments_status = getApptStatus($appointments);
79 // Below are new constants for the translation pipeline
80 // xl('None')
81 // xl('Reminder done')
82 // xl('Chart pulled')
83 // xl('Canceled')
84 // xl('No show')
85 // xl('Arrived')
86 // xl('Arrived late')
87 // xl('Left w/o visit')
88 // xl('Ins/fin issue')
89 // xl('In exam room')
90 // xl('Checked out')
91 // xl('Coding done')
92 // xl('Canceled < 24h')
93 $lres = sqlStatement("SELECT option_id, title FROM list_options WHERE list_id = ? AND activity=1", array('apptstat'));
94 while ( $lrow = sqlFetchArray ( $lres ) ) {
95 // if exists, remove the legend character
96 if($lrow['title'][1] == ' '){
97 $splitTitle = explode(' ', $lrow['title']);
98 array_shift($splitTitle);
99 $title = implode(' ', $splitTitle);
100 }else{
101 $title = $lrow['title'];
104 $statuses_list[$lrow['option_id']] = $title;
107 $chk_prov = array(); // list of providers with appointments
109 // Scan appointments for additional info
110 foreach ( $appointments as $apt ) {
111 $chk_prov[$apt['uprovider_id']] = $apt['ulname'] . ', ' . $apt['ufname'] . ' ' . $apt['umname'];
114 <html>
115 <head>
116 <title><?php echo xlt("Flow Board") ?></title>
117 <link rel="stylesheet" href="<?php echo $css_header;?>" type="text/css">
118 <link rel="stylesheet" href="<?php echo $GLOBALS['assets_static_relative'];?>/font-awesome-4-6-3/css/font-awesome.css" type="text/css">
120 <script type="text/javascript" src="../../library/dialog.js"></script>
121 <script type="text/javascript" src="../../library/js/common.js"></script>
122 <script type="text/javascript" src="<?php echo $GLOBALS['assets_static_relative']; ?>/jquery-min-1-9-1/index.js"></script>
123 <script type="text/javascript" src="<?php echo $GLOBALS['assets_static_relative'];?>/jquery-modern-blink-0-1-3/jquery.modern-blink.js"></script>
125 <script language="JavaScript">
126 // Refresh self
127 function refreshme() {
128 top.restoreSession();
129 document.pattrk.submit();
131 // popup for patient tracker status
132 function bpopup(tkid) {
133 top.restoreSession()
134 dlgopen('../patient_tracker/patient_tracker_status.php?tracker_id=' + tkid, '_blank', 500, 250);
135 return false;
138 // popup for calendar add edit
139 function calendarpopup(eid,date_squash) {
140 top.restoreSession()
141 dlgopen('../main/calendar/add_edit_event.php?eid=' + eid + '&date=' + date_squash, '_blank', 775, 500);
142 return false;
145 // auto refresh screen pat_trkr_timer is the timer variable
146 function refreshbegin(first){
147 <?php if ($GLOBALS['pat_trkr_timer'] != '0') { ?>
148 var reftime="<?php echo attr($GLOBALS['pat_trkr_timer']); ?>";
149 var parsetime=reftime.split(":");
150 parsetime=(parsetime[0]*60)+(parsetime[1]*1)*1000;
151 if (first != '1') {
152 refreshme();
154 setTimeout("refreshbegin('0')",parsetime);
155 <?php } else { ?>
156 return;
157 <?php } ?>
160 // used to display the patient demographic and encounter screens
161 function topatient(newpid, enc) {
162 if (document.pattrk.form_new_window.checked) {
163 openNewTopWindow(newpid,enc);
165 else {
166 top.restoreSession();
167 if (enc > 0) {
168 top.RTop.location= "<?php echo $GLOBALS['webroot']; ?>/interface/patient_file/summary/demographics.php?set_pid=" + newpid + "&set_encounterid=" + enc;
170 else {
171 top.RTop.location = "<?php echo $GLOBALS['webroot']; ?>/interface/patient_file/summary/demographics.php?set_pid=" + newpid;
176 // opens the demographic and encounter screens in a new window
177 function openNewTopWindow(newpid,newencounterid) {
178 document.fnew.patientID.value = newpid;
179 document.fnew.encounterID.value = newencounterid;
180 top.restoreSession();
181 document.fnew.submit();
184 </script>
186 </head>
188 <?php
189 if ($GLOBALS['pat_trkr_timer'] == '0') {
190 // if the screen is not set up for auto refresh, use standard page call
191 $action_page = "patient_tracker.php";
193 else {
194 // if the screen is set up for auto refresh, this will allow it to be closed by auto logoff
195 $action_page = "patient_tracker.php?skip_timeout_reset=1";
199 <span class="title"><?php echo xlt("Flow Board") ?></span>
200 <body class="body_top" >
201 <form method='post' name='theform' id='theform' action='<?php echo $action_page; ?>' onsubmit='return top.restoreSession()'>
202 <div id="flow_board_parameters">
203 <table>
204 <tr class="text">
205 <td class='label'><?php echo xlt('Provider'); ?>:</td>
206 <td><?php
208 # Build a drop-down list of providers.
210 $query = "SELECT id, lname, fname FROM users WHERE ".
211 "authorized = 1 ORDER BY lname, fname"; #(CHEMED) facility filter
213 $ures = sqlStatement($query);
215 echo " <select name='form_provider'>\n";
216 echo " <option value='ALL'>-- " . xlt('All') . " --\n";
218 while ($urow = sqlFetchArray($ures)) {
219 $provid = $urow['id'];
220 echo " <option value='" . attr($provid) . "'";
221 if (isset($_POST['form_provider']) && $provid == $_POST['form_provider']){
222 echo " selected";
223 } elseif(!isset($_POST['form_provider'])&& $_SESSION['userauthorized'] && $provid == $_SESSION['authUserID']){
224 echo " selected";
226 echo ">" . text($urow['lname']) . ", " . text($urow['fname']) . "\n";
229 echo " </select>\n";
232 </td>
233 <td class='label'><?php echo xlt('Status'); # status code drop down creation ?>:</td>
234 <td><?php generate_form_field(array('data_type'=>1,'field_id'=>'apptstatus','list_id'=>'apptstat','empty_title'=>'All'),$_POST['form_apptstatus']);?></td>
235 <td><?php echo xlt('Category') #category drop down creation ?>:</td>
236 <td>
237 <select id="form_apptcat" name="form_apptcat">
238 <?php
239 $categories=fetchAppointmentCategories();
240 echo "<option value='ALL'>".xlt("All")."</option>";
241 while($cat=sqlFetchArray($categories))
243 echo "<option value='".attr($cat['id'])."'";
244 if($cat['id']==$_POST['form_apptcat'])
246 echo " selected='true' ";
248 echo ">".text(xl_appt_category($cat['category']))."</option>";
251 </select>
252 </td>
253 <td style="border-left: 1px solid;">
254 <div style='margin-left: 15px'>
255 <a href='#' class='css_button' onclick='$("#form_refresh").attr("value","true"); $("#theform").submit();'>
256 <span> <?php echo xlt('Submit'); ?> </span> </a>
257 <?php if ($_POST['form_refresh'] || $_POST['form_orderby'] ) { ?>
258 <a href='#' class='css_button' id='printbutton'>
259 <span> <?php echo xlt('Print'); ?> </span> </a>
260 <?php } ?>
261 </div>
262 </td>
263 </tr>
264 </table>
265 </div>
266 </form>
268 <form name='pattrk' id='pattrk' method='post' action='<?php echo $action_page; ?>' onsubmit='return top.restoreSession()' enctype='multipart/form-data'>
270 <div>
271 <?php if (count($chk_prov) == 1) {?>
272 <h2><span style='float: left'><?php echo xlt('Appointments for'). ' : '. text(reset($chk_prov)) ?></span></h2>
273 <?php } ?>
274 <div id= 'inanewwindow' class='inanewwindow'>
275 <span style='float: right'>
276 <a id='setting_cog'><i class="fa fa-cog fa-2x fa-fw">&nbsp;</i></a>
277 <?php // Note that are unable to html escape below $setting_new_window, or else will break the code, secondary to white space issues. ?>
278 <input type='hidden' name='setting_new_window' id='setting_new_window' value='<?php echo $setting_new_window ?>' />
279 <label id='settings'><input type='checkbox' name='form_new_window' id='form_new_window' value='1'<?php echo $setting_new_window ?> >
280 <?php echo xlt('Open Patient in New Window'); ?></input></label>
281 <a id='refreshme'><i class="fa fa-refresh fa-2x fa-fw">&nbsp;</i></a>
282 </span>
283 </div>
284 </div>
285 <?php if ($GLOBALS['pat_trkr_timer'] =='0') { ?>
286 <table border='0' cellpadding='5' cellspacing='0'>
287 <tr>
288 <td align='center'><br>
289 <a href='javascript:;' class='css_button_small' align='center' style='color:gray' onclick="document.getElementById('pattrk').submit();"><span><?php echo xlt('Refresh Screen'); ?></span></a>
290 </td>
291 </tr>
292 </table>
293 <?php } ?>
295 <table border='0' cellpadding='1' cellspacing='2' width='100%'>
296 <tr>
297 <td colspan="12">
298 <b><small>
299 <?php
300 $statuses_output = xlt('Total patients') . ':' . text($appointments_status['count_all']);
301 unset($appointments_status['count_all']);
302 foreach($appointments_status as $status_symbol => $count){
303 $statuses_output .= " | " . text(xl_list_label($statuses_list[$status_symbol])) .":" . $count;
305 echo $statuses_output;
307 </small></b>
308 </td>
309 </tr>
310 <tr bgcolor="#cccff">
311 <?php if ($GLOBALS['ptkr_show_pid']) { ?>
312 <td class="dehead" align="center">
313 <?php echo xlt('PID'); ?>
314 </td>
315 <?php } ?>
316 <td class="dehead" align="center">
317 <?php echo xlt('Patient'); ?>
318 </td>
319 <?php if ($GLOBALS['ptkr_visit_reason']) { ?>
320 <td class="dehead" align="center">
321 <?php echo xlt('Reason'); ?>
322 </td>
323 <?php } ?>
324 <?php if ($GLOBALS['ptkr_show_encounter']) { ?>
325 <td class="dehead" align="center">
326 <?php echo xlt('Encounter'); ?>
327 </td>
328 <?php } ?>
329 <td class="dehead" align="center">
330 <?php echo xlt('Exam Room #'); ?>
331 </td>
332 <td class="dehead" align="center">
333 <?php echo xlt('Appt Time'); ?>
334 </td>
335 <td class="dehead" align="center">
336 <?php echo xlt('Arrive Time'); ?>
337 </td>
338 <td class="dehead" align="center">
339 <?php echo xlt('Status'); ?>
340 </td>
341 <td class="dehead" align="center">
342 <?php echo xlt('Current Status Time'); ?>
343 </td>
344 <td class="dehead" align="center">
345 <?php echo xlt('Visit Type'); ?>
346 </td>
347 <?php if (count($chk_prov) > 1) { ?>
348 <td class="dehead" align="center">
349 <?php echo xlt('Provider'); ?>
350 </td>
351 <?php } ?>
352 <td class="dehead" align="center">
353 <?php echo xlt('Total Time'); ?>
354 </td>
355 <td class="dehead" align="center">
356 <?php echo xlt('Check Out Time'); ?>
357 </td>
358 <td class="dehead" align="center">
359 <?php echo xlt('Updated By'); ?>
360 </td>
361 <?php if ($GLOBALS['drug_screen']) { ?>
362 <td class="dehead" align="center">
363 <?php echo xlt('Random Drug Screen'); ?>
364 </td>
365 <td class="dehead" align="center">
366 <?php echo xlt('Drug Screen Completed'); ?>
367 </td>
368 <?php } ?>
369 </tr>
371 <?php
372 foreach ( $appointments as $appointment ) {
374 # Collect appt date and set up squashed date for use below
375 $date_appt = $appointment['pc_eventDate'];
376 $date_squash = str_replace("-","",$date_appt);
378 # Collect variables and do some processing
379 $docname = $chk_prov[$appointment['uprovider_id']];
380 if (strlen($docname)<= 3 ) continue;
381 $ptname = $appointment['lname'] . ', ' . $appointment['fname'] . ' ' . $appointment['mname'];
382 $appt_enc = $appointment['encounter'];
383 $appt_eid = (!empty($appointment['eid'])) ? $appointment['eid'] : $appointment['pc_eid'];
384 $appt_pid = (!empty($appointment['pid'])) ? $appointment['pid'] : $appointment['pc_pid'];
385 if ($appt_pid ==0 ) continue; // skip when $appt_pid = 0, since this means it is not a patient specific appt slot
386 $status = (!empty($appointment['status'])) ? $appointment['status'] : $appointment['pc_apptstatus'];
387 $appt_room = (!empty($appointment['room'])) ? $appointment['room'] : $appointment['pc_room'];
388 $appt_time = (!empty($appointment['appttime'])) ? $appointment['appttime'] : $appointment['pc_startTime'];
389 $tracker_id = $appointment['id'];
390 # reason for visit
391 if ($GLOBALS['ptkr_visit_reason']) {
392 $reason_visit = $appointment['pc_hometext'];
394 $newarrive = collect_checkin($tracker_id);
395 $newend = collect_checkout($tracker_id);
396 $colorevents = (collectApptStatusSettings($status));
397 $bgcolor = $colorevents['color'];
398 $statalert = $colorevents['time_alert'];
399 # process the time to allow items with a check out status to be displayed
400 if ( is_checkout($status) && ($GLOBALS['checkout_roll_off'] > 0) ) {
401 $to_time = strtotime($newend);
402 $from_time = strtotime($datetime);
403 $display_check_out = round(abs($from_time - $to_time) / 60,0);
404 if ( $display_check_out >= $GLOBALS['checkout_roll_off'] ) continue;
407 <tr bgcolor='<?php echo $bgcolor ?>'>
408 <?php if ($GLOBALS['ptkr_show_pid']) { ?>
409 <td class="detail" align="center">
410 <?php echo text($appt_pid) ?>
411 </td>
412 <?php } ?>
413 <td class="detail" align="center">
414 <a href="#" onclick="return topatient('<?php echo attr($appt_pid);?>','<?php echo attr($appt_enc);?>')" >
415 <?php echo text($ptname); ?></a>
416 </td>
417 <!-- reason -->
418 <?php if ($GLOBALS['ptkr_visit_reason']) { ?>
419 <td class="detail" align="center">
420 <?php echo text($reason_visit) ?>
421 </td>
422 <?php } ?>
423 <?php if ($GLOBALS['ptkr_show_encounter']) { ?>
424 <td class="detail" align="center">
425 <?php if($appt_enc != 0) echo text($appt_enc); ?></a>
426 </td>
427 <?php } ?>
428 <td class="detail" align="center">
429 <?php echo getListItemTitle('patient_flow_board_rooms', $appt_room);?>
430 </td>
431 <td class="detail" align="center">
432 <?php echo oeFormatTime($appt_time) ?>
433 </td>
434 <td class="detail" align="center">
435 <?php echo ($newarrive ? oeFormatTime($newarrive) : '&nbsp;') ?>
436 </td>
437 <td class="detail" align="center">
438 <?php if (empty($tracker_id)) { #for appt not yet with tracker id and for recurring appt ?>
439 <a href="" onclick="return calendarpopup(<?php echo attr($appt_eid).",".attr($date_squash); # calls popup for add edit calendar event?>)">
440 <?php } else { ?>
441 <a href="" onclick="return bpopup(<?php echo attr($tracker_id); # calls popup for patient tracker status?>)">
442 <?php } ?>
443 <?php echo text(getListItemTitle("apptstat",$status)); # drop down list for appointment status?>
444 </a>
446 </td>
447 <?php
448 #time in current status
449 $to_time = strtotime(date("Y-m-d H:i:s"));
450 $yestime = '0';
451 if (strtotime($newend) != '') {
452 $from_time = strtotime($newarrive);
453 $to_time = strtotime($newend);
454 $yestime = '0';
456 else
458 $from_time = strtotime($appointment['start_datetime']);
459 $yestime = '1';
462 $timecheck = round(abs($to_time - $from_time) / 60,0);
463 if ($timecheck >= $statalert && ($statalert != '0')) { # Determine if the time in status limit has been reached.
464 echo "<td align='center' class='js-blink-infinite'> "; # and if so blink
466 else
468 echo "<td align='center' class='detail'> "; # and if not do not blink
470 if (($yestime == '1') && ($timecheck >=1) && (strtotime($newarrive)!= '')) {
471 echo text($timecheck . ' ' .($timecheck >=2 ? xl('minutes'): xl('minute')));
473 #end time in current status
475 </td>
476 <td class="detail" align="center">
477 <?php echo text(xl_appt_category($appointment['pc_title'])) ?>
478 </td>
479 <?php if (count($chk_prov) > 1) { ?>
480 <td class="detail" align="center">
481 <?php echo text($docname); ?>
482 </td>
483 <?php } ?>
484 <td class="detail" align="center">
485 <?php
487 # total time in practice
488 if (strtotime($newend) != '') {
489 $from_time = strtotime($newarrive);
490 $to_time = strtotime($newend);
492 else
494 $from_time = strtotime($newarrive);
495 $to_time = strtotime(date("Y-m-d H:i:s"));
497 $timecheck2 = round(abs($to_time - $from_time) / 60,0);
498 if (strtotime($newarrive) != '' && ($timecheck2 >=1)) {
499 echo text($timecheck2 . ' ' .($timecheck2 >=2 ? xl('minutes'): xl('minute')));
501 # end total time in practice
503 <?php echo text($appointment['pc_time']); ?>
504 </td>
505 <td class="detail" align="center">
506 <?php
507 if (strtotime($newend) != '') {
508 echo oeFormatTime($newend) ;
511 </td>
512 <td class="detail" align="center">
513 <?php echo text($appointment['user']) ?>
514 </td>
515 <?php if ($GLOBALS['drug_screen']) { ?>
516 <?php if (strtotime($newarrive) != '') { ?>
517 <td class="detail" align="center">
518 <?php if (text($appointment['random_drug_test']) == '1') { echo xl('Yes'); } else { echo xl('No'); }?>
519 </td>
520 <?php } else { echo " <td>"; }?>
521 <?php if (strtotime($newarrive) != '' && $appointment['random_drug_test'] == '1') { ?>
522 <td class="detail" align="center">
523 <?php if (strtotime($newend) != '') { # the following block allows the check box for drug screens to be disabled once the status is check out ?>
524 <input type=checkbox disabled='disable' class="drug_screen_completed" id="<?php echo htmlspecialchars($appointment['pt_tracker_id'], ENT_NOQUOTES) ?>" <?php if ($appointment['drug_screen_completed'] == "1") echo "checked";?>>
525 <?php } else { ?>
526 <input type=checkbox class="drug_screen_completed" id='<?php echo htmlspecialchars($appointment['pt_tracker_id'], ENT_NOQUOTES) ?>' name="drug_screen_completed" <?php if ($appointment['drug_screen_completed'] == "1") echo "checked";?>>
527 <?php } ?>
528 </td>
529 <?php } else { echo " <td>"; }?>
530 <?php } ?>
531 </tr>
532 <?php
533 } //end for
536 <?php
537 //saving the filter for auto refresh
538 if(!is_null($_POST['form_provider']) ){
539 echo "<input type='hidden' name='form_provider' value='" . attr($_POST['form_provider']) . "'>";
541 if(!is_null($_POST['form_facility']) ){
542 echo "<input type='hidden' name='form_facility' value='" . attr($_POST['form_facility']) . "'>";
544 if(!is_null($_POST['form_apptstatus']) ){
545 echo "<input type='hidden' name='form_apptstatus' value='" . attr($_POST['form_apptstatus']) . "'>";
547 if(!is_null($_POST['form_apptcat']) ){
548 echo "<input type='hidden' name='form_apptcat' value='" . attr($_POST['form_apptcat']) . "'>";
552 </table>
553 </form>
555 <script type="text/javascript">
556 $(document).ready(function() {
557 $('#settings').css("display","none");
558 refreshbegin('1');
559 $('.js-blink-infinite').modernBlink();
561 // toggle of the check box status for drug screen completed and ajax call to update the database
562 $(".drug_screen_completed").change(function() {
563 top.restoreSession();
564 if (this.checked) {
565 testcomplete_toggle="true";
566 } else {
567 testcomplete_toggle="false";
569 $.post( "../../library/ajax/drug_screen_completed.php", {
570 trackerid: this.id,
571 testcomplete: testcomplete_toggle
576 // mdsupport - Immediately post changes to form_new_window
577 $('#form_new_window').click(function () {
578 $('#setting_new_window').val(this.checked ? ' checked' : ' ');
579 $.post( "<?php echo basename(__FILE__) ?>", {
580 data: $('form#pattrk').serialize(),
581 success: function (data) {}
585 $('#setting_cog').click(function () {
586 $(this).css("display","none");
587 $('#settings').css("display","inline");
590 $('#refreshme').click(function () {
591 refreshme();
593 </script>
594 <!-- form used to open a new top level window when a patient row is clicked -->
595 <form name='fnew' method='post' target='_blank' action='../main/main_screen.php?auth=login&site=<?php echo attr($_SESSION['site_id']); ?>'>
596 <input type='hidden' name='patientID' value='0' />
597 <input type='hidden' name='encounterID' value='0' />
598 </form>
599 </body>
600 </html>