diff --git a/application/config/Events.php b/application/config/Events.php new file mode 100644 index 000000000..191a1eb98 --- /dev/null +++ b/application/config/Events.php @@ -0,0 +1,14 @@ + 'TEST', + 'component' => './Stv/Studentenverwaltung/Details/Notizen.js' + ]; + }); + */ diff --git a/application/config/anrechnung.php b/application/config/anrechnung.php index 768ec3197..2466d2bb1 100644 --- a/application/config/anrechnung.php +++ b/application/config/anrechnung.php @@ -21,3 +21,6 @@ $config['grades_blocking_application'] = array( $config['fbl'] = FALSE; //Enables Info Mails $config['send_mail'] = TRUE; + +// Display fields to explain equivalence of ECTS and LV-Inhalte +$config['explain_equivalence'] = TRUE; diff --git a/application/config/db_crypt.php b/application/config/db_crypt.php new file mode 100644 index 000000000..b9360861b --- /dev/null +++ b/application/config/db_crypt.php @@ -0,0 +1,29 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +// NOTE: if database encryption is _not_ used then leave this array empty! +$config['encryption_passwords'] = array( + // 'password name 1' => 'password 1' + // 'password name 2' => 'password 2' + // 'password name ...' => 'password ...' + // 'password name N' => 'password N' +); + diff --git a/application/config/migratecontract.php b/application/config/migratecontract.php new file mode 100644 index 000000000..75ba2f505 --- /dev/null +++ b/application/config/migratecontract.php @@ -0,0 +1,36 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +$config['migratecontract_oe_default'] = 'TODO_OE_DEFAULT'; + +$config['migratecontract_matching_ba1_vertragsart'] = array( + '101'=>'dvbund', + '102'=>'dvanderengk', + '103'=>'echterdv', + '104'=>'studentischehilfskr', + '105'=>'externerlehrender', + '106'=>'dvanderenbet', + '107'=>'werkvertrag', + '108'=>'studentischehilfskr', + '109'=>'ueberlassungsvertrag', + '110'=>'echterfreier', + '111'=>'echterdv' //All-In +); \ No newline at end of file diff --git a/application/config/navigation.php b/application/config/navigation.php index 56d142d08..d57cd697a 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -31,6 +31,14 @@ $config['navigation_header'] = array( 'expand' => true, 'sort' => 20, 'requiredPermissions' => 'admin:w' + ), + 'bismeldestichtagsverwaltung' => array( + 'link' => site_url('codex/Bismeldestichtag'), + 'icon' => '', + 'description' => 'BIS-Meldestichtagsverwaltung', + 'expand' => true, + 'sort' => 30, + 'requiredPermissions' => 'admin:w' ) ) ), @@ -47,6 +55,12 @@ $config['navigation_header'] = array( 'description' => 'CIS', 'sort' => 10 ), + 'lehrveranstaltungen' => array( + 'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'), + 'icon' => '', + 'description' => 'Lehrveranstaltungen', + 'sort' => 15 + ), 'reihungstest' => array( 'link' => site_url('organisation/Reihungstest'), 'description' => 'Reihungstests', @@ -279,6 +293,15 @@ $config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array( ) ); +$config['navigation_menu']['lehre/lvplanung/LvTemplateUebersicht/index'] = array( + 'lvTemplateUebersicht' => array( + 'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'), + 'description' => 'LV Template Übersicht', + 'icon' => '', + 'sort' => 1 + ) +); + $config['navigation_menu']['system/issues/Issues/*'] = array( 'fehlerzustaendigkeiten' => array( 'link' => site_url('system/issues/IssuesZustaendigkeiten'), diff --git a/application/config/studierendenantrag.php b/application/config/studierendenantrag.php new file mode 100644 index 000000000..4e25aef28 --- /dev/null +++ b/application/config/studierendenantrag.php @@ -0,0 +1,170 @@ + null, 'dokument_kurzbz' => null, 'kategorie_kurzbz' => null]; +$config['unterbrechung_dms'] = ['oe_kurzbz' => null, 'dokument_kurzbz' => null, 'kategorie_kurzbz' => 'Akte']; + +/** + * UPLOAD + */ + +/** + * Allowed filetypes for attachment upload in unterbrechung antrag + * + * @var array An array of fileextensions + */ +$config['unterbrechung_dms_filetypes'] = ['jpg', 'pdf']; + + +/** + * GRADES + */ + +/** + * On wiederholung the student must repeat certain lvs. + * This lvs will be graded with this id + * + * @var integer tbl_note.note + */ +$config['wiederholung_note_angerechnet'] = 19; + +/** + * On wiederholung the student can not attend certain lvs. + * Those lvs will be graded with this id + * + * @var integer tbl_note.note + */ +$config['wiederholung_note_nicht_zugelassen'] = 20; + + +/** + * JOBS + */ + +/** + * The Job will remind for every Unterbrecher who has a + * wiedereinstieg_datum between the date the Job is run + * and the modified date + * e.g.: If the Job is running on 2023-04-20 and the modifier + * is '+3 days' it will remind of everyone that + * has a wiedereinstiegs_datum between 2023-04-20 and 2023-04-23 + * + * @var string A string formated as PHP DateTime modifier + * @see https://www.php.net/manual/de/datetime.modify.php + */ +$config['unterbrechung_job_remind_wiedereinstieg_date_modifier'] = '+3 days'; + +/** + * The Job will sent a request to everyone who faild the 3rd committee exam + * and respecting the given conditions (not repeated yet, stg not in blacklist) + * to decide if he/she will repeat or not + * + * First request + * + * @var string A string formated as PHP DateTime modifier + * @see https://www.php.net/manual/de/datetime.modify.php + */ +$config['wiederholung_job_request_1_date_modifier'] = '+0 days'; + +/** + * Second request + * + * @var string A string formated as PHP DateTime modifier + * @see https://www.php.net/manual/de/datetime.modify.php + */ +$config['wiederholung_job_request_2_date_modifier'] = '+3 weeks'; + +/** + * Final deadline - after this the student will be abgemeldet if he hasn't chosen yet + * + * @var string A string formated as PHP DateTime modifier + * @see https://www.php.net/manual/de/datetime.modify.php + */ +$config['wiederholung_job_deadline_date_modifier'] = '+1 month'; + +/** + * before this exam dates for Wiederholer will be ignored + * + * @var string A string formated as Date + * + */ +$config['digitalization_start'] = '2022-07-01'; + + + + +/** + * Objection period - the student will be abgemeldet if he hasn't objected in this period + * + * @var string A string formated as PHP DateTime modifier + * @see https://www.php.net/manual/de/datetime.modify.php + */ +$config['abmeldung_job_deadline_date_modifier'] = '+2 weeks'; + + + +/** + * System User - uid of a user that is allowed to set prestudentstatus + * + * @var string + */ +$config['antrag_job_systemuser'] = ''; + + +/** + * WHITELISTS + */ + +/** + * List of stati who entitle a prestudent to create an Antrag + * + * @var array Array of tbl_status.status_kurzbz's + */ +$config['antrag_prestudentstatus_whitelist'] = ['Student', 'Diplomand']; +$config['antrag_prestudentstatus_whitelist_abmeldung'] = ['Student', 'Diplomand', 'Unterbrecher']; + + +/** + * BLACKLISTS + */ + +/** + * List of Statusgründe that prevent a prestudent from create an Wiederholungsantrag + * + * @var array An array of tbl_status_grund.statusgrund_id's + */ +$config['status_gruende_wiederholer'] = [16, 15]; + +/** + * Blacklisted for abmeldung anträge + * + * @var array An array of tbl_studiengang.studiengang_kz's + */ +$config['stgkz_blacklist_abmeldung'] = []; + +/** + * Blacklisted for unterbrechung anträge + * + * @var array An array of tbl_studiengang.studiengang_kz's + */ +$config['stgkz_blacklist_unterbrechung'] = []; + +/** + * Blacklisted for wiederholung anträge + * + * @var array An array of tbl_studiengang.studiengang_kz's + */ +$config['stgkz_blacklist_wiederholung'] = []; + +/** + * Blacklisted noten for negative committee exams + * noten with this ids won't be seen as negative + * + * @var array An array of noten ids + */ +$config['note_blacklist_wiederholung'] = []; diff --git a/application/controllers/Studentenverwaltung.php b/application/controllers/Studentenverwaltung.php new file mode 100644 index 000000000..e09d04c6a --- /dev/null +++ b/application/controllers/Studentenverwaltung.php @@ -0,0 +1,40 @@ +method] = ['admin:r', 'assistenz:r']; + parent::__construct($permissions); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + } + + /** + * @return void + */ + public function _remap() + { + $this->load->view('Studentenverwaltung', [ + 'permissions' => [ + 'student/bpk' => $this->permissionlib->isBerechtigt('student/bpk'), + 'student/alias' => $this->permissionlib->isBerechtigt('student/alias'), + 'basis/prestudent' => $this->permissionlib->isBerechtigt('basis/prestudent'), + 'basis/prestudentstatus' => $this->permissionlib->isBerechtigt('basis/prestudentstatus'), + 'assistenz_stgs' => $this->permissionlib->getSTG_isEntitledFor('assistenz'), + 'admin' => $this->permissionlib->isBerechtigt('admin'), + 'assistenz_schreibrechte' => $this->permissionlib->isBerechtigt('assistenz','suid'), + 'student/keine_studstatuspruefung' => $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'), + 'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht') + ], + 'variables' => [ + 'semester_aktuell' => $this->variablelib->getVar('semester_aktuell') + ] + ]); + } +} diff --git a/application/controllers/Test.php b/application/controllers/Test.php new file mode 100644 index 000000000..2a7aa4e4e --- /dev/null +++ b/application/controllers/Test.php @@ -0,0 +1,16 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + + +/** + * This controller operates between (interface) the JS (FAS) and the AntragLib (back-end) + * This controller works with calls on the HTTP GET or POST and the output is always RDF + */ +class Wiederholung extends Auth_Controller +{ + + /** + * Calls the parent's constructor and loads the FilterCmptLib + */ + public function __construct() + { + parent::__construct([ + 'getLvs' => ['student/studierendenantrag:r', 'student/noten:r'], + 'moveLvsToZeugnis' => ['student/studierendenantrag:w', 'student/noten:w'] + ]); + + // Libraries + $this->load->library('AntragLib'); + + // Load language phrases + $this->loadPhrases([ + 'global', + 'studierendenantrag' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + public function getLvs($prestudent_id) + { + // header für no cache + $this->output->set_header("Cache-Control: no-cache"); + $this->output->set_header("Cache-Control: post-check=0, pre-check=0", false); + $this->output->set_header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); + $this->output->set_header("Pragma: no-cache"); + $this->output->set_header("Content-type: application/xhtml+xml"); + + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $sem_akt = $this->variablelib->getVar('semester_aktuell'); + + + $result = $this->antraglib->getLvsForPrestudent($prestudent_id, $sem_akt); + if (isError($result)) + return $result; + $lvs = $result->retval; + + $rdf_url = 'http://www.technikum-wien.at/antragnote'; + + $this->load->view('lehre/Antrag/Wiederholung/getLvs.rdf.php', [ + 'url' => $rdf_url, + 'lvs' => $lvs + ]); + } + + public function moveLvsToZeugnis() + { + $anzahl = $this->input->post('anzahl'); + $student_uid = $this->input->post('student_uid'); + $this->load->model('education/Studierendenantraglehrveranstaltung_model', 'StudierendenantraglehrveranstaltungModel'); + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $errormsg = array(); + + for($i=0; $i<$anzahl; $i++) + { + $id = $this->input->post('studierendenantrag_lehrveranstaltung_id_' . $i); + $result =$this->StudierendenantraglehrveranstaltungModel->load($id); + if(isError($result)) + { + $errormsg[] = getError($result); + } + elseif(!hasData($result)) + { + $errormsg[] = $this->p->t('studierendenantrag', 'error_no_lv_in_application'); + } + else + { + $antragLv = getData($result)[0]; + $result= $this->ZeugnisnoteModel->load([ + 'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id, + 'student_uid'=> $student_uid, + 'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz + ]); + if(isError($result)) + { + $errormsg[] = getError($result); + } + else + { + if (hasData($result)) + { + $result = $this->ZeugnisnoteModel->update( + [ + 'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id, + 'student_uid'=> $student_uid, + 'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz + ], + [ + 'note'=> $antragLv->note, + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $antragLv->insertamum, + 'updateamum' => date('c'), + 'bemerkung'=>$antragLv->anmerkung, + 'updatevon'=>getAuthUID() + ] + ); + } + else + { + $result = $this->ZeugnisnoteModel->insert([ + 'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id, + 'student_uid'=> $student_uid, + 'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz, + 'note'=> $antragLv->note, + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $antragLv->insertamum, + 'insertamum' => date('c'), + 'bemerkung'=>$antragLv->anmerkung, + 'insertvon'=>getAuthUID() + ]); + } + if(isError($result)) + { + $errormsg[] = getError($result); + } + } + } + } + + if($errormsg) + $return = false; + else + $return = true; + + $this->load->view('lehre/Antrag/Wiederholung/moveLvs.rdf.php', [ + 'return' => $return, + 'errormsg' => $errormsg + ]); + } +} diff --git a/application/controllers/api/frontend/v1/Filter.php b/application/controllers/api/frontend/v1/Filter.php new file mode 100644 index 000000000..45838fc5f --- /dev/null +++ b/application/controllers/api/frontend/v1/Filter.php @@ -0,0 +1,231 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the FilterCmptLib (back-end) + * Provides data to the ajax get calls about the filter component + * Listens to ajax post calls to change the filter data + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Filter extends FHCAPI_Controller +{ + const FILTER_UNIQUE_ID = 'filterUniqueId'; // Name of the filter cmpt unique id (mandatory) + const FILTER_TYPE = 'filterType'; // The filter type (PHP filter definition) used (mandatory) + const FILTER_ID = 'filterId'; // The id of the used filter (optional) + + /** + * Calls the parent's constructor and loads the FilterCmptLib + */ + public function __construct() + { + // NOTE: FilterCmpt has its own permissions checks + parent::__construct([ + 'getFilter' => self::PERM_LOGGED, + 'removeFilterField' => self::PERM_LOGGED, + 'addFilterField' => self::PERM_LOGGED, + 'applyFilterFields' => self::PERM_LOGGED, + 'removeCustomFilter' => self::PERM_LOGGED, + 'saveCustomFilter' => self::PERM_LOGGED, + 'reloadDataset' => self::PERM_LOGGED + ]); + + // Loads the FiltersModel + $this->load->model('system/Filters_model', 'FiltersModel'); + + // Loads the FilterCmptLib with HTTP GET/POST parameters + $this->_startFilterCmptLib(); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Retrieves data about the current filter from the session and will be written on the output in JSON format + */ + public function getFilter() + { + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $session = $this->filtercmptlib->getSession(); + if (is_object($session)) { + // If stdClass it is an retval object + $session = $this->getDataOrTerminateWithError($session); + } + $this->terminateWithSuccess($session); + } + + /** + * Remove an applied filter (SQL where condition) from the current filter + */ + public function removeFilterField() + { + $this->form_validation->set_rules('filterField', 'filterField', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = $this->filtercmptlib->removeFilterField($this->input->post('filterField')); + + if (!$result) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + $this->terminateWithSuccess('Field removed'); + } + + /** + * Add a filter (SQL where clause) to be applied to the current filter + */ + public function addFilterField() + { + $this->form_validation->set_rules('filterField', 'filterField', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = $this->filtercmptlib->addFilterField($this->input->post('filterField')); + + if (!$result) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + $this->terminateWithSuccess('Field added'); + } + + /** + * Apply the filter changes + */ + public function applyFilterFields() + { + $this->form_validation->set_rules('filterFields', 'filterFields', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = $this->filtercmptlib->applyFilterFields($this->input->post('filterFields')); + + if (!$result) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + $this->terminateWithSuccess('Applied'); + } + + /** + * Save the current filter as a custom filter for this user with the given description + */ + public function saveCustomFilter() + { + $this->form_validation->set_rules('customFilterName', 'customFilterName', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = $this->filtercmptlib->saveCustomFilter($this->input->post('customFilterName')); + + if (!$result) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + $this->terminateWithSuccess('Saved'); + } + + /** + * Remove a custom filter by its filterId + */ + public function removeCustomFilter() + { + $this->form_validation->set_rules('filterId', 'filterId', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = $this->filtercmptlib->removeCustomFilter($this->input->post('filterId')); + + if (!$result) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + $this->terminateWithSuccess('Removed'); + } + + /** + * Reloads the dataset + */ + public function reloadDataset() + { + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $this->filtercmptlib->reloadDataset(); + + $this->terminateWithSuccess('Success'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Loads the FilterCmptLib with the FILTER_UNIQUE_ID parameter + * If the parameter FILTER_UNIQUE_ID is not given then the execution of the controller is terminated and + * an error message is printed + */ + private function _startFilterCmptLib() + { + $filterUniqueId = null; + $filterType = null; + $filterId = null; + + $validations = [ + [ + 'field' => self::FILTER_UNIQUE_ID, + 'label' => self::FILTER_UNIQUE_ID, + 'rules' => 'required' + ], + [ + 'field' => self::FILTER_TYPE, + 'label' => self::FILTER_TYPE, + 'rules' => 'required' + ], + ]; + + $this->load->library('form_validation'); + + if ($this->input->method() == 'get') + $this->form_validation->set_data($this->input->get()); + $this->form_validation->set_rules($validations); + + if ($this->form_validation->run()) { + $filterUniqueId = $this->input->post_get(self::FILTER_UNIQUE_ID); + $filterType = $this->input->post_get(self::FILTER_TYPE); + $filterId = $this->input->post_get(self::FILTER_ID); + + // Loads the FilterCmptLib that contains all the used logic + $this->load->library( + 'FilterCmptLib', + array( + 'filterUniqueId' => $filterUniqueId, + 'filterType' => $filterType, + 'filterId' => $filterId + ) + ); + + // Start the component + $this->filtercmptlib->start(); + } + } +} + diff --git a/application/controllers/api/frontend/v1/Navigation.php b/application/controllers/api/frontend/v1/Navigation.php new file mode 100644 index 000000000..6cbbbd385 --- /dev/null +++ b/application/controllers/api/frontend/v1/Navigation.php @@ -0,0 +1,101 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the NavigationLib (back-end) + * Provides data to the ajax get calls about the filter + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Navigation extends FHCAPI_Controller +{ + const NAVIGATION_PAGE_PARAM = 'navigation_page'; // Navigation page parameter name + + /** + * Loads the NavigationLib where the used logic lies + */ + public function __construct() + { + parent::__construct([ + 'menu' => self::PERM_LOGGED, + 'header' => self::PERM_LOGGED + ]); + + $this->_loadNavigationLib(); // Loads the NavigationLib with parameters + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * This function creates the left Menu for each Page + * @param NAVIGATION_PAGE_PARAM GET Parameter witch holds the currently called Page + * @return JSON object with the Menu Entries + */ + public function menu() + { + $menuArray = $this->navigationlib->getMenuArray($this->input->get(self::NAVIGATION_PAGE_PARAM)); + + $this->terminateWithSuccess($menuArray); + } + + /** + * This function creates the Top Menu for each Page + * @param NAVIGATION_PAGE_PARAM GET Parameter witch holds the currently called Page + * @return JSON object with the Menu Entries + */ + public function header() + { + $headerArray = $this->navigationlib->getHeaderArray($this->input->get(self::NAVIGATION_PAGE_PARAM)); + + $this->terminateWithSuccess($headerArray); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Loads the NavigationLib with the NAVIGATION_PAGE_PARAM parameter + * If the parameter NAVIGATION_PAGE_PARAM is not given then the execution of the controller is terminated and + * an error message is printed + */ + private function _loadNavigationLib() + { + // If the parameter NAVIGATION_PAGE_PARAM is present in the HTTP GET or POST + if (isset($_GET[self::NAVIGATION_PAGE_PARAM]) || isset($_POST[self::NAVIGATION_PAGE_PARAM])) + { + // If it is present in the HTTP GET + if (isset($_GET[self::NAVIGATION_PAGE_PARAM])) + { + $navigationPage = $this->input->get(self::NAVIGATION_PAGE_PARAM); // is retrieved from the HTTP GET + } + elseif (isset($_POST[self::NAVIGATION_PAGE_PARAM])) // Else if it is present in the HTTP POST + { + $navigationPage = $this->input->post(self::NAVIGATION_PAGE_PARAM); // is retrieved from the HTTP POST + } + + // Loads the NavigationLib that contains all the used logic + $this->load->library('NavigationLib', array(self::NAVIGATION_PAGE_PARAM => $navigationPage)); + } + else // Otherwise an error will be written in the output + { + show_error('Parameter "' . self::NAVIGATION_PAGE_PARAM . '" not provided!'); + } + } +} diff --git a/application/controllers/api/frontend/v1/Phrasen.php b/application/controllers/api/frontend/v1/Phrasen.php new file mode 100644 index 000000000..472308d2b --- /dev/null +++ b/application/controllers/api/frontend/v1/Phrasen.php @@ -0,0 +1,46 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the PhrasesLib (back-end) + * Provides data to the ajax get calls about the Phrasen plugin + * This controller works with JSON calls on the HTTP GET and the output is always JSON + */ +class Phrasen extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'loadModule' => self::PERM_ANONYMOUS + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * @param string $module + */ + public function loadModule($module) + { + $this->load->library('PhrasesLib', [$module], 'pj'); + $this->terminateWithSuccess(json_decode($this->pj->getJSON())); + } +} diff --git a/application/controllers/api/frontend/v1/Searchbar.php b/application/controllers/api/frontend/v1/Searchbar.php new file mode 100644 index 000000000..8b383e042 --- /dev/null +++ b/application/controllers/api/frontend/v1/Searchbar.php @@ -0,0 +1,69 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the SearchBarLib (back-end) + * Provides data to the ajax get calls about the searchbar component + * This controller works with JSON calls on the HTTP GET and the output is always JSON + */ +class Searchbar extends FHCAPI_Controller +{ + const SEARCHSTR_PARAM = 'searchstr'; + const TYPES_PARAM = 'types'; + + /** + * Object initialization + */ + public function __construct() + { + // NOTE(chris): additional permission checks will be done in SearchBarLib + parent::__construct([ + 'search' => self::PERM_LOGGED + ]); + + // Load the library SearchBarLib + $this->load->library('SearchBarLib'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Gets a JSON body via HTTP POST and provides the parameters + */ + public function search() + { + $this->load->library('form_validation'); + + // Checks if the searchstr and the types parameters are in the POSTed JSON + $this->form_validation->set_rules(self::SEARCHSTR_PARAM, null, 'required'); + $this->form_validation->set_rules(self::TYPES_PARAM . '[]', null, 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithError(SearchBarLib::ERROR_WRONG_JSON, self::ERROR_TYPE_GENERAL); + + // Convert to json the result from searchbarlib->search + $result = $this->searchbarlib->search($this->input->post(self::SEARCHSTR_PARAM), $this->input->post(self::TYPES_PARAM)); + if (property_exists($result, 'error')) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $this->terminateWithSuccess($result); + } +} + diff --git a/application/controllers/api/frontend/v1/Udf.php b/application/controllers/api/frontend/v1/Udf.php new file mode 100644 index 000000000..4bdc613e0 --- /dev/null +++ b/application/controllers/api/frontend/v1/Udf.php @@ -0,0 +1,133 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the UDFLib (back-end) + * Provides data to the ajax get calls about the Udf component + * Listens to ajax post calls to change the Udf data + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Udf extends FHCAPI_Controller +{ + /** + * Calls the parent's constructor and prepares the UDFLib + */ + public function __construct() + { + // NOTE: UdfLib has its own permissions checks + parent::__construct([ + 'load' => self::PERM_LOGGED, + 'save' => self::PERM_LOGGED + ]); + + // Libraries + $this->load->library('form_validation'); + $this->load->library('UDFLib'); + + // Models + $this->load->model($this->getTargetModelPath(), 'TargetModel'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Load all UDFs for a dataset + * + * @return void + */ + public function load() + { + $pks = $this->TargetModel->getPks(); + foreach ($pks as $id) + $this->form_validation->set_rules($id, $id, 'required'); + + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $id = []; + foreach ($pks as $pk) + $id[$pk] = $this->input->post($pk); + if (!is_array($this->TargetModel->getPk())) + $id = current($id); + + $result = $this->udflib->getFieldArray($this->TargetModel, $id); + + $fields = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($fields); + } + + /** + * Saves UDFs to a dataset + * + * @return void + */ + public function save() + { + $pks = $this->TargetModel->getPks(); + foreach ($pks as $id) + $this->form_validation->set_rules($id, $id, 'required'); + + $result = $this->udflib->getCiValidations($this->TargetModel, $this->input->post()); + + $fieldValidations = $this->getDataOrTerminateWithError($result); + + $this->form_validation->set_rules($fieldvalidations); + + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $id = []; + $fields = $this->input->post(); + foreach ($pks as $pk) { + $id[$pk] = $fields[$pk]; + unset($fields[$pk]); + } + if (!is_array($this->TargetModel->getPk())) + $id = current($id); + + $result = $this->TargetModel->update($id, $fields); + + $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(array_fill_keys(array_keys($fields), '')); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Get the path to the target model from the url + * + * @return string + */ + private function getTargetModelPath() + { + $ci_model_path = array_slice($this->uri->rsegments, 2); + if ($ci_model_path) + $ci_model_path[] = ucfirst(array_pop($ci_model_path)) . '_model'; + return implode(DIRECTORY_SEPARATOR, $ci_model_path); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/betriebsmittel/BetriebsmittelP.php b/application/controllers/api/frontend/v1/betriebsmittel/BetriebsmittelP.php new file mode 100644 index 000000000..8e44b2326 --- /dev/null +++ b/application/controllers/api/frontend/v1/betriebsmittel/BetriebsmittelP.php @@ -0,0 +1,387 @@ + ['admin:r', 'assistenz:r'], + 'addNewBetriebsmittel' => self::PERM_LOGGED, + 'updateBetriebsmittel' => self::PERM_LOGGED, + 'loadBetriebsmittel' => ['admin:r', 'assistenz:r'], + 'deleteBetriebsmittel' => self::PERM_LOGGED, + 'getTypenBetriebsmittel' => ['admin:r', 'assistenz:r'], + 'loadInventarliste' => ['admin:r', 'assistenz:r'] + ]); + + //Load Models + $this->load->model('ressource/Betriebsmittel_model', 'BetriebsmittelModel'); + $this->load->model('ressource/Betriebsmittelperson_model', 'BetriebsmittelpersonModel'); + + // Additional Permission Checks + if ($this->router->method == 'addNewBetriebsmittel') { + $this->person_id = current(array_slice($this->uri->rsegments, 2)); + + $this->checkPermissionsForPerson( + $this->person_id, + ['admin:rw', 'mitarbeiter:rw', 'basis/betriebsmittel:rw'], + ['admin:rw', 'assistenz:rw', 'basis/betriebsmittel:rw'] + ); + } elseif ($this->router->method == 'updateBetriebsmittel' || $this->router->method == 'deleteBetriebsmittel') { + $betriebsmittelperson_id = current(array_slice($this->uri->rsegments, 2)); + $result = $this->BetriebsmittelpersonModel->load($betriebsmittelperson_id); + if (!hasData($result)) + show_404(); + $this->person_id = current(getData($result))->person_id; + + $this->checkPermissionsForPerson( + $this->person_id, + ['admin:rw', 'mitarbeiter:rw', 'basis/betriebsmittel:rw'], + ['admin:rw', 'assistenz:rw', 'basis/betriebsmittel:rw'] + ); + } + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'wawi' + ]); + } + + public function getAllBetriebsmittel($type_id, $id) + { + $result = $this->BetriebsmittelpersonModel->getBetriebsmittelData($id, $type_id); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $this->terminateWithSuccess((getData($result) ?: [])); + } + + protected function validateNewOrUpdate() + { + $this->form_validation->set_rules('betriebsmitteltyp', 'Typ', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired') + ]); + + $this->form_validation->set_rules('kaution', 'Kaution', 'numeric|less_than_equal_to[9999.99]', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric') + ]); + + $this->form_validation->set_rules('ausgegebenam', 'Ausgegeben am', 'required|is_valid_date', [ + 'required' => $this->p->t('ui', 'error_fieldRequired') + ]); + + if ($this->input->post('ausgegebenam') && $this->input->post('retouram')) { + $this->form_validation->set_rules('retouram', 'Retour am', [ + 'is_valid_date', + ['is_not_before_ausgegebenam', function ($value) { + return (new DateTime($value) >= new DateTime($this->input->post('ausgegebenam'))); + }] + ], [ + 'is_not_before_ausgegebenam' => $this->p->t('wawi', 'error_retourdatumVorAusgabe') + ]); + } else { + $this->form_validation->set_rules('retouram', 'Retour am', 'is_valid_date'); + } + + $this->form_validation->set_rules('anmerkung', 'Anmerkung', 'max_length[256]'); + + if ($this->input->post('betriebsmitteltyp') == 'Inventar') { + // Inventar + $this->form_validation->set_rules('betriebsmittel_id', 'Inventarnummer', 'required'); + } elseif ($this->input->post('betriebsmitteltyp') == 'Zutrittskarte') { + // Zutrittskarte + if ($this->input->post('nummer') === null && $this->input->post('nummer') === null) { + $this->form_validation->set_rules('nummer', 'Nummer', 'required', [ + 'required' => $this->p->t('wawi', 'error_zutrittskarteOhneNummer') + ]); + $this->form_validation->set_rules('nummer2', 'Nummer2', 'required', [ + 'required' => $this->p->t('wawi', 'error_zutrittskarteOhneNummer') + ]); + } else { + if ($this->input->post('nummer') === null) { + $result = $this->BetriebsmittelpersonModel->loadViewWhere([ + 'betriebsmitteltyp' => $this->input->post('betriebsmitteltyp'), + 'nummer2' => $this->input->post('nummer2'), + 'person_id !=' => $this->person_id, + 'retouram IS NULL' => null + ]); + if (hasData($result)) + $this->form_validation->set_rules('nummer2', 'Nummer2', 'is_array', [ + 'is_array' => $this->p->t('wawi', 'error_bmZutrittskarteOccupied', (array)current(getData($result))) + ]); + } else { + $result = $this->BetriebsmittelpersonModel->loadViewWhere([ + 'betriebsmitteltyp' => $this->input->post('betriebsmitteltyp'), + 'nummer' => $this->input->post('nummer'), + 'person_id !=' => $this->person_id, + 'retouram IS NULL' => null + ]); + if (hasData($result)) + $this->form_validation->set_rules('nummer', 'Nummer', 'is_array', [ + 'is_array' => $this->p->t('wawi', 'error_bmZutrittskarteOccupied', (array)current(getData($result))) + ]); + } + } + } + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + public function addNewBetriebsmittel($person_id) + { + $this->form_validation->set_rules('uid', 'UID', [ + ['uid_in_person', function ($value) use ($person_id) { + if ($value === null) + return true; + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $result = $this->BenutzerModel->loadWhere([ + 'uid' => $value, + 'person_id' => $person_id + ]); + + return hasData($result); + }] + ], [ + 'uid_in_person' => $this->p->t('person', 'error_uidNotInPerson') + ]); + $this->validateNewOrUpdate(); + + $betriebsmitteltyp = $this->input->post('betriebsmitteltyp'); + $nummer = $this->input->post('nummer'); + $nummer2 = $this->input->post('nummer2'); + $beschreibung = $this->input->post('beschreibung'); + $betriebsmittel_id = $this->input->post('betriebsmittel_id'); + $anmerkung = $this->input->post('anmerkung'); + $kaution = $this->input->post('kaution'); + $ausgegebenam = $this->input->post('ausgegebenam'); + $retouram = $this->input->post('retouram'); + $uid = $this->input->post('uid'); + + // NOTE(chris): transform_kartennummer + if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer) + $nummer = is_numeric($nummer) ? ltrim($nummer, "0") : hexdec(implode("", array_reverse(str_split(trim($nummer))))); + + $this->db->trans_start(); + + if ($betriebsmitteltyp != 'Inventar') { + $this->BetriebsmittelModel->addOrder('updateamum', 'DESC'); + if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer === null) { + $result = $this->BetriebsmittelModel->loadWhere([ + 'betriebsmitteltyp' => $betriebsmitteltyp, + 'nummer2' => $nummer2 + ]); + } else { + $result = $this->BetriebsmittelModel->loadWhere([ + 'betriebsmitteltyp' => $betriebsmitteltyp, + 'nummer' => $nummer + ]); + } + $data = $this->getDataOrTerminateWithError($result); + + if ($data) { + $data = current($data); + if ($data->nummer !== $nummer || $data->nummer2 !== $nummer2 || $data->beschreibung !== $beschreibung) { + $result = $this->BetriebsmittelModel->update($data->betriebsmittel_id, [ + 'nummer' => $nummer, + 'nummer2' => $nummer2, + 'beschreibung' => $beschreibung, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ]); + $this->getDataOrTerminateWithError($result); + } + $betriebsmittel_id = $data->betriebsmittel_id; + } else { + $result = $this->BetriebsmittelModel->insert([ + 'betriebsmitteltyp' => $betriebsmitteltyp, + 'nummer' => $nummer, + 'nummer2' => $nummer2, + 'beschreibung' => $beschreibung, + 'reservieren' => false, + 'ort_kurzbz' => null, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID(), + ]); + $betriebsmittel_id = $this->getDataOrTerminateWithError($result); + } + } + + $result = $this->BetriebsmittelpersonModel->insert([ + 'person_id' => $person_id, + 'betriebsmittel_id' => $betriebsmittel_id, + 'anmerkung' => $anmerkung, + 'kaution' => $kaution, + 'ausgegebenam' => $ausgegebenam, + 'retouram' => $retouram, + 'uid' => $uid, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]); + + $data = $this->getDataOrTerminateWithError($result); + + $this->db->trans_complete(); + + $this->terminateWithSuccess(true); + } + + public function updateBetriebsmittel($betriebsmittelperson_id) + { + $this->validateNewOrUpdate(); + + $betriebsmitteltyp = $this->input->post('betriebsmitteltyp'); + $nummer = $this->input->post('nummer'); + $nummer2 = $this->input->post('nummer2'); + $beschreibung = $this->input->post('beschreibung'); + $betriebsmittel_id = $this->input->post('betriebsmittel_id'); + $anmerkung = $this->input->post('anmerkung'); + $kaution = $this->input->post('kaution'); + $ausgegebenam = $this->input->post('ausgegebenam'); + $retouram = $this->input->post('retouram'); + + // NOTE(chris): transform_kartennummer + if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer) + $nummer = is_numeric($nummer) ? ltrim($nummer, "0") : hexdec(implode("", array_reverse(str_split(trim($nummer))))); + + $this->db->trans_start(); + + if ($betriebsmitteltyp != 'Inventar') { + $found = false; + if ($nummer !== null && $betriebsmittel_id !== null) { + $result = $this->BetriebsmittelModel->load($betriebsmittel_id); + $data = $this->getDataOrTerminateWithError($result); + if ($data && current($data)->nummer == $nummer) { + $found = true; + } + } + + if (!$found) { + $this->BetriebsmittelModel->addOrder('updateamum', 'DESC'); + if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer === null) { + $result = $this->BetriebsmittelModel->loadWhere([ + 'betriebsmitteltyp' => $betriebsmitteltyp, + 'nummer2' => $nummer2 + ]); + } else { + $result = $this->BetriebsmittelModel->loadWhere([ + 'betriebsmitteltyp' => $betriebsmitteltyp, + 'nummer' => $nummer + ]); + } + $data = $this->getDataOrTerminateWithError($result); + } + + if ($data) { + $data = current($data); + if ($data->nummer !== $nummer || $data->nummer2 !== $nummer2 || $data->beschreibung !== $beschreibung) { + $result = $this->BetriebsmittelModel->update($data->betriebsmittel_id, [ + 'nummer' => $nummer, + 'nummer2' => $nummer2, + 'beschreibung' => $beschreibung, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ]); + $this->getDataOrTerminateWithError($result); + } + $betriebsmittel_id = $data->betriebsmittel_id; + } else { + $result = $this->BetriebsmittelModel->insert([ + 'betriebsmitteltyp' => $betriebsmitteltyp, + 'nummer' => $nummer, + 'nummer2' => $nummer2, + 'beschreibung' => $beschreibung, + 'reservieren' => false, + 'ort_kurzbz' => null, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID(), + ]); + $betriebsmittel_id = $this->getDataOrTerminateWithError($result); + } + } + + $result = $this->BetriebsmittelpersonModel->update($betriebsmittelperson_id, [ + 'betriebsmittel_id' => $betriebsmittel_id, + 'anmerkung' => $anmerkung, + 'kaution' => $kaution, + 'ausgegebenam' => $ausgegebenam, + 'retouram' => $retouram, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ]); + + $data = $this->getDataOrTerminateWithError($result); + + $this->db->trans_complete(); + + $this->terminateWithSuccess(true); + } + + public function loadBetriebsmittel($betriebsmittelperson_id) + { + $result = $this->BetriebsmittelpersonModel->getBetriebsmittelData($betriebsmittelperson_id, 'betriebsmittelperson_id'); + + if (isError($result)) { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) { + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Betriebsmittelperson_id']), self::ERROR_TYPE_GENERAL); + } + + $this->terminateWithSuccess(current(getData($result))); + } + + public function deleteBetriebsmittel($betriebsmittelperson_id) + { + $result = $this->BetriebsmittelpersonModel->delete( + array('betriebsmittelperson_id' => $betriebsmittelperson_id, + ) + ); + + if (isError($result)) { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Betriebsmittelperson_id']), self::ERROR_TYPE_GENERAL); + } + return $this->outputJsonSuccess(current(getData($result))); + } + + public function getTypenBetriebsmittel() + { + $this->load->model('ressource/Betriebsmitteltyp_model', 'BetriebsmitteltypModel'); + + $this->BetriebsmitteltypModel->addOrder('beschreibung', 'ASC'); + $result = $this->BetriebsmitteltypModel->load(); // load All + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function loadInventarliste($searchString) + { + $result = $this->BetriebsmittelModel->loadInventarliste($searchString); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} + + diff --git a/application/controllers/api/frontend/v1/checkperson/CheckPerson.php b/application/controllers/api/frontend/v1/checkperson/CheckPerson.php new file mode 100644 index 000000000..321893610 --- /dev/null +++ b/application/controllers/api/frontend/v1/checkperson/CheckPerson.php @@ -0,0 +1,141 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +class CheckPerson extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'updatePersonUnrulyStatus' => array('basis/mitarbeiter:rw', 'student/antragfreigabe:rw', 'student/studierendenantrag:rw'), + 'filterPerson' => array('basis/mitarbeiter:rw', 'student/antragfreigabe:rw', 'student/studierendenantrag:rw'), + 'checkUnruly' => array('basis/mitarbeiter:r', 'student/antragfreigabe:r', 'student/studierendenantrag:r', 'infocenter:r'), + 'checkDuplicate' => array('infocenter:r'), + ]); + + $this->_ci =& get_instance(); + $this->_ci->load->model('person/Person_model', 'PersonModel'); + } + + public function updatePersonUnrulyStatus() + { + $data = json_decode($this->input->raw_input_stream, true); + + $person_id = $data['person_id']; + $unruly = $data['unruly']; + + $result = $this->_ci->PersonModel->updateUnruly($person_id, $unruly); + + if(isError($result)) { + $this->terminateWithError($result); + } else if (isSuccess($result)) { + $this->terminateWithSuccess($result); + } + + } + + public function checkDuplicate() { + + $person_id = $this->input->post('person_id'); + + $result = $this->_ci->PersonModel->checkDuplicate($person_id); + + if (isSuccess($result)) + $this->terminateWithSuccess($result); + else + $this->terminateWithError('Error when searching for person'); + + } + + // performs strict check over vorname, nachname, gebdatum + public function checkUnruly() { + + $vorname = $this->input->post('vorname'); + $nachname = $this->input->post('nachname'); + $gebdatum = $this->input->post('gebdatum'); + + $result = $this->_ci->PersonModel->checkUnruly($vorname, $nachname, $gebdatum); + + if (isSuccess($result)) + $this->terminateWithSuccess($result); + else + $this->terminateWithError('Error when searching for person'); + } + + // filters nachname on similarity and vorname/gebdatum are optional + public function filterPerson() { + $payload = json_decode($this->input->raw_input_stream, TRUE); + + $nachnameString = ''; + $vornameString = ''; + $filterUnruly = true; + $birthdateString = ''; + + if(array_key_exists( 'nachname', $payload) ) { + $nachnameString = $payload['nachname']; + } + + if(array_key_exists('vorname', $payload)) { + $vornameString = $payload['vorname']; + } + + if(array_key_exists('unruly', $payload)){ + $filterUnruly = $payload['unruly']; + } + + if(array_key_exists('gebdatum', $payload)) { + // TODO: enable if gebdatum filter for unrulys is desired +// $birthdateString = $payload['gebdatum']; + } + + $parametersArray = array($nachnameString); + $where ="p.nachname~* ? "; + if (mb_strlen($nachnameString) == 2) + { + $where = "p.nachname=? "; + } + + if(isset($vornameString) && $vornameString != '') + { + $where.= " AND p.vorname~*?"; + $parametersArray[] = $vornameString; + } + + if(isset($birthdateString) && $birthdateString != '') + { + $where.=" AND p.gebdatum=?"; + $parametersArray[] = $birthdateString; + } + + if(isset($filterUnruly)) + { + $where.=" AND p.unruly=?"; + $parametersArray[] = $filterUnruly; + } + + $result = $this->_ci->PersonModel->checkUnrulyWhere($where, $parametersArray); + + if (isSuccess($result)) + $this->terminateWithSuccess($result); + else + $this->terminateWithError('Error when searching for person'); + + + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php new file mode 100644 index 000000000..636c8e3f3 --- /dev/null +++ b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php @@ -0,0 +1,65 @@ + array( + 'lehre/lehrveranstaltung:rw' + ) + )); + + // Load model LehrveranstaltungModel + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + } + + /** + * Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes of given Berechtigung, + * that are assigned to a template. This data structure can be used for nested tabulators' data tree. + * + * @param null|string $studiensemester_kurzbz + * @param null|string $berechtigung + * @return array|stdClass|null + */ + public function getTemplateLvTree() + { + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + $berechtigung = $this->input->get('berechtigung'); + + if ($berechtigung) + { + $oe_permissions = $this->permissionlib->getOE_isEntitledFor($berechtigung); + if(!$oe_permissions) $oe_permissions = []; + + $result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz, $oe_permissions); + } + else + { + $result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz); + } + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess((getData($result) ?: [])); + } +} diff --git a/application/controllers/api/frontend/v1/notiz/NotizPerson.php b/application/controllers/api/frontend/v1/notiz/NotizPerson.php new file mode 100644 index 000000000..cb9d31024 --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizPerson.php @@ -0,0 +1,51 @@ + ['admin:r', 'assistenz:r'], + 'getNotizen' => ['admin:r', 'assistenz:r'], + 'loadNotiz' => ['admin:r', 'assistenz:r'], + 'addNewNotiz' => ['admin:rw', 'assistenz:rw'], + 'updateNotiz' => ['admin:rw', 'assistenz:rw'], + 'deleteNotiz' => ['admin:rw', 'assistenz:rw'], + 'loadDokumente' => ['admin:r', 'assistenz:r'], + 'getMitarbeiter' => ['admin:r', 'assistenz:r'], + 'isBerechtigt' => ['admin:r', 'assistenz:r'], + ]); + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "person_id") + { + return $this->terminateWithError($this->p->t('ui', 'error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + + //TODO define permission + if (!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre', 'error_keineSchreibrechte'); + + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + return $this->outputJsonSuccess(true); + } + + public function loadDokumente() + { + $notiz_id = $this->input->post('notiz_id'); + + // TODO(chris): make CI variant of endpoint + $this->NotizModel->addSelect($this->NotizModel->escape(base_url('content/notizdokdownload.php?id=')) . ' || campus.tbl_dms_version.dms_id AS preview'); + + return parent::loadDokumente(); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/organisation/Studiensemester.php b/application/controllers/api/frontend/v1/organisation/Studiensemester.php new file mode 100644 index 000000000..72a449aaa --- /dev/null +++ b/application/controllers/api/frontend/v1/organisation/Studiensemester.php @@ -0,0 +1,118 @@ + self::PERM_LOGGED, + 'getAktNext' => self::PERM_LOGGED + ) + ); + // Load model StudiensemesterModel + $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); + } + + /** + * Get all Studiensemester. + * + * @param null|string $order Sorting order for the Studiensemester, 'asc' or 'desc'. Defaults to 'asc'. + * @param null|string $start Start date of the displayed Studiensemester in the format 'YYYY-MM-DD'. + * If provided, only Studiensemester starting from this date onwards will be returned. + * eg. '2020-09-01' will start with WS2020. + */ + public function getAll() + { + $order = $this->input->get('order'); + $start = $this->input->get('start'); + + if (strcasecmp($order, 'DESC') == 0) + { + $this->StudiensemesterModel->addOrder('ende', 'DESC'); + } + else + { + $this->StudiensemesterModel->addOrder('ende', 'ASC'); + } + + if ($start) + { + $result = $this->StudiensemesterModel->loadWhere([ + 'start >= ' => $start + ]); + } + else + { + $result = $this->StudiensemesterModel->load(); + } + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess((getData($result) ?: [])); + } + + /** + * @return void + */ + public function getAktNext() + { + $semester = $this->input->get('semester'); + + $result = null; + + if (!is_numeric($semester)) + { + $result = $this->StudiensemesterModel->loadWhere(array('start <=' => 'NOW()', 'ende >=' => 'NOW()')); + } + + if (!hasData($result)) + { + $this->StudiensemesterModel->addOrder('ende'); + $this->StudiensemesterModel->addLimit(1); + + $whereArray = array('ende >=' => 'NOW()'); + + if (is_numeric($semester)) + { + if ($semester % 2 == 0) + { + $ss = 'SS'; + } + else + { + $ss = 'WS'; + } + + $whereArray['SUBSTRING(studiensemester_kurzbz FROM 1 FOR 2) ='] = $ss; + } + + $result = $this->StudiensemesterModel->loadWhere($whereArray); + } + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess((getData($result) ?: '')); + } +} diff --git a/application/controllers/api/frontend/v1/studstatus/Abmeldung.php b/application/controllers/api/frontend/v1/studstatus/Abmeldung.php new file mode 100644 index 000000000..aada1f436 --- /dev/null +++ b/application/controllers/api/frontend/v1/studstatus/Abmeldung.php @@ -0,0 +1,187 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use \REST_Controller as REST_Controller; +use \Studierendenantrag_model as Studierendenantrag_model; + +/** + * This controller operates between (interface) the JS (GUI) and the AntragLib (back-end) + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Abmeldung extends FHCAPI_Controller +{ + + /** + * Calls the parent's constructor and loads the AntragLib + */ + public function __construct() + { + parent::__construct([ + 'getDetailsForNewAntrag' => self::PERM_LOGGED, + 'getDetailsForAntrag' => self::PERM_LOGGED, + 'createAntrag' => self::PERM_LOGGED, + 'cancelAntrag' => self::PERM_LOGGED + ]); + + // Libraries + $this->load->library('AntragLib'); + + // Load language phrases + $this->loadPhrases([ + 'studierendenantrag' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Retrieves data of the current studiengang for the current user + */ + + public function getDetailsForNewAntrag($prestudent_id) + { + if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, true)) + $this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN); + + $result = $this->antraglib->getPrestudentAbmeldeBerechtigt($prestudent_id); + $result = $this->getDataOrTerminateWithError($result); + + if (!$result) { + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_no_student'), + self::ERROR_TYPE_AUTH, + REST_Controller::HTTP_FORBIDDEN + ); + } elseif ($result == -3) { + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_stg_blacklist'), + self::ERROR_TYPE_AUTH, + REST_Controller::HTTP_FORBIDDEN + ); + } elseif ($result == -1) { + $result = $this->antraglib->getDetailsForLastAntrag( + $prestudent_id, + [ + Studierendenantrag_model::TYP_ABMELDUNG, + Studierendenantrag_model::TYP_ABMELDUNG_STGL + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $data->canCancel = ( + $data->status == Studierendenantragstatus_model::STATUS_CREATED && + $this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id) + ); + + $this->terminateWithSuccess($data); + } + + $result = $this->antraglib->getDetailsForNewAntrag($prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getDetailsForAntrag($studierendenantrag_id) + { + if (!$this->antraglib->isEntitledToShowAntrag($studierendenantrag_id)) + return show_404(); + + $result = $this->antraglib->getDetailsForAntrag($studierendenantrag_id); + + $data = $this->getDataOrTerminateWithError($result); + + if ($data->typ !== Studierendenantrag_model::TYP_ABMELDUNG_STGL && $data->typ !== Studierendenantrag_model::TYP_ABMELDUNG) + return show_404(); + + $data->canCancel = ( + $data->status == Studierendenantragstatus_model::STATUS_CREATED && + $this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id) + ); + + $this->terminateWithSuccess($data); + } + + public function createAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required'); + $this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required'); + $this->form_validation->set_rules('grund', 'Grund', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $grund = $this->input->post('grund'); + $studiensemester = $this->input->post('studiensemester'); + $prestudent_id = $this->input->post('prestudent_id'); + + $result = $this->antraglib->getPrestudentAbmeldeBerechtigt($prestudent_id); + $result = $this->getDataOrTerminateWithError($result); + if (!$result) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL); + elseif ($result == -3) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL); + elseif ($result < 0) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL); + + $result = $this->antraglib->createAbmeldung($prestudent_id, $studiensemester, getAuthUID(), $grund); + $data = $this->getDataOrTerminateWithError($result); + + $result = $this->antraglib->getDetailsForAntrag($data); + if (!hasData($result)) + return $this->terminateWithSuccess(true); + + $data = getData($result); + $data->canCancel = (boolean)$this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id); + + $this->terminateWithSuccess($data); + } + + public function cancelAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('antrag_id', 'Antrag ID', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $antrag_id = $this->input->post('antrag_id'); + + if (!$this->antraglib->isEntitledToCancelAntrag($antrag_id)) + $this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN); + + $result = $this->antraglib->cancelAntrag($antrag_id, getAuthUID()); + $this->getDataOrTerminateWithError($result); + + $result = $this->antraglib->getDetailsForAntrag($antrag_id); + if (!hasData($result)) + $this->terminateWithSuccess($antrag_id); + + $data = getData($result); + + $this->terminateWithSuccess($data); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/studstatus/Leitung.php b/application/controllers/api/frontend/v1/studstatus/Leitung.php new file mode 100644 index 000000000..87099ad74 --- /dev/null +++ b/application/controllers/api/frontend/v1/studstatus/Leitung.php @@ -0,0 +1,429 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use \stdClass as stdClass; +use \Studierendenantrag_model as Studierendenantrag_model; + +/** + * This controller operates between (interface) the JS (GUI) and the AntragLib (back-end) + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Leitung extends FHCAPI_Controller +{ + + /** + * Calls the parent's constructor and loads the AntragLib + */ + public function __construct() + { + parent::__construct([ + 'getActiveStgs' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'], + 'getAntraege' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'], + 'getHistory' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'], + 'getPrestudents' => 'student/studierendenantrag:w', + 'approveAntrag' => 'student/antragfreigabe:w', + 'rejectAntrag' => 'student/antragfreigabe:w', + 'reopenAntrag' => 'student/studierendenantrag:w', + 'pauseAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'], + 'unpauseAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'], + 'objectAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'], + 'approveObjection' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'], + 'denyObjection' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'] + ]); + + // Libraries + $this->load->library('AntragLib'); + + // Load language phrases + $this->loadPhrases([ + 'studierendenantrag', + 'lehre' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + public function getActiveStgs() + { + $studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe') ?: []; + $studiengaenge = array_merge($studiengaenge, $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag') ?: []); + + $result = $this->StudierendenantragModel->loadStgsWithAntraege($studiengaenge); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getAntraege($studiengang = null, $extra = null) + { + if ($studiengang && $studiengang == 'todo') { + $studiengang = $extra; + $extra = true; + } else { + $extra = false; + } + + $studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe'); + if(!is_array($studiengaenge)) + $studiengaenge = []; + + + $stgsNeuanlage = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag'); + if(!is_array($stgsNeuanlage)) + $stgsNeuanlage = []; + + $studiengaenge = array_unique(array_merge($studiengaenge, $stgsNeuanlage)); + + if ($studiengang) { + if (!in_array($studiengang, $studiengaenge)) + $this->terminateWithError( + 'Forbidden', + self::ERROR_TYPE_AUTH, + REST_Controller::HTTP_FORBIDDEN + ); + $studiengaenge = [$studiengang]; + } + + $antraege = []; + if ($studiengaenge) { + $result = $extra + ? $this->StudierendenantragModel->loadActiveForStudiengaenge($studiengaenge) + : $this->StudierendenantragModel->loadForStudiengaenge($studiengaenge); + + $antraege = $this->getDataOrTerminateWithError($result); + } + + $this->terminateWithSuccess($antraege ?: []); + } + + public function getHistory($studierendenantrag_id) + { + if (!$this->antraglib->isEntitledToSeeHistoryForAntrag($studierendenantrag_id)) + $this->terminateWithError( + 'Forbidden', + self::ERROR_TYPE_AUTH, + REST_Controller::HTTP_FORBIDDEN + ); + + $result = $this->antraglib->getAntragHistory($studierendenantrag_id); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data ?: []); + } + + public function getPrestudents() + { + $query = $this->input->post('query'); + + $studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag'); + + $result = $this->antraglib->getAktivePrestudentenInStgs($studiengaenge, $query); + $result = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($result ?: []); + } + + public function approveAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'studierendenantrag_id', + 'Studierenden Antrag', + [ + 'required', + ['isEntitledToApproveAntrag', [$this->antraglib, 'isEntitledToApproveAntrag']], + ], + [ + 'isEntitledToApproveAntrag' => $this->p->t('studierendenantrag', 'error_no_right') + ] + ); + $this->form_validation->set_rules( + 'typ', + 'Typ', + 'required|in_list[' . implode(',', [ + Studierendenantrag_model::TYP_ABMELDUNG, + Studierendenantrag_model::TYP_ABMELDUNG_STGL, + Studierendenantrag_model::TYP_UNTERBRECHUNG, + Studierendenantrag_model::TYP_WIEDERHOLUNG + ]) . ']' + ); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studierendenantrag_id = $this->input->post('studierendenantrag_id'); + switch ($this->input->post('typ')) { + case Studierendenantrag_model::TYP_ABMELDUNG: + case Studierendenantrag_model::TYP_ABMELDUNG_STGL: + $result = $this->antraglib->approveAbmeldung([$studierendenantrag_id], getAuthUID()); + break; + case Studierendenantrag_model::TYP_UNTERBRECHUNG: + $result = $this->antraglib->approveUnterbrechung([$studierendenantrag_id], getAuthUID()); + break; + case Studierendenantrag_model::TYP_WIEDERHOLUNG: + $result = $this->antraglib->approveWiederholung($studierendenantrag_id, getAuthUID()); + break; + } + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($studierendenantrag_id); + } + + public function rejectAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'studierendenantrag_id', + 'Studierenden Antrag', + [ + 'required', + ['isEntitledToRejectAntrag', [$this->antraglib, 'isEntitledToRejectAntrag']], + ], + [ + 'isEntitledToRejectAntrag' => $this->p->t('studierendenantrag', 'error_no_right') + ] + ); + $this->form_validation->set_rules('grund', 'Grund', 'required'); + $this->form_validation->set_rules( + 'typ', + 'Typ', + 'required|in_list[' . implode(',', [ + Studierendenantrag_model::TYP_UNTERBRECHUNG + ]) . ']' + ); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studierendenantrag_id = $this->input->post('studierendenantrag_id'); + $grund = $this->input->post('grund'); + + $result = $this->antraglib->rejectUnterbrechung([$studierendenantrag_id], getAuthUID(), $grund); + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($studierendenantrag_id); + } + + public function reopenAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'studierendenantrag_id', + 'Studierenden Antrag', + [ + 'required', + ['isEntitledToReopenAntrag', [$this->antraglib, 'isEntitledToReopenAntrag']], + ], + [ + 'isEntitledToReopenAntrag' => $this->p->t('studierendenantrag', 'error_no_right') + ] + ); + $this->form_validation->set_rules( + 'typ', + 'Typ', + 'required|in_list[' . implode(',', [ + Studierendenantrag_model::TYP_WIEDERHOLUNG + ]) . ']' + ); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studierendenantrag_id = $this->input->post('studierendenantrag_id'); + + $result = $this->antraglib->reopenWiederholung($studierendenantrag_id, getAuthUID()); + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($studierendenantrag_id); + } + + public function pauseAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'studierendenantrag_id', + 'Studierenden Antrag', + [ + 'required', + ['isEntitledToPauseAntrag', [$this->antraglib, 'isEntitledToPauseAntrag']], + ['antragCanBeManualPaused', [$this->antraglib, 'antragCanBeManualPaused']] + ], + [ + 'isEntitledToPauseAntrag' => $this->p->t('studierendenantrag', 'error_no_right'), + 'antragCanBeManualPaused' => $this->p->t( + 'studierendenantrag', + 'error_not_pauseable', + ['id' => $this->input->post('studierendenantrag_id')] + ) + ] + ); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studierendenantrag_id = $this->input->post('studierendenantrag_id'); + + $result = $this->antraglib->pauseAntrag($studierendenantrag_id, getAuthUID()); + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($studierendenantrag_id); + } + + public function unpauseAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'studierendenantrag_id', + 'Studierenden Antrag', + [ + 'required', + ['isEntitledToUnpauseAntrag', [$this->antraglib, 'isEntitledToUnpauseAntrag']], + ['antragCanBeManualUnpaused', [$this->antraglib, 'antragCanBeManualUnpaused']] + ], + [ + 'isEntitledToUnpauseAntrag' => $this->p->t('studierendenantrag', 'error_no_right'), + 'antragCanBeManualUnpaused' => $this->p->t( + 'studierendenantrag', + 'error_not_paused', + ['id' => $this->input->post('studierendenantrag_id')] + ) + ] + ); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studierendenantrag_id = $this->input->post('studierendenantrag_id'); + + $result = $this->antraglib->unpauseAntrag($studierendenantrag_id, getAuthUID()); + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($studierendenantrag_id); + } + + public function objectAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'studierendenantrag_id', + 'Studierenden Antrag', + [ + 'required', + ['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']], + ['canBeObjected', function ($a) { + return $this->antraglib->hasType($a, Studierendenantrag_model::TYP_ABMELDUNG_STGL); + }] + ], + [ + 'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'), + 'canBeObjected' => $this->p->t( + 'studierendenantrag', + 'error_no_objection' + ) + ] + ); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studierendenantrag_id = $this->input->post('studierendenantrag_id'); + + $result = $this->antraglib->objectAbmeldung($studierendenantrag_id, getAuthUID()); + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($studierendenantrag_id); + } + + public function approveObjection() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'studierendenantrag_id', + 'Studierenden Antrag', + [ + 'required', + ['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']], + ['isObjected', function ($a) { + return $this->antraglib->hasStatus($a, Studierendenantragstatus_model::STATUS_OBJECTED); + }] + ], + [ + 'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'), + 'isObjected' => $this->p->t( + 'studierendenantrag', + 'error_not_objected' + ) + ] + ); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studierendenantrag_id = $this->input->post('studierendenantrag_id'); + + $result = $this->antraglib->cancelAntrag($studierendenantrag_id, getAuthUID()); + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($studierendenantrag_id); + } + + public function denyObjection() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'studierendenantrag_id', + 'Studierenden Antrag', + [ + 'required', + ['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']], + ['isObjected', function ($a) { + return $this->antraglib->hasStatus($a, Studierendenantragstatus_model::STATUS_OBJECTED); + }] + ], + [ + 'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'), + 'isObjected' => $this->p->t( + 'studierendenantrag', + 'error_not_objected' + ) + ] + ); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studierendenantrag_id = $this->input->post('studierendenantrag_id'); + $grund = $this->input->post('grund'); + + $result = $this->antraglib->denyObjectionAbmeldung($studierendenantrag_id, getAuthUID(), $grund); + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($studierendenantrag_id); + } +} diff --git a/application/controllers/api/frontend/v1/studstatus/Unterbrechung.php b/application/controllers/api/frontend/v1/studstatus/Unterbrechung.php new file mode 100644 index 000000000..abf58cf4f --- /dev/null +++ b/application/controllers/api/frontend/v1/studstatus/Unterbrechung.php @@ -0,0 +1,226 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use \Studierendenantrag_model as Studierendenantrag_model; +use \DateTime as DateTime; + +/** + * This controller operates between (interface) the JS (GUI) and the AntragLib (back-end) + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Unterbrechung extends FHCAPI_Controller +{ + + /** + * Calls the parent's constructor and loads the AntragLib + */ + public function __construct() + { + parent::__construct([ + 'getDetailsForNewAntrag' => self::PERM_LOGGED, + 'getDetailsForAntrag' => self::PERM_LOGGED, + 'createAntrag' => self::PERM_LOGGED, + 'cancelAntrag' => self::PERM_LOGGED + ]); + + // Configs + $this->load->config('studierendenantrag'); + + // Libraries + $this->load->library('AntragLib'); + + // Load language phrases + $this->loadPhrases([ + 'studierendenantrag', + 'ui' + ]); + } + + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + public function getDetailsForNewAntrag($prestudent_id) + { + if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, false)) + $this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN); + + $result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($prestudent_id); + $result = $this->getDataOrTerminateWithError($result); + + if (!$result) { + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_no_student'), + self::ERROR_TYPE_AUTH, + REST_Controller::HTTP_FORBIDDEN + ); + } elseif ($result == -1) { + $result = $this->antraglib->getDetailsForLastAntrag($prestudent_id, Studierendenantrag_model::TYP_UNTERBRECHUNG); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($data); + } elseif ($result == -2) { + $result = $this->antraglib->getDetailsForLastAntrag($prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_pending', [ + 'typ' => $this->p->t('studierendenantrag', 'antrag_typ_' . $result->typ) + ])); + } elseif ($result == -3) { + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_stg_blacklist'), + self::ERROR_TYPE_AUTH, + REST_Controller::HTTP_FORBIDDEN + ); + } + + $result = $this->antraglib->getDetailsForNewAntrag($prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + + $data->studiensemester = $this->antraglib->getSemesterForUnterbrechung($prestudent_id, null); + + $this->terminateWithSuccess($data); + } + + public function getDetailsForAntrag($studierendenantrag_id) + { + if (!$this->antraglib->isEntitledToShowAntrag($studierendenantrag_id)) + return show_404(); + + $result = $this->antraglib->getDetailsForAntrag($studierendenantrag_id); + + $data = $this->getDataOrTerminateWithError($result); + + if ($data->typ !== Studierendenantrag_model::TYP_UNTERBRECHUNG) + return show_404(); + + $this->terminateWithSuccess($data); + } + + public function createAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required'); + $this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required'); + $this->form_validation->set_rules('grund', 'Grund', 'required'); + $this->form_validation->set_rules( + 'datum_wiedereinstieg', + 'Datum Wiedereinstieg', + 'required|callback_isValidDate|callback_isDateInFuture', + [ + 'isValidDate' => $this->p->t('ui', 'error_invalid_date'), + 'isDateInFuture' => $this->p->t('ui', 'error_invalid_date') + ] + ); + + if (!$this->form_validation->run()) { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $grund = $this->input->post('grund'); + $studiensemester = $this->input->post('studiensemester'); + $prestudent_id = $this->input->post('prestudent_id'); + $datum_wiedereinstieg = $this->input->post('datum_wiedereinstieg'); + $dms_id = null; + + $result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($prestudent_id, $studiensemester, $datum_wiedereinstieg); + + $result = $this->getDataOrTerminateWithError($result); + + if (!$result) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL); + elseif ($result == -3) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL); + elseif ($result < 0) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL); + + if (isset($_FILES['attachment']) && (!isset($_FILES['attachment']['error']) || $_FILES['attachment']['error'] != UPLOAD_ERR_NO_FILE)) { + $this->load->library('DmsLib'); + + $dms = $this->config->item('unterbrechung_dms'); + if (!count(array_filter($dms, function ($v) { + return $v !== null; + }))) + $dms = ['kategorie_kurzbz' => 'Akte']; + $dms['version'] = 0; + + $allowed_filetypes = $this->config->item('unterbrechung_dms_filetypes') ?: ['*']; + $result = $this->dmslib->upload($dms, 'attachment', $allowed_filetypes); + + $data = $this->getDataOrTerminateWithError($result); + + $dms_id = $data['dms_id']; + } + + $result = $this->antraglib->createUnterbrechung($prestudent_id, $studiensemester, getAuthUID(), $grund, $datum_wiedereinstieg, $dms_id); + + $antragId = $this->getDataOrTerminateWithError($result); + + $result = $this->antraglib->getDetailsForAntrag($antragId); + + if (!hasData($result)) + $this->terminateWithSuccess($antragId); + + $this->terminateWithSuccess(getData($result)); + } + + public function cancelAntrag() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('antrag_id', 'Antrag ID', 'required'); + + if (!$this->form_validation->run()) { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $antrag_id = $this->input->post('antrag_id'); + + $result = $this->antraglib->cancelAntrag($antrag_id, getAuthUID()); + + $this->getDataOrTerminateWithError($result); + + $result = $this->antraglib->getDetailsForAntrag($antrag_id); + + if (!hasData($result)) + return $this->terminateWithSuccess($antrag_id); + + $this->terminateWithSuccess(getData($result)); + } + + public function isValidDate($date) + { + try { + new DateTime($date); + } catch (Exception $e) { + return false; + } + return true; + } + + public function isDateInFuture($date) + { + return new DateTime() < new DateTime($date); + } +} diff --git a/application/controllers/api/frontend/v1/studstatus/Wiederholung.php b/application/controllers/api/frontend/v1/studstatus/Wiederholung.php new file mode 100644 index 000000000..1a8f70d52 --- /dev/null +++ b/application/controllers/api/frontend/v1/studstatus/Wiederholung.php @@ -0,0 +1,258 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use \REST_Controller as REST_Controller; +use \Studierendenantragstatus_model as Studierendenantragstatus_model; + +/** + * This controller operates between (interface) the JS (GUI) and the AntragLib (back-end) + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Wiederholung extends FHCAPI_Controller +{ + + /** + * Calls the parent's constructor and loads the FilterCmptLib + */ + public function __construct() + { + parent::__construct([ + 'getDetailsForNewAntrag' => self::PERM_LOGGED, + 'createAntrag' => self::PERM_LOGGED, + 'cancelAntrag' => self::PERM_LOGGED, + 'getLvs' => self::PERM_LOGGED, + 'saveLvs' => ['student/studierendenantrag:w'] + ]); + + // Libraries + $this->load->library('AntragLib'); + + // Load language phrases + $this->loadPhrases([ + 'global', + 'studierendenantrag' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Retrieves data of the current studiengang for the current user + */ + + public function getDetailsForNewAntrag($prestudent_id) + { + if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, false)) + $this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN); + + $result = $this->antraglib->getPrestudentWiederholungsBerechtigt($prestudent_id); + $result = $this->getDataOrTerminateWithError($result); + + if (!$result) { + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_no_student_no_failed_exam'), + self::ERROR_TYPE_AUTH, + REST_Controller::HTTP_FORBIDDEN + ); + } elseif ($result == -1) { + $result = $this->antraglib->getDetailsForLastAntrag($prestudent_id, Studierendenantrag_model::TYP_WIEDERHOLUNG); + $data = $this->getDataOrTerminateWithError($result); + + $result = $this->antraglib->getFailedExamForPrestudent($prestudent_id, $data->datum, $data->studiensemester_kurzbz); + // NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt() + $pruefungsdata = current(getData($result)); + + $data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz; + $data->lvbezeichnung = $pruefungsdata->lvbezeichnung; + $data->pruefungsdatum = $pruefungsdata->datum; + + $this->terminateWithSuccess($data); + } elseif ($result == -2) { + $result = $this->antraglib->getDetailsForLastAntrag($prestudent_id); + $result = $this->getDataOrTerminateWithError($result); + + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_antrag_pending', [ + 'typ' => $this->p->t('studierendenantrag', 'antrag_typ_' . $result->typ) + ]), + self::ERROR_TYPE_GENERAL, + REST_Controller::HTTP_BAD_REQUEST + ); + } elseif ($result == -3) { + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_stg_blacklist'), + self::ERROR_TYPE_GENERAL, + REST_Controller::HTTP_BAD_REQUEST + ); + } + + $result = $this->antraglib->getDetailsForNewAntrag($prestudent_id); + $data = $this->getDataOrTerminateWithError($result); + + $result = $this->antraglib->getFailedExamForPrestudent($prestudent_id); + // NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt() + $pruefungsdata = current(getData($result)); + + $data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz; + $data->lvbezeichnung = $pruefungsdata->lvbezeichnung; + $data->pruefungsdatum = $pruefungsdata->datum; + + $this->terminateWithSuccess($data); + } + + public function createAntrag() + { + $this->createAntragWithStatus(true); + } + + public function cancelAntrag() + { + $this->createAntragWithStatus(false); + } + + protected function createAntragWithStatus($repeat) + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required'); + $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $prestudent_id = $this->input->post('prestudent_id'); + $studiensemester = $this->input->post('studiensemester'); + + $result = $this->antraglib->getPrestudentWiederholungsBerechtigt($prestudent_id); + $result = $this->getDataOrTerminateWithError($result); + + if (!$result) { + $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL); + } elseif ($result == -1) { + $result = $this->PrestudentstatusModel->getLastStatus($prestudent_id); + $result = $this->getDataOrTerminateWithError($result); + if (!$result) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_prestudentstatus', [ + 'prestudent_id' => $prestudent_id + ]), self::ERROR_TYPE_GENERAL); + if (!in_array(current($result)->status_kurzbz, $this->config->item('antrag_prestudentstatus_whitelist'))) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL); + } elseif ($result == -2) { + $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL); + } elseif ($result == -3) { + $this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL); + } + + $result = $this->antraglib->createWiederholung($prestudent_id, $studiensemester, getAuthUID(), $repeat); + $antragId = $this->getDataOrTerminateWithError($result); + + $result = $this->antraglib->getDetailsForAntrag($antragId); + + if (!hasData($result)) + $this->terminateWithSuccess(true); + + $data = getData($result); + + $result = $this->antraglib->getFailedExamForPrestudent($prestudent_id); + // NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt() + $pruefungsdata = current(getData($result)); + + $data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz; + $data->lvbezeichnung = $pruefungsdata->lvbezeichnung; + $data->pruefungsdatum = $pruefungsdata->datum; + + $this->terminateWithSuccess($data); + } + + + public function getLvs($antrag_id) + { + $result = $this->antraglib->getLvsForAntrag($antrag_id); + if (isError($result)) { + $error = getError($result); + if ($error == 'Forbidden') + $this->terminateWithError( + $error, + self::ERROR_TYPE_AUTH, + REST_Controller::HTTP_FORBIDDEN + ); + $this->terminateWithError( + $error, + self::ERROR_TYPE_GENERAL + ); + } + $lvs = getData($result); + + $this->terminateWithSuccess($lvs); + } + + public function saveLvs() + { + $forbiddenLvs = $this->input->post('forbiddenLvs'); + $mandatoryLvs = $this->input->post('mandatoryLvs'); + $antragsLvs = array_merge($forbiddenLvs, $mandatoryLvs); + + if (!$antragsLvs) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_lv'), self::ERROR_TYPE_GENERAL); + + $insert = array_map(function ($lv) { + return [ + 'studierendenantrag_id' => $lv['studierendenantrag_id'], + 'lehrveranstaltung_id' => $lv['lehrveranstaltung_id'], + 'note' => $lv['zugelassen'] + ? ($lv['zugelassen'] == 1 ? 0 : $this->config->item('wiederholung_note_angerechnet')) + : $this->config->item('wiederholung_note_nicht_zugelassen'), + 'anmerkung' => $lv['anmerkung'], + 'insertvon' => getAuthUID(), + 'studiensemester_kurzbz' => $lv['studiensemester_kurzbz'] + ]; + }, $antragsLvs); + + $antrag_ids = array_unique(array_map(function ($lv) { + return $lv['studierendenantrag_id']; + }, $insert)); + + foreach ($antrag_ids as $antrag_id) { + $result = $this->StudierendenantragModel->loadIdAndStatusWhere([ + 'studierendenantrag_id' => $antrag_id + ]); + $antrag = $this->getDataOrTerminateWithError($result); + if (!$antrag) + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $antrag_id]), + self::ERROR_TYPE_GENERAL + ); + $antrag = current($antrag); + + if ($antrag->status != Studierendenantragstatus_model::STATUS_CREATED + && $antrag->status != Studierendenantragstatus_model::STATUS_LVSASSIGNED) + $this->terminateWithError( + $this->p->t('studierendenantrag', 'error_antrag_locked'), + self::ERROR_TYPE_GENERAL + ); + } + + $result = $this->antraglib->saveLvs($insert); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Address.php b/application/controllers/api/frontend/v1/stv/Address.php new file mode 100644 index 000000000..7685fcd04 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Address.php @@ -0,0 +1,66 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about addresses + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Address extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'getNations' => self::PERM_LOGGED, + 'getPlaces' => self::PERM_LOGGED + ]); + } + + public function getNations() + { + $this->load->model('codex/Nation_model', 'NationModel'); + + $this->NationModel->addOrder('kurztext'); + + $result = $this->NationModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getPlaces($plz) + { + $this->load->model('codex/Gemeinde_model', 'GemeindeModel'); + + $this->load->library('form_validation'); + + $this->form_validation->set_data(['address.plz' => $plz]); + + $this->form_validation->set_rules('address.plz', 'PLZ', 'numeric|less_than[10000]'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = $this->GemeindeModel->getGemeindeByPlz($plz); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php new file mode 100644 index 000000000..c28c49485 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -0,0 +1,233 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +use CI3_Events as Events; + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about the StV Config + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Config extends FHCAPI_Controller +{ + + + public function __construct() + { + // TODO(chris): permissions + parent::__construct([ + 'student' => ['admin:r', 'assistenz:r'], + 'students' => ['admin:r', 'assistenz:r'] + ]); + + + // Load Phrases + $this->loadPhrases([ + 'global', + 'person', + 'lehre', + 'stv', + 'konto' + ]); + } + + public function student() + { + $result = []; + $result['details'] = [ + 'title' => $this->p->t('stv', 'tab_details'), + 'component' => './Stv/Studentenverwaltung/Details/Details.js' + ]; + $result['notes'] = [ + 'title' => $this->p->t('stv', 'tab_notes'), + 'component' => './Stv/Studentenverwaltung/Details/Notizen.js' + ]; + $result['contact'] = [ + 'title' => $this->p->t('stv', 'tab_contact'), + 'component' => './Stv/Studentenverwaltung/Details/Kontakt.js', + 'config' => [ + 'showBankaccount' => $this->permissionlib->isBerechtigt('mitarbeiter/bankdaten') + || $this->permissionlib->isBerechtigt('student/bankdaten') + ] + ]; + $result['prestudent'] = [ + 'title' => $this->p->t('stv', 'tab_prestudent'), + 'component' => './Stv/Studentenverwaltung/Details/Prestudent.js' + ]; + $result['status'] = [ + 'title' => 'Status', + 'component' => './Stv/Studentenverwaltung/Details/MultiStatus.js' + ]; + $result['banking'] = [ + 'title' => $this->p->t('stv', 'tab_banking'), + 'component' => './Stv/Studentenverwaltung/Details/Konto.js', + 'config' => [ + 'showZahlungsbestaetigung' => (defined('ZAHLUNGSBESTAETIGUNG_ANZEIGEN') && ZAHLUNGSBESTAETIGUNG_ANZEIGEN), + 'showBuchungsnr' => $this->permissionlib->isBerechtigt('admin'), + 'showMahnspanne' => (!defined('FAS_KONTO_SHOW_MAHNSPANNE') || FAS_KONTO_SHOW_MAHNSPANNE===true), + 'showCreditpoints' => (defined('FAS_KONTO_SHOW_CREDIT_POINTS') && FAS_KONTO_SHOW_CREDIT_POINTS == 'true'), + 'columns' => $this->kontoColumns(), + 'additionalCols' => [] + ] + ]; + $result['resources'] = [ + 'title' => $this->p->t('stv', 'tab_resources'), + 'component' => './Stv/Studentenverwaltung/Details/Betriebsmittel.js' + ]; + /* TODO(chris): Ausgeblendet für Testing + $result['grades'] = [ + 'title' => $this->p->t('stv', 'tab_grades'), + 'component' => './Stv/Studentenverwaltung/Details/Noten.js' + ]; + */ + + Events::trigger('stv_conf_student', function & () use (&$result) { + return $result; + }); + + $this->terminateWithSuccess($result); + } + + public function students() + { + $result = []; + $result['banking'] = [ + 'title' => $this->p->t('stv', 'tab_banking'), + 'component' => './Stv/Studentenverwaltung/Details/Konto.js', + 'config' => [ + 'showZahlungsbestaetigung' => (defined('ZAHLUNGSBESTAETIGUNG_ANZEIGEN') && ZAHLUNGSBESTAETIGUNG_ANZEIGEN), + 'showBuchungsnr' => $this->permissionlib->isBerechtigt('admin'), + 'showMahnspanne' => (!defined('FAS_KONTO_SHOW_MAHNSPANNE') || FAS_KONTO_SHOW_MAHNSPANNE===true), + 'showCreditpoints' => (defined('FAS_KONTO_SHOW_CREDIT_POINTS') && FAS_KONTO_SHOW_CREDIT_POINTS == 'true'), + 'columns' => $this->kontoColumnsMultiPerson(), + 'additionalCols' => [] + ] + ]; + $result['status'] = [ + 'title' => 'Status', + 'component' => './Stv/Studentenverwaltung/Details/MultiStatus.js', + 'config' => [ + 'changeStatusToAbbrecherStgl' => $this->permissionlib->isBerechtigt('admin'), + 'changeStatusToAbbrecherStud' => $this->permissionlib->isBerechtigt('admin'), + 'changeStatusToUnterbrecher' => $this->permissionlib->isBerechtigt('admin'), + 'changeStatusToDiplomand' => $this->permissionlib->isBerechtigt('admin'), + 'changeStatusToAbsolvent' => $this->permissionlib->isBerechtigt('admin') + ] + ]; + + Events::trigger('stv_conf_students', function & () use (&$result) { + return $result; + }); + + $this->terminateWithSuccess($result); + } + + protected function kontoColumns() + { + return [ + 'buchungsdatum' => [ + 'field' => "buchungsdatum", + 'title' => $this->p->t('konto', 'buchungsdatum') + ], + 'buchungstext' => [ + 'field' => "buchungstext", + 'title' => $this->p->t('konto', 'buchungstext') + ], + 'betrag' => [ + 'field' => "betrag", + 'title' => $this->p->t('konto', 'betrag') + ], + 'studiensemester_kurzbz' => [ + 'field' => "studiensemester_kurzbz", + 'title' => $this->p->t('lehre', 'studiensemester') + ], + 'buchungstyp_kurzbz' => [ + 'field' => "buchungstyp_kurzbz", + 'title' => $this->p->t('konto', 'buchungstyp'), + 'visible' => false + ], + 'buchungsnr' => [ + 'field' => "buchungsnr", + 'title' => $this->p->t('konto', 'buchungsnr'), + 'visible' => false + ], + 'insertvon' => [ + 'field' => "insertvon", + 'title' => $this->p->t('global', 'insertvon'), + 'visible' => false + ], + 'insertamum' => [ + 'field' => "insertamum", + 'title' => $this->p->t('global', 'insertamum'), + 'visible' => false + ], + 'kuerzel' => [ + 'field' => "kuerzel", + 'title' => $this->p->t('lehre', 'studiengang'), + 'visible' => false + ], + 'anmerkung' => [ + 'field' => "anmerkung", + 'title' => $this->p->t('global', 'anmerkung') + ], + 'actions' => [ + 'title' => $this->p->t('global', 'actions'), + 'frozen' => true + ] + ]; + } + protected function kontoColumnsMultiPerson() + { + return [ + 'person_id' => [ + 'field' => "person_id", + 'title' => $this->p->t('person', 'person_id') + ], + 'anrede' => [ + 'field' => "anrede", + 'title' => $this->p->t('person', 'anrede'), + 'visible' => false + ], + 'titelpost' => [ + 'field' => "titelpost", + 'title' => $this->p->t('person', 'titelpost'), + 'visible' => false + ], + 'titelpre' => [ + 'field' => "titelpre", + 'title' => $this->p->t('person', 'titelpre'), + 'visible' => false + ], + 'vorname' => [ + 'field' => "vorname", + 'title' => $this->p->t('person', 'vorname') + ], + 'vornamen' => [ + 'field' => "vornamen", + 'title' => $this->p->t('person', 'vornamen'), + 'visible' => false + ], + 'nachname' => [ + 'field' => "nachname", + 'title' => $this->p->t('person', 'nachname') + ] + ] + $this->kontoColumns(); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Favorites.php b/application/controllers/api/frontend/v1/stv/Favorites.php new file mode 100644 index 000000000..8d7a6cd14 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Favorites.php @@ -0,0 +1,71 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about favorite verbände + * Listens to ajax post calls to change the favorite verbände data + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Favorites extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'index' => self::PERM_LOGGED, + 'set' => self::PERM_LOGGED + ]); + + // Load models + $this->load->model('system/Variable_model', 'VariableModel'); + + // TODO(chris): variable table might be to small to store favorites! + } + + public function index() + { + $result = $this->VariableModel->getVariables(getAuthUID(), ['stv_favorites']); + + $data = $this->getDataOrTerminateWithError($result); + + if (!$data) + $this->terminateWithSuccess(null); + else + $this->terminateWithSuccess($data['stv_favorites']); + } + + public function set() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('favorites', 'Favorites', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $favorites = $this->input->post('favorites'); + + $result = $this->VariableModel->setVariable(getAuthUID(), 'stv_favorites', $favorites); + + $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(true); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Filter.php b/application/controllers/api/frontend/v1/stv/Filter.php new file mode 100644 index 000000000..dbf70e4fb --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Filter.php @@ -0,0 +1,84 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about the Studiengang filter + * Listens to ajax post calls to change the Studiengang filter data + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Filter extends FHCAPI_Controller +{ + /** + * Calls the parent's constructor and prepares libraries and phrases + */ + public function __construct() + { + parent::__construct([ + 'getStg' => self::PERM_LOGGED, + 'setStg' => self::PERM_LOGGED + ]); + + // Load models + $this->load->model('system/Variable_model', 'VariableModel'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Get current setting + * + * @return void + */ + public function getStg() + { + $result = $this->VariableModel->getVariables(getAuthUID(), ['kontofilterstg']); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data['kontofilterstg'] == 'true'); + } + + /** + * Set current setting + * + * @return void + */ + public function setStg() + { + $this->load->library('form_validation'); + + $studiengang_kz = $this->input->post('studiengang_kz'); + + if ($studiengang_kz === null) { + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->VariableModel->setVariable(getAuthUID(), 'kontofilterstg', $studiengang_kz ? 'true' : 'false'); + + $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(true); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Kontakt.php b/application/controllers/api/frontend/v1/stv/Kontakt.php new file mode 100644 index 000000000..379184ee0 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Kontakt.php @@ -0,0 +1,754 @@ + ['admin:r', 'assistenz:r'], + 'addNewAddress' => ['admin:rw', 'assistenz:rw'], + 'addNewContact' => ['admin:rw', 'assistenz:rw'], + 'addNewBankverbindung' => ['mitarbeiter/bankdaten:rw', 'student/bankdaten:rw'], + 'updateAddress' => ['admin:rw', 'assistenz:rw'], + 'updateContact' => ['admin:rw', 'assistenz:rw'], + 'updateBankverbindung' => ['mitarbeiter/bankdaten:rw', 'student/bankdaten:rw'], + 'loadAddress' => ['admin:r', 'assistenz:r'], + 'loadContact' => ['admin:r', 'assistenz:r'], + 'loadBankverbindung' => ['mitarbeiter/bankdaten:r', 'student/bankdaten:r'], + 'deleteAddress' => ['admin:rw', 'assistenz:rw'], + 'deleteContact' => ['admin:rw','assistenz:rw'], + 'deleteBankverbindung' => ['mitarbeiter/bankdaten:rw','astudent/bankdaten:rw'], + 'getAdressentypen' => ['admin:r', 'assistenz:r'], + 'getKontakttypen' => ['admin:r', 'assistenz:r'], + 'getFirmen' => ['admin:r', 'assistenz:r'], + 'getStandorte' => ['admin:r', 'assistenz:r'], + 'getStandorteByFirma' => ['admin:r', 'assistenz:r'], + 'getKontakte' => ['admin:r', 'assistenz:r'], + 'getBankverbindung' => ['mitarbeiter/bankdaten:r', 'student/bankdaten:r'] + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person' + ]); + + // Load models + $this->load->model('person/Adresse_model', 'AdresseModel'); + $this->load->model('organisation/standort_model', 'StandortModel'); + $this->load->model('ressource/firma_model', 'FirmaModel'); + $this->load->model('person/Kontakt_model', 'KontaktModel'); + + // Extra Permissionchecks + $permsMa = []; + $permsStud = []; + switch ($this->router->method) { + case 'getBankverbindung': + case 'loadBankverbindung': + $permsMa = ['mitarbeiter/bankdaten:r']; + $permsStud = ['student/bankdaten:r']; + break; + case 'addNewBankverbindung': + case 'updateBankverbindung': + case 'deleteBankverbindung': + $permsMa = ['mitarbeiter/bankdaten:rw']; + $permsStud = ['student/bankdaten:rw']; + break; + case 'getAdressen': + case 'getKontakte': + case 'loadAddress': + case 'loadContact': + $permsMa = $permsStud = ['admin:r', 'assistenz:r']; + break; + case 'addNewAddress': + case 'addNewContact': + case 'updateAddress': + case 'updateContact': + case 'deleteAddress': + case 'deleteContact': + $permsMa = $permsStud = ['admin:rw', 'assistenz:rw']; + break; + } + if ($this->router->method == 'getAdressen' + || $this->router->method == 'getKontakte' + || $this->router->method == 'getBankverbindung' + || $this->router->method == 'addNewAddress' + || $this->router->method == 'addNewContact' + || $this->router->method == 'addNewBankverbindung' + ) { + $person_id = current(array_slice($this->uri->rsegments, 2)); + + $this->checkPermissionsForPerson($person_id, $permsMa, $permsStud); + } elseif ($this->router->method == 'loadAddress' + || $this->router->method == 'loadContact' + || $this->router->method == 'loadBankverbindung' + || $this->router->method == 'updateAddress' + || $this->router->method == 'updateContact' + || $this->router->method == 'updateBankverbindung' + || $this->router->method == 'deleteAddress' + || $this->router->method == 'deleteContact' + || $this->router->method == 'deleteBankverbindung' + ) { + $id = current(array_slice($this->uri->rsegments, 2)); + + $model = 'person/Adresse_model'; + if ($this->router->method == 'loadContact' + || $this->router->method == 'updateContact' + || $this->router->method == 'deleteContact' + ) { + $model = 'person/Kontakt_model'; + } elseif ($this->router->method == 'loadBankverbindung' + || $this->router->method == 'updateBankverbindung' + || $this->router->method == 'deleteBankverbindung' + ) { + $model = 'person/Bankverbindung_model'; + } + + $this->load->model($model, 'TempModel'); + $result = $this->TempModel->load($id); + $data = $this->getDataOrTerminateWithError($result); + if (!$result) + show_404(); + + $person_id = current($data)->person_id; + + $this->checkPermissionsForPerson($person_id, $permsMa, $permsStud); + } + } + public function getAdressen($person_id) + { + $this->AdresseModel->addSelect('public.tbl_adresse.*'); + $this->AdresseModel->addSelect('t.*'); + $this->AdresseModel->addSelect('f.firma_id'); + $this->AdresseModel->addSelect('f.name as firmenname'); + $this->AdresseModel->addJoin('public.tbl_adressentyp t', 'ON (t.adressentyp_kurzbz = public.tbl_adresse.typ)'); + $this->AdresseModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = public.tbl_adresse.firma_id)', 'LEFT'); + + $result = $this->AdresseModel->loadWhere( + array('person_id' => $person_id) + ); + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function addNewAddress($person_id) + { + $this->form_validation->set_rules('plz', 'PLZ', 'required|numeric', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ']) + ]); + + if(isset($_POST['gemeinde']) && isset($_POST['ort'])) + $this->form_validation->set_rules('plz', 'Postleitzahl', 'callback_validateLocationCombination', [ + 'validateLocationCombination' => $this->p->t('ui', 'error_location_combination') + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $uid = getAuthUID(); + $co_name = isset($_POST['co_name']) ? $_POST['co_name'] : null; + $strasse = isset($_POST['strasse']) ? $_POST['strasse'] : null; + $ort = isset($_POST['ort']) ? $_POST['ort'] : null; + $gemeinde = isset($_POST['gemeinde']) ? $_POST['gemeinde'] : null; + $nation = isset($_POST['nation']) ? $_POST['nation'] : null; + $name = isset($_POST['name']) ? $_POST['name'] : null; + $typ = isset($_POST['typ']) ? $_POST['typ'] : null; + $anmerkung = isset($_POST['anmerkung']) ? $_POST['anmerkung'] : null; + + if(isset($_POST['firma'])) + { + $firma_id = $_POST['firma']['firma_id']; + } + else + $firma_id = null; + + $result = $this->AdresseModel->insert( + [ + 'person_id' => $person_id, + 'strasse' => $strasse, + 'insertvon' => $uid, + 'insertamum' => date('c'), + 'plz' => $_POST['plz'], + 'ort' => $ort, + 'gemeinde' => $gemeinde, + 'nation' => $nation, + 'heimatadresse' => $_POST['heimatadresse'], + 'zustelladresse' => $_POST['zustelladresse'], + 'co_name' => $co_name, + 'typ' => $typ, + 'firma_id' => $firma_id, + 'name' => $name, + 'rechnungsadresse' => $_POST['rechnungsadresse'], + 'anmerkung' => $anmerkung + + ] + ); + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->outputJsonSuccess(true); + } + + public function updateAddress($address_id) + { + $uid = getAuthUID(); + $this->form_validation->set_rules('plz', 'PLZ', 'required|numeric', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ']) + ]); + + if(isset($_POST['gemeinde']) && isset($_POST['ort'])) + $this->form_validation->set_rules('plz', 'Postleitzahl', 'callback_validateLocationCombination', [ + 'validateLocationCombination' => $this->p->t('ui', 'error_location_combination') + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->load->model('person/Adresse_model', 'AdresseModel'); + + if(!$address_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Adresse_id']), self::ERROR_TYPE_GENERAL); + } + + if(isset($_POST['firma'])) + { + $firma_id = $_POST['firma']['firma_id']; + } + elseif(isset($_POST['firma_id'])) + { + $firma_id = $_POST['firma_id']; + } + else + $firma_id = null; + + $person_id = isset($_POST['person_id']) ? $_POST['person_id'] : null; + $co_name = isset($_POST['co_name']) ? $_POST['co_name'] : null; + $strasse = isset($_POST['strasse']) ? $_POST['strasse'] : null; + $ort = isset($_POST['ort']) ? $_POST['ort'] : null; + $gemeinde = isset($_POST['gemeinde']) ? $_POST['gemeinde'] : null; + $nation = isset($_POST['nation']) ? $_POST['nation'] : null; + $name = isset($_POST['name']) ? $_POST['name'] : null; + $typ = isset($_POST['typ']) ? $_POST['typ'] : null; + $anmerkung = isset($_POST['anmerkung']) ? $_POST['anmerkung'] : null; + + $result = $this->AdresseModel->update( + [ + 'adresse_id' => $address_id + ], + [ 'person_id' => $person_id, + 'strasse' => $strasse, + 'updatevon' => $uid, + 'updateamum' => date('c'), + 'plz' => $_POST['plz'], + 'ort' => $ort, + 'gemeinde' => $gemeinde, + 'nation' => $nation, + 'heimatadresse' => $_POST['heimatadresse'], + 'zustelladresse' => $_POST['zustelladresse'], + 'co_name' => $co_name, + 'typ' => $typ, + 'firma_id' => $firma_id, + 'name' => $name, + 'rechnungsadresse' => $_POST['rechnungsadresse'], + 'anmerkung' => $anmerkung + ] + ); + + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->outputJsonSuccess(true); + } + + public function loadAddress($adresse_id) + { + $this->load->model('person/Adresse_model', 'AdresseModel'); + + $this->AdresseModel->addSelect('public.tbl_adresse.*'); + $this->AdresseModel->addSelect('t.*'); + $this->AdresseModel->addSelect('f.firma_id'); + $this->AdresseModel->addSelect('f.name as firmenname'); + $this->AdresseModel->addJoin('public.tbl_adressentyp t', 'ON (t.adressentyp_kurzbz = public.tbl_adresse.typ)'); + $this->AdresseModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = public.tbl_adresse.firma_id)', 'LEFT'); + + $this->AdresseModel->addLimit(1); + + $result = $this->AdresseModel->loadWhere( + array('adresse_id' => $adresse_id) + ); + if (isError($result)) { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Adresse_id']), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function deleteAddress($adresse_id) + { + $this->load->model('person/Adresse_model', 'AdresseModel'); + $result = $this->AdresseModel->load([ + 'adresse_id'=> $adresse_id, + ]); + if(isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $result = current(getData($result)); + + if($result->heimatadresse) + + $this->terminateWithError($this->p->t('person', 'error_deleteHomeAdress'), self::ERROR_TYPE_GENERAL); + + $result = $this->AdresseModel->delete( + array('adresse_id' => $adresse_id) + ); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Adresse_id']), self::ERROR_TYPE_GENERAL); + } + + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function getAdressentypen() + { + $this->load->model('person/Adressentyp_model', 'AdressentypModel'); + + $result = $this->AdressentypModel->load(); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getFirmen($searchString) + { + $this->load->model('ressource/firma_model', 'FirmaModel'); + + $result = $this->FirmaModel->searchFirmen($searchString); + if (isError($result)) { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess($result ?: []); + } + + public function getStandorte($searchString) + { + $this->load->model('organisation/standort_model', 'StandortModel'); + + $result = $this->StandortModel->searchStandorte($searchString); + if (isError($result)) { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess($result ?: []); + } + + public function getStandorteByFirma($firma_id) + { + $this->load->model('organisation/standort_model', 'StandortModel'); + + $result = $this->StandortModel->getStandorteByFirma($firma_id); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getKontakte($person_id) + { + $this->KontaktModel->addSelect("public.tbl_kontakt.*, + TO_CHAR (CASE + WHEN public.tbl_kontakt.updateamum >= public.tbl_kontakt.insertamum + THEN public.tbl_kontakt.updateamum + ELSE public.tbl_kontakt.insertamum + END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate, st.bezeichnung, f.name"); + $this->StandortModel->addJoin('public.tbl_standort st', 'ON (public.tbl_kontakt.standort_id = st.standort_id)', 'LEFT'); + $this->FirmaModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = st.firma_id)', 'LEFT'); + $result = $this->KontaktModel->loadWhere( + array('person_id' => $person_id) + ); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function getKontakttypen() + { + $this->load->model('person/Kontakttyp_model', 'KontakttypModel'); + + $result = $this->KontakttypModel->load(); + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + else + { + $this->terminateWithSuccess(getData($result) ?: []); + } + } + + public function loadContact($kontakt_id) + { + $this->load->model('person/Kontakt_model', 'KontaktModel'); + + $this->KontaktModel->addSelect('*, public.tbl_kontakt.*'); + $this->KontaktModel->addSelect('st.kurzbz'); + $this->KontaktModel->addJoin('public.tbl_standort st', 'ON (public.tbl_kontakt.standort_id = st.standort_id)', 'LEFT'); + $this->FirmaModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = st.firma_id)', 'LEFT'); + + $this->KontaktModel->addLimit(1); + + $result = $this->KontaktModel->loadWhere( + array('kontakt_id' => $kontakt_id) + ); + if (isError($result)) { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Kontakt_id']), self::ERROR_TYPE_GENERAL); + } + // $this->outputJsonSuccess(current(getData($result))); + $this->terminateWithSuccess(current(getData($result))); + } + + public function addNewContact($person_id) + { + if(($_POST['kontakttyp'] == 'email' && isset($_POST['kontakt']))) + { + $this->form_validation->set_rules('kontakt', 'Kontakt', 'required|valid_email', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Kontakt']), + 'valid_email' => $this->p->t('ui', 'error_fieldNoValidEmail', ['field' => 'Kontakt']) + ]); + } + else + { + $this->form_validation->set_rules('kontakt', 'Kontakt', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Kontakt']) + ]); + } + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->load->model('person/Kontakt_model', 'KontaktModel'); + + $uid = getAuthUID(); + + $kontakttyp = $this->input->post('kontakttyp'); + $anmerkung = $this->input->post('anmerkung'); + $kontakt = $this->input->post('kontakt'); + $ext_id = $this->input->post('ext_id'); + $standort_id = $this->input->post('standort_id'); + + $result = $this->KontaktModel->insert( + [ + 'person_id' => $person_id, + 'kontakttyp' => $kontakttyp, + 'anmerkung' => $anmerkung, + 'kontakt' => $kontakt, + 'zustellung' => $_POST['zustellung'], + 'insertvon' => $uid, + 'insertamum' => date('c'), + 'standort_id' => $standort_id, + 'ext_id' => $ext_id + ] + ); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + return $this->outputJsonSuccess(true); + } + + public function updateContact($kontakt_id) + { + $this->load->model('person/Kontakt_model', 'KontaktModel'); + + if(!$kontakt_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Kontakt_id']), self::ERROR_TYPE_GENERAL); + } + + if(($_POST['kontakttyp'] == 'email' && isset($_POST['kontakt']))) + { + $this->form_validation->set_rules('kontakt', 'Kontakt', 'required|valid_email', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Kontakt']), + 'valid_email' => $this->p->t('ui', 'error_fieldNoValidEmail', ['field' => 'Kontakt']) + ]); + } + else + { + $this->form_validation->set_rules('kontakt', 'Kontakt', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Kontakt']) + ]); + } + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + +/* if(isset($_POST['standort'])) + { + $standort_id = $_POST['standort']['standort_id']; + } + else + $standort_id = null;*/ + + $uid = getAuthUID(); + $kontakttyp = $this->input->post('kontakttyp'); + $anmerkung = $this->input->post('anmerkung'); + $kontakt = $this->input->post('kontakt'); + $ext_id = $this->input->post('ext_id'); + $person_id = $this->input->post('person_id'); + $standort_id = $this->input->post('standort_id'); + + //return $this->terminateWithError("in update " . $standort_id, self::ERROR_TYPE_GENERAL); + + $result = $this->KontaktModel->update( + [ + 'kontakt_id' => $kontakt_id + ], + [ + 'person_id' => $person_id, + 'kontakttyp' => $kontakttyp, + 'anmerkung' => $anmerkung, + 'kontakt' => $kontakt, + 'zustellung' => $_POST['zustellung'], + 'insertvon' => $uid, + 'insertamum' => date('c'), + 'standort_id' => $standort_id, + 'ext_id' => $ext_id + ] + ); + + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->outputJsonSuccess(true); + } + + public function deleteContact($kontakt_id) + { + $this->load->model('person/Kontakt_model', 'KontaktModel'); + + $result = $this->KontaktModel->delete( + array('kontakt_id' => $kontakt_id) + ); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + elseif (!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Kontakt_id']), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function getBankverbindung($person_id) + { + $this->load->model('person/Bankverbindung_model', 'BankverbindungModel'); + + $this->BankverbindungModel->addSelect('*'); + + $result = $this->BankverbindungModel->loadWhere( + array('person_id' => $person_id) + ); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function addNewBankverbindung($person_id) + { + $this->form_validation->set_rules('iban', 'IBAN', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'IBAN']) + ]); + + $this->form_validation->set_rules('typ', 'TYP', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'TYP']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->load->model('person/Bankverbindung_model', 'BankverbindungModel'); + + $ext_id = $this->input->post('ext_id'); + $oe_kurzbz = $this->input->post('oe_kurzbz'); + $orgform_kurzbz = $this->input->post('orgform_kurzbz'); + $name = $this->input->post('name'); + $anschrift = $this->input->post('anschrift'); + $bic = $this->input->post('bic'); + $blz = $this->input->post('blz'); + $kontonr = $this->input->post('kontonr'); + + $result = $this->BankverbindungModel->insert( + [ + 'person_id' => $person_id, + 'name' => $name, + 'anschrift' => $anschrift, + 'bic' => $bic, + 'iban' => $_POST['iban'], + 'blz' => $blz, + 'kontonr' => $kontonr, + 'insertvon' => 'uid', + 'insertamum' => date('c'), + 'typ' => $_POST['typ'], + 'verrechnung' => $_POST['verrechnung'], + 'ext_id' => $ext_id, + 'oe_kurzbz' => $oe_kurzbz, + 'orgform_kurzbz' => $orgform_kurzbz + ] + ); + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + return $this->outputJsonSuccess(true); + } + + public function loadBankverbindung($bankverbindung_id) + { + $this->load->model('person/Bankverbindung_model', 'BankverbindungModel'); + + $this->BankverbindungModel->addSelect('*'); + + $this->BankverbindungModel->addLimit(1); + + $result = $this->BankverbindungModel->loadWhere( + array('bankverbindung_id' => $bankverbindung_id) + ); + if (isError($result)) + { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Bankverbindung_id']), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(current(getData($result))); + } + + public function updateBankverbindung($bankverbindung_id) + { + $this->form_validation->set_rules('iban', 'IBAN', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'IBAN']) + ]); + + $this->form_validation->set_rules('typ', 'TYP', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'TYP']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->load->model('person/Bankverbindung_model', 'BankverbindungModel'); + + if(!$bankverbindung_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Bankverbindung_id']), self::ERROR_TYPE_GENERAL); + } + + $uid = getAuthUID(); + + $result = $this->BankverbindungModel->update( + [ + 'bankverbindung_id' => $bankverbindung_id + ], + [ + 'person_id' => $_POST['person_id'], + 'name' => $_POST['name'], + 'anschrift' => $_POST['anschrift'], + 'bic' => $_POST['bic'], + 'iban' => $_POST['iban'], + 'blz' => $_POST['blz'], + 'kontonr' => $_POST['kontonr'], + 'updatevon' => $uid, + 'updateamum' => date('c'), + 'typ' => $_POST['typ'], + 'verrechnung' => $_POST['verrechnung'], + 'ext_id' => $_POST['ext_id'], + 'oe_kurzbz' => $_POST['oe_kurzbz'], + 'orgform_kurzbz' => $_POST['orgform_kurzbz'] + ] + ); + + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->outputJsonSuccess(true); + } + + public function deleteBankverbindung($bankverbindung_id) + { + $this->load->model('person/Bankverbindung_model', 'BankverbindungModel'); + + $result = $this->BankverbindungModel->delete( + array('bankverbindung_id' => $bankverbindung_id) + ); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) + { + $this->outputJson($result); + } + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function validateLocationCombination() + { + $this->load->model('codex/Gemeinde_model', 'GemeindeModel'); + + return $this->GemeindeModel->checkLocation($_POST['plz'], $_POST['gemeinde'], $_POST['ort']); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Konto.php b/application/controllers/api/frontend/v1/stv/Konto.php new file mode 100644 index 000000000..ac36b5d8f --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Konto.php @@ -0,0 +1,495 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +use CI3_Events as Events; + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about a Konto + * Listens to ajax post calls to change the Konto data + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Konto extends FHCAPI_Controller +{ + /** + * Calls the parent's constructor and prepares libraries and phrases + */ + public function __construct() + { + parent::__construct([ + 'get' => 'student/stammdaten:r', + 'getBuchungstypen' => self::PERM_LOGGED, + 'checkDoubles' => ['admin:r', 'assistenz:r'], + 'insert' => ['admin:w', 'assistenz:w'], + 'counter' => ['admin:w', 'assistenz:w'], + 'update' => ['admin:w', 'assistenz:w'], + 'delete' => ['admin:w', 'assistenz:w'] + ]); + + // Load models + $this->load->model('crm/Konto_model', 'KontoModel'); + + // Load language phrases + $this->loadPhrases([ + 'konto' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Get details for a prestudent + * + * @return void + */ + public function get() + { + $this->load->library('form_validation'); + + $person_id = $this->input->post('person_id'); + if (!$person_id || !is_array($person_id)) { + $this->form_validation->set_rules('person_id', 'Person ID', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + + $studiengang_kz = $this->input->post('studiengang_kz'); + + if ($this->input->post('only_open')) { + $result = $this->KontoModel->getOffeneBuchungen($person_id, $studiengang_kz); + } else { + $result = $this->KontoModel->getAlleBuchungen($person_id, $studiengang_kz); + } + + $result = $this->getDataOrTerminateWithError($result); + + // sort into tree + $childs = []; + $data = []; + foreach ($result as $entry) { + if ($entry->buchungsnr_verweis) { + if (isset($data[$entry->buchungsnr_verweis])) { + if (!isset($data[$entry->buchungsnr_verweis]->_children)) + $data[$entry->buchungsnr_verweis]->_children = []; + $data[$entry->buchungsnr_verweis]->_children[] = $entry; + } else { + if (!isset($childs[$entry->buchungsnr_verweis])) + $childs[$entry->buchungsnr_verweis] = []; + $childs[$entry->buchungsnr_verweis][] = $entry; + } + } else { + $data[$entry->buchungsnr] = $entry; + if (isset($childs[$entry->buchungsnr])) + $entry->_children = $childs[$entry->buchungsnr]; + } + } + + $this->terminateWithSuccess(array_values($data)); + } + + /** + * Get list of Buchungstypen + * + * @return void + */ + public function getBuchungstypen() + { + $this->load->model('crm/Buchungstyp_model', 'BuchungstypModel'); + + $result = $this->BuchungstypModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * Check double Buchungen + * + * @return void + */ + public function checkDoubles() + { + if (!defined('FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK') || !FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK) + $this->terminateWithSuccess(false); + + $this->load->library('form_validation'); + + $person_ids = $this->input->post('person_id'); + + if (!$person_ids || !is_array($person_ids)) { + $person_ids = [$person_ids]; + $this->form_validation->set_rules('person_id', 'Person ID', 'required'); + } + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required'); + $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $buchungstypen = unserialize(FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK); + $buchung = $this->input->post('buchungstyp_kurzbz'); + + if (!isset($buchungstypen[$buchung])) + $this->terminateWithSuccess(false); + + $result = $this->KontoModel->checkDoubleBuchung($person_ids, $this->input->post('studiensemester_kurzbz'), $buchungstypen[$buchung]); + + $result = $this->getDataOrTerminateWithError($result); + + if (!$result) + $this->terminateWithSuccess(false); + + $persons = array_map(function ($row) { + return $row->nachname . ' ' . $row->vorname; + }, $result); + + $result = $this->p->t('konto', 'confirm_overwrite') . "\n"; + if (count($persons) > 10) { + $result .= "-" . implode("\n-", array_slice($persons, 0, 10)) . "\n"; + + if (count($persons) == 11) { + $result .= "\n" . $this->p->t('konto', 'confirm_overwrite_1_add_pers'); + } else { + $result .= "\n" . $this->p->t('konto', 'confirm_overwrite_x_add_pers', [ + 'x' => count($persons) - 10 + ]); + } + } else { + $result .= "-" . implode("\n-", $persons) . "\n"; + } + $result .= $this->p->t('konto', 'confirm_overwrite_proceed'); + + $this->addError($result, 'confirm'); + + $this->terminateWithSuccess(true); + } + + + /** + * Save Buchung + * + * @return void + */ + public function insert() + { + $this->load->library('form_validation'); + + $person_ids = $this->input->post('person_id'); + + if (!$person_ids || !is_array($person_ids)) { + $person_ids = [$person_ids]; + $this->form_validation->set_rules('person_id', 'Person ID', 'required'); + } + $this->form_validation->set_rules('betrag', 'Betrag', 'numeric'); + $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date'); + $this->form_validation->set_rules('buchungstext', 'Buchungstext', 'max_length[256]'); + $this->form_validation->set_rules('mahnspanne', 'Mahnspanne', 'integer'); + $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required|max_length[32]'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required|max_length[16]'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required|has_permissions_for_stg[admin:rw,assistenz:rw]'); + $this->form_validation->set_rules('credit_points', 'Credit Points', 'numeric'); + + Events::trigger('konto_insert_validation', $this->form_validation); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $allowed = [ + 'betrag', + 'buchungsdatum', + 'buchungstext', + 'mahnspanne', + 'buchungstyp_kurzbz', + 'studiensemester_kurzbz', + 'studiengang_kz', + 'credit_points', + 'anmerkung' + ]; + $data = [ + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]; + foreach ($allowed as $field) + if ($this->input->post($field) !== null) + $data[$field] = $this->input->post($field); + + if (defined('FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE') && isset(unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']])) { + $data['kostenstelle'] = unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']]; + } + + $result = []; + foreach ($person_ids as $person_id) { + $id = $this->KontoModel->insert(array_merge($data, ['person_id' => $person_id])); + if (isError($id)) { + $this->addError(getError($id), self::ERROR_TYPE_DB); + } else { + $kontodata = $this->KontoModel->withAdditionalInfo()->load(getData($id)); + if (isError($kontodata)) + $this->addError(getError($kontodata), self::ERROR_TYPE_DB); + else + $result[] = current(getData($kontodata)); + } + } + + if ($result) + $this->terminateWithSuccess($result); + + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + + /** + * Save Counter Buchung + * + * @return void + */ + public function counter() + { + $this->load->library('form_validation'); + + $buchungsnrs = $this->input->post('buchungsnr'); + + if (!$buchungsnrs || !is_array($buchungsnrs)) { + $buchungsnrs = $buchungsnrs ? [$buchungsnrs] : []; + $this->form_validation->set_rules('buchungsnr', 'Buchungsnr', 'required'); + } + $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $data = []; + $rules = []; + foreach ($buchungsnrs as $k => $buchungsnr) { + $result = $this->KontoModel->load($buchungsnr); + if (isError($result)) { + $rules[] = [ + 'field' => 'buchung[' . $k . ']', + 'label' => 'Buchung #' . $buchungsnr, + 'rules' => 'required', + 'errors' => [ + 'required' => getError($result) + ] + ]; + } elseif (!hasData($result)) { + $rules[] = [ + 'field' => 'buchung[' . $k . ']', + 'label' => 'Buchung #' . $buchungsnr, + 'rules' => 'required' + ]; + } else { + $data[$k] = get_object_vars(current(getData($result))); + $rules[] = [ + 'field' => 'buchung[' . $k . '][buchungsnr]', + 'label' => 'Buchung # ' . $buchungsnr, + 'rules' => 'required|numeric' + ]; + $rules[] = [ + 'field' => 'buchung[' . $k . '][studiengang_kz]', + 'label' => 'Buchung # ' . $buchungsnr, + 'rules' => 'required|has_permissions_for_stg[admin:rw,assistenz:rw]' + ]; + $rules[] = [ + 'field' => 'buchung[' . $k . '][buchungsnr_verweis]', + 'label' => 'Buchung # ' . $buchungsnr, + 'rules' => 'regex_match[/^$/]', + 'errors' => [ + 'regex_match' => $this->p->t('konto', 'error_counter_level') + ] + ]; + } + } + + $this->form_validation->reset_validation(); + $this->form_validation->set_data(['buchung' => $data]); + $this->form_validation->set_rules($rules); + + Events::trigger('konto_counter_validation', $this->form_validation); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $buchungsdatum = $this->input->post('buchungsdatum'); + + $newItems = []; + foreach ($data as $buchung) { + $result = $this->KontoModel->getDifferenz($buchung['buchungsnr']); + if (isError($result)) { + $this->addError(getError($result), self::ERROR_TYPE_GENERAL); + continue; + } + $betrag = $result->retval; + if ($betrag === null) { + $this->addError($this->p->t( + 'konto', + 'error_missing', + $buchung + ), self::ERROR_TYPE_GENERAL); + continue; + } + + + $result = $this->KontoModel->insert([ + 'person_id' => $buchung['person_id'], + 'studiengang_kz' => $buchung['studiengang_kz'], + 'studiensemester_kurzbz' => $buchung['studiensemester_kurzbz'], + 'buchungstext' => $buchung['buchungstext'], + 'buchungstyp_kurzbz' => $buchung['buchungstyp_kurzbz'], + 'credit_points' => $buchung['credit_points'], + 'zahlungsreferenz' => $buchung['zahlungsreferenz'], + 'betrag' => $betrag, + 'buchungsdatum' => $buchungsdatum, + 'mahnspanne' => '0', + 'buchungsnr_verweis' => $buchung['buchungsnr'], + 'insertamum' => date('c'), + 'insertvon' => getAuthUID(), + 'anmerkung' => '' + ]); + if (isError($result)) { + $this->addError(getError($result), self::ERROR_TYPE_GENERAL); + continue; + } + + $newItems = null; + // TODO(chris): get as tree? + /*$result = $this->KontoModel->withAdditionalInfo()->load($result->retval); + if (!hasData($result)) + $newItems = null; + elseif ($newItems !== null) + $newItems[] = current(getData($result));*/ + } + + $this->terminateWithSuccess($newItems); + } + + /** + * Save Buchung + * + * @return void + */ + public function update() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('buchungsnr', 'Buchungsnr', 'required'); + $this->form_validation->set_rules('betrag', 'Betrag', 'numeric'); + $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date'); + $this->form_validation->set_rules('buchungstext', 'Buchungstext', 'max_length[256]'); + $this->form_validation->set_rules('mahnspanne', 'Mahnspanne', 'integer'); + $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required|max_length[32]'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required|max_length[16]'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required|has_permissions_for_stg[admin:rw,assistenz:rw]'); + $this->form_validation->set_rules('credit_points', 'Credit Points', 'numeric'); + + Events::trigger('konto_update_validation', $this->form_validation); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $id = $this->input->post('buchungsnr'); + $allowed = [ + 'betrag', + 'buchungsdatum', + 'buchungstext', + 'mahnspanne', + 'buchungstyp_kurzbz', + 'studiensemester_kurzbz', + 'studiengang_kz', + 'credit_points', + 'anmerkung' + ]; + $data = [ + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ]; + foreach ($allowed as $field) + if ($this->input->post($field) !== null) + $data[$field] = $this->input->post($field); + + $result = $this->KontoModel->update($id, $data); + + $this->getDataOrTerminateWithError($result); + + $result = null; + // TODO(chris): get as tree? + /*$result = $this->KontoModel->withAdditionalInfo()->load($id); + + #$result = $this->getDataOrTerminateWithError($result); + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $result = $result->retval;*/ + + $this->terminateWithSuccess($result); + } + + /** + * Delete Buchung + * + * @return void + */ + public function delete() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('buchungsnr', 'Buchungsnr', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $buchungsnr = $this->input->post('buchungsnr'); + + $result = $this->KontoModel->load($buchungsnr); + + $result = $this->getDataOrTerminateWithError($result); + + if (!$result) + $this->terminateWithError($this->p->t('konto', 'error_missing', [ + 'buchungsnr' => $buchungsnr + ])); + + $_POST['studiengang_kz'] = current($result)->studiengang_kz; + + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'has_permissions_for_stg[admin:rw,assistenz:rw]'); + + Events::trigger('konto_delete_validation', $this->form_validation); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + Events::trigger('konto_delete', $buchungsnr); + + $result = $this->KontoModel->delete($buchungsnr); + if (isError($result)) { + if (getCode($result) != 42) + $this->terminateWithError(getError($result)); + $this->terminateWithError($this->p->t('konto', 'error_delete_level')); + } + + $this->terminateWithSuccess(); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Lists.php b/application/controllers/api/frontend/v1/stv/Lists.php new file mode 100644 index 000000000..1c0c25db7 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Lists.php @@ -0,0 +1,147 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about generally used lists + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Lists extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'getStudiensemester' => self::PERM_LOGGED, + 'getStgs' => self::PERM_LOGGED, + 'getSprachen' => self::PERM_LOGGED, + 'getGeschlechter' => self::PERM_LOGGED, + 'getAusbildungen' => self::PERM_LOGGED, + 'getOrgforms' => self::PERM_LOGGED, + 'getStati' => self::PERM_LOGGED + ]); + } + + public function getStudiensemester() + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addOrder('ende'); + + $result = $this->StudiensemesterModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getStgs() + { + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $this->StudiengangModel->addSelect('*'); + $this->StudiengangModel->addSelect('UPPER(typ || kurzbz) AS kuerzel'); + + $this->StudiengangModel->addOrder('typ'); + $this->StudiengangModel->addOrder('kurzbz'); + + $result = $this->StudiengangModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getSprachen() + { + $this->load->model('system/Sprache_model', 'SpracheModel'); + + $this->SpracheModel->addOrder('sprache'); + + $result = $this->SpracheModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getGeschlechter() + { + $this->load->model('person/Geschlecht_model', 'GeschlechtModel'); + + $this->GeschlechtModel->addOrder('sort'); + $this->GeschlechtModel->addOrder('geschlecht'); + + $this->GeschlechtModel->addSelect('*'); + #$this->GeschlechtModel->addTranslatedSelect("bezeichnung_mehrsprachig", "bezeichnung"); + $this->GeschlechtModel->addSelect("bezeichnung_mehrsprachig[(SELECT index FROM public.tbl_sprache WHERE sprache=" . $this->GeschlechtModel->escape(DEFAULT_LANGUAGE) . " LIMIT 1)] AS bezeichnung"); + + $result = $this->GeschlechtModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getAusbildungen() + { + $this->load->model('codex/Ausbildung_model', 'AusbildungModel'); + + $this->AusbildungModel->addOrder('ausbildungcode'); + + $result = $this->AusbildungModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getOrgforms() + { + $this->load->model('codex/Orgform_model', 'OrgformModel'); + + $this->OrgformModel->addOrder('bezeichnung'); + + $result = $this->OrgformModel->loadWhere(['rolle' => true]); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getStati() + { + $lang = getUserLanguage(); + $this->load->model('crm/Status_model', 'StatusModel'); + + $this->StatusModel->addSelect('*'); + #$this->StatusModel->addTranslatedSelect('bezeichnung_mehrsprachig', 'bezeichnung'); + $this->StatusModel->addSelect( + 'bezeichnung_mehrsprachig[( + SELECT index + FROM public.tbl_sprache + WHERE sprache=' . $this->StatusModel->escape($lang) . ' + LIMIT 1 + )] AS bezeichnung', + false + ); + #$this->StatusModel->addOrder('ext_id'); + + $result = $this->StatusModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Notiz.php b/application/controllers/api/frontend/v1/stv/Notiz.php new file mode 100644 index 000000000..19e568f33 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Notiz.php @@ -0,0 +1,384 @@ + ['admin:r', 'assistenz:r'], + 'getNotizen' => ['admin:r', 'assistenz:r'], + 'loadNotiz' => ['admin:r', 'assistenz:r'], // TODO(manu): self::PERM_LOGGED + 'addNewNotiz' => ['admin:rw', 'assistenz:rw'], // TODO(manu): self::PERM_LOGGED + 'updateNotiz' => ['admin:rw', 'assistenz:rw'], // TODO(manu): self::PERM_LOGGED + 'deleteNotiz' => ['admin:r', 'assistenz:r'], + 'loadDokumente' => ['admin:r', 'assistenz:r'], + 'getMitarbeiter' => ['admin:r', 'assistenz:r'] + ]); + + //Load Models + $this->load->model('person/Notiz_model', 'NotizModel'); + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + +/* public function getUid() + { + $this->terminateWithSuccess(getAuthUID()); + }*/ + + + public function getNotizen($id, $type) + { + + //check if valid type + $result = $this->NotizzuordnungModel->isValidType($type); + if(isError($result)) + $this->terminateWithError($result->retval, self::ERROR_TYPE_GENERAL); + + //$this->terminateWithError(" after check type not valid", self::ERROR_TYPE_GENERAL); + $result = $this->NotizModel->getNotizWithDocEntries($id, $type); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + + // return $this->terminateWithError("type not valid", self::ERROR_TYPE_GENERAL); + + } + +/* public function loadNotiz() + { + $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true); + + $notiz_id = $this->input->post('notiz_id'); + + //$this->load->model('person/Notiz_model', 'NotizModel'); + $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'notiz_id', 'LEFT'); + $this->NotizModel->addSelect('*'); + $this->NotizModel->addSelect("TO_CHAR(CASE WHEN public.tbl_notiz.updateamum >= public.tbl_notiz.insertamum + THEN public.tbl_notiz.updateamum ELSE public.tbl_notiz.insertamum END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate"); + $this->NotizModel->addLimit(1); + + $result = $this->NotizModel->loadWhere( + array('notiz_id' => $notiz_id) + ); + if (isError($result)) + { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + elseif (!hasData($result)) + { + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL); + } + else + { + $this->terminateWithSuccess(current(getData($result))); + } + } + + + public function updateNotiz() + { + $this->load->library('form_validation'); + $this->load->library('DmsLib'); + + if (isset($_POST['data'])) + { + $data = json_decode($_POST['data']); + unset($_POST['data']); + foreach ($data as $k => $v) { + $_POST[$k] = $v; + } + } + + $notiz_id = $this->input->post('notiz_id'); + + if(!$notiz_id) + { + $this->terminateWithError($this->p->t('ui','error_missingId',['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL); + } + + //Form Validation + $this->form_validation->set_rules('titel', 'Titel', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel']) + ]); + + $this->form_validation->set_rules('text', 'Text', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Text']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + //update Notiz + $uid = getAuthUID(); + $titel = $this->input->post('titel'); + $text = $this->input->post('text'); + $verfasser_uid = $this->input->post('verfasser'); + $bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : $uid; + $erledigt = $this->input->post('erledigt'); + $start = $this->input->post('start'); + $ende = $this->input->post('ende'); + + $result = $this->NotizModel->update( + [ + 'notiz_id' => $notiz_id + ], + [ + 'titel' => $titel, + 'updatevon' => $uid, + 'updateamum' => date('c'), + 'text' => $text, + 'verfasser_uid' => $verfasser_uid, + 'bearbeiter_uid' => $bearbeiter_uid, + 'start' => $start, + 'ende' => $ende, + 'erledigt' => $erledigt + ] + ); + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + //update(1) laden aller bereits mit dieser notiz_id verknüpften DMS-Einträge + $this->load->model('person/Notizdokument_model', 'NotizdokumentModel'); + $this->NotizdokumentModel->addJoin('campus.tbl_dms_version', 'dms_id'); + $dms_uploaded = null; + + $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id)); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + elseif (!hasData($result)) + { + $dms_id_arr = null; + } + else + { + $result = getData($result); + foreach($result as $doc) { + $dms_id_arr[] = array( + 'name' => $doc->name, + 'dms_id' => $doc->dms_id + ); + } + } + + foreach ($_FILES as $k => $file) + { + //update(2) alle neuen files (alle außer type application/x.fhc-dms+json) anhängen + if($file["type"] == 'application/x.fhc-dms+json') + { + $dms_uploaded[] = array( + 'name' => $file["name"] + ); + } + else + { + $dms = array( + 'kategorie_kurzbz' => 'notiz', + 'version' => 0, + 'name' => $file["name"], + 'mimetype' => $file["type"], + 'insertamum' => date('c'), + 'insertvon' => $uid + ); + + //Todo(manu) check if filetypes weiter eingeschränkt werden sollen + //Todo(manu)check name files: nicht gleiches file 2mal hochladen + $result = $this->dmslib->upload($dms, $k, array('*')); + + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $dms_id = $result->retval['dms_id']; + + $result = $this->NotizdokumentModel->insert(array('notiz_id' => $notiz_id, 'dms_id' => $dms_id)); + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + } + } + + //update(3) check if Dateien gelöscht wurden + if(count($dms_uploaded) != count($dms_id_arr)) + { + if (count($dms_uploaded) == 0) + { + $filesDeleted = $dms_id_arr; + } + else + { + $upload_new_names = array_column($dms_uploaded, "name"); + + $filesDeleted = array_filter($dms_id_arr, function ($file) use ($upload_new_names) { + return !in_array($file["name"], $upload_new_names); + }); + } + + foreach ($filesDeleted as $file) + { + $result = $this->dmslib->removeAll($file['dms_id']); + + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + else + $this->outputJson($result); + } + } + return $this->terminateWithSuccess($result); + }*/ + + +/* public function deleteNotiz() + { + $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true); + $notiz_id = $this->input->post('notiz_id'); + $type = $this->input->post('type_id'); + $id = $this->input->post('id'); + + //dms_id auslesen aus notizdokument wenn vorhanden + $dms_id_arr = []; + $this->load->model('person/Notizdokument_model', 'NotizdokumentModel'); + + $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id)); + + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + if(hasData($result)) + { + $result = getData($result); + foreach ($result as $doc) { + $dms_id_arr[] = $doc->dms_id; + } + } + + if($dms_id_arr) + { + $this->load->library('DmsLib'); + foreach($dms_id_arr as $dms_id) + { + $result = $this->dmslib->removeAll($dms_id); + + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $this->outputJson($result); + } + } + + //delete Notizzuordnung + if($type == "software_id") + { + // Loads extension Model + $this->load->model('extensions/FHC-Core-Softwarebereitstellung/Softwarenotizzuordnung_model', 'ExtensionnotizzuordnungModel'); + $result = $this->ExtensionnotizzuordnungModel->delete([ + 'notiz_id' => $notiz_id, + 'id' => strval($id) + ], + [ + 'type_id' => $type + ]); + + } + else + { + //notizzuordnungsid! + $result = $this->NotizzuordnungModel->delete(['notiz_id' => $notiz_id, $type => $id]); + } + + + $this->load->model('person/Notiz_model', 'NotizModel'); + //$this->NotizModel->addJoin('public.tbl_notizzuordnung', 'notiz_id'); + + //TODO (erweitern um Type_id) für Extensions, damit auch Notizzuordnung gelöscht werden kann + + //Löschen von Notiz + $result = $this->NotizModel->delete( + array('notiz_id' => $notiz_id) + ); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if(!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL); + } + + return $this->terminateWithSuccess(current(getData($result))); + }*/ + +/* public function loadDokumente() + { + $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true); + $notiz_id = $this->input->post('notiz_id'); + + $this->NotizModel->addSelect('campus.tbl_dms_version.*'); + + $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'ON (public.tbl_notiz_dokument.notiz_id = public.tbl_notiz.notiz_id)'); + $this->NotizModel->addJoin('campus.tbl_dms_version', 'ON (public.tbl_notiz_dokument.dms_id = campus.tbl_dms_version.dms_id)'); + + $result = $this->NotizModel->loadWhere( + array('public.tbl_notiz.notiz_id' => $notiz_id) + ); + if (isError($result)) { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + if(!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result)); + }*/ + +/* public function getMitarbeiter($searchString) + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $result = $this->MitarbeiterModel->searchMitarbeiter($searchString); + if (isError($result)) { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess($result); + }*/ + + public function isBerechtigt($id, $typeId) + { + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + return success("berechtigt in überschreibender Funktion"); +/* return $this->terminateWithError('keine Berechtigung bro', self::ERROR_TYPE_GENERAL);*/ + } + +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/stv/Prestudent.php b/application/controllers/api/frontend/v1/stv/Prestudent.php new file mode 100644 index 000000000..ef9aeb111 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Prestudent.php @@ -0,0 +1,299 @@ + ['admin:r', 'assistenz:r'], + 'updatePrestudent' => ['admin:rw', 'assistenz:rw'], + 'getHistoryPrestudents' => ['admin:r', 'assistenz:r'], + 'getBezeichnungZGV' => ['admin:r', 'assistenz:r'], + 'getBezeichnungDZgv' => ['admin:r', 'assistenz:r'], + 'getBezeichnungMZgv' => ['admin:r', 'assistenz:r'], + 'getAusbildung' => ['admin:r', 'assistenz:r'], + 'getAufmerksamdurch' => ['admin:r', 'assistenz:r'], + 'getBerufstaetigkeit' => ['admin:r', 'assistenz:r'], + 'getTypenStg' => ['admin:r', 'assistenz:r'], + 'getStudienplaene' => ['admin:r', 'assistenz:r'], + 'getStudiengang' => ['admin:r', 'assistenz:r'] + ]); + + if ($this->router->method == 'updatePrestudent') { + $prestudent_id = current(array_slice($this->uri->rsegments, 2)); + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:rw', 'assistenz:rw']); + } elseif ($this->router->method == 'get' + || $this->router->method == 'getStudienplaene' + || $this->router->method == 'getStudiengang' + ) { + $prestudent_id = current(array_slice($this->uri->rsegments, 2)); + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:r', 'assistenz:r']); + } elseif ($this->router->method == 'getHistoryPrestudents') { + $person_id = current(array_slice($this->uri->rsegments, 2)); + $this->checkPermissionsForPerson($person_id, ['admin:r', 'assistenz:r'], ['admin:r', 'assistenz:r']); + } + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui', 'studierendenantrag', 'lehre' + ]); + } + + public function get($prestudent_id) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $this->PrestudentModel->addSelect('*'); + $result = $this->PrestudentModel->loadWhere(['prestudent_id' => $prestudent_id]); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + if(!hasData($result)) + { + return show_404(); + } + $this->terminateWithSuccess(current(getData($result))); + } + + public function updatePrestudent($prestudent_id) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + // UDF + $this->load->library('UDFLib'); + + $result = $this->udflib->getCiValidations($this->PrestudentModel, $this->input->post()); + $udf_field_validations = $this->getDataOrTerminateWithError($result); + + //Form validation + $this->load->library('form_validation'); + + $this->form_validation->set_rules($udf_field_validations); + + $this->form_validation->set_rules('priorisierung', 'Priorisierung', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Priorisierung']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $uid = getAuthUID(); + + $array_allowed_props_prestudent = [ + 'aufmerksamdurch_kurzbz', + 'studiengang_kz', + 'gsstudientyp_kurzbz', + 'person_id', + 'berufstaetigkeit_code', + 'ausbildungcode', + 'zgv_code', + 'zgvort', + 'zgvdatum', + 'zgvnation', + 'zgvmas_code', + 'zgvmaort', + 'zgvmadatum', + 'zgvmanation', + 'facheinschlberuf', + 'bismelden', + 'anmerkung', + 'dual', + 'zgvdoktor_code', + 'zgvdoktorort', + 'zgvdoktordatum', + 'zgvdoktornation', + 'aufnahmegruppe_kurzbz', + 'priorisierung', + 'foerderrelevant', + 'zgv_erfuellt', + 'zgvmas_erfuellt', + 'zgvdoktor_erfuellt', + 'mentor', + 'aufnahmeschluessel', + 'standort_code' + ]; + + // add UDFs + $result = $this->udflib->getDefinitionForModel($this->PrestudentModel); + + $definitions = $this->getDataOrTerminateWithError($result); + + foreach ($definitions as $def) + $array_allowed_props_prestudent[] = $def['name']; + + $update_prestudent = array(); + foreach ($array_allowed_props_prestudent as $prop) + { + $val = $this->input->post($prop); + if ($val !== null || $prop == 'foerderrelevant') { + $update_prestudent[$prop] = $val; + } + } + + $update_prestudent['updateamum'] = date('c'); + $update_prestudent['updatevon'] = $uid; + + if (count($update_prestudent)) + { + $result = $this->PrestudentModel->update( + $prestudent_id, + $update_prestudent + ); + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess(true); + } + return $this->terminateWithSuccess(false); + } + + public function getHistoryPrestudents($person_id) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $result = $this->PrestudentModel->getHistoryPrestudents($person_id); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getBezeichnungZGV() + { + $this->load->model('codex/Zgv_model', 'ZgvModel'); + + $this->ZgvModel->addOrder('zgv_code'); + + $result = $this->ZgvModel->load(); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getBezeichnungDZgv() + { + $this->load->model('codex/Zgvdoktor_model', 'ZgvdoktorModel'); + + $this->ZgvdoktorModel->addOrder('zgvdoktor_code'); + + $result = $this->ZgvdoktorModel->load(); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getBezeichnungMZgv() + { + $this->load->model('codex/Zgvmaster_model', 'ZgvmasterModel'); + + $this->ZgvmasterModel->addOrder('zgvmas_code'); + + $result = $this->ZgvmasterModel->load(); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getAusbildung() + { + $this->load->model('codex/Ausbildung_model', 'AusbildungModel'); + + $this->AusbildungModel->addOrder('ausbildungcode'); + + $result = $this->AusbildungModel->load(); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getAufmerksamdurch() + { + $this->load->model('codex/Aufmerksamdurch_model', 'AufmerksamdurchModel'); + + $this->AufmerksamdurchModel->addOrder('aufmerksamdurch_kurzbz'); + + $result = $this->AufmerksamdurchModel->load(); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getBerufstaetigkeit() + { + $this->load->model('codex/Berufstaetigkeit_model', 'BerufstaetigkeitModel'); + + $this->BerufstaetigkeitModel->addOrder('berufstaetigkeit_code'); + + $result = $this->BerufstaetigkeitModel->load(); + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getTypenStg() + { + $this->load->model('education/Gsstudientyp_model', 'GsstudientypModel'); + + $this->GsstudientypModel->addOrder('gsstudientyp_kurzbz'); + + $result = $this->GsstudientypModel->load(); + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getStudienplaene($prestudent_id) + { + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + $result = $this->StudienplanModel->getStudienplaeneByPrestudents($prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($data); + } + + /** + * Gets details for the Studiengang of the Prestudent + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function getStudiengang($prestudent_id) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $this->PrestudentModel->addSelect('stg.*'); + + $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz'); + + $result = $this->PrestudentModel->load($prestudent_id); + + $stg = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($stg)); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Status.php b/application/controllers/api/frontend/v1/stv/Status.php new file mode 100644 index 000000000..074f4029e --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Status.php @@ -0,0 +1,1753 @@ + ['admin:r', 'assistenz:r'], + 'getMaxSemester' => ['admin:r', 'assistenz:r'], + 'changeStatus' => ['admin:rw', 'assistenz:rw'], + 'addStudent' => ['admin:rw', 'assistenz:rw'], + 'getStatusgruende' => self::PERM_LOGGED, + 'getLastBismeldestichtag' => self::PERM_LOGGED, + 'isLastStatus' => self::PERM_LOGGED, + 'getStatusarray' => self::PERM_LOGGED, + 'deleteStatus' => ['admin:rw','assistenz:rw'], + 'loadStatus' => ['admin:r', 'assistenz:r'], + 'insertStatus' => ['admin:rw', 'assistenz:rw'], + 'updateStatus' => ['admin:rw', 'assistenz:rw'], + 'advanceStatus' => ['admin:rw', 'assistenz:rw'], + 'confirmStatus' => ['admin:rw', 'assistenz:rw'], + + ]); + + //Load Models + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->load->model('person/Person_model', 'PersonModel'); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('PrestudentstatusCheckLib'); + + // Additional Permission Checks + if ($this->router->method == 'insertStatus' + || $this->router->method == 'updateStatus' + || $this->router->method == 'confirmStatus' + || $this->router->method == 'deleteStatus' + || $this->router->method == 'advanceStatus' + || $this->router->method == 'changeStatus' + || $this->router->method == 'addStudent' + ) { + $prestudent_id = current(array_slice($this->uri->rsegments, 2)); + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:rw', 'assistenz:rw']); + } + + // Load language phrases + $this->loadPhrases([ + 'global', 'ui', 'bismeldestichtag','lehre','studierendenantrag' + ]); + } + + public function getHistoryPrestudent($prestudent_id) + { + $result = $this->PrestudentstatusModel->getHistoryPrestudent($prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * Gets the maximum possible semester for one or more Studiengaenge. + * If there are more than one Studiengang each maximum is calculated and + * the smallest result is returned. + * + * @return void + */ + public function getMaxSemester() + { + $studiengang_kzs = $this->input->post('studiengang_kzs'); + + if (!$studiengang_kzs || !is_array($studiengang_kzs)) { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('studiengang_kzs', '', 'required|is_null', [ + 'is_null' => $this->p->t('ui', 'error_fieldMustBeArray') + ]); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + + if (defined('VORRUECKUNG_STATUS_MAX_SEMESTER') && VORRUECKUNG_STATUS_MAX_SEMESTER == false) + $this->terminateWithSuccess(100); + + $this->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); + + $result = $this->LehrverbandModel->getMaxSemester($studiengang_kzs); + + $maxsem = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($maxsem ? current($maxsem)->maxsem : 10); + } + + public function getStatusgruende() + { + $this->load->model('crm/Statusgrund_model', 'StatusgrundModel'); + + $result = $this->StatusgrundModel->getAktiveGruende(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getLastBismeldestichtag() + { + $this->load->model('codex/Bismeldestichtag_model', 'BismeldestichtagModel'); + + $result = $this->BismeldestichtagModel->getLastReachedMeldestichtag(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function isLastStatus($prestudent_id) + { + $result = $this->PrestudentstatusModel->checkIfLastStatusEntry($prestudent_id); + + $result = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($result); + } + + public function getStudiensemesterOfStatus($prestudent_id, $status) + { + $result = $this->PrestudentstatusModel->loadWhere([ + "prestudent_id" => $prestudent_id, + "status_kurzbz" => $status + ]); + $this->PrestudentstatusModel->addLimit(1); + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $studiensem = current(getData($result)); + + return $studiensem->studiensemester_kurzbz; + } + + public function getStatusarray() + { + $this->load->model('crm/Status_model', 'StatusModel'); + $result = $this->StatusModel->getAllStatiWithStatusgruende(); + + if(isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * Changes the status of a prestudent with full additional logic. + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function changeStatus($prestudent_id) + { + $isBerechtigtNoStudstatusCheck = $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'); + + //GET lastStatus + $result = $this->PrestudentstatusModel->getLastStatus($prestudent_id); + + $lastStatusData = $this->getDataOrTerminateWithError($result); + $lastStatusData = current($lastStatusData); + + $this->load->model('person/Person_model', 'PersonModel'); + $this->PersonModel->addJoin('public.tbl_prestudent', 'person_id'); + $result = $this->PersonModel->loadWhere(['prestudent_id' => $prestudent_id]); + $prestudent_person = $this->getDataOrTerminateWithError($result); + $prestudent_person = current($prestudent_person); + + $studentName = trim($prestudent_person->vorname . ' ' . $prestudent_person->nachname); + + $status_kurzbz = $this->input->post('status_kurzbz'); + + $studiensemester_kurzbz = $lastStatusData->studiensemester_kurzbz; + if ($status_kurzbz == Prestudentstatus_model::STATUS_ABSOLVENT + || $status_kurzbz == Prestudentstatus_model::STATUS_DIPLOMAND + ) { + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + } + + $ausbildungssemester = $lastStatusData->ausbildungssemester; + if ($status_kurzbz == Prestudentstatus_model::STATUS_STUDENT) { + $ausbildungssemester = $this->input->post('ausbildungssemester'); + } + + $statusgrund_id = $this->input->post('statusgrund_id'); + $datum_string = date('c'); + $datum = new DateTime($datum_string); + + //Form Validation + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'status_kurzbz', + $this->p->t('global', 'status'), + [ + 'required', + //Check Reihungstest + ['reihungstest_check', function ($value) use ($prestudent_person) { + if (!REIHUNGSTEST_CHECK) + return true; + if ($value != Prestudentstatus_model::STATUS_BEWERBER) + return true; + $result = $this->prestudentstatuschecklib->checkIfAngetreten($prestudent_person); + return $this->getDataOrTerminateWithError($result); + }], + //Check ZGV + ['checkIfZGV', function ($value) use ($prestudent_person) { + if (defined("ZGV_CHECK") && !ZGV_CHECK) + return true; + if ($value != Prestudentstatus_model::STATUS_BEWERBER) + return true; + $result = $this->prestudentstatuschecklib->checkIfZGVEingetragen($prestudent_person); + return $this->getDataOrTerminateWithError($result); + }], + //Check ZGV Master + ['checkIfZGVMaster', function ($value) use ($prestudent_person) { + if (defined("ZGV_CHECK") && !ZGV_CHECK) + return true; + if ($value != Prestudentstatus_model::STATUS_BEWERBER) + return true; + $result = $this->prestudentstatuschecklib->checkIfZGVEingetragenMaster($prestudent_person); + return $this->getDataOrTerminateWithError($result); + }], + //Check Bewerberstatus + ['checkIfExistingBewerberstatus', function ($value) use ($prestudent_id) { + if ($value != Prestudentstatus_model::STATUS_AUFGENOMMENER + && $value != Prestudentstatus_model::STATUS_WARTENDER + ) + return true; + $result = $this->prestudentstatuschecklib->checkIfExistingBewerberstatus($prestudent_id); + return $this->getDataOrTerminateWithError($result); + }], + //Check If Student + ['status_stud_exists', function ($value) use ($prestudent_id) { + if ($value != Prestudentstatus_model::STATUS_STUDENT + && $value != Prestudentstatus_model::STATUS_ABBRECHER + ) + return true; // Only test if new status is Student + + $result = $this->prestudentstatuschecklib->checkIfExistingStudent($prestudent_id); + + return $this->getDataOrTerminateWithError($result); + }], + ], + [ + 'reihungstest_check' => $this->p->t('lehre', 'error_keinReihungstestverfahren', ['name' => $studentName]), + 'checkIfExistingBewerberstatus' => $this->p->t('lehre', 'error_keinBewerber', ['name' => $studentName]), + 'checkIfZGV' => $this->p->t('lehre', 'error_ZGVNichtEingetragen', ['name' => $studentName]), + 'checkIfZGVMaster' => $this->p->t('lehre', 'error_ZGVMasterNichtEingetragen', ['name' => $studentName]), + 'status_stud_exists' => $this->p->t('lehre', 'error_noStudstatus') + ] + ); + + if ($status_kurzbz == Prestudentstatus_model::STATUS_STUDENT) + $this->form_validation->set_rules('ausbildungssemester', $this->p->t('lehre', 'ausbildungssemester'), 'required|integer', [ + 'integer' => $this->p->t('ui', 'error_fieldNotInteger') + ]); + else + $this->form_validation->set_rules('ausbildungssemester', $this->p->t('lehre', 'ausbildungssemester'), 'integer', [ + 'integer' => $this->p->t('ui', 'error_fieldNotInteger') + ]); + + $this->form_validation->set_rules('statusgrund_id', $this->p->t('international', 'grund'), 'integer', [ + 'integer' => $this->p->t('ui', 'error_fieldNotInteger') + ]); + + $this->form_validation->set_rules('_default', '', [ + ['meldestichtag_not_exceeded', function () use ($datum, $isBerechtigtNoStudstatusCheck) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + + $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($datum); + + return !$this->getDataOrTerminateWithError($result); + }], + //Check if Rolle already exists + ['rolle_doesnt_exist', function () use ($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester) { + if (!$status_kurzbz || !$studiensemester_kurzbz || !$ausbildungssemester) + return true; // Error will be handled by the required statements above + + $result = $this->PrestudentstatusModel->load([$ausbildungssemester, $studiensemester_kurzbz, $status_kurzbz, $prestudent_id]); + + return !$this->getDataOrTerminateWithError($result); + }], + ['history_timesequence', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz) + return true; // Error will be handled by the required statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryTimesequence( + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_laststatus', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz) + return true; // Error will be handled by the required statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryLaststatus( + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_unterbrecher', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz) + return true; // Error will be handled by the required statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryUnterbrechersemester( + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_abbrecher', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz) + return true; // Error will be handled by the required statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryAbbrechersemester( + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_diplomant', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz) + return true; // Error will be handled by the required statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryDiplomant( + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }] + ], [ + 'meldestichtag_not_exceeded' => $this->p->t('lehre', 'error_dataVorMeldestichtag'), + 'rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhandenMitNamen', ['name' => $studentName]), + 'history_timesequence' => $this->p->t('lehre', 'error_statuseintrag_zeitabfolge'), + 'history_laststatus' => $this->p->t('lehre', 'error_endstatus'), + 'history_unterbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecher'), + 'history_abbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecherAbbrecher'), + 'history_diplomant' => $this->p->t('lehre', 'error_consecutiveDiplomandStudent') + ]); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $this->load->library('PrestudentLib'); + + $this->db->trans_start(); + + switch($status_kurzbz){ + case Prestudentstatus_model::STATUS_ABBRECHER: + $result = $this->prestudentlib->setAbbrecher( + $prestudent_id, + $studiensemester_kurzbz, + null, + $statusgrund_id, + $datum_string, + null, + null + ); + break; + case Prestudentstatus_model::STATUS_UNTERBRECHER: + $result = $this->prestudentlib->setUnterbrecher( + $prestudent_id, + $studiensemester_kurzbz, + null, + null, + $ausbildungssemester, + $statusgrund_id + ); + break; + case Prestudentstatus_model::STATUS_STUDENT: + $result = $this->prestudentlib->setStudent( + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + break; + case Prestudentstatus_model::STATUS_DIPLOMAND: + $result = $this->prestudentlib->setDiplomand( + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + break; + case Prestudentstatus_model::STATUS_ABSOLVENT: + $result = $this->prestudentlib->setAbsolvent( + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + break; + case Prestudentstatus_model::STATUS_BEWERBER: + $result = $this->prestudentlib->setBewerber( + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + break; + case Prestudentstatus_model::STATUS_AUFGENOMMENER: + $result = $this->prestudentlib->setAufgenommener( + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + break; + case Prestudentstatus_model::STATUS_ABGEWIESENER: + $result = $this->prestudentlib->setAbgewiesener( + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + break; + case Prestudentstatus_model::STATUS_WARTENDER: + $result = $this->prestudentlib->setWartender( + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + break; + default: + $this->terminateWithError("Action not yet defined in Prestudentlib", self::ERROR_TYPE_GENERAL); + } + + $this->getDataOrTerminateWithError($result); + + $this->db->trans_complete(); + + $this->terminateWithSuccess($prestudent_id); + } + + public function addStudent($prestudent_id) + { + // Prepare lastAufgenommener Status + $this->PrestudentstatusModel->addOrder('datum', 'DESC'); + $this->PrestudentstatusModel->addOrder('insertamum', 'DESC'); + $this->PrestudentstatusModel->addLimit(1); + $result = $this->PrestudentstatusModel->loadWhere([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_AUFGENOMMENER + ]); + $lastAufgenommener = $this->getDataOrTerminateWithError($result); + + if ($lastAufgenommener) + $lastAufgenommener = current($lastAufgenommener); + + //get studentname for validations + $this->load->model('person/Person_model', 'PersonModel'); + $this->PersonModel->addJoin('public.tbl_prestudent', 'person_id'); + $result = $this->PersonModel->loadWhere(['prestudent_id' => $prestudent_id]); + $prestudent_person = $this->getDataOrTerminateWithError($result); + $prestudent_person = current($prestudent_person); + + $studentName = trim($prestudent_person->vorname . ' ' . $prestudent_person->nachname); + + + //Form Validation + $this->load->library('form_validation'); + + $this->form_validation->set_rules('statusgrund_id', $this->p->t('international', 'grund'), 'integer', [ + 'integer' => $this->p->t('ui', 'error_fieldNotInteger') + ]); + + $this->form_validation->set_rules('_default', '', [ + //Check ZGV + ['checkIfZGV', function () use ($prestudent_person) { + if (defined("ZGV_CHECK") && !ZGV_CHECK) + return true; + $result = $this->prestudentstatuschecklib->checkIfZGVEingetragen($prestudent_person); + return $this->getDataOrTerminateWithError($result); + }], + //Check ZGV Master + ['checkIfZGVMaster', function () use ($prestudent_person) { + if (defined("ZGV_CHECK") && !ZGV_CHECK) + return true; + $result = $this->prestudentstatuschecklib->checkIfZGVEingetragenMaster($prestudent_person); + return $this->getDataOrTerminateWithError($result); + }], + //Check Bewerberstatus + ['checkIfExistingBewerberstatus', function () use ($prestudent_id) { + $result = $this->prestudentstatuschecklib->checkIfExistingBewerberstatus($prestudent_id); + return $this->getDataOrTerminateWithError($result); + }], + //Check Aufgenommenerstatus + ['checkIfExistingAufgenommenerstatus', function () use ($lastAufgenommener) { + return !!$lastAufgenommener; + }], + //Check Bewerberstatus & Aufgenommenerstatus semester + ['checkIfLastBewerberAndAufgenommenerShareSemesters', function () use ($prestudent_id) { + $result = $this->prestudentstatuschecklib->checkIfLastBewerberAndAufgenommenerShareSemesters($prestudent_id); + return $this->getDataOrTerminateWithError($result); + }], + //Check If FirstStudent + ['check_isFirstStudStatus', function () use ($prestudent_id) { + $result = $this->prestudentstatuschecklib->checkIfExistingStudent($prestudent_id); + + return !$this->getDataOrTerminateWithError($result); + }], + //Check if Rolle already exists + ['rolle_doesnt_exist', function () use ($prestudent_id, $lastAufgenommener) { + if (!$lastAufgenommener) + return true; // Error will be handled by the checkIfExistingAufgenommenerstatus statement above + + $result = $this->PrestudentstatusModel->loadWhere([ + 'studiensemester_kurzbz' => $lastAufgenommener->studiensemester_kurzbz, + 'status_kurzbz' => Prestudentstatus_model::STATUS_STUDENT, + 'prestudent_id' => $prestudent_id + ]); + + return !$this->getDataOrTerminateWithError($result); + }] + ], [ + 'reihungstest_check' => $this->p->t('lehre', 'error_keinReihungstestverfahren', ['name' => $studentName]), + 'checkIfExistingBewerberstatus' => $this->p->t('lehre', 'error_keinBewerber', ['name' => $studentName]), + 'checkIfExistingAufgenommenerstatus' => $this->p->t('lehre', 'error_keinAufgenommener', ['name' => $studentName]), + 'checkIfLastBewerberAndAufgenommenerShareSemesters' => $this->p->t('lehre', 'error_lastBewerberAndAufgenommenerSemesters'), + 'checkIfZGV' => $this->p->t('lehre', 'error_ZGVNichtEingetragen', ['name' => $studentName]), + 'checkIfZGVMaster' => $this->p->t('lehre', 'error_ZGVMasterNichtEingetragen', ['name' => $studentName]), + 'check_isFirstStudStatus' => $this->p->t('lehre', 'error_personBereitsStudent', ['name' => $studentName]), + 'rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhandenMitNamen', ['name' => $studentName]) + ]); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + // Start DB transaction + $this->db->trans_start(); + + $this->load->library('PrestudentLib'); + + $this->prestudentlib->setFirstStudent( + $prestudent_id, + $lastAufgenommener->studiensemester_kurzbz, + $lastAufgenommener->ausbildungssemester, + $lastAufgenommener->orgform_kurzbz, + $lastAufgenommener->studienplan_id, + $this->input->post('statusgrund_id') + ); + + $this->getDataOrTerminateWithError($result); + + $this->db->trans_commit(); + + return $this->outputJsonSuccess(true); + } + + public function loadStatus() + { + $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true); + + $prestudent_id = $this->input->post('prestudent_id'); + $status_kurzbz = $this->input->post('status_kurzbz'); + $ausbildungssemester = $this->input->post('ausbildungssemester'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + + $result = $this->PrestudentstatusModel->loadWhere( + array( + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ) + ); + if (isError($result)) + { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + elseif (!hasData($result)) + { + $this->terminateWithError($this->p->t('lehre', 'error_noStatusFound'), self::ERROR_TYPE_GENERAL); + } + else + { + $this->terminateWithSuccess(current(getData($result))); + } + } + + /** + * Delete a status entry + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param string $studiensemester_kurzbz + * @param integer $ausbildungssemester + * + * @return void + */ + public function deleteStatus($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester) + { + $result = $this->PrestudentstatusModel->load([ + $ausbildungssemester, + $studiensemester_kurzbz, + $status_kurzbz, + $prestudent_id + ]); + $oldstatus = $this->getDataOrTerminateWithError($result); + if (!$oldstatus) + show_404(); // Status that should be updated does not exist + + $oldstatus = current($oldstatus); + + + $erweiterteBerechtigung = + $this->permissionlib->isBerechtigt('admin', null, 'suid') + || $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung', null, 'suid'); + + + //check if last status + $result = $this->PrestudentstatusModel->checkIfLastStatusEntry($prestudent_id); + + $result = $this->getDataOrTerminateWithError($result); + + $deletePrestudent = $result; + + + //Berechtigungen nach Check prüfen! + if (!$erweiterteBerechtigung) { + if ($status_kurzbz == Prestudentstatus_model::STATUS_STUDENT) + $this->terminateWithError( + $this->p->t('lehre', 'error_onlyAdminDeleteRolleStudent'), + self::ERROR_TYPE_GENERAL, + REST_Controller::HTTP_FORBIDDEN + ); + + if ($deletePrestudent) + $this->terminateWithError( + $this->p->t('lehre', 'error_onlyAdminDeleteLastStatus'), + self::ERROR_TYPE_GENERAL, + REST_Controller::HTTP_FORBIDDEN + ); + + $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($oldstatus->datum); + + if (!$this->getDataOrTerminateWithError($result)) + $this->terminateWithError( + $this->p->t('lehre', 'error_dataVorMeldestichtag'), + self::ERROR_TYPE_GENERAL, + REST_Controller::HTTP_FORBIDDEN + ); + } + + // Start DB transaction + $this->db->trans_begin(); + + //Delete Status + $result = $this->PrestudentstatusModel->delete( + [ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ] + ); + + $this->getDataOrTerminateWithError($result); + + //Delete Studentlehrverband if no Status left in this semester + $result = $this->PrestudentstatusModel->checkIfLastStatusEntry($prestudent_id, $studiensemester_kurzbz); + + $result = $this->getDataOrTerminateWithError($result); + if ($result) + { + //get student_uid + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + + $student = $this->getDataOrTerminateWithError($result); + if ($student) + { + $student = current($student); + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $result = $this->StudentlehrverbandModel->delete( + array( + 'student_uid' => $student->student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ) + ); + + $this->getDataOrTerminateWithError($result); + } + } + + //Delete Prestudent if no data is left + if ($deletePrestudent) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->delete($prestudent_id); + + $this->getDataOrTerminateWithError($result); + } + + $this->db->trans_commit(); + + return $this->terminateWithSuccess(true); + } + + /** + * Inserts a status with less validations and extra logic for manual + * manipulation + * + * @param integer $prestudent_id + * + * @return void + */ + public function insertStatus($prestudent_id) + { + $isBerechtigtNoStudstatusCheck = $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'); + $isBerechtigtBasisPrestudentstatus = $this->permissionlib->isBerechtigt('basis/prestudentstatus'); + + + $authUID = getAuthUID(); + $status_kurzbz = $this->input->post('status_kurzbz'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $ausbildungssemester = $this->input->post('ausbildungssemester'); + $datum = $this->input->post('datum'); + $bestaetigtam = $this->input->post('bestaetigtam'); + $orgform_kurzbz = $this->input->post('orgform_kurzbz'); + $anmerkung = $this->input->post('anmerkung'); + $bewerbung_abgeschicktamum = $this->input->post('bewerbung_abgeschicktamum'); + $studienplan_id = $this->input->post('studienplan_id'); + $rt_stufe = $this->input->post('rt_stufe'); + $statusgrund_id = $this->input->post('statusgrund_id'); + + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('statusgrund_id', $this->p->t('international', 'grund'), 'integer', [ + 'integer' => $this->p->t('ui', 'error_fieldNotInteger') + ]); + + if (!$isBerechtigtBasisPrestudentstatus) + $this->form_validation->set_rules( + 'bewerbung_abgeschicktamum', + $this->p->t('lehre', 'bewerbung_abgeschickt_am'), + 'is_null', + [ + 'is_null' => $this->p->t('ui', 'error_fieldWriteAccess') + ] + ); + + $this->form_validation->set_rules( + 'datum', + $this->p->t('global', 'datum'), + [ + 'required', // In FAS empty datum results in todays + 'is_valid_date', + ['is_date_not_before_today', function ($value) { + if (!is_valid_date($value)) + return true; // Error will be handled by the is_valid_date statement above + $today = new DateTime('today'); + return (new DateTime($value) >= $today); + }], + ['meldestichtag_not_exceeded', function ($value) use ($isBerechtigtNoStudstatusCheck) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$value) + return true; // Error will be handled by the required statement above + + $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($value); + + return !$this->getDataOrTerminateWithError($result); + }] + ], + [ + 'meldestichtag_not_exceeded' => $this->p->t('lehre', 'error_dataVorMeldestichtag'), + 'is_date_not_before_today' => $this->p->t('lehre', 'error_entryInPast') + ] + ); + + $this->form_validation->set_rules( + 'status_kurzbz', + $this->p->t('lehre', 'status_rolle'), + [ + 'required', + ['status_stud_exists', function ($value) use ($prestudent_id) { + if ($value != Prestudentstatus_model::STATUS_STUDENT) + return true; // Only test if new status is Student + + $result = $this->prestudentstatuschecklib->checkIfExistingStudent($prestudent_id); + + return $this->getDataOrTerminateWithError($result); + }] + ], + [ + 'status_stud_exists' => $this->p->t('lehre', 'error_noStudstatus') + ] + ); + + $this->form_validation->set_rules('studiensemester_kurzbz', $this->p->t('lehre', 'studiensemester'), 'required'); + + $this->form_validation->set_rules('ausbildungssemester', $this->p->t('lehre', 'ausbildungssemester'), 'required'); + + $this->form_validation->set_rules('bestaetigtam', $this->p->t('lehre', 'bestaetigt_am'), 'is_valid_date'); + + // Set Datum to null to prevent multiple is_valid_date checks in the following validation rules + if (!$datum || !is_valid_date($datum)) + $datum = null; + + $this->form_validation->set_rules('_default', '', [ + ['rolle_doesnt_exist', function () use ($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester) { + if (!$status_kurzbz || !$studiensemester_kurzbz || !$ausbildungssemester) + return true; // Error will be handled by the required statements above + + $result = $this->PrestudentstatusModel->load([$ausbildungssemester, $studiensemester_kurzbz, $status_kurzbz, $prestudent_id]); + + return !$this->getDataOrTerminateWithError($result); + }], + ['history_timesequence', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester) + return true; // Error will be handled by the required statements above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryTimesequence( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_laststatus', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester) + return true; // Error will be handled by the required statements above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryLaststatus( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_unterbrecher', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester) + return true; // Error will be handled by the required statements above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryUnterbrechersemester( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_abbrecher', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester) + return true; // Error will be handled by the required statements above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryAbbrechersemester( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_diplomant', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester) + return true; // Error will be handled by the required statements above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryDiplomant( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + '', + '' + ); + + return $this->getDataOrTerminateWithError($result); + }] + ], [ + 'rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhanden'), + 'history_timesequence' => $this->p->t('lehre', 'error_statuseintrag_zeitabfolge'), + 'history_laststatus' => $this->p->t('lehre', 'error_endstatus'), + 'history_unterbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecher'), + 'history_abbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecherAbbrecher'), + 'history_diplomant' => $this->p->t('lehre', 'error_consecutiveDiplomandStudent') + ]); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + // Start DB transaction + $this->db->trans_start(); + + $this->updateLehrverbandForInsertAndUpdate($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $authUID); + + //insert status + $result = $this->PrestudentstatusModel->insert([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + 'datum' => $datum, + 'insertamum' => date('c'), + 'insertvon' => $authUID, + 'orgform_kurzbz' => $orgform_kurzbz, + 'bestaetigtam' => $bestaetigtam, + 'bestaetigtvon' => $bestaetigtam ? $authUID : null, + 'anmerkung' => $anmerkung, + 'bewerbung_abgeschicktamum' => $bewerbung_abgeschicktamum, + 'studienplan_id' => $studienplan_id, + 'rt_stufe' => $rt_stufe, + 'statusgrund_id' => $statusgrund_id + ]); + + $this->getDataOrTerminateWithError($result); + + $this->db->trans_complete(); + + $this->terminateWithSuccess(true); + } + + /** + * Updates a status entry + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param string $key_studiensemester_kurzbz + * @param integer $key_ausbildungssemester + * + * @return void + */ + public function updateStatus($prestudent_id, $status_kurzbz, $key_studiensemester_kurzbz, $key_ausbildungssemester) + { + $result = $this->PrestudentstatusModel->load([ + $key_ausbildungssemester, + $key_studiensemester_kurzbz, + $status_kurzbz, + $prestudent_id + ]); + $oldstatus = $this->getDataOrTerminateWithError($result); + if (!$oldstatus) + show_404(); // Status that should be updated does not exist + + $oldstatus = current($oldstatus); + + + $isBerechtigtNoStudstatusCheck = $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'); + $isBerechtigtBasisPrestudentstatus = $this->permissionlib->isBerechtigt('basis/prestudentstatus'); + + + $authUID = getAuthUID(); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz') ?: $oldstatus->studiensemester_kurzbz; + $ausbildungssemester = $this->input->post('ausbildungssemester') ?: $oldstatus->ausbildungssemester; + $datum = $this->input->post('datum') ?: $oldstatus->datum; + + + //Form Validation + $this->load->library('form_validation'); + + $this->form_validation->set_rules('statusgrund_id', $this->p->t('international', 'grund'), 'integer', [ + 'integer' => $this->p->t('ui', 'error_fieldNotInteger') + ]); + + if (!$isBerechtigtBasisPrestudentstatus) + $this->form_validation->set_rules( + 'bewerbung_abgeschicktamum', + $this->p->t('lehre', 'bewerbung_abgeschickt_am'), + 'is_null', + [ + 'is_null' => $this->p->t('ui', 'error_fieldWriteAccess') + ] + ); + + $this->form_validation->set_rules( + 'datum', + $this->p->t('global', 'datum'), + [ + 'is_valid_date', + ['meldestichtag_not_exceeded', function ($value) use ($isBerechtigtNoStudstatusCheck) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$value) + return true; // Error will be handled by the required statement above + + $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($value); + + return !$this->getDataOrTerminateWithError($result); + }] + ], + [ + 'meldestichtag_not_exceeded' => $this->p->t('lehre', 'error_dataVorMeldestichtag') + ] + ); + + $this->form_validation->set_rules('bestaetigtam', $this->p->t('lehre', 'bestaetigt_am'), 'is_valid_date'); + + if (!is_valid_date($datum)) + $datum = null; + + // Set Datum to null to prevent multiple is_valid_date checks in the following validation rules + $this->form_validation->set_rules('_default', '', [ + //Check if Rolle already exists + ['new_rolle_doesnt_exist', function () use ( + $prestudent_id, + $status_kurzbz, + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ) { + if ($key_studiensemester_kurzbz == $studiensemester_kurzbz + && $key_ausbildungssemester == $ausbildungssemester + ) + return true; // Primary key has not change we update in place + + $result = $this->PrestudentstatusModel->load([ + $ausbildungssemester, + $studiensemester_kurzbz, + $status_kurzbz, + $prestudent_id + ]); + return !$this->getDataOrTerminateWithError($result); + }], + ['history_timesequence', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$datum) + return true; // Error will be handled by the is_valid_date statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryTimesequence( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_laststatus', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$datum) + return true; // Error will be handled by the is_valid_date statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryLaststatus( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_unterbrecher', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$datum) + return true; // Error will be handled by the is_valid_date statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryUnterbrechersemester( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_abbrecher', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$datum) + return true; // Error will be handled by the is_valid_date statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryAbbrechersemester( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ); + + return $this->getDataOrTerminateWithError($result); + }], + ['history_diplomant', function () use ( + $isBerechtigtNoStudstatusCheck, + $prestudent_id, + $status_kurzbz, + $datum, + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ) { + if ($isBerechtigtNoStudstatusCheck) + return true; // Skip if access right says so + if (!$datum) + return true; // Error will be handled by the is_valid_date statement above + + $result = $this->prestudentstatuschecklib->checkStatusHistoryDiplomant( + $prestudent_id, + $status_kurzbz, + new DateTime($datum), + $studiensemester_kurzbz, + $ausbildungssemester, + $key_studiensemester_kurzbz, + $key_ausbildungssemester + ); + + return $this->getDataOrTerminateWithError($result); + }] + ], [ + 'new_rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhanden'), + 'history_timesequence' => $this->p->t('lehre', 'error_statuseintrag_zeitabfolge'), + 'history_laststatus' => $this->p->t('lehre', 'error_endstatus'), + 'history_unterbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecher'), + 'history_abbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecherAbbrecher'), + 'history_diplomant' => $this->p->t('lehre', 'error_consecutiveDiplomandStudent') + ]); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + // Start DB transaction + $this->db->trans_start(); + + $this->updateLehrverbandForInsertAndUpdate($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $authUID); + + //update status + $updateData = [ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + 'datum' => $datum, + 'updateamum' => date('c'), + 'updatevon' => $authUID + ]; + foreach ([ + 'orgform_kurzbz', + 'anmerkung', + 'bewerbung_abgeschicktamum', + 'studienplan_id', + 'rt_stufe', + 'statusgrund_id' + ] as $key) + if ($this->input->post($key)) + $updateData[$key] = $this->input->post($key); + + if ($this->input->post('bestaetigtam')) { + $updateData['bestaetigtam'] = $this->input->post('bestaetigtam'); + $updateData['bestaetigtvon'] = $authUID; + } + + $result = $this->PrestudentstatusModel->update([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'studiensemester_kurzbz' => $key_studiensemester_kurzbz, + 'ausbildungssemester' => $key_ausbildungssemester, + ], $updateData); + + $this->getDataOrTerminateWithError($result); + + $this->db->trans_commit(); + + return $this->outputJsonSuccess(true); + } + + /** + * Advances a status entry + * must be of type Student, Diplomand or Unterbrecher + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param string $key_studiensemester_kurzbz + * @param integer $key_ausbildungssemester + * + * @return void + */ + public function advanceStatus($prestudent_id, $status_kurzbz, $key_studiensemester_kurzbz, $key_ausbildungssemester) + { + $result = $this->PrestudentstatusModel->load([ + $key_ausbildungssemester, + $key_studiensemester_kurzbz, + $status_kurzbz, + $prestudent_id + ]); + $oldstatus = $this->getDataOrTerminateWithError($result); + if (!$oldstatus) + show_404(); // Status that should be updated does not exist + + $oldstatus = current($oldstatus); + + + //Target studiensemester_kurzbz + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $result = $this->StudiensemesterModel->getNextFrom($key_studiensemester_kurzbz); + + $studiensemester_kurzbz = $this->getDataOrTerminateWithError($result); + $studiensemester_kurzbz = current($studiensemester_kurzbz)->studiensemester_kurzbz; + + + //Target ausbildungssemester + $ausbildungssemester = $key_ausbildungssemester + 1; + + + //Form Validation + $this->load->library('form_validation'); + + $this->form_validation->set_data([ + 'status_kurzbz' => $status_kurzbz + ]); + + $this->form_validation->set_rules('status_kurzbz', $this->p->t('lehre', 'status_rolle'), [ + 'in_list[' . + Prestudentstatus_model::STATUS_STUDENT . ',' . + Prestudentstatus_model::STATUS_DIPLOMAND . ',' . + Prestudentstatus_model::STATUS_UNTERBRECHER . ']', + ['status_stud_exists', function ($value) use ($prestudent_id) { + if ($value != Prestudentstatus_model::STATUS_STUDENT) + return true; + + $result = $this->prestudentstatuschecklib->checkIfExistingStudent($prestudent_id); + + return $this->getDataOrTerminateWithError($result); + }] + ], [ + 'status_stud_exists' => $this->p->t('lehre', 'error_noStudstatus') + ]); + + $this->form_validation->set_rules('_default', '', [ + //Check if Rolle already exists + ['rolle_doesnt_exist', function () use ( + $prestudent_id, + $status_kurzbz, + $studiensemester_kurzbz, + $ausbildungssemester + ) { + $result = $this->PrestudentstatusModel->load([$ausbildungssemester, $studiensemester_kurzbz, $status_kurzbz, $prestudent_id]); + + return !$this->getDataOrTerminateWithError($result); + }] + ], [ + 'rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhanden') + ]); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + // Start DB transaction + $this->db->trans_begin(); + + $authUID = getAuthUID(); + $now = date('c'); + + //insert prestudentstatus + $result = $this->PrestudentstatusModel->insert([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + 'datum' => $now, + 'insertamum' => $now, + 'insertvon' => $authUID, + 'orgform_kurzbz' => $oldstatus->orgform_kurzbz, + 'studienplan_id' => $oldstatus->studienplan_id, + 'bestaetigtam' => $now, + 'bestaetigtvon' => $authUID, + 'anmerkung' => $oldstatus->anmerkung + ]); + + $this->getDataOrTerminateWithError($result); + + + //get student_uid + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + + $student = $this->getDataOrTerminateWithError($result); + + if (!$student) + $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id])); + $student = current($student); + + + //process studentlehrverband + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $result = $this->StudentlehrverbandModel->load([ + $key_studiensemester_kurzbz, + $student->student_uid + ]); + + $studentlvb = $this->getDataOrTerminateWithError($result); + if (!$studentlvb) + $this->terminateWithError($this->p->t('lehre', 'error_noStudentlehrverband')); + + //Data of current Semester + $studentlvb = current($studentlvb); + + + $newStudentlvb = [ + 'student_uid' => $studentlvb->student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $studentlvb->studiengang_kz, + 'semester' => $studentlvb->semester, + 'verband' => $studentlvb->verband, + 'gruppe' => $studentlvb->gruppe, + 'insertamum' => $now, + 'insertvon' => $authUID, + 'ext_id' => $studentlvb->ext_id + + ]; + + + $this->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); + + $result = $this->LehrverbandModel->load([ + $student->gruppe, + $student->verband, + $ausbildungssemester, + $student->studiengang_kz + ]); + + $lv = $this->getDataOrTerminateWithError($result); + if ($lv) { + $newStudentlvb['semester'] = $ausbildungssemester; + } // If there is no lehrverband just use the same as in the previous studiensemester + + + //add studentlehrverband + $result = $this->StudentlehrverbandModel->insert($newStudentlvb); + + $this->getDataOrTerminateWithError($result); + + $this->db->trans_commit(); + + return $this->outputJsonSuccess(true); + } + + /** + * Confirms a status entry + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param string $key_studiensemester_kurzbz + * @param integer $key_ausbildungssemester + * + * @return void + */ + public function confirmStatus($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester) + { + $result = $this->PrestudentstatusModel->load([ + $ausbildungssemester, + $studiensemester_kurzbz, + $status_kurzbz, + $prestudent_id + ]); + $oldstatus = $this->getDataOrTerminateWithError($result); + if (!$oldstatus) + show_404(); // Status that should be updated does not exist + + $oldstatus = current($oldstatus); + + + $authUID = getAuthUID(); + $now = date('c'); + + //Form Validation + $this->load->library('form_validation'); + + $this->form_validation->set_rules('Status', '', [ + ['status_not_yet_confirmed', function () use ($oldstatus) { + return !$oldstatus->bestaetigtam; + }], + ['bewerbung_abgeschickt', function () use ($oldstatus) { + return !!$oldstatus->bewerbung_abgeschicktamum; + }] + ], [ + 'status_not_yet_confirmed' => $this->p->t('lehre', 'error_statusConfirmedYet'), + 'bewerbung_abgeschickt' => $this->p->t('lehre', 'error_bewerbungNochNichtAbgeschickt') + ]); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + //update status + $result = $this->PrestudentstatusModel->update([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + ], [ + 'bestaetigtam' => $now, + 'bestaetigtvon' => $authUID, + 'updateamum' => $now, + 'updatevon' => $authUID + ]); + + $this->getDataOrTerminateWithError($result); + + + //Send Message + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $this->PrestudentModel->addSelect('p.*'); + $this->PrestudentModel->addSelect('stg.oe_kurzbz'); + $this->PrestudentModel->addSelect('stg.bezeichnung AS stg_bezeichnung'); + $this->PrestudentModel->addSelect('stg.email AS stg_email'); + $this->PrestudentModel->addSelect('plan.orgform_kurzbz'); + $this->PrestudentModel->addSelect('typ.bezeichnung AS typ_bezeichnung'); + + $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz'); + $this->PrestudentModel->addJoin('public.tbl_studiengangstyp typ', 'typ'); + $this->PrestudentModel->addJoin('public.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + + $result = $this->PrestudentModel->load($prestudent_id); + + $studentdata = $this->getDataOrTerminateWithError($result); + + $this->load->library('MessageLib'); + $result = $this->messagelib->sendMessageUserTemplate( + $studentdata->person_id, // receiversPersonId + 'MailStatConfirm' . $status_kurzbz, // vorlage + [ + 'anrede' => $studentdata->anrede, + 'vorname' => $studentdata->vorname, + 'nachname' => $studentdata->nachname, + 'typ' => $studentdata->typ_bezeichnung, + 'studiengang' => $studentdata->stg_bezeichnung, + 'orgform' => $studentdata->orgform_kurzbz ?: $oldstatus->orgform_kurzbz, + 'stgMail' => $studentdata->stg_email + ], // parseData + null, // orgform + 1, // TODO + $studentdata->oe_kurzbz, // senderOU + null, // relationmessage_id + MSG_PRIORITY_NORMAL, // priority + true // multiPartMime + ); + + + $this->terminateWithSuccess(true); + } + + /** + * Helper function for insertStatus and updateStatus. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param string $studiensemester_kurzbz + * @param integer $ausbildungssemester + * @param string $authUID + * + * @return void + */ + private function updateLehrverbandForInsertAndUpdate($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $authUID) + { + if (!in_array($status_kurzbz, [ + Prestudentstatus_model::STATUS_STUDENT, + Prestudentstatus_model::STATUS_DIPLOMAND, + Prestudentstatus_model::STATUS_ABSOLVENT, + Prestudentstatus_model::STATUS_INCOMING, + Prestudentstatus_model::STATUS_ABBRECHER, + Prestudentstatus_model::STATUS_UNTERBRECHER + ])) + return; // No Update necessary + + $result = $this->StudentModel->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + + $student = $this->getDataOrTerminateWithError($result); + + if (!$student) + return; // No Update necessary + + $student = current($student); + + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $result = $this->StudentlehrverbandModel->loadWhere([ + 'student_uid' => $student->student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); + + $studentlvb = $this->getDataOrTerminateWithError($result); + + + $this->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); + + $this->LehrverbandModel->addLimit(1); + $result = $this->LehrverbandModel->load([ + $student->gruppe, + $student->verband, + $ausbildungssemester, + $student->studiengang_kz + ]); + $lv = $this->getDataOrTerminateWithError($result); + + + if ($studentlvb && !$lv) + return; // No Update necessary + + if ($studentlvb) // Update current Student-Lehrverband entry + $this->StudentlehrverbandModel->update([ + 'student_uid' => $student->student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ], [ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => $ausbildungssemester, + 'verband' => $student->verband, + 'gruppe' => $student->gruppe, + 'updateamum' => date('c'), + 'updatevon' => $authUID + ]); + else // Add new Student-Lehrverband entry + $this->StudentlehrverbandModel->insert([ + 'student_uid' => $student->student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => $lv ? $ausbildungssemester : $student->semester, + 'verband' => $student->verband, + 'gruppe' => $student->gruppe, + 'insertamum' => date('c'), + 'insertvon' => $authUID + ]); + } + + /** + * Helper function for sanitizing Alias Name + * replaces empty spaces with underlines + * + * @param string $str + * + * @return string + */ + private function _sanitizeAliasName($str) + { + $str = sanitizeProblemChars($str); + return mb_strtolower(str_replace(' ', '_', $str)); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Student.php b/application/controllers/api/frontend/v1/stv/Student.php new file mode 100644 index 000000000..89c317ae4 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Student.php @@ -0,0 +1,562 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use \DateTime as DateTime; + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about a Student + * Listens to ajax post calls to change the Student data + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Student extends FHCAPI_Controller +{ + /** + * Calls the parent's constructor and prepares libraries and phrases + */ + public function __construct() + { + parent::__construct([ + 'get' => ['admin:r', 'assistenz:r'], + 'save' => ['admin:rw', 'assistenz:rw'], + 'check' => ['admin:rw', 'assistenz:rw'], + 'add' => ['admin:rw', 'assistenz:rw'] // TODO(chris): extra permissions + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + if ($this->router->method == 'get' + || $this->router->method == 'save' + ) { + $prestudent_id = current(array_slice($this->uri->rsegments, 2)); + if ($this->router->method == 'get') + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:r', 'assistenz:r']); + else + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:rw', 'assistenz:rw']); + } + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Get details for a prestudent + * + * @param string $prestudent_id + * @return void + */ + public function get($prestudent_id) + { + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $this->PrestudentModel->addSelect('p.*'); + $this->PrestudentModel->addSelect('s.student_uid'); + $this->PrestudentModel->addSelect('matrikelnr'); + $this->PrestudentModel->addSelect('b.aktiv'); + $this->PrestudentModel->addSelect('v.semester'); + $this->PrestudentModel->addSelect('v.verband'); + $this->PrestudentModel->addSelect('v.gruppe'); + $this->PrestudentModel->addSelect('b.alias'); + + if (defined('ACTIVE_ADDONS') && strpos(ACTIVE_ADDONS, 'bewerbung') !== false) { + $this->PrestudentModel->addSelect( + "( + SELECT kontakt + FROM public.tbl_kontakt + WHERE kontakttyp='email' + AND person_id=p.person_id + AND zustellung + ORDER BY kontakt_id + LIMIT 1 + ) AS email_privat", + false + ); + } + + $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_benutzer b', 'student_uid = uid', 'LEFT'); + $this->PrestudentModel->addJoin( + 'public.tbl_studentlehrverband v', + 'b.uid = v.student_uid AND v.studiensemester_kurzbz = ' . $this->PrestudentModel->escape($studiensemester_kurzbz), + 'LEFT' + ); + $this->PrestudentModel->addJoin('public.tbl_person p', 'p.person_id = tbl_prestudent.person_id'); + + $result = $this->PrestudentModel->loadWhere(['prestudent_id' => $prestudent_id]); + + $student = $this->getDataOrTerminateWithError($result); + + if (!$student) + return show_404(); + + $this->terminateWithSuccess(current($student)); + } + + /** + * Saves data to a prestudent + * + * @param string $prestudent_id + * @return void + */ + public function save($prestudent_id) + { + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'is_valid_date'); + + $this->form_validation->set_rules('semester', 'Semester', 'integer'); + + $this->load->library('UDFLib'); + + $result = $this->udflib->getCiValidations($this->PersonModel, $this->input->post()); + + //TODO(Manu) check with Chris: input number not allowed + $udf_field_validations = $this->getDataOrTerminateWithError($result); + + $this->form_validation->set_rules($udf_field_validations); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = $this->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]); + + $student = $this->getDataOrTerminateWithError($result); + + $uid = $student ? current($student)->student_uid : null; + + $result = $this->PrestudentModel->loadWhere(['prestudent_id' => $prestudent_id]); + + $person = $this->getDataOrTerminateWithError($result); + + $person_id = $person ? current($person)->person_id : null; + + + $array_allowed_props_lehrverband = ['verband', 'semester', 'gruppe']; + $update_lehrverband = array(); + foreach ($array_allowed_props_lehrverband as $prop) { + $val = $this->input->post($prop); + if ($val !== null) { + $update_lehrverband[$prop] = $val; + } + } + + $array_allowed_props_person = [ + 'anrede', + 'bpk', + 'titelpre', + 'titelpost', + 'nachname', + 'vorname', + 'vornamen', + 'wahlname', + 'gebdatum', + 'gebort', + 'geburtsnation', + 'svnr', + 'ersatzkennzeichen', + 'staatsbuergerschaft', + 'matr_nr', + 'sprache', + 'geschlecht', + 'familienstand', + 'foto', + 'anmerkung', + 'homepage' + ]; + + // add UDFs + $result = $this->udflib->getDefinitionForModel($this->PersonModel); + + $definitions = $this->getDataOrTerminateWithError($result); + + foreach ($definitions as $def) + $array_allowed_props_person[] = $def['name']; + + $update_person = array(); + foreach ($array_allowed_props_person as $prop) { + $val = $this->input->post($prop); + if ($val !== null) { + $update_person[$prop] = $val; + } + } + + $array_allowed_props_student = ['matrikelnr']; + $update_student = array(); + foreach ($array_allowed_props_student as $prop) { + $val = $this->input->post($prop); + if ($val !== null) { + $update_student[$prop] = $val; + } + } + + // Check PKs + if (count($update_lehrverband) + count($update_student) && $uid === null) { + // TODO(chris): phrase + $this->terminateWithValidationErrors(['' => "Kein/e StudentIn vorhanden!"]); + } + if (count($update_person) && $person_id === null) { + // TODO(chris): phrase + $this->terminateWithValidationErrors(['' => "Keine Person vorhanden!"]); + } + + // Do Updates + if (count($update_lehrverband)) { + $result = $this->StudentlehrverbandModel->update([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $uid + ], $update_lehrverband); + $this->getDataOrTerminateWithError($result); + } + + if (count($update_person)) { + $result = $this->PersonModel->update( + $person_id, + $update_person + ); + $this->getDataOrTerminateWithError($result); + } + + + if (count($update_student)) { + $result = $this->StudentModel->update( + [$uid], + $update_student + ); + $this->getDataOrTerminateWithError($result); + } + + $this->terminateWithSuccess(array_fill_keys(array_merge( + array_keys($update_lehrverband), + array_keys($update_person), + array_keys($update_student) + ), '')); + } + + public function check() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'is_valid_date'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $vorname = $this->input->post('vorname'); + $nachname = $this->input->post('nachname'); + $gebdatum = $this->input->post('gebdatum'); + + if (!$vorname && !$nachname && !$gebdatum) + $this->terminateWithValidationErrors(['At least one of vorname, nachname or gebdatum must be set']); + + $this->load->model('person/Person_model', 'PersonModel'); + + if ($gebdatum) + $this->PersonModel->db->where('gebdatum', (new DateTime($gebdatum))->format('Y-m-d')); + if ($vorname && $nachname) { + $this->PersonModel->db->or_group_start(); + $this->PersonModel->db->where('LOWER(nachname)', 'LOWER(' . $this->PersonModel->db->escape($nachname) . ')', false); + $this->PersonModel->db->where('LOWER(vorname)', 'LOWER(' . $this->PersonModel->db->escape($vorname) . ')', false); + $this->PersonModel->db->group_end(); + } elseif ($nachname) { + $this->PersonModel->db->or_where('LOWER(nachname)', 'LOWER(' . $this->PersonModel->escape($nachname) . ')', false); + } + + $result = $this->PersonModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function add() + { + if (!$this->input->post('person_id')) { + if (!isset($_POST['address']) || !is_array($_POST['address'])) + $_POST['address'] = []; + $_POST['address']['func'] = 1; + } + if ($this->input->post('incoming')) { + $_POST['ausbildungssemester'] = 0; + } + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('nachname', 'Nachname', 'callback_requiredIfNotPersonId', [ + 'requiredIfNotPersonId' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('geschlecht', 'Geschlecht', 'callback_requiredIfNotPersonId', [ + 'requiredIfNotPersonId' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'callback_isValidDate', [ + 'isValidDate' => $this->p->t('ui', 'error_invalid_date') + ]); + $this->form_validation->set_rules('address[func]', 'Address', 'required|integer|less_than[2]|greater_than[-2]'); + $this->form_validation->set_rules('address[plz]', 'PLZ', 'callback_requiredIfAddressFunc', [ + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('address[gemeinde]', 'Gemeinde', 'callback_requiredIfAddressFunc', [ + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('address[ort]', 'Ort', 'callback_requiredIfAddressFunc', [ + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('address[address]', 'Adresse', 'callback_requiredIfAddressFunc', [ + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('email', 'E-Mail', 'valid_email'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required'); + $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'required|integer|less_than[9]|greater_than[-1]'); + // TODO(chris): validate studienplan with studiengang, semester and orgform? + // TODO(chris): validate person_id, studiengang_kz, studiensemester_kurzbz, orgform_kurzbz, nation, gemeinde, ort, geschlecht? + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // TODO(chris): This should be in a library + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + + $this->db->trans_start(); + + $result = $this->addInteressent(); + + $this->db->trans_complete(); + + if ($this->db->trans_status() === FALSE) + $this->terminateWithError('TODO(chris): TEXT', self::ERROR_TYPE_GENERAL); + + $this->terminateWithSuccess($result); + } + + protected function addInteressent() + { + // Person anlegen wenn nötig + $person_id = $this->input->post('person_id'); + if (!$person_id) { + $this->load->model('person/Person_model', 'PersonModel'); + + $data = [ + 'nachname' => $this->input->post('nachname'), + 'insertamum' => date('c'), + 'insertvon' => getAuthUID(), + 'zugangscode' => uniqid(), + 'aktiv' => true + ]; + if ($this->input->post('anrede')) + $data['anrede'] = $this->input->post('anrede'); + if ($this->input->post('titelpre')) + $data['titelpre'] = $this->input->post('titelpre'); + if ($this->input->post('titelpost')) + $data['titelpost'] = $this->input->post('titelpost'); + if ($this->input->post('vorname')) + $data['vorname'] = $this->input->post('vorname'); + if ($this->input->post('vornamen')) + $data['vornamen'] = $this->input->post('vornamen'); + if ($this->input->post('wahlname')) + $data['wahlname'] = $this->input->post('wahlname'); + if ($this->input->post('geschlecht')) + $data['geschlecht'] = $this->input->post('geschlecht'); + if ($this->input->post('gebdatum')) + $data['gebdatum'] = (new DateTime($this->input->post('datum_obj')))->format('Y-m-d'); + if ($this->input->post('geburtsnation')) + $data['geburtsnation'] = $this->input->post('geburtsnation'); + if ($this->input->post('staatsbuergerschaft')) + $data['staatsbuergerschaft'] = $this->input->post('staatsbuergerschaft'); + + $result = $this->PersonModel->insert($data); + $person_id = $this->getDataOrTerminateWithError($result); + } + + // Addresse anlegen + $anlegen = $this->input->post('address[func]'); + if ($anlegen) { + $this->load->model('person/Adresse_model', 'AdresseModel'); + + $data = [ + 'nation' => $this->input->post('address[nation]'), + 'strasse' => $this->input->post('address[address]'), + 'plz' => $this->input->post('address[plz]'), + 'ort' => $this->input->post('address[ort]'), + 'gemeinde' => $this->input->post('address[gemeinde]'), + 'typ' => 'h', + 'zustelladresse' => true, + ]; + if ($anlegen < 0) { // Überschreiben + $this->AdresseModel->addOrder('zustelladresse', 'DESC'); + $this->AdresseModel->addOrder('sort'); + $result = $this->AdresseModel->loadWhere([ + 'person_id' => $person_id + ]); + $address = $this->getDataOrTerminateWithError($result); + if ($address) { + $address = current($address); + + $data['updateamum'] = date('c'); + $data['updatevon'] = getAuthUID(); + + $result = $this->AdresseModel->update($address->adresse_id, $data); + $this->getDataOrTerminateWithError($result); + } else { + //Wenn keine Adrese vorhanden ist dann eine neue Anlegen + $anlegen = 1; + $data['heimatadresse'] = true; + } + } + if ($anlegen > 0) { + $data['person_id'] = $person_id; + $data['insertamum'] = date('c'); + $data['insertvon'] = getAuthUID(); + if (!isset($data['heimatadresse'])) + $data['heimatadresse'] = !$this->input->post('person_id'); + + $result = $this->AdresseModel->insert($data); + $this->getDataOrTerminateWithError($result); + } + } + + // Kontaktdaten + $kontaktdaten = []; + foreach (['email', 'telefon', 'mobil'] as $k) { + $v = $this->input->post($k); + if ($v) + $kontaktdaten[$k] = $v; + } + if (count($kontaktdaten)) { + $this->load->model('person/Kontakt_model', 'KontaktModel'); + + foreach ($kontaktdaten as $typ => $kontakt) { + $data = [ + 'person_id' => $person_id, + 'kontakttyp' => $typ, + 'kontakt' => $kontakt, + 'zustellung' => true, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]; + $result = $this->KontaktModel->insert($data); + $this->getDataOrTerminateWithError($result); + } + } + + // Prestudent anlegen + $data = [ + 'aufmerksamdurch_kurzbz' => 'k.A.', + 'person_id' => $person_id, + 'studiengang_kz' => $this->input->post('studiengang_kz'), + 'ausbildungcode' => $this->input->post('letzteausbildung'), + 'anmerkung' => $this->input->post('anmerkungen'), + 'reihungstestangetreten' => false, + 'bismelden' => true + ]; + $ausbildungsart = $this->input->post('ausbildungsart'); + if ($ausbildungsart) + $data['anmerkung'] .= ' Ausbildungsart:' . $ausbildungsart; + // Incomings und ausserordentliche sind bei Meldung nicht förderrelevant + $incoming = $this->input->post('incoming'); + if ($incoming || substr($data['studiengang_kz'], 0, 1) == '9') + $data['foerderrelevant'] = false; + // Wenn die Person schon im System erfasst ist, dann die ZGV des Datensatzes uebernehmen + $this->PrestudentModel->addOrder('zgvmas_code'); + $this->PrestudentModel->addOrder('zgv_code', 'DESC'); + $this->PrestudentModel->addLimit(1); + $result = $this->PrestudentModel->loadWhere([ + 'person_id' => $person_id + ]); + $prestudent = $this->getDataOrTerminateWithError($result); + if ($prestudent) { + $prestudent = current($prestudent); + if ($prestudent->zgv_code) { + $data['zgv_code'] = $prestudent->zgv_code; + $data['zgvort'] = $prestudent->zgvort; + $data['zgvdatum'] = $prestudent->zgvdatum; + + $data['zgvmas_code'] = $prestudent->zgvmas_code; + $data['zgvmaort'] = $prestudent->zgvmaort; + $data['zgvmadatum'] = $prestudent->zgvmadatum; + } + } + // Prestudent speichern + $result = $this->PrestudentModel->insert($data); + $prestudent_id = $this->getDataOrTerminateWithError($result); + + // Prestudent Rolle Anlegen + $data = [ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $incoming ? 'Incoming' : 'Interessent', + 'studiensemester_kurzbz' => $this->input->post('studiensemester_kurzbz'), + 'ausbildungssemester' => $this->input->post('ausbildungssemester') ?: 0, + 'orgform_kurzbz' => $this->input->post('orgform_kurzbz') ?: null, + 'studienplan_id' => $this->input->post('studienplan_id') ?: null, + 'datum' => date('Y-m-d'), + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]; + $result = $this->PrestudentstatusModel->insert($data); + $this->getDataOrTerminateWithError($result); + + if ($incoming) { + // TODO(chris): IMPLEMENT! + //Matrikelnummer und UID generieren + //Benutzerdatensatz anlegen + //Studentendatensatz anlegen + //StudentLehrverband anlegen + } + + // TODO(chris): DEBUG + /*$result = $this->PrestudentModel->loadWhere([ + 'pestudent_id' => 1 + ]); + if (isError($result)) { + return $result; + }*/ + + $this->terminateWithSuccess(true); + } + + public function requiredIfNotPersonId($value) + { + if (isset($_POST['person_id'])) + return true; + return !!$value; + } + + public function requiredIfAddressFunc($value) + { + if (!$_POST['address']['func']) + return true; + return !!$value; + } +} diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php new file mode 100644 index 000000000..5fb7b592c --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -0,0 +1,743 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about listing students + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Students extends FHCAPI_Controller +{ + private $allowedStgs = []; + + + public function __construct() + { + $permissions = []; + $router = load_class('Router'); + $permissions[$router->method] = ['admin:r', 'assistenz:r']; + parent::__construct($permissions); + + $this->allowedStgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: []; + $this->allowedStgs = array_merge($this->allowedStgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []); + + if (!$this->allowedStgs) { + $this->_outputAuthError([$router->method => ['admin:r', 'assistenz:r']]); + exit; + } + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + } + + /** + * Remap calls: + * / => return [] + * /inout => return [] + * /inout/incoming => getIncoming + * /inout/outgoing => getOutgoing + * /inout/gemeinsamestudien => getGemeinsamestudien + * /(studiengang_kz) => getStudents + * /(studiengang_kz)/prestudent => getPrestudents + * /(studiengang_kz)/prestudent/* => getPrestudents + * /(studiengang_kz)/(semester) => getStudents + * /(studiengang_kz)/(semester)/grp/(gruppe_kurzbz) => getStudents + * /(studiengang_kz)/(semester)/(verband) => getStudents + * /(studiengang_kz)/(semester)/(verband)/(gruppe) => getStudents + * /(studiengang_kz)/(org_form) => getStudents + * /(studiengang_kz)/(org_form)/prestudent => getPrestudents + * /(studiengang_kz)/(org_form)/prestudent/* => getPrestudents + * /(studiengang_kz)/(org_form)/(semester) => getStudents + * /(studiengang_kz)/(org_form)/(semester)/grp/(gruppe_kurzbz) + * => getStudents + * /(studiengang_kz)/(org_form)/(semester)/(verband) => getStudents + * /(studiengang_kz)/(org_form)/(semester)/(verband)/(gruppe) + * => getStudents + * /uid/(student_uid) => getStudent + * /prestudent/(prestudent_id) => getPrestudent + * /person/(person_id) => getPerson + * + * @param string $method + * @param array $params (optional) + * + * @return void + */ + public function _remap($method, $params = []) + { + if ($method == '' || $method == 'index') + return $this->terminateWithSuccess([]); + + if ($method == 'inout') { + if (!count($params)) + return $this->terminateWithSuccess([]); + switch ($params[0]) { + case 'incoming': + return $this->getIncoming(); + case 'outgoing': + return $this->getOutgoing(); + case 'gemeinsamestudien': + return $this->getGemeinsamestudien(); + default: + return show_404(); + } + } + + $count = count($params); + if (!$count) + return $this->getStudents($method); + + if ($method == 'uid' && $count == 1) + return $this->getStudent($params[0]); + + if ($method == 'prestudent' && $count == 1) + return $this->getPrestudent($params[0]); + + if ($method == 'person' && $count == 1) + return $this->getPerson($params[0]); + + if (is_numeric($params[0])) { + $sem = $params[0]; + if ($count == 3 && $params[1] == 'grp') { + $g = $params[2]; + $ver = null; + $grp = null; + } else { + $g = null; + $ver = $count > 1 ? $params[1] : null; + $grp = $count > 2 ? $params[2] : null; + } + return $this->getStudents($method, $sem, $ver, $grp, $g); + } elseif ($params[0] == 'prestudent') { + if ($count == 1) + return $this->getPrestudents($method); + if ($count == 2) + return $this->getPrestudents($method, $params[1]); + return $this->getPrestudents($method, $params[1], $params[$count-1]); + } else { + $org = $params[0]; + if ($count > 1 && $params[1] == 'prestudent') { + if ($count == 2) + return $this->getPrestudents($method, null, null, $org); + if ($count == 3) + return $this->getPrestudents($method, $params[2], null, $org); + return $this->getPrestudents($method, $params[2], $params[$count-1], $org); + } + $sem = $count > 1 ? $params[1] : null; + if ($count == 4 && $params[2] == 'grp') { + $g = $params[3]; + $ver = null; + $grp = null; + } else { + $g = null; + $ver = $count > 2 ? $params[2] : null; + $grp = $count > 3 ? $params[3] : null; + } + + return $this->getStudents($method, $sem, $ver, $grp, $g, $org); + } + + show_404(); + } + + /** + * @return void + */ + protected function getIncoming() + { + // TODO(chris): IMPLEMENT! + $this->terminateWithSuccess([]); + } + + /** + * @return void + */ + protected function getOutgoing() + { + // TODO(chris): IMPLEMENT! + $this->terminateWithSuccess([]); + } + + /** + * @return void + */ + protected function getGemeinsamestudien() + { + // TODO(chris): IMPLEMENT! + $this->terminateWithSuccess([]); + } + + /** + * @param integer $studiengang_kz + * @param string $studiensemester_kurzbz (optional) + * @param string $filter (optional) + * @param string $orgform_kurzbz (optional) + * + * @return void + */ + protected function getPrestudents($studiengang_kz, $studiensemester_kurzbz = null, $filter = null, $orgform_kurzbz = null) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL'; + + $selectRT = " + SELECT 1 + FROM public.tbl_rt_person + JOIN public.tbl_reihungstest r ON (rt_id = reihungstest_id) + WHERE person_id=p.person_id + AND studienplan_id IN ( + SELECT studienplan_id + FROM lehre.tbl_studienplan + JOIN lehre.tbl_studienordnung o USING(studienordnung_id) + WHERE o.studiengang_kz=tbl_prestudent.studiengang_kz + ) + AND r.studiensemester_kurzbz=" . $stdsemEsc; + + + $where = ['tbl_prestudent.studiengang_kz' => $studiengang_kz]; + + if ($orgform_kurzbz) { + $where['ps.orgform_kurzbz'] = $orgform_kurzbz; + } + + switch ($filter) { + case "interessenten": + $where['ps.status_kurzbz'] = 'Interessent'; + break; + case "bewerbungnichtabgeschickt": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['bewerbung_abgeschicktamum'] = null; + break; + case "bewerbungabgeschickt": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['bewerbung_abgeschicktamum IS NOT NULL'] = null; + $where['bestaetigtam'] = null; + break; + case "statusbestaetigt": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['bestaetigtam IS NOT NULL'] = null; + break; + case "statusbestaetigtrtnichtangemeldet": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['bestaetigtam IS NOT NULL'] = null; + $this->PrestudentModel->db->where('NOT EXISTS(' . $selectRT . ')', null, false); + break; + case "statusbestaetigtrtangemeldet": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['bestaetigtam IS NOT NULL'] = null; + $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false); + break; + case "zgv": + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $result = $this->StudiengangModel->load($studiengang_kz); + + $stg = $this->getDataOrTerminateWithError($result); + if (!$stg) + $this->terminateWithValidationErrors(['' => 'Studiengang does not exist']); // TODO(chris): phrase + $stg = current($stg); + + $where['ps.status_kurzbz'] = 'Interessent'; + + if ($stg->typ == 'm') { + $where['zgvmas_code IS NOT NULL'] = null; + if (defined('ZGV_ERFUELLT_ANZEIGEN') && ZGV_ERFUELLT_ANZEIGEN) + $where['zgvmas_erfuellt'] = true; + } elseif ($stg->typ == 'p') { + $where['zgvdoktor_code IS NOT NULL'] = null; + if (defined('ZGV_DOKTOR_ANZEIGEN') && ZGV_DOKTOR_ANZEIGEN) + $where['zgvdoktor_erfuellt'] = true; + } else { + $where['zgv_code IS NOT NULL'] = null; + if (defined('ZGV_ERFUELLT_ANZEIGEN') && ZGV_ERFUELLT_ANZEIGEN) + $where['zgv_erfuellt'] = true; + } + break; + case "reihungstestangemeldet": + $where['ps.status_kurzbz'] = 'Interessent'; + $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false); + break; + case "reihungstestnichtangemeldet": + $where['ps.status_kurzbz'] = 'Interessent'; + $this->PrestudentModel->db->where('NOT EXISTS(' . $selectRT . ')', null, false); + break; + case "bewerber": + $where['ps.status_kurzbz'] = 'Bewerber'; + break; + case "bewerberrtnichtangemeldet": + $where['ps.status_kurzbz'] = 'Bewerber'; + $this->PrestudentModel->db->where('NOT EXISTS(' . $selectRT . ')', null, false); + break; + case "bewerberrtangemeldet": + $where['ps.status_kurzbz'] = 'Bewerber'; + $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false); + break; + case "bewerberrtangemeldetteilgenommen": + $where['ps.status_kurzbz'] = 'Bewerber'; + $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false); + $where['reihungstestangetreten'] = true; + break; + case "bewerberrtangemeldetnichtteilgenommen": + $where['ps.status_kurzbz'] = 'Bewerber'; + $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false); + $where['reihungstestangetreten'] = false; + break; + case "aufgenommen": + $where['ps.status_kurzbz'] = 'Aufgenommener'; + break; + case "warteliste": + $where['ps.status_kurzbz'] = 'Wartender'; + break; + case "absage": + $where['ps.status_kurzbz'] = 'Abgewiesener'; + break; + case "incoming": + // NOTE(chris): in FAS it was not filtered for studiengang_kz + $where['ps.status_kurzbz'] = 'Incoming'; + break; + case "absolvent": + $where['ps.status_kurzbz'] = 'Absolvent'; + break; + case "diplomand": + $where['ps.status_kurzbz'] = 'Diplomand'; + break; + default: + if (!$studiensemester_kurzbz) { + // TODO(chris): this does not work with $orgform_kurzbz != null + $where['ps.status_kurzbz'] = null; + } else { + $this->PrestudentModel->db->where_in('ps.status_kurzbz', [ + 'Interessent', + 'Bewerber', + 'Aufgenommener', + 'Wartender', + 'Abgewiesener' + ]); + } + break; + } + + /* + $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' + pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.prestudent_id=tbl_prestudent.prestudent_id + AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); + $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_prestudentstatus ps', ' + ps.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') + AND ps.prestudent_id=tbl_prestudent.prestudent_id + AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') + AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT');*/ + $this->prepareQuery($studiensemester_kurzbz); + + $this->PrestudentModel->addSelect(" + CASE WHEN ps.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN ps.ausbildungssemester::text + ELSE ''::text END AS semester", false); + $this->PrestudentModel->addSelect("'' AS verband"); + $this->PrestudentModel->addSelect("'' AS gruppe"); + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + $result = $this->PrestudentModel->loadWhere($where); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * @param integer $studiengang_kz + * @param integer $semester (optional) + * @param string $verband (optional) + * @param integer $gruppe (optional) + * @param string $gruppe_kurzbz (optional) + * @param string $orgform_kurzbz (optional) + * + * @return void + */ + protected function getStudents($studiengang_kz, $semester = null, $verband = null, $gruppe = null, $gruppe_kurzbz = null, $orgform_kurzbz = null) + { + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + /* + $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); + $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' + pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.prestudent_id=tbl_prestudent.prestudent_id + AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); + $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); + $this->PrestudentModel->addJoin( + 'public.tbl_studentlehrverband v', + 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz) + );*/ + $this->prepareQuery($studiensemester_kurzbz, ''); + + $this->PrestudentModel->addSelect('v.semester'); + $this->PrestudentModel->addSelect('v.verband'); + $this->PrestudentModel->addSelect('v.gruppe'); + $this->PrestudentModel->addSelect("'' AS priorisierung_relativ"); + + + $where = []; + + if ($gruppe_kurzbz !== null) { + $this->PrestudentModel->addJoin('public.tbl_benutzergruppe g', 'uid'); + $where['g.gruppe_kurzbz'] = $gruppe_kurzbz; + $where['g.studiensemester_kurzbz'] = $studiensemester_kurzbz; + } else { + $where['v.studiengang_kz'] = $studiengang_kz; + + if ($semester !== null) + $where['v.semester'] = $semester; + + if ($verband !== null) + $where['v.verband'] = $verband; + + if ($gruppe !== null) + $where['v.gruppe'] = $gruppe; + + if (!$verband && !$gruppe && $orgform_kurzbz !== null) { + $this->PrestudentModel->db->where( + "( + SELECT orgform_kurzbz + FROM public.tbl_prestudentstatus + WHERE prestudent_id=tbl_prestudent.prestudent_id + AND studiensemester_kurzbz=" . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1 + ) =", + $this->PrestudentModel->escape($orgform_kurzbz), + false + ); + } + + } + + $this->addFilter($studiensemester_kurzbz); + + $result = $this->PrestudentModel->loadWhere($where); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * @param string $prestudent_id + * + * @return void + */ + protected function getPrestudent($prestudent_id) + { + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + /* + $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' + pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.prestudent_id=tbl_prestudent.prestudent_id + AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); + $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid', 'LEFT'); + $this->PrestudentModel->addJoin( + 'public.tbl_studentlehrverband v', + 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), + 'LEFT' + );*/ + $this->prepareQuery($studiensemester_kurzbz); + + $this->PrestudentModel->addSelect("COALESCE(v.semester::text, CASE WHEN public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') THEN public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)::text ELSE ''::text END) AS semester", false); + $this->PrestudentModel->addSelect('v.verband'); + $this->PrestudentModel->addSelect('v.gruppe'); + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + $result = $this->PrestudentModel->loadWhere([ + 'tbl_prestudent.prestudent_id' => $prestudent_id + ]); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * @param string $student_uid + * + * @return void + */ + protected function getStudent($student_uid) + { + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + /* + $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); + $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' + pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.prestudent_id=tbl_prestudent.prestudent_id + AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); + $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); + $this->PrestudentModel->addJoin( + 'public.tbl_studentlehrverband v', + 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), + 'LEFT' + );*/ + $this->prepareQuery($studiensemester_kurzbz); + + $this->PrestudentModel->addSelect('v.semester'); + $this->PrestudentModel->addSelect('v.verband'); + $this->PrestudentModel->addSelect('v.gruppe'); + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + $result = $this->PrestudentModel->loadWhere([ + 's.student_uid' => $student_uid + ]); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * @param integer $person_id + * + * @return void + */ + protected function getPerson($person_id) + { + $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + /* + $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); + $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); + $this->PrestudentModel->addJoin( + 'public.tbl_studentlehrverband v', + 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), + 'LEFT' + );*/ + $this->prepareQuery($studiensemester_kurzbz); + + $this->PrestudentModel->addSelect('v.semester'); + $this->PrestudentModel->addSelect('v.verband'); + $this->PrestudentModel->addSelect('v.gruppe'); + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + $result = $this->PrestudentModel->loadWhere([ + 'p.person_id' => $person_id + ]); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * @param string|null $studiensemester_kurzbz + * @param string $type + * + * @return void + */ + protected function prepareQuery($studiensemester_kurzbz, $type = 'LEFT') + { + $stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL'; + + + $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', $type); + $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' + pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.prestudent_id=tbl_prestudent.prestudent_id + AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) + AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); + $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); + $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid', 'LEFT'); + $this->PrestudentModel->addJoin( + 'public.tbl_studentlehrverband v', + 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz' . ($studiensemester_kurzbz ? '=' . $stdsemEsc : ' IS NULL'), + $type + ); + $this->PrestudentModel->addJoin('public.tbl_prestudentstatus ps', ' + ps.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') + AND ps.prestudent_id=tbl_prestudent.prestudent_id + AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') + AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT'); + + + $this->PrestudentModel->addSelect("b.uid"); + $this->PrestudentModel->addSelect('titelpre'); + $this->PrestudentModel->addSelect('nachname'); + $this->PrestudentModel->addSelect('vorname'); + $this->PrestudentModel->addSelect('wahlname'); + $this->PrestudentModel->addSelect('vornamen'); + $this->PrestudentModel->addSelect('titelpost'); + $this->PrestudentModel->addSelect('svnr'); + $this->PrestudentModel->addSelect('ersatzkennzeichen'); + $this->PrestudentModel->addSelect('gebdatum'); + $this->PrestudentModel->addSelect('geschlecht'); + + // semester + // verband + // gruppe + + $this->PrestudentModel->addSelect('UPPER(stg.typ || stg.kurzbz) AS studiengang'); + $this->PrestudentModel->addSelect('tbl_prestudent.studiengang_kz'); + $this->PrestudentModel->addSelect("s.matrikelnr"); + $this->PrestudentModel->addSelect('p.person_id'); + $this->PrestudentModel->addSelect('pls.status_kurzbz AS status'); + $this->PrestudentModel->addSelect('pls.datum AS status_datum'); + $this->PrestudentModel->addSelect('pls.bestaetigtam AS status_bestaetigung'); + $this->PrestudentModel->addSelect( + "(SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp='email' AND person_id=p.person_id AND zustellung LIMIT 1) AS mail_privat", + false + ); + $this->PrestudentModel->addSelect(" + CASE WHEN b.uid IS NOT NULL AND b.uid<>'' + THEN b.uid || " . $this->PrestudentModel->escape(DOMAIN) . " + ELSE '' END AS mail_intern", false); + $this->PrestudentModel->addSelect('p.anmerkung AS anmerkungen'); + $this->PrestudentModel->addSelect('tbl_prestudent.anmerkung'); + $this->PrestudentModel->addSelect('pls.orgform_kurzbz'); + $this->PrestudentModel->addSelect('aufmerksamdurch_kurzbz'); + $this->PrestudentModel->addSelect( + "(SELECT rt_gesamtpunkte AS punkte FROM public.tbl_prestudent WHERE prestudent_id=ps.prestudent_id) AS punkte", + false + ); + $this->PrestudentModel->addSelect('tbl_prestudent.aufnahmegruppe_kurzbz'); + $this->PrestudentModel->addSelect('tbl_prestudent.dual'); + $this->PrestudentModel->addSelect('p.matr_nr'); + $this->PrestudentModel->addSelect('sp.bezeichnung AS studienplan_bezeichnung'); + $this->PrestudentModel->addSelect('tbl_prestudent.prestudent_id'); + + // priorisierung_relativ + + $this->PrestudentModel->addSelect('mentor'); + $this->PrestudentModel->addSelect('b.aktiv AS bnaktiv'); + + /*$this->PrestudentModel->addSelect('tbl_prestudent.reihungstest_id'); + $this->PrestudentModel->addSelect('tbl_prestudent.anmeldungreihungstest'); + $this->PrestudentModel->addSelect('tbl_prestudent.gsstudientyp_kurzbz'); + $this->PrestudentModel->addSelect('tbl_prestudent.priorisierung'); + $this->PrestudentModel->addSelect('p.zugangscode'); + $this->PrestudentModel->addSelect('p.bpk');*/ + + $this->PrestudentModel->db->where_in('tbl_prestudent.studiengang_kz', $this->allowedStgs); + + $this->PrestudentModel->addOrder('nachname'); + $this->PrestudentModel->addOrder('vorname'); + } + + /** + * @return void + */ + protected function addSelectPrioRel() + { + $this->PrestudentModel->addSelect("( + SELECT count(*) + FROM ( + SELECT *, public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) AS laststatus + FROM PUBLIC.tbl_prestudent pss + JOIN PUBLIC.tbl_prestudentstatus USING (prestudent_id) + WHERE person_id = p.person_id + AND studiensemester_kurzbz = ( + SELECT studiensemester_kurzbz + FROM PUBLIC.tbl_prestudentstatus + WHERE prestudent_id = tbl_prestudent.prestudent_id + AND status_kurzbz = 'Interessent' + LIMIT 1 + ) + AND status_kurzbz = 'Interessent' + ) prest + WHERE laststatus NOT IN ('Abbrecher', 'Abgewiesener', 'Absolvent') + AND priorisierung <= tbl_prestudent.priorisierung + ) || ' (' || tbl_prestudent.priorisierung || ')' AS priorisierung_relativ", false); + } + + /** + * Adds additional filters to the query + * + * @param string $studiensemester_kurzbz + * + * @return void + */ + protected function addFilter($studiensemester_kurzbz) + { + $filter = $this->input->get('filter'); + if (isset($filter['konto_count_0'])) { + $bt = $this->PrestudentModel->escape($filter['konto_count_0']); + $stdsem = $this->PrestudentModel->escape($studiensemester_kurzbz); + + $this->PrestudentModel->db->where('( + SELECT count(*) + FROM public.tbl_konto + WHERE person_id=tbl_prestudent.person_id + AND buchungstyp_kurzbz=' . $bt . ' + AND studiensemester_kurzbz=' . $stdsem . ' + ) =', 0); + $this->PrestudentModel->db->where('get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) !=', 'Incoming'); + } + if (isset($filter['konto_missing_counter'])) { + $bt = $this->PrestudentModel->escape($filter['konto_missing_counter']); + $stg = ''; + if ($this->variablelib->getVar('kontofilterstg') == 'true') + $stg = ' AND studiengang_kz=tbl_prestudent.studiengang_kz'; + + $bt = $bt == 'alle' ? '' : ' AND buchungstyp_kurzbz=' . $bt; + + $this->PrestudentModel->db->where('( + SELECT sum(betrag) + FROM public.tbl_konto + WHERE person_id=tbl_prestudent.person_id' . + $bt . + $stg . ' + ) !=', 0); + } + } +} diff --git a/application/controllers/api/frontend/v1/stv/Verband.php b/application/controllers/api/frontend/v1/stv/Verband.php new file mode 100644 index 000000000..e8c532652 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Verband.php @@ -0,0 +1,493 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about verbände + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Verband extends FHCAPI_Controller +{ + public function __construct() + { + $permissions = []; + $router = load_class('Router'); + $permissions[$router->method] = ['admin:r', 'assistenz:r']; + parent::__construct($permissions); + + // Load Models + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + } + + /** + * Remap calls: + * / + * /(studiengang_kz) => getStudiengang + * /(studiengang_kz)/(semester) => getSemester + * /(studiengang_kz)/(semester)/(verband) => getVerband + * /(studiengang_kz)/(org_form) => getStudiengang + * /(studiengang_kz)/(org_form)/(semester) => getSemester + * /(studiengang_kz)/(org_form)/(semester)/(verband) => getVerband + * + * @param string $method + * @param array $params (optional) + * + * @return void + */ + public function _remap($method, $params = []) + { + if ($method == '' || $method == 'index') + return $this->getBase(); + + // NOTE(chris): Test if access is allowed ($method is the Studiengang) + if (!$this->permissionlib->isBerechtigt('assistenz', 's', $method) + && !$this->permissionlib->isBerechtigt('admin', 's', $method) + ) { + return $this->_outputAuthError([$method => ['admin:r', 'assistenz:r']]); + } + + $count = count($params); + if (!$count) + return $this->getStudiengang($method); + + if ($count == 1) { + if (is_numeric($params[0])) + return $this->getSemester($method, $params[0]); + elseif ($params[0] == 'prestudent') + return $this->terminateWithSuccess($this->getStdSem($method . '/prestudent/', $method)); + else + return $this->getStudiengang($method, $params[0]); + } + if ($count == 2) { + if (is_numeric($params[0])) + return $this->getVerband($method, $params[0], $params[1]); + elseif ($params[1] == 'prestudent') + return $this->terminateWithSuccess($this->getStdSem($method . '/' . $params[0] . '/prestudent/', $method)); + else + return $this->getSemester($method, $params[1], $params[0]); + } + if ($count == 3 && !is_numeric($params[0]) && is_numeric($params[1]) && !is_numeric($params[2])) + return $this->getVerband($method, $params[1], $params[2], $params[0]); + + show_404(); + } + + /** + * @return void + */ + protected function getBase() + { + $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz'); + + $this->StudiengangModel->addDistinct(); + $this->StudiengangModel->addSelect("v.studiengang_kz AS link"); + $this->StudiengangModel->addSelect( + "CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name", + false + ); + $this->StudiengangModel->addSelect('erhalter_kz'); + $this->StudiengangModel->addSelect('typ'); + $this->StudiengangModel->addSelect('kurzbz'); + $this->StudiengangModel->addSelect('studiengang_kz'); + $this->StudiengangModel->addSelect('studiengang_kz AS stg_kz'); + + $this->StudiengangModel->addOrder('erhalter_kz'); + $this->StudiengangModel->addOrder('typ'); + $this->StudiengangModel->addOrder('kurzbz'); + + $stgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: []; + $stgs = array_merge($stgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []); + + if (!$stgs) + $this->terminateWithSuccess([]); + + $this->StudiengangModel->db->where_in('studiengang_kz', $stgs); + + $result = $this->StudiengangModel->loadWhere(['v.aktiv' => true]); + + $list = $this->getDataOrTerminateWithError($result); + + if ($this->permissionlib->isBerechtigt('inout/uebersicht')) + $list[] = [ + 'name' => 'International', + 'link' => 'inout', + 'children' => [ + [ + 'name' => 'Incoming', + 'link' => 'inout/incoming', + 'leaf' => true + ], + [ + 'name' => 'Outgoing', + 'link' => 'inout/outgoing', + 'leaf' => true + ], + [ + 'name' => 'Gemeinsame Studien', + 'link' => 'inout/gemeinsamestudien', + 'leaf' => true + ] + ] + ]; + $this->terminateWithSuccess($list); + } + + /** + * @param integer $studiengang_kz + * @param string $orgform (optional) + * + * @return void + */ + protected function getStudiengang($studiengang_kz, $org_form = null) + { + $link = $studiengang_kz . '/'; + if ($org_form !== null) + $link .= $org_form . '/'; + + $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz'); + + $this->StudiengangModel->addDistinct(); + $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", semester) AS link", false); + $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester ORDER BY verband, gruppe LIMIT 1)) AS name", false); + + $this->StudiengangModel->addSelect('semester'); + $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false); + + $this->StudiengangModel->addOrder('semester'); + + if ($org_form !== null) { + $this->StudiengangModel->db->group_start(); + $this->StudiengangModel->db->where('v.semester', 0); + $this->StudiengangModel->db->or_where('v.orgform_kurzbz', $org_form); + $this->StudiengangModel->db->group_end(); + } + + $result = $this->StudiengangModel->loadWhere([ + 'v.studiengang_kz' => $studiengang_kz, + 'v.aktiv' => true + ]); + $list = $this->getDataOrTerminateWithError($result); + + array_unshift($list, [ + 'name' => 'PreStudent', + 'link' => $link . 'prestudent', + 'children' => $this->getStdSem($link . 'prestudent/', $studiengang_kz) + ]); + + if ($org_form === null) { + // NOTE(chris): if mischform show orgforms + $result = $this->StudiengangModel->load($studiengang_kz); + $result = $this->getDataOrTerminateWithError($result); + if ($result) { + if (current($result)->mischform) { + $this->load->model('organisation/Studienordnung_model', 'StudienordnungModel'); + + $this->StudienordnungModel->addDistinct(); + $this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link"); + $this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name"); + + $this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id'); + + $result = $this->StudienordnungModel->loadWhere([ + 'aktiv' => true, + 'studiengang_kz' => $studiengang_kz, + 'p.orgform_kurzbz !=' => 'DDP' + ]); + $result = $this->getDataOrTerminateWithError($result); + + $list = array_merge($list, $result); + } + } + + } + $this->terminateWithSuccess($list); + } + + /** + * @param integer $studiengang_kz + * @param integer $semester + * @param string $orgform + * + * @return void + */ + protected function getSemester($studiengang_kz, $semester, $org_form = null) + { + $link = $studiengang_kz . '/'; + if ($org_form !== null) + $link .= $org_form . '/'; + $link .= $semester . '/'; + + + $this->load->model('organisation/Gruppe_model', 'GruppeModel'); + + $this->GruppeModel->addDistinct(); + $this->GruppeModel->addSelect("CONCAT(" . $this->GruppeModel->escape($link . 'grp/') . ", gruppe_kurzbz) AS link", false); + $this->GruppeModel->addSelect("CONCAT(gruppe_kurzbz, ' (', bezeichnung, ')') AS name", false); + $this->GruppeModel->addSelect("TRUE AS leaf", false); + + $this->GruppeModel->addSelect('sort'); + $this->GruppeModel->addSelect('gruppe_kurzbz'); + $this->GruppeModel->addSelect($this->GruppeModel->escape($studiengang_kz) . '::integer AS stg_kz', false); + + $this->GruppeModel->addOrder('sort'); + $this->GruppeModel->addOrder('gruppe_kurzbz'); + + $where = [ + 'studiengang_kz' => $studiengang_kz, + 'semester' => $semester, + 'lehre' => true, + 'sichtbar' => true, + 'aktiv' => true, + 'direktinskription' => false + ]; + + if ($org_form !== null) + $where['orgform_kurzbz'] = $org_form; + + $result = $this->GruppeModel->loadWhere($where); + + $list = $this->getDataOrTerminateWithError($result); + + $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz'); + + $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", verband) AS link", false); + $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, verband, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester AND verband=v.verband ORDER BY gruppe LIMIT 1)) AS name", false); + $this->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf"); + + $this->StudiengangModel->addSelect('verband'); + $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false); + + $this->StudiengangModel->addOrder('verband'); + + $this->StudiengangModel->addGroupBy('link, name, verband'); + + $where = [ + 'v.studiengang_kz' => $studiengang_kz, + 'v.semester' => $semester, + 'v.verband !=' => '', + 'v.aktiv' => true + ]; + + if ($org_form !== null && $semester) // NOTE(chris): on semester 0 show all? + $where['v.orgform_kurzbz'] = $org_form; + + $result = $this->StudiengangModel->loadWhere($where); + $result = $this->getDataOrTerminateWithError($result); + + $list = array_merge($list, $result); + + $this->terminateWithSuccess($list); + } + + /** + * @param integer $studiengang_kz + * @param integer $semester + * @param integer $verband + * @param string $orgform + * + * @return void + */ + protected function getVerband($studiengang_kz, $semester, $verband, $org_form = null) + { + $link = $studiengang_kz . '/'; + if ($org_form !== null) + $link .= $org_form . '/'; + $link .= $semester . '/'. $verband . '/'; + + + $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz'); + + $this->StudiengangModel->addDistinct(); + $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", gruppe) AS link", false); + $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, verband, gruppe, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester AND verband=v.verband AND gruppe=v.gruppe ORDER BY gruppe LIMIT 1)) AS name", false); + $this->StudiengangModel->addSelect("TRUE AS leaf", false); + + $this->StudiengangModel->addSelect('gruppe'); + $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false); + + $this->StudiengangModel->addOrder('gruppe'); + + $where = [ + 'v.studiengang_kz' => $studiengang_kz, + 'v.semester' => $semester, + 'v.verband' => $verband, + 'v.gruppe !=' => '', + 'v.aktiv' => true + ]; + + if ($org_form !== null && $semester) // NOTE(chris): on semester 0 show all? + $where['v.orgform_kurzbz'] = $org_form; + + $result = $this->StudiengangModel->loadWhere($where); + + $list = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($list); + } + + /** + * @param string $link + * @param integer $studiengang_kz + * + * @return array + */ + protected function getStdSem($link, $studiengang_kz) + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->load->model('system/Variable_model', 'VariableModel'); + $result = $this->VariableModel->getVariables(getAuthUID(), ['number_displayed_past_studiensemester']); + $data = $this->getDataOrTerminateWithError($result); + $number_displayed_past_studiensemester = $data['number_displayed_past_studiensemester'] ?? null; + + $this->StudiensemesterModel->addPlusMinus(null, $number_displayed_past_studiensemester); + $this->StudiensemesterModel->addOrder('ende'); + $result = $this->StudiensemesterModel->load(); + + $studiensemester = $this->getDataOrTerminateWithError($result); + $result = []; + + $studiengang_kz = (int)$studiengang_kz; + + foreach ($studiensemester as $sem) { + $semlink = $link . $sem->studiensemester_kurzbz; + $intlink = $semlink . '/interessenten'; + $result[] = [ + 'name' => $sem->studiensemester_kurzbz, + 'link' => $semlink, + 'stg_kz' => $studiengang_kz, + 'children' => [ + [ + 'name' => 'Interessenten', + 'link' => $intlink, + 'stg_kz' => $studiengang_kz, + 'children' => [ + [ + 'name' => 'Bewerbung nicht abgeschickt', + 'link' => $intlink . '/bewerbungnichtabgeschickt', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'Bewerbung abgeschickt, Status unbestätigt', + 'link' => $intlink . '/bewerbungabgeschickt', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'ZGV erfüllt', + 'link' => $intlink . '/zgv', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'Status bestätigt', + 'link' => $intlink . '/statusbestaetigt', + 'stg_kz' => $studiengang_kz, + 'children' => [ + [ + 'name' => 'Nicht zum Reihungstest angemeldet', + 'link' => $intlink . '/statusbestaetigtrtnichtangemeldet', + 'leaf' => true + ], + [ + 'name' => 'Reihungstest angemeldet', + 'link' => $intlink . '/statusbestaetigtrtangemeldet', + 'leaf' => true + ] + ] + ], + [ + 'name' => 'Nicht zum Reihungstest angemeldet', + 'link' => $intlink . '/reihungstestnichtangemeldet', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'Reihungstest angemeldet', + 'link' => $intlink . '/reihungstestangemeldet', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ] + ] + ], + [ + 'name' => 'Bewerber', + 'link' => $semlink . '/bewerber', + 'stg_kz' => $studiengang_kz, + 'children' => [ + [ + 'name' => 'Nicht zum Reihungstest angemeldet', + 'link' => $intlink . '/bewerberrtnichtangemeldet', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'Reihungstest angemeldet', + 'link' => $intlink . '/bewerberrtangemeldet', + 'stg_kz' => $studiengang_kz, + 'children' => [ + [ + 'name' => 'Teilgenommen', + 'link' => $intlink . '/bewerberrtangemeldetteilgenommen', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'Nicht teilgenommen', + 'link' => $intlink . '/bewerberrtangemeldetnichtteilgenommen', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ] + ] + ] + ] + ], + [ + 'name' => 'Aufgenommen', + 'link' => $semlink . '/aufgenommen', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'Warteliste', + 'link' => $semlink . '/warteliste', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'Absage', + 'link' => $semlink . '/absage', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ], + [ + 'name' => 'Incoming', + 'link' => $semlink . '/incoming', + 'stg_kz' => $studiengang_kz, + 'leaf' => true + ] + ] + ]; + } + + return $result; + } +} diff --git a/application/controllers/api/v1/person/Person.php b/application/controllers/api/v1/person/Person.php index a686f6060..6a373137f 100644 --- a/application/controllers/api/v1/person/Person.php +++ b/application/controllers/api/v1/person/Person.php @@ -264,4 +264,4 @@ class Person extends API_Controller return success('Input data are valid'); } -} +} \ No newline at end of file diff --git a/application/controllers/codex/Bismeldestichtag.php b/application/controllers/codex/Bismeldestichtag.php new file mode 100644 index 000000000..2723b2f7c --- /dev/null +++ b/application/controllers/codex/Bismeldestichtag.php @@ -0,0 +1,140 @@ + 'admin:r', + 'getStudiensemester' => 'admin:r', + 'getBismeldestichtage' => 'admin:r', + 'addBismeldestichtag' => 'admin:rw', + 'deleteBismeldestichtag' => 'admin:rw' + ) + ); + + // Load models + $this->load->model('codex/Bismeldestichtag_model', 'BismeldestichtagModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + // Loads phrases system + $this->loadPhrases( + array( + 'bismeldestichtag' + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Everything has a beginning + */ + public function index() + { + $this->load->view('codex/bismeldestichtag.php'); + } + + public function getStudiensemester() + { + // load semester list + $semList = array(); + $this->StudiensemesterModel->addSelect('studiensemester_kurzbz'); + $this->StudiensemesterModel->addOrder('start', 'DESC'); + $semRes = $this->StudiensemesterModel->load(); + + if (hasData($semRes)) + { + $semList = getData($semRes); + } + + // load current semester + $currSem = null; + $semRes = $this->StudiensemesterModel->getAkt(); + + if (hasData($semRes)) + { + $currSem = getData($semRes)[0]->studiensemester_kurzbz; + } + + // output data + $this->outputJsonSuccess( + array('semList' => $semList, 'currSem' => $currSem) + ); + } + + public function getBismeldestichtage() + { + $this->BismeldestichtagModel->addSelect( + 'meldestichtag_id, meldestichtag, + tbl_bismeldestichtag.studiensemester_kurzbz, sem.start AS semester_start, + tbl_bismeldestichtag.insertamum, tbl_bismeldestichtag.insertvon, tbl_bismeldestichtag.updateamum, tbl_bismeldestichtag.updatevon' + ); + $this->BismeldestichtagModel->addJoin('public.tbl_studiensemester sem', 'studiensemester_kurzbz', 'LEFT'); + $this->BismeldestichtagModel->addOrder('semester_start'); + $this->BismeldestichtagModel->addOrder('meldestichtag', 'DESC'); + $this->BismeldestichtagModel->addOrder('meldestichtag_id', 'DESC'); + $this->outputJson($this->BismeldestichtagModel->load()); + } + + public function addBismeldestichtag() + { + // get request data + $request = $this->getPostJSON(); + + // check request data + if (!property_exists($request, 'meldestichtag') || isEmptyString($request->meldestichtag)) + $this->terminateWithJsonError('Error occured: Meldestichtag missing'); + if (!property_exists($request, 'studiensemester_kurzbz') || isEmptyString($request->studiensemester_kurzbz)) + $this->terminateWithJsonError('Error occured: Studiensemester missing'); + + $meldestichtag = $request->meldestichtag; + $studiensemester_kurzbz = $request->studiensemester_kurzbz; + + // check if Bismeldestichtag already exists + $this->BismeldestichtagModel->addSelect('1'); + $bismeldestichtagRes = $this->BismeldestichtagModel->loadWhere( + array('meldestichtag' => $meldestichtag, 'studiensemester_kurzbz' => $studiensemester_kurzbz) + ); + + // return success if already exists + if (hasData($bismeldestichtagRes)) + $this->outputJsonSuccess('Bismeldestichtag already exists'); + else + { + // insert new if Stichtag does not exist + $this->outputJson($this->BismeldestichtagModel->insert( + array( + 'meldestichtag' => $request->meldestichtag, + 'studiensemester_kurzbz' => $request->studiensemester_kurzbz, + 'insertvon' => getAuthUID() + ) + )); + } + } + + public function deleteBismeldestichtag() + { + // get request data + $request = $this->getPostJSON(); + + // check request data + if (!property_exists($request, 'meldestichtag_id')) + $this->terminateWithJsonError('Error occured: Meldestichtag Id missing'); + + $meldestichtag_id = $request->meldestichtag_id; + + // deletetion + $this->outputJson($this->BismeldestichtagModel->delete($meldestichtag_id)); + } +} diff --git a/application/controllers/codex/UHSTAT1.php b/application/controllers/codex/UHSTAT1.php index 6bbd4d4f8..ff59ef41a 100644 --- a/application/controllers/codex/UHSTAT1.php +++ b/application/controllers/codex/UHSTAT1.php @@ -5,8 +5,12 @@ if (! defined("BASEPATH")) exit("No direct script access allowed"); class UHSTAT1 extends FHC_Controller { const BERECHTIGUNG_UHSTAT_VERWALTEN = 'student/uhstat1daten_verwalten'; + const LOGIN_SESSION_INDEX = 'bewerbung/user'; const PERSON_ID_SESSION_INDEX = 'bewerbung/personId'; const CODEX_OESTERREICH = 'A'; + const CODEX_UNKNOWN_YEAR = 9999; + const CODEX_UNKNOWN_NATION = 'XXX'; + const CODEX_UNKNOWN_BILDUNGMAX = 999; const LOWER_BOUNDARY_YEARS = 160; const UPPER_BOUNDARY_YEARS = 20; @@ -210,7 +214,9 @@ class UHSTAT1 extends FHC_Controller else return true; - if (!isset($bildungsstaat)) return true; + // if no Bildungsstaat or Bildungmax unknown - valid + if (!isset($bildungsstaat) || $bildungmax == self::CODEX_UNKNOWN_BILDUNGMAX) return true; + // find out if abschluss is in Austria $this->AbschlussModel->addSelect("in_oesterreich"); @@ -219,8 +225,11 @@ class UHSTAT1 extends FHC_Controller if (hasData($abschlussRes)) { $in_oesterreich = getData($abschlussRes)[0]->in_oesterreich; - // invalid if abschluss in Austria, but not Bildungsstaat, or abschluss not in Austria, but Bildungsstaat in Austria - return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH) || (!$in_oesterreich && $bildungsstaat != self::CODEX_OESTERREICH); + + // valid if Bildungsstaat and Abschluss in Austria, or Bildungsstaat and Abschluss not in Austria + // (or Abschluss not in Austria and Bildungsstaat unknown) + return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH) + || (!$in_oesterreich && ($bildungsstaat != self::CODEX_OESTERREICH || $bildungsstaat == self::CODEX_UNKNOWN_NATION)); } return false; @@ -321,7 +330,7 @@ class UHSTAT1 extends FHC_Controller $this->NationModel->addSelect("nation_code, $nationTextFieldName AS nation_text"); $this->NationModel->addOrder("nation_text"); - $nationRes = $this->NationModel->load(); + $nationRes = $this->NationModel->loadWhere('sperre IS NULL OR sperre = FALSE'); if (isError($nationRes)) return $nationRes; @@ -363,7 +372,11 @@ class UHSTAT1 extends FHC_Controller // get realistic birth years, dated back from current year $currYear = date("Y"); - $formMetaData['jahre'] = range($currYear - self::UPPER_BOUNDARY_YEARS, $currYear - self::LOWER_BOUNDARY_YEARS); + $yearRange = range($currYear - self::UPPER_BOUNDARY_YEARS, $currYear - self::LOWER_BOUNDARY_YEARS); + $formMetaData['jahre'] = array_combine($yearRange, $yearRange); + + // add "unknown" option + $formMetaData['jahre'][self::CODEX_UNKNOWN_YEAR] = 'unbekannt'; return success($formMetaData); } @@ -411,7 +424,10 @@ class UHSTAT1 extends FHC_Controller private function _getValidPersonId($berechtigungsArt) { // if coming from bewerbungstool - person id is in session (person must be logged in bewerbungstool) - if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX]) && is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX])) + if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX]) + && is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX]) + && isset($_SESSION[self::LOGIN_SESSION_INDEX]) + ) return $_SESSION[self::PERSON_ID_SESSION_INDEX]; // if person id passed directly... diff --git a/application/controllers/components/Filter.php b/application/controllers/components/Filter.php index ab7e1493e..617edd69f 100644 --- a/application/controllers/components/Filter.php +++ b/application/controllers/components/Filter.php @@ -9,6 +9,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON * NOTE: extends the FHC_Controller instead of the Auth_Controller because the FilterCmpt has its * own permissions check + * TODO(chris): deprecated */ class Filter extends FHC_Controller { @@ -26,6 +27,9 @@ class Filter extends FHC_Controller // Loads authentication library and starts authentication $this->load->library('AuthLib'); + // Loads the FiltersModel + $this->load->model('system/Filters_model', 'FiltersModel'); + // Loads the FilterCmptLib with HTTP GET/POST parameters $this->_startFilterCmptLib(); } diff --git a/application/controllers/components/Phrasen.php b/application/controllers/components/Phrasen.php new file mode 100644 index 000000000..3ac35a652 --- /dev/null +++ b/application/controllers/components/Phrasen.php @@ -0,0 +1,22 @@ +load->library('PhrasesLib', [$module], 'pj'); + $this->outputJsonSuccess(json_decode($this->pj->getJSON())); + } +} diff --git a/application/controllers/components/SearchBar.php b/application/controllers/components/SearchBar.php index dd3c22690..eac1a4cbc 100644 --- a/application/controllers/components/SearchBar.php +++ b/application/controllers/components/SearchBar.php @@ -3,7 +3,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** - * + * TODO(chris): deprecated */ class SearchBar extends FHC_Controller { @@ -17,11 +17,17 @@ class SearchBar extends FHC_Controller { parent::__construct(); - // Loads the AuthLib and starts the authentication + // Loads the AuthLib _without_ starting the authentication + // NOTE: + // - A user must be authenticated via another controller to access this one + // - It is loaded to be able to call the isLogged function later $this->load->library('AuthLib'); // Load the library SearchBarLib $this->load->library('SearchBarLib'); + + // Checks if the user is authenticated, otherwise returns an error code in JSON format + if (!isLogged()) $this->terminateWithJsonError(SearchBarLib::ERROR_NOT_AUTH); } //------------------------------------------------------------------------------------------------------------------ diff --git a/application/controllers/components/stv/Noten.php b/application/controllers/components/stv/Noten.php new file mode 100644 index 000000000..fb61de065 --- /dev/null +++ b/application/controllers/components/stv/Noten.php @@ -0,0 +1,168 @@ + 'student/noten:r', + 'getZeugnis' => 'student/noten:r', + 'update' => ['admin:w', 'assistenz:w'] + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + } + + public function get() + { + $this->load->model('codex/Note_model', 'NoteModel'); + + $result = $this->NoteModel->addOrder('note'); + + $result = $this->NoteModel->load(); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + + return $this->outputJson($result); + } + + public function getZeugnis($prestudent_id, $all = null) + { + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $result = $this->StudentModel->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + return $this->outputJson($result); + } + if (!hasData($result)) + return $this->outputJsonSuccess(null); + + $student_uid = current(getData($result))->student_uid; + + $studiensemester_kurzbz = ($all === null) ? $this->variablelib->getVar('semester_aktuell') : null; + + $result = $this->ZeugnisnoteModel->getZeugnisnoten($student_uid, $studiensemester_kurzbz); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + + return $this->outputJson($result); + } + + public function update() + { + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $this->load->library('form_validation'); + + $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true); + + if (empty($_POST) || !is_array(current($_POST))) { + $result = $this->hasPermissionUpdate($this->input->post('lehrveranstaltung_id'), $this->input->post('student_uid')); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN); + return $this->outputJson($result); + } + + $this->form_validation->set_rules('lehrveranstaltung_id', 'Lehrverantaltung ID', 'required|numeric'); + $this->form_validation->set_rules('student_uid', 'Student UID', 'required'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester Kurzbezeichnung', 'required'); + $this->form_validation->set_rules('note', 'Note', 'required|numeric'); + $post = [$_POST]; + } else { + foreach ($_POST as $i => $data) { + $lvid = isset($data['lehrveranstaltung_id']) ? $data['lehrveranstaltung_id'] : null; + $uid = isset($data['student_uid']) ? $data['student_uid'] : null; + $result = $this->hasPermissionUpdate($lvid, $uid); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN); + return $this->outputJson($result); + } + + $this->form_validation->set_rules($i . '[lehrveranstaltung_id]', '#' . $i . ' Lehrverantaltung ID', 'required|numeric'); + $this->form_validation->set_rules($i . '[student_uid]', '#' . $i . ' Student UID', 'required'); + $this->form_validation->set_rules($i . '[studiensemester_kurzbz]', '#' . $i . ' Studiensemester Kurzbezeichnung', 'required'); + $this->form_validation->set_rules($i . '[note]', '#' . $i . ' Note', 'required|numeric'); + } + $post = $_POST; + } + if ($this->form_validation->run() == false) { + $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); + return $this->outputJsonError($this->form_validation->error_array()); + } + + $final_result = success(); + $this->ZeugnisnoteModel->db->trans_start(); + + foreach ($post as $i => $data) { + $note = $data['note']; + unset($data['note']); + $result = $this->ZeugnisnoteModel->update($data, [ + 'note' => $note, + 'benotungsdatum' => date('c'), + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ]); + if (isError($result)) { + $final_result = $result; + break; + } + } + + $this->ZeugnisnoteModel->db->trans_complete(); + + if (isError($final_result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + + $this->outputJson($final_result); + } + + protected function hasPermissionUpdate($lehrveranstaltung_id, $student_uid) + { + // TODO(chris): error phrases! + if ($lehrveranstaltung_id === null || $student_uid === null) + return success(); + $result = $this->StudentModel->load([$student_uid]); + if (isError($result)) + return $result; + if (!hasData($result)) + return error('Fehler beim Ermitteln des Studenten'); + $student = current(getData($result)); + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz)) + return success(); + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz)) + return success(); + + $result = $this->StudienplanModel->getAllOesForLv($lehrveranstaltung_id); + if (isError($result)) + return $result; + $oes = getData($result) ?: []; + $result = $this->LehrveranstaltungModel->getStg($lehrveranstaltung_id); + if (isError($result)) + return $result; + if (hasData($result)) + $oes[] = current(getData($result)); + + foreach ($oes as $oe) { + if ($this->permissionlib->isBerechtigt('admin', 'suid', $oe->oe_kurzbz)) + return success(); + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $oe->oe_kurzbz)) + return success(); + } + + return error('Forbidden'); + } +} diff --git a/application/controllers/components/stv/Studienplan.php b/application/controllers/components/stv/Studienplan.php new file mode 100644 index 000000000..b60388ac1 --- /dev/null +++ b/application/controllers/components/stv/Studienplan.php @@ -0,0 +1,43 @@ + self::PERM_LOGGED + ]); + } + + public function get() + { + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $_POST = json_decode($this->input->raw_input_stream, true); + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('studiengang_kz', 'StudiengangKz', 'required|numeric'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'StudiensemesterKurbz', 'required'); + $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'numeric'); + + if ($this->form_validation->run() == false) { + $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); + return $this->outputJsonError($this->form_validation->error_array()); + } + + $studiengang_kz = $this->input->post('studiengang_kz'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $ausbildungssemester = $this->input->post('ausbildungssemester') ?: null; + $orgform_kurzbz = $this->input->post('orgform_kurzbz') ?: null; + + $result = $this->StudienplanModel->getStudienplaeneBySemester($studiengang_kz, $studiensemester_kurzbz, $ausbildungssemester, $orgform_kurzbz); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } +} diff --git a/application/controllers/components/stv/Studiensemester.php b/application/controllers/components/stv/Studiensemester.php new file mode 100644 index 000000000..c3db99686 --- /dev/null +++ b/application/controllers/components/stv/Studiensemester.php @@ -0,0 +1,78 @@ + self::PERM_LOGGED, + 'now' => self::PERM_LOGGED, + 'set' => self::PERM_LOGGED + ]); + } + + public function index() + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addOrder('start'); + + $result = $this->StudiensemesterModel->load(); + + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } + + public function now() + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $result = $this->StudiensemesterModel->getNearest(); + + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + $this->outputJson(getError($result)); + } + $result = getData($result) ?: []; + + if (count($result) != 1) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + $this->outputJsonError(count($result) ? 'Mehrere Studiensemester aktiv' : 'Kein Studiensemester aktiv'); + } else { + $this->outputJsonSuccess(current($result)->studiensemester_kurzbz); + } + } + + public function set() + { + $this->load->library('AuthLib'); + $this->load->library('form_validation'); + + $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true); + + $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required'); + + if ($this->form_validation->run() == false) { + $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); + return $this->outputJsonError($this->form_validation->error_array()); + } + + $stdsem = $this->input->post('studiensemester'); + + $this->load->model('system/Variable_model', 'VariableModel'); + + $result = $this->VariableModel->setVariable(getAuthUID(), 'semester_aktuell', $stdsem); + + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + return $this->outputJson($result); + } + + $this->outputJsonSuccess(true); + } +} diff --git a/application/controllers/jobs/AntragJob.php b/application/controllers/jobs/AntragJob.php new file mode 100644 index 000000000..46a31f3d6 --- /dev/null +++ b/application/controllers/jobs/AntragJob.php @@ -0,0 +1,707 @@ +load->config('studierendenantrag'); + + // Loads SanchoHelper + $this->load->helper('hlp_sancho_helper'); + + $this->load->library('AntragLib'); + + // Load Model + $this->load->model('education/Studierendenantrag_model', 'StudierendenantragModel'); + $this->load->model('education/Studierendenantragstatus_model', 'StudierendenantragstatusModel'); + $this->load->model('education/Pruefung_model', 'PruefungModel'); + $this->load->model('person/Kontakt_model', 'KontaktModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->loadPhrases([ + 'lehre' + ]); + } + + /** + * Send infomail to Stgl + */ + public function sendStglSammelmail() + { + $this->load->model('person/Person_model', 'PersonModel'); + + $this->logInfo('Start Job sendStglSammelmail'); + + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $this->StudierendenantragModel->addJoin('public.tbl_prestudent', 'prestudent_id'); + $this->db->group_start(); + $this->db->where('typ', Studierendenantrag_model::TYP_ABMELDUNG); + $this->db->where('campus.get_status_studierendenantrag(studierendenantrag_id)', Studierendenantragstatus_model::STATUS_CREATED); + $this->db->group_end(); + + $this->db->or_group_start(); + $this->db->where('typ', Studierendenantrag_model::TYP_ABMELDUNG_STGL); + $this->db->where('campus.get_status_studierendenantrag(studierendenantrag_id)', Studierendenantragstatus_model::STATUS_CREATED); + $this->db->group_end(); + + $this->db->or_group_start(); + $this->db->where('typ', Studierendenantrag_model::TYP_UNTERBRECHUNG); + $this->db->where('campus.get_status_studierendenantrag(studierendenantrag_id)', Studierendenantragstatus_model::STATUS_CREATED); + $this->db->group_end(); + + $this->db->or_group_start(); + $this->db->where('typ', Studierendenantrag_model::TYP_WIEDERHOLUNG); + $this->db->where('campus.get_status_studierendenantrag(studierendenantrag_id)', Studierendenantragstatus_model::STATUS_LVSASSIGNED); + $this->db->group_end(); + + $result = $this->StudierendenantragModel->load(); + if(isError($result)) + return $this->logError(getError($result)); + + if(!hasData($result)) + return $this->logInfo('End Job sendStglSammelmail: 0 Mails sent'); + + $antraege = getData($result); + + $stgs = array(); + $stgLeitungen = array(); + + foreach ($antraege as $antrag) + { + if (!isset($stgs[$antrag->studiengang_kz])) + { + $result = $this->StudiengangModel->getLeitung($antrag->studiengang_kz); + if (isError($result)) + { + $this->logError(getError($result)); + continue; + } + if (!hasData($result)) + { + $this->logError('Keine Leitung für Studiengang ' . $antrag->studiengang_kz . ' gefunden!'); + continue; + } + + $leitung = current(getData($result)); + if (!isset($stgLeitungen[$leitung->uid])) + { + $stgLeitungen[$leitung->uid] = [ 'Details' => $leitung, 'stgs' => [] ]; + } + $stgLeitungen[$leitung->uid]['stgs'][] = $antrag->studiengang_kz; + + $result = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id); + if (isError($result)) + { + $this->logError(getError($result)); + continue; + } + if (!hasData($result)) + { + $this->logError('Keine Details für Studiengang ' . $antrag->studiengang_kz . ' gefunden!'); + continue; + } + $details = current(getData($result)); + + $stgs[$antrag->studiengang_kz] = [ + 'Abmeldung' => [], + 'Unterbrechung' => [], + 'Wiederholung' => [], + 'Details' => $details + ]; + } + $stgs[$antrag->studiengang_kz][str_replace('Stgl', '', $antrag->typ)] = $antrag; + } + + $this->load->model('system/Sprache_model', 'SpracheModel'); + $result = $this->SpracheModel->loadWhere(['content' => true]); + if (isError($result)) { + $this->logError(getError($result)); + $languages = [DEFAULT_LANGUAGE]; + } elseif (!hasData($result)) { + $languages = [DEFAULT_LANGUAGE]; + } else { + $languages = array_map(function ($row) { + return $row->sprache; + }, getData($result)); + } + + $count = 0; + foreach ($stgLeitungen as $leitung) + { + $data = [ + 'name' => trim($leitung['Details']->vorname . ' ' . $leitung['Details']->nachname), + 'vorname' => $leitung['Details']->vorname, + 'nachname' => $leitung['Details']->nachname + ]; + + foreach ($languages as $lang) { + unset($this->p); + $this->loadPhrases(['studierendenantrag'], $lang); + + $table = ''; + foreach ($leitung['stgs'] as $studiengang_kz) { + $rows = ''; + $stg = $stgs[$studiengang_kz]; + foreach (['Abmeldung', 'Unterbrechung', 'Wiederholung'] as $typ) { + $c = count($stg[$typ]); + if ($c) { + $rows .= $this->p->t('studierendenantrag', 'mail_part_x_new_' . $typ, ['count' => $c]); + } + } + $table .= $this->p->t('studierendenantrag', 'mail_part_table', [ + 'stg_bezeichnung' => $stg['Details']->bezeichnung, + 'stg_orgform_kurzbz' => $stg['Details']->orgform_kurzbz, + 'rows' => $rows + ]); + } + $data['table_' . $lang] = $table; + } + + $data['table'] = $data['table_' . DEFAULT_LANGUAGE]; + $data['leitungLink'] = APP_ROOT. 'index.ci.php/lehre/Studierendenantrag/leitung'; + + //Mail an Stgl und Assistenz + $to = $leitung['Details']->uid . '@' . DOMAIN; + $cc = $leitung['Details']->email; + + // NOTE(chris): Sancho mail + if (sendSanchoMail( + "Sancho_Mail_Antrag_Stgl", + $data, + $to, + 'Anträge - Aktion(en) erforderlich', + DEFAULT_SANCHO_HEADER_IMG, + DEFAULT_SANCHO_FOOTER_IMG, + '', + $cc + )) + $count++; + } + + $this->logInfo($count . " Emails erfolgreich versandt"); + + $this->logInfo('End Job sendStglSammelmail'); + } + + /** + * Send reminder to Assistant for Wiedereinstieg Unterbrecher + * + */ + public function sendReminderWiedereinstieg() + { + $now = new DateTime(); + $modifier = $this->config->item('unterbrechung_job_remind_wiedereinstieg_date_modifier'); + if (!$modifier) + return $this->logError('Konnte Job nicht starten: Config "unterbrechung_job_remind_wiedereinstieg_date_modifiers" nicht gesetzt'); + + $end = new DateTime(); + $end->modify($modifier); + + $this->logInfo(sprintf( + 'Start Job sendReminderWiedereinstieg (Wiedereinstieg zwischen %s - %s)', + $now->format('Y-m-d'), + $end->format('Y-m-d') + )); + + $result = $this->StudierendenantragModel->getAntraegeWhereWiedereinstiegBetween($now, $end); + + if(isError($result)) + { + $this->logError(getError($result)); + $this->logInfo('Ende Job sendReminderWiedereinstieg'); + return; + } + + $antraege = getData($result) ?: []; + $count = 0; + foreach ($antraege as $antrag) + { + $res = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id); + $stg = ''; + $orgform = ''; + if (hasData($res)) { + $studiengang = current(getData($res)); + $stg = $studiengang->bezeichnung; + $orgform = $studiengang->orgform_kurzbz; + } + + $datum = new DateTime($antrag->datum_wiedereinstieg); + $data = array( + 'prestudent' => $antrag->prestudent_id, + 'name' => trim($antrag->vorname . ' '. $antrag->nachname), + 'datum_wiedereinstieg' => $datum->format('d.m.Y'), + 'vorname' => $antrag->vorname, + 'nachname' => $antrag->nachname, + 'Orgform' => $orgform, + 'stg' => $stg + ); + $result = $this->StudentModel->loadWhere(['prestudent_id'=> $antrag->prestudent_id]); + if (hasData($result)) { + $student = current(getData($result)); + $data['UID'] = $student->student_uid; + } + + // NOTE(chris): Sancho mail + if(sendSanchoMail('Sancho_Mail_Antrag_U_Reminder', $data, $antrag->email, 'Reminder: Unterbrechung Wiedereinstieg')) + { + $count++; + $this->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag->studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_REMINDERSENT, + 'insertvon' => 'AntragJob' + ]); + } + } + $this->logInfo($count . ' Reminder gesendet - Ende Job sendReminderWiedereinstieg'); + } + + /** + * Set Wiederholer after deadline to Abbrecher + * + */ + public function handleWiederholerDeadline() + { + $this->logInfo('Start Job handleWiederholerDeadline'); + + $this->load->library('PrestudentLib'); + + $insertvon = $this->config->item('antrag_job_systemuser'); + if (!$insertvon) { + $this->logError('Config "antrag_job_systemuser" nicht gesetzt'); + $this->logInfo('Ende Job handleWiederholerDeadline'); + return; + } + + $modifier_deadline = $this->config->item('wiederholung_job_deadline_date_modifier'); + if (!$modifier_deadline) { + $this->logError('Config "wiederholung_job_deadline_date_modifier" nicht gesetzt'); + $this->logInfo('Ende Job handleWiederholerDeadline'); + return; + } + + $digi_start= $this->config->item('digitalization_start'); + if($digi_start) + $digi_start = new DateTime($digi_start); + + $dateDeadline = new DateTime(); + $dateDeadline->sub(DateInterval::createFromDateString($modifier_deadline)); + + $result = $this->PruefungModel->getAllPrestudentsWhereCommitteeExamFailed( + [ + Studierendenantragstatus_model::STATUS_REQUESTSENT_1, + Studierendenantragstatus_model::STATUS_REQUESTSENT_2 + ], + $dateDeadline, + $digi_start + ); + if(isError($result)) + { + $this->logError(getError($result)); + } + else + { + $prestudents = getData($result) ?: []; + $count = 0; + + $prestudents = $this->prestudentsGetUnique($prestudents); + + + foreach ($prestudents as $prestudent) + { + $result = $this->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $prestudent->studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED, + 'insertvon' => 'AntragJob' + ]); + if (isError($result)) { + $this->logError(getError($result)); + } else { + $deregisterStatus = getData($result); + + $result = $this->antraglib->pauseAntrag( + $prestudent->studierendenantrag_id, + Studierendenantragstatus_model::INSERTVON_DEREGISTERED + ); + if (isError($result)) + $this->logError(getError($result)); + + $result = $this->prestudentlib->setAbbrecher($prestudent->prestudent_id, '', $insertvon); + if (isError($result)) { + $this->StudierendenantragstatusModel->delete($deregisterStatus); + $this->logError(getError($result)); + } else { + $count++; + + $datum_kp = new DateTime($prestudent->datum); + $dataMail = array( + 'name'=> trim($prestudent->vorname . ' '. $prestudent->nachname), + 'vorname' => $prestudent->vorname, + 'nachname' => $prestudent->nachname, + 'pers_kz'=> $prestudent->matrikelnr, + 'stg' => $prestudent->bezeichnung, + 'lvbezeichnung' => $prestudent->lvbezeichnung, + 'datum_kp' => $datum_kp->format('d.m.Y'), + 'studiensemester'=> $prestudent->studiensemester_kurzbz, + 'Orgform'=> $prestudent->orgform, + 'prestudent_id' => $prestudent->prestudent_id, + 'fristablauf' => $dateDeadline->format('d.m.Y') + ); + + $email = $this->StudentModel->getEmailFH($this->StudentModel->getUID($prestudent->prestudent_id)); + // Mail to Student + if (!sendSanchoMail('Sancho_Mail_Antrag_W_DL_Stud', $dataMail, $email, 'Wiederholung: Frist abgelaufen')) { + $this->logWarning("Failed to send Notification to " . $email); + } + + $result = $this->StudiengangModel->load($prestudent->studiengang_kz); + if (!hasData($result)) { + $this->logWarning('No Studiengang found'); + continue; + } + $studiengang = current(getData($result)); + $email = $studiengang->email; + // Mail to Assistenz + if (!sendSanchoMail('Sancho_Mail_Antrag_W_DL_Assist', $dataMail, $email, 'Wiederholung: Frist abgelaufen')) { + $this->logWarning("Failed to send Notification to " . $email); + } + } + } + } + $this->logInfo($count . " Students set to Abbrecher"); + } + + $this->logInfo('Ende Job handleWiederholerDeadline'); + } + + /** + * Set Abmeldungen after deadline to Abbrecher + * + */ + public function handleAbmeldungenStglDeadline() + { + $this->logInfo('Start Job handleAbmeldungenStglDeadline'); + + $insertvon = $this->config->item('antrag_job_systemuser'); + if (!$insertvon) { + $this->logError('Config "antrag_job_systemuser" nicht gesetzt'); + $this->logInfo('Ende Job handleAbmeldungenStglDeadline'); + return; + } + + $modifier_deadline = $this->config->item('abmeldung_job_deadline_date_modifier'); + if (!$modifier_deadline) { + $this->logError('Config "abmeldung_job_deadline_date_modifier" nicht gesetzt'); + $this->logInfo('Ende Job handleAbmeldungenStglDeadline'); + return; + } + + $dateDeadline = new DateTime(); + $dateDeadline->sub(DateInterval::createFromDateString($modifier_deadline)); + + $this->StudierendenantragModel->addSelect('tbl_studierendenantrag.studierendenantrag_id'); + $this->StudierendenantragModel->addSelect('prestudent_id'); + $this->StudierendenantragModel->addSelect('studiensemester_kurzbz'); + $this->StudierendenantragModel->addSelect('s.insertamum'); + $this->StudierendenantragModel->addSelect('s.insertvon'); + $this->StudierendenantragModel->addJoin('public.tbl_student pts', 'prestudent_id'); + $this->StudierendenantragModel->addSelect('pts.student_uid'); + + $this->StudierendenantragModel->db->where_in( + 'public.get_rolle_prestudent(prestudent_id, studiensemester_kurzbz)', + $this->config->item('antrag_prestudentstatus_whitelist_abmeldung') + ); + + $result = $this->StudierendenantragModel->getWithLastStatusWhere([ + 'typ' => Studierendenantrag_model::TYP_ABMELDUNG_STGL, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED, + 's.insertamum <=' => $dateDeadline->format('c') + ]); + + if(isError($result)) + { + $this->logError(getError($result)); + } + else + { + $antraege = getData($result) ?: []; + $count = 0; + + foreach ($antraege as $antrag) + { + $result = $this->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag->studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED, + 'insertvon' => 'AntragJob' + ]); + if (isError($result)) + $this->logError(getError($result)); + else { + $deregisterStatus = getData($result); + + $result = $this->antraglib->pauseAntrag($antrag->studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_DEREGISTERED); + if (isError($result)) + $this->logError(getError($result)); + + $this->load->model('crm/Statusgrund_model', 'StatusgrundModel'); + $result = $this->StatusgrundModel->loadWhere(['statusgrund_kurzbz' => 'abbrecherStgl']); + if (isError($result)) { + $this->logError(getError($result)); + continue; + } elseif (!hasData($result)) { + $this->logError($this->p->t('lehre', 'error_noStatusgrund', ['statusgrund_kurzbz' => 'abbrecherStgl'])); + continue; + } + + $statusgrund = current(getData($result)); + + $result = $this->prestudentlib->setAbbrecher( + $antrag->prestudent_id, + $antrag->studiensemester_kurzbz, + 'AntragJob', + $statusgrund->statusgrund_id, + $antrag->insertamum, + null, + $antrag->insertvon ?: $insertvon + ); + if (isError($result)) { + $this->StudierendenantragstatusModel->delete($deregisterStatus); + $this->logError(getError($result)); + } else { + $count++; + $result = $this->PrestudentModel->load($antrag->prestudent_id); + if(!hasData($result)) { + $this->logWarning('No Prestudent found'); + continue; + } + $prestudent = current(getData($result)); + $result = $this->StudiengangModel->load($prestudent->studiengang_kz); + if(!hasData($result)) { + $this->logWarning('No Studiengang found'); + continue; + } + $studiengang = current(getData($result)); + $result = $this->PersonModel->loadPrestudent($antrag->prestudent_id); + if(!hasData($result)) + { + $this->logWarning('No Person found'); + continue; + } + $person = current(getData($result)); + $email = $studiengang->email; + $dataMail = array( + 'prestudent' => 'UID: ' . $antrag->student_uid . ', PreStudentId: ' . $antrag->prestudent_id, + 'studiensemester' => $antrag->studiensemester_kurzbz, + 'name' => trim($person->vorname . ' '. $person->nachname), + ); + + if(!sendSanchoMail('Sancho_Mail_Antrag_A_Assist', $dataMail, $email, 'Einspruchsfrist abgelaufen')) + { + $this->logWarning("Failed to send Notification to " . $email); + } + } + } + } + $this->logInfo($count . "/" . count($antraege) . " Students set to Abbrecher"); + } + $this->logInfo('Ende Job handleAbmeldungenStglDeadline'); + } + + /** + * Send Request to Student do Decide between Wiederholung and Verzicht + * + */ + public function sendAufforderungWiederholer() + { + $this->logInfo('Start Job sendAufforderungWiederholer'); + + $modifier_request_1 = $this->config->item('wiederholung_job_request_1_date_modifier'); + $modifier_request_2 = $this->config->item('wiederholung_job_request_2_date_modifier'); + $modifier_deadline = $this->config->item('wiederholung_job_deadline_date_modifier'); + + $digi_start = $this->config->item('digitalization_start'); + if ($digi_start) { + try { + $digi_start = new DateTime($digi_start); + } catch(Exception $e) { + } + } + + if ($modifier_deadline) { + $dateDeadline = new DateTime(); + $dateDeadline->sub(DateInterval::createFromDateString($modifier_deadline)); + + if ($digi_start) + $dateDeadline = max($digi_start, $dateDeadline); + } else { + $dateDeadline = $digi_start ?: null; + } + + //first request + if ($modifier_request_1) { + $dateStichtag = new DateTime(); + $dateStichtag->sub(DateInterval::createFromDateString($modifier_request_1)); + if (!$dateDeadline || $dateStichtag > $dateDeadline) + $this->sendReminder( + 'Request1', + null, + Studierendenantragstatus_model::STATUS_REQUESTSENT_1, + $dateDeadline, + $dateStichtag, + $modifier_deadline, + 'Aufforderung: Bekanntgabe Wiederholung' + ); + } else + $this->logError('Config "wiederholung_job_request_1_date_modifier" nicht gesetzt'); + + //second request + if ($modifier_request_2) { + $dateStichtag = new DateTime(); + $dateStichtag->sub(DateInterval::createFromDateString($modifier_request_2)); + if (!$dateDeadline || $dateStichtag > $dateDeadline) + $this->sendReminder( + 'Request2', + Studierendenantragstatus_model::STATUS_REQUESTSENT_1, + Studierendenantragstatus_model::STATUS_REQUESTSENT_2, + $dateDeadline, + $dateStichtag, + $modifier_deadline, + 'Reminder Aufforderung: Bekanntgabe Wiederholung' + ); + } else + $this->logError('Config "wiederholung_job_request_2_date_modifier" nicht gesetzt'); + + $this->logInfo('Ende Job sendAufforderungWiederholer'); + } + + protected function prestudentsGetUnique($prestudents) + { + $result = []; + foreach ($prestudents as $prestudent) { + if (!isset($result[$prestudent->prestudent_id])) + $result[$prestudent->prestudent_id] = $prestudent; + else { + if ($result[$prestudent->prestudent_id]->datum > $prestudent->datum) + $result[$prestudent->prestudent_id] = $prestudent; + } + } + return $result; + } + + protected function sendReminder($name, $status_from, $status_to, $deadline, $date_stichtag, $modifier_deadline, $subject) + { + $this->logInfo('Start Job sendAufforderungWiederholer ' . $name); + + $result = $this->PruefungModel->getAllPrestudentsWhereCommitteeExamFailed($status_from, $date_stichtag, $deadline); + + if(isError($result)) + { + $this->logError(getError($result)); + } + else + { + $prestudents = getData($result) ?: []; + $count = 0; + + $prestudents = $this->prestudentsGetUnique($prestudents); + + foreach ($prestudents as $prestudent) + { + $stg_kz = $prestudent->studiengang_kz; + if (in_array($stg_kz, $this->config->item('stgkz_blacklist_wiederholung'))) + continue; + $url = site_url('lehre/Studierendenantrag/wiederholung/' . $prestudent->prestudent_id); + $urlCIS = CIS_ROOT . 'index.ci.php/lehre/Studierendenantrag/wiederholung/' . $prestudent->prestudent_id; + $email = $this->StudentModel->getEmailFH($this->StudentModel->getUID($prestudent->prestudent_id)); + + $fristende = new DateTime($prestudent->datum); + $fristende->add(DateInterval::createFromDateString($modifier_deadline)); + + $datum_kp = new DateTime($prestudent->datum); + + $result = $this->StudiensemesterModel->getNextFrom($prestudent->studiensemester_kurzbz); + $next_sem = ""; + $sem_after_next_sem = ""; + if (hasData($result)) { + $next_sem = current(getData($result))->studiensemester_kurzbz; + $result = $this->StudiensemesterModel->getNextFrom($next_sem); + if (hasData($result)) { + $sem_after_next_sem = current(getData($result))->studiensemester_kurzbz; + } + } + + $dataMail = array( + 'name'=> trim($prestudent->vorname . ' '. $prestudent->nachname), + 'vorname' => $prestudent->vorname, + 'nachname' => $prestudent->nachname, + 'pers_kz'=> $prestudent->matrikelnr, + 'stg' => $prestudent->bezeichnung, + 'lvbezeichnung' => $prestudent->lvbezeichnung, + 'datum_kp' => $datum_kp->format('d.m.Y'), + 'studiensemester'=> $prestudent->studiensemester_kurzbz, + 'Orgform'=> $prestudent->orgform, + 'prestudent_id' => $prestudent->prestudent_id, + 'url' => $url, + 'urlCIS' => $urlCIS, + 'fristablauf' => $fristende->format('d.m.Y'), + 'pre_wiederholer_sem' => $next_sem, + 'wiederholer_sem' => $sem_after_next_sem, + 'sem' => $prestudent->ausbildungssemester + ); + + // NOTE(chris): Sancho mail + if(sendSanchoMail('Sancho_Mail_Antrag_W_' . $name, $dataMail, $email, $subject)) + { + $antrag_id = null; + $result = $this->StudierendenantragModel->loadWhere([ + 'prestudent_id' => $prestudent->prestudent_id, + 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG + ]); + if (isError($result)) + $this->logError(getError($result)); + elseif (hasData($result)) + $antrag_id = current(getData($result) ?: []) -> studierendenantrag_id; + if ($antrag_id == null) + { + $result = $this->StudierendenantragModel->insert([ + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz'=> $prestudent->studiensemester_kurzbz, + 'datum' => date('c'), + 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG, + 'insertvon' => 'AntragJob' + ]); + if (isError($result)) + $this->logError(getError($result)); + else + $antrag_id = getData($result); + } + if ($antrag_id) + { + $result = $this->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz' => $status_to, + 'insertvon' => 'AntragJob' + ]); + if (isError($result)) + $this->logError(getError($result)); + } + $count++; + } + } + $this->logInfo($count . " Mails '" . $subject . "' sent"); + } + $this->logInfo('Ende Job sendAufforderungWiederholer ' . $name); + } +} diff --git a/application/controllers/jobs/ESIJob.php b/application/controllers/jobs/ESIJob.php new file mode 100644 index 000000000..c9a558a46 --- /dev/null +++ b/application/controllers/jobs/ESIJob.php @@ -0,0 +1,165 @@ +load->model('person/Person_model', 'PersonModel'); + $this->load->model('person/Kennzeichen_model', 'KennzeichenModel'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Initialises generateESI job, handles job queue, logs infos/errors + */ + public function generateESI() + { + //$jobType = 'DVUHSendPruefungsaktivitaeten'; + $this->logInfo(ESIScheduler::JOB_TYPE_GENERATE_ESI.' job start'); + + // Gets the latest jobs + $lastJobs = $this->getLastJobs(ESIScheduler::JOB_TYPE_GENERATE_ESI); + + if (isError($lastJobs)) + { + $this->logError(getCode($lastJobs).': '.getError($lastJobs), ESIScheduler::JOB_TYPE_GENERATE_ESI); + } + else + { + $this->updateJobs( + getData($lastJobs), // Jobs to be updated + array(JobsQueueLib::PROPERTY_START_TIME), // Job properties to be updated + array(date('Y-m-d H:i:s')) // Job properties new values + ); + + $person_arr = $this->_getInputObjArray(getData($lastJobs)); + + foreach ($person_arr as $persobj) + { + if (!isset($persobj->person_id)) + $this->logError("Error when generating ESI: invalid parameters"); + else + { + $person_id = $persobj->person_id; + + // check if there already is an active ESI + $this->KennzeichenModel->addSelect('1'); + $activeKennzeichenRes = $this->KennzeichenModel->loadWhere( + array('person_id' => $person_id, 'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ, 'aktiv' => true) + ); + + if (hasData($activeKennzeichenRes)) + { + $this->logError("Active ESI for person Id $person_id already exists"); + continue; + } + + // get Matrikelnr for person for which ESI should be generated + $this->PersonModel->addSelect('matr_nr'); + $personRes = $this->PersonModel->load($person_id); + + if (!hasData($personRes)) + { + $this->logError("Person with Id $person_id not found"); + continue; + } + + $matr_nr = getData($personRes)[0]->matr_nr; + + if (isEmptyString($matr_nr)) + { + $this->logError("Matrikelnummer for person with Id $person_id is empty"); + continue; + } + + $esi = self::ESI_PREFIX.$matr_nr; + + // check if ESI was already used + $this->KennzeichenModel->addSelect('1'); + $existingKennzeichenRes = $this->KennzeichenModel->loadWhere( + array('person_id' => $person_id, 'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ, 'inhalt' => $esi) + ); + + if (hasData($existingKennzeichenRes)) + { + $this->logError("ESI $esi for person Id $person_id already exists"); + continue; + } + + // if everything ok, save the esi for the person + $saveEsiResult = $this->KennzeichenModel->insert( + array( + 'person_id' => $person_id, + 'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ, + 'inhalt' => $esi, + 'aktiv' => true, + 'insertvon' => self::INSERT_VON + ) + ); + + if (isError($saveEsiResult)) + { + $this->logError("Error when sending ESI, person Id $person_id ".getError($saveEsiResult)); + } + } + } + + // Update jobs properties values + $this->updateJobs( + getData($lastJobs), // Jobs to be updated + array(JobsQueueLib::PROPERTY_STATUS, JobsQueueLib::PROPERTY_END_TIME), // Job properties to be updated + array(JobsQueueLib::STATUS_DONE, date('Y-m-d H:i:s')) // Job properties new values + ); + + if (hasData($lastJobs)) $this->updateJobsQueue(ESIScheduler::JOB_TYPE_GENERATE_ESI, getData($lastJobs)); + } + + $this->logInfo(ESIScheduler::JOB_TYPE_GENERATE_ESI.' job stop'); + } + + // -------------------------------------------------------------------------------------------- + // Private methods + + /** + * Extracts input data from jobs. + * @param $jobs + * @return array with jobinput + */ + private function _getInputObjArray($jobs) + { + $mergedUsersArray = array(); + + if (count($jobs) == 0) return $mergedUsersArray; + + foreach ($jobs as $job) + { + $decodedInput = json_decode($job->input); + if ($decodedInput != null) + { + foreach ($decodedInput as $el) + { + $mergedUsersArray[] = $el; + } + } + } + return $mergedUsersArray; + } +} diff --git a/application/controllers/jobs/IssueResolver.php b/application/controllers/jobs/IssueResolver.php index cf97b7f68..ca07439c3 100755 --- a/application/controllers/jobs/IssueResolver.php +++ b/application/controllers/jobs/IssueResolver.php @@ -9,8 +9,8 @@ class IssueResolver extends IssueResolver_Controller { parent::__construct(); - // set fehler codes which can be resolved by the job - // structure: fehlercode => class (library) name for resolving + // set fehler codes which can be resolved by the job, with own resolver defined + // structure: fehlercode => class (library) name for resolving in "resolvers" folder $this->_codeLibMappings = array( 'CORE_ZGV_0001' => 'CORE_ZGV_0001', 'CORE_ZGV_0002' => 'CORE_ZGV_0002', @@ -30,7 +30,6 @@ class IssueResolver extends IssueResolver_Controller 'CORE_STG_0002' => 'CORE_STG_0002', 'CORE_STG_0003' => 'CORE_STG_0003', 'CORE_STG_0004' => 'CORE_STG_0004', - 'CORE_STUDENTSTATUS_0001' => 'CORE_STUDENTSTATUS_0001', 'CORE_STUDENTSTATUS_0002' => 'CORE_STUDENTSTATUS_0002', 'CORE_STUDENTSTATUS_0003' => 'CORE_STUDENTSTATUS_0003', 'CORE_STUDENTSTATUS_0004' => 'CORE_STUDENTSTATUS_0004', @@ -45,10 +44,17 @@ class IssueResolver extends IssueResolver_Controller 'CORE_STUDENTSTATUS_0013' => 'CORE_STUDENTSTATUS_0013', 'CORE_STUDENTSTATUS_0014' => 'CORE_STUDENTSTATUS_0014', 'CORE_STUDENTSTATUS_0015' => 'CORE_STUDENTSTATUS_0015', + 'CORE_STUDENTSTATUS_0016' => 'CORE_STUDENTSTATUS_0016', 'CORE_PERSON_0001' => 'CORE_PERSON_0001', 'CORE_PERSON_0002' => 'CORE_PERSON_0002', 'CORE_PERSON_0003' => 'CORE_PERSON_0003', 'CORE_PERSON_0004' => 'CORE_PERSON_0004' ); + + // fehler which are resolved by the job the same way as they are produced + // structure: fehlercode => class (library) name for resolving in "plausichecks" folder + $this->_codeProducerLibMappings = array( + 'CORE_STUDENTSTATUS_0001' => 'AbbrecherAktiv', + ); } } diff --git a/application/controllers/jobs/OneTimeMessages.php b/application/controllers/jobs/OneTimeMessages.php index 58bc1fb7c..525f63c3b 100644 --- a/application/controllers/jobs/OneTimeMessages.php +++ b/application/controllers/jobs/OneTimeMessages.php @@ -51,7 +51,7 @@ class OneTimeMessages extends JOB_Controller FROM public.tbl_prestudent p JOIN public.tbl_prestudentstatus ps USING (prestudent_id) JOIN public.tbl_studiengang s USING (studiengang_kz) - WHERE ps.status_kurzbz = \'Wartender\' + WHERE get_rolle_prestudent(ps.prestudent_id, NULL) = \'Wartender\' AND ps.studiensemester_kurzbz = ? AND ps.datum <= NOW() - \''.$days.' days\'::interval AND s.typ = ? diff --git a/application/controllers/jobs/ReihungstestJob.php b/application/controllers/jobs/ReihungstestJob.php index 431ac5b04..b55287439 100644 --- a/application/controllers/jobs/ReihungstestJob.php +++ b/application/controllers/jobs/ReihungstestJob.php @@ -467,7 +467,7 @@ class ReihungstestJob extends JOB_Controller $this->PrestudentstatusModel->addJoin('public.tbl_person', 'person_id'); $yesterdays_applicants_arr = $this->PrestudentstatusModel->loadWhere(' - status_kurzbz = \'Interessent\' AND + status_kurzbz IN (\'Interessent\', \'Bewerber\') AND typ = \'b\' AND bestaetigtam = current_date - 1 '); @@ -730,33 +730,27 @@ class ReihungstestJob extends JOB_Controller tbl_reihungstest.reihungstest_id, tbl_studienplan.studienplan_id, tbl_reihungstest.studiensemester_kurzbz, - tbl_studienordnung.studiengang_kz + tbl_studienordnung.studiengang_kz, + tbl_studienplan.orgform_kurzbz FROM public.tbl_reihungstest - JOIN public.tbl_rt_studienplan ON(tbl_rt_studienplan.reihungstest_id=tbl_reihungstest.reihungstest_id) - JOIN lehre.tbl_studienplan USING(studienplan_id) - JOIN lehre.tbl_studienordnung USING(studienordnung_id) + JOIN public.tbl_rt_studienplan ON(tbl_rt_studienplan.reihungstest_id=tbl_reihungstest.reihungstest_id) + JOIN lehre.tbl_studienplan USING(studienplan_id) + JOIN lehre.tbl_studienordnung USING(studienordnung_id) WHERE - NOT EXISTS( - SELECT 1 FROM lehre.tbl_studienplan_semester - WHERE studienplan_id=tbl_rt_studienplan.studienplan_id - AND tbl_studienplan_semester.studiensemester_kurzbz=tbl_reihungstest.studiensemester_kurzbz + EXISTS ( + SELECT studienplan_id + FROM lehre.tbl_studienordnung sordnung + JOIN lehre.tbl_studienplan USING (studienordnung_id) + JOIN lehre.tbl_studienplan_semester USING (studienplan_id) + WHERE sordnung.studiengang_kz = tbl_studienordnung.studiengang_kz + AND tbl_studienplan_semester.studiensemester_kurzbz = tbl_reihungstest.studiensemester_kurzbz + AND tbl_studienplan.studienplan_id NOT IN + ( + SELECT studienplan_id FROM tbl_rt_studienplan WHERE reihungstest_id = tbl_reihungstest.reihungstest_id + ) ) - AND tbl_reihungstest.datum >= now() - AND NOT EXISTS( - SELECT - 1 - FROM - public.tbl_rt_studienplan rtstp - JOIN lehre.tbl_studienplan stp USING(studienplan_id) - JOIN lehre.tbl_studienordnung sto USING(studienordnung_id) - JOIN lehre.tbl_studienplan_semester stpsem USING(studienplan_id) - WHERE - sto.studiengang_kz=tbl_studienordnung.studiengang_kz - AND rtstp.reihungstest_id=tbl_reihungstest.reihungstest_id - AND stpsem.studiensemester_kurzbz=tbl_reihungstest.studiensemester_kurzbz - ) - "; + AND tbl_reihungstest.datum >= now()"; $db = new DB_Model(); $result_rt = $db->execReadOnlyQuery($qry); @@ -766,7 +760,9 @@ class ReihungstestJob extends JOB_Controller // find an active studyplan for the same degree program with is valid in this semester $result_stpl = $this->StudienplanModel->getStudienplaeneBySemester( $row_rt->studiengang_kz, - $row_rt->studiensemester_kurzbz + $row_rt->studiensemester_kurzbz, + null, + $row_rt->orgform_kurzbz ); if (hasData($result_stpl)) { @@ -1027,7 +1023,7 @@ class ReihungstestJob extends JOB_Controller { $studiengang = $this->StudiengangModel->load($stg); $mailcontent = ''; - + $content = false; foreach ($orgform AS $art=>$value) { // Orgform nur dazu schreiben, wenn es mehr als Eine gibt @@ -1048,6 +1044,7 @@ class ReihungstestJob extends JOB_Controller $mailcontent .= ''.$bewerber.''; } $mailcontent .= '

'; + $content = true; } if (isset($value['AufnahmeHoeherePrio']) && !isEmptyArray($value['AufnahmeHoeherePrio'])) { @@ -1062,6 +1059,7 @@ class ReihungstestJob extends JOB_Controller $mailcontent .= ''.$bewerber.''; } $mailcontent .= ''; + $content = true; } if (isset($value['AbgewiesenHoeherePrio']) && !isEmptyArray($value['AbgewiesenHoeherePrio'])) { @@ -1075,6 +1073,7 @@ class ReihungstestJob extends JOB_Controller $mailcontent .= ''.$bewerber.''; } $mailcontent .= ''; + $content = true; } if ($bcc != '' && isset($value['AbgewiesenWeilBewerber']) && !isEmptyArray($value['AbgewiesenWeilBewerber'])) { @@ -1089,13 +1088,14 @@ class ReihungstestJob extends JOB_Controller $mailcontent .= ''.$bewerber.''; } $mailcontent .= ''; + $content = true; } } $mailcontent_data_arr['table'] = $mailcontent; // Send email in Sancho design - if (!isEmptyString($mailcontent)) + if (!isEmptyString($mailcontent) && $content === true) { sendSanchoMail( 'Sancho_ReihungstestteilnehmerJob', diff --git a/application/controllers/jobs/schedulers/ESIScheduler.php b/application/controllers/jobs/schedulers/ESIScheduler.php new file mode 100644 index 000000000..3ab858937 --- /dev/null +++ b/application/controllers/jobs/schedulers/ESIScheduler.php @@ -0,0 +1,108 @@ +load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Creates jobs queue entries for generateESI job. + * @param string $studiensemester_kurzbz semester for which ESIs should be generated + */ + public function generateESI($studiensemester_kurzbz = null) + { + // if no semester given, get current studiensemester + if (!isset($studiensemester_kurzbz)) + { + $semRes = $this->StudiensemesterModel->getAkt(); + + if (hasData($semRes)) + { + $studiensemester_kurzbz = getData($semRes)[0]->studiensemester_kurzbz; + } + } + + if (isset($studiensemester_kurzbz)) + { + $this->logInfo('Start job queue scheduler '.self::JOB_TYPE_GENERATE_ESI); + + $qry = " + SELECT + DISTINCT person_id + FROM + public.tbl_person pers + JOIN public.tbl_prestudent ps USING (person_id) + JOIN public.tbl_prestudentstatus pss USING (prestudent_id) + WHERE + pss.studiensemester_kurzbz = ? + AND pers.matr_nr IS NOT NULL + AND pss.status_kurzbz IN ? + AND NOT EXISTS ( -- has no ESI yet + SELECT 1 + FROM + public.tbl_kennzeichen + WHERE + person_id = pers.person_id + AND kennzeichentyp_kurzbz = ? + AND aktiv + ) + AND NOT EXISTS ( -- making sure it's not an incoming + SELECT 1 + FROM + public.tbl_prestudentstatus + WHERE + prestudent_id = ps.prestudent_id + AND status_kurzbz = 'Incoming' + )"; + + $db = new DB_Model(); + $jobInputResult = $db->execReadOnlyQuery($qry, array($studiensemester_kurzbz, $this->_active_status_kurzbz, self::KENNZEICHENTYP_KURZBZ)); + + // If an error occured then log it + if (isError($jobInputResult)) + { + $this->logError(getError($jobInputResult)); + } + elseif (hasData($jobInputResult)) // if persons found + { + // Add the new job to the jobs queue + $addNewJobResult = $this->addNewJobsToQueue( + self::JOB_TYPE_GENERATE_ESI, // job type + $this->generateJobs( // gnerate the structure of the new job + JobsQueueLib::STATUS_NEW, + json_encode(getData($jobInputResult)) + ) + ); + + // If error occurred return it + if (isError($addNewJobResult)) $this->logError(getError($addNewJobResult)); + } + } + else + { + $this->logError('Error when getting Studiensemester'); + } + + $this->logInfo('End job queue scheduler '.self::JOB_TYPE_GENERATE_ESI); + } +} diff --git a/application/controllers/jobs/vertragsbestandteil_test/VertragsbestandteilTest.php b/application/controllers/jobs/vertragsbestandteil_test/VertragsbestandteilTest.php new file mode 100644 index 000000000..d22ddb85f --- /dev/null +++ b/application/controllers/jobs/vertragsbestandteil_test/VertragsbestandteilTest.php @@ -0,0 +1,114 @@ +load->library('vertragsbestandteil/VertragsbestandteilLib', + null, 'VertragsbestandteilLib'); + $this->load->library('vertragsbestandteil/GehaltsbestandteilLib', + null, 'GehaltsbestandteilLib'); + } + + public function testFetch() + { + $dienstverhaeltnis_id = 1; + $stichtag = null; + + foreach($this->VertragsbestandteilLib->fetchVertragsbestandteile( + $dienstverhaeltnis_id, $stichtag) as $vertragsbestandteil) + { + //print_r($vertragsbestandteil); + echo $vertragsbestandteil . "\n"; + } + } + + public function testUpdate() + { + $now = new DateTime(); + + $data = new stdClass(); + $data->vertragsbestandteil_id = 32; + $data->von = '2022-12-05'; + + $data->wochenstunden = 45.0; + $data->vertragsbestandteiltyp_kurzbz = VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_STUNDEN; + + $vb = VertragsbestandteilFactory::getVertragsbestandteil($data); + + try + { + $this->VertragsbestandteilLib->storeVertragsbestandteil($vb); + echo "Update successful.\n"; + } + catch( Exception $ex ) + { + echo "Update failed.\n"; + } + } + + + public function testInsert() + { + $now = new DateTime(); + + $data = new stdClass(); + $data->dienstverhaeltnis_id = 1; + $data->von = '2022-12-01'; + $data->insertamum = $now->format(DateTime::ATOM); + $data->insertvon = 'ma0080'; + $data->vertragsbestandteiltyp_kurzbz = VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FUNKTION; + + $data->benutzerfunktion_id = 112667; + $data->anmerkung = 'test funkton'; + $data->kuendigungsrelevant = false; + + $vb = VertragsbestandteilFactory::getVertragsbestandteil($data); + + try + { + $this->VertragsbestandteilLib->storeVertragsbestandteil($vb); + echo "Insert successful.\n"; + } + catch( Exception $ex ) + { + echo "Insert failed.\n"; + } + } + + public function testGehaltsbestandteilInsert() + { + $data = new stdClass(); + $data->gehaltsbestandteil_id = 2; + /* + $data->dienstverhaeltnis_id = 39; + $data->vertragsbestandteil_id = 123; + $data->gehaltstyp_kurzbz = 'zulage'; + $data->von = '2023-04-01'; + $data->bis = '2023-08-31'; + $data->anmerkung = 'test anmerkung'; + $data->grundbetrag = 100; + $data->betrag_valorisiert = 100; + $data->valorisierung = true; + */ + $data->auszahlungen = 12; + + $gb = new \vertragsbestandteil\Gehaltsbestandteil(); + $gb->hydrateByStdClass($data); + + print_r($gb->toStdClass()); + + $this->GehaltsbestandteilLib->storeGehaltsbestandteil($gb); + } +} diff --git a/application/controllers/lehre/Antrag/Attachment.php b/application/controllers/lehre/Antrag/Attachment.php new file mode 100644 index 000000000..073a03df0 --- /dev/null +++ b/application/controllers/lehre/Antrag/Attachment.php @@ -0,0 +1,82 @@ +load->model('education/Studierendenantrag_model', 'StudierendenantragModel'); + + $this->load->library('DmsLib'); + $this->load->library('AuthLib'); + $this->load->library('PermissionLib'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @param integer $dms_id + * + * @return void + */ + public function show($dms_id) + { + $result = $this->StudierendenantragModel->loadWhere(['dms_id' => $dms_id]); + if (!getData($result)) + return show_404(); + + if (!$this->permissionlib->isBerechtigt('student/antragfreigabe')) + { + $isSamePerson = false; + $antraege = getData($result); + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + foreach ($antraege as $antrag) + { + $prestudent = $this->PrestudentModel->load($antrag->prestudent_id); + if(hasData($prestudent)) + { + if(current(getData($prestudent))->person_id == getAuthPersonId()) + { + $isSamePerson = true; + break; + } + } + } + + if ($isSamePerson == false) + { + $this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN); // set the HTTP header as unauthorized + + $this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output + + // Prints the main error message + $this->eprintflib->printError('You are not allowed to access to this content'); + // Prints the called controller name + $this->eprintflib->printInfo('Controller name: '.$this->router->class); + // Prints the called controller method name + $this->eprintflib->printInfo('Method name: '.$this->router->method); + // Prints the required permissions needed to access to this method + $this->eprintflib->printInfo('Required permissions: student/antragfreigabe'); + + return show_error('You are not entitled to read this document'); + } + } + + $result = $this->dmslib->download($dms_id); + if (isError($result)) + return show_error(getError($result)); + + $this->outputFile(getData($result)); + } +} diff --git a/application/controllers/lehre/Antrag/Wiederholung.php b/application/controllers/lehre/Antrag/Wiederholung.php new file mode 100644 index 000000000..2aa57d733 --- /dev/null +++ b/application/controllers/lehre/Antrag/Wiederholung.php @@ -0,0 +1,48 @@ + 'student/studierendenantrag:w' + ]); + + $this->load->library('AntragLib'); + + // Load language phrases + $this->loadPhrases([ + 'studierendenantrag' + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + public function assistenz($antrag_id) + { + + $result = $this->antraglib->getDetailsForAntrag($antrag_id); + + if (isError($result)) + return show_error(getError($result)); + + if (!hasData($result)) + return show_404(); + + $this->load->view('lehre/Antrag/Wiederholung/Student', [ + 'antrag_id' => $antrag_id, + 'antrag' => getData($result) + ]); + } +} diff --git a/application/controllers/lehre/Studierendenantrag.php b/application/controllers/lehre/Studierendenantrag.php new file mode 100644 index 000000000..107c9af96 --- /dev/null +++ b/application/controllers/lehre/Studierendenantrag.php @@ -0,0 +1,190 @@ +load->library('AuthLib'); + $this->load->library('AntragLib'); + + // Load Models + $this->load->model('education/Studierendenantrag_model', 'StudierendenantragModel'); + $this->load->model('person/Person_model', 'PersonModel'); + + // Load language phrases + $this->loadPhrases([ + 'studierendenantrag' + ]); + + if (strtolower($this->router->method) === 'leitung') + $this->_isAllowed([ + 'leitung' => ['student/studierendenantrag:r', 'student/antragfreigabe:r'] + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + public function index() + { + $dataAntrag = $this->StudierendenantragModel->loadForPerson(getAuthPersonId()); + if (isError($dataAntrag)) + return show_error(getError($dataAntrag)); + $dataAntrag = (getData($dataAntrag) ? : []); + $prestudentenArr = array(); + + foreach ($dataAntrag as $antrag) + { + if (!isset($prestudentenArr[$antrag->prestudent_id])) + { + $prestudentenArr[$antrag->prestudent_id] = array( + 'allowedNewTypes' => array(), + 'antraege'=> array(), + 'bezeichnungStg' => $antrag->bezeichnung, + 'bezeichnungOrgform' => $antrag->orgform + ); + + $result = $this->antraglib->getPrestudentWiederholungsBerechtigt($antrag->prestudent_id); + if (getData($result) == 1) + $prestudentenArr[$antrag->prestudent_id]['allowedNewTypes'][] = 'Wiederholung'; + + $result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($antrag->prestudent_id); + if (getData($result) == 1) + $prestudentenArr[$antrag->prestudent_id]['allowedNewTypes'][] = 'Unterbrechung'; + + $result = $this->antraglib->getPrestudentAbmeldeBerechtigt($antrag->prestudent_id); + if (getData($result) == 1) + $prestudentenArr[$antrag->prestudent_id]['allowedNewTypes'][] = 'Abmeldung'; + } + if ($antrag->studierendenantrag_id == null) + continue; + if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL && (!$antrag->isapproved)) + continue; + + $prestudentenArr[$antrag->prestudent_id]['antraege'][] = $antrag; + } + + $this->load->view('lehre/Antrag/Student/List', [ + 'antraege' => $prestudentenArr + ]); + } + + public function leitung() + { + $stgL = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe') ?: []; + + $stgA = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag') ?: []; + + $this->load->view('lehre/Antrag/Leitung/List', [ + 'stgA' => $stgA, + 'stgL' => $stgL + ]); + } + + public function abmeldung($prestudent_id, $studierendenantrag_id = null) + { + $this->load->view('lehre/Antrag/Create', [ + 'prestudent_id' => $prestudent_id, + 'studierendenantrag_id' => $studierendenantrag_id, + 'antrag_type' => 'Abmeldung' + ]); + } + + public function abmeldungstgl($prestudent_id, $studierendenantrag_id = null) + { + + $this->load->view('lehre/Antrag/Create', [ + 'prestudent_id' => $prestudent_id, + 'studierendenantrag_id' => $studierendenantrag_id, + 'antrag_type' => 'AbmeldungStgl' + ]); + } + + public function unterbrechung($prestudent_id, $studierendenantrag_id = null) + { + $this->load->view('lehre/Antrag/Create', [ + 'prestudent_id' => $prestudent_id, + 'studierendenantrag_id' => $studierendenantrag_id, + 'antrag_type' => 'Unterbrechung' + ]); + } + + public function wiederholung($prestudent_id, $studierendenantrag_id = null) + { + $this->load->view('lehre/Antrag/Create', [ + 'prestudent_id' => $prestudent_id, + 'studierendenantrag_id' => $studierendenantrag_id, + 'antrag_type' => 'Wiederholung' + ]); + } + + /** + * Checks if the caller is allowed to access to this content with the given permissions + * If it is not allowed will set the HTTP header with code 401 + * Wrapper for permissionlib->isEntitled + */ + private function _isAllowed($requiredPermissions) + { + // Loads permission lib + $this->load->library('PermissionLib'); + + // Checks if this user is entitled to access to this content + if (!$this->permissionlib->isEntitled($requiredPermissions, $this->router->method)) + { + $this->output->set_status_header(REST_Controller::HTTP_UNAUTHORIZED); // set the HTTP header as unauthorized + + $this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output + + // Prints the main error message + $this->eprintflib->printError('You are not allowed to access to this content'); + // Prints the called controller name + $this->eprintflib->printInfo('Controller name: '.$this->router->class); + // Prints the called controller method name + $this->eprintflib->printInfo('Method name: '.$this->router->method); + // Prints the required permissions needed to access to this method + $this->eprintflib->printInfo('Required permissions: '.$this->_rpsToString($requiredPermissions, $this->router->method)); + + exit; // immediately terminate the execution + } + } + + /** + * Converts an array of permissions to a string that contains them as a comma separated list + * Ex: ", , " + */ + private function _rpsToString($requiredPermissions, $method) + { + $strRequiredPermissions = ''; // string that contains all the required permissions needed to access to this method + + if (isset($requiredPermissions[$method])) // if the called method is present in the permissions array + { + // If it is NOT then convert it into an array + $rpsMethod = $requiredPermissions[$method]; + if (!is_array($rpsMethod)) + { + $rpsMethod = array($rpsMethod); + } + + // Copy all the permissions into $strRequiredPermissions separated by a comma + for ($i = 0; $i < count($rpsMethod); $i++) + { + $strRequiredPermissions .= $rpsMethod[$i].', '; + } + + $strRequiredPermissions = rtrim($strRequiredPermissions, ', '); + } + + return $strRequiredPermissions; + } +} \ No newline at end of file diff --git a/application/controllers/lehre/anrechnung/RequestAnrechnung.php b/application/controllers/lehre/anrechnung/RequestAnrechnung.php index 1922bacda..ebc272e3e 100644 --- a/application/controllers/lehre/anrechnung/RequestAnrechnung.php +++ b/application/controllers/lehre/anrechnung/RequestAnrechnung.php @@ -111,8 +111,13 @@ class requestAnrechnung extends Auth_Controller $lehrveranstaltung_id = $this->input->post('lv_id'); $studiensemester_kurzbz = $this->input->post('studiensemester'); $bestaetigung = $this->input->post('bestaetigung'); - $begruendung_ects = $this->input->post('begruendung_ects'); - $begruendung_lvinhalt = $this->input->post('begruendung_lvinhalt'); + $begruendung_ects = $this->config->item('explain_equivalence') === TRUE + ? $this->input->post('begruendung_ects') + : NULL; + $begruendung_lvinhalt = $this->config->item('explain_equivalence') === TRUE + ? $this->input->post('begruendung_lvinhalt') + : NULL; + // Validate data if (empty($_FILES['uploadfile']['name'])) @@ -124,8 +129,8 @@ class requestAnrechnung extends Auth_Controller isEmptyString($anmerkung) || isEmptyString($lehrveranstaltung_id) || isEmptyString($studiensemester_kurzbz) || - isEmptyString($begruendung_ects) || - isEmptyString($begruendung_lvinhalt)) + ($this->config->item('explain_equivalence') === TRUE && isEmptyString($begruendung_ects)) || + ($this->config->item('explain_equivalence') === TRUE && isEmptyString($begruendung_lvinhalt))) { return $this->outputJsonError($this->p->t('ui', 'errorFelderFehlen')); } @@ -152,10 +157,10 @@ class requestAnrechnung extends Auth_Controller return $this->outputJsonError($this->p->t('anrechnung', 'antragBereitsGestellt')); } - // Exit if application is not for actual studysemester - if (!self::_applicationIsForActualSS($studiensemester_kurzbz)) + // Exit if application is a past ( < actual ) studysemester + if (self::_applicationIsPastSS($studiensemester_kurzbz)) { - return $this->outputJsonError($this->p->t('anrechnung', 'antragNurImAktSS')); + return $this->outputJsonError($this->p->t('anrechnung', 'antragNichtFuerVerganganeSS')); } // Upload document @@ -168,7 +173,7 @@ class requestAnrechnung extends Auth_Controller // Hold just inserted DMS ID $lastInsert_dms_id = $result->retval['dms_id']; - + // Save Anrechnung and Anrechnungstatus $result = $this->AnrechnungModel->createAnrechnungsantrag( $prestudent_id, @@ -312,18 +317,21 @@ class requestAnrechnung extends Auth_Controller } /** - * Check if applications' study semester is actual study semester. + * Check if applications' study semester is < actual study semester. * * @param $studiensemester_kurzbz * @return bool */ - private function _applicationIsForActualSS($studiensemester_kurzbz) + private function _applicationIsPastSS($studiensemester_kurzbz) { $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); $result = $this->StudiensemesterModel->getNearest(); - $actual_ss = getData($result)[0]->studiensemester_kurzbz; + $actual_ss = getData($result)[0]; - return $studiensemester_kurzbz == $actual_ss; + $result = $this->StudiensemesterModel->load($studiensemester_kurzbz); + $anrechnung_ss = getData($result)[0]; + + return $anrechnung_ss->ende < $actual_ss->start; } private function _LVhasBlockingGrades($studiensemester_kurzbz, $lehrveranstaltung_id) diff --git a/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php b/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php index 6ac2da887..4abb1c400 100644 --- a/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php +++ b/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php @@ -35,6 +35,7 @@ class LehrauftragAkzeptieren extends Auth_Controller $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); $this->load->model('codex/Bisverwendung_model', 'BisverwendungModel'); $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model', 'DienstverhaeltnisModel'); // Load libraries $this->load->library('WidgetLib'); @@ -94,9 +95,9 @@ class LehrauftragAkzeptieren extends Auth_Controller 'lektor' => true, 'aktiv' => true )); - + $is_external_lector = hasData($result) ? true : false; - + $view_data = array( 'studiensemester_selected' => $studiensemester_kurzbz, 'is_external_lector' => $is_external_lector @@ -207,15 +208,41 @@ class LehrauftragAkzeptieren extends Auth_Controller */ public function checkInkludierteLehre() { - $result = $this->BisverwendungModel->getLast($this->_uid, false); - - if (hasData($result)) + if(defined('DIENSTVERHAELTNIS_SUPPORT') && DIENSTVERHAELTNIS_SUPPORT) { - $this->outputJsonSuccess(!is_null($result->retval[0]->inkludierte_lehre) && $result->retval[0]->inkludierte_lehre != 0); + // Bei neuer Vertragsstruktur wird nur anhand des echten DVs entschieden ob eine Anzeige + // des Stundensatzes erfolgt oder nicht. + $result = $this->DienstverhaeltnisModel->getDVByPersonUID($this->_uid, null, date('Y-m-d')); + + if (hasData($result)) + { + $data = getData($result); + foreach($data as $row) + { + if($row->vertragsart_kurzbz == 'echterdv') + $this->outputJsonSuccess(true); + else + $this->outputJsonSuccess(false); + } + } + else + { + $this->outputJsonError(getError($result)); + } } else { - $this->outputJsonError(getError($result)); + // DEPRECATED + $result = $this->BisverwendungModel->getLast($this->_uid, false); + + if (hasData($result)) + { + $this->outputJsonSuccess(!is_null($result->retval[0]->inkludierte_lehre) && $result->retval[0]->inkludierte_lehre != 0); + } + else + { + $this->outputJsonError(getError($result)); + } } } diff --git a/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php new file mode 100644 index 000000000..b1ab2fe26 --- /dev/null +++ b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php @@ -0,0 +1,45 @@ + 'lehre/lehrveranstaltung:rw', + ) + ); + + // Load libraries + $this->load->library('AuthLib'); + + + // Load language phrases + $this->loadPhrases( + array( + 'global', + 'lehre' + ) + ); + + $this->_setAuthUID(); + } + + public function index() + { + $this->load->view('lehre/lvplanung/lvTemplateUebersicht.php'); + } + + + /** + * Retrieve the UID of the logged user and checks if it is valid + */ + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) show_error('User authentification failed'); + } +} \ No newline at end of file diff --git a/application/controllers/public/js/Components.php b/application/controllers/public/js/Components.php new file mode 100644 index 000000000..830e7ea65 --- /dev/null +++ b/application/controllers/public/js/Components.php @@ -0,0 +1,43 @@ +output->set_content_type('text/javascript'); + $this->output->set_output($contents); + } +} diff --git a/application/controllers/system/MigrateContract.php b/application/controllers/system/MigrateContract.php new file mode 100644 index 000000000..817eaa4f0 --- /dev/null +++ b/application/controllers/system/MigrateContract.php @@ -0,0 +1,759 @@ +load->model('codex/bisverwendung_model', 'BisVerwendungModel'); + $this->load->model('person/benutzerfunktion_model', 'BenutzerfunktionModel'); + + $this->load->config('migratecontract'); + + $this->OE_DEFAULT = $this->config->item('migratecontract_oe_default'); + $this->matching_ba1_vertragsart = $this->config->item('migratecontract_matching_ba1_vertragsart'); + $this->configerrors = array(); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + public function checkConfig() + { + echo "OE_DEFAULT: " . $this->OE_DEFAULT . "\n"; + echo "matching_ba1_vertragsart: " . print_r($this->matching_ba1_vertragsart, true); + + $this->checkOE_DEFAULT(); + $this->checkMatching_ba1_vertragsart(); + + if( count($this->configerrors) > 0 ) + { + foreach($this->configerrors AS $configerror) + { + echo $configerror . "\n"; + } + die("Fehler in der Konfiguration. Abbruch!\n"); + } + else + { + echo "Konfiguration OK.\n"; + } + } + + protected function checkOE_DEFAULT() + { + $db = new DB_Model(); + $oesql = 'SELECT * FROM public.tbl_organisationseinheit WHERE oe_kurzbz = ?'; + $oeres = $db->execReadOnlyQuery($oesql, array($this->OE_DEFAULT)); + if( !hasData($oeres) ) + { + $this->configerrors[] = 'Default Organisationseinheit: "' + . $this->OE_DEFAULT . '" nicht gefunden.'; + } + } + + protected function checkMatching_ba1_vertragsart() { + $db = new DB_Model(); + foreach( $this->matching_ba1_vertragsart AS $vertragsart_kurzbz ) + { + $vasql = 'SELECT * FROM hr.tbl_vertragsart WHERE vertragsart_kurzbz = ?'; + $vares = $db->execReadOnlyQuery($vasql, array($vertragsart_kurzbz)); + if( !hasData($vares) ) + { + $this->configerrors[] = 'Vertragsart "' . $vertragsart_kurzbz + . '" nicht gefunden.'; + } + } + } + + /** + * Everything has a beginning + */ + public function index($user = null) + { + $this->checkConfig(); + + if (!is_null($user)) + { + $contracts = $this->_transformUser($user); + + /* + Format: + $contracts['dv'][]['vbs'][] + */ + //$this->outputJson($contracts); + var_dump($contracts); + $this->_saveJSON($contracts); + } + else + { + $qry = "SELECT distinct mitarbeiter_uid FROM bis.tbl_bisverwendung"; + $db = new DB_Model(); + + $resultUser = $db->execReadOnlyQuery($qry); + if (hasData($resultUser)) + { + $users = getData($resultUser); + foreach($users as $user) + { + $contracts = $this->_transformUser($user->mitarbeiter_uid); + $this->_saveJSON($contracts); + } + } + + } + } + + private function _saveJSON($contracts) + { + $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel'); + $this->load->model('vertragsbestandteil/Vertragsbestandteil_model','VertragsbestandteilModel'); + $this->load->model('vertragsbestandteil/VertragsbestandteilStunden_model','VertragsbestandteilStundenModel'); + $this->load->model('vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model','VertragsbestandteilZeitaufzeichnungModel'); + $this->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model','VertragsbestandteilFreitextModel'); + $this->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model','VertragsbestandteilFunktionModel'); + $this->load->model('vertragsbestandteil/VertragsbestandteilKarenz_model','VertragsbestandteilKarenzModel'); + + $failed = false; + $this->db->trans_begin(); + + foreach($contracts['dv'] as $row_dv) + { + // Dienstvertrag erstellen + $resultDV = $this->DienstverhaeltnisModel->insert( + array( + 'mitarbeiter_uid' => $row_dv['mitarbeiter_uid'], + 'vertragsart_kurzbz' => $row_dv['vertragsart_kurzbz'], + 'oe_kurzbz' => $row_dv['oe_kurzbz'], + 'von' => $row_dv['von'], + 'bis' => $row_dv['bis'], + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => 'MigrateContract' + ) + ); + + if (isSuccess($resultDV) && hasData($resultDV)) + { + $dv_id = getData($resultDV); + + // Vertragsbetandteile erstellen + foreach($row_dv['vbs'] as $row_vbs) + { + $resultVBS = $this->VertragsbestandteilModel->insert( + array( + 'dienstverhaeltnis_id' => $dv_id, + 'vertragsbestandteiltyp_kurzbz' => $row_vbs['vertragsbestandteiltyp_kurzbz'], + 'von' => $row_vbs['von'], + 'bis' => $row_vbs['bis'], + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => 'MigrateContract' + ) + ); + + if (isSuccess($resultVBS) && hasData($resultVBS)) + { + $vbs_id = getData($resultVBS); + echo 'VBS:'.$vbs_id; + + switch($row_vbs['vertragsbestandteiltyp_kurzbz']) + { + case 'stunden': + $resultVBS = $this->_insertVBSStunden($vbs_id, $row_vbs); + break; + case 'zeitaufzeichnung': + $resultVBS = $this->_insertVBSZeitaufzeichnung($vbs_id, $row_vbs); + break; + case 'funktion': + $resultVBS = $this->_insertVBSFunktion($vbs_id, $row_vbs); + break; + case 'freitext': + $resultVBS = $this->_insertVBSFreitext($vbs_id, $row_vbs); + break; + case 'karenz': + $resultVBS = $this->_insertVBSKarenz($vbs_id, $row_vbs); + break; + } + + if (isError($resultVBS)) + { + echo "FAILED:".getError($resultVBS); + $failed = true; + } + } + else + { + $failed = true; + } + } + } + else + { + $failed = true; + } + } + + if(!$failed) + { + $this->db->trans_commit(); + } + else + { + echo "ROLLBACK"; + $this->db->trans_rollback(); + } + } + + private function _insertVBSKarenz($vbs_id, $row_vbs) + { + return $this->VertragsbestandteilKarenzModel->insert( + array( + 'vertragsbestandteil_id' => $vbs_id, + 'karenztyp_kurzbz' => $row_vbs['karenztyp_kurzbz'] + ) + ); + } + + private function _insertVBSFreitext($vbs_id, $row_vbs) + { + return $this->VertragsbestandteilFreitextModel->insert( + array( + 'vertragsbestandteil_id' => $vbs_id, + 'freitexttyp_kurzbz' => $row_vbs['freitexttyp_kurzbz'], + 'titel' => $row_vbs['titel'], + 'anmerkung' => $row_vbs['anmerkung'] + ) + ); + } + + private function _insertVBSFunktion($vbs_id, $row_vbs) + { + return $this->VertragsbestandteilFunktionModel->insert( + array( + 'vertragsbestandteil_id' => $vbs_id, + 'benutzerfunktion_id' => $row_vbs['benutzerfunktion_id'] + ) + ); + } + + private function _insertVBSZeitaufzeichnung($vbs_id, $row_vbs) + { + return $this->VertragsbestandteilZeitaufzeichnungModel->insert( + array( + 'vertragsbestandteil_id' => $vbs_id, + 'zeitaufzeichnung' => $row_vbs['zeitaufzeichnung'], + 'azgrelevant' => $row_vbs['azgrelevant'], + 'homeoffice' => $row_vbs['homeoffice'] + ) + ); + } + + private function _insertVBSStunden($vbs_id, $row_vbs) + { + return $this->VertragsbestandteilStundenModel->insert( + array( + 'vertragsbestandteil_id' => $vbs_id, + 'wochenstunden' => $row_vbs['wochenstunden'], + 'teilzeittyp_kurzbz' => $row_vbs['teilzeittyp_kurzbz'] + ) + ); + } + + /** + * Ermittelt die neue Vertragsstruktur fuer einen User + */ + private function _transformUser($user) + { + $contracts = array(); + $this->BisVerwendungModel->addOrder('beginn'); + $result_verwendung = $this->BisVerwendungModel->loadWhere(array("mitarbeiter_uid" => $user)); + + if (isError($result_verwendung)) + die("Failed to load Verwendung"); + + if (hasData($result_verwendung)) + { + $verwendung = getData($result_verwendung); + + foreach ($verwendung as $row_verwendung) + { + $dv = $this->_getOrCreateDV($contracts, $row_verwendung); + + // Ende des DV aktualisieren + if ($contracts['dv'][$dv]['bis'] < $row_verwendung->ende || $row_verwendung->ende == '') + $contracts['dv'][$dv]['bis'] = $row_verwendung->ende; + + // Stundenbestandteil pruefen + $this->_addVertragsbestandteilStunden($contracts, $dv, $row_verwendung); + + // Befristung + $this->_addVertragsbestandteilFreitextBefristung($contracts, $dv, $row_verwendung); + + // All-In + $this->_addVertragsbestandteilFreitextAllIn($contracts, $dv, $row_verwendung); + + // Zeitaufzeichnung + $this->_addVertragsbestandteilZeitaufzeichnung($contracts, $dv, $row_verwendung); + + // Karenz + $this->_addVertragsbestandteilKarenz($contracts, $dv, $row_verwendung); + + // Inkludierte Lehre + // Kuendigungsfrist + // Urlaubsanspruch + } + + // Funktion + $this->_addVertragsbestandteilFunktion($contracts, $user); + + } + + return $contracts; + } + + /** + * Fuegt Karenzierungseintraege zu bestehenden Dienstverhaeltnissen hinzu + */ + private function _addVertragsbestandteilKarenz(&$contracts, $dv, $row_verwendung) + { + if ($row_verwendung->beschausmasscode == 5) + { + $dtstart = new DateTime($row_verwendung->beginn); + $dtende = new DateTime($row_verwendung->ende); + $interval = $dtende->diff($dtstart); + $dauer = $interval->format('%a'); + + // TODO: klären ob das so machbar ist + if ($dauer < 65) + $karenztyp = 'papamonat'; + elseif ($dauer < 120) + $karenztyp = 'bildungskarenz'; + else + $karenztyp = 'elternkarenz'; + + // VBS anlegen und Funktion zuweisen + $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv); + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'karenz'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['karenztyp_kurzbz'] = $karenztyp; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['geplanter_geburtstermin'] = null; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['tatsaechlicher_geburtstermin'] = null; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['hint'] = 'Dauer:'.$dauer; + } + } + + /** + * Holt die Funktionen die Vertragsrelevant sind und verknüpft diese + */ + private function _addVertragsbestandteilFunktion(&$contracts, $user) + { + // Alle Funktionen holen die Vertragsrelevant sind + $this->BenutzerfunktionModel->addOrder('datum_von'); + $this->BenutzerfunktionModel->addJoin('public.tbl_funktion','funktion_kurzbz'); + $resultFunktionen = $this->BenutzerfunktionModel->loadWhere(array('uid' => $user, 'vertragsrelevant' => true)); + + if (isSuccess($resultFunktionen) && hasData($resultFunktionen)) + { + $funktionen = getData($resultFunktionen); + + foreach ($funktionen as $row_funktion) + { + $funktion_added = 0; + $dv = ''; + + // Passendes DV suchen + foreach ($contracts['dv'] as $key_dv => $row_contract) + { + // Eine Funktion kann zu mehreren DV zugeordnet sein + // es werden daher alle durchsucht ob es reinfaellt und ggf mehrfach zugeordnet + if ((isset($row_funktion->datum_von) && $row_funktion->datum_von >= $row_contract['von']) + && ($row_contract['bis'] == '' || $row_contract['bis'] >= $row_funktion->datum_von) + && ( + ( + isset($row_funktion->datum_bis) && isset($row_contract['bis']) + && $row_funktion->datum_bis <= $row_contract['bis'] + ) + || $row_funktion->datum_bis == '' + || (isset($row_funktion->datum_bis) && !isset($row_contract['bis'])) + ) + ) + { + + $dv = $key_dv; + + // Startdatum und Endedatum ermitteln wenn die Funktion ueber das DV hinausgeht + // Wenn die Dauer laenger ist, wird beim Beginn/Ende des DV abgegrenzt + $dtstart_fkt = new DateTime($row_funktion->datum_von); + $dtstart_dv = new DateTime($row_contract['von']); + if ($dtstart_fkt < $dtstart_dv) + $startdatum = $row_contract['von']; + else + $startdatum = $row_funktion->datum_von; + + $dtende_fkt = new DateTime($row_funktion->datum_bis); + $dtende_dv = new DateTime($row_contract['bis']); + if ($dtende_fkt < $dtende_dv) + $endedatum = $row_funktion->datum_bis; + else + $endedatum = $row_contract['bis']; + + // VBS anlegen und Funktion zuweisen + $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv); + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'funktion'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $startdatum; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $endedatum; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['benutzerfunktion_id'] = $row_funktion->benutzerfunktion_id; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['hint'] = $row_funktion->funktion_kurzbz.' '.$row_funktion->datum_von.' - '.$row_funktion->datum_bis; + $funktion_added++; + } + } + if ($funktion_added == 0) + { + echo "\nFunktion nicht zugeordnet: ".$row_funktion->funktion_kurzbz.' '.$row_funktion->datum_von.' - '.$row_funktion->datum_bis; + } + } + } + } + + /** + * Prueft ob schon ein Vertragsbestandteil fuer Zeitaufzeichnung vorhanden ist das in den Zeitraum passt + * bzw direkt anschließt. Wenn es direkt anschließend ist und die Art gleich sind wird die Laufzeit verlaengert + * Ansonsten wird ein neuer VBS angelegt + */ + private function _addVertragsbestandteilZeitaufzeichnung(&$contracts, $dv, $row_verwendung) + { + if( is_null($row_verwendung->zeitaufzeichnungspflichtig) || is_null($row_verwendung->azgrelevant) ) + { + return; + } + + if (isset($contracts['dv'][$dv]['vbs'])) + { + foreach ($contracts['dv'][$dv]['vbs'] as $index_vbs=>$row_vbs) + { + if ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'zeitaufzeichnung') + { + if ($this->_isVBSAngrenzend($row_verwendung, $row_vbs) + && $row_vbs['zeitaufzeichnung'] == $row_verwendung->zeitaufzeichnungspflichtig + && $row_vbs['azgrelevant'] == $row_verwendung->azgrelevant + && $row_vbs['homeoffice'] == $row_verwendung->homeoffice + ) + { + // Zeitaufzeichnungsarten bleiben gleich - Ende des VBS verlaengern + $contracts['dv'][$dv]['vbs'][$index_vbs]['bis'] = $row_verwendung->ende; + return true; + } + } + } + } + + // kein passender VBS gefunden - neuen anlegen + $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv); + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'zeitaufzeichnung'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['zeitaufzeichnung'] = $row_verwendung->zeitaufzeichnungspflichtig; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['azgrelevant'] = $row_verwendung->azgrelevant; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['homeoffice'] = $row_verwendung->homeoffice; + + return true; + } + + /** + * Fueg einen Freitextbestandteil fuer All-In zum DV hinzu + */ + private function _addVertragsbestandteilFreitextAllIn(&$contracts, $dv, $row_verwendung) + { + if ($row_verwendung->ba1code == 111) // All-In + { + $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv); + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'freitext'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['freitexttyp_kurzbz'] = 'allin'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['titel'] = 'allin'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['anmerkung'] = 'allin'; + } + return true; + } + + /** + * Fueg einen Freitextbestandteil fuer die Berfristung zum DV hinzu + */ + private function _addVertragsbestandteilFreitextBefristung(&$contracts, $dv, $row_verwendung) + { + if ($row_verwendung->ba2code == 1) // Befristung + { + $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv); + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'freitext'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['freitexttyp_kurzbz'] = 'befristung'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['titel'] = 'befristung'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['anmerkung'] = 'befristung'; + } + return true; + } + + /** + * Prueft ob schon ein Vertragsbestandteil mit diesem Stundenausmass vorhanden ist das in den Zeitraum passt + * bzw direkt anschließt. Wenn es direkt anschließend ist und die Stunden gleich sind wird die Laufzeit verlaengert + * Ansonsten wird ein neuer VBS angelegt + */ + private function _addVertragsbestandteilStunden(&$contracts, $dv, $row_verwendung) + { + // Nur anlegen wenn im aktuellen Eintrag auch Stunden eingetragen sind + if ($row_verwendung->vertragsstunden != '') + { + if (isset($contracts['dv'][$dv]['vbs'])) + { + foreach ($contracts['dv'][$dv]['vbs'] as $index_vbs=>$row_vbs) + { + if ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'stunden' || ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'karenz' && $row_verwendung->vertragsstunden === '0.00')) + { + if ($this->_isVBSAngrenzend($row_verwendung, $row_vbs) && ((isset($row_vbs['wochenstunden']) && $row_vbs['wochenstunden'] == $row_verwendung->vertragsstunden) || $row_verwendung->vertragsstunden === '0.00')) + { + // stunden bleiben gleich - Ende des VBS verlaengern + $contracts['dv'][$dv]['vbs'][$index_vbs]['bis'] = $row_verwendung->ende; + return true; + } + } + } + } + + // kein passender VBS gefunden - neuen anlegen + $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv); + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'stunden'; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['wochenstunden'] = $row_verwendung->vertragsstunden; + $contracts['dv'][$dv]['vbs'][$newVBSIndex]['teilzeittyp_kurzbz'] = null; + } + return true; + } + + /** + * Prueft ob die Verwendung direkt an den Vertragsbestandteil angrenzt + * @return boolean true wenn ja, sonst false + */ + private function _isVBSAngrenzend($verwendung, $vbs) + { + // Beginn Minus 1 Tag + $dtstart = new DateTime($verwendung->beginn); + $dtstartMinus1 = $dtstart->sub(new DateInterval('P1D'))->format('Y-m-d'); + + if ($vbs['bis'] == '' + || $vbs['bis'] == $dtstartMinus1) + { + return true; + } + + return false; + } + + /** + * Create a new DV or Returns the Index of an existing + */ + private function _getOrCreateDV(&$contracts, $row_verwendung) + { + $unternehmen = $this->OE_DEFAULT; + $resultUnternehmen = $this->_getUnternehmen($row_verwendung); + if(hasData($resultUnternehmen)) + { + $unternehmen = getData($resultUnternehmen)[0]->oe_kurzbz; + } + else + { + // Fallback Unternehmen wird verwendet falls keine Zuordnung ermittelt werden kann + } + + if (isset($contracts['dv']) && is_array($contracts['dv'])) + { + foreach($contracts['dv'] as $indexdv => $row_dv) + { + // Vertragsart ist die selbe und selbes Unternehmen + if ($row_dv['vertragsart_kurzbz'] == $this->matching_ba1_vertragsart[$row_verwendung->ba1code] + && $row_dv['oe_kurzbz'] == $unternehmen + ) + { + + $dtstart = new DateTime($row_verwendung->beginn); + + // Zeitraum passt zur Verwendung + if ($row_dv['von'] <= $row_verwendung->beginn // Beginn Datum Pruefen + && ( // Ende innerhalb des DV + (isset($row_dv['bis']) && $row_verwendung->ende != '' && ($row_dv['bis'] == '' || $row_dv['bis'] >= $row_verwendung->ende) + ) + || // direkt angrenzend an dieses DV + (isset($row_dv['bis']) + && ($row_dv['bis'] == '' + || $row_dv['bis'] == $dtstart->sub(new DateInterval('P1D'))->format('Y-m-d') + ) + ) + ) + ) + { + return $indexdv; + } + } + } + } + + $newDvIndex = $this->_getNewDVIndex($contracts); + $contracts['dv'][$newDvIndex]['mitarbeiter_uid'] = $row_verwendung->mitarbeiter_uid; + $contracts['dv'][$newDvIndex]['von'] = $row_verwendung->beginn; + $contracts['dv'][$newDvIndex]['bis'] = $row_verwendung->ende; + $contracts['dv'][$newDvIndex]['oe_kurzbz'] = $unternehmen; + $contracts['dv'][$newDvIndex]['vertragsart_kurzbz'] = $this->matching_ba1_vertragsart[$row_verwendung->ba1code]; + + return $newDvIndex; + } + + /** + * Ermittelt in welchem Unternehmen die Person zum betreffenden Zeitpunkt ist. + */ + private function _getUnternehmen($row_verwendung) + { + + $resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung'", $row_verwendung->beginn); + + // Wenn zeitlich keine passende Unternehmenszuordnung vorhanden ist, dann suchen ob generell eine Zuordnung ermittelt werden kann + if(!hasData($resultUnternehmen)) + { + $resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung'"); + + // Falls nicht wird nach erweiterten Funktionen gesucht um die Zuordnung zu ermitteln. + if(!hasData($resultUnternehmen)) + { + $resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung','hilfskraft','Leitung','fbk','fbl'"); + } + } + + return $resultUnternehmen; + } + + /** + * Detailsuche fuer die Ermittlung des Unternehmenszuordnung einer Person + */ + private function _findUnternehmen($uid, $fkt=null, $datum=null) + { + $db = new DB_Model(); + + $qry = " + WITH RECURSIVE meine_oes(oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz) as + ( + SELECT + oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz + FROM + public.tbl_organisationseinheit + WHERE + oe_kurzbz=(SELECT + oe_kurzbz + FROM + public.tbl_benutzerfunktion + WHERE + uid=".$db->escape($uid); + + if(!is_null($datum)) + $qry.=" AND ".$db->escape($datum)." BETWEEN datum_von AND COALESCE(datum_bis, '2999-12-31')"; + + if(!is_null($fkt)) + $qry.=" AND funktion_kurzbz in ($fkt)"; + + $qry.=" + ORDER BY funktion_kurzbz, datum_von LIMIT 1) + UNION ALL + SELECT + o.oe_kurzbz, o.oe_parent_kurzbz, o.organisationseinheittyp_kurzbz + FROM + public.tbl_organisationseinheit o, meine_oes + WHERE + o.oe_kurzbz=meine_oes.oe_parent_kurzbz + ) + SELECT + oe_kurzbz + FROM + meine_oes + WHERE + oe_parent_kurzbz is null + LIMIT 1 + "; + + $resultUnternehmen = $db->execReadOnlyQuery($qry); + return $resultUnternehmen; + } + + /** + * Ermittelt den nächsten (freien) Index für den Vertragsbetandteil + */ + private function _getNewVBSIndex($contracts, $dv) + { + if (isset($contracts['dv'][$dv]['vbs'])) + return max(array_keys($contracts['dv'][$dv]['vbs'])) + 1; + else + return 0; + } + + /** + * Ermittelt den nächsten (freien) Index für das Dienstverhältnis + */ + private function _getNewDVIndex($contracts) + { + if (isset($contracts['dv']) && is_array($contracts['dv'])) + return max(array_keys($contracts['dv'])) + 1; + else + return 0; + } + + /** + * Habilitation wird aus der Tabelle bis.tbl_bisverwendung in die Tabelle public.tbl_mitarbeiter uebernommen + * Sofern die Person einmal in den Verwendungen eine habiliation eingetragen hat wird diese in den MA-Datensatz übernommen + * Da es in der regel öfter vorkommt dass das hakerl vergessen wurde beim Vertragswechsel als dass die person die habiliation verliert. + */ + public function migrateHabilitation() + { + $this->load->model('ressource/Mitarbeiter_model','MitarbeiterModel'); + $db = new DB_Model(); + + $qry = " + SELECT + distinct mitarbeiter_uid + FROM + bis.tbl_bisverwendung + WHERE + habilitation=true"; + + $resultHabilitation = $db->execReadOnlyQuery($qry); + + if (isSuccess($resultHabilitation) && hasData($resultHabilitation)) + { + $habilitationen = getData($resultHabilitation); + + foreach ($habilitationen as $row_habilitationen) + { + $this->MitarbeiterModel->update($row_habilitationen->mitarbeiter_uid, array('habilitation'=>true)); + } + } + } +} diff --git a/application/controllers/system/MigrateHourlyRate.php b/application/controllers/system/MigrateHourlyRate.php new file mode 100644 index 000000000..dbc8f1416 --- /dev/null +++ b/application/controllers/system/MigrateHourlyRate.php @@ -0,0 +1,268 @@ +_ci = & get_instance(); + + $this->load->model('codex/Bisverwendung_model', 'BisVerwendungModel'); + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $this->load->model('ressource/Stundensatz_model', 'StundensatzModel'); + + $this->load->config('migratecontract'); + + $this->OE_DEFAULT = $this->config->item('migratecontract_oe_default'); + $this->configerrors = array(); + } + + public function checkConfig() + { + echo "OE_DEFAULT: " . $this->OE_DEFAULT . "\n"; + + $this->checkOE_DEFAULT(); + + if( count($this->configerrors) > 0 ) + { + foreach($this->configerrors AS $configerror) + { + echo $configerror . "\n"; + } + die("Fehler in der Konfiguration. Abbruch!\n"); + } + else + { + echo "Konfiguration OK.\n"; + } + } + + public function index($user = null) + { + $this->checkConfig(); + + echo "Lehre Stundensaetze werden migriert.\n"; + $mitarbeiterResult = $this->_getMitarbeiterStunden($user); + if (isError($mitarbeiterResult)) return $mitarbeiterResult; + if (!hasData($mitarbeiterResult)) return error('Keine Mitarbeiterstunden gefunden'); + + $mitarbeiterArray = getData($mitarbeiterResult); + + foreach ($mitarbeiterArray as $mitarbeiter) + { + $this->_getUnternehmen($mitarbeiter); + $insertResult = $this->_addStundensatz($mitarbeiter, self::STUNDENSTAZTYP_LEHRE, self::DEFAULT_DATE); + if (isError($insertResult)) return $insertResult; + } + + if( $this->checkIfSAPSyncTableExists() ) + { + echo "SAP Sync Tabelle gefunden. SAP Stundensaetze werden migriert.\n"; + $sapResult = $this->_getSapStunden($user); + if (isError($sapResult)) return $sapResult; + if (!hasData($sapResult)) return error('Keinen kalkulatorischen Stundensaetze gefunden'); + + $mitarbeiterArray = getData($sapResult); + + foreach ($mitarbeiterArray as $mitarbeiter) + { + $this->_getUnternehmen($mitarbeiter); + $insertResult = $this->_addStundensatz($mitarbeiter, self::STUNDENSTAZTYP_KALKULATORISCH, date_format(date_create($mitarbeiter->beginn), 'Y-m-d')); + if (isError($insertResult)) return $insertResult; + } + } + else + { + echo "SAP Sync Tabelle nicht gefunden. Ignoriere SAP Stundensaetze.\n"; + } + } + + protected function checkOE_DEFAULT() + { + $db = new DB_Model(); + $oesql = 'SELECT * FROM public.tbl_organisationseinheit WHERE oe_kurzbz = ?'; + $oeres = $db->execReadOnlyQuery($oesql, array($this->OE_DEFAULT)); + if( !hasData($oeres) ) + { + $this->configerrors[] = 'Default Organisationseinheit: "' + . $this->OE_DEFAULT . '" nicht gefunden.'; + } + } + + protected function checkIfSAPSyncTableExists() + { + $dbModel = new DB_Model(); + $params = array( + DB_NAME, + 'sync', + 'tbl_sap_stundensatz' + ); + + $sql = "SELECT + 1 AS exists + FROM + information_schema.tables + WHERE + table_catalog = ? AND + table_schema = ? AND + table_name = ?"; + + $res = $dbModel->execReadOnlyQuery($sql, $params); + + if( hasData($res) ) + { + return true; + } + else + { + return false; + } + } + + + private function _getSapStunden($user = null) + { + $dbModel = new DB_Model(); + $params = array(); + + $qry = "SELECT ss.mitarbeiter_uid as uid, + ss.sap_kalkulatorischer_stundensatz as stundensatz, + ss.insertamum as beginn + FROM sync.tbl_sap_stundensatz ss + WHERE ss.sap_kalkulatorischer_stundensatz IS NOT NULL"; + + if (!is_null($user)) + { + $qry .= " AND ss.mitarbeiter_uid = ? "; + $params[] = $user; + } + $qry .= " ORDER BY ss.mitarbeiter_uid"; + + return $dbModel->execReadOnlyQuery($qry, $params); + } + + private function _getMitarbeiterStunden($user = null) + { + $dbModel = new DB_Model(); + $params = array(); + + $qry = "SELECT mitarbeiter.mitarbeiter_uid as uid, + stundensatz + FROM public.tbl_mitarbeiter mitarbeiter + WHERE mitarbeiter.stundensatz != 0.00 + AND mitarbeiter.stundensatz IS NOT NULL"; + + if (!is_null($user)) + { + $qry .= " AND mitarbeiter.mitarbeiter_uid = ?"; + $params[] = $user; + } + + $qry .= " ORDER BY mitarbeiter.mitarbeiter_uid"; + + return $dbModel->execReadOnlyQuery($qry, $params); + } + + private function _addStundensatz($mitarbeiter, $stundensatztyp, $gueltig_von) + { + return $this->_ci->StundensatzModel->insert( + array( + 'uid' => $mitarbeiter->uid, + 'stundensatztyp' => $stundensatztyp, + 'stundensatz' => $mitarbeiter->stundensatz, + 'oe_kurzbz' => $mitarbeiter->unternehmen, + 'gueltig_von' => $gueltig_von, + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => 'MigrateHours' + ) + ); + } + + private function _getUnternehmen(&$mitarbeiter) + { + $bvResult = $this->_ci->BisVerwendungModel->getLast($mitarbeiter->uid); + + $beginn = null; + if (hasData($bvResult)) + { + $beginn = getData($bvResult)[0]->beginn; + } + + $unternehmenResult = $this->_findUnternehmen($mitarbeiter->uid, "'kstzuordnung', 'oezuordnung'", $beginn); + + if(!hasData($unternehmenResult)) //&& hasData($bvResult) + { + $unternehmenResult = $this->_findUnternehmen($mitarbeiter->uid, "'kstzuordnung', 'oezuordnung'"); + } + + $unternehmen = $this->OE_DEFAULT; + + if (hasData($unternehmenResult)) + $unternehmen = getData($unternehmenResult)[0]->oe_kurzbz; + + $mitarbeiter->unternehmen = $unternehmen; + } + + /** + * Detailsuche fuer die Ermittlung des Unternehmenszuordnung einer Person + */ + private function _findUnternehmen($uid, $fkt=null, $datum=null) + { + $dbModel = new DB_Model(); + + $qry = " + WITH RECURSIVE meine_oes(oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz) as + ( + SELECT + oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz + FROM + public.tbl_organisationseinheit + WHERE + oe_kurzbz=(SELECT + oe_kurzbz + FROM + public.tbl_benutzerfunktion + WHERE + uid=".$dbModel->escape($uid); + + if(!is_null($datum)) + $qry.=" AND ".$dbModel->escape($datum)." BETWEEN datum_von AND COALESCE(datum_bis, '2999-12-31')"; + + if(!is_null($fkt)) + $qry.=" AND funktion_kurzbz in ($fkt)"; + + $qry.=" + ORDER BY funktion_kurzbz, datum_von LIMIT 1) + UNION ALL + SELECT + o.oe_kurzbz, o.oe_parent_kurzbz, o.organisationseinheittyp_kurzbz + FROM + public.tbl_organisationseinheit o, meine_oes + WHERE + o.oe_kurzbz=meine_oes.oe_parent_kurzbz + ) + SELECT + oe_kurzbz + FROM + meine_oes + WHERE + oe_parent_kurzbz is null + LIMIT 1 + "; + + return $dbModel->execReadOnlyQuery($qry); + } + +} diff --git a/application/controllers/system/MigrateSalary.php b/application/controllers/system/MigrateSalary.php new file mode 100644 index 000000000..4bd1d3e7d --- /dev/null +++ b/application/controllers/system/MigrateSalary.php @@ -0,0 +1,495 @@ + G + private $INDEX_LOHNART = 4; + private $INDEX_BEZEICHNUNG = 5; + + /** + * Constructor + */ + public function __construct() + { + parent::__construct(); + + $this->load->model('vertragsbestandteil/Gehaltsbestandteil_model', 'GehaltsbestandteilModel'); + $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel'); + $this->load->model('vertragsbestandteil/Vertragsbestandteil_model','VertragsbestandteilModel'); + $this->load->model('vertragsbestandteil/VertragsbestandteilStunden_model','VertragsbestandteilStundenModel'); + $this->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model','VertragsbestandteilFreitextModel'); + $this->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model','VertragsbestandteilFunktionModel'); + + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Everything has a beginning + */ + public function import($file) + { + + // CSV Laden + $file = urldecode($file); + if($handle = fopen($file, "r")) + { + $csvrow = -1; + $lastuser = ''; + $monate = array(); + $gehaltsarr = array(); + $gehaltsindex = 0; + + while (($data = fgetcsv($handle, null, ';')) !== FALSE) + { + $csvrow++; + // Kopfzeile ueberspringen + if($csvrow == 0) + { + for($i = $this->GEHALT_BEGINN_SPALTE; $i < count($data); $i++) + { + $monate[] = $data[$i]; + } + continue; + } + + // User zur SVNR ermitteln + $svnr = str_replace(' ', '',$data[0]); + $resultuser = $this->_getUser($svnr); + + if(!hasData($resultuser)) + { + echo getError($resultuser); + break; + } + + $user = getData($resultuser)[0]->mitarbeiter_uid; + echo "\nUser:".$user; + + if($user != $lastuser && $lastuser != '') + { + $this->_saveGehalt($lastuser, $gehaltsarr); + $gehaltsarr = array(); + $gehaltsindex = 0; + $lastuser = $user; + } + else + { + $lastuser = $user; + } + + // Gehalt Clustern + + $monat = 0; + for ($i = $this->GEHALT_BEGINN_SPALTE; $i < count($data); $i++) + { + if (count($gehaltsarr) == 0 && $data[$i] != '') + { + $gehaltsarr[$gehaltsindex]['betrag'] = $data[$i]; + $gehaltsarr[$gehaltsindex]['lohnart'] = $data[$this->INDEX_LOHNART]; + $gehaltsarr[$gehaltsindex]['bezeichnung'] = $data[$this->INDEX_BEZEICHNUNG]; + $gehaltsarr[$gehaltsindex]['beginn'] = $monate[$monat]; + } + else + { + if ($data[$i] != '' + && isset($gehaltsarr[$gehaltsindex]) && isset($gehaltsarr[$gehaltsindex]['betrag']) + && $gehaltsarr[$gehaltsindex]['betrag'] == $data[$i]) + { + // Gehalt bleibt gleich + } + else + { + if ($data[$i] != '') + { + // Gehalt hat sich geändert + if ($monat != 0 && isset($gehaltsarr[$gehaltsindex])) + $gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1]; + + $gehaltsindex++; + + $gehaltsarr[$gehaltsindex]['betrag'] = $data[$i]; + $gehaltsarr[$gehaltsindex]['lohnart'] = $data[$this->INDEX_LOHNART]; + $gehaltsarr[$gehaltsindex]['bezeichnung'] = $data[$this->INDEX_BEZEICHNUNG]; + $gehaltsarr[$gehaltsindex]['beginn'] = $monate[$monat]; + } + elseif(isset($gehaltsarr[$gehaltsindex])) + { + // Gehalt wurde beendet + if($monat!=0) + $gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1]; + $gehaltsindex++; + } + } + } + + $monat++; + } + + // Zeile zu Ende - Ende Datum setzen wenn nicht für alle Monate ein Eintrag vorhanden ist + if($monat < count($monate) && isset($gehaltsarr[$gehaltsindex])) + $gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1]; + + } + $this->_saveGehalt($lastuser, $gehaltsarr); + } + } + + /** + * Ermittelt das passende Dienstverhaeltnis uns speichert den + * Gehaltsbestandteil + */ + private function _saveGehalt($uid, $gehaltsarr) + { + $failed = false; + $this->db->trans_begin(); + + foreach($gehaltsarr as $row_gehalt) + { + //var_dump($row_gehalt); + $auszahlungen = 14; + $dvid = ''; + $vbsid = ''; + $typ = ''; + $allin = false; + + //DV und VBS Ermitteln + $dv = $this->DienstverhaeltnisModel->getDVByPersonUID($uid, $this->OE_DEFAULT, $row_gehalt['beginn']); + + // Wenn keiner gefunden wird oder mit Monatsersteln nur ein externer gefunden wird, weitersuchen ob im Monat noch ein + // "richtiger" Vertrag startet + if (!hasData($dv) || getData($dv)[0]->vertragsart_kurzbz='externerLehrender') + { + $date = new DateTime($row_gehalt['beginn']); + $date->modify('last day of this month'); + $last_day_this_month = $date->format('Y-m-d'); + + // Wenn mit Monatsersten kein DV gefunden wird, wird stattdessen mit Monatsletzten gesucht um DVs zu finden + // für Personen die erst später im Monat in ihr DV einsteigen + $dv = $this->DienstverhaeltnisModel->getDVByPersonUIDOverlapping($uid, $this->OE_DEFAULT, $row_gehalt['beginn'], $last_day_this_month); + + if (!hasData($dv)) + { + echo "\nKein passendes DV gefunden für User ".$uid." und Datum ".$row_gehalt['beginn']." -> ROLLBACK\n"; + $failed = true; + break; + } + else + { + $resultdata = getData($dv); + foreach($resultdata as $dvdata) + { + // Externer DV wird in Monatsmitte zu echten DV - daher weitersuchen bei externenDVs da + // diese sowieso kein Gehalt zugeordnet haben + if($dvdata->vertragsart_kurzbz != 'externerLehrender') + { + $dvid = $dvdata->dienstverhaeltnis_id; + // Gehaltsstart wird auf den Start des DV korrigiert wenn nicht der Monatserste + // nur wenn das Beginndatum vor dem DV-Start liegt da sonst das Datum korrigiert wird + // wenn der Vertragsbestandteil wechselt + if($row_gehalt['beginn'] < $dvdata->von) + $row_gehalt['beginn'] = $dvdata->von; + break; + } + } + } + } + else + { + $resultdata = getData($dv); + + if (count($resultdata) == 1) + $dvid = $resultdata[0]->dienstverhaeltnis_id; + } + + if ($dvid == '') + { + echo "Kein oder mehrere DVs gefunden -> ROLLBACK"; + $failed = true; + break; + } + + $allin = $this->_isAllIn($dvid, $row_gehalt['beginn']); + + $db = new DB_Model(); + + $resultVBS = $this->_getVBS($dvid, $row_gehalt['beginn']); + + if (hasData($resultVBS)) + { + $vbsid = getData($resultVBS)[0]->vertragsbestandteil_id; + $vbsbis = getData($resultVBS)[0]->bis; + } + else + { + echo "Vertragsbestandteil fuer $uid DV $dvid wurde nicht gefunden mit Beginn ".$row_gehalt['beginn']."-> ROLLBACK"; + $failed = true; + break; + } + + if ($row_gehalt['lohnart'] == 1000) + { + if($allin) + $typ = 'grundgehalt'; + else + $typ = 'basisgehalt'; + } + elseif ($row_gehalt['lohnart']==1041 // 14x + || $row_gehalt['lohnart']==1042 // 12x + || $row_gehalt['lohnart']==3410) // USTDPausch + { + $typ = 'zusatzvereinbarung'; + + // Freitextbestandteil anlegen fuer die Zulage + // Gaehalt wird der Zuglage zugeordnet + + $data = array( + 'dienstverhaeltnis_id' => $dvid, + 'von' => $row_gehalt['beginn'], + 'vertragsbestandteiltyp_kurzbz' => 'freitext', + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => 'MigrateSalary' + ); + if (isset($row_gehalt['ende']) && $row_gehalt['ende']!='') + $data['bis'] = $row_gehalt['ende']; + + $resultVBS = $this->VertragsbestandteilModel->Insert($data); + if(!isSuccess($resultVBS)) + { + echo "VBS kann nicht erstellt werden -> ROLLBACK"; + $failed = true; + break; + } + $vbsid = getData($resultVBS); + + $data = array( + 'vertragsbestandteil_id' => $vbsid, + 'freitexttyp_kurzbz' => 'zusatzvereinbarung', + 'titel' => $row_gehalt['bezeichnung'], + 'anmerkung' => $row_gehalt['bezeichnung'], + ); + $resultVBSFreitext = $this->VertragsbestandteilFreitextModel->Insert($data); + if(!isSuccess($resultVBSFreitext)) + { + echo "VBS Freitext Zusatz kann nicht erstellt werden -> ROLLBACK"; + $failed = true; + break; + } + } + elseif ($row_gehalt['lohnart']==9999) // All-In Custom Lohnart nicht per Default vorhanden + { + $typ = 'zulage'; + + // Freitextbestandteil anlegen fuer die Zulage + // Gaehalt wird der Zuglage zugeordnet + + $data = array( + 'dienstverhaeltnis_id' => $dvid, + 'von' => $row_gehalt['beginn'], + 'vertragsbestandteiltyp_kurzbz' => 'freitext', + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => 'MigrateSalary' + ); + if (isset($row_gehalt['ende']) && $row_gehalt['ende']!='') + $data['bis'] = $row_gehalt['ende']; + + $resultVBS = $this->VertragsbestandteilModel->Insert($data); + if(!isSuccess($resultVBS)) + { + echo "VBS AllIn kann nicht erstellt werden -> ROLLBACK"; + $failed = true; + break; + } + $vbsid = getData($resultVBS); + + $data = array( + 'vertragsbestandteil_id' => $vbsid, + 'freitexttyp_kurzbz' => 'allin', + 'titel' => $row_gehalt['bezeichnung'], + 'anmerkung' => $row_gehalt['bezeichnung'], + ); + $resultVBSFreitext = $this->VertragsbestandteilFreitextModel->Insert($data); + if(!isSuccess($resultVBSFreitext)) + { + echo "VBS Freitext AllIn Zusatz kann nicht erstellt werden -> ROLLBACK"; + $failed = true; + break; + } + } + elseif($row_gehalt['lohnart']==5500) // ATZ + { + $typ = 'lohnausgleichatz'; + } + else + { + $typ = 'unbekannt - '.$row_gehalt['lohnart']; + echo "\nGehaltstyp unbekannt Lohnart: ".$row_gehalt['lohnart']." -> ROLLBACK"; + $failed = true; + break; + } + + // Zulage 12x und Zulage 14x aus der Bezeichnung ermitteln + if(strstr($row_gehalt['bezeichnung'], '12x')) + { + $auszahlungen = 12; + } + + // Format ist 7.777,77 und wird umformattiert in 7777.77 + $betrag = str_replace('.','', $row_gehalt['betrag']); + $betrag = str_replace(',','.',$betrag); + + $data = array( + 'dienstverhaeltnis_id' => $dvid, + 'vertragsbestandteil_id' => $vbsid, + 'gehaltstyp_kurzbz' => $typ, + 'von' => $row_gehalt['beginn'], + 'grundbetrag' => $betrag, + 'betrag_valorisiert' => $betrag, + 'anmerkung' => $row_gehalt['bezeichnung'], + 'valorisierung' => true, + 'auszahlungen' => $auszahlungen, + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => 'MigrateSalary', + 'updateamum' => date('Y-m-d H:i:s'), + 'updatevon' => 'MigrateSalary' + ); + + if (isset($row_gehalt['ende']) && $row_gehalt['ende'] != '') + { + // Im Ende steht noch der Monatserste des letzten Monats + // Das muss geaendert werden auf den Monatsletzten oder das Ende des DVs + $date = new DateTime($row_gehalt['ende']); + $date->modify('last day of this month'); + $last_day_this_month = $date->format('Y-m-d'); + + // Wenn das Dienstverhaeltnis in diesem Monat endet und nicht der Monatsletzte ist, + // dann muss hier das Ende Datum des DV stehen bzw das Ende + // oder das Ende des VBS falls die Person in der Monatsmitte Stunden wechselt + $data['bis'] = $last_day_this_month; + + // Wenn der Vertragsbestandteil endet bevor das Gehalt endet, dann wir das Gehaltsende auf VBS Ende gesetzt + //echo "Ende des VBS: $vbsbis Ende des Gehalt: ".$data['bis']; + if ($vbsbis != '' && $vbsbis < $data['bis']) + { + $data['bis'] = $vbsbis; + //echo "Gehalt auf vbs ende gesetzt"; + } + } + + $ret = $this->GehaltsbestandteilModel->insert($data, + $this->GehaltsbestandteilModel->getEncryptedColumns() + ); + } + + if(!$failed) + { + $this->db->trans_commit(); + } + else + { + echo "ROLLBACK"; + $this->db->trans_rollback(); + } + } + + /** + * Prueft ob ein AllIn Vertrag vorhanden ist + */ + private function _isAllIn($dvid, $datum) + { + $db = new DB_Model(); + + $qry = " + SELECT + * + FROM + hr.tbl_vertragsbestandteil + JOIN hr.tbl_vertragsbestandteil_freitext USING(vertragsbestandteil_id) + WHERE + dienstverhaeltnis_id=".$db->escape($dvid)." + AND vertragsbestandteiltyp_kurzbz='freitext' + AND ".$db->escape($datum)." BETWEEN von AND COALESCE(bis, '2999-12-31') + AND freitexttyp_kurzbz='allin'"; + + $resultAllIn = $db->execReadOnlyQuery($qry); + + if (hasData($resultAllIn)) + return true; + else + return false; + } + + private function _getVBS($dvid, $datum) + { + $db = new DB_Model(); + + $qry = " + SELECT + * + FROM + hr.tbl_vertragsbestandteil + WHERE + dienstverhaeltnis_id=".$db->escape($dvid)." + AND vertragsbestandteiltyp_kurzbz='stunden' + AND ".$db->escape($datum)." BETWEEN von AND COALESCE(bis, '2999-12-31')"; + + $resultVBS = $db->execReadOnlyQuery($qry); + + return $resultVBS; + } + + /** + * Ermittelt den User zu einer SVNR + */ + private function _getUser($svnr) + { + $db = new DB_Model(); + + $qry = " + SELECT + mitarbeiter_uid + FROM + public.tbl_person + JOIN public.tbl_benutzer using(person_id) + JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) + WHERE + tbl_person.svnr = ". $db->escape($svnr)." + AND EXISTS( + SELECT + 1 + FROM + hr.tbl_dienstverhaeltnis + WHERE + mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid + AND oe_kurzbz=". $db->escape($this->OE_DEFAULT)." + ) + ORDER BY tbl_benutzer.aktiv DESC + LIMIT 1; + "; + + $result = $db->execReadOnlyQuery($qry); + + if (hasdata($result)) + { + return $result; + } + else + return error('Kein Benutzer mit DV und SVNR:'.$svnr.' gefunden'); + } +} diff --git a/application/controllers/system/Navigation.php b/application/controllers/system/Navigation.php index c3764b612..71ab1c81b 100644 --- a/application/controllers/system/Navigation.php +++ b/application/controllers/system/Navigation.php @@ -22,6 +22,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); * This controller operates between (interface) the JS (GUI) and the NavigationLib (back-end) * Provides data to the ajax get calls about the filter * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + * TODO(chris): deprecated */ class Navigation extends FHC_Controller { diff --git a/application/controllers/system/TestVBform.php b/application/controllers/system/TestVBform.php new file mode 100644 index 000000000..9923bf05b --- /dev/null +++ b/application/controllers/system/TestVBform.php @@ -0,0 +1,32 @@ + 'system/developer:r' + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Everything has a beginning + */ + public function index() + { + $this->load->view('system/logs/testVBform.php'); + } +} diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index cf0c6755a..f6e41d2e6 100644 --- a/application/controllers/system/infocenter/InfoCenter.php +++ b/application/controllers/system/infocenter/InfoCenter.php @@ -337,10 +337,13 @@ class InfoCenter extends Auth_Controller $persondata = $this->_loadPersonData($person_id); $checkPerson = $this->PersonModel->checkDuplicate($person_id); - if (isError($checkPerson)) show_error(getError($checkPerson)); - $duplicate = array('duplicated' => getData($checkPerson)); + $checkUnruly = $this->PersonModel->checkUnruly($persondata['stammdaten']->vorname, $persondata['stammdaten']->nachname, $persondata['stammdaten']->gebdatum); + if (isError($checkUnruly)) show_error(getError($checkUnruly)); + + $duplicate = array('duplicate' => getData($checkPerson)); + $unruly = array('unruly' => getData($checkUnruly)); $prestudentdata = $this->_loadPrestudentData($person_id); @@ -351,7 +354,8 @@ class InfoCenter extends Auth_Controller $persondata, $prestudentdata, $dokumentdata, - $duplicate + $duplicate, + $unruly ); $data[self::FHC_CONTROLLER_ID] = $this->getControllerId(); @@ -1285,67 +1289,28 @@ class InfoCenter extends Auth_Controller $this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern')); $kontakte = $this->input->post('kontakt'); - foreach ($kontakte as $kontakt) - { - $kontaktExists = $this->KontaktModel->loadWhere(array( - 'kontakt_id' => $kontakt['id'], - 'person_id' => $person_id, - )); + if($kontakte) { - if (hasData($kontaktExists)) - { - $kontaktExists = getData($kontaktExists)[0]; + foreach ($kontakte as $kontakt) { + $kontaktExists = $this->KontaktModel->loadWhere(array( + 'kontakt_id' => $kontakt['id'], + 'person_id' => $person_id, + )); - if ($kontaktExists->kontakt === $kontakt['value']) - continue; + if (hasData($kontaktExists)) { + $kontaktExists = getData($kontaktExists)[0]; - $update = $this->KontaktModel->update( - array - ( - 'kontakt_id' => $kontakt['id'] - ), - array - ( - 'kontakt' => isEmptyString($kontakt['value']) ? null : $kontakt['value'], - 'updateamum' => date('Y-m-d H:i:s'), - 'updatevon' => $this->_uid - ) - ); + if ($kontaktExists->kontakt === $kontakt['value']) + continue; - if (isError($update)) - $this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern')); - } - } - - $adressen = $this->input->post('adresse'); - - foreach ($adressen as $adresse) - { - $adresseExists = $this->AdresseModel->loadWhere(array( - 'adresse_id' => $adresse['id'], - 'person_id' => $person_id, - )); - - if (hasData($adresseExists)) - { - $adresse = $adresse['value']; - $adresseExists = getData($adresseExists)[0]; - if ($adresseExists->strasse !== $adresse['strasse'] || - $adresseExists->plz !== $adresse['plz'] || - $adresseExists->ort !== $adresse['ort'] || - $adresseExists->nation !== $adresse['nation']) - { - $update = $this->AdresseModel->update( + $update = $this->KontaktModel->update( array ( - 'adresse_id' => $adresseExists->adresse_id + 'kontakt_id' => $kontakt['id'] ), array ( - 'strasse' => isEmptyString($adresse['strasse']) ? null : $adresse['strasse'], - 'plz' => isEmptyString($adresse['plz']) ? null : $adresse['plz'], - 'ort' => isEmptyString($adresse['ort']) ? null : $adresse['ort'], - 'nation' => isEmptyString($adresse['nation']) ? null : $adresse['nation'], + 'kontakt' => isEmptyString($kontakt['value']) ? null : $kontakt['value'], 'updateamum' => date('Y-m-d H:i:s'), 'updatevon' => $this->_uid ) @@ -1354,7 +1319,48 @@ class InfoCenter extends Auth_Controller if (isError($update)) $this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern')); } + } + } + + $adressen = $this->input->post('adresse'); + + if($adressen) { + + foreach ($adressen as $adresse) { + $adresseExists = $this->AdresseModel->loadWhere(array( + 'adresse_id' => $adresse['id'], + 'person_id' => $person_id, + )); + + if (hasData($adresseExists)) { + $adresse = $adresse['value']; + $adresseExists = getData($adresseExists)[0]; + if ($adresseExists->strasse !== $adresse['strasse'] || + $adresseExists->plz !== $adresse['plz'] || + $adresseExists->ort !== $adresse['ort'] || + $adresseExists->nation !== $adresse['nation']) { + $update = $this->AdresseModel->update( + array + ( + 'adresse_id' => $adresseExists->adresse_id + ), + array + ( + 'strasse' => isEmptyString($adresse['strasse']) ? null : $adresse['strasse'], + 'plz' => isEmptyString($adresse['plz']) ? null : $adresse['plz'], + 'ort' => isEmptyString($adresse['ort']) ? null : $adresse['ort'], + 'nation' => isEmptyString($adresse['nation']) ? null : $adresse['nation'], + 'updateamum' => date('Y-m-d H:i:s'), + 'updatevon' => $this->_uid + ) + ); + + if (isError($update)) + $this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern')); + } + + } } } @@ -2383,4 +2389,4 @@ class InfoCenter extends Auth_Controller $this->outputJsonSuccess("Success"); } -} +} \ No newline at end of file diff --git a/application/controllers/system/messages/FASMessages.php b/application/controllers/system/messages/FASMessages.php index 55d1da25f..e2169af9b 100644 --- a/application/controllers/system/messages/FASMessages.php +++ b/application/controllers/system/messages/FASMessages.php @@ -37,7 +37,7 @@ class FASMessages extends Auth_Controller // Loads the view to write a new message with a template $this->load->view( - 'system/messages/htmlWriteTemplate', + 'system/messages/FAShtmlWriteTemplate', $this->CLMessagesModel->prepareHtmlWriteTemplatePrestudents($prestudents) ); } @@ -53,7 +53,7 @@ class FASMessages extends Auth_Controller // Loads the view to write a new message with a template $this->load->view( - 'system/messages/htmlWriteTemplate', + 'system/messages/FAShtmlWriteTemplate', $this->CLMessagesModel->prepareHtmlWriteTemplatePrestudents($prestudents, $message_id, $recipient_id) ); } diff --git a/application/core/Auth_Controller.php b/application/core/Auth_Controller.php index c407a106f..466627fe3 100644 --- a/application/core/Auth_Controller.php +++ b/application/core/Auth_Controller.php @@ -7,6 +7,10 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); */ abstract class Auth_Controller extends FHC_Controller { + // Special Permissions + const PERM_ANONYMOUS = 'anonymous'; // Everyone + const PERM_LOGGED = 'logged_in'; // Every registered user + /** * Extends this controller if authentication is required */ @@ -14,17 +18,41 @@ abstract class Auth_Controller extends FHC_Controller { parent::__construct(); - // Loads authentication library and starts authentication - $this->load->library('AuthLib'); + if (!is_array($requiredPermissions) || isEmptyArray($requiredPermissions)) + show_error('The given permissions is not a valid array or it is an empty one'); + + if (!isset($requiredPermissions[$this->router->method])) + show_error('The given permission array does not contain the given method or is not correctly set'); + + $anonAllowed = false; + if ($requiredPermissions[$this->router->method] == self::PERM_ANONYMOUS) + $anonAllowed = true; + elseif (is_array($requiredPermissions[$this->router->method]) + && in_array(self::PERM_ANONYMOUS, $requiredPermissions[$this->router->method])) + $anonAllowed = true; - // Checks if the caller is allowed to access to this content - $this->_isAllowed($requiredPermissions); + if ($anonAllowed) { + // Loads authentication library without authentication + $this->load->library('AuthLib', [false]); + + // Loads helper since it would only be called on authentication + $this->load->helper('hlp_authentication'); + } else { + // Loads authentication library and starts authentication + $this->load->library('AuthLib'); + + // Checks if the caller is allowed to access to this content + $this->_isAllowed($requiredPermissions); + } } /** * Checks if the caller is allowed to access to this content with the given permissions * If it is not allowed will set the HTTP header with code 401 * Wrapper for permissionlib->isEntitled + * + * @param array $requiredPermissions + * @return void */ private function _isAllowed($requiredPermissions) { @@ -34,28 +62,145 @@ abstract class Auth_Controller extends FHC_Controller // Checks if this user is entitled to access to this content if (!$this->permissionlib->isEntitled($requiredPermissions, $this->router->method)) { - $this->output->set_status_header(REST_Controller::HTTP_UNAUTHORIZED); // set the HTTP header as unauthorized - - $this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output - - // Prints the main error message - $this->eprintflib->printError('You are not allowed to access to this content'); - // Prints the called controller name - $this->eprintflib->printInfo('Controller name: '.$this->router->class); - // Prints the called controller method name - $this->eprintflib->printInfo('Method name: '.$this->router->method); - // Prints the required permissions needed to access to this method - $this->eprintflib->printInfo('Required permissions: '.$this->_rpsToString($requiredPermissions, $this->router->method)); - + $this->_outputAuthError($requiredPermissions); exit; // immediately terminate the execution } } + /** + * Checks for Permissions depending if the given person is a + * Mitarbeiter and/or Student + * and exits/outputs an error if they are not met. + * + * @param integer $person_id + * @param array $permMa Perms if the person is a Mitarbeiter + * @param array $permStud Perms if the person is a Student + * + * @return void + */ + protected function checkPermissionsForPerson($person_id, $permMa, $permStud) + { + $res = $this->hasPermissionsForPerson($person_id, $permMa, $permStud); + + if ($res) { + $perm = array_keys(array_flip(array_merge($res|1 ? $permMa : [], $res|2 ? $permStud : []))); + $this->_outputAuthError([$this->router->method => $perm]); + } + } + + /** + * Checks for Permissions depending on the Studiengang of a Prestudent + * and exits/outputs an error if they are not met. + * + * @param integer $prestudent_id + * @param array $permStud Perms if the person is a Student + * + * @return void + */ + protected function checkPermissionsForPrestudent($prestudent_id, $permStud) + { + if (!$this->hasPermissionsForPrestudent($prestudent_id, $permStud)) { + $this->_outputAuthError([$this->router->method => $permStud]); + } + } + + /** + * Checks for Permissions depending if the given person is a + * Mitarbeiter and/or Student + * and returns the result. + * + * @param integer $person_id + * @param array $permMa Perms if the person is a Mitarbeiter + * @param array $permStud Perms if the person is a Student + * + * @return integer 0 if permission is granted + */ + protected function hasPermissionsForPerson($person_id, $permMa, $permStud) + { + $res = 3; + $this->load->model('person/Person_model', 'PersonModel'); + $this->PersonModel->addJoin('public.tbl_benutzer', 'person_id'); + $this->PersonModel->addJoin('public.tbl_mitarbeiter', 'uid = mitarbeiter_uid'); + $result = $this->PersonModel->load($person_id); + if (hasData($result)) { + if ($this->permissionlib->isEntitled(['a' => $permMa], 'a')) + return 0; + $res = 1; + } + $this->PersonModel->addJoin('public.tbl_prestudent', 'person_id'); + $result = $this->PersonModel->load($person_id); + if (hasData($result)) { + $permStudConverted = []; + foreach (getData($result) as $row) { + foreach ($permStud as $k => $v) { + if (!isset($permStudConverted[$k])) { + $permStudConverted[$k] = $this->permissionlib->convertAccessType($v); + } + if ($this->permissionlib->isBerechtigt($permStudConverted[$k][0], $permStudConverted[$k][1], $row->studiengang_kz)) + return 0; + } + } + $res += 2; + } + return $res; + } + + /** + * Checks for Permissions depending on the Studiengang of a Prestudent + * and returns the result. + * + * @param integer $prestudent_id + * @param array $permStud Perms if the person is a Student + * + * @return boolean + */ + protected function hasPermissionsForPrestudent($prestudent_id, $permStud) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->load($prestudent_id); + if (!hasData($result)) + show_404(); + $stg = current(getData($result))->studiengang_kz; + foreach ($permStud as $k => $v) { + $perm = $this->permissionlib->convertAccessType($v); + if ($this->permissionlib->isBerechtigt($perm[0], $perm[1], $stg)) + return true; + } + return false; + } + + /** + * Outputs an error message and sets the HTTP Header. + * This function is protected so that it can be overwritten. + * + * @param array $requiredPermissions + * @return void + */ + protected function _outputAuthError($requiredPermissions) + { + $this->output->set_status_header(REST_Controller::HTTP_UNAUTHORIZED); // set the HTTP header as unauthorized + + $this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output + + // Prints the main error message + $this->eprintflib->printError('You are not allowed to access to this content'); + // Prints the called controller name + $this->eprintflib->printInfo('Controller name: '.$this->router->class); + // Prints the called controller method name + $this->eprintflib->printInfo('Method name: '.$this->router->method); + // Prints the required permissions needed to access to this method + $this->eprintflib->printInfo('Required permissions: '.$this->_rpsToString($requiredPermissions, $this->router->method)); + } + /** * Converts an array of permissions to a string that contains them as a comma separated list * Ex: ", , " + * + * @param array $requiredPermissions + * @param string $method + * @return void */ - private function _rpsToString($requiredPermissions, $method) + final protected function _rpsToString($requiredPermissions, $method) { $strRequiredPermissions = ''; // string that contains all the required permissions needed to access to this method diff --git a/application/core/CI3_Events.php b/application/core/CI3_Events.php new file mode 100644 index 000000000..33a96b89e --- /dev/null +++ b/application/core/CI3_Events.php @@ -0,0 +1,51 @@ +. + */ + +use \stdClass as stdClass; + if (!defined('BASEPATH')) exit('No direct script access allowed'); /** @@ -27,6 +46,15 @@ class DB_Model extends CI_Model const PGSQL_INT8_TYPE = 'int8'; const PGSQL_FLOAT4_TYPE = 'float4'; const PGSQL_FLOAT8_TYPE = 'float8'; + const PGSQL_BYTEA_TYPE = 'bytea'; + + // Name of the config entry containing an array of password that can be used to encrypt/decrypt + const CRYPT_CONF_PASSWORDS = 'encryption_passwords'; + const CRYPT_CAST = 'cast'; + const CRYPT_PASSWORD_NAME = 'passwordName'; + const CRYPT_SELECT_TEMPLATE = 'PGP_SYM_DECRYPT(%s, \'%s\')::%s AS %s'; + const CRYPT_WHERE_TEMPLATE = 'PGP_SYM_DECRYPT(%s, \'%s\')::%s'; + const CRYPT_WRITE_TEMPLATE = 'PGP_SYM_ENCRYPT(\'%s\', \'%s\')'; protected $dbTable; // Name of the DB-Table for CI-Insert, -Update, ... protected $pk; // Name of the PrimaryKey for DB-Update, Load, ... @@ -36,7 +64,7 @@ class DB_Model extends CI_Model private $executedQueryMetaData; private $executedQueryListFields; - private $debugMode; + private $debugMode; // Debug mode enable (true) or disabled (false) /** * Constructor @@ -46,20 +74,23 @@ class DB_Model extends CI_Model // Call parent constructor parent::__construct(); - // Set properties - $this->hasSequence = true; - - // Loads DB conns and confs + // Loads DB connections and configs $this->load->database($dbtype); + // Loads the DB config to encrypt/decrypt data + $this->config->load('db_crypt'); + + // Set properties + $this->hasSequence = true; + $this->debugMode = isset($this->db->db_debug) && $this->db->db_debug === true; + + // Loads UDF model $this->load->model('system/UDF_model', 'UDFModel'); // Loads the UDF library $this->load->library('UDFLib'); // Loads the logs library $this->load->library('LogLib'); - - $this->debugMode = isset($this->db->db_debug) && $this->db->db_debug === true; } // ------------------------------------------------------------------------------------------ @@ -85,13 +116,20 @@ class DB_Model extends CI_Model * @param array $data DataArray for Insert * @return array */ - public function insert($data) + public function insert($data, $encryptedColumns = null) { // Check class properties if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL); // If this table has UDF and the validation of them is ok - if (isError($validate = $this->_prepareUDFsWrite($data, $this->dbTable))) return $validate; + $validate = $this->_prepareUDFsWrite($data, $this->dbTable); + if (isError($validate)) return $validate; + + // Add the pgp_sym_eccrypt postgresql function to the set clause if needed + $this->_addEncrypt($encryptedColumns, $data); + + // Add the pgp_sym_eccrypt postgresql function to the set clause if needed + if (!empty($encryptedColumns)) $this->_addEncrypt($encryptedColumns, $data); // DB-INSERT $insert = $this->db->insert($this->dbTable, $data); @@ -135,14 +173,15 @@ class DB_Model extends CI_Model * @param array $data DataArray for Insert * @return array */ - public function update($id, $data) + public function update($id, $data, $encryptedColumns = null) { // Check class properties if (is_null($this->pk)) return error('The given primary key is not valid', EXIT_MODEL); if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL); // If this table has UDF and the validation of them is ok - if (isError($validate = $this->_prepareUDFsWrite($data, $this->dbTable, $id))) return $validate; + $validate = $this->_prepareUDFsWrite($data, $this->dbTable, $id); + if (isError($validate)) return $validate; $tmpId = $id; @@ -161,6 +200,9 @@ class DB_Model extends CI_Model $this->db->where($tmpId); + // Add the pgp_sym_eccrypt postgresql function to the set clause if needed + $this->_addEncrypt($encryptedColumns, $data); + // DB-UPDATE $update = $this->db->update($this->dbTable, $data); @@ -224,7 +266,7 @@ class DB_Model extends CI_Model * @param string $id ID (Primary Key) for SELECT ... WHERE * @return array */ - public function load($id = null) + public function load($id = null, $encryptedColumns = null) { // Check class properties if (is_null($this->pk)) return error('The given primary key is not valid', EXIT_MODEL); @@ -245,7 +287,7 @@ class DB_Model extends CI_Model $tmpId = array($this->pk => $id); } - return $this->loadWhere($tmpId); + return $this->loadWhere($tmpId, $encryptedColumns); } /** @@ -253,11 +295,14 @@ class DB_Model extends CI_Model * * @return array */ - public function loadWhere($where = null) + public function loadWhere($where = null, $encryptedColumns = null) { // Check class properties if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL); + // Add the pgp_sym_decrypt postgresql function to the select and where clause if needed + $this->_addDecryptLoad($encryptedColumns, $where); + // Execute query $result = $this->db->get_where($this->dbTable, $where); @@ -265,7 +310,7 @@ class DB_Model extends CI_Model if ($result) { - return success($this->_toPhp($result)); + return success($this->_toPhp($result, $encryptedColumns)); } else { @@ -303,7 +348,8 @@ class DB_Model extends CI_Model // NOTE: $this->db->list_fields($tables[$t]) doesn't work if there are two tables with // the same name in two different schemas, use this workaround $fields = array(); - if (isSuccess($lstColumns = $this->_list_columns($schemaAndTable->schema, $schemaAndTable->table))) + $lstColumns = $this->_list_columns($schemaAndTable->schema, $schemaAndTable->table); + if (isSuccess($lstColumns)) { $fields = $lstColumns->retval; } @@ -381,7 +427,8 @@ class DB_Model extends CI_Model $tmpFilteredArray = array_filter(get_object_vars($sideTableObj)); if (isset($tmpFilteredArray) && count($tmpFilteredArray) > 0) { - if (($k = $this->_findMainTable($mainTableObj, $returnArray)) === false) + $k = $this->_findMainTable($mainTableObj, $returnArray); + if ($k === false) { $mainTableObj->{$sideTableProperty} = array($sideTableObj); $returnArray[$returnArrayCounter++] = $mainTableObj; @@ -758,14 +805,13 @@ class DB_Model extends CI_Model /** * Like execQuery, but it allows only to perform queries to read data */ - public function execReadOnlyQuery($query, $parametersArray = null) + public function execReadOnlyQuery($query, $parametersArray = null, $encryptedColumns = null) { $result = error('You are allowed to run only query for reading data'); // $cleanedQuery = trim(preg_replace('/\t|\n|\r|;/', '', $query)); // // - if ( - (stripos($cleanedQuery, 'INSERT') > 0 || stripos($cleanedQuery, 'INSERT') == false) + if ((stripos($cleanedQuery, 'INSERT') > 0 || stripos($cleanedQuery, 'INSERT') == false) && (stripos($cleanedQuery, 'UPDATE') > 0 || stripos($cleanedQuery, 'UPDATE') == false) && (stripos($cleanedQuery, 'CREATE') > 0 || stripos($cleanedQuery, 'CREATE') == false) && (stripos($cleanedQuery, 'DELETE') > 0 || stripos($cleanedQuery, 'DELETE') == false) @@ -775,12 +821,29 @@ class DB_Model extends CI_Model { $queryToExec = str_replace(';', '', $query); // - $result = $this->execQuery($queryToExec, $parametersArray); + $result = $this->execQuery($queryToExec, $parametersArray, $encryptedColumns); } return $result; } + public function getDbTable() + { + return $this->dbTable; + } + + public function getPk() + { + return $this->pk; + } + + public function getPks() + { + if (is_array($this->pk)) + return $this->pk; + return [$this->pk]; + } + // ------------------------------------------------------------------------------------------ // Protected methods @@ -790,13 +853,16 @@ class DB_Model extends CI_Model * boolean if the query is of the write type (INSERT, UPDATE, DELETE...) * array that represents DB data */ - protected function execQuery($query, $parametersArray = null) + protected function execQuery($query, $parametersArray = null, $encryptedColumns = null) { $result = null; // If the query is empty don't lose time if (!isEmptyString($query)) { + // Add the pgp_sym_decrypt postgresql function to the given query + $this->_addDecryptQuery($encryptedColumns, $query); + // If there are parameters to bind to the query if (is_array($parametersArray) && count($parametersArray) > 0) { @@ -812,7 +878,7 @@ class DB_Model extends CI_Model // If no errors occurred if ($resultDB) { - $result = success($this->_toPhp($resultDB)); + $result = success($this->_toPhp($resultDB, $encryptedColumns)); } else { @@ -840,7 +906,8 @@ class DB_Model extends CI_Model $result->schema = DB_Model::DEFAULT_SCHEMA; // If a schema is specified - if (($pos = strpos($schemaAndTable, '.')) !== false) + $pos = strpos($schemaAndTable, '.'); + if ($pos !== false) { $result->schema = substr($schemaAndTable, 0, $pos); $result->table = substr($schemaAndTable, $pos + 1); @@ -851,6 +918,207 @@ class DB_Model extends CI_Model // ------------------------------------------------------------------------------------------ // Private methods + // + // + + /** + * To add the pgp_sym_encrypt function to the set clause where needed + */ + private function _addEncrypt($encryptedColumns, &$data) + { + // If encryptedColumns is not defined then exit + if (isEmptyArray($encryptedColumns)) return; + + $tmpData = array(); // Temporary array used to copy not encrypted columns + + // For each column that is going to be inserted/updated + foreach ($data as $column => $value) + { + // If the current column is in the list of the columns to be encrypted + // and contains the password name element + if (array_key_exists($column, $encryptedColumns) + && array_key_exists(self::CRYPT_PASSWORD_NAME, $encryptedColumns[$column])) + { + // Password to encrypt data + $cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS); + $encryptionPassword = $cryptConfPasswords[$encryptedColumns[$column][self::CRYPT_PASSWORD_NAME]]; + + // Add the encrypted column to the set clause without escaping + $this->db->set( + $column, + sprintf( + self::CRYPT_WRITE_TEMPLATE, + $value, + $encryptionPassword + ), + false // no escaping + ); + } + else // otherwise copy this element as it is + { + $tmpData[$column] = $value; + } + } + + $data = $tmpData; // this array does not contain encrypted columns + } + + /** + * To add the pgp_sym_decrypt function to the given query + */ + private function _addDecryptQuery($encryptedColumns, &$query) + { + // If it is request to get encrypted columns + if (!isEmptyArray($encryptedColumns)) + { + // For each requested encrypted column + foreach ($encryptedColumns as $encryptedColumn => $definition) + { + // If the requested encrypted column is well defined + if (!isEmptyArray($definition) + && array_key_exists(self::CRYPT_CAST, $definition) + && array_key_exists(self::CRYPT_PASSWORD_NAME, $definition)) + { + // And if exists the wanted password to decrypt in the configs + if (array_key_exists($definition[self::CRYPT_PASSWORD_NAME], $this->config->item(self::CRYPT_CONF_PASSWORDS))) + { + // Password to decrypt data + $cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS); + $decryptionPassword = $cryptConfPasswords[$definition[self::CRYPT_PASSWORD_NAME]]; + + // Find and replace all the occurrences of the provided encrypted columns + // with the postgresql decryption function + $query = str_replace( + $encryptedColumn, + sprintf( + self::CRYPT_WHERE_TEMPLATE, + $encryptedColumn, + $decryptionPassword, + $definition[self::CRYPT_CAST] + ), + $query + ); + } + } + } + } + } + + /** + * To add the pgp_sym_decrypt function to the select and where clause where needed + */ + private function _addDecryptLoad($encryptedColumns, &$where) + { + // If it is request to get encrypted columns + if (!isEmptyArray($encryptedColumns)) + { + // For each requested encrypted column + foreach ($encryptedColumns as $encryptedColumn => $definition) + { + // If the requested encrypted column is well defined + if (!isEmptyArray($definition) + && array_key_exists(self::CRYPT_CAST, $definition) + && array_key_exists(self::CRYPT_PASSWORD_NAME, $definition)) + { + // And if exists the wanted password to decrypt in the configs + if (array_key_exists($definition[self::CRYPT_PASSWORD_NAME], $this->config->item(self::CRYPT_CONF_PASSWORDS))) + { + // Password to decrypt data + $cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS); + $decryptionPassword = $cryptConfPasswords[$definition[self::CRYPT_PASSWORD_NAME]]; + + // ----------------------------------------- + // SELECT + + // Add to the select clause the column to be decrypted + // NOTE: this is going to override any previously added column with the same name + $this->addSelect( + sprintf( + self::CRYPT_SELECT_TEMPLATE, + $encryptedColumn, + $decryptionPassword, + $definition[self::CRYPT_CAST], + $encryptedColumn + ) + ); + + // ----------------------------------------- + // WHERE + + // If the where parameter is a valid array + if (!isEmptyArray($where)) + { + $tmpWhere = array(); + + // For each condition of the where clause + foreach ($where as $column => $condition) + { + $operator = null; // operator not found in the column name + + // Custom operators with 2 chars + if (strpos($column, '>=') != false + || strpos($column, '<=') != false + || strpos($column, '!=') != false + || strpos($column, '<>') != false + ) + { + $operator = ' '.substr(trim($column), -2).' '; + } + // Custom operators with 1 chars + elseif (strpos($column, '>') != false + || strpos($column, '<') != false + || strpos($column, '=') != false + ) + { + $operator = ' '.substr(trim($column), -1).' '; + } + else // default operator + { + $operator = ' = '; + } + + // If the column from the where clause is the same from the encrypted columns definition + if (trim($column) == $encryptedColumn + || ($operator != null && substr(trim($column), 0, strlen(trim($column)) - 2) == $encryptedColumn) + ) + { + // Then rename the column using the postgresql decryption function + $tmpWhere[sprintf( + self::CRYPT_WHERE_TEMPLATE, + $encryptedColumn, + $decryptionPassword, + $definition[self::CRYPT_CAST] + ).$operator] = $condition; + } + else // otherwise copy the column as it is + { + $tmpWhere[$column] = $condition; + } + } + + $where = $tmpWhere; // replace with the new where + } + // Otherwise if the where parameter is a valid string + elseif (!isEmptyString($where)) + { + // Find and replace all the occurrences of the provided encrypted columns + // with the postgresql decryption function + $where = str_replace( + $encryptedColumn, + sprintf( + self::CRYPT_WHERE_TEMPLATE, + $encryptedColumn, + $decryptionPassword, + $definition[self::CRYPT_CAST] + ), + $where + ); + } + } + } + } + } + } /** * Invalid ID @@ -877,11 +1145,11 @@ class DB_Model extends CI_Model { if ($id != null) { - $prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $this->dbTable, $this->_getUDFsNoPerms($id)); + $prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $schemaAndTable, $this->_getUDFsNoPerms($id)); } else { - $prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $this->dbTable); + $prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $schemaAndTable); } } @@ -895,7 +1163,7 @@ class DB_Model extends CI_Model * - A FALSE value on failure * - Otherwise an object filled with data on success */ - private function _toPhp($result) + private function _toPhp($result, $encryptedColumns = null) { $udfs = false; // if UDFs are inside the given result set $toPhp = $result; // if there is nothing to convert then return the result from DB @@ -911,7 +1179,9 @@ class DB_Model extends CI_Model // Looking for booleans, arrays and UDFs foreach ($this->executedQueryMetaData as $eqmd) { - // If array type, boolean type OR a UDF + // If array type, boolean type, numeric type + // Or bytea type + // Or UDF type if (strpos($eqmd->type, DB_Model::PGSQL_ARRAY_TYPE) !== false || $eqmd->type == DB_Model::PGSQL_BOOLEAN_TYPE || $eqmd->type == DB_Model::PGSQL_INT2_TYPE @@ -919,6 +1189,7 @@ class DB_Model extends CI_Model || $eqmd->type == DB_Model::PGSQL_INT8_TYPE || $eqmd->type == DB_Model::PGSQL_FLOAT4_TYPE || $eqmd->type == DB_Model::PGSQL_FLOAT8_TYPE + || $eqmd->type == DB_Model::PGSQL_BYTEA_TYPE || $this->udflib->isUDFColumn($eqmd->name, $eqmd->type)) { // If UDFs are inside this result set @@ -981,6 +1252,21 @@ class DB_Model extends CI_Model { $resultElement->{$toBeConverted->name} = $this->pgFloatPhp($resultElement->{$toBeConverted->name}); } + // Byte A type + elseif ($toBeConverted->type == DB_Model::PGSQL_BYTEA_TYPE) + { + // If encrypted columns are defined + // and if the byte a column is defined as encrypted column + if (!isEmptyArray($encryptedColumns) + && array_key_exists($toBeConverted->name, $encryptedColumns)) + { + // keep the column + } + else // otherwise remove the column from the result + { + unset($resultElement->{$toBeConverted->name}); + } + } } } } diff --git a/application/core/FHCAPI_Controller.php b/application/core/FHCAPI_Controller.php new file mode 100644 index 000000000..36388e271 --- /dev/null +++ b/application/core/FHCAPI_Controller.php @@ -0,0 +1,236 @@ +returnObj['meta']) || !isset($this->returnObj['meta']['status'])) { + switch ($http_response_code) { + case 200: + $this->setStatus(self::STATUS_SUCCESS); + break; + case 400: + $this->setStatus(self::STATUS_FAIL); + break; + default: + $this->setStatus(self::STATUS_ERROR); + break; + } + } + + return json_encode($this->returnObj); + }); + + // NOTE(chris): overwrite error_views_path before constructor + load_class('Config')->set_item('error_views_path', VIEWPATH.'errors'.DIRECTORY_SEPARATOR.'json'.DIRECTORY_SEPARATOR); + + parent::__construct($requiredPermissions); + + // For JSON Requests (as opposed to multipart/form-data) get the $_POST variable from the input stream instead + if ($this->input->get_request_header('Content-Type', true) == 'application/json') + $_POST = json_decode($this->security->xss_clean($this->input->raw_input_stream), true); + elseif (isset($_POST['_jsondata'])) { + $_POST = array_merge($_POST, json_decode($_POST['_jsondata'], true)); + unset($_POST['_jsondata']); + } + } + + + // --------------------------------------------------------------- + // Handle Output object + // --------------------------------------------------------------- + + /** + * @param string|array|object $data + * @param string $type (optional) + * @return void + */ + public function addError($data, $type = null) + { + if (!isset($this->returnObj['errors'])) + $this->returnObj['errors'] = []; + + $error = []; + + if (is_array($data)) { + if ($type == self::ERROR_TYPE_VALIDATION) + $error['messages'] = $data; + else + $error = $data; + } elseif (is_object($data)) { + $error = (array)$data; + } else { + $error['message'] = $data; + } + + if ($type) + $error['type'] = $type; + + if (!isset($error['type'])) + $error['type'] = self::ERROR_TYPE_GENERAL; + + $this->returnObj['errors'][] = $error; + } + + /** + * @param mixed $data + * @return void + */ + public function setData($data) + { + $this->returnObj['data'] = $data; + } + + /** + * @param string $key + * @param mixed $value + * @return void + */ + public function addMeta($key, $value) + { + if (!isset($this->returnObj['meta'])) + $this->returnObj['meta'] = []; + $this->returnObj['meta'][$key] = $value; + } + + /** + * @param string $status + * @return void + */ + public function setStatus($status) + { + $this->addMeta('status', $status); + } + + + // --------------------------------------------------------------- + // Handle Output object - Shortcut functions + // --------------------------------------------------------------- + + /** + * @param mixed $data (optional) + * @return void + */ + protected function terminateWithSuccess($data = null) + { + $this->setData($data); + $this->setStatus(self::STATUS_SUCCESS); + exit; + } + + /** + * @param array $errors + * @return void + */ + protected function terminateWithValidationErrors($errors) + { + $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); + $this->addError($errors, self::ERROR_TYPE_VALIDATION); + $this->setStatus(self::STATUS_FAIL); + exit(EXIT_ERROR); + } + + /** + * @param array $error + * @param string $type (optional) + * @param integer $status (optional) + * @return void + */ + protected function terminateWithError($error, $type = null, $status = REST_Controller::HTTP_INTERNAL_SERVER_ERROR) + { + $this->output->set_status_header($status); + $this->addError($error, $type); + $this->setStatus(self::STATUS_ERROR); + exit; + } + + /** + * @param stdclass $result + * @param string $errortype + * @return void + */ + protected function getDataOrTerminateWithError($result, $errortype = self::ERROR_TYPE_GENERAL) + { + if (isError($result)) { + $this->terminateWithError(getError($result), $errortype); + } + return $result->retval; + } + + + // --------------------------------------------------------------- + // Security + // --------------------------------------------------------------- + + /** + * Outputs an error message and sets the HTTP Header. + * This overwrites the default behaviour to output a json object. + * + * @param array $requiredPermissions + * @return void + */ + protected function _outputAuthError($requiredPermissions) + { + $this->output->set_status_header(isLogged() ? REST_Controller::HTTP_FORBIDDEN : REST_Controller::HTTP_UNAUTHORIZED); + + $this->addError([ + 'message' => 'You are not allowed to access to this content', + 'controller' => $this->router->class, + 'method' => $this->router->method, + 'required_permissions' => $this->_rpsToString($requiredPermissions, $this->router->method) + ], self::ERROR_TYPE_AUTH); + } +} diff --git a/application/core/IEncryption.php b/application/core/IEncryption.php new file mode 100644 index 000000000..6b9132c23 --- /dev/null +++ b/application/core/IEncryption.php @@ -0,0 +1,24 @@ +. + */ + +interface IEncryption +{ + public function getEncryptedColumns(): array; +} + diff --git a/application/core/IssueResolver_Controller.php b/application/core/IssueResolver_Controller.php index 758064ed8..ea278ddb0 100755 --- a/application/core/IssueResolver_Controller.php +++ b/application/core/IssueResolver_Controller.php @@ -5,21 +5,18 @@ */ abstract class IssueResolver_Controller extends JOB_Controller { - const CI_PATH = 'application'; - const CI_LIBRARY_FOLDER = 'libraries'; - const EXTENSIONS_FOLDER = 'extensions'; - const ISSUE_RESOLVERS_FOLDER = 'issues/resolvers'; - const CHECK_ISSUE_RESOLVED_METHOD_NAME = 'checkIfIssueIsResolved'; + // mappings in form fehlercode -> resolverlibrary name, fehler which have explicit resolver class defined + protected $_codeLibMappings = []; - protected $_codeLibMappings; + // mappings in form fehlercode -> producer library name, fehler which are resolved the same way they are produced + protected $_codeProducerLibMappings = []; public function __construct() { parent::__construct(); + // pass extension name if calling from extension $this->load->model('system/Issue_model', 'IssueModel'); - - $this->load->library('IssuesLib'); } /** @@ -27,97 +24,29 @@ abstract class IssueResolver_Controller extends JOB_Controller */ public function run() { + $this->load->library( + 'issues/PlausicheckResolverLib', + [ + 'extensionName' => $this->_extensionName ?? null, + 'codeLibMappings' => $this->_codeLibMappings, + 'codeProducerLibMappings' => $this->_codeProducerLibMappings + ] + ); + $this->logInfo("Issue resolve job started"); // load open issues with given errorcodes - $openIssuesRes = $this->IssueModel->getOpenIssues(array_keys($this->_codeLibMappings)); + $openIssuesRes = $this->IssueModel->getOpenIssues( + array_merge(array_keys($this->_codeLibMappings), array_keys($this->_codeProducerLibMappings)) + ); - // log error if occured - if (isError($openIssuesRes)) - { - $this->logError(getError($openIssuesRes)); - } - else - { - // log info if no data found - if (!hasData($openIssuesRes)) - { - $this->logInfo("No open issues found"); - } - else - { - $openIssues = getData($openIssuesRes); + $openIssues = hasData($openIssuesRes) ? getData($openIssuesRes) : []; - foreach ($openIssues as $issue) - { - // ignore if Fehlercode is not in libmappings (shouldn't be checked) - if (!isset($this->_codeLibMappings[$issue->fehlercode])) continue; + $result = $this->plausicheckresolverlib->resolvePlausicheckIssues($openIssues); - $libName = $this->_codeLibMappings[$issue->fehlercode]; - - // add person id and oe kurzbz automatically as params, merge it with additional params - // decode bewerbung_parameter into assoc array - $params = array_merge( - array('issue_id' => $issue->issue_id, 'issue_person_id' => $issue->person_id, 'issue_oe_kurzbz' => $issue->oe_kurzbz), - isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array() - ); - - // if called from extension (extension name set), path includes extension names - $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : ''; - - // path for loading issue library - $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/'; - - // file path of library for check if file exists - $issuesLibFilePath = DOC_ROOT . self::CI_PATH - . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php'; - - // check if library file exists - if (!file_exists($issuesLibFilePath)) - { - // log error and continue with next issue if not - $this->logError("Issue library file " . $issuesLibFilePath . " does not exist"); - continue; - } - - // load library connected to fehlercode - $this->load->library($issuesLibPath . $libName); - - $lowercaseLibName = mb_strtolower($libName); - - // check if method is defined in library class - if (!is_callable(array($this->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME))) - { - // log error and continue with next issue if not - $this->logError("Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName"); - continue; - } - - // call the function for checking for issue resolution - $issueResolvedRes = $this->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); - - if (isError($issueResolvedRes)) - { - $this->logError(getError($issueResolvedRes)); - } - else - { - $issueResolvedData = getData($issueResolvedRes); - - if ($issueResolvedData === true) - { - // set issue to resolved if needed - $behobenRes = $this->issueslib->setBehoben($issue->issue_id, null); - - if (isError($behobenRes)) - $this->logError(getError($behobenRes)); - else - $this->logInfo("Issue " . $issue->issue_id . " successfully resolved"); - } - } - } - } - } + // log if error, or log info if inserted new issue + foreach ($result->errors as $error) $this->logError($error); + foreach ($result->infos as $info) $this->logInfo($info); $this->logInfo("Issue resolve job ended"); } diff --git a/application/core/Notiz_Controller.php b/application/core/Notiz_Controller.php new file mode 100644 index 000000000..05f70ee85 --- /dev/null +++ b/application/core/Notiz_Controller.php @@ -0,0 +1,461 @@ + self::DEFAULT_PERMISSION_R, + 'getNotizen' => self::DEFAULT_PERMISSION_R, + 'loadNotiz' => self::DEFAULT_PERMISSION_R, + 'addNewNotiz' => self::DEFAULT_PERMISSION_RW, + 'updateNotiz' => self::DEFAULT_PERMISSION_RW, + 'deleteNotiz' => self::DEFAULT_PERMISSION_RW, + 'loadDokumente' => self::DEFAULT_PERMISSION_R, + 'getMitarbeiter' => self::DEFAULT_PERMISSION_R, + 'isBerechtigt' => self::DEFAULT_PERMISSION_R, + ]; + + if(!is_array($permissions)) + { + $this->terminateWithError("Notiz_controller construct: permissions must be an array"); + } + + $merged_permissions = array_merge($default_permissions, $permissions); + + parent::__construct($merged_permissions); + + //Load Models + $this->load->model('person/Notiz_model', 'NotizModel'); + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + public function getUid() + { + $this->terminateWithSuccess(getAuthUID()); + } + + + //Override function for extensions + protected function assignNotiz($notiz_id, $id, $type) + { + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + $result = $this->NotizzuordnungModel->isValidType($type); + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $result = $this->NotizzuordnungModel->insert(array('notiz_id' => $notiz_id, $type => $id)); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return success(getData($result)); + } + + //Override function for extensions + protected function deleteNotizzuordnung($notiz_id, $id, $type) + { + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + $result = $this->NotizzuordnungModel->isValidType($type); + if (isError($result)) { + $this->terminateWithError('type not in table notizzuordnung enthalten..', self::ERROR_TYPE_GENERAL); + } + + $result = $this->NotizzuordnungModel->delete(['notiz_id' => $notiz_id, $type => $id]); + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return success(getData($result)); + } + + + //Override function for extensions + public function getNotizen($id, $type) + { + $result = $this->NotizzuordnungModel->isValidType($type); + if(isError($result)) + $this->terminateWithError($result->retval, self::ERROR_TYPE_GENERAL); + + $result = $this->NotizModel->getNotizWithDocEntries($id, $type); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + + //Override function + protected function isBerechtigt($id, $typeId){ + return $this->terminateWithError("in abstract function: define right in extension", self::ERROR_TYPE_GENERAL); + } + + public function loadNotiz() + { + $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true); + + $notiz_id = $this->input->post('notiz_id'); + + //$this->load->model('person/Notiz_model', 'NotizModel'); + $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'notiz_id', 'LEFT'); + $this->NotizModel->addSelect('*'); + $this->NotizModel->addSelect("TO_CHAR(CASE WHEN public.tbl_notiz.updateamum >= public.tbl_notiz.insertamum + THEN public.tbl_notiz.updateamum ELSE public.tbl_notiz.insertamum END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate"); + $this->NotizModel->addLimit(1); + + $result = $this->NotizModel->loadWhere( + array('notiz_id' => $notiz_id) + ); + if (isError($result)) + { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + elseif (!hasData($result)) + { + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL); + } + else + { + $this->terminateWithSuccess(current(getData($result))); + } + } + + public function addNewNotiz($id, $paramTyp = null) + { + $this->load->library('DmsLib'); + $this->load->library('form_validation'); + + $uid = getAuthUID(); + + if (isset($_POST['data'])) + { + $data = json_decode($_POST['data']); + unset($_POST['data']); + foreach ($data as $k => $v) { + $_POST[$k] = $v; + } + } + + //Form Validation + $this->form_validation->set_rules('titel', 'Titel', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel']) + ]); + + $this->form_validation->set_rules('text', 'Text', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Text']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $titel = $this->input->post('titel'); + $text = $this->input->post('text'); + $erledigt = $this->input->post('erledigt'); + $verfasser_uid = isset($_POST['verfasser']) ? $_POST['verfasser'] : $uid; + $bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : null; + $type = $this->input->post('typeId'); + $start = $this->input->post('start'); + $ende = $this->input->post('ende'); + + // Start DB transaction + $this->db->trans_start(); + + //Save note + $result = $this->NotizModel->insert(array('titel' => $titel, 'text' => $text, 'erledigt' => $erledigt, 'verfasser_uid' => $verfasser_uid, + "insertvon" => $verfasser_uid, 'start' => $start, 'ende' => $ende, 'bearbeiter_uid' => $bearbeiter_uid)); + + if (isError($result)) + { + $this->db->trans_rollback(); + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $notiz_id = $result->retval; + + //save Notizzuordnung + $result = $this->assignNotiz($notiz_id, $id, $type); + + if (isError($result)) + { + $this->db->trans_rollback(); + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + //save Documents + $dms_id_arr = []; + foreach ($_FILES as $k => $file) + { + $dms = array( + 'kategorie_kurzbz' => 'notiz', + 'version' => 0, + 'name' => $file["name"], + 'mimetype' => $file["type"], + 'insertamum' => date('c'), + 'insertvon' => $uid + ); + + //Todo(manu) check if filetypes weiter eingeschränkt werden sollen + //Todo(manu)check name files: nicht gleiches file 2mal hochladen + //Todo define in dms component: readFile, downloadFile + $result = $this->dmslib->upload($dms, $k, ['*']); + /* $result = $this->dmslib->upload($dms, $k, ['application/pdf','application/x.fhc-dms+json']);*/ + if (isError($result)) + { + $this->db->trans_rollback(); + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $dms_id_arr[] = $result->retval['dms_id']; + } + + //save entry in Notizdokument + if($dms_id_arr) + { + $this->load->model('person/Notizdokument_model', 'NotizdokumentModel'); + foreach($dms_id_arr as $dms_id) + { + $result = $this->NotizdokumentModel->insert(array('notiz_id' => $notiz_id, 'dms_id' => $dms_id)); + if (isError($result)) + { + $this->db->trans_rollback(); + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + } + } + $this->db->trans_commit(); + return $this->terminateWithSuccess($result); + } + + public function updateNotiz() + { + $this->load->library('form_validation'); + $this->load->library('DmsLib'); + + if (isset($_POST['data'])) + { + $data = json_decode($_POST['data']); + unset($_POST['data']); + foreach ($data as $k => $v) { + $_POST[$k] = $v; + } + } + + $notiz_id = $this->input->post('notiz_id'); + + if(!$notiz_id) + { + $this->terminateWithError($this->p->t('ui','error_missingId',['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL); + } + + //Form Validation + $this->form_validation->set_rules('titel', 'Titel', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel']) + ]); + + $this->form_validation->set_rules('text', 'Text', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Text']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + //update Notiz + $uid = getAuthUID(); + $titel = $this->input->post('titel'); + $text = $this->input->post('text'); + $verfasser_uid = isset($_POST['verfasser']) ? $_POST['verfasser'] : $uid; + $bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : $uid; + $erledigt = $this->input->post('erledigt'); + $start = $this->input->post('start'); + $ende = $this->input->post('ende'); + + $result = $this->NotizModel->update( + [ + 'notiz_id' => $notiz_id + ], + [ + 'titel' => $titel, + 'updatevon' => $uid, + 'updateamum' => date('c'), + 'text' => $text, + 'verfasser_uid' => $verfasser_uid, + 'bearbeiter_uid' => $bearbeiter_uid, + 'start' => $start, + 'ende' => $ende, + 'erledigt' => $erledigt + ] + ); + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + //update(1) loading all dms-entries with this notiz_id + $this->load->model('person/Notizdokument_model', 'NotizdokumentModel'); + $this->NotizdokumentModel->addJoin('campus.tbl_dms_version', 'dms_id'); + + $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id)); + $result = $this->getDataOrTerminateWithError($result); + foreach ($result as $doc) { + $dms_id_arr[$doc->dms_id] = array( + 'name' => $doc->name, + 'dms_id' => $doc->dms_id + ); + } + + foreach ($_FILES as $k => $file) + { + //update(2) attach all new files (except type application/x.fhc-dms+json) + if($file["type"] == 'application/x.fhc-dms+json') + { + $jsonFile = json_decode(file_get_contents($file['tmp_name'])); + unset($dms_id_arr[$jsonFile->dms_id]); + #$dms_uploaded[] = $jsonFile->dms_id; + } + else + { + $dms = array( + 'kategorie_kurzbz' => 'notiz', + 'version' => 0, + 'name' => $file["name"], + 'mimetype' => $file["type"], + 'insertamum' => date('c'), + 'insertvon' => $uid + ); + + //Todo(manu) check if filetypes weiter eingeschränkt werden sollen + //Todo(manu)check name files: nicht gleiches file 2mal hochladen + //Todo define in dms component: readFile, downloadFile + $result = $this->dmslib->upload($dms, $k, array('*')); + + $result = $this->getDataOrTerminateWithError($result); + $dms_id = $result['dms_id']; + + $result = $this->NotizdokumentModel->insert(array('notiz_id' => $notiz_id, 'dms_id' => $dms_id)); + + $this->getDataOrTerminateWithError($result); + } + } + + //update(3) check if all files have been deleted + foreach ($dms_id_arr as $file) + { + $result = $this->dmslib->removeAll($file['dms_id']); + + $this->getDataOrTerminateWithError($result); + } + + return $this->terminateWithSuccess($result); + } + + public function deleteNotiz() + { + $this->load->library('DmsLib'); + + $notiz_id = $this->input->post('notiz_id'); + $typeId = $this->input->post('type_id'); + $id = $this->input->post('id'); + + //TODO(manu): define Permissions for deletion document if filecomponent finished + + //get dms_id from notizdokument + $this->load->model('person/Notizdokument_model', 'NotizdokumentModel'); + + $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id)); + + $result = $this->getDataOrTerminateWithError($result); + + // Start DB transaction + $this->db->trans_start(); + + if ($result) + $this->load->library('DmsLib'); + + foreach ($result as $doc) { + $res = $this->dmslib->removeAll($doc->dms_id); + if (isError($result)) + { + $this->db->trans_rollback(); + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + } + + //delete Notizzuordnung + $result = $this-> deleteNotizzuordnung($notiz_id, $id, $typeId); + if (isError($result)) + { + $this->db->trans_rollback(); + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $this->load->model('person/Notiz_model', 'NotizModel'); + + //Delete Note + $result = $this->NotizModel->delete($notiz_id); + + if (isError($result)) + { + $this->db->trans_rollback(); + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if(!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL); + } + + $this->db->trans_complete(); + return $this->terminateWithSuccess(getData($result)); + } + + public function loadDokumente() + { + $notiz_id = $this->input->post('notiz_id'); + + $this->NotizModel->addSelect('campus.tbl_dms_version.*'); + + $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'ON (public.tbl_notiz_dokument.notiz_id = public.tbl_notiz.notiz_id)'); + $this->NotizModel->addJoin('campus.tbl_dms_version', 'ON (public.tbl_notiz_dokument.dms_id = campus.tbl_dms_version.dms_id)'); + + $result = $this->NotizModel->loadWhere( + array('public.tbl_notiz.notiz_id' => $notiz_id) + ); + if (isError($result)) { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + if(!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result)); + } + + public function getMitarbeiter($searchString) + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $result = $this->MitarbeiterModel->searchMitarbeiter($searchString); + if (isError($result)) { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess($result); + } + +} \ No newline at end of file diff --git a/application/core/PlausiIssueProducer_Controller.php b/application/core/PlausiIssueProducer_Controller.php index 0dce7a487..5216d284c 100644 --- a/application/core/PlausiIssueProducer_Controller.php +++ b/application/core/PlausiIssueProducer_Controller.php @@ -5,61 +5,23 @@ */ abstract class PlausiIssueProducer_Controller extends JOB_Controller { - protected $_fehlerLibMappings; + protected $_fehlerLibMappings = []; protected $_app; - public function __construct($app = null) - { - parent::__construct(); - - // pass extension name if calling from extension - $extensionName = isset($this->_extensionName) ? $this->_extensionName : null; - - // load libraries - $this->load->library('issues/PlausicheckProducerLib', array('extensionName' => $extensionName, 'app' => $this->_app)); - $this->load->library('IssuesLib'); - } - protected function producePlausicheckIssues($params) { + $this->load->library( + 'issues/PlausicheckProducerLib', + ['extensionName' => $this->_extensionName ?? null, 'app' => $this->_app, 'fehlerLibMappings' => $this->_fehlerLibMappings] + ); + $this->logInfo("Plausicheck issue producer job started"); - // get the data returned by Plausicheck - foreach ($this->_fehlerLibMappings as $fehler_kurzbz => $libName) - { - // execute the check - $this->logInfo("Checking " . $fehler_kurzbz . "..."); - $plausicheckRes = $this->plausicheckproducerlib->producePlausicheckIssue( - $libName, - $fehler_kurzbz, - $params - ); + $result = $this->plausicheckproducerlib->producePlausicheckIssues($params); - if (isError($plausicheckRes)) $this->logError(getError($plausicheckRes)); - - if (hasData($plausicheckRes)) - { - $plausicheckData = getData($plausicheckRes); - - foreach ($plausicheckData as $plausiData) - { - // get the data needed for issue production - $person_id = isset($plausiData['person_id']) ? $plausiData['person_id'] : null; - $oe_kurzbz = isset($plausiData['oe_kurzbz']) ? $plausiData['oe_kurzbz'] : null; - $fehlertext_params = isset($plausiData['fehlertext_params']) ? $plausiData['fehlertext_params'] : null; - $resolution_params = isset($plausiData['resolution_params']) ? $plausiData['resolution_params'] : null; - - // write the issue - $addIssueRes = $this->issueslib->addFhcIssue($fehler_kurzbz, $person_id, $oe_kurzbz, $fehlertext_params, $resolution_params); - - // log if error, or log info if inserted new issue - if (isError($addIssueRes)) - $this->logError(getError($addIssueRes)); - elseif (hasData($addIssueRes) && is_integer(getData($addIssueRes))) - $this->logInfo("Plausicheck issue " . $fehler_kurzbz . " successfully produced, person_id: " . $person_id); - } - } - } + // log if error, or log info if inserted new issue + foreach ($result->errors as $error) $this->logError($error); + foreach ($result->infos as $info) $this->logInfo($info); $this->logInfo("Plausicheck issue producer job stopped"); } diff --git a/application/helpers/hlp_common_helper.php b/application/helpers/hlp_common_helper.php index 913d29b54..40aed007c 100644 --- a/application/helpers/hlp_common_helper.php +++ b/application/helpers/hlp_common_helper.php @@ -18,6 +18,8 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); +use \DateTime as DateTime; + // ------------------------------------------------------------------------ // Collection of utility functions for general purpose // ------------------------------------------------------------------------ @@ -354,7 +356,8 @@ function sanitizeProblemChars($str) 'ss' => '/ß/' ); - return preg_replace($acentos, array_keys($acentos), htmlentities($str, ENT_NOQUOTES | ENT_HTML5, $enc)); + $tmp = preg_replace($acentos, array_keys($acentos), htmlentities($str, ENT_NOQUOTES | ENT_HTML5, $enc)); + return html_entity_decode($tmp, ENT_NOQUOTES | ENT_HTML5, $enc); } /** @@ -405,3 +408,93 @@ function findResource($path, $resource, $subdir = false, $extraDir = null) return null; } +/** + * check if String can be converted to a date + */ +function isValidDate($dateString) +{ + try + { + return (new DateTime($dateString)) !== false; + } + catch(Exception $e) + { + return false; + } +} + + +// ------------------------------------------------------------------------ +// Collection of utility functions for form validation purposes +// ------------------------------------------------------------------------ + +/** + * check if string can be converted to a date + */ +function is_valid_date($dateString) +{ + try + { + return (new DateTime($dateString)) !== false; + } + catch(Exception $e) + { + return false; + } +} + +/** + * check if given permissions are met + */ +function has_write_permissions($value, $permissions = '') +{ + if (!$permissions) + $permissions = $value; + $permissions = explode(',', $permissions); + + $CI =& get_instance(); + $CI->load->library('AuthLib'); + $CI->load->library('PermissionLib'); + + return $CI->permissionlib->hasAtLeastOne( + $permissions, + 'sometable', + PermissionLib::WRITE_RIGHT + ); +} + +/** + * check if has permissions for a studiengang_kz + */ +function has_permissions_for_stg($studiengang_kz, $permissions = '') +{ + if (!$permissions) + return false; + $permissions = explode(',', $permissions); + + $CI =& get_instance(); + $CI->load->library('AuthLib'); + $CI->load->library('PermissionLib'); + + foreach ($permissions as $perm) { + if (strpos($perm, PermissionLib::PERMISSION_SEPARATOR) === false) { + $CI->addError( + 'The given permission does not use the correct format', + FHCAPI_Controller::ERROR_TYPE_GENERAL + ); + return false; + } + + list($perm, $accesstype) = explode(PermissionLib::PERMISSION_SEPARATOR, $perm); + $at = ''; + if (strpos($accesstype, PermissionLib::READ_RIGHT) !== false) + $at = PermissionLib::SELECT_RIGHT; // S + if (strpos($accesstype, PermissionLib::WRITE_RIGHT) !== false) + $at .= PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT; // UID + + if ($CI->permissionlib->isBerechtigt($perm, $at, $studiengang_kz)) + return true; + } + + return false; +} diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php index 05bba48c4..ea1795ad5 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -96,7 +96,8 @@ function generateJSDataStorageObject($indexPage, $calledPath, $calledMethod) app_root: "'.APP_ROOT.'", ci_router: "'.$indexPage.'", called_path: "'.$calledPath.'", - called_method: "'.$calledMethod.'" + called_method: "'.$calledMethod.'", + user_language: "'.$user_language.'" };'; $toPrint .= "\n"; $toPrint .= ''; diff --git a/application/language/english/form_validation_lang.php b/application/language/english/form_validation_lang.php new file mode 100644 index 000000000..b8918a721 --- /dev/null +++ b/application/language/english/form_validation_lang.php @@ -0,0 +1,43 @@ +_ci =& get_instance(); + + // Configs + $this->_ci->load->config('studierendenantrag'); + + // Models + $this->_ci->load->model('education/Studierendenantrag_model', 'StudierendenantragModel'); + $this->_ci->load->model('education/Studierendenantragstatus_model', 'StudierendenantragstatusModel'); + $this->_ci->load->model('education/Studierendenantraglehrveranstaltung_model', 'StudierendenantraglehrveranstaltungModel'); + $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->_ci->load->model('person/Person_model', 'PersonModel'); + $this->_ci->load->model('education/Pruefung_model', 'PruefungModel'); + + // Helper + $this->_ci->load->helper('hlp_sancho_helper'); + + // Libraries + $this->_ci->load->library('PermissionLib'); + $this->_ci->load->library('PrestudentLib'); + } + + /** + * @param integer $antrag_id + * @param string $insertvon + * + * @return stdClass + */ + public function cancelAntrag($antrag_id, $insertvon) + { + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CANCELLED, + 'insertvon' => $insertvon + ]); + + // NOTE(chris): remove "preabbrecher" statusgrund and paused stati for sibling Anträge for Stgl-Abmeldungen if set + $res = $this->_ci->StudierendenantragModel->load($antrag_id); + if (hasData($res) && current(getData($res))->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL) { + $this->unpauseAntrag($antrag_id, Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL); + + $this->_ci->PrestudentstatusModel->addSelect('tbl_status_grund.statusgrund_kurzbz'); + $res = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail(current(getData($res))->prestudent_id, '', 'Student'); + if (hasData($res) && current(getData($res))->statusgrund_kurzbz == 'preabbrecher') { + $prestudentstatus = current(getData($res)); + $this->_ci->PrestudentstatusModel->update([ + 'prestudent_id' => $prestudentstatus->prestudent_id, + 'status_kurzbz'=>$prestudentstatus->status_kurzbz, + 'studiensemester_kurzbz'=>$prestudentstatus->studiensemester_kurzbz, + 'ausbildungssemester'=>$prestudentstatus->ausbildungssemester + ], [ + 'statusgrund_id' => null + ]); + } + } + + return $result; + } + + /** + * @param integer $antrag_id + * @param string $insertvon + * + * @return stdClass + */ + public function pauseAntrag($antrag_id, $insertvon) + { + switch ($insertvon) { + case Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL: + $result = $this->_ci->StudierendenantragstatusModel->stopAntraegeForAbmeldungStgl($antrag_id); + break; + case Studierendenantragstatus_model::INSERTVON_DEREGISTERED: + $result = $this->_ci->StudierendenantragstatusModel->stopAntraegeForAbbruchBy($antrag_id); + break; + default: + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE, + 'insertvon' => $insertvon + ]); + break; + } + + return $result; + } + + /** + * @param integer $antrag_id + * @param string $insertvon + * + * @return stdClass + */ + public function unpauseAntrag($antrag_id, $insertvon) + { + if ($insertvon == Studierendenantragstatus_model::INSERTVON_DEREGISTERED) + return error($this->_ci->p->t('studierendenantrag', 'error_no_right')); + if ($insertvon == Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL) { + return $this->_ci->StudierendenantragstatusModel->resumeAntraegeForAbmeldungStgl($antrag_id); + } + // NOTE(chris): get last status that is not pause + $this->_ci->StudierendenantragstatusModel->addOrder('insertamum'); + $this->_ci->StudierendenantragstatusModel->addLimit(1); + $result = $this->_ci->StudierendenantragstatusModel->loadWhere([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz !=' => Studierendenantragstatus_model::STATUS_PAUSE + ]); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_antragstatus', ['id' => $antrag_id])); + $status = current(getData($result)); + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz' => $status->studierendenantrag_statustyp_kurzbz, + 'insertvon' => $insertvon + ]); + return $result; + } + + /** + * NOTE(chris): permissions & verification must be handled outside + * + * @param integer $prestudent_id + * @param string $studiensemester_kurzbz + * @param string $insertvon + * @param string $grund + * + * @return stdClass + */ + public function createAbmeldung($prestudent_id, $studiensemester_kurzbz, $insertvon, $grund) + { + $result = $this->_ci->PrestudentModel->load($prestudent_id); + if (isError($result)) + return $result; + if(!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', "error_no_prestudent", ['prestudent_id' => $prestudent_id])); + + $prestudent = getData($result)[0]; + if($prestudent->person_id == getAuthPersonId()) + $typ = Studierendenantrag_model::TYP_ABMELDUNG; + else + $typ = Studierendenantrag_model::TYP_ABMELDUNG_STGL; + + $result = $this->_ci->StudierendenantragModel->insert([ + 'prestudent_id' => $prestudent_id, + 'studiensemester_kurzbz'=> $studiensemester_kurzbz, + 'datum' => date('c'), + 'typ' => $typ, + 'insertvon' => $insertvon, + 'grund' => $grund + ]); + + if (isError($result)) + return $result; + + $antrag_id = getData($result); + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED, + 'insertvon' => $insertvon + ]); + + if (isError($result)) + return $result; + + return success($antrag_id); + } + + /** + * @param array $studierendenantrag_ids + * @param string $insertvon + * + * @return stdClass + */ + public function approveAbmeldung($studierendenantrag_ids, $insertvon) + { + $this->_ci->load->model('crm/Student_model', 'StudentModel'); + + $errors = []; + foreach ($studierendenantrag_ids as $studierendenantrag_id) { + $result = $this->_ci->StudierendenantragModel->load($studierendenantrag_id); + if (isError($result)) + { + $errors[] = getError($result); + continue; + } + if(!hasData($result)) + { + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id]); + continue; + } + $antrag = getData($result)[0]; + + $insertam = date('c'); + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED, + 'insertvon' => $insertvon, + 'insertamum' => $insertam + ]); + if (isError($result)) + $errors[] = getError($result); + else { + $this->_ci->StudiengangModel->addJoin('public.tbl_prestudent ps', 'studiengang_kz'); + $result = $this->_ci->StudiengangModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]); + $stg = ''; + $orgform = ''; + if (hasData($result)) { + $studiengang = current(getData($result)); + $stg = $studiengang->bezeichnung; + } + if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG) + { + $resultPrestudentStatus = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail($antrag->prestudent_id); + if (isError($resultPrestudentStatus)) + $errors[] = getError($resultPrestudentStatus); + + else { + $prestudent_status = getData($resultPrestudentStatus)[0]; + $orgform = $prestudent_status->orgform_kurzbz; + + $vorlage ='Sancho_Mail_Antrag_A_Approve'; + $subject = $this->_ci->p->t('studierendenantrag', 'mail_subject_A_Approve'); + + $result = $this->pauseAntrag($studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_DEREGISTERED); + if (isError($result)) + $errors[] = getError($result); + + $this->_ci->load->model('crm/Statusgrund_model', 'StatusgrundModel'); + $result = $this->_ci->StatusgrundModel->loadWhere(['statusgrund_kurzbz' => 'abbrecherStud']); + if (isError($result)) { + $errors[] = getError($result); + continue; + } elseif (!hasData($result)) { + $errors[] = $this->_ci->p->t('lehre', 'error_noStatusgrund', ['statusgrund_kurzbz' => 'abbrecherStud']); + continue; + } + $statusgrund = current(getData($result)); + + $result = $this->_ci->prestudentlib->setAbbrecher( + $antrag->prestudent_id, + $antrag->studiensemester_kurzbz, + $insertvon, + $statusgrund->statusgrund_id, + $antrag->datum, + $insertam + ); + if (isError($result)) { + $errors[] = getError($result); + continue; + } + + $result = $this->_ci->PersonModel->loadPrestudent($antrag->prestudent_id); + $data = [ + 'student' => $this->_ci->p->t('person', 'studentIn'), + 'sem' => $antrag->studiensemester_kurzbz, + 'linkPdf' => base_url('content/pdfExport.php?xml=Antrag' . + $antrag->typ . + '.xml.php&xsl=Antrag' . + $antrag->typ . + '&id=' . + $antrag->studierendenantrag_id . + '&output=pdf') + ]; + if (hasData($result)) { + $person = current(getData($result)); + $data['student'] = trim($person->vorname . ' ' . $person->nachname); + $data['vorname'] = $person->vorname; + $data['nachname'] = $person->nachname; + } + $result = $this->_ci->StudentModel->loadWhere(['prestudent_id'=> $antrag->prestudent_id]); + if (hasData($result)) { + $student = current(getData($result)); + $data['UID'] = $student->student_uid; + } + + $data['Orgform'] = $prestudent_status->orgform; + $data['stg'] = $stg; + + // NOTE(chris): Sancho mail + sendSanchoMail($vorlage, $data, $prestudent_status->email, $subject); + } + } else { // ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL) + $result = $this->pauseAntrag($studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL); + if (isError($result)) + $errors[] = getError($result); + + $result = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail($antrag->prestudent_id, '', 'Student'); + if (isError($result)) + { + $errors[] = getError($result); + continue; + } + if(!hasData($result)) + { + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', ['prestudent_id' => $antrag->prestudent_id]); + continue; + } + $prestudentstatus = getData($result)[0]; + $orgform = $prestudentstatus->orgform_kurzbz; + + $result = $this->_ci->PrestudentstatusModel->withGrund('preabbrecher')->update([ + 'prestudent_id' => $prestudentstatus->prestudent_id, + 'status_kurzbz'=>$prestudentstatus->status_kurzbz, + 'studiensemester_kurzbz'=>$prestudentstatus->studiensemester_kurzbz, + 'ausbildungssemester'=>$prestudentstatus->ausbildungssemester + ], []); + if (isError($result)) + { + $errors[] = getError($result); + continue; + } + } + + $res = $this->_ci->PrestudentModel->load($antrag->prestudent_id); + + if (hasData($res)) { + $prestudent = current(getData($res)); + $res = $this->_ci->PersonModel->load($prestudent->person_id); + if (hasData($res)) { + $person = current(getData($res)); + $name = trim($person->vorname . ' ' . $person->nachname); + $vorname = $person->vorname; + $nachname = $person->nachname; + } else { + $name = $this->_ci->p->t('person', 'studentIn'); + $vorname = ''; + $nachname = $name; + } + $res = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]); + if (hasData($res)) { + $email = $this->_ci->StudentModel->getEmailFH(current(getData($res))->student_uid); + $vorlage = $antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG ? 'Student' : 'Stgl'; + + // NOTE(chris): Sancho mail + sendSanchoMail( + 'Sancho_Mail_Antrag_A_' . $vorlage, + [ + 'name' => $name, + 'grund' => $antrag->grund, + 'vorname' => $vorname, + 'nachname' => $nachname, + 'Orgform' => $orgform, + 'stg' => $stg + ], + $email, + $this->_ci->p->t('studierendenantrag', 'mail_subject_A_' . $vorlage) + ); + } + } + } + } + + if (count($errors)) + return error(implode(',', $errors)); + + return success(); + } + + /** + * @param integer $studierendenantrag_id + * @param string $insertvon + * + * @return stdClass + */ + public function denyObjectionAbmeldung($studierendenantrag_id, $insertvon, $grund = null) + { + $result = $this->_ci->StudierendenantragModel->load($studierendenantrag_id); + if (isError($result)) + { + return $result; + } + if(!hasData($result)) + { + return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id])); + } + $antrag = getData($result)[0]; + + $result = $this->_ci->StudierendenantragstatusModel->loadWhere([ + 'studierendenantrag_id' => $studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED + ]); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_not_approved')); + + $status = current(getData($result)); + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_OBJECTION_DENIED, + 'grund' => $grund, + 'insertvon' => $insertvon + ]); + if (isError($result)) + return $result; + else { + $result = $this->pauseAntrag($studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_DEREGISTERED); + // NOTE(chris): here we should have error handling but at the + // moment there is no way to notify the user for "soft" errors + + $this->_ci->load->model('crm/Statusgrund_model', 'StatusgrundModel'); + $result = $this->_ci->StatusgrundModel->loadWhere(['statusgrund_kurzbz' => 'abbrecherStgl']); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('lehre', 'error_noStatusgrund', ['statusgrund_kurzbz' => 'abbrecherStgl'])); + + $statusgrund = current(getData($result)); + + $result = $this->_ci->prestudentlib->setAbbrecher( + $antrag->prestudent_id, + $antrag->studiensemester_kurzbz, + $insertvon, + $statusgrund->statusgrund_id, + $status->insertamum + ); + + if (isError($result)) + return $result; + + $res = $this->_ci->PrestudentModel->load($antrag->prestudent_id); + + if (hasData($res)) { + $this->_ci->load->model('crm/Student_model', 'StudentModel'); + + $prestudent = current(getData($res)); + $res = $this->_ci->PersonModel->load($prestudent->person_id); + if (hasData($res)) { + $person = current(getData($res)); + $name = trim($person->vorname . ' ' . $person->nachname); + $vorname = $person->vorname; + $nachname = $person->nachname; + } else { + $name = $this->_ci->p->t('person', 'studentIn'); + } + + $res = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]); + if (hasData($res)) { + $email = $this->_ci->StudentModel->getEmailFH(current(getData($res))->student_uid); + + $res = $this->_ci->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id); + $stg = ''; + $orgform = ''; + if (hasData($res)) { + $studiengang = current(getData($res)); + $stg = $studiengang->bezeichnung; + $orgform = $studiengang->orgform_kurzbz; + } + + sendSanchoMail( + 'Sancho_Mail_Antrag_A_ObjDenied', + [ + 'name' => $name, + 'vorname' => $vorname, + 'nachname' => $nachname, + 'grund' => $grund, + 'Orgform' => $orgform, + 'stg' => $stg + ], + $email, + $this->_ci->p->t('studierendenantrag', 'mail_subject_A_ObjectionDenied') + ); + } + } + } + + return success(); + } + + /** + * NOTE(chris): permissions & verification must be handled outside + * + * @param integer $prestudent_id + * @param string $studiensemester_kurzbz + * @param string $insertvon + * @param string $grund + * @param string $datum_wiedereinstieg + * + * @return stdClass + */ + public function createUnterbrechung($prestudent_id, $studiensemester_kurzbz, $insertvon, $grund, $datum_wiedereinstieg, $dms_id) + { + $datum_wiedereinstieg = new DateTime($datum_wiedereinstieg); + $datum_wiedereinstieg = $datum_wiedereinstieg->format("Y-m-d"); + $result = $this->_ci->StudierendenantragModel->insert([ + 'prestudent_id' => $prestudent_id, + 'studiensemester_kurzbz'=> $studiensemester_kurzbz, + 'datum' => date('c'), + 'typ' => Studierendenantrag_model::TYP_UNTERBRECHUNG, + 'insertvon' => $insertvon, + 'grund' => $grund, + 'datum_wiedereinstieg' => $datum_wiedereinstieg, + 'dms_id' => $dms_id + ]); + + if (isError($result)) + return $result; + + $antrag_id = getData($result); + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED, + 'insertvon' => $insertvon + ]); + + if (isError($result)) + return $result; + + return success($antrag_id); + } + + + /** + * @param array $studierendenantrag_ids + * @param string $insertvon + * + * @return stdClass + */ + public function approveUnterbrechung($studierendenantrag_ids, $insertvon) + { + $this->_ci->load->model('person/Kontakt_model', 'KontaktModel'); + $this->_ci->load->model('crm/Student_model', 'StudentModel'); + + $errors = []; + + foreach ($studierendenantrag_ids as $studierendenantrag_id) + { + $data = $this->getDataForUnterbrechung($studierendenantrag_id); + + if (isError($data)) { + $error_msg = getError($data); + if (is_array($error_msg) && isset($error_msg['message'])) + $error_msg = $error_msg['message']; + + $errors['failed_' . $studierendenantrag_id] = 'Could not approve Unterbrechung for studierendenantrag_id: ' . + $studierendenantrag_id . + '
Details:
' . + $error_msg; + } else { + $data = getData($data); + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED, + 'insertvon' => $insertvon + ]); + if (isError($result)) + { + $errors['failed_' . $studierendenantrag_id] = $this->_ci->p->t('studierendenantrag', 'error_U_Approve', [ + 'studierendenantrag_id' => $studierendenantrag_id, + 'message' => getError($result)['message'] + ]); + } + else + { + $studierendenantrag_status_id = getData($result); + $resultAntrag = $this->_ci->StudierendenantragModel->load($studierendenantrag_id); + if (isError($resultAntrag)) + return $resultAntrag; + $resultAntrag = getData($resultAntrag); + if (!$resultAntrag) + return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id])); + $resultAntrag = current($resultAntrag); + + // Prestudentstatus und Unterbrechungsfolgeaktionen setzen + $result = $this->_ci->prestudentlib->setUnterbrecher( + $resultAntrag->prestudent_id, + $resultAntrag->studiensemester_kurzbz, + $studierendenantrag_id + ); + + if (isError($result)) { + $this->_ci->StudierendenantragstatusModel->delete($studierendenantrag_status_id); + return $result; + } + + + //Mail + $subject = $this->_ci->p->t('studierendenantrag', 'mail_subject_U_Approve'); + $mail = []; + + if (isset($data['errors']['person_id'])) + { + //send assistenz mit id + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_and_name', ['message' => $data['errors']['person_id']]); + $mail['ass'] = $this->_ci->p->t('studierendenantrag', 'StudentIn', ['prestudent_id' => $data['antrag']->prestudent_id]); + } + elseif (isset($data['errors']['email'])) + { + if (isset($data['errors']['person'])) + { + //send assistenz mit id + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_and_name', [ + 'message' => $data['errors']['email'] . '
' . $data['errors']['person'] + ]); + $mail['ass'] = $this->_ci->p->t('studierendenantrag', 'StudentIn', ['prestudent_id' => $data['antrag']->prestudent_id]); + } + else + { + //send assistenz mit name + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail', ['message' => $data['errors']['email']]); + $mail['ass'] = trim($data['person']->vorname . ' ' . $data['person']->nachname); + } + } + else + { + if (isset($data['errors']['person'])) + { + //send assistenz mit id & student mit "Student/in" + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_name', ['message' => $data['errors']['person']]); + $mail['ass'] = $this->_ci->p->t('studierendenantrag', 'StudentIn', ['prestudent_id' => $data['antrag']->prestudent_id]); + $mail['stu'] = $this->_ci->p->t('person', 'StudentIn'); + } + else + { + //send normal + $mail['ass'] = $mail['stu'] = trim($data['person']->vorname . ' ' . $data['person']->nachname); + } + } + + if (isset($mail['ass'])) { + // NOTE(chris): Sancho mail + $mailVorlage = 'Sancho_Mail_Antrag_U_Approve'; + + $result = $this->_ci->StudentModel->loadWhere(['prestudent_id'=> $data['antrag']->prestudent_id]); + if (hasData($result)) { + $student = current(getData($result)); + $data['UID'] = $student->student_uid; + } + + $result = $this->_ci->PersonModel->getFullName($insertvon); + if (isError($result)) + return $result; + $approvedBy = $insertvon; + if (hasData($result)) + { + $approvedBy = getData($result); + } + + if (!sendSanchoMail( + $mailVorlage, + [ + 'name' => $mail['ass'], + 'stg' => $data['studiengang']->bezeichnung, + 'Orgform' => $data['prestudent_status']->orgform_kurzbz, + 'vorname' => $data['person']->vorname, + 'nachname' => $data['person']->nachname, + 'UID' => $data['UID'], + 'sem' => $resultAntrag->studiensemester_kurzbz, + 'linkPdf' => base_url( + 'content/pdfExport.php?xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&id=' . + $studierendenantrag_id . + '&output=pdf' + ), + 'insertvon' => $approvedBy + ], + $data['prestudent_status']->email, + $subject + )) { + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_to', $data['prestudent_status']); + } + } + if (isset($mail['stu'])) { + // NOTE(chris): Sancho mail + $mailVorlage = 'Sancho_Mail_Antrag_U_Student'; + if ($data['studienbeitrag']) + $mailVorlage .= '_SB'; + if (!sendSanchoMail( + $mailVorlage, + [ + 'name' => $mail['stu'], + 'stg' => $data['studiengang']->bezeichnung, + 'Orgform' => $data['prestudent_status']->orgform_kurzbz, + 'vorname' => $data['person']->vorname, + 'nachname' => $data['person']->nachname + ], + $data['email'], + $subject + )) { + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_to', $data); + } + } + } + } + } + + if (count($errors)) + return error($errors); + + return success(); + } + + /** + * @param array $studierendenantrag_ids + * @param string $insertvon + * @param string $grund + * + * @return stdClass + */ + public function rejectUnterbrechung($studierendenantrag_ids, $insertvon, $grund) + { + $this->_ci->load->model('person/Kontakt_model', 'KontaktModel'); + $this->_ci->load->model('crm/Student_model', 'StudentModel'); + + $errors = []; + + foreach ($studierendenantrag_ids as $studierendenantrag_id) { + $data = $this->getDataForUnterbrechung($studierendenantrag_id); + + if (isError($data)) { + $error_msg = getError($data); + if (is_array($error_msg) && isset($error_msg['message'])) + $error_msg = $error_msg['message']; + + $errors['failed_' . $studierendenantrag_id] = $this->_ci->p->t('studierendenantrag', 'error_U_Reject', [ + 'studierendenantrag_id' => $studierendenantrag_id, + 'message' => $error_msg + ]); + } else { + $data = getData($data); + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_REJECTED, + 'insertvon' => $insertvon, + 'grund' => $grund + ]); + if (isError($result)) { + $errors['failed_' . $studierendenantrag_id] = $this->_ci->p->t('studierendenantrag', 'error_U_Reject', [ + 'studierendenantrag_id' => $studierendenantrag_id, + 'message' => getError($result)['message'] + ]); + } else { + $name = ''; + + if (isset($data['errors']['person_id']) || isset($data['errors']['email'])) { + $error_msg = []; + if (isset($data['errors']['person_id'])) + $error_msg[] = $data['errors']['person_id']; + if (isset($data['errors']['email'])) + $error_msg[] = $data['errors']['email']; + $error_msg = $this->_ci->p->t('studierendenantrag', 'error_mail', ['message' => implode('
', $error_msg)]); + $errors[] = $error_msg; + } else { + if (isset($data['errors']['person'])) { + //send student mit "Student/in" + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_name', ['message' => $data['errors']['person']]); + $name = $this->_ci->p->t('person', 'studentIn'); + $vorname = ""; + $nachname = $name; + } else { + //send normal + $name = trim($data['person']->vorname . ' ' . $data['person']->nachname); + $vorname = $data['person']->vorname; + $nachname = $data['person']->nachname; + } + } + if ($name) + // NOTE(chris): Sancho mail + if (!sendSanchoMail( + 'Sancho_Mail_Antrag_U_Reject', + [ + 'name' => $name, + 'vorname' => $vorname, + 'nachname' => $nachname, + 'grund' => $grund, + 'stg' => $data['studiengang']->bezeichnung, + 'Orgform' => $data['prestudent_status']->orgform_kurzbz, + 'prestudent_id' => $data['prestudent_status']->prestudent_id, + 'abmeldungLink' => site_url('lehre/Studierendenantrag/abmeldung/' . $data['prestudent_status']->prestudent_id), + 'abmeldungLinkCIS' => CIS_ROOT . + 'index.ci.php/lehre/Studierendenantrag/abmeldung/' . + $data['prestudent_status']->prestudent_id + ], + $data['email'], + $this->_ci->p->t('studierendenantrag', 'mail_subject_U_Reject') + )) + $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_to', $data); + } + } + } + + if (count($errors)) + return error($errors); + + return success(); + } + + /** + * @param integer $studierendenantrag_id + * + * @return array + */ + private function getDataForUnterbrechung($studierendenantrag_id) + { + $result = []; + $errors = []; + + $res = $this->_ci->StudierendenantragModel->load($studierendenantrag_id); + if (isError($res)) + return $res; + + $res = getData($res); + if (!$res) + return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id])); + + $result['antrag'] = $antrag = current($res); + $this->_ci->StudiengangModel->addJoin('public.tbl_prestudent ps', 'studiengang_kz'); + $res = $this->_ci->StudiengangModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]); + if (hasData($res)) { + $result['studiengang'] = current(getData($res)); + } + else{ + $result['studiengang'] = new stdClass(); + $result['studiengang']->bezeichnung = ""; + } + + $res = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail($antrag->prestudent_id); + if (isError($res)) + return $res; + + $res = getData($res); + if (!$res) + return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', $antrag)); + + $result['prestudent_status'] = current($res); + + + $res = $this->_ci->PrestudentModel->load($antrag->prestudent_id); + + if (isError($res)) { + $errors['person_id'] = getError($res); + } else { + $res = getData($res); + if (!$res) { + $errors['person_id'] = $this->_ci->p->t('studierendenantrag', 'error_no_prestudent', $antrag); + } else { + $person_id = current($res)->person_id; + + $res = $this->_ci->PersonModel->load($person_id); + if (isError($res)) { + $errors['person'] = getError($res); + } else { + $res = getData($res); + if (!$res) { + $errors['person'] = $this->_ci->p->t('studierendenantrag', 'error_no_person', ['person_id' => $person_id]); + } else { + $result['person'] = current($res); + } + } + + $res = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]); + if (isError($res)) { + $errors['email'] = getError($res); + } else { + $res = getData($res); + + if (!$res) { + $errors['email'] = $this->_ci->p->t('studierendenantrag', 'error_no_email', ['person_id' => $person_id]); + } else { + $result['email'] = $this->_ci->StudentModel->getEmailFH(current($res)->student_uid); + } + } + } + } + + $result['studienbeitrag'] = false; + if (!isset($errors['person_id'])) { + $date_target = new DateTime( + $this->_ci->config->item('frist_rueckzahlung_studiengebuer_' . substr($result['antrag']->studiensemester_kurzbz, 0, 2)) . + substr($result['antrag']->studiensemester_kurzbz, 2) + ); + $date_created = new DateTime($result['antrag']->datum); + if ($date_created < $date_target) { + $this->_ci->load->model('crm/Konto_model', 'KontoModel'); + $result['studienbeitrag'] = $this->_ci->KontoModel->checkStudienbeitragFromPerson( + $person_id, + $result['antrag']->studiensemester_kurzbz + ); + } + } + + $result['errors'] = $errors; + + return success($result); + } + + /** + * @param integer $prestudent_id + * @param string $studiensemester_kurzbz + * @param string $insertvon + * @param boolean $repeat + * + * @return stdClass + */ + public function createWiederholung($prestudent_id, $studiensemester_kurzbz, $insertvon, $repeat) + { + $result = $this->_ci->StudierendenantragModel->loadIdAndStatusWhere([ + 'tbl_studierendenantrag.prestudent_id' => $prestudent_id, + 'studiensemester_kurzbz'=> $studiensemester_kurzbz, + 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG + ]); + + $antrag_id = null; + if (hasData($result)) { + $antrag = current(getData($result)); + if ($antrag->status == Studierendenantragstatus_model::STATUS_REOPENED || + $antrag->status == Studierendenantragstatus_model::STATUS_REQUESTSENT_1 || + $antrag->status == Studierendenantragstatus_model::STATUS_REQUESTSENT_2) + { + $antrag_id = $antrag->studierendenantrag_id; + } + else + { + return error($this->_ci->p->t('global', 'antragBereitsGestellt')); + } + } + + if ($antrag_id === null) { + $result = $this->_ci->StudierendenantragModel->insert([ + 'prestudent_id' => $prestudent_id, + 'studiensemester_kurzbz'=> $studiensemester_kurzbz, + 'datum' => date('c'), + 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG, + 'insertvon' => $insertvon + ]); + + if (isError($result)) + return $result; + + $antrag_id = getData($result); + } + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz' => $repeat + ? Studierendenantragstatus_model::STATUS_CREATED + : Studierendenantragstatus_model::STATUS_PASS, + 'insertvon' => $insertvon + ]); + + if ($repeat) { + $res = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail($prestudent_id); + if (isError($res)) + return $res; + $res = getData($res); + if (!$res) + return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', ['prestudent_id' => $prestudent_id])); + + $prestudent_status = current($res); + $email = $prestudent_status->email; + // NOTE(chris): Sancho mail + $lvzuweisungLink = site_url('lehre/Antrag/Wiederholung/assistenz/' . $antrag_id); + if (defined('VILESCI_ROOT')) { + $lvzuweisungLink = VILESCI_ROOT . 'index.ci.php/lehre/Antrag/Wiederholung/assistenz/' . $antrag_id; + } + sendSanchoMail( + 'Sancho_Mail_Antrag_W_New', + [ + 'antrag_id' => $antrag_id, + 'stg' => $prestudent_status->stg_bezeichnung, + 'Orgform' => $prestudent_status->orgform, + 'lvzuweisungLink' => $lvzuweisungLink + ], + $email, + $this->_ci->p->t('studierendenantrag', 'mail_subject_W_New') + ); + } + + if (isError($result)) + return $result; + + return success($antrag_id); + } + + /** + * @param integer $studierendenantrag_id + * @param string $insertvon + * + * @return stdClass + */ + public function reopenWiederholung($studierendenantrag_id, $insertvon) + { + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_REOPENED, + 'insertvon' => $insertvon + ]); + return $result; + } + + /** + * @param integer $studierendenantrag_id + * @param string $objectedvon + * + * @return stdClass + */ + public function objectAbmeldung($studierendenantrag_id, $objectedvon) + { + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $studierendenantrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_OBJECTED, + 'insertvon' => $objectedvon + ]); + return $result; + } + + public function getWiederholungsAntraege($status) + { + $studiengaenge = $this->_ci->permissionlib->getSTG_isEntitledFor('student/studierendenantrag'); + $result = $this->_ci->StudierendenantragModel->loadForStudiengaenge( + $studiengaenge, + Studierendenantrag_model::TYP_WIEDERHOLUNG, + $status + ); + if (!getData($result)) + return $result; + $result = getData($result); + $grouped = []; + + foreach ($result as $item) { + if (!isset($grouped[$item->studiengang_kz])) { + $grouped[$item->studiengang_kz] = [ + 'bezeichnung' => $item->bezeichnung, + 'bezeichnung_mehrsprachig' => $item->bezeichnung_mehrsprachig, + 'antraege' => [] + ]; + } + $grouped[$item->studiengang_kz]['antraege'][] = $item; + } + + return success($grouped); + } + + public function getLvsForAntrag($antrag_id) + { + $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $result = $this->_ci->StudierendenantragModel->load($antrag_id); + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $antrag_id])); + $antrag = current($result); + + + $result = $this->_ci->StudierendenantragModel->getStgAndSem($antrag_id); + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_stg_and_sem', ['id' => $antrag_id])); + $result = current($result); + $studiengang_kz = $result->studiengang_kz; + $orgform_kurzbz = $result->orgform_kurzbz; + $ausbildungssemester = $result->ausbildungssemester; + $sprache = $result->sprache; + + // NOTE(chris): check permission + $allowedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('student/studierendenantrag') ?: []; + if (!in_array($studiengang_kz, $allowedStgs)) { + $allowedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('student/antragfreigabe') ?: []; + if (!in_array($studiengang_kz, $allowedStgs)) { + if(!$this->isOwnAntrag($antrag_id)) + return error('Forbidden'); + } + } + + + $result = $this->_ci->StudiensemesterModel->getNextFrom($antrag->studiensemester_kurzbz); + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_sem_after', ['semester' => $antrag->studiensemester_kurzbz])); + $semA = current($result)->studiensemester_kurzbz; + + $result = $this->_ci->StudiensemesterModel->getNextFrom($semA); + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_sem_after', ['semester' => $semA])); + $semB = current($result)->studiensemester_kurzbz; + + $result = $this->_ci->StudierendenantraglehrveranstaltungModel->loadWhere(['studierendenantrag_id' => $antrag_id]); + if (isError($result)) + return $result; + $result = getData($result) ?: []; + + $lvszugewiesen = array(); + foreach ($result as $lv) + { + $lvszugewiesen[$lv->lehrveranstaltung_id] = $lv; + } + + $result = $this->getLvsByStgStsemAndSem( + $studiengang_kz, + $orgform_kurzbz, + $semA, + $ausbildungssemester + 1, + $antrag->prestudent_id, + $sprache + ); + if (isError($result)) + return $result; + $lvsA = $result->retval; // NOTE(chris): don't use getData() because we want to differenciate [] and null + $repeat_last = false; + if ($lvsA) { + foreach($lvsA as $lv) + { + if (isset($lvszugewiesen[$lv->lehrveranstaltung_id]) && + ($lvszugewiesen[$lv->lehrveranstaltung_id]->note == $this->_ci->config->item('wiederholung_note_nicht_zugelassen'))) + { + $lv->antrag_zugelassen = true; + $lv->antrag_anmerkung = $lvszugewiesen[$lv->lehrveranstaltung_id]->anmerkung; + } + } + } elseif ($lvsA === null) { + // NOTE(chris): We are repeating the last semester + $repeat_last = true; + + $result = $this->_ci->PrestudentstatusModel->getStatusByFilter($antrag->prestudent_id, 'Student', $ausbildungssemester - 1); + if (isError($result)) + return $result; + + $stdsems = getData($result) ?: []; + $stdsem = null; + + $result = $this->_ci->StudiensemesterModel->load($antrag->studiensemester_kurzbz); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t( + 'studierendenantrag', + 'error_no_stdsem', + ['studiensemester_kurzbz' => $antrag->studiensemester_kurzbz] + )); + $asem = current(getData($result)); + + foreach ($stdsems as $sem) { + $result = $this->_ci->StudiensemesterModel->load($sem->studiensemester_kurzbz); + if (isError($result)) + return $result; + if (hasData($result)) { + if (current(getData($result))->start < $asem->start) { + $stdsem = $sem->studiensemester_kurzbz; + break; + } + } + } + + // NOTE(chris): if we don't find a status in the previous semester there is something wrong + if (!$stdsem) + return error($this->_ci->p->t('studierendenantrag', 'error_no_status_in_prev_sem')); + + $result = $this->getLvsByStgStsemAndSem( + $studiengang_kz, + $orgform_kurzbz, + $semA, + $ausbildungssemester - 1, + $antrag->prestudent_id, + $sprache + ); + if (isError($result)) + return $result; + + $lvsA = getData($result) ?: []; + + $result = $this->getLvsByStgStsemAndSem( + $studiengang_kz, + $orgform_kurzbz, + $stdsem, + $ausbildungssemester - 1, + $antrag->prestudent_id, + $sprache + ); + if (isError($result)) + return $result; + + $lvsAtest = getData($result) ?: []; + + if (count(array_intersect(array_map(function ($a) { + return $a->lehrveranstaltung_id; + }, $lvsA), array_map(function ($a) { + return $a->lehrveranstaltung_id; + }, $lvsAtest)))) { + foreach ($lvsA as $lv) { + if (isset($lvszugewiesen[$lv->lehrveranstaltung_id]) && ($lvszugewiesen[$lv->lehrveranstaltung_id]->note == 0)) { + $lv->antrag_anmerkung = $lvszugewiesen[$lv->lehrveranstaltung_id]->anmerkung; + $lv->antrag_zugelassen = true; + } + } + } else { + $lvsA = null; + } + } + + $result = $this->getLvsByStgStsemAndSem( + $studiengang_kz, + $orgform_kurzbz, + $semB, + $ausbildungssemester, + $antrag->prestudent_id, + $sprache + ); + if (isError($result)) + return $result; + $lvsB = getData($result) ?: []; + foreach($lvsB as $lv) + { + if(isset($lvszugewiesen[$lv->lehrveranstaltung_id]) && ($lvszugewiesen[$lv->lehrveranstaltung_id]->note == 0)) + { + $lv->antrag_anmerkung = $lvszugewiesen[$lv->lehrveranstaltung_id]->anmerkung; + $lv->antrag_zugelassen = true; + } + // TODO(manu): eventuelle Änderungen taggen + } + + $result = [ + '1' . $semA => $lvsA, + '2' . $semB => $lvsB ?: [] + ]; + if ($repeat_last) + $result['repeat_last'] = true; + + return success($result); + } + + public function getLvsByStgStsemAndSem( + $studiengang_kz, + $orgform_kurzbz, + $studiensemester_kurzbz, + $ausbildungssemester, + $prestudent_id, + $sprache + ) { + $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $result = $this->_ci->StudienplanModel->getStudienplaeneBySemester( + $studiengang_kz, + $studiensemester_kurzbz, + $ausbildungssemester, + $orgform_kurzbz + ); + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) { + $result = $this->_ci->StudiengangModel->load($studiengang_kz); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_stg', ['studiengang_kz' => $studiengang_kz])); + $stg = current(getData($result)); + + if ($ausbildungssemester > $stg->max_semester) + return success(); + return error($this->_ci->p->t('studierendenantrag', 'error_no_studienplan', [ + 'studiengang_kz' => $studiengang_kz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'semester' => $ausbildungssemester + ])); + } + if (count($result) > 1) { + $langmap = array_unique(array_map(function ($a) { + return $a->sprache; + }, $result)); + if ($sprache + && count($langmap) == count($result) + && in_array($sprache, $langmap) + ) { + $result = array_filter($result, function ($a) use ($sprache) { + return $a->sprache == $sprache; + }); + } else { + return error($this->_ci->p->t('studierendenantrag', 'error_multiple_studienplan', [ + 'studiengang_kz' => $studiengang_kz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'semester' => $ausbildungssemester + ])); + } + } + $studienplan = current($result); + + return $this->_ci->StudienplanModel->getStudienplanLehrveranstaltungForPrestudent( + $studienplan->studienplan_id, + $ausbildungssemester, + $prestudent_id + ); + } + + /** + * Checks if a prestudent can submit an Antrag for Abmeldung + * + * @param integer $prestudent_id + * + * @return \stdClass on success retval 0 means not a student; + * retval 1 means Berechtigt; + * retval -1 means has already an Antrag pending; + * retval -2 means other Antrag pending; + * retval -3 means in blacklist stg + */ + public function getPrestudentAbmeldeBerechtigt($prestudent_id) + { + $result = $this->_ci->PrestudentModel->load($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(0); + $result = current(getData($result)); + $stg_kz = $result->studiengang_kz; + if (in_array($stg_kz, $this->_ci->config->item('stgkz_blacklist_abmeldung'))) + return success(-3); + + $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(0); + $result = current(getData($result)); + $datumStatus = $result->datum; + + if (!in_array($result->status_kurzbz, $this->_ci->config->item('antrag_prestudentstatus_whitelist_abmeldung'))) { + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([ + 'tbl_studierendenantrag.prestudent_id' => $prestudent_id, + 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED + ], [ + Studierendenantrag_model::TYP_ABMELDUNG, + Studierendenantrag_model::TYP_ABMELDUNG_STGL + ]); + if (isError($result)) + return $result; + if (hasData($result)) + return success(-1); + + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([ + 'tbl_studierendenantrag.prestudent_id' => $prestudent_id, + 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE + ], [ + Studierendenantrag_model::TYP_ABMELDUNG, + Studierendenantrag_model::TYP_ABMELDUNG_STGL + ]); + if (isError($result)) + return $result; + if (hasData($result)) + return success(-1); + + return success(0); + } + + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(1); + $result= getData($result); + foreach ($result as $antrag) + { + if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG || $antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL) + { + if ($antrag->status == Studierendenantragstatus_model::STATUS_CREATED) + return success(-1); + elseif ($antrag->status == Studierendenantragstatus_model::STATUS_APPROVED && $antrag->datum > $datumStatus) + return success(-1); + } + if ($antrag->typ == Studierendenantrag_model::TYP_WIEDERHOLUNG) + { + if($antrag->status == Studierendenantragstatus_model::STATUS_PASS) + return success(-2); + } + } + + return success(1); + } + + /** + * Checks if a prestudent can submit an Antrag for Unterbrechung + * + * @param integer $prestudent_id + * @param string $studiensemester_kurzbz (optional) + * + * @return \stdClass on success retval 0 means not a student; + * retval 1 means Berechtigt; + * retval -1 means has already an Antrag pending; + * retval -2 means other Antrag pending; + * retval -3 means in blacklist stg + */ + public function getPrestudentUnterbrechungsBerechtigt($prestudent_id, $studiensemester_kurzbz = null, $datum_wiedereinstieg = null) + { + $result = $this->_ci->PrestudentModel->load($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(0); + $result = current(getData($result)); + $stg_kz = $result->studiengang_kz; + if (in_array($stg_kz, $this->_ci->config->item('stgkz_blacklist_unterbrechung'))) + return success(-3); + + $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(0); + $result = current(getData($result)); + $prestudent_stdsem = $result->studiensemester_kurzbz; + $datumStatus = $result->datum; + if (!in_array($result->status_kurzbz, $this->_ci->config->item('antrag_prestudentstatus_whitelist')) + && $result->status_kurzbz != 'Unterbrecher') { + return success(0); + } + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(1); + + $result = getData($result); + foreach ($result as $antrag) + { + if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG || $antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL) + { + if($antrag->status == Studierendenantragstatus_model::STATUS_CREATED) + return success(-2); + elseif($antrag->status == Studierendenantragstatus_model::STATUS_APPROVED && $antrag->datum > $datumStatus) + return success(-2); + } + if ($antrag->typ == Studierendenantrag_model::TYP_WIEDERHOLUNG) + { + if($antrag->status == Studierendenantragstatus_model::STATUS_PASS) + return success(-2); + } + } + + if (!$studiensemester_kurzbz) { + $sems = $this->getSemesterForUnterbrechung($prestudent_id, $prestudent_stdsem); + if (!count(array_filter($sems, function ($item) { + return !$item['disabled']; + }))) + return success(-1); + } else { + if ($this->_ci->StudierendenantragModel->hasRunningUnterbrechungBetween($prestudent_id, $studiensemester_kurzbz, $datum_wiedereinstieg)) + return success(-1); + } + + return success(1); + } + + /** + * Checks if a prestudent can submit an Antrag for Wiederholung + * + * @param integer $prestudent_id + * + * @return \stdClass on success retval 0 means not a student; + * retval 1 means Berechtigt; + * retval -1 means has already an Antrag pending; + * retval -2 means other Antrag pending; + * retval -3 means in blacklist stg + */ + public function getPrestudentWiederholungsBerechtigt($prestudent_id) + { + $result = $this->_ci->PrestudentModel->load($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(0); + $result = current(getData($result)); + $stg_kz = $result->studiengang_kz; + if (in_array($stg_kz, $this->_ci->config->item('stgkz_blacklist_wiederholung'))) + return success(-3); + + $result = $this->getFailedExamForPrestudent($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(0); + + $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(0); + + $result = current(getData($result)); + $datumStatus = $result->datum; + if (!in_array($result->status_kurzbz, $this->_ci->config->item('antrag_prestudentstatus_whitelist'))) { + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([ + 'tbl_studierendenantrag.prestudent_id' => $prestudent_id, + 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG, + 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED + ]); + if (isError($result)) + return $result; + if (hasData($result)) + return success(-1); + + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([ + 'tbl_studierendenantrag.prestudent_id' => $prestudent_id, + 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG, + 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED + ]); + if (isError($result)) + return $result; + if (hasData($result)) + return success(-1); + + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([ + 'tbl_studierendenantrag.prestudent_id' => $prestudent_id, + 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG, + 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE + ]); + if (isError($result)) + return $result; + if (hasData($result)) + return success(-1); + + return success(0); + } + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(1); + $result= getData($result); + foreach ($result as $antrag) + { + if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG || $antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL) + { + if($antrag->status == Studierendenantragstatus_model::STATUS_CREATED) + return success(-2); + elseif($antrag->status == Studierendenantragstatus_model::STATUS_APPROVED && $antrag->datum > $datumStatus) + return success(-2); + } + if ($antrag->typ == Studierendenantrag_model::TYP_WIEDERHOLUNG) + { + return success(-1); + } + } + + return success(1); + } + + /** + * Gets details for a new Antrag + * + * @param integer $prestudent_id + * + * @return \stdClass + */ + public function getDetailsForNewAntrag($prestudent_id) + { + $result = $this->_ci->PrestudentstatusModel->loadLastWithStgDetails($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', ['prestudent_id' => $prestudent_id])); + $result = current(getData($result)); + return success($result); + } + + /** + * Gets details for the latest Antrag of one or more types + * + * @param integer $prestudent_id + * @param array|string $typ + * + * @return \stdClass + */ + public function getDetailsForLastAntrag($prestudent_id, $typ = null) + { + $where = [ + 'tbl_studierendenantrag.prestudent_id' => $prestudent_id + ]; + $types = null; + if ($typ) { + if (is_array($typ)) + $types = $typ; + else + $where['typ'] = $typ; + } + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere($where, $types); + if (isError($result)) + return $result; + + $antraege = getData($result) ?: []; + $resultAntrag = null; + foreach ($antraege as $antrag) { + if ($antrag->status != Studierendenantragstatus_model::STATUS_CANCELLED) { + $resultAntrag = $antrag; + break; + } + } + if (!$resultAntrag) + return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found_prestudent', [ + 'typ' => $typ ?: '', + 'prestudent_id' => $prestudent_id + ])); + + return $this->addDetailsToAntrag($resultAntrag); + } + + /** + * Gets details for a specific Antrag + * + * @param integer $studierendenantrag_id + * + * @return \stdClass + */ + public function getDetailsForAntrag($studierendenantrag_id) + { + $where = [ + 's.studierendenantrag_id' => $studierendenantrag_id + ]; + + $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere($where); + if (isError($result)) + return $result; + + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', "error_no_antrag_found", ['id' => $studierendenantrag_id])); + $resultAntrag = current(getData($result)); + + return $this->addDetailsToAntrag($resultAntrag); + } + + /** + * Helper function for getDetailsForAntrag and getDetailsForLastAntrag + * + * @param \stdClass $antrag + * + * @return \stdClass + */ + protected function addDetailsToAntrag($antrag) + { + $result = $this->_ci->PrestudentstatusModel->loadLastWithStgDetails( + $antrag->prestudent_id, + $antrag->studiensemester_kurzbz, + $antrag->insertamum + ); + if (isError($result)) + return $result; + if (!hasData($result)) { + $result = $this->_ci->PrestudentstatusModel->loadLastWithStgDetails( + $antrag->prestudent_id, + null, + $antrag->insertamum + ); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudent_in_sem', $antrag)); + $tmp = current(getData($result)); + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $res = $this->_ci->StudiensemesterModel->load($antrag->studiensemester_kurzbz); + if (hasData($res)) + $tmp->studienjahr_kurzbz = current(getData($res))->studienjahr_kurzbz; + else + $tmp->studienjahr_kurzbz = ''; + // NOTE(chris): the semester might not be correct on this fallback so we disable it + $tmp->semester = ''; + } + + $result = current(getData($result)); + + $result->status = $antrag->status; + $result->statustyp = $antrag->statustyp; + $result->status_insertvon = $antrag->status_insertvon; + $result->grund = $antrag->grund; + $result->studierendenantrag_id = $antrag->studierendenantrag_id; + $result->typ = $antrag->typ; + $result->datum = $antrag->datum; + $result->dms_id = $antrag->dms_id; + $result->datum_wiedereinstieg = $antrag->datum_wiedereinstieg; + + return success($result); + } + + /** + * Rearrange the free semester slots for a new Unterbrechung + * + * @param integer $prestudent_id + * @param string $studiensemester_kurzbz + * + * @return array + */ + public function getSemesterForUnterbrechung($prestudent_id, $studiensemester_kurzbz) + { + $result = $this->_ci->StudierendenantragModel->getFreeSlotsForUnterbrechung($prestudent_id, $studiensemester_kurzbz); + if (isError($result)) + return []; + $result = getData($result); + if (!$result) + return []; + return array_reduce($result, function ($carry, $item) { + if (!isset($carry[$item->von])) + $carry[$item->von] = [ + 'studienjahr_kurzbz' => $item->studienjahr_kurzbz, + 'studiensemester_kurzbz' => $item->von, + 'wiedereinstieg' => [], + 'disabled' => true + ]; + + $carry[$item->von]['wiedereinstieg'][] = [ + 'studiensemester_kurzbz' => $item->bis, + 'start' => $item->ende, + 'disabled' => (boolean)$item->studierendenantrag_id + ]; + + if ($carry[$item->von]['disabled'] && !$item->studierendenantrag_id) { + $carry[$item->von]['disabled'] = false; + } + + return $carry; + }, []); + return $result; + } + + public function getAktivePrestudentenInStgs($studiengaenge, $query) + { + $blacklist = $this->_ci->config->item('stgkz_blacklist_abmeldung'); + $studiengaenge = array_diff($studiengaenge, $blacklist); + return $this->_ci->StudiengangModel->getAktivePrestudenten( + $studiengaenge, + [ Studierendenantrag_model::TYP_ABMELDUNG ], + $query + ); + } + + public function getFailedExamForPrestudent($prestudent_id, $max_date = null, $studiensemester_kurzbz = null) + { + return $this->_ci->PruefungModel->loadWhereCommitteeExamFailedForPrestudent($prestudent_id, $max_date, $studiensemester_kurzbz); + } + + public function saveLvs($lvArray) + { + $result = $this->_ci->StudierendenantraglehrveranstaltungModel->deleteWhere([ + 'studierendenantrag_id' => $lvArray[0]['studierendenantrag_id'] + ]); + if (isError($result)) + return $result; + + $result = $this->_ci->StudierendenantraglehrveranstaltungModel->insertBatch($lvArray); + if (isError($result)) + return $result; + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $lvArray[0]['studierendenantrag_id'], + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_LVSASSIGNED, + 'insertvon' => $lvArray[0]['insertvon'] + ]); + if (isError($result)) + return $result; + + $antrag_status_id = getData($result); + $result = $this->_ci->StudierendenantragstatusModel->loadWithTyp($antrag_status_id); + + return $result; + } + + public function approveWiederholung($antrag_id, $insertvon) + { + $this->_ci->load->model('crm/Student_model', 'StudentModel'); + + $result = $this->_ci->StudierendenantragstatusModel->insert([ + 'studierendenantrag_id' => $antrag_id, + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED, + 'insertvon' => $insertvon + ]); + + if (isError($result)) { + return $result; + } + + $result = $this->_ci->StudierendenantragModel->getStgEmail($antrag_id); + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_stg_email', ['id' => $antrag_id])); + + $email = current($result)->email; + + $result = $this->_ci->StudierendenantragModel->getStgAndSem($antrag_id); + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_stg_antrag', ['id' => $antrag_id])); + + $stg = current($result); + $semester = $stg->ausbildungssemester; + + $result = $this->_ci->StudierendenantragModel->load($antrag_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $antrag_id])); + $result = current(getData($result)); + $prestudent_id = $result->prestudent_id; + + $result = $this->_ci->PersonModel->loadPrestudent($prestudent_id); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_person_prestudent', ['prestudent_id' => $prestudent_id])); + $person = current(getData($result)); + $student = trim($person->vorname . ' ' . $person->nachname); + + $result = $this->_ci->PersonModel->getFullName($insertvon); + if (isError($result)) + return $result; + $mitarbeiter = $insertvon; + if (hasData($result)) { + $mitarbeiter = getData($result); + } + + $result = $this->_ci->StudentModel->loadWhere(['prestudent_id'=> $prestudent_id]); + if (hasData($result)) { + $studentObj = current(getData($result)); + $student_uid = $studentObj->student_uid; + } + else + $student_uid = ''; + + // NOTE(chris): Sancho mail + if (!sendSanchoMail( + 'Sancho_Mail_Antrag_W_Approve', + [ + 'antrag_id' => $antrag_id, + 'stg' => $stg->bezeichnung, + 'sem' => $semester, + 'student' => $student, + 'mitarbeiter' => $mitarbeiter, + 'Orgform' => $stg->orgform_kurzbz, + 'UID' => $student_uid + ], + $email, + $this->_ci->p->t('studierendenantrag', 'mail_subject_W_Approve') + )) + return error($this->_ci->p->t('studierendenantrag', 'error_mail_to', ['email' => $email])); + + if ($student_uid) { + $email = $this->_ci->StudentModel->getEmailFH($student_uid); + $vorlage = 'Sancho_Mail_Antrag_W_Student'; + + $sem_not_allowed = $sem_to_repeat = ''; + $list_not_allowed = $list_to_repeat = $this->_ci->p->t('studierendenantrag', 'mail_part_error_no_lvs'); + + $result = $this->getLvsForAntrag($antrag_id); + if (hasData($result)) { + $lvs = getData($result); + if (isset($lvs['repeat_last'])) { + unset($lvs['repeat_last']); + $vorlage .= '_Lst'; + } + foreach ($lvs as $sem => $lv_list) { + $lvs_filtered = array_filter($lv_list, function ($el) { + return property_exists($el, 'antrag_zugelassen') && $el->antrag_zugelassen; + }); + if (substr($sem, 0, 1) == '1') { + $sem_not_allowed = substr($sem, 1); + $list_not_allowed = array_map(function ($el) { + return $el->bezeichnung . '(' . $el->lehrform_kurzbz . ')'; + }, $lvs_filtered); + $list_not_allowed = '
  • ' . implode('
  • ', $list_not_allowed) . '
'; + } else { + $sem_to_repeat = substr($sem, 1); + $list_to_repeat = array_map(function ($el) { + return $el->bezeichnung . '(' . $el->lehrform_kurzbz . ')'; + }, $lvs_filtered); + $list_to_repeat = '
  • ' . implode('
  • ', $list_to_repeat) . '
'; + } + } + } + + // NOTE(chris): Sancho mail + sendSanchoMail( + $vorlage, + [ + 'antrag_id' => $antrag_id, + 'stg' => $stg->bezeichnung, + 'sem' => $semester, + 'mitarbeiter' => $mitarbeiter, + 'student' => $student, + 'sem_not_allowed' => $sem_not_allowed, + 'list_not_allowed' => $list_not_allowed, + 'sem_to_repeat' => $sem_to_repeat, + 'list_to_repeat' => $list_to_repeat, + 'Orgform' => $stg->orgform_kurzbz + ], + $email, + $this->_ci->p->t('studierendenantrag', 'mail_subject_W_Student') + ); + } + + + return success(); + } + + public function getAntragHistory($antrag_id) + { + $result = $this->_ci->StudierendenantragstatusModel->loadWithTypWhere([ + 'studierendenantrag_id' => $antrag_id + ]); + return $result; + } + + + /** + * @param integer $studierendenantrag_id + * + * @return boolean + */ + protected function isOwnAntrag($studierendenantrag_id) + { + if ($studierendenantrag_id == null) + return false; + $result = $this->_ci->StudierendenantragModel->loadForPerson(getAuthPersonId()); + if (!hasData($result)) + return false; + $antraege = array_map(function ($antrag) { + return $antrag->studierendenantrag_id; + }, getData($result)); + + return in_array($studierendenantrag_id, $antraege); + } + + /** + * @param integer $studierendenantrag_id + * @param string $permission either 'student/antragfreigabe' or 'student/studierendenantrag' + * + * @return boolean + */ + protected function hasAccessToAntrag($studierendenantrag_id, $permission) + { + $studiengaenge = $this->_ci->permissionlib->getSTG_isEntitledFor($permission); + if (!$studiengaenge) + return false; + $result = $this->_ci->StudierendenantragModel->isInStudiengang($studierendenantrag_id, $studiengaenge); + return (boolean)getData($result); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToShowAntrag($antrag_id) + { + return + ( + $this->isOwnAntrag($antrag_id) || + $this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') || + $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag') + ); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToSeeHistoryForAntrag($antrag_id) + { + return + ( + $this->isOwnAntrag($antrag_id) || + $this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') || + $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag') + ); + } + + /** + * @param integer $prestudent_id + * @param boolean $checkAssistencePermission + * + * @return boolean + */ + public function isEntitledToCreateAntragFor($prestudent_id, $checkAssistencePermission = false) + { + $result = $this->_ci->PrestudentModel->load($prestudent_id); + if (!hasData($result)) + return false; + + $result = getData($result)[0]; + $person_id = $result->person_id; + + if (getAuthPersonId() == $person_id) + return true; + + if ($checkAssistencePermission) + { + $studiengaenge = $this->_ci->permissionlib->getSTG_isEntitledFor('student/studierendenantrag'); + if (in_array($result->studiengang_kz, $studiengaenge ?: [])) + return true; + } + + return false; + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToCancelAntrag($antrag_id) + { + $result = $this->_ci->StudierendenantragModel->load($antrag_id); + if (!hasData($result)) + return false; + $antrag = current(getData($result)); + + if ($antrag->typ != Studierendenantrag_model::TYP_ABMELDUNG_STGL) + return $this->isOwnAntrag($antrag_id); + + return $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag'); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToPauseAntrag($antrag_id) + { + return ($this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') || $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag')); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToUnpauseAntrag($antrag_id) + { + return ($this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') || $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag')); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToReopenAntrag($antrag_id) + { + return $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag'); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToObjectAntrag($antrag_id) + { + return ($this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') || $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag')); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToApproveAntrag($antrag_id) + { + return $this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe'); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function isEntitledToRejectAntrag($antrag_id) + { + return $this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe'); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function antragCanBeManualPaused($antrag_id) + { + $this->_ci->StudierendenantragModel->db->where_not_in('campus.get_status_studierendenantrag(studierendenantrag_id)', [ + Studierendenantragstatus_model::STATUS_DEREGISTERED, + Studierendenantragstatus_model::STATUS_APPROVED, + Studierendenantragstatus_model::STATUS_PAUSE + ]); + $result = $this->_ci->StudierendenantragModel->loadWhere([ + 'studierendenantrag_id' => $antrag_id, + 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG + ]); + + return hasData($result); + } + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function antragCanBeManualUnpaused($antrag_id) + { + return $this->_ci->StudierendenantragModel->isManuallyPaused($antrag_id); + } + + /** + * @param integer $antrag_id + * @param string|array $status + * + * @return boolean + */ + public function hasStatus($antrag_id, $status) + { + $result = $this->_ci->StudierendenantragModel->getWithLastStatusWhere(['s.studierendenantrag_id' => $antrag_id]); + if (!hasData($result)) + return false; + $lastStatus = getData($result)[0]; + + if (!is_array($status)) + $status = [$status]; + + return in_array($lastStatus->studierendenantrag_statustyp_kurzbz, $status); + } + + /** + * @param integer $antrag_id + * @param string|array $type + * + * @return boolean + */ + public function hasType($antrag_id, $type) + { + $result = $this->_ci->StudierendenantragModel->load($antrag_id); + if (!hasData($result)) + return false; + $antrag = getData($result)[0]; + + if (!is_array($type)) + $type = [$type]; + + return in_array($antrag->typ, $type); + } + + + /** + * @param integer $antrag_id + * + * @return boolean + */ + public function getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz) + { + $result = $this->_ci->StudierendenantraglehrveranstaltungModel->getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz); + return $result; + } +} \ No newline at end of file diff --git a/application/libraries/DmsLib.php b/application/libraries/DmsLib.php index fccfe503b..774ebdc79 100644 --- a/application/libraries/DmsLib.php +++ b/application/libraries/DmsLib.php @@ -595,6 +595,8 @@ class DmsLib if (isError($insDmsResult)) return $insDmsResult; $upload_data['dms_id'] = getData($insDmsResult); + if(isset($upload_data['file_type']) && !isset($dms['mimetype'])) + $dms['mimetype'] = $upload_data['file_type']; // Insert DMS version $insVersionResult = $this->_ci->DmsVersionModel->insert( diff --git a/application/libraries/FilterCmptLib.php b/application/libraries/FilterCmptLib.php index 9d6dfa681..8b13ae3e5 100644 --- a/application/libraries/FilterCmptLib.php +++ b/application/libraries/FilterCmptLib.php @@ -1,4 +1,5 @@ _setSessionElement(FilterCmptLib::SESSION_SIDE_MENU, - $this->_generateFilterMenu($this->_app, $this->_datasetName)); + $this->_setSessionElement( + FilterCmptLib::SESSION_SIDE_MENU, + $this->_generateFilterMenu($this->_app, $this->_datasetName) + ); } return $saveCustomFilter; @@ -717,6 +723,7 @@ class FilterCmptLib $this->_filterKurzbz = null; $this->_query = null; $this->_requiredPermissions = null; + $this->_encryptedColumns = null; $this->_reloadDataset = true; // by default the dataset is NOT cached in session $this->_sessionTimeout = FilterCmptLib::SESSION_DEFAULT_TIMEOUT; @@ -727,6 +734,12 @@ class FilterCmptLib $this->_requiredPermissions = $filterCmptArray[FilterCmptLib::REQUIRED_PERMISSIONS]; } + // Retrieved the encrypted columns parameter if present + if (isset($filterCmptArray[FilterCmptLib::ENCRYPTED_COLUMNS])) + { + $this->_encryptedColumns = $filterCmptArray[FilterCmptLib::ENCRYPTED_COLUMNS]; + } + // Parameters needed to retrieve univocally a filter from DB if (isset($filterCmptArray[FilterCmptLib::APP])) { @@ -1129,7 +1142,7 @@ class FilterCmptLib $this->_ci->load->model('system/Filters_model', 'FiltersModel'); // Execute the given SQL statement suppressing error messages - $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery); + $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $this->_encryptedColumns); } return $dataset; diff --git a/application/libraries/FilterWidgetLib.php b/application/libraries/FilterWidgetLib.php index 19cdec848..9968767d9 100644 --- a/application/libraries/FilterWidgetLib.php +++ b/application/libraries/FilterWidgetLib.php @@ -1,7 +1,26 @@ . + */ + if (! defined('BASEPATH')) exit('No direct script access allowed'); +use \stdClass as stdClass; + /** * FilterWidget logic */ @@ -16,6 +35,7 @@ class FilterWidgetLib const SESSION_SELECTED_FIELDS = 'selectedFields'; const SESSION_COLUMNS_ALIASES = 'columnsAliases'; const SESSION_ADDITIONAL_COLUMNS = 'additionalColumns'; + const SESSION_ENCRYPTED_COLUMNS = 'encryptedColumns'; const SESSION_CHECKBOXES = 'checkboxes'; const SESSION_FILTERS = 'filters'; const SESSION_METADATA = 'datasetMetadata'; @@ -56,6 +76,7 @@ class FilterWidgetLib const ADDITIONAL_COLUMNS = 'additionalColumns'; const CHECKBOXES = 'checkboxes'; const COLUMNS_ALIASES = 'columnsAliases'; + const ENCRYPTED_COLUMNS = 'encryptedColumns'; // ...to format/mark records of a dataset const FORMAT_ROW = 'formatRow'; @@ -120,7 +141,7 @@ class FilterWidgetLib /** * Gets the CI instance and loads message helper */ - public function __construct($params = null) + public function __construct() { $this->_ci =& get_instance(); // get code igniter instance } @@ -367,7 +388,7 @@ class FilterWidgetLib /** * Retrieves the dataset from the DB */ - public function getDataset($datasetQuery) + public function getDataset($datasetQuery, $encryptedColumns) { $dataset = null; @@ -376,7 +397,7 @@ class FilterWidgetLib $this->_ci->load->model('system/Filters_model', 'FiltersModel'); // Execute the given SQL statement suppressing error messages - $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery); + $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $encryptedColumns); } return $dataset; @@ -390,7 +411,7 @@ class FilterWidgetLib public function getFilterName($filterJson) { $filterName = $filterJson->name; // always present, used as default - $trimedname = (isset($filterJson->namePhrase)?trim($filterJson->namePhrase):''); + // Filter name from phrases system if (isset($filterJson->namePhrase) && !isEmptyString($filterJson->namePhrase)) { @@ -451,7 +472,8 @@ class FilterWidgetLib if (in_array($selectedField, $fields)) { // If the selected field is present in the list of the selected fields by the current filter - if (($pos = array_search($selectedField, $selectedFields)) !== false) + $pos = array_search($selectedField, $selectedFields); + if ($pos !== false) { // Then remove it and shift the rest of elements by one if needed array_splice($selectedFields, $pos, 1); @@ -750,7 +772,6 @@ class FilterWidgetLib $this->_ci->load->library('NavigationLib', array(self::NAVIGATION_PAGE => $navigationPage)); $filterMenu = null; - $currentMenu = $this->_ci->navigationlib->getSessionMenu(); // The navigation menu currently stored in session $session = $this->getSession(); // The filter currently stored in session (the one that is currently used) if ($session != null) diff --git a/application/libraries/IssuesLib.php b/application/libraries/IssuesLib.php index 9b3a9de6e..f38303b3c 100644 --- a/application/libraries/IssuesLib.php +++ b/application/libraries/IssuesLib.php @@ -246,7 +246,27 @@ class IssuesLib $fehlertext = vsprintf($fehlertextVorlage, $fehlertext_params); } - $openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount($fehlercode, $person_id, $oe_kurzbz, $fehlercode_extern); + if (isset($resolution_params)) + { + if (is_array($resolution_params)) + { + foreach ($resolution_params as $resolution_key => $resolution_param) + { + if (!is_string($resolution_key)) + return error("Invalid parameter for resolution, must be an associative array"); + } + } + else + return error("Invalid parameters for resolution"); + } + + $openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount( + $fehlercode, + $person_id, + $oe_kurzbz, + $fehlercode_extern, + $resolution_params + ); if (hasData($openIssuesCountRes)) { @@ -256,20 +276,6 @@ class IssuesLib if ($openIssueCount == 0) { - if (isset($resolution_params)) - { - if (is_array($resolution_params)) - { - foreach ($resolution_params as $resolution_key => $resolution_param) - { - if (!is_string($resolution_key)) - return error("Invalid parameter for resolution, must be an associative array"); - } - } - else - return error("Invalid parameters for resolution"); - } - // insert new issue return $this->_ci->IssueModel->insert( array( diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index 09f89abee..857defbf7 100644 --- a/application/libraries/PermissionLib.php +++ b/application/libraries/PermissionLib.php @@ -21,6 +21,8 @@ require_once(FHCPATH.'include/functions.inc.php'); require_once(FHCPATH.'include/wawi_kostenstelle.class.php'); require_once(FHCPATH.'include/benutzerberechtigung.class.php'); +use \benutzerberechtigung as benutzerberechtigung; + class PermissionLib { // Available rights in the DB @@ -65,8 +67,10 @@ class PermissionLib if (!is_cli()) { // API Caller rights initialization + $authObj = $this->_ci->authlib->getAuthObj(); self::$bb = new benutzerberechtigung(); - self::$bb->getBerechtigungen(($this->_ci->authlib->getAuthObj())->{AuthLib::AO_USERNAME}); + if ($authObj) + self::$bb->getBerechtigungen($authObj->{AuthLib::AO_USERNAME}); } } @@ -143,19 +147,7 @@ class PermissionLib if (strpos($permissions[$pCounter], PermissionLib::PERMISSION_SEPARATOR) !== false) { // Retrieves permission and required access type from the $requiredPermissions array - list($permission, $requiredAccessType) = explode(PermissionLib::PERMISSION_SEPARATOR, $permissions[$pCounter]); - - $accessType = ''; - - // Set the access type - if (strpos($requiredAccessType, PermissionLib::READ_RIGHT) !== false) - { - $accessType = PermissionLib::SELECT_RIGHT; // S - } - if (strpos($requiredAccessType, PermissionLib::WRITE_RIGHT) !== false) - { - $accessType .= PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT; // UID - } + list($permission, $accessType) = $this->convertAccessType($permissions[$pCounter]); if (!isEmptyString($accessType)) // if compliant { @@ -166,6 +158,16 @@ class PermissionLib if ($checkPermissions === true) break; } } + elseif ($permissions[$pCounter] == Auth_Controller::PERM_ANONYMOUS) + { + $checkPermissions = true; + break; + } + elseif ($permissions[$pCounter] == Auth_Controller::PERM_LOGGED) + { + $checkPermissions = isLogged(); + break; + } else { show_error('The given permission does not use the correct format'); @@ -195,6 +197,24 @@ class PermissionLib return $checkPermissions; } + /** + * Retrieves permission and required access type from the newly formatted permission string + * + * @param string $permission + * + * @return array + */ + public function convertAccessType($permission) + { + list($permission, $reqAccessType) = explode(PermissionLib::PERMISSION_SEPARATOR, $permission); + $accessType = ''; + if (strpos($reqAccessType, PermissionLib::READ_RIGHT) !== false) + $accessType = PermissionLib::SELECT_RIGHT; + if (strpos($reqAccessType, PermissionLib::WRITE_RIGHT) !== false) + $accessType = PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT; + return [$permission, $accessType]; + } + /** * Checks if at least one of the permissions given as parameter (requiredPermissions) belongs to the authenticated user * It checks the given permissions against a given method (controller method name) and a given permission type (R and/or W) diff --git a/application/libraries/PrestudentLib.php b/application/libraries/PrestudentLib.php new file mode 100644 index 000000000..ef5e2e3a9 --- /dev/null +++ b/application/libraries/PrestudentLib.php @@ -0,0 +1,934 @@ +_ci =& get_instance(); + + // // Configs + // $this->_ci->load->config('studierendenantrag'); + + // // Models + $this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->_ci->load->model('crm/Student_model', 'StudentModel'); + $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->_ci->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + $this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); + $this->_ci->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel'); + } + + public function setAbbrecher( + $prestudent_id, + $studiensemester_kurzbz, + $insertvon = null, + $statusgrund_id = null, + $datum = null, + $bestaetigtam = null, + $bestaetigtvon = null + ) { + if (!$insertvon) + $insertvon = getAuthUID(); + if (!$bestaetigtvon) + $bestaetigtvon = $insertvon; + + $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id, $studiensemester_kurzbz); + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudent_in_sem', [ + 'prestudent_id' => $prestudent_id, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ])); + + $prestudent_status = current($result); + + $result = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]); + + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id])); + + $student = current($result); + + if(!$datum) + $datum = date('c'); + + if(!$bestaetigtam) + $bestaetigtam = date('c'); + + // Status und Statusgrund updaten + $result = $this->_ci->PrestudentstatusModel->insert([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_ABBRECHER, + 'studiensemester_kurzbz' => $prestudent_status->studiensemester_kurzbz, + 'ausbildungssemester' => $prestudent_status->ausbildungssemester, + 'datum' => $datum, + 'insertvon' => $insertvon, + 'insertamum' => date('c'), + 'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz, + 'studienplan_id'=> $prestudent_status->studienplan_id, + 'bestaetigtvon' => $bestaetigtvon, + 'bestaetigtam' => $bestaetigtam, + 'statusgrund_id' => $statusgrund_id + ]); + + if (isError($result)) + return $result; + + //Verband anlegen + $result = $this->_ci->LehrverbandModel->load([ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => 'A', + 'gruppe' => '' + ]); + + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + { + $result = $this->_ci->LehrverbandModel->load([ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => '', + 'gruppe' => '' + ]); + if (isError($result)) + return $result; + $result = getData($result); + + if(!$result) + { + $this->_ci->LehrverbandModel->insert([ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => '', + 'gruppe' => '', + 'bezeichnung' => 'Ab-Unterbrecher', + 'aktiv' => true, + ]); + } + + $this->_ci->LehrverbandModel->insert([ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => 'A', + 'gruppe' => '', + 'bezeichnung' => 'Abbrecher', + 'aktiv' => true + ]); + } + + // noch nicht eingetragene Zeugnisnoten auf 9 setzen + $result = $this->_ci->ZeugnisnoteModel->getZeugnisnoten($student->student_uid, $prestudent_status->studiensemester_kurzbz); + if (isError($result)) + return $result; + $result = getData($result) ?: []; + + foreach ($result as $lv) + { + if (!$lv->note) + { + $result = $this->_ci->ZeugnisnoteModel->insert([ + 'note' => 9, + 'studiensemester_kurzbz' => $lv->studiensemester_kurzbz, + 'student_uid' => $lv->uid, + 'lehrveranstaltung_id' => $lv->lehrveranstaltung_id + ]); + if (isError($result)) { + $result = $this->_ci->ZeugnisnoteModel->update([ + 'studiensemester_kurzbz' => $lv->studiensemester_kurzbz, + 'student_uid' => $lv->uid, + 'lehrveranstaltung_id' => $lv->lehrveranstaltung_id + ], [ + 'note' => 9 + ]); + + if (isError($result)) + return $result; + } + } + } + + + // Update Aktionen + + // StudentModel updaten + $this->_ci->StudentModel->update([ + 'student_uid' => $student->student_uid + ], [ + 'verband' => 'A', + 'gruppe' => '', + 'semester' => 0, + 'updatevon' => $insertvon, + 'updateamum' => date('c') + ]); + + //Studentlehrverband setzen + $this->_ci->StudentlehrverbandModel->update([ + 'studiensemester_kurzbz' => $prestudent_status->studiensemester_kurzbz, + 'student_uid' => $student->student_uid + ], [ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => 'A', + 'gruppe' => '', + 'updateamum' => date('c'), + 'updatevon' => $insertvon + ]); + + // Benutzer inaktiv setzen + $this->_ci->BenutzerModel->update([ + 'uid' => $student->student_uid + ], [ + 'aktiv' => false, + 'updateaktivvon' => $insertvon, + 'updateaktivam' => date('c'), + 'updatevon' => $insertvon, + 'updateamum' => date('c') + ]); + + return success(); + } + + public function setUnterbrecher( + $prestudent_id, + $studiensemester_kurzbz, + $studierendenantrag_id = null, + $insertvon = null, + $ausbildungssemester = null, + $statusgrund_id = null + ) { + $ausbildungssemester_plus = 0; + + if (!$insertvon) + $insertvon = getAuthUID(); + + + $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id, $studiensemester_kurzbz); + + if (isError($result)) + return $result; + + $result = getData($result); + + if (!$result) { // NOTE(chris): no status in target stdsem + //NOTE(manu): only valid if nextSemester focus max + + $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id); + if (isError($result)) + return $result; + $result = getData($result); + + // check if ausbildungssemester is last + $this->_ci->StudiengangModel->addJoin('public.tbl_prestudent p', 'studiengang_kz'); + $res = $this->_ci->StudiengangModel->loadWhere(['p.prestudent_id' => $prestudent_id]); + if(isError($res)) + return $res; + if(!hasData($res)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_stg_for_prestudent', [ + 'prestudent_id' => $prestudent_id + ])); + + $studiengang = current(getData($res)); + $prestudent_status = current($result); + if ($prestudent_status->status_kurzbz != Prestudentstatus_model::STATUS_UNTERBRECHER && $prestudent_status->ausbildungssemester + 1 < $studiengang->max_semester) + $ausbildungssemester_plus = 1; + + if(!$result) + { + return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudent_in_sem', [ + 'prestudent_id' => $prestudent_id, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ])); + } + } elseif (current($result)->status_kurzbz == Prestudentstatus_model::STATUS_UNTERBRECHER) { + if ($studierendenantrag_id) + { + $resultAntrag = $this->_ci->StudierendenantragModel->load($studierendenantrag_id); + if (isError($resultAntrag)) + return $resultAntrag; + $resultAntrag = getData($resultAntrag); + if (!$resultAntrag) + return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id])); + + $antrag = current($resultAntrag); + $anmerkung = current($result)->anmerkung . ' Wiedereinstieg ' . $antrag->datum_wiedereinstieg; + + $result = $this->_ci->PrestudentstatusModel->update([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_UNTERBRECHER, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => current($result)->ausbildungssemester + ], [ + 'updatevon' => $insertvon, + 'updateamum' => date('c'), + 'anmerkung'=> $anmerkung + ]); + + if (isError($result)) + return $result; + } + + return success(); + } + + $prestudent_status = current($result); + + + $result = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]); + + if (isError($result)) + return $result; + + $result = getData($result); + + if (!$result) + return error($this->_ci->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id])); + + $student = current($result); + + + if ($studierendenantrag_id) + { + $resultAntrag = $this->_ci->StudierendenantragModel->load($studierendenantrag_id); + if (isError($resultAntrag)) + return $resultAntrag; + $resultAntrag = getData($resultAntrag); + if (!$resultAntrag) + return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id])); + + $antrag = current($resultAntrag); + $anmerkung = 'Wiedereinstieg ' . $antrag->datum_wiedereinstieg; + } + else + $anmerkung = ''; + + if ($ausbildungssemester) + $semester = $ausbildungssemester; + else + $semester = $prestudent_status->ausbildungssemester + $ausbildungssemester_plus; + + // Status updaten + $result = $this->_ci->PrestudentstatusModel->insert([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_UNTERBRECHER, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => $semester, + 'datum' => date('c'), + 'insertvon' => $insertvon, + 'insertamum' => date('c'), + 'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz, + 'studienplan_id'=> $prestudent_status->studienplan_id, + 'bestaetigtvon' => $insertvon, + 'bestaetigtam' => date('c'), + 'anmerkung'=> $anmerkung, + 'statusgrund_id' => $statusgrund_id + ]); + + if (isError($result)) + return $result; + + //Verband anlegen + $result = $this->_ci->LehrverbandModel->load([ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => 'B', + 'gruppe' => '' + ]); + + if (isError($result)) + return $result; + $result = getData($result); + if (!$result) + { + $result = $this->_ci->LehrverbandModel->load([ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => '', + 'gruppe' => '' + ]); + if (isError($result)) + return $result; + $result = getData($result); + + if(!$result) + { + $this->_ci->LehrverbandModel->insert([ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => '', + 'gruppe' => '', + 'bezeichnung' => 'Ab-Unterbrecher', + 'aktiv' => true, + ]); + } + + $this->_ci->LehrverbandModel->insert([ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => 'B', + 'gruppe' => '', + 'bezeichnung' => 'Unterbrecher', + 'aktiv' => true + ]); + } + + // noch nicht eingetragene Zeugnisnoten auf 9 setzen + $result = $this->_ci->ZeugnisnoteModel->getZeugnisnoten($student->student_uid, $studiensemester_kurzbz); + if (isError($result)) + return $result; + $result = getData($result) ?: []; + + foreach ($result as $lv) + { + if (!$lv->note) + { + $result = $this->_ci->ZeugnisnoteModel->insert([ + 'note' => 9, + 'studiensemester_kurzbz' => $lv->studiensemester_kurzbz, + 'student_uid' => $lv->uid, + 'lehrveranstaltung_id' => $lv->lehrveranstaltung_id + ]); + if (isError($result)) { + $result = $this->_ci->ZeugnisnoteModel->update([ + 'studiensemester_kurzbz' => $lv->studiensemester_kurzbz, + 'student_uid' => $lv->uid, + 'lehrveranstaltung_id' => $lv->lehrveranstaltung_id + ], [ + 'note' => 9 + ]); + + if (isError($result)) + return $result; + } + } + } + + // Update Aktionen + + // StudentModel updaten + $this->_ci->StudentModel->update([ + 'student_uid' => $student->student_uid + ], [ + 'verband' => 'B', + 'gruppe' => '', + 'semester' => 0, + 'updatevon' => $insertvon, + 'updateamum' => date('c') + ]); + + //Studentlehrverband setzen + $result = $this->_ci->StudentlehrverbandModel->loadWhere([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student->student_uid + ]); + if (hasData($result)) { + $this->_ci->StudentlehrverbandModel->update([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student->student_uid + ], [ + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => 'B', + 'gruppe' => '', + 'updateamum' => date('c'), + 'updatevon' => $insertvon + ]); + } else { + $this->_ci->StudentlehrverbandModel->insert([ + 'student_uid' => $student->student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $student->studiengang_kz, + 'semester' => 0, + 'verband' => 'B', + 'gruppe' => '', + 'insertamum' => date('c'), + 'insertvon' => $insertvon + ]); + } + + return success(); + } + + public function setStudent($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id) + { + $authUID = getAuthUID(); + $now = date('c'); + + + $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id); + + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', [ + 'prestudent_id' => $prestudent_id + ])); + + $prestudent_status = current(getData($result)); + + + $result = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]); + + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id])); + + $student = current(getData($result)); + + + $this->_ci->load->library('VariableLib', ['uid' => $authUID]); + $semester_aktuell = $this->_ci->variablelib->getVar('semester_aktuell'); + + + // Update Aktionen + + // Status updaten + $result = $this->_ci->PrestudentstatusModel->insert([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_STUDENT, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'statusgrund_id' => $statusgrund_id, + 'ausbildungssemester' => $ausbildungssemester, + 'datum' => $now, + 'insertvon' => $authUID, + 'insertamum' => $now, + 'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz, + 'studienplan_id'=> $prestudent_status->studienplan_id, + 'bestaetigtvon' => $authUID, + 'bestaetigtam' => $now + ]); + + if (isError($result)) + return $result; + + + // Student updaten + $result = $this->_ci->StudentModel->update([ + 'student_uid' => $student->student_uid + ], [ + 'semester' => $ausbildungssemester, + 'verband' => '', + 'gruppe' => '', + 'updatevon' => $authUID, + 'updateamum' => $now + ]); + + if (isError($result)) + return $result; + + + // Studentlehrverband updaten + $result = $this->_ci->StudentlehrverbandModel->update([ + 'student_uid' => $student->student_uid, + 'studiensemester_kurzbz' => $semester_aktuell + ], [ + 'semester' => $ausbildungssemester, + 'verband' => '', + 'gruppe' => '', + 'updatevon' => $authUID, + 'updateamum' => $now + ]); + + if (isError($result)) + return $result; + + + // Benutzer updaten + $result = $this->_ci->BenutzerModel->load([$student->student_uid]); + + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('person', 'error_noBenutzer')); + + $benutzer = current(getData($result)); + $updateData = [ + 'aktiv' => true, + 'updateamum' => $now, + 'updatevon' => $authUID + ]; + if (!$benutzer->aktiv) { + $updateData['updateaktivam'] = $now; + $updateData['updateaktivvon'] = $authUID; + } + + + $this->_ci->BenutzerModel->update([$student->student_uid], $updateData); + + return success(); + } + + public function setFirstStudent( + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $orgform_kurzbz, + $studienplan_id, + $statusgrund_id + ) { + $this->_ci->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->_ci->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz'); + $result = $this->_ci->PrestudentModel->load($prestudent_id); + + if (isError($result)) + return $result; + + if (!hasData($result)) + return error('No prestudent'); + + $student_data = current(getData($result)); + + + $authUID = getAuthUID(); + $now = date('c'); + $today = date('Y-m-d'); + + $jahr = mb_substr($studiensemester_kurzbz, 4, 2); + + + // Genererate Personenkennzeichen + $personenkennzeichen = $this->_ci->StudentModel->generateMatrikelnummer2( + $student_data->studiengang_kz, + $studiensemester_kurzbz, + $student_data->typ + ); + if (isError($personenkennzeichen)) + return $personenkennzeichen; + $personenkennzeichen = getData($personenkennzeichen); + + + // Generate UID + $uid = $this->_ci->StudentModel->generateUID( + $student_data->kurzbz, + $jahr, + $student_data->typ, + $personenkennzeichen, + $student_data->vorname, + $student_data->nachname + ); + if (isError($uid)) + return $uid; + $uid = getData($uid); + + + // Generate Matrikelnummer + $matrikelnummer = $this->_ci->BenutzerModel->generateMatrikelnummer( + $student_data->oe_kurzbz + ); + if (isError($matrikelnummer)) + return $matrikelnummer; + $matrikelnummer = getData($matrikelnummer); + + + // Generate Alias + $alias = ''; + if (!defined('GENERATE_ALIAS_STUDENT') + || GENERATE_ALIAS_STUDENT === true + ) { + $result = $this->_ci->BenutzerModel->generateAliasFromName($student_data->vorname, $student_data->nachname); + if (isError($result)) + return $result; + $alias = getData($result); + } + + // Generate Activation Key + $activationkey = $this->_ci->BenutzerModel->generateActivationkey(); + + + // Overwrite stuff + if (defined('SET_UID_AS_MATRIKELNUMMER') + && SET_UID_AS_MATRIKELNUMMER) + $matrikelnummer = $uid; + if (defined('SET_UID_AS_PERSONENKENNZEICHEN') + && SET_UID_AS_PERSONENKENNZEICHEN) + $personenkennzeichen = $uid; + + + // Update Person + $this->_ci->load->model('person/Person_model', 'PersonModel'); + $result = $this->_ci->PersonModel->update([ + 'person_id' => $student_data->person_id, + 'matr_nr' => null + ], [ + 'matr_nr' => $matrikelnummer + ]); + + if (isError($result)) + return $result; + + + // Add Benutzer + $result = $this->_ci->BenutzerModel->insert([ + 'uid' => $uid, + 'person_id' => $student_data->person_id, + 'aktiv' => true, + 'aktivierungscode' => $activationkey, + 'alias' => $alias, + 'insertvon' => $authUID, + 'insertamum' => $now, + ]); + + if (isError($result)) + return $result; + + + // Add Student + $result = $this->_ci->StudentModel->insert([ + 'student_uid' => $uid, + 'matrikelnr' => $personenkennzeichen, + 'prestudent_id' => $prestudent_id, + 'studiengang_kz' => $student_data->studiengang_kz, + 'semester' => $ausbildungssemester, + 'verband' => ' ', + 'gruppe' => ' ', + 'insertvon' => $authUID, + 'insertamum' => $now + ]); + + if (isError($result)) + return $result; + + + // Add Lehrverband if it does not exist + $result = $this->_ci->LehrverbandModel->load([' ', ' ', $ausbildungssemester, $student_data->studiengang_kz]); + + if (isError($result)) + return $result; + + if (!hasData($result)) { + $result = $this->_ci->LehrverbandModel->insert([ + 'studiengang_kz' => $student_data->studiengang_kz, + 'semester' => $ausbildungssemester, + 'verband' => ' ', + 'gruppe' => ' ', + 'aktiv' => true + ]); + + if (isError($result)) + return $result; + } + + + // Add Rolle + $result = $this->_ci->PrestudentstatusModel->insert([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_STUDENT, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + 'orgform_kurzbz'=> $orgform_kurzbz, + 'studienplan_id'=> $studienplan_id, + 'datum' => $today, + 'insertamum' => $now, + 'insertvon' => $authUID, + 'bestaetigtam' => $today, + 'bestaetigtvon' => $authUID, + 'statusgrund_id' => $statusgrund_id + ]); + + if (isError($result)) + return $result; + + + // Add Studentlehrverband + $result = $this->_ci->StudentlehrverbandModel->insert([ + 'student_uid' => $uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $student_data->studiengang_kz, + 'semester' => $ausbildungssemester, + 'verband' => ' ', + 'gruppe' => ' ', + 'insertamum' => $now, + 'insertvon' => $authUID + ]); + + if (isError($result)) + return $result; + + return success(); + } + + public function setDiplomand($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id) + { + return $this->setBasic( + getAuthUID(), + date('c'), + Prestudentstatus_model::STATUS_DIPLOMAND, + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + } + + public function setAbsolvent($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id) + { + $authUID = getAuthUID(); + $now = date('c'); + + + $result = $this->setBasic( + $authUID, + $now, + Prestudentstatus_model::STATUS_ABSOLVENT, + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + + if (isError($result)) + return $result; + + + // Load Student + $result = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]); + + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id])); + + $student = current(getData($result)); + + + // Benutzer inaktiv setzen + $this->_ci->BenutzerModel->update([ + 'uid' => $student->student_uid + ], [ + 'aktiv' => false, + 'updateaktivvon' => $authUID, + 'updateaktivam' => $now, + 'updatevon' => $authUID, + 'updateamum' => $now + ]); + + if (isError($result)) + return $result; + + return success(); + } + + public function setBewerber($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id) + { + $result = $this->setBasic( + getAuthUID(), + date('c'), + Prestudentstatus_model::STATUS_BEWERBER, + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + + if (isError($result)) + return $result; + + if (SEND_BEWERBER_INFOMAIL) { + // TODO(chris): IMPLEMENT! + } + + return success(); + } + + public function setAufgenommener($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id) + { + return $this->setBasic( + getAuthUID(), + date('c'), + Prestudentstatus_model::STATUS_AUFGENOMMENER, + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + } + + public function setAbgewiesener($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id) + { + return $this->setBasic( + getAuthUID(), + date('c'), + Prestudentstatus_model::STATUS_ABGEWIESENER, + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + } + + public function setWartender($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id) + { + return $this->setBasic( + getAuthUID(), + date('c'), + Prestudentstatus_model::STATUS_WARTENDER, + $prestudent_id, + $studiensemester_kurzbz, + $ausbildungssemester, + $statusgrund_id + ); + } + + protected function setBasic($authUID, $now, $status_kurzbz, $prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id = null) + { + $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id); + + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', [ + 'prestudent_id' => $prestudent_id + ])); + + $prestudent_status = current(getData($result)); + + + // Update Aktionen + + // Status updaten + $result = $this->_ci->PrestudentstatusModel->insert([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + 'datum' => $now, + 'insertvon' => $authUID, + 'insertamum' => $now, + 'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz, + 'studienplan_id'=> $prestudent_status->studienplan_id, + 'bestaetigtvon' => $authUID, + 'bestaetigtam' => $now, + 'statusgrund_id' => $statusgrund_id + ]); + + if (isError($result)) + return $result; + + return success(); + } +} diff --git a/application/libraries/PrestudentstatusCheckLib.php b/application/libraries/PrestudentstatusCheckLib.php new file mode 100644 index 000000000..5e3d8a307 --- /dev/null +++ b/application/libraries/PrestudentstatusCheckLib.php @@ -0,0 +1,922 @@ +_ci =& get_instance(); + + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->_ci->load->model('person/Person_model', 'PersonModel'); + $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->_ci->load->model('crm/Student_model', 'StudentModel'); + $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel'); + $this->_ci->load->model('codex/Bismeldestichtag_model', 'BismeldestichtagModel'); + } + + /** + * Checks if a status add is valid. + * @return object error if invalid + */ + public function checkStatusAdd( + $prestudent_id, + $status_kurzbz, + $new_status_studiensemester_kurzbz, + $new_status_datum, + $new_status_ausbildungssemester, + $new_studienplan_id + ) { + $studentName = ''; + + $nameRes = $this->_ci->PersonModel->loadPrestudent($prestudent_id); + + if (hasData($nameRes)) + { + $nameData = getData($nameRes)[0]; + $studentName = $nameData->vorname.' '.$nameData->nachname; + } + + // Datum des neuen Status darf nicht in Vergangenheit liegen, sonst Probleme wenn neues Datum < Bismeldedatum + if (new DateTime($new_status_datum) < new DateTime('today')) + return error($studentName . $this->_ci->p->t('lehre', 'error_entryInPast')); + + return $this->_checkIfValidStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_status_studiensemester_kurzbz, + $new_status_datum, + $new_status_ausbildungssemester, + $new_studienplan_id + ); + } + + /** + * Checks if a status update is valid. + * @return error if invalid + */ + public function checkStatusUpdate( + $prestudent_id, + $status_kurzbz, + $new_status_studiensemester_kurzbz, + $new_status_datum, + $new_status_ausbildungssemester, + $new_studienplan_id, + $old_status_studiensemester, + $old_status_ausbildungssemester + ) { + + return $this->_checkIfValidStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_status_studiensemester_kurzbz, + $new_status_datum, + $new_status_ausbildungssemester, + $new_studienplan_id, + $old_status_studiensemester, + $old_status_ausbildungssemester + ); + } + + /** + * Checks if a student already exists. + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function checkIfExistingStudent($prestudent_id) + { + $result = $this->_ci->StudentModel->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + + if (isError($result)) + return $result; + + return success(hasData($result)); + } + + /** + * Check if Reihungstest was admitted + * + * @param stdClass $prestudent + * + * @return stdClass + */ + public function checkIfAngetreten($prestudent) + { + return success($prestudent->reihungstestangetreten); + } + + /** + * Check if ZGV-Code is registered + * + * @param stdClass $prestudent + * + * @return stdClass + */ + public function checkIfZGVEingetragen($prestudent_person) + { + return success((boolean)$prestudent_person->zgv_code); + } + + /** + * Check if Master ZGV-Code is registered + * + * @param stdClass $prestudent + * + * @return booleans $zgv_code, error if not registered + */ + public function checkIfZGVEingetragenMaster($prestudent) + { + $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $result = $this->_ci->StudiengangModel->load($prestudent->studiengang_kz); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->_ci->p->t('studierendenantrag', 'error_no_stg', ['studiengang_kz' => $prestudent->studiengang_kz])); + + if (current($result->retval)->typ != 'm') + return success(true); // NOTE(chris): we only test master stgs, all other stgs should default to true + + return success((boolean)$prestudent->zgvmas_code); + } + + /** + * Checks if a bewerber status already exists. + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function checkIfExistingBewerberstatus($prestudent_id) + { + $result = $this->_ci->PrestudentstatusModel->loadWhere([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_BEWERBER + ]); + if (isError($result)) + return $result; + + return success(hasData($result)); + } + + + /** + * Checks if status aufgenommen already exists. + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function checkIfExistingAufgenommenerstatus($prestudent_id) + { + $result = $this->_ci->PrestudentstatusModel->loadWhere([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_AUFGENOMMENER + ]); + if (isError($result)) + return $result; + + return success(hasData($result)); + } + + /** + * Checks if the last Bewerber status and the last Aufgenommener status + * have the same studiensemester and ausbildungssemester. + * + * Attention: + * If one of those two status is missing the function returns true! + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function checkIfLastBewerberAndAufgenommenerShareSemesters($prestudent_id) + { + $this->_ci->PrestudentstatusModel->addOrder('datum', 'DESC'); + $this->_ci->PrestudentstatusModel->addOrder('insertamum', 'DESC'); + $this->_ci->PrestudentstatusModel->addLimit(1); + $result = $this->_ci->PrestudentstatusModel->loadWhere([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_BEWERBER + ]); + + if (isError($result)) + return $result; + if (!hasData($result)) + return success(true); + + $bewerber = current(getData($result)); + + $this->_ci->PrestudentstatusModel->addOrder('datum', 'DESC'); + $this->_ci->PrestudentstatusModel->addOrder('insertamum', 'DESC'); + $this->_ci->PrestudentstatusModel->addLimit(1); + $result = $this->_ci->PrestudentstatusModel->loadWhere([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => Prestudentstatus_model::STATUS_AUFGENOMMENER + ]); + + if (isError($result)) + return $result; + if (!hasData($result)) + return success(true); + + $aufgenommener = current(getData($result)); + + return success( + $bewerber->studiensemester_kurzbz == $aufgenommener->studiensemester_kurzbz + && $bewerber->ausbildungssemester == $aufgenommener->ausbildungssemester + ); + } + + /** + * Check if Bismeldestichtag erreicht + * + * @param DateTime $statusDatum + * @param string $studiensemester_kurzbz + * + * @return stdClass + */ + public function checkIfMeldestichtagErreicht($statusDatum, $studiensemester_kurzbz = null) + { + $result = $this->_ci->BismeldestichtagModel->checkIfMeldestichtagErreicht($statusDatum, $studiensemester_kurzbz); + + if (isError($result)) + return $result; + + return success(getData($result) == "1"); + } + + /** + * Runs all checks on Status History and saves it in cache. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param DateTime $new_date + * @param string $new_studiensemester_kurzbz + * @param integer $new_ausbildungssemester + * @param string $old_studiensemester_kurzbz + * @param integer $old_ausbildungssemester + * + * @return stdClass + */ + protected function prepareStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ) { + // Generate key for caching + $primary = implode('|', [ + $prestudent_id, + $status_kurzbz, + $new_date->format('Y-m-d'), + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ]); + + if (isset($this->_cache_history[$primary])) + return $this->_cache_history[$primary]; + + $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + + // Get the history + $result = $this->_ci->PrestudentstatusModel->getHistoryWithNewOrEditedState( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ); + + if (isError($result)) + return $result; + + if (!hasData($result)) + return error('This is impossible'); + + $history = getData($result); + $historyCount = count($history); + + // Run checks + $checks = [ + 'timesequence' => true, + 'laststatus' => true, + 'unterbrechersemester' => true, + 'abbrechersemester' => true, + 'diplomant' => true, + 'student' => true + ]; + + for ($n = 0, $c = 1; $c < $historyCount; $n++, $c++) { + if (!$checks['timesequence'] + && !$checks['laststatus'] + && !$checks['unterbrechersemester'] + && !$checks['abbrechersemester'] + && !$checks['diplomant'] + && !$checks['student'] + ) + break; // early out + + $next = $history[$n]; + $current = $history[$c]; + + // Zeitabfolge ungültig? + if ($checks['timesequence'] + && $next->start < $current->start + ) + $checks['timesequence'] = false; + + // Abbrecher- oder Absolventenstatus muss Endstatus sein + if ($checks['laststatus'] + && in_array($current->status_kurzbz, [self::ABSOLVENT_STATUS, self::ABBRECHER_STATUS]) + ) + $checks['laststatus'] = false; + + // wenn Unterbrecher auf Unterbrecher folgt, muss Ausbildungssemester gleich sein + if ($checks['unterbrechersemester'] + && $current->status_kurzbz == self::UNTERBRECHER_STATUS + && $next->status_kurzbz == self::UNTERBRECHER_STATUS + && $current->ausbildungssemester != $next->ausbildungssemester + ) + $checks['unterbrechersemester'] = false; + + // wenn Abbrecher auf Unterbrecher folgt, muss Ausbildungssemester gleich sein + if ($checks['abbrechersemester'] + && $current->status_kurzbz == self::UNTERBRECHER_STATUS + && $next->status_kurzbz == self::ABBRECHER_STATUS + && $current->ausbildungssemester != $next->ausbildungssemester + ) + $checks['abbrechersemester'] = false; + + if (($checks['diplomant'] + || $checks['student']) + && $next->status_kurzbz == self::STUDENT_STATUS + ) { + $restl_stati = array_unique(array_column(array_slice($history, $c), 'status_kurzbz')); + + // keine Studenten nach Diplomand Status + if ($checks['diplomant'] + && in_array(self::DIPLOMAND_STATUS, $restl_stati) + ) + $checks['diplomant'] = false; + + // vor Studentenstatus müssen bestimmte Status vorhanden sein + if ($checks['student'] + && array_values(array_intersect($restl_stati, $this->_statusAbfolgeVorStudent)) != array_values($this->_statusAbfolgeVorStudent) + ) + $checks['student'] = false; + } + } + + $this->_cache_history[$primary] = success($checks); + + return success($checks); + } + + /** + * Checks if the time sequence of the status history is valid. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param DateTime $new_date + * @param string $new_studiensemester_kurzbz + * @param integer $new_ausbildungssemester + * @param string $old_studiensemester_kurzbz + * @param integer $old_ausbildungssemester + * + * @return stdClass + */ + public function checkStatusHistoryTimesequence( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ) { + $result = $this->prepareStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ); + + if (isError($result)) + return $result; + + return success(getData($result)['timesequence']); + } + + /** + * Checks if the last status of the status history is not Abbrecher or + * Absolvent. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param DateTime $new_date + * @param string $new_studiensemester_kurzbz + * @param integer $new_ausbildungssemester + * @param string $old_studiensemester_kurzbz + * @param integer $old_ausbildungssemester + * + * @return stdClass + */ + public function checkStatusHistoryLaststatus( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ) { + $result = $this->prepareStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ); + + if (isError($result)) + return $result; + + return success(getData($result)['laststatus']); + } + + /** + * Checks if two consecutively Unterbrecher have the same + * ausbildungssemester in the status history. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param DateTime $new_date + * @param string $new_studiensemester_kurzbz + * @param integer $new_ausbildungssemester + * @param string $old_studiensemester_kurzbz + * @param integer $old_ausbildungssemester + * + * @return stdClass + */ + public function checkStatusHistoryUnterbrechersemester( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ) { + $result = $this->prepareStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ); + + if (isError($result)) + return $result; + + return success(getData($result)['unterbrechersemester']); + } + + /** + * Checks if an Unterbrecher followed by an Abbrecher have the same + * ausbildungssemester in the status history. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param DateTime $new_date + * @param string $new_studiensemester_kurzbz + * @param integer $new_ausbildungssemester + * @param string $old_studiensemester_kurzbz + * @param integer $old_ausbildungssemester + * + * @return stdClass + */ + public function checkStatusHistoryAbbrechersemester( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ) { + $result = $this->prepareStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ); + + if (isError($result)) + return $result; + + return success(getData($result)['abbrechersemester']); + } + + /** + * Checks if no Diplomant is followed by a Student in the status history. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param DateTime $new_date + * @param string $new_studiensemester_kurzbz + * @param integer $new_ausbildungssemester + * @param string $old_studiensemester_kurzbz + * @param integer $old_ausbildungssemester + * + * @return stdClass + */ + public function checkStatusHistoryDiplomant( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ) { + $result = $this->prepareStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ); + + if (isError($result)) + return $result; + + return success(getData($result)['diplomant']); + } + + /** + * Checks if a Student precedes given stati in the status history. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param DateTime $new_date + * @param string $new_studiensemester_kurzbz + * @param integer $new_ausbildungssemester + * @param string $old_studiensemester_kurzbz + * @param integer $old_ausbildungssemester + * + * @return stdClass + */ + public function checkStatusHistoryStudent( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ) { + // TODO(chris): TEST + $result = $this->prepareStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ); + + if (isError($result)) + return $result; + + return success(getData($result)['student']); + } + + /** + * Checks if Personenkennzeichen is set correctly. + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function checkPersonenkennzeichen($prestudent_id) + { + // TODO(chris): TEST + $this->_ci->PrestudentstatusModel->addSelect('tbl_prestudentstatus.prestudent_id'); + $this->_ci->PrestudentstatusModel->addSelect('tbl_student.matrikelnr'); + + $this->_ci->PrestudentstatusModel->addJoin('public.tbl_student', 'prestudent_id'); + + $this->_ci->PrestudentstatusModel->addOrder('tbl_prestudentstatus.datum', 'DESC'); + $this->_ci->PrestudentstatusModel->addOrder('tbl_prestudentstatus.insertamum', 'DESC'); + $this->_ci->PrestudentstatusModel->addOrder('tbl_prestudentstatus.ext_id', 'DESC'); + + $this->_ci->PrestudentstatusModel->addLimit(1); + + $result = $this->_ci->PrestudentstatusModel->loadWhere([ + 'tbl_prestudentstatus.prestudent_id' => $prestudent_id, + 'tbl_prestudentstatus.status_kurzbz' => self::STATUS_STUDENT + ]); + + if (isError($result)) + return $result; + + if (!hasData($result)) + return success(true); // Not a student yet so no wrong personenkennzeichen + + $data = current(getData($result)); + + $jahr = $this->_ci->StudiensemesterModel->getStudienjahrNumberFromStudiensemester($data->studiensemester_kurzbz); + + + return success($jahr == mb_substr($data->matrikelnr, 0, 2)); + } + + /** + * Checks if Orgform of Student status and Bewerber status match. + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function checkStudentOrgform($prestudent_id) + { + // TODO(chris): TEST + $result = $this->_ci->PrestudentstatusModel->getBewerberWhereOrgformNotStudent($prestudent_id); + + if (isError($result)) + return $result; + + return success(!hasData($result)); + } + + /** + * Check if History of StatusData is valid + * @param integer $prestudent_id + * @return error if not valid, array StatusArr if valid + */ + private function _checkIfValidStatusHistory( + $prestudent_id, + $status_kurzbz, + $new_status_studiensemester_kurzbz, + $new_status_datum, + $new_status_ausbildungssemester, + $new_studienplan_id, + $old_status_studiensemester = null, + $old_status_ausbildungssemester = null + ) { + //get start studiensemester + $semResult = $this->_ci->StudiensemesterModel->load([ + 'studiensemester_kurzbz' => $new_status_studiensemester_kurzbz + ]); + + if (isError($semResult)) + { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + return $this->outputJson(getError($semResult)); + } + + if (!hasData($semResult)) { + return error($this->_ci->p->t('lehre', 'error_noStudiensemester') . $new_status_studiensemester_kurzbz); + } + + $studiensemester = getData($semResult)[0]; + $new_status_semesterstart = $studiensemester->start; + + // get studienplan orgform + $new_studienplan_orgform_kurzbz = ''; + $this->_ci->StudienplanModel->addSelect('orgform_kurzbz'); + $stplResult = $this->_ci->StudienplanModel->load([ + 'studienplan_id' => $new_studienplan_id + ]); + + if (isError($stplResult)) + { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + return $this->outputJson(getError($stplResult)); + } + + if (hasData($stplResult)) $new_studienplan_orgform_kurzbz = getData($stplResult)[0]->orgform_kurzbz; + + + //get all prestudentstati + $resultPs = $this->_ci->PrestudentstatusModel->getAllPrestudentstatiWithStudiensemester($prestudent_id); + + if (isError($resultPs)) return $resultPs; + + $resultArr = hasData($resultPs) ? getData($resultPs) : []; + $statusArr = []; + + $newStatusInserted = false; + $new_status_datum_form = new DateTime($new_status_datum); + $new_status_semesterstart_form = new DateTime($new_status_semesterstart); + + if (!isEmptyArray($resultArr)) + { + // neuen Status zum Hinzufügen + $first_status = $resultArr[0]; + $neuer_status = new stdClass(); + $neuer_status->status_kurzbz = $status_kurzbz; + $neuer_status->studiensemester_kurzbz = $new_status_studiensemester_kurzbz; + $neuer_status->datum = $new_status_datum; + $neuer_status->ausbildungssemester = $new_status_ausbildungssemester; + $neuer_status->studienplan_orgform_kurzbz = $new_studienplan_orgform_kurzbz; + $neuer_status->matrikelnr = $first_status->matrikelnr; + $neuer_status->vorname = $first_status->vorname; + $neuer_status->nachname = $first_status->nachname; + + // Status, welcher gerade geändert wird, holen + $status_to_change = array_filter( + $resultArr, + function ($status) use ($status_kurzbz, $old_status_studiensemester, $old_status_ausbildungssemester) { + return + $status->status_kurzbz == $status_kurzbz + && $status->studiensemester_kurzbz == $old_status_studiensemester + && $status->ausbildungssemester == $old_status_ausbildungssemester; + } + ); + + if (!isEmptyArray($status_to_change)) + { + $status_to_change_index = key($status_to_change); + + // wenn sich Studiensemester und Ausbildungssemester nicht geändert haben... + if ($new_status_studiensemester_kurzbz == $old_status_studiensemester + && $new_status_ausbildungssemester == $old_status_ausbildungssemester) + { + // ...neuen status an selber stelle einfügen wie zu ändernder Status + $resultArr[$status_to_change_index] = (object)array_merge((array)$resultArr[$status_to_change_index], (array)$neuer_status); + $newStatusInserted = true; + } + else + { + // bei Status mit neuem Semester: alten Status entfernen + unset($resultArr[$status_to_change_index]); + } + } + } + + foreach ($resultArr as $row) + { + $studiensemester_start = new DateTime($row->studiensemester_start); + $status_datum = new DateTime($row->datum); + + if ($new_status_datum_form >= $status_datum && $new_status_semesterstart_form >= $studiensemester_start) + { + if (!$newStatusInserted) + { + // neuer Status erstmals größer als Datum eines bestehenden Status -> neuen Status EINMALIG einfügen für spätere Statusprüfung + $statusArr[] = $neuer_status; + $newStatusInserted = true; + } + $statusArr[] = $row; + } + elseif ($new_status_datum_form <= $status_datum && $new_status_semesterstart_form <= $studiensemester_start) + { + $statusArr[] = $row; + } + else + { + // Zeitabfolge ungültig, Fehler + return error($this->_ci->p->t('lehre', 'error_statuseintrag_zeitabfolge')); + } + } + + // erster Studentstatus + $ersterStudent = null; + + // Über alle gespeicherten Status gehen und Statusabfolge prüfen + for ($i = 0; $i < count($statusArr); $i++) + { + $curr_status = $statusArr[$i]; + $curr_status_kurzbz = $curr_status->status_kurzbz; + $curr_status_ausbildungssemester = $curr_status->ausbildungssemester; + $next_idx = $i - 1; //absteigend sortiert, nächster Status ist vorheriger Eintrag + $next_status = isset($statusArr[$next_idx]) ? $statusArr[$next_idx] : null; + + $studentName = $curr_status->vorname . ' ' . $curr_status->nachname; + + if ($curr_status_kurzbz == self::STUDENT_STATUS) $ersterStudent = $curr_status; + + // Abbrecher- oder Absolventenstatus muss Endstatus sein + if (isset($next_status) && in_array($curr_status_kurzbz, $this->_endStatusArr)) + { + return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_endstatus')); + } + + // wenn Unterbrecher auf Unterbrecher folgt, muss Ausbildungssemester gleich sein + if + ($curr_status_kurzbz == self::UNTERBRECHER_STATUS && isset($next_status) && $next_status->status_kurzbz == self::UNTERBRECHER_STATUS + && $curr_status_ausbildungssemester != $next_status->ausbildungssemester) + { + return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_consecutiveUnterbrecher')); + } + + // wenn Abbrecher auf Unterbrecher folgt, muss Ausbildungssemester gleich sein + if (isset($next_status) + && $curr_status_kurzbz == self::UNTERBRECHER_STATUS + && $next_status->status_kurzbz == self::ABBRECHER_STATUS && $curr_status_ausbildungssemester != $next_status->ausbildungssemester) + { + return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_consecutiveUnterbrecherAbbrecher')); + } + + if (isset($next_status) && $next_status->status_kurzbz == self::STUDENT_STATUS) + { + $restliche_status_obj = array_slice($statusArr, $i); + $restliche_status = array_unique(array_column($restliche_status_obj, 'status_kurzbz')); + $status_intersected = array_intersect($restliche_status, $this->_statusAbfolgeVorStudent); + + // Vor Studentstatus darf kein Diplomand Status vorhanden sein + if (in_array(self::DIPLOMAND_STATUS, $restliche_status)) + { + return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_consecutiveDiplomandStudent')); + } + + // Vor Studentstatus müssen bestimmte Status vorhanden sein + if (array_values($status_intersected) != array_values(array_reverse($this->_statusAbfolgeVorStudent))) + { + return error( + $studentName . ' ' + . $this->_ci->p->t('lehre', 'error_wrongStatusOrderBeforeStudent', array(implode(', ', $this->_statusAbfolgeVorStudent))) + ); + } + } + } + + if (isset($ersterStudent)) + { + $studentName = $ersterStudent->vorname . ' ' . $ersterStudent->nachname; + + // wenn erster Studentstatus, checken ob Personenkennzeichen passt + $studienjahrNumber = $this->_ci->StudiensemesterModel->getStudienjahrNumberFromStudiensemester($ersterStudent->studiensemester_kurzbz); + + if ($studienjahrNumber != mb_substr($ersterStudent->matrikelnr, 0, 2)) + { + return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_personenkennzeichenPasstNichtZuStudiensemester')); + } + + // wenn erster Studentstatus, checken ob Orgform des Bewerbers mit Studenten übereinstimmt + if (!isEmptyArray( + array_filter( + $restliche_status_obj, + function ($s) use ($ersterStudent) { + return + $s->status_kurzbz == self::BEWERBER_STATUS + && ( + $s->studienplan_orgform_kurzbz != $ersterStudent->studienplan_orgform_kurzbz + ); + } + ) + ) + ) + { + return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_bewerberOrgformUngleichStudentOrgform')); + } + } + + return $resultPs; + } +} diff --git a/application/libraries/SearchBarLib.php b/application/libraries/SearchBarLib.php index 3a9d06d13..b725f6e90 100644 --- a/application/libraries/SearchBarLib.php +++ b/application/libraries/SearchBarLib.php @@ -30,9 +30,10 @@ class SearchBarLib const ERROR_WRONG_SEARCHSTR = 'ERR002'; const ERROR_NO_TYPES = 'ERR003'; const ERROR_WRONG_TYPES = 'ERR004'; + const ERROR_NOT_AUTH = 'ERR005'; // List of allowed types of search - const ALLOWED_TYPES = ['mitarbeiter', 'organisationunit', 'raum', 'person', 'student', 'prestudent', 'document', 'cms']; + const ALLOWED_TYPES = ['mitarbeiter', 'mitarbeiter_ohne_zuordnung', 'organisationunit', 'raum', 'person', 'student', 'prestudent', 'document', 'cms']; const PHOTO_IMG_URL = '/cis/public/bild.php?src=person&person_id='; @@ -108,6 +109,92 @@ class SearchBarLib return $result; } + private function _mitarbeiter_ohne_zuordnung($searchstr, $type) + { + $dbModel = new DB_Model(); + + $sql = ' + SELECT + \''.$type.'\' AS type, + b.uid AS uid, + p.person_id AS person_id, + p.vorname || \' \' || p.nachname AS name, + ARRAY_AGG(DISTINCT(org.bezeichnung)) AS organisationunit_name, + COALESCE(b.alias, b.uid) || \''.'@'.DOMAIN.'\' AS email, + TRIM(COALESCE(k.kontakt, \'\') || \' \' || COALESCE(m.telefonklappe, \'\')) AS phone, + \''.base_url(self::PHOTO_IMG_URL).'\' || p.person_id AS photo_url, + ARRAY_AGG(DISTINCT(stdkst.bezeichnung)) AS standardkostenstelle + FROM public.tbl_mitarbeiter m + JOIN public.tbl_benutzer b ON(b.uid = m.mitarbeiter_uid) + LEFT JOIN ( + SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid + FROM public.tbl_benutzerfunktion bf + JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) + JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) + WHERE bf.funktion_kurzbz = \'kstzuordnung\' + AND (bf.datum_von IS NULL OR bf.datum_von <= NOW()) + AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW()) + GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid + ) stdkst ON stdkst.uid = b.uid + JOIN public.tbl_person p USING(person_id) + LEFT JOIN ( + SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid + FROM public.tbl_benutzerfunktion bf + JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) + JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) + WHERE bf.funktion_kurzbz = \'oezuordnung\' + AND (bf.datum_von IS NULL OR bf.datum_von <= NOW()) + AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW()) + GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid + ) org ON org.uid = b.uid + LEFT JOIN ( + SELECT kontakt, standort_id + FROM public.tbl_kontakt + WHERE kontakttyp = \'telefon\' + ) k ON(k.standort_id = m.standort_id) + WHERE + (stdkst.bezeichnung IS NULL + OR org.bezeichnung IS NULL) + AND ( + ' . + $this->buildSearchClause( + $dbModel, + array('b.uid', 'p.vorname', 'p.nachname'), + $searchstr + ) . + ' + ) + GROUP BY type, b.uid, p.person_id, name, email, m.telefonklappe, phone + '; + + $employees = $dbModel->execReadOnlyQuery($sql); + + // If something has been found then return it + if (hasData($employees)) return getData($employees); + + // Otherwise return an empty array + return array(); + } + + protected function buildSearchClause(DB_Model $dbModel, array $columns, $searchstr) + { + $document = implode(' || \' \' || ', $columns); + $query = '\'' . implode(':* & ', explode(' ', trim($searchstr))) . ':*\''; + $reversequery = '\'*:' . implode(' & *:', explode(' ', trim($searchstr))) . '\''; + $nospacequery = '\'' . implode('', explode(' ', trim($searchstr))) . ':*\''; + + $searchclause = <<= NOW()) - GROUP BY o.bezeichnung, bf.uid + GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid ) stdkst ON stdkst.uid = b.uid JOIN public.tbl_person p USING(person_id) JOIN ( - SELECT o.bezeichnung, bf.uid + SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid FROM public.tbl_benutzerfunktion bf JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) + JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) WHERE bf.funktion_kurzbz = \'oezuordnung\' AND (bf.datum_von IS NULL OR bf.datum_von <= NOW()) AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW()) - GROUP BY o.bezeichnung, bf.uid + GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid ) org ON org.uid = b.uid LEFT JOIN ( SELECT kontakt, standort_id FROM public.tbl_kontakt WHERE kontakttyp = \'telefon\' ) k ON(k.standort_id = m.standort_id) - WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' - OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' - OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' - OR org.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' - OR stdkst.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' + WHERE ' . + $this->buildSearchClause( + $dbModel, + array('b.uid', 'p.vorname', 'p.nachname', 'org.bezeichnung', 'stdkst.bezeichnung'), + $searchstr + ) . + ' GROUP BY type, b.uid, p.person_id, name, email, m.telefonklappe, phone '); @@ -178,15 +269,17 @@ class SearchBarLib SELECT \''.$type.'\' AS type, o.oe_kurzbz AS oe_kurzbz, - o.bezeichnung AS name, + \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS name, oParent.oe_kurzbz AS parentoe_kurzbz, - oParent.bezeichnung AS parentoe_name, + (CASE WHEN oParent.bezeichnung IS NOT NULL THEN \'[\' || otParent.bezeichnung || \'] \' || oParent.bezeichnung END) AS parentoe_name, ARRAY_AGG(DISTINCT(bfLeader.uid)) AS leader_uid, ARRAY_AGG(DISTINCT(bfLeader.vorname || \' \' || bfLeader.nachname)) AS leader_name, COUNT(bfCount.benutzerfunktion_id) AS number_of_people, (CASE WHEN o.mailverteiler = TRUE THEN o.oe_kurzbz || \''.'@'.DOMAIN.'\' END) AS mailgroup FROM public.tbl_organisationseinheit o + JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz) LEFT JOIN public.tbl_organisationseinheit oParent ON(oParent.oe_kurzbz = o.oe_parent_kurzbz) + LEFT JOIN public.tbl_organisationseinheittyp otParent ON(oParent.organisationseinheittyp_kurzbz = otParent.organisationseinheittyp_kurzbz) LEFT JOIN ( SELECT benutzerfunktion_id, oe_kurzbz FROM public.tbl_benutzerfunktion @@ -204,9 +297,14 @@ class SearchBarLib AND (datum_bis IS NULL OR datum_bis >= NOW()) AND b.aktiv = TRUE ) bfLeader ON(bfLeader.oe_kurzbz = o.oe_kurzbz) - WHERE o.oe_kurzbz ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' - OR o.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' - GROUP BY type, o.oe_kurzbz, o.bezeichnung, oParent.oe_kurzbz, oParent.bezeichnung + WHERE ' . + $this->buildSearchClause( + $dbModel, + array('o.oe_kurzbz', 'o.bezeichnung', 'ot.bezeichnung'), + $searchstr + ) . + ' + GROUP BY type, o.oe_kurzbz, o.bezeichnung, ot.bezeichnung, oParent.oe_kurzbz, oParent.bezeichnung, otParent.bezeichnung '); // If something has been found @@ -260,6 +358,35 @@ class SearchBarLib */ private function _student($searchstr, $type) { + $dbModel = new DB_Model(); + + $students = $dbModel->execReadOnlyQuery(' + SELECT + \''.$type.'\' AS type, + s.student_uid AS uid, + s.matrikelnr, + p.person_id AS person_id, + p.vorname || \' \' || p.nachname AS name, + k.kontakt as email , + p.foto + FROM public.tbl_student s + JOIN public.tbl_benutzer b ON(b.uid = s.student_uid) + JOIN public.tbl_person p USING(person_id) + LEFT JOIN ( + SELECT kontakt, person_id + FROM public.tbl_kontakt + WHERE kontakttyp = \'email\' + ) as k USING(person_id) + WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' + OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' + OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' + GROUP BY type, s.student_uid, s.matrikelnr, p.person_id, name, email, p.foto + '); + + // If something has been found then return it + if (hasData($students)) return getData($students); + + // Otherwise return an empty array return array(); } @@ -268,6 +395,41 @@ class SearchBarLib */ private function _prestudent($searchstr, $type) { + $dbModel = new DB_Model(); + + $prestudent = $dbModel->execReadOnlyQuery(' + SELECT + \''.$type.'\' AS type, + ps.prestudent_id, + ps.studiengang_kz, + p.person_id AS person_id, + b.uid, + p.vorname || \' \' || p.nachname AS name, + ( + SELECT kontakt + FROM public.tbl_kontakt + WHERE kontakttyp = \'email\' + AND person_id = p.person_id + LIMIT 1 + ) as email, + p.foto, + sg.bezeichnung + FROM public.tbl_prestudent ps + LEFT JOIN public.tbl_student s USING (prestudent_id) + LEFT JOIN public.tbl_benutzer b ON (b.uid = s.student_uid) + JOIN public.tbl_person p ON (p.person_id = ps.person_id) + LEFT JOIN public.tbl_studiengang sg ON (sg.studiengang_kz = ps.studiengang_kz) + WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' + OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' + OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\' + or cast(ps.prestudent_id as text) ILIKE \'%'.$dbModel->escapeLIKE($searchstr).'%\' + GROUP BY type, b.uid, ps.prestudent_id, ps.studiengang_kz, sg.bezeichnung, s.student_uid, s.matrikelnr, p.person_id, name, email, p.foto + '); + + // If something has been found then return it + if (hasData($prestudent)) return getData($prestudent); + + // Otherwise return an empty array return array(); } diff --git a/application/libraries/TableWidgetLib.php b/application/libraries/TableWidgetLib.php index dc746b6d5..3af99cca7 100644 --- a/application/libraries/TableWidgetLib.php +++ b/application/libraries/TableWidgetLib.php @@ -1,5 +1,22 @@ . + */ + if (! defined('BASEPATH')) exit('No direct script access allowed'); /** @@ -16,6 +33,7 @@ class TableWidgetLib const SESSION_FIELDS = 'fields'; const SESSION_COLUMNS_ALIASES = 'columnsAliases'; const SESSION_ADDITIONAL_COLUMNS = 'additionalColumns'; + const SESSION_ENCRYPTED_COLUMNS = 'encryptedColumns'; const SESSION_CHECKBOXES = 'checkboxes'; const SESSION_METADATA = 'datasetMetadata'; const SESSION_ROW_NUMBER = 'rowNumber'; @@ -49,6 +67,7 @@ class TableWidgetLib const ADDITIONAL_COLUMNS = 'additionalColumns'; const CHECKBOXES = 'checkboxes'; const COLUMNS_ALIASES = 'columnsAliases'; + const ENCRYPTED_COLUMNS = 'encryptedColumns'; // ...to format/mark records of a dataset const FORMAT_ROW = 'formatRow'; @@ -74,7 +93,7 @@ class TableWidgetLib /** * Gets the CI instance and loads message helper */ - public function __construct($params = null) + public function __construct() { $this->_ci =& get_instance(); // get code igniter instance } @@ -177,7 +196,7 @@ class TableWidgetLib /** * Retrieves the dataset from the DB */ - public function getDataset($datasetQuery) + public function getDataset($datasetQuery, $encryptedColumns) { $dataset = null; @@ -186,7 +205,7 @@ class TableWidgetLib $this->_ci->load->model('system/Filters_model', 'FiltersModel'); // Execute the given SQL statement suppressing error messages - $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery); + $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $encryptedColumns); } return $dataset; diff --git a/application/libraries/UDFLib.php b/application/libraries/UDFLib.php index c5f0d3e98..7437c58ff 100644 --- a/application/libraries/UDFLib.php +++ b/application/libraries/UDFLib.php @@ -65,6 +65,8 @@ class UDFLib private $_udfUniqueId; // Property that contains the UDF widget unique id + private $_definition_cache = []; + /** * Gets CI instance */ @@ -157,7 +159,7 @@ class UDFLib $found = false; // used to check if the field is found or not in the json schema $this->_sortJsonSchemas($jsonSchemasArray); // Sort the list of UDF by sort property - + // Loops through json schemas foreach ($jsonSchemasArray as $jsonSchema) { @@ -292,7 +294,7 @@ class UDFLib // Checks if the requiredPermissions is available and it is a valid array or a valid string if (isset($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}) && (!isEmptyArray($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}) - || !isEmptyString($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}))) + || !isEmptyString($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}))) { // Then check if the user has the permissions to read such UDF if (!$this->_readAllowed($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})) @@ -353,7 +355,7 @@ class UDFLib // Checks if the requiredPermissions is available and it is a valid array or a valid string if (isset($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}) && (!isEmptyArray($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}) - || !isEmptyString($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}))) + || !isEmptyString($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}))) { // Then check if the user has the permissions to write such UDF if (!$this->_writeAllowed($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})) @@ -613,6 +615,162 @@ class UDFLib ); } + /** + * Gets the UDF definitions for a model + * + * @param DB_Model $targetModel + * + * @return stdClass + */ + public function getDefinitionForModel($targetModel) + { + $dbTable = $targetModel->getDbTable(); + if (!isset($this->_definition_cache[$dbTable])) { + $this->_ci->load->model('system/UDF_model', 'UDFModel'); + list($schema, $table) = explode('.', $dbTable); + $result = $this->_ci->UDFModel->loadWhere([ + 'schema' => $schema, + 'table' => $table + ]); + if (isError($result)) + return $result; + if (!hasData($result)) + $this->_definition_cache[$dbTable] = []; + else + $this->_definition_cache[$dbTable] = json_decode(current($result->retval)->jsons, true); + } + return success($this->_definition_cache[$dbTable]); + } + + /** + * Gets the UDFs for db entry with translated params and resolved listValues for dropdowns + * + * @param DB_Model $targetModel + * @param mixed $id + * + * @return stdClass + */ + public function getFieldArray($targetModel, $id) + { + // Load Libraries + $this->_ci->load->library('PhrasesLib'); + $this->_ci->load->library('PermissionLib'); + + $result = $this->getDefinitionForModel($targetModel); + if (isError($result)) + return $result; + $definitions = $result->retval; + + usort($definitions, function ($a, $b) { + return $a[self::SORT] - $b[self::SORT]; + }); + + $values = $targetModel->getUDFs($id); + + $fields = []; + foreach ($definitions as $field) { + // check read permissions + if (!$this->_ci->permissionlib->hasAtLeastOne( + $field[self::REQUIRED_PERMISSIONS_PARAMETER], + self::PERMISSION_TABLE_METHOD, + self::PERMISSION_TYPE_READ + )) + continue; + + // set value + if (isset($values[$field[self::NAME]])) { + $field['value'] = $values[$field[self::NAME]]; + } elseif (isset($field['defaultValue'])) { + $field['value'] = $field['defaultValue']; + } elseif (isset($field[self::TYPE]) && $field[self::TYPE] == 'checkbox') { + $field['value'] = false; + } else { + $field['value'] = ''; + } + + // translate params + foreach ([self::LABEL, self::TITLE, self::PLACEHOLDER] as $key) { + if (isset($field[$key])) { + $res = $this->_ci->phraseslib->getPhrases(self::PHRASES_APP_NAME, getUserLanguage(), $field[$key], null, null, 'no'); + if (hasData($res)) + $field[$key] = current(getData($res))->text; + } + } + + // check write permissions + $field['disabled'] = !$this->_ci->permissionlib->hasAtLeastOne( + $field[self::REQUIRED_PERMISSIONS_PARAMETER], + self::PERMISSION_TABLE_METHOD, + self::PERMISSION_TYPE_WRITE + ); + + // set listValues for dropdowns + if (isset($field[self::LIST_VALUES])) { + if (isset($field[self::LIST_VALUES]['enum'])) { + $field['options'] = $field[self::LIST_VALUES]['enum']; + } elseif (isset($field[self::LIST_VALUES]['sql'])) { + $res = $this->_ci->UDFModel->execReadOnlyQuery($field[self::LIST_VALUES]['sql']); + $field['options'] = hasData($res) ? getData($res) : []; + } + } + + // add to array + $fields[] = $field; + } + return success($fields); + } + + /** + * Gets a validation config array for CI form_validation + * + * @param DB_Model $targetModel + * @param array (optional) $filter + * + * @return stdClass + */ + public function getCiValidations($targetModel, $filter = null) + { + $result = $this->getDefinitionForModel($targetModel); + if (isError($result)) + return $result; + $definitions = getData($result); + + $result = []; + foreach ($definitions as $def) { + if ($filter && !isset($filter[$def['name']])) + continue; + $validations = []; + if (isset($def['requiredPermissions'])) + $validations[] = 'has_write_permissions[' . implode(',', $def['requiredPermissions']) . ']'; + if (isset($def['required'])) + $validations[] = 'required'; + if (isset($def['validation'])) { + if (isset($def['validation']['max-value'])) + $validations[] = 'less_than_equal_to[' . $def['validation']['max-value'] . ']'; + if (isset($def['validation']['min-value'])) + $validations[] = 'greater_than_equal_to[' . $def['validation']['min-value'] . ']'; + if (isset($def['validation']['max-length'])) + $validations[] = 'max_length[' . $def['validation']['max-length'] . ']'; + if (isset($def['validation']['min-length'])) + $validations[] = 'min_length[' . $def['validation']['min-length'] . ']'; + if (isset($def['validation']['regex']) && is_array($def['validation']['regex'])) { + foreach ($def['validation']['regex'] as $regex) { + if ($regex['language'] == 'php') { + $validations[] = 'regex_match[' . $regex['expression'] . ']'; + } + } + } + } + if ($validations) + $result[] = [ + 'field' => $def['name'], + 'label' => $def['title'], + 'rules' => $validations + ]; + } + return success($result); + } + // ------------------------------------------------------------------------------------------------- // Private methods // @@ -841,7 +999,7 @@ class UDFLib $htmlParameters[HTMLWidget::HTML_ID] = $jsonSchema->{self::NAME}; $htmlParameters[HTMLWidget::HTML_NAME] = $jsonSchema->{self::NAME}; } - + /** * Sort the list of UDF by sort property */ @@ -864,7 +1022,7 @@ class UDFLib return ($a->{self::SORT} < $b->{self::SORT}) ? -1 : 1; }); } - + /** * Loads the UDF description by the given schema and table */ diff --git a/application/libraries/issues/PlausicheckDefinitionLib.php b/application/libraries/issues/PlausicheckDefinitionLib.php index cef28a736..d8c26d43a 100644 --- a/application/libraries/issues/PlausicheckDefinitionLib.php +++ b/application/libraries/issues/PlausicheckDefinitionLib.php @@ -15,7 +15,6 @@ class PlausicheckDefinitionLib 'AktSemesterNull' => 'AktSemesterNull', 'AktiverStudentOhneStatus' => 'AktiverStudentOhneStatus', 'AusbildungssemPrestudentUngleichAusbildungssemStatus' => 'AusbildungssemPrestudentUngleichAusbildungssemStatus', - 'BewerberNichtZumRtAngetreten' => 'BewerberNichtZumRtAngetreten', 'DatumAbschlusspruefungFehlt' => 'DatumAbschlusspruefungFehlt', 'DatumSponsionFehlt' => 'DatumSponsionFehlt', 'DatumStudiensemesterFalscheReihenfolge' => 'DatumStudiensemesterFalscheReihenfolge', @@ -33,8 +32,10 @@ class PlausicheckDefinitionLib 'PrestudentMischformOhneOrgform' => 'PrestudentMischformOhneOrgform', 'StgPrestudentUngleichStgStudienplan' => 'StgPrestudentUngleichStgStudienplan', 'StgPrestudentUngleichStgStudent' => 'StgPrestudentUngleichStgStudent', - 'StudentstatusNachAbbrecher' => 'StudentstatusNachAbbrecher' + 'StudentstatusNachAbbrecher' => 'StudentstatusNachAbbrecher', + 'DualesStudiumOhneMarkierung' => 'DualesStudiumOhneMarkierung' //'StudienplanUngueltig' => 'StudienplanUngueltig' + //'BewerberNichtZumRtAngetreten' => 'BewerberNichtZumRtAngetreten' ); /** diff --git a/application/libraries/issues/PlausicheckProducerLib.php b/application/libraries/issues/PlausicheckProducerLib.php index c32f1f863..cea9967fb 100644 --- a/application/libraries/issues/PlausicheckProducerLib.php +++ b/application/libraries/issues/PlausicheckProducerLib.php @@ -12,19 +12,25 @@ class PlausicheckProducerLib private $_ci; // ci instance private $_extensionName; // name of extension - private $_app; // name of application - private $_konfiguration = array(); // konfigratio parameters + private $_konfiguration = []; // configuration parameters + private $_fehlerLibMappings = []; // mappings of fehler and libraries for producing them + private $_isForResolutionCheck = false; // mappings of fehler and libraries for producing them public function __construct($params = null) { // set extension name if called from extension if (isset($params['extensionName'])) $this->_extensionName = $params['extensionName']; + if (isset($params['fehlerLibMappings'])) $this->_fehlerLibMappings = $params['fehlerLibMappings']; + if (isset($params['isForResolutionCheck'])) $this->_isForResolutionCheck = $params['isForResolutionCheck']; // set application $app = isset($params['app']) ? $params['app'] : null; $this->_ci =& get_instance(); // get ci instance + // load libraries + $this->_ci->load->library('IssuesLib'); + // load models $this->_ci->load->model('system/Fehlerkonfiguration_model', 'FehlerkonfigurationModel'); @@ -42,6 +48,52 @@ class PlausicheckProducerLib } } + /** + * Produces multiple plausicheck issues at once and saved them to db. + * @param array $params passed to each plausicheck + * @return result object with occured error and info + */ + public function producePlausicheckIssues($params) + { + $result = new StdClass(); + $result->errors = []; + $result->infos = []; + + foreach ($this->_fehlerLibMappings as $fehler_kurzbz => $libName) + { + $plausicheckRes = $this->producePlausicheckIssue( + $libName, + $fehler_kurzbz, + $params + ); + + if (hasData($plausicheckRes)) + { + $plausicheckData = getData($plausicheckRes); + + foreach ($plausicheckData as $plausiData) + { + // get the data needed for issue production + $person_id = isset($plausiData['person_id']) ? $plausiData['person_id'] : null; + $oe_kurzbz = isset($plausiData['oe_kurzbz']) ? $plausiData['oe_kurzbz'] : null; + $fehlertext_params = isset($plausiData['fehlertext_params']) ? $plausiData['fehlertext_params'] : null; + $resolution_params = isset($plausiData['resolution_params']) ? $plausiData['resolution_params'] : null; + + // write the issue + $addIssueRes = $this->_ci->issueslib->addFhcIssue($fehler_kurzbz, $person_id, $oe_kurzbz, $fehlertext_params, $resolution_params); + + // log if error, or log info if inserted new issue + if (isError($addIssueRes)) + $result->errors[] = getError($addIssueRes); + elseif (hasData($addIssueRes) && is_integer(getData($addIssueRes))) + $result->infos[] = "Plausicheck issue " . $fehler_kurzbz . " successfully produced, person_id: " . $person_id; + } + } + } + + return $result; + } + /** * Executes plausicheck using a given library, returns the result. * @param $libName string name of library producing the issue @@ -67,7 +119,10 @@ class PlausicheckProducerLib $config = isset($this->_konfiguration[$fehler_kurzbz]) ? $this->_konfiguration[$fehler_kurzbz] : null; // load library connected to fehlercode - $this->_ci->load->library($issuesLibPath . $libName, $config); + $this->_ci->load->library( + $issuesLibPath . $libName, + ['configurationParams' => $config, 'isForResolutionCheck' => $this->_isForResolutionCheck] + ); $lowercaseLibName = mb_strtolower($libName); diff --git a/application/libraries/issues/PlausicheckResolverLib.php b/application/libraries/issues/PlausicheckResolverLib.php new file mode 100644 index 000000000..26da985f6 --- /dev/null +++ b/application/libraries/issues/PlausicheckResolverLib.php @@ -0,0 +1,136 @@ +_extensionName = $params['extensionName']; + if (isset($params['codeLibMappings'])) $this->_codeLibMappings = $params['codeLibMappings']; + if (isset($params['codeProducerLibMappings'])) $this->_codeProducerLibMappings = $params['codeProducerLibMappings']; + + $this->_ci =& get_instance(); // get ci instance + + $this->_ci->load->library('IssuesLib'); + $this->_ci->load->library('issues/PlausicheckProducerLib', ['extensionName' => $this->_extensionName, 'isForResolutionCheck' => true]); + } + + /** + * Reseolves multiple plausicheck issues at once. + * @param array $codeLibMappings contains fehler type to check and library responsible for check (fehlercode => libName) + * @param array $openIssues passed issues to resolve + * @return result object with occured error and info + */ + public function resolvePlausicheckIssues($openIssues) + { + $result = new StdClass(); + $result->errors = []; + $result->infos = []; + + foreach ($openIssues as $issue) + { + // add person id and oe kurzbz automatically as params, merge it with additional params + // decode bewerbung_parameter into assoc array + $params = array_merge( + array('issue_id' => $issue->issue_id, 'issue_person_id' => $issue->person_id, 'issue_oe_kurzbz' => $issue->oe_kurzbz), + isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array() + ); + + $issueResolved = false; + + // ignore if Fehlercode is not in libmappings (shouldn't be checked) + if (isset($this->_codeLibMappings[$issue->fehlercode])) + { + $libName = $this->_codeLibMappings[$issue->fehlercode]; + + // if called from extension (extension name set), path includes extension names + $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : ''; + + // path for loading issue library + $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/'; + + // file path of library for check if file exists + $issuesLibFilePath = DOC_ROOT . self::CI_PATH + . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php'; + + // check if library file exists + if (!file_exists($issuesLibFilePath)) + { + // log error and continue with next issue if not + $result->errors[] = "Issue library file " . $issuesLibFilePath . " does not exist"; + continue; + } + + // load library connected to fehlercode + $this->_ci->load->library($issuesLibPath . $libName); + + $lowercaseLibName = mb_strtolower($libName); + + // check if method is defined in library class + if (!is_callable(array($this->_ci->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME))) + { + // log error and continue with next issue if not + $result->errors[] = "Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName"; + continue; + } + + // call the function for checking for issue resolution + $issueResolvedRes = $this->_ci->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); + + if (isError($issueResolvedRes)) + { + $result->errors[] = getError($issueResolvedRes); + } + else + { + $issueResolved = getData($issueResolvedRes) === true; + } + } + elseif (isset($this->_codeProducerLibMappings[$issue->fehlercode])) + { + $libName = $this->_codeProducerLibMappings[$issue->fehlercode]; + + $issueResolvedRes = $this->_ci->plausicheckproducerlib->producePlausicheckIssue( + $libName, + $issue->fehler_kurzbz, + $params + ); + + if (isError($issueResolvedRes)) + { + $result->errors[] = getError($issueResolvedRes); + } + else + { + $issueResolved = !hasData($issueResolvedRes); + } + } + + // set issue to resolved if needed + if ($issueResolved) + { + $behobenRes = $this->_ci->issueslib->setBehoben($issue->issue_id, null); + + if (isError($behobenRes)) + $result->errors[] = getError($behobenRes); + else + $result->infos[] = "Issue " . $issue->issue_id . " successfully resolved"; + } + } + + return $result; + } +} diff --git a/application/libraries/issues/plausichecks/AbbrecherAktiv.php b/application/libraries/issues/plausichecks/AbbrecherAktiv.php index 9eae389b5..464b77a30 100644 --- a/application/libraries/issues/plausichecks/AbbrecherAktiv.php +++ b/application/libraries/issues/plausichecks/AbbrecherAktiv.php @@ -9,83 +9,21 @@ require_once('PlausiChecker.php'); */ class AbbrecherAktiv extends PlausiChecker { - public function executePlausiCheck($params) - { - $results = array(); + protected $_base_sql = " + SELECT + pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_prestudentstatus pre_status + JOIN public.tbl_prestudent pre USING(prestudent_id) + JOIN public.tbl_student student USING(prestudent_id) + JOIN public.tbl_benutzer benutzer on(benutzer.uid=student.student_uid) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + WHERE + pre_status.status_kurzbz ='Abbrecher' + AND benutzer.aktiv=true"; - // get parameters from config - $exkludierte_studiengang_kz = isset($this->_config['exkludierteStudiengaenge']) ? $this->_config['exkludierteStudiengaenge'] : null; - - // pass parameters needed for plausicheck - $studiengang_kz = isset($params['studiengang_kz']) ? $params['studiengang_kz'] : null; - - // get all students failing the plausicheck - $prestudentRes = $this->getAbbrecherAktiv($studiengang_kz, null, $exkludierte_studiengang_kz); - - if (isError($prestudentRes)) return $prestudentRes; - - if (hasData($prestudentRes)) - { - $prestudents = getData($prestudentRes); - - // populate results with data necessary for writing issues - foreach ($prestudents as $prestudent) - { - $results[] = array( - 'person_id' => $prestudent->person_id, - 'oe_kurzbz' => $prestudent->prestudent_stg_oe_kurzbz, - 'fehlertext_params' => array('prestudent_id' => $prestudent->prestudent_id), - 'resolution_params' => array('prestudent_id' => $prestudent->prestudent_id) - ); - } - } - - // return the results - return success($results); - } - - /** - * Abbrecher cannot be active. - * @param studiengang_kz int if check is to be executed for certain Studiengang - * @param prestudent_id int if check is to be executed only for one prestudent - * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check - * @return success with prestudents or error - */ - public function getAbbrecherAktiv($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null) - { - $params = array(); - - $qry = " - SELECT - pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz - FROM - public.tbl_prestudentstatus pre_status - JOIN public.tbl_prestudent pre USING(prestudent_id) - JOIN public.tbl_student student USING(prestudent_id) - JOIN public.tbl_benutzer benutzer on(benutzer.uid=student.student_uid) - JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz - WHERE - pre_status.status_kurzbz ='Abbrecher' - AND benutzer.aktiv=true"; - - if (isset($studiengang_kz)) - { - $qry .= " AND stg.studiengang_kz = ?"; - $params[] = $studiengang_kz; - } - - if (isset($prestudent_id)) - { - $qry .= " AND pre.prestudent_id = ?"; - $params[] = $prestudent_id; - } - - if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz)) - { - $qry .= " AND stg.studiengang_kz NOT IN ?"; - $params[] = $exkludierte_studiengang_kz; - } - - return $this->_db->execReadOnlyQuery($qry, $params); - } + protected $_config_params = ['exkludierteStudiengaenge' => " AND stg.studiengang_kz NOT IN ?"]; + protected $_params_for_checking = ['studiengang_kz' => " AND stg.studiengang_kz = ?", 'prestudent_id' => " AND pre.prestudent_id = ?"]; + protected $_fehlertext_params = ['prestudent_id']; + protected $_resolution_params = ['prestudent_id']; } diff --git a/application/libraries/issues/plausichecks/DualesStudiumOhneMarkierung.php b/application/libraries/issues/plausichecks/DualesStudiumOhneMarkierung.php new file mode 100644 index 000000000..3951f6d76 --- /dev/null +++ b/application/libraries/issues/plausichecks/DualesStudiumOhneMarkierung.php @@ -0,0 +1,143 @@ +_config['exkludierteStudiengaenge']) ? $this->_config['exkludierteStudiengaenge'] : null; + + // pass parameters needed for plausicheck + $studiensemester_kurzbz = isset($params['studiensemester_kurzbz']) ? $params['studiensemester_kurzbz'] : null; + $studiengang_kz = isset($params['studiengang_kz']) ? $params['studiengang_kz'] : null; + + // get all students failing the plausicheck + $prestudentRes = $this->getDualesStudiumOhneMarkierung( + $studiensemester_kurzbz, + $studiengang_kz, + null, + $exkludierte_studiengang_kz + ); + + if (isError($prestudentRes)) return $prestudentRes; + + if (hasData($prestudentRes)) + { + $prestudents = getData($prestudentRes); + + // populate results with data necessary for writing issues + foreach ($prestudents as $prestudent) + { + $results[] = array( + 'person_id' => $prestudent->person_id, + 'oe_kurzbz' => $prestudent->prestudent_stg_oe_kurzbz, + 'fehlertext_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studienplan' => $prestudent->studienplan + ), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * All prestudents in dual Studiengang should have set the dual flag to true. + * @param studiensemester_kurzbz string check is to be executed for certain Studiensemester + * @param studiengang_kz int if check is to be executed for certain Studiengang + * @param prestudent_id int if check is to be executed only for one prestudent + * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check + * @return success with prestudents or error + */ + public function getDualesStudiumOhneMarkierung( + $studiensemester_kurzbz, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array($studiensemester_kurzbz); + + $qry = " + SELECT + DISTINCT pre.person_id, pre.prestudent_id, + stpl.bezeichnung AS studienplan, + status.studiensemester_kurzbz, + status.ausbildungssemester, + stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_person USING(person_id) + JOIN lehre.tbl_studienplan stpl USING(studienplan_id) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + JOIN public.tbl_studiensemester sem USING(studiensemester_kurzbz) + WHERE + (stpl.orgform_kurzbz = 'DUA' OR status.orgform_kurzbz = 'DUA') + AND pre.dual = FALSE + AND status.studiensemester_kurzbz=? + AND pre.bismelden + AND stg.melderelevant + AND NOT EXISTS ( + SELECT 1 + FROM + public.tbl_prestudentstatus + JOIN lehre.tbl_studienplan USING(studienplan_id) + JOIN public.tbl_studiensemester USING(studiensemester_kurzbz) + WHERE + prestudent_id = pre.prestudent_id + AND + ( + -- if there is a newer non-dual status, dual has not to be set + ( + ( + tbl_studienplan.orgform_kurzbz <> stpl.orgform_kurzbz + OR status.orgform_kurzbz <> tbl_prestudentstatus.orgform_kurzbz + ) + AND + ( + tbl_studiensemester.ende::date > sem.ende::date + OR (tbl_studiensemester.ende::date = sem.ende::date AND tbl_prestudentstatus.datum::date > status.datum::date) + ) + ) + OR + -- exclude Abgewiesene - they are not reported + tbl_prestudentstatus.status_kurzbz = 'Abgewiesener' + ) + )"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND pre.prestudent_id = ?"; + $params[] = $prestudent_id; + } + + if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz NOT IN ?"; + $params[] = $exkludierte_studiengang_kz; + } + + return $this->_db->execReadOnlyQuery($qry, $params); + } +} diff --git a/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php b/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php index dead2b1e7..59965e238 100644 --- a/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php +++ b/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php @@ -67,6 +67,7 @@ class InaktiverStudentAktiverStatus extends PlausiChecker $prestudent_id = null, $exkludierte_studiengang_kz = null ) { + $this->_ci->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); $aktStudiensemesterRes = $this->_ci->StudiensemesterModel->getAkt(); if (isError($aktStudiensemesterRes)) return $aktStudiensemesterRes; diff --git a/application/libraries/issues/plausichecks/PlausiChecker.php b/application/libraries/issues/plausichecks/PlausiChecker.php index 086a44cc4..7e5fe7db0 100644 --- a/application/libraries/issues/plausichecks/PlausiChecker.php +++ b/application/libraries/issues/plausichecks/PlausiChecker.php @@ -6,15 +6,25 @@ abstract class PlausiChecker { protected $_ci; // code igniter instance - protected $_config; // configuration parameters for this plausicheck + protected $_config; // all applicable configuration parameters for this plausicheck protected $_db; // database for queries - public function __construct($configurationParams = null) + protected $_isForResolutionCheck; // if true, additional parameters only needed for resolution are checked + + protected $_config_params = []; // name of all config params which should be applied for this plausicheck, with sql [name] => [sql] + protected $_params_for_checking = []; // name of all passed params for checking, with sql [name] => [sql] + + protected $_fehlertext_params = []; // parameter names for fehlertext params used for this plausicheck + protected $_resolution_params = []; // parameter names for resolution params used for this plausicheck + + public function __construct($params = null) { $this->_ci =& get_instance(); // get code igniter instance // set configuration - $this->_config = $configurationParams; + $this->_config = $params['configurationParams'] ?? []; + + $this->_isForResolutionCheck = $params['isForResolutionCheck'] ?? false; // get database for queries $this->_db = new DB_Model(); @@ -25,5 +35,83 @@ abstract class PlausiChecker * @param $paramsForChecking array parameters needed for executing the check * @return array with objects which failed the plausi check */ - abstract public function executePlausiCheck($paramsForChecking); + public function executePlausiCheck($paramsForChecking) + { + $results = []; + $params = []; + $qry = $this->_base_sql; + + if ($this->_isForResolutionCheck == true) + { + foreach ($this->_resolution_params as $resParam) + { + if (!isset($paramsForChecking[$resParam])) + return error("$resParam missing".(isset($paramsForChecking['issue_id']) ? ", issue ID: ".$paramsForChecking['issue_id'] : "")); + } + } + + // add config params to query + if (isset($this->_config_params) && !isEmptyArray($this->_config_params)) + { + foreach ($this->_config_params as $param_name => $param_sql) + { + if (isset($this->_config[$param_name])) + { + $qry .= $param_sql; + $params[] = $this->_config[$param_name]; + } + } + } + + // add check params to query + if (isset($this->_params_for_checking) && !isEmptyArray($this->_params_for_checking)) + { + foreach ($this->_params_for_checking as $param_name => $param_sql) + { + if (isset($paramsForChecking[$param_name])) + { + $qry .= $param_sql; + $params[] = $paramsForChecking[$param_name]; + } + } + } + + $result = $this->_db->execReadOnlyQuery($qry, $params); + + if (isError($result)) return $result; + + if (hasData($result)) + { + $data = getData($result); + + // populate results with data necessary for writing issues + foreach ($data as $d) + { + $fehlertext_params = []; + $resolution_params = []; + + // add params for error texts + foreach ($this->_fehlertext_params as $param) + { + if (isset($d->{$param})) $fehlertext_params[$param] = $d->{$param}; + } + + // add params for resolution of issue + foreach ($this->_resolution_params as $param) + { + if (isset($d->{$param})) $resolution_params[$param] = $d->{$param}; + } + + $results[] = array( + 'person_id' => $d->person_id, + 'oe_kurzbz' => $d->prestudent_stg_oe_kurzbz, + 'fehlertext_params' => $fehlertext_params, + 'resolution_params' => $resolution_params + ); + } + } + + // return the results + return success($results); + } } diff --git a/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0016.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0016.php new file mode 100644 index 000000000..0bba1ddff --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0016.php @@ -0,0 +1,36 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/DualesStudiumOhneMarkierung'); + + // check if issue persists + $checkRes = $this->_ci->dualesstudiumohnemarkierung->getDualesStudiumOhneMarkierung( + $params['studiensemester_kurzbz'], + null, + $params['prestudent_id'] + ); + + if (isError($checkRes)) return $checkRes; + + if (hasData($checkRes)) + return success(false); // not resolved if issue is still present + else + return success(true); // resolved otherwise + } +} diff --git a/application/libraries/vertragsbestandteil/AbstractBestandteil.php b/application/libraries/vertragsbestandteil/AbstractBestandteil.php new file mode 100644 index 000000000..ccd05f5e2 --- /dev/null +++ b/application/libraries/vertragsbestandteil/AbstractBestandteil.php @@ -0,0 +1,69 @@ +isvalid = false; + $this->validationerrors = array(); + + $this->modifiedcolumns = array(); + $this->fromdb = false; + } + + public function isDirty() { + return count($this->modifiedcolumns) > 0; + } + + protected function markDirty($columnname, $old_value, $new_value) { + if( $this->fromdb ) { + // data comes from db dont check for changes + if( isset($this->modifiedcolumns[$columnname]) ) { + unset($this->modifiedcolumns[$columnname]); + } + return; + } + + if( is_bool($new_value) && ($old_value !== $new_value) ) { + $this->modifiedcolumns[$columnname] = $columnname; + } else if($old_value != $new_value) { + $this->modifiedcolumns[$columnname] = $columnname; + } + } + + public function isValid() + { + return $this->isvalid; + } + + public function getValidationErrors() + { + return $this->validationerrors; + } + + + public function addValidationError($errormsg) + { + if( !in_array($errormsg, $this->validationerrors, true) ) + { + $this->validationerrors[] = $errormsg; + } + $this->isvalid = false; + } + + abstract public function hydrateByStdClass($data, $fromdb=false); +} diff --git a/application/libraries/vertragsbestandteil/Dienstverhaeltnis.php b/application/libraries/vertragsbestandteil/Dienstverhaeltnis.php new file mode 100644 index 000000000..07c417077 --- /dev/null +++ b/application/libraries/vertragsbestandteil/Dienstverhaeltnis.php @@ -0,0 +1,296 @@ +checkoverlap = true; + } + + public function hydrateByStdClass($data, $fromdb=false) + { + $this->fromdb = $fromdb; + isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id); + isset($data->mitarbeiter_uid) && $this->setMitarbeiter_uid($data->mitarbeiter_uid); + isset($data->vertragsart_kurzbz) && $this->setVertragsart_kurzbz($data->vertragsart_kurzbz); + isset($data->checkoverlap) && $this->setCheckoverlap($data->checkoverlap); + isset($data->oe_kurzbz) && $this->setOe_kurzbz($data->oe_kurzbz); + isset($data->von) && $this->setVon($data->von); + isset($data->bis) && $this->setBis($data->bis); + isset($data->insertamum) && $this->setInsertamum($data->insertamum); + isset($data->insertvon) && $this->setInsertvon($data->insertvon); + isset($data->updateamum) && $this->setUpdateamum($data->updateamum); + isset($data->updatevon) && $this->setUpdatevon($data->updatevon); + isset($data->dvendegrund_kurzbz) && $this->setDvendegrund_kurzbz($data->dvendegrund_kurzbz); + isset($data->dvendegrund_anmerkung) && $this->setDvendegrund_anmerkung($data->dvendegrund_anmerkung); + $this->fromdb = false; + } + + public function toStdClass(): \stdClass + { + $tmp = array( + 'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(), + 'mitarbeiter_uid' => $this->getMitarbeiter_uid(), + 'vertragsart_kurzbz' => $this->getVertragsart_kurzbz(), + 'oe_kurzbz' => $this->getOe_kurzbz(), + 'von' => $this->getVon(), + 'bis' => $this->getBis(), + 'insertamum' => $this->getInsertamum(), + 'insertvon' => $this->getInsertvon(), + 'updateamum' => $this->getUpdateamum(), + 'updatevon' => $this->getUpdatevon(), + 'dvendegrund_kurzbz' => $this->getDvendegrund_kurzbz(), + 'dvendegrund_anmerkung' => $this->getDvendegrund_anmerkung() + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + + public function __toString() + { + $txt = <<getDienstverhaeltnis_id()} + mitarbeiter_uid: {$this->getMitarbeiter_uid()} + vertragsart_kurzbz: {$this->getVertragsart_kurzbz()} + oe_kurzbz: {$this->getOe_kurzbz()} + von: {$this->getVon()} + bis: {$this->getBis()} + +EOTXT; + return $txt; + } + + public function getDienstverhaeltnis_id() + { + return $this->dienstverhaeltnis_id; + } + + public function getMitarbeiter_uid() + { + return $this->mitarbeiter_uid; + } + + public function getVertragsart_kurzbz() + { + return $this->vertragsart_kurzbz; + } + + public function getOe_kurzbz() + { + return $this->oe_kurzbz; + } + + public function getVon() + { + return $this->von; + } + + public function getBis() + { + return $this->bis; + } + + public function getInsertamum() + { + return $this->insertamum; + } + + public function getInsertvon() + { + return $this->insertvon; + } + + public function getUpdateamum() + { + return $this->updateamum; + } + + public function getUpdatevon() + { + return $this->updatevon; + } + + public function getDvendegrund_kurzbz() + { + return $this->dvendegrund_kurzbz; + } + + public function getDvendegrund_anmerkung() + { + return $this->dvendegrund_anmerkung; + } + + public function setDienstverhaeltnis_id($dienstverhaeltnis_id) + { + $this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id); + $this->dienstverhaeltnis_id = $dienstverhaeltnis_id; + return $this; + } + + public function setMitarbeiter_uid($mitarbeiter_uid) + { + $this->markDirty('mitarbeiter_uid', $this->mitarbeiter_uid, $mitarbeiter_uid); + $this->mitarbeiter_uid = $mitarbeiter_uid; + return $this; + } + + public function setVertragsart_kurzbz($vertragsart_kurzbz) + { + $this->markDirty('vertragsart_kurzbz', $this->vertragsart_kurzbz, $vertragsart_kurzbz); + $this->vertragsart_kurzbz = $vertragsart_kurzbz; + return $this; + } + + public function setCheckoverlap(bool $checkoverlap) + { + $this->checkoverlap = $checkoverlap; + } + + public function setOe_kurzbz($oe_kurzbz) + { + $this->markDirty('oe_kurzbz', $this->oe_kurzbz, $oe_kurzbz); + $this->oe_kurzbz = $oe_kurzbz; + return $this; + } + + public function setVon($von) + { + $this->markDirty('von', $this->von, $von); + $this->von = $von; + return $this; + } + + public function setBis($bis) + { + $this->markDirty('bis', $this->bis, $bis); + $this->bis = $bis; + return $this; + } + + public function setInsertamum($insertamum) + { + $this->markDirty('insertamum', $this->insertamum, $insertamum); + $this->insertamum = $insertamum; + return $this; + } + + public function setInsertvon($insertvon) + { + $this->markDirty('insertvon', $this->insertvon, $insertvon); + $this->insertvon = $insertvon; + return $this; + } + + public function setUpdateamum($updateamum) + { + $this->markDirty('updateamum', $this->updateamum, $updateamum); + $this->updateamum = $updateamum; + return $this; + } + + public function setUpdatevon($updatevon) + { + $this->markDirty('updatevon', $this->updatevon, $updatevon); + $this->updatevon = $updatevon; + return $this; + } + + public function setDvendegrund_kurzbz($dvendegrund_kurzbz) + { + $this->markDirty('dvendegrund_kurzbz', $this->dvendegrund_kurzbz, $dvendegrund_kurzbz); + $this->dvendegrund_kurzbz = $dvendegrund_kurzbz; + return $this; + } + + public function setDvendegrund_anmerkung($dvendegrund_anmerkung) + { + $this->markDirty('dvendegrund_anmerkung', $this->dvendegrund_anmerkung, $dvendegrund_anmerkung); + $this->dvendegrund_anmerkung = $dvendegrund_anmerkung; + return $this; + } + + public function validate() { + //do Validation here + $ci = get_instance(); + $ci->load->library('vertragsbestandteil/VertragsbestandteilLib', + null, 'VertragsbestandteilLib'); + + if( empty($this->mitarbeiter_uid) ) { + $this->validationerrors[] = 'Mitarbeiter_UID fehlt.'; + } + + if( empty($this->oe_kurzbz) ) { + $this->validationerrors[] = 'Unternehmen fehlt.'; + } + + if( empty($this->vertragsart_kurzbz) ) { + $this->validationerrors[] = 'Vertragsart fehlt.'; + } + + $von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von); + $bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis); + + if( false === $von ) { + $this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.'; + } + + if( $this->bis !== null && $bis === false ) { + $this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.'; + } + + if( $this-> bis !== null && $von && $bis && $von > $bis ) { + $this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.'; + } + + if( $this->checkoverlap && !(in_array($this->vertragsart_kurzbz, array('werkvertrag', 'studentischehilfskr')) ) + && $ci->VertragsbestandteilLib->isOverlappingExistingDV($this) ) + { + $this->validationerrors[] = 'Es existiert bereits ein überlappendes Dienstverhältnis'; + } + + // return status after Validation + if( count($this->validationerrors) > 0 ) { + $this->isvalid = false; + } else { + $this->isvalid = true; + } + + return $this->isvalid; + } +} \ No newline at end of file diff --git a/application/libraries/vertragsbestandteil/Gehaltsbestandteil.php b/application/libraries/vertragsbestandteil/Gehaltsbestandteil.php new file mode 100644 index 000000000..95bbdd908 --- /dev/null +++ b/application/libraries/vertragsbestandteil/Gehaltsbestandteil.php @@ -0,0 +1,368 @@ +fromdb = $fromdb; + isset($data->gehaltsbestandteil_id) && $this->setGehaltsbestandteil_id($data->gehaltsbestandteil_id); + isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id); + isset($data->vertragsbestandteil_id) && $this->setVertragsbestandteil_id($data->vertragsbestandteil_id); + isset($data->gehaltstyp_kurzbz) && $this->setGehaltstyp_kurzbz($data->gehaltstyp_kurzbz); + isset($data->von) && $this->setVon($data->von); + isset($data->bis) && $this->setBis($data->bis); + isset($data->anmerkung) && $this->setAnmerkung($data->anmerkung); + isset($data->grundbetrag) && $this->setGrundbetrag($data->grundbetrag); + isset($data->betrag_valorisiert) && $this->setBetrag_valorisiert($data->betrag_valorisiert); + isset($data->valorisierungssperre) && $this->setValorisierungssperre($data->valorisierungssperre); + isset($data->valorisierung) && $this->setValorisierung($data->valorisierung); + isset($data->auszahlungen) && $this->setAuszahlungen($data->auszahlungen); + + isset($data->insertamum) && $this->setInsertamum($data->insertamum); + isset($data->insertvon) && $this->setInsertvon($data->insertvon); + isset($data->updateamum) && $this->setUpdateamum($data->updateamum); + isset($data->updatevon) && $this->setUpdatevon($data->updatevon); + $this->fromdb = false; + } + + public function getGehaltsbestandteil_id() + { + return $this->gehaltsbestandteil_id; + } + + public function getDienstverhaeltnis_id() + { + return $this->dienstverhaeltnis_id; + } + + public function getVertragsbestandteil_id() + { + return $this->vertragsbestandteil_id; + } + + public function getGehaltstyp_kurzbz() + { + return $this->gehaltstyp_kurzbz; + } + + public function getVon() + { + return $this->von; + } + + public function getBis() + { + return $this->bis; + } + + public function getVonDateTime() + { + return $this->toDateTime($this->von); + } + + public function getBisDateTime() + { + return $this->toDateTime($this->bis); + } + + protected function toDateTime($d) { + if ($d == null) return null; + return new DateTimeImmutable($d); + } + + public function getAnmerkung() + { + return $this->anmerkung; + } + + public function getGrundbetrag() + { + return $this->grundbetrag; + } + + public function getBetrag_valorisiert() + { + return $this->betrag_valorisiert; + } + + public function getValorisierungssperre() + { + return $this->valorisierungssperre; + } + + public function getValorisierung() + { + return $this->valorisierung; + } + + public function getAuszahlungen() + { + return $this->auszahlungen; + } + + public function getInsertamum() + { + return $this->insertamum; + } + + public function getInsertvon() + { + return $this->insertvon; + } + + public function getUpdateamum() + { + return $this->updateamum; + } + + public function getUpdatevon() + { + return $this->updatevon; + } + + public function setGehaltsbestandteil_id($gehaltsbestandteil_id) + { + $this->markDirty('gehaltsbestandteil_id', $this->gehaltsbestandteil_id, $gehaltsbestandteil_id); + $this->gehaltsbestandteil_id = $gehaltsbestandteil_id; + return $this; + } + + public function setDienstverhaeltnis_id($dienstverhaeltnis_id) + { + $this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id); + $this->dienstverhaeltnis_id = $dienstverhaeltnis_id; + return $this; + } + + public function setVertragsbestandteil_id($vertragsbestandteil_id) + { + $this->markDirty('vertragsbestandteil_id', $this->vertragsbestandteil_id, $vertragsbestandteil_id); + $this->vertragsbestandteil_id = $vertragsbestandteil_id; + return $this; + } + + public function setGehaltstyp_kurzbz($gehaltstyp_kurzbz) + { + $this->markDirty('gehaltstyp_kurzbz', $this->gehaltstyp_kurzbz, $gehaltstyp_kurzbz); + $this->gehaltstyp_kurzbz = $gehaltstyp_kurzbz; + return $this; + } + + public function setVon($von) + { + $this->markDirty('von', $this->von, $von); + $this->von = $von; + return $this; + } + + public function setBis($bis) + { + $this->markDirty('bis', $this->bis, $bis); + $this->bis = $bis; + return $this; + } + + public function setAnmerkung($anmerkung) + { + $this->markDirty('anmerkung', $this->anmerkung, $anmerkung); + $this->anmerkung = $anmerkung; + return $this; + } + + public function setGrundbetrag($grundbetrag) + { + if(is_float($grundbetrag)) + { + $grundbetrag = number_format($grundbetrag, 2, '.', ''); + } + $this->markDirty('grundbetrag', $this->grundbetrag, $grundbetrag); + $this->grundbetrag = $grundbetrag; + return $this; + } + + public function setBetrag_valorisiert($betrag_valorisiert) + { + if(is_float($betrag_valorisiert)) + { + $betrag_valorisiert = number_format($betrag_valorisiert, 2, '.', ''); + } + $this->markDirty('betrag_valorisiert', $this->betrag_valorisiert, $betrag_valorisiert); + $this->betrag_valorisiert = $betrag_valorisiert; + return $this; + } + + public function setValorisierungssperre($valorisierungssperre) + { + $this->markDirty('valorisierungssperre', $this->valorisierungssperre, $valorisierungssperre); + $this->valorisierungssperre = $valorisierungssperre; + return $this; + } + + public function setValorisierung($valorisierung) + { + $this->markDirty('valorisierung', $this->valorisierung, $valorisierung); + $this->valorisierung = $valorisierung; + return $this; + } + + public function setAuszahlungen($auszahlungen) + { + $this->markDirty('auszahlungen', $this->auszahlungen, $auszahlungen); + $this->auszahlungen = $auszahlungen; + return $this; + } + + public function setInsertamum($insertamum) + { + $this->markDirty('insertamum', $this->insertamum, $insertamum); + $this->insertamum = $insertamum; + return $this; + } + + public function setInsertvon($insertvon) + { + $this->markDirty('insertvon', $this->insertvon, $insertvon); + $this->insertvon = $insertvon; + return $this; + } + + public function setUpdateamum($updateamum) + { + $this->markDirty('updateamum', $this->updateamum, $updateamum); + $this->updateamum = $updateamum; + return $this; + } + + public function setUpdatevon($updatevon) + { + $this->markDirty('updatevon', $this->updatevon, $updatevon); + $this->updatevon = $updatevon; + return $this; + } + + public function jsonSerialize() + { + $vars = get_object_vars($this); + unset($vars['CI']); + return $vars; + } + + public function toStdClass(): \stdClass + { + $tmp = array( + 'gehaltsbestandteil_id' => $this->getGehaltsbestandteil_id(), + 'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(), + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'gehaltstyp_kurzbz' => $this->getGehaltstyp_kurzbz(), + 'von' => $this->getVon(), + 'bis' => $this->getBis(), + 'anmerkung' => $this->getAnmerkung(), + 'grundbetrag' => $this->getGrundbetrag(), + 'betrag_valorisiert' => $this->getBetrag_valorisiert(), + 'valorisierungssperre' => $this->getValorisierungssperre(), + 'valorisierung' => $this->getValorisierung(), + 'auszahlungen' => $this->getAuszahlungen(), + 'insertamum' => $this->getInsertamum(), + 'insertvon' => $this->getInsertvon(), + 'updateamum' => $this->getUpdateamum(), + 'updatevon' => $this->getUpdatevon() + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function __toString() + { + $txt = <<getGehaltsbestandteil_id()} + dienstverhaeltnis_id: {$this->getDienstverhaeltnis_id()} + vertragsbestandteil_id: {$this->getVertragsbestandteil_id()} + gehaltstyp_kurzbz: {$this->getGehaltstyp_kurzbz()} + von: {$this->getVon()} + bis: {$this->getBis()} + anmerkung: {$this->getAnmerkung()} + grundbetrag: {$this->getGrundbetrag()} + betrag_valorisiert: {$this->getBetrag_valorisiert()} + valorisierungssperre: {$this->getValorisierungssperre()} + valorisierung: {$this->getValorisierung()} + auszahlungen: {$this->getAuszahlungen()} + insertamum: {$this->getInsertamum()} + insertvon: {$this->getInsertvon()} + updateamum: {$this->getUpdateamum()} + updatevon: {$this->getUpdatevon()} + +EOTXT; + return $txt; + } + + public function validate() { + //do Validation here + if( empty($this->gehaltstyp_kurzbz) ) + { + $this->validationerrors[] = "Ein Gehaltstyp muss ausgewählt sein."; + } + + if( empty($this->grundbetrag) ) + { + $this->validationerrors[] = "Betrag fehlt."; + } + + $von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von); + $bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis); + + if( false === $von ) { + $this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.'; + } + + if( $this->bis !== null && $bis === false ) { + $this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.'; + } + + if( $this-> bis !== null && $von && $bis && $von > $bis ) { + $this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.'; + } + + // return status after Validation + if( count($this->validationerrors) > 0 ) { + $this->isvalid = false; + } else { + $this->isvalid = true; + } + + return $this->isvalid; + } +} diff --git a/application/libraries/vertragsbestandteil/GehaltsbestandteilLib.php b/application/libraries/vertragsbestandteil/GehaltsbestandteilLib.php new file mode 100644 index 000000000..b75bdd722 --- /dev/null +++ b/application/libraries/vertragsbestandteil/GehaltsbestandteilLib.php @@ -0,0 +1,149 @@ +loggedInUser = getAuthUID(); + $this->CI = get_instance(); + $this->CI->load->model('vertragsbestandteil/Gehaltsbestandteil_model', + 'GehaltsbestandteilModel'); + $this->CI->load->library('extensions/FHC-Core-Personalverwaltung/abrechnung/GehaltsLib'); + $this->GehaltsbestandteilModel = $this->CI->GehaltsbestandteilModel; + } + + public function fetchGehaltsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false) + { + return $this->GehaltsbestandteilModel->getGehaltsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture); + } + + public function fetchGehaltsbestandteil($gehaltsbestandteil_id) + { + return $this->GehaltsbestandteilModel->getGehaltsbestandteil($gehaltsbestandteil_id); + } + + public function storeGehaltsbestandteile($gehaltsbestandteile) + { + foreach( $gehaltsbestandteile as $gehaltsbestandteil ) + { + $this->storeGehaltsbestandteil($gehaltsbestandteil); + } + } + + public function storeGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil) + { + try + { + $this->setUIDtoPGSQL(); + if( intval($gehaltsbestandteil->getGehaltsbestandteil_id()) > 0 ) + { + $this->updateGehaltsbestandteil($gehaltsbestandteil); + } + else + { + $this->insertGehaltsbestandteil($gehaltsbestandteil); + } + } + catch (Exception $ex) + { + log_message('debug', "Storing Gehaltsbestandteil failed. " . $ex->getMessage()); + throw new Exception('Storing Gehaltsbestandteil failed.'); + } + } + + protected function insertGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil) + { + $gehaltsbestandteil->setInsertvon($this->loggedInUser) + ->setInsertamum(strftime('%Y-%m-%d %H:%M:%S')); + $ret = $this->GehaltsbestandteilModel->insert($gehaltsbestandteil->toStdClass(), + $this->GehaltsbestandteilModel->getEncryptedColumns()); + if( hasData($ret) ) + { + $gehaltsbestandteil->setGehaltsbestandteil_id(getData($ret)); + } + else + { + throw new Exception('error inserting gehaltsbestandteil'); + } + } + + protected function updateGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil) + { + if(!$gehaltsbestandteil->isDirty()) { + return; + } + + $gehaltsbestandteil->setUpdatevon($this->loggedInUser) + ->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S')); + $ret = $this->GehaltsbestandteilModel->update($gehaltsbestandteil->getGehaltsbestandteil_id(), + $gehaltsbestandteil->toStdClass(), + $this->GehaltsbestandteilModel->getEncryptedColumns()); + + if(isError($ret) ) + { + throw new Exception('error updating gehaltsbestandteil'); + } + } + + public function deleteGehaltsbestandteile($gehaltsbestandteile) + { + foreach( $gehaltsbestandteile as $gehaltsbestandteil ) + { + $this->deleteGehaltsbestandteil($gehaltsbestandteil); + } + } + + public function deleteGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil) + { + $this->setUIDtoPGSQL(); + + // delete Gehaltsabrechnung + $ret = $this->CI->gehaltslib->deleteAbrechnung($gehaltsbestandteil); + + // + $ret = $this->GehaltsbestandteilModel->delete($gehaltsbestandteil->getGehaltsbestandteil_id()); + + if (isError($ret)) + { + throw new Exception('error deleting gehaltsbestandteil'); + } + } + + public function endGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil, $enddate) + { + $this->setUIDtoPGSQL(); + if( $gehaltsbestandteil->getBis() !== null && $gehaltsbestandteil->getBis() < $enddate ) + { + return; + } + + $gehaltsbestandteil->setBis($enddate); + $this->updateGehaltsbestandteil($gehaltsbestandteil); + } + + protected function setUIDtoPGSQL() { + $ret = $this->GehaltsbestandteilModel + ->execReadOnlyQuery('SET LOCAL pv21.uid TO \'' + . $this->loggedInUser . '\''); + if(isError($ret)) + { + throw new Exception('error setting uid to pgsql'); + } + } +} diff --git a/application/libraries/vertragsbestandteil/IValidation.php b/application/libraries/vertragsbestandteil/IValidation.php new file mode 100644 index 000000000..c55e33bcd --- /dev/null +++ b/application/libraries/vertragsbestandteil/IValidation.php @@ -0,0 +1,18 @@ +CI = get_instance(); + $this->CI->load->model('vertragsbestandteil/Vertragsbestandteil_model', + 'VertragsbestandteilModel'); + $this->VertragsbestandteilModel = $this->CI->VertragsbestandteilModel; + $this->CI->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model', + 'VertragsbestandteilFreitextModel'); + $this->VertragsbestandteilFreitextModel = $this->CI->VertragsbestandteilFreitextModel; + $this->CI->load->model('vertragsbestandteil/Vertragsbestandteiltyp_model', + 'VertragsbestandteilTypModel'); + $this->VertragsbestandteilTypModel = $this->CI->VertragsbestandteilTypModel; + $this->CI->load->model('vertragsbestandteil/VertragsbestandteilFreitexttyp_model', + 'VertragsbestandteilFreitexttypModel'); + $this->VertragsbestandteilFreitexttypModel = $this->CI->VertragsbestandteilFreitexttypModel; + } + + public function overlapsVB(Vertragsbestandteil $vb) + { + $result = $this->VertragsbestandteilTypModel->load($vb->getVertragsbestandteiltyp_kurzbz()); + if( null === ($vertragsbestandteiltyp = getData($result)) ) + { + throw new Exception('vertragsbestandteiltyp: ' + . $vb->getVertragsbestandteiltyp_kurzbz() . ' not found.'); + } + + if( true === $vertragsbestandteiltyp[0]->ueberlappend ) + { + // vertragsbestandteiltyp can overlap + return false; + } + + if( $this->VertragsbestandteilModel->countOverlappingVBsOfSameType($vb) === 0 ) + { + return false; + } + else + { + return true; + } + } + + public function overlapsFreitext(VertragsbestandteilFreitext $vbft) + { + $result = $this->VertragsbestandteilFreitexttypModel->load($vbft->getFreitexttypKurzbz()); + if( null === ($vertragsbestandteilfreitexttyp = getData($result)) ) + { + throw new Exception('vertragsbestandteilfreitexttyp: ' + . $vbft->getFreitexttypKurzbz() . ' not found.'); + } + + if( true === $vertragsbestandteilfreitexttyp[0]->ueberlappend ) + { + // freitexttyp can overlap + return false; + } + + if( $this->VertragsbestandteilFreitextModel->countOverlappingVBFreitextsOfSameType($vbft) === 0 ) + { + return false; + } + else + { + return true; + } + } + + private function __clone() {} +} diff --git a/application/libraries/vertragsbestandteil/Vertragsbestandteil.php b/application/libraries/vertragsbestandteil/Vertragsbestandteil.php new file mode 100644 index 000000000..bf5ec6211 --- /dev/null +++ b/application/libraries/vertragsbestandteil/Vertragsbestandteil.php @@ -0,0 +1,265 @@ +gehaltsbestandteile = array(); + } + + public function hydrateByStdClass($data, $fromdb=false) + { + $this->fromdb = $fromdb; + isset($data->vertragsbestandteil_id) && $this->setVertragsbestandteil_id($data->vertragsbestandteil_id); + isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id); + isset($data->von) && $this->setVon($data->von); + isset($data->bis) && $this->setBis($data->bis); + isset($data->vertragsbestandteiltyp_kurzbz) && $this->setVertragsbestandteiltyp_kurzbz($data->vertragsbestandteiltyp_kurzbz); + isset($data->insertamum) && $this->setInsertamum($data->insertamum); + isset($data->insertvon) && $this->setInsertvon($data->insertvon); + isset($data->updateamum) && $this->setUpdateamum($data->updateamum); + isset($data->updatevon) && $this->setUpdatevon($data->updatevon); + $this->fromdb = false; + } + + public function addGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil) + { + $gehaltsbestandteil->setDienstverhaeltnis_id($this->getDienstverhaeltnis_id()); + $gehaltsbestandteil->setVertragsbestandteil_id($this->getVertragsbestandteil_id()); + $this->gehaltsbestandteile[] = $gehaltsbestandteil; + return $this; + } + + public function getGehaltsbestandteile() + { + return $this->gehaltsbestandteile; + } + + public function getVertragsbestandteil_id() + { + return $this->vertragsbestandteil_id; + } + + public function getDienstverhaeltnis_id() + { + return $this->dienstverhaeltnis_id; + } + + public function getVon() + { + return $this->von; + } + + public function getBis() + { + return $this->bis; + } + + public function getVertragsbestandteiltyp_kurzbz() + { + return $this->vertragsbestandteiltyp_kurzbz; + } + + public function getInsertamum() + { + return $this->insertamum; + } + + public function getInsertvon() + { + return $this->insertvon; + } + + public function getUpdateamum() + { + return $this->updateamum; + } + + public function getUpdatevon() + { + return $this->updatevon; + } + + public function setGehaltsbestandteile($gehaltsbestandteile) + { + $this->gehaltsbestandteile = $gehaltsbestandteile; + return $this; + } + + public function setVertragsbestandteil_id($vertragsbestandteil_id) + { + $this->markDirty('vertragsbestandteil_id', $this->vertragsbestandteil_id, $vertragsbestandteil_id); + $this->vertragsbestandteil_id = $vertragsbestandteil_id; + foreach ($this->gehaltsbestandteile as $gehaltsbestandteil) + { + $gehaltsbestandteil->setVertragsbestandteil_id($vertragsbestandteil_id); + } + return $this; + } + + public function setDienstverhaeltnis_id($dienstverhaeltnis_id) + { + $this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id); + $this->dienstverhaeltnis_id = $dienstverhaeltnis_id; + foreach ($this->gehaltsbestandteile as $gehaltsbestandteil) + { + $gehaltsbestandteil->setDienstverhaeltnis_id($dienstverhaeltnis_id); + } + return $this; + } + + public function setVon($von) + { + $this->markDirty('von', $this->von, $von); + $this->von = $von; + return $this; + } + + public function setBis($bis) + { + $this->markDirty('bis', $this->bis, $bis); + $this->bis = $bis; + return $this; + } + + public function setVertragsbestandteiltyp_kurzbz($vertragsbestandteiltyp_kurzbz) + { + $this->markDirty('vertragsbestandteiltyp_kurzbz', $this->vertragsbestandteiltyp_kurzbz, $vertragsbestandteiltyp_kurzbz); + $this->vertragsbestandteiltyp_kurzbz = $vertragsbestandteiltyp_kurzbz; + return $this; + } + + public function setInsertamum($insertamum) + { + $this->markDirty('insertamum', $this->insertamum, $insertamum); + $this->insertamum = $insertamum; + return $this; + } + + public function setInsertvon($insertvon) + { + $this->markDirty('insertvon', $this->insertvon, $insertvon); + $this->insertvon = $insertvon; + return $this; + } + + public function setUpdateamum($updateamum) + { + $this->markDirty('updateamum', $this->updateamum, $updateamum); + $this->updateamum = $updateamum; + return $this; + } + + public function setUpdatevon($updatevon) + { + $this->markDirty('updatevon', $this->updatevon, $updatevon); + $this->updatevon = $updatevon; + return $this; + } + + public function baseToStdClass() { + $tmp = array( + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(), + 'von' => $this->getVon(), + 'bis' => $this->getBis(), + 'vertragsbestandteiltyp_kurzbz' => $this->getVertragsbestandteiltyp_kurzbz(), + 'insertamum' => $this->getInsertamum(), + 'insertvon' => $this->getInsertvon(), + 'updateamum' => $this->getUpdateamum(), + 'updatevon' => $this->getUpdatevon(), + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function jsonSerialize() + { + $vars = get_object_vars($this); + unset($vars['CI']); + + // TODO cleanup workaroung for vb freitext where db column is anmerkung and formfield is freitext + if( isset($vars['anmerkung']) ) { + $vars['freitext'] = $vars['anmerkung']; + } + + return $vars; + } + + public function __toString() + { + return <<getVertragsbestandteil_id()} + dienstverhaeltnis_id: {$this->getDienstverhaeltnis_id()} + von: {$this->getVon()} + bis: {$this->getBis()} + vertragsbestandteiltyp_kurzbz: {$this->getVertragsbestandteiltyp_kurzbz()} + insertamum: {$this->getInsertamum()} + insertvon: {$this->getInsertvon()} + updateamum: {$this->getUpdateamum()} + updatevon: {$this->getUpdatevon()} + +EOTXT; + + } + + public function beforePersist() { + // can be overridden in childs + } + + public function afterDelete() { + // can be overridden in childs + } + + public function validate() { + $von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von); + $bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis); + + if( false === $von ) { + $this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.'; + } + + if( $this->bis !== null && $bis === false ) { + $this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.'; + } + + if( $this-> bis !== null && $von && $bis && $von > $bis ) { + $this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.'; + } + + if( count($this->validationerrors) > 0 ) { + $this->isvalid = false; + } else { + $this->isvalid = true; + } + + return $this->isvalid; + } + + public abstract function toStdClass(); +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilFactory.php b/application/libraries/vertragsbestandteil/VertragsbestandteilFactory.php new file mode 100644 index 000000000..6e7b0af06 --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilFactory.php @@ -0,0 +1,137 @@ +vertragsbestandteiltyp_kurzbz) + ? $data->vertragsbestandteiltyp_kurzbz : false; + if( false === $vertragsbestandteiltyp_kurzbz ) + { + throw new Exception('Missing Parameter vertragsbestandteiltyp_kurzbz'); + } + + $vertragsbestandteil = null; + switch ($vertragsbestandteiltyp_kurzbz) + { + case self::VERTRAGSBESTANDTEIL_FREITEXT: + $vertragsbestandteil = new VertragsbestandteilFreitext(); + $vertragsbestandteil->hydrateByStdClass($data, $fromdb); + break; + + case self::VERTRAGSBESTANDTEIL_FUNKTION: + $vertragsbestandteil = new VertragsbestandteilFunktion(); + $vertragsbestandteil->hydrateByStdClass($data, $fromdb); + break; + + case self::VERTRAGSBESTANDTEIL_KARENZ: + $vertragsbestandteil = new VertragsbestandteilKarenz(); + $vertragsbestandteil->hydrateByStdClass($data, $fromdb); + break; + + case self::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST: + $vertragsbestandteil = new VertragsbestandteilKuendigungsfrist(); + $vertragsbestandteil->hydrateByStdClass($data, $fromdb); + break; + + case self::VERTRAGSBESTANDTEIL_STUNDEN: + $vertragsbestandteil = new VertragsbestandteilStunden(); + $vertragsbestandteil->hydrateByStdClass($data, $fromdb); + break; + + case self::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH: + $vertragsbestandteil = new VertragsbestandteilUrlaubsanspruch(); + $vertragsbestandteil->hydrateByStdClass($data, $fromdb); + break; + + case self::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG: + $vertragsbestandteil = new VertragsbestandteilZeitaufzeichnung(); + $vertragsbestandteil->hydrateByStdClass($data, $fromdb); + break; + + default: + throw new Exception('Unknown vertragsbestandteiltyp_kurzbz ' + . $vertragsbestandteiltyp_kurzbz); + } + + return $vertragsbestandteil; + } + + public static function getVertragsbestandteilDBModel($vertragsbestandteil_kurzbz): \DB_model + { + $CI = get_instance(); + + $vertragsbestandteildbmodel = null; + switch ($vertragsbestandteil_kurzbz) + { + case self::VERTRAGSBESTANDTEIL_FREITEXT: + $CI->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model', + 'VertragsbestandteilFreitext_model'); + $vertragsbestandteildbmodel = $CI->VertragsbestandteilFreitext_model; + break; + + case self::VERTRAGSBESTANDTEIL_FUNKTION: + $CI->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model', + 'VertragsbestandteilFunktion_model'); + $vertragsbestandteildbmodel = $CI->VertragsbestandteilFunktion_model; + break; + + case self::VERTRAGSBESTANDTEIL_KARENZ: + $CI->load->model('vertragsbestandteil/VertragsbestandteilKarenz_model', + 'VertragsbestandteilKarenz_model'); + $vertragsbestandteildbmodel = $CI->VertragsbestandteilKarenz_model; + break; + + case self::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST: + $CI->load->model('vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model', + 'VertragsbestandteilKuendigungsfrist_model'); + $vertragsbestandteildbmodel = $CI->VertragsbestandteilKuendigungsfrist_model; + break; + + case self::VERTRAGSBESTANDTEIL_STUNDEN: + $CI->load->model('vertragsbestandteil/VertragsbestandteilStunden_model', + 'VertragsbestandteilStunden_model'); + $vertragsbestandteildbmodel = $CI->VertragsbestandteilStunden_model; + break; + + case self::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH: + $CI->load->model('vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model', + 'VertragsbestandteilUrlaubsanspruch_model'); + $vertragsbestandteildbmodel = $CI->VertragsbestandteilUrlaubsanspruch_model; + break; + + case self::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG: + $CI->load->model('vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model', + 'VertragsbestandteilZeitaufzeichnung_model'); + $vertragsbestandteildbmodel = $CI->VertragsbestandteilZeitaufzeichnung_model; + break; + + default: + throw new Exception('Unknown vertragsbestandteil_kurzbz ' + . $vertragsbestandteil_kurzbz); + } + + return $vertragsbestandteildbmodel; + } +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilFreitext.php b/application/libraries/vertragsbestandteil/VertragsbestandteilFreitext.php new file mode 100644 index 000000000..07e8a3c58 --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilFreitext.php @@ -0,0 +1,134 @@ +setVertragsbestandteiltyp_kurzbz( + VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FREITEXT); + } + + public function hydrateByStdClass($data, $fromdb=false) + { + parent::hydrateByStdClass($data, $fromdb); + $this->fromdb = $fromdb; + isset($data->freitexttyp) && $this->setFreitexttypKurzbz($data->freitexttyp); + isset($data->freitexttyp_kurzbz) && $this->setFreitexttypKurzbz($data->freitexttyp_kurzbz); + isset($data->titel) && $this->setTitel($data->titel); + isset($data->freitext) && $this->setAnmerkung($data->freitext); + isset($data->anmerkung) && $this->setAnmerkung($data->anmerkung); + $this->fromdb = false; + } + + public function toStdClass(): \stdClass + { + $tmp = array( + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'freitexttyp_kurzbz' => $this->getFreitexttypKurzbz(), + 'titel' => $this->getTitel(), + 'anmerkung' => $this->getAnmerkung() + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function __toString() + { + $txt = <<getAnmerkung()} + titel: {$this->getTitel()} + freitexttyp_kurzbz: {$this->getFreitexttypKurzbz()} + +EOTXT; + return parent::__toString() . $txt; + } + + /** + * Get the value of anmerkung + */ + public function getAnmerkung() + { + return $this->anmerkung; + } + + /** + * Set the value of anmerkung + */ + public function setAnmerkung($anmerkung): self + { + $this->markDirty('anmerkung', $this->anmerkung, $anmerkung); + $this->anmerkung = $anmerkung; + + return $this; + } + + /** + * Get the value of titel + */ + public function getTitel() + { + return $this->titel; + } + + /** + * Set the value of titel + */ + public function setTitel($titel): self + { + $this->markDirty('titel', $this->titel, $titel); + $this->titel = $titel; + + return $this; + } + + /** + * Get the value of freitexttyp_kurzbz + */ + public function getFreitexttypKurzbz() + { + return $this->freitexttyp_kurzbz; + } + + /** + * Set the value of freitexttyp_kurzbz + */ + public function setFreitexttypKurzbz($freitexttyp_kurzbz): self + { + $this->markDirty('freitexttyp_kurzbz', $this->freitexttyp_kurzbz, $freitexttyp_kurzbz); + $this->freitexttyp_kurzbz = $freitexttyp_kurzbz; + + return $this; + } + + public function validate() + { + if( empty($this->freitexttyp_kurzbz) ) { + $this->validationerrors[] = 'Bitte einen gültigen Freitexttyp auswählen.'; + } + + if( empty($this->titel) ) { + $this->validationerrors[] = 'Bitte einen Titel angeben.'; + } + + if( empty($this->anmerkung) ) { + $this->validationerrors[] = 'Bitte eine Beschreibung eingeben.'; + } + + return parent::validate(); + } + + +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilFunktion.php b/application/libraries/vertragsbestandteil/VertragsbestandteilFunktion.php new file mode 100644 index 000000000..ee5cd713f --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilFunktion.php @@ -0,0 +1,369 @@ +benutzerfunktiondata = null; + + $this->setVertragsbestandteiltyp_kurzbz( + VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FUNKTION); + + $this->CI = get_instance(); + $this->CI->load->model('person/Benutzerfunktion_model', + 'BenutzerfunktionModel'); + $this->CI->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model', + 'VertragsbestandteilFunktionModel'); + $this->CI->load->library('vertragsbestandteil/VertragsbestandteilLib', + null, 'VertragsbestandteilLib'); + } + + public function isDirty() + { + $isdirty = parent::isDirty(); + if( !$isdirty ) { + $bf = $this->loadBenutzerfunktion($this->getBenutzerfunktion_id()); + if( !$this->areVbAndBfInSync($bf) ) + { + $isdirty = true; + } + } + return $isdirty; + } + + public function beforePersist() + { + if( isset($this->benutzerfunktion_id) && intval($this->benutzerfunktion_id) > 0 ) + { + $this->beforePersitExisting(); + } + else + { + $this->beforePersitNew(); + } + } + + protected function loadBenutzerfunktion($bfid) + { + $bfres = $this->CI->BenutzerfunktionModel->load($bfid); + if(!hasData($bfres)) + { + throw new Exception('failed to load existing Benutzerfunktion'); + } + return (getData($bfres))[0]; + } + + protected function loadPersitedVB($vbid) + { + $vb = $this->CI->VertragsbestandteilLib->fetchVertragsbestandteil($vbid); + if( $vb === null ) + { + throw new Exception('failed to load persited Vertragsbestandteil'); + } + return $vb; + } + + protected function areVbAndBfInSync($bf) + { + $vbvon = $this->getVon(); + $vbbis = $this->getBis(); + if( intval($this->getVertragsbestandteil_id()) > 0 ) + { + $vb = $this->loadPersitedVB($this->getVertragsbestandteil_id()); + $vbvon = $vb->getVon(); + $vbbis = $vb->getBis(); + } + + if( ($bf->datum_von === $vbvon) && ($bf->datum_bis === $vbbis) ) + { + return true; + } + return false; + } + + protected function isBefore($a, $b) + { + if($a === null) { + return false; + } + elseif($b === null) { + return true; + } + else { + return $a < $b; + } + } + + protected function isAfter($a, $b) + { + if($b === null) { + return false; + } + elseif($a === null) { + return true; + } + else { + return $a > $b; + } + } + + protected function beforePersitExisting() + { + $bf = $this->loadBenutzerfunktion($this->getBenutzerfunktion_id()); + if( $this->areVbAndBfInSync($bf) ) + { + // vb or stored vb von bis is in sync so update benutzerfunktion + $this->updateBenutzerfunktion($bf, $this->getVon(), $this->getBis()); + } + else + { + $daybeforevon = \DateTime::createFromFormat('Y-m-d', $this->getVon(), + new \DateTimeZone('Europe/Vienna')); + $daybeforevon->sub(new \DateInterval('P1D')); + + if( $this->isBefore($bf->datum_von, $this->getVon()) && + $this->isBefore($bf->datum_von, $this->getBis()) ) + { + $data = (object) array( + 'mitarbeiter_uid' => $bf->uid, + 'funktion' => $bf->funktion_kurzbz, + 'orget' => $bf->oe_kurzbz + ); + $this->createBenutzerfunktionData($data); + $bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert()); + $this->setBenutzerfunktion_id($bfid); + } + elseif( $this->isBefore($bf->datum_von, $this->getVon()) && + $this->isAfter($this->getBis(), $bf->datum_von) ) + { + $this->updateBenutzerfunktion($bf, $bf->datum_von, $daybeforevon->format('Y-m-d')); + $data = (object) array( + 'mitarbeiter_uid' => $bf->uid, + 'funktion' => $bf->funktion_kurzbz, + 'orget' => $bf->oe_kurzbz + ); + $this->createBenutzerfunktionData($data); + $bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert()); + $this->setBenutzerfunktion_id($bfid); + } + else + { + $this->updateBenutzerfunktion($bf, $this->getVon(), $this->getBis()); + } + } + } + + protected function updateBenutzerfunktion($bf, $von, $bis) + { + $data = array(); + + if($von !== $bf->datum_von) + { + $data['datum_von'] = $von; + } + if($bis !== $bf->datum_bis) + { + $data['datum_bis'] = $bis; + } + + if( count($data) === 0 ) + { + return; + } + + $data['updateamum'] = strftime('%Y-%m-%d %H:%M:%S'); + $data['updatevon'] = getAuthUID(); + + $ret = $this->CI->BenutzerfunktionModel->update($bf->benutzerfunktion_id, $data); + + if(isError($ret) ) + { + throw new Exception('failed to update Benutzerfunktion'); + } + } + + protected function insertBenutzerfunktion($benutzerfunktiondata) + { + $ret = $this->CI->BenutzerfunktionModel->insert($benutzerfunktiondata); + + if(isError($ret) ) + { + throw new Exception('failed to create Benutzerfunktion'); + } + + return getData($ret); + } + + protected function deleteBenutzerfunktion($benutzerfunktion_id) + { + $ret = $this->CI->BenutzerfunktionModel->delete($benutzerfunktion_id); + + if(isError($ret) ) + { + throw new Exception('failed to delete Benutzerfunktion'); + } + } + + protected function beforePersitNew() { + if( $this->benutzerfunktiondata === null) + { + return; + } + + $bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert()); + + $this->setBenutzerfunktion_id($bfid); + } + + public function afterDelete() + { + if( !(intval($this->getBenutzerfunktion_id()) > 0) ) + { + return; + } + + $this->deleteBenutzerfunktion($this->getBenutzerfunktion_id()); + } + + public function toStdClass() + { + $tmp = array( + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'benutzerfunktion_id' => $this->getBenutzerfunktion_id() + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function __toString() + { + $txt = <<getBenutzerfunktion_id()} + +EOTXT; + return parent::__toString() . $txt; + } + + public function hydrateByStdClass($data, $fromdb=false) + { + parent::hydrateByStdClass($data, $fromdb); + $this->fromdb = $fromdb; + isset($data->benutzerfunktionid) && $this->setBenutzerfunktion_id($data->benutzerfunktionid); + isset($data->benutzerfunktion_id) && $this->setBenutzerfunktion_id($data->benutzerfunktion_id); + isset($data->funktion) && isset($data->orget) + && isset($data->mitarbeiter_uid) && $this->createBenutzerfunktionData($data); + isset($data->funktion_bezeichnung) && isset($data->oe_bezeichnung) + && $this->createBenutzerfunktionData4Display($data); + $this->fromdb = false; + + } + + public function getBenutzerfunktion_id() + { + return $this->benutzerfunktion_id; + } + + public function setBenutzerfunktion_id($benutzerfunktion_id) + { + $this->markDirty('benutzerfunktion_id', $this->benutzerfunktion_id, $benutzerfunktion_id); + $this->benutzerfunktion_id = $benutzerfunktion_id; + return $this; + } + + protected function getBenutzerfunktionData4Insert() + { + if( null === $this->benutzerfunktiondata ) { + return null; + } + + $benutzerfunktiondata = (object) array( + 'funktion_kurzbz' => $this->benutzerfunktiondata->funktion_kurzbz, + 'oe_kurzbz' => $this->benutzerfunktiondata->oe_kurzbz, + 'uid' => $this->benutzerfunktiondata->uid, + 'datum_von' => $this->getVon(), + 'datum_bis' => $this->getBis(), + 'insertamum' => strftime('%Y-%m-%d %H:%M:%S'), + 'insertvon' => getAuthUID() + ); + + return $benutzerfunktiondata; + } + + protected function createBenutzerfunktionData($data) + { + if( empty($data->funktion) || empty($data->orget) ) + { + return; + } + + $this->benutzerfunktiondata = (object) array( + 'funktion_kurzbz' => $data->funktion, + 'oe_kurzbz' => $data->orget, + 'uid' => $data->mitarbeiter_uid + ); + } + + protected function createBenutzerfunktionData4Display($data) + { + if( empty($data->funktion_bezeichnung) || empty($data->oe_bezeichnung) ) + { + return; + } + + $this->benutzerfunktiondata = (object) array( + 'funktion_kurzbz' => $data->funktion_kurzbz, + 'funktion_bezeichnung' => $data->funktion_bezeichnung, + 'oe_kurzbz' => $data->oe_kurzbz, + 'oe_bezeichnung' => $data->oe_bezeichnung, + 'oe_kurzbz_sap' => $data->oe_kurzbz_sap, + 'oe_typ_kurzbz' => $data->oe_typ_kurzbz, + 'oe_typ_bezeichnung' => $data->oe_typ_bezeichnung, + 'uid' => $data->mitarbeiter_uid + ); + } + + public function validate() + { + if( (intval($this->benutzerfunktion_id) < 1) + && ($this->benutzerfunktiondata === NULL) ) { + $this->validationerrors[] = 'Eine bestehende Funktion oder eine ' + . 'Funktion und eine Organisationseinheit müssen ausgewählt sein.'; + } + + // TODO check if Benutzerfunktion is assigned to another vb + if( intval($this->benutzerfunktion_id) > 0 ) + { + if ( $this->CI->VertragsbestandteilFunktionModel + ->isBenutzerfunktionAlreadyAttachedToAnotherVB( + $this->benutzerfunktion_id, + $this->getVertragsbestandteil_id()) ) + { + $this->validationerrors[] = 'Die Benutzerfunktion ist bereits ' + . 'mit einem anderen Vertragsbestandteil verknüpft und kann ' + . 'nicht mehrfach verknüft werden.'; + } + } + + return parent::validate(); + } +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilKarenz.php b/application/libraries/vertragsbestandteil/VertragsbestandteilKarenz.php new file mode 100644 index 000000000..7b49bfe4c --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilKarenz.php @@ -0,0 +1,141 @@ +setVertragsbestandteiltyp_kurzbz( + VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_KARENZ); + } + + public function hydrateByStdClass($data, $fromdb=false) + { + parent::hydrateByStdClass($data, $fromdb); + $this->fromdb = $fromdb; + isset($data->karenztyp_kurzbz) && $this->setKarenztypKurzbz($data->karenztyp_kurzbz); + isset($data->geplanter_geburtstermin) && $this->setGeplanterGeburtstermin($data->geplanter_geburtstermin); + isset($data->tatsaechlicher_geburtstermin) && $this->setTatsaechlicherGeburtstermin($data->tatsaechlicher_geburtstermin); + $this->fromdb = false; + } + + /** + * Get the value of karenztyp_kurzbz + */ + public function getKarenztypKurzbz() + { + return $this->karenztyp_kurzbz; + } + + /** + * Set the value of karenztyp_kurzbz + */ + public function setKarenztypKurzbz($karenztyp_kurzbz): self + { + $this->markDirty('karenztyp_kurzbz', $this->karenztyp_kurzbz, $karenztyp_kurzbz); + $this->karenztyp_kurzbz = $karenztyp_kurzbz; + + return $this; + } + + /** + * Get the value of tatsaechlicher_geburtstermin + */ + public function getTatsaechlicherGeburtstermin() + { + return $this->tatsaechlicher_geburtstermin; + } + + /** + * Set the value of tatsaechlicher_geburtstermin + */ + public function setTatsaechlicherGeburtstermin($tatsaechlicher_geburtstermin): self + { + $this->markDirty('tatsaechlicher_geburtstermin', $this->tatsaechlicher_geburtstermin, $tatsaechlicher_geburtstermin); + $this->tatsaechlicher_geburtstermin = $tatsaechlicher_geburtstermin; + + return $this; + } + + /** + * Get the value of geplanter_geburtstermin + */ + public function getGeplanterGeburtstermin() + { + return $this->geplanter_geburtstermin; + } + + /** + * Set the value of geplanter_geburtstermin + */ + public function setGeplanterGeburtstermin($geplanter_geburtstermin): self + { + $this->markDirty('geplanter_geburtstermin', $this->geplanter_geburtstermin, $geplanter_geburtstermin); + $this->geplanter_geburtstermin = $geplanter_geburtstermin; + + return $this; + } + + public function toStdClass(): \stdClass + { + $tmp = array( + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'karenztyp_kurzbz' => $this->getKarenztypKurzbz(), + 'tatsaechlicher_geburtstermin' => $this->getTatsaechlicherGeburtstermin(), + 'geplanter_geburtstermin' => $this->getGeplanterGeburtstermin() + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function __toString() + { + $txt = <<getKarenztypKurzbz()} + tatsaechlicher_geburtstermin: {$this->getTatsaechlicherGeburtstermin()} + geplanter_geburtstermin: {$this->getGeplanterGeburtstermin()} + +EOTXT; + return parent::__toString() . $txt; + } + + public function validate() + { + if( empty($this->karenztyp_kurzbz) ) { + $this->validationerrors[] = 'Ein Karenztyp muss ausgewählt sein.'; + } + + if( $this->karenztyp_kurzbz === 'elternkarenz' ) { + $geplant = \DateTimeImmutable::createFromFormat('Y-m-d', $this->geplanter_geburtstermin); + $tatsaechlich = \DateTimeImmutable::createFromFormat('Y-m-d', $this->tatsaechlicher_geburtstermin); + + if( false === $geplant ) { + $this->validationerrors[] = 'Bei Elternkarenz muss der geplanter Geburtstermin ein gültiges Datum sein.'; + } + + if( !empty($this->tatsaechlicher_geburtstermin) && $tatsaechlich === false ) { + $this->validationerrors[] = 'Bei Elternkarenz muss der tatsaechliche Geburtstermin leer oder ein gültiges Datum sein.'; + } + } + + $bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis); + + if( false === $bis ) { + $this->validationerrors[] = 'Bei einer Karenz muss ein gültiges Ende-Datum angegeben werden.'; + } + + return parent::validate(); + } +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilKuendigungsfrist.php b/application/libraries/vertragsbestandteil/VertragsbestandteilKuendigungsfrist.php new file mode 100644 index 000000000..81ea0dcec --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilKuendigungsfrist.php @@ -0,0 +1,117 @@ +setVertragsbestandteiltyp_kurzbz( + VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST); + } + + public function hydrateByStdClass($data, $fromdb=false) + { + parent::hydrateByStdClass($data, $fromdb); + $this->fromdb = $fromdb; + isset($data->arbeitgeber_frist) && $this->setArbeitgeberFrist($data->arbeitgeber_frist); + isset($data->arbeitnehmer_frist) && $this->setArbeitnehmerFrist($data->arbeitnehmer_frist); + $this->fromdb = false; + } + + /** + * Get the value of arbeitgeber_frist + */ + public function getArbeitgeberFrist() + { + return $this->arbeitgeber_frist; + } + + /** + * Set the value of arbeitgeber_frist + */ + public function setArbeitgeberFrist($arbeitgeber_frist): self + { + $this->markDirty('arbeitgeber_frist', $this->arbeitgeber_frist, $arbeitgeber_frist); + $this->arbeitgeber_frist = $arbeitgeber_frist; + + return $this; + } + + /** + * Get the value of arbeitnehmer_frist + */ + public function getArbeitnehmerFrist() + { + return $this->arbeitnehmer_frist; + } + + /** + * Set the value of arbeitnehmer_frist + */ + public function setArbeitnehmerFrist($arbeitnehmer_frist): self + { + $this->markDirty('arbeitnehmer_frist', $this->arbeitnehmer_frist, $arbeitnehmer_frist); + $this->arbeitnehmer_frist = $arbeitnehmer_frist; + + return $this; + } + + public function toStdClass(): \stdClass + { + $tmp = array( + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'arbeitgeber_frist' => $this->getArbeitgeberFrist(), + 'arbeitnehmer_frist' => $this->getArbeitnehmerFrist() + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function __toString() + { + $txt = <<getArbeitgeberFrist()} + arbeitnehmer_frist: {$this->getArbeitnehmerFrist()} + +EOTXT; + return parent::__toString() . $txt; + } + + public function validate() + { + if( !(filter_var($this->arbeitgeber_frist, FILTER_VALIDATE_INT, + array( + 'options' => array( + 'min_range' => 0, + 'max_range' => 52 + ) + ) + )) ) { + $this->validationerrors[] = 'Arbeitgeberfrist muss eine Wochenanzahl im Bereich 1 bis 52 sein.'; + } + + if( !(filter_var($this->arbeitnehmer_frist, FILTER_VALIDATE_INT, + array( + 'options' => array( + 'min_range' => 1, + 'max_range' => 52 + ) + ) + )) ) { + $this->validationerrors[] = 'Arbeitnehmerfrist muss eine Wochenanzahl im Bereich 1 bis 52 sein.'; + } + + return parent::validate(); + } +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilLib.php b/application/libraries/vertragsbestandteil/VertragsbestandteilLib.php new file mode 100644 index 000000000..b58c514e1 --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilLib.php @@ -0,0 +1,512 @@ +loggedInUser = getAuthUID(); + $this->CI = get_instance(); + $this->CI->load->model('vertragsbestandteil/Dienstverhaeltnis_model', + 'DienstverhaeltnisModel'); + $this->DienstverhaeltnisModel = $this->CI->DienstverhaeltnisModel; + $this->CI->load->model('vertragsbestandteil/Vertragsbestandteil_model', + 'VertragsbestandteilModel'); + $this->VertragsbestandteilModel = $this->CI->VertragsbestandteilModel; + $this->CI->load->model('person/benutzer_model', + 'BenutzerModel'); + $this->BenutzerModel = $this->CI->BenutzerModel; + $this->CI->load->library('vertragsbestandteil/GehaltsbestandteilLib', + null, 'GehaltsbestandteilLib'); + $this->GehaltsbestandteilLib = $this->CI->GehaltsbestandteilLib; + } + + public function handleGUIData($guidata, $employeeUID, $userUID) + { + $guiHandler = new GUIHandler($employeeUID, $userUID); + $ret = false; + try { + $ret = $guiHandler->handle($guidata, $employeeUID, $userUID); + } catch (Exception $ex) + { + log_message('debug', "Error handling json data from GUI. " . $ex->getMessage()); + } + + return $ret; + } + + public function fetchDienstverhaeltnisse($unternehmen, $stichtag=null, $mitarbeiteruid=null) { + $dvs = $this->DienstverhaeltnisModel->fetchDienstverhaeltnisse($unternehmen, $stichtag, $mitarbeiteruid); + return $dvs; + } + + public function fetchDienstverhaeltnis($dienstverhaeltnis_id) + { + $result = $this->DienstverhaeltnisModel->load($dienstverhaeltnis_id); + $dv = null; + if(null !== ($row = getData($result))) + { + $dv = new Dienstverhaeltnis(); + $dv->hydrateByStdClass($row[0], true); + } + return $dv; + } + + public function fetchVertragsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false) + { + $vbs = $this->VertragsbestandteilModel->getVertragsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture); + $gbs = $this->GehaltsbestandteilLib->fetchGehaltsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture); + + $gbsByVBid = array(); + foreach( $gbs as $gb ) + { + if( intval($gb->getVertragsbestandteil_id()) > 0 ) + { + if( !isset($gbsByVBid[$gb->getVertragsbestandteil_id()]) + || !is_array($gbsByVBid[$gb->getVertragsbestandteil_id()]) ) { + $gbsByVBid[$gb->getVertragsbestandteil_id()] = array(); + } + $gbsByVBid[$gb->getVertragsbestandteil_id()][] = $gb; + } + } + + foreach ($vbs as $vb) + { + if( isset($gbsByVBid[$vb->getVertragsbestandteil_id()]) ) + { + $vb->setGehaltsbestandteile($gbsByVBid[$vb->getVertragsbestandteil_id()]); + } + } + + return $vbs; + } + + public function fetchVertragsbestandteil($vertragsbestandteil_id) + { + return $this->VertragsbestandteilModel->getVertragsbestandteil($vertragsbestandteil_id); + } + + public function storeDienstverhaeltnis(Dienstverhaeltnis $dv) + { + if( intval($dv->getDienstverhaeltnis_id()) > 0 ) + { + $this->updateDienstverhaeltnis($dv); + } + else + { + $this->insertDienstverhaeltnis($dv); + } + } + + public function storeVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil) + { + $this->CI->db->trans_begin(); + try + { + $this->setUIDtoPGSQL(); + if( intval($vertragsbestandteil->getVertragsbestandteil_id()) > 0 ) + { + $this->updateVertragsbestandteil($vertragsbestandteil); + } + else + { + $this->insertVertragsbestandteil($vertragsbestandteil); + } + if( $this->CI->db->trans_status() === false ) + { + log_message('debug', "Transaction failed"); + throw new Exception("Transaction failed"); + } + $this->CI->db->trans_commit(); + } + catch (Exception $ex) + { + log_message('debug', "Transaction rolled back. " . $ex->getMessage()); + $this->CI->db->trans_rollback(); + throw new Exception('Storing Vertragsbestandteil failed.'); + } + } + + public function deleteDienstverhaeltnis(Dienstverhaeltnis $dv) + { + $this->CI->db->trans_begin(); + try + { + $this->setUIDtoPGSQL(); + if( intval($dv->getDienstverhaeltnis_id()) > 0 ) + { + $vbs = $this->fetchVertragsbestandteile($dv->getDienstverhaeltnis_id()); + foreach ($vbs as $vb) + { + $this->deleteVertragsbestandteil($vb); + } + + $ret = $this->DienstverhaeltnisModel->delete($dv->getDienstverhaeltnis_id()); + if(isError($ret) ) + { + log_message('debug', "Delete DV failed"); + throw new Exception('error deleting dienstverhaeltnis ' + . $dv->getDienstverhaeltnis_id()); + } + + if( $this->CI->db->trans_status() === false ) + { + log_message('debug', "Transaction failed"); + throw new Exception("Transaction failed"); + } + $this->CI->db->trans_commit(); + } + } + catch (Exception $ex) + { + log_message('debug', "Transaction rolled back. " . $ex->getMessage()); + $this->CI->db->trans_rollback(); + return $ex->getMessage(); + } + + return true; + + } + + public function deleteVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil) + { + $this->CI->db->trans_begin(); + try + { + $this->setUIDtoPGSQL(); + if( intval($vertragsbestandteil->getVertragsbestandteil_id()) > 0 ) + { + $this->deleteVertragsbestandteilHelper($vertragsbestandteil); + } + if( $this->CI->db->trans_status() === false ) + { + log_message('debug', "Transaction failed"); + throw new Exception("Transaction failed"); + } + $this->CI->db->trans_commit(); + } + catch (Exception $ex) + { + log_message('debug', "Transaction rolled back. " . $ex->getMessage()); + $this->CI->db->trans_rollback(); + throw new Exception('Delete Vertragsbestandteil failed.'); + } + } + + protected function insertDienstverhaeltnis(Dienstverhaeltnis $dv) + { + $dv->setInsertvon($this->loggedInUser) + ->setInsertamum(strftime('%Y-%m-%d %H:%M:%S')); + $ret = $this->DienstverhaeltnisModel->insert($dv->toStdClass()); + if( hasData($ret) ) + { + $dv->setDienstverhaeltnis_id(getData($ret)); + } + else + { + throw new Exception('error inserting dienstverhaeltnis'); + } + } + + protected function insertVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil) + { + $vertragsbestandteil->setInsertvon($this->loggedInUser) + ->setInsertamum(strftime('%Y-%m-%d %H:%M:%S')); + $vertragsbestandteil->beforePersist(); + $ret = $this->VertragsbestandteilModel->insert($vertragsbestandteil->baseToStdClass()); + if( hasData($ret) ) + { + $vertragsbestandteil->setVertragsbestandteil_id(getData($ret)); + } + else + { + throw new Exception('error inserting vertragsbestandteil'); + } + + $specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel( + $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz()); + $retspecial = $specialisedModel->insert($vertragsbestandteil->toStdClass()); + + if(isError($retspecial) ) + { + throw new Exception('error updating vertragsbestandteil ' + . $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz()); + } + + try + { + $gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile(); + $this->GehaltsbestandteilLib->storeGehaltsbestandteile($gehaltsbestandteile); + } + catch(Exception $ex) + { + throw new Exception('VertragsbestandteilLib insertVertragsbestandteil ' + . 'failed to store Gehaltsbestandteile. ' . $ex->getMessage()); + } + } + + protected function updateDienstverhaeltnis(Dienstverhaeltnis $dv) + { + if(!$dv->isDirty()) { + return; + } + + $dv->setUpdatevon($this->loggedInUser) + ->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S')); + $ret = $this->DienstverhaeltnisModel->update($dv->getDienstverhaeltnis_id(), + $dv->toStdClass()); + if(isError($ret) ) + { + throw new Exception('error updating dienstverhaeltnis'); + } + } + + private function deleteVertragsbestandteilHelper(Vertragsbestandteil $vertragsbestandteil) + { + + $specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel( + $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz()); + $retspecial = $specialisedModel->delete($vertragsbestandteil->getVertragsbestandteil_id()); + + if(isError($retspecial) ) + { + throw new Exception('error deleting vertragsbestandteil ' + . $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz()); + } + + try + { + $gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile(); + $this->GehaltsbestandteilLib->deleteGehaltsbestandteile($gehaltsbestandteile); + } + catch(Exception $ex) + { + throw new Exception('VertragsbestandteilLib deleteVertragsbestandteil ' + . 'failed to delete Gehaltsbestandteile. ' . $ex->getMessage()); + } + + + $ret = $this->VertragsbestandteilModel->delete($vertragsbestandteil->getVertragsbestandteil_id()); + + if(isError($ret) ) + { + throw new Exception('error deleting vertragsbestandteil'); + } + + $vertragsbestandteil->afterDelete(); + } + + protected function updateVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil) + { + if($vertragsbestandteil->isDirty()) { + $vertragsbestandteil->setUpdatevon($this->loggedInUser) + ->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S')); + $vertragsbestandteil->beforePersist(); + $basedata = $vertragsbestandteil->baseToStdClass(); + if( count((array) $basedata) > 0 ) + { + $ret = $this->VertragsbestandteilModel->update( + $vertragsbestandteil->getVertragsbestandteil_id(), + $basedata); + + if(isError($ret) ) + { + throw new Exception('error updating vertragsbestandteil'); + } + } + + $specialisedData = $vertragsbestandteil->toStdClass(); + if( count((array) $specialisedData) > 0 ) + { + $specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel( + $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz()); + $retspecial = $specialisedModel->update( + $vertragsbestandteil->getVertragsbestandteil_id(), + $specialisedData); + + if(isError($retspecial) ) + { + throw new Exception('error updating vertragsbestandteil ' + . $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz()); + } + } + } + + try + { + $gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile(); + $this->GehaltsbestandteilLib->storeGehaltsbestandteile($gehaltsbestandteile); + } + catch(Exception $ex) + { + throw new Exception('VertragsbestandteilLib updateVertragsbestandteil ' + . 'failed to store Gehaltsbestandteile. ' . $ex->getMessage()); + } + } + + public function isOverlappingExistingDV(Dienstverhaeltnis $dv) + { + return $this->DienstverhaeltnisModel->isOverlappingExistingDV( + $dv->getMitarbeiter_uid(), + $dv->getOe_kurzbz(), + $dv->getVon(), + $dv->getBis(), + $dv->getDienstverhaeltnis_id() + ); + } + + protected function hasOtherActiveDV(Dienstverhaeltnis $dv, $duedate) + { + $hasotheractivedv = false; + $result = $this->DienstverhaeltnisModel->getDVByPersonUID($dv->getMitarbeiter_uid(), null, $duedate); + $dvs = getData($result); + foreach ($dvs as $tmpdv) + { + if(intval($tmpdv->dienstverhaeltnis_id) !== intval($dv->getDienstverhaeltnis_id())) + { + $hasotheractivedv = true; + break; + } + } + return $hasotheractivedv; + } + + /** + * like endDienstverhaeltnis, but also sets aktiv flag to false + */ + public function deactivateDienstverhaeltnis(Dienstverhaeltnis $dv, $enddate, $deactivate) + { + $result = $this->endDienstverhaeltnis($dv, $enddate); + if ( $result === true) + { + if (!$deactivate) return $result; + + if(!$this->hasOtherActiveDV($dv, $enddate)) + { + $result = $this->BenutzerModel->update( + array('uid' => $dv->getMitarbeiter_uid()), + array( + 'aktiv' => false, + 'updateaktivam' => date('Y-m-d'), + 'updateaktivvon' => $this->loggedInUser + ) + ); + } + } + + return $result; + } + + public function endDienstverhaeltnis(Dienstverhaeltnis $dv, $enddate, $dvendegrund_kurzbz=null, $dvendegrund_anmerkung=null) + { + if( $dv->getBis() !== null && $dv->getBis() < $enddate ) + { + return 'Dienstverhältnis ist bereits beendet.'; + } + + $this->CI->db->trans_begin(); + try + { + $this->setUIDtoPGSQL(); + if( intval($dv->getDienstverhaeltnis_id()) > 0 ) + { + $gbs = $this->GehaltsbestandteilLib->fetchGehaltsbestandteile($dv->getDienstverhaeltnis_id()); + foreach ($gbs as $gb) + { + $this->GehaltsbestandteilLib->endGehaltsbestandteil($gb, $enddate); + } + + $vbs = $this->fetchVertragsbestandteile($dv->getDienstverhaeltnis_id()); + foreach ($vbs as $vb) + { + $this->endVertragsbestandteil($vb, $enddate); + } + + if( $dvendegrund_kurzbz !== null ) + { + $dv->setDvendegrund_kurzbz($dvendegrund_kurzbz); + } + if( $dvendegrund_anmerkung !== null ) + { + $dv->setDvendegrund_anmerkung($dvendegrund_anmerkung); + } + $dv->setBis($enddate); + $this->updateDienstverhaeltnis($dv); + + if( $this->CI->db->trans_status() === false ) + { + log_message('debug', "Transaction failed"); + throw new Exception("Transaction failed"); + } + $this->CI->db->trans_commit(); + } + } + catch (Exception $ex) + { + log_message('debug', "end DV failed " . $dv->getDienstverhaeltnis_id()); + log_message('debug', "Transaction rolled back. " . $ex->getMessage()); + $this->CI->db->trans_rollback(); + return $ex->getMessage(); + } + return true; + } + + public function endVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil, $enddate) + { + if( $vertragsbestandteil->getBis() !== null && $vertragsbestandteil->getBis() < $enddate ) + { + return; + } + + $vertragsbestandteil->setBis($enddate); + $this->updateVertragsbestandteil($vertragsbestandteil); + } + + protected function setUIDtoPGSQL() { + $ret = $this->VertragsbestandteilModel + ->execReadOnlyQuery('SET LOCAL pv21.uid TO \'' + . $this->loggedInUser . '\''); + if(isError($ret)) + { + throw new Exception('error setting uid to pgsql'); + } + } +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilStunden.php b/application/libraries/vertragsbestandteil/VertragsbestandteilStunden.php new file mode 100644 index 000000000..f2d8c8081 --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilStunden.php @@ -0,0 +1,110 @@ +setVertragsbestandteiltyp_kurzbz( + VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_STUNDEN); + } + + public function hydrateByStdClass($data, $fromdb=false) + { + parent::hydrateByStdClass($data, $fromdb); + $this->fromdb = $fromdb; + isset($data->wochenstunden) && $this->setWochenstunden($data->wochenstunden); + isset($data->teilzeittyp_kurzbz) && $this->setTeilzeittyp_kurzbz($data->teilzeittyp_kurzbz); + $this->fromdb = false; + } + + public function getWochenstunden() + { + return $this->wochenstunden; + } + + public function getTeilzeittyp_kurzbz() + { + return $this->teilzeittyp_kurzbz; + } + + public function setWochenstunden($wochenstunden) + { + $this->markDirty('wochenstunden', $this->wochenstunden, $wochenstunden); + $this->wochenstunden = $wochenstunden; + return $this; + } + + public function setTeilzeittyp_kurzbz($teilzeittyp_kurzbz) + { + $teilzeittyp_kurzbz = ($teilzeittyp_kurzbz !== '') + ? $teilzeittyp_kurzbz : null; + $this->markDirty('teilzeittyp_kurzbz', $this->teilzeittyp_kurzbz, $teilzeittyp_kurzbz); + $this->teilzeittyp_kurzbz = $teilzeittyp_kurzbz; + return $this; + } + + public function toStdClass(): \stdClass + { + $tmp = array( + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'wochenstunden' => $this->getWochenstunden(), + 'teilzeittyp_kurzbz' => $this->getTeilzeittyp_kurzbz() + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function __toString() + { + $txt = <<getWochenstunden()} + teilzeittyp_kurzbz: {$this->getTeilzeittyp_kurzbz()} + +EOTXT; + return parent::__toString() . $txt; + } + + public function validate() + { + if( false === filter_var($this->wochenstunden, FILTER_VALIDATE_FLOAT, + array( + 'options' => array( + 'min_range' => 0, + 'max_range' => 100 + ) + ) + ) ) { + $this->validationerrors[] = 'Stunden muss eine Kommazahl im Bereich 0 bis 100 sein.'; + } + else + { + if( floatval($this->wochenstunden) < floatval('0.01') && + $this->teilzeittyp_kurzbz !== 'altersteilzeit' ) + { + $this->validationerrors[] = '0 Wochenstunden ist nur in Kombination mit Altersteilzeit zulässig.'; + } + } + + return parent::validate(); + } +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch.php b/application/libraries/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch.php new file mode 100644 index 000000000..fe683211d --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch.php @@ -0,0 +1,83 @@ +setVertragsbestandteiltyp_kurzbz( + VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH); + } + + public function hydrateByStdClass($data, $fromdb=false) + { + parent::hydrateByStdClass($data, $fromdb); + $this->fromdb = $fromdb; + isset($data->tage) && $this->setTage($data->tage); + $this->fromdb = false; + } + + /** + * Get the value of tage + */ + public function getTage() + { + return $this->tage; + } + + /** + * Set the value of tage + */ + public function setTage($tage): self + { + $this->markDirty('tage', $this->tage, $tage); + $this->tage = $tage; + + return $this; + } + + public function toStdClass(): \stdClass + { + $tmp = array( + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'tage' => $this->getTage(), + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function __toString() + { + $txt = <<getTage()} + +EOTXT; + return parent::__toString() . $txt; + } + + public function validate() + { + if( !(filter_var($this->tage, FILTER_VALIDATE_INT, + array( + 'options' => array( + 'min_range' => 1, + 'max_range' => 50 + ) + ) + )) ) { + $this->validationerrors[] = 'Urlaubsanspruch muss eine Tagesanzahl im Bereich 1 bis 50 sein.'; + } + + return parent::validate(); + } +} diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung.php b/application/libraries/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung.php new file mode 100644 index 000000000..5bbdaa36f --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung.php @@ -0,0 +1,118 @@ +setVertragsbestandteiltyp_kurzbz( + VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG); + } + + public function hydrateByStdClass($data, $fromdb=false) + { + parent::hydrateByStdClass($data, $fromdb); + $this->fromdb = $fromdb; + isset($data->zeitaufzeichnung) && $this->setZeitaufzeichnung($data->zeitaufzeichnung); + isset($data->azgrelevant) && $this->setAzgrelevant($data->azgrelevant); + isset($data->homeoffice) && $this->setHomeoffice($data->homeoffice); + $this->fromdb = false; + } + + /** + * Get the value of zeitaufzeichnung + */ + public function getZeitaufzeichnung() + { + return $this->zeitaufzeichnung; + } + + /** + * Set the value of zeitaufzeichnung + */ + public function setZeitaufzeichnung($zeitaufzeichnung): self + { + $this->markDirty('zeitaufzeichnung', $this->zeitaufzeichnung, $zeitaufzeichnung); + $this->zeitaufzeichnung = $zeitaufzeichnung; + + return $this; + } + + /** + * Get the value of azgrelevant + */ + public function getAzgrelevant() + { + return $this->azgrelevant; + } + + /** + * Set the value of azgrelevant + */ + public function setAzgrelevant($azgrelevant): self + { + $this->markDirty('azgrelevant', $this->azgrelevant, $azgrelevant); + $this->azgrelevant = $azgrelevant; + + return $this; + } + + /** + * Get the value of homeoffice + */ + public function getHomeoffice() + { + return $this->homeoffice; + } + + /** + * Set the value of homeoffice + */ + public function setHomeoffice($homeoffice): self + { + $this->markDirty('homeoffice', $this->homeoffice, $homeoffice); + $this->homeoffice = $homeoffice; + + return $this; + } + + public function toStdClass(): \stdClass + { + $tmp = array( + 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(), + 'zeitaufzeichnung' => $this->getZeitaufzeichnung(), + 'azgrelevant' => $this->getAzgrelevant(), + 'homeoffice' => $this->getHomeoffice() + ); + + $tmp = array_filter($tmp, function($k) { + return in_array($k, $this->modifiedcolumns); + }, ARRAY_FILTER_USE_KEY); + + return (object) $tmp; + } + + public function __toString() + { + $txt = <<getZeitaufzeichnung()} + azgrelevant: {$this->getAzgrelevant()} + homeoffice: {$this->getHomeoffice()} + +EOTXT; + return parent::__toString() . $txt; + } + + public function validate() + { + return parent::validate(); + } +} diff --git a/application/models/codex/Bismeldestichtag_model.php b/application/models/codex/Bismeldestichtag_model.php new file mode 100644 index 000000000..f9b412e7a --- /dev/null +++ b/application/models/codex/Bismeldestichtag_model.php @@ -0,0 +1,133 @@ +dbTable = 'bis.tbl_bismeldestichtag'; + $this->pk = 'meldestichtag_id'; + } + + public function getLastReachedMeldestichtag($studiensemester_kurzbz = null) + { + $this->addSelect('meldestichtag_id'); + $this->addSelect('meldestichtag'); + $this->addSelect('studiensemester_kurzbz'); + $this->addSelect('insertamum'); + $this->addSelect('insertvon'); + $this->addSelect('updateamum'); + $this->addSelect('updatevon'); + + if ($studiensemester_kurzbz) { + $this->db->where('studiensemester_kurzbz', $studiensemester_kurzbz); + } + + $this->addOrder('meldestichtag', 'DESC'); + $this->addLimit(1); + + return $this->loadWhere([ + 'meldestichtag < NOW()' => null + ]); + } + + /** + * Liefert nächstliegenden Bismeldestichtag. + * @return object success or error + */ + public function getNextMeldestichtag() + { + $this->addSelect('meldestichtag'); + $this->addSelect('studiensemester_kurzbz'); + + $this->addOrder('meldestichtag', 'ASC'); + $this->addLimit(1); + + return $this->loadWhere([ + 'meldestichtag >= NOW()' => null + ]); + } + + /** + * Prüft, ob Meldestichtag für ein bestimmtes Statusdatum und Studiensemester erreicht ist. + * + * @param $status_datum + * @return boolean true wenn erreicht, oder false + */ + public function checkIfMeldestichtagErreicht($status_datum, $studiensemester_kurzbz = null) + { + $erreicht = false; + + if (isset($studiensemester_kurzbz)) + { + // Studiensemesterende holen + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $result = $this->StudiensemesterModel->loadWhere( + array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ) + ); + if(isError($result)) + { + return $result; + } + $result = current(getData($result)); + + $studiensemester_ende = new DateTime($result->ende); + } + + // letztes erreichtes Bismeldedatum holen + $result = $this->getLastReachedMeldestichtag(); + if (isError($result)) + { + return $result; + } + if (!hasData($result)) { + return success("0",'No Statusdata vorhanden'); + } + $stichtag = current(getData($result)); + $stichtag = new DateTime($stichtag->meldestichtag); + + $statusDatum = new DateTime($status_datum); + + // Prüfen, ob Studentstatusdatum oder Studiensemester vor dem Stichtagsdatum liegen + if (isset($statusDatum)) + { + if (isset($stichtag)) + $erreicht = $statusDatum < $stichtag; + } + + if (isset($studiensemester_ende)) + { + $erreicht = $erreicht || $studiensemester_ende < $stichtag; + } + + if ($erreicht) + return success("1", "Studentstatus mit Datum oder Semesterende vor erreichtem Meldestichtag können nicht hinzugefügt werden"); + + return success("0", "Meldestatus nicht erreicht"); + } + + /** + * Gets last Bismeldestichtag for a Studiensemester. + * @param $studiensemester_kurzbz + * @return object success or error + */ + public function getByStudiensemester($studiensemester_kurzbz) + { + $query = ' + SELECT + meldestichtag + FROM + bis.tbl_bismeldestichtag + JOIN public.tbl_studiensemester USING (studiensemester_kurzbz) + WHERE + studiensemester_kurzbz = ? + ORDER BY meldestichtag DESC + LIMIT 1'; + + return $this->execQuery($query, array($studiensemester_kurzbz)); + } +} diff --git a/application/models/codex/Gemeinde_model.php b/application/models/codex/Gemeinde_model.php index c782346a0..670da739d 100644 --- a/application/models/codex/Gemeinde_model.php +++ b/application/models/codex/Gemeinde_model.php @@ -19,4 +19,13 @@ class Gemeinde_model extends DB_Model return $this->loadWhere(array("plz" => $plz)); } + + public function checkLocation($plz, $gemeinde, $ort) + { + $this->db->where('ortschaftsname', $ort); + $this->db->where('name', $gemeinde); + $this->db->where('plz', $plz); + + return (boolean)$this->db->count_all_results($this->dbTable); + } } \ No newline at end of file diff --git a/application/models/crm/Konto_model.php b/application/models/crm/Konto_model.php index 4b2a259c9..d130d5db8 100644 --- a/application/models/crm/Konto_model.php +++ b/application/models/crm/Konto_model.php @@ -1,4 +1,7 @@ pk = 'buchungsnr'; } + /** + * Insert Data into DB-Table + * + * @param array $data DataArray for Insert + * @return stdClass + */ + public function insert($data, $encryptedColumns = null) + { + if (isset($data['buchungsnr_verweis']) && $data['buchungsnr_verweis']) + return parent::insert($data, $encryptedColumns); + + $this->db->trans_begin(); + + $result = parent::insert($data, $encryptedColumns); + if (isError($result)) { + $this->db->trans_rollback(); + return $result; + } + + $buchungsnr = $result->retval; + // If studiengang_kz is not present in $data it will fail above since it is a not null field + $studiengang_kz = $data['studiengang_kz']; + + + $zahlungsreferenz = false; + Events::trigger('generate_zahlungsreferenz', $buchungsnr, $data, function ($value) use ($zahlungsreferenz) { + $zahlungsreferenz = $value; + }); + + if ($zahlungsreferenz === false) { + $result = $this->execQuery('SELECT UPPER(oe_kurzbz) || ? as zahlungsreferenz + FROM public.tbl_studiengang + WHERE studiengang_kz=?', [$buchungsnr, $studiengang_kz]); + if (isError($result)) { + $this->db->trans_rollback(); + return $result; + } + $zahlungsreferenz = current(getData($result))->zahlungsreferenz; + } elseif (isError($zahlungsreferenz)) { + $this->db->trans_rollback(); + return $zahlungsreferenz; + } + + + $result = $this->update($buchungsnr, [ + 'zahlungsreferenz' => $zahlungsreferenz + ]); + + if (isError($result)) { + $this->db->trans_rollback(); + return $result; + } + + $this->db->trans_commit(); + + return success($buchungsnr); + } + + /** + * Delete data from DB-Table + * + * @param string $id Primary Key for DELETE + * + * @return stdClass + */ + public function delete($id) + { + $this->db->where('buchungsnr_verweis', $id); + if ($this->db->count_all_results($this->dbTable)) + return error('Bitte zuerst die zugeordneten Buchungen loeschen', 42); + return parent::delete($id); + } + + /** + * Adds additional fields to the Query + * + * @return Konto_model + */ + public function withAdditionalInfo() + { + $this->addSelect($this->dbTable . '.*'); + $this->addSelect('UPPER(typ::varchar(1) || kurzbz) AS kuerzel'); + $this->addSelect('person.anrede'); + $this->addSelect('person.titelpost'); + $this->addSelect('person.titelpre'); + $this->addSelect('person.vorname'); + $this->addSelect('person.vornamen'); + $this->addSelect('person.nachname'); + + $this->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); + $this->addJoin('public.tbl_person person', 'person_id', 'LEFT'); + + Events::trigger('konto_query'); + + return $this; + } + + /** + * Get all accounting entries for a person optionally filtered by Studiengang + * + * @param integer|array $person_id + * @param string (optional) $studiengang_kz + * + * @return stdClass + */ + public function getAlleBuchungen($person_id, $studiengang_kz = '') + { + $this->withAdditionalInfo(); + + $this->addOrder('buchungsdatum'); + + if (is_array($person_id)) + $this->db->where_in('person_id', $person_id); + else + $this->db->where('person_id', $person_id); + + if ($studiengang_kz) + return $this->loadWhere([ + 'studiengang_kz' => $studiengang_kz + ]); + return $this->load(); + } + + /** + * Get all open accounting entries for a person optionally filtered by Studiengang + * + * @param integer|array $person_id + * @param string (optional) $studiengang_kz + * + * @return stdClass + */ + public function getOffeneBuchungen($person_id, $studiengang_kz = '') + { + $this->addSelect('buchungsnr'); + $this->db->where('(betrag + ( + SELECT CASE WHEN sum(betrag) is null THEN 0 ELSE sum(betrag) END + FROM ' . $this->dbTable . ' + WHERE buchungsnr_verweis=konto_a.buchungsnr + )) !=', 0, false); + if (is_array($person_id)) + $this->db->where_in('person_id', $person_id); + else + $this->db->where('person_id', $person_id); + $sql = $this->db->get_compiled_select($this->dbTable . ' konto_a'); + + $this->db->group_start(); + $this->db->where_in('buchungsnr', $sql, false); + $this->db->or_where_in('buchungsnr_verweis', $sql, false); + $this->db->group_end(); + + return $this->getAlleBuchungen($person_id, $studiengang_kz); + } + + /** + * Check double Buchungen + * + * @param array $person_ids + * @param string $studiensemester_kurzbz + * @param array $buchungstyp_kurzbzs + * + * @return stdClass + */ + public function checkDoubleBuchung($person_ids, $studiensemester_kurzbz, $buchungstyp_kurzbzs) + { + $this->addSelect('vorname'); + $this->addSelect('nachname'); + + $this->addJoin('public.tbl_person', 'person_id'); + + $this->db->where_in('person_id', $person_ids); + $this->db->where_in('buchungstyp_kurzbz', $buchungstyp_kurzbzs); + + $this->addGroupBy('vorname, nachname'); + $this->addOrder('nachname'); + $this->addOrder('vorname'); + + return $this->loadWhere([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); + } + + /** + * Berechnet den offenen Betrag einer Buchung + * + * @param integer $buchungsnr + * + * @return stdClass + */ + public function getDifferenz($buchungsnr) + { + $this->addSelect('buchungsnr_verweis'); + $this->db->where('buchungsnr', $buchungsnr); + $sql = $this->db->get_compiled_select($this->dbTable); + + $this->addSelect('buchungsnr_verweis'); + $this->db->where('buchungsnr', $buchungsnr); + $this->db->or_where('buchungsnr_verweis', '(' . $sql . ')', false); + $sql = $this->db->get_compiled_select($this->dbTable); + + $this->addSelect('sum(betrag) differenz'); + $this->db->where('buchungsnr', $buchungsnr); + $this->db->or_where('buchungsnr_verweis', $buchungsnr); + $this->db->or_where('buchungsnr', '(' . $sql . ')', false); + + $result = $this->load(); + if (isError($result)) + return $result; + if (!hasData($result)) + return success(null); + return success(current(getData($result))->differenz * -1); + } + /** * Sets a Payment as paid */ @@ -100,8 +315,8 @@ class Konto_model extends DB_Model public function checkStudienbeitrag($uid, $stsem, $buchungstypen) { - $query = 'SELECT tbl_konto.buchungsnr, - tbl_konto.buchungsdatum + $query = 'SELECT tbl_konto.buchungsnr, + tbl_konto.buchungsdatum FROM public.tbl_konto, public.tbl_benutzer, public.tbl_student @@ -117,10 +332,47 @@ class Konto_model extends DB_Model FROM public.tbl_konto skonto WHERE skonto.buchungsnr = tbl_konto.buchungsnr_verweis OR skonto.buchungsnr_verweis = tbl_konto.buchungsnr_verweis - ) + ) ORDER BY buchungsnr DESC LIMIT 1 '; return $this->execQuery($query); } + + /** + * check if student has paid studienbeitrag for certain semester + * + * @param $person_id person_id + * @param $stsem stsem + * + * @return boolean + */ + public function checkStudienbeitragFromPerson($person_id, $stsem) + { + $this->addOrder('buchungsnr'); + $this->addLimit(1); + $result = $this->loadWhere([ + 'person_id'=>$person_id, + 'studiensemester_kurzbz' => $stsem, + 'buchungstyp_kurzbz' => 'Studiengebuehr' + ]); + + if (!getData($result)) + return false; + + $data = getData($result)[0]; + + $this->resetQuery(); + + $this->addSelect('sum(betrag) as differenz'); + $this->db->or_where('buchungsnr', $data->buchungsnr); + $this->db->or_where('buchungsnr_verweis', $data->buchungsnr); + + $result = $this->load(); + if (!getData($result)) + return false; + + $data = getData($result)[0]; + return $data->differenz >= 0; + } } diff --git a/application/models/crm/Prestudent_model.php b/application/models/crm/Prestudent_model.php index 7b24b8769..242c26518 100644 --- a/application/models/crm/Prestudent_model.php +++ b/application/models/crm/Prestudent_model.php @@ -14,6 +14,39 @@ class Prestudent_model extends DB_Model $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel'); } + /** + * Update Data in DB-Table + * + * @param string $id PK for DB-Table + * @param array $data DataArray for Insert + * @return array + */ + public function update($id, $data, $encryptedColumns = null) + { + if (isset($data['zgvmas_code']) + || isset($data['zgvmanation']) + || isset($data['zgv_code']) + || isset($data['zgvnation']) + ) { + /** + * Falls ZGV vorhanden, setze Ausstellungsstaat (für BIS-Meldung) + * auf Nation der höchsten angegebenen ZGV + */ + $case = '(CASE + WHEN zgvmas_code IS NOT NULL AND zgvmanation IS NOT NULL THEN zgvmanation + WHEN zgv_code IS NOT NULL AND zgvnation IS NOT NULL THEN zgvnation + ELSE NULL END)'; + + foreach (['zgvmas_code', 'zgvmanation', 'zgv_code', 'zgvnation'] as $key) + if (isset($data[$key])) + $case = str_replace($key, $this->escape($data[$key]), $case); + + $this->db->set('ausstellungsstaat', $case, false); + } + + return parent::update($id, $data, $encryptedColumns); + } + /** * getLastStatuses */ @@ -700,4 +733,33 @@ class Prestudent_model extends DB_Model return $this->execQuery($query, array($prestudent_id)); } + /** + * Gets history of all prestudents, person_id given + * @param int $person_id + * @return object + */ + public function getHistoryPrestudents($person_id) + { + + $query = " + SELECT ps.studiensemester_kurzbz, p.priorisierung, p.studiengang_kz, sg.kurzbzlang, ps.orgform_kurzbz, + ps.status_kurzbz, s.student_uid, sp.bezeichnung, ps.ausbildungssemester, + CONCAT(ps.status_kurzbz, ' (', ps.ausbildungssemester, '. Semester)') as status, p.prestudent_id + 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) + LEFT JOIN public.tbl_status_grund g USING (statusgrund_id) + JOIN public.tbl_studiengang sg USING(studiengang_kz) + LEFT JOIN lehre.tbl_studienplan sp USING (studienplan_id) + LEFT JOIN public.tbl_student s USING (prestudent_id) + ORDER BY p.priorisierung + "; + + return $this->execQuery($query, array($person_id)); + } } diff --git a/application/models/crm/Prestudentstatus_model.php b/application/models/crm/Prestudentstatus_model.php index f39a41fda..5f0b5876c 100644 --- a/application/models/crm/Prestudentstatus_model.php +++ b/application/models/crm/Prestudentstatus_model.php @@ -2,6 +2,19 @@ class Prestudentstatus_model extends DB_Model { + + const STATUS_ABBRECHER = 'Abbrecher'; + const STATUS_UNTERBRECHER = 'Unterbrecher'; + const STATUS_STUDENT = 'Student'; + const STATUS_DIPLOMAND = 'Diplomand'; + const STATUS_ABSOLVENT = 'Absolvent'; + const STATUS_BEWERBER = 'Bewerber'; + const STATUS_AUFGENOMMENER = 'Aufgenommener'; + const STATUS_WARTENDER = 'Wartender'; + const STATUS_ABGEWIESENER = 'Abgewiesener'; + const STATUS_INTERESSENT = 'Interessent'; + const STATUS_INCOMING = 'Incoming'; + /** * Constructor */ @@ -226,4 +239,353 @@ class Prestudentstatus_model extends DB_Model return $this->execQuery($query, $parametersArray); } -} + + /** + * get Email of relevant Studiengang of prestudent + */ + public function getLastStatusWithStgEmail($prestudent_id, $studiensemester_kurzbz = '', $status_kurzbz = '') + { + $this->addSelect('tbl_prestudentstatus.*, + tbl_studienplan.bezeichnung AS studienplan_bezeichnung, + tbl_orgform.orgform_kurzbz AS orgform, + tbl_studienplan.sprache, + tbl_orgform.bezeichnung_mehrsprachig AS bezeichnung_orgform, + tbl_status.bezeichnung_mehrsprachig, + tbl_status_grund.bezeichnung_mehrsprachig AS bezeichnung_statusgrund, + tbl_studiengang.bezeichnung AS stg_bezeichnung, + tbl_studiengang.email'); + $this->addJoin('lehre.tbl_studienplan', 'studienplan_id', 'LEFT'); + $this->addJoin('lehre.tbl_studienordnung', 'studienordnung_id', 'LEFT'); + $this->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT'); + $this->addJoin('public.tbl_status', 'tbl_status.status_kurzbz = tbl_prestudentstatus.status_kurzbz'); + $this->addJoin('public.tbl_status_grund', 'statusgrund_id', 'LEFT'); + $this->addJoin('bis.tbl_orgform', 'COALESCE(tbl_studienplan.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz, tbl_studiengang.orgform_kurzbz) = tbl_orgform.orgform_kurzbz', 'LEFT'); + $this->db->where('tbl_status.status_kurzbz = tbl_prestudentstatus.status_kurzbz'); + + $where = array('prestudent_id' => $prestudent_id); + if ($studiensemester_kurzbz) + $where['studiensemester_kurzbz'] = $studiensemester_kurzbz; + if ($status_kurzbz) + $where['tbl_prestudentstatus.status_kurzbz'] = $status_kurzbz; + + $this->addOrder('datum', 'DESC'); + $this->addOrder('insertamum', 'DESC'); + $this->addOrder('ext_id', 'DESC'); + $this->addLimit(1); + + return $this->loadWhere($where); + } + + public function loadLastWithStgDetails($prestudent_id, $studiensemester_kurzbz = null, $max_date = null) + { + $this->load->config('studierendenantrag'); + + $lang = getUserLanguage(); + + $this->addSelect($this->dbTable . '.prestudent_id'); + $this->addSelect($this->dbTable . '.ausbildungssemester AS semester'); + $this->addSelect($this->dbTable . '.studiensemester_kurzbz'); + $this->addSelect('s.matrikelnr'); + $this->addSelect('ss.studienjahr_kurzbz'); + $this->addSelect('pers.vorname'); + $this->addSelect('pers.nachname'); + $this->addSelect('pers.unruly'); + $this->addSelect('TRIM(CONCAT(pers.vorname, \' \', pers.nachname)) AS name'); + $this->addSelect('pers.person_id'); + $this->addSelect('g.studiengang_kz'); + $this->addSelect('g.bezeichnung'); + $this->addSelect('o.orgform_kurzbz'); + $this->addSelect( + 'o.bezeichnung_mehrsprachig[(SELECT index FROM public.tbl_sprache WHERE sprache=\'' . $lang . '\')] AS orgform_bezeichnung', + false + ); + + $this->addJoin('public.tbl_student s', 'prestudent_id'); + $this->addJoin('public.tbl_prestudent p', 'prestudent_id'); + $this->addJoin('public.tbl_studiensemester ss', 'studiensemester_kurzbz'); + $this->addJoin('public.tbl_person pers', 'person_id'); + $this->addJoin('public.tbl_studiengang g', 'p.studiengang_kz=g.studiengang_kz'); + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + $this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz'); + + $this->addOrder($this->dbTable . '.datum', 'DESC'); + $this->addOrder($this->dbTable . '.insertamum', 'DESC'); + $this->addOrder($this->dbTable . '.ext_id', 'DESC'); + + $this->addLimit(1); + + if ($max_date) + $this->db->where($this->dbTable . '.insertamum <', $max_date); + + $whereArr = [ + $this->dbTable . '.prestudent_id' => $prestudent_id, + 'g.aktiv' => true + ]; + + if ($studiensemester_kurzbz !== null) + { + $whereArr[$this->dbTable. '.studiensemester_kurzbz'] = $studiensemester_kurzbz; + } + + return $this->loadWhere($whereArr); + } + + /** + * call like this: + * $this->PrestudentstatusModel->withGrund('grund_kurzbz')->update($id, $otherData); + * or: + * $this->PrestudentstatusModel->withGrund('grund_kurzbz')->insert($otherData); + * @param string $statusgrund_kurzbz + * @return object $this + */ + public function withGrund($statusgrund_kurzbz) + { + if ($statusgrund_kurzbz) + $this->db->set( + 'statusgrund_id', + '(SELECT statusgrund_id FROM public.tbl_status_grund WHERE statusgrund_kurzbz=' . $this->db->escape($statusgrund_kurzbz) . ')', + false + ); + + return $this; + } + + /** + * Check if there is only one prestudentstatus left + * + * @param integer $prestudent_id + * @param string $studiensemester_kurzbz + * + * @return stdClass + */ + public function checkIfLastStatusEntry($prestudent_id, $studiensemester_kurzbz = null) + { + $this->addSelect('COUNT(*) AS anzahl', false); + + if ($studiensemester_kurzbz) + $this->db->where('studiensemester_kurzbz', $studiensemester_kurzbz); + + $result = $this->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + + if (isError($result)) + return $result; + + $resultObject = current($result->retval); + + $anzahl = (int)$resultObject->anzahl; + + if ($anzahl <= 1) + return success(true, $this->p->t('lehre', 'error_lastRole')); + + return success(false, $this->p->t('lehre', 'anzahl_existingRoles', ['anzahl' => $anzahl])); + } + + public function getAllPrestudentstatiWithStudiensemester($prestudent_id) + { + $qry = " + SELECT + tbl_prestudentstatus.status_kurzbz, + tbl_prestudentstatus.studiensemester_kurzbz, + tbl_prestudentstatus.ausbildungssemester, + tbl_prestudentstatus.datum, + s.start AS studiensemester_start, + pl.orgform_kurzbz AS studienplan_orgform_kurzbz, + stud.matrikelnr, + pers.vorname, + pers.nachname + FROM + public.tbl_prestudentstatus + JOIN public.tbl_studiensemester s USING (studiensemester_kurzbz) + JOIN public.tbl_prestudent USING (prestudent_id) + JOIN public.tbl_person pers USING (person_id) + LEFT JOIN public.tbl_student stud USING (prestudent_id) + LEFT JOIN lehre.tbl_studienplan pl USING (studienplan_id) + WHERE + prestudent_id = ? + ORDER BY + public.tbl_prestudentstatus.datum DESC, + public.tbl_prestudentstatus.insertamum DESC, + public.tbl_prestudentstatus.ext_id DESC + "; + + return $this->execQuery($qry, array($prestudent_id)); + } + + /** + * Gets status history of a prestudent + * This function uses the language of the logged in user to + * translate the given statusgrund + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function getHistoryPrestudent($prestudent_id) + { + $lang= getUserLanguage(); + $this->addSelect('tbl_prestudentstatus.prestudent_id'); + $this->addSelect('tbl_prestudentstatus.status_kurzbz'); + $this->addSelect('tbl_prestudentstatus.studiensemester_kurzbz'); + $this->addSelect('tbl_prestudentstatus.ausbildungssemester'); + $this->addSelect('tbl_prestudentstatus.datum'); + $this->addSelect("TO_CHAR(tbl_prestudentstatus.datum::timestamp, 'DD.MM.YYYY') AS format_datum"); + $this->addSelect('tbl_prestudentstatus.insertamum'); + $this->addSelect('tbl_prestudentstatus.insertvon'); + $this->addSelect('tbl_prestudentstatus.updateamum'); + $this->addSelect('tbl_prestudentstatus.updatevon'); + $this->addSelect('tbl_prestudentstatus.orgform_kurzbz'); + $this->addSelect('tbl_prestudentstatus.bestaetigtam'); + $this->addSelect("TO_CHAR(tbl_prestudentstatus.bestaetigtam::timestamp, 'DD.MM.YYYY') AS format_bestaetigtam"); + $this->addSelect('tbl_prestudentstatus.bestaetigtvon'); + $this->addSelect('tbl_prestudentstatus.bewerbung_abgeschicktamum'); + $this->addSelect("TO_CHAR(tbl_prestudentstatus.bewerbung_abgeschicktamum::timestamp, 'DD.MM.YYYY') AS format_bewerbung_abgeschicktamum"); + $this->addSelect('tbl_prestudentstatus.anmerkung'); + $this->addSelect('plan.studienplan_id'); + $this->addSelect('plan.bezeichnung'); + + $this->addSelect('grund.beschreibung[( + SELECT index + FROM public.tbl_sprache + WHERE sprache=' . $this->escape($lang) . ' + )] AS statusgrund_bezeichnung', false); + $this->addSelect("CASE + WHEN s.student_uid IS NOT NULL + AND tbl_prestudentstatus.status_kurzbz IN (" . implode(",", $this->escape([ + 'Student', + 'Diplomand', + 'Abbrecher', + 'Absolvent', + 'Ausserodentlicher', + 'Incoming', + 'Outgoing', + 'Unterbrecher' + ])) . ") + THEN lv.semester || lv.verband || lv.gruppe + ELSE '-' + END AS lehrverband", false); + + + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + $this->addJoin('public.tbl_status_grund grund', 'statusgrund_id', 'LEFT'); + $this->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT'); + $this->addJoin( + 'public.tbl_studentlehrverband lv', + 's.student_uid IS NOT NULL AND s.student_uid=lv.student_uid AND tbl_prestudentstatus.studiensemester_kurzbz=lv.studiensemester_kurzbz', + 'LEFT' + ); + + $this->addOrder('tbl_prestudentstatus.datum', 'DESC'); + $this->addOrder('tbl_prestudentstatus.insertamum', 'DESC'); + $this->addOrder('tbl_prestudentstatus.ext_id', 'DESC'); + + return $this->loadWhere([ + 'tbl_prestudentstatus.prestudent_id' => $prestudent_id + ]); + } + + /** + * Gets status history of a prestudent for checking purposes. + * This function adds the new state or replaces the edited. + * + * @param integer $prestudent_id + * @param string $status_kurzbz + * @param DateTime $new_date + * @param string $new_studiensemester_kurzbz + * @param integer $new_ausbildungssemester + * @param string $old_studiensemester_kurzbz + * @param integer $old_ausbildungssemester + * + * @return stdClass + */ + public function getHistoryWithNewOrEditedState( + $prestudent_id, + $status_kurzbz, + $new_date, + $new_studiensemester_kurzbz, + $new_ausbildungssemester, + $old_studiensemester_kurzbz, + $old_ausbildungssemester + ) { + $new_date = $new_date->format('Y-m-d'); + + $this->addSelect('status_kurzbz'); + $this->addSelect('studiensemester_kurzbz'); + $this->addSelect('ausbildungssemester'); + $this->addSelect('datum'); + $this->addSelect('insertamum'); + $this->addSelect('ext_id'); + + if ($old_studiensemester_kurzbz || $old_ausbildungssemester) { + $this->db->not_group_start(); + $this->db->where('status_kurzbz', $status_kurzbz); + $this->db->where('studiensemester_kurzbz', $old_studiensemester_kurzbz); + $this->db->where('ausbildungssemester', $old_ausbildungssemester); + $this->db->group_end(); + } + + $this->db->where('prestudent_id', $prestudent_id); + + $tmpTable = $this->db->get_compiled_select($this->dbTable); + + $tmpTable .= "UNION + SELECT " . + $this->escape($status_kurzbz) . " AS status_kurzbz, " . + $this->escape($new_studiensemester_kurzbz) . " AS studiensemester_kurzbz, " . + $this->escape($new_ausbildungssemester) . " AS ausbildungssemester, " . + $this->escape($new_date) . "::date AS datum," . + $this->escape(date('c')) . "::date AS insertamum," . + "NULL AS ext_id"; + + $this->addJoin('public.tbl_studiensemester sem', 'studiensemester_kurzbz'); + + $this->addOrder('s.datum', 'DESC'); + $this->addOrder('s.insertamum', 'DESC'); + $this->addOrder('s.ext_id', 'DESC'); + + $dbTable = $this->dbTable; + $this->dbTable = "(" . $tmpTable . ") s"; + + $result = $this->load(); + + $this->dbTable = $dbTable; + + return $result; + } + + /** + * For checks if Orgform of Student status and Bewerber status match. + * Returns any Bewerber status that does not match the first Student + * status' Orgform. + * + * @param integer $prestudent_id + * + * @return stdClass + */ + public function getBewerberWhereOrgformNotStudent($prestudent_id) + { + $this->addSelect('plan.orgform_kurzbz'); + + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + + $this->addOrder('tbl_prestudentstatus.datum', 'DESC'); + $this->addOrder('tbl_prestudentstatus.insertamum', 'DESC'); + $this->addOrder('tbl_prestudentstatus.ext_id', 'DESC'); + + $this->addLimit(1); + + $this->db->where('prestudent_id', $prestudent_id); + $this->db->where('status_kurzbz', self::STATUS_STUDENT); + + $sql = $this->db->get_compiled_select($this->dbTable); + + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + + $this->db->where('plan.orgform_kurzbz !=', '(' . $sql . ')', false); + return $this->loadWhere([ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => self::STATUS_BEWERBER + ]); + } +} \ No newline at end of file diff --git a/application/models/crm/Reihungstest_model.php b/application/models/crm/Reihungstest_model.php index ec1982ea6..86ebfd0af 100644 --- a/application/models/crm/Reihungstest_model.php +++ b/application/models/crm/Reihungstest_model.php @@ -322,7 +322,7 @@ class Reihungstest_model extends DB_Model JOIN lehre.tbl_studienplan ON (tbl_prestudentstatus.studienplan_id = tbl_studienplan.studienplan_id) LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code) WHERE rt_id = ? - AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\' + AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\') AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz AND bewerbung_abgeschicktamum IS NOT NULL AND bestaetigtam IS NOT NULL @@ -411,7 +411,7 @@ class Reihungstest_model extends DB_Model JOIN lehre.tbl_studienplan ON (tbl_prestudentstatus.studienplan_id = tbl_studienplan.studienplan_id) LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code) WHERE rt.studiengang_kz = ? - AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\' + AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\') AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz AND bewerbung_abgeschicktamum IS NOT NULL AND bestaetigtam IS NOT NULL @@ -462,7 +462,7 @@ class Reihungstest_model extends DB_Model LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code) LEFT JOIN PUBLIC.tbl_ort ON (tbl_rt_person.ort_kurzbz = tbl_ort.ort_kurzbz) WHERE rt_id = ? - AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\' + AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\') AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz AND bewerbung_abgeschicktamum IS NOT NULL AND bestaetigtam IS NOT NULL diff --git a/application/models/crm/Rueckstellung_model.php b/application/models/crm/Rueckstellung_model.php index d2c39ffde..c84c625eb 100644 --- a/application/models/crm/Rueckstellung_model.php +++ b/application/models/crm/Rueckstellung_model.php @@ -20,7 +20,7 @@ class Rueckstellung_model extends DB_Model $this->addLimit(1); $this->addJoin('tbl_rueckstellung_status', 'status_kurzbz'); $this->addSelect('*, - array_to_json(bezeichnung_mehrsprachig::varchar[])->>'.$language_index . 'as bezeichnung'); + array_to_json(bezeichnung_mehrsprachig::varchar[])->>'.$language_index . ' as bezeichnung'); $this->addOrder('datum_bis', 'DESC'); $where['person_id'] = $person_id; diff --git a/application/models/crm/Status_model.php b/application/models/crm/Status_model.php index 7b1b38ecb..1ee2a5199 100644 --- a/application/models/crm/Status_model.php +++ b/application/models/crm/Status_model.php @@ -11,4 +11,21 @@ class Status_model extends DB_Model $this->dbTable = 'public.tbl_status'; $this->pk = 'status_kurzbz'; } + + public function getAllStatiWithStatusgruende() + { + $lang = '[(SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()) . ' LIMIT 1)]'; + + $this->addSelect('sg.status_kurzbz'); + + $this->addSelect('statusgrund_id'); + $this->addSelect('sg.bezeichnung_mehrsprachig' . $lang . ' AS bezeichnung'); + $this->addSelect('sg.beschreibung' . $lang . ' AS beschreibung'); + + $this->addJoin('public.tbl_status_grund sg', 'ON (sg.status_kurzbz = public.tbl_status.status_kurzbz)', 'LEFT'); + + return $this->loadWhere([ + 'aktiv'=> true, + ]); + } } diff --git a/application/models/crm/Statusgrund_model.php b/application/models/crm/Statusgrund_model.php index d488e12d1..8fc2a3a62 100644 --- a/application/models/crm/Statusgrund_model.php +++ b/application/models/crm/Statusgrund_model.php @@ -27,4 +27,19 @@ class Statusgrund_model extends DB_Model return success($status->retval); } + + public function getAktiveGruende() + { + $lang = '[(SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()) . ' LIMIT 1)]'; + + $this->addSelect('tbl_status_grund.*'); + $this->addSelect('bezeichnung_mehrsprachig' . $lang . ' AS bezeichnung'); + $this->addSelect('beschreibung' . $lang . ' AS beschreibung'); + + $this->addOrder('bezeichnung_mehrsprachig' . $lang); + + return $this->loadWhere([ + 'aktiv' => true + ]); + } } diff --git a/application/models/crm/Student_model.php b/application/models/crm/Student_model.php index 4404beb54..bd7ab41b6 100644 --- a/application/models/crm/Student_model.php +++ b/application/models/crm/Student_model.php @@ -1,4 +1,8 @@ = 90010 && $studiengang_kz <= 90019) + { + $matrikelnummer = sprintf("%02d", $jahr).$art.substr($studiengang_kz, 0, 4); + } + else + { + $matrikelnummer = sprintf("%02d", $jahr).$art.sprintf("%04d", $studiengang_kz); + } + + $qry = "SELECT matrikelnr FROM public.tbl_student WHERE matrikelnr LIKE ? ORDER BY matrikelnr DESC LIMIT 1"; + $matrikelnrres = $this->execQuery($qry, array($matrikelnummer.'%')); + + $max = 0; + if ($matrikelnrres && hasData($matrikelnrres)) { + $max = mb_substr($matrikelnrres->retval[0]->matrikelnr, 7); + if (!is_numeric($max)) { + $max = (int)$max; + } + } + + $max += 1; + return success($matrikelnummer.sprintf("%03d", $max)); + } + + /** + * Generiert die UID + * FORMAT: el07b001 + * $stgkzl: el = studiengangskuerzel + * $jahr: 07 = Jahr + * $stgtyp: b/m/d/x = Bachelor/Master/Diplom/Incoming + * $matrikelnummer + * 001 = Laufende Nummer Wenn StSem==SS dann wird zur Nummer 500 dazugezaehlt + * Bei Incoming im Masterstudiengang wird auch 500 dazugezaehlt + * + * @param string $stgkzl + * @param string $jahr + * @param string $stgtyp + * @param string $matrikelnummer + * @param string $vorname + * @param string $nachname + * + * @return stdClass + */ + public function generateUID($stgkzl, $jahr, $stgtyp, $matrikelnummer, $vorname, $nachname) + { + $uid = false; + + Events::trigger( + 'generate_student_uid', + function ($value) use ($uid) { + $uid = $value; + }, + $stgkzl, + $jahr, + $stgtyp, + $matrikelnummer, + $vorname, + $nachname + ); + + if ($uid !== false) + return success($uid); + + $art = mb_substr($matrikelnummer, 2, 1); + $nr = mb_substr($matrikelnummer, mb_strlen(trim($matrikelnummer))-3); + if($art=='2') //Sommersemester + $nr = $nr+500; + elseif($art=='0' && $stgtyp=='m') //Incoming im Masterstudiengang + $nr = $nr+500; + elseif($art=='4' && $stgtyp=='l') // Lehrgangsteilnehmer im Sommersemester + $nr = $nr+500; + + + return success(mb_strtolower($stgkzl.$jahr.($art!='0'?$stgtyp:'x').$nr)); + } + + /** * Get students UID by PrestudentID. * @param $prestudent_id @@ -78,8 +242,19 @@ class Student_model extends DB_Model OR lower(person.nachname) like ".$this->db->escape('%'.$filter.'%')." OR lower(person.vorname) like ".$this->db->escape('%'.$filter.'%')." OR lower(person.nachname || ' ' || person.vorname) like ".$this->db->escape('%'.$filter.'%')." - OR lower(person.vorname || ' ' || person.nachname) like ".$this->db->escape('%'.$filter.'%')); + OR lower(person.vorname || ' ' || person.nachname) like ".$this->db->escape('%'.$filter.'%') + ); return $result; } + + /** + * Get the FH-Email for a student (not the private kontakt email) + * @param $student_uid + * @return string + */ + public function getEmailFH($student_uid) + { + return $student_uid . '@' . DOMAIN; + } } diff --git a/application/models/education/Gsstudientyp_model.php b/application/models/education/Gsstudientyp_model.php new file mode 100644 index 000000000..ca9106d99 --- /dev/null +++ b/application/models/education/Gsstudientyp_model.php @@ -0,0 +1,14 @@ +dbTable = 'bis.tbl_gsstudientyp'; + $this->pk = 'gsstudientyp_kurzbz'; + } +} \ No newline at end of file diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 1f1b90131..de8ebc5c9 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -15,6 +15,297 @@ class Lehrveranstaltung_model extends DB_Model $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); } + /** + * Get Lehrveranstaltungen by eventQuery string. Use with autocomplete event queries. + * @param $eventQuery String + * @param string $studiensemester_kurzbz Filter by Studiensemester + * @param array $oes Filter by Organisationseinheiten + * @return array + */ + public function getAutocompleteSuggestions($eventQuery, $studiensemester_kurzbz = null, $oes = null) + { + $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes); + $params = []; + + /* filter by input string */ + if (is_string($eventQuery)) { + $subQry.= ' AND lv.bezeichnung ILIKE ?'; + $params[] = '%' . $eventQuery . '%'; + } + + $qry = 'SELECT DISTINCT ON (lehrveranstaltung_id) * FROM ('. $subQry. ') AS tmp'; + + return $this->execQuery($qry, $params); + } + + /** + * Get Lehrveranstaltungen with its Stg, OE and OE-type. + * Filter by Studiensemester and Organisationseinheiten if necessary. + * @param $eventQuery String + * @param string $studiensemester_kurzbz Filter by Studiensemester + * @param array $oes Filter by Organisationseinheiten + * @param array $lv_ids Filter by Lehrveranstaltung-Ids + * @return array + */ + public function getLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lv_ids = null) + { + $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes); + $qry = 'SELECT * FROM ('. $subQry. ') AS tmp'; + + if (isset($lv_ids) && is_array($lv_ids)) + { + /* filter by lv_ids */ + $implodedLvIds = "'". implode("', '", $lv_ids). "'"; + $qry.= ' WHERE lehrveranstaltung_id IN ('. $implodedLvIds. ')'; + } + + $qry.= ' ORDER BY stg_typ_kurzbz, orgform_kurzbz DESC'; + + return $this->execQuery($qry); + } + + /** + * Get basic query to retrieve Lehrveranstaltungen according to the Orgforms and Ausbildungssemesters actual Studienplan. + * + * @return string + */ + private function _getQryLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lehrtyp_kurzbz = 'lv') + { + $qry = ' + SELECT + lv.oe_kurzbz AS lv_oe_kurzbz, + CASE + WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung) + WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung) + ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung) + END AS lv_oe_bezeichnung, + stplsem.studiensemester_kurzbz, + studienordnung_id, + sto.studiengang_kz, + stpl.studienplan_id, + stplsem.semester, + stpl.orgform_kurzbz, + upper(stg.typ || stg.kurzbz) AS stg_typ_kurzbz, + stg.bezeichnung AS stg_bezeichnung, + stgtyp.bezeichnung AS stg_typ_bezeichnung, + lv.lehrveranstaltung_id, + lv.semester, + lv.bezeichnung AS lv_bezeichnung, + ( + -- comma seperated string of all lehreinheitgruppen + SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung + FROM( + -- distinct bezeichnung, as may come multiple times from different lehreinheiten + SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM + ( + -- distinct lehreinheitgruppe, as may come multiple times from different lehrform + SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz, + -- get Spezialgruppe or Lehrverbandgruppe + COALESCE( + legr.gruppe_kurzbz, + CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe ) + ) as bezeichnung + FROM lehre.tbl_lehreinheitgruppe legr + JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id) + JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz + WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id + AND le.studiensemester_kurzbz = stplsem.studiensemester_kurzbz + ) AS lehreinheitgruppen + GROUP BY studiengang_kz, bezeichnung + ORDER BY studiengang_kz DESC + ) AS uniqueLehreinheitgruppen_bezeichnung + ) AS lehreinheitgruppen_bezeichnung + FROM + lehre.tbl_studienplan stpl + JOIN lehre.tbl_studienordnung sto USING (studienordnung_id) + JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id) + JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester) + JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz) + JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz + JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ + /* filter by lehrtyp_kurzbz, default is lvs only */ + WHERE + lehrtyp_kurzbz = '. $this->db->escape($lehrtyp_kurzbz); + + if (isset($studiensemester_kurzbz) && is_string($studiensemester_kurzbz)) + { + /* filter by studiensemester */ + $qry.= ' AND stplsem.studiensemester_kurzbz = '. $this->db->escape($studiensemester_kurzbz); + + } + + if (isset($oes) && is_array($oes)) + { + /* filter by organisationseinheit */ + $implodedOes = "'". implode("', '", $oes). "'"; + $qry.= ' AND lv.oe_kurzbz IN ('. $implodedOes. ')'; + } + + return $qry; + } + + /** + * Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes, that are assigned to + * a template. This data structure can be used for nested tabulator data tree. + * + * @param null|string $studiensemester_kurzbz + * @param null|array $oes + * @return array|stdClass|null + */ + public function getTemplateLvTree($studiensemester_kurzbz = null, $oes = null){ + $params = []; + $qry = ' + WITH + -- All Lvs that are assigned to a template in given Studiensemester for given Oes + -- joining via actual Studienplan + standardisierteLvs AS ( + SELECT + lv.*, + stpl.studienplan_id::text as studienplan_id, + stpl.bezeichnung AS studienplan_bezeichnung, + stplsem.studiensemester_kurzbz + FROM + lehre.tbl_studienplan stpl + JOIN lehre.tbl_studienordnung sto USING (studienordnung_id) + JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id) + JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester) + JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz) + JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz + JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ + WHERE + -- filter type lv + lehrtyp_kurzbz = \'lv\' + -- filter lvs assigned to template (= standardisierte lv) + AND lehrveranstaltung_template_id IS NOT NULL'; + + if (is_string($studiensemester_kurzbz)) + { + /* filter by studiensemester */ + $params[]= $studiensemester_kurzbz; + $qry.= ' AND stplsem.studiensemester_kurzbz = ? '; + + } + + if (is_array($oes)) + { + /* filter by organisationseinheit */ + $params[]= $oes; + $qry.= ' AND lv.oe_kurzbz IN ? '; + } + $qry.= ' + ), + -- All templates + templateLvs AS ( + SELECT + lv.*, + NULL AS studienplan_id, + ( + SELECT string_agg(stpl_bezeichnung, \', \') + FROM + ( + SELECT stlv.studienplan_bezeichnung AS stpl_bezeichnung + FROM standardisierteLvs stlv + WHERE stlv.lehrveranstaltung_template_id = lv.lehrveranstaltung_id + ) AS studienplaene + ) AS studienplan_bezeichnung, + NULL AS studiensemester_kurzbz + FROM + lehre.tbl_lehrveranstaltung lv + WHERE + -- filter type template + lehrtyp_kurzbz = \'tpl\' + -- filter semester that were retrieved by standardisierte lvs semester for selected studiensemester + AND EXISTS ( + SELECT 1 + FROM standardisierteLvs std + WHERE std.lehrveranstaltung_template_id = lv.lehrveranstaltung_id + )'; + + if (is_array($oes)) + { + /* filter by organisationseinheit */ + $params[]= $oes; + $qry.= ' AND lv.oe_kurzbz IN ? '; + } + $qry.= ' + ) + '; + + $qry.= ' + SELECT + lv.lehrveranstaltung_id, + lv.kurzbz, + lv.lehrtyp_kurzbz, + lv.bezeichnung AS lv_bezeichnung, + lv.bezeichnung_english, + lv.studiengang_kz, + lv.semester, + lv.oe_kurzbz, + lv.ects, + lv.lehrform_kurzbz, + lv.orgform_kurzbz, + lv.sprache, + lv.aktiv, + lv.lehrveranstaltung_template_id, + lv.studienplan_id, + lv.studienplan_bezeichnung, + lv.studiensemester_kurzbz, + upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz", + stg.bezeichnung AS "stg_bezeichnung", + stgtyp.bezeichnung AS "stg_typ_bezeichnung", + CASE + WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung) + WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung) + ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung) + END AS "lv_oe_bezeichnung", + ( + -- comma seperated string of all lehreinheitgruppen + SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung + FROM( + -- distinct bezeichnung, as may come multiple times from different lehreinheiten + SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM + ( + -- distinct lehreinheitgruppe, as may come multiple times from different lehrform + SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz, + -- get Spezialgruppe or Lehrverbandgruppe + COALESCE( + legr.gruppe_kurzbz, + CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe ) + ) as bezeichnung + FROM lehre.tbl_lehreinheitgruppe legr + JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id) + JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz + WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id + AND le.studiensemester_kurzbz = lv.studiensemester_kurzbz + ) AS lehreinheitgruppen + GROUP BY studiengang_kz, bezeichnung + ORDER BY studiengang_kz DESC + ) AS uniqueLehreinheitgruppen_bezeichnung + ) AS lehreinheitgruppen_bezeichnung + FROM ( + SELECT + * + FROM + standardisierteLvs + UNION + SELECT + * + FROM templateLvs + ) AS lv + JOIN public.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz + JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ + JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = lv.oe_kurzbz + ORDER BY + oe.bezeichnung, lv.semester, lv.bezeichnung + '; + + return $this->execQuery($qry, $params); + } + /** * Gets unique Groupstrings for Lehrveranstaltungen, e.g. WS2018_BIF_1_PRJM_VZ_LV12345 * @param string $studiensemester_kurzbz @@ -493,4 +784,11 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($qry, array($student_uid)); } + + public function getStg($lehrveranstaltung_id) + { + $this->addSelect('stg.*'); + $this->addJoin('public.tbl_studiengang stg', 'studiengang_kz'); + return $this->load($lehrveranstaltung_id); + } } diff --git a/application/models/education/Lvgesamtnote_model.php b/application/models/education/Lvgesamtnote_model.php index f0c1883de..975833287 100644 --- a/application/models/education/Lvgesamtnote_model.php +++ b/application/models/education/Lvgesamtnote_model.php @@ -10,5 +10,6 @@ class Lvgesamtnote_model extends DB_Model parent::__construct(); $this->dbTable = 'campus.tbl_lvgesamtnote'; $this->pk = array('student_uid', 'studiensemester_kurzbz', 'lehrveranstaltung_id'); + $this->hasSequence = false; } } diff --git a/application/models/education/Paabgabe_model.php b/application/models/education/Paabgabe_model.php index b876030a6..5fb58cc81 100644 --- a/application/models/education/Paabgabe_model.php +++ b/application/models/education/Paabgabe_model.php @@ -25,7 +25,7 @@ class Paabgabe_model extends DB_Model WHERE projektarbeit_id = ? AND paabgabetyp_kurzbz = 'end' AND paabg.abgabedatum IS NOT NULL - ORDER BY paabg.abgabedatum, paabg.datum DESC + ORDER BY paabg.abgabedatum DESC, paabg.datum DESC LIMIT 1"; return $this->execQuery($qry, array($projektarbeit_id)); diff --git a/application/models/education/Pruefung_model.php b/application/models/education/Pruefung_model.php index e3776c4ad..409c0b733 100644 --- a/application/models/education/Pruefung_model.php +++ b/application/models/education/Pruefung_model.php @@ -29,11 +29,252 @@ class Pruefung_model extends DB_Model JOIN lehre.tbl_pruefung prfg USING (student_uid) JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id) JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) - JOIN public.tbl_studiengang stg ON prst.studiengang_kz = stg.studiengang_kz + JOIN public.tbl_studiengang stg ON prst.studiengang_kz = stg.studiengang_kz WHERE pers.person_id = ? AND le.studiensemester_kurzbz = ? ORDER BY prfg.datum, pruefung_id'; return $this->execQuery($qry, array($person_id, $studiensemester_kurzbz)); } + + + /** + * NOTE(chris): not used + * @return string + */ + protected function loadWhereThreeExamsFailed() + { + $this->load->config('studierendenantrag'); + + $this->dbTable = 'lehre.tbl_pruefung p'; + + $sprache_index = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1"; + + $this->addSelect('max(p.datum) as datum'); + $this->addSelect('pers.vorname'); + $this->addSelect('pers.nachname'); + $this->addSelect('pers.person_id'); + $this->addSelect('s.matrikelnr'); + $this->addSelect('g.bezeichnung'); + $this->addSelect('g.studiengang_kz'); + $this->addSelect('o.bezeichnung_mehrsprachig[(' . $sprache_index . ')] AS orgform', false); + $this->addSelect('ps.prestudent_id'); + $this->addSelect('lv.bezeichnung as lvbezeichnung'); + $this->addSelect('le.studiensemester_kurzbz'); + $this->addSelect('a.typ'); + $this->addSelect('campus.get_status_studierendenantrag(a.studierendenantrag_id) status'); + $this->addSelect('count(1) as count'); + + $this->addGroupBy([ + 'pers.vorname', + 'pers.nachname', + 'pers.person_id', + 's.matrikelnr', + 'g.bezeichnung', + 'g.studiengang_kz', + 'o.bezeichnung_mehrsprachig', + 'ps.prestudent_id', + 'lv.bezeichnung', + 'le.studiensemester_kurzbz', + 'a.typ', + 'a.studierendenantrag_id' + ]); + $this->addJoin('lehre.tbl_note n', 'note'); + $this->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->addJoin('public.tbl_student s', 'student_uid'); + $this->addJoin('public.tbl_prestudent ps', 'prestudent_id'); + $this->addJoin('public.tbl_person pers', 'person_id'); + $this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); + $this->addJoin('public.tbl_studiengang g', 'ps.studiengang_kz=g.studiengang_kz'); + $this->addJoin( + 'public.tbl_prestudentstatus pss', + 'pss.prestudent_id=ps.prestudent_id + AND pss.studiensemester_kurzbz=le.studiensemester_kurzbz + AND pss.status_kurzbz=get_rolle_prestudent(ps.prestudent_id, le.studiensemester_kurzbz)', + 'LEFT' + ); + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + $this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, pss.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz'); + $this->db->join('campus.tbl_studierendenantrag a', 'ps.prestudent_id=a.prestudent_id and a.typ = ?', 'LEFT', false); + + $this->db->where("n.positiv", false); + /* $this->db->where_in("p.pruefungstyp_kurzbz1", ['kommPruef','zusKommPruef']);*/ + $this->db->where_in("get_rolle_prestudent(ps.prestudent_id, null)", $this->config->item('antrag_prestudentstatus_whitelist')); + + $this->db->where("g.aktiv", true); + + $this->db->where('lv.studiengang_kz not in( + SELECT ps.studiengang_kz + FROM + public.tbl_prestudent ps1 + JOIN public.tbl_prestudentstatus pss USING (prestudent_id) + WHERE pss.statusgrund_id in ? + AND ps.prestudent_id = ps1.prestudent_id)', null, false); + + // NOTE(chris): is Wiederholer without set statusgrund (legacy?) + $this->db->where( + '(SELECT COUNT(*) + FROM (SELECT DISTINCT studiensemester_kurzbz + FROM tbl_prestudentstatus _s + WHERE ausbildungssemester=get_absem_prestudent(ps.prestudent_id, le.studiensemester_kurzbz) + AND prestudent_id=ps.prestudent_id) a) = 1', + null, + false + ); + + return $this->db->get_compiled_select($this->dbTable); + } + + /** + * @return stdClass + */ + public function loadWhereCommitteeExamsFailed() + { + $this->load->config('studierendenantrag'); + + $this->dbTable = 'lehre.tbl_pruefung p'; + + $this->addSelect('p.datum'); + + $this->addJoin('lehre.tbl_note n', 'note'); + + $this->db->where("n.positiv", false); + $note_blacklist = $this->config->item('note_blacklist_wiederholung'); + if ($note_blacklist) + $this->db->where_not_in("n.note", $note_blacklist); + $this->db->where_in("p.pruefungstyp_kurzbz", ['kommPruef','zusKommPruef']); + + $this->addOrder('p.datum', 'DESC'); + + return $this->load(); + } + + + /** + * @return void + */ + protected function withDetailsForStudierendenAntrag() + { + $this->load->config('studierendenantrag'); + + $sprache_index = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1"; + + $this->addSelect('pers.vorname'); + $this->addSelect('pers.nachname'); + $this->addSelect('pers.person_id'); + $this->addSelect('s.matrikelnr'); + $this->addSelect('g.bezeichnung'); + $this->addSelect('g.studiengang_kz'); + $this->addSelect('o.bezeichnung_mehrsprachig[(' . $sprache_index . ')] AS orgform', false); + $this->addSelect('ps.prestudent_id'); + $this->addSelect('lv.bezeichnung as lvbezeichnung'); + $this->addSelect('le.studiensemester_kurzbz'); + $this->addSelect('a.studierendenantrag_id'); + $this->addSelect('a.typ'); + $this->addSelect('campus.get_status_studierendenantrag(a.studierendenantrag_id) status'); + $this->addSelect('pss.ausbildungssemester'); + + $this->addJoin('(SELECT MAX(datum) AS datum, lehreinheit_id AS le_id, student_uid AS stud_uid FROM lehre.tbl_pruefung p WHERE pruefungstyp_kurzbz IN (\'kommPruef\', \'zusKommPruef\') GROUP BY lehreinheit_id, student_uid) lpd', + 'p.datum = lpd.datum AND p.lehreinheit_id = lpd.le_id AND p.student_uid = lpd.stud_uid'); + $this->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->addJoin('public.tbl_student s', 'student_uid'); + $this->addJoin('public.tbl_prestudent ps', 'prestudent_id'); + $this->addJoin('public.tbl_person pers', 'person_id'); + $this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); + $this->addJoin('public.tbl_studiengang g', 'ps.studiengang_kz=g.studiengang_kz'); + $this->addJoin( + 'public.tbl_prestudentstatus pss', + 'pss.prestudent_id=ps.prestudent_id + AND pss.studiensemester_kurzbz=le.studiensemester_kurzbz + AND pss.status_kurzbz=get_rolle_prestudent(ps.prestudent_id, le.studiensemester_kurzbz)', + 'LEFT' + ); + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + $this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, pss.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz'); + $this->addJoin( + 'campus.tbl_studierendenantrag a', + 'ps.prestudent_id=a.prestudent_id and a.typ=' . $this->escape(Studierendenantrag_model::TYP_WIEDERHOLUNG), + 'LEFT' + ); + + $this->db->where("g.aktiv", true); + + $statusgruende = $this->config->item('status_gruende_wiederholer'); + if (is_array($statusgruende) && !isEmptyArray($statusgruende)) { + foreach ($statusgruende as $k => $v) { + $statusgruende[$k] = $this->db->escape($v); + } + $this->db->where('lv.studiengang_kz NOT IN( + SELECT ps1.studiengang_kz + FROM + public.tbl_prestudent ps1 + JOIN public.tbl_prestudentstatus pss USING (prestudent_id) + WHERE pss.statusgrund_id in (' . implode(',', $statusgruende) . ') + AND ps.prestudent_id = ps1.prestudent_id)', null, false); + } + } + + /** + * @param integer $prestudent_id student_uid + * + * @return stdClass + */ + public function loadWhereCommitteeExamFailedForPrestudent($prestudent_id, $max_date = null, $studiensemester_kurzbz = null) + { + $this->withDetailsForStudierendenAntrag(); + + $this->db->where('ps.prestudent_id', $prestudent_id); + + if ($max_date !== null) { + $this->db->where('p.datum <=', $max_date); + } + if ($studiensemester_kurzbz !== null) { + $this->db->where('le.studiensemester_kurzbz', $studiensemester_kurzbz); + } + + return $this->loadWhereCommitteeExamsFailed(); + } + + /** + * @param string $status + * @param \DateTime $maxDate + * @param \DateTime $minDate + * + * @return stdClass + */ + public function getAllPrestudentsWhereCommitteeExamFailed($status, $maxDate, $minDate) + { + $this->withDetailsForStudierendenAntrag(); + + if ($maxDate) + $this->db->where("p.datum <= ", $maxDate->format('Y-m-d')); + if ($minDate) + $this->db->where("p.datum > ", $minDate->format('Y-m-d')); + + $this->db->where("b.aktiv", true); + + $this->db->where_in("get_rolle_prestudent(ps.prestudent_id, null)", $this->config->item('antrag_prestudentstatus_whitelist')); + + if (is_array($status)) { + if (in_array(null, $status)) { + $status = array_filter($status); + if (count($status)) { + $this->db->group_start(); + $this->db->where_in('campus.get_status_studierendenantrag(a.studierendenantrag_id)', $status); + $this->db->or_where('campus.get_status_studierendenantrag(a.studierendenantrag_id)', null); + $this->db->group_end(); + } else { + $this->db->where('campus.get_status_studierendenantrag(a.studierendenantrag_id)', null); + } + } else { + $this->db->where_in('campus.get_status_studierendenantrag(a.studierendenantrag_id)', $status); + } + } else { + $this->db->where('campus.get_status_studierendenantrag(a.studierendenantrag_id)', $status); + } + + return $this->loadWhereCommitteeExamsFailed(); + } } diff --git a/application/models/education/Studentlehrverband_model.php b/application/models/education/Studentlehrverband_model.php index 765429396..2ef14e58e 100644 --- a/application/models/education/Studentlehrverband_model.php +++ b/application/models/education/Studentlehrverband_model.php @@ -11,5 +11,7 @@ class Studentlehrverband_model extends DB_Model $this->dbTable = 'public.tbl_studentlehrverband'; $this->pk = array('studiensemester_kurzbz', 'student_uid'); $this->hasSequence = false; + + $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel'); } } diff --git a/application/models/education/Studierendenantrag_model.php b/application/models/education/Studierendenantrag_model.php new file mode 100644 index 000000000..677d01f04 --- /dev/null +++ b/application/models/education/Studierendenantrag_model.php @@ -0,0 +1,493 @@ +dbTable = 'campus.tbl_studierendenantrag'; + $this->pk = 'studierendenantrag_id'; + + $this->load->config('studierendenantrag'); + + $this->load->model('education/Studierendenantragstatus_model', 'StudierendenantragstatusModel'); + } + + public function loadCreatedForStudiengaenge($studiengaenge, $typ) + { + return $this->loadForStudiengaenge($studiengaenge, $typ, $this->StudierendenantragstatusModel::STATUS_CREATED); + } + + public function loadForStudiengaenge($studiengaenge, $typ = null, $status = null, $sql = null) + { + if ($sql == null) + $sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1"; + + $this->addSelect('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung AS bezeichnung'); + $this->addSelect('bezeichnung_mehrsprachig[(' . $sql . ')] AS orgform', false); + $this->addSelect('s.studierendenantrag_id'); + $this->addSelect('matrikelnr'); + $this->addSelect('studienjahr_kurzbz'); + $this->addSelect('vorname'); + $this->addSelect('nachname'); + $this->addSelect('unruly'); + $this->addSelect('p.prestudent_id'); + $this->addSelect('p.studiengang_kz'); + $this->addSelect('semester'); + $this->addSelect($this->dbTable . '.grund'); + $this->addSelect($this->dbTable . '.datum'); + $this->addSelect('datum_wiedereinstieg'); + $this->addSelect($this->dbTable . '.typ'); + $this->addSelect('st.studierendenantrag_statustyp_kurzbz as status'); + $this->addSelect('s.insertvon as status_insertvon'); + $this->addSelect('s.insertamum as status_insertamum'); + $this->addSelect('dms_id'); + $this->addSelect('st.bezeichnung[(' . $sql . ')] as statustyp'); + + $this->addJoin('public.tbl_prestudent p', 'prestudent_id'); + $this->addJoin('public.tbl_student', 'prestudent_id'); + $this->addJoin('public.tbl_person', 'person_id'); + $this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz'); + $this->addJoin('public.tbl_studiensemester ss', 'studiensemester_kurzbz'); + $this->addJoin( + 'public.tbl_prestudentstatus ps', + 'ps.prestudent_id=p.prestudent_id + AND ps.studiensemester_kurzbz=ss.studiensemester_kurzbz + AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, ss.studiensemester_kurzbz)', + 'LEFT' + ); + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + $this->addJoin('bis.tbl_orgform of', 'of.orgform_kurzbz=COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, stg.orgform_kurzbz)'); + $this->addJoin( + 'campus.tbl_studierendenantrag_status as s', + 'campus.get_status_id_studierendenantrag('. $this->dbTable .'.studierendenantrag_id) = studierendenantrag_status_id' + ); + $this->addJoin('campus.tbl_studierendenantrag_statustyp as st', 'studierendenantrag_statustyp_kurzbz'); + + $this->db->where_in('p.studiengang_kz', $studiengaenge); + + $where = []; + if ($status !== null) + $where['st.studierendenantrag_statustyp_kurzbz'] = $status; + if ($typ !== null) + $where[$this->dbTable . '.typ'] = $typ; + + return $this->loadWhere($where); + } + + public function loadActiveForStudiengaenge($studiengaenge) + { + // NOTE(chris): get language before changing things in the global + // db object because getUserLanguage() might use it and it should + // not have been tampered with + $sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1"; + + $this->db->group_start(); + $this->db->where_not_in('s.studierendenantrag_statustyp_kurzbz', [ + Studierendenantragstatus_model::STATUS_CANCELLED, + Studierendenantragstatus_model::STATUS_APPROVED, + Studierendenantragstatus_model::STATUS_REJECTED, + Studierendenantragstatus_model::STATUS_OBJECTION_DENIED, + Studierendenantragstatus_model::STATUS_DEREGISTERED, + Studierendenantragstatus_model::STATUS_PAUSE, + Studierendenantragstatus_model::STATUS_REMINDERSENT + ]); + $this->db->or_group_start(); + $this->db->where('s.studierendenantrag_statustyp_kurzbz', Studierendenantragstatus_model::STATUS_APPROVED); + $this->db->where('tbl_studierendenantrag.typ', Studierendenantrag_model::TYP_ABMELDUNG_STGL); + $this->db->group_end(); + $this->db->group_end(); + + return $this->loadForStudiengaenge($studiengaenge, null, null, $sql); + } + + public function loadStgsWithAntraege($studiengaenge) + { + $this->addDistinct(); + $this->addSelect('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung AS bezeichnung'); + $this->addSelect('p.studiengang_kz'); + + $this->addJoin('public.tbl_prestudent p', 'prestudent_id'); + $this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz'); + + $this->addOrder('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung'); + + $this->db->where_in('p.studiengang_kz', $studiengaenge); + + return $this->load(); + } + + public function isInStudiengang($studierendenantrag_id, $studiengaenge) + { + $this->addJoin('public.tbl_prestudent', 'prestudent_id'); + + $this->db->where_in('studiengang_kz', $studiengaenge); + + return $this->load($studierendenantrag_id); + } + + public function loadIdAndStatusWhere($where) + { + $this->addSelect('studierendenantrag_id'); + $this->addSelect('campus.get_status_studierendenantrag(studierendenantrag_id) status'); + return $this->loadWhere($where); + } + + public function loadWithStatusWhere($where, $types = null) + { + $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()); + + $this->addSelect('*'); + $this->addSelect($this->dbTable . '.grund AS grund'); + $this->addSelect('s.studierendenantrag_statustyp_kurzbz status'); + $this->addSelect('s.insertvon status_insertvon'); + $this->addSelect('t.bezeichnung[(' . $lang . ')] statustyp'); + $this->addSelect('p.unruly AS unruly'); + $this->addSelect($this->dbTable . '.insertamum AS insertamum'); + + $this->addJoin( + 'campus.tbl_studierendenantrag_status s', + 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id' + ); + $this->addJoin( + 'campus.tbl_studierendenantrag_statustyp t', + 's.studierendenantrag_statustyp_kurzbz=t.studierendenantrag_statustyp_kurzbz' + ); + $this->addJoin( + 'public.tbl_student st', + 'st.prestudent_id=tbl_studierendenantrag.prestudent_id' + ); + $this->addJoin( + 'public.tbl_benutzer b', + 'st.student_uid=b.uid' + ); + $this->addJoin( + 'public.tbl_person p', + 'b.person_id=p.person_id' + ); + + if ($types && is_array($types)) { + $this->db->where_in('typ', $types); + } + + $this->addOrder('datum', 'DESC'); + + return $this->loadWhere($where); + } + + /** + * Get the studiengang and ausbildungssemester the student was in + * for the studiensemester the antrag was committed for + * + * @param integer $antrag_id + * + * @return stdClass + */ + public function getStgAndSem($antrag_id) + { + $this->addSelect('p.studiengang_kz'); + $this->addSelect('stg.bezeichnung'); + $this->addSelect('s.ausbildungssemester'); + $this->addSelect('plan.sprache'); + $this->addSelect('COALESCE(plan.orgform_kurzbz, s.orgform_kurzbz, stg.orgform_kurzbz) AS orgform_kurzbz'); + + $this->addJoin( + 'public.tbl_prestudentstatus s', + $this->dbTable . '.prestudent_id=s.prestudent_id + AND ' . + $this->dbTable . '.studiensemester_kurzbz=s.studiensemester_kurzbz + AND ' . + $this->dbTable . '.insertamum > s.insertamum' + ); + $this->addJoin('public.tbl_prestudent p', $this->dbTable . '.prestudent_id=p.prestudent_id'); + $this->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + + $this->addOrder('s.datum', 'DESC'); + $this->addOrder('s.insertamum', 'DESC'); + $this->addOrder('s.ext_id', 'DESC'); + + $this->addLimit(1); + + return $this->loadWhere([ + $this->pk => $antrag_id + ]); + } + + /** + * Get the studiengang the student is in + * + * @param integer $antrag_id + * + * @return stdClass + */ + public function getStg($antrag_id) + { + $this->addSelect('p.studiengang_kz'); + $this->addJoin('public.tbl_prestudent p', 'prestudent_id'); + + $this->addLimit(1); + + return $this->load( + $antrag_id + ); + } + + public function getStgEmail($antrag_id) + { + $this->addJoin('public.tbl_prestudent p', 'prestudent_id'); + $this->addJoin('public.tbl_studiengang sg', 'studiengang_kz'); + $this->addSelect('sg.email'); + + return $this->load($antrag_id); + } + + public function loadForPerson($person_id) + { + $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()); + $this->addSelect('stg.bezeichnung'); + $this->addSelect('bezeichnung_mehrsprachig[(' . $lang . ')] as orgform'); + $this->addSelect('p.studiengang_kz'); + $this->addSelect('st.studierendenantrag_statustyp_kurzbz as status'); + $this->addSelect('st.bezeichnung[(' . $lang . ')] as status_bezeichnung'); + $this->addSelect('p.prestudent_id'); + $this->addSelect($this->dbTable . '.studierendenantrag_id'); + $this->addSelect($this->dbTable . '.studiensemester_kurzbz'); + $this->addSelect($this->dbTable . '.datum'); + $this->addSelect($this->dbTable . '.typ'); + $this->addSelect($this->dbTable . '.insertamum'); + $this->addSelect($this->dbTable . '.insertvon'); + $this->addSelect($this->dbTable . '.datum_wiedereinstieg'); + $this->addSelect($this->dbTable . '.grund'); + $this->addSelect($this->dbTable . '.dms_id'); + $this->addSelect('s.insertvon AS status_insertvon'); + $this->addSelect( + "(SELECT count(1) FROM campus.tbl_studierendenantrag_status WHERE studierendenantrag_id = " . + $this->dbTable . + ".studierendenantrag_id AND studierendenantrag_statustyp_kurzbz = 'Genehmigt') AS isapproved", + false + ); + + $this->addJoin('public.tbl_prestudent p', 'prestudent_id', 'RIGHT'); + $this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz'); + $this->addJoin( + 'public.tbl_prestudentstatus ps', + 'ps.prestudent_id=p.prestudent_id AND ps.studiensemester_kurzbz=' . + $this->dbTable . + '.studiensemester_kurzbz AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, ' . + $this->dbTable . + '.studiensemester_kurzbz)', + 'LEFT' + ); + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT'); + $this->addJoin('bis.tbl_orgform of', 'of.orgform_kurzbz=COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, stg.orgform_kurzbz)'); + $this->addJoin( + 'campus.tbl_studierendenantrag_status s', + 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id', + 'LEFT' + ); + $this->addJoin( + 'campus.tbl_studierendenantrag_statustyp st', + 's.studierendenantrag_statustyp_kurzbz=st.studierendenantrag_statustyp_kurzbz', + 'LEFT' + ); + + $this->db->where("( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus + WHERE prestudent_id=p.prestudent_id + AND status_kurzbz='Student' + LIMIT 1 + ) IS NOT NULL", null, false); + + + return $this->loadWhere([ + 'p.person_id' => $person_id + ]); + } + + public function getAntraegeWhereWiedereinstiegBetween($start, $end) + { + $this->addSelect('sg.email'); + $this->addSelect('vorname'); + $this->addSelect('nachname'); + $this->addSelect($this->dbTable.'.*'); + + $this->addJoin( + 'campus.tbl_studierendenantrag_status s', + 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id' + ); + $this->addJoin('public.tbl_prestudent p', 'prestudent_id'); + $this->addJoin('public.tbl_person', 'person_id'); + $this->addJoin('public.tbl_studiengang sg', 'studiengang_kz'); + + $this->db->where('datum_wiedereinstieg >=', $start->format('Y-m-d')); + $this->db->where('datum_wiedereinstieg <=', $end->format('Y-m-d')); + + return $this->loadWhere([ + 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED, + $this->dbTable.'.typ' => self::TYP_UNTERBRECHUNG, + ]); + } + + public function getWithLastStatusWhere($where) + { + $this->addJoin( + 'campus.tbl_studierendenantrag_status s', + 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id' + ); + + return $this->loadWhere($where); + } + + /** + * Checks if the Prestudent has an active Unterbrechung between + * the start of the given semester and the given enddate. + * If the enddate is omitted the end of the given semester is used. + * + * @param integer $prestudent_id + * @param string $studiensemester_kurzbz + * @param string $enddate (optional) + * + * @return boolean + */ + public function hasRunningUnterbrechungBetween($prestudent_id, $studiensemester, $enddate = null) + { + $start = '(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=' . $this->db->escape($studiensemester) . ')'; + $end = $enddate + ? $this->db->escape($enddate) + : '(SELECT ende FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=' . $this->db->escape($studiensemester) . ')'; + + $this->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + $this->db->where([ + 'prestudent_id' => $prestudent_id, + 'typ' => Studierendenantrag_model::TYP_UNTERBRECHUNG, + 'campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN (\'' . Studierendenantragstatus_model::STATUS_CANCELLED . '\', \'' . Studierendenantragstatus_model::STATUS_REJECTED . '\')' => null, + 'start < ' . $end => null, + 'datum_wiedereinstieg > ' . $start => null, + ]); + return (boolean)$this->db->count_all_results($this->dbTable); + } + + /** + * Gets free semester slots for a new Unterbrechung. + * + * @param integer $prestudent_id + * @param string $studiensemester_kurzbz (optional) + * + * @return stdClass + */ + public function getFreeSlotsForUnterbrechung($prestudent_id, $studiensemester = null) + { + $max_starters = 2; + $max_length = max( + 2, + (integer)$this->config->item('unterbrecher_semester_max_length') + ); + + + $subquery = ''; + if ($studiensemester) + $subquery = 'SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=?'; + else + $subquery = 'SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=public.get_stdsem_prestudent (?, null)'; + + $sql = "WITH numbered_sems AS ( + SELECT + a.studienjahr_kurzbz AS studienjahr_kurzbz, + a.studiensemester_kurzbz AS von, + b.studiensemester_kurzbz AS bis, + a.start AS start, + b.start AS ende, + ROW_NUMBER() OVER ( + PARTITION BY a.studiensemester_kurzbz + ORDER BY b.start + ) AS row_number + FROM public.tbl_studiensemester a + LEFT JOIN public.tbl_studiensemester b ON (b.start > a.ende) + ), + last_sems AS ( + SELECT * + FROM numbered_sems + WHERE numbered_sems.row_number <= ? + ) + SELECT s.von, s.bis, s.start, s.ende, studierendenantrag_id, studienjahr_kurzbz + FROM last_sems s + LEFT JOIN ( + SELECT studierendenantrag_id, start, datum_wiedereinstieg AS ende + FROM campus.tbl_studierendenantrag + LEFT JOIN public.tbl_studiensemester USING(studiensemester_kurzbz) + WHERE typ=? + AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ? + AND prestudent_id=? + ) a ON (s.start < a.ende AND s.ende > a.start) + WHERE s.start >= (" . $subquery . ") + ORDER BY s.start, s.ende + LIMIT ?;"; + + return $this->execQuery($sql, [ + $max_length, + self::TYP_UNTERBRECHUNG, + array( + Studierendenantragstatus_model::STATUS_CANCELLED, + Studierendenantragstatus_model::STATUS_REJECTED + ), + $prestudent_id, + $studiensemester ?: $prestudent_id, + $max_length * $max_starters + ]); + } + + /** + * Returns if an Antrag is manually paused + * + * @param integer $antrag_id + * + * @return boolean + */ + public function isManuallyPaused($antrag_id) + { + $this->addJoin( + 'campus.tbl_studierendenantrag_status s', + 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id' + ); + + $this->db->where([ + 's.studierendenantrag_id' => $antrag_id, + 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE + ]); + + $this->db->group_start(); + $this->db->where_not_in('s.insertvon', [ + Studierendenantragstatus_model::INSERTVON_DEREGISTERED, + Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL + ]); + $this->db->or_group_start(); + $this->db->where('s.insertvon', Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL); + $this->db->where('1 !=', '( + SELECT COUNT(*)%2 + FROM campus.tbl_studierendenantrag_status i + WHERE i.studierendenantrag_id = s.studierendenantrag_id + AND i.insertamum > ( + SELECT ii.insertamum + FROM campus.tbl_studierendenantrag_status ii + WHERE ii.studierendenantrag_id = s.studierendenantrag_id + AND ii.insertvon <> ' . $this->escape(Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL) . ' + ORDER BY ii.insertamum DESC + LIMIT 1 + ) + )', false); + $this->db->group_end(); + $this->db->group_end(); + + return hasData($this->load()); + } +} diff --git a/application/models/education/Studierendenantraglehrveranstaltung_model.php b/application/models/education/Studierendenantraglehrveranstaltung_model.php new file mode 100644 index 000000000..4318c773e --- /dev/null +++ b/application/models/education/Studierendenantraglehrveranstaltung_model.php @@ -0,0 +1,104 @@ +dbTable = 'campus.tbl_studierendenantrag_lehrveranstaltung'; + $this->pk = 'studierendenantrag_lehrveranstaltung_id'; + } + + public function insertBatch($data) + { + // Check class properties + if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL); + + // DB-INSERT + $insert = $this->db->insert_batch($this->dbTable, $data); + + if ($insert) + { + return success(); + } + else + { + return error($this->db->error(), EXIT_DATABASE); + } + } + + public function deleteWhere($where) + { + if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL); + + $delete = $this->db->delete($this->dbTable, $where); + + if ($delete) + { + return success(); + } + else + { + return error($this->db->error(), EXIT_DATABASE); + } + } + + public function getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz) + { + $this->addSelect($this->dbTable . '.*'); + $this->addSelect('a.prestudent_id'); + $this->addSelect('lv.bezeichnung as lv_bezeichnung'); + $this->addSelect('stat.insertamum as freigabedatum'); + $this->addSelect('n.bezeichnung as note_bezeichnung'); + $this->addSelect('stg.bezeichnung as stg_bezeichnung'); + + $this->addJoin('campus.tbl_studierendenantrag a', 'studierendenantrag_id'); + $this->addJoin('lehre.tbl_note n', 'note'); + $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->addJoin('public.tbl_prestudent ps', 'prestudent_id'); + $this->addJoin('public.tbl_studiengang stg', 'ps.studiengang_kz = stg.studiengang_kz'); + $this->addJoin( + 'campus.tbl_studierendenantrag_status stat', + 'stat.studierendenantrag_status_id = campus.get_status_id_studierendenantrag(a.studierendenantrag_id)' + ); + $this->addJoin('public.tbl_student s', 'prestudent_id'); + + // NOTE(chris): last offizell note + $this->addJoin('( + SELECT z.* + FROM lehre.tbl_zeugnisnote z + LEFT JOIN public.tbl_studiensemester zs + USING(studiensemester_kurzbz) + JOIN ( + SELECT zi.lehrveranstaltung_id, zi.student_uid, MAX(zis.start) AS start + FROM lehre.tbl_zeugnisnote zi + LEFT JOIN lehre.tbl_note zin + USING(note) + LEFT JOIN public.tbl_studiensemester zis + USING(studiensemester_kurzbz) + WHERE zin.aktiv AND zin.offiziell + GROUP BY zi.lehrveranstaltung_id, zi.student_uid + ) zx + ON ( + z.lehrveranstaltung_id=zx.lehrveranstaltung_id + AND z.student_uid=zx.student_uid + AND zs.start = zx.start + )) z', 'z.lehrveranstaltung_id=lv.lehrveranstaltung_id AND z.student_uid=s.student_uid', 'LEFT'); + $this->addJoin('lehre.tbl_note zn', 'z.note = zn.note', 'LEFT'); + + $this->load->config('studierendenantrag'); + $note_intern_angerechntet = $this->config->item('wiederholung_note_angerechnet'); + + return $this->loadWhere([ + 'ps.prestudent_id' => $prestudent_id, + 'a.typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG, + 'stat.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED, + 'n.note <> ' => 0, + $this->dbTable . '.studiensemester_kurzbz' => $studiensemester_kurzbz, + '(n.note<>' . $this->db->escape($note_intern_angerechntet) . ' OR (z.note IS NOT NULL AND zn.positiv))' => null + ]); + } +} diff --git a/application/models/education/Studierendenantragstatus_model.php b/application/models/education/Studierendenantragstatus_model.php new file mode 100644 index 000000000..cf9cce1be --- /dev/null +++ b/application/models/education/Studierendenantragstatus_model.php @@ -0,0 +1,209 @@ +dbTable = 'campus.tbl_studierendenantrag_status'; + $this->pk = 'studierendenantrag_status_id'; + } + + public function loadWithTyp($studierendenantrag_status_id) + { + $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()); + + $this->addSelect($this->dbTable . '.*'); + $this->addSelect('bezeichnung[(' . $lang . ')] AS typ'); + + $this->addJoin('campus.tbl_studierendenantrag_statustyp', 'studierendenantrag_statustyp_kurzbz'); + + return $this->load($studierendenantrag_status_id); + } + + public function loadWithTypWhere($where) + { + $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()); + + $this->addSelect($this->dbTable . '.*'); + $this->addSelect('bezeichnung[(' . $lang . ')] AS typ'); + + $this->addJoin('campus.tbl_studierendenantrag_statustyp', 'studierendenantrag_statustyp_kurzbz'); + + return $this->loadWhere($where); + } + + public function stopAntraegeForAbmeldungStgl($antrag_id) + { + $sql = 'INSERT INTO campus.tbl_studierendenantrag_status + (studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum) + SELECT studierendenantrag_id, ?, ?, ( + SELECT insertamum + FROM campus.tbl_studierendenantrag_status + WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?) + ) + FROM campus.tbl_studierendenantrag + WHERE prestudent_id = ( + SELECT prestudent_id + FROM campus.tbl_studierendenantrag + WHERE studierendenantrag_id = ? + ) + AND studierendenantrag_id <> ? + AND ( + ( + typ = ? + AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ? + ) OR ( + typ = ? + AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ? + ) OR ( + typ = ? + AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ? + ) + )'; + + return $this->execQuery($sql, [ + self::STATUS_PAUSE, + self::INSERTVON_ABMELDUNGSTGL, + $antrag_id, + $antrag_id, + $antrag_id, + Studierendenantrag_model::TYP_ABMELDUNG, + [ + Studierendenantragstatus_model::STATUS_CREATED + ], + Studierendenantrag_model::TYP_UNTERBRECHUNG, + [ + Studierendenantragstatus_model::STATUS_CREATED + ], + Studierendenantrag_model::TYP_WIEDERHOLUNG, + [ + Studierendenantragstatus_model::STATUS_REQUESTSENT_1, + Studierendenantragstatus_model::STATUS_REQUESTSENT_2, + Studierendenantragstatus_model::STATUS_CREATED, + Studierendenantragstatus_model::STATUS_LVSASSIGNED, + Studierendenantragstatus_model::STATUS_PAUSE + ], + ]); + } + + public function resumeAntraegeForAbmeldungStgl($antrag_id) + { + $sql = 'INSERT INTO campus.tbl_studierendenantrag_status + (studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum) + SELECT studierendenantrag_id, ( + SELECT studierendenantrag_statustyp_kurzbz + FROM campus.tbl_studierendenantrag_status s + WHERE s.studierendenantrag_id=a.studierendenantrag_id + AND campus.get_status_id_studierendenantrag(a.studierendenantrag_id) <> studierendenantrag_status_id + ORDER BY insertamum DESC + LIMIT 1 + ), ?, ( + SELECT insertamum + FROM campus.tbl_studierendenantrag_status + WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?) + ) + FROM campus.tbl_studierendenantrag a + WHERE prestudent_id = ( + SELECT prestudent_id + FROM campus.tbl_studierendenantrag + WHERE studierendenantrag_id = ? + ) + AND typ <> ? + AND campus.get_status_studierendenantrag(studierendenantrag_id) = ? + '; + + return $this->execQuery($sql, [ + self::INSERTVON_ABMELDUNGSTGL, + $antrag_id, + $antrag_id, + Studierendenantrag_model::TYP_ABMELDUNG_STGL, + Studierendenantragstatus_model::STATUS_PAUSE + ]); + } + + public function stopAntraegeForAbbruchBy($antrag_id) + { + $sql = 'INSERT INTO campus.tbl_studierendenantrag_status + (studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum) + SELECT studierendenantrag_id, ?, ?, ( + SELECT insertamum + FROM campus.tbl_studierendenantrag_status + WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?) + ) + FROM campus.tbl_studierendenantrag + WHERE prestudent_id = ( + SELECT prestudent_id + FROM campus.tbl_studierendenantrag + WHERE studierendenantrag_id = ? + ) + AND studierendenantrag_id <> ? + AND ( + ( + typ = ? + AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ? + ) OR ( + typ = ? + AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ? + ) OR ( + typ = ? + AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ? + ) OR ( + typ = ? + AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ? + ) + )'; + + return $this->execQuery($sql, [ + self::STATUS_PAUSE, + self::INSERTVON_DEREGISTERED, + $antrag_id, + $antrag_id, + $antrag_id, + Studierendenantrag_model::TYP_ABMELDUNG, + [ + Studierendenantragstatus_model::STATUS_APPROVED, + Studierendenantragstatus_model::STATUS_CANCELLED + ], + Studierendenantrag_model::TYP_UNTERBRECHUNG, + [ + Studierendenantragstatus_model::STATUS_APPROVED, + Studierendenantragstatus_model::STATUS_CANCELLED, + Studierendenantragstatus_model::STATUS_REMINDERSENT, + Studierendenantragstatus_model::STATUS_REJECTED + ], + Studierendenantrag_model::TYP_ABMELDUNG_STGL, + [ + Studierendenantragstatus_model::STATUS_CANCELLED, + Studierendenantragstatus_model::STATUS_DEREGISTERED, + Studierendenantragstatus_model::STATUS_OBJECTION_DENIED + ], + Studierendenantrag_model::TYP_WIEDERHOLUNG, + [ + Studierendenantragstatus_model::STATUS_DEREGISTERED, + Studierendenantragstatus_model::STATUS_APPROVED + ], + ]); + } +} diff --git a/application/models/education/Zeugnisnote_model.php b/application/models/education/Zeugnisnote_model.php index a4185a7f4..b4d909e37 100644 --- a/application/models/education/Zeugnisnote_model.php +++ b/application/models/education/Zeugnisnote_model.php @@ -102,7 +102,7 @@ class Zeugnisnote_model extends DB_Model JOIN lehre.tbl_zeugnisnote zgnisnote USING (student_uid) JOIN lehre.tbl_note note ON zgnisnote.note = note.note JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) - JOIN public.tbl_studiengang stg ON prst.studiengang_kz = stg.studiengang_kz + JOIN public.tbl_studiengang stg ON prst.studiengang_kz = stg.studiengang_kz WHERE pers.person_id = ? AND zgnisnote.studiensemester_kurzbz = ?"; @@ -140,4 +140,83 @@ class Zeugnisnote_model extends DB_Model return $this->execQuery($qry, $params); } + + /** + * Gets courses (Zeugnisnoten) for a student. + * @param string $student_uid, + * @param string $studiensemester_kurzbz + * + * @return object + */ + public function getZeugnisnoten($student_uid, $studiensemester_kurzbz) + { + $params = array(); + $where=''; + + if ($student_uid != null) + { + $where .= " AND uid=?"; + $params[] = $student_uid; + } + if ($studiensemester_kurzbz !=null) + { + $where.=" AND vw_student_lehrveranstaltung.studiensemester_kurzbz= ?"; + $params[] = $studiensemester_kurzbz; + } + + $where2=''; + + if ($student_uid != null) + { + $where2 .= " AND student_uid=?"; + $params[] = $student_uid; + } + if ($studiensemester_kurzbz !=null) + { + $where2 .= " AND studiensemester_kurzbz= ?"; + $params[] = $studiensemester_kurzbz; + } + + $qry = "SELECT vw_student_lehrveranstaltung.lehrveranstaltung_id, uid, + vw_student_lehrveranstaltung.studiensemester_kurzbz, note, punkte, uebernahmedatum, benotungsdatum, + vw_student_lehrveranstaltung.ects, vw_student_lehrveranstaltung.semesterstunden, + tbl_zeugnisnote.updateamum, tbl_zeugnisnote.updatevon, tbl_zeugnisnote.insertamum, + tbl_zeugnisnote.insertvon, tbl_zeugnisnote.ext_id, + vw_student_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung, + vw_student_lehrveranstaltung.bezeichnung_english as lehrveranstaltung_bezeichnung_english, + tbl_note.bezeichnung as note_bezeichnung, + tbl_note.positiv as note_positiv, + tbl_zeugnisnote.bemerkung as bemerkung, + vw_student_lehrveranstaltung.sort, + vw_student_lehrveranstaltung.zeugnis, + vw_student_lehrveranstaltung.studiengang_kz, + vw_student_lehrveranstaltung.lv_lehrform_kurzbz, + tbl_lehrveranstaltung.sws + FROM + ( + campus.vw_student_lehrveranstaltung LEFT JOIN lehre.tbl_zeugnisnote + ON(uid=student_uid + AND vw_student_lehrveranstaltung.studiensemester_kurzbz=tbl_zeugnisnote.studiensemester_kurzbz + AND vw_student_lehrveranstaltung.lehrveranstaltung_id=tbl_zeugnisnote.lehrveranstaltung_id + ) + ) LEFT JOIN lehre.tbl_note USING(note) + JOIN lehre.tbl_lehrveranstaltung ON(vw_student_lehrveranstaltung.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id) + WHERE true $where + + UNION + SELECT lehre.tbl_lehrveranstaltung.lehrveranstaltung_id,student_uid AS uid,studiensemester_kurzbz, note, punkte, + uebernahmedatum, benotungsdatum,lehre.tbl_lehrveranstaltung.ects,lehre.tbl_lehrveranstaltung.semesterstunden, tbl_zeugnisnote.updateamum, tbl_zeugnisnote.updatevon, tbl_zeugnisnote.insertamum, + tbl_zeugnisnote.insertvon, tbl_zeugnisnote.ext_id, lehre.tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung, lehre.tbl_lehrveranstaltung.bezeichnung_english as lehrveranstaltung_bezeichnung_english, + tbl_note.bezeichnung as note_bezeichnung, tbl_note.positiv as note_positiv, tbl_zeugnisnote.bemerkung as bemerkung, tbl_lehrveranstaltung.sort, tbl_lehrveranstaltung.zeugnis, tbl_lehrveranstaltung.studiengang_kz, + tbl_lehrveranstaltung.lehrform_kurzbz as lv_lehrform_kurzbz, tbl_lehrveranstaltung.sws + FROM + lehre.tbl_zeugnisnote + JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) + JOIN lehre.tbl_note USING(note) + WHERE true $where2 + + ORDER BY sort"; + + return $this->execQuery($qry, $params); + } } diff --git a/application/models/organisation/Geschaeftsjahr_model.php b/application/models/organisation/Geschaeftsjahr_model.php index 4f0d03b73..fdd774a8c 100644 --- a/application/models/organisation/Geschaeftsjahr_model.php +++ b/application/models/organisation/Geschaeftsjahr_model.php @@ -32,11 +32,20 @@ class Geschaeftsjahr_model extends DB_Model * Gets next Geschaeftsjahr, as determined by its start date * @return array|null */ - public function getNextGeschaeftsjahr() + public function getNextGeschaeftsjahr($offsetDays=null) { $query = 'SELECT * - FROM public.tbl_geschaeftsjahr - WHERE start > now() + FROM public.tbl_geschaeftsjahr WHERE '; + + if(!is_null($offsetDays)) + { + $query .= "start > now() - '".$offsetDays." days'::interval"; + } + else + { + $query .= 'start > now()'; + } + $query .= ' ORDER BY start LIMIT 1'; diff --git a/application/models/organisation/Lehrverband_model.php b/application/models/organisation/Lehrverband_model.php index 953e4b7b2..0e760a116 100644 --- a/application/models/organisation/Lehrverband_model.php +++ b/application/models/organisation/Lehrverband_model.php @@ -11,4 +11,34 @@ class Lehrverband_model extends DB_Model $this->dbTable = 'public.tbl_lehrverband'; $this->pk = array('gruppe', 'verband', 'semester', 'studiengang_kz'); } + + /** + * Gets the maximum possible semester for one or more Studiengaenge. + * If there are more than one Studiengang each maximum is calculated and + * the smallest result is returned. + * + * @param array $studiengang_kzs + * + * @return stdClass + */ + public function getMaxSemester($studiengang_kzs) + { + $sqls = []; + foreach ($studiengang_kzs as $studiengang_kz) { + $this->addSelect('MAX(semester) AS maxsem'); + $this->db->where('studiengang_kz', $studiengang_kz); + $sqls[] = $this->db->get_compiled_select($this->dbTable); + } + + $this->addSelect('MIN(a.maxsem) AS maxsem'); + + $dbTable = $this->dbTable; + $this->dbTable = '(' . implode(' UNION ', $sqls) . ') AS a'; + + $result = $this->load(); + + $this->dbTable = $dbTable; + + return $result; + } } diff --git a/application/models/organisation/Organisationseinheit_model.php b/application/models/organisation/Organisationseinheit_model.php index bec4aee47..4a64ee055 100644 --- a/application/models/organisation/Organisationseinheit_model.php +++ b/application/models/organisation/Organisationseinheit_model.php @@ -188,4 +188,20 @@ class Organisationseinheit_model extends DB_Model } return $this->loadWhere($condition); } + + /** + * Get OEs by eventQuery string. Use with autocomplete event queries. + * @param $eventQuery String + * @return array + */ + public function getAutocompleteSuggestions($eventQuery) + { + $this->addSelect('oe_kurzbz'); + $this->addSelect('organisationseinheittyp_kurzbz, oe_kurzbz, bezeichnung, aktiv, lehre'); + $this->addOrder('organisationseinheittyp_kurzbz, bezeichnung'); + + return $this->loadWhere(" + oe_kurzbz ILIKE '%". $this->escapeLike($eventQuery). "%' + "); + } } diff --git a/application/models/organisation/Standort_model.php b/application/models/organisation/Standort_model.php index 382236e2f..aeeab4497 100644 --- a/application/models/organisation/Standort_model.php +++ b/application/models/organisation/Standort_model.php @@ -11,4 +11,29 @@ class Standort_model extends DB_Model $this->dbTable = 'public.tbl_standort'; $this->pk = 'standort_id'; } + + public function searchStandorte($filter) + { + $filter = strtoLower($filter); + $qry = " + SELECT + s.kurzbz, s.standort_id + FROM + public.tbl_standort s + WHERE + lower (s.kurzbz) LIKE '%". $this->db->escape_like_str($filter)."%' + OR + lower (s.bezeichnung) LIKE '%". $this->db->escape_like_str($filter)."%'"; + + + return $this->execQuery($qry); + } + + public function getStandorteByFirma($firma_id) + { + $this->addSelect("DISTINCT ON (standort_id) bezeichnung, standort_id"); + + return $this->loadWhere(array("firma_id" => $firma_id)); + } } + diff --git a/application/models/organisation/Studiengang_model.php b/application/models/organisation/Studiengang_model.php index f4f8b3c9e..4bbb63805 100644 --- a/application/models/organisation/Studiengang_model.php +++ b/application/models/organisation/Studiengang_model.php @@ -511,10 +511,10 @@ class Studiengang_model extends DB_Model public function getStudiengangTyp($studiengang_kz, $typ = null) { $query = "SELECT DISTINCT(sgt.*) - FROM tbl_studiengangstyp sgt JOIN tbl_studiengang sg on sgt.typ = sg.typ + FROM tbl_studiengangstyp sgt JOIN tbl_studiengang sg on sgt.typ = sg.typ WHERE studiengang_kz IN ?"; - $params[] = $studiengang_kz; + $params = [$studiengang_kz]; if (!is_null($typ)) { @@ -524,4 +524,80 @@ class Studiengang_model extends DB_Model return $this->execQuery($query, $params); } + + /** + * @param array $studiengang_kzs + * @param array $not_antrag_typ (optional) If the prestudent has an antrag with one of the specified types it will be excluded from the result + * @param array $prestudent_stati (optional) + * + * @return stdClass + */ + public function getAktivePrestudenten($studiengang_kzs, $not_antrag_typ = null, $query = null) + { + $this->load->config('studierendenantrag'); + + $sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1"; + + $this->addSelect($this->dbTable . '.studiengang_kz'); + $this->addSelect($this->dbTable . '.bezeichnung'); + $this->addSelect('o.orgform_kurzbz'); + $this->addSelect('o.bezeichnung_mehrsprachig[(' . $sql . ')] AS orgform', false); + $this->addSelect('ps.ausbildungssemester AS semester'); + $this->addSelect('ps.studiensemester_kurzbz'); + $this->addSelect('p.prestudent_id'); + $this->addSelect('pers.vorname'); + $this->addSelect('pers.nachname'); + $this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', " . $this->dbTable . ".bezeichnung, ')') AS name"); + + $this->addJoin('public.tbl_prestudent p', 'studiengang_kz'); + $this->addJoin( + 'public.tbl_prestudentstatus ps', + 'ps.prestudent_id=p.prestudent_id + AND ps.studiensemester_kurzbz=get_stdsem_prestudent(p.prestudent_id, NULL) + AND ps.ausbildungssemester=get_absem_prestudent(p.prestudent_id, NULL) + AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, NULL)' + ); + $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id'); + $this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz)=o.orgform_kurzbz'); + $this->addJoin('public.tbl_person pers', 'person_id'); + $this->addJoin('public.tbl_student stud', 'p.prestudent_id=stud.prestudent_id', 'LEFT'); + + $this->db->where_in($this->dbTable . '.studiengang_kz', $studiengang_kzs); + $this->db->where_in('ps.status_kurzbz', $this->config->item('antrag_prestudentstatus_whitelist_abmeldung')); + $this->db->where($this->dbTable . ".aktiv", true); + + if ($not_antrag_typ !== null && is_array($not_antrag_typ)) { + foreach($not_antrag_typ as $k => $v) + $not_antrag_typ[$k] = $this->db->escape($v); + $this->addJoin( + 'campus.tbl_studierendenantrag a', + 'a.prestudent_id=p.prestudent_id and a.typ in ('. + implode(',', $not_antrag_typ). + ") AND campus.get_status_studierendenantrag (a.studierendenantrag_id)<>'" . + Studierendenantragstatus_model::STATUS_CANCELLED . "'", + 'LEFT' + ); + $this->db->where('a.typ IS NULL'); + } + + if ($query) { + $query = explode(' ', $query); + $this->db->group_start(); + foreach ($query as $q) { + $this->db->group_start(); + $this->db->where('pers.vorname ILIKE', "%" . $q . "%"); + $this->db->or_where('pers.nachname ILIKE', "%" . $q . "%"); + $this->db->or_where('stud.student_uid ILIKE', "%" . $q . "%"); + $this->db->or_where($this->dbTable . '.bezeichnung ILIKE', "%" . $q . "%"); + if (is_numeric($q)) + $this->db->or_where('p.prestudent_id', $q); + $this->db->group_end(); + } + $this->db->group_end(); + } + + $this->addOrder('name'); + + return $this->load(); + } } diff --git a/application/models/organisation/Studienjahr_model.php b/application/models/organisation/Studienjahr_model.php index 3bbe3a07f..a6e1bc575 100644 --- a/application/models/organisation/Studienjahr_model.php +++ b/application/models/organisation/Studienjahr_model.php @@ -29,4 +29,54 @@ class Studienjahr_model extends DB_Model return $this->execQuery($query); } + + /** + * Get the current Studienjahr. During the summer term, continue using the previous Studienjahr. + * + * @param int $days + * @return array|stdClass|null + */ + public function getLastOrAktStudienjahr($days = 60) + { + if (!is_numeric($days)) + { + $days = 60; + } + + $query = ' + SELECT * + FROM public.tbl_studienjahr + JOIN public.tbl_studiensemester USING (studienjahr_kurzbz) + WHERE start < NOW() - \'' . $days . ' DAYS\'::INTERVAL + ORDER by start DESC + LIMIT 1 + '; + + return $this->execQuery($query); + } + + /** + * Get the current Studienjahr. During the summer term, get the upcoming next Studienjahr. + * + * @param int $days + * @return array|stdClass|null + */ + public function getAktOrNextStudienjahr($days = 62) + { + if (!is_numeric($days)) + { + $days = 62; + } + + $query = ' + SELECT * + FROM public.tbl_studienjahr + JOIN public.tbl_studiensemester using(studienjahr_kurzbz) + WHERE start < NOW() + \'' . $days . ' DAYS\'::INTERVAL + ORDER by start DESC + LIMIT 1 + '; + + return $this->execQuery($query); + } } diff --git a/application/models/organisation/Studienplan_model.php b/application/models/organisation/Studienplan_model.php index 0cc23b85d..e35ba52fb 100644 --- a/application/models/organisation/Studienplan_model.php +++ b/application/models/organisation/Studienplan_model.php @@ -45,7 +45,7 @@ class Studienplan_model extends DB_Model $whereArray["tbl_studienplan.sprache"] = $sprache; } - return $this->StudienplanModel->loadWhere($whereArray); + return $this->loadWhere($whereArray); } public function getStudienplanLehrveranstaltung($studienplan_id, $semester) @@ -53,9 +53,85 @@ class Studienplan_model extends DB_Model $this->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'studienplan_id'); $this->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id'); $this->addOrder('tbl_lehrveranstaltung.sort'); + return $this->loadWhere(array( 'studienplan_id' => $studienplan_id, 'tbl_studienplan_lehrveranstaltung.semester' => $semester )); } + + public function getStudienplanLehrveranstaltungForPrestudent($studienplan_id, $semester, $prestudent_id) + { + $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()); + $sql = 'SELECT student_uid FROM public.tbl_student WHERE prestudent_id=' . $this->escape($prestudent_id); + + $this->addSelect($this->dbTable . '.*'); + $this->addSelect('lv.*'); + $this->addSelect('COALESCE(n.bezeichnung_mehrsprachig[(' . $lang . ')], NULL) AS note'); + $this->addSelect('n.positiv'); + $this->addSelect('lehre.tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id'); + $this->addSelect('lehre.tbl_studienplan_lehrveranstaltung.sort plan_sort'); + $this->addSelect('lehre.tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent'); + + $this->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'studienplan_id'); + $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + // NOTE(chris): last offizell note + $this->addJoin('( + SELECT z.* + FROM lehre.tbl_zeugnisnote z + LEFT JOIN public.tbl_studiensemester zs + USING(studiensemester_kurzbz) + JOIN ( + SELECT zi.lehrveranstaltung_id, zi.student_uid, MAX(zis.start) AS start + FROM lehre.tbl_zeugnisnote zi + LEFT JOIN lehre.tbl_note zin + USING(note) + LEFT JOIN public.tbl_studiensemester zis + USING(studiensemester_kurzbz) + WHERE zin.aktiv AND zin.offiziell + GROUP BY zi.lehrveranstaltung_id, zi.student_uid + ) zx + ON ( + z.lehrveranstaltung_id=zx.lehrveranstaltung_id + AND z.student_uid=zx.student_uid + AND zs.start = zx.start + )) zn', 'zn.lehrveranstaltung_id=lv.lehrveranstaltung_id AND zn.student_uid=( ' . $sql . ')', 'LEFT'); + $this->addJoin('lehre.tbl_note n', 'n.note=zn.note', 'LEFT'); + + $this->addOrder('lehre.tbl_studienplan_lehrveranstaltung.sort'); + $this->addOrder('lv.sort'); + + return $this->loadWhere(array( + 'studienplan_id' => $studienplan_id, + 'tbl_studienplan_lehrveranstaltung.semester' => $semester + )); + } + + public function getAllOesForLv($lehrveranstaltung_id) + { + $this->addDistinct('oe_kurzbz'); + + $this->addJoin('lehre.tbl_studienplan_lehrveranstaltung lv', 'studienplan_id'); + $this->addJoin('lehre.tbl_studienordnung', 'studienordnung_id'); + $this->addJoin('public.tbl_studiengang', 'studiengang_kz'); + + return $this->loadWhere([ + 'lv.lehrveranstaltung_id' => $lehrveranstaltung_id + ]); + } + + public function getStudienplaeneByPrestudents($prestudent_id) + { + $this->addDistinct(); + $this->addSelect($this->dbTable . '.*'); + $this->addSelect('sem.start AS start_stsem'); + $this->addJoin('lehre.tbl_studienordnung o', 'studienordnung_id'); + $this->addJoin('public.tbl_prestudent p', 'studiengang_kz'); + $this->addJoin('public.tbl_studiensemester sem', 'sem.studiensemester_kurzbz = o.gueltigvon', 'LEFT'); + $this->addOrder('sem.start'); + + return $this->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + } } diff --git a/application/models/organisation/Studiensemester_model.php b/application/models/organisation/Studiensemester_model.php index 45a4eac7c..c59c9d343 100644 --- a/application/models/organisation/Studiensemester_model.php +++ b/application/models/organisation/Studiensemester_model.php @@ -13,35 +13,35 @@ class Studiensemester_model extends DB_Model $this->hasSequence = false; } - /** - * Get actual Studiensemester. - * - * @return array - */ - public function getAkt() - { - return $this->loadWhere(array( - 'start <= ' => 'NOW()', - 'ende >= ' => 'NOW()' - ) - ); - } + /** + * Get actual Studiensemester. + * + * @return array + */ + public function getAkt() + { + return $this->loadWhere(array( + 'start <= ' => 'NOW()', + 'ende >= ' => 'NOW()' + ) + ); + } // Get next study semester public function getNext() - { - $query = ' - SELECT * - FROM - public.tbl_studiensemester - WHERE - start > now() - ORDER BY start - LIMIT 1; - '; + { + $query = ' + SELECT * + FROM + public.tbl_studiensemester + WHERE + start > now() + ORDER BY start + LIMIT 1; + '; - return $this->execQuery($query); - } + return $this->execQuery($query); + } /** * getLastOrAktSemester @@ -182,10 +182,10 @@ class Studiensemester_model extends DB_Model return success(array()); $query = " - SELECT * - FROM public.tbl_studiensemester - WHERE ( ?::date < ende AND ?::date > start ) - ORDER BY start DESC"; + SELECT * + FROM public.tbl_studiensemester + WHERE ( ?::date < ende AND ?::date > start ) + ORDER BY start DESC"; return $this->execQuery($query, array($from, $to)); } @@ -200,7 +200,7 @@ class Studiensemester_model extends DB_Model { $query = "SELECT studiensemester_kurzbz, start, ende FROM public.vw_studiensemester WHERE studiensemester_kurzbz <> ? - ORDER BY delta, start LIMIT 1"; + ORDER BY delta, start LIMIT 1"; return $this->execQuery($query, array($studiensemester_kurzbz)); } @@ -211,7 +211,46 @@ class Studiensemester_model extends DB_Model FROM public.tbl_studiensemester WHERE start >= NOW() OR (start <= NOW() AND ende >= NOW()) ORDER BY start'; - + return $this->execQuery($query); } + + /** + * Liefert ausgehend von heutigen Datum $plus studiensemester in die Zukunft und $minus Studiensemester in die Vergangenheit + * + * @param integer $plus Optional. Wieviele Studiensemester in die Zukunft sollen ausgegeben werden. Wenn NULL werden alle zukuenftigen geliefert. + * @param integer $minus Optional. Wieviele Studiensemester in die Vergangenheit sollen ausgegeben werden. Wenn NULL werden alle vergangenen geliefert. + * + * @return stdClass + */ + public function addPlusMinus($plus = null, $minus = null) + { + $this->addSelect($this->pk); + $this->addOrder('ende'); + if ($plus) + $this->addLimit($plus); + $this->db->where('start >= NOW()', null, false); + $plus = $this->db->get_compiled_select($this->dbTable); + + $this->addSelect($this->pk); + $this->addOrder('start', 'DESC'); + if ($minus) + $this->addLimit($minus); + $this->db->where('start <= NOW()', null, false); + $minus = $this->db->get_compiled_select($this->dbTable); + + $this->db->where_in($this->pk, '(' . $plus . ') UNION (' . $minus . ')', false); + } + + /** + * Holt letzen zwei Ziffern des Studienjahres von Studiensemester, z.B. 24 für WS2024 und SS2025 + * @param studiensemester_kurzbz + * @return string Studienjahr Nummer + */ + public function getStudienjahrNumberFromStudiensemester($studiensemester_kurzbz) + { + $studienjahrNumber = mb_substr($studiensemester_kurzbz, 4, 2); + if (is_numeric($studienjahrNumber) && mb_substr($studiensemester_kurzbz, 0, 2) == 'SS') (int)$studienjahrNumber -= 1; + return $studienjahrNumber; + } } diff --git a/application/models/person/Adresse_model.php b/application/models/person/Adresse_model.php index fb5112a8d..4dd03ea6b 100644 --- a/application/models/person/Adresse_model.php +++ b/application/models/person/Adresse_model.php @@ -24,4 +24,4 @@ class Adresse_model extends DB_Model $this->addSelect($select); return $this->loadWhere(array('person_id' => $person_id, 'zustelladresse'=> true)); } -} +} \ No newline at end of file diff --git a/application/models/person/Benutzer_model.php b/application/models/person/Benutzer_model.php index eff1329a6..65121dbb5 100644 --- a/application/models/person/Benutzer_model.php +++ b/application/models/person/Benutzer_model.php @@ -1,4 +1,7 @@ addLimit(1); $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 (isError($nameresult)) + return $nameresult; - if (hasData($aliasexists) && !getData($aliasexists)[0]) - $aliasres = $alias; - } - return success($aliasres); + if (!hasData($nameresult)) + return success(''); + + $aliasdata = current(getData($nameresult)); + + return $this->generateAliasFromName($aliasdata->vorname, $aliasdata->nachname); + } + + /** + * Generates alias for a vor- and nachname. + * + * @param string $vorname + * @param string $nachname + * + * @return stdClass + */ + public function generateAliasFromName($vorname, $nachname) + { + $alias = $this->_sanitizeAliasName($vorname . '.' . $nachname); + + $result = $this->aliasExists($alias); + + if (isError($result)) + return $result; + + if (current(getData($result))) + return success(''); + + return success($alias); + } + + /** + * Generates a matrikelnummer + * + * @param string $oe_kurzbz + * + * @return stdClass + */ + public function generateMatrikelnummer($oe_kurzbz) + { + $matrikelnummer = false; + + Events::trigger( + 'generate_matrikelnummer', + function ($value) use ($matrikelnummer) { + $matrikelnummer = $value; + }, + $oe_kurzbz + ); + + if ($matrikelnummer !== false) + return success($matrikelnummer); + + return success(null); + } + + /** + * Generates an activation key + * + * @return string + */ + public function generateActivationkey() + { + $this->load->library('CryptLib'); + + $key = ''; + for ($i=0; $i<32; $i++) + $key .= ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'][mt_rand(0, 15)]; + + $value = uniqid(mt_rand(), true); + $length = strlen($value); + $value = str_pad($value, $length + 32 - ($length % 32), chr(0)); + + return md5($this->cryptlib->RIJNDAEL_256_ECB($value, $key, true)); } // -------------------------------------------------------------------------------------------- @@ -100,9 +169,10 @@ class Benutzer_model extends DB_Model * @param string $str * @return string */ + private function _sanitizeAliasName($str) { $str = sanitizeProblemChars($str); - return mb_strtolower(str_replace(' ','_', $str)); + return mb_strtolower(str_replace(' ', '_', $str)); } } diff --git a/application/models/person/Benutzerfunktion_model.php b/application/models/person/Benutzerfunktion_model.php index 27f9b6184..e44281a92 100644 --- a/application/models/person/Benutzerfunktion_model.php +++ b/application/models/person/Benutzerfunktion_model.php @@ -180,4 +180,60 @@ class Benutzerfunktion_model extends DB_Model return $this->execQuery($query, $parameters_array); } + + + public function insertBenutzerfunktion($Json) + { + unset($Json['benutzerfunktion_id']); + unset($Json['updateamum']); + $Json['insertvon'] = getAuthUID(); + $Json['insertamum'] = $this->escape('NOW()'); + + if ($Json['datum_bis']=='') + { + unset($Json['datum_bis']); + } + + $result = $this->insert($Json); + + if (isError($result)) + { + return error($result->msg, EXIT_ERROR); + } + + $record = $this->load($result->retval); + + return $record; + } + + function updateBenutzerfunktion($funktionJson) + { + $funktionJson['updatevon'] = getAuthUID(); + $funktionJson['updateamum'] = $this->escape('NOW()'); + + $result = $this->update($funktionJson['benutzerfunktion_id'], $funktionJson); + + if (isError($result)) + { + return error($result->msg, EXIT_ERROR); + } + + $result = $this->load($funktionJson['benutzerfunktion_id']); + + return $result; + } + + function deleteBenutzerfunktion($funktionJson) + { + $result = $this->delete($funktionJson); + + if (isError($result)) + { + return error($result->msg, EXIT_ERROR); + } + + return success($funktionJson); + } + + } diff --git a/application/models/person/Kennzeichen_model.php b/application/models/person/Kennzeichen_model.php new file mode 100644 index 000000000..fe8a9ac62 --- /dev/null +++ b/application/models/person/Kennzeichen_model.php @@ -0,0 +1,15 @@ +dbTable = 'public.tbl_kennzeichen'; + $this->pk = 'kennzeichen_id'; + } + +} diff --git a/application/models/person/Notiz_model.php b/application/models/person/Notiz_model.php index bfd8aa258..349eaac60 100644 --- a/application/models/person/Notiz_model.php +++ b/application/models/person/Notiz_model.php @@ -139,12 +139,51 @@ class Notiz_model extends DB_Model */ public function getNotiz($person_id) { - // Join with the table public.tbl_notizzuordnung using notiz_id + $this->addSelect('public.tbl_notiz.*'); $this->addJoin('public.tbl_notizzuordnung', 'notiz_id'); return $this->loadWhere(array('person_id' => $person_id)); } + /** + * gets all Notizen with Documententries for a certain type and type_id + * @param String type of id eg. person_id, prestudent_id, mitarbeiter_uid, projekt_kurzbz, projektphase_id, projekttask_id, + * bestellung_id, lehreinheit_id, anrechnung_id, uid) + * @param $id the corresponding id, part of public.tbl_notizzuordnung + */ + public function getNotizWithDocEntries($id, $type) + { + $qry = " + SELECT + n.*, count(dms_id) as countDoc, z.notizzuordnung_id, + TO_CHAR (CASE + WHEN n.updateamum >= n.insertamum THEN n.updateamum + ELSE n.insertamum + END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate, + regexp_replace(n.text, '<[^>]*>', '', 'g') as text_stripped, + TO_CHAR(n.start::timestamp, 'DD.MM.YYYY') AS start_format, + TO_CHAR(n.ende::timestamp, 'DD.MM.YYYY') AS ende_format, + z.notiz_id, z.person_id as id, ? as type_id + + FROM + public.tbl_notiz n + JOIN + public.tbl_notizzuordnung z USING (notiz_id) + LEFT JOIN + public.tbl_notiz_dokument dok USING (notiz_id) + LEFT JOIN + campus.tbl_dms_version USING (dms_id) + WHERE + z.$type = ? + GROUP BY + notiz_id, z.notizzuordnung_id + "; + + return $this->execQuery($qry, array($type, $id)); + + } + + /** * gets all Notizen for a person with a specific title * @param $person_id @@ -231,6 +270,4 @@ class Notiz_model extends DB_Model return $this->loadWhere(array('anrechnung_id' => $anrechnung_id)); } - // ------------------------------------------------------------------------------------------------------ - } diff --git a/application/models/person/Notizdokument_model.php b/application/models/person/Notizdokument_model.php new file mode 100644 index 000000000..6b141307f --- /dev/null +++ b/application/models/person/Notizdokument_model.php @@ -0,0 +1,14 @@ +dbTable = 'public.tbl_notiz_dokument'; + $this->pk= array('notiz_id' , 'dms_id'); + } +} \ No newline at end of file diff --git a/application/models/person/Notizzuordnung_model.php b/application/models/person/Notizzuordnung_model.php index 187a8399b..b94ff3fb6 100644 --- a/application/models/person/Notizzuordnung_model.php +++ b/application/models/person/Notizzuordnung_model.php @@ -11,4 +11,38 @@ class Notizzuordnung_model extends DB_Model $this->dbTable = 'public.tbl_notizzuordnung'; $this->pk = 'notizzuordnung_id'; } + + public function isValidType($type) + { + $validTypes = []; + + $qry = " + SELECT column_name + FROM information_schema.columns + WHERE table_schema = 'public' + AND table_name = 'tbl_notizzuordnung' + AND column_name not in ('notizzuordnung_id', 'notiz_id') + "; + + $type_arr = $this->execQuery($qry); + $type_arr = $type_arr->retval; + + foreach ($type_arr as $t) + { + $validTypes[] = $t->column_name; + } + + //TODO(manu) param id + if (in_array($type, $validTypes) ) + //if (in_array($type, $validTypes) ||($type == 'software_id')) //Just for testing + { + return success("Type " . $type . " is valid"); + // $result = success('Type of Id is valid'); + } + else + { + return error("Type " . $type . " is NOT valid"); + } + //return $result; + } } diff --git a/application/models/person/Person_model.php b/application/models/person/Person_model.php index ed21082e2..dc925a171 100644 --- a/application/models/person/Person_model.php +++ b/application/models/person/Person_model.php @@ -1,5 +1,22 @@ . + */ + class Person_model extends DB_Model { /** @@ -8,6 +25,7 @@ class Person_model extends DB_Model public function __construct() { parent::__construct(); + $this->dbTable = 'public.tbl_person'; $this->pk = 'person_id'; @@ -70,7 +88,7 @@ class Person_model extends DB_Model if (isset($person['svnr']) && $person['svnr'] != '') { $this->PersonModel->addOrder('svnr', 'DESC'); - $result = $this->PersonModel->loadWhere(array( + $result = $this->PersonModel->loadWhere(array( 'person_id != ' => $person['person_id'], 'SUBSTRING(svnr FROM 1 FOR 10) = ' => $person['svnr']) ); @@ -138,7 +156,8 @@ class Person_model extends DB_Model 'lower(nachname) like '.$this->db->escape('%'.$filter.'%')." OR lower(vorname) like ".$this->db->escape('%'.$filter.'%')." OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.$filter.'%')." - OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%')); + OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%') + ); return $result; } @@ -152,8 +171,12 @@ class Person_model extends DB_Model */ public function getPersonStammdaten($person_id, $zustellung_only = false) { - $this->addSelect('public.tbl_person.*, tbl_person.staatsbuergerschaft AS staatsbuergerschaft_code, tbl_person.geburtsnation AS geburtsnation_code, - s.kurztext as staatsbuergerschaft, g.kurztext as geburtsnation'); + $this->addSelect('public.tbl_person.*, + tbl_person.staatsbuergerschaft AS staatsbuergerschaft_code, + tbl_person.geburtsnation AS geburtsnation_code, + s.kurztext as staatsbuergerschaft, + g.kurztext as geburtsnation' + ); $this->addJoin('bis.tbl_nation s', 'public.tbl_person.staatsbuergerschaft = s.nation_code', 'LEFT'); $this->addJoin('bis.tbl_nation g', 'public.tbl_person.geburtsnation = g.nation_code', 'LEFT'); @@ -258,7 +281,8 @@ class Person_model extends DB_Model */ public function getFullName($uid) { - if (!$result = getData($this->getByUid($uid))[0]) + $result = getData($this->getByUid($uid))[0]; + if (!$result) { show_error('Failed loading person'); } @@ -270,15 +294,15 @@ class Person_model extends DB_Model { $qry = "SELECT person_id FROM public.tbl_prestudent p - JOIN + JOIN ( SELECT DISTINCT ON(prestudent_id) * FROM public.tbl_prestudentstatus - WHERE prestudent_id IN + WHERE prestudent_id IN ( - SELECT prestudent_id - FROM public.tbl_prestudent - WHERE person_id IN + SELECT prestudent_id + FROM public.tbl_prestudent + WHERE person_id IN ( SELECT p2.person_id FROM public.tbl_person p @@ -292,8 +316,8 @@ class Person_model extends DB_Model ORDER BY prestudent_id, datum DESC, insertamum DESC ) ps USING(prestudent_id) JOIN public.tbl_status USING(status_kurzbz) - WHERE status_kurzbz = 'Interessent' - AND studiengang_kz IN + WHERE status_kurzbz = 'Interessent' + AND studiengang_kz IN ( SELECT studiengang_kz FROM public.tbl_prestudent p @@ -337,4 +361,51 @@ class Person_model extends DB_Model return $this->execQuery($qry, array($person_id, $person_id, $person_id)); } -} + + public function loadPrestudent($prestudent_id) + { + $this->addSelect($this->dbTable . '.*'); + + $this->addJoin('public.tbl_prestudent p', 'person_id'); + + $this->addLimit(1); + + return $this->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + } + + public function checkUnruly($vorname, $nachname, $gebdatum) + { + $qry = "SELECT person_id, vorname, nachname, gebdatum, unruly + FROM tbl_person + WHERE tbl_person.vorname = ? + AND tbl_person.nachname = ? + AND tbl_person.gebdatum = ? + AND tbl_person.unruly = TRUE;"; + + return $this->execQuery($qry, [$vorname, $nachname, $gebdatum]); + } + + public function checkUnrulyWhere($where, $paramsArray) + { + $qry = 'SELECT * + FROM tbl_person p + WHERE '.$where.';'; + + return $this->execQuery($qry, $paramsArray); + } + + public function updateUnruly($person_id, $unruly) + { + $result = $this->update($person_id, array( + 'unruly' => $unruly + )); + + if (isError($result)) { + return error($result->msg, EXIT_ERROR); + } else if (isSuccess($result) && hasData($result)) { + return success($result); + } + } +} \ No newline at end of file diff --git a/application/models/ressource/Betriebsmittel_model.php b/application/models/ressource/Betriebsmittel_model.php index 849a9199f..290c3491d 100644 --- a/application/models/ressource/Betriebsmittel_model.php +++ b/application/models/ressource/Betriebsmittel_model.php @@ -11,4 +11,24 @@ class Betriebsmittel_model extends DB_Model $this->dbTable = 'wawi.tbl_betriebsmittel'; $this->pk = 'betriebsmittel_id'; } + + /** + * load Liste Inventarnummern + */ + public function loadInventarliste($filter) + { + $filter = urldecode(strtoLower($filter)); + + $qry = " + SELECT + bm.inventarnummer, bm.betriebsmitteltyp, bm.betriebsmittel_id, CONCAT(bm.inventarnummer, ' ', bm.beschreibung) as dropdowntext + FROM + wawi.tbl_betriebsmittel bm + WHERE + upper(bm.inventarnummer) LIKE '%" .$this->db->escape_like_str($filter)."%' + OR + lower(bm.inventarnummer) LIKE '%" .$this->db->escape_like_str($filter)."%'"; + + return $this->execQuery($qry); + } } diff --git a/application/models/ressource/Betriebsmittelperson_model.php b/application/models/ressource/Betriebsmittelperson_model.php index 04878a9ad..39f08b5cd 100644 --- a/application/models/ressource/Betriebsmittelperson_model.php +++ b/application/models/ressource/Betriebsmittelperson_model.php @@ -96,4 +96,49 @@ class Betriebsmittelperson_model extends DB_Model return $this->loadWhere($condition); } + + public function getBetriebsmittelData($id, $type_id) + { + switch ($type_id) { + case 'person_id': + $cond = 'bmp.person_id'; + break; + case 'uid': + $cond = 'bmp.uid'; + break; + case 'betriebsmittelperson_id': + $cond = 'bmp.betriebsmittelperson_id'; + break; + default: + return error("ID nicht gültig"); + } + + $query = " + SELECT + bm.nummer, bmp.person_id, bm.betriebsmitteltyp, bmp.anmerkung as anmerkung, bmp.retouram, TO_CHAR(bmp.retouram::timestamp, 'DD.MM.YYYY') AS format_retour, bmp.ausgegebenam, TO_CHAR(bmp.ausgegebenam::timestamp, 'DD.MM.YYYY') AS format_ausgabe, bm.beschreibung, bmp.uid, bmp.kaution, bm.betriebsmittel_id, bmp.betriebsmittelperson_id, bm.inventarnummer, bm.nummer2 + FROM + wawi.tbl_betriebsmittelperson bmp + JOIN + wawi.tbl_betriebsmittel bm ON (bmp.betriebsmittel_id = bm.betriebsmittel_id) + WHERE + " . $cond . " = ? "; + + return $this->execQuery($query, array($id)); + } + + /** + * Perform a loadWhere on the vw_betriebsmittelperson DB View + * + * @param array $where + * + * @return stdClass + */ + public function loadViewWhere($where) + { + $table = $this->dbTable; + $this->dbTable = 'public.vw_betriebsmittelperson'; + $result = $this->loadWhere($where); + $this->dbTable = $table; + return $result; + } } diff --git a/application/models/ressource/Firma_model.php b/application/models/ressource/Firma_model.php index 1b8dfb51d..431f0815f 100644 --- a/application/models/ressource/Firma_model.php +++ b/application/models/ressource/Firma_model.php @@ -11,4 +11,18 @@ class Firma_model extends DB_Model $this->dbTable = 'public.tbl_firma'; $this->pk = 'firma_id'; } + + public function searchFirmen($filter) + { + $filter = strtoLower($filter); + $qry = " + SELECT + f.name, f.firma_id + FROM + public.tbl_firma f + WHERE + lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'"; + + return $this->execQuery($qry); + } } diff --git a/application/models/ressource/Mitarbeiter_model.php b/application/models/ressource/Mitarbeiter_model.php index 90c30927f..c38fcf054 100644 --- a/application/models/ressource/Mitarbeiter_model.php +++ b/application/models/ressource/Mitarbeiter_model.php @@ -144,10 +144,15 @@ class Mitarbeiter_model extends DB_Model * Checks if alias exists * @param $kurzbz */ - public function kurzbzExists($kurzbz) + public function kurzbzExists($kurzbz, $uid=null) { $this->addSelect('1'); - $result = $this->loadWhere(array('kurzbz' => $kurzbz)); + $where = array('kurzbz' => $kurzbz); + if ($uid != null) + { + $where['mitarbeiter_uid<>'] = $uid; + } + $result = $this->loadWhere($where); if (isSuccess($result)) { @@ -171,7 +176,6 @@ class Mitarbeiter_model extends DB_Model */ public function generateKurzbz($uid) { - $kurzbz = ''; $this->addLimit(1); $this->addSelect('vorname, nachname'); $this->addJoin('public.tbl_benutzer', 'tbl_mitarbeiter.mitarbeiter_uid = tbl_benutzer.uid'); @@ -181,25 +185,57 @@ class Mitarbeiter_model extends DB_Model if (hasData($nameresult)) { $kurzbzdata = getData($nameresult); - $nachname_clean = sanitizeProblemChars($kurzbzdata[0]->nachname); - $vorname_clean = sanitizeProblemChars($kurzbzdata[0]->vorname); + $genKurzbz = $this->generateKurzbzHelper($kurzbzdata[0]->vorname, $kurzbzdata[0]->nachname); - for ($nn = 6, $vn = 2; $nn != 0; $nn--, $vn++) - { - $kurzbz = mb_substr($nachname_clean, 0, $nn); - $kurzbz .= mb_substr($vorname_clean, 0, $vn); + return $genKurzbz; + } + return error('No Kurzbezeichnung could be generated'); + } - $kurzbzexists = $this->kurzbzExists($kurzbz); + public function generateKurzbzHelper($vorname, $nachname) + { + $nachname_clean = sanitizeProblemChars($nachname); + $vorname_clean = sanitizeProblemChars($vorname); + $kurzbz = ''; - if (hasData($kurzbzexists) && !getData($kurzbzexists)[0]) - break; - } + for ($nn = 6, $vn = 2; $nn != 0; $nn--, $vn++) + { + $kurzbz = mb_substr($nachname_clean, 0, $nn); + $kurzbz .= mb_substr($vorname_clean, 0, $vn); $kurzbzexists = $this->kurzbzExists($kurzbz); - if (hasData($kurzbzexists) && getData($kurzbzexists)[0]) - return error('No Kurzbezeichnung could be generated'); + if (hasData($kurzbzexists) && !getData($kurzbzexists)[0]) + break; } + + $kurzbzexists = $this->kurzbzExists($kurzbz); + + if (hasData($kurzbzexists) && getData($kurzbzexists)[0]) + return error('No Kurzbezeichnung could be generated'); + return success($kurzbz); } + + public function searchMitarbeiter($filter) + { + $filter = strtoLower($filter); + $qry = " + SELECT + ma.mitarbeiter_uid, CONCAT(p.nachname, ' ', p.vorname, ' (', ma.mitarbeiter_uid , ')') as mitarbeiter + FROM + public.tbl_mitarbeiter ma + JOIN + public.tbl_benutzer b on (ma.mitarbeiter_uid = b.uid) + JOIN + public.tbl_person p on (p.person_id = b.person_id) + WHERE + lower (p.nachname) LIKE '%". $this->db->escape_like_str($filter)."%' + OR + lower (p.vorname) LIKE '%". $this->db->escape_like_str($filter)."%' + OR + (ma.mitarbeiter_uid) LIKE '%". $this->db->escape_like_str($filter)."%'"; + + return $this->execQuery($qry); + } } diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php new file mode 100644 index 000000000..c397d8573 --- /dev/null +++ b/application/models/ressource/Stundensatz_model.php @@ -0,0 +1,17 @@ +dbTable = 'hr.tbl_stundensatz'; + $this->pk = 'stundensatz_id'; + $this->hasSequence = true; + } + +} \ No newline at end of file diff --git a/application/models/ressource/Stundensatztyp_model.php b/application/models/ressource/Stundensatztyp_model.php new file mode 100644 index 000000000..8dfd54c7d --- /dev/null +++ b/application/models/ressource/Stundensatztyp_model.php @@ -0,0 +1,16 @@ +dbTable = 'hr.tbl_stundensatztyp'; + $this->pk = 'stundensatztyp'; + } + +} \ No newline at end of file diff --git a/application/models/ressource/Zeitaufzeichnung_model.php b/application/models/ressource/Zeitaufzeichnung_model.php index b44861d13..8639a716a 100644 --- a/application/models/ressource/Zeitaufzeichnung_model.php +++ b/application/models/ressource/Zeitaufzeichnung_model.php @@ -21,4 +21,26 @@ class Zeitaufzeichnung_model extends DB_Model return $this->execQuery($qry); } + + public function getFullInterval($uid, $fromDate, $toDate) + { + $qry = <<execQuery($qry, array($uid, $fromDate, $toDate, $uid, $fromDate, $toDate, $fromDate, $toDate)); + } } diff --git a/application/models/system/Issue_model.php b/application/models/system/Issue_model.php index ab1f9ba6e..331b0f050 100644 --- a/application/models/system/Issue_model.php +++ b/application/models/system/Issue_model.php @@ -22,13 +22,23 @@ class Issue_model extends DB_Model */ public function getOpenIssues($fehlercodes, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null) { - $params = array($fehlercodes); + $params = array(); // issue exists for a fehlercode (or fehlercode_extern), person_id, oe_kurzbz, if not verarbeitet yet - $qry = 'SELECT issue_id, fehlercode, inhalt, fehlercode_extern, inhalt_extern, person_id, oe_kurzbz, - behebung_parameter, datum, verarbeitetvon, verarbeitetamum - FROM system.tbl_issue - WHERE fehlercode IN ? - AND verarbeitetamum IS NULL'; + $qry = 'SELECT + iss.issue_id, iss.fehlercode, fe.fehler_kurzbz, iss.inhalt, iss.fehlercode_extern, + iss.inhalt_extern, iss.person_id, iss.oe_kurzbz, iss.behebung_parameter, + iss.datum, iss.verarbeitetvon, iss.verarbeitetamum + FROM + system.tbl_issue iss + JOIN system.tbl_fehler fe USING (fehlercode) + WHERE + verarbeitetamum IS NULL'; + + if (!isEmptyArray($fehlercodes)) + { + $qry .= ' AND fehlercode IN ?'; + $params[] = $fehlercodes; + } if (!isEmptyString($fehlercode_extern)) { @@ -59,7 +69,7 @@ class Issue_model extends DB_Model * @param string $fehlercode_extern if provided, only issues with this external fehlercode are counted (for identifying issues from external systems). * @return Object success with number of issues or error */ - public function getOpenIssueCount($fehlercode, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null) + public function getOpenIssueCount($fehlercode, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null, $behebung_parameter = null) { $params = array($fehlercode); // issue exists for a fehlercode (or fehlercode_extern), person_id, oe_kurzbz, if not verarbeitet yet @@ -85,6 +95,19 @@ class Issue_model extends DB_Model $params[] = $oe_kurzbz; } + if (isset($behebung_parameter) && !isEmptyArray($behebung_parameter)) + { + // convert array to JSON string for postgres + $behebung_parameter_string = json_encode($behebung_parameter); + + if ($behebung_parameter_string) + { + // check if jsonb value is equal to the passed parameters array (if value contains array and array contains value) + $qry .= ' AND behebung_parameter @> ? AND behebung_parameter <@ ?'; + $params = array_merge($params, array($behebung_parameter_string, $behebung_parameter_string)); + } + } + return $this->execQuery($qry, $params); } } diff --git a/application/models/system/PersonLog_model.php b/application/models/system/PersonLog_model.php index 7a66958b8..88b50487a 100644 --- a/application/models/system/PersonLog_model.php +++ b/application/models/system/PersonLog_model.php @@ -1,5 +1,22 @@ . + */ + class PersonLog_model extends DB_Model { /** @@ -17,7 +34,7 @@ class PersonLog_model extends DB_Model * @param array $data Data of Log Entry to save. * @return success object if true */ - public function insert($data) + public function insert($data, $encryptedColumns = null) { $result = $this->db->insert($this->dbTable, $data); if ($result) diff --git a/application/models/system/Recipient_model.php b/application/models/system/Recipient_model.php index d74d03243..1c7811f93 100644 --- a/application/models/system/Recipient_model.php +++ b/application/models/system/Recipient_model.php @@ -327,7 +327,7 @@ class Recipient_model extends DB_Model pr.nachname, ms.person_id, mrou.token - ORDER BY sent DESC'; + ORDER BY sent DESC LIMIT 1500'; return $this->execQuery($sql, array($person_id, $functions, $person_id)); } diff --git a/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php b/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php new file mode 100644 index 000000000..6827beaa4 --- /dev/null +++ b/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php @@ -0,0 +1,249 @@ +dbTable = 'hr.tbl_dienstverhaeltnis'; + $this->pk = 'dienstverhaeltnis_id'; + } + + /** + * @return list of DV + */ + public function getDVByPersonUID($uid, $oe_kurzbz=null, $datum=null) + { + $result = null; + + $qry = " + SELECT + dv.dienstverhaeltnis_id, + tbl_benutzer.uid, + tbl_mitarbeiter.personalnummer, + tbl_mitarbeiter.kurzbz, + tbl_mitarbeiter.lektor, + tbl_mitarbeiter.fixangestellt, + tbl_person.person_id, + tbl_benutzer.alias, + org.oe_kurzbz, + org.bezeichnung oe_bezeichnung, + dv.von, + dv.bis, + dv.dvendegrund_kurzbz, + dv.dvendegrund_anmerkung, + dv.vertragsart_kurzbz, + dv.updateamum, + dv.updatevon, + dv.dvendegrund_kurzbz, + dv.dvendegrund_anmerkung + FROM tbl_mitarbeiter + JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text + JOIN tbl_person USING (person_id) + JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text) + JOIN public.tbl_organisationseinheit org USING(oe_kurzbz) + WHERE tbl_benutzer.uid=?"; + $data = array($uid); + + if(!is_null($oe_kurzbz)) + { + $qry.=" AND oe_kurzbz=?"; + $data[] = $oe_kurzbz; + } + + if (!is_null($datum)) + { + $qry.=" AND ? BETWEEN dv.von AND COALESCE(dv.bis, '2999-12-31')"; + $data[] = $datum; + } + + $qry .=" + ORDER BY dv.von desc + "; + + return $this->execQuery($qry, $data); + + } + + public function getDVByID($dvid) { + $this->addSelect('hr.tbl_dienstverhaeltnis.*, public.tbl_organisationseinheit.bezeichnung as unternehmen'); + $this->addJoin('public.tbl_organisationseinheit', 'hr.tbl_dienstverhaeltnis.oe_kurzbz = public.tbl_organisationseinheit.oe_kurzbz'); + $result = $this->load($dvid); + + if (hasData($result)) { + return $result; + } + return error('could not fetch DV by ID'); + } + + + public function getCurrentDVByPersonUID($uid, $dateAsUnixTS) + { + + $date = DateTime::createFromFormat( 'U', $dateAsUnixTS ); + $datestring = $date->format("Y-m-d"); + + $qry = " + SELECT + dv.dienstverhaeltnis_id, + tbl_benutzer.uid, + tbl_mitarbeiter.personalnummer, + tbl_mitarbeiter.kurzbz, + tbl_mitarbeiter.lektor, + tbl_mitarbeiter.fixangestellt, + tbl_person.person_id, + tbl_benutzer.alias, + dv.von, + dv.bis, + dv.vertragsart_kurzbz, + dv.updateamum, + dv.updatevon + FROM tbl_mitarbeiter + JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text + JOIN tbl_person USING (person_id) + JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text) + WHERE tbl_benutzer.uid=? and (dv.von<=? and (dv.bis is null OR dv.bis>=?)) + ORDER BY dv.von desc + "; + + return $this->execQuery($qry, array($uid, $datestring, $datestring)); + } + + public function isOverlappingExistingDV($mitarbeiter_uid, $oe_kurzbz, $von, $bis, $dvid=null) + { + $params = array($mitarbeiter_uid, $oe_kurzbz, $von, $bis, $von, $bis); + $dvidclause = ''; + if (intval($dvid) > 0) + { + $params = array_merge($params, array($dvid, $dvid)); + $dvidclause = <<= COALESCE(vb.von, '1970-01-01'::date) + AND + COALESCE(dv.bis::date, '2170-12-31'::date) <= COALESCE(vb.bis, '2170-12-31') + ) = 0 + AND dv.dienstverhaeltnis_id != ? +EODVIDC; + + } + + $query = <<= dv.von + AND ( + SELECT + COUNT(*) AS karenzen + FROM + hr.tbl_vertragsbestandteil vb + WHERE + vb.dienstverhaeltnis_id = dv.dienstverhaeltnis_id + AND + vb.vertragsbestandteiltyp_kurzbz = 'karenz' + AND + ?::date >= COALESCE(vb.von, '1970-01-01'::date) + AND + COALESCE(?::date, '2170-12-31'::date) <= COALESCE(vb.bis, '2170-12-31') + ) = 0 + {$dvidclause} +EOSQL; + + $ret = $this->execReadOnlyQuery($query, $params); + + if( ($dvcount = getData($ret)) && ($dvcount[0]->dvcount > 0) ) { + return true; + } + + return false; + } + + public function getDVByPersonUIDOverlapping($uid, $oe_kurzbz=null, $beginn=null, $ende=null) + { + $result = null; + + $qry = " + SELECT + dv.dienstverhaeltnis_id, + tbl_benutzer.uid, + tbl_mitarbeiter.personalnummer, + tbl_mitarbeiter.kurzbz, + tbl_mitarbeiter.lektor, + tbl_mitarbeiter.fixangestellt, + tbl_person.person_id, + tbl_benutzer.alias, + org.oe_kurzbz, + org.bezeichnung oe_bezeichnung, + dv.von, + dv.bis, + dv.vertragsart_kurzbz, + dv.updateamum, + dv.updatevon + FROM tbl_mitarbeiter + JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text + JOIN tbl_person USING (person_id) + JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text) + JOIN public.tbl_organisationseinheit org USING(oe_kurzbz) + WHERE tbl_benutzer.uid=?"; + $data = array($uid); + + if(!is_null($oe_kurzbz)) + { + $qry.=" AND oe_kurzbz=?"; + $data[] = $oe_kurzbz; + } + + if (!is_null($beginn) && !is_null($ende)) + { + $qry.=" AND (?,?) OVERLAPS (dv.von, COALESCE(dv.bis, '2999-12-31'))"; + $data[] = $beginn; + $data[] = $ende; + } + + $qry .=" + ORDER BY dv.von desc + "; + + return $this->execQuery($qry, $data); + + } + + public function fetchDienstverhaeltnisse($unternehmen, $stichtag=null, $mitarbeiteruid=null) { + $where = "oe_kurzbz = " . $this->escape($unternehmen); + if( !is_null($stichtag) ) + { + $where .= " AND " . $this->escape($stichtag) . " BETWEEN COALESCE(von, '1970-01-01') AND COALESCE(bis, '2070-12-31')"; + } + if( !is_null($mitarbeiteruid) ) + { + $where .= " AND mitarbeiter_uid = " . $this->escape($mitarbeiteruid); + } + $res = $this->loadWhere($where); + $dvs = array(); + if(hasData($res) ) + { + $dvs = getData($res); + } + return $dvs; + } +} diff --git a/application/models/vertragsbestandteil/GehaltsTyp_model.php b/application/models/vertragsbestandteil/GehaltsTyp_model.php new file mode 100644 index 000000000..c933a3b38 --- /dev/null +++ b/application/models/vertragsbestandteil/GehaltsTyp_model.php @@ -0,0 +1,28 @@ +dbTable = 'hr.tbl_gehaltstyp'; + $this->pk = 'gehaltstyp_kurzbz'; + } + + /** + * Gets Gehaltstyp for a Gehaltsbestandteil. + * @param int gehaltsbestandteil_id + * @return object the typ + */ + public function getGehaltstypByGehaltsbestandteil($gehaltsbestandteil_id) + { + $gehaltsTyp = null; + $this->addJoin('hr.tbl_gehaltsbestandteil', 'gehaltstyp_kurzbz'); + $result = $this->loadWhere(['gehaltsbestandteil_id' => $gehaltsbestandteil_id]); + + if (hasData($result)) $gehaltsTyp = getData($result)[0]; + + return $gehaltsTyp; + } +} diff --git a/application/models/vertragsbestandteil/Gehaltsbestandteil_model.php b/application/models/vertragsbestandteil/Gehaltsbestandteil_model.php new file mode 100644 index 000000000..e9006dfc0 --- /dev/null +++ b/application/models/vertragsbestandteil/Gehaltsbestandteil_model.php @@ -0,0 +1,147 @@ +dbTable = 'hr.tbl_gehaltsbestandteil'; + $this->pk = 'gehaltsbestandteil_id'; + } + + public function getEncryptedColumns(): array + { + return array( + 'grundbetrag' => array( + DB_Model::CRYPT_CAST => 'numeric', + DB_Model::CRYPT_PASSWORD_NAME => 'ENCRYPTIONKEYGEHALT' + ), + 'betrag_valorisiert' => array( + DB_Model::CRYPT_CAST => 'numeric', + DB_Model::CRYPT_PASSWORD_NAME => 'ENCRYPTIONKEYGEHALT' + ) + ); + } + + public function getCurrentGBTByDV($dienstverhaeltnis_id, $dateAsUnixTS) + { + $date = DateTime::createFromFormat( 'U', $dateAsUnixTS ); + $datestring = $date->format("Y-m-d"); + + $qry = " + SELECT + gehaltsbestandteil_id, + gbt.von, + gbt.bis, + gbt.anmerkung, + gbt.dienstverhaeltnis_id, + gehaltstyp_kurzbz, + valorisierungssperre, + gbt.valorisierung, + grundbetrag as grund_betrag_decrypted, + betrag_valorisiert as betrag_val_decrypted, + gt.bezeichnung as gehaltstyp_bezeichnung, + vb.vertragsbestandteiltyp_kurzbz, + bf.funktion_kurzbz, + bf.oe_kurzbz, + fkt.beschreibung as fkt_beschreibung, + fb.bezeichnung as fb_bezeichnung, + org.bezeichnung as org_bezeichnung, + freitext.freitexttyp_kurzbz, + freitext.titel as freitext_titel + FROM hr.tbl_gehaltsbestandteil gbt LEFT JOIN hr.tbl_gehaltstyp gt using(gehaltstyp_kurzbz) + LEFT JOIN hr.tbl_vertragsbestandteil vb using(vertragsbestandteil_id) + LEFT JOIN hr.tbl_vertragsbestandteil_funktion vbf using(vertragsbestandteil_id) + LEFT JOIN public.tbl_benutzerfunktion bf using(benutzerfunktion_id) + LEFT JOIN public.tbl_funktion fkt using(funktion_kurzbz) + LEFT JOIN public.tbl_fachbereich fb using(fachbereich_kurzbz) + LEFT JOIN public.tbl_organisationseinheit org on (bf.oe_kurzbz=org.oe_kurzbz) + LEFT JOIN hr.tbl_vertragsbestandteil_freitext freitext on(vb.vertragsbestandteil_id=freitext.vertragsbestandteil_id) + WHERE gbt.dienstverhaeltnis_id=? AND + (gbt.von<=? and (gbt.bis is null OR gbt.bis>=?)) + ORDER BY gt.sort + "; + + return $this->execQuery($qry, + array($dienstverhaeltnis_id, $datestring, $datestring), + $this->getEncryptedColumns()); + } + + public function getGBTChartDataByDV_old($dienstverhaeltnis_id) + { + + $qry = " + WITH gbt as + (select von,bis,grundbetrag as grund_betrag_decrypted from hr.tbl_gehaltsbestandteil where dienstverhaeltnis_id=?) + select von,bis, (select sum(gbt.grund_betrag_decrypted) as sum_betrag + from gbt where gbt.von<=gbtmeta.von and (gbt.bis is null or gbt.bis>=gbtmeta.von) + ) as summe from gbt as gbtmeta order by von,bis + "; + + return $this->execQuery($qry, + array($dienstverhaeltnis_id), + $this->getEncryptedColumns()); + } + + + public function getGehaltsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false) + { + $stichtagclause = ''; + if( !is_null($stichtag) ) + { + $date = strftime('%Y-%m-%d', strtotime($stichtag)); + $stichtagclause = 'AND (' . $this->escape($date) + . ' BETWEEN COALESCE(von, \'1970-01-01\'::date)' + . ' AND COALESCE(bis, \'2170-01-01\'::date)'; + if( $includefuture ) + { + $stichtagclause .= ' OR COALESCE(von, \'1970-01-01\'::date) > ' + . $this->escape($date); + } + $stichtagclause .= ')'; + } + + $this->addSelect('*'); + $where = <<escape($dienstverhaeltnis_id)} + {$stichtagclause} +EOSQL; + + $query = $this->loadWhere( + $where, + $this->getEncryptedColumns() + ); + + $gehaltsbestandteile = array(); + if( null !== ($rows = getData($query)) ) + { + foreach( $rows as $row ) { + $tmpgb = new Gehaltsbestandteil(); + $tmpgb->hydrateByStdClass($row, true); + $gehaltsbestandteile[] = $tmpgb; + } + } + + return $gehaltsbestandteile; + } + + + public function getGehaltsbestandteil($id) + { + $this->addSelect('*'); + $query = $this->load($id, $this->getEncryptedColumns()); + $gehaltsbestandteil = null; + + if( null !== ($row = getData($query)) ) + { + $gehaltsbestandteil = new Gehaltsbestandteil(); + $gehaltsbestandteil->hydrateByStdClass($row[0], true); + } + + return $gehaltsbestandteil; + } +} diff --git a/application/models/vertragsbestandteil/IEncryption.php b/application/models/vertragsbestandteil/IEncryption.php new file mode 100644 index 000000000..ebfb437ea --- /dev/null +++ b/application/models/vertragsbestandteil/IEncryption.php @@ -0,0 +1,7 @@ +dbTable = 'hr.tbl_vertragsbestandteil_freitext'; + $this->pk = 'vertragsbestandteil_id'; + } + + public function countOverlappingVBFreitextsOfSameType(vertragsbestandteil\VertragsbestandteilFreitext $vbft) + { + $notselfclause = (intval($vbft->getVertragsbestandteil_id()) > 0) + ? 'AND v.vertragsbestandteil_id <> ' . $this->escape($vbft->getVertragsbestandteil_id()) + : ''; + $sql = <<= COALESCE(v.von, '1970-01-01'::date) + AND + ?::date <= COALESCE(v.bis, '2170-12-31') + {$notselfclause} +EOSQL; + $ret = $this->execReadOnlyQuery($sql, array( + $vbft->getDienstverhaeltnis_id(), + $vbft->getVertragsbestandteiltyp_kurzbz(), + $vbft->getFreitexttypKurzbz(), + $vbft->getBis(), + $vbft->getVon() + )); + + if( null === ($vbcount = getData($ret)) ) { + throw new Exception('failed to fetch overlappingvbs count'); + } + + return $vbcount[0]->overlappingvbs; + } +} diff --git a/application/models/vertragsbestandteil/VertragsbestandteilFreitexttyp_model.php b/application/models/vertragsbestandteil/VertragsbestandteilFreitexttyp_model.php new file mode 100644 index 000000000..09d2380b6 --- /dev/null +++ b/application/models/vertragsbestandteil/VertragsbestandteilFreitexttyp_model.php @@ -0,0 +1,12 @@ +dbTable = 'hr.tbl_vertragsbestandteil_freitexttyp'; + $this->pk = 'freitexttyp_kurzbz'; + } +} diff --git a/application/models/vertragsbestandteil/VertragsbestandteilFunktion_model.php b/application/models/vertragsbestandteil/VertragsbestandteilFunktion_model.php new file mode 100644 index 000000000..7263ac893 --- /dev/null +++ b/application/models/vertragsbestandteil/VertragsbestandteilFunktion_model.php @@ -0,0 +1,35 @@ +dbTable = 'hr.tbl_vertragsbestandteil_funktion'; + $this->pk = 'vertragsbestandteil_id'; + } + + public function isBenutzerfunktionAlreadyAttachedToAnotherVB($benutzerfunktion_id, $vertragsbestandteil_id) + { + $where = array('benutzerfunktion_id' => $benutzerfunktion_id); + if( intval($vertragsbestandteil_id) > 0 ) + { + $where['vertragsbestandteil_id != '] = $vertragsbestandteil_id; + } + $this->addSelect('count(*) AS vbscount'); + $res = $this->loadWhere($where); + if(isError($res)) + { + throw new Exception('failed to check if benutzerfunktionid is already attached to another vertragsbestanteil'); + } + $count = (getData($res))[0]->vbscount; + return $count > 0; + } +} diff --git a/application/models/vertragsbestandteil/VertragsbestandteilKarenz_model.php b/application/models/vertragsbestandteil/VertragsbestandteilKarenz_model.php new file mode 100644 index 000000000..525291439 --- /dev/null +++ b/application/models/vertragsbestandteil/VertragsbestandteilKarenz_model.php @@ -0,0 +1,14 @@ +dbTable = 'hr.tbl_vertragsbestandteil_karenz'; + $this->pk = 'vertragsbestandteil_id'; + } +} diff --git a/application/models/vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model.php b/application/models/vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model.php new file mode 100644 index 000000000..ccb02dd88 --- /dev/null +++ b/application/models/vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model.php @@ -0,0 +1,14 @@ +dbTable = 'hr.tbl_vertragsbestandteil_kuendigungsfrist'; + $this->pk = 'vertragsbestandteil_id'; + } +} diff --git a/application/models/vertragsbestandteil/VertragsbestandteilStunden_model.php b/application/models/vertragsbestandteil/VertragsbestandteilStunden_model.php new file mode 100644 index 000000000..569c9a601 --- /dev/null +++ b/application/models/vertragsbestandteil/VertragsbestandteilStunden_model.php @@ -0,0 +1,18 @@ +dbTable = 'hr.tbl_vertragsbestandteil_stunden'; + $this->pk = 'vertragsbestandteil_id'; + } +} diff --git a/application/models/vertragsbestandteil/VertragsbestandteilTyp_model.php b/application/models/vertragsbestandteil/VertragsbestandteilTyp_model.php new file mode 100644 index 000000000..f64cb70f4 --- /dev/null +++ b/application/models/vertragsbestandteil/VertragsbestandteilTyp_model.php @@ -0,0 +1,12 @@ +dbTable = 'hr.tbl_vertragsbestandteiltyp'; + $this->pk = 'vertragsbestandteiltyp_kurzbz'; + } +} diff --git a/application/models/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model.php b/application/models/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model.php new file mode 100644 index 000000000..561ed2932 --- /dev/null +++ b/application/models/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model.php @@ -0,0 +1,11 @@ +dbTable = 'hr.tbl_vertragsbestandteil_urlaubsanspruch'; + $this->pk = 'vertragsbestandteil_id'; + } +} diff --git a/application/models/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model.php b/application/models/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model.php new file mode 100644 index 000000000..8e2d45e1a --- /dev/null +++ b/application/models/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model.php @@ -0,0 +1,12 @@ +dbTable = 'hr.tbl_vertragsbestandteil_zeitaufzeichnung'; + $this->pk = 'vertragsbestandteil_id'; + } +} diff --git a/application/models/vertragsbestandteil/Vertragsbestandteil_model.php b/application/models/vertragsbestandteil/Vertragsbestandteil_model.php new file mode 100644 index 000000000..6d8c18859 --- /dev/null +++ b/application/models/vertragsbestandteil/Vertragsbestandteil_model.php @@ -0,0 +1,181 @@ +dbTable = 'hr.tbl_vertragsbestandteil'; + $this->pk = 'vertragsbestandteil_id'; + } + + protected function getVertragsbestandteilSQL() + { + $sql = <<escape($date) + . ' BETWEEN COALESCE(v.von, \'1970-01-01\'::date)' + . ' AND COALESCE(v.bis, \'2170-01-01\'::date)'; + if( $includefuture ) + { + $stichtagclause .= ' OR COALESCE(v.von, \'1970-01-01\'::date) > ' + . $this->escape($date); + } + $stichtagclause .= ')'; + } + + $sql = <<getVertragsbestandteilSQL()} + WHERE + v.dienstverhaeltnis_id = {$this->escape($dienstverhaeltnis_id)} + {$stichtagclause} + ; +EOSQL; + + // echo $sql . "\n\n"; + $query = $this->execReadOnlyQuery($sql); // TODO add decryption + $data = getData($query); + + if ($data == null) + { + return array(); + } + + $vertragsbestandteile = array(); + foreach( $data as $row ) { + try + { + $vertragsbestandteile[] = VertragsbestandteilFactory::getVertragsbestandteil($row, true); + } + catch (Exception $ex) + { + echo $ex->getMessage() . "\n"; + } + } + + $dummy = json_encode($vertragsbestandteile); + return $vertragsbestandteile; + } + + + public function getVertragsbestandteil($id) + { + + $sql = <<getVertragsbestandteilSQL()} + WHERE + v.vertragsbestandteil_id = {$this->escape($id)} + ; +EOSQL; + + $query = $this->execReadOnlyQuery($sql); + + $vertragsbestandteil = null; + + if( hasData($query) ) + { + $data = getData($query)[0]; + try + { + $vertragsbestandteil = VertragsbestandteilFactory::getVertragsbestandteil($data, true); // TODO add decryption + } + catch (Exception $ex) + { + echo $ex->getMessage() . "\n"; + } + } + + return $vertragsbestandteil; + + } + + public function countOverlappingVBsOfSameType(vertragsbestandteil\Vertragsbestandteil $vb) + { + $notselfclause = (intval($vb->getVertragsbestandteil_id()) > 0) + ? 'AND v.vertragsbestandteil_id <> ' . $this->escape($vb->getVertragsbestandteil_id()) + : ''; + $sql = <<= COALESCE(v.von, '1970-01-01'::date) + AND + ?::date <= COALESCE(v.bis, '2170-12-31') + {$notselfclause} +EOSQL; + $ret = $this->execReadOnlyQuery($sql, array( + $vb->getDienstverhaeltnis_id(), + $vb->getVertragsbestandteiltyp_kurzbz(), + $vb->getBis(), + $vb->getVon() + )); + + if( null === ($vbcount = getData($ret)) ) { + throw new Exception('failed to fetch overlappingvbs count'); + } + + return $vbcount[0]->overlappingvbs; + } +} diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php new file mode 100644 index 000000000..2d0d22346 --- /dev/null +++ b/application/views/Studentenverwaltung.php @@ -0,0 +1,55 @@ + 'Studentenverwaltung', + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'vue3' => true, + 'primevue3' => true, + #'filtercomponent' => true, + 'tabulator5' => true, + 'tinymce5' => true, + 'phrases' => array( + 'global', + 'ui', + 'notiz', + ), + 'customCSSs' => [ + 'public/css/components/vue-datepicker.css', + 'public/css/components/primevue.css', + 'public/css/Studentenverwaltung.css' + ], + 'customJSs' => [ + #'vendor/npm-asset/primevue/tree/tree.min.js', + #'vendor/npm-asset/primevue/toast/toast.min.js' + ], + 'customJSModules' => [ + 'public/js/apps/Studentenverwaltung.js' + ] + ); + + $this->load->view('templates/FHC-Header', $includesArray); +?> + + !defined('GENERATE_ALIAS_STUDENT') ? true : GENERATE_ALIAS_STUDENT, + 'showZgvDoktor' => !defined('ZGV_DOKTOR_ANZEIGEN') ? false : ZGV_DOKTOR_ANZEIGEN, + 'showZgvErfuellt' => !defined('ZGV_ERFUELLT_ANZEIGEN') ? false : ZGV_ERFUELLT_ANZEIGEN +]; +?> + +
+ + +
+ +load->view('templates/FHC-Footer', $includesArray); ?> + diff --git a/application/views/codex/bismeldestichtag.php b/application/views/codex/bismeldestichtag.php new file mode 100644 index 000000000..37af16cc6 --- /dev/null +++ b/application/views/codex/bismeldestichtag.php @@ -0,0 +1,75 @@ + 'Bismeldestichtage', + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'vue3' => true, + 'filtercomponent' => true, + 'navigationcomponent' => true, + 'tabulator5' => true, + 'customCSSs' => array('vendor/vuejs/vuedatepicker_css/main.css'), + 'customJSs' => array('vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js'), + 'customJSModules' => array('public/js/apps/Bismeldestichtag/Bismeldestichtag.js') + ); + + $this->load->view('templates/FHC-Header', $includesArray); +?> +
+ + + + + + + + +
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+
+ + +
+
+
+
+ +load->view('templates/FHC-Footer', $includesArray); ?> diff --git a/application/views/codex/uhstat1.php b/application/views/codex/uhstat1.php index a09f9c70a..a255781f1 100644 --- a/application/views/codex/uhstat1.php +++ b/application/views/codex/uhstat1.php @@ -47,6 +47,9 @@ $saved = isset($saved) && $saved === true;

p->t('uhstat', 'uhstat1AnmeldungEinleitungstext') ?>

+

+ p->t('uhstat', 'uhstat1EinleitungSvnrtext') ?> +


@@ -71,16 +74,23 @@ $saved = isset($saved) && $saved === true;
- +
+ + + + +
@@ -91,16 +101,23 @@ $saved = isset($saved) && $saved === true; p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
- +
+ + + + +
@@ -111,16 +128,23 @@ $saved = isset($saved) && $saved === true; p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
- +
+ + + + +
@@ -158,16 +182,23 @@ $saved = isset($saved) && $saved === true;
- > + + $jahr): ?> + - - + + + + + +
@@ -178,16 +209,23 @@ $saved = isset($saved) && $saved === true; p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
- +
+ + + + +
@@ -198,16 +236,23 @@ $saved = isset($saved) && $saved === true; p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
- +
+ + + + +
@@ -268,7 +313,7 @@ $saved = isset($saved) && $saved === true; - - + + load->view('templates/FHC-Footer'); ?> diff --git a/application/views/errors/json/html/error_404.php b/application/views/errors/json/html/error_404.php new file mode 100644 index 000000000..0caade2b1 --- /dev/null +++ b/application/views/errors/json/html/error_404.php @@ -0,0 +1,65 @@ + + + + +404 Page Not Found + + + +
+

+ +
+ + diff --git a/application/views/errors/json/html/error_db.php b/application/views/errors/json/html/error_db.php new file mode 100644 index 000000000..dce6a7572 --- /dev/null +++ b/application/views/errors/json/html/error_db.php @@ -0,0 +1,49 @@ +

', $msg); + +$msgs = []; + +$error = [ + 'heading' => $heading +]; + +/** NOTE(chris): extract Error Number and SQL + * @see: DB_driver.php:692 + */ +if (substr(current($msg), 0, 14) == 'Error Number: ') { + $code = substr(array_shift($msg), 14); + if ($code) + $error['code'] = (int)$code; + $msgs[] = array_shift($msg); + $error['sql'] = array_shift($msg); +} + +/** NOTE(chris): extract Line Number and Filename + * @see: DB_driver.php:1782 + * @see: DB_driver.php:1783 + */ +if (count($msg) >= 2) { + if (substr(end($msg), 0, 13) == 'Line Number: ' && substr(prev($msg), 0, 10) == 'Filename: ') { + $error['line'] = (int)substr(array_pop($msg), 13); + $error['filename'] = substr(array_pop($msg), 10); + } +} + +foreach ($msg as $m) + $msgs[] = $m; + + +if (count($msgs) == 1) + $error['message'] = current($msgs); +else + $error['messages'] = $msgs; + +$g_result->addError($error, FHCAPI_Controller::ERROR_TYPE_DB); +$g_result->setStatus(FHCAPI_Controller::STATUS_ERROR); diff --git a/application/views/errors/json/html/error_exception.php b/application/views/errors/json/html/error_exception.php new file mode 100644 index 000000000..7984bd13e --- /dev/null +++ b/application/views/errors/json/html/error_exception.php @@ -0,0 +1,27 @@ + $message, + 'class' => get_class($exception), + 'filename' => $exception->getFile(), + 'line' => $exception->getLine() +]; + +if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === true) { + $error['backtrace'] = []; + foreach (debug_backtrace() as $err) { + if (isset($err['file']) && strpos($err['file'], realpath(BASEPATH)) !== 0) { + $error['backtrace'][] = [ + 'file' => $err['file'], + 'line' => $err['line'], + 'function' => $err['function'] + ]; + } + } +} + +$g_result->addError($error, FHCAPI_Controller::ERROR_TYPE_EXCEPTION); +$g_result->setStatus(FHCAPI_Controller::STATUS_ERROR); diff --git a/application/views/errors/json/html/error_general.php b/application/views/errors/json/html/error_general.php new file mode 100644 index 000000000..e69494463 --- /dev/null +++ b/application/views/errors/json/html/error_general.php @@ -0,0 +1,20 @@ +

', $msg); + +$error = [ + 'heading' => $heading +]; +if (count($msg) == 1) + $error['message'] = current($msg); +else + $error['messages'] = $msg; + +$g_result->addError($error, FHCAPI_Controller::ERROR_TYPE_GENERAL); +$g_result->setStatus(FHCAPI_Controller::STATUS_ERROR); diff --git a/application/views/errors/json/html/error_php.php b/application/views/errors/json/html/error_php.php new file mode 100644 index 000000000..91f2abf3c --- /dev/null +++ b/application/views/errors/json/html/error_php.php @@ -0,0 +1,31 @@ + $message, + 'severity' => $severity, + 'filename' => $filepath, + 'line' => $line +]; + +if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === true) { + $error['backtrace'] = []; + foreach (debug_backtrace() as $err) { + if (isset($err['file']) && strpos($err['file'], realpath(BASEPATH)) !== 0) { + $error['backtrace'][] = [ + 'file' => $err['file'], + 'line' => $err['line'], + 'function' => $err['function'] + ]; + } + } +} + +// TODO(chris): change type with severity +$g_result->addError($error, 'php'); + +if (((E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity) { + $g_result->setStatus('error'); +} diff --git a/application/views/lehre/Antrag/Create.php b/application/views/lehre/Antrag/Create.php new file mode 100644 index 000000000..7e8bda874 --- /dev/null +++ b/application/views/lehre/Antrag/Create.php @@ -0,0 +1,55 @@ + 'Antrag auf Änderung des Studierendenstatus', + 'cis' => true, + 'vue3' => true, + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'phrases' => array( + ), + 'customJSModules' => array('public/js/apps/lehre/Antrag.js'), + 'customCSSs' => array( + 'public/css/Fhc.css', + 'public/css/components/primevue.css', + 'vendor/vuejs/vuedatepicker_css/main.css' + ), + 'customJSs' => array( + ) +); + +$this->load->view( + 'templates/FHC-Header', + $sitesettings +); +?> + +

+
+

p->t('studierendenantrag', 'antrag_header'); ?>

+
+ +
+
+ + +
+
+ + +
+
+
+ +load->view( + 'templates/FHC-Footer', + $sitesettings +); \ No newline at end of file diff --git a/application/views/lehre/Antrag/Leitung/List.php b/application/views/lehre/Antrag/Leitung/List.php new file mode 100644 index 000000000..1225b16b6 --- /dev/null +++ b/application/views/lehre/Antrag/Leitung/List.php @@ -0,0 +1,60 @@ + 'Anträge auf Änderung des Studierendenstatus', + 'cis' => true, + 'vue3' => true, + 'axios027' => true, + 'bootstrap5' => true, + 'tabulator5' => true, + 'fontawesome6' => true, + 'primevue3' => true, + 'phrases' => array( + 'global', + 'ui', + 'studierendenantrag', + 'lehre', + 'person', + ), + 'customJSModules' => array('public/js/apps/lehre/Antrag/Leitung.js'), + 'customCSSs' => array( + 'public/css/Fhc.css', + 'public/css/components/primevue.css', + ), + 'customJSs' => array( + ) +); + +$this->load->view( + 'templates/FHC-Header', + $sitesettings +); +?> + +
+
+

p->t('studierendenantrag', 'antrag_header'); ?>

+
+ +
+
+ + + + +
+
+
+
+
+ +load->view( + 'templates/FHC-Footer', + $sitesettings +); diff --git a/application/views/lehre/Antrag/Student/List.php b/application/views/lehre/Antrag/Student/List.php new file mode 100644 index 000000000..4a4b4f064 --- /dev/null +++ b/application/views/lehre/Antrag/Student/List.php @@ -0,0 +1,227 @@ + 'Antrag auf Änderung des Studierendenstatus', + 'cis' => true, + 'vue3' => true, + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'phrases' => array( + ), + 'customJSModules' => array('public/js/apps/lehre/Antrag/Student.js'), + 'customCSSs' => array( + 'public/css/Fhc.css', + 'public/css/components/primevue.css', + ), + 'customJSs' => array( + ) +); + +$this->load->view( + 'templates/FHC-Header', + $sitesettings +); +?> + +
+ +
+

p->t('studierendenantrag', 'antrag_header'); ?>

+
+ +
+
+ + $array){ ?> +

()

+ + +
+

p->t('studierendenantrag', 'calltoaction_' . $type); ?>

+
+ + p->t('studierendenantrag', 'antrag_typ_' . $type); ?> + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#p->t('studierendenantrag', 'antrag_typ'); ?>p->t('studierendenantrag', 'antrag_status'); ?>p->t('studierendenantrag', 'antrag_studiensemester'); ?>p->t('studierendenantrag', 'antrag_erstelldatum'); ?>p->t('studierendenantrag', 'antrag_datum_wiedereinstieg'); ?>p->t('studierendenantrag', 'antrag_grund'); ?>p->t('studierendenantrag', 'antrag_dateianhaenge'); ?> 
studierendenantrag_id; ?>p->t('studierendenantrag', 'antrag_typ_' . $antrag->typ); ?> + status == Studierendenantragstatus_model::STATUS_PAUSE + && $antrag->status_insertvon == Studierendenantragstatus_model::INSERTVON_DEREGISTERED + ) + ? $this->p->t('studierendenantrag', 'status_stop') + : $antrag->status_bezeichnung; + ?> + studiensemester_kurzbz; ?>datum))->format('d.m.Y'); ?>datum_wiedereinstieg ? (new DateTime($antrag->datum_wiedereinstieg))->format('d.m.Y') : ''; ?> + grund){ ?> + + p->t('studierendenantrag', 'antrag_grund'); ?> + + + + + + + dms_id) {?> + + p->t('studierendenantrag', 'antrag_anhang'); ?> + + + + + + + typ) { + case Studierendenantrag_model::TYP_ABMELDUNG: + $allowed = [ + Studierendenantragstatus_model::STATUS_APPROVED + ]; + break; + case Studierendenantrag_model::TYP_ABMELDUNG_STGL: + $allowed = [ + Studierendenantragstatus_model::STATUS_OBJECTION_DENIED, + Studierendenantragstatus_model::STATUS_DEREGISTERED + ]; + break; + case Studierendenantrag_model::TYP_UNTERBRECHUNG: + $allowed = [ + Studierendenantragstatus_model::STATUS_APPROVED, + Studierendenantragstatus_model::STATUS_REMINDERSENT + ]; + break; + case Studierendenantrag_model::TYP_WIEDERHOLUNG: + $allowed = [ + Studierendenantragstatus_model::STATUS_DEREGISTERED + ]; + break; + } + if (in_array($antrag->status, $allowed)) { ?> + + + + + + typ == Studierendenantrag_model::TYP_WIEDERHOLUNG + && $antrag->status == Studierendenantragstatus_model::STATUS_APPROVED + ) { ?> + + p->t('studierendenantrag', 'btn_show_lvs'); ?> + + + p->t('studierendenantrag', 'my_lvs'); ?> + + +
+ + + + +
+
+
+
+
+ +load->view( + 'templates/FHC-Footer', + $sitesettings +); diff --git a/application/views/lehre/Antrag/Wiederholung/Student.php b/application/views/lehre/Antrag/Wiederholung/Student.php new file mode 100644 index 000000000..2171d6928 --- /dev/null +++ b/application/views/lehre/Antrag/Wiederholung/Student.php @@ -0,0 +1,43 @@ + 'Antrag Wiederholung vom Studium', + 'cis' => true, + 'vue3' => true, + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'tabulator5' => true, + 'phrases' => array( + 'ui', + 'lehre', + 'global' + ), + 'customJSModules' => array('public/js/apps/lehre/Antrag/Lvzuweisung.js'), + 'customCSSs' => array( + 'public/css/Fhc.css', + 'public/css/components/primevue.css', + ), + 'customJSs' => array( + ) +); + +$this->load->view( + 'templates/FHC-Header', + $sitesettings +); +?> + +
+
+

p->t('studierendenantrag', 'title_lvzuweisen', ['name' => $antrag->name]);?>

+
+
+ status != Studierendenantragstatus_model::STATUS_CREATED && $antrag->status != Studierendenantragstatus_model::STATUS_LVSASSIGNED) ? ' disabled' : ''; ?>> +
+
+ +load->view( + 'templates/FHC-Footer', + $sitesettings +); diff --git a/application/views/lehre/Antrag/Wiederholung/getLvs.rdf.php b/application/views/lehre/Antrag/Wiederholung/getLvs.rdf.php new file mode 100644 index 000000000..24eb1e23f --- /dev/null +++ b/application/views/lehre/Antrag/Wiederholung/getLvs.rdf.php @@ -0,0 +1,31 @@ + + + + + + freigabedatum); ?> + insertamum); ?> + + + studierendenantrag_lehrveranstaltung_id; ?>]]> + lehrveranstaltung_id; ?>]]> + prestudent_id; ?>]]> + insertvon; ?>]]> + studiensemester_kurzbz; ?>]]> + note; ?>]]> + format('c'); ?>]]> + format('d.m.Y'); ?>]]> + format('c'); ?>]]> + format('d.m.Y'); ?>]]> + note_bezeichnung; ?>]]> + lv_bezeichnung; ?>]]> + stg_bezeichnung; ?>]]> + + + + + + diff --git a/application/views/lehre/Antrag/Wiederholung/moveLvs.rdf.php b/application/views/lehre/Antrag/Wiederholung/moveLvs.rdf.php new file mode 100644 index 000000000..4ed31218d --- /dev/null +++ b/application/views/lehre/Antrag/Wiederholung/moveLvs.rdf.php @@ -0,0 +1,17 @@ + + + + + + + ]]> + + + + + + diff --git a/application/views/lehre/anrechnung/approveAnrechnungDetail.php b/application/views/lehre/anrechnung/approveAnrechnungDetail.php index 0970b6edd..c96631781 100644 --- a/application/views/lehre/anrechnung/approveAnrechnungDetail.php +++ b/application/views/lehre/anrechnung/approveAnrechnungDetail.php @@ -1,4 +1,5 @@ load->config('anrechnung'); $this->load->view( 'templates/FHC-Header', array( @@ -172,14 +173,16 @@ $this->load->view( p->t('global', 'begruendung'); ?> begruendung ?> - - p->t('anrechnung', 'begruendungEctsLabel'); ?> - begruendung_ects ?> - - - p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> - begruendung_lvinhalt ?> - + config->item('explain_equivalence')): ?> + + p->t('anrechnung', 'begruendungEctsLabel'); ?> + begruendung_ects ?> + + + p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> + begruendung_lvinhalt ?> + + diff --git a/application/views/lehre/anrechnung/requestAnrechnung.php b/application/views/lehre/anrechnung/requestAnrechnung.php index 18fd66a67..bb3c48235 100644 --- a/application/views/lehre/anrechnung/requestAnrechnung.php +++ b/application/views/lehre/anrechnung/requestAnrechnung.php @@ -4,6 +4,7 @@ const CHAR_LENGTH150 = 150; const CHAR_LENGTH500 = 500; const CHAR_LENGTH1000 = 1000; +$this->load->config('anrechnung'); $this->load->view( 'templates/FHC-Header', array( @@ -200,27 +201,29 @@ $this->load->view( - -
-
-
-
- p->t('anrechnung', 'begruendungEcts'); ?>  - - - -
-
- - p->t('ui', 'maxZeichen'); ?> : + + config->item('explain_equivalence')): ?> + +
+
+
+
+ p->t('anrechnung', 'begruendungEcts'); ?>  + + + +
+
+ + p->t('ui', 'maxZeichen'); ?> : +
-
- -
+ +
@@ -240,6 +243,8 @@ $this->load->view(
+ +
diff --git a/application/views/lehre/anrechnung/reviewAnrechnungDetail.php b/application/views/lehre/anrechnung/reviewAnrechnungDetail.php index 08d23d8c4..98fee67a3 100644 --- a/application/views/lehre/anrechnung/reviewAnrechnungDetail.php +++ b/application/views/lehre/anrechnung/reviewAnrechnungDetail.php @@ -1,4 +1,5 @@ load->config('anrechnung'); $this->load->view( 'templates/FHC-Header', array( @@ -143,14 +144,16 @@ $this->load->view( target="_blank">dokumentname) ?> - - p->t('anrechnung', 'begruendungEctsLabel'); ?> - begruendung_ects ?> - - - p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> - begruendung_lvinhalt ?> - + config->item('explain_equivalence')): ?> + + p->t('anrechnung', 'begruendungEctsLabel'); ?> + begruendung_ects ?> + + + p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> + begruendung_lvinhalt ?> + + diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftrag.php b/application/views/lehre/lehrauftrag/acceptLehrauftrag.php index d018beda8..6c65559d9 100644 --- a/application/views/lehre/lehrauftrag/acceptLehrauftrag.php +++ b/application/views/lehre/lehrauftrag/acceptLehrauftrag.php @@ -142,14 +142,17 @@ $this->load->view(
- +
- p->t('dms' , 'informationsblattExterneLehrende'); ?> + p->t('ui' , 'hinweistextLehrauftrag'); ?> + + p->t('dms' , 'informationsblattExterneLehrende'); ?> +

- +
diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php index 92c896ce7..fcd9b953c 100644 --- a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php @@ -142,7 +142,7 @@ FROM WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung) ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung) END AS "lv_oe_kurzbz", - TRUNC(lema.semesterstunden, 1) AS "stunden", + TRUNC(lema.semesterstunden, 2) AS "stunden", TRUNC((lema.semesterstunden * lema.stundensatz), 2) AS "betrag", vertrag_id, vertragsstunden AS "vertrag_stunden", @@ -232,7 +232,7 @@ FROM SELECT pa.lehreinheit_id, lv.lehrveranstaltung_id, - pa.projektarbeit_id AS "projektarbeit_id", + pa.projektarbeit_id::text AS "projektarbeit_id", le.studiensemester_kurzbz, stg.studiengang_kz, upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz", @@ -375,9 +375,9 @@ $filterWidgetArray = array( orgform_kurzbz: {visible: false, headerFilter:"input"}, person_id: {visible: false, headerFilter:"input"}, lv_oe_kurzbz: {visible: false, headerFilter:"input"}, - stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:2}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, - bottomCalc:"sum", bottomCalcParams:{precision:1} + bottomCalc:"sum", bottomCalcParams:{precision:2} }, betrag: {align:"right", formatter: form_formatNulltoStringNumber, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, diff --git a/application/views/lehre/lehrauftrag/approveLehrauftragData.php b/application/views/lehre/lehrauftrag/approveLehrauftragData.php index 0414ddbf6..4f0c61193 100644 --- a/application/views/lehre/lehrauftrag/approveLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/approveLehrauftragData.php @@ -149,7 +149,7 @@ FROM ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung) END AS "lv_oe_kurzbz", (person.nachname || \' \' || person.vorname) AS "lektor", - TRUNC(lema.semesterstunden, 1) AS "stunden", + TRUNC(lema.semesterstunden, 2) AS "stunden", lema.stundensatz, TRUNC((lema.semesterstunden * lema.stundensatz), 2) AS "betrag", vertrag_id, @@ -400,9 +400,9 @@ $filterWidgetArray = array( person_id: {visible: false, headerFilter:"input"}, lv_oe_kurzbz: {visible: false, headerFilter:"input"}, lektor: {headerFilter:"input", widthGrow: 2}, - stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:2}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, - bottomCalc:"sum", bottomCalcParams:{precision:1}}, + bottomCalc:"sum", bottomCalcParams:{precision:2}}, stundensatz: {visible: true, align:"right", formatter: form_formatNulltoStringNumber, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator}, betrag: {align:"right", formatter: form_formatNulltoStringNumber, diff --git a/application/views/lehre/lehrauftrag/orderLehrauftragData.php b/application/views/lehre/lehrauftrag/orderLehrauftragData.php index 5a2ad98bd..85b663d4a 100644 --- a/application/views/lehre/lehrauftrag/orderLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/orderLehrauftragData.php @@ -159,7 +159,7 @@ FROM ( SELECT /* lehrauftraege also planned with dummies, therefore personalnummer is needed */ - ma.personalnummer, + ma.personalnummer::text, lema.lehreinheit_id, lv.lehrveranstaltung_id, lv.bezeichnung AS "lv_bezeichnung", @@ -179,7 +179,7 @@ FROM ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung) END AS "lv_oe_kurzbz", (person.nachname || \' \' || person.vorname) AS "lektor", - TRUNC(lema.semesterstunden, 1) AS "stunden", + TRUNC(lema.semesterstunden, 2) AS "stunden", lema.stundensatz, TRUNC((lema.semesterstunden * lema.stundensatz), 2) AS "betrag", vertrag_id, @@ -219,7 +219,7 @@ FROM (SELECT uid FROM - public.tbl_benutzer JOIN public.tbl_mitarbeiter ma + public.tbl_benutzer JOIN public.tbl_mitarbeiter ma ON tbl_benutzer.uid = ma.mitarbeiter_uid WHERE person_id = tmp_projektbetreuung.person_id @@ -272,7 +272,7 @@ FROM pa.lehreinheit_id, lv.lehrveranstaltung_id, lv.bezeichnung AS "lv_bezeichnung", - pa.projektarbeit_id AS "projektarbeit_id", + pa.projektarbeit_id::text AS "projektarbeit_id", le.studiensemester_kurzbz, stg.studiengang_kz, upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz", @@ -414,7 +414,7 @@ $filterWidgetArray = array( row_index: {visible: false}, personalnummer: {visible: false, headerFilter:"input"}, auftrag: { - headerFilter:"input", widthGrow: 2, + headerFilter:"input", widthGrow: 2, bottomCalc:"count", bottomCalcFormatter:function(cell){return "'. ucfirst($this->p->t('global', 'anzahl')). ': " + cell.getValue();} }, stg_typ_kurzbz: {headerFilter:"input"}, @@ -432,9 +432,9 @@ $filterWidgetArray = array( person_id: {visible: false, headerFilter:"input"}, lv_oe_kurzbz: {headerFilter:"input"}, lektor: {headerFilter:"input", widthGrow: 2}, - stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:2}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, - bottomCalc:"sum", bottomCalcParams:{precision:1}}, + bottomCalc:"sum", bottomCalcParams:{precision:2}}, stundensatz: {visible: true, align:"right", formatter: form_formatNulltoStringNumber, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator}, betrag: {align:"right", formatter: form_formatNulltoStringNumber, diff --git a/application/views/lehre/lvplanung/lvTemplateUebersicht.php b/application/views/lehre/lvplanung/lvTemplateUebersicht.php new file mode 100644 index 000000000..5c873486c --- /dev/null +++ b/application/views/lehre/lvplanung/lvTemplateUebersicht.php @@ -0,0 +1,29 @@ + 'LV Template Übersicht', + 'vue3' => true, + 'axios027' => true, + 'bootstrap5' => true, + 'tabulator5' => true, + 'fontawesome6' => true, + 'primevue3' => true, + 'navigationcomponent' => true, + 'filtercomponent' => true, + 'customJSModules' => array('public/js/apps/lehre/lvplanung/LvTemplates.js'), + 'customCSSs' => array( + 'public/css/Fhc.css', + 'public/css/lvTemplateUebersicht.css' + ) +); + +$this->load->view('templates/FHC-Header', $includesArray); +?> + +
+ + + + +
+ +load->view('templates/FHC-Footer', $includesArray); ?> diff --git a/application/views/person/bpk/bpkDetails.php b/application/views/person/bpk/bpkDetails.php index 198065c24..bd6191c6a 100644 --- a/application/views/person/bpk/bpkDetails.php +++ b/application/views/person/bpk/bpkDetails.php @@ -9,7 +9,6 @@ 'jqueryui1' => true, 'ajaxlib' => true, 'tablesorter2' => true, - 'tinymce4' => true, 'sbadmintemplate3' => true, 'addons' => true, 'navigationwidget' => true, @@ -126,10 +125,18 @@
-
+ - +
diff --git a/application/views/system/infocenter/infocenterAbgewiesenData.php b/application/views/system/infocenter/infocenterAbgewiesenData.php index 2307ea87e..da816b2c7 100644 --- a/application/views/system/infocenter/infocenterAbgewiesenData.php +++ b/application/views/system/infocenter/infocenterAbgewiesenData.php @@ -31,21 +31,35 @@ $query = ' ORDER BY l.log_id DESC LIMIT 1 ) - AND '. $LOGDATA_VON .' = ( + AND ('. $LOGDATA_VON .' = ( SELECT l.insertvon FROM system.tbl_log l WHERE l.person_id = p.person_id ORDER BY l.log_id DESC LIMIT 1 ) + OR + ( + ( + SELECT l.insertvon + FROM system.tbl_log l + WHERE l.person_id = p.person_id + ORDER BY l.log_id DESC + LIMIT 1 + ) IS NULL + ) + ) AND l.zeitpunkt >= pss.insertamum ORDER BY l.log_id DESC LIMIT 1 ) AS "Nachricht", ( - SELECT SUM(konto.betrag) + SELECT + CASE + WHEN COUNT(CASE WHEN konto.betrag != 0 THEN 1 END) = 0 THEN null + ELSE SUM(konto.betrag) + END AS "Kaution" FROM public.tbl_konto konto - LEFT JOIN tbl_konto skonto ON (skonto.buchungsnr_verweis = konto.buchungsnr) WHERE konto.person_id = p.person_id AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .' AND konto.buchungstyp_kurzbz = '. $STUDIENGEBUEHR_ANZAHLUNG .' diff --git a/application/views/system/infocenter/infocenterData.php b/application/views/system/infocenter/infocenterData.php index bb5b84479..61dc5a575 100644 --- a/application/views/system/infocenter/infocenterData.php +++ b/application/views/system/infocenter/infocenterData.php @@ -292,9 +292,12 @@ rueck.datum_bis AS "HoldDate", rueck.bezeichnung AS "Rueckstellgrund", ( - SELECT SUM(konto.betrag) + SELECT + CASE + WHEN COUNT(CASE WHEN konto.betrag != 0 THEN 1 END) = 0 THEN null + ELSE SUM(konto.betrag) + END AS "Kaution" FROM public.tbl_konto konto - LEFT JOIN tbl_konto skonto ON (skonto.buchungsnr_verweis = konto.buchungsnr) WHERE konto.person_id = p.person_id AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .' AND konto.buchungstyp_kurzbz = '. $STUDIENGEBUEHR_ANZAHLUNG .' diff --git a/application/views/system/infocenter/infocenterDetails.php b/application/views/system/infocenter/infocenterDetails.php index c61bb3cd2..51b913b6c 100644 --- a/application/views/system/infocenter/infocenterDetails.php +++ b/application/views/system/infocenter/infocenterDetails.php @@ -8,7 +8,7 @@ 'dialoglib' => true, 'ajaxlib' => true, 'tablesorter2' => true, - 'tinymce4' => true, + 'tinymce5' => true, 'sbadmintemplate3' => true, 'addons' => true, 'navigationwidget' => true, @@ -27,7 +27,8 @@ 'public/js/infocenter/rueckstellung.js', 'public/js/infocenter/zgvUeberpruefung.js', 'public/js/infocenter/docUeberpruefung.js', - 'public/js/infocenter/stammdaten.js' + 'public/js/infocenter/stammdaten.js', + 'public/js/infocenter/personcheck.js' ), 'phrases' => array( 'infocenter', @@ -38,6 +39,14 @@ $this->load->view('templates/FHC-Header', $includesArray); ?> + + +
widgetlib->widget('NavigationWidget'); ?> @@ -74,22 +83,8 @@
- -
-

- p->t('global', 'bewerberVorhanden') . ':'; ?> -

-
- person_id . '
'; - } - ?> -
- -
- +
+ load->view('system/infocenter/personCheck.php', array('unruly' => $unruly, 'duplicate' => $duplicate)); ?>
@@ -201,5 +196,4 @@
-load->view('templates/FHC-Footer', $includesArray); ?> - +load->view('templates/FHC-Footer', $includesArray); ?> \ No newline at end of file diff --git a/application/views/system/infocenter/infocenterFreigegebenData.php b/application/views/system/infocenter/infocenterFreigegebenData.php index 32315c145..8003b42e0 100644 --- a/application/views/system/infocenter/infocenterFreigegebenData.php +++ b/application/views/system/infocenter/infocenterFreigegebenData.php @@ -267,9 +267,12 @@ $query = ' LIMIT 1 ) AS "AktenId", ( - SELECT SUM(konto.betrag) + SELECT + CASE + WHEN COUNT(CASE WHEN konto.betrag != 0 THEN 1 END) = 0 THEN null + ELSE SUM(konto.betrag) + END AS "Kaution" FROM public.tbl_konto konto - LEFT JOIN tbl_konto skonto ON (skonto.buchungsnr_verweis = konto.buchungsnr) WHERE konto.person_id = p.person_id AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .' AND konto.buchungstyp_kurzbz = '. $STUDIENGEBUEHR_ANZAHLUNG .' diff --git a/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php b/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php index e6b6d2495..7f9ee1288 100644 --- a/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php +++ b/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php @@ -198,7 +198,11 @@ $query = ' LIMIT 1 ) AS "InfoCenterMitarbeiter", ( - SELECT SUM(konto.betrag) + SELECT + CASE + WHEN COUNT(CASE WHEN konto.betrag != 0 THEN 1 END) = 0 THEN null + ELSE SUM(konto.betrag) + END AS "Kaution" FROM public.tbl_konto konto WHERE konto.person_id = p.person_id AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .' diff --git a/application/views/system/infocenter/infocenterZgvDetails.php b/application/views/system/infocenter/infocenterZgvDetails.php index 7636647ab..aefd95da0 100644 --- a/application/views/system/infocenter/infocenterZgvDetails.php +++ b/application/views/system/infocenter/infocenterZgvDetails.php @@ -10,7 +10,7 @@ 'dialoglib' => true, 'ajaxlib' => true, 'tablesorter2' => true, - 'tinymce4' => true, + 'tinymce5' => true, 'sbadmintemplate3' => true, 'addons' => true, 'navigationwidget' => true, @@ -131,7 +131,11 @@ p->t('infocenter', 'zgvNichtErfuellt') ?> - diff --git a/application/views/system/infocenter/personCheck.php b/application/views/system/infocenter/personCheck.php new file mode 100644 index 000000000..d24d26419 --- /dev/null +++ b/application/views/system/infocenter/personCheck.php @@ -0,0 +1,34 @@ + + + + \ No newline at end of file diff --git a/application/views/system/infocenter/zgvpruefungen.php b/application/views/system/infocenter/zgvpruefungen.php index 1d26b9d55..b021379a8 100644 --- a/application/views/system/infocenter/zgvpruefungen.php +++ b/application/views/system/infocenter/zgvpruefungen.php @@ -447,7 +447,6 @@
diff --git a/application/views/system/logs/testSearch.php b/application/views/system/logs/testSearch.php index 882b953f5..57ed0d48a 100644 --- a/application/views/system/logs/testSearch.php +++ b/application/views/system/logs/testSearch.php @@ -1,13 +1,12 @@ 'Test Search', - 'jquery3' => true, 'bootstrap5' => true, 'fontawesome6' => true, - 'tablesorter2' => true, + 'tabulator5' => true, + 'primevue3' => true, + 'axios027' => true, 'vue3' => true, - 'ajaxlib' => true, - 'jqueryui1' => true, 'filtercomponent' => true, 'navigationcomponent' => true, 'phrases' => array( @@ -17,8 +16,8 @@ 'customCSSs' => array( 'public/css/components/verticalsplit.css', 'public/css/components/searchbar.css', + 'public/css/components/primevue.css', ), - 'customJSs' => array('vendor/axios/axios/axios.min.js'), 'customJSModules' => array('public/js/apps/TestSearch.js') ); @@ -40,17 +39,17 @@
- + - + - +
diff --git a/application/views/system/logs/testVBform.php b/application/views/system/logs/testVBform.php new file mode 100644 index 000000000..566abb1cb --- /dev/null +++ b/application/views/system/logs/testVBform.php @@ -0,0 +1,16 @@ + 'Test VBform', + 'bootstrap5' => true, + 'fontawesome6' => true, + 'vue3' => true, + 'customJSModules' => array('public/js/apps/vbform/vbform.js') + ); + + $this->load->view('templates/FHC-Header', $includesArray); +?> + +
+ +load->view('templates/FHC-Footer', $includesArray); ?> + diff --git a/application/views/system/messages/FAShtmlWriteTemplate.php b/application/views/system/messages/FAShtmlWriteTemplate.php new file mode 100644 index 000000000..83f895d14 --- /dev/null +++ b/application/views/system/messages/FAShtmlWriteTemplate.php @@ -0,0 +1,197 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Write a new message or reply using templates', + 'jquery3' => true, + 'jqueryui1' => true, + 'bootstrap3' => true, + 'ajaxlib' => true, + 'fontawesome4' => true, + 'tinymce3' => true, + 'sbadmintemplate3' => true, + 'dialoglib' => true, + 'widgets' => true, + 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), + 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/fasMessageWrite.js') + ) + ); +?> + +
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+   +
+ +
+
+
+
+
+
+ + +
+
+
+ + + 19 ? 19 : count($variables); + echo $this->widgetlib->widget( + 'MultipleDropdown_widget', + array('elements' => success($variables)), + array( + 'name' => 'variables[]', + 'id' => 'variables', + 'size' => $size, + 'multiple' => true + ) + ); + ?> +
+
+
+ + + 5 ? 5 : count($user_fields); + echo $this->widgetlib->widget( + 'MultipleDropdown_widget', + array('elements' => success($user_fields)), + array( + 'name' => 'user_fields[]', + 'id' => 'user_fields', + 'size' => $size, + 'multiple' => true + ) + ); + ?> +
+
+
+
+
+
+ + widgetlib->widget( + 'Vorlage_widget', + array('oe_kurzbz' => $organisationUnits, 'isAdmin' => $senderIsAdmin), + array('name' => 'vorlage', 'id' => 'vorlageDnD') + ); + ?> + +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+ widgetlib->widget( + 'Dropdown_widget', + array( + 'elements' => success($recipientsArray), + 'emptyElement' => ucfirst($this->p->t('global', 'empfaenger')).'...' + ), + array( + 'name' => 'recipients[]', + 'id' => 'recipients' + ) + ); + ?> + + + p->t('ui', 'refresh')); ?> + + +
+
+
+
+
+ +
+ + + + + +
+
+
+
+ + +load->view("templates/FHC-Footer"); ?> + diff --git a/application/views/system/messages/ajaxRead.php b/application/views/system/messages/ajaxRead.php index 2cb88708e..4c1a77deb 100644 --- a/application/views/system/messages/ajaxRead.php +++ b/application/views/system/messages/ajaxRead.php @@ -12,7 +12,7 @@ 'tabulator4' => true, 'ajaxlib' => true, 'dialoglib' => true, - 'tinymce4' => true, + 'tinymce5' => true, 'phrases' => array('global', 'ui'), 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/read.js') diff --git a/application/views/system/messages/ajaxWrite.php b/application/views/system/messages/ajaxWrite.php index 3b1582f22..b3a598506 100644 --- a/application/views/system/messages/ajaxWrite.php +++ b/application/views/system/messages/ajaxWrite.php @@ -10,7 +10,7 @@ 'sbadmintemplate3' => true, 'ajaxlib' => true, 'dialoglib' => true, - 'tinymce4' => true, + 'tinymce5' => true, 'phrases' => array('global', 'ui'), 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/write.js') diff --git a/application/views/system/messages/ajaxWriteReply.php b/application/views/system/messages/ajaxWriteReply.php index 0a496c93e..08dc188fa 100644 --- a/application/views/system/messages/ajaxWriteReply.php +++ b/application/views/system/messages/ajaxWriteReply.php @@ -10,7 +10,7 @@ 'sbadmintemplate3' => true, 'ajaxlib' => true, 'dialoglib' => true, - 'tinymce4' => true, + 'tinymce5' => true, 'phrases' => array('global', 'ui'), 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/writeReply.js') diff --git a/application/views/system/messages/htmlWriteReply.php b/application/views/system/messages/htmlWriteReply.php index 9106d802b..d2150c1fb 100644 --- a/application/views/system/messages/htmlWriteReply.php +++ b/application/views/system/messages/htmlWriteReply.php @@ -6,7 +6,7 @@ 'jquery3' => true, 'bootstrap3' => true, 'fontawesome4' => true, - 'tinymce4' => true, + 'tinymce5' => true, 'sbadmintemplate3' => true, 'customCSSs' => array('public/css/sbadmin2/admintemplate_contentonly.css', 'public/css/messaging/message.css'), 'customJSs' => array('public/js/bootstrapper.js', 'public/js/messaging/messageWriteReply.js') diff --git a/application/views/system/messages/htmlWriteTemplate.php b/application/views/system/messages/htmlWriteTemplate.php index 761e05f96..42a31f374 100644 --- a/application/views/system/messages/htmlWriteTemplate.php +++ b/application/views/system/messages/htmlWriteTemplate.php @@ -8,7 +8,7 @@ 'bootstrap3' => true, 'ajaxlib' => true, 'fontawesome4' => true, - 'tinymce4' => true, + 'tinymce5' => true, 'sbadmintemplate3' => true, 'dialoglib' => true, 'widgets' => true, diff --git a/application/views/system/vorlage/templatetextEdit.php b/application/views/system/vorlage/templatetextEdit.php index 42efc1519..cc2487959 100644 --- a/application/views/system/vorlage/templatetextEdit.php +++ b/application/views/system/vorlage/templatetextEdit.php @@ -1,5 +1,5 @@ load->view('templates/header', array('title' => 'VorlageEdit', 'tinymce4' => true, 'jsonforms' => true)); + $this->load->view('templates/header', array('title' => 'VorlageEdit', 'tinymce5' => true, 'jsonforms' => true)); ?>
diff --git a/application/views/templates/FHC-Common.php b/application/views/templates/FHC-Common.php index dd1d8ae1c..072ff1d7f 100644 --- a/application/views/templates/FHC-Common.php +++ b/application/views/templates/FHC-Common.php @@ -23,7 +23,7 @@ $tablesorter2 = isset($tablesorter2) ? $tablesorter2 : false; $tabulator4 = isset($tabulator4) ? $tabulator4 : false; $tabulator5 = isset($tabulator5) ? $tabulator5 : false; - $tinymce4 = isset($tinymce4) ? $tinymce4 : false; + $tinymce3 = isset($tinymce3) ? $tinymce3 : false; $tinymce5 = isset($tinymce5) ? $tinymce5 : false; $vue3 = isset($vue3) ? $vue3 : false; $primevue3 = isset($primevue3) ? $primevue3 : false; @@ -34,6 +34,7 @@ // Internal resources $ajaxlib = isset($ajaxlib) ? $ajaxlib : false; $bootstrapper = isset($bootstrapper) ? $bootstrapper : false; + $cis = isset($cis) ? $cis : false; $dialoglib = isset($dialoglib) ? $dialoglib : false; $filtercomponent = isset($filtercomponent) ? $filtercomponent : false; $filterwidget = isset($filterwidget) ? $filterwidget : false; @@ -43,4 +44,3 @@ $tablewidget = isset($tablewidget) ? $tablewidget : false; $udfs = isset($udfs) ? $udfs : false; $widgets = isset($widgets) ? $widgets : false; - diff --git a/application/views/templates/FHC-Footer.php b/application/views/templates/FHC-Footer.php index c461dd8b0..31e610289 100644 --- a/application/views/templates/FHC-Footer.php +++ b/application/views/templates/FHC-Footer.php @@ -100,14 +100,14 @@ // Tabulator 5 JS if ($tabulator5 === true) generateJSsInclude('vendor/olifolkerd/tabulator5/dist/js/tabulator.min.js'); - // Tinymce 4 JS - if ($tinymce4 === true) generateJSsInclude('vendor/tinymce/tinymce4/tinymce.min.js'); + // Tinymce 3 JS + if ($tinymce3 === true) generateJSsInclude('include/tiny_mce/tiny_mce.js'); // Tinymce 5 JS if ($tinymce5 === true) generateJSsInclude('vendor/tinymce/tinymce5/tinymce.min.js'); // Vue 3 JS - if ($vue3 === true) + if ($vue3 === true) { generateJSsInclude('vendor/vuejs/vuejs3/vue.global.prod.js'); generateJSsInclude('vendor/vuejs/vuerouter4/vue-router.global.js'); @@ -122,6 +122,16 @@ generateJSsInclude('vendor/npm-asset/primevue/column/column.min.js'); generateJSsInclude('vendor/npm-asset/primevue/calendar/calendar.min.js'); generateJSsInclude('vendor/npm-asset/primevue/skeleton/skeleton.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/timeline/timeline.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/multiselect/multiselect.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/autocomplete/autocomplete.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/overlaypanel/overlaypanel.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/datatable/datatable.min.js'); + // TODO check ob notwendig + generateJSsInclude('vendor/npm-asset/primevue/toast/toast.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/toastservice/toastservice.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/confirmdialog/confirmdialog.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/confirmationservice/confirmationservice.min.js'); } // -------------------------------------------------------------------------------------------------------- diff --git a/application/views/templates/FHC-Header.php b/application/views/templates/FHC-Header.php index aa63541c5..cf0658cf0 100644 --- a/application/views/templates/FHC-Header.php +++ b/application/views/templates/FHC-Header.php @@ -41,6 +41,7 @@ { generateCSSsInclude('vendor/fortawesome/font-awesome6/css/fontawesome.min.css'); generateCSSsInclude('vendor/fortawesome/font-awesome6/css/solid.min.css'); + generateCSSsInclude('vendor/fortawesome/font-awesome6/css/regular.min.css'); // NOTE(chris): for favorites in stv generateCSSsInclude('vendor/fortawesome/font-awesome6/css/brands.min.css'); } @@ -77,10 +78,7 @@ } // Tabulator 5 CSS - if ($tabulator5 === true) generateCSSsInclude('vendor/olifolkerd/tabulator5/dist/css/tabulator_bootstrap5.min.css'); - - // Tinymce 4 CSS - if ($tinymce4 === true) generateCSSsInclude('public/css/TinyMCE4.css'); + if ($tabulator5 === true) generateCSSsInclude('public/css/Tabulator5.css'); // Tinymce 5 CSS if ($tinymce5 === true) generateCSSsInclude('public/css/TinyMCE5.css'); @@ -118,6 +116,9 @@ // HTML Widget CSS if ($widgets === true) generateCSSsInclude('public/css/Widgets.css'); + // CIS + if ($cis === true) generateCSSsInclude('public/css/cis_bs5.css'); + // Eventually required CSS generateCSSsInclude($customCSSs); // Eventually required CSS ?> diff --git a/application/views/templates/header.php b/application/views/templates/header.php index 637eb3c7a..e75acca4f 100644 --- a/application/views/templates/header.php +++ b/application/views/templates/header.php @@ -95,7 +95,7 @@ if($jqueryV1 && $jqueryV2) show_error("Two JQuery versions used: composer and in - + diff --git a/application/views/widgets/tinymce.php b/application/views/widgets/tinymce.php index 3e2093e55..618cb4836 100644 --- a/application/views/widgets/tinymce.php +++ b/application/views/widgets/tinymce.php @@ -5,5 +5,6 @@ plugins: [], toolbar: "" }); - - < name="" style="">> + +< name="" style="">> + diff --git a/application/widgets/FilterWidget.php b/application/widgets/FilterWidget.php index 1cef91c15..45bcf7e04 100644 --- a/application/widgets/FilterWidget.php +++ b/application/widgets/FilterWidget.php @@ -1,5 +1,22 @@ . + */ + /** * To filter data using a SQL statement */ @@ -59,6 +76,8 @@ class FilterWidget extends Widget private $_sessionTimeout; // session expiring time + private $_encryptedColumns; // contains info about encrypted columns + private static $_FilterWidgetInstance; // static property that contains the instance of itself /** @@ -195,6 +214,7 @@ class FilterWidget extends Widget $this->_formatRow = null; $this->_markRow = null; $this->_checkboxes = null; + $this->_encryptedColumns = null; $this->_hideOptions = null; $this->_hideSelectFields = null; $this->_hideSelectFilters = null; @@ -252,6 +272,14 @@ class FilterWidget extends Widget $this->_additionalColumns = $args[FilterWidgetLib::ADDITIONAL_COLUMNS]; } + // Parameter is used to define the ecrypted columns + if (isset($args[FilterWidgetLib::ENCRYPTED_COLUMNS]) + && is_array($args[FilterWidgetLib::ENCRYPTED_COLUMNS]) + && count($args[FilterWidgetLib::ENCRYPTED_COLUMNS]) > 0) + { + $this->_encryptedColumns = $args[FilterWidgetLib::ENCRYPTED_COLUMNS]; + } + // Parameter is used to add use aliases for the columns fo the dataset if (isset($args[FilterWidgetLib::COLUMNS_ALIASES]) && is_array($args[FilterWidgetLib::COLUMNS_ALIASES]) @@ -441,7 +469,7 @@ class FilterWidget extends Widget ); // Then retrieve dataset from DB - $dataset = $this->filterwidgetlib->getDataset($datasetQuery); + $dataset = $this->filterwidgetlib->getDataset($datasetQuery, $this->_encryptedColumns); // Save changes into session if data are valid if (!isError($dataset)) @@ -476,7 +504,7 @@ class FilterWidget extends Widget $datasetQuery = $this->filterwidgetlib->generateDatasetQuery($this->_query, $parsedFilterJson->filters); // Then retrieve dataset from DB - $dataset = $this->filterwidgetlib->getDataset($datasetQuery); + $dataset = $this->filterwidgetlib->getDataset($datasetQuery, $this->_encryptedColumns); // Try to load the name of the filter using the PhrasesLib $filterName = $this->filterwidgetlib->getFilterName($parsedFilterJson); @@ -497,6 +525,7 @@ class FilterWidget extends Widget FilterWidgetLib::SESSION_SELECTED_FIELDS => $this->_getColumnsNames($parsedFilterJson->columns), // all the selected fields FilterWidgetLib::SESSION_COLUMNS_ALIASES => $this->_columnsAliases, // all the fields aliases FilterWidgetLib::SESSION_ADDITIONAL_COLUMNS => $this->_additionalColumns, // additional columns + FilterWidgetLib::SESSION_ENCRYPTED_COLUMNS => $this->_encryptedColumns, // encrypted columns FilterWidgetLib::SESSION_CHECKBOXES => $this->_checkboxes, // the name of the field used to build the checkboxes column FilterWidgetLib::SESSION_FILTERS => $parsedFilterJson->filters, // all the filters used to filter the dataset FilterWidgetLib::SESSION_METADATA => $this->FiltersModel->getExecutedQueryMetaData(), // the metadata of the dataset @@ -525,7 +554,7 @@ class FilterWidget extends Widget private function _setFilterMenu() { // Generates the filters structure array - $filterMenu = $this->filterwidgetlib->generateFilterMenu( + $this->filterwidgetlib->generateFilterMenu( $this->router->directory.$this->router->class.'/'.$this->router->method ); } @@ -604,7 +633,7 @@ class FilterWidget extends Widget { $columnsNames = array(); - foreach ($columns as $key => $obj) + foreach ($columns as $obj) { if (isset($obj->name)) { diff --git a/application/widgets/TableWidget.php b/application/widgets/TableWidget.php index 5a000601f..e59efce10 100644 --- a/application/widgets/TableWidget.php +++ b/application/widgets/TableWidget.php @@ -1,5 +1,22 @@ . + */ + /** * To display a table that shows data retriev by a SQL statement */ @@ -40,6 +57,8 @@ class TableWidget extends Widget private $_sessionTimeout; // session expiring time + private $_encryptedColumns; // contains info about encrypted columns + private static $_TableWidgetInstance; // static property that contains the instance of itself /** @@ -127,6 +146,7 @@ class TableWidget extends Widget $this->_datasetRepresentationOptions = null; $this->_datasetRepFieldsDefs = null; $this->_sessionTimeout = TableWidgetLib::SESSION_DEFAULT_TIMEOUT; + $this->_encryptedColumns = null; // Retrieved the required permissions parameter if present if (isset($args[TableWidgetLib::REQUIRED_PERMISSIONS])) @@ -206,6 +226,14 @@ class TableWidget extends Widget { $this->_sessionTimeout = $args[TableWidgetLib::SESSION_TIMEOUT]; } + + // Parameter is used to define the ecrypted columns + if (isset($args[TableWidgetLib::ENCRYPTED_COLUMNS]) + && is_array($args[TableWidgetLib::ENCRYPTED_COLUMNS]) + && count($args[TableWidgetLib::ENCRYPTED_COLUMNS]) > 0) + { + $this->_encryptedColumns = $args[TableWidgetLib::ENCRYPTED_COLUMNS]; + } } /** @@ -288,7 +316,7 @@ class TableWidget extends Widget $datasetQuery = $this->tablewidgetlib->generateDatasetQuery($this->_query); // Then retrieve dataset from DB - $dataset = $this->tablewidgetlib->getDataset($datasetQuery); + $dataset = $this->tablewidgetlib->getDataset($datasetQuery, $this->_encryptedColumns); // Save changes into session if data are valid if (!isError($dataset)) @@ -310,7 +338,7 @@ class TableWidget extends Widget $datasetQuery = $this->tablewidgetlib->generateDatasetQuery($this->_query); // Then retrieve dataset from DB - $dataset = $this->tablewidgetlib->getDataset($datasetQuery); + $dataset = $this->tablewidgetlib->getDataset($datasetQuery, $this->_encryptedColumns); // Save changes into session if data are valid if (!isError($dataset)) @@ -324,6 +352,7 @@ class TableWidget extends Widget TableWidgetLib::SESSION_FIELDS => $this->tablewidgetlib->getExecutedQueryListFields(), // all the fields of the dataset TableWidgetLib::SESSION_COLUMNS_ALIASES => $this->_columnsAliases, // all the fields aliases TableWidgetLib::SESSION_ADDITIONAL_COLUMNS => $this->_additionalColumns, // additional columns + TableWidgetLib::SESSION_ENCRYPTED_COLUMNS => $this->_encryptedColumns, // encrypted columns TableWidgetLib::SESSION_CHECKBOXES => $this->_checkboxes, // the name of the field used to build the checkboxes column TableWidgetLib::SESSION_METADATA => $this->tablewidgetlib->getExecutedQueryMetaData(), // the metadata of the dataset TableWidgetLib::SESSION_ROW_NUMBER => count($dataset->retval), // the number of loaded rows by this table @@ -411,24 +440,6 @@ class TableWidget extends Widget return !isset($class) ? '' : $class; } - /** - * Utility method that retrieves the name of the columns present in a table JSON definition - */ - private function _getColumnsNames($columns) - { - $columnsNames = array(); - - foreach ($columns as $key => $obj) - { - if (isset($obj->name)) - { - $columnsNames[] = $obj->name; - } - } - - return $columnsNames; - } - /** * Loads a view using the given viewName and eventually other parameters */ @@ -438,3 +449,4 @@ class TableWidget extends Widget $ci->load->view($viewName, $parameters); } } + diff --git a/cis/index.php b/cis/index.php index 38af9f50d..d490a201a 100644 --- a/cis/index.php +++ b/cis/index.php @@ -215,7 +215,13 @@ function loadampel()
- + t('menu/sucheOrtDokumentInhalt'); + else + $searchText = $p->t('menu/suchePersonOrtDokumentInhalt'); + ?> +
diff --git a/cis/private/info/service_uebersicht.php b/cis/private/info/service_uebersicht.php index 27759e6c6..348a82b0d 100644 --- a/cis/private/info/service_uebersicht.php +++ b/cis/private/info/service_uebersicht.php @@ -45,25 +45,22 @@ echo ' - - - - - -'; + + + + + + '; + +const MOODLE_ADDON_KURZBZ = 'moodle'; // Load Addons to get Moodle_Path $addon_obj = new addon(); -if ($addon_obj->loadAddons()) + +// include moodle addon config if active +if ($addon_obj->checkActiveAddon(MOODLE_ADDON_KURZBZ) && file_exists('../../../addons/'.MOODLE_ADDON_KURZBZ.'/config.inc.php')) { - if (count($addon_obj->result) > 0) - { - foreach ($addon_obj->result as $row) - { - if (file_exists('../../../addons/'.$row->kurzbz.'/config.inc.php')) - include_once('../../../addons/'.$row->kurzbz.'/config.inc.php'); - } - } + include_once('../../../addons/'.MOODLE_ADDON_KURZBZ.'/config.inc.php'); } echo ' @@ -117,6 +114,7 @@ echo ' '; +$servicekategorie_arr = $service->getKategorieArray(); if($oe_kurzbz!='') { @@ -134,6 +132,7 @@ echo ' + @@ -159,6 +158,8 @@ foreach($service->result as $row) echo ''; //echo ''; //echo ''; + $title = (isset($servicekategorie_arr[$row->servicekategorie_kurzbz])?$servicekategorie_arr[$row->servicekategorie_kurzbz]:''); + echo ''; echo ' - + - + - + diff --git a/cis/private/lehre/abgabe_student.php b/cis/private/lehre/abgabe_student.php index 9b3cec6f6..2512d9831 100644 --- a/cis/private/lehre/abgabe_student.php +++ b/cis/private/lehre/abgabe_student.php @@ -124,7 +124,6 @@ $sql_query = "SELECT (SELECT nachname FROM public.tbl_person WHERE person_id=tb AND tbl_projektarbeit.student_uid=".$db->db_add_param($uid)." ORDER BY studiensemester_kurzbz desc, tbl_lehrveranstaltung.kurzbz"; -//AND tbl_projektarbeit.student_uid='$getuid' 'ie07m102'; if(!$erg=$db->db_query($sql_query)) { $errormsg=$p->t('global/fehlerBeimLesenAusDatenbank'); diff --git a/cis/private/lehre/abgabe_student_details.php b/cis/private/lehre/abgabe_student_details.php index 6575dcf70..860eb7579 100644 --- a/cis/private/lehre/abgabe_student_details.php +++ b/cis/private/lehre/abgabe_student_details.php @@ -64,7 +64,6 @@ if(!isset($_POST['uid'])) $fixtermin = false; $datum = '01.01.1980'; $kurzbz = ''; - $kontrollschlagwoerter = ''; $schlagwoerter = ''; $schlagwoerter_en = ''; $abstract = ''; @@ -88,7 +87,6 @@ else $kurzbz = (isset($_POST['kurzbz'])?$_POST['kurzbz']:''); $betreuer = (isset($_POST['betreuer'])?$_POST['betreuer']:'-1'); $sprache = (isset($_POST['sprache'])?$_POST['sprache']:'German'); - $kontrollschlagwoerter = (isset($_POST['kontrollschlagwoerter'])?$_POST['kontrollschlagwoerter']:'-1'); $schlagwoerter = (isset($_POST['schlagwoerter'])?$_POST['schlagwoerter']:'-1'); $schlagwoerter_en = (isset($_POST['schlagwoerter_en'])?$_POST['schlagwoerter_en']:'-1'); $abstract = (isset($_POST['abstract'])?$_POST['abstract']:'-1'); @@ -211,23 +209,7 @@ if($command=='add') { //zusätzliche Daten bearbeiten //Check der Eingabedaten - if(strlen($kontrollschlagwoerter)<1) - { - $error=true; - } - if(mb_strlen($kontrollschlagwoerter)>=150) - { - $kontrollschlagwoerter = mb_substr($kontrollschlagwoerter, 0, 146).'...'; - } - if(strlen($abstract)<1) - { - $error=true; - } - if(strlen($abstract_en)<1) - { - $error=true; - } - if($seitenanzahl<1) + if((strlen($schlagwoerter) < 1) || (strlen($schlagwoerter_en) < 1) || (strlen($abstract) < 1) || (strlen($abstract_en) < 1) || ($seitenanzahl < 1)) { $error=true; } @@ -237,7 +219,6 @@ if($command=='add') seitenanzahl = ".$db->db_add_param($seitenanzahl).", abgabedatum = now(), sprache = ".$db->db_add_param($sprache).", - kontrollschlagwoerter = ".$db->db_add_param($kontrollschlagwoerter).", schlagwoerter_en = ".$db->db_add_param($schlagwoerter_en).", schlagwoerter = ".$db->db_add_param($schlagwoerter).", abstract = ".$db->db_add_param($abstract).", @@ -413,19 +394,16 @@ if($command=="update" && $error!=true) $htmlstr .= " \n"; } $htmlstr .= "\n"; - $htmlstr .= ' - - '."\n"; - $htmlstr .= ' - '."\n"; - $htmlstr .= ' - '."\n"; + $htmlstr .= ' + '."\n"; + $htmlstr .= ' + '."\n"; $htmlstr .= ' - '."\n"; + '."\n"; $htmlstr .= ' - '."\n"; + '."\n"; $htmlstr .= ' - '."\n"; + '."\n"; $htmlstr .="\n"; // If there are info about the signed document @@ -657,7 +635,6 @@ if($command!="add") $htmlstr .= ''."\n"; $htmlstr .= ''."\n"; $htmlstr .= ''."\n"; - $htmlstr .= ''."\n"; $htmlstr .= ''."\n"; $htmlstr .= ''."\n"; $htmlstr .= ''."\n"; diff --git a/cis/private/lehre/anwesenheitsliste.php b/cis/private/lehre/anwesenheitsliste.php index 8b1f28408..0ba5531c8 100644 --- a/cis/private/lehre/anwesenheitsliste.php +++ b/cis/private/lehre/anwesenheitsliste.php @@ -62,7 +62,7 @@ $stsem = $_GET['stsem']; else die($p->t('anwesenheitsliste/studiensemesterIstUngueltig')); - + $covidhelper = new CovidHelper(); ?> "; - $qry = "SELECT *, tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester FROM lehre.tbl_lehreinheit JOIN lehre.tbl_lehreinheitgruppe USING(lehreinheit_id) JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) - WHERE lehrveranstaltung_id='$lvid' AND studiensemester_kurzbz=".$db->db_add_param($stsem); - $qry = "SELECT *, tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester ,tbl_lehreinheit.lehrform_kurzbz FROM lehre.tbl_lehreinheit JOIN lehre.tbl_lehreinheitgruppe USING(lehreinheit_id) @@ -213,7 +210,7 @@ $covidhelper = new CovidHelper(); $covid_content = "
'.$p->t("global/bezeichnung").' '.$p->t("services/leistung").' '.$p->t("services/design").''.$p->t("services/kritikalitaet").' '.$p->t("services/details").'
',$design,'',$betrieb,'',$operativ,'',$title,''.($row->content_id!=''?'Details':''); if (defined("ADDON_MOODLE_PATH")) echo ' '.($row->ext_id!=''?'Beschreibung':''); diff --git a/cis/private/lehre/abgabe_lektor_zusatz.php b/cis/private/lehre/abgabe_lektor_zusatz.php index 39488b6c3..b764fd556 100644 --- a/cis/private/lehre/abgabe_lektor_zusatz.php +++ b/cis/private/lehre/abgabe_lektor_zusatz.php @@ -121,15 +121,15 @@ echo '
'.$p->t('abgabetool/kontrollierteSchlagwoerter').':*'.$p->t('abgabetool/kontrollierteSchlagwoerter').':
'.$p->t('abgabetool/deutscheSchlagwoerter').': '.$p->t('abgabetool/deutscheSchlagwoerter').':*
'.$p->t('abgabetool/englischeSchlagwoerter').': '.$p->t('abgabetool/englischeSchlagwoerter').':*
'.$p->t('abgabetool/kontrollierteSchlagwoerter').':*
'.$p->t('abgabetool/deutscheSchlagwoerter').':
'.$p->t('abgabetool/englischeSchlagwoerter').':
'.$p->t('abgabetool/deutscheSchlagwoerter').':*
'.$p->t('abgabetool/englischeSchlagwoerter').':*
'.$p->t('abgabetool/abstract').' '.$p->t('abgabetool/maxZeichen').':*
'.$p->t('abgabetool/abstractEng').''.$p->t('abgabetool/maxZeichen').':*
'.$p->t('abgabetool/seitenanzahl').':*
 
".$covid_content."

".$p->t('anwesenheitsliste/covidstatuslisten')."

"; else $covid_content = ($covidhelper->isUdfDefined()) ? $p->t('anwesenheitsliste/keineStudentenVorhanden') : ''; - + if($aw_content!='') $aw_content = "".$aw_content."

".$p->t('anwesenheitsliste/anwesenheitslisten')."

"; else @@ -241,9 +238,9 @@ $covidhelper = new CovidHelper(); { $covid_content = ''; } - + echo " - + diff --git a/cis/private/lehre/benotungstool/lvgesamtnoteverwalten.php b/cis/private/lehre/benotungstool/lvgesamtnoteverwalten.php index 6dce2b6ae..a799c9fad 100644 --- a/cis/private/lehre/benotungstool/lvgesamtnoteverwalten.php +++ b/cis/private/lehre/benotungstool/lvgesamtnoteverwalten.php @@ -102,6 +102,22 @@ $noten_obj->getAll(); $sprachen = new sprache(); $sprachen->getAll(true); + +$noten_array = array(); +$js_noten=''; +foreach ($noten_obj->result as $row) +{ + $js_noten .= " noten_array['" . $row->note . "']='" . addslashes($row->bezeichnung) . "';\n"; + $noten_array[$row->note]['bezeichnung'] = $row->bezeichnung; + $noten_array[$row->note]['positiv'] = $row->positiv; + $noten_array[$row->note]['aktiv'] = $row->aktiv; + $noten_array[$row->note]['lehre'] = $row->lehre; + $noten_array[$row->note]['lkt_ueberschreibbar'] = $row->lkt_ueberschreibbar; + $noten_array[$row->note]['anmerkung'] = $row->anmerkung; + foreach ($sprachen->result as $s) + $noten_array[$row->note]['bezeichnung_mehrsprachig'][$s->sprache] = $row->bezeichnung_mehrsprachig[$s->sprache]; +} + $errormsg = ''; // eingetragene lv-gesamtnoten freigeben @@ -326,19 +342,7 @@ echo ' var noten_array = Array(); '; -$noten_array = array(); -foreach ($noten_obj->result as $row) -{ - echo " noten_array['" . $row->note . "']='" . addslashes($row->bezeichnung) . "';\n"; - $noten_array[$row->note]['bezeichnung'] = $row->bezeichnung; - $noten_array[$row->note]['positiv'] = $row->positiv; - $noten_array[$row->note]['aktiv'] = $row->aktiv; - $noten_array[$row->note]['lehre'] = $row->lehre; - $noten_array[$row->note]['lkt_ueberschreibbar'] = $row->lkt_ueberschreibbar; - $noten_array[$row->note]['anmerkung'] = $row->anmerkung; - foreach ($sprachen->result as $s) - $noten_array[$row->note]['bezeichnung_mehrsprachig'][$s->sprache] = $row->bezeichnung_mehrsprachig[$s->sprache]; -} +echo $js_noten; ?> @@ -806,16 +810,16 @@ foreach ($noten_obj->result as $row) for(row in rows) { linenumber++; - if( rows[row] == '' ) + if( rows[row] == '' ) { //skip empty lines continue; } zeile = rows[row].split(" "); - + if( zeile.length < 2 ) { - alertMsg = alertMsg + "Zeile " + linenumber + ': ' + alertMsg = alertMsg + "Zeile " + linenumber + ': ' + 'Zu wenig Paramter - 2 erforderlich. ' + 'Die Zeile wurde uebersprungen.' + "\n\n"; continue; @@ -917,36 +921,36 @@ foreach ($noten_obj->result as $row) for(row in rows) { linenumber++; - if( rows[row] == '' ) + if( rows[row] == '' ) { //skip empty lines continue; } zeile = rows[row].split(" "); - + if( zeile.length < 3 ) { - alertMsg = alertMsg + "Zeile " + linenumber + ': ' + alertMsg = alertMsg + "Zeile " + linenumber + ': ' + 'Zu wenig Paramter - 3 erforderlich. ' + 'Die Zeile wurde uebersprungen.' + "\n\n"; continue; } - + if( zeile[1] == '' && zeile[2] == '' ) { - // ignore lines just copied from excel + // ignore lines just copied from excel continue; } - - if( zeile[2] == '' ) + + if( zeile[2] == '' ) { alertMsg = alertMsg + "Zeile " + linenumber + ': ' + "Die Note oder Punkte fehlen. " + "Die Zeile wurde uebersprungen. \n\n"; - continue; + continue; } - - if (CIS_GESAMTNOTE_PUNKTE == false) + + if (CIS_GESAMTNOTE_PUNKTE == false) { // check for valid grades if (validGrades.indexOf(zeile[2]) === -1) @@ -958,7 +962,7 @@ foreach ($noten_obj->result as $row) } } - if( !zeile[1].match(/[0-9]{2}\.[0-9]{2}\.[0-9]{4}/) ) + if( !zeile[1].match(/[0-9]{2}\.[0-9]{2}\.[0-9]{4}/) ) { alertMsg = alertMsg + "Zeile " + linenumber + ': ' + "Das Datum "+zeile[1]+" fehlt oder ist nicht zulaessig. " diff --git a/cis/private/lehre/benotungstool/nachpruefungeintragen.php b/cis/private/lehre/benotungstool/nachpruefungeintragen.php index 873c0f173..55954fcda 100644 --- a/cis/private/lehre/benotungstool/nachpruefungeintragen.php +++ b/cis/private/lehre/benotungstool/nachpruefungeintragen.php @@ -251,7 +251,7 @@ else // deshalb wird hier versucht eine passende Lehreinheit zu ermitteln. $lehreinheit_id = getLehreinheit($db, $lvid, $student_uid, $stsem); - $response = savePruefung($lvid, $student_uid, $stsem, $lehreinheit_id, $datum, $typ, $note); + $response = savePruefung($lvid, $student_uid, $stsem, $lehreinheit_id, $datum, $typ, $note, $punkte); echo $response; } else diff --git a/cis/private/lehre/notenliste.xls.php b/cis/private/lehre/notenliste.xls.php index 63cf45d29..6c8db5246 100644 --- a/cis/private/lehre/notenliste.xls.php +++ b/cis/private/lehre/notenliste.xls.php @@ -114,12 +114,15 @@ else $format_highlight->setFgColor(15); $format_highlight->setBorder(1); $format_highlight->setBorderColor('white'); + $format_highlight->setAlign('left'); + $format_highlight->setNumFormat(49); $format_highlightright=& $workbook->addFormat(); $format_highlightright->setFgColor(15); $format_highlightright->setBorder(1); $format_highlightright->setBorderColor('white'); $format_highlightright->setAlign('right'); + $format_highlightright->setNumFormat(49); $format_highlightright_date=& $workbook->addFormat(); $format_highlightright_date->setFgColor(15); @@ -318,17 +321,23 @@ else $worksheet->write($lines,1,$elem->uid); $worksheet->write($lines,2,$elem->nachname.$inc); - $worksheet->write($lines,3,$elem->vorname); - //wenn Wahlname vorhanden überschreibt dieser den Vornamen - $worksheet->write($lines,3,$elem->wahlname); - $worksheet->write($lines,4,'="'.$elem->semester.$elem->verband.$elem->gruppe.'"'); - $worksheet->write($lines,5,'="'.trim($elem->matrikelnr).'"',$format_highlight); + if( NULL !== $elem->wahlname ) + { + //wenn Wahlname vorhanden überschreibt dieser den Vornamen + $worksheet->write($lines,3,$elem->wahlname); + } + else + { + $worksheet->write($lines,3,$elem->vorname); + } + $worksheet->write($lines,4,$elem->semester.$elem->verband.$elem->gruppe); + $worksheet->write($lines,5,trim($elem->matrikelnr),$format_highlight); $worksheet->write($lines,6, $note, $format_highlightright); // Nachprüfung if (defined('CIS_GESAMTNOTE_PRUEFUNG_TERMIN2') && CIS_GESAMTNOTE_PRUEFUNG_TERMIN2) { - $worksheet->write($lines,8, '="'.trim($elem->matrikelnr).'"', $format_highlight); + $worksheet->write($lines,8, trim($elem->matrikelnr), $format_highlight); $pr = new Pruefung(); $pr->getPruefungen($elem->uid, "Termin2", $lvid, $sem); $output2 = $pr->result; @@ -349,7 +358,7 @@ else // Nachprüfung if (defined('CIS_GESAMTNOTE_PRUEFUNG_TERMIN3') && CIS_GESAMTNOTE_PRUEFUNG_TERMIN3) { - $worksheet->write($lines,12, '="'.trim($elem->matrikelnr).'"', $format_highlight); + $worksheet->write($lines,12, trim($elem->matrikelnr), $format_highlight); $pr = new Pruefung(); $pr->getPruefungen($elem->uid, "Termin3", $lvid, $sem); $output3 = $pr->result; diff --git a/cis/private/lehre/swd.php b/cis/private/lehre/swd.php deleted file mode 100644 index 248779aac..000000000 --- a/cis/private/lehre/swd.php +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/cis/private/lvplan/stpl_week.php b/cis/private/lvplan/stpl_week.php index e58ce03ed..f600c6db5 100644 --- a/cis/private/lvplan/stpl_week.php +++ b/cis/private/lvplan/stpl_week.php @@ -270,7 +270,7 @@ if (isset($_POST['titel'])) foreach($addon_obj->result as $addon) { if(file_exists('../../../addons/'.$addon->kurzbz.'/cis/init.js.php')) - echo ''; + echo ''; } // Wenn Seite fertig geladen ist Addons aufrufen diff --git a/cis/private/pdfExport.php b/cis/private/pdfExport.php index 4535ff74d..ad2bb1fae 100644 --- a/cis/private/pdfExport.php +++ b/cis/private/pdfExport.php @@ -65,6 +65,11 @@ $xsl_stg_kz = 0; $sign = false; +/* Signing on CIS disabled +if(isset($_GET['sign'])) + $sign = true; +*/ + // Direkte uebergabe des Studienganges dessen Vorlage verwendet werden soll if (isset($_GET['xsl_stg_kz'])) $xsl_stg_kz = $_GET['xsl_stg_kz']; @@ -144,6 +149,8 @@ if (isset($_GET['projektarbeit_id'])) $params .= '&projektarbeit_id='. $_GET['projektarbeit_id']; if (isset($_GET['betreuerart_kurzbz'])) $params .= '&betreuerart_kurzbz='. $_GET['betreuerart_kurzbz']; +if (isset($_GET['id'])) + $params .= '&id='. $_GET['id']; // Logeintrag bei Download von Zahlungsbestaetigungen @@ -296,22 +303,18 @@ if ((((isset($_GET["uid"]) && $user == $_GET["uid"])) || $rechte->isBerechtigt(' $dokument->setFilename($filename); - if (!$dokument->create($output)) - die($dokument->errormsg); - if ($sign === true) { - if ($dokument->sign($user)) - { - $dokument->output(); - } - else + if (!$dokument->sign($user)) { echo $dokument->errormsg; } } - else - $dokument->output(); + + if (!$dokument->create($output)) + die($dokument->errormsg); + + $dokument->output(); $dokument->close(); } else diff --git a/cis/private/profile/dokumente.php b/cis/private/profile/dokumente.php index f75529561..9e7f6bf5b 100644 --- a/cis/private/profile/dokumente.php +++ b/cis/private/profile/dokumente.php @@ -31,6 +31,7 @@ require_once('../../../include/akte.class.php'); require_once('../../../include/datum.class.php'); require_once('../../../include/benutzerberechtigung.class.php'); require_once('../../../include/webservicelog.class.php'); +require_once('../../../include/studierendenantrag.class.php'); $sprache = getSprache(); $p = new phrasen($sprache); @@ -228,6 +229,28 @@ echo '

'; // Wenn es für das übergebene Studiensemester keinen PreStudentStatus gibt, werden nur Abschlussdokumente angezeigt if (in_array($stsem, $stsem_arr)) { + $studierendenantrag = new studierendenantrag(); + if ($studierendenantrag->loadUserAntrag($student_studiengang->prestudent_id, $stsem) && $studierendenantrag->result) { + echo '

' . $p->t('studierendenantrag/antraege_header') . '

'; + echo '
$aw_content $covid_content
+ + + + + + + '; + foreach ($studierendenantrag->result as $antrag) { + $path = "../pdfExport.php?xsl=Antrag" . $antrag->typ . "&xml=Antrag" . $antrag->typ . ".xml.php&uid=" . $uid . "&id=" . $antrag->studierendenantrag_id; + echo ''; + echo ''; + echo ''; + echo ''; + } + echo '
'.$p->t('global/name').'
' . $p->t('studierendenantrag/title_' . $antrag->typ) . '
'; + } + + $konto = new konto(); $buchungstypen = array(); diff --git a/cis/private/profile/index.php b/cis/private/profile/index.php index ed3295287..26312d5be 100644 --- a/cis/private/profile/index.php +++ b/cis/private/profile/index.php @@ -276,15 +276,22 @@ if (!$ansicht) { if ($type === 'mitarbeiter') { - $verwendung = new bisverwendung(); - if($verwendung->getLastVerwendung($uid)) + if(defined('DIENSTVERHAELTNIS_SUPPORT') && DIENSTVERHAELTNIS_SUPPORT) { - if (!$verwendung->hauptberuflich) - { - echo 'Hauptberuf: '. $verwendung->hauptberuf; - } + // TODO Hauptberuf wieder anzeigen sobald verfuegbar } - echo "

"; + else + { + $verwendung = new bisverwendung(); + if($verwendung->getLastVerwendung($uid)) + { + if (!$verwendung->hauptberuflich) + { + echo 'Hauptberuf: '. $verwendung->hauptberuf; + } + } + echo "

"; + } } } @@ -606,9 +613,36 @@ function printFunctionsTable($query, $headingphrase, $tableid, $showVertragsstun if ($showVertragsstunden === true && $adminOrOwnUser) { $vertragsstunden = 0.00; - $qry = "SELECT sum(vertragsstunden) AS vertragsstdsumme from bis.tbl_bisverwendung - WHERE mitarbeiter_uid = ".$db->db_add_param($uid)." - AND (ende > now() OR ende IS NULL)"; + if(defined('DIENSTVERHAELTNIS_SUPPORT') && DIENSTVERHAELTNIS_SUPPORT) + { + $qry = "SELECT + sum(wochenstunden) AS vertragsstdsumme + FROM + hr.tbl_vertragsbestandteil_stunden vbs + JOIN + hr.tbl_vertragsbestandteil vb USING(vertragsbestandteil_id) + JOIN + hr.tbl_dienstverhaeltnis dv USING(dienstverhaeltnis_id) + WHERE + dv.mitarbeiter_uid = ".$db->db_add_param($uid)." + AND NOW() BETWEEN COALESCE(vb.von, '1970-01-01'::date) AND COALESCE(vb.bis, '2170-12-31'::date) + AND NOT EXISTS ( + SELECT + 1 + FROM + hr.tbl_vertragsbestandteil + WHERE + dienstverhaeltnis_id = dv.dienstverhaeltnis_id + AND vertragsbestandteiltyp_kurzbz = 'karenz' + AND NOW() BETWEEN COALESCE(von, '1970-01-01'::date) AND COALESCE(bis, '2170-12-31'::date) + )"; + } + else + { + $qry = "SELECT sum(vertragsstunden) AS vertragsstdsumme from bis.tbl_bisverwendung + WHERE mitarbeiter_uid = ".$db->db_add_param($uid)." + AND (ende > now() OR ende IS NULL)"; + } if ($result_vertragsstd = $db->db_query($qry)) { diff --git a/cis/private/profile/zeitsperre_resturlaub.php b/cis/private/profile/zeitsperre_resturlaub.php index 46d342971..ffd179401 100644 --- a/cis/private/profile/zeitsperre_resturlaub.php +++ b/cis/private/profile/zeitsperre_resturlaub.php @@ -79,7 +79,12 @@ else if (defined('CIS_ZEITAUFZEICHNUNG_GESPERRT_BIS') && CIS_ZEITAUFZEICHNUNG_GE else $gesperrt_bis = '2015-08-31'; -//echo $gesperrt_bis; +//Default-Wert für Max-Intervall in Tagen für Zeitsperre, über Config veränderbar +$maxDauerZS = 730; + +if (defined('CIS_ZEITSPERREN_MAX_DAUER') && CIS_ZEITSPERREN_MAX_DAUER != '') { + $maxDauerZS = CIS_ZEITSPERREN_MAX_DAUER; +} //Stundentabelleholen if(! $result_stunde=$db->db_query("SELECT * FROM lehre.tbl_stunde ORDER BY stunde")) @@ -204,66 +209,72 @@ function berechnen() function checkdatum() { - if(document.getElementById('vondatum').value.length<10) + if (document.getElementById('vondatum').value.length < 10) { alert('t('zeitsperre/vonDatumIstUngueltigNullenAngeben');?>'); return false; } - if(document.getElementById('bisdatum').value.length<10) + if (document.getElementById('bisdatum').value.length < 10) { alert('t('zeitsperre/bisDatumIstUngueltigNullenAngeben');?>'); return false; } - var Datum, Tag, Monat,Jahr,vonDatum,bisDatum, diff; + var Datum, Tag, Monat, Jahr, vonDatum, bisDatum, vonDatumDate, bisDatumDate, diff, diffTime, diffmax; - Datum=document.getElementById('vondatum').value; - Tag=Datum.substring(0,2); - Monat=Datum.substring(3,5); - if (parseInt(Monat,10)<1 || parseInt(Monat,10)>12) - { - alert('t('zeitsperre/vonDatumMonat');?>'+ document.getElementById('vondatum').value+ ' t('zeitsperre/istNichtRichtig');?>.'); + Datum = document.getElementById('vondatum').value; + Tag = Datum.substring(0, 2); + Monat = Datum.substring(3, 5); + if (parseInt(Monat, 10) < 1 || parseInt(Monat, 10) > 12) + { + alert('t('zeitsperre/vonDatumMonat');?>' + document.getElementById('vondatum').value + ' t('zeitsperre/istNichtRichtig');?>.'); document.getElementById('vondatum').focus(); - return false; - } + return false; + } - Jahr=Datum.substring(6,10); + Jahr = Datum.substring(6, 10); - vonDatum=Jahr+''+Monat+''+Tag; + vonDatum = Jahr + '' + Monat + '' + Tag; + vonDatumDate = Jahr + '-' + Monat + '-' + Tag; - Datum=document.getElementById('bisdatum').value; - Tag=Datum.substring(0,2); - Monat=Datum.substring(3,5); - if (parseInt(Monat,10)<1 || parseInt(Monat,10)>12) - { - alert('t('zeitsperre/bisDatumMonat');?>'+ document.getElementById('bisdatum').value+ ' t('zeitsperre/istNichtRichtig');?>.'); + Datum = document.getElementById('bisdatum').value; + Tag = Datum.substring(0, 2); + Monat = Datum.substring(3, 5); + if (parseInt(Monat, 10) < 1 || parseInt(Monat, 10) > 12) { + alert('t('zeitsperre/bisDatumMonat');?>' + document.getElementById('bisdatum').value + ' t('zeitsperre/istNichtRichtig');?>.'); document.getElementById('bisdatum').focus(); - return false; - } + return false; + } - Jahr=Datum.substring(6,10); + Jahr = Datum.substring(6, 10); + bisDatum = Jahr + '' + Monat + '' + Tag; + bisDatumDate = Jahr + '-' + Monat + '-' + Tag; - bisDatum=Jahr+''+Monat+''+Tag; + bisDatumDate = new Date(bisDatumDate); + vonDatumDate = new Date(vonDatumDate); - diff=bisDatum-vonDatum; + diffTime = bisDatumDate.getTime() - vonDatumDate.getTime(); + diff = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + diffmax = - if (vonDatum>bisDatum) - { - alert('t('zeitsperre/vonDatum');?> '+ document.getElementById('vondatum').value+ ' t('zeitsperre/istGroesserAlsBisDatum');?> '+document.getElementById('bisdatum').value); + if (vonDatum > bisDatum) { + alert('t('zeitsperre/vonDatum');?> ' + document.getElementById('vondatum').value + ' t('zeitsperre/istGroesserAlsBisDatum');?> ' + document.getElementById('bisdatum').value); document.getElementById('vondatum').focus(); - return false; - } - else if (diff>14) - { - Check = confirm('t('zeitaufzeichnung/zeitraumAuffallendHoch');?>'); + return false; + } + else if (diff > 14 && diff < diffmax) { + Check = confirm('t('zeitaufzeichnung/zeitraumAuffallendHoch');?>'); document.getElementById('bisdatum').focus(); - if (Check == false) - return false; - else - return true; - } - + if (Check == false) + return false; + else + return true; + } else if (diff >= diffmax) { + alert('t('zeitsperre/bisDatumGroesserMax');?> '); + document.getElementById('bisdatum').focus(); + return false; + } return true; } @@ -445,7 +456,8 @@ if(isset($_GET['type']) && ($_GET['type']=='edit_sperre' || $_GET['type']=='new_ $date=explode('.',$_POST['bisdatum']); if (@checkdate($date[1], $date[0], $date[2])) { - $bisdatum=$date[2].$date[1].$date[0]; + $bisdatum=$date[2].$date[1].$date[0]; + $bisdatum_iso = $date[2].'-'.$date[1].'-'.$date[0]; } else { @@ -464,6 +476,17 @@ if(isset($_GET['type']) && ($_GET['type']=='edit_sperre' || $_GET['type']=='new_ $error_msg .= $p->t('zeitsperre/vonDatumGroesserAlsBisDatum').'! '; } + //check if bis-Datum zu weit in der Zukunft + $bis = new DateTime($bisdatum); + $von = new DateTime($vondatum); + + $intervall = $bis->diff($von); + if ($intervall->days >= $maxDauerZS) + { + $error=true; + $error_msg = $p->t('zeitsperre/bisDatumGroesserMax'); + } + //von-datum pruefen TODO if($vondatum_iso < $gesperrt_bis && in_array($_POST['zeitsperretyp_kurzbz'],$typen_arr)) { diff --git a/cis/private/tools/suche.php b/cis/private/tools/suche.php index 52dbc2385..09d63b12a 100644 --- a/cis/private/tools/suche.php +++ b/cis/private/tools/suche.php @@ -126,6 +126,9 @@ if (!$searchPerson && !$searchOrt && !$searchDms && !$searchContent && !$searchO function searchPerson($searchItems) { + if (defined('CIS_ALLOW_PERSON_SEARCH') && !CIS_ALLOW_PERSON_SEARCH) + return false; + global $db, $p, $noalias, $uid; $bn = new benutzer(); //search only active and Mitarbeiter with positive Personalnr @@ -172,9 +175,6 @@ function searchPerson($searchItems) '; foreach($bn->result as $row) { - $bisverwendung = new bisverwendung(); - $bisverwendung->getLastAktVerwendung($row->uid); - echo ''; //echo '',$row->titelpre,''; echo '',$row->anrede,''; @@ -185,21 +185,16 @@ function searchPerson($searchItems) echo '',$row->vorname, ''; echo ''; - if(!defined('CIS_SUCHE_PROFIL_ANZEIGEN')) - echo '',$row->nachname,''; - else if(!CIS_SUCHE_PROFIL_ANZEIGEN) - { - $mitarbeiter = new Mitarbeiter($uid); - if($mitarbeiter->errormsg === NULL) - echo '',$row->nachname,''; - else + + $mitarbeiter = new Mitarbeiter(); + if (defined('CIS_SUCHE_PROFIL_ANZEIGEN') && CIS_SUCHE_PROFIL_ANZEIGEN === false && !$mitarbeiter->load($uid)) echo $row->nachname; - } else echo '',$row->nachname,''; + if($row->aktiv==false) echo ' (ausgeschieden)'; - elseif($bisverwendung->beschausmasscode=='5') + elseif(isKarenziert($row->uid)) echo ' (karenziert)'; echo ''; //echo '',$row->titelpost,''; @@ -262,6 +257,47 @@ function searchPerson($searchItems) else return false; } + +function isKarenziert($uid) +{ + global $db; + + if(defined('DIENSTVERHAELTNIS_SUPPORT') && DIENSTVERHAELTNIS_SUPPORT) + { + $qry =" + SELECT + 1 + FROM + hr.tbl_dienstverhaeltnis + JOIN hr.tbl_vertragsbestandteil USING(dienstverhaeltnis_id) + JOIN hr.tbl_vertragsbestandteil_karenz USING(vertragsbestandteil_id) + WHERE + tbl_dienstverhaeltnis.mitarbeiter_uid=".$db->db_add_param($uid)." + AND tbl_vertragsbestandteil.von<=now() AND tbl_vertragsbestandteil.bis>=now() + "; + + if($result = $db->db_query($qry)) + { + if($db->db_num_rows($result)>0) + return true; + else + return false; + } + else + return false; + } + else + { + $bisverwendung = new bisverwendung(); + $bisverwendung->getLastAktVerwendung($uid); + + if($bisverwendung->beschausmasscode=='5') + return true; + else + return false; + } +} + function searchOE($searchItems) { global $db, $p, $noalias; @@ -332,8 +368,6 @@ function searchOE($searchItems) $mitarbeiter->load($bf->uid); $kontakt = new kontakt(); $kontakt->loadFirmaKontakttyp($mitarbeiter->standort_id,'telefon'); - $bisverwendung = new bisverwendung(); - $bisverwendung->getLastAktVerwendung($bf->uid); $benutzer = new benutzer($bf->uid); if ($benutzer->bnaktiv) { @@ -341,8 +375,8 @@ function searchOE($searchItems) echo ''.$person->vorname.''; echo '',$person->nachname,''; echo ''.$bf->bezeichnung; - if($bisverwendung->beschausmasscode=='5') - echo ' (karenziert)'; + if( isKarenziert($bf->uid)) + echo ' (karenziert)'; echo ''; // Display phone number diff --git a/cis/private/tools/zeitaufzeichnung.php b/cis/private/tools/zeitaufzeichnung.php index 46834190b..17c826c28 100644 --- a/cis/private/tools/zeitaufzeichnung.php +++ b/cis/private/tools/zeitaufzeichnung.php @@ -41,11 +41,10 @@ require_once('../../../include/service.class.php'); require_once('../../../include/mitarbeiter.class.php'); require_once('../../../include/betriebsmittelperson.class.php'); require_once('../../../include/globals.inc.php'); -require_once('../../../include/bisverwendung.class.php'); -require_once('../../../include/studiensemester.class.php'); require_once('../../../include/benutzerberechtigung.class.php'); require_once('../../../include/zeitaufzeichnung_import_csv.class.php'); require_once('../../../include/zeitaufzeichnung_import_post.class.php'); +require_once('../../../include/vertragsbestandteil.class.php'); $sprache = getSprache(); $p=new phrasen($sprache); @@ -229,6 +228,21 @@ $( document ).ready(function() '; +echo << + $(document).ready(function() { + const scrollDiv = document.createElement('div'); + scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'; + document.body.appendChild(scrollDiv); + const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + var marginright = Math.max((20 - scrollbarWidth), 0); + document.body.style.setProperty('width', 'calc(100% - ' + marginright + 'px)'); + }); + + +EOSBJS; + echo ' @@ -598,7 +622,7 @@ if($frage->frage_id!='') $display_well = $frage->nummer == 0 ? '' : 'well'; // don't style frage 0 because this is always the introduction to gebiet echo ' -
+
'. $frage->text. '
diff --git a/cis/testtool/gebietfertig.php b/cis/testtool/gebietfertig.php index d8f9982d0..cf0a86ae2 100644 --- a/cis/testtool/gebietfertig.php +++ b/cis/testtool/gebietfertig.php @@ -50,9 +50,22 @@ $p = new phrasen($sprache_user); - + +




t('testtool/zeitAbgelaufen');?>

diff --git a/cis/testtool/login.php b/cis/testtool/login.php index 0ff84f4a0..d1944fe7a 100644 --- a/cis/testtool/login.php +++ b/cis/testtool/login.php @@ -126,10 +126,6 @@ if (isset($_REQUEST['prestudent'])) $rt->getReihungstestPerson($ps->person_id); if (isset($rt->result[0])) $reihungstest_id = $rt->result[0]->reihungstest_id; - else - { - $alertmsg .= '
'.$p->t('testtool/reihungstestKannNichtGeladenWerden').'
'; - } } else { @@ -138,10 +134,6 @@ if (isset($_REQUEST['prestudent'])) // TODO Was ist wenn da mehrere Zurueckkommen?! if (isset($rt->result[0])) $reihungstest_id = $rt->result[0]->reihungstest_id; - else - { - $alertmsg .= '
'.$p->t('testtool/reihungstestKannNichtGeladenWerden').'
'; - } } else { @@ -434,6 +426,26 @@ if (isset($_POST['save']) && isset($_SESSION['prestudent_id'])) });'; ?> + $(document).bind('cut copy paste', function(e) + { + if (document.querySelector('.frage')) + { + e.preventDefault(); + } + }); + + $(document).on("keydown", function (e) + { + if (((e.ctrlKey || e.metaKey) && e.keyCode === 85) || e.keyCode === 123) + { + e.preventDefault(); + } + }); + + $(document).on("contextmenu", function (e) + { + e.preventDefault(); + }); // If Browser is any other than Mozilla Firefox and the test includes any MathML, // show message to use Mozilla Firefox var ua = navigator.userAgent; diff --git a/cis/testtool/menu.php b/cis/testtool/menu.php index 11fbc61d5..7c8b12b9d 100644 --- a/cis/testtool/menu.php +++ b/cis/testtool/menu.php @@ -414,7 +414,17 @@ else + +




t('testtool/prueflingGesperrt');?>

diff --git a/cis/testtool/topbar.php b/cis/testtool/topbar.php index 8432d4f41..7ca218ede 100644 --- a/cis/testtool/topbar.php +++ b/cis/testtool/topbar.php @@ -71,6 +71,18 @@ function changeSprache(sprache) parent.menu.location.href = parent.menu.location.pathname + '?sprache_user=' + sprache; // refreshes menu.php parent.content.location.href = parent.content.location.pathname + '?' + content_params; // refreshes login.php or frage.php } + + $(document).on("keydown", function (e) { + if (((e.ctrlKey || e.metaKey) && e.keyCode === 85) || e.keyCode === 123) + { + e.preventDefault(); + } + }); + + $(document).on("contextmenu", function (e) + { + e.preventDefault(); + }); =5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.0.5" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2015-06-14T21:17:01+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.x" + }, + "time": "2017-10-19T19:58:43+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.18.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { @@ -1878,32 +2185,36 @@ "parser", "php" ], - "time": "2022-05-31T20:59:12+00:00" + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" + }, + "time": "2023-12-10T21:03:43+00:00" }, { "name": "pdepend/pdepend", - "version": "2.10.3", + "version": "2.16.2", "source": { "type": "git", "url": "https://github.com/pdepend/pdepend.git", - "reference": "da3166a06b4a89915920a42444f707122a1584c9" + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/da3166a06b4a89915920a42444f707122a1584c9", - "reference": "da3166a06b4a89915920a42444f707122a1584c9", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/f942b208dc2a0868454d01b29f0c75bbcfc6ed58", + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58", "shasum": "" }, "require": { "php": ">=5.3.7", - "symfony/config": "^2.3.0|^3|^4|^5|^6.0", - "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0", - "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0" + "symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/polyfill-mbstring": "^1.19" }, "require-dev": { "easy-doc/easy-doc": "0.0.0|^1.2.3", "gregwar/rst": "^1.0", - "phpunit/phpunit": "^4.8.36|^5.7.27", "squizlabs/php_codesniffer": "^2.0.0" }, "bin": [ @@ -1925,26 +2236,315 @@ "BSD-3-Clause" ], "description": "Official version of pdepend to be handled with Composer", - "time": "2022-02-23T07:53:09+00:00" + "keywords": [ + "PHP Depend", + "PHP_Depend", + "dev", + "pdepend" + ], + "support": { + "issues": "https://github.com/pdepend/pdepend/issues", + "source": "https://github.com/pdepend/pdepend/tree/2.16.2" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend", + "type": "tidelift" + } + ], + "time": "2023-12-17T18:09:59+00:00" }, { - "name": "phpmd/phpmd", - "version": "2.12.0", + "name": "phar-io/manifest", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/phpmd/phpmd.git", - "reference": "c0b678ba71902f539c27c14332aa0ddcf14388ec" + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/c0b678ba71902f539c27c14332aa0ddcf14388ec", - "reference": "c0b678ba71902f539c27c14332aa0ddcf14388ec", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/master" + }, + "time": "2017-03-05T18:14:27+00:00" + }, + { + "name": "phar-io/version", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/master" + }, + "time": "2017-03-05T17:38:23+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" + }, + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "^1.0.5", + "mockery/mockery": "^1.0", + "phpdocumentor/type-resolver": "0.4.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/4.x" + }, + "time": "2019-12-28T18:55:12+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.5.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "cf842904952e64e703800d094cdf34e715a8a3ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/cf842904952e64e703800d094cdf34e715a8a3ae", + "reference": "cf842904952e64e703800d094cdf34e715a8a3ae", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/master" + }, + "time": "2017-12-30T13:23:38+00:00" + }, + { + "name": "phpmd/phpmd", + "version": "2.15.0", + "source": { + "type": "git", + "url": "https://github.com/phpmd/phpmd.git", + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/74a1f56e33afad4128b886e334093e98e1b5e7c0", + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0", "shasum": "" }, "require": { "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", "ext-xml": "*", - "pdepend/pdepend": "^2.10.3", + "pdepend/pdepend": "^2.16.1", "php": ">=5.3.9" }, "require-dev": { @@ -1953,8 +2553,7 @@ "ext-simplexml": "*", "gregwar/rst": "^1.0", "mikey179/vfsstream": "^1.6.8", - "phpunit/phpunit": "^4.8.36 || ^5.7.27", - "squizlabs/php_codesniffer": "^2.0" + "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2" }, "bin": [ "src/bin/phpmd" @@ -1991,26 +2590,38 @@ "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", "homepage": "https://phpmd.org/", "keywords": [ + "dev", "mess detection", "mess detector", "pdepend", "phpmd", "pmd" ], - "time": "2022-03-24T13:33:01+00:00" + "support": { + "irc": "irc://irc.freenode.org/phpmd", + "issues": "https://github.com/phpmd/phpmd/issues", + "source": "https://github.com/phpmd/phpmd/tree/2.15.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd", + "type": "tidelift" + } + ], + "time": "2023-12-11T08:22:20+00:00" }, { "name": "phpmetrics/phpmetrics", - "version": "v2.8.1", + "version": "v2.8.2", "source": { "type": "git", "url": "https://github.com/phpmetrics/PhpMetrics.git", - "reference": "e279f7317390f642339941b693359e9a181817a7" + "reference": "4b77140a11452e63c7a9b98e0648320bf6710090" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmetrics/PhpMetrics/zipball/e279f7317390f642339941b693359e9a181817a7", - "reference": "e279f7317390f642339941b693359e9a181817a7", + "url": "https://api.github.com/repos/phpmetrics/PhpMetrics/zipball/4b77140a11452e63c7a9b98e0648320bf6710090", + "reference": "4b77140a11452e63c7a9b98e0648320bf6710090", "shasum": "" }, "require": { @@ -2061,7 +2672,242 @@ "quality", "testing" ], - "time": "2022-03-24T10:19:51+00:00" + "support": { + "issues": "https://github.com/PhpMetrics/PhpMetrics/issues", + "source": "https://github.com/phpmetrics/PhpMetrics/tree/v2.8.2" + }, + "time": "2023-03-08T15:03:36+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "v1.10.3", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "451c3cd1418cf640de218914901e51b064abb093" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" + }, + "time": "2020-03-05T15:02:03+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "5.3.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.0", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^2.0.1", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-xdebug": "^2.5.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/5.3" + }, + "time": "2018-04-06T15:36:58+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "irc": "irc://irc.freenode.net/phpunit", + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/1.4.5" + }, + "time": "2017-11-27T13:52:08+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + }, + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -2110,8 +2956,218 @@ "keywords": [ "timer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/master" + }, "time": "2017-02-26T11:10:40+00:00" }, + { + "name": "phpunit/php-token-stream", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "791198a2c6254db10131eecfe8c06670700904db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" + }, + "abandoned": true, + "time": "2017-11-27T05:48:46+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "6.5.14", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bac23fe7ff13dbdb461481f706f0e9fe746334b7", + "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^1.0.9", + "phpunit/phpunit-mock-objects": "^5.0.9", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^2.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2", + "phpunit/dbunit": "<3.0" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "^1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.5.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/6.5.14" + }, + "time": "2019-02-01T05:22:47+00:00" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "5.0.10", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/cd1cf05c553ecfec36b170070573e540b67d3f1f", + "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.5", + "php": "^7.0", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" + }, + "conflict": { + "phpunit/phpunit": "<6.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5.11" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues", + "source": "https://github.com/sebastianbergmann/phpunit-mock-objects/tree/5.0.10" + }, + "abandoned": true, + "time": "2018-08-09T05:50:03+00:00" + }, { "name": "psr/container", "version": "1.0.0", @@ -2159,6 +3215,10 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/master" + }, "time": "2017-02-14T16:28:37+00:00" }, { @@ -2206,8 +3266,321 @@ "psr", "psr-3" ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, "time": "2021-05-03T11:20:27+00:00" }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:15:22+00:00" + }, + { + "name": "sebastian/comparator", + "version": "2.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/diff": "^2.0 || ^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/master" + }, + "time": "2018-02-01T13:46:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/master" + }, + "time": "2017-08-03T08:09:46+00:00" + }, + { + "name": "sebastian/environment", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/master" + }, + "time": "2017-07-01T08:51:00+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/73a9676f2833b9a7c36968f9d882589cd75511e6", + "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:00:17+00:00" + }, { "name": "sebastian/finder-facade", "version": "1.2.2", @@ -2245,9 +3618,180 @@ ], "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", "homepage": "https://github.com/sebastianbergmann/finder-facade", + "support": { + "issues": "https://github.com/sebastianbergmann/finder-facade/issues", + "source": "https://github.com/sebastianbergmann/finder-facade/tree/master" + }, "abandoned": true, "time": "2017-11-18T17:31:49+00:00" }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/2.0.0" + }, + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:40:27+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:37:18+00:00" + }, { "name": "sebastian/phpcpd", "version": "3.0.1", @@ -2296,8 +3840,122 @@ ], "description": "Copy/Paste Detector (CPD) for PHP code.", "homepage": "https://github.com/sebastianbergmann/phpcpd", + "support": { + "issues": "https://github.com/sebastianbergmann/phpcpd/issues", + "source": "https://github.com/sebastianbergmann/phpcpd/tree/master" + }, + "abandoned": true, "time": "2017-11-16T08:49:28+00:00" }, + { + "name": "sebastian/recursion-context", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:34:24+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/master" + }, + "time": "2015-07-28T20:34:47+00:00" + }, { "name": "sebastian/version", "version": "2.0.1", @@ -2339,6 +3997,10 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/master" + }, "time": "2016-10-03T07:35:21+00:00" }, { @@ -2346,12 +4008,12 @@ "version": "3.6.2", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a", "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a", "shasum": "" }, @@ -2390,6 +4052,25 @@ "phpcs", "standards" ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], "time": "2021-12-12T21:44:58+00:00" }, { @@ -2449,6 +4130,23 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/config/tree/v3.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-10-24T10:57:07+00:00" }, { @@ -2516,6 +4214,23 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/console/tree/v3.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-10-24T10:57:07+00:00" }, { @@ -2567,6 +4282,23 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug/tree/v3.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "abandoned": "symfony/error-handler", "time": "2020-10-24T10:57:07+00:00" }, @@ -2634,6 +4366,23 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v3.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-10-24T10:57:07+00:00" }, { @@ -2679,6 +4428,23 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v3.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-10-24T10:57:07+00:00" }, { @@ -2723,6 +4489,23 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v3.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-11-16T17:02:08+00:00" }, { @@ -2786,6 +4569,23 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.19.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-10-23T09:01:57+00:00" }, { @@ -2829,8 +4629,109 @@ ], "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", "homepage": "https://github.com/theseer/fDOMDocument", + "support": { + "issues": "https://github.com/theseer/fDOMDocument/issues", + "source": "https://github.com/theseer/fDOMDocument/tree/1.6.7" + }, "abandoned": true, "time": "2022-01-25T23:10:35+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/master" + }, + "time": "2019-06-13T22:48:21+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<3.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.9.1" + }, + "time": "2020-07-08T17:02:28+00:00" } ], "aliases": [], @@ -2842,5 +4743,5 @@ "php": ">=5.6.40" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/config/cis.config-default.inc.php b/config/cis.config-default.inc.php index 27e0a9a70..b61ce9869 100644 --- a/config/cis.config-default.inc.php +++ b/config/cis.config-default.inc.php @@ -129,6 +129,8 @@ define('MAILVERTEILER_SPERRE', true); // Bezeichnung des Campus define('CAMPUS_NAME','FH Technikum Wien'); +define('CI_ENVIRONMENT', 'development'); // Code igniter environment variable + // Anzahl der Tag die eine Nachricht am Pinboard angezeigt wird. define("MAXNEWSALTER",60); // Anzahl der Newseintraege die maximal angezeigt werden @@ -294,5 +296,4 @@ define ('DEFAULT_ALLIN_DIENSTVERTRAG',[111]); //Echter Dienstvertrag define ('DEFAULT_ECHTER_DIENSTVERTRAG',[103,111]); - ?> diff --git a/config/global.config-default.inc.php b/config/global.config-default.inc.php index 8990bbd81..b945a15d2 100644 --- a/config/global.config-default.inc.php +++ b/config/global.config-default.inc.php @@ -47,6 +47,9 @@ define('CIS_PROFIL_STUDIENINFORMATION_ANZEIGEN',true); // Zeitaufzeichnung gesperrt_bis Datum YYYY-MM-DD define('CIS_ZEITAUFZEICHNUNG_GESPERRT_BIS',''); +// maximale Dauer einer Zeitsperre in Tagen +define('CIS_ZEITSPERREN_MAX_DAUER', 730); + // Anzeige des Links zur Noteneingabe in der LVA Uebersicht define('CIS_LVALISTE_NOTENEINGABE_ANZEIGEN',true); @@ -54,8 +57,13 @@ define('CIS_LVALISTE_NOTENEINGABE_ANZEIGEN',true); define('CIS_SUCHE_LVPLAN_ANZEIGEN',true); // Anzeige des Links zum Profil von Personen bei globaler Suche +// Wenn ein Mitarbeiter sucht, wird der Link IMMER angezeigt, unabhängig von der Config +// Wenn ein Studierender sucht und die Config auf false ist, wird der Link nicht angezeigt - ansonsten schon define('CIS_SUCHE_PROFIL_ANZEIGEN',true); +// Anzeige von Personen bei globaler Suche +define('CIS_ALLOW_PERSON_SEARCH', true); + // Soll geprueft werden ob das Passwort innerhalb des letzten Jahres geaendert wurde true|false // Wenn dies nicht geaendert wurde wird nach dem Login auf die Passwort aendern Seite umgeleitet define('CIS_CHECK_PASSWORD_CHANGE',false); @@ -319,4 +327,11 @@ define ('ZAHLUNGSBESTAETIGUNG_ZAHLUNGSREFERENZ_ANZEIGEN', false); define('DOCSBOX_ENABLED', false); +// Aktiviert Abfragen auf die Dienstverhaeltnisse im HR Schema anstatt auf die BIS-Verwendung +// Uebergangsphase bis zur entfernung der BIS-Verwendungen +// (true | false) +define('DIENSTVERHAELTNIS_SUPPORT', false); + +// Falls Studstatus (Abmeldung, AbmeldungStg, Unterbrechung, Wiederholung) verwendet wird zeige Hinweistext bei Eingabe einer kommissionellen oder zusaetzlichen kommissionellen Pruefung +define('FAS_STUDSTATUS_SHOW_KOMM_PRFG_HINT', false); ?> diff --git a/config/vilesci.config-default.inc.php b/config/vilesci.config-default.inc.php index fdd971be0..09f33ee31 100644 --- a/config/vilesci.config-default.inc.php +++ b/config/vilesci.config-default.inc.php @@ -266,6 +266,8 @@ define('BIS_FUNKTIONSCODE_6_ARR', array( // bPk Abfrage define('BPK_FUER_ALLE_BENUTZER_ABFRAGEN', false); +// bPk Typen in Form 'BEREICH' => 'kennzeichenTyp' +define('VBPK_TYPES', array('AS' => 'vbpkAs', 'BF' => 'vbpkBf', 'ZP-TD' => 'vbpkTd')); // Docsbox configs define('DOCSBOX_SERVER', 'http://docconverter.technikum-wien.at/'); @@ -276,8 +278,14 @@ define('DOCSBOX_WAITING_SLEEP_TIME', 1); // Bei folgenden Buchungstypen wird ein Anlegen geprüft ob bereits ein Eintrag für diesen Typ vorhanden ist im selben // Semester und ggf ein Hinweis ausgegeben define('FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK', serialize( - array('StudiengebuehrAnzahlung', 'Studiengebuehr', 'StudiengebuehrRestzahlung', 'OEH') -)); + array( + 'Studiengebuehr' => array('StudiengebuehrErhoeht', 'Studiengebuehr', 'StudiengebuehrAnzahlung', 'StudiengebuehrRestzahlung'), + 'StudiengebuehrErhoeht' => array('StudiengebuehrErhoeht', 'Studiengebuehr', 'StudiengebuehrAnzahlung', 'StudiengebuehrRestzahlung'), + 'StudiengebuehrAnzahlung' => array('StudiengebuehrErhoeht', 'Studiengebuehr', 'StudiengebuehrAnzahlung'), + 'StudiengebuehrRestzahlung' => array('StudiengebuehrErhoeht', 'Studiengebuehr', 'StudiengebuehrRestzahlung'), + 'OEH' => array('OEH') + )) +); // Spezialnoten die am Zeunigs und Diplomasupplement ignoriert werden define('ZEUGNISNOTE_NICHT_ANZEIGEN',serialize(array('iar', 'nz'))); @@ -289,4 +297,13 @@ define ('DEFAULT_LEHRMODUS','regulaer'); //Echter Dienstvertrag define ('DEFAULT_ECHTER_DIENSTVERTRAG',[103,110]); +//Buchungstypen die fix auf eine bestimmte Kostenstelle gebucht werden sollen +//Buchungstyp => Studiengang_kz +define('FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE', serialize( + array( + 'Test_1' => 0, + 'Test_2' => 2 + ) +)); + ?> diff --git a/content/dragboard.js.php b/content/dragboard.js.php index 6510cfc47..9f720c57a 100644 --- a/content/dragboard.js.php +++ b/content/dragboard.js.php @@ -385,6 +385,7 @@ var LeLektorDDObserver= req.add('lehreinheit_id', lehreinheit_id); req.add('mitarbeiter_uid', uid); + req.add('studiensemester_kurzbz', getStudiensemester()); var response = req.executePOST(); diff --git a/content/fas.xul.php b/content/fas.xul.php index 80efdb2f9..29515eae6 100644 --- a/content/fas.xul.php +++ b/content/fas.xul.php @@ -140,6 +140,10 @@ foreach($addon_obj->result as $addon) + + + + @@ -507,19 +511,52 @@ foreach($addon_obj->result as $addon) label = "&menu-dokumente-zutrittskarte.label;" command = "menu-dokumente-zutrittskarte:command" accesskey = "&menu-dokumente-zutrittskarte.accesskey;"/> + + + + + + + + - + + accesskey = "&menu-dokumente-inskriptionsbestaetigungeng.accesskey;" + /> new=true; $fixangestellt=false; - //Stundensatz aus tbl_mitarbeiter holen - $mitarbeiter = new mitarbeiter(); - if ($mitarbeiter->load($_POST['mitarbeiter_uid'])) + //"lehre" Stundensatz aus hr.tbl_stundensatz holen + + $studiensemester = new studiensemester(); + if (!$studiensemester->load($_POST['studiensemester_kurzbz'])) { - $fixangestellt = $mitarbeiter->fixangestellt; - $lem->stundensatz = $mitarbeiter->stundensatz; + $return = false; + $error = true; + $errormsg = 'Fehler beim Laden des Studiensemesters'; + } - if (defined('FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ') - && !FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ) + if (!$error) + { + $mitarbeiter = new mitarbeiter(); + if ($mitarbeiter->load($_POST['mitarbeiter_uid'])) { - $stsem = new studiensemester(); - $stsem->load($semester_aktuell); - $bisverwendung = new bisverwendung(); - $data = $mitarbeiter->stundensatz; - if(!$bisverwendung->getVerwendungRange($mitarbeiter->uid, $stsem->start, $stsem->ende)) + $fixangestellt = $mitarbeiter->fixangestellt; + + $stundensatz = new stundensatz(); + $stundensatz->getStundensatzDatum($mitarbeiter->uid, $studiensemester->start, $studiensemester->ende, 'lehre'); + $lem->stundensatz = $stundensatz->stundensatz; + + if (defined('FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ') + && !FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ) { - $bisverwendung->getLastAktVerwendung($mitarbeiter->uid); - $bisverwendung->result[] = $bisverwendung; - } - - foreach($bisverwendung->result as $row_verwendung) - { - // Bei echten Dienstvertraegen mit voller inkludierter Lehre wird kein Stundensatz - // geliefert da dies im Vertrag inkludiert ist. - - if ((in_array($row_verwendung->ba1code, $arrEchterDV)) && $row_verwendung->inkludierte_lehre == -1) + $stsem = new studiensemester(); + $stsem->load($semester_aktuell); + $bisverwendung = new bisverwendung(); + + if(!$bisverwendung->getVerwendungRange($mitarbeiter->uid, $stsem->start, $stsem->ende)) { - $fixangestellt = true; - $lem->stundensatz = ''; - - break; + $bisverwendung->getLastAktVerwendung($mitarbeiter->uid); + $bisverwendung->result[] = $bisverwendung; + } + + foreach($bisverwendung->result as $row_verwendung) + { + // Bei echten Dienstvertraegen mit voller inkludierter Lehre wird kein Stundensatz + // geliefert da dies im Vertrag inkludiert ist. + + if ((in_array($row_verwendung->ba1code, $arrEchterDV)) && $row_verwendung->inkludierte_lehre == -1) + { + $fixangestellt = true; + $lem->stundensatz = ''; + break; + } } } } else { - $lem->stundensatz = $mitarbeiter->stundensatz; + $error=true; + $return=false; + $errormsg='Mitarbeiter '.$db->convert_html_chars($_POST['mitarbeiter_uid']).' wurde nicht gefunden'; } } - else - { - $error=true; - $return=false; - $errormsg='Mitarbeiter '.$db->convert_html_chars($_POST['mitarbeiter_uid']).' wurde nicht gefunden'; - } $maxstunden=9999; @@ -1556,49 +1567,61 @@ if(!$error) } elseif(isset($_POST['type']) && $_POST['type']=='getstundensatz') { - if(isset($_POST['mitarbeiter_uid'])) + if(isset($_POST['mitarbeiter_uid']) && isset($_POST['studiensemester_kurzbz'])) { - $mitarbeiter = new mitarbeiter(); - if($mitarbeiter->load($_POST['mitarbeiter_uid'])) + $studiensemester = new studiensemester(); + if (!$studiensemester->load($_POST['studiensemester_kurzbz'])) { - if (defined('FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ') - && !FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ) + $return = false; + $error = true; + $errormsg = 'Fehler beim Laden des Studiensemesters'; + } + + if (!$error) + { + $mitarbeiter = new mitarbeiter(); + if($mitarbeiter->load($_POST['mitarbeiter_uid'])) { - $stsem = new studiensemester(); - $stsem->load($semester_aktuell); - $bisverwendung = new bisverwendung(); - $data = $mitarbeiter->stundensatz; - if(!$bisverwendung->getVerwendungRange($mitarbeiter->uid, $stsem->start, $stsem->ende)) + $stundensatz = new stundensatz(); + $stundensatz->getStundensatzDatum($mitarbeiter->uid, $studiensemester->start, $studiensemester->ende, 'lehre'); + $data = $stundensatz->stundensatz; + + if (defined('FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ') + && !FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ) { - $bisverwendung->getLastAktVerwendung($mitarbeiter->uid); - $bisverwendung->result[] = $bisverwendung; - } - - foreach($bisverwendung->result as $row_verwendung) - { - - // Bei echten Dienstvertraegen mit voller inkludierter Lehre wird kein Stundensatz - // geliefert da dies im Vertrag inkludiert ist. - if ((in_array($row_verwendung->ba1code, $arrEchterDV)) && $row_verwendung->inkludierte_lehre == -1) + $stsem = new studiensemester(); + $stsem->load($semester_aktuell); + $bisverwendung = new bisverwendung(); + if(!$bisverwendung->getVerwendungRange($mitarbeiter->uid, $stsem->start, $stsem->ende)) { - $data = ''; - break; + $bisverwendung->getLastAktVerwendung($mitarbeiter->uid); + $bisverwendung->result[] = $bisverwendung; + } + + foreach($bisverwendung->result as $row_verwendung) + { + + // Bei echten Dienstvertraegen mit voller inkludierter Lehre wird kein Stundensatz + // geliefert da dies im Vertrag inkludiert ist. + if ((in_array($row_verwendung->ba1code, $arrEchterDV)) && $row_verwendung->inkludierte_lehre == -1) + { + $data = ''; + break; + } } } + $return = true; } else - $data = $mitarbeiter->stundensatz; - $return = true; - } - else - { - $errormsg = 'Fehler beim Laden des Mitarbeitenden'; - $return = false; + { + $errormsg = 'Fehler beim Laden des Mitarbeitenden'; + $return = false; + } } } else { - $errormsg = 'MitarbeitendeUID muss uebergeben werden'; + $errormsg = 'MitarbeitendeUID und Studiensemester muessen uebergeben werden'; $return = false; } } diff --git a/content/lvplanung/lehrveranstaltungnotenoverlay.xul.php b/content/lvplanung/lehrveranstaltungnotenoverlay.xul.php index fda16c07a..033bd7344 100644 --- a/content/lvplanung/lehrveranstaltungnotenoverlay.xul.php +++ b/content/lvplanung/lehrveranstaltungnotenoverlay.xul.php @@ -122,7 +122,7 @@ echo "