consolidate similar x12 gen 837 function (#5691)
[openemr.git] / src / Services / PatientTrackerService.php
blobe421b9e2dc69786e96fa10dc8331e12346a3a5d4
1 <?php
3 /**
4 * PatientTrackerService Handles the select, create, and update of patient events that we are track. This is used typically
5 * in the patient flow board and for patient reporting.
7 * Much of this code was refactored from the patient_tracker.inc.php file.
9 * @package openemr
10 * @link http://www.open-emr.org
11 * @author Stephen Nielson <stephen@nielson.org>
12 * @author Terry Hill <terry@lillysystems.com>
13 * @copyright Copyright (C) 2015 Terry Hill <terry@lillysystems.com>
14 * @copyright Copyright (c) 2021 Stephen Nielson <stephen@nielson.org>
15 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
18 namespace OpenEMR\Services;
20 use OpenEMR\Events\Services\ServiceSaveEvent;
22 class PatientTrackerService extends BaseService
24 const TABLE_NAME = "patient_tracker";
25 const TABLE_NAME_TRACKER_ELEMENT = "patient_tracker_element";
27 public function __construct()
29 parent::__construct(self::TABLE_NAME);
32 /**
33 * @param $tracker_from_time
34 * @param $tracker_to_time
35 * @param bool $allow_sec
36 * @return string
38 public function get_Tracker_Time_Interval($tracker_from_time, $tracker_to_time, $allow_sec = false)
41 $tracker_time_calc = strtotime($tracker_to_time) - strtotime($tracker_from_time);
43 $tracker_time = "";
44 if ($tracker_time_calc > 60 * 60 * 24) {
45 $days = floor($tracker_time_calc / 60 / 60 / 24);
46 if ($days >= 2) {
47 $tracker_time .= "$days " . xl('days');
48 } else {
49 $tracker_time .= "$days " . xl('day');
52 $tracker_time_calc = $tracker_time_calc - ($days * (60 * 60 * 24));
55 if ($tracker_time_calc > 60 * 60) {
56 $hours = floor($tracker_time_calc / 60 / 60);
57 if (strlen($days != 0)) {
58 if ($hours >= 2) {
59 $tracker_time .= ", $hours " . xl('hours');
60 } else {
61 $tracker_time .= ", $hours " . xl('hour');
63 } else {
64 if ($hours >= 2) {
65 $tracker_time .= "$hours " . xl('hours');
66 } else {
67 $tracker_time .= "$hours " . xl('hour');
71 $tracker_time_calc = $tracker_time_calc - ($hours * (60 * 60));
74 if ($allow_sec) {
75 if ($tracker_time_calc > 60) {
76 $minutes = floor($tracker_time_calc / 60);
77 if (strlen($hours != 0)) {
78 if ($minutes >= 2) {
79 $tracker_time .= ", $minutes " . xl('minutes');
80 } else {
81 $tracker_time .= ", $minutes " . xl('minute');
83 } else {
84 if ($minutes >= 2) {
85 $tracker_time .= "$minutes " . xl('minutes');
86 } else {
87 $tracker_time .= "$minutes " . xl('minute');
91 $tracker_time_calc = $tracker_time_calc - ($minutes * 60);
93 } else {
94 $minutes = round($tracker_time_calc / 60);
95 if (!empty($hours) && strlen($hours != 0)) {
96 if ($minutes >= 2) {
97 $tracker_time .= ", $minutes " . xl('minutes');
98 } else {
99 $tracker_time .= ", $minutes " . xl('minute');
101 } else {
102 if ($minutes >= 2) {
103 $tracker_time .= "$minutes " . xl('minutes');
104 } else {
105 if ($minutes > 0) {
106 $tracker_time .= "$minutes " . xl('minute');
111 $tracker_time_calc = $tracker_time_calc - ($minutes * 60);
114 if ($allow_sec) {
115 if ($tracker_time_calc > 0) {
116 if (strlen($minutes != 0)) {
117 if ($tracker_time_calc >= 2) {
118 $tracker_time .= ", $tracker_time_calc " . xl('seconds');
119 } else {
120 $tracker_time .= ", $tracker_time_calc " . xl('second');
122 } else {
123 if ($tracker_time_calc >= 2) {
124 $tracker_time .= "$tracker_time_calc " . xl('seconds');
125 } else {
126 $tracker_time .= "$tracker_time_calc " . xl('second');
132 return $tracker_time ;
136 * This function will return false for both below scenarios:
137 * 1. The tracker item does not exist
138 * 2. If the tracker item does exist, but the encounter has not been set
139 * @param $apptdate
140 * @param $appttime
141 * @param $pid
142 * @param $eid
143 * @return int
145 public function is_tracker_encounter_exist($apptdate, $appttime, $pid, $eid)
147 #Check to see if there is an encounter in the patient_tracker table.
148 $enc_yn = sqlQuery("SELECT encounter from patient_tracker WHERE `apptdate` = ? AND encounter > 0 " .
149 "AND `eid` = ? AND `pid` = ?", array($apptdate, $eid, $pid));
150 if (empty($enc_yn['encounter']) || $enc_yn === false) {
151 return (0);
154 return ($enc_yn['encounter']);
158 * this function will return the tracker id that is managed
159 * or will return false if no tracker id was managed (in the case of a recurrent appointment)
160 * @param $apptdate
161 * @param $appttime
162 * @param $eid
163 * @param $pid
164 * @param $user
165 * @param string $status
166 * @param string $room
167 * @param string $enc_id
168 * @return bool|int
170 public function manage_tracker_status($apptdate, $appttime, $eid, $pid, $user, $status = '', $room = '', $enc_id = '')
172 #First ensure the eid is not a recurrent appointment. If it is, then do not do anything and return false.
173 $pc_appt = sqlQuery("SELECT `pc_recurrtype` FROM `openemr_postcalendar_events` WHERE `pc_eid` = ?", array($eid));
174 if ($pc_appt['pc_recurrtype'] != 0) {
175 return false;
178 $datetime = date("Y-m-d H:i:s");
179 if (is_null($room)) {
180 $room = '';
183 #Check to see if there is an entry in the patient_tracker table.
184 $tracker = sqlQuery("SELECT id, apptdate, appttime, eid, pid, original_user, encounter, lastseq," .
185 "patient_tracker_element.room AS lastroom,patient_tracker_element.status AS laststatus " .
186 "from `patient_tracker`" .
187 "LEFT JOIN patient_tracker_element " .
188 "ON patient_tracker.id = patient_tracker_element.pt_tracker_id " .
189 "AND patient_tracker.lastseq = patient_tracker_element.seq " .
190 "WHERE `apptdate` = ? AND `appttime` = ? " .
191 "AND `eid` = ? AND `pid` = ?", array($apptdate,$appttime,$eid,$pid));
193 if (empty($tracker)) {
194 #Add a new tracker.
195 $tracker_id = sqlInsert(
196 "INSERT INTO `patient_tracker` " .
197 "(`date`, `apptdate`, `appttime`, `eid`, `pid`, `original_user`, `encounter`, `lastseq`) " .
198 "VALUES (?,?,?,?,?,?,?,'1')",
199 array($datetime,$apptdate,$appttime,$eid,$pid,$user,$enc_id)
201 #If there is a status or a room, then add a tracker item.
202 if (!empty($status) || !empty($room)) {
203 sqlStatement(
204 "INSERT INTO `patient_tracker_element` " .
205 "(`pt_tracker_id`, `start_datetime`, `user`, `status`, `room`, `seq`) " .
206 "VALUES (?,?,?,?,?,'1')",
207 array($tracker_id,$datetime,$user,$status,$room)
210 $tracker = [
211 'id' => $tracker_id
212 ,'date' => $datetime
213 ,'apptdate' => $apptdate
214 ,'appttime' => $appttime
215 ,'eid' => $eid
216 ,'pid' => $pid
217 ,'original_user' => $user
218 ,'encounter' => $enc_id
219 ,'lastseq' => '1'
220 ,'element' => [
221 'pt_tracker_id' => $tracker_id
222 ,'start_datetime' => $datetime
223 ,'user' => $user
224 ,'status' => $status
225 ,'room' => $room
226 ,'seq' => '1'
229 } else {
230 #Tracker already exists.
231 $tracker_id = $tracker['id'];
232 if (($status != $tracker['laststatus']) || ($room != $tracker['lastroom'])) {
233 #Status or room has changed, so need to update tracker.
234 #Update lastseq in tracker.
235 sqlStatement(
236 "UPDATE `patient_tracker` SET `lastseq` = ? WHERE `id` = ?",
237 array(($tracker['lastseq'] + 1),$tracker_id)
239 #Add a tracker item.
240 sqlStatement(
241 "INSERT INTO `patient_tracker_element` " .
242 "(`pt_tracker_id`, `start_datetime`, `user`, `status`, `room`, `seq`) " .
243 "VALUES (?,?,?,?,?,?)",
244 array($tracker_id,$datetime,$user,$status,$room,($tracker['lastseq'] + 1))
248 if (!empty($enc_id)) {
249 #enc_id (encounter number) is not blank, so update this in tracker.
250 sqlStatement("UPDATE `patient_tracker` SET `encounter` = ? WHERE `id` = ?", array($enc_id,$tracker_id));
252 $tracker['lastseq'] = $tracker['lastseq'] + 1;
253 $tracker['element'] = [
254 'pt_tracker_id' => $tracker_id
255 ,'start_datetime' => $datetime
256 ,'user' => $user
257 ,'status' => $status
258 ,'room' => $room
259 ,'seq' => $tracker['lastseq']
263 #Ensure the entry in calendar appt entry has been updated.
264 $pc_appt = sqlQuery("SELECT `pc_apptstatus`, `pc_room` FROM `openemr_postcalendar_events` WHERE `pc_eid` = ?", array($eid));
265 if ($status != $pc_appt['pc_apptstatus']) {
266 sqlStatement("UPDATE `openemr_postcalendar_events` SET `pc_apptstatus` = ? WHERE `pc_eid` = ?", array($status,$eid));
269 if ($room != $pc_appt['pc_room']) {
270 sqlStatement("UPDATE `openemr_postcalendar_events` SET `pc_room` = ? WHERE `pc_eid` = ?", array($room,$eid));
273 $GLOBALS['kernel']->getEventDispatcher()->dispatch(new ServiceSaveEvent($this, $tracker), ServiceSaveEvent::EVENT_POST_SAVE);
275 # Returning the tracker id that has been managed
276 return $tracker_id;
280 * This is used to break apart the information contained in the notes field of
281 * list_options. Currently the color and alert time are the only items stored
282 * @param $option
283 * @return array
285 public function collectApptStatusSettings($option)
287 $color_settings = array();
288 $row = sqlQuery("SELECT notes FROM list_options WHERE " .
289 "list_id = 'apptstat' AND option_id = ? AND activity = 1", array($option));
290 if (empty($row['notes'])) {
291 return $option;
294 list($color_settings['color'], $color_settings['time_alert']) = explode("|", $row['notes']);
295 return $color_settings;
299 * This is used to collect the tracker elements for the Patient Flow Board Report
300 * returns the elements in an array
301 * @param $trackerid
302 * @return mixed
304 public function collect_Tracker_Elements($trackerid)
306 $res = sqlStatement("SELECT * FROM patient_tracker_element WHERE pt_tracker_id = ? ORDER BY LENGTH(seq), seq ", array($trackerid));
307 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
308 $returnval[$iter] = $row;
311 return $returnval;
315 * used to determine check in time
316 * @param $trackerid
317 * @return bool
319 public function collect_checkin($trackerid)
321 $tracker = sqlQuery(
322 "SELECT patient_tracker_element.start_datetime " .
323 "FROM patient_tracker_element " .
324 "INNER JOIN list_options " .
325 "ON patient_tracker_element.status = list_options.option_id " .
326 "WHERE list_options.list_id = 'apptstat' " .
327 "AND list_options.toggle_setting_1 = '1' AND list_options.activity = 1 " .
328 "AND patient_tracker_element.pt_tracker_id = ?",
329 array($trackerid)
331 if (empty($tracker['start_datetime'])) {
332 return false;
333 } else {
334 return $tracker['start_datetime'];
339 * used to determine check out time
340 * @param $trackerid
341 * @return bool
343 public function collect_checkout($trackerid)
345 $tracker = sqlQuery(
346 "SELECT patient_tracker_element.start_datetime " .
347 "FROM patient_tracker_element " .
348 "INNER JOIN list_options " .
349 "ON patient_tracker_element.status = list_options.option_id " .
350 "WHERE list_options.list_id = 'apptstat' " .
351 "AND list_options.toggle_setting_2 = '1' AND list_options.activity = 1 " .
352 "AND patient_tracker_element.pt_tracker_id = ?",
353 array($trackerid)
355 if (empty($tracker['start_datetime'])) {
356 return false;
357 } else {
358 return $tracker['start_datetime'];
362 public function getApptStatus($appointments)
364 $astat = array();
365 $astat['count_all'] = count($appointments);
366 //group the appointment by status
367 foreach ($appointments as $appointment) {
368 ($astat[$appointment['pc_apptstatus']] ?? null) ? $astat[$appointment['pc_apptstatus']] : $astat[$appointment['pc_apptstatus']] = 0;
369 $astat[$appointment['pc_apptstatus']] += 1;
372 return $astat;