mirror of
https://github.com/alextselegidis/easyappointments.git
synced 2024-11-10 10:02:33 +03:00
Moved duplicated code into re-usable library classes
This commit is contained in:
parent
d2dd9925ec
commit
f7ca104836
6 changed files with 1023 additions and 968 deletions
File diff suppressed because it is too large
Load diff
|
@ -38,6 +38,8 @@ use EA\Engine\Types\Url;
|
||||||
* @property Customers_Model $customers_model
|
* @property Customers_Model $customers_model
|
||||||
* @property Settings_Model $settings_model
|
* @property Settings_Model $settings_model
|
||||||
* @property Timezones $timezones
|
* @property Timezones $timezones
|
||||||
|
* @property Synchronization $synchronization
|
||||||
|
* @property Notifications $notifications
|
||||||
* @property Roles_Model $roles_model
|
* @property Roles_Model $roles_model
|
||||||
* @property Secretaries_Model $secretaries_model
|
* @property Secretaries_Model $secretaries_model
|
||||||
* @property Admins_Model $admins_model
|
* @property Admins_Model $admins_model
|
||||||
|
@ -283,6 +285,8 @@ class Backend_api extends CI_Controller {
|
||||||
$this->load->model('customers_model');
|
$this->load->model('customers_model');
|
||||||
$this->load->model('settings_model');
|
$this->load->model('settings_model');
|
||||||
$this->load->library('timezones');
|
$this->load->library('timezones');
|
||||||
|
$this->load->library('synchronization');
|
||||||
|
$this->load->library('notifications');
|
||||||
$this->load->model('user_model');
|
$this->load->model('user_model');
|
||||||
|
|
||||||
// Save customer changes to the database.
|
// Save customer changes to the database.
|
||||||
|
@ -290,10 +294,10 @@ class Backend_api extends CI_Controller {
|
||||||
{
|
{
|
||||||
$customer = json_decode($this->input->post('customer_data'), TRUE);
|
$customer = json_decode($this->input->post('customer_data'), TRUE);
|
||||||
|
|
||||||
$required_privilegesileges = ( ! isset($customer['id']))
|
$required_privileges = ( ! isset($customer['id']))
|
||||||
? $this->privileges[PRIV_CUSTOMERS]['add']
|
? $this->privileges[PRIV_CUSTOMERS]['add']
|
||||||
: $this->privileges[PRIV_CUSTOMERS]['edit'];
|
: $this->privileges[PRIV_CUSTOMERS]['edit'];
|
||||||
if ($required_privilegesileges == FALSE)
|
if ($required_privileges == FALSE)
|
||||||
{
|
{
|
||||||
throw new Exception('You do not have the required privileges for this task.');
|
throw new Exception('You do not have the required privileges for this task.');
|
||||||
}
|
}
|
||||||
|
@ -306,17 +310,17 @@ class Backend_api extends CI_Controller {
|
||||||
{
|
{
|
||||||
$appointment = json_decode($this->input->post('appointment_data'), TRUE);
|
$appointment = json_decode($this->input->post('appointment_data'), TRUE);
|
||||||
|
|
||||||
$required_privilegesileges = ( ! isset($appointment['id']))
|
$required_privileges = ( ! isset($appointment['id']))
|
||||||
? $this->privileges[PRIV_APPOINTMENTS]['add']
|
? $this->privileges[PRIV_APPOINTMENTS]['add']
|
||||||
: $this->privileges[PRIV_APPOINTMENTS]['edit'];
|
: $this->privileges[PRIV_APPOINTMENTS]['edit'];
|
||||||
if ($required_privilegesileges == FALSE)
|
if ($required_privileges == FALSE)
|
||||||
{
|
{
|
||||||
throw new Exception('You do not have the required privileges for this task.');
|
throw new Exception('You do not have the required privileges for this task.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$manage_mode = isset($appointment['id']);
|
$manage_mode = isset($appointment['id']);
|
||||||
// If the appointment does not contain the customer record id, then it
|
// If the appointment does not contain the customer record id, then it means that is is going to be
|
||||||
// means that is is going to be inserted. Get the customer's record id.
|
// inserted. Get the customer's record ID.
|
||||||
if ( ! isset($appointment['id_users_customer']))
|
if ( ! isset($appointment['id_users_customer']))
|
||||||
{
|
{
|
||||||
$appointment['id_users_customer'] = $customer['id'];
|
$appointment['id_users_customer'] = $customer['id'];
|
||||||
|
@ -348,140 +352,11 @@ class Backend_api extends CI_Controller {
|
||||||
'time_format' => $this->settings_model->get_setting('time_format')
|
'time_format' => $this->settings_model->get_setting('time_format')
|
||||||
];
|
];
|
||||||
|
|
||||||
// Sync appointment changes with Google Calendar.
|
$this->synchronization->sync_appointment_deleted($appointment, $provider);
|
||||||
try
|
$this->notifications->notify_appointment_deleted($appointment, $service, $provider, $customer, $settings);
|
||||||
{
|
|
||||||
$google_sync = $this->providers_model->get_setting('google_sync',
|
|
||||||
$appointment['id_users_provider']);
|
|
||||||
|
|
||||||
if ($google_sync == TRUE)
|
|
||||||
{
|
|
||||||
$google_token = json_decode($this->providers_model->get_setting('google_token',
|
|
||||||
$appointment['id_users_provider']));
|
|
||||||
|
|
||||||
$this->load->library('Google_sync');
|
|
||||||
$this->google_sync->refresh_token($google_token->refresh_token);
|
|
||||||
|
|
||||||
if ($appointment['id_google_calendar'] == NULL)
|
|
||||||
{
|
|
||||||
$google_event = $this->google_sync->add_appointment($appointment, $provider,
|
|
||||||
$service, $customer, $settings);
|
|
||||||
$appointment['id_google_calendar'] = $google_event->id;
|
|
||||||
$this->appointments_model->add($appointment); // Store google calendar id.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$this->google_sync->update_appointment($appointment, $provider,
|
|
||||||
$service, $customer, $settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $exception)
|
|
||||||
{
|
|
||||||
$warnings[] = [
|
|
||||||
'message' => $exception->getMessage(),
|
|
||||||
'trace' => config('debug') ? $exception->getTrace() : []
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send email notifications to provider and customer.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$this->config->load('email');
|
|
||||||
$email = new EmailClient($this, $this->config->config);
|
|
||||||
|
|
||||||
$send_provider = $this->providers_model
|
|
||||||
->get_setting('notifications', $provider['id']);
|
|
||||||
|
|
||||||
if ( ! $manage_mode)
|
|
||||||
{
|
|
||||||
$customer_title = new Text(lang('appointment_booked'));
|
|
||||||
$customer_message = new Text(lang('thank_you_for_appointment'));
|
|
||||||
$provider_title = new Text(lang('appointment_added_to_your_plan'));
|
|
||||||
$provider_message = new Text(lang('appointment_link_description'));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$customer_title = new Text(lang('appointment_details_changed'));
|
|
||||||
$customer_message = new Text('');
|
|
||||||
$provider_title = new Text(lang('appointment_changes_saved'));
|
|
||||||
$provider_message = new Text('');
|
|
||||||
}
|
|
||||||
|
|
||||||
$customer_link = new Url(site_url('appointments/index/' . $appointment['hash']));
|
|
||||||
$provider_link = new Url(site_url('backend/index/' . $appointment['hash']));
|
|
||||||
|
|
||||||
$send_customer = $this->settings_model->get_setting('customer_notifications');
|
|
||||||
|
|
||||||
$this->load->library('ics_file');
|
|
||||||
$ics_stream = $this->ics_file->get_stream($appointment, $service, $provider, $customer);
|
|
||||||
|
|
||||||
if ((bool)$send_customer === TRUE)
|
|
||||||
{
|
|
||||||
$email->sendAppointmentDetails($appointment, $provider,
|
|
||||||
$service, $customer, $settings, $customer_title,
|
|
||||||
$customer_message, $customer_link, new Email($customer['email']), new Text($ics_stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($send_provider == TRUE)
|
|
||||||
{
|
|
||||||
$email->sendAppointmentDetails($appointment, $provider,
|
|
||||||
$service, $customer, $settings, $provider_title,
|
|
||||||
$provider_message, $provider_link, new Email($provider['email']), new Text($ics_stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify admins
|
|
||||||
$admins = $this->admins_model->get_batch();
|
|
||||||
|
|
||||||
foreach($admins as $admin)
|
|
||||||
{
|
|
||||||
if (!$admin['settings']['notifications'] === '0')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$email->sendAppointmentDetails($appointment, $provider,
|
|
||||||
$service, $customer, $settings, $provider_title,
|
|
||||||
$provider_message, $provider_link, new Email($admin['email']), new Text($ics_stream));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify secretaries
|
|
||||||
$secretaries = $this->secretaries_model->get_batch();
|
|
||||||
|
|
||||||
foreach($secretaries as $secretary)
|
|
||||||
{
|
|
||||||
if (!$secretary['settings']['notifications'] === '0')
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array($provider['id'], $secretary['providers']))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$email->sendAppointmentDetails($appointment, $provider,
|
|
||||||
$service, $customer, $settings, $provider_title,
|
|
||||||
$provider_message, $provider_link, new Email($secretary['email']), new Text($ics_stream));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $exception)
|
|
||||||
{
|
|
||||||
$warnings[] = [
|
|
||||||
'message' => $exception->getMessage(),
|
|
||||||
'trace' => config('debug') ? $exception->getTrace() : []
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($warnings))
|
|
||||||
{
|
|
||||||
$response = AJAX_SUCCESS;
|
$response = AJAX_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
$response = ['warnings' => $warnings];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $exception)
|
catch (Exception $exception)
|
||||||
{
|
{
|
||||||
$this->output->set_status_header(500);
|
$this->output->set_status_header(500);
|
||||||
|
@ -1032,10 +907,10 @@ class Backend_api extends CI_Controller {
|
||||||
$this->load->model('customers_model');
|
$this->load->model('customers_model');
|
||||||
$customer = json_decode($this->input->post('customer'), TRUE);
|
$customer = json_decode($this->input->post('customer'), TRUE);
|
||||||
|
|
||||||
$required_privilegesileges = ( ! isset($customer['id']))
|
$required_privileges = ( ! isset($customer['id']))
|
||||||
? $this->privileges[PRIV_CUSTOMERS]['add']
|
? $this->privileges[PRIV_CUSTOMERS]['add']
|
||||||
: $this->privileges[PRIV_CUSTOMERS]['edit'];
|
: $this->privileges[PRIV_CUSTOMERS]['edit'];
|
||||||
if ($required_privilegesileges == FALSE)
|
if ($required_privileges == FALSE)
|
||||||
{
|
{
|
||||||
throw new Exception('You do not have the required privileges for this task.');
|
throw new Exception('You do not have the required privileges for this task.');
|
||||||
}
|
}
|
||||||
|
@ -1105,10 +980,10 @@ class Backend_api extends CI_Controller {
|
||||||
$this->load->model('services_model');
|
$this->load->model('services_model');
|
||||||
$service = json_decode($this->input->post('service'), TRUE);
|
$service = json_decode($this->input->post('service'), TRUE);
|
||||||
|
|
||||||
$required_privilegesileges = ( ! isset($service['id']))
|
$required_privileges = ( ! isset($service['id']))
|
||||||
? $this->privileges[PRIV_SERVICES]['add']
|
? $this->privileges[PRIV_SERVICES]['add']
|
||||||
: $this->privileges[PRIV_SERVICES]['edit'];
|
: $this->privileges[PRIV_SERVICES]['edit'];
|
||||||
if ($required_privilegesileges == FALSE)
|
if ($required_privileges == FALSE)
|
||||||
{
|
{
|
||||||
throw new Exception('You do not have the required privileges for this task.');
|
throw new Exception('You do not have the required privileges for this task.');
|
||||||
}
|
}
|
||||||
|
@ -1215,10 +1090,10 @@ class Backend_api extends CI_Controller {
|
||||||
$this->load->model('services_model');
|
$this->load->model('services_model');
|
||||||
$category = json_decode($this->input->post('category'), TRUE);
|
$category = json_decode($this->input->post('category'), TRUE);
|
||||||
|
|
||||||
$required_privilegesileges = ( ! isset($category['id']))
|
$required_privileges = ( ! isset($category['id']))
|
||||||
? $this->privileges[PRIV_SERVICES]['add']
|
? $this->privileges[PRIV_SERVICES]['add']
|
||||||
: $this->privileges[PRIV_SERVICES]['edit'];
|
: $this->privileges[PRIV_SERVICES]['edit'];
|
||||||
if ($required_privilegesileges == FALSE)
|
if ($required_privileges == FALSE)
|
||||||
{
|
{
|
||||||
throw new Exception('You do not have the required privileges for this task.');
|
throw new Exception('You do not have the required privileges for this task.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ use EA\Engine\Types\NonEmptyText;
|
||||||
* @property Customers_Model $customers_model
|
* @property Customers_Model $customers_model
|
||||||
* @property Settings_Model $settings_model
|
* @property Settings_Model $settings_model
|
||||||
* @property Timezones $timezones
|
* @property Timezones $timezones
|
||||||
|
* @property Notifications $notifications
|
||||||
|
* @property Synchronization $synchronization
|
||||||
* @property Roles_Model $roles_model
|
* @property Roles_Model $roles_model
|
||||||
* @property Secretaries_Model $secretaries_model
|
* @property Secretaries_Model $secretaries_model
|
||||||
* @property Admins_Model $admins_model
|
* @property Admins_Model $admins_model
|
||||||
|
@ -59,6 +61,12 @@ class Appointments extends API_V1_Controller {
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->load->model('appointments_model');
|
$this->load->model('appointments_model');
|
||||||
|
$this->load->model('services_model');
|
||||||
|
$this->load->model('providers_model');
|
||||||
|
$this->load->model('customers_model');
|
||||||
|
$this->load->model('settings_model');
|
||||||
|
$this->load->library('synchronization');
|
||||||
|
$this->load->library('notifications');
|
||||||
$this->parser = new \EA\Engine\Api\V1\Parsers\Appointments;
|
$this->parser = new \EA\Engine\Api\V1\Parsers\Appointments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +117,6 @@ class Appointments extends API_V1_Controller {
|
||||||
*/
|
*/
|
||||||
public function post()
|
public function post()
|
||||||
{
|
{
|
||||||
$this->load->model('services_model');
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Insert the appointment to the database.
|
// Insert the appointment to the database.
|
||||||
|
@ -138,6 +144,20 @@ class Appointments extends API_V1_Controller {
|
||||||
|
|
||||||
$id = $this->appointments_model->add($appointment);
|
$id = $this->appointments_model->add($appointment);
|
||||||
|
|
||||||
|
$service = $this->services_model->get_row($appointment['id_services']);
|
||||||
|
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
|
||||||
|
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
|
||||||
|
$settings = [
|
||||||
|
'company_name' => $this->settings_model->get_setting('company_name'),
|
||||||
|
'company_email' => $this->settings_model->get_setting('company_email'),
|
||||||
|
'company_link' => $this->settings_model->get_setting('company_link'),
|
||||||
|
'date_format' => $this->settings_model->get_setting('date_format'),
|
||||||
|
'time_format' => $this->settings_model->get_setting('time_format')
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->synchronization->sync_appointment_saved($appointment, $service, $provider, $customer, $settings, FALSE);
|
||||||
|
$this->notifications->notify_appointment_saved($appointment, $service, $provider, $customer, $settings, FALSE);
|
||||||
|
|
||||||
// Fetch the new object from the database and return it to the client.
|
// Fetch the new object from the database and return it to the client.
|
||||||
$batch = $this->appointments_model->get_batch('id = ' . $id);
|
$batch = $this->appointments_model->get_batch('id = ' . $id);
|
||||||
$response = new Response($batch);
|
$response = new Response($batch);
|
||||||
|
@ -174,6 +194,21 @@ class Appointments extends API_V1_Controller {
|
||||||
$updatedAppointment['id'] = $id;
|
$updatedAppointment['id'] = $id;
|
||||||
$id = $this->appointments_model->add($updatedAppointment);
|
$id = $this->appointments_model->add($updatedAppointment);
|
||||||
|
|
||||||
|
$service = $this->services_model->get_row($updatedAppointment['id_services']);
|
||||||
|
$provider = $this->providers_model->get_row($updatedAppointment['id_users_provider']);
|
||||||
|
$customer = $this->customers_model->get_row($updatedAppointment['id_users_customer']);
|
||||||
|
$settings = [
|
||||||
|
'company_name' => $this->settings_model->get_setting('company_name'),
|
||||||
|
'company_email' => $this->settings_model->get_setting('company_email'),
|
||||||
|
'company_link' => $this->settings_model->get_setting('company_link'),
|
||||||
|
'date_format' => $this->settings_model->get_setting('date_format'),
|
||||||
|
'time_format' => $this->settings_model->get_setting('time_format')
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->synchronization->sync_appointment_saved($updatedAppointment, $service, $provider, $customer, $settings, TRUE);
|
||||||
|
$this->notifications->notify_appointment_saved($updatedAppointment, $service, $provider, $customer, $settings, TRUE);
|
||||||
|
|
||||||
|
|
||||||
// Fetch the updated object from the database and return it to the client.
|
// Fetch the updated object from the database and return it to the client.
|
||||||
$batch = $this->appointments_model->get_batch('id = ' . $id);
|
$batch = $this->appointments_model->get_batch('id = ' . $id);
|
||||||
$response = new Response($batch);
|
$response = new Response($batch);
|
||||||
|
@ -194,8 +229,23 @@ class Appointments extends API_V1_Controller {
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
$appointment = $this->appointments_model->get_row($id);
|
||||||
|
$service = $this->services_model->get_row($appointment['id_services']);
|
||||||
|
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
|
||||||
|
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
|
||||||
|
$settings = [
|
||||||
|
'company_name' => $this->settings_model->get_setting('company_name'),
|
||||||
|
'company_email' => $this->settings_model->get_setting('company_email'),
|
||||||
|
'company_link' => $this->settings_model->get_setting('company_link'),
|
||||||
|
'date_format' => $this->settings_model->get_setting('date_format'),
|
||||||
|
'time_format' => $this->settings_model->get_setting('time_format')
|
||||||
|
];
|
||||||
|
|
||||||
$this->appointments_model->delete($id);
|
$this->appointments_model->delete($id);
|
||||||
|
|
||||||
|
$this->synchronization->sync_appointment_deleted($appointment, $provider);
|
||||||
|
$this->notifications->notify_appointment_deleted($appointment, $service, $provider, $customer, $settings);
|
||||||
|
|
||||||
$response = new Response([
|
$response = new Response([
|
||||||
'code' => 200,
|
'code' => 200,
|
||||||
'message' => 'Record was deleted successfully!'
|
'message' => 'Record was deleted successfully!'
|
||||||
|
|
552
application/libraries/Availability.php
Normal file
552
application/libraries/Availability.php
Normal file
|
@ -0,0 +1,552 @@
|
||||||
|
<?php defined('BASEPATH') or exit('No direct script access allowed');
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Easy!Appointments - Open Source Web Scheduler
|
||||||
|
*
|
||||||
|
* @package EasyAppointments
|
||||||
|
* @author A.Tselegidis <alextselegidis@gmail.com>
|
||||||
|
* @copyright Copyright (c) 2013 - 2020, Alex Tselegidis
|
||||||
|
* @license http://opensource.org/licenses/GPL-3.0 - GPLv3
|
||||||
|
* @link http://easyappointments.org
|
||||||
|
* @since v1.4.0
|
||||||
|
* ---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Availability
|
||||||
|
*
|
||||||
|
* Handles the availability generation of providers, based on their working plan and their schedule.
|
||||||
|
*/
|
||||||
|
class Availability {
|
||||||
|
/**
|
||||||
|
* @var CI_Controller
|
||||||
|
*/
|
||||||
|
protected $CI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Availability constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->CI =& get_instance();
|
||||||
|
$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');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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)
|
||||||
|
{
|
||||||
|
$available_periods = $this->get_available_periods($date, $provider, $exclude_appointment_id);
|
||||||
|
|
||||||
|
$available_hours = $this->generate_available_hours($date, $service, $available_periods);
|
||||||
|
|
||||||
|
if ($service['attendants_number'] > 1)
|
||||||
|
{
|
||||||
|
$available_hours = $this->consider_multiple_attendants($date, $service, $provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->consider_book_advance_timeout($date, $available_hours, $provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @param string $date Select date string.
|
||||||
|
* @param array $provider Provider record.
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
public function get_available_periods(
|
||||||
|
$date,
|
||||||
|
$provider,
|
||||||
|
$exclude_appointment_id = NULL
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Get the service, provider's working plan and provider appointments.
|
||||||
|
$working_plan = json_decode($provider['settings']['working_plan'], TRUE);
|
||||||
|
|
||||||
|
// Get the provider's working plan exceptions.
|
||||||
|
$working_plan_exceptions = json_decode($provider['settings']['working_plan_exceptions'], TRUE);
|
||||||
|
|
||||||
|
$conditions = [
|
||||||
|
'id_users_provider' => $provider['id'],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Sometimes it might be necessary to exclude an appointment from the calculation (e.g. when editing an
|
||||||
|
// existing appointment).
|
||||||
|
if ($exclude_appointment_id)
|
||||||
|
{
|
||||||
|
$conditions['id !='] = $exclude_appointment_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$appointments = $this->CI->appointments_model->get_batch($conditions);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
$date_working_plan = $working_plan[strtolower(date('l', strtotime($date)))];
|
||||||
|
|
||||||
|
// Search if the $date is an custom availability period added outside the normal working plan.
|
||||||
|
if (isset($working_plan_exceptions[$date]))
|
||||||
|
{
|
||||||
|
$date_working_plan = $working_plan_exceptions[$date];
|
||||||
|
}
|
||||||
|
|
||||||
|
$periods = [];
|
||||||
|
|
||||||
|
if (isset($date_working_plan['breaks']))
|
||||||
|
{
|
||||||
|
$periods[] = [
|
||||||
|
'start' => $date_working_plan['start'],
|
||||||
|
'end' => $date_working_plan['end']
|
||||||
|
];
|
||||||
|
|
||||||
|
$day_start = new DateTime($date_working_plan['start']);
|
||||||
|
$day_end = new DateTime($date_working_plan['end']);
|
||||||
|
|
||||||
|
// Split the working plan to available time periods that do not contain the breaks in them.
|
||||||
|
foreach ($date_working_plan['breaks'] as $index => $break)
|
||||||
|
{
|
||||||
|
$break_start = new DateTime($break['start']);
|
||||||
|
$break_end = new DateTime($break['end']);
|
||||||
|
|
||||||
|
if ($break_start < $day_start)
|
||||||
|
{
|
||||||
|
$break_start = $day_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($break_end > $day_end)
|
||||||
|
{
|
||||||
|
$break_end = $day_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($break_start >= $break_end)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($periods as $key => $period)
|
||||||
|
{
|
||||||
|
$period_start = new DateTime($period['start']);
|
||||||
|
$period_end = new DateTime($period['end']);
|
||||||
|
|
||||||
|
$remove_current_period = FALSE;
|
||||||
|
|
||||||
|
if ($break_start > $period_start && $break_start < $period_end && $break_end > $period_start)
|
||||||
|
{
|
||||||
|
$periods[] = [
|
||||||
|
'start' => $period_start->format('H:i'),
|
||||||
|
'end' => $break_start->format('H:i')
|
||||||
|
];
|
||||||
|
|
||||||
|
$remove_current_period = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($break_start < $period_end && $break_end > $period_start && $break_end < $period_end)
|
||||||
|
{
|
||||||
|
$periods[] = [
|
||||||
|
'start' => $break_end->format('H:i'),
|
||||||
|
'end' => $period_end->format('H:i')
|
||||||
|
];
|
||||||
|
|
||||||
|
$remove_current_period = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($break_start == $period_start && $break_end == $period_end)
|
||||||
|
{
|
||||||
|
$remove_current_period = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($remove_current_period)
|
||||||
|
{
|
||||||
|
unset($periods[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break the empty periods with the reserved appointments.
|
||||||
|
foreach ($appointments as $appointment)
|
||||||
|
{
|
||||||
|
foreach ($periods as $index => &$period)
|
||||||
|
{
|
||||||
|
$appointment_start = new DateTime($appointment['start_datetime']);
|
||||||
|
$appointment_end = new DateTime($appointment['end_datetime']);
|
||||||
|
|
||||||
|
if ($appointment_start >= $appointment_end)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$period_start = new DateTime($date . ' ' . $period['start']);
|
||||||
|
$period_end = new DateTime($date . ' ' . $period['end']);
|
||||||
|
|
||||||
|
if ($appointment_start <= $period_start && $appointment_end <= $period_end && $appointment_end <= $period_start)
|
||||||
|
{
|
||||||
|
// The appointment does not belong in this time period, so we will not change anything.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($appointment_start <= $period_start && $appointment_end <= $period_end && $appointment_end >= $period_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'] = $appointment_end->format('H:i');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($appointment_start >= $period_start && $appointment_end < $period_end)
|
||||||
|
{
|
||||||
|
// The appointment is inside the time period, so we will split the period into two new
|
||||||
|
// others.
|
||||||
|
unset($periods[$index]);
|
||||||
|
|
||||||
|
$periods[] = [
|
||||||
|
'start' => $period_start->format('H:i'),
|
||||||
|
'end' => $appointment_start->format('H:i')
|
||||||
|
];
|
||||||
|
|
||||||
|
$periods[] = [
|
||||||
|
'start' => $appointment_end->format('H:i'),
|
||||||
|
'end' => $period_end->format('H:i')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else if ($appointment_start == $period_start && $appointment_end == $period_end)
|
||||||
|
{
|
||||||
|
unset($periods[$index]); // The whole period is blocked so remove it from the available periods array.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($appointment_start >= $period_start && $appointment_end >= $period_start && $appointment_start <= $period_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'] = $appointment_start->format('H:i');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($appointment_start >= $period_start && $appointment_end >= $period_end && $appointment_start >= $period_end)
|
||||||
|
{
|
||||||
|
// The appointment does not belong in the period so do not change anything.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($appointment_start <= $period_start && $appointment_end >= $period_end && $appointment_start <= $period_end)
|
||||||
|
{
|
||||||
|
// The appointment is bigger than the period, so this period needs to be removed.
|
||||||
|
unset($periods[$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values($periods);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @return array Returns an array with the available hours for the appointment.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function generate_available_hours(
|
||||||
|
$date,
|
||||||
|
$service,
|
||||||
|
$empty_periods
|
||||||
|
)
|
||||||
|
{
|
||||||
|
$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'])
|
||||||
|
{
|
||||||
|
$available_hours[] = $current_hour->format('H:i');
|
||||||
|
$current_hour->add(new DateInterval('PT' . $interval . 'M'));
|
||||||
|
$diff = $current_hour->diff($end_hour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $available_hours;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get multiple attendants hours.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @return array Returns the available hours array.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function consider_multiple_attendants(
|
||||||
|
$date,
|
||||||
|
$service,
|
||||||
|
$provider
|
||||||
|
)
|
||||||
|
{
|
||||||
|
$unavailability_events = $this->CI->appointments_model->get_batch([
|
||||||
|
'is_unavailable' => TRUE,
|
||||||
|
'DATE(start_datetime)' => $date,
|
||||||
|
'id_users_provider' => $provider['id']
|
||||||
|
]);
|
||||||
|
|
||||||
|
$working_plan = json_decode($provider['settings']['working_plan'], TRUE);
|
||||||
|
$working_day = strtolower(date('l', strtotime($date)));
|
||||||
|
$working_hours = $working_plan[$working_day];
|
||||||
|
|
||||||
|
$periods = [
|
||||||
|
[
|
||||||
|
'start' => new DateTime($date . ' ' . $working_hours['start']),
|
||||||
|
'end' => new DateTime($date . ' ' . $working_hours['end'])
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$periods = $this->remove_breaks($date, $periods, $working_hours['breaks']);
|
||||||
|
$periods = $this->remove_unavailability_events($periods, $unavailability_events);
|
||||||
|
|
||||||
|
$hours = [];
|
||||||
|
|
||||||
|
$interval_value = $service['availabilities_type'] == AVAILABILITIES_TYPE_FIXED ? $service['duration'] : '15';
|
||||||
|
$interval = new DateInterval('PT' . (int)$interval_value . 'M');
|
||||||
|
$duration = new DateInterval('PT' . (int)$service['duration'] . 'M');
|
||||||
|
|
||||||
|
foreach ($periods as $period)
|
||||||
|
{
|
||||||
|
$slot_start = clone $period['start'];
|
||||||
|
$slot_end = clone $slot_start;
|
||||||
|
$slot_end->add($duration);
|
||||||
|
|
||||||
|
while ($slot_end <= $period['end'])
|
||||||
|
{
|
||||||
|
// Check reserved attendants for this time slot and see if current attendants fit.
|
||||||
|
$appointment_attendants_number = $this->CI->appointments_model->get_attendants_number_for_period(
|
||||||
|
$slot_start,
|
||||||
|
$slot_end,
|
||||||
|
$service['id']
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($appointment_attendants_number < $service['attendants_number'])
|
||||||
|
{
|
||||||
|
$hours[] = $slot_start->format('H:i');
|
||||||
|
}
|
||||||
|
|
||||||
|
$slot_start->add($interval);
|
||||||
|
$slot_end->add($interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hours;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @return array Returns the available time periods without the breaks.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function remove_breaks($selected_date, $periods, $breaks)
|
||||||
|
{
|
||||||
|
if ( ! $breaks)
|
||||||
|
{
|
||||||
|
return $periods;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($breaks as $break)
|
||||||
|
{
|
||||||
|
$break_start = new DateTime($selected_date . ' ' . $break['start']);
|
||||||
|
$break_end = new DateTime($selected_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)
|
||||||
|
{
|
||||||
|
// left
|
||||||
|
$period['start'] = $break_end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($break_start >= $period_start && $break_start <= $period_end && $break_end >= $period_start && $break_end <= $period_end)
|
||||||
|
{
|
||||||
|
// middle
|
||||||
|
$period['end'] = $break_start;
|
||||||
|
$periods[] = [
|
||||||
|
'start' => $break_end,
|
||||||
|
'end' => $period_end
|
||||||
|
];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($break_start >= $period_start && $break_start <= $period_end && $break_end >= $period_end)
|
||||||
|
{
|
||||||
|
// right
|
||||||
|
$period['end'] = $break_start;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($break_start <= $period_start && $break_end >= $period_end)
|
||||||
|
{
|
||||||
|
// break contains period
|
||||||
|
$period['start'] = $break_end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $periods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the unavailability entries from the available time periods of the selected date.
|
||||||
|
*
|
||||||
|
* @param array $periods Available time periods.
|
||||||
|
* @param array $unavailability_events Unavailability events of the current date.
|
||||||
|
*
|
||||||
|
* @return array Returns the available time periods without the unavailability events.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function remove_unavailability_events($periods, $unavailability_events)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
$period['start'] = $unavailability_end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_start && $unavailability_end <= $period_end)
|
||||||
|
{
|
||||||
|
// middle
|
||||||
|
$period['end'] = $unavailability_start;
|
||||||
|
$periods[] = [
|
||||||
|
'start' => $unavailability_end,
|
||||||
|
'end' => $period_end
|
||||||
|
];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_end)
|
||||||
|
{
|
||||||
|
// right
|
||||||
|
$period['end'] = $unavailability_start;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($unavailability_start <= $period_start && $unavailability_end >= $period_end)
|
||||||
|
{
|
||||||
|
// Unavailability contains period
|
||||||
|
$period['start'] = $unavailability_end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $periods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consider the book advance timeout and remove available hours that have passed the threshold.
|
||||||
|
*
|
||||||
|
* If the selected date is today, remove past hours. It is important include the timeout before booking
|
||||||
|
* 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 array $available_hours Already generated available hours.
|
||||||
|
* @param array $provider Provider information.
|
||||||
|
*
|
||||||
|
* @return array Returns the updated available hours.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function consider_book_advance_timeout($selected_date, $available_hours, $provider)
|
||||||
|
{
|
||||||
|
$provider_timezone = new DateTimeZone($provider['timezone']);
|
||||||
|
|
||||||
|
$book_advance_timeout = $this->CI->settings_model->get_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);
|
||||||
|
|
||||||
|
if ($available_hour->getTimestamp() <= $threshold->getTimestamp())
|
||||||
|
{
|
||||||
|
unset($available_hours[$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$available_hours = array_values($available_hours);
|
||||||
|
sort($available_hours, SORT_STRING);
|
||||||
|
return array_values($available_hours);
|
||||||
|
}
|
||||||
|
}
|
227
application/libraries/Notifications.php
Normal file
227
application/libraries/Notifications.php
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
<?php defined('BASEPATH') or exit('No direct script access allowed');
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Easy!Appointments - Open Source Web Scheduler
|
||||||
|
*
|
||||||
|
* @package EasyAppointments
|
||||||
|
* @author A.Tselegidis <alextselegidis@gmail.com>
|
||||||
|
* @copyright Copyright (c) 2013 - 2020, Alex Tselegidis
|
||||||
|
* @license http://opensource.org/licenses/GPL-3.0 - GPLv3
|
||||||
|
* @link http://easyappointments.org
|
||||||
|
* @since v1.4.0
|
||||||
|
* ---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
use EA\Engine\Notifications\Email as EmailClient;
|
||||||
|
use EA\Engine\Types\Email;
|
||||||
|
use EA\Engine\Types\Text;
|
||||||
|
use EA\Engine\Types\Url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Notifications
|
||||||
|
*
|
||||||
|
* Handles the system notifications (mostly related to scheduling changes).
|
||||||
|
*/
|
||||||
|
class Notifications {
|
||||||
|
/**
|
||||||
|
* @var CI_Controller
|
||||||
|
*/
|
||||||
|
protected $CI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifications constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->CI =& get_instance();
|
||||||
|
$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');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the required notifications, related to an appointment creation/modification.
|
||||||
|
*
|
||||||
|
* @param array $appointment Appointment record.
|
||||||
|
* @param array $service Service record.
|
||||||
|
* @param array $provider Provider record.
|
||||||
|
* @param array $customer Customer record.
|
||||||
|
* @param array $settings Required settings for the notification content.
|
||||||
|
* @param bool|false $manage_mode
|
||||||
|
*/
|
||||||
|
public function notify_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode = FALSE)
|
||||||
|
{
|
||||||
|
// Send email notifications to customer and provider.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$this->CI->config->load('email');
|
||||||
|
|
||||||
|
$email = new EmailClient($this->CI, $this->CI->config->config);
|
||||||
|
|
||||||
|
if ($manage_mode === FALSE)
|
||||||
|
{
|
||||||
|
$customer_title = new Text(lang('appointment_booked'));
|
||||||
|
$customer_message = new Text(lang('thank_you_for_appointment'));
|
||||||
|
$provider_title = new Text(lang('appointment_added_to_your_plan'));
|
||||||
|
$provider_message = new Text(lang('appointment_link_description'));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$customer_title = new Text(lang('appointment_changes_saved'));
|
||||||
|
$customer_message = new Text('');
|
||||||
|
$provider_title = new Text(lang('appointment_details_changed'));
|
||||||
|
$provider_message = new Text('');
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer_link = new Url(site_url('appointments/index/' . $appointment['hash']));
|
||||||
|
$provider_link = new Url(site_url('backend/index/' . $appointment['hash']));
|
||||||
|
|
||||||
|
$send_customer = filter_var(
|
||||||
|
$this->CI->settings_model->get_setting('customer_notifications'),
|
||||||
|
FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
|
||||||
|
$ics_stream = $this->CI->ics_file->get_stream($appointment, $service, $provider, $customer);
|
||||||
|
|
||||||
|
if ($send_customer === TRUE)
|
||||||
|
{
|
||||||
|
$email->sendAppointmentDetails($appointment, $provider,
|
||||||
|
$service, $customer, $settings, $customer_title,
|
||||||
|
$customer_message, $customer_link, new Email($customer['email']), new Text($ics_stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
$send_provider = filter_var(
|
||||||
|
$this->CI->providers_model->get_setting('notifications', $provider['id']),
|
||||||
|
FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
if ($send_provider === TRUE)
|
||||||
|
{
|
||||||
|
$email->sendAppointmentDetails($appointment, $provider,
|
||||||
|
$service, $customer, $settings, $provider_title,
|
||||||
|
$provider_message, $provider_link, new Email($provider['email']), new Text($ics_stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify admins
|
||||||
|
$admins = $this->CI->admins_model->get_batch();
|
||||||
|
|
||||||
|
foreach ($admins as $admin)
|
||||||
|
{
|
||||||
|
if ( ! $admin['settings']['notifications'] === '0')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$email->sendAppointmentDetails($appointment, $provider,
|
||||||
|
$service, $customer, $settings, $provider_title,
|
||||||
|
$provider_message, $provider_link, new Email($admin['email']), new Text($ics_stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify secretaries
|
||||||
|
$secretaries = $this->CI->secretaries_model->get_batch();
|
||||||
|
|
||||||
|
foreach ($secretaries as $secretary)
|
||||||
|
{
|
||||||
|
if ( ! $secretary['settings']['notifications'] === '0')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($provider['id'], $secretary['providers']))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$email->sendAppointmentDetails($appointment, $provider,
|
||||||
|
$service, $customer, $settings, $provider_title,
|
||||||
|
$provider_message, $provider_link, new Email($secretary['email']), new Text($ics_stream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $exception)
|
||||||
|
{
|
||||||
|
log_message('error', $exception->getMessage());
|
||||||
|
log_message('error', $exception->getTraceAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the required notifications, related to an appointment removal.
|
||||||
|
*
|
||||||
|
* @param array $appointment Appointment record.
|
||||||
|
* @param array $service Service record.
|
||||||
|
* @param array $provider Provider record.
|
||||||
|
* @param array $customer Customer record.
|
||||||
|
* @param array $settings Required settings for the notification content.
|
||||||
|
*/
|
||||||
|
public function notify_appointment_deleted($appointment, $service, $provider, $customer, $settings)
|
||||||
|
{
|
||||||
|
// Send email notification to customer and provider.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$email = new EmailClient($this->CI, $this->CI->config->config);
|
||||||
|
|
||||||
|
$send_provider = filter_var($this->CI->providers_model->get_setting('notifications', $provider['id']),
|
||||||
|
FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
if ($send_provider === TRUE)
|
||||||
|
{
|
||||||
|
$email->sendDeleteAppointment($appointment, $provider,
|
||||||
|
$service, $customer, $settings, new Email($provider['email']),
|
||||||
|
new Text($this->CI->input->post('cancel_reason')));
|
||||||
|
}
|
||||||
|
|
||||||
|
$send_customer = filter_var(
|
||||||
|
$this->CI->settings_model->get_setting('customer_notifications'),
|
||||||
|
FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
if ($send_customer === TRUE)
|
||||||
|
{
|
||||||
|
$email->sendDeleteAppointment($appointment, $provider,
|
||||||
|
$service, $customer, $settings, new Email($customer['email']),
|
||||||
|
new Text($this->CI->input->post('cancel_reason')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify admins
|
||||||
|
$admins = $this->CI->admins_model->get_batch();
|
||||||
|
|
||||||
|
foreach ($admins as $admin)
|
||||||
|
{
|
||||||
|
if ( ! $admin['settings']['notifications'] === '0')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$email->sendDeleteAppointment($appointment, $provider,
|
||||||
|
$service, $customer, $settings, new Email($admin['email']),
|
||||||
|
new Text($this->CI->input->post('cancel_reason')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify secretaries
|
||||||
|
$secretaries = $this->CI->secretaries_model->get_batch();
|
||||||
|
|
||||||
|
foreach ($secretaries as $secretary)
|
||||||
|
{
|
||||||
|
if ( ! $secretary['settings']['notifications'] === '0')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($provider['id'], $secretary['providers']))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$email->sendDeleteAppointment($appointment, $provider,
|
||||||
|
$service, $customer, $settings, new Email($secretary['email']),
|
||||||
|
new Text($this->CI->input->post('cancel_reason')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $exception)
|
||||||
|
{
|
||||||
|
$exceptions[] = $exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
120
application/libraries/Synchronization.php
Normal file
120
application/libraries/Synchronization.php
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
<?php defined('BASEPATH') or exit('No direct script access allowed');
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Easy!Appointments - Open Source Web Scheduler
|
||||||
|
*
|
||||||
|
* @package EasyAppointments
|
||||||
|
* @author A.Tselegidis <alextselegidis@gmail.com>
|
||||||
|
* @copyright Copyright (c) 2013 - 2020, Alex Tselegidis
|
||||||
|
* @license http://opensource.org/licenses/GPL-3.0 - GPLv3
|
||||||
|
* @link http://easyappointments.org
|
||||||
|
* @since v1.4.0
|
||||||
|
* ---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Synchronization
|
||||||
|
*
|
||||||
|
* Handles the external calendar synchronization.
|
||||||
|
*/
|
||||||
|
class Synchronization {
|
||||||
|
/**
|
||||||
|
* @var CI_Controller
|
||||||
|
*/
|
||||||
|
protected $CI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronization constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->CI =& get_instance();
|
||||||
|
$this->CI->load->model('providers_model');
|
||||||
|
$this->CI->load->model('appointments_model');
|
||||||
|
$this->CI->load->library('google_sync');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize changes made to the appointment with external calendars.
|
||||||
|
*
|
||||||
|
* @param array $appointment Appointment record.
|
||||||
|
* @param array $service Service record.
|
||||||
|
* @param array $provider Provider record.
|
||||||
|
* @param array $customer Customer record.
|
||||||
|
* @param array $settings Required settings for the notification content.
|
||||||
|
* @param bool|false $manage_mode True if the appointment is being edited.
|
||||||
|
*/
|
||||||
|
public function sync_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode = FALSE)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$google_sync = filter_var(
|
||||||
|
$this->CI->providers_model->get_setting('google_sync', $appointment['id_users_provider']),
|
||||||
|
FILTER_VALIDATE_BOOLEAN
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($google_sync === TRUE)
|
||||||
|
{
|
||||||
|
$google_token = json_decode(
|
||||||
|
$this->CI->providers_model->get_setting('google_token', $appointment['id_users_provider']));
|
||||||
|
|
||||||
|
$this->CI->load->library('google_sync');
|
||||||
|
|
||||||
|
$this->CI->google_sync->refresh_token($google_token->refresh_token);
|
||||||
|
|
||||||
|
if ($manage_mode === FALSE)
|
||||||
|
{
|
||||||
|
// Add appointment to Google Calendar.
|
||||||
|
$google_event = $this->CI->google_sync->add_appointment($appointment, $provider,
|
||||||
|
$service, $customer, $settings);
|
||||||
|
$appointment['id_google_calendar'] = $google_event->id;
|
||||||
|
$this->CI->appointments_model->add($appointment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Update appointment to Google Calendar.
|
||||||
|
$appointment['id_google_calendar'] = $this->CI->appointments_model
|
||||||
|
->get_value('id_google_calendar', $appointment['id']);
|
||||||
|
|
||||||
|
$this->CI->google_sync->update_appointment($appointment, $provider,
|
||||||
|
$service, $customer, $settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $exception)
|
||||||
|
{
|
||||||
|
log_message('error', $exception->getMessage());
|
||||||
|
log_message('error', $exception->getTraceAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize removal of an appointment with external calendars.
|
||||||
|
*
|
||||||
|
* @param array $appointment Appointment record.
|
||||||
|
* @param array $provider Provider record.
|
||||||
|
*/
|
||||||
|
public function sync_appointment_deleted($appointment, $provider)
|
||||||
|
{
|
||||||
|
if ($appointment['id_google_calendar'] != NULL)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$google_sync = filter_var(
|
||||||
|
$this->CI->providers_model->get_setting('google_sync', $appointment['id_users_provider']),
|
||||||
|
FILTER_VALIDATE_BOOLEAN);
|
||||||
|
|
||||||
|
if ($google_sync === TRUE)
|
||||||
|
{
|
||||||
|
$google_token = json_decode($this->CI->providers_model->get_setting('google_token', $provider['id']));
|
||||||
|
$this->CI->load->library('Google_sync');
|
||||||
|
$this->CI->google_sync->refresh_token($google_token->refresh_token);
|
||||||
|
$this->CI->google_sync->delete_appointment($provider, $appointment['id_google_calendar']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $exception)
|
||||||
|
{
|
||||||
|
$exceptions[] = $exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue