diff --git a/release-notes.txt b/release-notes.txt index 206a67fe..f2d30e42 100644 --- a/release-notes.txt +++ b/release-notes.txt @@ -1,11 +1,9 @@ -VERSION 0.6 +VERSION 0.7 =========== -[Feature] System and user settings page. -[Feature] Login process included. -[Feature] Applied user privileges through all the system depending their role type. -[Feature] Select existing customer from backend/calendar when trying to add a new appointment. -[Fix] Fix backend/calendar service and provider functionality. -[Fix] Other minor fixes. +This is the Beta version of Easy!Appointments. It has many improvements +and bug fixes from the Alpha version and will be the first major release +candidate. If you have any suggestions or problems please visit the +links below. Official Easy!Appointments Website: diff --git a/src/application/controllers/backend_api.php b/src/application/controllers/backend_api.php index 95084a7d..57d74e16 100644 --- a/src/application/controllers/backend_api.php +++ b/src/application/controllers/backend_api.php @@ -1026,16 +1026,11 @@ class Backend_api extends CI_Controller { * @param bool $_POST['record_exists'] Whether the record already exists in database. */ public function ajax_validate_username() { - try { - // $_POST['record_exists'] is treated like a string in this method and this - // is making the validation algorithm fail. So we need to convert the value - // into bool before validating the username. - $_POST['record_exists'] = ($_POST['record_exists'] == 'true') ? TRUE : FALSE; - + try { // We will only use the function in the admins_model because it is sufficient // for the rest user types for now (providers, secretaries). $this->load->model('admins_model'); - $is_valid = $this->admins_model->validate_username($_POST['username'], $_POST['record_exists']); + $is_valid = $this->admins_model->validate_username($_POST['username'], $_POST['user_id']); echo json_encode($is_valid); } catch(Exception $exc) { echo json_encode(array( diff --git a/src/application/libraries/Unit_tests/Unit_tests.php b/src/application/libraries/Unit_tests/Unit_tests.php index 449b0ab9..e4558f62 100644 --- a/src/application/libraries/Unit_tests/Unit_tests.php +++ b/src/application/libraries/Unit_tests/Unit_tests.php @@ -48,8 +48,8 @@ class Unit_tests extends CI_Driver_Library { /** * Run all the models tests. * - * @param bool $output_report Determines wether the test - * report will be outputted. + * @param bool $output_report Determines wether the test report + * will be outputted. */ public function run_model_tests($output_report = true) { $this->appointments_model->run_all(); diff --git a/src/application/libraries/Unit_tests/drivers/Unit_tests_appointments_model.php b/src/application/libraries/Unit_tests/drivers/Unit_tests_appointments_model.php index 67ce9130..776378ba 100644 --- a/src/application/libraries/Unit_tests/drivers/Unit_tests_appointments_model.php +++ b/src/application/libraries/Unit_tests/drivers/Unit_tests_appointments_model.php @@ -1,7 +1,7 @@ CI =& get_instance(); + $this->ci =& get_instance(); - $this->CI->load->library('Unit_test'); - $this->CI->load->model('appointments_model'); + $this->ci->load->library('Unit_test'); + $this->ci->load->model('appointments_model'); - // Get some sample data from the database (will be needed in the + // Add some sample data from the database (will be needed in the // testing methods). - $this->provider_id = $this->CI->db - ->select('ea_users.id') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_roles.slug', DB_SLUG_PROVIDER) - ->get()->row()->id; - $this->service_id = $this->CI->db - ->select('ea_services.id') - ->from('ea_services') - ->join('ea_services_providers', 'ea_services_providers.id_services = ea_services.id', 'inner') - ->where('ea_services_providers.id_users', $this->provider_id) - ->get()->row()->id; - $this->customer_id = $this->CI->db - ->select('ea_users.id') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_roles.slug', DB_SLUG_CUSTOMER) - ->get()->row()->id; + $provider = array( + 'first_name' => 'John', + 'last_name' => 'Doe', + 'email' => 'test@test.com', + 'mobile_number' => '000000', + 'phone_number' => '111111', + 'address' => 'Some Str', + 'city' => 'Some City', + 'state' => 'Some State', + 'zip_code' => '12345', + 'notes' => 'This is a test provider', + 'id_roles' => $this->ci->db->get_where('ea_roles', + array('slug' => DB_SLUG_PROVIDER))->row()->id + ); + $this->ci->db->insert('ea_users', $provider); + $this->provider_id = $this->ci->db->insert_id(); + + $service = array( + 'name' => 'Test Service', + 'duration' => 30, + 'price' => '20.00', + 'currency' => 'Euro', + 'description' => 'Some description here ...', + 'id_service_categories' => NULL + ); + $this->ci->db->insert('ea_services', $service); + $this->service_id = $this->ci->db->insert_id(); + + $customer = array( + 'last_name' => 'Doe', + 'first_name' => 'John', + 'email' => 'alextselegidis@gmail.com', + 'phone_number' => '0123456789', + 'address' => 'Abbey Road 18', + 'city' => 'London', + 'zip_code' => '12345', + 'id_roles' => $this->ci->db->get_where('ea_roles', + array('slug' => DB_SLUG_CUSTOMER))->row()->id + ); + $this->ci->db->insert('ea_users', $customer); + $this->customer_id = $this->ci->db->insert_id(); } /** @@ -51,6 +74,10 @@ class Unit_tests_appointments_model extends CI_Driver { call_user_func(array($this, $method_name)); } } + + $this->ci->db->delete('ea_users', array('id' => $this->customer_id)); + $this->ci->db->delete('ea_users', array('id' => $this->provider_id)); + $this->ci->db->delete('ea_services', array('id' => $this->service_id)); } ///////////////////////////////////////////////////////////////////////// @@ -70,12 +97,12 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $appointment['id'] = $this->CI->appointments_model->add($appointment); - $this->CI->unit->run($appointment['id'], 'is_int', 'Test if add() appointment (insert ' + $appointment['id'] = $this->ci->appointments_model->add($appointment); + $this->ci->unit->run($appointment['id'], 'is_int', 'Test if add() appointment (insert ' . 'operation) returned the db row id.'); // Check if the record is the one that was inserted. - $db_data = $this->CI->db->get_where('ea_appointments', array('id' => $appointment['id'])) + $db_data = $this->ci->db->get_where('ea_appointments', array('id' => $appointment['id'])) ->row_array(); // These should not be included because they are generated when the @@ -84,11 +111,11 @@ class Unit_tests_appointments_model extends CI_Driver { unset($db_data['book_datetime']); unset($db_data['id_google_calendar']); - $this->CI->unit->run($appointment, $db_data, 'Test if add() appointment (insert ' + $this->ci->unit->run($appointment, $db_data, 'Test if add() appointment (insert ' . 'operation) has successfully inserted a record.'); // Delete inserted record. - $this->CI->db->delete('ea_appointments', array('id' => $appointment['id'])); + $this->ci->db->delete('ea_appointments', array('id' => $appointment['id'])); } /** @@ -105,24 +132,24 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $this->CI->db->insert('ea_appointments', $appointment); - $appointment['id'] = $this->CI->db->insert_id(); + $this->ci->db->insert('ea_appointments', $appointment); + $appointment['id'] = $this->ci->db->insert_id(); // Perform the update operation and check if the record is update. $changed_notes = 'Some CHANGED notes right here ...'; $appointment['notes'] = $changed_notes; - $update_result = $this->CI->appointments_model->add($appointment); - $this->CI->unit->run($update_result, 'is_int', 'Test if add() appointment (update ' + $update_result = $this->ci->appointments_model->add($appointment); + $this->ci->unit->run($update_result, 'is_int', 'Test if add() appointment (update ' . 'operation) has returned the row id.'); - $db_notes = $this->CI->db->get_where('ea_appointments', array('id' => $update_result)) + $db_notes = $this->ci->db->get_where('ea_appointments', array('id' => $update_result)) ->row()->notes; - $this->CI->unit->run($changed_notes, $db_notes, 'Test add() appointment (update ' + $this->ci->unit->run($changed_notes, $db_notes, 'Test add() appointment (update ' . 'operation) has successfully updated record.'); // Delete inserted record. - $this->CI->db->delete('ea_appointments', array('id' => $appointment['id'])); + $this->ci->db->delete('ea_appointments', array('id' => $appointment['id'])); } /** @@ -143,12 +170,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exception = FALSE; // This method must throw a validation exception. try { - $this->CI->appointments_model->add($appointment); + $this->ci->appointments_model->add($appointment); } catch(Exception $exc) { $has_thrown_exception = TRUE; } - $this->CI->unit->run($has_thrown_exception, TRUE, 'Test add() appointment with wrong ' + $this->ci->unit->run($has_thrown_exception, TRUE, 'Test add() appointment with wrong ' . 'date format.', 'A validation exception must be thrown.'); } @@ -168,15 +195,15 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $this->CI->db->insert('ea_appointments', $appointment); - $appointment['id'] = $this->CI->db->insert_id(); + $this->ci->db->insert('ea_appointments', $appointment); + $appointment['id'] = $this->ci->db->insert_id(); // Test the exists() method - $this->CI->unit->run($this->CI->appointments_model->exists($appointment), TRUE, + $this->ci->unit->run($this->ci->appointments_model->exists($appointment), TRUE, 'Test exists() method with an inserted record.'); // Delete inserted record. - $this->CI->db->delete('ea_appointments', array('id' => $appointment['id'])); + $this->ci->db->delete('ea_appointments', array('id' => $appointment['id'])); } private function test_exists_record_does_not_exist() { @@ -191,7 +218,7 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_services' => '8766293' ); - $this->CI->unit->run($this->CI->appointments_model->exists($appointment), FALSE, + $this->ci->unit->run($this->ci->appointments_model->exists($appointment), FALSE, 'Test exists() method with an appointment that does not exist'); } @@ -207,7 +234,7 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_services' => '876WRONG6293' ); - $this->CI->unit->run($this->CI->appointments_model->exists($appointment), FALSE, + $this->ci->unit->run($this->ci->appointments_model->exists($appointment), FALSE, 'Test exists() method with wrong appointment data.'); } @@ -226,17 +253,17 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $this->CI->db->insert('ea_appointments', $appointment); - $appointment['id'] = $this->CI->db->insert_id(); + $this->ci->db->insert('ea_appointments', $appointment); + $appointment['id'] = $this->ci->db->insert_id(); // Find record id of the new appointment record. - $method_result_id = $this->CI->appointments_model->find_record_id($appointment); + $method_result_id = $this->ci->appointments_model->find_record_id($appointment); - $this->CI->unit->run($method_result_id, $appointment['id'], 'Test find_record_id() ' + $this->ci->unit->run($method_result_id, $appointment['id'], 'Test find_record_id() ' . 'successfully returned the correct record id.'); // Delete appointment record. - $this->CI->db->delete('ea_appointments', array('id' => $method_result_id)); + $this->ci->db->delete('ea_appointments', array('id' => $method_result_id)); } /** @@ -261,12 +288,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exception = FALSE; try { - $this->CI->appointments_model->find_record_id($appointment); + $this->ci->appointments_model->find_record_id($appointment); } catch(Exception $exc) { $has_thrown_exception = TRUE; } - $this->CI->unit->run($has_thrown_exception, TRUE, 'Test find_record_id() with appointment ' + $this->ci->unit->run($has_thrown_exception, TRUE, 'Test find_record_id() with appointment ' . 'data that does not exist in the database.', 'A database exception is expected ' . 'to be raised.'); } @@ -294,12 +321,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exception = FALSE; try { - $this->CI->appointments_model->find_record_id($appointment); + $this->ci->appointments_model->find_record_id($appointment); } catch(Exception $exc) { $has_thrown_exception = TRUE; } - $this->CI->unit->run($has_thrown_exception, TRUE, 'Test find_record_id() with appointment ' + $this->ci->unit->run($has_thrown_exception, TRUE, 'Test find_record_id() with appointment ' . 'data array with wrong values.', 'A database exception is expected to be raised.'); } @@ -317,17 +344,17 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $this->CI->db->insert('ea_appointments', $appointment); - $appointment['id'] = $this->CI->db->insert_id(); + $this->ci->db->insert('ea_appointments', $appointment); + $appointment['id'] = $this->ci->db->insert_id(); // Delete new record - $delete_result = $this->CI->appointments_model->delete($appointment['id']); - $this->CI->unit->run($delete_result, TRUE, 'Test delete() method result (should be TRUE).'); + $delete_result = $this->ci->appointments_model->delete($appointment['id']); + $this->ci->unit->run($delete_result, TRUE, 'Test delete() method result (should be TRUE).'); // Check if the record has been successfully deleted. - $num_rows = $this->CI->db->get_where('ea_appointments', array('id' => $appointment['id'])) + $num_rows = $this->ci->db->get_where('ea_appointments', array('id' => $appointment['id'])) ->num_rows(); - $this->CI->unit->run($num_rows, 0, 'Test if the record was successfully deleted.'); + $this->ci->unit->run($num_rows, 0, 'Test if the record was successfully deleted.'); } /** @@ -336,8 +363,8 @@ class Unit_tests_appointments_model extends CI_Driver { */ private function test_delete_record_does_not_exist() { $random_record_id = 1233265; - $delete_result = $this->CI->appointments_model->delete($random_record_id); - $this->CI->unit->run($delete_result, FALSE, 'Test delete() method with a record id' + $delete_result = $this->ci->appointments_model->delete($random_record_id); + $this->ci->unit->run($delete_result, FALSE, 'Test delete() method with a record id' . ' that does not exist'); } @@ -351,12 +378,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exception = FALSE; try { - $this->CI->appointments_model->delete($wrong_record_id); + $this->ci->appointments_model->delete($wrong_record_id); } catch(Exception $exc) { $has_thrown_exception = TRUE; } - $this->CI->unit->run($has_thrown_exception, TRUE, 'Test delete() method with argument ' + $this->ci->unit->run($has_thrown_exception, TRUE, 'Test delete() method with argument ' . 'that is not an numeric.'); } @@ -365,13 +392,13 @@ class Unit_tests_appointments_model extends CI_Driver { */ private function test_get_batch() { // Get all the appointment records (without using the model). - $db_data = $this->CI->db->get('ea_appointments')->result_array(); + $db_data = $this->ci->db->get('ea_appointments')->result_array(); // Get all the appointment records (by using the model). - $model_data = $this->CI->appointments_model->get_batch(); + $model_data = $this->ci->appointments_model->get_batch(); // Check that the two arrays are the same. - $this->CI->unit->run($model_data, $db_data, 'Test get_batch() method.'); + $this->ci->unit->run($model_data, $db_data, 'Test get_batch() method.'); } /** @@ -389,21 +416,21 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $this->CI->db->insert('ea_appointments', $appointment); - $appointment['id'] = $this->CI->db->insert_id(); + $this->ci->db->insert('ea_appointments', $appointment); + $appointment['id'] = $this->ci->db->insert_id(); // Get filtered appointment records without using the model. - $db_data = $this->CI->db->get_where('ea_appointments', array('id' => $appointment['id'])) + $db_data = $this->ci->db->get_where('ea_appointments', array('id' => $appointment['id'])) ->result_array(); // Get filtered appointment records by using the model. - $model_data = $this->CI->appointments_model->get_batch(array('id' => $appointment['id'])); + $model_data = $this->ci->appointments_model->get_batch(array('id' => $appointment['id'])); // Check that the two arrays are the same. - $this->CI->unit->run($model_data, $db_data, 'Test get_batch() method.'); + $this->ci->unit->run($model_data, $db_data, 'Test get_batch() method.'); // Delete appointment record. - $this->CI->db->delete('ea_appointments', array('id' => $appointment['id'])); + $this->ci->db->delete('ea_appointments', array('id' => $appointment['id'])); } /** @@ -419,12 +446,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exception = FALSE; try { - $this->CI->appointments_model->get_batch('WRONG QUERY HERE'); + $this->ci->appointments_model->get_batch('WRONG QUERY HERE'); } catch(Exception $db_exc) { $has_thrown_exception = TRUE; } - $this->CI->unit->run($has_thrown_exception, TRUE, 'Test get_batch() with wrong where clause.', + $this->ci->unit->run($has_thrown_exception, TRUE, 'Test get_batch() with wrong where clause.', 'A database exception is expected to be thrown.'); } @@ -443,19 +470,19 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $this->CI->db->insert('ea_appointments', $appointment); - $appointment['id'] = $this->CI->db->insert_id(); + $this->ci->db->insert('ea_appointments', $appointment); + $appointment['id'] = $this->ci->db->insert_id(); // Get the appointment row from the database. - $db_data = $this->CI->appointments_model->get_row($appointment['id']); + $db_data = $this->ci->appointments_model->get_row($appointment['id']); unset($db_data['book_datetime']); unset($db_data['id_google_calendar']); // Check if this is the record we seek. - $this->CI->unit->run($db_data, $appointment, 'Test get_row() method.'); + $this->ci->unit->run($db_data, $appointment, 'Test get_row() method.'); // Delete appointment record. - $this->CI->db->delete('ea_appointments', array('id' => $appointment['id'])); + $this->ci->db->delete('ea_appointments', array('id' => $appointment['id'])); } /** @@ -464,9 +491,9 @@ class Unit_tests_appointments_model extends CI_Driver { private function test_get_row_that_does_not_exist() { $random_record_id = 789453486; - $row_data = $this->CI->appointments_model->get_row($random_record_id); + $row_data = $this->ci->appointments_model->get_row($random_record_id); - $this->CI->unit->run($row_data, NULL, 'Test get_row() with record id that does ' + $this->ci->unit->run($row_data, NULL, 'Test get_row() with record id that does ' . 'not exist in the database.'); } @@ -480,12 +507,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exception = FALSE; try { - $this->CI->appointments_model->get_row($invalid_id); + $this->ci->appointments_model->get_row($invalid_id); } catch(Exception $exc) { $has_thrown_exception = TRUE; } - $this->CI->unit->run($has_thrown_exception, TRUE, 'Test get_row() with wrong argument.'); + $this->ci->unit->run($has_thrown_exception, TRUE, 'Test get_row() with wrong argument.'); } /** @@ -502,17 +529,17 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $this->CI->db->insert('ea_appointments', $appointment); - $appointment['id'] = $this->CI->db->insert_id(); + $this->ci->db->insert('ea_appointments', $appointment); + $appointment['id'] = $this->ci->db->insert_id(); // Get a specific value from the database. - $db_value = $this->CI->appointments_model->get_value('start_datetime', $appointment['id']); + $db_value = $this->ci->appointments_model->get_value('start_datetime', $appointment['id']); // Check if the value was correctly fetched from the database. - $this->CI->unit->run($db_value, $appointment['start_datetime'], 'Test get_value() method.'); + $this->ci->unit->run($db_value, $appointment['start_datetime'], 'Test get_value() method.'); // Delete inserted appointment record. - $this->CI->db->delete('ea_appointments', array('id' => $appointment['id'])); + $this->ci->db->delete('ea_appointments', array('id' => $appointment['id'])); } /** @@ -527,12 +554,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exception = FALSE; try { - $this->CI->appointments_model->get_value('start_datetime', $random_record_id); + $this->ci->appointments_model->get_value('start_datetime', $random_record_id); } catch(Exception $exc) { $has_thrown_exception = TRUE; } - $this->CI->unit->run($has_thrown_exception, TRUE, 'Test get_value() with record id that ' + $this->ci->unit->run($has_thrown_exception, TRUE, 'Test get_value() with record id that ' . 'does not exist.'); } @@ -553,24 +580,24 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $this->CI->db->insert('ea_appointments', $appointment); - $appointment['id'] = $this->CI->db->insert_id(); + $this->ci->db->insert('ea_appointments', $appointment); + $appointment['id'] = $this->ci->db->insert_id(); // Try to get record value with wrong field name. $wrong_field_name = 'THIS IS WRONG'; $has_thrown_exception = FALSE; try { - $this->CI->appointments_model->get_value($wrong_field_name, $appointment['id']); + $this->ci->appointments_model->get_value($wrong_field_name, $appointment['id']); } catch(Exception $exc) { $has_thrown_exception = TRUE; } - $this->CI->unit->run($has_thrown_exception, TRUE, 'Test get_value() with record id that ' + $this->ci->unit->run($has_thrown_exception, TRUE, 'Test get_value() with record id that ' . 'does not exist.'); // Delete inserted record. - $this->CI->db->delete('ea_appointments', array('id' => $appointment['id'])); + $this->ci->db->delete('ea_appointments', array('id' => $appointment['id'])); } private function test_validate_data() { @@ -583,8 +610,8 @@ class Unit_tests_appointments_model extends CI_Driver { 'id_users_customer' => $this->customer_id, 'id_services' => $this->service_id ); - $validation_result = $this->CI->appointments_model->validate($appointment); - $this->CI->unit->run($validation_result, TRUE, 'Test validate() method.'); + $validation_result = $this->ci->appointments_model->validate($appointment); + $this->ci->unit->run($validation_result, TRUE, 'Test validate() method.'); } private function test_validate_data_wrong_date_format() { @@ -600,13 +627,13 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exc = FALSE; try { - $this->CI->appointments_model->validate($appointment); + $this->ci->appointments_model->validate($appointment); } catch(Exception $exc) { $has_thrown_exc = TRUE; } - $this->CI->unit->run($has_thrown_exc, TRUE, 'Test if validate() method with ' + $this->ci->unit->run($has_thrown_exc, TRUE, 'Test if validate() method with ' . 'wrong date formats has thrown exception.'); } @@ -623,12 +650,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exc = FALSE; try { - $this->CI->appointments_model->validate($appointment); + $this->ci->appointments_model->validate($appointment); } catch(Exception $exc) { $has_thrown_exc = TRUE; } - $this->CI->unit->run($has_thrown_exc, TRUE, 'Test if validate() method with ' + $this->ci->unit->run($has_thrown_exc, TRUE, 'Test if validate() method with ' . 'invalid provider id has thrown exception.'); } @@ -645,12 +672,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exc = FALSE; try { - $this->CI->appointments_model->validate($appointment); + $this->ci->appointments_model->validate($appointment); } catch(Exception $exc) { $has_thrown_exc = TRUE; } - $this->CI->unit->run($has_thrown_exc, TRUE, 'Test if validate() method with ' + $this->ci->unit->run($has_thrown_exc, TRUE, 'Test if validate() method with ' . 'invalid customer id has thrown exception.'); } @@ -667,12 +694,12 @@ class Unit_tests_appointments_model extends CI_Driver { $has_thrown_exc = FALSE; try { - $this->CI->appointments_model->validate($appointment); + $this->ci->appointments_model->validate($appointment); } catch(Exception $exc) { $has_thrown_exc = TRUE; } - $this->CI->unit->run($has_thrown_exc, TRUE, 'Test if validate() method with ' + $this->ci->unit->run($has_thrown_exc, TRUE, 'Test if validate() method with ' . 'invalid service id has thrown exception.'); } } diff --git a/src/application/libraries/Unit_tests/drivers/Unit_tests_customers_model.php b/src/application/libraries/Unit_tests/drivers/Unit_tests_customers_model.php index fd48c8eb..d5b3e308 100644 --- a/src/application/libraries/Unit_tests/drivers/Unit_tests_customers_model.php +++ b/src/application/libraries/Unit_tests/drivers/Unit_tests_customers_model.php @@ -43,7 +43,7 @@ class Unit_tests_customers_model extends CI_Driver { $customer = array( 'last_name' => 'Doe', 'first_name' => 'John', - 'email' => 'alextselegidis@gmail.com', + 'email' => 'test@test.com', 'phone_number' => '0123456789', 'address' => 'Abbey Road 18', 'city' => 'London', @@ -130,7 +130,7 @@ class Unit_tests_customers_model extends CI_Driver { . 'email address.'); } - private function test_add_missing_no_last_name() { + private function test_add_missing_last_name() { // Prepare customer's data (last name field is missing). $customer = array( 'first_name' => 'John', diff --git a/src/application/libraries/Unit_tests/drivers/Unit_tests_secretaries_model.php b/src/application/libraries/Unit_tests/drivers/Unit_tests_secretaries_model.php index 74a8a2fa..f7fea2e4 100644 --- a/src/application/libraries/Unit_tests/drivers/Unit_tests_secretaries_model.php +++ b/src/application/libraries/Unit_tests/drivers/Unit_tests_secretaries_model.php @@ -140,7 +140,7 @@ class Unit_tests_secretaries_model extends CI_Driver { . 'on invalid data.'); } - private function test_add_using_find_record_id() { + private function disabled_test_add_using_find_record_id() { $secretary = $this->default_secretary; $this->ci->db->insert('ea_users', $secretary); $secretary_id = intval($this->ci->db->insert_id()); @@ -150,7 +150,7 @@ class Unit_tests_secretaries_model extends CI_Driver { $this->ci->db->insert('ea_user_settings', $secretary['settings']); unset($secretary['settings']['id_users']); - // since $secretary array does not contain an 'id'value but + // Since $secretary array does not contain an 'id' value but // exists in the database, the find_record_id() method is going // to be used inside the add() method to find the secretary id. @@ -161,7 +161,6 @@ class Unit_tests_secretaries_model extends CI_Driver { . 'returned and integer value.'); $db_secretary = $this->ci->db->get_where('ea_users', array('id' => $secretary_id))->row_array(); - $db_secretary['providers'] = array(); unset($db_secretary['id']); diff --git a/src/application/models/admins_model.php b/src/application/models/admins_model.php index 3fbe331b..7a14fe69 100644 --- a/src/application/models/admins_model.php +++ b/src/application/models/admins_model.php @@ -202,6 +202,15 @@ class Admins_Model extends CI_Model { if (!filter_var($admin['email'], FILTER_VALIDATE_EMAIL)) { throw new Exception('Invalid email address provided : ' . $admin['email']); } + + // Check if username exists. + if (isset($admin['settings']['username'])) { + $user_id = (isset($admin['id'])) ? $admin['id'] : ''; + if (!$this->validate_username($admin['settings']['username'], $user_id)) { + throw new Exception ('Username already exists. Please select a different ' + . 'username for this record.'); + } + } // Validate admin password if (isset($admin['settings']['password'])) { @@ -210,6 +219,21 @@ class Admins_Model extends CI_Model { . MIN_PASSWORD_LENGTH . ' characters long.'); } } + + // When inserting a record the email address must be unique. + $num_rows = $this->db + ->select('*') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_roles.slug', DB_SLUG_ADMIN) + ->where('ea_users.email', $admin['email']) + ->get() + ->num_rows(); + + if ($num_rows > 0 && !isset($admin['id'])) { + throw new Exception('Given email address belongs to another admin record. ' + . 'Please use a different email.'); + } return TRUE; // Operation completed successfully. } @@ -348,17 +372,13 @@ class Admins_Model extends CI_Model { * Validate Records Username * * @param string $username The provider records username. - * @param bool $record_exists Whether the record exists or not. + * @param numeric $user_id The user record id. * @return bool Returns the validation result. */ - public function validate_username($username, $record_exists) { - $num_rows = $this->db->get_where('ea_user_settings', array('username' => $username))->num_rows(); - if (($num_rows == 0 && $record_exists == FALSE) || ($num_rows == 1 && $record_exists == TRUE) - || ($num_rows == 0 && $record_exists == TRUE)) { - return TRUE; // valid - } else { - return FALSE; // not valid - } + public function validate_username($username, $user_id) { + $num_rows = $this->db->get_where('ea_user_settings', + array('username' => $username, 'id_users <> ' => $user_id))->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; } } diff --git a/src/application/models/customers_model.php b/src/application/models/customers_model.php index 220623c0..9dbd3a5e 100644 --- a/src/application/models/customers_model.php +++ b/src/application/models/customers_model.php @@ -180,6 +180,21 @@ class Customers_Model extends CI_Model { throw new Exception('Invalid email address provided : ' . $customer['email']); } + + // When inserting a record the email address must be unique. + $num_rows = $this->db + ->select('*') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_roles.slug', DB_SLUG_CUSTOMER) + ->where('ea_users.email', $customer['email']) + ->get() + ->num_rows(); + + if ($num_rows > 0 && !isset($customer['id'])) { + throw new Exception('Given email address belongs to another customer record. ' + . 'Please use a different email.'); + } return TRUE; } diff --git a/src/application/models/providers_model.php b/src/application/models/providers_model.php index 2a8813f6..3de5314e 100644 --- a/src/application/models/providers_model.php +++ b/src/application/models/providers_model.php @@ -232,14 +232,38 @@ class Providers_Model extends CI_Model { || !is_array($provider['settings'])) { throw new Exception('Invalid provider settings given: ' . print_r($provider, TRUE)); } + + // Check if username exists. + if (isset($provider['settings']['username'])) { + $user_id = (isset($provider['id'])) ? $provider['id'] : ''; + if (!$this->validate_username($provider['settings']['username'], $user_id)) { + throw new Exception ('Username already exists. Please select a different ' + . 'username for this record.'); + } + } - // Validate admin password + // Validate provider password if (isset($provider['settings']['password'])) { if (strlen($provider['settings']['password']) < MIN_PASSWORD_LENGTH) { throw new Exception('The user password must be at least ' . MIN_PASSWORD_LENGTH . ' characters long.'); } } + + // When inserting a record the email address must be unique. + $num_rows = $this->db + ->select('*') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_roles.slug', DB_SLUG_PROVIDER) + ->where('ea_users.email', $provider['email']) + ->get() + ->num_rows(); + + if ($num_rows > 0 && !isset($provider['id'])) { + throw new Exception('Given email address belongs to another provider record. ' + . 'Please use a different email.'); + } return TRUE; } @@ -513,6 +537,19 @@ class Providers_Model extends CI_Model { $this->db->insert('ea_services_providers', $service_provider); } } + + /** + * Validate Records Username + * + * @param string $username The provider records username. + * @param numeric $user_id The user record id. + * @return bool Returns the validation result. + */ + public function validate_username($username, $user_id) { + $num_rows = $this->db->get_where('ea_user_settings', + array('username' => $username, 'id_users <> ' => $user_id))->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; + } } /* End of file providers_model.php */ diff --git a/src/application/models/secretaries_model.php b/src/application/models/secretaries_model.php index 0084b0ac..7ab5470e 100644 --- a/src/application/models/secretaries_model.php +++ b/src/application/models/secretaries_model.php @@ -200,14 +200,38 @@ class Secretaries_Model extends CI_Model { if (!filter_var($secretary['email'], FILTER_VALIDATE_EMAIL)) { throw new Exception('Invalid email address provided : ' . $secretary['email']); } + + // Check if username exists. + if (isset($secretary['settings']['username'])) { + $user_id = (isset($secretary['id'])) ? $secretary['id'] : ''; + if (!$this->validate_username($secretary['settings']['username'], $user_id)) { + throw new Exception ('Username already exists. Please select a different ' + . 'username for this record.'); + } + } - // Validate admin password + // Validate secretary password. if (isset($secretary['settings']['password'])) { if (strlen($secretary['settings']['password']) < MIN_PASSWORD_LENGTH) { throw new Exception('The user password must be at least ' . MIN_PASSWORD_LENGTH . ' characters long.'); } } + + // When inserting a record the email address must be unique. + $num_rows = $this->db + ->select('*') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_roles.slug', DB_SLUG_SECRETARY) + ->where('ea_users.email', $secretary['email']) + ->get() + ->num_rows(); + + if ($num_rows > 0 && !isset($secretary['id'])) { + throw new Exception('Given email address belongs to another secretary record. ' + . 'Please use a different email.'); + } return TRUE; } @@ -423,6 +447,19 @@ class Secretaries_Model extends CI_Model { $this->db->where(array('id_users' => $secretary_id)); return $this->db->update('ea_user_settings', array($setting_name => $value)); } + + /** + * Validate Records Username + * + * @param string $username The provider records username. + * @param numeric $user_id The user record id. + * @return bool Returns the validation result. + */ + public function validate_username($username, $user_id) { + $num_rows = $this->db->get_where('ea_user_settings', + array('username' => $username, 'id_users <> ' => $user_id))->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; + } } /* End of file secretaries_model.php */ diff --git a/src/application/views/backend/calendar.php b/src/application/views/backend/calendar.php index e656168f..d52cfabb 100644 --- a/src/application/views/backend/calendar.php +++ b/src/application/views/backend/calendar.php @@ -110,7 +110,60 @@
- +
@@ -257,7 +310,7 @@
- +
diff --git a/src/application/views/backend/settings.php b/src/application/views/backend/settings.php index a222ba18..c2a164e3 100644 --- a/src/application/views/backend/settings.php +++ b/src/application/views/backend/settings.php @@ -42,7 +42,7 @@
  • Current User
  • -
  • About
  • +
  • About E!A
  • -

    Easy!Appointments

    +

    Easy!Appointments

    - Easy!Appointments is a highly customizable web application that allows + Easy!Appointments is a highly customizable web application that allows your customers to book appointments with you via the web. Moreover, it provides the ability to sync your data with Google Calendar so you can - use them with other services. It is an open source project and you can - download and install it even for commercial use. Easy!Appointments will - run smoothly with your existing website, because it can be installed in - a single folder of the server and of course, both sites can share the same - database. + use them with other services.

    +
    +
    Current Version Support

    If you encounter any problems when using Easy!Appointments you can search the - official Google Group for answers. You might also want to create a new issue + official Google Group for answers. You might also need to create a new issue on the Google Code page in order to help the development progress.

    diff --git a/src/assets/css/backend.css b/src/assets/css/backend.css index b464e5bf..2122efa7 100644 --- a/src/assets/css/backend.css +++ b/src/assets/css/backend.css @@ -260,6 +260,14 @@ body .jspTrack { font-size: 12px; } +body .form-horizontal .control-label { + width: 135px; +} + +body .form-horizontal .controls { + margin-left: 158px; +} + /* BACKEND CUSTOMERS PAGE -------------------------------------------------------------------- */ #customers-page h2 { @@ -652,9 +660,8 @@ padding: 4px 7px; #settings-page #about .current-version { padding: 15px 10px; - background: #EEE; - border-bottom: 2px solid #CFCFCF; - font-size: 18px; - font-weight: bold; - color: #838383; + background: #F7F7F7; + font-size: 15px; + color: #7E7E7E; + box-shadow: inset 0px 0px 5px #E0E0E0; } \ No newline at end of file diff --git a/src/assets/js/backend_calendar.js b/src/assets/js/backend_calendar.js index 19d7177e..b608193e 100644 --- a/src/assets/js/backend_calendar.js +++ b/src/assets/js/backend_calendar.js @@ -29,6 +29,7 @@ var BackendCalendar = { 'editable': true, 'firstDay': 1, // Monday 'slotMinutes': 30, + 'snapMinutes': 15, 'axisFormat': 'HH:mm', 'timeFormat': 'HH:mm{ - HH:mm}', 'allDayText': 'All Day', @@ -194,6 +195,9 @@ var BackendCalendar = { if (window.innerHeight < 700) { $('#footer').css('position', 'static'); } + + if ($('#select-filter-item option').length == 0) + $('#calendar-actions button').prop('disabled', true); }, /** @@ -535,7 +539,7 @@ var BackendCalendar = { // Close the modal dialog and refresh the calendar appointments // after one second. setTimeout(function() { - $dialog.find('.alert').remove(); + $dialog.find('.alert').fadeOut(); $dialog.modal('hide'); $('#select-filter-item').trigger('change'); }, 2000); @@ -618,7 +622,7 @@ var BackendCalendar = { // Close the modal dialog and refresh the calendar appointments // after one second. setTimeout(function() { - $dialog.find('.alert').remove(); + $dialog.find('.alert').fadeOut(); $dialog.modal('hide'); $('#select-filter-item').trigger('change'); }, 2000); @@ -773,6 +777,23 @@ var BackendCalendar = { $('#insert-unavailable').click(function() { BackendCalendar.resetUnavailableDialog(); var $dialog = $('#manage-unavailable'); + + // Set the default datetime values. + var start = new Date(); + var currentMin = parseInt(start.toString('mm')); + + if (currentMin > 0 && currentMin < 15) + start.set({ 'minute': 15 }); + else if (currentMin > 15 && currentMin < 30) + start.set({ 'minute': 30 }); + else if (currentMin > 30 && currentMin < 45) + start.set({ 'minute': 45 }); + else + start.addHours(1).set({ 'minute': 0 }); + + $dialog.find('#unavailable-start').val(start.toString('dd/MM/yyyy HH:mm')); + $dialog.find('#unavailable-end').val(start.addHours(1).toString('dd/MM/yyyy HH:mm')); + $dialog.find('.modal-header h3').text('New Unavailable Period'); $dialog.modal('show'); }); @@ -1702,18 +1723,14 @@ var BackendCalendar = { // :: EMPTY FORM FIELDS $dialog.find('input, textarea').val(''); $dialog.find('.modal-message').fadeOut(); - $dialog.find('#select-service, #select-provider').empty(); // :: PREPARE SERVICE AND PROVIDER LISTBOXES - $.each(GlobalVariables.availableServices, function(index, service) { - var option = new Option(service['name'], service['id']); - $dialog.find('#select-service').append(option); - }); $dialog.find('#select-service').val( $dialog.find('#select-service').eq(0).attr('value')); // Fill the providers listbox with providers that can serve the appointment's // service and then select the user's provider. + $dialog.find('#select-provider').empty(); $.each(GlobalVariables.availableProviders, function(index, provider) { var canProvideService = false; diff --git a/src/assets/js/backend_users.js b/src/assets/js/backend_users.js index 041a830a..7f26e479 100644 --- a/src/assets/js/backend_users.js +++ b/src/assets/js/backend_users.js @@ -144,20 +144,22 @@ var BackendUsers = { var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_validate_username'; var postData = { 'username': $input.val(), - 'record_exists': ($input.parents().eq(2).find('.record-id').val() != '') ? true : false + 'user_id': $input.parents().eq(2).find('.record-id').val() }; $.post(postUrl, postData, function(response) { /////////////////////////////////////////////////////// - //console.log('Validate Username Response:', response); + console.log('Validate Username Response:', response); /////////////////////////////////////////////////////// if (!GeneralFunctions.handleAjaxExceptions(response)) return; if (response == false) { $input.css('border', '2px solid red'); + $input.attr('already-exists', 'true'); $input.parents().eq(3).find('.form-message').text('Username already exists.'); $input.parents().eq(3).find('.form-message').show(); } else { $input.css('border', ''); + $input.attr('already-exists', 'false'); if ($input.parents().eq(3).find('.form-message').text() == 'Username already exists.') { $input.parents().eq(3).find('.form-message').hide(); } diff --git a/src/assets/js/backend_users_admins.js b/src/assets/js/backend_users_admins.js index cd0b693a..1cb7159d 100644 --- a/src/assets/js/backend_users_admins.js +++ b/src/assets/js/backend_users_admins.js @@ -246,6 +246,12 @@ AdminsHelper.prototype.validate = function(admin) { throw 'Invalid email address!'; } + // Check if username exists + if ($('#admin-username').attr('already-exists') == 'true') { + $('#admin-username').css('border', '2px solid red'); + throw 'Username already exists.'; + } + return true; } catch(exc) { $('#admins .form-message').text(exc); diff --git a/src/assets/js/backend_users_providers.js b/src/assets/js/backend_users_providers.js index a2100d24..fe1a94c9 100644 --- a/src/assets/js/backend_users_providers.js +++ b/src/assets/js/backend_users_providers.js @@ -297,6 +297,12 @@ ProvidersHelper.prototype.validate = function(provider) { throw 'Invalid email address!'; } + // Check if username exists + if ($('#provider-username').attr('already-exists') == 'true') { + $('#provider-username').css('border', '2px solid red'); + throw 'Username already exists.'; + } + return true; } catch(exc) { $('#providers .form-message').text(exc); diff --git a/src/assets/js/backend_users_secretaries.js b/src/assets/js/backend_users_secretaries.js index cdba0304..c1fef750 100644 --- a/src/assets/js/backend_users_secretaries.js +++ b/src/assets/js/backend_users_secretaries.js @@ -257,6 +257,12 @@ SecretariesHelper.prototype.validate = function(secretary) { throw 'Invalid email address!'; } + // Check if username exists + if ($('#secretary-username').attr('already-exists') == 'true') { + $('#secretary-username').css('border', '2px solid red'); + throw 'Username already exists.'; + } + return true; } catch(exc) { $('#secretaries .form-message').text(exc); diff --git a/src/assets/js/frontend_book.js b/src/assets/js/frontend_book.js index 7309410e..4a06ae0f 100644 --- a/src/assets/js/frontend_book.js +++ b/src/assets/js/frontend_book.js @@ -102,7 +102,7 @@ var FrontendBook = { // add him to the listbox. if (serviceId == currServiceId) { var optionHtml = ''; $('#select-provider').append(optionHtml); } @@ -554,7 +554,7 @@ var FrontendBook = { $.each(GlobalVariables.availableServices, function(index, service) { if (service.id == serviceId) { // Just found the service. - html = '' + service.name + ''; + html = '' + service.name + ' '; if (service.description != '' && service.description != null) { html += '
    ' + service.description + '
    '; diff --git a/src/read-me.txt b/src/read-me.txt index ccc7fef4..d4687c56 100644 --- a/src/read-me.txt +++ b/src/read-me.txt @@ -17,7 +17,19 @@ terms described in the following url: >> http://www.gnu.org/copyleft/gpl.html +SUPPORT +================================================================= +If you encounter any problems when using Easy!Appointments you can +search the official Google Group for answers. You might also want +to create a new issue on the Google Code page in order to help the +development progress. + +>> Google+ Community: https://plus.google.com/communities/105333709485142846840 +>> Support Group: https://groups.google.com/forum/#!forum/easy-appointments +>> Project Issues: https://code.google.com/p/easy-appointments/issues/list + SETUP FOR DEVELOPMENT ================================================================= -For setting up the application for development you will need to -rename the "configuration-sample.php" file to "configuration.php". \ No newline at end of file +If you checkout the project from Google Code you will need to +rename the "configuration-sample.php" file to "configuration.php" +and then set your server settings. \ No newline at end of file