From 1e31c113415611c3a1500aa2bd658d13d0bbe4d0 Mon Sep 17 00:00:00 2001 From: Alex Tselegidis Date: Tue, 24 Nov 2015 22:12:44 +0100 Subject: [PATCH] Fixes #66 thanks to bikimike solution. --- src/application/controllers/appointments.php | 217 ++++++++++--------- 1 file changed, 116 insertions(+), 101 deletions(-) diff --git a/src/application/controllers/appointments.php b/src/application/controllers/appointments.php index 3f475430..0ec72250 100755 --- a/src/application/controllers/appointments.php +++ b/src/application/controllers/appointments.php @@ -547,117 +547,132 @@ class Appointments extends CI_Controller { private function get_provider_available_time_periods($provider_id, $selected_date, $exclude_appointments = array()) { $this->load->model('appointments_model'); - $this->load->model('providers_model'); + $this->load->model('providers_model'); - // Get the provider's working plan and reserved appointments. - $working_plan = json_decode($this->providers_model - ->get_setting('working_plan', $provider_id), true); + // Get the provider's working plan and reserved appointments. + $working_plan = json_decode($this->providers_model->get_setting('working_plan', $provider_id), true); - $where_clause = array( - 'DATE(start_datetime)' => date('Y-m-d', strtotime($selected_date)), - 'id_users_provider' => $provider_id - ); + $where_clause = array( + //'DATE(start_datetime)' => date('Y-m-d', strtotime($selected_date)), + 'id_users_provider' => $provider_id + ); - $reserved_appointments = $this->appointments_model->get_batch($where_clause); + $reserved_appointments = $this->appointments_model->get_batch($where_clause); - // Sometimes it might be necessary to not take into account some appointment records - // in order to display what the providers' available time periods would be without them. - foreach ($exclude_appointments as $excluded_id) { - foreach ($reserved_appointments as $index => $reserved) { - if ($reserved['id'] == $excluded_id) { - unset($reserved_appointments[$index]); - } - } - } + // Sometimes it might be necessary to not take into account some appointment records + // in order to display what the providers' available time periods would be without them. + foreach ($exclude_appointments as $excluded_id) { + foreach ($reserved_appointments as $index => $reserved) { + if ($reserved['id'] == $excluded_id) { + unset($reserved_appointments[$index]); + } + } + } - // Find the empty spaces on the plan. The first split between the plan is due to - // a break (if exist). After that every reserved appointment is considered to be - // a taken space in the plan. - $selected_date_working_plan = $working_plan[strtolower(date('l', strtotime($selected_date)))]; - $available_periods_with_breaks = array(); + // Find the empty spaces on the plan. The first split between the plan is due to + // a break (if exist). After that every reserved appointment is considered to be + // a taken space in the plan. + $selected_date_working_plan = $working_plan[strtolower(date('l', strtotime($selected_date)))]; + $available_periods_with_breaks = array(); - if (isset($selected_date_working_plan['breaks'])) { - if (count($selected_date_working_plan['breaks'])) { - foreach($selected_date_working_plan['breaks'] as $index=>$break) { - // Split the working plan to available time periods that do not - // contain the breaks in them. - $last_break_index = $index - 1; + if (isset($selected_date_working_plan['breaks'])) { + $start = new DateTime($selected_date_working_plan['start']); + $end = new DateTime($selected_date_working_plan['end']); + $available_periods_with_breaks[] = array( + 'start' => $selected_date_working_plan['start'], + 'end' => $selected_date_working_plan['end'] + ); + // Split the working plan to available time periods that do not + // contain the breaks in them. + foreach($selected_date_working_plan['breaks'] as $index=>$break) { + $break_start = new DateTime($break['start']); + $break_end = new DateTime($break['end']); + if ($break_start < $start) + $break_start = $start; + if ($break_end > $end) + $break_end = $end; + if ($break_start >= $break_end) + continue; + foreach ($available_periods_with_breaks as $key => $open_period) + { + $s = new DateTime($open_period['start']); + $e = new DateTime($open_period['end']); + if ($s < $break_end && $break_start < $e) // check for overlap + { + $changed = FALSE; + if ($s < $break_start) + { + $open_start = $s; + $open_end = $break_start; + $available_periods_with_breaks[] = array( + 'start' => $open_start->format("H:i"), + 'end' => $open_end->format("H:i") + ); + $changed = TRUE; + } + if ($break_end < $e) + { + $open_start = $break_end; + $open_end = $e; + $available_periods_with_breaks[] = array( + 'start' => $open_start->format("H:i"), + 'end' => $open_end->format("H:i") + ); + $changed = TRUE; + } + if ($changed) + { + unset($available_periods_with_breaks[$key]); + } + } + } + } + } - if (count($available_periods_with_breaks) === 0) { - $start_hour = $selected_date_working_plan['start']; - $end_hour = $break['start']; - } else { - $start_hour = $selected_date_working_plan['breaks'][$last_break_index]['end']; - $end_hour = $break['start']; - } + // Break the empty periods with the reserved appointments. + $available_periods_with_appointments = $available_periods_with_breaks; - $available_periods_with_breaks[] = array( - 'start' => $start_hour, - 'end' => $end_hour - ); - } + foreach($reserved_appointments as $appointment) { + foreach($available_periods_with_appointments as $index => &$period) { - // Add the period from the last break to the end of the day. - $available_periods_with_breaks[] = array( - 'start' => $selected_date_working_plan['breaks'][$index]['end'], - 'end' => $selected_date_working_plan['end'] - ); - } else { - $available_periods_with_breaks[] = array( - 'start' => $selected_date_working_plan['start'], - 'end' => $selected_date_working_plan['end'] - ); - } - } + $a_start = strtotime($appointment['start_datetime']); + $a_end = strtotime($appointment['end_datetime']); + $p_start = strtotime($selected_date . ' ' . $period['start']); + $p_end = strtotime($selected_date . ' ' .$period['end']); + if ($a_start <= $p_start && $a_end <= $p_end && $a_end <= $p_start) { + // The appointment does not belong in this time period, so we + // will not change anything. + } else if ($a_start <= $p_start && $a_end <= $p_end && $a_end >= $p_start) { + // The appointment starts before the period and finishes somewhere inside. + // We will need to break this period and leave the available part. + $period['start'] = date('H:i', $a_end); + } else if ($a_start >= $p_start && $a_end <= $p_end) { + // The appointment is inside the time period, so we will split the period + // into two new others. + unset($available_periods_with_appointments[$index]); + $available_periods_with_appointments[] = array( + 'start' => date('H:i', $p_start), + 'end' => date('H:i', $a_start) + ); + $available_periods_with_appointments[] = array( + 'start' => date('H:i', $a_end), + 'end' => date('H:i', $p_end) + ); + } else if ($a_start >= $p_start && $a_end >= $p_start && $a_start <= $p_end) { + // The appointment starts in the period and finishes out of it. We will + // need to remove the time that is taken from the appointment. + $period['end'] = date('H:i', $a_start); + } else if ($a_start >= $p_start && $a_end >= $p_end && $a_start >= $p_end) { + // The appointment does not belong in the period so do not change anything. + } else if ($a_start <= $p_start && $a_end >= $p_end && $a_start <= $p_end) { + // The appointment is bigger than the period, so this period needs to be + // removed. + unset($available_periods_with_appointments[$index]); + } + } + } - // Break the empty periods with the reserved appointments. - $available_periods_with_appointments = $available_periods_with_breaks; - - foreach($reserved_appointments as $appointment) { - foreach($available_periods_with_appointments as $index => &$period) { - - $a_start = strtotime($appointment['start_datetime']); - $a_end = strtotime($appointment['end_datetime']); - $p_start = strtotime($selected_date . ' ' . $period['start']); - $p_end = strtotime($selected_date . ' ' .$period['end']); - - if ($a_start <= $p_start && $a_end <= $p_end && $a_end <= $p_start) { - // The appointment does not belong in this time period, so we - // will not change anything. - } else if ($a_start <= $p_start && $a_end <= $p_end && $a_end >= $p_start) { - // The appointment starts before the period and finishes somewhere inside. - // We will need to break this period and leave the available part. - $period['start'] = date('H:i', $a_end); - - } else if ($a_start >= $p_start && $a_end <= $p_end) { - // The appointment is inside the time period, so we will split the period - // into two new others. - unset($available_periods_with_appointments[$index]); - $available_periods_with_appointments[] = array( - 'start' => date('H:i', $p_start), - 'end' => date('H:i', $a_start) - ); - $available_periods_with_appointments[] = array( - 'start' => date('H:i', $a_end), - 'end' => date('H:i', $p_end) - ); - - } else if ($a_start >= $p_start && $a_end >= $p_start && $a_start <= $p_end) { - // The appointment starts in the period and finishes out of it. We will - // need to remove the time that is taken from the appointment. - $period['end'] = date('H:i', $a_start); - - } else if ($a_start >= $p_start && $a_end >= $p_end && $a_start >= $p_end) { - // The appointment does not belong in the period so do not change anything. - } else if ($a_start <= $p_start && $a_end >= $p_end && $a_start <= $p_end) { - // The appointment is bigger than the period, so this period needs to be - // removed. - unset($available_periods_with_appointments[$index]); - } - } - } - - return array_values($available_periods_with_appointments); + return array_values($available_periods_with_appointments); } }