feat: Improved spacing of additional code buttons on fee sheet (#6790)
[openemr.git] / library / appointments.inc.php
blob234d1c92b500a9b8cc72719fd956e3468b152d2b
1 <?php
3 /**
4 * Holds library functions (and hashes) used by the appointment reporting module
5 * @package OpenEMR
6 * @link https://www.open-emr.org
7 * @author Ken Chapple <ken@mi-squared.com>
8 * @author Ian Jardine <https://github.com/epsdky>
9 * @copyright Copyright (c) 2011 Ken Chapple <ken@mi-squared.com>
10 * @copyright Copyright (c) 2023 Ian Jardine <https://github.com/epsdky>
11 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
14 require_once(dirname(__FILE__) . "/encounter_events.inc.php");
15 require_once(dirname(__FILE__) . "/../interface/main/calendar/modules/PostCalendar/pnincludes/Date/Calc.php");
17 use OpenEMR\Events\Appointments\AppointmentsFilterEvent;
18 use OpenEMR\Events\BoundFilter;
20 $COMPARE_FUNCTION_HASH = array(
21 'doctor' => 'compareAppointmentsByDoctorName',
22 'patient' => 'compareAppointmentsByPatientName',
23 'pubpid' => 'compareAppointmentsByPatientId',
24 'date' => 'compareAppointmentsByDate',
25 'time' => 'compareAppointmentsByTime',
26 'type' => 'compareAppointmentsByType',
27 'comment' => 'compareAppointmentsByComment',
28 'status' => 'compareAppointmentsByStatus',
29 'completed' => 'compareAppointmentsByCompletedDrugScreen',
30 'trackerstatus' => 'compareAppointmentsByTrackerStatus'
33 $ORDERHASH = array(
34 'doctor' => array( 'doctor', 'date', 'time' ),
35 'patient' => array( 'patient', 'date', 'time' ),
36 'pubpid' => array( 'pubpid', 'date', 'time' ),
37 'date' => array( 'date', 'time', 'type', 'patient' ),
38 'time' => array( 'time', 'date', 'patient' ),
39 'type' => array( 'type', 'date', 'time', 'patient' ),
40 'comment' => array( 'comment', 'date', 'time', 'patient' ),
41 'status' => array( 'status', 'date', 'time', 'patient' ),
42 'completed' => array( 'completed', 'date', 'time', 'patient' ),
43 'trackerstatus' => array( 'trackerstatus', 'date', 'time', 'patient' ),
46 /*Arrays for the interpretation of recurrence patterns.*/
47 $REPEAT_FREQ = array(
48 '1' => xl('Every'),
49 '2' => xl('Every 2nd'),
50 '3' => xl('Every 3rd'),
51 '4' => xl('Every 4th'),
52 '5' => xl('Every 5th'),
53 '6' => xl('Every 6th')
56 $REPEAT_FREQ_TYPE = array(
57 '0' => xl('day'),
58 '1' => xl('week'),
59 '2' => xl('month'),
60 '3' => xl('year'),
61 '4' => xl('workday')
64 $REPEAT_ON_NUM = array(
65 '1' => xl('1st{{nth}}'),
66 '2' => xl('2nd{{nth}}'),
67 '3' => xl('3rd{{nth}}'),
68 '4' => xl('4th{{nth}}'),
69 '5' => xl('Last')
72 $REPEAT_ON_DAY = array(
73 '0' => xl('Sunday'),
74 '1' => xl('Monday'),
75 '2' => xl('Tuesday'),
76 '3' => xl('Wednesday'),
77 '4' => xl('Thursday'),
78 '5' => xl('Friday'),
79 '6' => xl('Saturday')
82 function checkEvent($recurrtype, $recurrspec)
85 $eFlag = 0;
87 switch ($recurrtype) {
88 case 1:
89 case 3:
90 if (empty($recurrspec['event_repeat_freq']) || !isset($recurrspec['event_repeat_freq_type'])) {
91 $eFlag = 1; }
93 break;
95 case 2:
96 if (empty($recurrspec['event_repeat_on_freq']) || empty($recurrspec['event_repeat_on_num']) || !isset($recurrspec['event_repeat_on_day'])) {
97 $eFlag = 1; }
99 break;
102 return $eFlag;
105 function fetchEvents($from_date, $to_date, $where_param = null, $orderby_param = null, $tracker_board = false, $nextX = 0, $bind_param = null, $query_param = null)
108 $sqlBindArray = array();
110 if ($query_param) {
111 $query = $query_param;
113 if ($bind_param) {
114 $sqlBindArray = $bind_param;
116 } else {
117 //////
118 if ($nextX) {
119 $where =
120 "((e.pc_endDate >= ? AND e.pc_recurrtype > '0') OR " .
121 "(e.pc_eventDate >= ?))";
123 array_push($sqlBindArray, $from_date, $from_date);
124 } else {
125 //////
126 $where =
127 "((e.pc_endDate >= ? AND e.pc_eventDate <= ? AND e.pc_recurrtype > '0') OR " .
128 "(e.pc_eventDate >= ? AND e.pc_eventDate <= ?))";
130 array_push($sqlBindArray, $from_date, $to_date, $from_date, $to_date);
133 if ($where_param) {
134 $where .= $where_param;
137 // Filter out appointments based on a custom module filter
138 $apptFilterEvent = new AppointmentsFilterEvent(new BoundFilter());
139 $apptFilterEvent = $GLOBALS["kernel"]->getEventDispatcher()->dispatch($apptFilterEvent, AppointmentsFilterEvent::EVENT_HANDLE, 10);
140 $boundFilter = $apptFilterEvent->getBoundFilter();
141 $sqlBindArray = array_merge($sqlBindArray, $boundFilter->getBoundValues());
142 $where .= " AND " . $boundFilter->getFilterClause();
144 $order_by = "e.pc_eventDate, e.pc_startTime";
145 if ($orderby_param) {
146 $order_by = $orderby_param;
149 // Tracker Board specific stuff
150 $tracker_fields = '';
151 $tracker_joins = '';
152 if ($tracker_board) {
153 $tracker_fields = "e.pc_room, e.pc_pid, t.id, t.date, t.apptdate, t.appttime, t.eid, t.pid, t.original_user, t.encounter, t.lastseq, t.random_drug_test, t.drug_screen_completed, " .
154 "q.pt_tracker_id, q.start_datetime, q.room, q.status, q.seq, q.user, " .
155 "s.toggle_setting_1, s.toggle_setting_2, s.option_id, ";
156 $tracker_joins = "LEFT OUTER JOIN patient_tracker AS t ON t.pid = e.pc_pid AND t.apptdate = e.pc_eventDate AND t.appttime = e.pc_starttime AND t.eid = e.pc_eid " .
157 "LEFT OUTER JOIN patient_tracker_element AS q ON q.pt_tracker_id = t.id AND q.seq = t.lastseq " .
158 "LEFT OUTER JOIN list_options AS s ON s.list_id = 'apptstat' AND s.option_id = q.status AND s.activity = 1 " ;
161 $query = "SELECT " .
162 "e.pc_eventDate, e.pc_endDate, e.pc_startTime, e.pc_endTime, e.pc_duration, e.pc_recurrtype, e.pc_recurrspec, e.pc_recurrfreq, e.pc_catid, e.pc_eid, e.pc_gid, " .
163 "e.pc_title, e.pc_hometext, e.pc_apptstatus, " .
164 "p.fname, p.mname, p.lname, p.DOB, p.pid, p.pubpid, p.phone_home, p.phone_cell, " .
165 "p.hipaa_allowsms, p.phone_home, p.phone_cell, p.hipaa_voice, p.hipaa_allowemail, p.email, " .
166 "u.fname AS ufname, u.mname AS umname, u.lname AS ulname, u.id AS uprovider_id, " .
167 "f.name, " .
168 "$tracker_fields" .
169 "c.pc_catname, c.pc_catid, e.pc_facility " .
170 "FROM openemr_postcalendar_events AS e " .
171 "$tracker_joins" .
172 "LEFT OUTER JOIN facility AS f ON e.pc_facility = f.id " .
173 "LEFT OUTER JOIN patient_data AS p ON p.pid = e.pc_pid " .
174 "LEFT OUTER JOIN users AS u ON u.id = e.pc_aid " .
175 "LEFT OUTER JOIN openemr_postcalendar_categories AS c ON c.pc_catid = e.pc_catid " .
176 "WHERE $where " .
177 "ORDER BY $order_by";
179 if ($bind_param) {
180 $sqlBindArray = array_merge($sqlBindArray, $bind_param);
185 ///////////////////////////////////////////////////////////////////////
186 // The following code is from the calculateEvents function in the //
187 // PostCalendar Module modified and inserted here by epsdky //
188 ///////////////////////////////////////////////////////////////////////
190 $events2 = array();
192 $res = sqlStatement($query, $sqlBindArray);
194 ////////
195 if ($nextX) {
196 global $resNotNull;
197 $resNotNull = (isset($res) && $res != null);
200 while ($event = sqlFetchArray($res)) {
201 ///////
202 if ($nextX) {
203 $stopDate = $event['pc_endDate'];
204 } else {
205 $stopDate = ($event['pc_endDate'] <= $to_date) ? $event['pc_endDate'] : $to_date;
208 ///////
209 $incX = 0;
210 switch ($event['pc_recurrtype']) {
211 case '0':
212 $events2[] = $event;
214 break;
215 //////
216 case '1':
217 case '3':
218 $event_recurrspec = @unserialize($event['pc_recurrspec'], ['allowed_classes' => false]);
220 if (checkEvent($event['pc_recurrtype'], $event_recurrspec)) {
221 break; }
223 $rfreq = $event_recurrspec['event_repeat_freq'];
224 $rtype = $event_recurrspec['event_repeat_freq_type'];
225 $exdate = $event_recurrspec['exdate'];
227 list($ny,$nm,$nd) = explode('-', $event['pc_eventDate']);
228 // $occurance = Date_Calc::dateFormat($nd,$nm,$ny,'%Y-%m-%d');
229 $occurance = $event['pc_eventDate'];
231 while ($occurance < $from_date) {
232 $occurance =& __increment($nd, $nm, $ny, $rfreq, $rtype);
233 list($ny,$nm,$nd) = explode('-', $occurance);
236 while ($occurance <= $stopDate) {
237 $excluded = false;
238 if (isset($exdate)) {
239 foreach (explode(",", $exdate) as $exception) {
240 // occurrance format == yyyy-mm-dd
241 // exception format == yyyymmdd
242 if (preg_replace("/-/", "", $occurance) == $exception) {
243 $excluded = true;
248 if ($excluded == false) {
249 $event['pc_eventDate'] = $occurance;
250 $event['pc_endDate'] = '0000-00-00';
251 $events2[] = $event;
252 //////
253 if ($nextX) {
254 ++$incX;
255 if ($incX == $nextX) {
256 break;
260 //////
263 $occurance =& __increment($nd, $nm, $ny, $rfreq, $rtype);
264 list($ny,$nm,$nd) = explode('-', $occurance);
266 break;
268 //////
269 case '2':
270 $event_recurrspec = @unserialize($event['pc_recurrspec'], ['allowed_classes' => false]);
272 if (checkEvent($event['pc_recurrtype'], $event_recurrspec)) {
273 break; }
275 $rfreq = $event_recurrspec['event_repeat_on_freq'];
276 $rnum = $event_recurrspec['event_repeat_on_num'];
277 $rday = $event_recurrspec['event_repeat_on_day'];
278 $exdate = $event_recurrspec['exdate'];
280 list($ny,$nm,$nd) = explode('-', $event['pc_eventDate']);
282 if (isset($event_recurrspec['rt2_pf_flag']) && $event_recurrspec['rt2_pf_flag']) {
283 $nd = 1;
286 $occuranceYm = "$ny-$nm"; // YYYY-mm
287 $from_dateYm = substr($from_date, 0, 7); // YYYY-mm
288 $stopDateYm = substr($stopDate, 0, 7); // YYYY-mm
290 // $nd will sometimes be 29, 30 or 31 and if used in the mktime functions below
291 // a problem with overflow will occur so it is set to 1 to avoid this (for rt2
292 // appointments set prior to fix $nd remains unchanged). This can be done since
293 // $nd has no influence past the mktime functions.
294 while ($occuranceYm < $from_dateYm) {
295 $occuranceYmX = date('Y-m-d', mktime(0, 0, 0, $nm + $rfreq, $nd, $ny));
296 list($ny,$nm,$nd) = explode('-', $occuranceYmX);
297 $occuranceYm = "$ny-$nm";
300 while ($occuranceYm <= $stopDateYm) {
301 // (YYYY-mm)-dd
302 $dnum = $rnum;
303 do {
304 $occurance = Date_Calc::NWeekdayOfMonth($dnum--, $rday, $nm, $ny, $format = "%Y-%m-%d");
305 } while ($occurance === -1);
307 if ($occurance >= $from_date && $occurance <= $stopDate) {
308 $excluded = false;
309 if (isset($exdate)) {
310 foreach (explode(",", $exdate) as $exception) {
311 // occurrance format == yyyy-mm-dd
312 // exception format == yyyymmdd
313 if (preg_replace("/-/", "", $occurance) == $exception) {
314 $excluded = true;
319 if ($excluded == false) {
320 $event['pc_eventDate'] = $occurance;
321 $event['pc_endDate'] = '0000-00-00';
322 $events2[] = $event;
323 //////
324 if ($nextX) {
325 ++$incX;
326 if ($incX == $nextX) {
327 break;
331 //////
335 $occuranceYmX = date('Y-m-d', mktime(0, 0, 0, $nm + $rfreq, $nd, $ny));
336 list($ny,$nm,$nd) = explode('-', $occuranceYmX);
337 $occuranceYm = "$ny-$nm";
339 break;
343 return $events2;
344 ////////////////////// End of code inserted by epsdky
347 function fetchAllEvents($from_date, $to_date, $provider_id = null, $facility_id = null)
349 $sqlBindArray = array();
351 $where = "";
353 if ($provider_id) {
354 $where .= " AND e.pc_aid = ?";
355 array_push($sqlBindArray, $provider_id);
358 if ($facility_id) {
359 $where .= " AND e.pc_facility = ? AND u.facility_id = ?";
360 array_push($sqlBindArray, $facility_id, $facility_id);
363 $appointments = fetchEvents($from_date, $to_date, $where, null, false, 0, $sqlBindArray);
364 return $appointments;
367 //Support for therapy group appointments added by shachar z.
368 function fetchAppointments($from_date, $to_date, $patient_id = null, $provider_id = null, $facility_id = null, $pc_appstatus = null, $with_out_provider = null, $with_out_facility = null, $pc_catid = null, $tracker_board = false, $nextX = 0, $group_id = null, $patient_name = null)
370 $sqlBindArray = array();
372 $where = "";
374 if ($provider_id) {
375 $where .= " AND e.pc_aid = ?";
376 array_push($sqlBindArray, $provider_id);
379 if ($patient_id) {
380 $where .= " AND e.pc_pid = ?";
381 array_push($sqlBindArray, $patient_id);
382 } elseif ($group_id) {
383 //if $group_id this means we want only the group events
384 $where .= " AND e.pc_gid = ? AND e.pc_pid = ''";
385 array_push($sqlBindArray, $group_id);
386 } else {
387 $where .= " AND e.pc_pid != ''";
390 if ($facility_id) {
391 $where .= " AND e.pc_facility = ?";
392 array_push($sqlBindArray, $facility_id);
395 //Appointment Status Checking
396 if ($pc_appstatus != '') {
397 $where .= " AND e.pc_apptstatus = ?";
398 array_push($sqlBindArray, $pc_appstatus);
401 if ($pc_catid != null) {
402 $where .= " AND e.pc_catid = ?";
403 array_push($sqlBindArray, $pc_catid);
406 if ($patient_name != null) {
407 $where .= " AND (p.fname LIKE CONCAT('%',?,'%') OR p.lname LIKE CONCAT('%',?,'%'))";
408 array_push($sqlBindArray, $patient_name, $patient_name);
411 //Without Provider checking
412 if ($with_out_provider != '') {
413 $where .= " AND e.pc_aid = ''";
416 //Without Facility checking
417 if ($with_out_facility != '') {
418 $where .= " AND e.pc_facility = 0";
421 $appointments = fetchEvents($from_date, $to_date, $where, '', $tracker_board, $nextX, $sqlBindArray);
422 return $appointments;
425 //Support for therapy group appointments added by shachar z.
426 function fetchNextXAppts($from_date, $patient_id, $nextX = 1, $group_id = null)
429 $appts = array();
430 $nextXAppts = array();
431 $appts = fetchAppointments($from_date, null, $patient_id, null, null, null, null, null, null, false, $nextX, $group_id);
432 if ($appts) {
433 $appts = sortAppointments($appts);
434 $nextXAppts = array_slice($appts, 0, $nextX);
437 return $nextXAppts;
440 function fetchXPastAppts($pid2, $pastApptsNumber, $orderOfAppts = '1')
443 $currentDate = date("Y-m-d");
444 $totalAppts = [];
445 $res2 = sqlStatement("SELECT MIN(pc_eventDate) as minDate " .
446 "FROM openemr_postcalendar_events " .
447 "WHERE pc_pid = ? " .
448 "AND pc_eventDate < ? ;", array($pid2, $currentDate));
449 $row2 = sqlFetchArray($res2);
451 if ($row2['minDate']) {
452 $periodOf = '26';
453 $limitRight = date("Y-m-d", strtotime("$currentDate -1 day"));
454 $limitLeft = date("Y-m-d", strtotime("$limitRight -$periodOf weeks"));
455 $apptRangeLeft = $row2['minDate'];
456 $count2 = 0;
458 while (($limitRight >= $apptRangeLeft) && ($count2 < $pastApptsNumber)) {
459 $appts2 = fetchAppointments($limitLeft, $limitRight, $pid2);
460 $totalAppts = array_merge($appts2, $totalAppts);
461 $limitRight = date("Y-m-d", strtotime("$limitLeft -1 day"));
462 $limitLeft = date("Y-m-d", strtotime("$limitRight -$periodOf weeks"));
463 $count2 = count($totalAppts);
465 if ($orderOfAppts == '1') {
466 $eventDate = array_column($totalAppts, 'pc_eventDate');
467 $eventTime = array_column($totalAppts, 'pc_startTime');
468 array_multisort($eventDate, SORT_ASC, $eventTime, SORT_ASC, $totalAppts);
469 $totalAppts = array_slice($totalAppts, -$pastApptsNumber, $pastApptsNumber);
470 } elseif ($orderOfAppts == '2') {
471 $eventDate = array_column($totalAppts, 'pc_eventDate');
472 $eventTime = array_column($totalAppts, 'pc_startTime');
473 array_multisort($eventDate, SORT_DESC, $eventTime, SORT_ASC, $totalAppts);
474 $totalAppts = array_slice($totalAppts, 0, $pastApptsNumber);
477 return $totalAppts;
480 // get the event slot size in seconds
481 function getSlotSize()
483 if (isset($GLOBALS['calendar_interval'])) {
484 return $GLOBALS['calendar_interval'] * 60;
487 return 15 * 60;
490 function getAvailableSlots($from_date, $to_date, $provider_id = null, $facility_id = null)
492 $appointments = fetchAllEvents($from_date, $to_date, $provider_id, $facility_id);
493 $appointments = sortAppointments($appointments, "date");
494 $from_datetime = strtotime($from_date . " 00:00:00");
495 $to_datetime = strtotime($to_date . " 23:59:59");
496 $availableSlots = array();
497 $start_time = 0;
498 $date = 0;
499 for ($i = 0; $i < count($appointments); ++$i) {
500 if ($appointments[$i]['pc_catid'] == 2) { // 2 == In Office
501 $start_time = $appointments[$i]['pc_startTime'];
502 $date = $appointments[$i]['pc_eventDate'];
503 $provider_id = $appointments[$i]['uprovider_id'];
504 } elseif ($appointments[$i]['pc_catid'] == 3) { // 3 == Out Of Office
505 continue;
506 } else {
507 $start_time = $appointments[$i]['pc_endTime'];
508 $date = $appointments[$i]['pc_eventDate'];
509 $provider_id = $appointments[$i]['uprovider_id'];
512 // find next appointment with the same provider
513 $next_appointment_date = 0;
514 $next_appointment_time = 0;
515 $appts_count = count($appointments);
516 if (
517 $appts_count == 1
518 && $appointments[0]['pc_catid'] == '2'
520 $next_appointment_date = $appointments[$i]['pc_eventDate'];
521 $next_appointment_time = $appointments[$i]['pc_endTime'];
522 } else {
523 for ($j = $i + 1; $j < $appts_count; ++$j) {
524 if ($appointments[$j]['uprovider_id'] == $provider_id) {
525 // if consecutive appointments are in office on separate days...
526 if (
527 $appointments[$i]['pc_catid'] == '2'
528 && $appointments[$j]['pc_catid'] == '2'
530 $next_appointment_date = $appointments[$i]['pc_eventDate'];
531 // default IN OFFICE appt for provider uses a duration of 0
532 // which opens up the entire day after the start time
533 // which prevents the next appointment time from being set
534 // for the $same_day assignment below, so this fix...
535 if ($appointments[$i]['pc_duration'] == 0) {
536 $next_appointment_time = $GLOBALS['schedule_end'] . ":00";
537 } else {
538 $next_appointment_time = $appointments[$i]['pc_endTime'];
540 } else {
541 $next_appointment_date = $appointments[$j]['pc_eventDate'];
542 $next_appointment_time = $appointments[$j]['pc_startTime'];
544 break;
549 $same_day = ( strtotime($next_appointment_date) == strtotime($date) ) ? true : false;
551 if ($next_appointment_time && $same_day) {
552 // check the start time of the next appointment
554 $start_datetime = strtotime($date . " " . $start_time);
555 $next_appointment_datetime = strtotime($next_appointment_date . " " . $next_appointment_time);
556 $curr_time = $start_datetime;
557 while ($curr_time < $next_appointment_datetime - (getSlotSize() / 2)) {
558 //create a new appointment ever 15 minutes
559 $time = date("H:i:s", $curr_time);
560 $available_slot = createAvailableSlot(
561 $appointments[$i]['pc_eventDate'],
562 $time,
563 $appointments[$i]['ufname'],
564 $appointments[$i]['ulname'],
565 $appointments[$i]['umname']
567 $availableSlots [] = $available_slot;
568 $curr_time += getSlotSize(); // add a 15-minute slot
573 return $availableSlots;
576 function createAvailableSlot($event_date, $start_time, $provider_fname, $provider_lname, $provider_mname = "", $cat_name = "Available")
578 $newSlot = array();
579 $newSlot['ulname'] = $provider_lname;
580 $newSlot['ufname'] = $provider_fname;
581 $newSlot['umname'] = $provider_mname;
582 $newSlot['pc_eventDate'] = $event_date;
583 $newSlot['pc_startTime'] = $start_time;
584 $newSlot['pc_endTime'] = $start_time;
585 $newSlot['pc_catname'] = $cat_name;
586 return $newSlot;
589 function getCompareFunction($code)
591 global $COMPARE_FUNCTION_HASH;
592 return $COMPARE_FUNCTION_HASH[$code];
595 function getComparisonOrder($code)
597 global $ORDERHASH;
598 return $ORDERHASH[$code];
602 function sortAppointments(array $appointments, $orderBy = 'date')
604 global $appointment_sort_order;
605 $appointment_sort_order = $orderBy;
606 usort($appointments, "compareAppointments");
607 return $appointments;
610 // cmp_function for usort
611 // The comparison function must return an integer less than, equal to,
612 // or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
613 function compareAppointments($appointment1, $appointment2)
615 global $appointment_sort_order;
616 $comparisonOrder = getComparisonOrder($appointment_sort_order);
617 foreach ($comparisonOrder as $comparison) {
618 $cmp_function = getCompareFunction($comparison);
619 $result = $cmp_function($appointment1, $appointment2);
620 if (0 != $result) {
621 return $result;
625 return 0;
628 function compareBasic($e1, $e2)
630 if ($e1 < $e2) {
631 return -1;
632 } elseif ($e1 > $e2) {
633 return 1;
636 return 0;
639 function compareAppointmentsByDate($appointment1, $appointment2)
641 $date1 = strtotime($appointment1['pc_eventDate']);
642 $date2 = strtotime($appointment2['pc_eventDate']);
644 return compareBasic($date1, $date2);
647 function compareAppointmentsByTime($appointment1, $appointment2)
649 $time1 = strtotime($appointment1['pc_startTime']);
650 $time2 = strtotime($appointment2['pc_startTime']);
652 return compareBasic($time1, $time2);
655 function compareAppointmentsByDoctorName($appointment1, $appointment2)
657 $name1 = $appointment1['ulname'];
658 $name2 = $appointment2['ulname'];
659 $cmp = compareBasic($name1, $name2);
660 if ($cmp == 0) {
661 $name1 = $appointment1['ufname'];
662 $name2 = $appointment2['ufname'];
663 return compareBasic($name1, $name2);
666 return $cmp;
669 function compareAppointmentsByPatientName($appointment1, $appointment2)
671 $name1 = $appointment1['lname'];
672 $name2 = $appointment2['lname'];
673 $cmp = compareBasic($name1, $name2);
674 if ($cmp == 0) {
675 $name1 = $appointment1['fname'];
676 $name2 = $appointment2['fname'];
677 return compareBasic($name1, $name2);
680 return $cmp;
683 function compareAppointmentsByType($appointment1, $appointment2)
685 $type1 = $appointment1['pc_catid'];
686 $type2 = $appointment2['pc_catid'];
687 return compareBasic($type1, $type2);
690 function compareAppointmentsByPatientId($appointment1, $appointment2)
692 $id1 = $appointment1['pubpid'];
693 $id2 = $appointment2['pubpid'];
694 return compareBasic($id1, $id2);
697 function compareAppointmentsByComment($appointment1, $appointment2)
699 $comment1 = $appointment1['pc_hometext'];
700 $comment2 = $appointment2['pc_hometext'];
701 return compareBasic($comment1, $comment2);
704 function compareAppointmentsByStatus($appointment1, $appointment2)
706 $status1 = $appointment1['pc_apptstatus'];
707 $status2 = $appointment2['pc_apptstatus'];
708 return compareBasic($status1, $status2);
711 function compareAppointmentsByTrackerStatus($appointment1, $appointment2)
713 $trackerstatus1 = $appointment1['status'];
714 $trackerstatus2 = $appointment2['status'];
715 return compareBasic($trackerstatus1, $trackerstatus2);
718 function compareAppointmentsByCompletedDrugScreen($appointment1, $appointment2)
720 $completed1 = $appointment1['drug_screen_completed'];
721 $completed2 = $appointment2['drug_screen_completed'];
722 return compareBasic($completed1, $completed2);
725 function fetchAppointmentCategories()
727 $catSQL = " SELECT pc_catid as id, pc_catname as category "
728 . " FROM openemr_postcalendar_categories WHERE pc_active=1 and pc_recurrtype=0 and pc_cattype=0";
729 if ($GLOBALS['enable_group_therapy']) {
730 $catSQL .= " OR pc_cattype=3";
733 $catSQL .= " ORDER BY category";
734 return sqlStatement($catSQL);
737 function interpretRecurrence($recurr_freq, $recurr_type)
739 global $REPEAT_FREQ, $REPEAT_FREQ_TYPE, $REPEAT_ON_NUM, $REPEAT_ON_DAY;
740 $interpreted = "";
741 $recurr_freq = unserialize($recurr_freq, ['allowed_classes' => false]);
742 if ($recurr_type == 1) {
743 $interpreted = $REPEAT_FREQ[$recurr_freq['event_repeat_freq']];
744 $interpreted .= " " . $REPEAT_FREQ_TYPE[$recurr_freq['event_repeat_freq_type']];
745 } elseif ($recurr_type == 2) {
746 $interpreted = $REPEAT_FREQ[$recurr_freq['event_repeat_on_freq']];
747 $interpreted .= " " . $REPEAT_ON_NUM[$recurr_freq['event_repeat_on_num']];
748 $interpreted .= " " . $REPEAT_ON_DAY[$recurr_freq['event_repeat_on_day']];
749 } elseif ($recurr_type == 3) {
750 $interpreted = $REPEAT_FREQ[1];
751 $comma = "";
752 $day_arr = explode(",", $recurr_freq['event_repeat_freq']);
753 foreach ($day_arr as $day) {
754 $interpreted .= $comma . " " . $REPEAT_ON_DAY[$day - 1];
755 $comma = ",";
759 return $interpreted;
762 function fetchRecurrences($pid)
764 $query = "SELECT pe.pc_title, pe.pc_endDate, pe.pc_recurrtype, pe.pc_recurrspec, pc.pc_catname FROM openemr_postcalendar_events AS pe "
765 . "JOIN openemr_postcalendar_categories AS pc ON pe.pc_catid=pc.pc_catid "
766 . "WHERE pe.pc_pid = ? AND pe.pc_recurrtype > 0;";
767 $sqlBindArray = array();
768 array_push($sqlBindArray, $pid);
769 $res = sqlStatement($query, $sqlBindArray);
770 $result_data = array();
771 while ($row = sqlFetchArray($res)) {
772 $u_recurrspec = unserialize($row['pc_recurrspec'], ['allowed_classes' => false]);
773 if (checkEvent($row['pc_recurrtype'], $u_recurrspec)) {
774 continue; }
775 $row['pc_recurrspec'] = interpretRecurrence($row['pc_recurrspec'], $row['pc_recurrtype']);
776 $result_data[] = $row;
778 return $result_data;
781 function ends_in_a_week($end_date)
783 $timestamp_in_a_week = strtotime('+7 day');
784 $timestamp_end_date = strtotime($end_date);
785 if ($timestamp_in_a_week > $timestamp_end_date) {
786 return true; //ends in a week
789 return false; // ends in more than a week
792 //Checks if recurrence is current (didn't end yet).
793 function recurrence_is_current($end_date)
795 $end_date_timestamp = strtotime($end_date);
796 $current_timestamp = time();
797 if ($current_timestamp <= $end_date_timestamp) {
798 return true; //recurrence is current
801 return false;