diff --git a/src/application/controllers/appointments.php b/src/application/controllers/appointments.php index d7524817..25a1df9d 100644 --- a/src/application/controllers/appointments.php +++ b/src/application/controllers/appointments.php @@ -159,6 +159,8 @@ class Appointments extends CI_Controller { $this->load->model('Appointments_Model'); $this->load->model('Providers_Model'); $this->load->model('Customers_Model'); + $this->load->model('Services_Model'); + $this->load->model('Settings_Model'); // Check whether the appointment hash exists in the database. $records = $this->Appointments_Model->get_batch(array('hash' => $appointment_hash)); @@ -167,40 +169,42 @@ class Appointments extends CI_Controller { } $appointment_data = $records[0]; + $provider_data = $this->Providers_Model->get_row($appointment_data['id_users_provider']); + $customer_data = $this->Customers_Model->get_row($appointment_data['id_users_customer']); + $service_data = $this->Services_Model->get_row($appointment_data['id_services']); + $company_settings = array( + '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') + ); - // Delete the appointment from the database. + // :: DELETE APPOINTMENT RECORD FROM THE DATABASE. if (!$this->Appointments_Model->delete($appointment_data['id'])) { throw new Exception('Appointment could not be deleted from the database.'); } - // Send notification emails to the customer and provider. - $provider_email = $this->Providers_Model->get_value('email', - $appointment_data['id_users_provider']); - $customer_email = $this->Customers_Model->get_value('email', - $appointment_data['id_users_customer']); - - $this->load->library('Notifications'); - $this->notifications->send_cancel_appointment($appointment_data, $provider_email); - $this->notifications->send_cancel_appointment($appointment_data, $customer_email); - - // Delete the appointment from Google Calendar, if it is synced. - if ($appointment_data['id_google_calendar'] != NULL) { + // :: SYNC APPOINTMENT REMOVAL WITH GOOGLE CALENDAR + if ($appointment_data['id_google_calendar'] != NULL) { $google_sync = $this->Providers_Model->get_setting('google_sync', $appointment_data['id_users_provider']); if ($google_sync == TRUE) { - $this->load->library('google_sync'); - - // Get the provider's refresh token and try to authenticate the - // Google Calendar API usage. - $google_token = $this->Providers_Model->get_setting('google_token', - $appointment_data['id_users_provider']); - - if ($this->google_sync->authendicate($google_token) === TRUE) { - $this->google_sync->delete_appointment($appointment_data['id']); - } + $google_token = json_decode($this->Providers_Model + ->get_setting('google_token', $provider_data['id'])); + + $this->load->library('Google_Sync'); + $this->google_sync->refresh_token($google_token->refresh_token); + $this->google_sync->delete_appointment($appointment_data['id_google_calendar']); } - } + } + + // :: SEND NOTIFICATION EMAILS TO CUSTOMER AND PROVIDER + $this->load->library('Notifications'); + $this->notifications->send_remove_appointment($appointment_data, $provider_data, + $service_data, $customer_data, $company_settings, $provider_data['email']); + $this->notifications->send_remove_appointment($appointment_data, $provider_data, + $service_data, $customer_data, $company_settings, $customer_data['email']); + } catch(Exception $exc) { // Display the error message to the customer. $view_data['error_message'] = $exc->getMessage(); diff --git a/src/application/controllers/backend.php b/src/application/controllers/backend.php index 9d0d93d2..8f9f0a82 100644 --- a/src/application/controllers/backend.php +++ b/src/application/controllers/backend.php @@ -102,9 +102,15 @@ class Backend extends CI_Controller { */ public function ajax_save_appointment_changes() { try { + $this->load->model('Appointments_Model'); + $this->load->model('Providers_Model'); + $this->load->model('Services_Model'); + $this->load->model('Customers_Model'); + $this->load->model('Settings_Model'); + + // :: SAVE APPOINTMENT CHANGES TO DATABASE if (isset($_POST['appointment_data'])) { $appointment_data = json_decode(stripcslashes($_POST['appointment_data']), true); - $this->load->model('Appointments_Model'); $this->Appointments_Model->add($appointment_data); if ($appointment_data['id_google_calendar'] != NULL) { @@ -120,12 +126,42 @@ class Backend extends CI_Controller { } } + // :: SAVE CUSTOMER CHANGES TO DATABASE if (isset($_POST['customer_data'])) { $customer_data = json_decode(stripcslashes($_POST['customer_data']), true); - $this->load->model('Customers_Model'); $this->Customers_Model->add($customer_data); } + // :: SYNC APPOINTMENT CHANGES WITH GOOGLE CALENDAR + if ($appointment_data['id_google_calendar'] != NULL) { + $google_sync = $this->Providers_Model + ->get_setting('google_sync', $appointment_data['id_users_provider']); + if ($google_sync == TRUE) { + $google_token = $this->Providers_Model + ->get_setting('google_token', $appointment_data['id_users_provider']); + $this->load->library('Google_Sync'); + $this->google_sync->refresh_token($google_token->refresh_token); + $this->google_sync->update_appointment($appointment_data, $provider_data, + $service_data, $customer_data); + } + } + + // :: SEND EMAIL NOTIFICATIONS TO PROVIDER AND CUSTOMER + $this->load->library('Notifications'); + try { + $customer_title = 'Appointment Changes Saved Successfully!'; + $provider_title = 'Appointment Details Have Changed'; + + $this->notifications->send_book_success( + $customer_data, $appointment_data, $customer_title); + $this->notifications->send_new_appointment( + $customer_data, $appointment_data, $provider_title); + + } catch(NotificationException $nt_exc) { + // @task Display message to the user that the notification messages could + // not be sent. + } + echo json_encode('SUCCESS'); } catch(Exception $exc) { @@ -144,9 +180,6 @@ class Backend extends CI_Controller { * account of the provider, if the "google_sync" setting is enabled. * * @param int $_POST['appointment_id'] The appointment id to be deleted. - * - * @task Sync action with GCal. - * @task Send email notifications to provider and customer. */ public function ajax_delete_appointment() { try { @@ -159,11 +192,17 @@ class Backend extends CI_Controller { $this->load->model('Providers_Model'); $this->load->model('Customers_Model'); $this->load->model('Services_Model'); + $this->load->model('Settings_Model'); $appointment_data = $this->Appointments_Model->get_row($_POST['appointment_id']); - $provider_data = $this->Providers_Model->get_row($appointment_data['id_users_provider']); - $customer_data = $this->Customers_Model->get_row($appointment_data['id_users_customer']); - $service_data = $this->services_Model->get_row($appointment_data['id_services']); + $provider_data = $this->Providers_Model->get_row($appointment_data['id_users_provider']); + $customer_data = $this->Customers_Model->get_row($appointment_data['id_users_customer']); + $service_data = $this->Services_Model->get_row($appointment_data['id_services']); + $company_settings = array( + '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') + ); // :: DELETE APPOINTMENT RECORD FROM DATABASE. $this->Appointments_Model->delete($_POST['appointment_id']); @@ -183,8 +222,8 @@ class Backend extends CI_Controller { // :: SEND NOTIFICATION EMAILS TO PROVIDER AND CUSTOMER. $this->load->library('Notifications'); - $this->notification->send_delete_appointment($appointment_data, $provider_data, - $service_data, $customer_data); + $this->notification->send_remove_appointment($appointment_data, $provider_data, + $service_data, $customer_data, $company_settings); echo json_encode('SUCCESS'); diff --git a/src/application/libraries/google_sync.php b/src/application/libraries/google_sync.php index 58cfe04c..2c571dcb 100644 --- a/src/application/libraries/google_sync.php +++ b/src/application/libraries/google_sync.php @@ -158,22 +158,16 @@ class Google_Sync { /** * Update an existing appointment that is already synced with Google Calendar. * - * @param int $appointment_id The appointment record id. + * This method updates the google calendar event item that is connected with the + * provided appointment record of Easy!Appointments. + * + * @param array $appointment_data Contains the appointment record data. + * @param array $provider_data Contains the provider record data. + * @param array $service_data Contains the service record data. + * @param array $customer_data Contains the customer recod data. */ public function update_appointment($appointment_data, $provider_data, $service_data, $customer_data) { - $this->CI->load->model('Appointments_Model'); - $this->CI->load->model('Services_Model'); - $this->CI->load->model('Providers_Model'); - $this->CI->load->model('Customers_Model'); - $this->CI->load->model('Settings_Model'); - - $appointment_data = $this->CI->Appointments_Model->get_row($appointment_id); - $provider_data = $this->CI->Providers_Model->get_row($appointment_data['id_users_provider']); - $customer_data = $this->CI->Customers_Model->get_row($appointment_data['id_users_customer']); - $service_data = $this->CI->Services_Model->get_row($appointment_data['id_services']); - $company_name = $this->CI->Settings_Model->get_setting('company_name'); - $this->CI->load->helper('general'); } diff --git a/src/application/libraries/notifications.php b/src/application/libraries/notifications.php index 1d558cda..82885aac 100644 --- a/src/application/libraries/notifications.php +++ b/src/application/libraries/notifications.php @@ -157,38 +157,45 @@ class Notifications { } /** - * Send an email notification to a user when an appointment is cancelled. + * Send an email notification to both provider and customer on appointment removal. * - * @param array $appointment_data The record data of the cancelled appointment. - * @param string $user_email The user email where the email notification is going - * to be send. + * Whenever an appointment is cancelled or removed, both the provider and customer + * need to be informed. This method sends the same email twice. + * + * IMPORTANT! This method's arguments should be taken + * from database before the appointment record is deleted. + * + * @param array $appointment_data The record data of the removed appointment. + * @param array $provider_data The record data of the appointment provider. + * @param array $service_data The record data of the appointment service. + * @param array $customer_data The record data of the appointment customer. + * @param array $company_settings Some settings that are required for this function. + * By now this array must contain the following values: "company_link", + * "company_name", "company_email". + * @param string $to_address The email address of the email receiver. */ - public function send_cancel_appointment($appointment_data, $user_email) { - $this->CI->load->model('Providers_Model'); - $this->CI->load->model('Services_Model'); - $this->CI->load->model('Settings_Model'); - - $provider_data = $this->CI->Providers_Model->get_row($appointment_data['id_users_provider']); - $service_data = $this->CI->Services_Model->get_row($appointment_data['id_services']); - + public function send_remove_appointment($appointment_data, $provider_data, + $service_data, $customer_data, $company_settings, $to_address) { + // :: PREPARE EMAIL REPLACE ARRAY $replace_array = array( '$email_title' => 'Appointment Cancelled', '$appointment_service' => $service_data['name'], '$appointment_provider' => $provider_data['first_name'] . ' ' . $provider_data['last_name'], '$appointment_date' => date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])), '$appointment_duration' => $service_data['duration'] . ' minutes', - '$company_link' => $this->CI->Settings_Model->get_setting('company_link'), - '$company_name' => $this->CI->Settings_Model->get_setting('company_name') + '$company_link' => $company_settings('company_link'), + '$company_name' => $company_settings('company_name') ); $email_html = file_get_contents(dirname(dirname(__FILE__)) . '/views/emails/cancel_appointment.php'); $email_html = $this->replace_template_variables($replace_array, $email_html); + // :: SETUP EMAIL OBJECT AND SEND NOTIFICATION $mail = new PHPMailer(); - $mail->From = $this->CI->Settings_Model->get_setting('company_email'); - $mail->FromName = $this->CI->Settings_Model->get_setting('company_name'); - $mail->AddAddress($user_email); // "Name" argument crushes the phpmailer class. + $mail->From = $company_settings['company_email']; + $mail->FromName = $company_settings['$company_name']; + $mail->AddAddress($to_address); // "Name" argument crushes the phpmailer class. $mail->IsHTML(true); $mail->CharSet = 'UTF-8'; $mail->Subject = 'Appointment Cancelled'; @@ -201,21 +208,7 @@ class Notifications { return TRUE; } - - /** - * Send delete appointment notification. - * - * This method should be called after the appointment has been deleted. - * - * IMPORTANT! This method's arguments should be taken - * from database before the appointment record is deleted. - */ - public function send_delete_appointment($appointment_data, $provider_data, - $service_data, $customer_data) { - // @task Implement sending delete appointment notification. - } } - /* End of file notifications.php */ /* Location: ./application/libraries/notifications.php */ \ No newline at end of file diff --git a/src/application/models/services_model.php b/src/application/models/services_model.php index d97f13b1..4e1eb34c 100644 --- a/src/application/models/services_model.php +++ b/src/application/models/services_model.php @@ -75,7 +75,13 @@ class Services_Model extends CI_Model { * database services. */ function get_available_services() { - return $this->db->get('ea_services')->result_array(); + $this->db->distinct(); + return $this->db + ->select('ea_services.*') + ->from('ea_services') + ->join('ea_services_providers', + 'ea_services_providers.id_services = ea_services.id', 'inner') + ->get()->result_array(); } } diff --git a/src/application/views/emails/cancel_appointment.php b/src/application/views/emails/remove_appointment.php similarity index 100% rename from src/application/views/emails/cancel_appointment.php rename to src/application/views/emails/remove_appointment.php diff --git a/src/assets/js/backend.js b/src/assets/js/backend.js index 43cde7a3..f8b552fd 100644 --- a/src/assets/js/backend.js +++ b/src/assets/js/backend.js @@ -66,8 +66,6 @@ var Backend = { notificationHtml += ''; - var leftValue = window.innerWidth / 2 - $('body .notification').width() - 200; - $('#notification').html(notificationHtml); $('#notification').show('blind'); } diff --git a/src/assets/js/backend_calendar.js b/src/assets/js/backend_calendar.js index 25273f6b..275022ad 100644 --- a/src/assets/js/backend_calendar.js +++ b/src/assets/js/backend_calendar.js @@ -69,7 +69,7 @@ var BackendCalendar = { provider['first_name'] + ' ' + provider['last_name'] + ''; }); optgroupHtml += ''; - $('#select-filter-item').append(optgroupHtml) + $('#select-filter-item').append(optgroupHtml); optgroupHtml = ''; $.each(GlobalVariables.availableServices, function(index, service) { @@ -78,7 +78,7 @@ var BackendCalendar = { service['name'] + ''; }); optgroupHtml += ''; - $('#select-filter-item').append(optgroupHtml) + $('#select-filter-item').append(optgroupHtml); // :: BIND THE DEFAULT EVENT HANDLERS if (defaultEventHandlers === true) { @@ -239,18 +239,19 @@ var BackendCalendar = { $.post(postUrl, postData, function(response) { ///////////////////////////////////////////////////////// - console.log('Delete Appointment Response :', response); + //console.log('Delete Appointment Response :', response); ///////////////////////////////////////////////////////// + $('#message_box').dialog('close'); + if (response.error) { GeneralFunctions.displayMessageBox('Delete Appointment Error', - 'An unexpected error occured during the deletion of the ' - + 'appointment. Please try again.'); + 'An unexpected error occured during the deletion of the ' + + 'appointment. Please try again.'); return; } - // Close dialog and refresh calendar events. - $('#message_box').dialog('close'); + // Refresh calendar event items. $('#select-filter-item').trigger('change'); }, 'json'); diff --git a/src/assets/js/general_functions.js b/src/assets/js/general_functions.js index aef1ac5e..2446c985 100644 --- a/src/assets/js/general_functions.js +++ b/src/assets/js/general_functions.js @@ -111,14 +111,14 @@ var GeneralFunctions = { * @returns {String} Returns the transformed string. */ ISODateString: function(dt){ - function pad(n){return n<10 ? '0'+n : n} + function pad(n){return n<10 ? '0'+n : n;} return dt.getUTCFullYear()+'-' + pad(dt.getUTCMonth()+1)+'-' + pad(dt.getUTCDate())+'T' + pad(dt.getUTCHours())+':' + pad(dt.getUTCMinutes())+':' - + pad(dt.getUTCSeconds())+'Z' + + pad(dt.getUTCSeconds())+'Z'; }, /**