/** * Direct input testing. */ public function test__survey_respondents_import_check__direct() { /** * 2 valid */ $rows = array(); $rows[] = '1234'; $rows[] = '12345'; // From DB $db_call_tasks = array(); $respondents = self::$CI->_survey_respondents_import_check($rows, $db_call_tasks); $expect = array('valid' => array('1234', '12345'), 'dups' => array(), 'invalid' => array()); $this->assertEquals($expect, $respondents); /* ========================================================= */ /** * 3 invalid */ $rows = array(); $rows[] = '1889798 548'; $rows[] = '5484.0'; $rows[] = '8754984.'; // From DB $db_call_tasks = array(); $respondents = self::$CI->_survey_respondents_import_check($rows, $db_call_tasks); $expect = array('valid' => array(), 'dups' => array(), 'invalid' => array('1889798 548', '5484.0', '8754984.')); $this->assertEquals($expect, $respondents); /* ========================================================= */ /** * 3 valid * 1 dups * 5 invalid */ $rows = array(); $rows[] = '1234'; $rows[] = '12345'; $rows[] = '123456'; $rows[] = '12345'; $rows[] = '12e4'; $rows[] = '123409875,2134234'; $rows[] = ''; $rows[] = '1889798 548'; $rows[] = '5484.0'; $rows[] = '8754984.'; // From DB $db_call_tasks = array(); $respondents = self::$CI->_survey_respondents_import_check($rows, $db_call_tasks); $expect = array('valid' => array('1234', '12345', '123456'), 'dups' => array('12345'), 'invalid' => array('12e4', '123409875,2134234', '1889798 548', '5484.0', '8754984.')); $this->assertEquals($expect, $respondents); /* ========================================================= */ /** * 2 valid * 1 dups with file * 1 dup with db */ $rows = array(); $rows[] = '1234'; $rows[] = '12345'; $rows[] = '12345'; $rows[] = '999'; // From DB - Array or call_task_entities // Fake data. $db_call_tasks = array(); $db_call_tasks[] = Call_task_entity::build(array('number' => '999')); $db_call_tasks[] = Call_task_entity::build(array('number' => '998')); $db_call_tasks[] = Call_task_entity::build(array('number' => '997')); $respondents = self::$CI->_survey_respondents_import_check($rows, $db_call_tasks); $expect = array('valid' => array('1234', '12345'), 'dups' => array('12345', '999'), 'invalid' => array()); $this->assertEquals($expect, $respondents); /* ========================================================= */ }
/** * Assigns Call Tasks to user. (Reserves them) * * Mongodb doesn't support limit on updates and the assignment of call tasks * needs to be an atomic operation. For this the findAndModify command is * being used. * This is not a scalable solution, although is a valid one since the amount * of call tasks to assign won't be that high. * * @param int $sid * The survey id * @param int $uid * The user to who the call tasks are going to be assigned * @param int $amount * The amount of call tasks to assign. * * @return mixed * Array of Call_task_entity or FALSE if no call tasks available */ public function reserve($sid, $uid, $amount) { $sid = (int) $sid; $uid = (int) $uid; $call_tasks = array(); for ($i = 0; $i < $amount; $i++) { $result = $this->mongo_db->command(array('findAndModify' => self::COLLECTION, 'query' => array('survey_sid' => (int) $sid, 'assignee_uid' => NULL), 'update' => array('$set' => array('assigned' => Mongo_db::date(), 'updated' => Mongo_db::date(), 'assignee_uid' => (int) $uid)), 'new' => TRUE, 'sort' => array('created' => -1))); if (empty($result['value'])) { break; } $call_tasks[] = Call_task_entity::build($result['value']); } return empty($call_tasks) ? FALSE : $call_tasks; }
/** * Summary page to add respondents to a given survey. * @param $sid * * Route - /survey/:sid/respondents/(file|input) */ public function survey_respondents_add($sid, $type) { $survey = $this->survey_model->get($sid); if (!$survey) { show_404(); } else { if (!has_permission('manage respondents any survey')) { show_403(); } } if (!$survey->status_allows('import respondents any survey')) { show_403(); } // Form validation based on import type. switch ($type) { case 'file': // Config data for the file upload. $file_upload_config = array('upload_path' => '/tmp/', 'allowed_types' => 'csv', 'file_name' => 'respondents_' . md5(microtime(true))); // Load needed libraries. $this->load->library('upload', $file_upload_config); $this->form_validation->set_rules('survey_respondents_file', 'Respondents File', 'callback__cb_survey_respondents_add_file_handle'); break; case 'direct': $this->form_validation->set_rules('survey_respondents_text', 'Respondents Text', 'trim|required|xss_clean'); break; } $this->form_validation->set_error_delimiters('<small class="error">', '</small>'); // If the import has invalid respondents they are added to the textarea // to allow the user to correct them. $invalid_respondents = array(); if (isset($_SESSION['respondents_numbers']['invalid'])) { $invalid_respondents = $_SESSION['respondents_numbers']['invalid']; // Unset so they don't bother anymore. unset($_SESSION['respondents_numbers']); } // If no data submitted show the form. if ($this->form_validation->run() == FALSE) { $this->load->view('base/html_start'); $this->load->view('components/navigation', array('active_menu' => 'surveys')); $this->load->view('surveys/survey_respondents_add', array('survey' => $survey, 'import_type' => $type, 'invalid_respondents' => $invalid_respondents)); $this->load->view('base/html_end'); } else { // Processing based on import type. switch ($type) { case 'file': // Read file. $file = $this->input->post('survey_respondents_file'); if (isset($file['full_path'])) { // Load CSVReader library. $this->load->helper('csvreader'); $csv = new CSVReader(); $csv->separator = ','; $rows = $csv->parse_file($file['full_path']); } break; case 'direct': $rows = explode("\n", $this->input->post('survey_respondents_text')); break; } if (!isset($rows)) { Status_msg::error('An error occurred when processing the numbers. Try again.'); redirect($survey->get_url_respondents()); } // Load all call_tasks from DB to check for duplicates. $db_call_tasks = $this->call_task_model->get_all($sid); try { $respondents_numbers = $this->_survey_respondents_import_check($rows, $db_call_tasks); } catch (Exception $e) { Status_msg::error($e->getMessage()); redirect($survey->get_url_respondents()); } // Create a call_task for each respondent number. $success_saves = array(); foreach ($respondents_numbers['valid'] as $number) { // Prepare survey data to construct a new survey_entity $call_task_data = array(); $call_task_data['survey_sid'] = (int) $sid; $call_task_data['number'] = (string) $number; // Construct survey. $new_call_task = Call_task_entity::build($call_task_data); // Save call task. if ($this->call_task_model->save($new_call_task)) { $success_saves[] = $number; } else { // If an error occurred flag as invalid to be imported again. // This should not happen, but you never know. $respondents_numbers['invalid'][] = $number; } } $respondents_numbers['valid'] = $success_saves; // Setting messages. $total_valid = count($respondents_numbers['valid']); $total_invalid = count($respondents_numbers['invalid']); $total_dups = count($respondents_numbers['dups']); $total_numbers = $total_valid + $total_invalid + $total_dups; if ($total_valid) { Status_msg::success("{$total_valid} of {$total_numbers} respondents were successfully imported.", TRUE); } else { Status_msg::warning("No respondents were imported."); } if ($total_invalid) { Status_msg::error("{$total_invalid} of {$total_numbers} respondents were not in a valid format."); } if ($total_dups) { Status_msg::notice("{$total_dups} of {$total_numbers} respondents have duplicate phone numbers."); } // Store invalid in any. if ($total_invalid) { $_SESSION['respondents_numbers']['invalid'] = $respondents_numbers['invalid']; redirect($survey->get_url_respondents_add('direct')); } redirect($survey->get_url_respondents()); } }