feat: New Clinical Note defaults to today (#6911)
[openemr.git] / library / dated_reminder_functions.php
blobff9adaa8c35e423204579968ad9da58421ba1159
1 <?php
3 /**
4 * Contains functions used in the dated reminders.
6 * @package OpenEMR
7 * @link https://www.open-emr.org
8 * @author Craig Bezuidenhout <http://www.tajemo.co.za/>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Jerry Padgett <sjpadgett@gmail.com>
11 * @copyright Copyright (c) 2012 tajemo.co.za <http://www.tajemo.co.za/>
12 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
13 * @copyright Copyright (c) 2018-2023 Jerry Padgett <sjpadhgett@gmail.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
17 use OpenEMR\Modules\FaxSMS\Controller\AppDispatch;
20 * We really need to set up a separate service for this stuff i.e. Node server.
21 * Get it out of app space and running all the timers.
23 * */
25 /**
26 * @return array
28 function GetServiceOtherCounts(): array
30 $counts['faxCnt'] = $counts['smsCnt'] = 0;
31 // unless main.php is reloaded Globals is most accurate.
32 if (!empty($GLOBALS['oefax_enable_fax'] ?? null)) {
33 $client = AppDispatch::getApiService('fax');
34 $counts['faxCnt'] = (int)$client->fetchReminderCount();
36 if (!empty($GLOBALS['oefax_enable_sms'] ?? null)) {
37 $client = AppDispatch::getApiService('sms');
38 $counts['smsCnt'] = (int)$client->fetchReminderCount();
40 $counts['serviceTotal'] = $counts['faxCnt'] + $counts['smsCnt'];
42 return $counts;
45 /**
46 * Get Portal Alerts function
48 * @returns array of alerts count
50 function GetPortalAlertCounts(): array
52 $counts = array();
53 $s_user = '%' . $_SESSION['authUser'] . '%';
55 $query = "SELECT Count(`m`.message_status) AS count_mail FROM onsite_mail `m` " .
56 "WHERE `m`.owner LIKE ? AND `m`.recipient_id LIKE ? AND `m`.message_status LIKE ? AND `m`.deleted = 0";
57 $qrtn = sqlQueryNoLog($query, array($s_user, $s_user, '%new%'));
58 $counts['mailCnt'] = $qrtn['count_mail'] ?: "0";
60 $query = "SELECT Count(`m`.status) AS count_audits FROM onsite_portal_activity `m` " .
61 "WHERE `m`.status LIKE ?";
62 $qrtn = sqlQueryNoLog($query, array('%waiting%'));
63 $counts['auditCnt'] = $qrtn['count_audits'] ?: "0";
65 $query = "SELECT Count(`m`.id) AS count_chats FROM onsite_messages `m` " .
66 "WHERE `m`.recip_id LIKE ? AND `m`.date > (CURRENT_DATE()-2) AND `m`.date < (CURRENT_DATE()+1)";
67 $qrtn = sqlQueryNoLog($query, array($s_user));
68 $counts['chatCnt'] = $qrtn['count_chats'] ? $qrtn['count_chats'] : "0";
70 $query = "SELECT Count(`m`.status) AS count_payments FROM onsite_portal_activity `m` " .
71 "WHERE `m`.status LIKE ? AND `m`.activity = ?";
72 $qrtn = sqlQueryNoLog($query, array('%waiting%', 'payment'));
73 $counts['paymentCnt'] = $qrtn['count_payments'] ?: "0";
75 $counts['total'] = $counts['mailCnt'] + $counts['auditCnt'] + $counts['chatCnt'] + $counts['paymentCnt'];
77 return $counts;
80 /**
81 * RemindersArray function
83 * @returns array reminders for specified user, defaults to current user if none specified
85 function RemindersArray($days_to_show, $today, $alerts_to_show, $userID = null)
87 if (!$userID) {
88 $userID = $_SESSION['authUserID'];
91 global $hasAlerts;
92 // ----- define a blank reminders array
93 $reminders = array();
95 // ----- sql statement for getting uncompleted reminders (sorts by date, then by priority)
96 $drSQL = sqlStatement("SELECT dr.pid, dr.dr_id, dr.dr_message_text,dr.dr_message_due_date,
97 u.fname ffname, u.mname fmname, u.lname flname FROM `dated_reminders` dr
98 JOIN `users` u ON dr.dr_from_ID = u.id
99 JOIN `dated_reminders_link` drl ON dr.dr_id = drl.dr_id
100 WHERE drl.to_id = ? AND dr.`message_processed` = 0
101 AND dr.`dr_message_due_date` < ADDDATE(NOW(), INTERVAL " . escape_limit($days_to_show) . " DAY)
102 ORDER BY `dr_message_due_date` ASC , `message_priority` ASC LIMIT 0," . escape_limit($alerts_to_show), array($userID));
104 // --------- loop through the results
105 for ($i = 0; $drRow = sqlFetchArray($drSQL); $i++) {
106 // --------- need to run patient query seperately to allow for reminders not linked to a patient
107 $pRow = array();
108 if ($drRow['pid'] > 0) {
109 $pSQL = sqlStatement("SELECT pd.title ptitle, pd.fname pfname, pd.mname pmname, pd.lname plname FROM `patient_data` pd WHERE pd.pid = ?", array($drRow['pid']));
110 $pRow = sqlFetchArray($pSQL);
113 // --------- fill the $reminders array
114 $reminders[$i]['messageID'] = $drRow['dr_id'];
115 $reminders[$i]['PatientID'] = $drRow['pid'];
117 // ------------------------------------- if there was a patient linked, set the name, else set it to blank
118 $reminders[$i]['PatientName'] = (empty($pRow) ? '' : $pRow['ptitle'] . ' ' . $pRow['pfname'] . ' ' . $pRow['pmname'] . ' ' . $pRow['plname']);
119 // -------------------------------------
121 $reminders[$i]['message'] = $drRow['dr_message_text'];
122 $reminders[$i]['dueDate'] = $drRow['dr_message_due_date'];
123 $reminders[$i]['fromName'] = $drRow['ffname'] . ' ' . $drRow['fmname'] . ' ' . $drRow['flname'];
125 // --------- if the message is due or overdue set $hasAlerts to true, this will stop autohiding of reminders
126 if (strtotime($drRow['dr_message_due_date']) <= $today) {
127 $hasAlerts = true;
131 // --------- END OF loop through the results
133 return $reminders;
136 // ------------------------------------------------
137 // @ END OF RemindersArray function
138 // ------------------------------------------------
142 * This function is used to get a count of the number of reminders due for a specified
143 * user.
145 * @param $days_to_show
146 * @param $today
147 * @param $userID
148 * @returns int with number of due reminders for specified user
150 function GetDueReminderCount($days_to_show, $today, $userID = false)
152 if (!$userID) {
153 $userID = $_SESSION['authUserID'];
156 // ----- sql statement for getting uncompleted reminders (sorts by date, then by priority)
157 $drSQL = sqlStatement(
158 "SELECT count(dr.dr_id) c
159 FROM `dated_reminders` dr
160 JOIN `users` u ON dr.dr_from_ID = u.id
161 JOIN `dated_reminders_link` drl ON dr.dr_id = drl.dr_id
162 WHERE drl.to_id = ?
163 AND dr.`message_processed` = 0
164 AND dr.`dr_message_due_date` < ADDDATE(NOW(), INTERVAL " . escape_limit($days_to_show) . " DAY)",
165 array($userID)
168 $drRow = sqlFetchArray($drSQL);
169 return $drRow['c'];
172 // ------------------------------------------------
173 // @ END OF GetDueReminder function
174 // ------------------------------------------------
176 // ------------------------------------------------
177 // @ GetAllReminderCount function
178 // @ returns int with number of unprocessed reminders for specified user, defaults to current user if none specified
179 // ------------------------------------------------
181 * @param $userID
182 * @return mixed
184 function GetAllReminderCount($userID = false)
186 if (!$userID) {
187 $userID = $_SESSION['authUserID'];
190 // ----- sql statement for getting uncompleted reminders
191 $drSQL = sqlStatement(
192 "SELECT count(dr.dr_id) c
193 FROM `dated_reminders` dr
194 JOIN `users` u ON dr.dr_from_ID = u.id
195 JOIN `dated_reminders_link` drl ON dr.dr_id = drl.dr_id
196 WHERE drl.to_id = ?
197 AND dr.`message_processed` = 0",
198 array($userID)
201 $drRow = sqlFetchArray($drSQL);
202 return $drRow['c'];
205 // ------------------------------------------------
206 // @ END OF GetAllReminderCount function
207 // ------------------------------------------------
209 // ------------------------------------------------
210 // @ getRemindersHTML(array $reminders)
211 // @ returns HTML as a string, for printing
212 // ------------------------------------------------
214 * @param $today
215 * @param $reminders
216 * @return string
218 function getRemindersHTML($today, $reminders = array()): string
220 global $hasAlerts;
221 // --- initialize the string as blank
222 $pdHTML = '';
223 // --- loop through the $reminders
224 foreach ($reminders as $r) {
225 // --- initialize $warning as the date, this is placed in front of the message
226 $warning = text($r['dueDate']);
227 // --- initialize $class as 'text dr', this is the basic class
228 $class = 'text dr';
230 // --------- check if reminder is overdue
231 if (strtotime($r['dueDate']) < $today) {
232 $warning = '<i class=\'fa fa-exclamation-triangle fa-lg text-danger\' aria-hidden=\'true\'></i> ' . xlt('OVERDUE');
233 //$class = 'bold alert dr';
234 $class = '';
235 } elseif (strtotime($r['dueDate']) == $today) {
236 // --------- check if reminder is due
237 $warning = '<i class=\'fa fa-exclamation-circle fa-lg\' style=\'color: var(--orange)\' aria-hidden=\'true\'></i> ' . xlt('TODAY');
238 $class = '';
239 } elseif (strtotime($r['dueDate']) > $today) {
240 $warning = '<i class=\'fa fa-exclamation-circle fa-lg text-success\' aria-hidden=\'true\'></i> ' . xlt('UPCOMING');
241 $class = '';
244 // end check if reminder is due or overdue
245 // apend to html string
246 $pdHTML .= '<p id="p_' . attr($r['messageID']) . '">
247 <a onclick="openAddScreen(' . attr(addslashes($r['messageID'])) . ')" class="dnForwarder btn btn-secondary btn-send-msg" id="' . attr($r['messageID']) . '" href="#"> ' . xlt('Forward') . ' </a>
248 <a class="dnRemover btn btn-secondary btn-save" onclick="updateme(' . "'" . attr(addslashes($r['messageID'])) . "'" . ')" id="' . attr($r['messageID']) . '" href="#">
249 <span>' . xlt('Set As Completed') . '</span>
250 </a>
251 <span title="' . ($r['PatientID'] > 0 ? xla('Click Patient Name to Open Patient File') : '') . '" class="' . attr($class) . '">' .
252 $warning . '
253 <span onclick="goPid(' . attr(addslashes($r['PatientID'])) . ')" class="patLink" id="' . attr($r['PatientID']) . '">' .
254 text($r['PatientName']) . '
255 </span> ' .
256 text($r['message']) . ' - [' . text($r['fromName']) . ']
257 </span>
258 </p>';
261 return ($pdHTML == '' ? '<i class=\'fa fa-exclamation-circle fa-lg\' aria-hidden=\'true\'></i> ' . xlt('No Reminders') : $pdHTML);
264 // ------------------------------------------------
265 // @ END OF getRemindersHTML function
266 // ------------------------------------------------
269 // ------------------------------------------------
270 // @ setReminderAsProccessed(int $rID)
271 // @ marks reminder as processed
272 // ------------------------------------------------
274 * @param $rID
275 * @param $userID
276 * @return void
278 function setReminderAsProcessed($rID, $userID = false): void
280 if (!$userID) {
281 $userID = $_SESSION['authUserID'];
284 if (is_numeric($rID) and $rID > 0) {
285 // --- check if this user can remove this message
286 // --- need a better way of checking the current user, I don't like using $_SESSION for checks
287 $rdrSQL = sqlStatement("SELECT count(dr.dr_id) c FROM `dated_reminders` dr JOIN `dated_reminders_link` drl ON dr.dr_id = drl.dr_id WHERE drl.to_id = ? AND dr.`dr_id` = ? LIMIT 0,1", array($userID, $rID));
288 $rdrRow = sqlFetchArray($rdrSQL);
290 // --- if this user can delete this message (ie if it was sent to this user)
291 if ($rdrRow['c'] == 1) {
292 // ----- update the data, set the message to proccesses
293 sqlStatement("UPDATE `dated_reminders` SET `message_processed` = 1, `processed_date` = NOW(), `dr_processed_by` = ? WHERE `dr_id` = ? ", array(intval($userID), intval($rID)));
298 // ------------------------------------------------
299 // @ END OF setReminderAsProccessed function
300 // ------------------------------------------------
303 // ------------------------------------------------
304 // @ getReminderById(int $mID)
305 // @ returns an array with message details for forwarding
306 // ------------------------------------------------
308 * @param $mID
309 * @param $userID
310 * @return bool|array
312 function getReminderById($mID, $userID = false): bool|array
314 if (!$userID) {
315 $userID = $_SESSION['authUserID'];
318 $rdrSQL = sqlStatement("SELECT * FROM `dated_reminders` dr
319 JOIN `dated_reminders_link` drl ON dr.dr_id = drl.dr_id
320 WHERE drl.to_id = ? AND dr.`dr_id` = ? LIMIT 0,1", array($userID, $mID));
321 $rdrRow = sqlFetchArray($rdrSQL);
322 if (!empty($rdrRow)) {
323 return $rdrRow;
326 return false;
329 // ------------------------------------------------
330 // @ END OF getReminderById function
331 // ------------------------------------------------
334 // ------------------------------------------------
335 // @ getReminderById(
336 // array $sendTo
337 // int $fromID
338 // string $message
339 // date $dueDate
340 // int $patID
341 // int $priority
342 // )
343 // @ returns an array with message details for forwarding
344 // ------------------------------------------------
346 * @param $sendTo
347 * @param $fromID
348 * @param $message
349 * @param $dueDate
350 * @param $patID
351 * @param $priority
352 * @return bool
354 function sendReminder($sendTo, $fromID, $message, $dueDate, $patID, $priority): bool
356 if (
357 // ------- Should run data checks before running this function for more accurate error reporting
358 // ------- check sendTo is not empty
359 !empty($sendTo) and
360 // ------- check dueDate, only allow valid dates, todo -> enhance date checker
361 preg_match('/\d{4}[-]\d{2}[-]\d{2}/', $dueDate) and
362 // ------- check priority, only allow 1-3
363 intval($priority) <= 3 and
364 // ------- check message, only up to 255 characters
365 strlen($message) <= 255 and strlen($message) > 0 and
366 // ------- check if PatientID is set and in numeric
367 is_numeric($patID)
369 // ------- check for valid recipient
370 $cRow = sqlFetchArray(sqlStatement('SELECT count(id) FROM `users` WHERE `id` = ?', array($sendDMTo ?? '')));
371 if ($cRow == 0) {
372 return false;
375 // ------- if no errors
376 // --------- insert the new message
377 $mID = sqlInsert(
378 "INSERT INTO `dated_reminders`
379 (`dr_from_ID` ,`dr_message_text` ,`dr_message_sent_date` ,`dr_message_due_date` ,`pid` ,`message_priority` ,`message_processed` ,`processed_date`)
380 VALUES (?, ?, NOW( ), ?, ?, ?, '0', '');",
381 array($fromID, $message, $dueDate, $patID, $priority)
384 foreach ($sendTo as $st) {
385 sqlStatement(
386 "INSERT INTO `dated_reminders_link`
387 (`dr_id` ,`to_id`)
388 VALUES (?, ?);",
389 array($mID, $st)
392 return true;
393 } //---- end of if block
394 return false;
397 // ------- get current patient name
398 // ---- returns string, blank if no current patient
400 * @param $patientID
401 * @return string
403 function getPatName($patientID): string
405 $patientID = intval($patientID);
406 $pSQL = sqlStatement("SELECT pd.title ptitle, pd.fname pfname, pd.mname pmname, pd.lname plname FROM `patient_data` pd WHERE pd.pid = ?", array($patientID));
407 $pRow = sqlFetchArray($pSQL);
408 return (empty($pRow) ? '' : $pRow['ptitle'] . ' ' . $pRow['pfname'] . ' ' . $pRow['pmname'] . ' ' . $pRow['plname']);
411 // -- log reminders array function uses $_GET to filter
413 * @return array
415 function logRemindersArray(): array
418 // set blank array for data to be parsed to sql
419 $input = array();
420 // set blank string for the query
421 $where = '';
422 $sentBy = $_GET['sentBy'] ?? '';
423 $sentTo = $_GET['sentTo'] ?? '';
424 //------------------------------------------
425 // ----- HANDLE SENT BY FILTER
426 if (!empty($sentBy)) {
427 $sbCount = 0;
428 foreach ($sentBy as $sb) {
429 $where .= ($sbCount == 0 ? '(' : ' OR ') . 'dr.dr_from_ID = ? ';
430 $sbCount++;
431 $input[] = $sb;
434 $where .= ')';
437 //------------------------------------------
438 // ----- HANDLE SENT TO FILTER
439 if (!empty($sentTo)) {
440 $where = ($where == '' ? '' : $where . ' AND ');
441 $stCount = 0;
442 foreach ($sentTo as $st) {
443 $where .= ($stCount == 0 ? '(' : ' OR ') . 'drl.to_id = ? ';
444 $stCount++;
445 $input[] = $st;
448 $where .= ')';
451 //------------------------------------------
452 // ----- HANDLE PROCCESSED/PENDING FILTER ONLY RUN THIS IF BOTH ARE NOT SET
453 if (isset($_GET['processed']) and !isset($_GET['pending'])) {
454 $where = ($where == '' ? 'dr.message_processed = 1' : $where . ' AND dr.message_processed = 1');
455 } elseif (!isset($_GET['processed']) and isset($_GET['pending'])) {
456 $where = ($where == '' ? 'dr.message_processed = 0' : $where . ' AND dr.message_processed = 0');
459 //------------------------------------------
460 // ----- HANDLE DATE RANGE FILTERS
461 if (isset($_GET['sd']) and $_GET['sd'] != '') {
462 $where = ($where == '' ? 'dr.dr_message_sent_date >= ?' : $where . ' AND dr.dr_message_sent_date >= ?');
463 $input[] = DateToYYYYMMDD($_GET['sd']) . ' 00:00:00';
466 if (isset($_GET['ed']) and $_GET['ed'] != '') {
467 $where = ($where == '' ? 'dr.dr_message_sent_date <= ?' : $where . ' AND dr.dr_message_sent_date <= ?');
468 $input[] = DateToYYYYMMDD($_GET['ed']) . ' 23:59:59';
471 //------------------------------------------
474 //-------- add the "WHERE" the string if string is not blank, avoid sql errors for blannk WHERE statements
475 $where = ($where == '' ? '' : 'WHERE ' . $where);
477 // ----- define a blank reminders array
478 $reminders = array();
480 // ----- sql statement for getting uncompleted reminders (sorts by date, then by priority)
481 $drSQL = sqlStatement(
482 "SELECT
483 dr.pid, dr.dr_id, dr.dr_message_text, dr.dr_message_due_date dDate, dr.dr_message_sent_date sDate,dr.processed_date processedDate, dr.dr_processed_by,
484 u.fname ffname, u.mname fmname, u.lname flname,
485 tu.fname tfname, tu.mname tmname, tu.lname tlname
486 FROM `dated_reminders` dr
487 JOIN `dated_reminders_link` drl ON dr.dr_id = drl.dr_id
488 JOIN `users` u ON dr.dr_from_ID = u.id
489 JOIN `users` tu ON drl.to_id = tu.id
490 $where",
491 $input
493 // --------- loop through the results
494 for ($i = 0; $drRow = sqlFetchArray($drSQL); $i++) {
495 // --------- need to run patient query seperately to allow for messages not linked to a patient
496 $pSQL = sqlStatement("SELECT pd.title ptitle, pd.fname pfname, pd.mname pmname, pd.lname plname FROM `patient_data` pd WHERE pd.pid = ?", array($drRow['pid']));
497 $pRow = sqlFetchArray($pSQL);
499 $prSQL = sqlStatement("SELECT u.fname pfname, u.mname pmname, u.lname plname FROM `users` u WHERE u.id = ?", array($drRow['dr_processed_by']));
500 $prRow = sqlFetchArray($prSQL);
502 // --------- fill the $reminders array
503 $reminders[$i]['messageID'] = $drRow['dr_id'];
504 $reminders[$i]['PatientID'] = $drRow['pid'];
506 $reminders[$i]['pDate'] = ($drRow['processedDate'] == '0000-00-00 00:00:00' ? 'N/A' : $drRow['processedDate']);
507 $reminders[$i]['sDate'] = $drRow['sDate'];
508 $reminders[$i]['dDate'] = $drRow['dDate'];
510 // ------------------------------------- if there was a patient linked, set the name, else set it to blank
511 $reminders[$i]['PatientName'] = (empty($pRow) ? 'N/A' : $pRow['ptitle'] . ' ' . $pRow['pfname'] . ' ' . $pRow['pmname'] . ' ' . $pRow['plname']);
512 // -------------------------------------
514 $reminders[$i]['message'] = $drRow['dr_message_text'];
515 $reminders[$i]['fromName'] = $drRow['ffname'] . ' ' . $drRow['fmname'] . ' ' . $drRow['flname'];
516 $reminders[$i]['ToName'] = $drRow['tfname'] . ' ' . $drRow['tmname'] . ' ' . $drRow['tlname'];
517 $reminders[$i]['processedByName'] = (empty($prRow) ? 'N/A' : ($prRow['ptitle'] ?? '') . ' ' . $prRow['pfname'] . ' ' . $prRow['pmname'] . ' ' . $prRow['plname']);
520 // --------- END OF loop through the results
522 return $reminders;