Ολοκλήρωση λειτουργιών για την έκδοση 0.3

This commit is contained in:
alextselegidis@gmail.com 2013-06-26 09:31:57 +00:00
parent 36718c87f9
commit 3062dbc001
12 changed files with 333 additions and 308 deletions

View File

@ -3,7 +3,7 @@
-- http://www.phpmyadmin.net
--
-- Φιλοξενητής: localhost
-- Χρόνος δημιουργίας: 19 Ιουν 2013 στις 22:27:32
-- Χρόνος δημιουργίας: 26 Ιουν 2013 στις 12:29:46
-- Έκδοση διακομιστή: 5.5.24-log
-- Έκδοση PHP: 5.4.3
@ -41,7 +41,7 @@ CREATE TABLE IF NOT EXISTS `ea_appointments` (
KEY `id_users_customer` (`id_users_customer`),
KEY `id_services` (`id_services`),
KEY `id_users_provider` (`id_users_provider`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=88 ;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=25 ;
-- --------------------------------------------------------
@ -184,17 +184,17 @@ CREATE TABLE IF NOT EXISTS `ea_users` (
`id_roles` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `id_roles` (`id_roles`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=154 ;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
--
-- Άδειασμα δεδομένων του πίνακα `ea_users`
--
INSERT INTO `ea_users` (`id`, `first_name`, `last_name`, `email`, `mobile_number`, `phone_number`, `address`, `city`, `state`, `zip_code`, `notes`, `id_roles`) VALUES
(1, '', '1', 'alextselegidis@gmail.com', '123456789', '1', '', '', NULL, '', 'This is me making Easy!Appointments', 1),
(2, 'Γεώργιος', 'Παπαδόπουλος', 'alextselegidis@gmail.com', '1212121212', '1', '', '', NULL, '', 'This is a test provider', 2),
(3, 'Νίκος', 'Αναστασίου', 'prov2@test.gr', '1313133113131', '32132165146', 'Some Street 3', NULL, NULL, NULL, NULL, 2),
(4, 'Ηρώ', 'Καριοφύλη', 'prov3@test.gr', '239203490', '029340923', 'John Doe 3 ', NULL, NULL, NULL, NULL, 2);
(1, 'Alex', 'Tselegidis', 'alextselegidis@gmail.com', '123456789', '123456789', 'Some Str', 'Some City', 'Some State', '12345', 'This is me making Easy!Appointments :P', 1),
(2, 'Γεώργιος', 'Παπαδόπουλος', 'alextselegidis@gmail.com', '1111111111111', '1111111111111', '', '', NULL, '', 'This is a test provider (with my email for google syncing).', 2),
(3, 'Νίκος', 'Αναστασίου', 'prov2@test.gr', '2222222222222', '2222222222222', 'Some Street 3', NULL, NULL, NULL, NULL, 2),
(4, 'Ηρώ', 'Καριοφύλη', 'prov3@test.gr', '3333333333333', '3333333333333', 'John Doe 3 ', NULL, NULL, NULL, NULL, 2);
-- --------------------------------------------------------
@ -218,9 +218,9 @@ CREATE TABLE IF NOT EXISTS `ea_user_settings` (
--
INSERT INTO `ea_user_settings` (`id_users`, `username`, `password`, `working_plan`, `notifications`, `google_sync`, `google_token`) VALUES
(2, 'provider_1', 'provider_1', '{"monday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"tuesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"wednesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"thursday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"friday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"saturday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"sunday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]}}', NULL, 1, '{"access_token":"ya29.AHES6ZRsDBInIFSW1vdMEUt9N_teDoKPk6IVLS-mM41J7P0","token_type":"Bearer","expires_in":3600,"refresh_token":"1\\/9KusWyDci21Fv-PpgeZr3Yik56WnNQ7LDTcmeUhNTN8","created":1371639646}'),
(2, 'provider_1', 'provider_1', '{"monday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"tuesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"wednesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"thursday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"friday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"saturday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"sunday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]}}', NULL, 1, NULL),
(3, 'provider_2', 'provider_2', '{"monday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"tuesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"wednesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"thursday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"friday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"saturday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"sunday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]}}', NULL, 0, NULL),
(4, 'provider_3', 'provider_3', '{"monday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"tuesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"wednesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"thursday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"friday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"saturday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"sunday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]}}', NULL, 1, '{"access_token":"ya29.AHES6ZQLXwNinpRgyZ30VP4aNy2MctNkj3fc6oJid8-Gc-TEifJ6WA","token_type":"Bearer","expires_in":3600,"refresh_token":"1\\/bBPokd195S2UX2so9-jclC3E3gpzxgyDjGhJkJxmkHU","created":1371639504}');
(4, 'provider_3', 'provider_3', '{"monday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"tuesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"wednesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"thursday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"friday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"saturday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"sunday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]}}', NULL, 1, NULL);
--
-- Περιορισμοί για άχρηστους πίνακες

View File

@ -12,28 +12,42 @@ class Appointments extends CI_Controller {
* record.
*/
public function index($appointment_hash = '') {
$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');
if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') {
$this->load->model('Settings_Model');
$this->load->model('Services_Model');
$this->load->model('Providers_Model');
$company_name = $this->Settings_Model->get_setting('company_name');
$available_services = $this->Services_Model->get_available_services();
$available_providers = $this->Providers_Model->get_available_providers();
$company_name = $this->Settings_Model->get_setting('company_name');
// If an appointment hash is provided then it means that the customer
// is trying to edit a registered record.
if ($appointment_hash !== ''){
// Load the appointments data and set the manage mode of the page.
$this->load->model('Appointments_Model');
$this->load->model('Customers_Model');
$manage_mode = TRUE;
$results = $this->Appointments_Model
->get_batch(array('hash' => $appointment_hash));
$appointment_data = $results[0]; // Php 5.3 does not support treating a function as an array.
if (count($results) === 0) {
// The requested appointment doesn't exist in the database. Display
// a message to the customer.
$view_data = array(
'message_title' => 'Appointment Not Found!',
'message_text' => 'The appointment you requested does not exist in the '
. 'database anymore.',
'message_icon' => $this->config->item('base_url') . 'assets/images/error.png'
);
$this->load->view('appointments/message', $view_data);
return;
}
// Php 5.3 does not support treating a function result as an array.
$appointment_data = $results[0];
$provider_data = $this->Providers_Model
->get_row($appointment_data['id_users_provider']);
@ -58,87 +72,111 @@ class Appointments extends CI_Controller {
'provider_data' => $provider_data,
'customer_data' => $customer_data
);
$this->load->view('appointments/book', $view_data);
} else {
// The page is a post-back. Register the appointment and send
// notification emails to the provider and the customer that are
// related to the appointment.
$post_data = json_decode($_POST['post_data'], true);
$appointment_data = $post_data['appointment'];
$customer_data = $post_data['customer'];
$this->load->model('Customers_Model');
$this->load->model('Appointments_Model');
$this->load->model('Services_Model');
$this->load->model('Providers_Model');
$this->load->model('Settings_Model');
$customer_id = $this->Customers_Model->add($customer_data);
$appointment_data['id_users_customer'] = $customer_id;
$appointment_data['id'] = $this->Appointments_Model->add($appointment_data);
$appointment_data['hash'] = $this->Appointments_Model
->get_value('hash', $appointment_data['id']);
// Send an email to the customer with the appointment info.
$this->load->library('Notifications');
// The page is a post-back. Register the appointment and send notification emails
// to the provider and the customer that are related to the appointment. If google
// sync is enabled then add the appointment to the provider's account.
try {
$post_data = json_decode($_POST['post_data'], true);
$appointment_data = $post_data['appointment'];
$customer_data = $post_data['customer'];
$customer_id = $this->Customers_Model->add($customer_data);
$appointment_data['id_users_customer'] = $customer_id;
$appointment_data['id'] = $this->Appointments_Model->add($appointment_data);
$appointment_data['hash'] = $this->Appointments_Model
->get_value('hash', $appointment_data['id']);
// :: SEND NOTIFICATION EMAILS TO BOTH CUSTOMER AND PROVIDER
$this->load->library('Notifications');
$provider_data = $this->Providers_Model
->get_row($appointment_data['id_users_provider']);
$service_data = $this->Services_Model->get_row($appointment_data['id_services']);
$company_settings = array(
'company_name' => $this->Settings_Model->get_setting('company_name'),
'company_link' => $this->Settings_Model->get_setting('company_link'),
'company_email' => $this->Settings_Model->get_setting('company_email')
);
if (!$post_data['manage_mode']) {
$customer_title = 'Your appointment has been successfully booked!';
$customer_message = 'Thank you for arranging an appointment with us. ' .
'Below you can see the appointment details. Make changes ' .
'by clicking the appointment link.';
$customer_link = $this->config->item('base_url') . 'appointments/index/'
. $appointment_data['hash'];
$provider_title = 'A new appointment has been added to your plan.';
$provider_message = 'You can make changes by clicking the appointment ' .
'link below';
$provider_link = $this->config->item('base_url') . 'backend/'
. $appointment_data['hash'];
} else {
$customer_title = 'Appointment Changes Saved Successfully!';
$provider_title = 'Appointment Details Have Changed';
$customer_title = 'Appointment changes have been successfully saved!';
$customer_message = '';
$customer_link = $this->config->item('base_url') . 'appointments/index/'
. $appointment_data['hash'];
$provider_title = 'Appointment details have changed.';
$provider_message = '';
$provider_link = $this->config->item('base_url') . 'backend/'
. $appointment_data['hash'];
}
$this->notifications->send_book_success(
$customer_data, $appointment_data, $customer_title);
$this->notifications->send_new_appointment(
$customer_data, $appointment_data, $provider_title);
} catch (NotificationException $not_exc) {
$view_data['notification_error'] = '<br><br>'
. '<pre>An unexpected error occured while sending you an '
. 'email. Please backup the appointment details so that '
. 'you can restore them later. <br><br>Error: <br>'
. $not_exc->getMessage() . '</pre>';
$this->notifications->send_appointment_details(
$appointment_data, $provider_data, $service_data, $customer_data,
$company_settings, $customer_title, $customer_message, $customer_link,
$customer_data['email']);
$this->notifications->send_appointment_details(
$appointment_data, $provider_data, $service_data, $customer_data,
$company_settings, $provider_title, $provider_message, $provider_link,
$provider_data['email']);
// :: SYNCHRONIZE APPOINTMENT WITH PROVIDER'S GOOGLE CALENDAR
// The provider must have previously granted access to his google calendar account
// in order to sync the appointment.
$google_sync = $this->Providers_Model->get_setting('google_sync',
$appointment_data['id_users_provider']);
if ($google_sync == TRUE) {
$google_token = json_decode($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);
if ($post_data['manage_mode'] === FALSE) {
// Add appointment to Google Calendar.
$this->google_sync->add_appointment($appointment_data['id']);
} else {
// Update appointment to Google Calendar.
$appointment_data['id_google_calendar'] = $this->Appointments_Model
->get_value('id_google_calendar', $appointment_data['id']);
$this->google_sync->update_appointment($appointment_data, $provider_data,
$service_data, $customer_data, $company_settings);
}
}
// :: LOAD THE BOOK SUCCESS VIEW
$view_data = array(
'appointment_data' => $appointment_data,
'provider_data' => $provider_data,
'service_data' => $service_data,
'company_name' => $company_settings['company_name']
);
} catch(Exception $exc) {
$view_data['error'] = array(
'message' => $exc->getMessage(),
'technical' => $exc->getTraceAsString()
);
}
// Synchronize the appointment with the providers plan, if the
// google sync option is enabled.
$google_sync = $this->Providers_Model->get_setting('google_sync',
$appointment_data['id_users_provider']);
if ($google_sync == TRUE) {
$google_token = json_decode($this->Providers_Model->get_setting('google_token',
$appointment_data['id_users_provider']));
// Authenticate the token. If it isn't valid, the sync operation cannot
// be completed.
$this->load->library('google_sync');
$this->google_sync->refresh_token($google_token->refresh_token);
if ($post_data['manage_mode'] === FALSE) {
// Add appointment to Google Calendar.
$this->google_sync->add_appointment($appointment_data['id']);
} else {
// Update appointment to Google Calendar.
$this->google_sync->update_appointment($appointment_data['id']);
}
}
// Load the book success view.
$service_data = $this->Services_Model->get_row($appointment_data['id_services']);
$provider_data = $this->Providers_Model->get_row($appointment_data['id_users_provider']);
$company_name = $this->Settings_Model->get_setting('company_name');
$view_data = array(
'appointment_data' => $appointment_data,
'service_data' => $service_data,
'provider_data' => $provider_data,
'company_name' => $company_name
);
$this->load->view('appointments/book_success', $view_data);
}
}
@ -169,13 +207,13 @@ 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')
$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 THE DATABASE.
@ -200,9 +238,9 @@ class Appointments extends CI_Controller {
// :: SEND NOTIFICATION EMAILS TO CUSTOMER AND PROVIDER
$this->load->library('Notifications');
$this->notifications->send_remove_appointment($appointment_data, $provider_data,
$this->notifications->send_delete_appointment($appointment_data, $provider_data,
$service_data, $customer_data, $company_settings, $provider_data['email']);
$this->notifications->send_remove_appointment($appointment_data, $provider_data,
$this->notifications->send_delete_appointment($appointment_data, $provider_data,
$service_data, $customer_data, $company_settings, $customer_data['email']);
} catch(Exception $exc) {
@ -216,12 +254,11 @@ class Appointments extends CI_Controller {
/**
* [AJAX] Get the available appointment hours for the given date.
*
* This method answers to an AJAX request. It calculates the
* available hours for the given service, provider and date.
* This method answers to an AJAX request. It calculates the available hours for the
* given service, provider and date.
*
* @param array $_POST['post_data'] An associative array that
* contains the user selected 'service_id', 'provider_id',
* 'selected_date' and 'service_duration' in minutes.
* @param array $_POST['post_data'] An associative array that contains the user selected
* 'service_id', 'provider_id', 'selected_date' and 'service_duration' in minutes.
* @return Returns a json object with the available hours.
*/
public function ajax_get_available_hours() {
@ -236,8 +273,7 @@ class Appointments extends CI_Controller {
$where_clause = array(
'DATE(start_datetime)' => date('Y-m-d', strtotime($_POST['selected_date'])),
'id_users_provider' => $_POST['provider_id']
);
);
$reserved_appointments = $this->Appointments_Model->get_batch($where_clause);
if ($_POST['manage_mode'] === 'true') {
@ -283,7 +319,7 @@ class Appointments extends CI_Controller {
'end' => $sel_date_working_plan['end']
);
}
// PROBLEM
// Break the empty spaces with the reserved appointments.
$empty_spaces_with_appointments = array();
if (count($reserved_appointments) > 0) {
@ -295,22 +331,49 @@ class Appointments extends CI_Controller {
$space_end = date('H:i', strtotime($space['end']));
if ($space_start < $appointment_start && $space_end > $appointment_end) {
// We need to check whether another appointment fits in the current
// space. If this happens, then we need to consider the whole appointment
// time as one, because the provider will not be available.
foreach ($reserved_appointments as $appt) {
$appt_start = date('H:i', strtotime($appt['start_datetime']));
$appt_end = date('H:i', strtotime($appt['end_datetime']));
if ($space_start < $appt_start && $space_end > $appt_end) {
if ($appointment_start > $appt_start) {
$appointment_start = $appt_start;
}
if ($appointment_end < $appt_end) {
$appointment_end = $appt_end;
}
}
}
// Current appointment is within the current empty space. So
// we need to break the empty space into two other spaces that
// don't include the appointment.
$empty_spaces_with_appointments[] = array(
'start' => $space_start,
'end' => $appointment_start
);
$empty_spaces_with_appointments[] = array(
'start' => $appointment_end,
'end' => $space_end
);
$new_space = array(
'start' => $space_start,
'end' => $appointment_start
);
if (!in_array($new_space, $empty_spaces_with_appointments)) {
$empty_spaces_with_appointments[] = $new_space;
}
$new_space = array(
'start' => $appointment_end,
'end' => $space_end
);
if (!in_array($new_space, $empty_spaces_with_appointments)) {
$empty_spaces_with_appointments[] = $new_space;
}
} else {
// Check if there are any other appointments between this
// time space. If not, it is going to be added as it is.
$found = FALSE;
foreach($reserved_appointments as $appt) {
foreach ($reserved_appointments as $appt) {
$appt_start = date('H:i', strtotime($appt['start_datetime']));
$appt_end = date('H:i', strtotime($appt['end_datetime']));
if ($space_start < $appt_start && $space_end > $appt_end) {

View File

@ -95,10 +95,6 @@ class Backend extends CI_Controller {
* appointment data.
* @param array $_POST['customer_data'] (OPTIONAL) Array with the customer
* data.
*
* @task Send email notifications to both provider and customer that changes
* have been made to the appointment.
* @task Sync changes with google calendar.
*/
public function ajax_save_appointment_changes() {
try {
@ -215,9 +211,9 @@ class Backend extends CI_Controller {
// :: SEND NOTIFICATION EMAILS TO PROVIDER AND CUSTOMER.
$this->load->library('Notifications');
$this->notifications->send_remove_appointment($appointment_data, $provider_data,
$this->notifications->send_delete_appointment($appointment_data, $provider_data,
$service_data, $customer_data, $company_settings, $provider_data['email']);
$this->notifications->send_remove_appointment($appointment_data, $provider_data,
$this->notifications->send_delete_appointment($appointment_data, $provider_data,
$service_data, $customer_data, $company_settings, $customer_data['email']);
echo json_encode('SUCCESS');

View File

@ -15,5 +15,10 @@ class ValidationException extends Exception {}
*/
class NotificationException extends Exception {}
/**
* Sync Exception Class
*/
class SyncException extends Exception {}
/* End of file exception_types_helper.php */
/* Location: ./application/helpers/exception_types_helper.php */

View File

@ -69,7 +69,6 @@ class Unit_tests extends CI_Driver_Library {
*/
public function run_library_tests($output_report = true) {
// @task Implement unit tests for the libraries.
if ($output_report) {
$this->CI->output->append_output($this->CI->unit->report());
}

View File

@ -94,36 +94,23 @@ class Google_Sync {
* If yes, the selected appointment record is going to be added to the Google
* Calendar account.
*
* <strong>IMPORTANT!</strong> If the access token is not valid anymore the
* appointment cannot be added to the Google Calendar. A notification warning
* must be sent to the provider in order to authorize the E!A again, and store
* the new access token to the database.
*
* @param int $appointment_id The record id of the appointment that is going to
* be added to the database.
* @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.
* @parma array $company_settings Contains some company settings that are used
* by this method. By the time the following values must be in the array:
* 'company_name'.
* @return Google_Event Returns the Google_Event class object.
*
* @task This library should not use the models. The data must be provided from
* the controllers (same for notification library).
*/
public function add_appointment($appointment_id) {
$this->CI->load->model('Appointments_Model');
$this->CI->load->model('Providers_Model');
$this->CI->load->model('Services_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');
public function add_appointment($appointment_data, $provider_data, $service_data,
$customer_data, $company_settings) {
$this->CI->load->helper('general');
$event = new Google_Event();
$event->setSummary($service_data['name']);
$event->setLocation($company_name);
$event->setLocation($company_settings['company_name']);
$start = new Google_EventDateTime();
$start->setDateTime(date3339(strtotime($appointment_data['start_datetime'])));
@ -152,7 +139,7 @@ class Google_Sync {
$created_event = $this->service->events->insert('primary', $event);
// Set the Google Calendar event id to the E!A database record.
$appointment_data['id_google_calendar'] = $created_event['id'];
$appointment_data['id_google_calendar'] = $created_event->id;
$this->CI->Appointments_Model->add($appointment_data);
return $created_event;
@ -171,7 +158,6 @@ class Google_Sync {
* @parma array $company_settings Contains some company settings that are used
* by this method. By the time the following values must be in the array:
* 'company_name'.
*
* @return Google_Event Returns the Google_Event class object.
*/
public function update_appointment($appointment_data, $provider_data,

View File

@ -41,94 +41,43 @@ class Notifications {
}
/**
* Send a success email to the customer that booked
* a new appointment.
* Send an email with the appointment details.
*
* @expectedException NotificationException Raises when an unexpected
* error has occured when the email is send.
* This email template also needs an email title and an email text in order to complete
* the appointment details.
*
* @param array $customer_data Associative array with the customer's
* data. Each key has the same name as the corresponding field in db.
* @param array $appointment_data Associative array with the appointment's
* data. Each key has the same name as the corresponding field in db.
* @param string $email_title The email title is going to inform the customer
* for the action that was taken.
* @expectedException NotificationException Raises when an unexpected error occures.
*
* @param array $appointment_data Contains the appointment data.
* @param array $provider_data Contains the provider data.
* @param array $service_data Contains the service data.
* @param array $company_settings Contains settings of the company. By the time the
* "company_name", "company_link" and "company_email" values are required in the array.
* @param string $title The email title may vary depending the receiver.
* @param string $message The email message may vary depending the receiver.
* @param string $appointment_link This link is going to enable the receiver to make changes
* to the appointment record.
* @param string $receiver_address The receiver email address.
* @return bool Returns the operation result.
*/
public function send_book_success($customer_data, $appointment_data, $email_title) {
$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_appointment_details($appointment_data, $provider_data, $service_data,
$customer_data, $company_settings, $title, $message, $appointment_link,
$receiver_address) {
// :: PREPARE THE EMAIL TEMPLATE REPLACE ARRAY
$replace_array = array(
'$email_title' => $email_title,
'$email_title' => $title,
'$email_message' => $message,
'$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',
'$appointment_link' => $this->CI->config->item('base_url') . 'appointments/index/' . $appointment_data['hash'],
'$company_link' => $this->CI->Settings_Model->get_setting('company_link'),
'$company_name' => $this->CI->Settings_Model->get_setting('company_name'),
'$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name']
);
$email_html = file_get_contents(dirname(dirname(__FILE__)) . '/views/emails/book_success.php');
$email_html = $this->replace_template_variables($replace_array, $email_html);
$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($customer_data['email']); // Do not use the name argument, phpmailer crushes.
$mail->IsHTML(true);
$mail->CharSet = 'UTF-8';
$mail->Subject = $email_title;
$mail->Body = $email_html;
if(!$mail->Send()) {
throw new NotificationException('Email could not been sent. '
. 'Mailer Error (' . __LINE__ . '): ' . $mail->ErrorInfo);
}
return TRUE;
}
/**
* Send an email notification to a provider that
* a new appointment has been added to his plan.
*
* @expectedException NotificationException Raises when an unexpected
* error has occured when the email is send.
*
* @param array $customer_data Associative array with the customer's
* data. Each key has the same name as the corresponding field in db.
* @param array $appointment_data Associative array with the appointment's
* data. Each key has the same name as the corresponding field in db.
* @param string $email_title The email title is going to inform the provider
* for the action that was taken.
* @return bool Returns the operation result.
*/
public function send_new_appointment($customer_data, $appointment_data, $email_title) {
$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']);
$replace_array = array(
'$email_title' => $email_title,
'$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',
'$appointment_link' => $this->CI->config->item('base_url') . 'appointments/admin/' . $appointment_data['hash'],
'$company_link' => $this->CI->Settings_Model->get_setting('company_link'),
'$company_name' => $this->CI->Settings_Model->get_setting('company_name'),
'$appointment_start_date' => date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])),
'$appointment_end_date' => date('d/m/Y H:i', strtotime($appointment_data['end_datetime'])),
'$appointment_link' => $appointment_link,
'$company_link' => $company_settings['company_link'],
'$company_name' => $company_settings['company_name'],
'$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name'],
'$customer_email' => $customer_data['email'],
'$customer_phone' => $customer_data['phone_number'],
@ -136,16 +85,17 @@ class Notifications {
);
$email_html = file_get_contents(dirname(dirname(__FILE__))
. '/views/emails/new_appointment.php');
. '/views/emails/appointment_details.php');
$email_html = $this->replace_template_variables($replace_array, $email_html);
// :: INSTANTIATE EMAIL OBJECT AND SEND EMAIL
$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($provider_data['email']); // "Name" argument crushes the phpmailer class.
$mail->From = $company_settings['company_email'];
$mail->FromName = $company_settings['company_name'];
$mail->AddAddress($receiver_address); // "Name" argument crushes the phpmailer class.
$mail->IsHTML(true);
$mail->CharSet = 'UTF-8';
$mail->Subject = $email_title;
$mail->Subject = $title;
$mail->Body = $email_html;
if (!$mail->Send()) {
@ -174,7 +124,7 @@ class Notifications {
* "company_name", "company_email".
* @param string $to_address The email address of the email receiver.
*/
public function send_remove_appointment($appointment_data, $provider_data,
public function send_delete_appointment($appointment_data, $provider_data,
$service_data, $customer_data, $company_settings, $to_address) {
// :: PREPARE EMAIL REPLACE ARRAY
$replace_array = array(
@ -184,11 +134,15 @@ class Notifications {
'$appointment_date' => date('d/m/Y H:i', strtotime($appointment_data['start_datetime'])),
'$appointment_duration' => $service_data['duration'] . ' minutes',
'$company_link' => $company_settings['company_link'],
'$company_name' => $company_settings['company_name']
'$company_name' => $company_settings['company_name'],
'$customer_name' => $customer_data['first_name'] . ' ' . $customer_data['last_name'],
'$customer_email' => $customer_data['email'],
'$customer_phone' => $customer_data['phone_number'],
'$customer_address' => $customer_data['address']
);
$email_html = file_get_contents(dirname(dirname(__FILE__))
. '/views/emails/remove_appointment.php');
. '/views/emails/delete_appointment.php');
$email_html = $this->replace_template_variables($replace_array, $email_html);
// :: SETUP EMAIL OBJECT AND SEND NOTIFICATION

View File

@ -190,12 +190,28 @@
<i class="icon-plus icon-white"></i>
Add to Google Calendar
</button>
<?php
// Display exception message (if any).
// @task Special display of exceptions within the app.
if (isset($notification_error)) {
echo $notification_error;
// Display error message (if any).
if (isset($error)) {
echo '
<hr>
<h4>An Unexpected Error Occured</h4>
<div class="accordion" id="error-accordion">
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse"
data-parent="#error-accordion" href="#error-technical">' .
$error['message'] . '
</a>
</div>
<div id="error-technical" class="accordion-body collapse">
<div class="accordion-inner">
<pre>' . $error['technical'] . '</pre>
</div>
</div>
</div>
</div>';
}
?>
</div>

View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<?php // INCLUDE JS FILES ?>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.min.js"></script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/bootstrap/bootstrap.min.js"></script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/date.js"></script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/general_functions.js"></script>
<?php // INCLUDE CSS FILES ?>
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<?php // SET FAVICON FOR PAGE ?>
<link
rel="icon"
type="image/x-icon"
href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<style>
body {
background-color: #CAEDF3;
}
#message-frame {
width: 630px;
margin: 150px auto 0 auto;
background: #FFF;
border: 1px solid #DDDADA;
padding: 70px;
}
#message-icon {
float: right;
margin-top: 17px;
}
</style>
</head>
<body>
<div id="message-frame" class="frame-container">
<img id="message-icon" src="<?php echo $message_icon; ?>" />
<h3><?php echo $message_title; ?></h3>
<p><?php echo $message_text; ?></p>
</div>
</body>
</html>

View File

@ -1,18 +1,19 @@
<html>
<head>
<title>New Appointment</title>
<title>Appointment Details</title>
</head>
<body style="font: 13px arial, helvetica, tahoma;">
<div class="email-container" style="width: 650px;border: 1px solid #eee;">
<div id="header" style="background-color: #3DD481; border-bottom: 4px solid #1A865F;
height: 40px; padding: 10px 15px;">
height: 40px;padding: 10px 15px;">
<strong id="logo" style="color: white; font-size: 31px;
text-shadow: 1px 1px 1px #8F8888;">$company_name</strong>
</div>
<div id="content" style="padding: 10px 15px;">
<h2>$email_title</h2>
<p>$email_message</p>
<h2>Appointment Details</h2>
<table id="appointment-details">
<tr>
@ -24,17 +25,17 @@
<td style="padding: 3px;">$appointment_provider</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Date</td>
<td style="padding: 3px;">$appointment_date</td>
<td class="label" style="padding: 3px;font-weight: bold;">Start</td>
<td style="padding: 3px;">$appointment_start_date</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Duration</td>
<td style="padding: 3px;">$appointment_duration</td>
<td class="label" style="padding: 3px;font-weight: bold;">End</td>
<td style="padding: 3px;">$appointment_end_date</td>
</tr>
</table>
<h2>Customer Details</h2>
<table id="appointment-details">
<table id="customer-details">
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Name</td>
<td style="padding: 3px;">$customer_name</td>
@ -54,12 +55,11 @@
</table>
<h2>Appointment Link</h2>
<p>You can make more actions by pressing the following link.</p>
<a href="$appointment_link" style="width: 600px;">$appointment_link</a>
</div>
<div id="footer" style="padding: 10px; text-align: center;
border-top: 1px solid #EEE; background: #FAFAFA;">
border-top: 1px solid #EEE;background: #FAFAFA;">
<a href="$company_link">$company_name</a> | Powered by Easy!Appointments
</div>
</div>

View File

@ -1,56 +0,0 @@
<html>
<head>
<title>Appointment Book Success</title>
</head>
<body style="font: 13px arial, helvetica, tahoma;">
<div class="email-container" style="width: 650px;border: 1px solid #eee;">
<div id="header" style="background-color: #3DD481; border-bottom: 4px solid #1A865F;
height: 40px;padding: 10px 15px;">
<strong id="logo" style="color: white; font-size: 31px;
text-shadow: 1px 1px 1px #8F8888;">$company_name</strong>
</div>
<div id="content" style="padding: 10px 15px;">
<h2>$email_title</h2>
<p>
Thank you $customer_name for arranging an appointment with us.
Below you can see the appointment details. Click on the edit
link to make changes to your appointment.
</p>
<h2>Appointment Details</h2>
<table id="appointment-details">
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Service</td>
<td style="padding: 3px;">$appointment_service</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Provider</td>
<td style="padding: 3px;">$appointment_provider</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Date</td>
<td style="padding: 3px;">$appointment_date</td>
</tr>
<tr>
<td class="label" style="padding: 3px;font-weight: bold;">Duration</td>
<td style="padding: 3px;">$appointment_duration</td>
</tr>
</table>
<h2>Edit Link</h2>
<p>
Press the following link to make changes to your appointment reservation.
You are able to change the appointment details three hours before
the appointment.
</p>
<a href="$appointment_link" style="width: 600px;">$appointment_link</a>
</div>
<div id="footer" style="padding: 10px; text-align: center;
border-top: 1px solid #EEE;background: #FAFAFA;">
<a href="$company_link">$company_name</a> | Powered by Easy!Appointments
</div>
</div>
</body>
</html>