Updated the Availability.php library to work with the updated code.

This commit is contained in:
Alex Tselegidis 2021-10-28 13:59:56 +02:00
parent adc6d00bb5
commit e4c01f54f8

View file

@ -13,9 +13,11 @@
/**
* Class Availability
* Availability library
*
* Handles the availability generation of providers, based on their working plan and their schedule.
* Handles availability related functionality.
*
* @package Libraries
*/
class Availability {
/**
@ -29,12 +31,14 @@ class Availability {
public function __construct()
{
$this->CI =& get_instance();
$this->CI->load->model('admins_model');
$this->CI->load->model('appointments_model');
$this->CI->load->model('providers_model');
$this->CI->load->model('secretaries_model');
$this->CI->load->model('secretaries_model');
$this->CI->load->model('admins_model');
$this->CI->load->model('appointments_model');
$this->CI->load->model('settings_model');
$this->CI->load->library('ics_file');
}
@ -42,15 +46,13 @@ class Availability {
* Get the available hours of a provider.
*
* @param string $date Selected date (Y-m-d).
* @param array $service Service record.
* @param array $provider Provider record.
* @param array $service Service data.
* @param array $provider Provider data.
* @param int|null $exclude_appointment_id Exclude an appointment from the availability generation.
*
* @return array
*
* @throws Exception
*/
public function get_available_hours($date, $service, $provider, $exclude_appointment_id = NULL)
public function get_available_hours(string $date, array $service, array $provider, int $exclude_appointment_id = NULL): array
{
$available_periods = $this->get_available_periods($date, $provider, $exclude_appointment_id);
@ -68,22 +70,18 @@ class Availability {
* Get an array containing the free time periods (start - end) of a selected date.
*
* This method is very important because there are many cases where the system needs to know when a provider is
* available for an appointment. This method will return an array that belongs to the selected date and contains
* values that have the start and the end time of an available time period.
* available for an appointment. It will return an array that belongs to the selected date and contains values that
* have the start and the end time of an available time period.
*
* @param string $date Select date string.
* @param array $provider Provider record.
* @param string $date Selected date (Y-m-d).
* @param array $provider Provider data.
* @param int|null $exclude_appointment_id Exclude an appointment from the availability generation.
*
* @return array Returns an array with the available time periods of the provider.
*
* @throws Exception
*/
protected function get_available_periods(
$date,
$provider,
$exclude_appointment_id = NULL
)
protected function get_available_periods(string $date, array $provider, int $exclude_appointment_id = NULL): array
{
// Get the service, provider's working plan and provider appointments.
$working_plan = json_decode($provider['settings']['working_plan'], TRUE);
@ -91,7 +89,7 @@ class Availability {
// Get the provider's working plan exceptions.
$working_plan_exceptions = json_decode($provider['settings']['working_plan_exceptions'], TRUE);
$conditions = [
$where = [
'id_users_provider' => $provider['id'],
];
@ -99,10 +97,10 @@ class Availability {
// existing appointment).
if ($exclude_appointment_id)
{
$conditions['id !='] = $exclude_appointment_id;
$where['id !='] = $exclude_appointment_id;
}
$appointments = $this->CI->appointments_model->get_batch($conditions);
$appointments = $this->CI->appointments_model->get($where);
// Find the empty spaces on the plan. The first split between the plan is due to a break (if any). After that
// every reserved appointment is considered to be a taken space in the plan.
@ -277,40 +275,43 @@ class Availability {
/**
* Calculate the available appointment hours.
*
* Calculate the available appointment hours for the given date. The empty spaces
* are broken down to 15 min and if the service fit in each quarter then a new
* available hour is added to the "$available_hours" array.
* Calculate the available appointment hours for the given date. The empty spaces are broken down to 15 min and if
* the service fit in each quarter then a new available hour is added to the "$available_hours" array.
*
* @param string $date Selected date (Y-m-d).
* @param array $service Service record.
* @param array $empty_periods Empty periods as generated by the "get_provider_available_time_periods"
* method.
* @param array $service Service data.
* @param array $empty_periods Empty periods array.
*
* @return array Returns an array with the available hours for the appointment.
*
* @throws Exception
*/
protected function generate_available_hours(
$date,
$service,
$empty_periods
)
string $date,
array $service,
array $empty_periods
): array
{
$available_hours = [];
foreach ($empty_periods as $period)
{
$start_hour = new DateTime($date . ' ' . $period['start']);
$end_hour = new DateTime($date . ' ' . $period['end']);
$interval = $service['availabilities_type'] === AVAILABILITIES_TYPE_FIXED ? (int)$service['duration'] : 15;
$current_hour = $start_hour;
$diff = $current_hour->diff($end_hour);
while (($diff->h * 60 + $diff->i) >= (int)$service['duration'] && $diff->invert === 0)
{
$available_hours[] = $current_hour->format('H:i');
$current_hour->add(new DateInterval('PT' . $interval . 'M'));
$diff = $current_hour->diff($end_hour);
}
}
@ -324,8 +325,8 @@ class Availability {
* This method will add the additional appointment hours whenever a service accepts multiple attendants.
*
* @param string $date Selected date (Y-m-d).
* @param array $service Service record.
* @param array $provider Provider record.
* @param array $service Service data.
* @param array $provider Provider data.
* @param int|null $exclude_appointment_id Exclude an appointment from the availability generation.
*
* @return array Returns the available hours array.
@ -333,13 +334,13 @@ class Availability {
* @throws Exception
*/
protected function consider_multiple_attendants(
$date,
$service,
$provider,
$exclude_appointment_id = NULL
)
string $date,
array $service,
array $provider,
int $exclude_appointment_id = NULL
): array
{
$unavailability_events = $this->CI->appointments_model->get_batch([
$unavailability_events = $this->CI->appointments_model->get([
'is_unavailable' => TRUE,
'DATE(start_datetime) <=' => $date,
'DATE(end_datetime) >=' => $date,
@ -430,14 +431,15 @@ class Availability {
/**
* Remove breaks from available time periods.
*
* @param string $selected_date Selected data (Y-m-d format).
* @param array $periods Time periods of the current date.
* @param array $breaks Breaks array for the current date.
* @param string $date Selected date (Y-m-d).
* @param array $periods Empty periods.
* @param array $breaks Array of breaks.
*
* @return array Returns the available time periods without the breaks.
*
* @throws Exception
*/
public function remove_breaks($selected_date, $periods, $breaks)
public function remove_breaks(string $date, array $periods, array $breaks): array
{
if ( ! $breaks)
{
@ -446,12 +448,14 @@ class Availability {
foreach ($breaks as $break)
{
$break_start = new DateTime($selected_date . ' ' . $break['start']);
$break_end = new DateTime($selected_date . ' ' . $break['end']);
$break_start = new DateTime($date . ' ' . $break['start']);
$break_end = new DateTime($date . ' ' . $break['end']);
foreach ($periods as &$period)
{
$period_start = $period['start'];
$period_end = $period['end'];
if ($break_start <= $period_start && $break_end >= $period_start && $break_end <= $period_end)
@ -501,28 +505,30 @@ class Availability {
*
* @throws Exception
*/
public function remove_unavailability_events($periods, $unavailability_events)
public function remove_unavailability_events(array $periods, array $unavailability_events): array
{
foreach ($unavailability_events as $unavailability_event)
{
$unavailability_start = new DateTime($unavailability_event['start_datetime']);
$unavailability_end = new DateTime($unavailability_event['end_datetime']);
foreach ($periods as &$period)
{
$period_start = $period['start'];
$period_end = $period['end'];
if ($unavailability_start <= $period_start && $unavailability_end >= $period_start && $unavailability_end <= $period_end)
{
// left
// Left
$period['start'] = $unavailability_end;
continue;
}
if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_start && $unavailability_end <= $period_end)
{
// middle
// Middle
$period['end'] = $unavailability_start;
$periods[] = [
'start' => $unavailability_end,
@ -533,7 +539,7 @@ class Availability {
if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_end)
{
// right
// Right
$period['end'] = $unavailability_start;
continue;
}
@ -542,7 +548,6 @@ class Availability {
{
// Unavailability contains period
$period['start'] = $unavailability_end;
continue;
}
}
}
@ -557,7 +562,7 @@ class Availability {
* that is set in the back-office the system. Normally we might want the customer to book an appointment
* that is at least half or one hour from now. The setting is stored in minutes.
*
* @param string $selected_date The selected date.
* @param string $date The selected date.
* @param array $available_hours Already generated available hours.
* @param array $provider Provider information.
*
@ -565,17 +570,17 @@ class Availability {
*
* @throws Exception
*/
protected function consider_book_advance_timeout($selected_date, $available_hours, $provider)
protected function consider_book_advance_timeout(string $date, array $available_hours, array $provider): array
{
$provider_timezone = new DateTimeZone($provider['timezone']);
$book_advance_timeout = $this->CI->settings_model->get_setting('book_advance_timeout');
$book_advance_timeout = setting('book_advance_timeout');
$threshold = new DateTime('+' . $book_advance_timeout . ' minutes', $provider_timezone);
foreach ($available_hours as $index => $value)
{
$available_hour = new DateTime($selected_date . ' ' . $value, $provider_timezone);
$available_hour = new DateTime($date . ' ' . $value, $provider_timezone);
if ($available_hour->getTimestamp() <= $threshold->getTimestamp())
{
@ -584,7 +589,9 @@ class Availability {
}
$available_hours = array_values($available_hours);
sort($available_hours, SORT_STRING);
return array_values($available_hours);
}
}