forked from mirrors/easyappointments
Updated the Availability.php library to work with the updated code.
This commit is contained in:
parent
adc6d00bb5
commit
e4c01f54f8
1 changed files with 61 additions and 54 deletions
|
@ -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 {
|
class Availability {
|
||||||
/**
|
/**
|
||||||
|
@ -29,12 +31,14 @@ class Availability {
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->CI =& get_instance();
|
$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('providers_model');
|
||||||
$this->CI->load->model('secretaries_model');
|
$this->CI->load->model('secretaries_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->model('settings_model');
|
||||||
|
|
||||||
$this->CI->load->library('ics_file');
|
$this->CI->load->library('ics_file');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,15 +46,13 @@ class Availability {
|
||||||
* Get the available hours of a provider.
|
* Get the available hours of a provider.
|
||||||
*
|
*
|
||||||
* @param string $date Selected date (Y-m-d).
|
* @param string $date Selected date (Y-m-d).
|
||||||
* @param array $service Service record.
|
* @param array $service Service data.
|
||||||
* @param array $provider Provider record.
|
* @param array $provider Provider data.
|
||||||
* @param int|null $exclude_appointment_id Exclude an appointment from the availability generation.
|
* @param int|null $exclude_appointment_id Exclude an appointment from the availability generation.
|
||||||
*
|
*
|
||||||
* @return array
|
* @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);
|
$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.
|
* 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
|
* 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
|
* available for an appointment. It will return an array that belongs to the selected date and contains values that
|
||||||
* values that have the start and the end time of an available time period.
|
* have the start and the end time of an available time period.
|
||||||
*
|
*
|
||||||
* @param string $date Select date string.
|
* @param string $date Selected date (Y-m-d).
|
||||||
* @param array $provider Provider record.
|
* @param array $provider Provider data.
|
||||||
* @param int|null $exclude_appointment_id Exclude an appointment from the availability generation.
|
* @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.
|
* @return array Returns an array with the available time periods of the provider.
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function get_available_periods(
|
protected function get_available_periods(string $date, array $provider, int $exclude_appointment_id = NULL): array
|
||||||
$date,
|
|
||||||
$provider,
|
|
||||||
$exclude_appointment_id = NULL
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Get the service, provider's working plan and provider appointments.
|
// Get the service, provider's working plan and provider appointments.
|
||||||
$working_plan = json_decode($provider['settings']['working_plan'], TRUE);
|
$working_plan = json_decode($provider['settings']['working_plan'], TRUE);
|
||||||
|
@ -91,7 +89,7 @@ class Availability {
|
||||||
// Get the provider's working plan exceptions.
|
// Get the provider's working plan exceptions.
|
||||||
$working_plan_exceptions = json_decode($provider['settings']['working_plan_exceptions'], TRUE);
|
$working_plan_exceptions = json_decode($provider['settings']['working_plan_exceptions'], TRUE);
|
||||||
|
|
||||||
$conditions = [
|
$where = [
|
||||||
'id_users_provider' => $provider['id'],
|
'id_users_provider' => $provider['id'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -99,10 +97,10 @@ class Availability {
|
||||||
// existing appointment).
|
// existing appointment).
|
||||||
if ($exclude_appointment_id)
|
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
|
// 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.
|
// 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.
|
||||||
*
|
*
|
||||||
* Calculate the available appointment hours for the given date. The empty spaces
|
* Calculate the available appointment hours for the given date. The empty spaces are broken down to 15 min and if
|
||||||
* are broken down to 15 min and if the service fit in each quarter then a new
|
* the service fit in each quarter then a new available hour is added to the "$available_hours" array.
|
||||||
* available hour is added to the "$available_hours" array.
|
|
||||||
*
|
*
|
||||||
* @param string $date Selected date (Y-m-d).
|
* @param string $date Selected date (Y-m-d).
|
||||||
* @param array $service Service record.
|
* @param array $service Service data.
|
||||||
* @param array $empty_periods Empty periods as generated by the "get_provider_available_time_periods"
|
* @param array $empty_periods Empty periods array.
|
||||||
* method.
|
|
||||||
*
|
*
|
||||||
* @return array Returns an array with the available hours for the appointment.
|
* @return array Returns an array with the available hours for the appointment.
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function generate_available_hours(
|
protected function generate_available_hours(
|
||||||
$date,
|
string $date,
|
||||||
$service,
|
array $service,
|
||||||
$empty_periods
|
array $empty_periods
|
||||||
)
|
): array
|
||||||
{
|
{
|
||||||
$available_hours = [];
|
$available_hours = [];
|
||||||
|
|
||||||
foreach ($empty_periods as $period)
|
foreach ($empty_periods as $period)
|
||||||
{
|
{
|
||||||
$start_hour = new DateTime($date . ' ' . $period['start']);
|
$start_hour = new DateTime($date . ' ' . $period['start']);
|
||||||
|
|
||||||
$end_hour = new DateTime($date . ' ' . $period['end']);
|
$end_hour = new DateTime($date . ' ' . $period['end']);
|
||||||
|
|
||||||
$interval = $service['availabilities_type'] === AVAILABILITIES_TYPE_FIXED ? (int)$service['duration'] : 15;
|
$interval = $service['availabilities_type'] === AVAILABILITIES_TYPE_FIXED ? (int)$service['duration'] : 15;
|
||||||
|
|
||||||
$current_hour = $start_hour;
|
$current_hour = $start_hour;
|
||||||
|
|
||||||
$diff = $current_hour->diff($end_hour);
|
$diff = $current_hour->diff($end_hour);
|
||||||
|
|
||||||
while (($diff->h * 60 + $diff->i) >= (int)$service['duration'] && $diff->invert === 0)
|
while (($diff->h * 60 + $diff->i) >= (int)$service['duration'] && $diff->invert === 0)
|
||||||
{
|
{
|
||||||
$available_hours[] = $current_hour->format('H:i');
|
$available_hours[] = $current_hour->format('H:i');
|
||||||
|
|
||||||
$current_hour->add(new DateInterval('PT' . $interval . 'M'));
|
$current_hour->add(new DateInterval('PT' . $interval . 'M'));
|
||||||
|
|
||||||
$diff = $current_hour->diff($end_hour);
|
$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.
|
* This method will add the additional appointment hours whenever a service accepts multiple attendants.
|
||||||
*
|
*
|
||||||
* @param string $date Selected date (Y-m-d).
|
* @param string $date Selected date (Y-m-d).
|
||||||
* @param array $service Service record.
|
* @param array $service Service data.
|
||||||
* @param array $provider Provider record.
|
* @param array $provider Provider data.
|
||||||
* @param int|null $exclude_appointment_id Exclude an appointment from the availability generation.
|
* @param int|null $exclude_appointment_id Exclude an appointment from the availability generation.
|
||||||
*
|
*
|
||||||
* @return array Returns the available hours array.
|
* @return array Returns the available hours array.
|
||||||
|
@ -333,13 +334,13 @@ class Availability {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function consider_multiple_attendants(
|
protected function consider_multiple_attendants(
|
||||||
$date,
|
string $date,
|
||||||
$service,
|
array $service,
|
||||||
$provider,
|
array $provider,
|
||||||
$exclude_appointment_id = NULL
|
int $exclude_appointment_id = NULL
|
||||||
)
|
): array
|
||||||
{
|
{
|
||||||
$unavailability_events = $this->CI->appointments_model->get_batch([
|
$unavailability_events = $this->CI->appointments_model->get([
|
||||||
'is_unavailable' => TRUE,
|
'is_unavailable' => TRUE,
|
||||||
'DATE(start_datetime) <=' => $date,
|
'DATE(start_datetime) <=' => $date,
|
||||||
'DATE(end_datetime) >=' => $date,
|
'DATE(end_datetime) >=' => $date,
|
||||||
|
@ -430,14 +431,15 @@ class Availability {
|
||||||
/**
|
/**
|
||||||
* Remove breaks from available time periods.
|
* Remove breaks from available time periods.
|
||||||
*
|
*
|
||||||
* @param string $selected_date Selected data (Y-m-d format).
|
* @param string $date Selected date (Y-m-d).
|
||||||
* @param array $periods Time periods of the current date.
|
* @param array $periods Empty periods.
|
||||||
* @param array $breaks Breaks array for the current date.
|
* @param array $breaks Array of breaks.
|
||||||
*
|
*
|
||||||
* @return array Returns the available time periods without the breaks.
|
* @return array Returns the available time periods without the breaks.
|
||||||
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function remove_breaks($selected_date, $periods, $breaks)
|
public function remove_breaks(string $date, array $periods, array $breaks): array
|
||||||
{
|
{
|
||||||
if ( ! $breaks)
|
if ( ! $breaks)
|
||||||
{
|
{
|
||||||
|
@ -446,12 +448,14 @@ class Availability {
|
||||||
|
|
||||||
foreach ($breaks as $break)
|
foreach ($breaks as $break)
|
||||||
{
|
{
|
||||||
$break_start = new DateTime($selected_date . ' ' . $break['start']);
|
$break_start = new DateTime($date . ' ' . $break['start']);
|
||||||
$break_end = new DateTime($selected_date . ' ' . $break['end']);
|
|
||||||
|
$break_end = new DateTime($date . ' ' . $break['end']);
|
||||||
|
|
||||||
foreach ($periods as &$period)
|
foreach ($periods as &$period)
|
||||||
{
|
{
|
||||||
$period_start = $period['start'];
|
$period_start = $period['start'];
|
||||||
|
|
||||||
$period_end = $period['end'];
|
$period_end = $period['end'];
|
||||||
|
|
||||||
if ($break_start <= $period_start && $break_end >= $period_start && $break_end <= $period_end)
|
if ($break_start <= $period_start && $break_end >= $period_start && $break_end <= $period_end)
|
||||||
|
@ -501,28 +505,30 @@ class Availability {
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @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)
|
foreach ($unavailability_events as $unavailability_event)
|
||||||
{
|
{
|
||||||
$unavailability_start = new DateTime($unavailability_event['start_datetime']);
|
$unavailability_start = new DateTime($unavailability_event['start_datetime']);
|
||||||
|
|
||||||
$unavailability_end = new DateTime($unavailability_event['end_datetime']);
|
$unavailability_end = new DateTime($unavailability_event['end_datetime']);
|
||||||
|
|
||||||
foreach ($periods as &$period)
|
foreach ($periods as &$period)
|
||||||
{
|
{
|
||||||
$period_start = $period['start'];
|
$period_start = $period['start'];
|
||||||
|
|
||||||
$period_end = $period['end'];
|
$period_end = $period['end'];
|
||||||
|
|
||||||
if ($unavailability_start <= $period_start && $unavailability_end >= $period_start && $unavailability_end <= $period_end)
|
if ($unavailability_start <= $period_start && $unavailability_end >= $period_start && $unavailability_end <= $period_end)
|
||||||
{
|
{
|
||||||
// left
|
// Left
|
||||||
$period['start'] = $unavailability_end;
|
$period['start'] = $unavailability_end;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_start && $unavailability_end <= $period_end)
|
if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_start && $unavailability_end <= $period_end)
|
||||||
{
|
{
|
||||||
// middle
|
// Middle
|
||||||
$period['end'] = $unavailability_start;
|
$period['end'] = $unavailability_start;
|
||||||
$periods[] = [
|
$periods[] = [
|
||||||
'start' => $unavailability_end,
|
'start' => $unavailability_end,
|
||||||
|
@ -533,7 +539,7 @@ class Availability {
|
||||||
|
|
||||||
if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_end)
|
if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_end)
|
||||||
{
|
{
|
||||||
// right
|
// Right
|
||||||
$period['end'] = $unavailability_start;
|
$period['end'] = $unavailability_start;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -542,7 +548,6 @@ class Availability {
|
||||||
{
|
{
|
||||||
// Unavailability contains period
|
// Unavailability contains period
|
||||||
$period['start'] = $unavailability_end;
|
$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 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.
|
* 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 $available_hours Already generated available hours.
|
||||||
* @param array $provider Provider information.
|
* @param array $provider Provider information.
|
||||||
*
|
*
|
||||||
|
@ -565,17 +570,17 @@ class Availability {
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @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']);
|
$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);
|
$threshold = new DateTime('+' . $book_advance_timeout . ' minutes', $provider_timezone);
|
||||||
|
|
||||||
foreach ($available_hours as $index => $value)
|
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())
|
if ($available_hour->getTimestamp() <= $threshold->getTimestamp())
|
||||||
{
|
{
|
||||||
|
@ -584,7 +589,9 @@ class Availability {
|
||||||
}
|
}
|
||||||
|
|
||||||
$available_hours = array_values($available_hours);
|
$available_hours = array_values($available_hours);
|
||||||
|
|
||||||
sort($available_hours, SORT_STRING);
|
sort($available_hours, SORT_STRING);
|
||||||
|
|
||||||
return array_values($available_hours);
|
return array_values($available_hours);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue