4 * This file contains functions for handling notes attached to patient files.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * 2013-02-08 EMR Direct: changes to allow notes added by background-services with pid=0
14 use OpenEMR\Common\Logging\SystemLogger;
17 * Retrieve a note, given its ID
19 * @param string $id the ID of the note to retrieve.
20 * @param string $cols A list of columns to retrieve. defaults to '*' for all.
22 function getPnoteById($id, $cols = "*")
24 return sqlQuery("SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes')) . " FROM pnotes WHERE id=? " .
25 ' AND deleted != 1 ' . // exclude ALL deleted notes
26 'order by date DESC limit 0,1', array($id));
30 * Get the patient notes for the given user.
32 * This function is used to retrieve notes assigned to the given user, or
33 * optionally notes assigned to any user.
35 * @param string $activity 0 for deleted notes, 1 (the default) for active
36 * notes, or 'All' for all.
37 * @param string $show_all whether to display only the selected user's
38 * messages, or all users' messages.
39 * @param string $user The user whom's notes you want to retrieve.
40 * @param bool $count Whether to return a count, or just return 0.
41 * @param string $sortby A field to sort results by. (options are users.lname,patient_data.lname,pnotes.title,pnotes.date,pnotes.message_status) (will default to users.lname)
42 * @param string $sortorder whether to sort ascending or descending.
43 * @param string $begin what row to start retrieving results from.
44 * @param string $listnumber number of rows to return.
45 * @return int The number of rows retrieved, or 0 if $count was true.
47 function getPnotesByUser($activity = "1", $show_all = "no", $user = '', $count = false, $sortby = '', $sortorder = '', $begin = '', $listnumber = '')
50 // Set the activity part of query
51 if ($activity == '1') {
52 $activity_query = " pnotes.message_status != 'Done' AND pnotes.activity = 1 AND ";
53 } elseif ($activity == '0') {
54 $activity_query = " (pnotes.message_status = 'Done' OR pnotes.activity = 0) AND ";
55 } else { //$activity=='all'
56 $activity_query = " ";
59 // Set whether to show chosen user or all users
60 if ($show_all == 'yes') {
67 // 2013-02-08 EMR Direct: minor changes to query so notes with pid=0 don't disappear
68 $sql = "SELECT pnotes.id, pnotes.user, pnotes.pid, pnotes.title, pnotes.date, pnotes.message_status, pnotes.activity,
69 IF(pnotes.pid = 0 OR pnotes.user != pnotes.pid,users.fname,patient_data.fname) as users_fname,
70 IF(pnotes.pid = 0 OR pnotes.user != pnotes.pid,users.lname,patient_data.lname) as users_lname,
71 patient_data.fname as patient_data_fname, patient_data.lname as patient_data_lname
72 FROM ((pnotes LEFT JOIN users ON pnotes.user = users.username)
73 LEFT JOIN patient_data ON pnotes.pid = patient_data.pid) WHERE $activity_query
74 pnotes.deleted != '1' AND pnotes.assigned_to LIKE ?";
75 if (!empty($sortby) || !empty($sortorder) || !empty($begin) || !empty($listnumber)) {
76 $sql .= " order by " . escape_sql_column_name($sortby, array('users','patient_data','pnotes'), true) .
77 " " . escape_sort_order($sortorder) .
78 " limit " . escape_limit($begin) . ", " . escape_limit($listnumber);
81 $result = sqlStatement($sql, array($usrvar));
85 if (sqlNumRows($result) != 0) {
86 $total = sqlNumRows($result);
97 function getPnotesByDate(
110 $sqlParameterArray = array();
112 $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes', 'gprelations')) . " FROM pnotes AS p, gprelations AS r " .
113 "WHERE p.date LIKE ? AND r.type1 = 1 AND " .
114 "r.id1 = ? AND r.type2 = 6 AND p.id = r.id2 AND p.pid != p.user";
115 array_push($sqlParameterArray, '%' . $date . '%', $docid);
116 } elseif ($orderid) {
117 $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes', 'gprelations')) . " FROM pnotes AS p, gprelations AS r " .
118 "WHERE p.date LIKE ? AND r.type1 = 2 AND " .
119 "r.id1 = ? AND r.type2 = 6 AND p.id = r.id2 AND p.pid != p.user";
120 array_push($sqlParameterArray, '%' . $date . '%', $orderid);
122 $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes')) . " FROM pnotes AS p " .
123 "WHERE date LIKE ? AND pid LIKE ? AND p.pid != p.user";
124 array_push($sqlParameterArray, '%' . $date . '%', $pid);
127 $sql .= " AND deleted != 1"; // exclude ALL deleted notes
128 if ($activity != "all") {
129 if ($activity == '0') {
130 // only return inactive
131 $sql .= " AND (activity = '0' OR message_status = 'Done') ";
132 } else { // $activity == '1'
133 // only return active
134 $sql .= " AND activity = '1' AND message_status != 'Done' ";
139 $sql .= " AND assigned_to LIKE ?";
140 array_push($sqlParameterArray, $username);
144 $sql .= " AND message_status IN ('" . str_replace(",", "','", add_escape_custom($status)) . "')";
147 $sql .= " ORDER BY date DESC";
148 if ($limit != "all") {
149 $sql .= " LIMIT " . escape_limit($start) . ", " . escape_limit($limit);
152 $res = sqlStatement($sql, $sqlParameterArray);
155 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
162 // activity can only be 0, 1, or 'all'
163 function getSentPnotesByDate(
176 $sqlParameterArray = array();
178 $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes', 'gprelations')) . " FROM pnotes AS p, gprelations AS r " .
179 "WHERE p.date LIKE ? AND r.type1 = 1 AND " .
180 "r.id1 = ? AND r.type2 = 6 AND p.id = r.id2 AND p.pid = p.user";
181 array_push($sqlParameterArray, '%' . $date . '%', $docid);
182 } elseif ($orderid) {
183 $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes','gprelations')) . " FROM pnotes AS p, gprelations AS r " .
184 "WHERE p.date LIKE ? AND r.type1 = 2 AND " .
185 "r.id1 = ? AND r.type2 = 6 AND p.id = r.id2 AND p.pid = p.user";
186 array_push($sqlParameterArray, '%' . $date . '%', $orderid);
188 $sql = "SELECT " . escape_sql_column_name(process_cols_escape($cols), array('pnotes')) . " FROM pnotes AS p " .
189 "WHERE date LIKE ? AND pid LIKE ? AND p.pid = p.user";
190 array_push($sqlParameterArray, '%' . $date . '%', $pid);
193 $sql .= " AND deleted != 1"; // exclude ALL deleted notes
194 if ($activity != "all") {
195 if ($activity == '0') {
196 // only return inactive
197 $sql .= " AND (activity = '0' OR message_status = 'Done') ";
198 } else { // $activity == '1'
199 // only return active
200 $sql .= " AND activity = '1' AND message_status != 'Done' ";
205 $sql .= " AND assigned_to LIKE ?";
206 array_push($sqlParameterArray, $username);
210 $sql .= " AND message_status IN ('" . str_replace(",", "','", add_escape_custom($status)) . "')";
213 $sql .= " ORDER BY date DESC";
214 if ($limit != "all") {
215 $sql .= " LIMIT " . escape_limit($start) . ", " . escape_limit($limit);
218 $res = sqlStatement($sql, $sqlParameterArray);
221 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
228 function getPatientNotes($pid = '', $limit = '', $offset = 0, $search = '')
231 $limit = "LIMIT " . escape_limit($offset) . ", " . escape_limit($limit);
243 CONCAT(pd.fname, ' ', pd.lname)
250 LEFT JOIN patient_data AS pd
252 WHERE assigned_to = '-patient-'
259 $res = sqlStatement($sql, array($pid));
260 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
267 function getPatientNotifications($pid = '', $limit = '', $offset = 0, $search = '')
270 $limit = "LIMIT " . escape_limit($offset) . ", " . escape_limit($limit);
276 date_created AS `date`,
277 'Patient Reminders' AS `user`,
279 CONCAT(lo.title, ':', lo2.title) AS body,
280 '' as message_status,
281 'Notification' as `type`
283 patient_reminders AS pr
284 LEFT JOIN list_options AS lo
285 ON lo.option_id = pr.category
286 AND lo.list_id = 'rule_action_category' AND lo.activity = 1
287 LEFT JOIN list_options AS lo2
288 ON lo2.option_id = pr.item
289 AND lo2.list_id = 'rule_action' AND lo2.activity = 1
292 AND date_created > DATE_SUB(NOW(), INTERVAL 1 MONTH)
297 $res = sqlStatement($sql, array($pid));
298 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
305 function getPatientSentNotes($pid = '', $limit = '', $offset = 0, $search = '')
308 $limit = "LIMIT " . escape_limit($offset) . ", " . escape_limit($limit);
320 CONCAT(pd.lname, ' ', pd.fname)
327 LEFT JOIN patient_data AS pd
332 AND p.message_status != 'Done'
337 $res = sqlStatement($sql, array($pid,$pid));
338 for ($iter = 0; $row = sqlFetchArray($res); $iter++) {
347 /** Add a note to a patient's medical record.
349 * @param int $pid the ID of the patient whos medical record this note is going to be attached to.
350 * @param string $newtext the note contents.
351 * @param int $authorized
352 * @param int $activity
353 * @param string $title
354 * @param string $assigned_to
355 * @param string $datetime
356 * @param string $message_status
357 * @param string $background_user if set then the pnote is created by a background-service rather than a user
358 * @return int the ID of the added note.
365 $title = 'Unassigned',
368 $message_status = 'New',
369 $background_user = ""
372 if (empty($datetime)) {
373 $datetime = date('Y-m-d H:i:s');
376 // make inactive if set as Done
377 if ($message_status == 'Done') {
380 $user = ($background_user != "" ? $background_user : $_SESSION['authUser']);
381 $body = date('Y-m-d H:i') . ' (' . $user;
383 $body .= " to $assigned_to";
386 $body = $body . ') ' . $newtext;
389 'INSERT INTO pnotes (date, body, pid, user, groupname, ' .
390 'authorized, activity, title, assigned_to, message_status, update_by, update_date) VALUES ' .
391 '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())',
392 array($datetime, $body, $pid, $user, $_SESSION['authProvider'], $authorized, $activity, $title, $assigned_to, $message_status, $_SESSION['authUserID'])
396 function addMailboxPnote(
401 $title = 'Unassigned',
404 $message_status = "New"
407 if (empty($datetime)) {
408 $datetime = date('Y-m-d H:i:s');
411 // make inactive if set as Done
412 if ($message_status == "Done") {
416 $body = date('Y-m-d H:i') . ' (' . $pid;
418 $body .= " to $assigned_to";
421 $body = $body . ') ' . $newtext;
424 "INSERT INTO pnotes (date, body, pid, user, groupname, " .
425 "authorized, activity, title, assigned_to, message_status, update_by, update_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())",
426 array($datetime, $body, $pid, $pid, 'Default', $authorized, $activity, $title, $assigned_to, $message_status, $_SESSION['authUserID'])
430 function updatePnote($id, $newtext, $title, $assigned_to, $message_status = "", $datetime = "")
432 $row = getPnoteById($id);
434 die("updatePnote() did not find id '" . text($id) . "'");
437 if (empty($datetime)) {
438 $datetime = date('Y-m-d H:i:s');
441 $activity = $assigned_to ? '1' : '0';
443 // make inactive if set as Done
444 if ($message_status == "Done") {
448 $body = $row['body'] . "\n" . date('Y-m-d H:i') .
449 ' (' . $_SESSION['authUser'];
451 $body .= " to $assigned_to";
454 $body = $body . ') ' . $newtext;
457 $sql = "UPDATE pnotes SET " .
458 "body = ?, activity = ?, title= ?, " .
459 "assigned_to = ?, update_by = ?, update_date = NOW()";
460 $bindingParams = array($body, $activity, $title, $assigned_to, $_SESSION['authUserID']);
461 if ($message_status) {
462 $sql .= " ,message_status = ?";
463 $bindingParams[] = $message_status;
465 if ($GLOBALS['messages_due_date']) {
466 $sql .= " ,date = ?";
467 $bindingParams[] = $datetime;
469 $sql .= " WHERE id = ?";
470 $bindingParams[] = $id;
471 sqlStatement($sql, $bindingParams);
474 function updatePnoteMessageStatus($id, $message_status)
476 if ($message_status == "Done") {
477 sqlStatement("update pnotes set message_status = ?, activity = '0', update_by = ?, update_date = NOW() where id = ?", array($message_status, $_SESSION['authUserID'], $id));
479 sqlStatement("update pnotes set message_status = ?, activity = '1', update_by = ?, update_date = NOW() where id = ?", array($message_status, $_SESSION['authUserID'], $id));
484 * Set the patient id in an existing message where pid=0
485 * @param $id the id of the existing note
486 * @param $patient_id the patient id to associate with the note
487 * @author EMR Direct <http://www.emrdirect.com/>
489 function updatePnotePatient($id, $patient_id)
491 $row = getPnoteById($id);
493 die("updatePnotePatient() did not find id '" . text($id) . "'");
496 $activity = $assigned_to ? '1' : '0';
500 if ($pid != 0 || (int)$patient_id < 1) {
501 (new SystemLogger())->errorLogCaller("invalid operation", ['id' => $id, 'patient_id' => $patient_id, 'pid' => $pid]);
502 die("updatePnotePatient invalid operation");
505 $pid = (int) $patient_id;
506 $newtext = "\n" . date('Y-m-d H:i') . " (patient set by " . $_SESSION['authUser'] . ")";
507 $body = $row['body'] . $newtext;
509 sqlStatement("UPDATE pnotes SET pid = ?, body = ?, update_by = ?, update_date = NOW() WHERE id = ?", array($pid, $body, $_SESSION['authUserID'], $id));
512 function authorizePnote($id, $authorized = "1")
514 sqlQuery("UPDATE pnotes SET authorized = ? , update_by = ?, update_date = NOW() WHERE id = ?", array ($authorized, $_SESSION['authUserID'], $id));
517 function disappearPnote($id)
519 sqlStatement("UPDATE pnotes SET activity = '0', message_status = 'Done', update_by = ?, update_date = NOW() WHERE id=?", array($_SESSION['authUserID'], $id));
523 function reappearPnote($id)
525 sqlStatement("UPDATE pnotes SET activity = '1', message_status = IF(message_status='Done','New',message_status), update_by = ?, update_date = NOW() WHERE id=?", array($_SESSION['authUserID'], $id));
529 function deletePnote($id)
532 getAssignedToById($id) == $_SESSION['authUser']
533 || getMessageStatusById($id) == 'Done'
535 sqlStatement("UPDATE pnotes SET deleted = '1', update_by = ?, update_date = NOW() WHERE id=?", array($_SESSION['authUserID'], $id));
542 // Note that it is assumed that html escaping has happened before this function is called
543 function pnoteConvertLinks($note)
545 $noteActiveLink = preg_replace('!(https://[-a-zA-Z()0-9@:%_+.~#?&;//=]+)!i', '<a href="$1" target="_blank" rel="noopener">$1</a>', $note);
546 if (empty($noteActiveLink)) {
547 // something bad happened (preg_replace returned null) or the $note was empty
550 return $noteActiveLink;
555 * Retrieve assigned_to field given the note ID
557 * @param string $id the ID of the note to retrieve.
559 function getAssignedToById($id)
561 $result = sqlQuery("SELECT assigned_to FROM pnotes WHERE id=?", array($id));
562 return $result['assigned_to'];
566 * Retrieve message_status field given the note ID
568 * @param string $id the ID of the note to retrieve.
570 function getMessageStatusById($id)
572 $result = sqlQuery("SELECT message_status FROM pnotes WHERE id=?", array($id));
573 return $result['message_status'];