diff --git a/application/config/constants.php b/application/config/constants.php index ef4cdaf2c..f21b6c962 100644 --- a/application/config/constants.php +++ b/application/config/constants.php @@ -31,6 +31,13 @@ define('EXIT_VALIDATION_UDF_NOT_VALID_VAL', 17); // UDF validation has been fail define('EXIT_AUTO_MIN', 1000); // lowest automatically-assigned error code define('EXIT_AUTO_MAX', 2000); // highest automatically-assigned error code +/* +|-------------------------------------------------------------------------- +| General purpose +|-------------------------------------------------------------------------- +*/ +define('BEGINNING_OF_TIME', '1970-01-01'); + /* |-------------------------------------------------------------------------- | Authentication constants diff --git a/application/config/jqm.php b/application/config/jqm.php new file mode 100644 index 000000000..43cc1c038 --- /dev/null +++ b/application/config/jqm.php @@ -0,0 +1,14 @@ + array( + 'admin:rw', + 'developer:rw' + ), + 'OEHPayment' => 'developer:rw', + 'SAPPayment' => 'developer:rw' +); + diff --git a/application/config/navigation.php b/application/config/navigation.php index a89c259ee..84004b58e 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -109,6 +109,13 @@ $config['navigation_header'] = array( 'expand' => true, 'sort' => 20, 'requiredPermissions' => 'system/developer:r' + ), + 'jobsqueueviewer' => array( + 'link' => site_url('system/jq/JobsQueueViewer'), + 'description' => 'Jobs Queue Viewer', + 'expand' => true, + 'sort' => 20, + 'requiredPermissions' => 'system/developer:r' ) ) ) diff --git a/application/controllers/system/LogsViewer.php b/application/controllers/system/LogsViewer.php index 8caf9f3a7..4e39db5e3 100644 --- a/application/controllers/system/LogsViewer.php +++ b/application/controllers/system/LogsViewer.php @@ -35,7 +35,7 @@ class LogsViewer extends Auth_Controller // Public methods /** - * Main page of the InfoCenter tool + * Everything has a beginning */ public function index() { diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php new file mode 100644 index 000000000..e72607675 --- /dev/null +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -0,0 +1,130 @@ + 'admin:r', + 'addNewJobsToQueue' => 'admin:rw', + 'updateJobsQueue' => 'admin:rw' + ) + ); + + // Loading config file jqm + $this->config->load('jqm'); + + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + // Loads permission lib + $this->load->library('PermissionLib'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * To get all the most recently added jobs using the given job type + */ + public function getLastJobs() + { + $type = $this->input->get(JobsQueueLib::PROPERTY_TYPE); + + $this->_checkPermissions($type); + + $this->outputJson($this->jobsqueuelib->getLastJobs($type)); + } + + /** + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects + */ + public function addNewJobsToQueue() + { + $type = $this->input->post(JobsQueueLib::PROPERTY_TYPE); + $jobs = $this->input->post(self::PARAM_JOBS); + + $this->_checkPermissions($type); + + // Otherwise convert jobs from json to php and call JobsQueueLib library + $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $this->_convertJobs($jobs))); + } + + /** + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects + */ + public function updateJobsQueue() + { + $type = $this->input->post(JobsQueueLib::PROPERTY_TYPE); + $jobs = $this->input->post(self::PARAM_JOBS); + + $this->_checkPermissions($type); + + // Otherwise convert jobs from json to php and call JobsQueueLib library + $this->outputJson($this->jobsqueuelib->updateJobsQueue($type, $this->_convertJobs($jobs))); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * + */ + private function _checkPermissions($type) + { + // Checks if the caller has the permissions to add new jobs with the given type in the queue + if (!$this->permissionlib->isEntitled($this->config->item(self::JOB_TYPE_PERMISSIONS_WHITE_LIST), $type)) + { + // Permissions NOT valid + $this->terminateWithJsonError('You are not allowed to access to this content'); + } + } + + /** + * + */ + private function _convertJobs($jobs) + { + if (isEmptyArray($jobs)) return null; // if not a valid array then return null + + $convertedJobsArray = array(); // returned values + + // Loops through all the provided jobs + foreach ($jobs as $job) + { + $tmpObj = json_decode($job); // Try to decode json to php + + // If decode was a success + if ($tmpObj != null) + { + $convertedJobsArray[] = $tmpObj; // then store the decoded object in the result array + } + else // otherwise + { + // Create a new object and store the error message in it + $tmpObj = new stdClass(); + $tmpObj->{JobsQueueLib::PROPERTY_ERROR} = 'A not valid json was provided'; + + $convertedJobsArray[] = $tmpObj; // store this object into the result array + } + } + + return $convertedJobsArray; + } +} diff --git a/application/controllers/system/jq/JobsQueueViewer.php b/application/controllers/system/jq/JobsQueueViewer.php new file mode 100644 index 000000000..2698d79d1 --- /dev/null +++ b/application/controllers/system/jq/JobsQueueViewer.php @@ -0,0 +1,51 @@ + 'system/developer:r' + ) + ); + + // Loads WidgetLib + $this->load->library('WidgetLib'); + + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + + // Loads phrases system + $this->loadPhrases( + array( + 'global', + 'ui', + 'filter' + ) + ); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Everything has a beginning + */ + public function index() + { + $this->load->view('system/jq/jobsQueueViewer.php'); + } +} diff --git a/application/core/JQW_Controller.php b/application/core/JQW_Controller.php new file mode 100644 index 000000000..ab63e7ffd --- /dev/null +++ b/application/core/JQW_Controller.php @@ -0,0 +1,129 @@ +load->library('LogLib', array( + 'classIndex' => 5, + 'functionIndex' => 5, + 'lineIndex' => 4, + 'dbLogType' => 'job', // required + 'dbExecuteUser' => 'Jobs queue system' + )); + + // Loads JobsQueueLib library + $this->load->library('JobsQueueLib'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Protected methods + + /** + * To get all the most recently added jobs using the given job type + */ + protected function getLastJobs($type) + { + $jobs = $this->jobsqueuelib->getLastJobs($type); + + // If an error occurred then log it in database + if (isError($jobs)) $this->logError(getError($jobs), $type); + + return $jobs; + } + + /** + * To get all the jobs specified by the given parameters + */ + protected function getJobsByTypeStatusInput($type, $status, $input) + { + $jobs = $this->jobsqueuelib->getJobsByTypeStatusInput($type, $status, $input); + + // If an error occurred then log it in database + if (isError($jobs)) $this->logError(getError($jobs), array($type, $status, $input)); + + return $jobs; + } + + /** + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects + */ + protected function addNewJobsToQueue($type, $jobs) + { + $result = $this->jobsqueuelib->addNewJobsToQueue($type, $jobs); + + // If an error occurred then log it in database + if (isError($result)) $this->logError(getError($result), $type); + + return $result; + } + + /** + * Updates jobs already present in the jobs queue + * jobs is an array of job objects + */ + protected function updateJobsQueue($type, $jobs) + { + $result = $this->jobsqueuelib->updateJobsQueue($type, $jobs); + + // If an error occurred then log it in database + if (isError($result)) $this->logError(getError($result), $type); + + return $result; + } + + /** + * Utility method to update the specified properties of the given jobs with the given values + */ + protected function updateJobs($jobs, $properties, $values) + { + // If not valid arrays of properties and values arrays are not of the same size then exit + if (isEmptyArray($jobs) || isEmptyArray($properties) || isEmptyArray($values)) return; + if (count($properties) != count($values)) return; + + // For each job + foreach ($jobs as $job) + { + // For each propery of the job + for ($pI = 0; $pI < count($properties); $pI++) + { + // If this property is present in the job object + if (property_exists($job, $properties[$pI])) + { + $job->{$properties[$pI]} = $values[$pI]; // set a new value + } + } + } + } + + /** + * Utility method to generate a job with the given parameters and return it inside an array + * ready to be used by addNewJobsToQueue and updateJobsQueue + */ + protected function generateJobs($status, $input) + { + $job = new stdClass(); + + $job->{JobsQueueLib::PROPERTY_STATUS} = $status; + $job->{JobsQueueLib::PROPERTY_INPUT} = $input; + + return array($job); + } +} + diff --git a/application/libraries/FilterWidgetLib.php b/application/libraries/FilterWidgetLib.php index 6e87833bd..f909c7083 100644 --- a/application/libraries/FilterWidgetLib.php +++ b/application/libraries/FilterWidgetLib.php @@ -93,6 +93,7 @@ class FilterWidgetLib const OP_NOT_SET = 'nset'; // Filter options values + const OPT_HOURS = 'hours'; const OPT_DAYS = 'days'; const OPT_MONTHS = 'months'; @@ -884,7 +885,8 @@ class FilterWidgetLib // It it's a date type if (is_numeric($filterDefinition->condition) && isset($filterDefinition->option) - && ($filterDefinition->option == self::OPT_DAYS + && ($filterDefinition->option == self::OPT_HOURS + || $filterDefinition->option == self::OPT_DAYS || $filterDefinition->option == self::OPT_MONTHS)) { $condition = '< (NOW() - \''.$filterDefinition->condition.' '.$filterDefinition->option.'\'::interval)'; @@ -899,7 +901,8 @@ class FilterWidgetLib // It it's a date type if (is_numeric($filterDefinition->condition) && isset($filterDefinition->option) - && ($filterDefinition->option == self::OPT_DAYS + && ($filterDefinition->option == self::OPT_HOURS + || $filterDefinition->option == self::OPT_DAYS || $filterDefinition->option == self::OPT_MONTHS)) { $condition = '> (NOW() - \''.$filterDefinition->condition.' '.$filterDefinition->option.'\'::interval)'; diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php new file mode 100644 index 000000000..0eb7c9b72 --- /dev/null +++ b/application/libraries/JobsQueueLib.php @@ -0,0 +1,370 @@ +_ci =& get_instance(); + + // Loads all needed models + $this->_ci->load->model('system/JobsQueue_model', 'JobsQueueModel'); + $this->_ci->load->model('system/JobTypes_model', 'JobTypesModel'); + $this->_ci->load->model('system/JobStatuses_model', 'JobStatusesModel'); + $this->_ci->load->model('system/JobTriggers_model', 'JobTriggersModel'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * To get all the most recently added jobs using the given job type + */ + public function getLastJobs($type) + { + $this->_ci->JobsQueueModel->resetQuery(); + + $this->_ci->JobsQueueModel->addOrder('creationtime', 'DESC'); + + return $this->_ci->JobsQueueModel->loadWhere(array('status' => self::STATUS_NEW, 'type' => $type)); + } + + /** + * To get all the jobs specified by the given parameters + */ + public function getJobsByTypeStatusInput($type, $status, $input) + { + $this->_ci->JobsQueueModel->resetQuery(); + + $this->_ci->JobsQueueModel->addOrder('creationtime', 'DESC'); + + return $this->_ci->JobsQueueModel->loadWhere(array('status' => $status, 'type' => $type, 'input' => $input)); + } + + /** + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects + */ + public function addNewJobsToQueue($type, $jobs) + { + // Checks parameters + if (isEmptyString($type)) return error('The provided type parameter is not a valid string'); + if (isEmptyArray($jobs)) return error('The provided jobs parameter is not a valid array'); + + // Get all the job types + $dbResult = $this->_ci->JobTypesModel->load(); + if (isError($dbResult)) return $dbResult; + $types = getData($dbResult); + + // If the given type is not present in database + if (!$this->_checkJobType($type, $types)) return error('The provided type parameter is not valid'); + + $results = $jobs; // returned values + $errorOccurred = false; // very optimistic + + // Get all the job statuses + $dbResult = $this->_ci->JobStatusesModel->load(); + if (isError($dbResult)) return $dbResult; + $statuses = getData($dbResult); + + // Loops through all the provided jobs + foreach ($results as $job) + { + // If the structure of the job object is valid AND the type is valid AND the status is valid + if ($this->_checkNewJobStructure($job) && $this->_checkJobStatus($job, $statuses)) + { + $this->_dropNotAllowedPropertiesNewJob($job); // remove the black listed properties from this object + + $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! + + // Try to insert the single job into database + $dbNewJobResult = $this->_ci->JobsQueueModel->insert($job); + + // If an error occurred during while inserting in database + if (isError($dbNewJobResult)) + { + $job->{self::PROPERTY_ERROR} = getError($dbNewJobResult); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + else // otherwise + { + $job->{self::PROPERTY_JOBID} = getData($dbNewJobResult); // get the jobid and store it in job object + + $dbNewTriggeredJobResult = $this->_addNewTriggeredJobToQueue($type, $job, array(self::STATUS_NEW)); + // If an error occurred during while inserting in database + if (isError($dbNewTriggeredJobResult)) return $dbNewTriggeredJobResult; + } + } + else // otherwise + { + $errorOccurred = true; // set error occurred flag + } + } + + // If an error occurred then returns the results in an error object + if ($errorOccurred) return error($results); + + return success($results); // otherwise return results in a success object + } + + /** + * Updates jobs already present in the jobs queue + * jobs is an array of job objects + */ + public function updateJobsQueue($type, $jobs) + { + // Checks parameters + if (isEmptyArray($jobs)) return error('The provided jobs parameter is not a valid array'); + + $results = $jobs; // returned values + $errorOccurred = false; // very optimistic + + // Get all the job statuses + $dbResultStatuses = $this->_ci->JobStatusesModel->load(); + if (isError($dbResultStatuses)) return $dbResultStatuses; + $statuses = getData($dbResultStatuses); + + // Loops through all the provided jobs + foreach ($results as $job) + { + // Check if the required job is present in the database + $dbResultJobs = $this->_ci->JobsQueueModel->load($job->{self::PROPERTY_JOBID}); + if (isError($dbResultJobs)) + { + $job->{self::PROPERTY_ERROR} = getError($dbResultJobs); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + elseif (!hasData($dbResultJobs)) // if no jobs were found + { + $job->{self::PROPERTY_ERROR} = 'The required job is not present'; + $errorOccurred = true; // set error occurred flag + } + else // if a job was found then it could be updated + { + // If the structure of the job object is valid + if ($this->_checkUpdateJobStructure($job) && $this->_checkJobStatus($job, $statuses)) + { + $this->_dropNotAllowedPropertiesUpdateJob($job); // remove the black listed properties from this object + + $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! + + // Try to update the single job into database + $dbResult = $this->_ci->JobsQueueModel->update($job->{self::PROPERTY_JOBID}, (array)$job); + + // If an error occurred during while updating in database + if (isError($dbResult)) + { + $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + else // otherwise + { + $dbNewTriggeredJobResult = $this->_addNewTriggeredJobToQueue( + $type, + $job, + array($job->status) + ); + // If an error occurred during while inserting in database + if (isError($dbNewTriggeredJobResult)) return $dbNewTriggeredJobResult; + } + } + else // otherwise + { + $errorOccurred = true; // set error occurred flag + } + } + } + + // If an error occurred then returns the results in an error object + if ($errorOccurred) return error($results); + + return success($results); // otherwise return results in a success object + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks the job object structure when needed for insert + */ + private function _checkNewJobStructure(&$job) + { + // If job is a valid object and contains the required properties AND does NOT already contain the property error + if (is_object($job) + && property_exists($job, self::PROPERTY_STATUS) + && !property_exists($job, self::PROPERTY_ERROR)) + { + return true; // it is valid! + } + + // If not object then object it! + if (!is_object($job)) $job = new stdClass(); + + // If an error property was not already previously stored then store an error message in job object + if (!property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The structure of the provided job is not valid'; + } + + return false; // better sorry than wrong + } + + /** + * Checks the job object structure when needed for update + */ + private function _checkUpdateJobStructure(&$job) + { + // If job is a valid object + if (is_object($job) && property_exists($job, self::PROPERTY_JOBID)) return true; // it is valid! + + // If not object then object it! + if (!is_object($job)) $job = new stdClass(); + + // If an error property was not already previously stored then store an error message in job object + if (!property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The structure of the provided job is not valid'; + } + + return false; // better sorry than wrong + } + + /** + * Checks if the given job contains a valid type + */ + private function _checkJobType($type, $types) + { + return $this->_inArray($type, $types, self::PROPERTY_TYPE); + } + + /** + * Checks if the given job contains a valid status + */ + private function _checkJobStatus(&$job, $statuses) + { + // If the given job doesn't have the property status then it is not valid + if (!isset($job->{self::PROPERTY_STATUS})) + { + $found = false; + } + else // otherwise test if it valid + { + $found = $this->_inArray($job->{self::PROPERTY_STATUS}, $statuses, self::PROPERTY_STATUS); + } + + // No status was found and does NOT already contain the property error + if (!$found && !property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The provided status of this job is not valid'; // store the error message in the object + } + + return $found; + } + + /** + * Search in an array the given value + * The elements of the given array are objects + * The given value is compared with the property specified by the $propertyName parameter of each object of the given array + */ + private function _inArray($value, $array, $propertyName) + { + $found = false; + + foreach ($array as $element) + { + if ($value == $element->{$propertyName}) + { + $found = true; + break; + } + } + + return $found; + } + + /** + * Drop not allowed properties from the given job + */ + private function _dropNotAllowedPropertiesNewJob(&$job) + { + unset($job->{self::PROPERTY_JOBID}); + unset($job->{self::PROPERTY_CREATIONTIME}); + unset($job->{self::PROPERTY_TYPE}); + } + + /** + * Drop not allowed properties from the given job + */ + private function _dropNotAllowedPropertiesUpdateJob(&$job) + { + unset($job->{self::PROPERTY_CREATIONTIME}); + unset($job->{self::PROPERTY_TYPE}); + } + + /** + * Add e new triggered job to the jobs queue + * NOTE: + * - In this method there are less checks compared to addNewJobsToQueue method because + * the new jobs that will be added are generate in this method + * - Job ids in this case are not returned, therefore the caller is not going to be informed about these new jobs + */ + private function _addNewTriggeredJobToQueue($type, $job, $triggeredStatuses) + { + // Get all the job trigggers for the given type and for the given statuses + $dbTriggersResult = $this->_ci->JobTriggersModel->getJobtriggersByTypeStatuses($type, $triggeredStatuses); + + // If an error occurred while getting job triggers from database then return it + if (isError($dbTriggersResult)) return $dbTriggersResult; + if (hasData($dbTriggersResult)) // If triggers were retrieved + { + // The output of the trigging job is the input of the trigged job + $triggeredJobInput = null; + if (isset($job->{self::PROPERTY_OUTPUT})) $triggeredJobInput = $job->{self::PROPERTY_OUTPUT}; + + // For each trigger + foreach (getData($dbTriggersResult) as $trigger) + { + $triggeredJob = array( + self::PROPERTY_TYPE => $trigger->following_type, // the new type is the one defined in tbl_jobtriggers + self::PROPERTY_STATUS => self::STATUS_NEW, // new job status is new + self::PROPERTY_INPUT => $triggeredJobInput // new job input + ); + + // Try to insert the single job into database + $dbNewJob = $this->_ci->JobsQueueModel->insert($triggeredJob); + // If an error occurred during while inserting in database + if (isError($dbNewJob)) return $dbNewJob; + } + } + + return success(); // if here then it was a success! + } +} + diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index 348c8b87b..09f89abee 100644 --- a/application/libraries/PermissionLib.php +++ b/application/libraries/PermissionLib.php @@ -147,7 +147,7 @@ class PermissionLib $accessType = ''; - // Checks if the required access type is compliant with the HTTP method (GET => r, POST => w) + // Set the access type if (strpos($requiredAccessType, PermissionLib::READ_RIGHT) !== false) { $accessType = PermissionLib::SELECT_RIGHT; // S @@ -184,12 +184,12 @@ class PermissionLib } else { - show_error('The given permission array does not contain the called method or is not correctly set'); + show_error('The given permission array does not contain the given method or is not correctly set'); } } else { - show_error('You must give the permissions array as parameter to the constructor of the controller'); + show_error('The given permissions is not a valid array or it is an empty one'); } return $checkPermissions; diff --git a/application/models/codex/Bisverwendung_model.php b/application/models/codex/Bisverwendung_model.php index 707e8af36..7f101bd4c 100644 --- a/application/models/codex/Bisverwendung_model.php +++ b/application/models/codex/Bisverwendung_model.php @@ -41,4 +41,35 @@ class Bisverwendung_model extends DB_Model return $this->loadWhere($condition); } + + /** + * Gets Verwendungen of the user, optionally in a time span. + * @param string $uid + * @param string $beginn + * @param string $ende + * @return array + */ + public function getVerwendungen($uid, $beginn = null, $ende = null) + { + $params = array($uid); + + $qry = 'SELECT * FROM bis.tbl_bisverwendung + WHERE mitarbeiter_uid = ?'; + + if (isset($beginn)) + { + $qry .= ' AND ( ende >= ? OR ende IS NULL )'; + $params[] = $beginn; + } + + if (isset($ende)) + { + $qry .= ' AND ( beginn <= ? OR beginn IS NULL )'; + $params[] = $ende; + } + + $qry .= ' ORDER BY beginn, ende'; + + return $this->execQuery($qry, $params); + } } diff --git a/application/models/crm/Prestudentstatus_model.php b/application/models/crm/Prestudentstatus_model.php index d579037e1..3335de021 100644 --- a/application/models/crm/Prestudentstatus_model.php +++ b/application/models/crm/Prestudentstatus_model.php @@ -182,4 +182,30 @@ class Prestudentstatus_model extends DB_Model return success(array()); } } + + /** + * getLastStatuses + */ + public function getLastStatusPerson($person_id, $studiensemester_kurzbz = null) + { + $query = 'SELECT * + FROM public.tbl_prestudent p + JOIN ( + SELECT DISTINCT ON(prestudent_id) * + FROM public.tbl_prestudentstatus + WHERE prestudent_id IN (SELECT prestudent_id FROM public.tbl_prestudent WHERE person_id = ?) + ORDER BY prestudent_id, datum desc, insertamum desc + ) ps USING(prestudent_id) + JOIN public.tbl_status USING(status_kurzbz)'; + + $parametersArray = array($person_id); + + if ($studiensemester_kurzbz != '') + { + array_push($parametersArray, $studiensemester_kurzbz); + $query .= ' AND ps.studiensemester_kurzbz = ?'; + } + + return $this->execQuery($query, $parametersArray); + } } diff --git a/application/models/organisation/Studiensemester_model.php b/application/models/organisation/Studiensemester_model.php index 9cdde7a52..6e3e48a98 100644 --- a/application/models/organisation/Studiensemester_model.php +++ b/application/models/organisation/Studiensemester_model.php @@ -39,7 +39,7 @@ class Studiensemester_model extends DB_Model $days = 60; } - $query = 'SELECT studiensemester_kurzbz + $query = 'SELECT studiensemester_kurzbz, start, ende FROM public.tbl_studiensemester WHERE start < NOW() - \'' . $days . ' DAYS\'::INTERVAL ORDER BY start DESC diff --git a/application/models/person/Benutzer_model.php b/application/models/person/Benutzer_model.php index a21811bb4..15bce56db 100644 --- a/application/models/person/Benutzer_model.php +++ b/application/models/person/Benutzer_model.php @@ -33,4 +33,96 @@ class Benutzer_model extends DB_Model return $this->execQuery($sql, array($person_id, $oe_kurzbz)); } + + /** + * Checks if alias exists + * @param $alias + */ + public function aliasExists($alias) + { + $this->addSelect('1'); + $result = $this->loadWhere(array('alias' => $alias)); + + if (!isError($result)) + { + if (hasData($result)) + { + $result = success(array(true)); + } + else if (!hasData($result)) + { + $result = success(array(false)); + } + } + + return $result; + } + + /** + * Generates alias for a uid. + * @param $uid + * @return array the alias if newly generated + */ + public function generateAlias($uid) + { + $aliasres = ''; + $this->addSelect('vorname, nachname'); + $this->addJoin('public.tbl_person', 'person_id'); + $nameresult = $this->loadWhere(array('uid' => $uid)); + + if (hasData($nameresult)) + { + $aliasdata = getData($nameresult); + $alias = $this->_sanitizeAliasName($aliasdata[0]->vorname).'.'.$this->_sanitizeAliasName($aliasdata[0]->nachname); + $aliasexists = $this->aliasExists($alias); + + if (hasData($aliasexists) && !getData($aliasexists)[0]) + $aliasres = $alias; + } + return success($aliasres); + } + + // -------------------------------------------------------------------------------------------- + // Private methods + + /** + * Sanitizes a string used for alias. Replaces special characters, spaces, upper case. + * @param string $str + * @return string + */ + private function _sanitizeAliasName($str) + { + $enc = 'UTF-8'; + + $acentos = array( + 'A' => '/À|Á|Â|Ã|Å/', + 'Ae' => '/Ä/', + 'a' => '/à|á|â|ã|å/', + 'ae'=> '/ä/', + 'C' => '/Ç/', + 'c' => '/ç/', + 'E' => '/È|É|Ê|Ë/', + 'e' => '/è|é|ê|ë/', + 'I' => '/Ì|Í|Î|Ï/', + 'i' => '/ì|í|î|ï/', + 'N' => '/Ñ/', + 'n' => '/ñ/', + 'O' => '/Ò|Ó|Ô|Õ/', + 'Oe' => '/Ö/', + 'o' => '/ò|ó|ô|õ/', + 'oe' => '/ö/', + 'U' => '/Ù|Ú|Û/', + 'Ue' => '/Ü/', + 'u' => '/ù|ú|û/', + 'ue' => '/ü/', + 'Y' => '/Ý/', + 'y' => '/ý|ÿ/', + 'a.' => '/ª/', + 'o.' => '/º/', + 'ss' => '/ß/', + ); + + $str = preg_replace($acentos, array_keys($acentos), htmlentities($str,ENT_NOQUOTES, $enc)); + return mb_strtolower(str_replace(' ','_', $str)); + } } diff --git a/application/models/person/Benutzerfunktion_model.php b/application/models/person/Benutzerfunktion_model.php index fb9b51c1a..27f9b6184 100644 --- a/application/models/person/Benutzerfunktion_model.php +++ b/application/models/person/Benutzerfunktion_model.php @@ -12,6 +12,44 @@ class Benutzerfunktion_model extends DB_Model $this->pk = 'benutzerfunktion_id'; } + /** + * Lädt alle Benutzerfunktionen zu einer UID + * @param type $uid UID des Mitarbeiters + * @param type $funktion_kurzbz OPTIONAL Kurzbezeichnung der Funktion + * @param type $startZeitraum OPTIONAL Start Zeitraum in dem die Funktion aktiv ist + * @param type $endeZeitraum OPTIONAL Ende Zeitraum in dem die Funktion aktiv ist + * @return boolean + */ + public function getBenutzerFunktionByUid($uid, $funktion_kurzbz=null, $startZeitraum=null, $endeZeitraum=null) + { + $params = array($uid); + + $qry = "SELECT tbl_benutzerfunktion.*, tbl_organisationseinheit.bezeichnung as organisationseinheit_bezeichnung, + tbl_organisationseinheit.organisationseinheittyp_kurzbz + FROM public.tbl_benutzerfunktion + LEFT JOIN public.tbl_organisationseinheit USING(oe_kurzbz) + WHERE uid=?"; + if(!is_null($funktion_kurzbz)) + { + $qry .= ' AND funktion_kurzbz = ?'; + $params[] = $funktion_kurzbz; + } + if(!is_null($startZeitraum)) + { + $qry .=' AND (datum_bis IS NULL OR datum_bis >= ?)'; + $params[] = $startZeitraum; + } + if(!is_null($endeZeitraum)) + { + $qry .=' AND (datum_von IS NULL OR datum_von <= ?)'; + $params[] = $endeZeitraum; + } + + $qry .= "ORDER BY datum_bis NULLS LAST, datum_von NULLS LAST;"; + + return $this->execQuery($qry, $params); + } + /** * Get the Benutzerfunktion using the person_id */ diff --git a/application/models/person/Kontakt_model.php b/application/models/person/Kontakt_model.php index e007b81fb..50ef18e15 100644 --- a/application/models/person/Kontakt_model.php +++ b/application/models/person/Kontakt_model.php @@ -10,6 +10,7 @@ class Kontakt_model extends DB_Model parent::__construct(); $this->dbTable = 'public.tbl_kontakt'; $this->pk = 'kontakt_id'; + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); } public function getWholeKontakt($kontakt_id, $person_id = null, $kontakttyp = null) @@ -59,7 +60,66 @@ class Kontakt_model extends DB_Model return $this->execQuery($sql, array($person_id, $kontakttyp)); } - + + /** + * Laedt einen Kontakt eines Standortes + * Es wird nur der erste Eintrag zurueckgeliefert! + * @param $standort_id + * @param $kontakttyp + */ + public function getFirmaKontakttyp($standort_id, $kontakttyp) + { + if (!is_numeric($standort_id)) + { + return error('StandortID ist ungueltig'); + } + + $qry = "SELECT kontakt, kontakt_id FROM public.tbl_kontakt WHERE standort_id=? AND kontakttyp=? ORDER BY kontakt_id LIMIT 1;"; + + return $this->execQuery($qry, array('standort_id' => $standort_id, 'kontakttyp' => $kontakttyp)); + } + + /** + * Gets Firmentelefon for a uid, can be Vorwahl with Telefonklappe or Firmenhandy + * @param $uid + */ + public function getFirmentelefon($uid) + { + $firmentelefon = success(array()); + + $this->MitarbeiterModel->addSelect('standort_id, telefonklappe, person_id'); + $this->MitarbeiterModel->addJoin('public.tbl_benutzer', 'tbl_mitarbeiter.mitarbeiter_uid = tbl_benutzer.uid'); + $mitarbeiter = $this->MitarbeiterModel->load(array('uid' => $uid)); + + if (hasData($mitarbeiter)) + { + $mitarbeiter = getData($mitarbeiter); + if (isEmptyString($mitarbeiter[0]->telefonklappe)) + { + $this->addSelect('kontakt'); + $this->addOrder('updateamum, insertamum', 'DESC'); + $this->addLimit(1); + $firmenhandy = $this->loadWhere(array('person_id' => $mitarbeiter[0]->person_id, 'kontakttyp' => 'firmenhandy')); + if (hasData($firmenhandy)) + { + $firmenhandy = getData($firmenhandy); + $firmentelefon = success(array('kontakt' => $firmenhandy[0]->kontakt, 'telefonklappe' => '')); + } + } + else + { + $firmaKontakttyp = $this->getFirmaKontakttyp($mitarbeiter[0]->standort_id, 'telefon'); + if (hasData($firmaKontakttyp)) + { + $vorwahl = getData($firmaKontakttyp); + $vorwahl = $vorwahl[0]->kontakt; + $firmentelefon = success(array('kontakt' => $vorwahl, 'telefonklappe' => $mitarbeiter[0]->telefonklappe)); + } + } + } + return $firmentelefon; + } + /** * Get all latest contact data of person, where Zustellung is true * @param $person_id @@ -71,13 +131,13 @@ class Kontakt_model extends DB_Model $this->addJoin('public.tbl_standort', 'standort_id', 'LEFT'); $this->addJoin('public.tbl_firma', 'firma_id', 'LEFT'); $this->addOrder('kontakttyp, kontakt, tbl_kontakt.updateamum, tbl_kontakt.insertamum'); - + return $this->loadWhere(array( 'zustellung' => TRUE, 'person_id' => $person_id )); } - + /** * Get all latest phones of person where zustellung is true. Ordered by * telefon > mobil > firmenhandy > else. @@ -96,7 +156,7 @@ class Kontakt_model extends DB_Model AND kontakttyp IN (\'telefon\', \'mobil\', \'firmenhandy\') ORDER BY kontakttyp, kontakt, kontakt.updateamum ) - + SELECT * FROM latest_phones ORDER BY CASE @@ -106,7 +166,7 @@ class Kontakt_model extends DB_Model ELSE 3 END '; - + return $this->execQuery($qry, array($person_id)); } } diff --git a/application/models/ressource/Mitarbeiter_model.php b/application/models/ressource/Mitarbeiter_model.php index ccaeacd0d..329cc3064 100644 --- a/application/models/ressource/Mitarbeiter_model.php +++ b/application/models/ressource/Mitarbeiter_model.php @@ -40,4 +40,96 @@ class Mitarbeiter_model extends DB_Model return success(false); } } + + /** + * Laedt das Personal + * + * @param $aktiv wenn true werden nur aktive geladen, wenn false dann nur inaktve, wenn null dann alle + * @param $fix wenn true werden nur fixangestellte geladen + * @param $verwendung wenn true werden alle geladen die eine BIS-Verwendung eingetragen haben + * @param $personaccount wenn true werden alle geladen die personalnr >= 0 haben, also "echte" Personaccounts + * @return array + */ + public function getPersonal($aktiv, $fix, $verwendung, $personaccount = null) + { + $qry = "SELECT DISTINCT ON(mitarbeiter_uid) staatsbuergerschaft, geburtsnation, sprache, anrede, titelpost, titelpre, + nachname, vorname, vornamen, gebdatum, gebort, gebzeit, tbl_person.anmerkung AS person_anmerkung, homepage, svnr, ersatzkennzeichen, familienstand, + geschlecht, anzahlkinder, tbl_person.insertamum AS person_insertamum, tbl_person.updateamum as person_updateamum, + tbl_person.updatevon AS person_updatevon, kompetenzen, kurzbeschreibung, zugangscode, zugangscode_timestamp, bpk, + tbl_benutzer.*, tbl_mitarbeiter.*, akt_funk.oe_kurzbz AS funktionale_zuordnung, akt_funk.wochenstunden + FROM ((public.tbl_mitarbeiter JOIN public.tbl_benutzer ON(mitarbeiter_uid=uid)) + JOIN public.tbl_person USING(person_id)) + LEFT JOIN public.tbl_benutzerfunktion USING(uid) + LEFT JOIN public.tbl_benutzerfunktion akt_funk ON tbl_mitarbeiter.mitarbeiter_uid = akt_funk.uid AND akt_funk.funktion_kurzbz = 'fachzuordnung' + AND (akt_funk.datum_von IS NULL OR akt_funk.datum_von <= now()) AND (akt_funk.datum_bis IS NULL OR akt_funk.datum_bis >= now()) + WHERE true"; + + if ($fix === true) + $qry .= " AND fixangestellt=true"; + elseif ($fix === false) + $qry .= " AND fixangestellt=false"; + + if ($aktiv === true) + $qry .= " AND tbl_benutzer.aktiv=true"; + elseif ($aktiv === false) + $qry .= " AND tbl_benutzer.aktiv=false"; + + if ($verwendung === true) + { + $qry.=" AND EXISTS(SELECT * FROM bis.tbl_bisverwendung WHERE (ende>now() or ende is null) AND tbl_bisverwendung.mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid)"; + } + elseif ($verwendung === false) + { + $qry.=" AND NOT EXISTS(SELECT * FROM bis.tbl_bisverwendung WHERE (ende>now() or ende is null) AND tbl_bisverwendung.mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid)"; + } + + if ($personaccount === true) + $qry .= " AND tbl_mitarbeiter.personalnummer >= 0"; + elseif ($personaccount === false) + $qry .= " AND tbl_mitarbeiter.personalnummer < 0"; + + return $this->execQuery($qry); + } + + /** + * Gibt ein Array mit den UIDs der Vorgesetzten zurück + * @return object + */ + public function getVorgesetzte($uid, $datum_von = null, $datum_bis = null) + { + $datum_von_var = isset($datum_von) ? '?' : 'now()'; + $datum_bis_var = isset($datum_bis) ? '?' : 'now()'; + $qry = "SELECT + DISTINCT uid as vorgesetzter + FROM + public.tbl_benutzerfunktion + WHERE + funktion_kurzbz='Leitung' AND + (datum_von is null OR datum_von<=%s) AND + (datum_bis is null OR datum_bis>=%s) AND + oe_kurzbz in (SELECT oe_kurzbz + FROM public.tbl_benutzerfunktion + WHERE + funktion_kurzbz='oezuordnung' AND uid=? AND + (datum_von is null OR datum_von<=%s) AND + (datum_bis is null OR datum_bis>=%s) + );"; + + $qry = sprintf($qry, $datum_von_var, $datum_bis_var, $datum_von_var, $datum_bis_var); + + $params = array(); + if (isset($datum_von)) + $params[] = $datum_von; + if (isset($datum_bis)) + $params[] = $datum_bis; + + $params[] = $uid; + + if (isset($datum_von)) + $params[] = $datum_von; + if (isset($datum_bis)) + $params[] = $datum_bis; + + return $this->execQuery($qry, $params); + } } diff --git a/application/models/ressource/Zeitaufzeichnung_model.php b/application/models/ressource/Zeitaufzeichnung_model.php index f887a20a0..b44861d13 100644 --- a/application/models/ressource/Zeitaufzeichnung_model.php +++ b/application/models/ressource/Zeitaufzeichnung_model.php @@ -11,4 +11,14 @@ class Zeitaufzeichnung_model extends DB_Model $this->dbTable = 'campus.tbl_zeitaufzeichnung'; $this->pk = 'zeitaufzeichnung_id'; } + + public function deleteEntriesForCurrentDay() + { + $today = date('Y-m-d'); + $qry = "DELETE FROM " . $this->dbTable . " + WHERE start >= '" . $today . " 00:00:00' + AND start <= '" . $today . " 23:59:59';"; + + return $this->execQuery($qry); + } } diff --git a/application/models/ressource/Zeitsperre_model.php b/application/models/ressource/Zeitsperre_model.php index 07889e349..350a7be58 100644 --- a/application/models/ressource/Zeitsperre_model.php +++ b/application/models/ressource/Zeitsperre_model.php @@ -11,4 +11,13 @@ class Zeitsperre_model extends DB_Model $this->dbTable = 'campus.tbl_zeitsperre'; $this->pk = 'zeitsperre_id'; } + + public function deleteEntriesForCurrentDay() + { + $today = date('Y-m-d'); + $qry = "DELETE FROM " . $this->dbTable . " + WHERE vondatum = '" . $today . "';"; + + return $this->execQuery($qry); + } } diff --git a/application/models/system/JobStatuses_model.php b/application/models/system/JobStatuses_model.php new file mode 100644 index 000000000..82d1ee31b --- /dev/null +++ b/application/models/system/JobStatuses_model.php @@ -0,0 +1,16 @@ +dbTable = 'system.tbl_jobstatuses'; + $this->pk = 'status'; + $this->hasSequence = false; + } +} diff --git a/application/models/system/JobTriggers_model.php b/application/models/system/JobTriggers_model.php new file mode 100644 index 000000000..176b4f5b1 --- /dev/null +++ b/application/models/system/JobTriggers_model.php @@ -0,0 +1,32 @@ +dbTable = 'system.tbl_jobtriggers'; + $this->pk = array('type', 'status', 'followingType'); + $this->hasSequence = false; + } + + /** + * + */ + public function getJobtriggersByTypeStatuses($type, $triggeredStatuses) + { + $query = 'SELECT jt.type, + jt.status, + jt.following_type + FROM system.tbl_jobtriggers jt + WHERE jt.type = ? + AND jt.status IN ? + ORDER BY jt.type, jt.status'; + + return $this->execQuery($query, array($type, $triggeredStatuses)); + } +} diff --git a/application/models/system/JobTypes_model.php b/application/models/system/JobTypes_model.php new file mode 100644 index 000000000..1d578bcab --- /dev/null +++ b/application/models/system/JobTypes_model.php @@ -0,0 +1,16 @@ +dbTable = 'system.tbl_jobtypes'; + $this->pk = 'type'; + $this->hasSequence = false; + } +} diff --git a/application/models/system/JobsQueue_model.php b/application/models/system/JobsQueue_model.php new file mode 100644 index 000000000..e35b45cb3 --- /dev/null +++ b/application/models/system/JobsQueue_model.php @@ -0,0 +1,15 @@ +dbTable = 'system.tbl_jobsqueue'; + $this->pk = 'jobid'; + } +} diff --git a/application/views/system/jq/jobsQueueViewer.php b/application/views/system/jq/jobsQueueViewer.php new file mode 100644 index 000000000..6d92d610b --- /dev/null +++ b/application/views/system/jq/jobsQueueViewer.php @@ -0,0 +1,47 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Jobs Queue Viewer', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'tablesorter' => true, + 'ajaxlib' => true, + 'filterwidget' => true, + 'navigationwidget' => true, + 'phrases' => array( + 'global' => array('mailAnXversandt'), + 'ui' => array('bitteEintragWaehlen') + ), + 'customCSSs' => 'public/css/sbadmin2/tablesort_bootstrap.css', + 'customJSs' => array('public/js/bootstrapper.js') + ) + ); +?> + +
+