diff --git a/.gitignore b/.gitignore index 96af3e5dc..84957a801 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ documents/ vendor/ /nbproject/ +.vscode +composer.phar /.idea/ .settings .project 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 c2e38385c..6713ef37d 100644 --- a/application/config/anrechnung.php +++ b/application/config/anrechnung.php @@ -1,15 +1,11 @@ TRUE, + 'referenzbeispiele_ects' => TRUE, + 'voraussetzungen' => TRUE, + 'nachweisdokumente' => TRUE, + 'herkunft_kenntnisse' => TRUE +]; diff --git a/application/config/cis.php b/application/config/cis.php new file mode 100644 index 000000000..b7330ef29 --- /dev/null +++ b/application/config/cis.php @@ -0,0 +1,9 @@ +. + */ + +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/javascript.php b/application/config/javascript.php new file mode 100644 index 000000000..5e9aa270a --- /dev/null +++ b/application/config/javascript.php @@ -0,0 +1,7 @@ +. + */ + +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 5f3414759..2327513ad 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -1,6 +1,12 @@ array( 'fhcomplete' => array( @@ -31,6 +37,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' ) ) ), @@ -42,11 +56,17 @@ $config['navigation_header'] = array( 'requiredPermissions' => 'basis/vilesci:r', 'children' => array( 'cis' => array( - 'link' => CIS_ROOT, + 'link' => $root, 'icon' => '', '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', @@ -120,11 +140,18 @@ $config['navigation_header'] = array( 'sort' => 30, 'requiredPermissions' => 'system/issues_verwalten:r' ), + 'plausichecks' => array( + 'link' => site_url('system/issues/Plausichecks'), + 'description' => 'Plausichecks', + 'expand' => true, + 'sort' => 40, + 'requiredPermissions' => 'system/issues_verwalten:r' + ), 'gruppenmanagement' => array( 'link' => site_url('person/Gruppenmanagement'), 'description' => 'Gruppenmanagement', 'expand' => true, - 'sort' => 40, + 'sort' => 50, 'requiredPermissions' => 'lehre/gruppenmanager:r' ) ) @@ -157,7 +184,14 @@ $config['navigation_header'] = array( 'expand' => true, 'sort' => 20, 'requiredPermissions' => 'system/developer:r' - ) + ), + 'anrechnungen' => array( + 'link' => site_url('lehre/anrechnung/AdminAnrechnung'), + 'description' => 'Anrechnungen', + 'expand' => true, + 'sort' => 30, + 'requiredPermissions' => 'lehre/anrechnungszeitfenster:rw' + ) ) ) ) @@ -177,6 +211,15 @@ $config['navigation_menu']['Vilesci/index'] = array( ) ); +$config['navigation_menu']['Vilesci/index'] = array( + 'dashboard' => array( + 'link' => '#', + 'description' => 'Dashboard', + 'icon' => 'dashboard', + 'sort' => 1 + ) +); + $config['navigation_menu']['organisation/Reihungstest/index'] = array( 'reihungstestverwalung' => array( 'link' => base_url('vilesci/stammdaten/reihungstestverwaltung.php'), @@ -186,7 +229,7 @@ $config['navigation_menu']['organisation/Reihungstest/index'] = array( 'target' => '_blank' ), 'auswertung' => array( - 'link' => CIS_ROOT.'/cis/testtool/admin/auswertung.php', + 'link' => $root.'/cis/testtool/admin/auswertung.php', 'description' => 'Auswertung', 'icon' => 'list-alt', 'sort' => 1, @@ -256,14 +299,30 @@ $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'), 'description' => 'Fehler Zuständigkeiten', - 'icon' => 'cogs', + 'icon' => 'users', 'sort' => 100, 'target' => '_blank', 'requiredPermissions' => array('admin:rw') - ) -); - + ), + 'fehlerkonfiguration' => array( + 'link' => site_url('system/issues/IssuesKonfiguration'), + 'description' => 'Fehler Konfiguration', + 'icon' => 'cogs', + 'sort' => 200, + 'target' => '_blank', + 'requiredPermissions' => array('admin:rw') + ), +); \ No newline at end of file diff --git a/application/config/routes.php b/application/config/routes.php index 15da5698f..b07497ae7 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -50,7 +50,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); | Examples: my-controller/index -> my_controller/index | my-controller/my-method -> my_controller/my_method */ -$route['default_controller'] = 'Vilesci'; +$route['default_controller'] = defined('CIS4') && CIS4 ? 'Cis4' : 'Vilesci'; $route['translate_uri_dashes'] = FALSE; // Class name conflicts @@ -61,6 +61,9 @@ $route['api/v1/organisation/[O|o]rganisationseinheit/(:any)'] = 'api/v1/organisa $route['api/v1/ressource/[B|b]etriebsmittelperson/(:any)'] = 'api/v1/ressource/betriebsmittelperson2/$1'; $route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1'; +$route['CisVue'] = 'CisVue/dashboard'; +$route['Cis/Stundenplan/(:any)'] = 'Cis/Stundenplan'; + // load routes from extensions $subdir = 'application/config/extensions'; $dirlist = scandir($subdir); @@ -81,5 +84,4 @@ if ($dirlist) } } } -} - +} \ No newline at end of file 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/Cis/Auth.php b/application/controllers/Cis/Auth.php new file mode 100644 index 000000000..59dab1568 --- /dev/null +++ b/application/controllers/Cis/Auth.php @@ -0,0 +1,77 @@ +load->helper('form'); + $this->load->helper('hlp_authentication'); + + // Loads phrases system + $this->loadPhrases([ + 'global' + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function login() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('username', 'Username', 'required|trim|callback_validation'); + $this->form_validation->set_rules('password', 'Password', 'required|trim'); + + + if ($this->form_validation->run()) + { + redirect($this->authlib->getLandingPage('/CisVue/Dashboard')); + } + else + { + $this->load->view('Cis/Login'); + } + } + + /** + * @return boolean + */ + public function validation() + { + $username = $this->input->post('username'); + $password = $this->input->post('password'); + + $this->load->library('AuthLib', [false]); // without authentication otherwise loooooop! + + $login = $this->authlib->loginLDAP($username, $password); + if (isSuccess($login)) + return true; + $this->form_validation->set_message('validation', 'Incorrect username/password.'); + return false; + } + + /** + * @return void + */ + public function logout() + { + $this->load->library('AuthLib'); + $this->authlib->logout(); + redirect('/Cis/Auth/login', 'refresh'); + } +} diff --git a/application/controllers/Cis/Documents.php b/application/controllers/Cis/Documents.php new file mode 100644 index 000000000..c5a6684d3 --- /dev/null +++ b/application/controllers/Cis/Documents.php @@ -0,0 +1,192 @@ + [self::PERM_LOGGED], + 'student' => ['admin:r'], + 'download' => [self::PERM_LOGGED] + ]); + + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + + $this->loadPhrases([ + 'global', + 'tools' + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + return $this->showDocuments(getAuthUID()); + } + + /** + * @param string $uid Administratoren dürfen die UID als Parameter übergeben um die Dokumente von anderen Personen anzuzeigen + * @return void + */ + public function student($uid) + { + return $this->showDocuments($uid); + } + + /** + * @param string $uid + * @return void + */ + protected function showDocuments($uid) + { + $this->load->model('crm/Konto_model', 'KontoModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $stati = $this->PrestudentstatusModel->loadWhereUid($uid, null, true); + if (isError($stati)) + return $this->load->view('errors/html/error_db.php', [ + 'heading' => 'Database Error', + 'message' => getError($stati) + ]); + $stati = getData($stati); + if (!$stati) + return $this->load->view('errors/html/error_general.php', [ + 'heading' => 'User ist kein Student', + 'message' => 'Es konnten keine Studiensemester gefunden werden in denen der User als Student inskripiert ist' + ]); + + $stgs = []; + $stsemArray = []; + $buchungstypen = implode('\',\'', defined("CIS_DOKUMENTE_STUDIENBEITRAG_TYPEN") ? unserialize(CIS_DOKUMENTE_STUDIENBEITRAG_TYPEN) : []); + $person_ids = []; + foreach ($stati as $status) { + $person_ids[] = $status->person_id; + + if(!in_array($status->studiensemester_kurzbz, $stsemArray)) { + $stsemArray[] = $status->studiensemester_kurzbz; + } + + if (!isset($stgs[$status->studiengang_kz])) { + $stg = $this->StudiengangModel->load($status->studiengang_kz); + if (isError($stg)) + return $this->load->view('errors/html/error_db.php', [ + 'heading' => 'Database Error', + 'message' => getError($stg) + ]); + $stg = getData($stg); + if (!$stg) + return $this->load->view('errors/html/error_db.php', [ + 'heading' => 'Database Error', + 'message' => 'No Studiengang found for studiengang_kz ' . $status->studiengang_kz + ]); + $stgs[$status->studiengang_kz] = current($stg); + $stgs[$status->studiengang_kz]->studiensemester = []; + } + if (!isset($stgs[$status->studiengang_kz]->studiensemester[$status->studiensemester_kurzbz])) { + $stgs[$status->studiengang_kz]->studiensemester[$status->studiensemester_kurzbz] = new stdClass(); + $stgs[$status->studiengang_kz]->studiensemester[$status->studiensemester_kurzbz]->inskriptionsbestaetigung = (boolean)getData( + $this->KontoModel->checkStudienbeitragFromPrestudent( + $status->prestudent_id, + $status->studiensemester_kurzbz, + $buchungstypen + ) + ); + } + } + $person_ids = array_unique($person_ids); + + $selfservice = null; + if (!defined('CIS_DOKUMENTE_SELFSERVICE') || CIS_DOKUMENTE_SELFSERVICE) { + $this->load->model('crm/Akte_model', 'AkteModel'); + $selfservice = []; + foreach ($person_ids as $person_id) { + $result = $this->AkteModel->getArchiv($person_id, null, true); + if (isError($result)) + return $this->load->view('errors/html/error_db.php', [ + 'heading' => 'Database Error', + 'message' => getError($result) + ]); + $selfservice = array_merge($selfservice, getData($result) ?: []); + } + } + + + $this->load->view('Cis/Documents', [ + 'stsemArray' => $stsemArray, + 'stgs' => $stgs, + 'uid' => $uid, + 'studienbuchblatt' => defined('CIS_DOKUMENTE_STUDIENBUCHLBATT_DRUCKEN') && CIS_DOKUMENTE_STUDIENBUCHLBATT_DRUCKEN, + 'studienerfolgsbestaetigung' => defined('CIS_DOKUMENTE_STUDIENERFOLGSBESTAETIGUNG_DRUCKEN') && CIS_DOKUMENTE_STUDIENERFOLGSBESTAETIGUNG_DRUCKEN, + 'selfservice' => $selfservice + ]); + } + + /** + * @param integer $akte_id + * @param string $uid (optional) Administratoren dürfen die UID als Parameter übergeben um die Dokumente von anderen Personen anzuzeigen + * + * @return void + */ + public function download($akte_id, $uid = null) + { + if (!is_numeric($akte_id)) + return show_404(); + + $this->load->model('crm/Akte_model', 'AkteModel'); + $result = $this->AkteModel->load($akte_id); + if (isError($result)) + return show_error(getError($result)); + $akte = getData($result); + if (!$akte) + return show_404(); + $akte = current($akte); + + $admin_access = false; + if ($uid !== null && $this->permissionlib->isBerechtigt('admin')) { + $stati = $this->PrestudentstatusModel->loadWhereUid($uid, null, true); + if (hasData($stati)) { + $person_ids = array_map(function ($status) { + return $status->person_id; + }, getData($stati)); + $person_ids = array_unique($person_ids); + if (count($person_ids) == 1 && current($person_ids) == $akte->person_id) { + $admin_access = true; + } + } + } + + if (!$admin_access && ($akte->person_id != getAuthPersonId() || !$akte->stud_selfservice)) + return show_error('Forbidden', 403); + + // NOTE(chris): Log bei einem Download vom Becheid + if (isset($akte->dokument_kurzbz) && ($akte->dokument_kurzbz === 'Bescheid' || $akte->dokument_kurzbz === 'BescheidEng')) { + $this->load->model('system/Webservicelog_model', 'WebservicelogModel'); + $this->WebservicelogModel->insert([ + 'webservicetyp_kurzbz' => 'content', + 'request_id' => (isset($akte->akte_id) && !empty($akte->akte_id)) ? $akte->akte_id : null, + 'beschreibung' => 'Bescheidbestaetigungsdownload', + 'request_data' => $_SERVER['QUERY_STRING'], + 'execute_time' => date('c'), + 'execute_user' => getAuthUID() + ]); + } + + $this->output->set_content_type($akte->mimetype); + $this->output->set_output(base64_decode($akte->inhalt)); + } +} diff --git a/application/controllers/Cis/MyLv.php b/application/controllers/Cis/MyLv.php new file mode 100644 index 000000000..08bf843b5 --- /dev/null +++ b/application/controllers/Cis/MyLv.php @@ -0,0 +1,36 @@ + ['basis/cis:r'], + 'Info' => [self::PERM_LOGGED] + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + $this->load->view('Cis/MyLv'); + } + + public function Info($studien_semester,$lvid) + { + $this->load->view('Cis/LvInfo',['lvid'=> $lvid, 'studien_semester' => $studien_semester]); + } +} diff --git a/application/controllers/Cis/Profil.php b/application/controllers/Cis/Profil.php new file mode 100644 index 000000000..e991d1976 --- /dev/null +++ b/application/controllers/Cis/Profil.php @@ -0,0 +1,737 @@ + ['basis/cis:r'], + 'foto_sperre_function' => ['basis/cis:r'], + 'getView' => ['basis/cis:r'], + 'View' => ['basis/cis:r'], + 'isMitarbeiter' => ['basis/cis:r'], + 'isStudent' => ['basis/cis:r'], + 'getZustellAdresse' => ['basis/cis:r'], + 'getZustellKontakt' => ['basis/cis:r'], + 'getAllNationen' => ['basis/cis:r'], + 'getGemeinden' => ['basis/cis:r'], + + ]); + + $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('person/Adresse_model', 'AdresseModel'); + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + $this->load->model('ressource/Betriebsmittelperson_model', 'BetriebsmittelpersonModel'); + $this->load->model('person/Kontakt_model', 'KontaktModel'); + $this->load->model('person/Profil_update_model', 'ProfilUpdateModel'); + $this->load->model('content/DmsVersion_model', 'DmsVersionModel'); + + + //? put the uid and pid inside the controller for reusability + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + + /** + * index loads the Profil view + * @access public + * @return void + */ + public function index() + { + $this->load->view('Cis/Profil'); + } + + /** + * redirects to the index function (needed to allow calling this URI) + * @access public + * @return void + */ + public function View($uid) + { + $this->load->view('Cis/Profil'); + } + + /** + * checks whether a specific userID is a mitarbeiter or not (foreword declaration of the function isMitarbeiter in Mitarbeiter_model.php) + * @access public + * @param $uid the userID used to check if it is a mitarbeiter + * @return boolean + */ + public function isStudent($uid) + { + $result = $this->StudentModel->isStudent($uid); + if (isError($result)) { + show_error("error when calling Student_model function isStudent with uid " . $uid); + } + $result = getData($result); + echo json_encode($result); + } + + /** + * checks whether a specific userID is a mitarbeiter or not (foreword declaration of the function isMitarbeiter in Mitarbeiter_model.php) + * @access public + * @param $uid the userID used to check if it is a mitarbeiter + * @return boolean + */ + public function isMitarbeiter($uid) + { + $result = $this->MitarbeiterModel->isMitarbeiter($uid); + if (isError($result)) { + show_error("error when calling Mitarbeiter_model function isMitarbeiter with uid " . $uid); + } + $result = getData($result); + echo json_encode($result); + } + + /** + * gets the adressen that are marked as zustell from the currenlty logged in user + * @access public + * @return array a list of adresse_id's + */ + public function getZustellAdresse() + { + $this->AdresseModel->addSelect(["adresse_id"]); + $adressen_res = $this->AdresseModel->loadWhere(['person_id' => $this->pid, 'zustelladresse' => true]); + $adressen_res = hasData($adressen_res) ? getData($adressen_res) : null; + $adressen_res = array_map(function ($item) { + return $item->adresse_id; + }, $adressen_res); + echo json_encode($adressen_res); + } + + /** + * gets the kontakte that are marked as zustell from the currenlty logged in user + * @access public + * @return array a list of kontakt_id's + */ + public function getZustellKontakt() + { + $this->KontaktModel->addSelect(["kontakt_id"]); + $kontakt_res = $this->KontaktModel->loadWhere(['person_id' => $this->pid, 'zustellung' => true]); + $kontakt_res = hasData($kontakt_res) ? getData($kontakt_res) : null; + $kontakt_res = array_map(function ($item) { + return $item->kontakt_id; + }, $kontakt_res); + echo json_encode($kontakt_res); + } + + /** + * function that returns the data used for the corresponding view + * the client side parses the @param $uid and calls this function to get the data to the correct view + * @access public + * @param boolean $uid the userID used to identify which information should be retrieved for which view + * @return stdClass all the data corresponding to a view of a user + */ + public function getView($uid) + { + $res = new stdClass(); + + // if parsing the URL did not found a UID then the UID of the logged in user is used + if ($uid == "Profil" || $uid == $this->uid) { + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter($this->uid); + if (isError($isMitarbeiter)) { + show_error("error while checking if UID: " . $this->uid . " is a mitarbeiter"); + } + $isMitarbeiter = getData($isMitarbeiter); + if ($isMitarbeiter) { + $res->view = "MitarbeiterProfil"; + $res->data = $this->mitarbeiterProfil(); + $res->data->pid = $this->pid; + } else { + $res->view = "StudentProfil"; + $res->data = $this->studentProfil(); + $res->data->pid = $this->pid; + } + } + // UID is availabe when accessing Profil/View/:uid + else { + $this->PersonModel->addSelect(["person_id"]); + $pid = $this->PersonModel->getByUid($uid); + if (isError($pid)) { + show_error("error while trying to update table public.tbl_person while searching for a person with UID: " . $uid); + } + $pid = hasData($pid) ? getData($pid)[0] : null; + if (!$pid) { + show_error("Person with UID: " . $uid . " does not exist"); + } + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid); + if (isError($isMitarbeiter)) { + show_error("error while checking if UID: " . $uid . " is a mitarbeiter"); + } + $isMitarbeiter = getData($isMitarbeiter); + if ($isMitarbeiter) { + $res->view = "ViewMitarbeiterProfil"; + $res->data = $this->viewMitarbeiterProfil($uid); + + } else { + $res->view = "ViewStudentProfil"; + $res->data = $this->viewStudentProfil($uid); + } + } + echo json_encode($res); + } + + /** + * update column foto_sperre in public.tbl_person + * @access public + * @param boolean $value new value for the column + * @return boolean the new value added to the column in public.tbl_person + */ + public function foto_sperre_function($value) + { + $res = $this->PersonModel->update($this->pid, ["foto_sperre" => $value]); + if (isError($res)) { + show_error("error while trying to update table public.tbl_person"); + } + $this->PersonModel->addSelect("foto_sperre"); + $res = $this->PersonModel->load($this->pid); + if (isError($res)) { + show_error("error while trying to query table public.tbl_person"); + } + $res = hasData($res) ? getData($res)[0] : null; + echo json_encode($res); + } + + /** + * gets all nations in the table bis.tbl_nation + * + * @access public + * @return array all the nations in table bis.tbl_nation + */ + public function getAllNationen() + { + $this->load->model('codex/Nation_model', "NationModel"); + $this->NationModel->addSelect(["nation_code as code", "langtext"]); + $nation_res = $this->NationModel->load(); + if (isError($nation_res)) { + show_error("error while trying to query table codex.tbl_nation"); + } + $nation_res = hasData($nation_res) ? getData($nation_res) : null; + echo json_encode($nation_res); + } + + /** + * gets specific gemeinden which are related to the ZIP and the Nation passed in the body of the get request + * @access public + * @var $_GET function uses GET request payload + * @return boolean the new value added to the column in public.tbl_person + */ + public function getGemeinden() + { + /** @var $nation value parsed out of the body of the get request */ + $nation = $this->input->get('nation', true); + /** @var $zip value parsed out of the body of the get request and converted to a php integer with json_decode */ + $zip = json_decode($this->input->get('zip', true)); + + $this->load->model('codex/Gemeinde_model', "GemeindeModel"); + $this->GemeindeModel->addDistinct(); + $this->GemeindeModel->addSelect(["name"]); + if ($nation == "A") { + if (isset($zip) && $zip > 999 && $zip < 32000) { + + $gemeinde_res = $this->GemeindeModel->loadWhere(['plz' => $zip]); + if (isError($gemeinde_res)) { + show_error("error while trying to query bis.tbl_gemeinde"); + } + $gemeinde_res = hasData($gemeinde_res) ? getData($gemeinde_res) : null; + $gemeinde_res = array_map(function ($obj) { + return $obj->name; + }, $gemeinde_res); + echo json_encode($gemeinde_res); + + } else { + echo json_encode(error("ortschaftskennziffer code was not valid")); + } + } else { + echo json_encode(error("Nation was not 'A' (Austria)")); + } + } + + + // ----------------------------------------------------------------------------------------------------------------- + // Private methods + + /** + * function that returns the data used for viewing another mitarbeiter profile + * @access private + * @param integer $uid the userID to retrieve the mitarbeiter data + * @return stdClass restricted mitarbeiter data + */ + private function viewMitarbeiterProfil($uid) + { + $mailverteiler_res = $this->getMailverteiler($uid); + $benutzer_funktion_res = $this->getBenutzerFunktion($uid); + $benutzer_res = $this->getBenutzerAlias($uid); + $person_res = $this->getPersonInfo($uid); + $mitarbeiter_res = $this->getMitarbeiterInfo($uid); + $telefon_res = $this->getTelefonInfo($uid); + + $res = new stdClass(); + $res->username = $uid; + + //? Person Info + foreach ($person_res as $key => $val) { + $res->$key = $val; + } + + //? Mitarbeiter Info + foreach ($mitarbeiter_res as $key => $val) { + $res->$key = $val; + + } + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = $uid . "@" . DOMAIN; + $extern_email = array(); + $extern_email["type"] = "alias"; + $extern_email["email"] = $benutzer_res->alias . "@" . DOMAIN; + $res->emails = array($intern_email, $extern_email); + + $res->funktionen = $benutzer_funktion_res; + $res->mailverteiler = $mailverteiler_res; + $res->standort_telefon = isset($telefon_res) ? $telefon_res->kontakt : null; + + return $res; + } + + /** + * function that returns the data used for viewing another student profile + * @access private + * @param integer $uid the userID to retrieve the student data + * @return stdClass restricted student data + */ + private function viewStudentProfil($uid) + { + $mailverteiler_res = $this->getMailverteiler($uid); + $person_res = $this->getPersonInfo($uid); + $student_res = $this->getStudentInfo($uid); + $matr_res = $this->getMatrikelNummer($uid); + + $res = new stdClass(); + $res->username = $uid; + + //? Person Information + foreach ($person_res as $key => $value) { + $res->$key = $value; + } + + //? Student Information + foreach ($student_res as $key => $value) { + $res->$key = $value; + } + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = $uid . "@" . DOMAIN; + + $res->emails = [$intern_email]; + $res->matrikelnummer = $matr_res->matr_nr; + $res->mailverteiler = $mailverteiler_res; + + return $res; + } + + /** + * function that returns the data used for the mitarbeiter profile + * @access private + * @return stdClass mitarbeiter data + */ + private function mitarbeiterProfil() + { + + $zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($this->uid); + $adresse_res = $this->getAdressenInfo($this->pid); + $kontakte_res = $this->getKontaktInfo($this->pid); + $mailverteiler_res = $this->getMailverteiler($this->uid); + $person_res = $this->getPersonInfo($this->uid, true); + $benutzer_funktion_res = $this->getBenutzerFunktion($this->uid); + $betriebsmittelperson_res = $this->getBetriebsmittelInfo($this->pid); + $profilUpdates = $this->getProfilUpdates($this->uid); + $telefon_res = $this->getTelefonInfo($this->uid); + $mitarbeiter_res = $this->getMitarbeiterInfo($this->uid); + + $res = new stdClass(); + $res->username = $this->uid; + + //? Person Information + foreach ($person_res as $key => $value) { + $res->$key = $value; + } + + //? Mitarbeiter Information + foreach ($mitarbeiter_res as $key => $value) { + $res->$key = $value; + } + + $res->adressen = $adresse_res; + $res->zutrittsdatum = $zutrittskarte_ausgegebenam; + $res->kontakte = $kontakte_res; + $res->mittel = $betriebsmittelperson_res; + $res->mailverteiler = $mailverteiler_res; + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = $this->uid . "@" . DOMAIN; + $extern_email = array(); + $extern_email["type"] = "alias"; + $extern_email["email"] = $mitarbeiter_res->alias . "@" . DOMAIN; + $res->emails = [$intern_email, $extern_email]; + + $res->funktionen = $benutzer_funktion_res; + $res->standort_telefon = $telefon_res; + $res->profilUpdates = $profilUpdates; + + return $res; + } + + /** + * function that returns the data used for the student profile + * @access private + * @return stdClass student data + */ + private function studentProfil() + { + $betriebsmittelperson_res = $this->getBetriebsmittelInfo($this->pid); + $kontakte_res = $this->getKontaktInfo($this->pid); + $zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($this->uid); + $adresse_res = $this->getAdressenInfo($this->pid); + $mailverteiler_res = $this->getMailverteiler($this->uid); + $person_res = $this->getPersonInfo($this->uid, true); + $zutrittsgruppe_res = $this->getZutrittsgruppen($this->uid); + $student_res = $this->getStudentInfo($this->uid); + $matr_res = $this->getMatrikelNummer($this->uid); + $profilUpdates = $this->getProfilUpdates($this->uid); + + $res = new stdClass(); + $res->username = $this->uid; + + //? Person Information + foreach ($person_res as $key => $value) { + $res->$key = $value; + } + + //? Student Information + foreach ($student_res as $key => $value) { + $res->$key = trim($value); + } + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = $this->uid . "@" . DOMAIN; + + $res->emails = [$intern_email]; + $res->adressen = $adresse_res; + $res->zutrittsdatum = $zutrittskarte_ausgegebenam; + $res->kontakte = $kontakte_res; + $res->mittel = $betriebsmittelperson_res; + $res->matrikelnummer = $matr_res->matr_nr; + $res->zuttritsgruppen = $zutrittsgruppe_res; + $res->mailverteiler = $mailverteiler_res; + $res->profilUpdates = $profilUpdates; + + return $res; + } + + /** + * gets all the mailverteiler using the tables: tbl_benutzer, tbl_benutzergruppe, tbl_gruppe + * @access private + * @param integer $uid the userID used to retrieve the mailverteiler + * @return array returns the mailvertailer corresponding to a userID + */ + private function getMailverteiler($uid) + { + $this->PersonModel->addSelect('gruppe_kurzbz, beschreibung'); + $this->PersonModel->addJoin('tbl_benutzer', 'person_id'); + $this->PersonModel->addJoin('tbl_benutzergruppe', 'uid'); + $this->PersonModel->addJoin('tbl_gruppe', 'gruppe_kurzbz'); + + $mailverteiler_res = $this->PersonModel->loadWhere(array('mailgrp' => true, 'uid' => $uid)); + if (isError($mailverteiler_res)) { + show_error("was not able to query the table public.tbl_benutzer:" . getData($mailverteiler_res)); + } + $mailverteiler_res = hasData($mailverteiler_res) ? getData($mailverteiler_res) : null; + $mailverteiler_res = array_map(function ($element) { + $element->mailto = "mailto:" . $element->gruppe_kurzbz . "@" . DOMAIN; + return $element; + }, $mailverteiler_res); + return $mailverteiler_res; + } + + /** + * gets all the Benutzerfunktionen of a corresponding user + * @access private + * @param integer $uid the userID used to retrieve the Benutzerfunktionen + * @return array returns the Benutzerfunktionen corresponding to a userID + */ + private function getBenutzerFunktion($uid) + { + $this->BenutzerfunktionModel->addSelect(["tbl_benutzerfunktion.bezeichnung as Bezeichnung", "tbl_organisationseinheit.bezeichnung as Organisationseinheit", "datum_von as Gültig_von", "datum_bis as Gültig_bis", "wochenstunden as Wochenstunden"]); + $this->BenutzerfunktionModel->addJoin("tbl_organisationseinheit", "oe_kurzbz"); + + $benutzer_funktion_res = $this->BenutzerfunktionModel->loadWhere(array('uid' => $uid)); + if (isError($benutzer_funktion_res)) { + show_error("was not able to query the table public.tbl_benutzerfunktion:" . getData($benutzer_funktion_res)); + } + $benutzer_funktion_res = hasData($benutzer_funktion_res) ? getData($benutzer_funktion_res) : null; + return $benutzer_funktion_res; + } + + /** + * gets all the Betriebsmittel of a corresponding user + * @access private + * @param integer $uid the userID used to retrieve the Betriebsmittel + * @return array returns the Betriebsmittel corresponding to a userID + */ + private function getBetriebsmittelInfo($pid) + { + $this->BetriebsmittelpersonModel->addSelect(["CONCAT(betriebsmitteltyp, ' ' ,beschreibung) as Betriebsmittel", "nummer as Nummer", "ausgegebenam as Ausgegeben_am"]); + + //? betriebsmittel are not needed in a view + $betriebsmittelperson_res = $this->BetriebsmittelpersonModel->getBetriebsmittel($pid); + if (isError($betriebsmittelperson_res)) { + show_error("was not able to query the table public.tbl_betriebsmittelperson:" . getData($betriebsmittelperson_res)); + } + $betriebsmittelperson_res = hasData($betriebsmittelperson_res) ? getData($betriebsmittelperson_res) : null; + return $betriebsmittelperson_res; + } + + /** + * gets the alias of a corresponding user + * @access private + * @param integer $uid the userID used to get the alias + * @return string the alias of the userID + */ + private function getBenutzerAlias($uid) + { + $this->BenutzerModel->addSelect(["alias"]); + $benutzer_res = $this->BenutzerModel->load([$uid]); + if (isError($benutzer_res)) { + show_error("was not able to query the table public.tbl_benutzer:" . getData($benutzer_res)); + } else { + $benutzer_res = hasData($benutzer_res) ? getData($benutzer_res)[0] : null; + } + + return $benutzer_res; + } + + /** + * gets the person information corresponding to a user + * @access private + * @param integer $uid the userID used to get the person information + * @param integer $geburtsInfo flag wether to add the columns gebort, gebdatum, foto_sperre or not + * @return array all the person informaion corresponding to a userID + */ + private function getPersonInfo($uid, $geburtsInfo = null) + { + $selectClause = ["foto", "anrede", "titelpost as postnomen", "titelpre as titel", "vorname", "nachname"]; + /** @param integer $geburtsInfo */ + if ($geburtsInfo) { + array_push($selectClause, "gebort"); + array_push($selectClause, "gebdatum"); + array_push($selectClause, "foto_sperre"); + } + $this->BenutzerModel->addSelect($selectClause); + $this->BenutzerModel->addJoin("tbl_person", "person_id"); + + $person_res = $this->BenutzerModel->load([$uid]); + if (isError($person_res)) { + show_error("was not able to query the table public.tbl_benutzer:" . getData($person_res)); + } else { + $person_res = hasData($person_res) ? getData($person_res)[0] : null; + } + + return $person_res; + } + + /** + * gets the mitarbeiter information corresponding to a user + * @access private + * @param integer $uid the userID used to get the mitarbeiter information + * @return array all the mitarbeiter informaion corresponding to a userID + */ + private function getMitarbeiterInfo($uid) + { + $this->MitarbeiterModel->addSelect(["kurzbz", "telefonklappe", "alias", "ort_kurzbz"]); + $this->MitarbeiterModel->addJoin("tbl_benutzer", "tbl_benutzer.uid = tbl_mitarbeiter.mitarbeiter_uid"); + $mitarbeiter_res = $this->MitarbeiterModel->load($uid); + if (isError($mitarbeiter_res)) { + show_error("was not able to query the table public.tbl_mitarbeiter:" . getData($mitarbeiter_res)); + } else { + $mitarbeiter_res = hasData($mitarbeiter_res) ? getData($mitarbeiter_res)[0] : null; + } + + return $mitarbeiter_res; + } + + /** + * gets the telefon information corresponding to a user + * @access private + * @param integer $uid the userID used to get the telefon information + * @return array all the telefon informaion corresponding to a userID + */ + private function getTelefonInfo($uid) + { + $this->MitarbeiterModel->addSelect(["kontakt"]); + $this->MitarbeiterModel->addJoin("tbl_kontakt", "tbl_mitarbeiter.standort_id = tbl_kontakt.standort_id"); + $this->MitarbeiterModel->addLimit(1); + $telefon_res = $this->MitarbeiterModel->loadWhere(["mitarbeiter_uid" => $uid, "kontakttyp" => "telefon"]); + if (isError($telefon_res)) { + show_error("was not able to query the table public.tbl_mitarbeiter:" . getData($telefon_res)); + } + $telefon_res = hasData($telefon_res) ? getData($telefon_res)[0] : null; + return $telefon_res; + } + + /** + * gets the student information corresponding to a user + * @access private + * @param integer $uid the userID used to get the student information + * @return array all the student informaion corresponding to a userID + */ + private function getStudentInfo($uid) + { + $this->StudentModel->addSelect(['tbl_studiengang.bezeichnung as studiengang', 'tbl_student.semester', 'tbl_student.verband', 'tbl_student.gruppe', 'tbl_student.matrikelnr as personenkennzeichen']); + $this->StudentModel->addJoin('tbl_studiengang', "tbl_studiengang.studiengang_kz=tbl_student.studiengang_kz"); + + $student_res = $this->StudentModel->load([$uid]); + if (isError($student_res)) { + show_error("was not able to query the table public.tbl_student:" . getData($student_res)); + } + $student_res = hasData($student_res) ? getData($student_res)[0] : null; + return $student_res; + } + + /** + * gets the profil updates corresponding to a user + * @access private + * @param integer $uid the userID used to get the profil updates + * @return array all the profil updates corresponding to a userID + */ + private function getProfilUpdates($uid) + { + $profilUpdates = $this->ProfilUpdateModel->getProfilUpdatesWhere(['uid' => $uid]); + if (isError($profilUpdates)) { + show_error("was not able to query the table public.tbl_profil_update:" . getData($profilUpdates)); + } + $profilUpdates = hasData($profilUpdates) ? getData($profilUpdates) : null; + return $profilUpdates; + } + + /** + * gets the Matrikelnummer corresponding to a user + * @access private + * @param integer $uid the userID used to get the Matrikelnummer + * @return integer the Matrikelnummer corresponding to a userID + */ + private function getMatrikelNummer($uid) + { + $this->BenutzerModel->addSelect(["matr_nr"]); + $this->BenutzerModel->addJoin("tbl_person", "person_id"); + + $matr_res = $this->BenutzerModel->load([$uid]); + if (isError($matr_res)) { + show_error("was not able to query the table public.tbl_benutzer:" . getData($matr_res)); + } + $matr_res = hasData($matr_res) ? getData($matr_res)[0] : []; + return $matr_res; + } + + /** + * gets the Zutrittsgruppen corresponding to a user + * @access private + * @param integer $uid the userID used to get the Zutrittsgruppen + * @return array all the Zutrittsgruppen corresponding to a userID + */ + private function getZutrittsgruppen($uid) + { + $this->BenutzergruppeModel->addSelect(['bezeichnung']); + $this->BenutzergruppeModel->addJoin('tbl_gruppe', 'gruppe_kurzbz'); + + $zutrittsgruppe_res = $this->BenutzergruppeModel->loadWhere(array("uid" => $uid, "zutrittssystem" => true)); + if (isError($zutrittsgruppe_res)) { + show_error("was not able to query the table public.tbl_benutzergruppe:" . getData($zutrittsgruppe_res)); + } + $zutrittsgruppe_res = hasData($zutrittsgruppe_res) ? getData($zutrittsgruppe_res) : null; + return $zutrittsgruppe_res; + } + + /** + * gets the address information corresponding to a user + * @access private + * @param integer $uid the userID used to get the address information + * @return array all the address information corresponding to a userID + */ + private function getAdressenInfo($pid) + { + $adresse_res = $this->AdresseModel->addSelect(["adresse_id", "strasse", "tbl_adressentyp.bezeichnung as typ", "plz", "ort", "zustelladresse", "gemeinde", "nation"]); + $adresse_res = $this->AdresseModel->addOrder("zustelladresse", "DESC"); + $adresse_res = $this->AdresseModel->addJoin("tbl_adressentyp", "typ=adressentyp_kurzbz"); + + $adresse_res = $this->AdresseModel->loadWhere(["person_id" => $pid]); + if (isError($adresse_res)) { + show_error("was not able to query the table public.tbl_adresse:" . getData($adresse_res)); + } + $adresse_res = hasData($adresse_res) ? getData($adresse_res) : null; + return $adresse_res; + } + + /** + * gets the kontakt information corresponding to a user + * @access private + * @param integer $uid the userID used to get the kontakt information + * @return array all the kontakt information corresponding to a userID + */ + private function getKontaktInfo($pid) + { + $this->KontaktModel->addSelect(['kontakttyp', 'kontakt_id', 'kontakt', 'tbl_kontakt.anmerkung', 'tbl_kontakt.zustellung']); + $this->KontaktModel->addJoin('public.tbl_standort', 'standort_id', 'LEFT'); + $this->KontaktModel->addJoin('public.tbl_firma', 'firma_id', 'LEFT'); + $this->KontaktModel->addOrder('kontakttyp, kontakt, tbl_kontakt.updateamum, tbl_kontakt.insertamum'); + + $kontakte_res = $this->KontaktModel->loadWhere(['person_id' => $pid]); + if (isError($kontakte_res)) { + show_error("was not able to query the table public.tbl_kontakt:" . getData($kontakte_res)); + } + $kontakte_res = hasData($kontakte_res) ? getData($kontakte_res) : null; + return $kontakte_res; + } + + /** + * gets the date of issue of the FH access card corresponding to a user + * @access private + * @param integer $uid the userID used to get the date of issue of the FH access card + * @return string the date of issue of the FH access card corresponding to a userID + */ + private function getZutrittskarteDatum($uid) + { + $zutrittskarte_ausgegebenam = $this->BetriebsmittelpersonModel->getBetriebsmittelByUid($uid, "Zutrittskarte"); + if (isError($zutrittskarte_ausgegebenam)) { + show_error("was not able to query the table wavi.tbl_bentriebsmittelperson:" . getData($zutrittskarte_ausgegebenam)); + } + $zutrittskarte_ausgegebenam = hasData($zutrittskarte_ausgegebenam) ? getData($zutrittskarte_ausgegebenam)[0]->ausgegebenam : null; + + //? formats date from 01-01-2000 to 01.01.2000 + $zutrittskarte_ausgegebenam = str_replace("-", ".", $zutrittskarte_ausgegebenam); + return $zutrittskarte_ausgegebenam; + } + + +} diff --git a/application/controllers/Cis/ProfilUpdate.php b/application/controllers/Cis/ProfilUpdate.php new file mode 100644 index 000000000..c47b7540b --- /dev/null +++ b/application/controllers/Cis/ProfilUpdate.php @@ -0,0 +1,814 @@ + ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'], + 'id' => ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'], + 'getProfilUpdateWithPermission' => ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'], + 'acceptProfilRequest' => ['student/stammdaten:rw', 'mitarbeiter/stammdaten:rw'], + 'denyProfilRequest' => ['student/stammdaten:rw', 'mitarbeiter/stammdaten:rw'], + 'show' => ['basis/cis:r'], + + 'insertProfilRequest' => ['basis/cis:rw'], + 'updateProfilRequest' => ['basis/cis:rw'], + 'deleteProfilRequest' => ['basis/cis:rw'], + 'selectProfilRequest' => ['basis/cis:r'], + 'insertFile' => ['basis/cis:rw'], + 'getProfilRequestFiles' => ['basis/cis:r'], + 'getStatus' => ['basis/cis:r'], + 'getTopic' => ['basis/cis:r'], + ]); + + $this->load->config('cis'); + + $this->load->model('person/Profil_update_model', 'ProfilUpdateModel'); + $this->load->model('person/Kontakt_model', 'KontaktModel'); + $this->load->model('person/Adresse_model', 'AdresseModel'); + $this->load->model('person/Adressentyp_model', 'AdressenTypModel'); + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->load->model('system/Sprache_model', 'SpracheModel'); + $this->load->model('person/Profil_update_status_model', 'ProfilUpdateStatusModel'); + $this->load->model('person/Profil_update_topic_model', 'ProfilUpdateTopicModel'); + + // Load language phrases + $this->loadPhrases( + array( + 'ui', + 'global', + 'person', + 'profil', + 'profilUpdate' + ) + ); + + $this->load->library('DmsLib'); + $this->load->library('PermissionLib'); + + //? put the uid and pid inside the controller for reusability + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + + // setup the ProfilUpdate states + $this->ProfilUpdateStatusModel->addSelect(['status_kurzbz']); + $status_kurzbz = $this->ProfilUpdateStatusModel->load(); + if (hasData($status_kurzbz)) { + list($status_pending, $status_accepted, $status_rejected) = getData($status_kurzbz); + + self::$STATUS_PENDING = $status_pending->status_kurzbz; + self::$STATUS_ACCEPTED = $status_accepted->status_kurzbz; + self::$STATUS_REJECTED = $status_rejected->status_kurzbz; + } + // setup the ProfilUpdate topics + $this->ProfilUpdateTopicModel->addSelect(['topic_kurzbz']); + $topic_kurzbz = $this->ProfilUpdateTopicModel->load(); + + if (hasData($topic_kurzbz)) { + foreach (getData($topic_kurzbz) as $topic) { + self::$TOPICS[$topic->topic_kurzbz] = $topic->topic_kurzbz; + } + } + } + + + public function index() + { + $this->load->view('Cis/ProfilUpdate'); + } + + public function id($profil_update_id = null) + { + $this->load->view('Cis/ProfilUpdate', ['profil_update_id' => $profil_update_id]); + } + + public function getStatus() + { + echo json_encode([self::$STATUS_PENDING => self::$STATUS_PENDING, self::$STATUS_ACCEPTED => self::$STATUS_ACCEPTED, self::$STATUS_REJECTED => self::$STATUS_REJECTED]); + } + + public function getTopic() + { + echo json_encode(self::$TOPICS); + } + + private function sendEmail_onProfilUpdate_response($uid, $topic, $status) + { + if($this->config->item('cis_send_profil_update_mails') === false) + { + return; + } + + $this->load->helper('hlp_sancho_helper'); + $email = $uid . "@" . DOMAIN; + + + function languageQuery($language) + { + return "select index from public.tbl_sprache where sprache = '" + $language + "'"; + } + $this->ProfilUpdateStatusModel->addSelect(["bezeichnung_mehrsprachig[(" . languageQuery('German') . ")] as status_de", "bezeichnung_mehrsprachig[(" . languageQuery('English') . ")] as status_en"]); + $status_translation = $this->ProfilUpdateStatusModel->loadWhere(["status_kurzbz" => $status]); + if (isError($status_translation)) { + show_error($this->p->t('profilUpdate', 'ProfilUpdateStatusTranslationError')); + } + $status_translation = hasData($status_translation) ? getData($status_translation)[0] : null; + if (isset($status_translation)) { + $mail_res = sendSanchoMail("profil_update_response", ['topic' => $topic, 'status_de' => $status_translation->status_de, 'status_en' => $status_translation->status_en, 'href' => APP_ROOT . 'Cis/Profil'], $email, ("Profil Änderung " . $this->p->t('profilUpdate', 'pending'))); + if (!$mail_res) { + show_error($this->p->t('profilUpdate', 'profilUpdate_email_error')); + } + } + + } + + + private function sendEmail_onProfilUpdate_insertion($uid, $profil_update_id, $topic) + { + if($this->config->item('cis_send_profil_update_mails') === false) + { + return; + } + + $this->load->helper('hlp_sancho_helper'); + $emails = []; + + $isMitarbeiter_res = $this->MitarbeiterModel->isMitarbeiter($uid); + if (isError($isMitarbeiter_res)) { + show_error($this->p->t('profilUpdate', 'profilUpdate_mitarbeiterCheck_error')); + } + $isMitarbeiter_res = getData($isMitarbeiter_res); + + //! if the $uid is a mitarbeiter and student, only the hr is notified by email + if ($isMitarbeiter_res) { + //? user is not a student therefore he is a mitarbeiter, send email to Personalverwaltung + //? use constant variable MAIL_GST to mail to the personalverwaltung + $this->MitarbeiterModel->addSelect([TRUE]); + $this->MitarbeiterModel->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid"); + //? check if the the userID is a mitarbeiter and if the benutzer is active + $res = $this->MitarbeiterModel->loadWhere(["public.tbl_mitarbeiter.mitarbeiter_uid" => $uid, "public.tbl_benutzer.aktiv" => TRUE]); + if (isError($res)) { + show_error("was not able to query the mitarbeiter and benutzer by the uid: " . $uid); + } + if (hasData($res)) { + array_push($emails, MAIL_GST); + } else { + show_error($this->p->t('profilUpdate', 'profilUpdate_mitarbeiterCheck_error')); + } + } else { + //? if it is not a mitarbeiter, check whether it is a student and send email to studiengang + $isStudent_res = $this->StudentModel->isStudent($uid); + if (isError($isStudent_res)) { + show_error($this->p->t('profilUpdate', 'profilUpdate_studentCheck_error')); + } + $isStudent_res = getData($isStudent_res); + if ($isStudent_res) { + //? Send email to the Studiengangsassistentinnen + $this->StudentModel->addSelect(["public.tbl_studiengang.email"]); + $this->StudentModel->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_student.student_uid"); + $this->StudentModel->addJoin("public.tbl_prestudent", "public.tbl_benutzer.person_id = public.tbl_prestudent.person_id"); + $this->StudentModel->addJoin("public.tbl_prestudentstatus", "public.tbl_prestudentstatus.prestudent_id = public.tbl_prestudent.prestudent_id"); + $this->StudentModel->addJoin("public.tbl_studiengang", "public.tbl_studiengang.studiengang_kz = public.tbl_prestudent.studiengang_kz"); + //* check if the benutzer itself is active + //* check if the student status is Student or Diplomand (active students) + $this->StudentModel->db->where_in("public.tbl_prestudentstatus.status_kurzbz", ['Student', 'Diplomand']); + $res = $this->StudentModel->loadWhere(["public.tbl_benutzer.aktiv" => TRUE, "public.tbl_student.student_uid" => $uid]); + if (isError($res)) { + show_error(getData($res)); + } else { + $res = hasData($res) ? getData($res) : []; + foreach ($res as $emailObj) { + array_push($emails, $emailObj->email); + } + } + } + } + $mail_res = []; + //? sending email + foreach ($emails as $email) { + array_push($mail_res, sendSanchoMail("profil_update", ['uid' => $uid, 'topic' => $topic, 'href' => APP_ROOT . 'Cis/ProfilUpdate/id/' . $profil_update_id], $email, ("Profil Änderung von " . $uid))); + } + foreach ($mail_res as $m_res) { + if (!$m_res) { + show_error($this->p->t('profilUpdate', 'profilUpdate_email_error')); + } + } + + } + + + public function show($dms_id) + { + + $profil_update = $this->ProfilUpdateModel->loadWhere(['attachment_id' => $dms_id]); + $profil_update = hasData($profil_update) ? getData($profil_update)[0] : null; + + //? checks if an profil update exists with the dms_id requested from the user + if ($profil_update) { + $is_mitarbeiter_profil_update = getData($this->MitarbeiterModel->isMitarbeiter($profil_update->uid)); + $is_student_profil_update = getData($this->StudentModel->isStudent($profil_update->uid)); + + if ( + $this->permissionlib->isBerechtigt('student/stammdaten:r') && $is_student_profil_update || + $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten:r') && $is_mitarbeiter_profil_update || + $this->uid == $profil_update->uid + ) { + // Get file to be downloaded from DMS + $newFilename = $this->uid . "/document_" . $dms_id; + $download = $this->dmslib->download($dms_id); + if (isError($download)) + return $download; + + // Download file + $this->outputFile(getData($download)); + + + } else { + show_error($this->p->t('profilUpdate', 'profilUpdate_permission_error')); + return; + } + + } else { + show_error($this->p->t('profilUpdate', 'profilUpdate_dms_error')); + return; + } + + } + + + public function insertFile($replace) + { + $replace = json_decode($replace); + + if (!count($_FILES)) { + echo json_encode([]); + return; + } + + //? if replace is set it contains the profil_update_id in which the attachment_id has to be replaced + if (isset($replace)) { + $this->ProfilUpdateModel->addSelect(["attachment_id"]); + $profilUpdate = $this->ProfilUpdateModel->load([$replace]); + if (isError($profilUpdate)) { + return json_encode(error($this->p->t('profilUpdate', 'profilUpdate_loading_error'))); + } + //? get the attachmentID + $dms_id = hasData($profilUpdate) ? getData($profilUpdate)[0]->attachment_id : null; + + //? delete old dms_file of Profil Update + $this->deleteOldVersionFile($dms_id); + } + + + $files = $_FILES['files']; + $file_count = count($files['name']); + + $res = []; + + for ($i = 0; $i < $file_count; $i++) { + $_FILES['files']['name'] = $files['name'][$i]; + $_FILES['files']['type'] = $files['type'][$i]; + $_FILES['files']['tmp_name'] = $files['tmp_name'][$i]; + $_FILES['files']['error'] = $files['error'][$i]; + $_FILES['files']['size'] = $files['size'][$i]; + + $dms = [ + "kategorie_kurzbz" => "profil_aenderung", + "version" => 0, + "name" => $_FILES['files']['name'], + "mimetype" => $_FILES['files']['type'], + "beschreibung" => $this->uid . " Profil Änderung", + "insertvon" => $this->uid, + "insertamum" => "NOW()", + ]; + + $tmp_res = $this->dmslib->upload($dms, 'files', array("jpg", "png", "pdf")); + + $tmp_res = hasData($tmp_res) ? getData($tmp_res) : null; + array_push($res, $tmp_res); + } + + echo json_encode($res); + } + + + public function selectProfilRequest() + { + $_GET = json_decode($this->input->raw_input_stream, true); + $uid = $this->input->get('uid'); + $id = $this->input->get('id'); + $whereClause = ['uid' => $this->uid]; + + if (isset($uid)) + $whereClause['uid'] = $uid; + if (isset($id)) + $whereClause['id'] = $id; + + $res = $this->ProfilUpdateModel->getProfilUpdatesWhere($whereClause); + $res = hasData($res) ? getData($res) : null; + echo json_encode($res); + + } + + + public function getProfilRequestFiles() + { + $id = json_decode($this->input->raw_input_stream); + + $this->ProfilUpdateModel->addSelect(["attachment_id"]); + $attachmentID = $this->ProfilUpdateModel->load([$id]); + if (isError($attachmentID)) { + return json_encode(error($this->p->t('profilUpdate', 'profilUpdate_loading_error'))); + } + //? get the attachmentID + $dms_id = hasData($attachmentID) ? getData($attachmentID)[0]->attachment_id : null; + + //? get the name to the file + $this->DmsVersionModel->addSelect(["name", "dms_id"]); + $attachment = $this->DmsVersionModel->load([$dms_id, 0]); + if (isError($attachment)) { + return json_encode(error($this->p->t('profilUpdate', 'profilUpdate_dmsVersion_error'))); + } + $attachment = hasData($attachment) ? getData($attachment) : null; + //? returns {name:..., dms_id:...} + echo json_encode($attachment); + } + + public function insertProfilRequest() + { + + $json = json_decode($this->input->raw_input_stream); + + $payload = $json->payload; + $identifier = property_exists($json->payload, "kontakt_id") ? "kontakt_id" : (property_exists($json->payload, "adresse_id") ? "adresse_id" : null); + + $data = ["topic" => $json->topic, "uid" => $this->uid, "requested_change" => json_encode($payload), "insertamum" => "NOW()", "insertvon" => $this->uid, "status" => self::$STATUS_PENDING ?: 'Pending']; + + //? insert fileID in the dataset if sent with post request + if (isset($json->fileID)) { + $data['attachment_id'] = $json->fileID; + + } + + //? loops over all updateRequests from a user to validate if the new request is valid + $res = $this->ProfilUpdateModel->getProfilUpdatesWhere(["uid" => $this->uid]); + if (isError($res)) { + show_error($this->p->t('profilUpdate', 'profilUpdate_loading_error')); + } + $res = hasData($res) ? getData($res) : null; + + //? the user cannot delete a zustelladresse/kontakt + if (isset($payload->delete) && $payload->{$identifier == "kontakt_id" ? "zustellung" : "zustelladresse"}) { + echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_deleteZustellung_error'))); + return; + } + + //? if the user tries to delete a adresse, checks whether the adresse is a heimatadresse, if so an error is raised + if (isset($payload->delete) && $identifier == "adresse_id") { + $adr = $this->AdresseModel->load($payload->$identifier); + $adr = getData($adr)[0]; + if ($adr->heimatadresse) { + echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_deleteZustellung_error'))); + return; + } + } + + if ($res) { + $pending_changes = array_filter($res, function ($element) { + return $element->status == (self::$STATUS_PENDING ?: "Pending"); + }); + + foreach ($pending_changes as $update_request) { + $existing_change = $update_request->requested_change; + + //? the user can add as many new kontakte/adressen as he likes + if (!isset($payload->add) && property_exists($existing_change, $identifier) && property_exists($payload, $identifier) && $existing_change->$identifier == $payload->$identifier) { + //? the kontakt_id / adresse_id of a change has to be unique + echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_changeTwice_error'))); + return; + } + + //? if it is not updating any kontakt/adresse, the topic has to be unique + elseif (!$identifier && $update_request->topic == $json->topic) { + echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_changeTopicTwice_error', ['0' => $update_request->topic]))); + return; + } + } + } + + $insertID = $this->ProfilUpdateModel->insert($data); + + if (isError($insertID)) { + show_error(getData($insertID)); + } else { + $insertID = hasData($insertID) ? getData($insertID) : null; + + //? sends emails to the correspondents of the $uid + $this->sendEmail_onProfilUpdate_insertion($this->uid, $insertID, $json->topic); + echo json_encode(success($insertID)); + } + } + + public function updateProfilRequest() + { + $json = json_decode($this->input->raw_input_stream); + + $updateData = ["requested_change" => json_encode($json->payload), "updateamum" => "NOW()", "updatevon" => $this->uid]; + if (isset($json->fileID)) { + $updateData['attachment_id'] = json_decode($json->fileID); + } + $updateID = $this->ProfilUpdateModel->update([$json->ID], $updateData); + //? insert fileID in the dataset if sent with post request + + if (isError($updateID)) { + //catch error + } else { + $updateID = hasData($updateID) ? getData($updateID)[0] : null; + //TODO: should an email be sent to the responsable people when the user changes his profil update + echo json_encode(success($updateID)); + } + } + + public function deleteProfilRequest() + { + + $json = json_decode($this->input->raw_input_stream); + $delete_res = $this->ProfilUpdateModel->delete([$json]); + echo json_encode($delete_res); + } + + + public function getProfilUpdateWithPermission($status = null) + { + // early return if no status has been passed as argument + if (!isset($status)) { + echo json_encode($this->ProfilUpdateModel->getProfilUpdateWithPermission()); + return; + } + + // get the sprache of the user + $sprachenIndex = $this->SpracheModel->loadWhere(["sprache" => getUserLanguage()]); + $sprachenIndex = hasData($sprachenIndex) ? getData($sprachenIndex)[0]->index : null; + + if (isset($sprachenIndex) && isset($status)) { + // get the corresponding status kurz_bz primary key out of the translation + $status = $this->ProfilUpdateStatusModel->execReadOnlyQuery("select * from public.tbl_profil_update_status where ? = ANY(bezeichnung_mehrsprachig)", [$status]); + $status = hasData($status) ? getData($status)[0]->status_kurzbz : null; + $res = $this->ProfilUpdateModel->getProfilUpdateWithPermission(isset($status) ? ['status' => $status] : null); + + echo json_encode($res); + } + } + + + + private function getOE_from_student($student_uid) + { + + //? returns the oe_einheit eines Studenten + $query = "SELECT public.tbl_studiengang.oe_kurzbz + FROM public.tbl_student + JOIN public.tbl_studiengang ON tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz + WHERE public.tbl_student.student_uid = ?;"; + + $res = $this->StudentModel->execReadOnlyQuery($query, [$student_uid]); + if (!isSuccess($res)) { + show_error($this->p->t('profilUpdate', 'profilUpdate_loadingOE_error')); + } + $res = hasData($res) ? getData($res) : []; + $res = array_map( + function ($item) { + return $item->oe_kurzbz; + }, + $res + ); + return $res; + } + + + public function acceptProfilRequest() + { + $_POST = json_decode($this->input->raw_input_stream, true); + $id = $this->input->post('profil_update_id', true); + $uid = $this->input->post('uid', true); + + //? fetching person_id using UID + $personID = $this->PersonModel->getByUid($uid); + $personID = hasData($personID) ? getData($personID)[0]->person_id : null; + $status_message = $this->input->post('status_message', true); + $topic = $this->input->post('topic', true); + + //! somehow the xss check converted boolean false to empty string + $requested_change = $this->input->post('requested_change'); + + //! check for required information + if (!isset($id) || !isset($uid) || !isset($personID) || !isset($requested_change) || !isset($topic)) { + return json_encode(error($this->p->t('profilUpdate', 'profilUpdate_requiredInformation_error'))); + } + + $is_mitarbeiter_profil_update = getData($this->MitarbeiterModel->isMitarbeiter($uid)); + $is_student_profil_update = getData($this->StudentModel->isStudent($uid)); + + + //? check if the permissions are set correctly + if ( + $this->permissionlib->isBerechtigt('student/stammdaten', "suid", $this->getOE_from_student($uid)) && $is_student_profil_update || + $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', "suid") && $is_mitarbeiter_profil_update + ) { + + if (is_array($requested_change) && array_key_exists("adresse_id", $requested_change)) { + $insertID = $this->handleAdresse($requested_change, $personID); + $insertID = hasData($insertID) ? getData($insertID) : null; + if (isset($insertID)) { + $requested_change['adresse_id'] = $insertID; + $update_res = $this->updateRequestedChange($id, $requested_change); + if (isError($update_res)) { + echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_address_error', [$insertID]))); + return; + } + } + + } else if (is_array($requested_change) && array_key_exists("kontakt_id", $requested_change)) { + $insertID = $this->handleKontakt($requested_change, $personID); + $insertID = hasData($insertID) ? getData($insertID) : null; + if (isset($insertID)) { + $requested_change['kontakt_id'] = $insertID; + $update_res = $this->updateRequestedChange($id, $requested_change); + if (isError($update_res)) { + echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_kontakt_error', [$insertID]))); + return; + } + } + + + } else { + switch ($topic) { + // mapping phrasen to database columns to make the update with the correct column names + case self::$TOPICS['Titel']: + $topic = "titelpre"; + break; + case self::$TOPICS['Postnomen']: + $topic = "titelpost"; + break; + case self::$TOPICS['Vorname']: + $topic = "vorname"; + break; + case self::$TOPICS['Nachname']: + $topic = "nachname"; + break; + default: + show_error($this->p->t('profilUpdate', 'profilUpdate_topic_error', [$topic])); + return; + } + + $result = $this->PersonModel->update($personID, [$topic => $requested_change["value"]]); + if (isError($result)) { + echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_insert_error'))); + return; + } + } + $this->sendEmail_onProfilUpdate_response($uid, $topic, self::$STATUS_ACCEPTED); + + echo json_encode($this->setStatusOnUpdateRequest($id, self::$STATUS_ACCEPTED, $status_message, $requested_change)); + } else { + show_error($this->p->t('profilUpdate', 'profilUpdate_permission_error')); + } + + + } + + public function denyProfilRequest() + { + + $_POST = json_decode($this->input->raw_input_stream, true); + $id = $this->input->post('profil_update_id', true); + $uid = $this->input->post('uid', true); + $topic = $this->input->post('topic', true); + $status_message = $this->input->post('status_message', true); + + $is_mitarbeiter_profil_update = getData($this->MitarbeiterModel->isMitarbeiter($uid)); + $is_student_profil_update = getData($this->StudentModel->isStudent($uid)); + + + if ( + $this->permissionlib->isBerechtigt('student/stammdaten', "suid", $this->getOE_from_student($uid)) && $is_student_profil_update || + $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', "suid") && $is_mitarbeiter_profil_update + ) { + $this->sendEmail_onProfilUpdate_response($uid, $topic, self::$STATUS_REJECTED); + echo json_encode($this->setStatusOnUpdateRequest($id, self::$STATUS_REJECTED, $status_message)); + } else { + show_error($this->p->t('profilUpdate', 'profilUpdate_permission_error')); + } + + + } + + private function updateRequestedChange($id, $requested_change) + { + return $this->ProfilUpdateModel->update([$id], ['requested_change' => json_encode($requested_change)]); + } + + private function setStatusOnUpdateRequest($id, $status, $status_message) + { + return $this->ProfilUpdateModel->update([$id], ["status" => $status, "status_timestamp" => "NOW()", "status_message" => $status_message]); + } + + private function deleteOldVersionFile($dms_id) + { + if (!isset($dms_id)) { + return; + } + + //? collect all the results of the deleted versions in an array + $res = array(); + + //? delete all the different versions of the dms_file + $dmsVersions = $this->DmsVersionModel->loadWhere(["dms_id" => $dms_id]); + $dmsVersions = hasData($dmsVersions) ? getData($dmsVersions) : null; + if (isset($dmsVersions)) { + $zwischen_res = array_map(function ($item) { + return $item->version; + }, $dmsVersions); + foreach ($zwischen_res as $version) { + array_push($res, $this->DmsVersionModel->delete([$dms_id, $version])); + } + } else { + echo json_encode(error($this->p->t('profilUpdate', 'profilUpdate_dmsVersion_error'))); + } + + //? returns a result for each deleted dms_file + return $res; + } + + + private function handleKontakt($requested_change, $personID) + { + $kontakt_id = $requested_change["kontakt_id"]; + //? removes the kontakt_id because we don't want to update the kontakt_id in the database + unset($requested_change["kontakt_id"]); + + + //! ADD + if (array_key_exists('add', $requested_change) && $requested_change['add']) { + //? removes add flag + unset($requested_change['add']); + $requested_change['person_id'] = $personID; + $requested_change['insertamum'] = "NOW()"; + $requested_change['insertvon'] = getAuthUID(); + $insertID = $this->KontaktModel->insert($requested_change); + $insert_kontakt_id = $insertID; + if (isError($insert_kontakt_id)) { + show_error($this->p->t('profilUpdate', 'profilUpdate_insertKontakt_error')); + } + $insert_kontakt_id = hasData($insert_kontakt_id) ? getData($insert_kontakt_id) : null; + if ($insert_kontakt_id) { + $this->handleDupplicateZustellKontakte($requested_change['zustellung'], $insert_kontakt_id); + } + + + } + //! DELETE + elseif (array_key_exists('delete', $requested_change) && $requested_change['delete']) { + $this->KontaktModel->delete($kontakt_id); + } + //! UPDATE + else { + $requested_change['updateamum'] = "NOW()"; + $requested_change['updatevon'] = getAuthUID(); + + $update_kontakt_id = $this->KontaktModel->update($kontakt_id, $requested_change); + + if (isError($update_kontakt_id)) { + show_error($this->p->t('profilUpdate', 'profilUpdate_updateKontakt_error')); + } + $update_kontakt_id = hasData($update_kontakt_id) ? getData($update_kontakt_id) : null; + if ($update_kontakt_id) { + $this->handleDupplicateZustellKontakte($requested_change['zustellung'], $update_kontakt_id); + } + } + return isset($insertID) ? $insertID : null; + } + + private function handleAdresse($requested_change, $personID) + { + + $this->AdressenTypModel->addSelect(["adressentyp_kurzbz"]); + $adr_kurzbz = $this->AdressenTypModel->loadWhere(["bezeichnung" => $requested_change['typ']]); + $adr_kurzbz = hasData($adr_kurzbz) ? getData($adr_kurzbz)[0]->adressentyp_kurzbz : null; + //? replace the address_typ with its correct kurzbz foreign key + $requested_change['typ'] = $adr_kurzbz; + + $adresse_id = $requested_change["adresse_id"]; + //? removes the adresse_id because we don't want to update the kontakt_id in the database + unset($requested_change["adresse_id"]); + + + //! ADD + if (array_key_exists('add', $requested_change) && $requested_change['add']) { + + //? removes add flag + unset($requested_change['add']); + $requested_change['insertamum'] = "NOW()"; + $requested_change['insertvon'] = getAuthUID(); + $requested_change['person_id'] = $personID; + //TODO: zustelladresse, heimatadresse, rechnungsadresse und nation werden nicht beachtet + $insertID = $this->AdresseModel->insert($requested_change); + $insert_adresse_id = $insertID; + if (isError($insert_adresse_id)) { + show_error($this->p->t('profilUpdate', 'profilUpdate_insertAdresse_error')); + } + $insert_adresse_id = hasData($insert_adresse_id) ? getData($insert_adresse_id) : null; + if ($insert_adresse_id) { + $this->handleDupplicateZustellAdressen($requested_change['zustelladresse'], $insert_adresse_id); + } + + } + //! DELETE + elseif (array_key_exists('delete', $requested_change) && $requested_change['delete']) { + $this->AdresseModel->delete($adresse_id); + } + //! UPDATE + else { + $requested_change['updateamum'] = "NOW()"; + $requested_change['updatevon'] = getAuthUID(); + $update_adresse_id = $this->AdresseModel->update($adresse_id, $requested_change); + if (isError($update_adresse_id)) { + show_error($this->p->t('profilUpdate', 'profilUpdate_updateAdresse_error')); + } + $update_adresse_id = hasData($update_adresse_id) ? getData($update_adresse_id) : null; + if ($update_adresse_id) { + $this->handleDupplicateZustellAdressen($requested_change['zustelladresse'], $update_adresse_id); + } + } + return isset($insertID) ? $insertID : null; + } + + + private function handleDupplicateZustellKontakte($zustellung, $kontakt_id) + { + if ($zustellung) { + $this->PersonModel->addSelect("public.tbl_kontakt.kontakt_id"); + $this->PersonModel->addJoin("public.tbl_kontakt", "public.tbl_kontakt.person_id = public.tbl_person.person_id"); + $zustellKontakteArray = $this->PersonModel->loadWhere(["public.tbl_person.person_id" => $this->pid, "zustellung" => TRUE]); + if (!isSuccess($zustellKontakteArray)) { + return error($this->p->t('profilUpdate', 'profilUpdate_loadingZustellkontakte_error')); + } + $zustellKontakteArray = hasData($zustellKontakteArray) ? getData($zustellKontakteArray) : null; + + if ($zustellung && count($zustellKontakteArray) > 0) { + $zustellKontakteArray = array_filter($zustellKontakteArray, function ($kontakt) use ($kontakt_id) { + return $kontakt->kontakt_id != $kontakt_id; + }); + foreach ($zustellKontakteArray as $kontakt) { + $this->KontaktModel->update($kontakt->kontakt_id, ["zustellung" => FALSE]); + } + + } + } + } + + private function handleDupplicateZustellAdressen($zustellung, $adresse_id) + { + if ($zustellung) { + $this->PersonModel->addSelect("public.tbl_adresse.adresse_id"); + $this->PersonModel->addJoin("public.tbl_adresse", "public.tbl_adresse.person_id = public.tbl_person.person_id"); + $zustellAdressenArray = $this->PersonModel->loadWhere(["public.tbl_person.person_id" => $this->pid, "zustelladresse" => TRUE]); + if (!isSuccess($zustellAdressenArray)) { + return error($this->p->t('profilUpdate', 'profilUpdate_loadingZustellAdressen_error')); + } + $zustellAdressenArray = hasData($zustellAdressenArray) ? getData($zustellAdressenArray) : null; + + if ($zustellung && count($zustellAdressenArray) > 0) { + + $zustellAdressenArray = array_filter($zustellAdressenArray, function ($adresse) use ($adresse_id) { + + return $adresse->adresse_id != $adresse_id; + }); + foreach ($zustellAdressenArray as $adresse) { + $this->AdresseModel->update($adresse->adresse_id, ["zustelladresse" => FALSE]); + } + + } + } + } + + +} \ No newline at end of file diff --git a/application/controllers/Cis/Pub.php b/application/controllers/Cis/Pub.php new file mode 100644 index 000000000..bebc844ab --- /dev/null +++ b/application/controllers/Cis/Pub.php @@ -0,0 +1,167 @@ + ['basis/cis:r'] + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @param string $source [person|akte] + * @param integer $id + * @return void + */ + public function bild($source, $id) + { + $this->load->model('person/Person_model', 'PersonModel'); + + $person_id_user = ''; + $serverzugriff = false; + + // Wenn das Bild direkt aufgerufen wird, ist eine Authentifizierung erforderlich + // Wenn es vom Server selbst aufgerufen wird, ist keine Auth. notwendig + // (z.B. fuer die Erstellung von PDFs) + if ($_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) { + // Wenn Session gesetzt ist, keine Abfrage, da diese Personen noch keine UID haben + + if (isset($_SESSION['incoming/user'])) { // Von Incomingtool + $result = $this->PersonModel->loadWhere([ + 'zugangscode' => $_SESSION['incoming/user'] + ]); + if (hasData($result)) + $person_id_user = current(getData($result))->person_id; + } elseif (isset($_SESSION['prestudent/user'])) { // Von Prestudententool + $result = $this->PersonModel->loadWhere([ + 'zugangscode' => $_SESSION['prestudent/user'] + ]); + if (hasData($result)) + $person_id_user = current(getData($result))->person_id; + } elseif (isset($_SESSION['bewerbung/personId'])) { // Von Bewerbungstool + $person_id_user = $_SESSION['bewerbung/personId']; + } else { + $person_id_user = getAuthPersonId(); + } + } else { + $serverzugriff = true; + } + + // Default Bild (Dummy Profilbild) + $cTmpHEX = base64_encode(file_get_contents(FHCPATH . 'skin/images/profilbild_dummy.jpg')); + + if ($source == 'person' && $id) { + $foto_gesperrt = false; + // Person laden und Fotosperre überprüfen + $result = $this->PersonModel->load($id); + if (hasData($result)) { + $person = current(getData($result)); + if ($person->foto_sperre) { + // Wenn der User selbst darauf zugreift darf er das Bild sehen + $foto_gesperrt = ($person_id_user != $id); + } elseif (!$person_id_user && !$serverzugriff) { + $foto_gesperrt = true; + } + + if ($person->foto && !$foto_gesperrt) { + $cTmpHEX = base64_decode($person->foto); + } + } + } + if($source == 'akte' && $id != '') + { + $this->load->model('crm/Akte_model', 'AkteModel'); + + $this->AkteModel->addJoin('public.tbl_person', 'person_id'); + $result = $this->AkteModel->loadWhere([ + 'person_id' => $id, + 'dokument_kurzbz' => 'Lichtbil' + ]); + + if (hasData($result)) { + $foto_gesperrt = false; + + $akte = current(getData($result)); + if ($akte->foto_sperre) { + // Wenn der User selbst darauf zugreift darf er das Bild sehen + $foto_gesperrt = ($person_id_user != $id); + } elseif (!$person_id_user && !$serverzugriff) { + $foto_gesperrt = true; + } + + // Wenn das Foto nicht im Inhalt steht wird aus aus dem DMS geladen + if (!$akte->inhalt && $akte->dms_id) { + $this->load->model('content/Dms_model', 'DmsModel'); + $this->load->model('content/DmsVersion_model', 'DmsVersionModel'); + + $this->DmsModel->addJoin('campus.tbl_dms_version', 'dms_id'); + $this->DmsModel->addOrder('version', 'DESC'); + $this->DmsModel->addLimit(1); + $result = $this->DmsModel->load($akte->dms_id); + + if (!hasData($result)) + die('Kein Dokument vorhanden'); + + $dms = current(getData($result)); + + $filename = DMS_PATH . $dms->filename; + + $this->DmsVersionModel->update([ + 'dms_id' => $dms->dms_id, + 'version' => $dms->version + ], [ + 'letzterzugriff' => date('c') + ]); + + if (file_exists($filename)) { + $handle = fopen($filename, "r"); + if ($handle) { + while (!feof($handle)) { + $akte->inhalt .= fread($handle, 8192); + } + fclose($handle); + } else { + echo 'Fehler: Datei konnte nicht geoeffnet werden'; + } + } else { + echo 'Die Datei existiert nicht'; + } + } + + if ($akte->inhalt && !$foto_gesperrt) { + $cTmpHEX = $akte->inhalt; + } + } + } + + // die bilder werden, sofern es funktioniert, in jpg umgewandelt da es sonst zu fehlern beim erstellen + // von pdfs kommen kann. + + $im = @imagecreatefromstring(base64_decode($cTmpHEX)); + if ($im) { + @ob_clean(); + header("Content-type: image/jpeg"); + exit(imagejpeg($im)); + } else { + // bei manchen Bildern funktioniert die konvertierung nicht + // diese werden dann einfach so angezeigt. + @ob_clean(); + header("Content-type: image/gif"); + exit($cTmpHEX); + } + } +} diff --git a/application/controllers/Cis/Stundenplan.php b/application/controllers/Cis/Stundenplan.php new file mode 100644 index 000000000..3e4e1a070 --- /dev/null +++ b/application/controllers/Cis/Stundenplan.php @@ -0,0 +1,30 @@ + ['basis/cis:r'] + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + $this->load->view('Cis/Stundenplan'); + } +} diff --git a/application/controllers/Cis4.php b/application/controllers/Cis4.php new file mode 100644 index 000000000..9197fd388 --- /dev/null +++ b/application/controllers/Cis4.php @@ -0,0 +1,41 @@ + 'basis/cis:r' + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + $this->load->model('person/Person_model','PersonModel'); + $personData = getData($this->PersonModel->getByUid(getAuthUID()))[0]; + + $viewData = array( + 'uid' => getAuthUID(), + 'name' => $personData->vorname, + 'person_id' => $personData->person_id + ); + + $this->load->view('CisVue/Dashboard.php',['viewData' => $viewData]); + } +} \ No newline at end of file diff --git a/application/controllers/CisVue/Cms.php b/application/controllers/CisVue/Cms.php new file mode 100644 index 000000000..d1fe5468e --- /dev/null +++ b/application/controllers/CisVue/Cms.php @@ -0,0 +1,127 @@ + 'basis/cis:r', + 'getNews' => 'basis/cis:r', + 'getNewsRowCount' => 'basis/cis:r', + 'getRoomInformation' => 'basis/cis:r', + 'news' => 'basis/cis:r' + ) + ); + + // Loads Libraries + $this->load->library('CmsLib'); + + // Loads phrases system + $this->loadPhrases([ + 'global' + ]); + + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @param int $content_id + * @param int $version + * @param string $sprache + * @param boolean $sichtbar + * + * @return void + */ + public function content($content_id, $version = null, $sprache = null, $sichtbar = true) + { + // return early if the content_id for the content is missing + if (!isset($content_id)) + $this->terminateWithError("content_id is missing"); + + $content = $this->ContentModel->load($content_id); + if (isError($content)) + $this->terminateWithError(getError($content)); + + $content = getData($content); + if (NULL === $content) + $this->terminateWithError("Content not found"); + + $content = current($content); + + $this->load->view('CisVue/Cms/Content', ['content_id' => $content_id, 'template_kurzbz' => $content->template_kurzbz, 'version' => $version, 'sprache' => $sprache, 'sichtbar' => $sichtbar]); + } + + /** + * @param boolean $infoscreen + * @param string | null $studiengang_kz + * @param int | null $semester + * @param boolean $mischen + * @param string $titel + * @param boolean $edit + * @param boolean $sichtbar + * + * @return void + */ + public function news($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $edit = false, $sichtbar = true) + { + $this->load->view('CisVue/Cms/Content', ['infoscreen' => $infoscreen, 'studiengang_kz' => $studiengang_kz, 'semester' => $semester, 'mischen' => $mischen, 'titel' => $titel, 'edit' => $edit, 'sichtbar' => $sichtbar]); + } + + public function getNews($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $edit = false, $sichtbar = true) + { + $get_page = intval($this->input->get('page', true)); + $get_page_size = intval($this->input->get('page_size', true)); + if ($get_page) { + $page = $get_page; + } + if ($get_page_size) { + $page_size = $get_page_size; + } else { + $page_size = $this->page_size; + } + $news = $this->cmslib->getNews($infoscreen, $studiengang_kz, $semester, $mischen, $titel, $edit, $sichtbar, $page, $page_size); + + if (isError($news)) { + $this->terminateWithJsonError(getError($news)); + } + $news = hasData($news) ? getData($news) : null; + if ($news) { + echo json_encode($news); + } else { + show_error("News: No data found"); + } + + } + + public function getNewsRowCount($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $fachbereich_kurzbz = null, $maxalter = 0, $edit = false, $sichtbar = true, $page = 1, $page_size = 10) + { + list($studiengang_kz, $semester) = $this->cmslib->getStgAndSem($studiengang_kz, $semester); + $all = $edit; + $num_rows = $this->NewsModel->countNewsWithContent(getSprache(), $studiengang_kz, $semester, $fachbereich_kurzbz, $sichtbar, $maxalter, $page, $this->page_size, $all, $mischen); + if (isError($num_rows)) { + $this->terminateWithJsonError(getError($num_rows)); + } + $num_rows = hasData($num_rows) ? getData($num_rows) : null; + if ($num_rows) { + echo json_encode($num_rows); + } else { + show_error("News number rows: No data found"); + } + } + + public function getRoomInformation($ort_kurzbz){ + $this->load->view('CisVue/Cms/RoomInformation',['ort_kurzbz'=>$ort_kurzbz]); + } +} diff --git a/application/controllers/CisVue/Dashboard.php b/application/controllers/CisVue/Dashboard.php new file mode 100644 index 000000000..5cb0d1a9e --- /dev/null +++ b/application/controllers/CisVue/Dashboard.php @@ -0,0 +1,45 @@ + 'dashboard/benutzer:r' + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + + $this->load->model('person/Person_model','PersonModel'); + $begruesung = $this->PersonModel->getFirstName(getAuthUID()); + if(isError($begruesung)) + { + show_error("name couldn't be loaded for username ".getAuthUID()); + } + $begruesung = getData($begruesung); + $viewData = array( + 'name' => $begruesung + ); + + $this->load->view('CisVue/Dashboard.php', ['viewData' => $viewData]); + + } +} \ No newline at end of file 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/api/frontend/fas/studstatus/Wiederholung.php b/application/controllers/api/frontend/fas/studstatus/Wiederholung.php new file mode 100644 index 000000000..19ace3d0d --- /dev/null +++ b/application/controllers/api/frontend/fas/studstatus/Wiederholung.php @@ -0,0 +1,163 @@ +. + */ + +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/Ampeln.php b/application/controllers/api/frontend/v1/Ampeln.php new file mode 100644 index 000000000..e0ffb4df5 --- /dev/null +++ b/application/controllers/api/frontend/v1/Ampeln.php @@ -0,0 +1,145 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +class Ampeln extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'open' => self::PERM_LOGGED, + 'all' => self::PERM_LOGGED, + 'confirm' => self::PERM_LOGGED, + 'alleAmpeln' => self::PERM_LOGGED, + ]); + + $this->load->model('content/Ampel_model', 'AmpelModel'); + $this->load->model('system/Sprache_model', 'SpracheModel'); + + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * confirms ampel and inserts ampel_id in public.tbl_ampel_benutzer_bestaetigt + * @access public + * + */ + public function confirm($ampel_id) + { + $this->load->library('form_validation'); + $this->form_validation->set_data(['ampel_id'=> $ampel_id]); + $this->form_validation->set_rules('ampel_id', 'Ampel ID', 'required|integer'); + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // load Ampel_benutzer_bestaetigt_model to confirm the ampel + $this->load->model('content/Ampel_Benutzer_Bestaetigt_model', 'AmpelBenutzerBestaetigtModel'); + $insert_into_result = $this->AmpelBenutzerBestaetigtModel->insert(["ampel_id"=> $ampel_id, "uid"=> $this->uid]); + + $insert_into_result = $this->getDataOrTerminateWithError($insert_into_result); + + $this->terminateWithSuccess($insert_into_result); + } + + /** + * queries active and not confirmed ampeln by the user + * @access public + * + */ + public function open() + { + $userAmpeln = array(); + + // fetch active ampeln + $activeAmpeln = $this->AmpelModel->openActive($this->uid, false); + + $activeAmpeln = $this->getDataOrTerminateWithError($activeAmpeln); + + foreach ($activeAmpeln as $ampel) { + // only include non confirmed active ampeln in the result + if (!$ampel->bestaetigt) { + // check if the user was assigned to the ampel + $zugeteilt = $this->AmpelModel->isZugeteilt($this->uid, $ampel->benutzer_select); + + $zugeteilt = $this->getDataOrTerminateWithError($zugeteilt); + + if($zugeteilt) $userAmpeln[] = $ampel; + } + } + + $this->terminateWithSuccess($userAmpeln); + } + + /** + * queries all ampeln of the user + * @access public + * + */ + public function all() + { + $userAmpeln = array(); + + $ampel_result = $this->AmpelModel->active(false, $this->uid); + + $ampel_result = $this->getDataOrTerminateWithError($ampel_result); + + foreach ($ampel_result as $ampel) { + // check if the ampel was assigned to the user + $zugeteilt = $this->AmpelModel->isZugeteilt($this->uid, $ampel->benutzer_select); + + $zugeteilt = $this->getDataOrTerminateWithError($zugeteilt); + + if ($zugeteilt) $userAmpeln[] = $ampel; + } + + $this->terminateWithSuccess($userAmpeln); + } + + /** + * queries all ampeln that were assigned to the user until start of first work day + * @access public + * + */ + public function alleAmpeln() + { + + //fetch all ampeln + $alle_ampeln = $this->AmpelModel->alleAmpeln($this->uid); + + $alle_ampeln = $this->getDataOrTerminateWithError($alle_ampeln); + + $alle_ampeln = array_map(function ($ampel) { + // check if ampel is confirmed by user + $confirmedByUser = $this->AmpelModel->isConfirmed($ampel->ampel_id, $this->uid); + $ampel->bestaetigt = $confirmedByUser; + return $ampel; + }, $alle_ampeln); + + $this->terminateWithSuccess($alle_ampeln); + } +} + diff --git a/application/controllers/api/frontend/v1/Bookmark.php b/application/controllers/api/frontend/v1/Bookmark.php new file mode 100644 index 000000000..a811843ce --- /dev/null +++ b/application/controllers/api/frontend/v1/Bookmark.php @@ -0,0 +1,109 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +class Bookmark extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getBookmarks' => self::PERM_LOGGED, + 'delete' => self::PERM_LOGGED, + 'insert' => self::PERM_LOGGED, + ]); + + $this->load->model('dashboard/Bookmark_model', 'BookmarkModel'); + + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + + /** + * gets the bookmarks associated to a user + * @access public + * @return void + */ + public function getBookmarks() + { + $bookmarks = $this->BookmarkModel->loadWhere(["uid"=>$this->uid]); + + $bookmarks = $this->getDataOrTerminateWithError($bookmarks); + + $this->terminateWithSuccess($bookmarks); + } + + /** + * deletes bookmark from associated user + * @access public + * @return void + */ + public function delete($bookmark_id) + { + $bookmark = $this->BookmarkModel->load($bookmark_id); + + $bookmark = current($this->getDataOrTerminateWithError($bookmark)); + + // only delete bookmark if the user is the owner of the bookmark + if($bookmark->uid == $this->uid || $this->permissionlib->isBerechtigt('admin')){ + + $delete_result = $this->BookmarkModel->delete($bookmark_id); + + $delete_result = $this->getDataOrTerminateWithError($delete_result); + + $this->terminateWithSuccess($delete_result); + }else{ + $this->_outputAuthError(['delete' => ['admin:rw']]); + } + } + + /** + * inserts new bookmark into the bookmark table + * @access public + * @return void + */ + public function insert() + { + // form validation + $this->load->library('form_validation'); + $this->form_validation->set_rules('url', 'URL', 'required|valid_url|max_length[511]'); + $this->form_validation->set_rules('title', 'Title', 'required|max_length[255]'); + if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $url = $this->input->post('url',true); + $title = $this->input->post('title',true); + $tag = $this->input->post('tag', true); + + $insert_into_result = $this->BookmarkModel->insert(['uid'=>$this->uid, 'url'=>$url, 'title'=>$title,'tag'=>$tag, 'insertvon'=>$this->uid, 'updateamum'=>NULL, 'updatevon'=>NULL]); + + $insert_into_result = $this->getDataOrTerminateWithError($insert_into_result); + + $this->terminateWithSuccess($insert_into_result); + + } +} + diff --git a/application/controllers/api/frontend/v1/Cms.php b/application/controllers/api/frontend/v1/Cms.php new file mode 100644 index 000000000..e41196f45 --- /dev/null +++ b/application/controllers/api/frontend/v1/Cms.php @@ -0,0 +1,195 @@ +. + */ + +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 Cms extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + // NOTE(chris): additional permission checks will be done in SearchBarLib + parent::__construct([ + 'ContentID' => self::PERM_LOGGED, + 'getOrtKurzbzContent' => self::PERM_LOGGED, + 'content' => self::PERM_LOGGED, + 'news' => self::PERM_LOGGED, + 'getNewsRowCount' => self::PERM_LOGGED, + 'getNews' => self::PERM_LOGGED, + + ]); + + $this->load->model('content/News_model', 'NewsModel'); + + // setting up the papgination_size + $this->page_size = 10; + + $this->load->library('CmsLib'); + + // Loads phrases system + $this->loadPhrases([ + 'global' + ]); + + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * fetches the content with the content_id and additional parameters + */ + public function content() + { + // form validation + $this->load->library('form_validation'); + $this->form_validation->set_data($_GET); + $this->form_validation->set_rules('content_id','Content ID','required|is_natural'); + if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // getting the get parameters + $content_id = $this->input->get("content_id",TRUE); + $version = $this->input->get("version",TRUE); + $sprache = $this->input->get("sprache",TRUE); + $sichtbar = $this->input->get("sichtbar",TRUE); + + $content = $this->cmslib->getContent($content_id, $version, $sprache, $sichtbar); + $content = $this->getDataOrTerminateWithError($content); + + $this->terminateWithSuccess($content); + } + + /** + * Gets a JSON body via HTTP POST and provides the parameters + */ + public function ContentID() + { + // form validation + $this->load->library('form_validation'); + $this->form_validation->set_data($_GET); + $this->form_validation->set_rules('ort_kurzbz', 'Ort', 'required'); + if ($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $ort_kurzbz = $this->input->get('ort_kurzbz',TRUE); + + $content_id = $this->OrtModel->getContentID($ort_kurzbz); + + $content_id = current($this->getDataOrTerminateWithError($content_id))->content_id; + + $this->terminateWithSuccess($content_id); + } + + //todo: there is the method news and getNews but only one should exist + public function news() + { + + // form validation + $this->load->library('form_validation'); + $this->form_validation->set_data($_GET); + $this->form_validation->set_rules('limit','Limit','required|is_natural_no_zero'); + if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $this->load->model('content/news_model', 'NewsModel'); + + $limit = $this->input->get('limit',TRUE); + + //query the news + $news = $this->NewsModel->getAll($limit); + + //get the data or terminate with error + $news = $this->getDataOrTerminateWithError($news); + + // collect the content of the news + foreach($news as $news_element){ + $this->addMeta("content_id",$news_element->content_id); + + //todo: quick fix, for query builder error when fetching content + $this->NewsModel->resetQuery(); + $content = $this->cmslib->getContent($news_element->content_id); + + $content = getData($content); + + $news_element->content_obj = $content; + } + $withContent = function($news) { + return $news->content_obj != null; + }; + + $newsWithContent = array_filter($news, $withContent); + + $this->terminateWithSuccess($newsWithContent); + + } + + public function getNewsRowCount($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $fachbereich_kurzbz = null, $maxalter = 0, $edit = false, $sichtbar = true, $page = 1, $page_size = 10) + { + list($studiengang_kz, $semester) = $this->cmslib->getStgAndSem($studiengang_kz, $semester); + $all = $edit; + + $this->load->model('content/News_model','NewsModel'); + + $num_rows = $this->NewsModel->countNewsWithContent(getSprache(), $studiengang_kz, $semester, $fachbereich_kurzbz, $sichtbar, $maxalter, $page, $page_size, $all, $mischen); + + $num_rows = $this->getDataOrTerminateWithError($num_rows); + + $this->terminateWithSuccess($num_rows); + + } + + + public function getNews($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $edit = false, $sichtbar = true) + { + //form validation + $this->load->library('form_validation'); + $this->form_validation->set_data($_GET); + $this->form_validation->set_rules('page','Page','required|is_natural'); + $this->form_validation->set_rules('page_size', 'PageSize', 'is_natural'); + if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // getting the GET parameters + $page = intval($this->input->get('page', true)); + $page_size = intval($this->input->get('page_size', true)); + + // default value for the page_size is 10 + $page_size = $page_size ?? 10; + + $news = $this->cmslib->getNews($infoscreen, $studiengang_kz, $semester, $mischen, $titel, $edit, $sichtbar, $page, $page_size); + + $news = $this->getDataOrTerminateWithError($news); + + $this->addMeta('test', $this->p->t('global', 'studiengangsleitung')); + $this->addMeta('phrases', json_decode($this->p->getJson())); + $this->terminateWithSuccess($news); + + } + + +} + 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/Lehre.php b/application/controllers/api/frontend/v1/Lehre.php new file mode 100644 index 000000000..c25dc1986 --- /dev/null +++ b/application/controllers/api/frontend/v1/Lehre.php @@ -0,0 +1,85 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + + +class Lehre extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'lvStudentenMail' => self::PERM_LOGGED, + 'LV' => self::PERM_LOGGED, + ]); + + + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * constructs the emails of the groups from a lehrveranstaltung + */ + public function lvStudentenMail() + { + $lehreinheit_id = $this->input->get("lehreinheit_id",TRUE); + + // return early if the required parameter is missing + if(!isset($lehreinheit_id)) + { + $this->terminateWithError('Missing required parameter', self::ERROR_TYPE_GENERAL); + } + + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + $studentenMails = $this->LehreinheitModel->getStudentenMail($lehreinheit_id); + + $studentenMails = $this->getDataOrTerminateWithError($studentenMails); + + //convert array of objects into array of strings + $studentenMails = array_map(function($element){ + return $element->mail; + }, $studentenMails); + + $this->terminateWithSuccess($studentenMails); + } + + public function LV($studiensemester_kurzbz, $lehrveranstaltung_id) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID(), $studiensemester_kurzbz, getUserLanguage(), $lehrveranstaltung_id); + + $result = current($this->getDataOrTerminateWithError($result)); + + $this->terminateWithSuccess($result); + } + + + + + +} + diff --git a/application/controllers/api/frontend/v1/LvMenu.php b/application/controllers/api/frontend/v1/LvMenu.php new file mode 100644 index 000000000..777d49b0c --- /dev/null +++ b/application/controllers/api/frontend/v1/LvMenu.php @@ -0,0 +1,532 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + + +use CI3_Events as Events; + +/** + * 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 LvMenu extends FHCAPI_Controller +{ + + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getLvMenu' => self::PERM_LOGGED + ]); + + $this->load->model("ressource/Mitarbeiter_model"); + $this->load->model("education/Lehreinheit_model"); + $this->load->model("education/Lehrveranstaltung_model"); + $this->load->model("organisation/Studiengang_model"); + $this->load->model("accounting/Vertrag_model"); + $this->load->model("system/Variable_model"); + $this->load->model("person/Benutzergruppe_model"); + $this->load->model("education/Lvangebot_model"); + $this->load->model("ressource/Lehretools_model"); + + $this->load->library("PermissionLib", null, 'PermissionLib'); + + $this->load->library("PhrasesLib"); + $this->loadPhrases(array('global', 'lehre')); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * + */ + public function getLvMenu($lvid, $studiensemester_kurzbz) + { + + // return early if parameters are missing + if(!isset($lvid) || !isset($studiensemester_kurzbz)) + $this->terminateWithError('Missing parameters', self::ERROR_TYPE_GENERAL); + + // get the sprache + $sprache = getUserLanguage(); + + // get the user + if (!$user=getAuthUID()) + $this->terminateWithError($this->p->t('global', 'nichtAngemeldet')); + + // check if is_lector + $is_lector = false; + $mares = $this->Mitarbeiter_model->isMitarbeiter($user); + if(hasData($mares)) + { + $is_lector = getData($mares); + } + + // definition of user_is_allowed_to_upload + $user_is_allowed_to_upload=false; + $angezeigtes_stsem = $studiensemester_kurzbz; + + // load lehrveranstaltung + $lvres = $this->Lehrveranstaltung_model->load($lvid); + if(!hasData($lvres)) + { + $this->terminateWithError('LV ' . $lvid . ' not found.'); + } + $lv = (getData($lvres))[0]; + + // define studiengang_kz / semester / lehrverzeichnis + $studiengang_kz = $lv->studiengang_kz; + $semester = $lv->semester; + $short = $lv->lehreverzeichnis; + + // load studiengang + $stgres = $this->Studiengang_model->load($lv->studiengang_kz); + if(!hasData($stgres)) + { + $this->terminateWithError('Stg ' . $lv->studiengang_kz . ' nof found.'); + } + $stg = (getData($stgres))[0]; + $kurzbz = strtoupper($stg->typ . $stg->kurzbz); + + $short_name = $lv->bezeichnung; + $short_short_name = $lv->lehreverzeichnis; + + // angemeldet + $angemeldet = true; + if(defined('CIS_LEHRVERANSTALTUNG_WENNANGEMELDET_DETAILS_ANZEIGEN') && CIS_LEHRVERANSTALTUNG_WENNANGEMELDET_DETAILS_ANZEIGEN && !$is_lector) + { + $angemeldet = false; + + $lesres = $this->Lehreinheit_model->getLehreinheitenForStudentAndStudienSemester( + $lvid, $user, $angezeigtes_stsem + ); + + if(hasData($lesres) && count(getData($lesres)) > 0) + $angemeldet = true; + } + + // lehrfach + $lehrfach_id=''; + + if(defined('CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN') && CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN) + { + // Wenn der eingeloggte User zu einer der Lehreinheiten zugeteilt ist + // wird zusätzlich das Lehrfach der Lehreinheit angezeigt. + if($is_lector ) + { + $result = $this->Lehreinheit_model->getLehrfachIdMitarbeiter($angezeigtes_stsem,$user,$lvid); + } + else + { + $result = $this->Lehreinheit_model->getLehrfachIdStudierender($angezeigtes_stsem,$user,$lvid); + } + + // Wenn die LV mehrere verschiedenen Lehrfaecher hat, und der User zu mehreren davon zugeteilt ist + // wird das Lehrfach nicht angezeigt damit es nicht zu verwirrungen kommt. + if( ($lehrfaecher = getData($result)) && count($lehrfaecher)==1 && ($lehrfach = $lehrfaecher[0])) + { + $lehrfach_id=$lehrfach->lehrfach_id; + } + } + + // lektor der lv + $lektor_der_lv=false; + + $leinfores = $this->Lehreinheit_model->getLehreinheitInfo($lvid,$angezeigtes_stsem,$lehrfach_id); + $db_result = hasData($leinfores) ? getData($leinfores) : array(); + + foreach($db_result as $row_lector) + { + + // Lektor wird erst angezeigt wenn der Auftrag erteilt wurde + if (defined('CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON') + && CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON != '') + { + if (!$this->Vertrag_model->isVertragErteiltLV($lvid, $angezeigtes_stsem, $row_lector->uid)) + { + continue; + } + } + + + if($user == $row_lector->uid) + { + $lektor_der_lv=true; + $user_is_allowed_to_upload=true; + } + + // style of the link + if($row_lector->lvleiter === true) + $style='style="font-weight: bold"'; + else + $style=''; + + } + + //Berechtigungen auf Fachbereichsebene + $lehrfach_oe_kurzbz_arr = array(); + $fbres = $this->Lehrveranstaltung_model->getBerechtigungenAufFachberechsebene($lvid, $angezeigtes_stsem); + $fbs = (hasData($fbres)) ? getData($fbres) : array(); + foreach($fbs as $row) + { + $lehrfach_oe_kurzbz_arr[] = $row->oe_kurzbz; + if($this->PermissionLib->isBerechtigt('lehre', null, $row->oe_kurzbz) + || $this->PermissionLib->isBerechtigt('assistenz', null, $stg->oe_kurzbz)) + { + $user_is_allowed_to_upload=true; + } + } + + // FH-Core Menu Logic + // ########################################################################################## + + $menu = array(); + + $this->fhc_menu_lvinfo($menu, $lvid, $studiengang_kz, $lektor_der_lv, $is_lector, $lehrfach_oe_kurzbz_arr); + + $this->fhc_menu_feedback($menu, $angemeldet, $lvid); + + $this->fhc_menu_gesamtnote($menu, $angemeldet, $lvid, $lv, $is_lector, $angezeigtes_stsem); + + $this->fhc_menu_emailStudierende($menu, $user, $angemeldet, $lvid, $angezeigtes_stsem); + + $this->fhc_menu_abmeldung($menu, $user, $is_lector, $lvid, $angezeigtes_stsem); + + $this->fhc_menu_lehretools($menu, $lvid, $angezeigtes_stsem, $sprache); + + $this->fhc_menu_anrechnungStudent($menu, $lvid, $angezeigtes_stsem); + + $this->fhc_menu_anrechnungLector($menu, $angezeigtes_stsem); + + + // Addons Menu Logic + // ########################################################################################## + + $params = [ + 'sprache'=>$sprache, + //'p'=>$p, + 'ci_p'=> $this->p, + //'db'=>$db, + 'user'=>$user, + 'is_lector'=>$is_lector, + 'user_is_allowed_to_upload'=>$user_is_allowed_to_upload, + //'rechte'=>$rechte, + 'angezeigtes_stsem'=>$angezeigtes_stsem, + //'lehreinheit'=>$lehreinheit, + 'lv_obj'=>$lv, + 'lv'=>$lv, + 'lvid'=>$lvid, + 'studiengang_kz'=>$studiengang_kz, + 'semester'=>$semester, + 'short'=>$short, + 'stg_obj'=>$stg, + 'kurzbz'=>$kurzbz, + 'short_name'=>$short_name, + 'short_short_name'=>$short_short_name, + //'dir_name'=>$dir_name, + 'angemeldet'=>$angemeldet, + 'lehrfach_id'=>$lehrfach_id, + 'lektor_der_lv'=>$lektor_der_lv, + 'lehrfach_oe_kurzbz_arr'=>$lehrfach_oe_kurzbz_arr, + ]; + + Events::trigger('lvMenuBuild', + // passing $menu per reference + function & () use (&$menu) { + return $menu; + }, + $params + ); + + // Menu sortieren + // ########################################################################################## + + foreach ($menu as $key => $row){ + + // removes menu points that are not needed in the c4 lvUebersicht + if( !array_key_exists('c4_link',$row) || !array_key_exists('c4_icon',$row)){ + unset($menu[$key]); + continue; + } + + // fills pos array to sort the menu + $pos[$key] = $row['position']; + + } + + array_multisort($pos, SORT_ASC, SORT_NUMERIC, $menu); + + // HTTP response + // ########################################################################################## + + $this->terminateWithSuccess($menu); + + } + + + private function fhc_menu_digitale_anwesenheiten(&$menu, $angemeldet, $studiengang_kz, $semester, $lvid, $angezeigtes_stsem){ + + // DIGITALE ANWESENHEITEN + if (defined('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN') && CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN && $angemeldet) { + + $menu[] = array + ( + 'id' => 'core_menu_digitale_anwesenheitslisten', + 'position' => '50', + 'name' => $this->p->t('lehre', 'digiAnw'), + 'c4_icon' => base_url('skin/images/button_kreuzerltool.png'), + 'c4_link' => base_url("index.ci.php/extensions/FHC-Core-Anwesenheiten/?stg_kz=$studiengang_kz&sem=$semester&lvid=$lvid&sem_kurzbz=$angezeigtes_stsem&nav=false"), + 'c4_linkList' => [] + ); + } + } + + private function fhc_menu_lvinfo(&$menu, $lvid, $studiengang_kz, $lektor_der_lv, $is_lector, $lehrfach_oe_kurzbz_arr){ + + // LVINFO + if(!defined('CIS_LEHRVERANSTALTUNG_LVINFO_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_LVINFO_ANZEIGEN) + { + $c4_linkList=array(); + + // Bearbeiten Button anzeigen wenn Lektor der LV und bearbeiten fuer Lektoren aktiviert ist + // Oder Berechtigung zum Bearbeiten eingetragen ist + if((!defined('CIS_LEHRVERANSTALTUNG_LVINFO_LEKTOR_EDIT') && $lektor_der_lv) + || (defined('CIS_LEHRVERANSTALTUNG_LVINFO_LEKTOR_EDIT') && CIS_LEHRVERANSTALTUNG_LVINFO_LEKTOR_EDIT==true && $lektor_der_lv) + || $this->PermissionLib->isBerechtigt('lehre/lvinfo',$studiengang_kz) + || $this->PermissionLib->isBerechtigtMultipleOe('lehre/lvinfo', $lehrfach_oe_kurzbz_arr) + ) + { + $c4_linkList[]= [$this->p->t('lehre', 'lvInfoBearbeiten'), 'ects/index.php?lvid='.$lvid]; + } + elseif ($is_lector) + { + $c4_linkList[]= ["Bearbeiten der LV-Infos derzeit gesperrt",'#']; + } + + $menu[]=array + ( + 'id'=>'core_menu_lvinfo', + 'position'=>'10', + 'name'=>$this->p->t('lehre', 'lehrveranstaltungsinformation'), + 'icon'=>'../../../skin/images/button_lvinfo.png', + 'link'=>'', + 'c4_icon'=> base_url('skin/images/button_lvinfo.png'), + 'c4_link'=>'', + 'c4_linkList'=>$c4_linkList + ); + } + } + + private function fhc_menu_feedback(&$menu, $angemeldet, $lvid){ + //FEEDBACK + if((!defined('CIS_LEHRVERANSTALTUNG_FEEDBACK_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_FEEDBACK_ANZEIGEN) && $angemeldet) + { + $menu[]=array + ( + 'id'=>'core_menu_feedback', + 'position'=>'60', + 'name'=>$this->p->t('lehre', 'feedback'), + 'c4_icon'=> base_url('skin/images/button_feedback.png'), + 'c4_link'=> base_url('feedback.php?lvid='.$lvid), + ); + } + } + + private function fhc_menu_gesamtnote(&$menu, $angemeldet, $lvid, $lv_obj, $is_lector, $angezeigtes_stsem){ + //Gesamtnote + if($is_lector && ((!defined('CIS_LEHRVERANSTALTUNG_GESAMTNOTE_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_GESAMTNOTE_ANZEIGEN) && $angemeldet)) + { + if($lv_obj->benotung) + { + $menu[]=array + ( + 'id'=>'core_menu_gesamtnote', + 'position'=>'80', + 'name'=>$this->p->t('lehre', 'gesamtnote'), + 'c4_icon'=> base_url('skin/images/button_endnote.png'), + 'c4_link'=> base_url('cis/private/lehre/benotungstool/lvgesamtnoteverwalten.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem)) + //'c4_link'=> base_url('benotungstool/lvgesamtnoteverwalten.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem)) + ); + } + else + { + $menu[]=array + ( + 'id'=>'core_menu_gesamtnote', + 'position'=>'80', + 'name'=>$this->p->t('lehre', 'gesamtnote'), + 'c4_icon'=>base_url('skin/images/button_endnote.png'), + 'c4_link'=>'#', + 'c4_linkList'=>[[$this->p->t('lehre', 'noteneingabedeaktiviert'),'#']], + ); + } + } + } + + + + private function fhc_menu_emailStudierende(&$menu, $user, $angemeldet, $lvid, $angezeigtes_stsem){ + // Email an Studierende + if((!defined('CIS_LEHRVERANSTALTUNG_MAILSTUDIERENDE_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_MAILSTUDIERENDE_ANZEIGEN) && $angemeldet) + { + $mailto='mailto:'; + $c4_linkList=array(); + + $studentMailsRes = $this->Lehrveranstaltung_model->getStudentEMail($lvid, $angezeigtes_stsem); + + // get the data of the database result and map the array of objects to their object property + $studentMails = $this->getDataOrTerminateWithError($studentMailsRes, 'No student mails found'); + + + $nomail=''; + $variablesres = $this->Variable_model->getVariables($user); + $variables = (hasData($variablesres)) ? getData($variablesres) : array(); + + foreach ($studentMails as $row) + { + if($row->gruppe_kurzbz != '') + { + $bngrp_uids = $this->Benutzergruppe_model->getUids($row->gruppe_kurzbz, $angezeigtes_stsem); + if(count($bngrp_uids) > 0) + { + if(!$row->mailgrp) + { + $nomail = $row->gruppe_kurzbz . ' '; + } + else + { + $mailto .= mb_strtolower($row->gruppe_kurzbz . '@' + . DOMAIN . $variables['emailadressentrennzeichen']); + } + } + } + else + { + $mailto .= mb_strtolower($row->stg_typ . $row->stg_kurzbz + . $row->semester . trim($row->verband) . trim($row->gruppe) + . '@' . DOMAIN . $variables['emailadressentrennzeichen']); + } + } + + if($nomail != '') + { + $c4_linkList[] = array( + $this->p->t('lehre', 'keinMailverteiler', array('nomail' => $nomail)), + '#' + ); + $link_onclick = 'alert(\''.$this->p->t('lehre', 'keinMailverteiler', array('nomail' => $nomail)) . '\');'; + } + else + { + $link_onclick = ''; + } + + + $menu[]=array + ( + 'id'=>'core_menu_mailanstudierende', + 'position'=>'100', + 'name'=>$this->p->t('lehre', 'mail'), + 'c4_icon'=>base_url('skin/images/button_feedback.png'), + 'c4_icon2' => 'fa-regular fa-envelope', + 'c4_link'=>$mailto, + 'c4_linkList'=>$c4_linkList, + 'link_onclick'=>$link_onclick + ); + } + } + + + + private function fhc_menu_abmeldung(&$menu, $user, $is_lector, $lvid, $angezeigtes_stsem){ + if(!defined('CIS_LEHRVERANSTALTUNG_ABMELDUNG_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_ABMELDUNG_ANZEIGEN) + { + if(!$is_lector) + { + $gruppen = $this->Lvangebot_model->AbmeldungMoeglich($lvid, $angezeigtes_stsem, $user); + if(count($gruppen) > 0) + { + $menu[]=array + ( + 'id'=>'core_menu_abmeldung', + 'position'=>'120', + 'name'=>$this->p->t('lehre', 'abmelden'), + 'c4_icon'=>base_url('skin/images/button_studiupload.png'), + 'c4_link'=>base_url('abmeldung.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem)), + ); + + } + } + } + } + + private function fhc_menu_lehretools(&$menu, $lvid, $angezeigtes_stsem, $sprache){ + //Anzeigen von zusaetzlichen Lehre-Tools + $lehretools = $this->Lehretools_model->getTools($lvid, $angezeigtes_stsem, $sprache); + foreach($lehretools as $row) + { + $menu[] = array( + 'id' => 'core_menu_lehretools_' . $row->lehre_tools_id, + 'position' => '1000', + 'name' => $row->bezeichnung, + 'c4_icon' => base_url('cms/dms.php?id='.$row->logo_dms_id), + 'c4_link' => $row->basis_url, + ); + } + } + + private function fhc_menu_anrechnungStudent(&$menu, $lvid, $angezeigtes_stsem){ + // Anerkennung nachgewiesener Kenntnisse (Anrechnung) - Anzeige fuer Studenten + if((!defined('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN) + && $this->PermissionLib->isBerechtigt('student/anrechnung_beantragen')) + { + $menu[]=array + ( + 'id' => 'core_menu_anerkennungNachgewiesenerKenntnisse', + 'position' => '128', + 'name' => $this->p->t('lehre', 'anrechnung'), + 'c4_icon' => base_url('skin/images/button_listen.png'), + 'c4_icon2' => 'fa-regular fa-folder-open', + 'c4_link' => base_url('cis.php/lehre/anrechnung/RequestAnrechnung?studiensemester='.urlencode($angezeigtes_stsem).'&lv_id='.urlencode($lvid)) + ); + } + } + + private function fhc_menu_anrechnungLector(&$menu, $angezeigtes_stsem){ + // Anerkennung nachgewiesener Kenntnisse (Anrechnung) - Anzeige fuer LektorInnen + if((!defined('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN') || CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN) + && $this->PermissionLib->isBerechtigt('lehre/anrechnung_empfehlen')) + { + $menu[]=array + ( + 'id' => 'core_menu_anerkennungNachgewiesenerKenntnisse_empfehlen', + 'position' => '128', + 'name' => $this->p->t('lehre', 'anrechnungen'), + 'c4_icon'=> base_url('skin/images/button_listen.png'), + 'c4_icon2' => 'fa-regular fa-folder-open', + 'c4_link' => base_url('cis.php/lehre/anrechnung/ReviewAnrechnungUebersicht?studiensemester='.urlencode($angezeigtes_stsem)) + ); + } + } +} \ No newline at end of file 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/Ort.php b/application/controllers/api/frontend/v1/Ort.php new file mode 100644 index 000000000..8c4059824 --- /dev/null +++ b/application/controllers/api/frontend/v1/Ort.php @@ -0,0 +1,95 @@ +. + */ + +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 Ort extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + // NOTE(chris): additional permission checks will be done in SearchBarLib + parent::__construct([ + 'ContentID' => self::PERM_LOGGED, + 'getOrtKurzbzContent' => self::PERM_LOGGED, + ]); + + $this->load->model('ressource/Ort_model', 'OrtModel'); + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Gets a JSON body via HTTP POST and provides the parameters + */ + public function ContentID() + { + // if error + //$this->terminateWithError(SearchBarLib::ERROR_WRONG_JSON, self::ERROR_TYPE_GENERAL); + + $ort_kurzbz = $this->input->get('ort_kurzbz',TRUE); + + if(!$ort_kurzbz){ + $this->terminateWithError("missing ort_kurzbz parameter", self::ERROR_TYPE_GENERAL); + } + + $result = $this->OrtModel->getContentID($ort_kurzbz); + + if(isError($result)){ + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $result = hasData($result) ? current(getData($result)) : null; + + $this->terminateWithSuccess($result->content_id ?? NULL); + } + + /** + * @param int $version + * @param string $sprache + * @param boolean $sichtbar + * + * @return $content + */ + public function getOrtKurzbzContent($version = null, $sprache = null, $sichtbar = true) + { + $content_id = $this->input->get("content_id",TRUE); + + $this->load->library('CmsLib'); + + $content = $this->cmslib->getContent($content_id, $version, $sprache, $sichtbar); + + if (isError($content)) + $this->terminateWithError(getError($content), self::ERROR_TYPE_GENERAL); + + $content = hasData($content) ? getData($content) : null; + + $this->terminateWithSuccess($content); + } +} + diff --git a/application/controllers/api/frontend/v1/Phrasen.php b/application/controllers/api/frontend/v1/Phrasen.php new file mode 100644 index 000000000..3509e6630 --- /dev/null +++ b/application/controllers/api/frontend/v1/Phrasen.php @@ -0,0 +1,84 @@ +. + */ + +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, + 'setLanguage' => self::PERM_ANONYMOUS, + 'getLanguage' => self::PERM_ANONYMOUS, + 'getAllLanguages' => self::PERM_ANONYMOUS, + ]); + + $this->load->helper('hlp_language'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * @param string $module + */ + public function loadModule($module) + { + $this->load->library('PhrasesLib', [$module], 'pj'); + $this->terminateWithSuccess(json_decode($this->pj->getJSON())); + } + + public function setLanguage() + { + $postParams = $this->getPostJSON(); + $language = $postParams->language; + $categories = $postParams->categories; + + setUserLanguage($language); + + $this->load->library('PhrasesLib', array($categories, $language), 'p'); + + $phrases = $this->p->setPhrases($categories, $language); + $this->terminateWithSuccess($phrases); + } + + // gets the langauge of the currently logged in user session and otherwhise the system language + public function getLanguage() + { + $lang = getUserLanguage(); + $this->terminateWithSuccess($lang); + } + + // gets all languages that are set as active in the database + public function getAllLanguages() + { + $langs = getDBActiveLanguages(); + $langs = $this->getDataOrTerminateWithError($langs); + $langs = array_map(function($lang){ + return $lang->sprache; + }, $langs); + $this->terminateWithSuccess($langs); + } + +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/Profil.php b/application/controllers/api/frontend/v1/Profil.php new file mode 100644 index 000000000..576a2a8ed --- /dev/null +++ b/application/controllers/api/frontend/v1/Profil.php @@ -0,0 +1,695 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +class Profil extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getView' => self::PERM_LOGGED, + 'fotoSperre' => self::PERM_LOGGED, + 'getGemeinden' => self::PERM_LOGGED, + 'getAllNationen' => self::PERM_LOGGED, + 'isMitarbeiter' => self::PERM_LOGGED, + + ]); + + $this->load->library('PermissionLib'); + + $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('person/Adresse_model', 'AdresseModel'); + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + $this->load->model('ressource/Betriebsmittelperson_model', 'BetriebsmittelpersonModel'); + $this->load->model('person/Kontakt_model', 'KontaktModel'); + $this->load->model('person/Profil_update_model', 'ProfilUpdateModel'); + $this->load->model('content/DmsVersion_model', 'DmsVersionModel'); + + + //? put the uid and pid inside the controller for reusability + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + + /** + * function that returns the data used for the corresponding view + * the client side parses the @param $uid and calls this function to get the data to the correct view + * @access public + * @param boolean $uid the userID used to identify which information should be retrieved for which view + * @return stdClass all the data corresponding to a view of a user + */ + public function getView($uid) + { + $res = new stdClass(); + $editAllowed = getAuthUID() == $uid || $this->permissionlib->isBerechtigt('admin'); + + // if parsing the URL did not found a UID then the UID of the logged in user is used + if ($uid == "Profil" || $uid == $this->uid) { + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter($this->uid); + if (isError($isMitarbeiter)) { + show_error("error while checking if UID: " . $this->uid . " is a mitarbeiter"); + } + $isMitarbeiter = getData($isMitarbeiter); + if ($isMitarbeiter) { + $res->view = "MitarbeiterProfil"; + $res->data = $this->mitarbeiterProfil(); + $res->data->pid = $this->pid; + } else { + $res->view = "StudentProfil"; + $res->data = $this->studentProfil(); + $res->data->pid = $this->pid; + } + // editing your own profil - true + $editAllowed = true; + } + // UID is availabe when accessing Profil/View/:uid + else { + $this->PersonModel->addSelect(["person_id"]); + $pid = $this->PersonModel->getByUid($uid); + if (isError($pid)) { + show_error("error while trying to update table public.tbl_person while searching for a person with UID: " . $uid); + } + $pid = hasData($pid) ? getData($pid)[0] : null; + if (!$pid) { + show_error("Person with UID: " . $uid . " does not exist"); + } + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid); + if (isError($isMitarbeiter)) { + show_error("error while checking if UID: " . $uid . " is a mitarbeiter"); + } + $isMitarbeiter = getData($isMitarbeiter); + if ($isMitarbeiter) { + $res->view = "ViewMitarbeiterProfil"; + $res->data = $this->viewMitarbeiterProfil($uid); + + } else { + $res->view = "ViewStudentProfil"; + $res->data = $this->viewStudentProfil($uid); + } + } + $res->data->editAllowed = $editAllowed; + $this->terminateWithSuccess($res); + } + + /** + * update column foto_sperre in public.tbl_person + * @access public + * @param boolean $value new value for the column + * @return boolean the new value added to the column in public.tbl_person + */ + public function fotoSperre($value) + { + if(!isset($value)){ + $this->terminateWithError("Missing parameter", self::ERROR_TYPE_GENERAL); + } + + $res = $this->PersonModel->update($this->pid, ["foto_sperre" => $value]); + if (isError($res)) { + show_error("error while trying to update table public.tbl_person"); + } + $this->PersonModel->addSelect("foto_sperre"); + $res = $this->PersonModel->load($this->pid); + if (isError($res)) { + show_error("error while trying to query table public.tbl_person"); + } + + $res = $this->getDataOrTerminateWithError($res); + + $this->terminateWithSuccess(current($res)); + } + + /** + * gets all nations in the table bis.tbl_nation + * + * @access public + * @return array all the nations in table bis.tbl_nation + */ + public function getAllNationen() + { + // load the nationen from the database + $this->load->model('codex/Nation_model', "NationModel"); + $this->NationModel->addSelect(["nation_code as code", "langtext"]); + $nation_res = $this->NationModel->load(); + + if (isError($nation_res)) { + $this->terminateWithError("error while trying to query table codex.tbl_nation", self::ERROR_TYPE_GENERAL); + } + + $nation_res = $this->getDataOrTerminateWithError($nation_res); + + $this->terminateWithSuccess($nation_res); + } + + public function getGemeinden($nation, $zip) + { + if(!isset($nation) || !isset($zip)){ + echo json_encode(error("Missing parameters")); + return; + } + + $this->load->model('codex/Gemeinde_model', "GemeindeModel"); + + + $gemeinde_res = $this->GemeindeModel->getGemeindeByPlz($zip); + + if (isError($gemeinde_res)) { + $this->terminateWithError(getError($gemeinde_res),self::ERROR_TYPE_GENERAL); + } + $gemeinde_res = $this->getDataOrTerminateWithError($gemeinde_res); + + /* $gemeinde_res = array_map(function ($obj) { + return $obj->ortschaftsname; + }, $gemeinde_res); */ + + $this->terminateWithSuccess($gemeinde_res); + + } + + + // ----------------------------------------------------------------------------------------------------------------- + // Private methods + + /** + * function that returns the data used for viewing another mitarbeiter profile + * @access private + * @param integer $uid the userID to retrieve the mitarbeiter data + * @return stdClass restricted mitarbeiter data + */ + private function viewMitarbeiterProfil($uid) + { + $mailverteiler_res = $this->getMailverteiler($uid); + $benutzer_funktion_res = $this->getBenutzerFunktion($uid); + $benutzer_res = $this->getBenutzerAlias($uid); + $person_res = $this->getPersonInfo($uid); + $mitarbeiter_res = $this->getMitarbeiterInfo($uid); + $telefon_res = $this->getTelefonInfo($uid); + + $res = new stdClass(); + $res->username = $uid; + + //? Person Info + foreach ($person_res as $key => $val) { + $res->$key = $val; + } + + //? Mitarbeiter Info + foreach ($mitarbeiter_res as $key => $val) { + $res->$key = $val; + + } + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = $uid . "@" . DOMAIN; + $extern_email = array(); + $extern_email["type"] = "alias"; + $extern_email["email"] = $benutzer_res->alias . "@" . DOMAIN; + $res->emails = array($intern_email, $extern_email); + + $res->funktionen = $benutzer_funktion_res; + $res->mailverteiler = $mailverteiler_res; + $res->standort_telefon = isset($telefon_res) ? $telefon_res->kontakt : null; + + return $res; + } + + /** + * function that returns the data used for viewing another student profile + * @access private + * @param integer $uid the userID to retrieve the student data + * @return stdClass restricted student data + */ + private function viewStudentProfil($uid) + { + $mailverteiler_res = $this->getMailverteiler($uid); + $person_res = $this->getPersonInfo($uid); + $student_res = $this->getStudentInfo($uid); + $matr_res = $this->getMatrikelNummer($uid); + + $res = new stdClass(); + $res->username = $uid; + + //? Person Information + foreach ($person_res as $key => $value) { + $res->$key = $value; + } + + //? Student Information + foreach ($student_res as $key => $value) { + $res->$key = $value; + } + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = $uid . "@" . DOMAIN; + + $res->emails = [$intern_email]; + $res->matrikelnummer = $matr_res->matr_nr; + $res->mailverteiler = $mailverteiler_res; + + return $res; + } + + /** + * checks whether a specific userID is a mitarbeiter or not (foreword declaration of the function isMitarbeiter in Mitarbeiter_model.php) + * @access public + * @param $uid the userID used to check if it is a mitarbeiter + * @return boolean + */ + public function isMitarbeiter($uid) + { + + if(!$uid) $this->terminateWithError("No uid provided", self::ERROR_TYPE_GENERAL); + + + $result = $this->MitarbeiterModel->isMitarbeiter($uid); + + if (isError($result)) { + $this->terminateWithError("error when calling Mitarbeiter_model function isMitarbeiter with uid " . $uid, self::ERROR_TYPE_GENERAL); + } + + $result = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($result); + } + + /** + * function that returns the data used for the mitarbeiter profile + * @access private + * @return stdClass mitarbeiter data + */ + private function mitarbeiterProfil() + { + + $zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($this->uid); + $adresse_res = $this->getAdressenInfo($this->pid); + $kontakte_res = $this->getKontaktInfo($this->pid); + $mailverteiler_res = $this->getMailverteiler($this->uid); + $person_res = $this->getPersonInfo($this->uid, true); + $benutzer_funktion_res = $this->getBenutzerFunktion($this->uid); + $betriebsmittelperson_res = $this->getBetriebsmittelInfo($this->pid); + $profilUpdates = $this->getProfilUpdates($this->uid); + $telefon_res = $this->getTelefonInfo($this->uid); + $mitarbeiter_res = $this->getMitarbeiterInfo($this->uid); + + $res = new stdClass(); + $res->username = $this->uid; + + //? Person Information + foreach ($person_res as $key => $value) { + $res->$key = $value; + } + + //? Mitarbeiter Information + foreach ($mitarbeiter_res as $key => $value) { + $res->$key = $value; + } + + $res->adressen = $adresse_res; + $res->zutrittsdatum = $zutrittskarte_ausgegebenam; + $res->kontakte = $kontakte_res; + $res->mittel = $betriebsmittelperson_res; + $res->mailverteiler = $mailverteiler_res; + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = $this->uid . "@" . DOMAIN; + $extern_email = array(); + $extern_email["type"] = "alias"; + $extern_email["email"] = $mitarbeiter_res->alias . "@" . DOMAIN; + $res->emails = [$intern_email, $extern_email]; + + $res->funktionen = $benutzer_funktion_res; + $res->standort_telefon = $telefon_res; + $res->profilUpdates = $profilUpdates; + + return $res; + } + + /** + * function that returns the data used for the student profile + * @access private + * @return stdClass student data + */ + private function studentProfil() + { + $betriebsmittelperson_res = $this->getBetriebsmittelInfo($this->pid); + $kontakte_res = $this->getKontaktInfo($this->pid); + $zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($this->uid); + $adresse_res = $this->getAdressenInfo($this->pid); + $mailverteiler_res = $this->getMailverteiler($this->uid); + $person_res = $this->getPersonInfo($this->uid, true); + $zutrittsgruppe_res = $this->getZutrittsgruppen($this->uid); + $student_res = $this->getStudentInfo($this->uid); + $matr_res = $this->getMatrikelNummer($this->uid); + $profilUpdates = $this->getProfilUpdates($this->uid); + + $res = new stdClass(); + $res->username = $this->uid; + + //? Person Information + foreach ($person_res as $key => $value) { + $res->$key = $value; + } + + //? Student Information + foreach ($student_res as $key => $value) { + $res->$key = trim($value); + } + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = $this->uid . "@" . DOMAIN; + + $res->emails = [$intern_email]; + $res->adressen = $adresse_res; + $res->zutrittsdatum = $zutrittskarte_ausgegebenam; + $res->kontakte = $kontakte_res; + $res->mittel = $betriebsmittelperson_res; + $res->matrikelnummer = $matr_res->matr_nr; + $res->zuttritsgruppen = $zutrittsgruppe_res; + $res->mailverteiler = $mailverteiler_res; + $res->profilUpdates = $profilUpdates; + + return $res; + } + + + /** + * gets all the mailverteiler using the tables: tbl_benutzer, tbl_benutzergruppe, tbl_gruppe + * @access private + * @param integer $uid the userID used to retrieve the mailverteiler + * @return array returns the mailvertailer corresponding to a userID + */ + private function getMailverteiler($uid) + { + $this->PersonModel->addSelect('gruppe_kurzbz, beschreibung'); + $this->PersonModel->addJoin('tbl_benutzer', 'person_id'); + $this->PersonModel->addJoin('tbl_benutzergruppe', 'uid'); + $this->PersonModel->addJoin('tbl_gruppe', 'gruppe_kurzbz'); + + $mailverteiler_res = $this->PersonModel->loadWhere(array('mailgrp' => true, 'uid' => $uid)); + if (isError($mailverteiler_res)) { + show_error("was not able to query the table public.tbl_benutzer:" . getData($mailverteiler_res)); + } + $mailverteiler_res = hasData($mailverteiler_res) ? getData($mailverteiler_res) : null; + $mailverteiler_res = array_map(function ($element) { + $element->mailto = "mailto:" . $element->gruppe_kurzbz . "@" . DOMAIN; + return $element; + }, $mailverteiler_res); + return $mailverteiler_res; + } + + /** + * gets all the Benutzerfunktionen of a corresponding user + * @access private + * @param integer $uid the userID used to retrieve the Benutzerfunktionen + * @return array returns the Benutzerfunktionen corresponding to a userID + */ + private function getBenutzerFunktion($uid) + { + $this->BenutzerfunktionModel->addSelect(["tbl_benutzerfunktion.bezeichnung as Bezeichnung", "tbl_organisationseinheit.bezeichnung as Organisationseinheit", "datum_von as Gültig_von", "datum_bis as Gültig_bis", "wochenstunden as Wochenstunden"]); + $this->BenutzerfunktionModel->addJoin("tbl_organisationseinheit", "oe_kurzbz"); + + $benutzer_funktion_res = $this->BenutzerfunktionModel->loadWhere(array('uid' => $uid)); + if (isError($benutzer_funktion_res)) { + show_error("was not able to query the table public.tbl_benutzerfunktion:" . getData($benutzer_funktion_res)); + } + $benutzer_funktion_res = hasData($benutzer_funktion_res) ? getData($benutzer_funktion_res) : null; + return $benutzer_funktion_res; + } + + /** + * gets all the Betriebsmittel of a corresponding user + * @access private + * @param integer $uid the userID used to retrieve the Betriebsmittel + * @return array returns the Betriebsmittel corresponding to a userID + */ + private function getBetriebsmittelInfo($pid) + { + $this->BetriebsmittelpersonModel->addSelect(["CONCAT(betriebsmitteltyp, ' ' ,beschreibung) as Betriebsmittel", "nummer as Nummer", "ausgegebenam as Ausgegeben_am"]); + + //? betriebsmittel are not needed in a view + $betriebsmittelperson_res = $this->BetriebsmittelpersonModel->getBetriebsmittel($pid); + if (isError($betriebsmittelperson_res)) { + show_error("was not able to query the table public.tbl_betriebsmittelperson:" . getData($betriebsmittelperson_res)); + } + $betriebsmittelperson_res = hasData($betriebsmittelperson_res) ? getData($betriebsmittelperson_res) : null; + return $betriebsmittelperson_res; + } + + /** + * gets the alias of a corresponding user + * @access private + * @param integer $uid the userID used to get the alias + * @return string the alias of the userID + */ + private function getBenutzerAlias($uid) + { + $this->BenutzerModel->addSelect(["alias"]); + $benutzer_res = $this->BenutzerModel->load([$uid]); + if (isError($benutzer_res)) { + show_error("was not able to query the table public.tbl_benutzer:" . getData($benutzer_res)); + } else { + $benutzer_res = hasData($benutzer_res) ? getData($benutzer_res)[0] : null; + } + + return $benutzer_res; + } + + /** + * gets the person information corresponding to a user + * @access private + * @param integer $uid the userID used to get the person information + * @param integer $geburtsInfo flag wether to add the columns gebort, gebdatum, foto_sperre or not + * @return array all the person informaion corresponding to a userID + */ + private function getPersonInfo($uid, $geburtsInfo = null) + { + $selectClause = ["foto", "foto_sperre", "anrede", "titelpost as postnomen", "titelpre as titel", "vorname", "nachname"]; + /** @param integer $geburtsInfo */ + if ($geburtsInfo) { + array_push($selectClause, "gebort"); + array_push($selectClause, "gebdatum"); + } + $this->BenutzerModel->addSelect($selectClause); + $this->BenutzerModel->addJoin("tbl_person", "person_id"); + + $person_res = $this->BenutzerModel->load([$uid]); + if (isError($person_res)) { + show_error("was not able to query the table public.tbl_benutzer:" . getData($person_res)); + } else { + $person_res = hasData($person_res) ? getData($person_res)[0] : null; + } + + if( ($person_res->foto === null) || (($this->uid !== $uid) && ($person_res->foto_sperre !== false)) ) + { + $dummy_foto = base64_encode(file_get_contents(DOC_ROOT.'skin/images/profilbild_dummy.jpg')); + $person_res->foto = $dummy_foto; + } + + return $person_res; + } + + /** + * gets the mitarbeiter information corresponding to a user + * @access private + * @param integer $uid the userID used to get the mitarbeiter information + * @return array all the mitarbeiter informaion corresponding to a userID + */ + private function getMitarbeiterInfo($uid) + { + $this->MitarbeiterModel->addSelect(["kurzbz", "telefonklappe", "alias", "ort_kurzbz"]); + $this->MitarbeiterModel->addJoin("tbl_benutzer", "tbl_benutzer.uid = tbl_mitarbeiter.mitarbeiter_uid"); + $mitarbeiter_res = $this->MitarbeiterModel->load($uid); + if (isError($mitarbeiter_res)) { + show_error("was not able to query the table public.tbl_mitarbeiter:" . getData($mitarbeiter_res)); + } else { + $mitarbeiter_res = hasData($mitarbeiter_res) ? getData($mitarbeiter_res)[0] : null; + } + + return $mitarbeiter_res; + } + + /** + * gets the telefon information corresponding to a user + * @access private + * @param integer $uid the userID used to get the telefon information + * @return array all the telefon informaion corresponding to a userID + */ + private function getTelefonInfo($uid) + { + $this->MitarbeiterModel->addSelect(["kontakt"]); + $this->MitarbeiterModel->addJoin("tbl_kontakt", "tbl_mitarbeiter.standort_id = tbl_kontakt.standort_id"); + $this->MitarbeiterModel->addLimit(1); + $telefon_res = $this->MitarbeiterModel->loadWhere(["mitarbeiter_uid" => $uid, "kontakttyp" => "telefon"]); + if (isError($telefon_res)) { + show_error("was not able to query the table public.tbl_mitarbeiter:" . getData($telefon_res)); + } + $telefon_res = hasData($telefon_res) ? getData($telefon_res)[0] : null; + return $telefon_res; + } + + /** + * gets the student information corresponding to a user + * @access private + * @param integer $uid the userID used to get the student information + * @return array all the student informaion corresponding to a userID + */ + private function getStudentInfo($uid) + { + $this->StudentModel->addSelect(['tbl_studiengang.bezeichnung as studiengang', 'tbl_student.semester', 'tbl_student.verband', 'tbl_student.gruppe', 'tbl_student.matrikelnr as personenkennzeichen']); + $this->StudentModel->addJoin('tbl_studiengang', "tbl_studiengang.studiengang_kz=tbl_student.studiengang_kz"); + + $student_res = $this->StudentModel->load([$uid]); + if (isError($student_res)) { + show_error("was not able to query the table public.tbl_student:" . getData($student_res)); + } + $student_res = hasData($student_res) ? getData($student_res)[0] : null; + return $student_res; + } + + /** + * gets the profil updates corresponding to a user + * @access private + * @param integer $uid the userID used to get the profil updates + * @return array all the profil updates corresponding to a userID + */ + private function getProfilUpdates($uid) + { + $profilUpdates = $this->ProfilUpdateModel->getProfilUpdatesWhere(['uid' => $uid]); + if (isError($profilUpdates)) { + show_error("was not able to query the table public.tbl_profil_update:" . getData($profilUpdates)); + } + $profilUpdates = hasData($profilUpdates) ? getData($profilUpdates) : null; + return $profilUpdates; + } + + /** + * gets the Matrikelnummer corresponding to a user + * @access private + * @param integer $uid the userID used to get the Matrikelnummer + * @return integer the Matrikelnummer corresponding to a userID + */ + private function getMatrikelNummer($uid) + { + $this->BenutzerModel->addSelect(["matr_nr"]); + $this->BenutzerModel->addJoin("tbl_person", "person_id"); + + $matr_res = $this->BenutzerModel->load([$uid]); + if (isError($matr_res)) { + show_error("was not able to query the table public.tbl_benutzer:" . getData($matr_res)); + } + $matr_res = hasData($matr_res) ? getData($matr_res)[0] : []; + return $matr_res; + } + + /** + * gets the Zutrittsgruppen corresponding to a user + * @access private + * @param integer $uid the userID used to get the Zutrittsgruppen + * @return array all the Zutrittsgruppen corresponding to a userID + */ + private function getZutrittsgruppen($uid) + { + $this->BenutzergruppeModel->addSelect(['bezeichnung']); + $this->BenutzergruppeModel->addJoin('tbl_gruppe', 'gruppe_kurzbz'); + + $zutrittsgruppe_res = $this->BenutzergruppeModel->loadWhere(array("uid" => $uid, "zutrittssystem" => true)); + if (isError($zutrittsgruppe_res)) { + show_error("was not able to query the table public.tbl_benutzergruppe:" . getData($zutrittsgruppe_res)); + } + $zutrittsgruppe_res = hasData($zutrittsgruppe_res) ? getData($zutrittsgruppe_res) : null; + return $zutrittsgruppe_res; + } + + /** + * gets the address information corresponding to a user + * @access private + * @param integer $uid the userID used to get the address information + * @return array all the address information corresponding to a userID + */ + private function getAdressenInfo($pid) + { + $adresse_res = $this->AdresseModel->addSelect(["adresse_id", "strasse", "tbl_adressentyp.bezeichnung as typ", "plz", "ort", "zustelladresse", "gemeinde", "nation"]); + $adresse_res = $this->AdresseModel->addOrder("zustelladresse", "DESC"); + $adresse_res = $this->AdresseModel->addJoin("tbl_adressentyp", "typ=adressentyp_kurzbz"); + + $adresse_res = $this->AdresseModel->loadWhere(["person_id" => $pid]); + if (isError($adresse_res)) { + show_error("was not able to query the table public.tbl_adresse:" . getData($adresse_res)); + } + $adresse_res = hasData($adresse_res) ? getData($adresse_res) : null; + return $adresse_res; + } + + /** + * gets the kontakt information corresponding to a user + * @access private + * @param integer $uid the userID used to get the kontakt information + * @return array all the kontakt information corresponding to a userID + */ + private function getKontaktInfo($pid) + { + $this->KontaktModel->addSelect(['kontakttyp', 'kontakt_id', 'kontakt', 'tbl_kontakt.anmerkung', 'tbl_kontakt.zustellung']); + $this->KontaktModel->addJoin('public.tbl_standort', 'standort_id', 'LEFT'); + $this->KontaktModel->addJoin('public.tbl_firma', 'firma_id', 'LEFT'); + $this->KontaktModel->addOrder('kontakttyp, kontakt, tbl_kontakt.updateamum, tbl_kontakt.insertamum'); + + $kontakte_res = $this->KontaktModel->loadWhere(['person_id' => $pid]); + if (isError($kontakte_res)) { + show_error("was not able to query the table public.tbl_kontakt:" . getData($kontakte_res)); + } + $kontakte_res = hasData($kontakte_res) ? getData($kontakte_res) : null; + return $kontakte_res; + } + + /** + * gets the date of issue of the FH access card corresponding to a user + * @access private + * @param integer $uid the userID used to get the date of issue of the FH access card + * @return string the date of issue of the FH access card corresponding to a userID + */ + private function getZutrittskarteDatum($uid) + { + $zutrittskarte_ausgegebenam = $this->BetriebsmittelpersonModel->getBetriebsmittelByUid($uid, "Zutrittskarte"); + if (isError($zutrittskarte_ausgegebenam)) { + show_error("was not able to query the table wavi.tbl_bentriebsmittelperson:" . getData($zutrittskarte_ausgegebenam)); + } + $zutrittskarte_ausgegebenam = hasData($zutrittskarte_ausgegebenam) ? getData($zutrittskarte_ausgegebenam)[0]->ausgegebenam : null; + + //? formats date from 01-01-2000 to 01.01.2000 + $zutrittskarte_ausgegebenam = str_replace("-", ".", $zutrittskarte_ausgegebenam); + return $zutrittskarte_ausgegebenam; + } +} + diff --git a/application/controllers/api/frontend/v1/ProfilUpdate.php b/application/controllers/api/frontend/v1/ProfilUpdate.php new file mode 100644 index 000000000..827654d21 --- /dev/null +++ b/application/controllers/api/frontend/v1/ProfilUpdate.php @@ -0,0 +1,837 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +class ProfilUpdate extends FHCAPI_Controller +{ + + public static $STATUS_PENDING = NULL; + public static $STATUS_ACCEPTED = NULL; + public static $STATUS_REJECTED = NULL; + + public static $TOPICS = []; + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getStatus' => self::PERM_LOGGED, + 'getTopic' => self::PERM_LOGGED, + 'getProfilRequestFiles' => self::PERM_LOGGED, + 'getProfilUpdateWithPermission' => ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'], + 'denyProfilRequest' => ['student/stammdaten:rw', 'mitarbeiter/stammdaten:rw'], + 'acceptProfilRequest' => ['student/stammdaten:rw', 'mitarbeiter/stammdaten:rw'], + 'selectProfilRequest' => self::PERM_LOGGED, + 'insertProfilRequest' => self::PERM_LOGGED, + 'updateProfilRequest' => self::PERM_LOGGED, + 'deleteProfilRequest' => self::PERM_LOGGED, + 'insertFile' => self::PERM_LOGGED, + 'show' => self::PERM_LOGGED, + ]); + + $this->load->config('cis'); + + // Load language phrases + $this->loadPhrases( + array( + 'ui', + 'global', + 'person', + 'profil', + 'profilUpdate' + ) + ); + + $this->load->model('person/Profil_update_model', 'ProfilUpdateModel'); + $this->load->model('person/Kontakt_model', 'KontaktModel'); + $this->load->model('person/Adresse_model', 'AdresseModel'); + $this->load->model('person/Adressentyp_model', 'AdressenTypModel'); + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->load->model('system/Sprache_model', 'SpracheModel'); + $this->load->model('person/Profil_update_status_model', 'ProfilUpdateStatusModel'); + $this->load->model('person/Profil_update_topic_model', 'ProfilUpdateTopicModel'); + + $this->load->library('DmsLib'); + $this->load->library('PermissionLib'); + + //? put the uid and pid inside the controller for reusability + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + + // setup the ProfilUpdate states + $this->ProfilUpdateStatusModel->addSelect(['status_kurzbz']); + $status_kurzbz = $this->ProfilUpdateStatusModel->load(); + if (hasData($status_kurzbz)) { + list($status_pending, $status_accepted, $status_rejected) = getData($status_kurzbz); + + self::$STATUS_PENDING = $status_pending->status_kurzbz; + self::$STATUS_ACCEPTED = $status_accepted->status_kurzbz; + self::$STATUS_REJECTED = $status_rejected->status_kurzbz; + } + // setup the ProfilUpdate topics + $this->ProfilUpdateTopicModel->addSelect(['topic_kurzbz']); + $topic_kurzbz = $this->ProfilUpdateTopicModel->load(); + + if (hasData($topic_kurzbz)) { + foreach (getData($topic_kurzbz) as $topic) { + self::$TOPICS[$topic->topic_kurzbz] = $topic->topic_kurzbz; + } + } + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + public function getStatus() + { + $this->terminateWithSuccess([self::$STATUS_PENDING => self::$STATUS_PENDING, self::$STATUS_ACCEPTED => self::$STATUS_ACCEPTED, self::$STATUS_REJECTED => self::$STATUS_REJECTED]); + } + + + public function getTopic() + { + if(!count(self::$TOPICS)){ + $this->terminateWithError('No topics found'); + } + $this->terminateWithSuccess(self::$TOPICS); + } + + public function show($dms_id) + { + + $profil_update = $this->ProfilUpdateModel->loadWhere(['attachment_id' => $dms_id]); + $profil_update = hasData($profil_update) ? getData($profil_update)[0] : null; + + //? checks if an profil update exists with the dms_id requested from the user + if ($profil_update) { + $is_mitarbeiter_profil_update = getData($this->MitarbeiterModel->isMitarbeiter($profil_update->uid)); + $is_student_profil_update = getData($this->StudentModel->isStudent($profil_update->uid)); + + if ( + $this->permissionlib->isBerechtigt('student/stammdaten:r') && $is_student_profil_update || + $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten:r') && $is_mitarbeiter_profil_update || + $this->uid == $profil_update->uid + ) { + // Get file to be downloaded from DMS + $download = $this->dmslib->download($dms_id); + $download = $this->getDataOrTerminateWithError($download); + // Download file + $this->outputFile($download); + + + } else { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_permission_error')); + } + + } else { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_dms_error')); + } + + } + + public function selectProfilRequest() + { + + $uid = $this->input->get('uid',true); + $id = $this->input->get('id',true); + $whereClause = ['uid' => $this->uid]; + + if (isset($uid)) + $whereClause['uid'] = $uid; + if (isset($id)) + $whereClause['id'] = $id; + + $res = $this->ProfilUpdateModel->getProfilUpdatesWhere($whereClause); + $res = $this->getDataOrTerminateWithError($res); + $this->terminateWithSuccess($res); + + } + + public function insertProfilRequest() + { + + $payload = $this->input->post('payload'); + $topic = $this->input->post('topic',true); + $fileID = $this->input->post('fileID',true); + + if(!isset($payload) || !isset($topic)){ + $this->terminateWithError("required parameters are missing"); + } + + $identifier = array_key_exists("kontakt_id", $payload) ? "kontakt_id" : (array_key_exists("adresse_id", $payload) ? "adresse_id" : null); + + $data = ["topic" => $topic, "uid" => $this->uid, "requested_change" => json_encode($payload), "insertamum" => "NOW()", "insertvon" => $this->uid, "status" => self::$STATUS_PENDING ?: 'Pending']; + + //? insert fileID in the dataset if sent with post request + if (isset($fileID)) { + $data['attachment_id'] = $fileID; + } + + //? loops over all updateRequests from a user to validate if the new request is valid + $res = $this->ProfilUpdateModel->getProfilUpdatesWhere(["uid" => $this->uid]); + $res = $this->getDataOrTerminateWithError($res); + + //? the user cannot delete a zustelladresse/kontakt + if (isset($payload["delete"]) && $payload[$identifier == "kontakt_id" ? "zustellung" : "zustelladresse"]) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_deleteZustellung_error')); + } + + //? if the user tries to delete a adresse, checks whether the adresse is a heimatadresse, if so an error is raised + if (isset($payload["delete"]) && $identifier == "adresse_id") { + $adr = $this->AdresseModel->load($payload[$identifier]); + $adr = $this->getDataOrTerminateWithError($adr)[0]; + if ($adr->heimatadresse) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_deleteZustellung_error')); + } + } + + if ($res) { + $pending_changes = array_filter($res, function ($element) { + return $element->status == (self::$STATUS_PENDING ?: "Pending"); + }); + foreach ($pending_changes as $update_request) { + $existing_change = $update_request->requested_change; + //? the user can add as many new kontakte/adressen as he likes + if (!isset($payload["add"]) && property_exists($existing_change, $identifier) && array_key_exists($identifier,$payload) && $existing_change->$identifier == $payload[$identifier]) { + //? the kontakt_id / adresse_id of a change has to be unique + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_changeTwice_error')); + } + + //? if it is not updating any kontakt/adresse, the topic has to be unique + elseif (!$identifier && $update_request->topic == $topic) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_changeTopicTwice_error', ['0' => $update_request->topic])); + } + } + } + + $insertID = $this->ProfilUpdateModel->insert($data); + + if (isError($insertID)) { + $this->terminateWithError(getError($insertID)); + } else { + + $insertID = hasData($insertID) ? getData($insertID) : null; + //? sends emails to the correspondents of the $uid + $this->sendEmail_onProfilUpdate_insertion($this->uid, $insertID, $topic); + $this->terminateWithSuccess(success($insertID)); + } + } + + public function updateProfilRequest() + { + $topic = $this->input->post('topic', true); + $payload = $this->input->post('payload', true); + $ID = $this->input->post('ID', true); + $fileID = $this->input->post('fileID', true);//optional + + if(!isset($topic) || !isset($payload) || !isset($ID)){ + $this->terminateWithError("required parameters are missing"); + } + + $updateData = ["requested_change" => json_encode($payload), "updateamum" => "NOW()", "updatevon" => $this->uid]; + if (isset($fileID)) { + $updateData['attachment_id'] = json_decode($fileID); + } + $updateID = $this->ProfilUpdateModel->update([$ID], $updateData); + //? insert fileID in the dataset if sent with post request + + if (isError($updateID)) { + $this->terminateWithError(getError($updateID)); + } + + $updateID = $this->getDataOrTerminateWithError($updateID)[0]; + + $this->terminateWithSuccess(success($updateID)); + } + + public function deleteProfilRequest() + { + + $requestID = $this->input->post('requestID', true); + $result = $this->ProfilUpdateModel->delete([$requestID]); + if (isError($result)) { + $this->terminateWithError(getError($result)); + } + $this->terminateWithSuccess($result); + } + + public function getProfilRequestFiles($id) + { + if(!$id){ + $this->terminateWithError("parameter id is missing"); + } + + $this->ProfilUpdateModel->addSelect(["attachment_id"]); + $attachmentID = $this->ProfilUpdateModel->load([$id]); + if (isError($attachmentID)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_loading_error'),self::ERROR_TYPE_GENERAL); + } + //? get the attachmentID + $dms_id = $this->getDataOrTerminateWithError($attachmentID)[0]->attachment_id; + + //? get the name to the file + $this->DmsVersionModel->addSelect(["name", "dms_id"]); + $attachment = $this->DmsVersionModel->load([$dms_id, 0]); + if (isError($attachment)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_dmsVersion_error'),self::ERROR_TYPE_GENERAL); + } + $attachment = $this->getDataOrTerminateWithError($attachment); + //? returns {name:..., dms_id:...} + $this->terminateWithSuccess($attachment); + } + + public function denyProfilRequest() + { + $id = $this->input->post('profil_update_id', true); + $uid = $this->input->post('uid', true); + $topic = $this->input->post('topic', true); + $status_message = $this->input->post('status_message', true); //optional + + if(!isset($id) || !isset($uid) || !isset($topic)){ + $this->terminateWithError("parameter id, uid, topic or status_message is missing"); + } + + $is_mitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid); + $is_mitarbeiter = $this->getDataOrTerminateWithError($is_mitarbeiter); + + $is_student = $this->StudentModel->isStudent($uid); + $is_student = $this->getDataOrTerminateWithError($is_student); + + if ( + $is_student && $this->permissionlib->isBerechtigt('student/stammdaten', "suid", $this->getOE_from_student($uid)) || + $is_mitarbeiter && $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', "suid") + ) { + $this->sendEmail_onProfilUpdate_response($uid, $topic, self::$STATUS_REJECTED); + $this->terminateWithSuccess($this->setStatusOnUpdateRequest($id, self::$STATUS_REJECTED, $status_message)); + } else { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_permission_error'),self::ERROR_TYPE_GENERAL); + } + } + + public function acceptProfilRequest() + { + $id = $this->input->post('profil_update_id', true); + $uid = $this->input->post('uid', true); + $topic = $this->input->post('topic', true); + $requested_change = $this->input->post('requested_change'); + $status_message = $this->input->post('status_message', true); //optional + + //? fetching person_id using UID + $personID = $this->PersonModel->getByUid($uid); + $personID = $this->getDataOrTerminateWithError($personID)[0]->person_id; + + //! check for required information + if (!isset($id) || !isset($uid) || !isset($personID) || !isset($requested_change) || !isset($topic)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_requiredInformation_error')); + } + + $is_mitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid); + $is_mitarbeiter = $this->getDataOrTerminateWithError($is_mitarbeiter); + + $is_student = $this->StudentModel->isStudent($uid); + $is_student = $this->getDataOrTerminateWithError($is_student); + + + //? check if the permissions are set correctly + if ( + $is_student && $this->permissionlib->isBerechtigt('student/stammdaten', "suid", $this->getOE_from_student($uid)) || + $is_mitarbeiter && $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', "suid") + ) { + + if (is_array($requested_change) && array_key_exists("adresse_id", $requested_change)) { + $insertID = $this->handleAdresse($requested_change, $personID); + $insertID = getData($insertID); + if (isset($insertID)) { + $requested_change['adresse_id'] = $insertID; + $update_res = $this->updateRequestedChange($id, $requested_change); + if (isError($update_res)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_address_error', [$insertID])); + } + } + + } else if (is_array($requested_change) && array_key_exists("kontakt_id", $requested_change)) { + $insertID = $this->handleKontakt($requested_change, $personID); + $insertID = getData($insertID); + if (isset($insertID)) { + $requested_change['kontakt_id'] = $insertID; + $update_res = $this->updateRequestedChange($id, $requested_change); + if (isError($update_res)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_kontakt_error', [$insertID])); + } + } + + + } else { + switch ($topic) { + // mapping phrasen to database columns to make the update with the correct column names + case self::$TOPICS['Titel']: + $topic = "titelpre"; + break; + case self::$TOPICS['Postnomen']: + $topic = "titelpost"; + break; + case self::$TOPICS['Vorname']: + $topic = "vorname"; + break; + case self::$TOPICS['Nachname']: + $topic = "nachname"; + break; + default: + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_topic_error', [$topic])); + } + + $result = $this->PersonModel->update($personID, [$topic => $requested_change["value"]]); + if (isError($result)) $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_insert_error')); + + } + $this->sendEmail_onProfilUpdate_response($uid, $topic, self::$STATUS_ACCEPTED); + + $this->terminateWithSuccess($this->setStatusOnUpdateRequest($id, self::$STATUS_ACCEPTED, $status_message, $requested_change)); + } else { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_permission_error')); + } + + + } + + public function insertFile($replace) + { + $replace = json_decode($replace); + + if (!count($_FILES)) { + $this->terminateWithError("No file available for upload"); + } + + //? if replace is set it contains the profil_update_id in which the attachment_id has to be replaced + if (isset($replace)) { + + $this->ProfilUpdateModel->addSelect(["attachment_id"]); + $profilUpdate = $this->ProfilUpdateModel->load([$replace]); + if (isError($profilUpdate)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_loading_error')); + } + //? get the attachmentID + $dms_id = $this->getDataOrTerminateWithError($profilUpdate)[0]->attachment_id; + + //? delete old dms_file of Profil Update + $deleteOldFile_result = $this->deleteOldVersionFile($dms_id); + if(!$deleteOldFile_result){ + $this->terminateWithError("error while deleting the old file"); + } + } + + + $files = $_FILES['files']; + $file_count = count($files['name']); + + $res = []; + + for ($i = 0; $i < $file_count; $i++) { + $_FILES['files']['name'] = $files['name'][$i]; + $_FILES['files']['type'] = $files['type'][$i]; + $_FILES['files']['tmp_name'] = $files['tmp_name'][$i]; + $_FILES['files']['error'] = $files['error'][$i]; + $_FILES['files']['size'] = $files['size'][$i]; + + $dms = [ + "kategorie_kurzbz" => "profil_aenderung", + "version" => 0, + "name" => $_FILES['files']['name'], + "mimetype" => $_FILES['files']['type'], + "beschreibung" => $this->uid . " Profil Änderung", + "insertvon" => $this->uid, + "insertamum" => "NOW()", + ]; + + $tmp_res = $this->dmslib->upload($dms, 'files', array("jpg", "png", "pdf")); + + if(isError($tmp_res)){ + $this->addError(getError($tmp_res)); + } + + $tmp_res = $this->getDataOrTerminateWithError($tmp_res); + array_push($res, $tmp_res); + } + + $this->terminateWithSuccess($res); + } + + public function getProfilUpdateWithPermission($status = null) + { + // early return if no status has been passed as argument + if (!isset($status)) { + echo json_encode($this->ProfilUpdateModel->getProfilUpdateWithPermission()); + return; + } + + // get the sprache of the user + $sprachenIndex = $this->SpracheModel->loadWhere(["sprache" => getUserLanguage()]); + $sprachenIndex = hasData($sprachenIndex) ? getData($sprachenIndex)[0]->index : null; + + if (isset($sprachenIndex) && isset($status)) { + // get the corresponding status kurz_bz primary key out of the translation + $status = $this->ProfilUpdateStatusModel->execReadOnlyQuery("select * from public.tbl_profil_update_status where ? = ANY(bezeichnung_mehrsprachig)", [$status]); + $status = hasData($status) ? getData($status)[0]->status_kurzbz : null; + $res = $this->ProfilUpdateModel->getProfilUpdateWithPermission(isset($status) ? ['status' => $status] : null); + + echo json_encode($res); + } + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + + private function sendEmail_onProfilUpdate_insertion($uid, $profil_update_id, $topic) + { + if($this->config->item('cis_send_profil_update_mails') === false) + { + return; + } + + $this->load->helper('hlp_sancho_helper'); + $emails = []; + + $is_mitarbeiter = $this->MitarbeiterModel->isMitarbeiter($uid); + if (isError($is_mitarbeiter)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_mitarbeiterCheck_error')); + } + $is_mitarbeiter = $this->getDataOrTerminateWithError($is_mitarbeiter); + + //! if the $uid is a mitarbeiter and student, only the hr is notified by email + if ($is_mitarbeiter) { + //? user is not a student therefore he is a mitarbeiter, send email to Personalverwaltung + //? use constant variable MAIL_GST to mail to the personalverwaltung + $this->MitarbeiterModel->addSelect([TRUE]); + $this->MitarbeiterModel->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid"); + //? check if the the userID is a mitarbeiter and if the benutzer is active + $res = $this->MitarbeiterModel->loadWhere(["public.tbl_mitarbeiter.mitarbeiter_uid" => $uid, "public.tbl_benutzer.aktiv" => TRUE]); + if (isError($res)) { + $this->terminateWithError("was not able to query the mitarbeiter and benutzer by the uid: " . $uid); + } + if (hasData($res)) { + array_push($emails, MAIL_GST); + } else { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_mitarbeiterCheck_error')); + } + } else { + //? if it is not a mitarbeiter, check whether it is a student and send email to studiengang + $is_student = $this->StudentModel->isStudent($uid); + if (isError($is_student)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_studentCheck_error')); + } + $is_student = $this->getDataOrTerminateWithError($is_student); + if ($is_student) { + //? Send email to the Studiengangsassistentinnen + $this->StudentModel->addSelect(["public.tbl_studiengang.email"]); + $this->StudentModel->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_student.student_uid"); + $this->StudentModel->addJoin("public.tbl_prestudent", "public.tbl_benutzer.person_id = public.tbl_prestudent.person_id"); + $this->StudentModel->addJoin("public.tbl_prestudentstatus", "public.tbl_prestudentstatus.prestudent_id = public.tbl_prestudent.prestudent_id"); + $this->StudentModel->addJoin("public.tbl_studiengang", "public.tbl_studiengang.studiengang_kz = public.tbl_prestudent.studiengang_kz"); + //* check if the benutzer itself is active + //* check if the student status is Student or Diplomand (active students) + $this->StudentModel->db->where_in("public.tbl_prestudentstatus.status_kurzbz", ['Student', 'Diplomand']); + $res = $this->StudentModel->loadWhere(["public.tbl_benutzer.aktiv" => TRUE, "public.tbl_student.student_uid" => $uid]); + if (isError($res)) { + $this->terminateWithError(getError($res)); + } else { + $res = $this->getDataOrTerminateWithError($res); + foreach ($res as $emailObj) { + array_push($emails, $emailObj->email); + } + } + } + } + $mail_res = []; + //? sending email + foreach ($emails as $email) { + array_push($mail_res, sendSanchoMail("profil_update", ['uid' => $uid, 'topic' => $topic, 'href' => APP_ROOT . 'Cis/ProfilUpdate/id/' . $profil_update_id], $email, ("Profil Änderung von " . $uid))); + } + foreach ($mail_res as $m_res) { + if (!$m_res) { + $this->addError($this->p->t('profilUpdate', 'profilUpdate_email_error')); + } + } + + } + + private function sendEmail_onProfilUpdate_response($uid, $topic, $status) + { + if($this->config->item('cis_send_profil_update_mails') === false) + { + return; + } + + $this->load->helper('hlp_sancho_helper'); + $email = $uid . "@" . DOMAIN; + + + function languageQuery($language) + { + return "select index from public.tbl_sprache where sprache = '" + $language + "'"; + } + + $this->ProfilUpdateStatusModel->addSelect(["bezeichnung_mehrsprachig[(" . languageQuery('German') . ")] as status_de", "bezeichnung_mehrsprachig[(" . languageQuery('English') . ")] as status_en"]); + + $status_translation = $this->ProfilUpdateStatusModel->loadWhere(["status_kurzbz" => $status]); + + if (isError($status_translation)) { + $this->terminateWithError($this->p->t('profilUpdate', 'ProfilUpdateStatusTranslationError')); + } + + $status_translation = hasData($status_translation) ? getData($status_translation)[0] : null; + + if (isset($status_translation)) { + $mail_res = sendSanchoMail("profil_update_response", ['topic' => $topic, 'status_de' => $status_translation->status_de, 'status_en' => $status_translation->status_en, 'href' => APP_ROOT . 'Cis/Profil'], $email, ("Profil Änderung " . $this->p->t('profilUpdate', 'pending'))); + if (!$mail_res) { + $this->addError($this->p->t('profilUpdate', 'profilUpdate_email_error')); + } + } + } + + private function setStatusOnUpdateRequest($id, $status, $status_message) + { + return $this->ProfilUpdateModel->update([$id], ["status" => $status, "status_timestamp" => "NOW()", "status_message" => $status_message]); + } + + private function updateRequestedChange($id, $requested_change) + { + return $this->ProfilUpdateModel->update([$id], ['requested_change' => json_encode($requested_change)]); + } + + private function deleteOldVersionFile($dms_id) + { + // starting the transaction + $this->db->trans_start(); + + + if (!isset($dms_id)) { + return; + } + + //? delete the file from the profilUpdate first + $profilUpdateFileDelete = $this->ProfilUpdateModel->removeFileFromProfilUpdate($dms_id); + if(isError($profilUpdateFileDelete)){ + $this->terminateWithError(getError($profilUpdateFileDelete)); + } + + //? delete all the different versions of the dms_file + $dmsVersions = $this->DmsVersionModel->loadWhere(["dms_id" => $dms_id]); + $dmsVersions = $this->getDataOrTerminateWithError($dmsVersions); + + + + $dms_versions = array_map(function ($item) { + return $item->version; + }, $dmsVersions); + + + $test_array = array(); + foreach ($dms_versions as $version) { + + $delete_result = $this->dmslib->removeVersion($dms_id, $version); + array_push($test_array, $delete_result); + + if(isError($delete_result)){ + $this->addError(getError($delete_result)); + } + } + + // transaction complete + $this->db->trans_complete(); + + if ($this->db->trans_status() === FALSE) + { + return false; + } + else + { + return true; + } + + } + + + private function getOE_from_student($student_uid) + { + //? returns the oe_einheit eines Studenten + $query = "SELECT public.tbl_studiengang.oe_kurzbz + FROM public.tbl_student + JOIN public.tbl_studiengang ON tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz + WHERE public.tbl_student.student_uid = ?;"; + + $res = $this->StudentModel->execReadOnlyQuery($query, [$student_uid]); + $res = $this->getDataOrTerminateWithError($res, $this->p->t('profilUpdate', 'profilUpdate_loadingOE_error')); + $res = array_map( + function ($item) { + return $item->oe_kurzbz; + }, + $res + ); + return $res; + } + + private function handleAdresse($requested_change, $personID) + { + $this->AdressenTypModel->addSelect(["adressentyp_kurzbz"]); + $adr_kurzbz = $this->AdressenTypModel->loadWhere(["bezeichnung" => $requested_change['typ']]); + $adr_kurzbz = $this->getDataOrTerminateWithError($adr_kurzbz)[0]->adressentyp_kurzbz; + + //? replace the address_typ with its correct kurzbz foreign key + $requested_change['typ'] = $adr_kurzbz; + + $adresse_id = $requested_change["adresse_id"]; + + //? removes the adresse_id because we don't want to update the kontakt_id in the database + unset($requested_change["adresse_id"]); + + //! ADD + if (array_key_exists('add', $requested_change) && $requested_change['add']) { + + //? removes add flag + unset($requested_change['add']); + $requested_change['insertamum'] = "NOW()"; + $requested_change['insertvon'] = getAuthUID(); + $requested_change['person_id'] = $personID; + //TODO: zustelladresse, heimatadresse, rechnungsadresse und nation werden nicht beachtet + $insertID = $this->AdresseModel->insert($requested_change); + $insert_adresse_id = $insertID; + $insert_adresse_id = $this->getDataOrTerminateWithError($insert_adresse_id, $this->p->t('profilUpdate', 'profilUpdate_insertAdresse_error')); + if ($insert_adresse_id) { + $this->handleDupplicateZustellAdressen($requested_change['zustelladresse'], $insert_adresse_id); + } + } + //! DELETE + elseif (array_key_exists('delete', $requested_change) && $requested_change['delete']) { + $result = $this->AdresseModel->delete($adresse_id); + if (isError($result)) { + $this->terminateWithError(getError($result)); + } + } + //! UPDATE + else { + $requested_change['updateamum'] = "NOW()"; + $requested_change['updatevon'] = getAuthUID(); + $update_adresse_id = $this->AdresseModel->update($adresse_id, $requested_change); + $update_adresse_id = $this->getDataOrTerminateWithError($update_adresse_id, $this->p->t('profilUpdate', 'profilUpdate_updateAdresse_error')); + $this->handleDupplicateZustellAdressen($requested_change['zustelladresse'], $update_adresse_id); + + } + return $insertID ?? null; + } + + private function handleKontakt($requested_change, $personID) + { + $kontakt_id = $requested_change["kontakt_id"]; + //? removes the kontakt_id because we don't want to update the kontakt_id in the database + unset($requested_change["kontakt_id"]); + + //! ADD + if (array_key_exists('add', $requested_change) && $requested_change['add']) { + //? removes add flag + unset($requested_change['add']); + $requested_change['person_id'] = $personID; + $requested_change['insertamum'] = "NOW()"; + $requested_change['insertvon'] = getAuthUID(); + $insertID = $this->KontaktModel->insert($requested_change); + $insert_kontakt_id = $insertID; + $insert_kontakt_id = $this->getDataOrTerminateWithError($insert_kontakt_id, $this->p->t('profilUpdate', 'profilUpdate_insertKontakt_error')); + if ($insert_kontakt_id) { + $this->handleDupplicateZustellKontakte($requested_change['zustellung'], $insert_kontakt_id); + } + } + //! DELETE + elseif (array_key_exists('delete', $requested_change) && $requested_change['delete']) { + $result = $this->KontaktModel->delete($kontakt_id); + if (isError($result)) { + $this->terminateWithError(getError($result)); + } + } + //! UPDATE + else { + $requested_change['updateamum'] = "NOW()"; + $requested_change['updatevon'] = getAuthUID(); + $update_kontakt_id = $this->KontaktModel->update($kontakt_id, $requested_change); + $update_kontakt_id = $this->getDataOrTerminateWithError($update_kontakt_id, $this->p->t('profilUpdate', 'profilUpdate_updateKontakt_error')); + if ($update_kontakt_id) { + $this->handleDupplicateZustellKontakte($requested_change['zustellung'], $update_kontakt_id); + } + } + return isset($insertID) ? $insertID : null; + } + + private function handleDupplicateZustellAdressen($zustellung, $adresse_id) + { + if ($zustellung) { + $this->PersonModel->addSelect("public.tbl_adresse.adresse_id"); + $this->PersonModel->addJoin("public.tbl_adresse", "public.tbl_adresse.person_id = public.tbl_person.person_id"); + $zustellAdressenArray = $this->PersonModel->loadWhere(["public.tbl_person.person_id" => $this->pid, "zustelladresse" => TRUE]); + if (isError($zustellAdressenArray)) { + $this->terminateWithError($this->p->t('profilUpdate', 'profilUpdate_loadingZustellAdressen_error')); + } + $zustellAdressenArray = $this->getDataOrTerminateWithError($zustellAdressenArray); + + if (count($zustellAdressenArray) > 0) { + + $zustellAdressenArray = array_filter($zustellAdressenArray, function ($adresse) use ($adresse_id) { + + return $adresse->adresse_id != $adresse_id; + }); + + // remove the zustelladresse from all other zustelladressen + foreach ($zustellAdressenArray as $adresse) { + $this->AdresseModel->update($adresse->adresse_id, ["zustelladresse" => FALSE]); + } + + } + } + } + + private function handleDupplicateZustellKontakte($zustellung, $kontakt_id) + { + if ($zustellung) { + $this->PersonModel->addSelect("public.tbl_kontakt.kontakt_id"); + $this->PersonModel->addJoin("public.tbl_kontakt", "public.tbl_kontakt.person_id = public.tbl_person.person_id"); + $zustellKontakteArray = $this->PersonModel->loadWhere(["public.tbl_person.person_id" => $this->pid, "zustellung" => TRUE]); + if (!isSuccess($zustellKontakteArray)) { + return error($this->p->t('profilUpdate', 'profilUpdate_loadingZustellkontakte_error')); + } + $zustellKontakteArray = hasData($zustellKontakteArray) ? getData($zustellKontakteArray) : null; + + if ($zustellung && count($zustellKontakteArray) > 0) { + $zustellKontakteArray = array_filter($zustellKontakteArray, function ($kontakt) use ($kontakt_id) { + return $kontakt->kontakt_id != $kontakt_id; + }); + foreach ($zustellKontakteArray as $kontakt) { + $this->KontaktModel->update($kontakt->kontakt_id, ["zustellung" => FALSE]); + } + + } + } + } + +} + + 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/Stundenplan.php b/application/controllers/api/frontend/v1/Stundenplan.php new file mode 100644 index 000000000..c14ea4315 --- /dev/null +++ b/application/controllers/api/frontend/v1/Stundenplan.php @@ -0,0 +1,564 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +class Stundenplan extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + + parent::__construct([ + 'getRoomplan' => self::PERM_LOGGED, + 'Stunden' => self::PERM_LOGGED, + 'Reservierungen' => self::PERM_LOGGED, + 'getStundenplan' => self::PERM_LOGGED, + 'getLehreinheitStudiensemester' => self::PERM_LOGGED, + ]); + + $this->load->library('LogLib'); + $this->loglib->setConfigs(array( + 'classIndex' => 5, + 'functionIndex' => 5, + 'lineIndex' => 4, + 'dbLogType' => 'API', // required + 'dbExecuteUser' => 'RESTful API' + )); + + $this->load->library('form_validation'); + + //load models + $this->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + $this->load->model('ressource/Reservierung_model', 'ReservierungModel'); + + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * fetches Stunden layout from database + * @access public + * + */ + public function Stunden() + { + $this->load->model('ressource/Stunde_model', 'StundeModel'); + + $stunden = $this->StundeModel->load(); + + $stunden = $this->getDataOrTerminateWithError($stunden); + + $this->terminateWithSuccess($stunden); + } + + /** + * fetches room events from a certain date + * @access public + * + */ + public function getRoomplan() + { + // form validation + $this->load->library('form_validation'); + $this->form_validation->set_data($_GET); + $this->form_validation->set_rules('ort_kurzbz',"Ort","required"); + $this->form_validation->set_rules('start_date',"start_date","required"); + $this->form_validation->set_rules('end_date',"end_date","required"); + if($this->form_validation->run() === FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // storing the get parameter in local variables + $ort_kurzbz = $this->input->get('ort_kurzbz', TRUE); + $start_date = $this->input->get('start_date', TRUE); + $end_date = $this->input->get('end_date', TRUE); + + $roomplan_data = $this->StundenplanModel->stundenplanGruppierung($this->StundenplanModel->getRoomQuery($ort_kurzbz, $start_date, $end_date)); + + $roomplan_data = $this->getDataOrTerminateWithError($roomplan_data); + + $this->expand_object_information($roomplan_data); + + $this->terminateWithSuccess($roomplan_data); + + } + + /** + * fetches stundenplan events from a UID and start/end date + * @access public + * + */ + //TODO: getStundenplan fuer Mitarbeiter anpassen + public function getStundenplan(){ + + $this->load->model('ressource/Mitarbeiter_model','MitarbeiterModel'); + $this->load->model('organisation/Studiensemester_model','StudiensemesterModel'); + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $this->load->model('person/Benutzergruppe_model','BenutzergruppeModel'); + + // form validation + $this->load->library('form_validation'); + $this->form_validation->set_data($_GET); + $this->form_validation->set_rules('start_date', "start_date", "required"); + $this->form_validation->set_rules('end_date', "end_date", "required"); + if ($this->form_validation->run() === FALSE) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // storing the get parameter in local variables + $start_date = $this->input->get('start_date', TRUE); + $end_date = $this->input->get('end_date', TRUE); + + $student_uid = getAuthUID(); + if(is_null($student_uid)) + { + $this->terminateWithError("No UID"); + } + + $is_mitarbeiter = getData($this->MitarbeiterModel->isMitarbeiter($student_uid)); + if($is_mitarbeiter) + { + $this->terminateWithError("Not possible to look at the Student Calendar as a Mitarbeiter"); + } + + $semester_range = $this->studienSemesterErmitteln($start_date,$end_date); + + $this->sortStudienSemester($semester_range); + + $this->applyLoadUeberSemesterHaelfte($semester_range); + + // getting the gruppen_kurzbz of the student in the different studiensemester + $benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($semester_range); + + // getting the student_lehrverbaende of the student in the different studiensemester + $student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($semester_range); + + $stundenplan_query = $this->StundenplanModel->getStundenplanQuery($start_date, $end_date, $semester_range, $benutzer_gruppen, $student_lehrverband); + if(!$stundenplan_query) + { + $this->terminateWithSuccess([]); + } + $stundenplan_data = $this->StundenplanModel->stundenplanGruppierung($stundenplan_query); + $stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? []; + + $this->expand_object_information($stundenplan_data); + + $this->terminateWithSuccess($stundenplan_data); + } + + // gets the reservierungen of a room if the ort_kurzbz parameter is supplied otherwise gets the reservierungen of the stundenplan of a student + public function Reservierungen($ort_kurzbz = null) + { + //form validation + $this->load->library('form_validation'); + $this->form_validation->set_data($_GET); + $this->form_validation->set_rules('start_date', "StartDate", "required"); + $this->form_validation->set_rules('end_date', "EndDate", "required"); + if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // storing the get parameter in local variables + $start_date = $this->input->get('start_date', TRUE); + $end_date = $this->input->get('end_date', TRUE); + + // querying the reservierungen + $reservierungen = $this->ReservierungModel->getReservierungen($start_date, $end_date, $ort_kurzbz); + + $reservierungen = $this->getDataOrTerminateWithError($reservierungen) ?? []; + + $this->expand_object_information($reservierungen); + + $this->terminateWithSuccess($reservierungen); + + } + + public function getLehreinheitStudiensemester($lehreinheit_id){ + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->LehreinheitModel->addSelect(["studiensemester_kurzbz"]); + $result = $this->LehreinheitModel->load($lehreinheit_id); + $result = current($this->getDataOrTerminateWithError($result))->studiensemester_kurzbz; + $this->terminateWithSuccess($result); + } + + // ################# Private Functions + + private function expand_object_information($data){ + + foreach ($data as $item) + { + + $lektor_obj_array = array(); + $gruppe_obj_array = array(); + + // load lektor object + foreach ($item->lektor as $lv_lektor) + { + $this->StundenplanModel->addLimit(1); + $lektor_object = $this->StundenplanModel->execReadOnlyQuery(" + SELECT mitarbeiter_uid, vorname, nachname, kurzbz + FROM public.tbl_mitarbeiter + JOIN public.tbl_benutzer benutzer ON benutzer.uid = mitarbeiter_uid + JOIN public.tbl_person person ON person.person_id = benutzer.person_id + WHERE kurzbz = ?", [$lv_lektor]); + if (isError($lektor_object)) { + $this->show_error(getError($lektor_object)); + } + $lektor_object = $this->getDataOrTerminateWithError($lektor_object); + if(count($lektor_object) == 0) + { + $this->terminateWithError("No lektor object"); + } + $lektor_object = current($lektor_object); + // only provide needed information of the mitarbeiter object + $lektor_obj_array[] = $lektor_object; + } + + // load gruppe object + foreach ($item->gruppe as $lv_gruppe) + { + $lv_gruppe = strtr($lv_gruppe, ['(' => '', ')' => '', '"' => '']); + $lv_gruppe_array = explode(",", $lv_gruppe); + list($gruppe, $verband, $semester, $studiengang_kz, $gruppen_kuerzel) = $lv_gruppe_array; + + $lv_gruppe_object = new stdClass(); + $lv_gruppe_object->gruppe = $gruppe; + $lv_gruppe_object->verband = $verband; + $lv_gruppe_object->semester = $semester; + $lv_gruppe_object->studiengang_kz = $studiengang_kz; + $lv_gruppe_object->kuerzel = $gruppen_kuerzel; + + $gruppe_obj_array[] = $lv_gruppe_object; + } + + $item->gruppe = $gruppe_obj_array; + $item->lektor = $lektor_obj_array; + + } + } + + // function used to sort an array of studiensemester strings + private function sortStudienSemester(&$semester_range){ + usort( + $semester_range, + function($first,$second) + { + $sem_first = null; + $year_first = null; + $match_first = null; + + $sem_second = null; + $year_second = null; + $match_second = null; + + preg_match('/([WS]+)([0-9]+)/',$first,$match_first); + preg_match('/([WS]+)([0-9]+)/',$second,$match_second); + + $sem_first = $match_first[1]; + $year_first = intval($match_first[2]); + + $sem_second = $match_second[1]; + $year_second = intval($match_second[2]); + + if($year_first < $year_second) + { + return -1; + } + else if($year_first > $year_second) + { + return 1; + } + else if($year_first == $year_second && $sem_first > $sem_second) + { + return 1; + } + else if($year_first == $year_second && $sem_first < $sem_second) + { + return -1; + } + return 0; + } + ); + } + + + + private function fetchBenutzerGruppenFromStudiensemester($semester_range){ + $student_uid = getAuthUID(); + $benutzer_gruppen = []; + // for each studiensemester fetch the benutzer gruppen and add them to an associate $bentuzer_gruppen array + /* + [ + ['WS2023'] => [['gruppe1_SS2023','gruppe2_SS2023'],['gruppe1_WS2023','gruppe2_WS2023']], + ['SS2024'] => [['gruppe1_WS2023','gruppe2_WS2023'],['gruppe1_SS2024','gruppe2_SS2024']], + ['WS2024'] => [['gruppe1_SS2024','gruppe2_SS2024'],['gruppe1_WS2024','gruppe2_WS2024']], + ] + */ + foreach($semester_range as $semester_key => $semester_array) + { + $benutzer_gruppen[$semester_key] = []; + // each semester could have ajoint semesters that need to be checked + foreach($semester_array as $semester=>$semester_date_range) + { + // for each active semester query the benutzer_gruppen associated to the semester + $benutzer_query = $this->BenutzergruppeModel->execReadOnlyQuery(" + SELECT * FROM tbl_benutzergruppe where uid = ? AND studiensemester_kurzbz = ?",[$student_uid, $semester]); + $benutzer_query_result = $this->getDataOrTerminateWithError($benutzer_query); + array_push( + $benutzer_gruppen[$semester_key], + array_map( + function($item) + { + return "'".$item->gruppe_kurzbz. "'"; + }, + $benutzer_query_result + ) + ); + } + } + + // merge the gruppen of each studiensemester together for the original studiensemester + /* + [ + ['WS2023'] => ['gruppe1_SS2023','gruppe2_SS2023','gruppe1_WS2023','gruppe2_WS2023'], + ['SS2024'] => ['gruppe1_WS2023','gruppe2_WS2023','gruppe1_SS2024','gruppe2_SS2024'], + ['WS2024'] => ['gruppe1_SS2024','gruppe2_SS2024','gruppe1_WS2024','gruppe2_WS2024'], + ] + */ + $benutzer_gruppen = array_map( + function($gruppe) + { + $merged_gruppe = []; + foreach($gruppe as $gruppen_array) + { + $merged_gruppe = array_merge($merged_gruppe, $gruppen_array); + } + return $merged_gruppe; + }, + $benutzer_gruppen + ); + + return $benutzer_gruppen; + } + + private function fetchStudentlehrverbandFromStudiensemester($semester_range){ + $student_uid = getAuthUID(); + $student_lehrverband = []; + // for each studiensemester fetch the studentlehrverbaende and add them to an associate $student_lehrverband array + /* + [ + ['WS2023'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ] ], + ['SS2024'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ] ], + ['WS2024'] => [ [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ] ], + ] + */ + foreach($semester_range as $semester_key => $semester_array) + { + $student_lehrverband[$semester_key] = []; + foreach($semester_array as $semester=>$semester_date_range) + { + // for each active semester query the student_lehrverband associated to the semester + $lehrverband_query = $this->BenutzergruppeModel->execReadOnlyQuery(" + SELECT * FROM tbl_studentlehrverband where student_uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]); + $lehrverband_query_result = $this->getDataOrTerminateWithError($lehrverband_query); + array_push($student_lehrverband[$semester_key], array_map( + function ($item) + { + $result = new stdClass(); + $result->studiengang_kz = $item->studiengang_kz; + $result->semester = $item->semester; + $result->verband = $item->verband; + $result->gruppe = $item->gruppe; + return $result; + }, + $lehrverband_query_result)); + } + } + + // merge the studentlehrverband of each studiensemester together for the original studiensemester + /* + [ + ['WS2023'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ], + ['SS2024'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ], + ['WS2024'] => [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ], + ] + */ + $student_lehrverband = array_map( + function($studentlehrverband) + { + $merged_studentlehrverband = []; + foreach($studentlehrverband as $studentlehrverband_array) + { + $merged_studentlehrverband = array_merge($merged_studentlehrverband, $studentlehrverband_array); + } + return $merged_studentlehrverband; + }, + $student_lehrverband + ); + + return $student_lehrverband; + } + + private function applyLoadUeberSemesterHaelfte(&$semester_range){ + /* + @var($semester_collection) + convert the array of studiensemester into an associative array with the studiensemester as the key + and the values of each key are the studiensemester needed for the query associated to that studiensemester + example: + + #INPUT: + ['WS2023','SS2024','WS2024'] + #OUTPUT: + [ + 'WS2023' => ['SS2023','WS2023'] + 'SS2024' => ['WS2023','SS2024'] + 'WS2024' => ['SS2024','WS2024'] + ] + */ + $semester_collection = []; + foreach($semester_range as $studiensemester) + { + $previous_studiensemester = $this->StudiensemesterModel->getPreviousFrom($studiensemester); + $previous_studiensemester = $this->getDataOrTerminateWithError($previous_studiensemester); + if (count($previous_studiensemester) == 0) { + $this->terminateWithError("No previous semester"); + } + $previous_studiensemester = current($previous_studiensemester)->studiensemester_kurzbz; + $semester_collection[$studiensemester] = [$previous_studiensemester, $studiensemester]; + } + + /* + @var($studienSemesterDateRanges) + fetches for each studiensemester the start and end date, (SS) summer studiensemester are extended by 1 month to cover the summerbreak + based on the LVPLAN_LOAD_UEBER_SEMESTERHAELFTE constant it will load both the semester and the previous semester with the full date range + or the semester with the full date range and the previous semester with the half date range: + + #INPUT: + [ + 'WS2023' => ['SS2023','WS2023'] + 'SS2024' => ['WS2023','SS2024'] + 'WS2024' => ['SS2024','WS2024'] + ] + #OUTPUT: depends whether LVPLAN_LOAD_UEBER_SEMESTERHAELFTE is true or false + ~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == true + [ + "SS2024": [ + "WS2023": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ], + "SS2024": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ] + ] + ] + ~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == false + [ + "SS2024": [ + "WS2023": [ + "start"=> "2024-02-03", + "ende"=> "2024-05-17" + ], + "SS2024": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ] + ] + ] + */ + $studienSemesterDateRanges=[]; + foreach($semester_collection as $semester_original => $semester_adjoint) + { + $semester_start_ende = $this->StudiensemesterModel->getStartEndeFromStudiensemester($semester_original); + $semester_start_ende = current($this->getDataOrTerminateWithError($semester_start_ende)); + + // initialize empty arrays to add key value pairs + $studienSemesterDateRanges[$semester_original] = []; + + // check if the studiensemester is a summer semester and add 1 month to bridge the school summer break + $match = null; + preg_match("/^(SS)([0-9]+)/",$semester_original,$match); + if(count($match) >0) + { + $one_month = new DateInterval('P1M'); + $one_day = DateInterval::createFromDateString('1 days'); + $summer_studiensemester_end_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->ende); + $summer_studiensemester_end_date->add($one_month); + $summer_studiensemester_end_date->sub($one_day); + $semester_start_ende->ende = date_format($summer_studiensemester_end_date,'Y-m-d'); + } + if (defined('LVPLAN_LOAD_UEBER_SEMESTERHAELFTE') && LVPLAN_LOAD_UEBER_SEMESTERHAELFTE === true) + { + foreach($semester_adjoint as $adjoint) + { + $studienSemesterDateRanges[$semester_original][$adjoint]=$semester_start_ende; + } + } + else + { + //TODO: half of a DateInterval might not be correctly calculated + // calculate the half of the studiensemester + $studiensemester_start_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->start); + $studiensemester_end_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->ende); + $studiensemester_time_difference = $studiensemester_start_date->diff($studiensemester_end_date); + $half_dateNumber = ceil($studiensemester_time_difference->d/2)+ceil(($studiensemester_time_difference->m*30)/2); + $half_dateInterval = new DateInterval('P'.strval($half_dateNumber) .'D'); + $studiensemester_half = date_format($studiensemester_start_date->add($half_dateInterval),'Y-m-d'); + + $first_half = new stdClass(); + $first_half->start = $semester_start_ende->start; + $first_half->ende = $studiensemester_half; + + $studienSemesterDateRanges[$semester_original][$semester_adjoint[0]] = $first_half; + $studienSemesterDateRanges[$semester_original][$semester_adjoint[1]] = $semester_start_ende; + } + $semester_range = $studienSemesterDateRanges; + } + } + + private function studienSemesterErmitteln($start_date,$end_date){ + + // gets all studiensemester from the student from start_date to end_date + $semester_range = $this->StudiensemesterModel->getByDate($start_date,$end_date); + $semester_range = array_map( + function($sem) + { + return $sem->studiensemester_kurzbz; + }, + $this->getDataOrTerminateWithError($semester_range) + ); + + // if no studiensemester is found for the given timespan, get the nearest studiensemester + if(count($semester_range) == 0) + { + $aktuelle_studiensemester = $this->StudiensemesterModel->getNearest(); + $aktuelle_studiensemester = $this->getDataOrTerminateWithError($aktuelle_studiensemester); + if (count($aktuelle_studiensemester) == 0) { + $this->terminateWithError("No aktuelles semester"); + } + $aktuelle_studiensemester = current($aktuelle_studiensemester)->studiensemester_kurzbz; + // push aktuelles semester in active semester array + array_push($semester_range, $aktuelle_studiensemester); + + } + return $semester_range; + } + +} 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 new file mode 100644 index 000000000..ff59ef41a --- /dev/null +++ b/application/controllers/codex/UHSTAT1.php @@ -0,0 +1,454 @@ +load->library('form_validation'); + + // load ci helpers + $this->load->helper(array('form', 'url')); + + // load libraries + $this->load->library('AuthLib'); + $this->load->library('PermissionLib'); + + // load models + $this->load->model('codex/Oehbeitrag_model', 'OehbeitragModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('system/Sprache_model', 'SpracheModel'); + $this->load->model('codex/Abschluss_model', 'AbschlussModel'); + $this->load->model('codex/Uhstat1daten_model', 'Uhstat1datenModel'); + + $this->loadPhrases( + array( + 'ui', + 'uhstat' + ) + ); + + $this->_uid = getAuthUID(); + + // set form field information + $this->_uhstat1Fields = array( + 'mutter_geburtsstaat' => array('name' => 'Geburtsstaat Mutter'), + 'mutter_geburtsjahr' => array('name' => 'Geburtsjahr Mutter'), + 'mutter_bildungsstaat' => array('name' => 'Bildungsstaat Mutter'), + 'mutter_bildungmax' => array( + 'name' => 'Geburtsjahr Mutter', + 'rules' => array( + 'callback_bildungsstaat_bildungmax_check[m]' => array( + 'bildungsstaat_bildungmax_check' => $this->p->t('uhstat', 'ausbildungBildungsstaatUebereinstimmung') + ) + ) + ), + 'vater_geburtsstaat' => array('name' => 'Geburtsstaat Vater'), + 'vater_geburtsjahr' => array('name' => 'Geburtsjahr Vater'), + 'vater_bildungsstaat' => array('name' => 'Bildungsstaat Vater'), + 'vater_bildungmax' => array('name' => 'Geburtsjahr Vater'), + 'vater_bildungmax' => array( + 'name' => 'Geburtsjahr Vater', + 'rules' => array( + 'callback_bildungsstaat_bildungmax_check[v]' => array( + 'bildungsstaat_bildungmax_check' => $this->p->t('uhstat', 'ausbildungBildungsstaatUebereinstimmung') + ) + ) + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + public function index() + { + $formMetaData = $this->_getFormMetaData(); + + if (isError($formMetaData)) show_error(getError($formMetaData)); + + if (!hasData($formMetaData)) show_error("No form meta data could be loaded"); + + $uhstatData = $this->_getUHSTAT1Data(); + + if (isError($uhstatData)) show_error(getError($uhstatData)); + + $this->load->view("codex/uhstat1.php", array( + 'formMetaData' => getData($formMetaData), + 'uhstatData' => getData($uhstatData) + ) + ); + } + + /** + * Add or update UHSTAT1 data + */ + public function saveUHSTAT1Data() + { + $saved = false; + + $person_id = $this->_getValidPersonId('sui'); + + $this->form_validation->set_error_delimiters('', ''); + + foreach ($this->_uhstat1Fields as $field => $params) + { + // all fields are required + $ruleNames = 'required'; + $ruleMessages = array('required' => $this->p->t('uhstat', 'angabeFehlt')); + + // add additional rules + if (isset($params['rules'])) + { + foreach ($params['rules'] as $ruleName => $ruleMessage) + { + $ruleNames .= '|'.$ruleName; + $ruleMessages = array_merge($ruleMessages, $ruleMessage); + } + } + + $this->form_validation->set_rules( + $field, + $params['name'], + $ruleNames, + $ruleMessages + ); + } + + $uhstat1datenRes = null; + if ($this->form_validation->run()) // if valid + { + // get post fields + $uhstatData = array(); + foreach ($this->_uhstat1Fields as $field => $params) + { + $uhstatData[$field] = $this->input->post($field); + } + + // check if entry already exists + $uhstat1datenloadRes = $this->Uhstat1datenModel->loadWhere(array('person_id' => $person_id)); + + // if yes, update + if (hasData($uhstat1datenloadRes)) + { + $uhstatData['updateamum'] = 'NOW()'; + $uhstatData['updatevon'] = $this->_uid; + $uhstat1datenRes = $this->Uhstat1datenModel->update( + array('person_id' => $person_id), + $uhstatData + ); + } + else // otherwise insert + { + $uhstatData['insertamum'] = 'NOW()'; + $uhstatData['insertvon'] = $this->_uid; + $uhstat1datenRes = $this->Uhstat1datenModel->insert( + array_merge($uhstatData, array('person_id' => $person_id)) + ); + } + } + + $formMetaData = $this->_getFormMetaData(); + + if (isError($formMetaData)) show_error(getError($formMetaData)); + + if (!hasData($formMetaData)) show_error("No form meta data could be loaded"); + + $successMessage = ''; + $errorMessage = ''; + // pass success/error messages to view + if (isset($uhstat1datenRes)) + { + if (isSuccess($uhstat1datenRes)) + { + $successMessage = $this->p->t('uhstat', 'erfolgreichGespeichert'); + $saved = true; + } + else + $errorMessage = $this->p->t('uhstat', 'fehlerBeimSpeichern'); + } + + // load view with form data + $this->load->view("codex/uhstat1.php", array( + 'formMetaData' => getData($formMetaData), + 'saved' => $saved, + 'successMessage' => $successMessage, + 'errorMessage' => $errorMessage + ) + ); + } + + /** + * Check callback for Bildungsstaat - if Bildungsstaat is Austria, a highest education should be in Austria. + * @param $bildungmax + * @param $bildungsstaat_typ - mother (m) or father (v) + * @return bool true if valid, false otherwise + */ + public function bildungsstaat_bildungmax_check($bildungmax, $bildungsstaat_typ) + { + // valid if no type passed + if (!isset($bildungsstaat_typ) || !isset($bildungmax)) return true; + + // get correct input + if ($bildungsstaat_typ == 'm') // mutter + $bildungsstaat = $this->input->post('mutter_bildungsstaat'); + elseif ($bildungsstaat_typ == 'v') // vater + $bildungsstaat = $this->input->post('vater_bildungsstaat'); + else + 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"); + $abschlussRes = $this->AbschlussModel->load($bildungmax); + + if (hasData($abschlussRes)) + { + $in_oesterreich = getData($abschlussRes)[0]->in_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; + } + + /** + * Deletes UHSTAT1 entry. + */ + public function deleteUHSTAT1Data() + { + $saved = false; + + // uhstat data can only be deleted with permission + if (!$this->_checkPermission('suid')) show_error('no permission'); + + $person_id = $this->_getValidPersonId('suid'); + + $uhstat1datenRes = $this->Uhstat1datenModel->delete( + array('person_id' => $person_id) + ); + + $formMetaData = $this->_getFormMetaData(); + + if (isError($formMetaData)) show_error(getError($formMetaData)); + + if (!hasData($formMetaData)) show_error("No form meta data could be loaded"); + + $successMessage = ''; + $errorMessage = ''; + // pass success/error messages to view + if (isset($uhstat1datenRes)) + { + if (isSuccess($uhstat1datenRes)) + { + $successMessage = $this->p->t('uhstat', 'erfolgreichGeloescht'); + } + else + $errorMessage = $this->p->t('uhstat', 'fehlerBeimLoeschen'); + } + + // load view with form data + $this->load->view("codex/uhstat1.php", array( + 'formMetaData' => getData($formMetaData), + 'successMessage' => $successMessage, + 'errorMessage' => $errorMessage + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Private methods + + /** + * Gets initial data needed to display UHSTAT1 form. + */ + private function _getFormMetaData() + { + $person_id = $this->_getValidPersonId('s'); + + // read only display param + $readOnly = $this->input->get('readOnly'); + + // depending on permissions, editing or deleting is possible + $editPermission = $this->_checkPermission('sui'); + $deletePermission = $this->_checkPermission('suid'); + + $languageIdx = $this->_getLanguageIndex(); + + $formMetaData = array( + 'nation' => array(), + 'abschluss_oesterreich' => array(), + 'abschluss_nicht_oesterreich' => array(), + 'jahre' => array(), + 'person_id' => $person_id, + 'editPermission' => $editPermission, + 'deletePermission' => $deletePermission, + 'readOnly' => $readOnly + ); + + // get person data + $this->load->model('person/Person_model', 'PersonModel'); + $this->PersonModel->addSelect("vorname, nachname"); + $personRes = $this->PersonModel->load($person_id); + + if (isError($personRes)) return $personRes; + + if (hasData($personRes)) + { + $person = getData($personRes)[0]; + $formMetaData['vorname'] = $person->vorname; + $formMetaData['nachname'] = $person->nachname; + } + + $nationTextFieldName = $languageIdx == 1 ? 'langtext' : 'engltext'; + + // get nation list + $this->load->model('codex/Nation_model', 'NationModel'); + + $this->NationModel->addSelect("nation_code, $nationTextFieldName AS nation_text"); + $this->NationModel->addOrder("nation_text"); + $nationRes = $this->NationModel->loadWhere('sperre IS NULL OR sperre = FALSE'); + + if (isError($nationRes)) return $nationRes; + + if (hasData($nationRes)) + { + $nations = getData($nationRes); + + // put austria in beginning of selection + foreach ($nations as $nation) + { + if ($nation->nation_code == self::CODEX_OESTERREICH) array_unshift($nations, $nation); + } + + $formMetaData['nation'] = $nations; + } + + // get abschluss list + $abschlussRes = $this->AbschlussModel->getActiveAbschluesse($languageIdx); + + if (isError($abschlussRes)) return $abschlussRes; + + $abschlussData = getData($abschlussRes); + + if (hasData($abschlussRes)) + { + foreach (getData($abschlussRes) as $abschluss) + { + if ($abschluss->in_oesterreich === true) + $formMetaData['abschluss_oesterreich'][] = $abschluss; + elseif ($abschluss->in_oesterreich === false) + $formMetaData['abschluss_nicht_oesterreich'][] = $abschluss; + else + { + $formMetaData['abschluss_oesterreich'][] = $abschluss; + $formMetaData['abschluss_nicht_oesterreich'][] = $abschluss; + } + } + } + + // get realistic birth years, dated back from current year + $currYear = date("Y"); + $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); + } + + /** + * Gets initial data needed to display UHSTAT1 form. + */ + private function _getUHSTAT1Data() + { + $person_id = $this->_getValidPersonId('s'); + + $this->Uhstat1datenModel->addSelect( + implode(', ', array_keys($this->_uhstat1Fields)) + ); + $uhstatRes = $this->Uhstat1datenModel->loadWhere(array('person_id' => $person_id)); + + if (isError($uhstatRes)) return $uhstatRes; + + return success(hasData($uhstatRes) ? getData($uhstatRes)[0] : null); + } + + /** + * Gets language index of currently logged in user. + * @return int (the index, start at 1) + */ + private function _getLanguageIndex() + { + $idx = 1; + $this->SpracheModel->addSelect('index'); + $langRes = $this->SpracheModel->loadWhere(array('sprache' => getUserLanguage())); + + if (hasData($langRes)) + { + $idx = getData($langRes)[0]->index; + } + + return $idx; + } + + /** + * Gets Id of person having permissions to manage UHSTAT1 data. + * Can be passed as parameter or be in session. + * @return int person_id + */ + 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]) + && isset($_SESSION[self::LOGIN_SESSION_INDEX]) + ) + return $_SESSION[self::PERSON_ID_SESSION_INDEX]; + + // if person id passed directly... + $person_id = $this->input->post('person_id'); + if (!isset($person_id)) $person_id = $this->input->get('person_id'); + + if (!isset($person_id) || !is_numeric($person_id)) show_error("invalid person id"); + + // ...check if there is a permission for editing UHSTAT1 data + if ($this->_checkPermission($berechtigungsArt)) return $person_id; + + show_error("No permission"); + } + + /** + * Checks if logged user has the UHSTAT management permission. + * @param $art - type of permission, e.g. suid for full permissions + * @return bool + */ + private function _checkPermission($art) + { + return $this->permissionlib->isBerechtigt(self::BERECHTIGUNG_UHSTAT_VERWALTEN, $art); + } +} diff --git a/application/controllers/components/Cis/Mylv.php b/application/controllers/components/Cis/Mylv.php new file mode 100644 index 000000000..1fdb7e2a1 --- /dev/null +++ b/application/controllers/components/Cis/Mylv.php @@ -0,0 +1,213 @@ + ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions? + 'Studiensemester' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions? + 'Lvs' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions? + 'Info' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions? + 'Pruefungen' => ['student/anrechnung_beantragen:r','user:r'] // TODO(chris): permissions? + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + */ + public function Student() + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID()); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $this->outputJsonSuccess(getData($result)); + } + + /** + */ + public function Studiensemester() + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $result = $this->StudiensemesterModel->getWhereStudentHasLvs(getAuthUID()); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $this->outputJsonSuccess(getData($result)); + } + + /** + */ + public function Lvs($studiensemester_kurzbz) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID(), $studiensemester_kurzbz, getUserLanguage()); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $this->outputJsonSuccess(getData($result)); + } + + /** + */ + public function Info($studiensemester_kurzbz, $lehrveranstaltung_id) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + $lv = current(getData($result) ?: []); + + if (!$lv) + return $this->outputJsonError('Could\'t find Lehrveranstaltung with id: ' . $lehrveranstaltung_id); + + + $this->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + + $result = $this->LehreinheitmitarbeiterModel->getForLv($lehrveranstaltung_id, $studiensemester_kurzbz); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $lvinfo = []; + $lvinfo['lektoren'] = getData($result) ?: []; + + $kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER); + $lvinfo['lektoren'] = array_values(array_filter($lvinfo['lektoren'], function ($v) use ($kollisionsfreie_user) { + return !in_array($v->uid, $kollisionsfreie_user); + })); + + $lvinfo['lvLeitung'] = array_values(array_filter($lvinfo['lektoren'], function ($v) { + return $v->lehrfunktion_kurzbz == 'LV-Leitung'; + })); + + + $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + $result = $this->OrganisationseinheitModel->getWithType($lv->oe_kurzbz); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $lvinfo['oe'] = current(getData($result) ?: []); + + + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $result = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('Leitung', $lv->oe_kurzbz); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $lvinfo['oeLeitung'] = getData($result) ?: []; + + + $result = $this->LehrveranstaltungModel->getKoordinator($lehrveranstaltung_id, $studiensemester_kurzbz); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $lvinfo['koordinator'] = getData($result) ?: []; + + if (defined('ACTIVE_ADDONS') && in_array('lvinfo', explode(';', ACTIVE_ADDONS)) && file_exists(FHCPATH . 'addons/lvinfo/include/lvinfo.class.php')) + { + require_once(FHCPATH . 'addons/lvinfo/include/lvinfo.class.php'); + $lvinfoObj = new lvinfo(); + $lvinfoObj->loadLVinfo($lehrveranstaltung_id, $studiensemester_kurzbz, null, true); + if (is_array($lvinfoObj->result)) + { + $oldP = property_exists($this, 'p') ? $this->p : null; + $result = []; + $lvinfos = $lvinfoObj->result; + $lvinfoSet = new lvinfo(); + $lvinfoSet->load_lvinfo_set($studiensemester_kurzbz); + foreach ($lvinfos as $lvi) + { + $this->p = null; + $this->loadPhrases('ui', $lvi->sprache); + $result[$lvi->sprache] = []; + foreach ($lvinfoSet->result as $set) + { + $key = $set->lvinfo_set_kurzbz; + if (!isset($lvi->data[$key])) + continue; + $info = [ + 'header' => $set->lvinfo_set_bezeichnung[$lvi->sprache] + ]; + if (isset($set->einleitungstext[$lvi->sprache])) + $info['subheader'] = $set->einleitungstext[$lvi->sprache]; + switch ($set->lvinfo_set_typ) + { + case 'boolean': + $info['body'] = $this->p->t('ui', $lvi->data[$key] === true ? 'ja' : 'nein'); + break; + case 'array': + $info['body'] = array_map('htmlspecialchars', $lvi->data[$key]); + break; + case 'editor': + $info['body'] = $lvi->data[$key]; + break; + default: + $info['body'] = htmlspecialchars($lvi->data[$key]); + } + if ($info['body']) + $result[$lvi->sprache][] = $info; + } + } + if ($result) + { + $lvinfo['lvinfo'] = $result; + $lvinfo['lvinfoDefaultLang'] = getUserLanguage(); + + $this->load->model('system/Sprache_model', 'SpracheModel'); + $result = $this->SpracheModel->loadMultiple(array_keys($result)); + if (!isError($result)) + { + $result = getData($result); + $lvinfo['sprachen'] = []; + foreach ($result as $sprache) { + $lvinfo['sprachen'][$sprache->sprache] = $sprache; + } + } + } + $this->p = $oldP; + } + } + + + $this->outputJsonSuccess($lvinfo); + } + + /** + */ + public function Pruefungen($lehrveranstaltung_id) + { + $this->load->model('education/Pruefung_model', 'PruefungModel'); + + $result = $this->PruefungModel->getByStudentAndLv(getAuthUID(), $lehrveranstaltung_id, getUserLanguage()); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $this->outputJsonSuccess(getData($result)); + } + +} diff --git a/application/controllers/components/Cis/Stundenplan.php b/application/controllers/components/Cis/Stundenplan.php new file mode 100644 index 000000000..a9f35c651 --- /dev/null +++ b/application/controllers/components/Cis/Stundenplan.php @@ -0,0 +1,73 @@ + ['basis/cis'], + 'Reservierungen' => ['basis/cis'], + 'Stunden' => ['basis/cis'], + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + */ + public function index() + { + $this->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + /* $result = $this->StundenplanModel->loadForUid(getAuthUID()); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + */ + $res = $this->StundenplanModel->stundenplanGruppierung($this->StundenplanModel->getStundenplanQuery(getAuthUID())); + + $res = getData($res); + + $this->outputJsonSuccess($res); + } + + /** + */ + public function Reservierungen() + { + $this->load->model('ressource/Reservierung_model', 'ReservierungModel'); + + $result = $this->ReservierungModel->loadForUid(getAuthUID()); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $this->outputJsonSuccess(getData($result)); + } + + /** + */ + public function Stunden() + { + $this->load->model('ressource/Stunde_model', 'StundeModel'); + + $result = $this->StundeModel->load(); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $this->outputJsonSuccess(getData($result)); + } + + +} 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 09a49e163..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,8 +17,17 @@ class SearchBar extends FHC_Controller { parent::__construct(); + // 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/dashboard/Api.php b/application/controllers/dashboard/Api.php new file mode 100644 index 000000000..422bf0675 --- /dev/null +++ b/application/controllers/dashboard/Api.php @@ -0,0 +1,76 @@ + 'dashboard/admin:rw', + 'getNews' => 'dashboard/benutzer:r', + 'getAmpeln' => 'dashboard/benutzer:r', + ) + ); + + $this->load->library('AuthLib', null, 'AuthLib'); + + $this->_setAuthUID(); + } + + public function index() + { + echo 'Dashboard API Controller'; + } + + /** + * Get News. + */ + public function getNews() + { + $limit = $this->input->get('limit'); + + $this->load->model('content/News_model', 'NewsModel'); + + $result = $this->NewsModel->getAll($limit); + + if (hasData($result)) + { + $this->outputJson(getData($result), REST_Controller::HTTP_OK); + } + else + { + $this->terminateWithJsonError('fehler entdeckt'); + } + } + + + /** + * Get Ampeln. + */ + public function getAmpeln() + { + + $this->load->model('content/Ampel_model', 'AmpelModel'); + $result = $this->AmpelModel->getByUser($this->_uid); + + if (hasData($result)) + { + $this->outputJson(getData($result), REST_Controller::HTTP_OK); + } + else + { + $this->terminateWithJsonError('fehler entdeckt'); + } + } + + /** + * 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'); + } +} diff --git a/application/controllers/dashboard/Config.php b/application/controllers/dashboard/Config.php new file mode 100644 index 000000000..2c0cf5fca --- /dev/null +++ b/application/controllers/dashboard/Config.php @@ -0,0 +1,216 @@ + 'dashboard/benutzer:r', + 'dummy' => 'dashboard/benutzer:r', + 'genWidgetId' => 'dashboard/benutzer:rw', + 'addWidgetsToPreset' => 'dashboard/admin:rw', + 'removeWidgetFromPreset' => 'dashboard/admin:rw', + 'addWidgetsToUserOverride' => 'dashboard/benutzer:rw', + 'removeWidgetFromUserOverride' => 'dashboard/benutzer:rw', + 'funktionen' => 'dashboard/admin:r', + 'preset' => 'dashboard/admin:r', + 'presetBatch' => 'dashboard/admin:r' + ) + ); + + $this->load->library('dashboard/DashboardLib', null, 'DashboardLib'); + $this->load->library('AuthLib', null, 'AuthLib'); + $this->load->model('ressource/Funktion_model', 'FunktionModel'); + } + + public function index() + { + $dashboard_kurzbz = $this->input->get('db'); + $uid = $this->AuthLib->getAuthObj()->username; + + $dashboard = $this->DashboardLib->getDashboardByKurzbz($dashboard_kurzbz); + if(!$dashboard) { + http_response_code(404); + $this->terminateWithJsonError(array( + 'error' => 'Dashboard ' . $dashboard_kurzbz . ' not found.' + )); + } + + $mergedconfig = $this->DashboardLib->getMergedConfig($dashboard->dashboard_id, $uid); + $this->outputJsonSuccess($mergedconfig); + } + + public function genWidgetId() + { + $dashboard_kurzbz = $this->input->get('db'); + $widgetid = $this->DashboardLib->generateWidgetId($dashboard_kurzbz); + $this->outputJsonSuccess(array( + 'widgetid' => $widgetid + )); + } + + public function addWidgetsToPreset() + { + $input = json_decode($this->input->raw_input_stream); + $dashboard_kurzbz = $input->db; + $funktion_kurzbz = $input->funktion_kurzbz; + + $preset = $this->DashboardLib->getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz); + + $preset_decoded = json_decode($preset->preset, true); + + $this->DashboardLib->addWidgetsToWidgets($preset_decoded['widgets'], $dashboard_kurzbz, $funktion_kurzbz, $input->widgets); + + $preset->preset = json_encode($preset_decoded); + + $result = $this->DashboardLib->insertOrUpdatePreset($preset); + if (isError($result)) { + http_response_code(500); + $this->terminateWithJsonError('preset could not be saved'); + } + + $this->outputJsonSuccess(array('msg' => 'preset successfully stored.', 'data' => $preset_decoded)); + } + + public function removeWidgetFromPreset() + { + $input = json_decode($this->input->raw_input_stream); + $dashboard_kurzbz = $input->db; + $funktion_kurzbz = $input->funktion_kurzbz; + $widgetid = $input->widgetid; + + $preset = $this->DashboardLib->getPreset($dashboard_kurzbz, $funktion_kurzbz); + if ($preset === null) { + http_response_code(404); + $this->terminateWithJsonError('preset for dashboard ' . $dashboard_kurzbz . ' and funktion ' . $funktion_kurzbz . ' not found.'); + } + + $preset_decoded = json_decode($preset->preset, true); + if (!$this->DashboardLib->removeWidgetFromWidgets($preset_decoded['widgets'], $funktion_kurzbz, $widgetid)) + { + http_response_code(404); + $this->terminateWithJsonError('widgetid ' . $widgetid . ' not found'); + } + + $preset->preset = json_encode($preset_decoded); + $result = $this->DashboardLib->insertOrUpdatePreset($preset); + if (isError($result)) + { + http_response_code(500); + $this->terminateWithJsonError('failed to remove widget'); + } + $this->outputJsonSuccess(array('msg' => 'preset successfully updated.')); + } + + public function addWidgetsToUserOverride() + { + $input = json_decode($this->input->raw_input_stream); + $dashboard_kurzbz = $input->db; + $funktion_kurzbz = $input->funktion_kurzbz; + $uid = $this->AuthLib->getAuthObj()->username; + + $override = $this->DashboardLib->getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid); + + $override_decoded = json_decode($override->override, true); + + $this->DashboardLib->addWidgetsToWidgets($override_decoded['widgets'], $dashboard_kurzbz, $funktion_kurzbz, $input->widgets); + + $override->override = json_encode($override_decoded); + + $result = $this->DashboardLib->insertOrUpdateOverride($override); + if (isError($result)) { + http_response_code(500); + $this->terminateWithJsonError('override could not be saved'); + } + + $this->outputJsonSuccess(array('msg' => 'override successfully stored.', 'data' => $override_decoded)); + } + + public function removeWidgetFromUserOverride() + { + $input = json_decode($this->input->raw_input_stream); + $dashboard_kurzbz = $input->db; + $funktion_kurzbz = $input->funktion_kurzbz; + $uid = $this->AuthLib->getAuthObj()->username; + $widgetid = $input->widgetid; + + $override = $this->DashboardLib->getOverride($dashboard_kurzbz, $uid); + if (empty($override)) { + http_response_code(404); + $this->terminateWithJsonError('userconfig for dashboard ' . $dashboard_kurzbz . ' not found.'); + } + + $override_decoded = json_decode($override->override, true); + + if (!$this->DashboardLib->removeWidgetFromWidgets($override_decoded['widgets'], $funktion_kurzbz, $widgetid)) + { + http_response_code(404); + $this->terminateWithJsonError('widgetid ' . $widgetid . ' not found'); + } + + $override->override = json_encode($override_decoded); + $result = $this->DashboardLib->insertOrUpdateOverride($override, $uid); + if (isError($result)) + { + http_response_code(500); + $this->terminateWithJsonError('failed to remove widget'); + } + $this->outputJsonSuccess(array('msg' => 'override successfully updated.')); + } + + public function funktionen() + { + $funktionen = $this->FunktionModel->load(); + + if (isError($funktionen)) { + http_response_code(404); + $this->terminateWithJsonError([ + 'error' => getError($funktionen) + ]); + } + + return $this->outputJsonSuccess(getData($funktionen) ?: []); + } + + public function preset() + { + $db = $this->input->get('db'); + $funktion = $this->input->get('funktion'); + + $conf = $this->DashboardLib->getPreset($db, $funktion); + + if (!$conf) + return $this->outputJsonSuccess(['widgets' => [$funktion => []]]); + + return $this->outputJsonSuccess(json_decode($conf->preset, true)); + } + + public function presetBatch() + { + $db = $this->input->get('db'); + $funktionen = $this->input->get('funktionen'); + $result = []; + + foreach ($funktionen as $funktion) { + $conf = $this->DashboardLib->getPreset($db, $funktion); + if ($conf) + { + $preset = json_decode($conf->preset, true); + if (!isset($preset['widgets']) || !isset($preset['widgets'][$funktion])) + $result[$funktion] = []; + else + $result[$funktion] = $preset['widgets'][$funktion]; + } + else + $result[$funktion] = []; + } + + return $this->outputJsonSuccess($result); + } +} diff --git a/application/controllers/dashboard/Dashboard.php b/application/controllers/dashboard/Dashboard.php new file mode 100644 index 000000000..3773a6d73 --- /dev/null +++ b/application/controllers/dashboard/Dashboard.php @@ -0,0 +1,86 @@ + 'dashboard/admin:r', + 'create' => 'dashboard/admin:rw', + 'update' => 'dashboard/admin:rw', + 'delete' => 'dashboard/admin:rw' + ) + ); + + $this->load->library('dashboard/DashboardLib', null, 'DashboardLib'); + $this->load->model('dashboard/Dashboard_model', 'DashboardModel'); + } + + public function index() + { + $result = $this->DashboardModel->load(); + + if (isError($result)) { + http_response_code(404); + $this->terminateWithJsonError([ + 'error' => getError($result) + ]); + } + + return $this->outputJsonSuccess(getData($result) ?: []); + } + + public function create() + { + $input = $this->getPostJSON(); + + $result = $this->DashboardModel->insert($input); + + if (isError($result)) { + http_response_code(404); + $this->terminateWithJsonError([ + 'error' => getError($result) + ]); + } + + return $this->outputJsonSuccess(getData($result) ?: []); + } + + public function update() + { + $input = $this->getPostJSON(); + + $result = $this->DashboardModel->update($input->dashboard_id, $input); + + if (isError($result)) { + http_response_code(404); + $this->terminateWithJsonError([ + 'error' => getError($result) + ]); + } + + return $this->outputJsonSuccess(getData($result) ?: []); + } + + public function delete() + { + $input = $this->getPostJSON(); + + $result = $this->DashboardModel->delete($input->dashboard_id); + + if (isError($result)) { + http_response_code(404); + $this->terminateWithJsonError([ + 'error' => getError($result) + ]); + } + + return $this->outputJsonSuccess(getData($result) ?: []); + } +} diff --git a/application/controllers/dashboard/DashboardDemo.php b/application/controllers/dashboard/DashboardDemo.php new file mode 100644 index 000000000..35d530384 --- /dev/null +++ b/application/controllers/dashboard/DashboardDemo.php @@ -0,0 +1,58 @@ + 'dashboard/benutzer:r', + 'admin' => 'dashboard/admin:rw' + ) + ); + + $this->load->library('AuthLib'); + $this->load->library('WidgetLib'); + + $this->_setAuthUID(); // sets property uid + + $this->setControllerId(); // sets the controller id + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + public function index() + { + $this->load->view('dashboard/dashboard_demo.php', []); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + public function admin() + { + $this->load->view('dashboard/dashboard_demo_admin.php', []); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Private methods + + /** + * 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'); + } +} diff --git a/application/controllers/dashboard/Widget.php b/application/controllers/dashboard/Widget.php new file mode 100644 index 000000000..0da6fe8da --- /dev/null +++ b/application/controllers/dashboard/Widget.php @@ -0,0 +1,109 @@ + ['dashboard/benutzer:r', 'dashboard/admin:r'], + 'getAll' => 'dashboard/admin:r', + 'getWidgetsForDashboard' => ['dashboard/benutzer:rw', 'dashboard/admin:r'], + 'setAllowed' => 'dashboard/admin:rw' + ) + ); + + $this->load->library('dashboard/DashboardLib', null, 'DashboardLib'); + $this->load->model('dashboard/Widget_model', 'WidgetModel'); + $this->load->model('dashboard/Dashboard_Widget_model', 'DashboardWidgetModel'); + } + + public function index() + { + $widget_id = $this->input->get('id'); + + $widget = $this->WidgetModel->load($widget_id); + + if (isError($widget) || !getData($widget)) + return $this->outputJsonSuccess([ + "widget_id" => 0, + "widget_kurzbz" => "notfound", + "arguments" => json_encode([ + "className" => 'alert-danger', + "title" => 'Widget Not Found', + "msg" => 'The widget with the id ' . $widget_id . ' could not be found' + ]), + "setup" => json_encode([ + "name" => 'Widget Not Found', + "file" => 'DashboardWidget/Default.js', + "width" => 1, + "height" => 1 + ]) + ]); + return $this->outputJsonSuccess(current(getData($widget))); + } + + public function getAll() + { + $dashboard_id = $this->input->get('dashboard_id'); + $result = $this->WidgetModel->getWithAllowedForDashboard($dashboard_id); + + if (isError($result)) + return $this->outputJsonError(getError($result)); + + $this->outputJsonSuccess(getData($result) ?: []); + } + + public function getWidgetsForDashboard() + { + $db = $this->input->get('db'); + $result = $this->WidgetModel->getForDashboard($db); + + if (isError($result)) { + http_response_code(404); + $this->terminateWithJsonError([ + 'error' => getError($result) + ]); + } + + $this->outputJsonSuccess(getData($result) ?: []); + } + + public function setAllowed() + { + $input = $this->getPostJSON(); + + $dashboard_id = $input->dashboard_id; + $widget_id = $input->widget_id; + $action = $input->action; + + if ($action == 'add') { + $result = $this->DashboardWidgetModel->insert([ + 'dashboard_id' => $dashboard_id, + 'widget_id' => $widget_id + ]); + } elseif ($action == 'delete') { + $result = $this->DashboardWidgetModel->delete([ + 'dashboard_id' => $dashboard_id, + 'widget_id' => $widget_id + ]); + } else { + http_response_code(404); // TODO(chris): 400? + $this->terminateWithJsonError([ + 'error' => 'action value invalid' + ]); + } + if (isError($result)) { + http_response_code(404); + $this->terminateWithJsonError([ + 'error' => getError($result) + ]); + } + return $this->outputJsonSuccess(getData($result)); + } +} diff --git a/application/controllers/jobs/AnrechnungJob.php b/application/controllers/jobs/AnrechnungJob.php index 7aae80d54..52bf972e3 100644 --- a/application/controllers/jobs/AnrechnungJob.php +++ b/application/controllers/jobs/AnrechnungJob.php @@ -37,6 +37,9 @@ class AnrechnungJob extends JOB_Controller $this->load->helper('hlp_sancho_helper'); $this->load->library('AnrechnungLib'); + + // Load configs + $this->load->config('anrechnung'); } /** @@ -192,10 +195,10 @@ class AnrechnungJob extends JOB_Controller $studiengang_bezeichnung = $this->StudiengangModel->load($studiengang_kz)->retval[0]->stg_bezeichnung; // Get STGL mail address - $stglMailReceiver_arr = self::_getSTGLMailAddress($studiengang_kz); + $stglMailReceiver_arr = $this->_getSTGLMailAddress($studiengang_kz); // Get HTML table with new Anrechnungen of that STG plus amount of them - list ($anrechnungen_amount, $anrechnungen_table) = self::_getSTGLMailDataTable($studiengang_kz, $anrechnungen); + list ($anrechnungen_amount, $anrechnungen_table) = $this->_getSTGLMailDataTable($studiengang_kz, $anrechnungen); // Link to Antrag genehmigen dashboard $url = @@ -213,7 +216,7 @@ class AnrechnungJob extends JOB_Controller 'datentabelle' => $anrechnungen_table, 'link' => anchor($url, 'Anrechnungsanträge Übersicht') ); - + // Send mail sendSanchoMail( 'AnrechnungAntragStellen', @@ -227,6 +230,82 @@ class AnrechnungJob extends JOB_Controller $this->logInfo('SUCCEDED: Sending emails to STGL about yesterdays new Anrechnungen succeded.'); } + // Send Sancho mail to LV-Leitung (fallback Lectors) that were requested for recommendation yesterday. + public function sendMailRecommendationRequests(){ + + $this->logInfo('Start AnrechnungJob sendMailRecommendationRequests to inform lecturers about yesterdays requests for recommendation.'); + + // Get Anrechnungen, für die gestern eine Empfehlung angefragt worden ist + $this->AnrechnungModel->addSelect('astat.anrechnung_id, astat.datum, astat.insertamum'); + $this->AnrechnungModel->addDistinct('astat.anrechnung_id'); + $this->AnrechnungModel->addJoin('lehre.tbl_anrechnung_anrechnungstatus astat', 'anrechnung_id'); + + $result = $this->AnrechnungModel->loadWhere(' + studiensemester_kurzbz = (SELECT studiensemester_kurzbz FROM tbl_studiensemester WHERE now()::date BETWEEN start AND ende) + AND genehmigt_von IS NULL + AND empfehlung_anrechnung IS NULL + AND status_kurzbz = '. $this->db->escape(self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR) .' -- in Bearbeitung durch Lektor + AND NOW()::date = (astat.datum + interval \'1 day\') -- nur gestrige Empfehlungsanfrage + ORDER BY astat.anrechnung_id, astat.datum DESC, astat.insertamum DESC -- nur letzten status dabei prüfen + '); + + // Exit, wenn es gestern keine Empfehlungsanfragen gab + if (!hasData($result)) + { + $this->logInfo('End AnrechnungJob sendMailRecommendationRequests, because no recommendations were requested yesterday.'); + exit; + } + + $anrechnung_id_arr = array_column(getData($result), 'anrechnung_id'); + + $arr_lvLector_arr = array(); + foreach ($anrechnung_id_arr as $anrechnung_id) + { + // Get full name of Fachbereichsleitung or LV Leitung. + if($this->config->item('fbl') === TRUE) + { + $arr_lvLector_arr[] = $this->anrechnunglib->getLeitungOfLvOe($anrechnung_id); + } + else + { + $arr_lvLector_arr[] = $this->anrechnunglib->getLectors($anrechnung_id); // Returns LV Leitung. If not present, then all lectors of LV. + } + } + + // Unique lector array to send only one mail per lector + $arr_lvLector_arr = array_unique($arr_lvLector_arr, SORT_REGULAR); + + // Link to 'Anrechnungen prüfen' dashboard + $url = + CIS_ROOT. 'cis/index.php?menu='. + CIS_ROOT. 'cis/menu.php?content_id=&content='. + CIS_ROOT. index_page(). self::REVIEW_ANRECHNUNG_URI; + + foreach ($arr_lvLector_arr as $lvLector_arr) + { + foreach ($lvLector_arr as $lector) + { + // Prepare mail content + $fields = array( + 'vorname' => $lector->vorname, + 'stgl_name' => 'Die Studiengangsleitung', + 'link' => anchor($url, 'Anrechnungsanträge Übersicht') + ); + + // Send mail + sendSanchoMail( + 'AnrechnungEmpfehlungAnfordern', + $fields, + $lector->uid. '@'. DOMAIN, + 'Deine Empfehlung wird benötigt zur Anerkennung nachgewiesener Kenntnisse' + ); + } + } + + $this->logInfo('SUCCEDED AnrechnungJob sendMailRecommendationRequests'); + + } + /** * Send Sancho mail to students, whose Anrechnungen were approved 24 hours ago. */ @@ -308,7 +387,7 @@ class AnrechnungJob extends JOB_Controller $db = new DB_Model(); $result = $db->execReadOnlyQuery($qry); - + // Exit if there are no rejected Anrechnungen if (!hasData($result)) { @@ -361,9 +440,9 @@ html; $result = $this->AnrechnungModel->loadWhere(' studiensemester_kurzbz = ( - SELECT studiensemester_kurzbz FROM tbl_studiensemester WHERE now()::date BETWEEN start AND ende) + SELECT studiensemester_kurzbz FROM tbl_studiensemester WHERE now()::date BETWEEN start AND ende ) - AND genehmigt_von IS NULL + AND genehmigt_von IS NULL AND empfehlung_anrechnung IS NULL AND status_kurzbz = '. $this->db->escape(self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR) .' -- in Bearbeitung durch Lektor AND NOW()::date = (astat.datum + interval \'1 week\') -- eine Woche nach Empfehlungsanfrage @@ -376,7 +455,7 @@ html; $this->logInfo('End AnrechnungJob sendMailRemindRecommendation, because no recommendations to be done.'); exit; } - + $anrechnung_id_arr = array_column(getData($result), 'anrechnung_id'); $arr_lvLector_arr = array(); @@ -435,8 +514,6 @@ html; 'vorname' => $stgl->vorname ); } - - return $stglMailAdress_arr; } // If not available, get assistance mail address else @@ -445,12 +522,13 @@ html; if (hasData($result)) { - return array( - $result->retval[0]->email, - '' + $stglMailAdress_arr[]= array( + 'to' => $result->retval[0]->email, + 'vorname' => '' ); } } + return $stglMailAdress_arr; } // Build HTML table with yesterdays new Anrechnungen of the given STG diff --git a/application/controllers/jobs/AntragJob.php b/application/controllers/jobs/AntragJob.php new file mode 100644 index 000000000..11b950174 --- /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', + '', + '', + '', + $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 17c4cb9ce..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', @@ -22,7 +22,39 @@ class IssueResolver extends IssueResolver_Controller 'CORE_INOUT_0003' => 'CORE_INOUT_0003', 'CORE_INOUT_0004' => 'CORE_INOUT_0004', 'CORE_INOUT_0005' => 'CORE_INOUT_0005', - 'CORE_INOUT_0006' => 'CORE_INOUT_0006' + 'CORE_INOUT_0006' => 'CORE_INOUT_0006', + 'CORE_INOUT_0007' => 'CORE_INOUT_0007', + 'CORE_INOUT_0008' => 'CORE_INOUT_0008', + 'CORE_INOUT_0009' => 'CORE_INOUT_0009', + 'CORE_STG_0001' => 'CORE_STG_0001', + 'CORE_STG_0002' => 'CORE_STG_0002', + 'CORE_STG_0003' => 'CORE_STG_0003', + 'CORE_STG_0004' => 'CORE_STG_0004', + 'CORE_STUDENTSTATUS_0002' => 'CORE_STUDENTSTATUS_0002', + 'CORE_STUDENTSTATUS_0003' => 'CORE_STUDENTSTATUS_0003', + 'CORE_STUDENTSTATUS_0004' => 'CORE_STUDENTSTATUS_0004', + 'CORE_STUDENTSTATUS_0005' => 'CORE_STUDENTSTATUS_0005', + 'CORE_STUDENTSTATUS_0006' => 'CORE_STUDENTSTATUS_0006', + 'CORE_STUDENTSTATUS_0007' => 'CORE_STUDENTSTATUS_0007', + 'CORE_STUDENTSTATUS_0008' => 'CORE_STUDENTSTATUS_0008', + 'CORE_STUDENTSTATUS_0009' => 'CORE_STUDENTSTATUS_0009', + 'CORE_STUDENTSTATUS_0010' => 'CORE_STUDENTSTATUS_0010', + 'CORE_STUDENTSTATUS_0011' => 'CORE_STUDENTSTATUS_0011', + 'CORE_STUDENTSTATUS_0012' => 'CORE_STUDENTSTATUS_0012', + '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/PlausiIssueProducer.php b/application/controllers/jobs/PlausiIssueProducer.php new file mode 100644 index 000000000..b667e835d --- /dev/null +++ b/application/controllers/jobs/PlausiIssueProducer.php @@ -0,0 +1,42 @@ +load->library('issues/PlausicheckDefinitionLib'); + + // load models + $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); + + // get current Studiensemester + $studiensemesterRes = $this->StudiensemesterModel->getAkt(); + if (hasData($studiensemesterRes)) $this->_currentStudiensemester = getData($studiensemesterRes)[0]->studiensemester_kurzbz; + + // set fehler which can be produced by the job + // structure: fehler_kurzbz => class (library) name for resolving + $this->_fehlerLibMappings = $this->plausicheckdefinitionlib->getFehlerLibMappings(); + } + + /** + * Runs issue production job. + * @param studiensemester_kurzbz string job is run for students of a certain semester. + * @param studiengang_kz int job is run for students of certain Studiengang. + */ + public function run($studiensemester_kurzbz = null, $studiengang_kz = null) + { + // get Studiensemester + if (isEmptyString($studiensemester_kurzbz)) $studiensemester_kurzbz = $this->_currentStudiensemester; + + // producing issues for semester and optionally Studiengang + $this->producePlausicheckIssues(array('studiensemester_kurzbz' => $studiensemester_kurzbz, 'studiengang_kz' => $studiengang_kz)); + } +} diff --git a/application/controllers/jobs/ReihungstestJob.php b/application/controllers/jobs/ReihungstestJob.php index ab6c429a0..9b2532b4b 100644 --- a/application/controllers/jobs/ReihungstestJob.php +++ b/application/controllers/jobs/ReihungstestJob.php @@ -3,6 +3,9 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); class ReihungstestJob extends JOB_Controller { + + const LAST_DAYS_PRESTUDENTSTATUS = 5; + /** * Constructor */ @@ -428,8 +431,8 @@ class ReihungstestJob extends JOB_Controller $mailcontent_data_arr, $applicant->email, 'Ihre Anmeldung zum Reihungstest - Reminder / Your registration for the placement test - Reminder', - DEFAULT_SANCHO_HEADER_IMG, - DEFAULT_SANCHO_FOOTER_IMG, + '', + '', $from, '', $bcc); @@ -464,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 '); @@ -727,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); @@ -763,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)) { @@ -826,7 +825,7 @@ class ReihungstestJob extends JOB_Controller AND tbl_studiengang.typ IN ('b', 'm') ) SELECT * FROM prst - WHERE prestudenstatus_datum >= (SELECT CURRENT_DATE - 1) + WHERE prestudenstatus_datum >= (SELECT CURRENT_DATE - ". self::LAST_DAYS_PRESTUDENTSTATUS .") AND (studiengang_typ = 'b' OR (studiengang_typ = 'm' AND EXISTS (SELECT 1 /* Master Studiengänge berücksichtigen wenn auch Bachelor im gleichen Semester */ FROM prst prstb WHERE studiengang_typ = 'b' @@ -868,7 +867,8 @@ class ReihungstestJob extends JOB_Controller tbl_person.nachname, tbl_person.vorname, tbl_prestudent.*, - tbl_studiengang.typ AS studiengang_typ + tbl_studiengang.typ AS studiengang_typ, + tbl_prestudentstatus.datum FROM PUBLIC.tbl_person JOIN PUBLIC.tbl_prestudent USING (person_id) JOIN PUBLIC.tbl_prestudentstatus USING (prestudent_id) @@ -876,7 +876,7 @@ class ReihungstestJob extends JOB_Controller JOIN PUBLIC.tbl_studiengang ON (tbl_prestudent.studiengang_kz = tbl_studiengang.studiengang_kz) WHERE tbl_prestudent.person_id = ".$row_ps->person_id." AND tbl_prestudent.prestudent_id != ".$row_ps->prestudent_id." - AND get_rolle_prestudent (tbl_prestudent.prestudent_id, '".$row_ps->studiensemester_kurzbz."') IN ('Aufgenommener','Bewerber','Wartender') + AND get_rolle_prestudent (tbl_prestudent.prestudent_id, '".$row_ps->studiensemester_kurzbz."') IN ('Aufgenommener','Bewerber','Wartender', 'Student') AND studiensemester_kurzbz = '".$row_ps->studiensemester_kurzbz."' AND tbl_studiengang.typ IN ('b', 'm') AND priorisierung > ".$row_ps->priorisierung." @@ -894,14 +894,24 @@ class ReihungstestJob extends JOB_Controller { foreach ($resultNiedrPrios->retval as $rowNiedrPrios) { - // nur Info wenn aufgenommen oder master - if ($rowNiedrPrios->laststatus == 'Aufgenommener' || $rowNiedrPrios->studiengang_typ == 'm') + // nur Info wenn aufgenommen/student oder master + if ($rowNiedrPrios->laststatus == 'Aufgenommener' || $rowNiedrPrios->laststatus == 'Student' || $rowNiedrPrios->studiengang_typ == 'm') { - // Mail zur Info an Assistenz schicken, dass in höherer Prio aufgenommen wurde - $mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['AufnahmeHoeherePrio'][] - = $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')'; + + if ($rowNiedrPrios->laststatus == 'Aufgenommener') + { + // Mail zur Info an Assistenz schicken, dass in höherer Prio aufgenommen wurde + $mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['AufnahmeHoeherePrio'][] + = $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')'; + } + else if ($rowNiedrPrios->laststatus == 'Student') + { + $mailArray[$rowNiedrPrios->studiengang_kz][$rowNiedrPrios->orgform_kurzbz]['StudentHoeherePrio'][] + = $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')'; + } + } - elseif ($rowNiedrPrios->laststatus == 'Bewerber') + elseif ($rowNiedrPrios->laststatus == 'Bewerber' && $row_ps->prestudenstatus_datum > $rowNiedrPrios->datum) { // Abgewiesenen-Status mit Statusgrund "Aufnahme anderer Studiengang" (ID 5) setzen $lastStatus = $this->PrestudentstatusModel->getLastStatus($rowNiedrPrios->prestudent_id); @@ -927,7 +937,7 @@ class ReihungstestJob extends JOB_Controller = $rowNiedrPrios->nachname.' '.$rowNiedrPrios->vorname.' ('.$rowNiedrPrios->prestudent_id.')'; } } - elseif ($rowNiedrPrios->laststatus == 'Wartender') + elseif ($rowNiedrPrios->laststatus == 'Wartender' && $row_ps->prestudenstatus_datum > $rowNiedrPrios->datum) { // Abgewiesenen-Status mit Statusgrund "Aufnahme anderer Studiengang" (ID 5) setzen // Mail zur Info an Assistenz schicken @@ -1023,7 +1033,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 @@ -1044,6 +1054,7 @@ class ReihungstestJob extends JOB_Controller $mailcontent .= ''.$bewerber.''; } $mailcontent .= '

'; + $content = true; } if (isset($value['AufnahmeHoeherePrio']) && !isEmptyArray($value['AufnahmeHoeherePrio'])) { @@ -1058,6 +1069,21 @@ class ReihungstestJob extends JOB_Controller $mailcontent .= ''.$bewerber.''; } $mailcontent .= ''; + $content = true; + } + if (isset($value['StudentHoeherePrio']) && !isEmptyArray($value['StudentHoeherePrio'])) + { + $mailcontent .= '

+ Folgende Studenten wurden in einem höher priorisierten Studiengang aufgenommen:

'; + $mailcontent .= ''; + $mailcontent .= ' '; + sort($value['StudentHoeherePrio']); + foreach ($value['StudentHoeherePrio'] AS $key=>$bewerber) + { + $mailcontent .= ''; + } + $mailcontent .= '
'.$bewerber.'
'; + $content = true; } if (isset($value['AbgewiesenHoeherePrio']) && !isEmptyArray($value['AbgewiesenHoeherePrio'])) { @@ -1071,6 +1097,7 @@ class ReihungstestJob extends JOB_Controller $mailcontent .= ''.$bewerber.''; } $mailcontent .= ''; + $content = true; } if ($bcc != '' && isset($value['AbgewiesenWeilBewerber']) && !isEmptyArray($value['AbgewiesenWeilBewerber'])) { @@ -1085,13 +1112,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/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/Pruefungsprotokoll.php b/application/controllers/lehre/Pruefungsprotokoll.php index 21f50acca..4d34b08ca 100644 --- a/application/controllers/lehre/Pruefungsprotokoll.php +++ b/application/controllers/lehre/Pruefungsprotokoll.php @@ -6,58 +6,59 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class Pruefungsprotokoll extends Auth_Controller { - private $_uid; // uid of the logged user + private $_uid; // uid of the logged user - /** - * Constructor - */ - public function __construct() - { - // Set required permissions - parent::__construct( - array( - 'index' => 'lehre/pruefungsbeurteilung:r', - 'Protokoll' => 'lehre/pruefungsbeurteilung:r', - 'saveProtokoll' => 'lehre/pruefungsbeurteilung:rw', - ) - ); + /** + * Constructor + */ + public function __construct() + { + // Set required permissions + parent::__construct( + array( + 'index' => 'lehre/pruefungsbeurteilung:r', + 'Protokoll' => 'lehre/pruefungsbeurteilung:r', + 'showProtokoll' => 'lehre/pruefungsbeurteilung:r', + 'saveProtokoll' => 'lehre/pruefungsbeurteilung:rw', + ) + ); - // Load models - $this->load->model('education/Abschlusspruefung_model', 'AbschlusspruefungModel'); - $this->load->model('education/Abschlussbeurteilung_model', 'AbschlussbeurteilungModel'); + // Load models + $this->load->model('education/Abschlusspruefung_model', 'AbschlusspruefungModel'); + $this->load->model('education/Abschlussbeurteilung_model', 'AbschlussbeurteilungModel'); - $this->load->library('PermissionLib'); - $this->load->library('AuthLib'); + $this->load->library('PermissionLib'); + $this->load->library('AuthLib'); - // Load language phrases - $this->loadPhrases( - array( - 'ui', - 'global', - 'person', - 'abschlusspruefung', + // Load language phrases + $this->loadPhrases( + array( + 'ui', + 'global', + 'person', + 'abschlusspruefung', 'password', 'lehre' - ) - ); + ) + ); - $this->_setAuthUID(); // sets property uid + $this->_setAuthUID(); // sets property uid - $this->setControllerId(); // sets the controller id - } + $this->setControllerId(); // sets the controller id + } - // ----------------------------------------------------------------------------------------------------------------- - // Public methods + // ----------------------------------------------------------------------------------------------------------------- + // Public methods public function index() { $this->load->library('WidgetLib'); - + // Protokolle anzeigen seit heute / letzte Woche / alle $period = $this->input->post('period'); $period = (!is_null($period)) ? $period : 'today'; - + $data = array('period' => $period); - + $this->load->view('lehre/pruefungsprotokollUebersicht.php', $data); } @@ -66,47 +67,15 @@ class Pruefungsprotokoll extends Auth_Controller */ public function Protokoll() { - $abschlusspruefung_id = $this->input->get('abschlusspruefung_id'); + $this->load->view('lehre/pruefungsprotokoll.php', $this->_getPruefungsprotokollData()); + } - if (!is_numeric($abschlusspruefung_id)) - show_error('invalid abschlusspruefung'); - - $abschlusspruefung_saved = false; - $abschlusspruefung = $this->_getAbschlusspruefungBerechtigt($abschlusspruefung_id); - - if (isError($abschlusspruefung)) - show_error(getError($abschlusspruefung)); - else - { - $abschlusspruefung = getData($abschlusspruefung); - $abschlusspruefung_saved = isset($abschlusspruefung->protokoll) && isset($abschlusspruefung->abschlussbeurteilung_kurzbz); - } - - $this->AbschlussbeurteilungModel->addOrder("sort", "ASC"); - $this->AbschlussbeurteilungModel->addOrder("(CASE WHEN abschlussbeurteilung_kurzbz = 'ausgezeichnet' THEN 1 - WHEN abschlussbeurteilung_kurzbz = 'gut' THEN 2 - WHEN abschlussbeurteilung_kurzbz = 'bestanden' THEN 3 - WHEN abschlussbeurteilung_kurzbz = 'angerechnet' THEN 4 - ELSE 5 - END - )"); - $abschlussbeurteilung = $this->AbschlussbeurteilungModel->load(); - - if (isError($abschlussbeurteilung)) - show_error(getError($abschlussbeurteilung)); - else - $abschlussbeurteilung = getData($abschlussbeurteilung); - - $language = getUserLanguage(); - - $data = array( - 'abschlusspruefung' => $abschlusspruefung, - 'abschlussbeurteilung' => $abschlussbeurteilung, - 'abschlusspruefung_saved' => $abschlusspruefung_saved, - 'language' => $language - ); - - $this->load->view('lehre/pruefungsprotokoll.php', $data); + /** + * Show Pruefungsprotokoll. + */ + public function showProtokoll() + { + $this->load->view('lehre/pruefungsprotokoll.php', array_merge($this->_getPruefungsprotokollData(), array('readonly' => true))); } /** @@ -168,18 +137,66 @@ class Pruefungsprotokoll extends Auth_Controller $this->outputJsonError($this->p->t('ui', 'ungueltigeParameter')); } - // ----------------------------------------------------------------------------------------------------------------- - // Private methods + // ----------------------------------------------------------------------------------------------------------------- + // Private methods - /** - * Retrieve the UID of the logged user and checks if it is valid - */ - private function _setAuthUID() - { - $this->_uid = getAuthUID(); + /** + * 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'); - } + if (!$this->_uid) show_error('User authentification failed'); + } + + /** + * + * @param + * @return object success or error + */ + private function _getPruefungsprotokollData() + { + $abschlusspruefung_id = $this->input->get('abschlusspruefung_id'); + + if (!is_numeric($abschlusspruefung_id)) + show_error('invalid abschlusspruefung'); + + $abschlusspruefung_saved = false; + $abschlusspruefung = $this->_getAbschlusspruefungBerechtigt($abschlusspruefung_id); + + if (isError($abschlusspruefung)) + show_error(getError($abschlusspruefung)); + else + { + $abschlusspruefung = getData($abschlusspruefung); + $abschlusspruefung_saved = isset($abschlusspruefung->protokoll) && isset($abschlusspruefung->abschlussbeurteilung_kurzbz); + } + + $this->AbschlussbeurteilungModel->addOrder("sort", "ASC"); + $this->AbschlussbeurteilungModel->addOrder("(CASE WHEN abschlussbeurteilung_kurzbz = 'ausgezeichnet' THEN 1 + WHEN abschlussbeurteilung_kurzbz = 'gut' THEN 2 + WHEN abschlussbeurteilung_kurzbz = 'bestanden' THEN 3 + WHEN abschlussbeurteilung_kurzbz = 'angerechnet' THEN 4 + ELSE 5 + END + )"); + $abschlussbeurteilung = $this->AbschlussbeurteilungModel->load(); + + if (isError($abschlussbeurteilung)) + show_error(getError($abschlussbeurteilung)); + else + $abschlussbeurteilung = getData($abschlussbeurteilung); + + $language = getUserLanguage(); + + return array( + 'abschlusspruefung' => $abschlusspruefung, + 'abschlussbeurteilung' => $abschlussbeurteilung, + 'abschlusspruefung_saved' => $abschlusspruefung_saved, + 'language' => $language + ); + } /** * Retrieves an Abschlussprüfung, with permission check @@ -187,7 +204,7 @@ class Pruefungsprotokoll extends Auth_Controller * @param $abschlusspruefung_id * @return object success or error */ - private function _getAbschlusspruefungBerechtigt($abschlusspruefung_id) + private function _getAbschlusspruefungBerechtigt($abschlusspruefung_id) { $result = error('Error when getting Abschlusspruefung'); 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/AdminAnrechnung.php b/application/controllers/lehre/anrechnung/AdminAnrechnung.php new file mode 100644 index 000000000..3c3fd3fc2 --- /dev/null +++ b/application/controllers/lehre/anrechnung/AdminAnrechnung.php @@ -0,0 +1,187 @@ + 'lehre/anrechnungszeitfenster:rw', + 'save' => 'lehre/anrechnungszeitfenster:rw', + 'edit' => 'lehre/anrechnungszeitfenster:rw', + 'delete' => 'lehre/anrechnungszeitfenster:rw' + ) + ); + + // Load models + $this->load->model('education/Anrechnung_model', 'AnrechnungModel'); + $this->load->model('education/Anrechnungszeitraum_model', 'AnrechnungszeitraumModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + // Load libraries + $this->load->library('WidgetLib'); + $this->load->library('PermissionLib'); + $this->load->library('AnrechnungLib'); + + + // Load language phrases + $this->loadPhrases( + array( + 'global', + 'ui', + 'lehre', + 'anrechnung', + 'table' + ) + ); + + $this->_setAuthUID(); + + $this->setControllerId(); + } + + public function index() + { + // Set nearest Studiensemester as default + $result = $this->StudiensemesterModel->getNearest(); + $studiensemester_kurzbz = hasData($result) ? getData($result)[0]->studiensemester_kurzbz : ''; + + // Get existing Anrechnungszeitraeume + $this->AnrechnungszeitraumModel->addOrder('anrechnungszeitraum_id', 'DESC'); + $result = $this->AnrechnungszeitraumModel->load(); + $anrechnungszeitraum_arr = hasData($result) ? getData($result) : array(); + + $viewData = array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'anrechnungszeitraum_arr' => $anrechnungszeitraum_arr + ); + + $this->load->view('lehre/anrechnung/adminAnrechnung.php', $viewData); + } + + /** + * Save new Anrechnungszeitraum. + */ + public function save() + { + $this->_validate($this->input->post()); + + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $anrechnungstart = $this->input->post('anrechnungstart'); + $anrechnungende = $this->input->post('anrechnungende'); + + $result = $this->AnrechnungszeitraumModel->insertAzr($studiensemester_kurzbz, $anrechnungstart, $anrechnungende); + + if (isError($result)) + { + $this->terminateWithJsonError(getError($result)); + } + + if (hasData($result)) + { + $this->outputJsonSuccess(array('anrechnungszeitraum_id' => getData($result))); + } + } + + /** + * Edit Anrechnungszeitraum. + */ + public function edit() + { + $this->_validate($this->input->post()); + + $anrechnungszeitraum_id = $this->input->post('anrechnungszeitraum_id'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $anrechnungstart = $this->input->post('anrechnungstart'); + $anrechnungende = $this->input->post('anrechnungende'); + + $result = $this->AnrechnungszeitraumModel->updateAzr( + $anrechnungszeitraum_id, + $studiensemester_kurzbz, + $anrechnungstart, + $anrechnungende + ); + + if (isError($result)) + { + $this->terminateWithJsonError(getError($result)); + } + + if (hasData($result)) + { + $this->outputJsonSuccess(array('anrechnungszeitraum_id' => getData($result))); + } + } + + /** + * Delete Anrechnungszeitraum. + */ + public function delete() + { + $anrechnungszeitraum_id = $this->input->post('anrechnungszeitraum_id'); + + $result = $this->AnrechnungszeitraumModel->deleteAzr($anrechnungszeitraum_id); + + if (isError($result)) + { + $this->terminateWithJsonError(getError($result)); + } + + if (hasData($result)) + { + $this->outputJsonSuccess(array('anrechnungszeitraum_id' => getData($result))); + } + } + + /** + * Validates post parameters. + * + * @param $post + */ + private function _validate($post) + { + $studiensemester_kurzbz = $post['studiensemester_kurzbz']; + $anrechnungstart = $post['anrechnungstart']; + $anrechnungende = $post['anrechnungende']; + + if (isEmptyString($studiensemester_kurzbz) + || isEmptyString($anrechnungstart) + || isEmptyString($anrechnungende)) + { + $this->terminateWithJsonError($this->p->t('ui', 'errorFelderFehlen')); + } + + if ($anrechnungstart > $anrechnungende) + { + $this->terminateWithJsonError($this->p->t('ui', 'errorStartdatumNachEndedatum')); + } + + $result = $this->StudiensemesterModel->load($studiensemester_kurzbz); + $studiensemester = getData($result)[0]; + + if ($anrechnungstart < $studiensemester->start || $anrechnungstart > $studiensemester->ende) + { + $this->terminateWithJsonError($this->p->t('ui', 'errorStartdatumNichtInStudiensemester')); + } + + if ($anrechnungende < $studiensemester->start || $anrechnungende > $studiensemester->ende) + { + $this->terminateWithJsonError($this->p->t('ui', 'errorEndedatumNichtInStudiensemester')); + } + + + } + + /** + * 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/lehre/anrechnung/ApproveAnrechnungDetail.php b/application/controllers/lehre/anrechnung/ApproveAnrechnungDetail.php index 1f5c853db..3a62ff7d9 100644 --- a/application/controllers/lehre/anrechnung/ApproveAnrechnungDetail.php +++ b/application/controllers/lehre/anrechnung/ApproveAnrechnungDetail.php @@ -33,6 +33,9 @@ class approveAnrechnungDetail extends Auth_Controller ) ); + //Load configs + $this->load->config('anrechnung'); + // Load models $this->load->model('education/Anrechnung_model', 'AnrechnungModel'); $this->load->model('education/Anrechnungstatus_model', 'AnrechnungstatusModel'); @@ -90,7 +93,8 @@ class approveAnrechnungDetail extends Auth_Controller $antragData = $this->anrechnunglib->getAntragData( $anrechnungData->prestudent_id, $anrechnungData->studiensemester_kurzbz, - $anrechnungData->lehrveranstaltung_id + $anrechnungData->lehrveranstaltung_id, + $anrechnungData->anrechnung_id ); // Get Empfehlung data @@ -209,71 +213,64 @@ class approveAnrechnungDetail extends Auth_Controller */ public function requestRecommendation() { - $data = $this->input->post('data'); + $anrechnung_id = $this->input->post('anrechnung_id'); - if(isEmptyArray($data)) + if(isEmptyString($anrechnung_id)) { return $this->outputJsonError('Fehler beim Übertragen der Daten.'); } $retval = array(); - $counter = 0; + + // Check if Anrechnungs-LV has lector + if (!$this->anrechnunglib->LVhasLector($anrechnung_id)) + { + $this->terminateWithJsonError('LV has no lector'); + } - foreach ($data as $item) - { - // Check if Anrechnungs-LV has lector - if (!$this->anrechnunglib->LVhasLector($item['anrechnung_id'])) - { - // Count up LV with no lector - $counter++; + // Get Fachbereichsleitung or LV Leitung. + if($this->config->item('fbl') === TRUE) + { + $result = $this->anrechnunglib->getLeitungOfLvOe($anrechnung_id); + } + else + { + // If LV Leitung is not present, gets all LV lectors. + $result = $this->anrechnunglib->getLectors($anrechnung_id); + } - // Break, if LV has no lector - break; - } + $empfehlungsanfrage_an = !isEmptyArray($result) ? implode(', ', array_column($result, 'fullname')) : ''; - // Get full name of LV Leitung. - // If LV Leitung is not present, get full name of LV lectors. - $lector_arr = $this->anrechnunglib->getLectors($item['anrechnung_id']); - $empfehlungsanfrage_an = !isEmptyArray($lector_arr) - ? implode(', ', array_column($lector_arr, 'fullname')) - : ''; - - // Request Recommendation - if($this->anrechnunglib->requestRecommendation($item['anrechnung_id'])) - { - $retval[]= array( - 'anrechnung_id' => $item['anrechnung_id'], - 'status_kurzbz' => self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR, - 'status_bezeichnung' => $this->anrechnunglib->getStatusbezeichnung(self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR), - 'empfehlung_anrechnung' => null, - 'empfehlungsanfrageAm' => (new DateTime())->format('d.m.Y'), - 'empfehlungsanfrageAn' => $empfehlungsanfrage_an - ); - } - } - - /** - * Send mails to lectors - * NOTE: mails are sent at the end to ensure sending only ONE mail to each LV-Leitung or lector - * even if they are required for more recommendations - * */ - if (!isEmptyArray($retval)) - { - self::_sendSanchoMailToLectors($retval); - - // Output json to ajax - return $this->outputJsonSuccess($retval); - } + // Request Recommendation + if ($this->anrechnunglib->requestRecommendation($anrechnung_id)) + { + $retval[]= array( + 'anrechnung_id' => $anrechnung_id, + 'status_kurzbz' => self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR, + 'status_bezeichnung' => $this->anrechnunglib->getStatusbezeichnung(self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR), + 'empfehlung_anrechnung' => null, + 'empfehlungsanfrageAm' => (new DateTime())->format('d.m.Y'), + 'empfehlungsanfrageAn' => $empfehlungsanfrage_an + ); + } // Output json to ajax - if (isEmptyArray($retval) && $counter > 0) - { - return $this->outputJsonError( - "Empfehlung wurde nicht angefordert,\nDer LV sind keine LektorInnen zugeteilt." - ); - } + if ($empfehlungsanfrage_an == '') + { + $this->terminateWithJsonError( + "Empfehlung wurde nicht angefordert,\nDer LV sind keine LektorInnen zugeteilt." + ); + } - return $this->outputJsonError($this->p->t('ui', 'errorNichtAusgefuehrt')); + if (isEmptyArray($retval)) + { + $this->terminateWithJsonError("Empfehlung wurde nicht angefordert"); + } + else + { + // Output json to ajax + return $this->outputJsonSuccess($retval); + } } /** @@ -467,39 +464,33 @@ class approveAnrechnungDetail extends Auth_Controller /** * Send mail to lectors asking for recommendation. (first to LV-Leitung, if not present to all lectors of lv) - * @param $mail_params + * @param $anrechnung_id * @return bool */ - private function _sendSanchoMailToLectors($mail_params) + private function _sendSanchoMailToLectors($anrechnung_id) { - // Get Lehrveranstaltungen - $anrechnung_arr = array(); - - foreach ($mail_params as $item) - { - $this->AnrechnungModel->addSelect('lehrveranstaltung_id, studiensemester_kurzbz'); - $anrechnung_arr[]= array( - 'lehrveranstaltung_id' => $this->AnrechnungModel->load($item['anrechnung_id'])->retval[0]->lehrveranstaltung_id, - 'studiensemester_kurzbz' => $this->AnrechnungModel->load($item['anrechnung_id'])->retval[0]->studiensemester_kurzbz - ); - } - - $anrechnung_arr = array_unique($anrechnung_arr, SORT_REGULAR); - + $lehrveranstaltung_id = $this->AnrechnungModel->load($anrechnung_id)->retval[0]->lehrveranstaltung_id; + $studiensemester_kurzbz = $this->AnrechnungModel->load($anrechnung_id)->retval[0]->studiensemester_kurzbz; /** - * Get lectors (prio for LV-Leitung, if not present to all lectors of LV. + * Get mail receivers. + * If config is default (lectors): prio for LV-Leitung, if not present to all lectors of LV. * Anyway this function will receive a unique array to avoid sending more mails to one and the same lector. * **/ - $lector_arr = $this->_getLectors($anrechnung_arr); + if ($this->config->item('fbl') === TRUE) + { + $receiver_arr = $this->_getLeitungOfLvOe($lehrveranstaltung_id); + } + else + { + $receiver_arr = $this->_getLectors($studiensemester_kurzbz, $lehrveranstaltung_id); + } - - - // Send mail to lectors - foreach ($lector_arr as $lector) + // Send mail + foreach ($receiver_arr as $receiver) { - $to = $lector->uid; - $vorname = $lector->vorname; + $to = $receiver->uid. '@'. DOMAIN;; + $vorname = $receiver->vorname; // Get full name of stgl $this->load->model('person/Person_model', 'PersonModel'); @@ -537,35 +528,30 @@ class approveAnrechnungDetail extends Auth_Controller * @param $anrechnung_arr * @return array */ - private function _getLectors($anrechnung_arr) + private function _getLectors($studiensemester_kurzbz, $lehrveranstaltung_id) { $lector_arr = array(); - // Get lectors - foreach($anrechnung_arr as $anrechnung) - { - $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); - $result = $this->LehrveranstaltungModel->getLecturersByLv($anrechnung['studiensemester_kurzbz'], $anrechnung['lehrveranstaltung_id']); + $result = $this->LehrveranstaltungModel->getLecturersByLv($studiensemester_kurzbz, $lehrveranstaltung_id); - if (!$result = getData($result)) - { - show_error('Failed retrieving lectors of Lehrveranstaltung'); - } + if (!$result = getData($result)) + { + show_error('Failed retrieving lectors of Lehrveranstaltung'); + } - // Check if lv has LV-Leitung - $key = array_search(true, array_column($result, 'lvleiter')); + // Check if lv has LV-Leitung + $key = array_search(true, array_column($result, 'lvleiter')); - // If lv has LV-Leitung, keep only the one - if ($key !== false) - { - $lector_arr[]= $result[$key]; - } - // ...otherwise keep all lectors - else - { - $lector_arr = array_merge($lector_arr, $result); - } - } + // If lv has LV-Leitung, keep only the one + if ($key !== false) + { + $lector_arr[]= $result[$key]; + } + // ...otherwise keep all lectors + else + { + $lector_arr = array_merge($lector_arr, $result); + } /** * NOTE: This step is only done to make the array unique by uid, vorname and nachname in the following step @@ -584,6 +570,14 @@ class approveAnrechnungDetail extends Auth_Controller } + // Get Leitungen of Lehrveranstaltungs-Organisationseinheit + private function _getLeitungOfLvOe($lehrveranstaltung_id) + { + $result = $this->LehrveranstaltungModel->getLeitungOfLvOe($lehrveranstaltung_id); + + return hasData($result) ? getData($result) : show_error('Failed retrieving Leitung of Lehrveranstaltungs-Organisationseinheit'); + } + private function _saveEmpfehlungsNotiz($anrechnung_id, $empfehlungstext, $notiz_id) { $this->load->model('person/Notiz_model', 'NotizModel'); @@ -606,8 +600,5 @@ class approveAnrechnungDetail extends Auth_Controller trim($empfehlungstext), $this->_uid ); - - } - } diff --git a/application/controllers/lehre/anrechnung/ApproveAnrechnungUebersicht.php b/application/controllers/lehre/anrechnung/ApproveAnrechnungUebersicht.php index 9eb0c9734..b5a44b8f6 100644 --- a/application/controllers/lehre/anrechnung/ApproveAnrechnungUebersicht.php +++ b/application/controllers/lehre/anrechnung/ApproveAnrechnungUebersicht.php @@ -28,6 +28,9 @@ class approveAnrechnungUebersicht extends Auth_Controller ) ); + // Load configs + $this->load->config('anrechnung'); + // Load models $this->load->model('education/Anrechnung_model', 'AnrechnungModel'); $this->load->model('education/Anrechnungstatus_model', 'AnrechnungstatusModel'); @@ -78,6 +81,19 @@ class approveAnrechnungUebersicht extends Auth_Controller show_error(getError($studiengang_kz_arr)); } + // Get oes the user is entitled for + $oe_kurzbz_arr_schreibberechtigt = array(); + if ($oe_arr = $this->permissionlib->getOE_isEntitledFor(self::BERECHTIGUNG_ANRECHNUNG_GENEHMIGEN)) + { + foreach($oe_arr as $oe) + { + $berechtigt = $this->permissionlib->isBerechtigt(self::BERECHTIGUNG_ANRECHNUNG_GENEHMIGEN, 'suid', $oe); + + if ($berechtigt) $oe_kurzbz_arr_schreibberechtigt[]= $oe; + } + } + + // Check if permission is readonly $hasReadOnlyAccess = $this->permissionlib->isBerechtigt(self::BERECHTIGUNG_ANRECHNUNG_GENEHMIGEN, 's') && !$this->permissionlib->isBerechtigt(self::BERECHTIGUNG_ANRECHNUNG_GENEHMIGEN, 'suid'); @@ -87,9 +103,11 @@ class approveAnrechnungUebersicht extends Auth_Controller $viewData = array( 'studiensemester_selected' => $studiensemester_kurzbz, - 'studiengaenge_entitled' => $studiengang_kz_arr, + 'studiengaenge_entitled' => $studiengang_kz_arr, // alle STG mit Lese- und Schreibberechtigung + 'oes_schreibberechtigt' => $oe_kurzbz_arr_schreibberechtigt, // alle STG nur mit Schreibberechtigung 'hasReadOnlyAccess' => $hasReadOnlyAccess, - 'hasCreateAnrechnungAccess' => $hasCreateAnrechnungAccess + 'hasCreateAnrechnungAccess' => $hasCreateAnrechnungAccess, + 'configFachbereichsleitung' => $this->config->item('fbl') ); $this->load->view('lehre/anrechnung/approveAnrechnungUebersicht.php', $viewData); @@ -207,14 +225,20 @@ class approveAnrechnungUebersicht extends Auth_Controller // Request Recommendation if($this->anrechnunglib->requestRecommendation($item['anrechnung_id'])) { - // Get full name of LV Leitung. - // If LV Leitung is not present, get full name of LV lectors. - $lector_arr = $this->anrechnunglib->getLectors($item['anrechnung_id']); - $empfehlungsanfrage_an = !isEmptyArray($lector_arr) - ? implode(', ', array_column($lector_arr, 'fullname')) - : ''; + // Get full name of Fachbereichsleitung or LV Leitung. + if($this->config->item('fbl') === TRUE) + { + $result = $this->anrechnunglib->getLeitungOfLvOe($item['anrechnung_id']); + } + else + { + // If LV Leitung is not present, get full name of LV lectors. + $result = $this->anrechnunglib->getLectors($item['anrechnung_id']); + } - $retval[]= array( + $empfehlungsanfrage_an = !isEmptyArray($result) ? implode(', ', array_column($result, 'fullname')) : ''; + + $retval[]= array( 'anrechnung_id' => $item['anrechnung_id'], 'status_kurzbz' => self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR, 'status_bezeichnung' => $this->anrechnunglib->getStatusbezeichnung(self::ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR), @@ -225,23 +249,18 @@ class approveAnrechnungUebersicht extends Auth_Controller } } - /** - * Send mails to lectors - * NOTE: mails are sent at the end to ensure sending only ONE mail to each LV-Leitung or lector - * even if they are required for more recommendations - * */ - if (!isEmptyArray($retval)) - { - self::_sendSanchoMailToLectors($retval); - } - // Output json to ajax - if (isEmptyArray($retval) && $counter == 0) + if (isEmptyArray($retval)) { - return $this->outputJsonError('Es wurden keine Empfehlungen angefordert'); + if ($counter > 0) + { + $this->terminateWithJsonError('Bei '. $counter.' LV sind keine LektorInnen zugeteilt.'); + } + + $this->terminateWithJsonError('Es wurden keine Empfehlungen angefordert'); } - return $this->outputJsonSuccess($retval); + $this->outputJsonSuccess($retval); } /** @@ -316,7 +335,7 @@ class approveAnrechnungUebersicht extends Auth_Controller * @param $mail_params * @return bool */ - private function _sendSanchoMailToLectors($mail_params) + private function _sendSanchoMail($mail_params) { // Get Lehrveranstaltungen $anrechnung_arr = array(); @@ -332,18 +351,25 @@ class approveAnrechnungUebersicht extends Auth_Controller $anrechnung_arr = array_unique($anrechnung_arr, SORT_REGULAR); - - /** - * Get lectors (prio for LV-Leitung, if not present to all lectors of LV. - * Anyway this function will receive a unique array to avoid sending more mails to one and the same lector. - * **/ - $lector_arr = $this->_getLectors($anrechnung_arr); + /** + * Get mail receivers. + * If retrieving lectors: prio for LV-Leitung, if not present to all lectors of LV. + * This function will receive a unique array to avoid sending more mails to one and the same user. + **/ + if($this->config->item('fbl') === TRUE) + { + $receiver_arr = $this->_getLeitungOfLvOe($anrechnung_arr); + } + else + { + $receiver_arr = $this->_getLectors($anrechnung_arr); + } // Send mail to lectors - foreach ($lector_arr as $lector) + foreach ($receiver_arr as $receiver) { - $to = $lector->uid; - $vorname = $lector->vorname; + $to = $receiver->uid. '@'. DOMAIN; + $vorname = $receiver->vorname; // Get full name of stgl $this->load->model('person/Person_model', 'PersonModel'); @@ -427,4 +453,34 @@ class approveAnrechnungUebersicht extends Auth_Controller return $lector_arr; } + + /** + * Get Leitungen of Lehrveranstaltungs-Organisationseinheit with unique uids. + * + * @param $anrechnung_arr + * @return array + */ + private function _getLeitungOfLvOe($anrechnung_arr) + { + $oeLeitung_arr = array(); + + // Get Leitungen + foreach($anrechnung_arr as $anrechnung) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $result = $this->LehrveranstaltungModel->getLeitungOfLvOe($anrechnung['lehrveranstaltung_id']); + + if (!hasData($result)) + { + show_error('No Leitung found'); + } + + $oeLeitung_arr = array_merge($oeLeitung_arr, getData($result)); + } + + // Make array unique + $oeLeitung_arr = array_unique($oeLeitung_arr, SORT_REGULAR); + + return $oeLeitung_arr; + } } diff --git a/application/controllers/lehre/anrechnung/RequestAnrechnung.php b/application/controllers/lehre/anrechnung/RequestAnrechnung.php index fbaac9b3e..ebc272e3e 100644 --- a/application/controllers/lehre/anrechnung/RequestAnrechnung.php +++ b/application/controllers/lehre/anrechnung/RequestAnrechnung.php @@ -80,11 +80,7 @@ class requestAnrechnung extends Auth_Controller $prestudent_id = getData($result)[0]->prestudent_id; // Check if application deadline is expired - $is_expired = self::_isExpired( - $this->config->item('submit_application_start'), - $this->config->item('submit_application_end'), - $studiensemester_kurzbz - ); + $is_expired = $this->_isExpired($studiensemester_kurzbz); // Check if Lehrveranstaltung was already graded with application blocking grades $is_blocked = self::_LVhasBlockingGrades($studiensemester_kurzbz, $lehrveranstaltung_id); @@ -93,7 +89,7 @@ class requestAnrechnung extends Auth_Controller $anrechnungData = $this->anrechnunglib->getAnrechnungDataByLv($lehrveranstaltung_id, $studiensemester_kurzbz, $prestudent_id); // Get Antrag data - $antragData = $this->anrechnunglib->getAntragData($prestudent_id, $studiensemester_kurzbz, $lehrveranstaltung_id); + $antragData = $this->anrechnunglib->getAntragData($prestudent_id, $studiensemester_kurzbz, $lehrveranstaltung_id, $anrechnungData->anrechnung_id); $viewData = array( 'antragData' => $antragData, @@ -115,6 +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->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'])) @@ -125,7 +128,9 @@ class requestAnrechnung extends Auth_Controller if (isEmptyString($begruendung_id) || isEmptyString($anmerkung) || isEmptyString($lehrveranstaltung_id) || - isEmptyString($studiensemester_kurzbz)) + isEmptyString($studiensemester_kurzbz) || + ($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, @@ -176,7 +181,9 @@ class requestAnrechnung extends Auth_Controller $lehrveranstaltung_id, $begruendung_id, $lastInsert_dms_id, - $anmerkung + $anmerkung, + $begruendung_ects, + $begruendung_lvinhalt ); if (isError($result)) @@ -234,32 +241,30 @@ class requestAnrechnung extends Auth_Controller * @return bool True if deadline is expired * @throws Exception */ - private function _isExpired($start, $ende, $studiensemester_kurzbz) + private function _isExpired($studiensemester_kurzbz) { - $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $today = new DateTime('today midnight'); - // If start is not given, set to Semesterstart. - if (!isset($start) || isEmptyString($start)) - { - $this->StudiensemesterModel->addSelect('start'); - $result = $this->StudiensemesterModel->load($studiensemester_kurzbz); - $start = getData($result)[0]->start; - } + // Load all Anrechnungszeitfenster for this Studiensemester + $this->load->model('education/Anrechnungszeitraum_model', 'AnrechnungszeitraumModel'); + $result = $this->AnrechnungszeitraumModel->loadWhere(array('studiensemester_kurzbz' => $studiensemester_kurzbz)); - // If ende is not given, set to Semesterende. - if (!isset($ende) || isEmptyString($ende)) - { - $this->StudiensemesterModel->addSelect('ende'); - $result = $this->StudiensemesterModel->load($studiensemester_kurzbz); - $ende = getData($result)[0]->ende; - } + if (hasData($result)) + { + // Loop through Anrechnungszeitfenster + foreach (getData($result) as $azrObj) + { + $start = new DateTime($azrObj->anrechnungstart); + $ende = new DateTime($azrObj->anrechnungende); - $today = new DateTime('today midnight'); - $start = new DateTime($start); - $ende = new DateTime($ende); + // Return false if today is at least within one Anrechnungszeitraum + if (($today >= $start && $today <= $ende)) return false; - // True if expired - return ($today < $start || $today > $ende); + } + } + + // Return true if today is in none Anrechnungszeitraum + return true; } /** @@ -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/anrechnung/ReviewAnrechnungDetail.php b/application/controllers/lehre/anrechnung/ReviewAnrechnungDetail.php index 1bd92004d..d141a0635 100644 --- a/application/controllers/lehre/anrechnung/ReviewAnrechnungDetail.php +++ b/application/controllers/lehre/anrechnung/ReviewAnrechnungDetail.php @@ -28,6 +28,9 @@ class reviewAnrechnungDetail extends Auth_Controller ) ); + // Load configs + $this->load->config('anrechnung'); + // Load models $this->load->model('education/Anrechnung_model', 'AnrechnungModel'); $this->load->model('education/Anrechnungstatus_model', 'AnrechnungstatusModel'); @@ -84,16 +87,21 @@ class reviewAnrechnungDetail extends Auth_Controller $antragData = $this->anrechnunglib->getAntragData( $anrechnungData->prestudent_id, $anrechnungData->studiensemester_kurzbz, - $anrechnungData->lehrveranstaltung_id + $anrechnungData->lehrveranstaltung_id, + $anrechnungData->anrechnung_id ); // Get Empfehlung data $empfehlungData = $this->anrechnunglib->getEmpfehlungData($anrechnung_id); + // False if LV-Leitung is present and user is not LV-Leitung. Otherwise always true. + $isEmpfehlungsberechtigt = $this->anrechnunglib->isEmpfehlungsberechtigt($anrechnung_id); + $viewData = array( 'antragData' => $antragData, 'anrechnungData' => $anrechnungData, - 'empfehlungData' => $empfehlungData + 'empfehlungData' => $empfehlungData, + 'isEmpfehlungsberechtigt' => $isEmpfehlungsberechtigt ); $this->load->view('lehre/anrechnung/reviewAnrechnungDetail.php', $viewData); @@ -140,10 +148,13 @@ class reviewAnrechnungDetail extends Auth_Controller * Send mails to STGL (if not present STGL, send to STGL assistance) * NOTE: mails are sent at the end to ensure sending only one mail to each STGL * */ - if (!$this->_sendSanchoMails($json, true)) - { - return $this->outputJsonError('Failed sending emails'); - } + if ($this->config->item('send_mail') === TRUE) + { + if (!$this->_sendSanchoMails($json, true)) + { + return $this->outputJsonError('Failed sending emails'); + } + } return $this->outputJsonSuccess($json); } @@ -191,10 +202,13 @@ class reviewAnrechnungDetail extends Auth_Controller if (isset($json) && !isEmptyArray($json)) { // Send mails to STGL (if not present STGL, send to STGL assistance) - if (!$this->_sendSanchoMails($json, false)) - { - return $this->outputJsonError('Failed sending emails'); - } + if ($this->config->item('send_mail') === TRUE) + { + if (!$this->_sendSanchoMails($json, false)) + { + return $this->outputJsonError('Failed sending emails'); + } + } return $this->outputJsonSuccess($json); } @@ -253,8 +267,14 @@ class reviewAnrechnungDetail extends Auth_Controller show_error('Failed retrieving Anrechnung'); } - $result = $this->LehrveranstaltungModel - ->getLecturersByLv($result->studiensemester_kurzbz, $result->lehrveranstaltung_id); + if($this->config->item('fbl') === TRUE) + { + $result = $this->LehrveranstaltungModel->getLeitungOfLvOe($result->lehrveranstaltung_id); + } + else + { + $result = $this->LehrveranstaltungModel->getLecturersByLv($result->studiensemester_kurzbz, $result->lehrveranstaltung_id); + } if($result = getData($result)) { @@ -282,14 +302,20 @@ class reviewAnrechnungDetail extends Auth_Controller show_error('Failed retrieving Anrechnung'); } - $result = $this->LehrveranstaltungModel - ->getLecturersByLv($result->studiensemester_kurzbz, $result->lehrveranstaltung_id); + if($this->config->item('fbl') === TRUE) + { + $result = $this->LehrveranstaltungModel->getLeitungOfLvOe($result->lehrveranstaltung_id); + } + else + { + $result = $this->LehrveranstaltungModel->getLecturersByLv($result->studiensemester_kurzbz, $result->lehrveranstaltung_id); + } if($result = getData($result)) { - $entitled_lector_arr = array_column($result, 'uid'); + $entitled_uid_arr = array_column($result, 'uid'); - if (in_array($this->_uid, $entitled_lector_arr)) + if (in_array($this->_uid, $entitled_uid_arr)) { return; } diff --git a/application/controllers/lehre/anrechnung/ReviewAnrechnungUebersicht.php b/application/controllers/lehre/anrechnung/ReviewAnrechnungUebersicht.php index c63d0af69..6d4107936 100644 --- a/application/controllers/lehre/anrechnung/ReviewAnrechnungUebersicht.php +++ b/application/controllers/lehre/anrechnung/ReviewAnrechnungUebersicht.php @@ -26,6 +26,9 @@ class reviewAnrechnungUebersicht extends Auth_Controller ) ); + // Load configs + $this->load->config('anrechnung'); + // Load models $this->load->model('education/Anrechnung_model', 'AnrechnungModel'); $this->load->model('education/Anrechnungstatus_model', 'AnrechnungstatusModel'); @@ -72,7 +75,8 @@ class reviewAnrechnungUebersicht extends Auth_Controller } $viewData = array( - 'studiensemester_selected' => $studiensemester_kurzbz + 'studiensemester_selected' => $studiensemester_kurzbz, + 'configFachbereichsleitung' => $this->config->item('fbl') ); $this->load->view('lehre/anrechnung/reviewAnrechnungUebersicht.php', $viewData); @@ -111,16 +115,19 @@ class reviewAnrechnungUebersicht extends Auth_Controller * Send mails to STGL (if not present STGL, send to STGL assistance) * NOTE: mails are sent at the end to ensure sending only one mail to each STGL * */ - if (!$this->_sendSanchoMails($json, true)) - { - show_error('Failed sending emails'); - } + if ($this->config->item('send_mail') === TRUE) + { + if (!$this->_sendSanchoMails($json, true)) + { + show_error('Failed sending emails'); + } + } return $this->outputJsonSuccess($json); } else { - return $this->outputJsonError($this->p->t('ui', 'errorNichtAusgefuehrt')); + $this->terminateWithJsonError($this->p->t('ui', 'errorNichtAusgefuehrt')); } } @@ -154,10 +161,13 @@ class reviewAnrechnungUebersicht extends Auth_Controller if (isset($json) && !isEmptyArray($json)) { // Send mails to STGL (if not present STGL, send to STGL assistance) - if (!$this->_sendSanchoMails($json, false)) - { - show_error('Failed sending emails'); - } + if ($this->config->item('send_mail') === TRUE) + { + if (!$this->_sendSanchoMails($json, false)) + { + show_error('Failed sending emails'); + } + } return $this->outputJsonSuccess($json); } @@ -217,14 +227,20 @@ class reviewAnrechnungUebersicht extends Auth_Controller show_error('Failed retrieving Anrechnung'); } - $result = $this->LehrveranstaltungModel - ->getLecturersByLv($result->studiensemester_kurzbz, $result->lehrveranstaltung_id); + if ($this->config->item('fbl') === TRUE) + { + $result = $this->LehrveranstaltungModel->getLeitungOfLvOe($result->lehrveranstaltung_id); + } + else + { + $result = $this->LehrveranstaltungModel->getLecturersByLv($result->studiensemester_kurzbz, $result->lehrveranstaltung_id); + } if($result = getData($result)) { - $entitled_lector_arr = array_column($result, 'uid'); + $entitled_uid_arr = array_column($result, 'uid'); - if (in_array($this->_uid, $entitled_lector_arr)) + if (in_array($this->_uid, $entitled_uid_arr)) { return; } 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/person/Gruppenmanagement.php b/application/controllers/person/Gruppenmanagement.php index 1a4c341a4..099871676 100644 --- a/application/controllers/person/Gruppenmanagement.php +++ b/application/controllers/person/Gruppenmanagement.php @@ -29,6 +29,7 @@ class Gruppenmanagement extends Auth_Controller $this->load->model('person/benutzer_model', 'BenutzerModel'); $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); $this->load->model('person/benutzergruppe_model', 'BenutzergruppeModel'); + $this->load->model('person/gruppe_manager_model', 'GruppemanagerModel'); $this->load->model('system/Log_model', 'LogModel'); $this->load->library('WidgetLib'); @@ -117,6 +118,27 @@ class Gruppenmanagement extends Auth_Controller $result = error('Uid missing'); else { + $this->GruppemanagerModel->addSelect('1'); + $isManagerRes = $this->GruppemanagerModel->loadWhere( + array( + 'uid' => $this->_uid, + 'gruppe_kurzbz' => $gruppe_kurzbz + ) + ); + + if (isError($isManagerRes)) + { + $this->outputJsonError(getError($isManagerRes)); + return; + } + + if (!hasData($isManagerRes)) + { + $this->outputJsonError($this->p->t('gruppenmanagement', 'nichtZumEditierenDerGruppeBerechtigt')); + return; + } + + $this->BenutzergruppeModel->addSelect('1'); $benutzerExistsRes = $this->BenutzergruppeModel->loadWhere( array( 'uid' => $uid, @@ -170,6 +192,26 @@ class Gruppenmanagement extends Auth_Controller $result = error('Uid missing'); else { + $this->GruppemanagerModel->addSelect('1'); + $isManagerRes = $this->GruppemanagerModel->loadWhere( + array( + 'uid' => $this->_uid, + 'gruppe_kurzbz' => $gruppe_kurzbz + ) + ); + + if (isError($isManagerRes)) + { + $this->outputJsonError(getError($isManagerRes)); + return; + } + + if (!hasData($isManagerRes)) + { + $this->outputJsonError($this->p->t('gruppenmanagement', 'nichtZumEditierenDerGruppeBerechtigt')); + return; + } + $result = $this->BenutzergruppeModel->delete( array( 'uid' => $uid, 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/TestSearch.php b/application/controllers/system/TestSearch.php deleted file mode 100644 index 1f5c66a1d..000000000 --- a/application/controllers/system/TestSearch.php +++ /dev/null @@ -1,44 +0,0 @@ - 'system/developer:r' - ) - ); - - // Loads WidgetLib - $this->load->library('WidgetLib'); - - // Loads phrases system - $this->loadPhrases( - array( - 'global', - 'ui', - 'filter' - ) - ); - } - - // ----------------------------------------------------------------------------------------------------------------- - // Public methods - - /** - * Everything has a beginning - */ - public function index() - { - $this->load->view('system/logs/testSearch.php'); - } -} diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index 48c50bb4a..f6e41d2e6 100644 --- a/application/controllers/system/infocenter/InfoCenter.php +++ b/application/controllers/system/infocenter/InfoCenter.php @@ -21,6 +21,7 @@ class InfoCenter extends Auth_Controller const FREIGEGEBEN_PAGE = 'freigegeben'; const REIHUNGSTESTABSOLVIERT_PAGE = 'reihungstestAbsolviert'; const ABGEWIESEN_PAGE = 'abgewiesen'; + const AUFGENOMMEN_PAGE = 'aufgenommen'; const SHOW_DETAILS_PAGE = 'showDetails'; const SHOW_ZGV_DETAILS_PAGE = 'showZGVDetails'; const ZGV_UBERPRUEFUNG_PAGE = 'ZGVUeberpruefung'; @@ -115,12 +116,14 @@ class InfoCenter extends Auth_Controller 'index' => 'infocenter:r', 'freigegeben' => 'infocenter:r', 'abgewiesen' => 'infocenter:r', + 'aufgenommen' => 'infocenter:r', 'reihungstestAbsolviert' => 'infocenter:r', 'showDetails' => 'infocenter:r', 'showZGVDetails' => 'lehre/zgvpruefung:r', 'unlockPerson' => 'infocenter:rw', 'saveFormalGeprueft' => 'infocenter:rw', 'saveDocTyp' => 'infocenter:rw', + 'updateStammdaten' => 'infocenter:rw', 'saveNachreichung' => 'infocenter:rw', 'getPrestudentData' => 'infocenter:r', 'getLastPrestudentWithZgvJson' => 'infocenter:r', @@ -141,12 +144,6 @@ class InfoCenter extends Auth_Controller 'reloadNotizen' => array('infocenter:r', 'lehre/zgvpruefung:r'), 'reloadLogs' => 'infocenter:r', 'outputAkteContent' => array('infocenter:r', 'lehre/zgvpruefung:r'), - 'getPostponeDate' => array('infocenter:r', 'lehre/zgvpruefung:r'), - 'park' => 'infocenter:rw', - 'unpark' => 'infocenter:rw', - 'setOnHold' => 'infocenter:rw', - 'removeOnHold' => array('infocenter:rw', 'lehre/zgvpruefung:rw'), - 'getStudienjahrEnd' => array('infocenter:r', 'lehre/zgvpruefung:r'), 'setNavigationMenuArrayJson' => 'infocenter:r', 'getAbsageData' => 'infocenter:r', 'saveAbsageForAll' => 'infocenter:rw', @@ -163,6 +160,7 @@ class InfoCenter extends Auth_Controller $this->load->model('crm/Statusgrund_model', 'StatusgrundModel'); $this->load->model('crm/ZGVPruefung_model', 'ZGVPruefungModel'); $this->load->model('crm/ZGVPruefungStatus_model', 'ZGVPruefungStatusModel'); + $this->load->model('crm/Rueckstellung_model', 'RueckstellungModel'); $this->load->model('person/Notiz_model', 'NotizModel'); $this->load->model('person/Person_model', 'PersonModel'); $this->load->model('system/Message_model', 'MessageModel'); @@ -172,11 +170,16 @@ class InfoCenter extends Auth_Controller $this->load->model('codex/Zgv_model', 'ZgvModel'); $this->load->model('codex/Zgvmaster_model', 'ZgvmasterModel'); $this->load->model('codex/Nation_model', 'NationModel'); + $this->load->model('person/Kontakt_model', 'KontaktModel'); + $this->load->model('person/Geschlecht_model', 'GeschlechtModel'); + $this->load->model('person/adresse_model', 'AdresseModel'); // Loads libraries $this->load->library('PersonLogLib'); $this->load->library('WidgetLib'); + $this->load->config('infocenter'); + $this->loadPhrases( array( 'global', @@ -227,6 +230,16 @@ class InfoCenter extends Auth_Controller $this->load->view('system/infocenter/infocenterAbgewiesen.php'); } + + /** + * Aufgenommene page of the InfoCenter tool + */ + public function aufgenommen() + { + $this->_setNavigationMenu(self::AUFGENOMMEN_PAGE); // define the navigation menu for this page + + $this->load->view('system/infocenter/infocenterAufgenommen.php'); + } /** * @@ -313,7 +326,7 @@ class InfoCenter extends Auth_Controller show_error('Person does not exist!'); $origin_page = $this->input->get(self::ORIGIN_PAGE); - if ($origin_page == self::INDEX_PAGE) + if (in_array($origin_page, array(self::INDEX_PAGE, self::ABGEWIESEN_PAGE))) { // mark person as locked for editing $result = $this->PersonLockModel->lockPerson($person_id, $this->_uid, self::APP); @@ -324,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); @@ -338,7 +354,8 @@ class InfoCenter extends Auth_Controller $persondata, $prestudentdata, $dokumentdata, - $duplicate + $duplicate, + $unruly ); $data[self::FHC_CONTROLLER_ID] = $this->getControllerId(); @@ -358,7 +375,14 @@ class InfoCenter extends Auth_Controller if (isError($result)) show_error(getError($result)); - $redirectLink = '/'.self::INFOCENTER_URI.'?'.self::FHC_CONTROLLER_ID.'='.$this->getControllerId(); + $origin_page = $this->input->get(self::ORIGIN_PAGE); + + if ($origin_page === self::ABGEWIESEN_PAGE) + $redirectLink = self::INFOCENTER_URI. '/' .self::ABGEWIESEN_PAGE; + else + $redirectLink = '/'.self::INFOCENTER_URI; + + $redirectLink .= '?'.self::FHC_CONTROLLER_ID.'='.$this->getControllerId(); // Force reload of Dataset after Unlock $redirectLink .= '&'.self::KEEP_TABLESORTER_FILTER.'=true'; @@ -600,7 +624,7 @@ class InfoCenter extends Auth_Controller } /** - * Sendet bei einer neuen ZGV Prüfung die Mail raus an den Studiengang + * Sendet bei einer neuen ZGV Prüfung eine Mail an den Studiengang */ private function sendZgvMail($mail, $typ, $person){ $data = array( @@ -691,7 +715,7 @@ class InfoCenter extends Auth_Controller /** * Fügt einen neuen ZGV Status hinzu oder updated einen bestehenden - * Falls es erfolgreich war, sendet er die Mail raus + * Falls es erfolgreich war, wird eine Mail rausgeschickt */ public function zgvRueckfragen() { @@ -745,7 +769,8 @@ class InfoCenter extends Auth_Controller $this->sendZgvMail($mail, $typ, $person); elseif (isError($insert)) $this->terminateWithJsonError('Fehler beim Speichern'); - }else + } + else { $insert = $this->ZGVPruefungModel->insert( array( @@ -775,7 +800,7 @@ class InfoCenter extends Auth_Controller } $hold = false; - if ($this->personloglib->getOnHoldDate($person_id) !== null) + if (hasData($this->RueckstellungModel->getByPersonId($person_id, 'onhold_zgv'))) $hold = true; $this->outputJsonSuccess( @@ -1111,14 +1136,14 @@ class InfoCenter extends Auth_Controller public function reloadDoks($person_id) { - $dokumente_nachgereicht = $this->AkteModel->getAktenWithDokInfo($person_id, null, true); + $dokumente_nachgereicht = $this->AkteModel->getAktenWithDokInfo($person_id, null, true, false); $this->load->view('system/infocenter/dokNachzureichend.php', array('dokumente_nachgereicht' => $dokumente_nachgereicht->retval)); } public function reloadUebersichtDoks($person_id) { - $dokumente = $this->AkteModel->getAktenWithDokInfo($person_id, null, false); + $dokumente = $this->AkteModel->getAktenWithDokInfo($person_id, null, false, false); $this->DokumentModel->addOrder('bezeichnung'); $dokumentdata = array('dokumententypen' => (getData($this->DokumentModel->load()))); @@ -1156,107 +1181,7 @@ class InfoCenter extends Auth_Controller ->set_output($aktecontent->retval) ->_display(); } - - /** - * Gets the date until which a person is parked - * @param $person_id - */ - public function getPostponeDate($person_id) - { - $result = array( - 'type' => null, - 'date' => null - ); - - $parkedDate = $this->personloglib->getParkedDate($person_id); - - if (isset($parkedDate)) - { - $result['type'] = 'parked'; - $result['date'] = $parkedDate; - } - else - { - $onholdDate = $this->personloglib->getOnHoldDate($person_id); - - if (isset($onholdDate)) - { - $result['type'] = 'onhold'; - $result['date'] = $onholdDate; - } - } - - $this->outputJsonSuccess($result); - } - - /** - * Initializes parking of a person, i.e. a person is not expected to do any actions while parked - */ - public function park() - { - $person_id = $this->input->post('person_id'); - $date = $this->input->post('parkdate'); - - $result = $this->personloglib->park($person_id, date_format(date_create($date), 'Y-m-d'), self::TAETIGKEIT, self::APP, null, $this->_uid); - - $this->outputJson($result); - } - - /** - * Removes parking of a person - */ - public function unPark() - { - $person_id = $this->input->post('person_id'); - - $result = $this->personloglib->unPark($person_id); - - $this->outputJson($result); - } - - /** - * Sets a person on hold ("zurückstellen") - */ - public function setOnHold() - { - $person_id = $this->input->post('person_id'); - $date = $this->input->post('onholddate'); - - $result = $this->personloglib->setOnHold($person_id, date_format(date_create($date), 'Y-m-d'), self::TAETIGKEIT, self::APP, null, $this->_uid); - - $this->outputJson($result); - } - - /** - * Removed on hold status of a person - */ - public function removeOnHold() - { - $person_id = $this->input->post('person_id'); - - $result = $this->personloglib->removeOnHold($person_id); - - $this->outputJson($result); - } - - /** - * Gets the End date of the current Studienjahr - */ - public function getStudienjahrEnd() - { - $this->load->model('organisation/studienjahr_model', 'StudienjahrModel'); - - $result = $this->StudienjahrModel->getCurrStudienjahr(); - - $json = null; - - if (hasData($result)) - { - $json = $result->retval[0]->ende; - } - - $this->outputJsonSuccess(array($json)); - } + /** * Wrapper for setNavigationMenu, returns JSON message @@ -1320,6 +1245,128 @@ class InfoCenter extends Auth_Controller $this->outputJsonSuccess('success'); } + public function updateStammdaten() + { + if (isEmptyString($this->input->post('nachname')) || + isEmptyString($this->input->post('geschlecht')) || + isEmptyString($this->input->post('gebdatum'))) + { + $this->terminateWithJsonError($this->p->t('infocenter', 'stammdatenFeldFehlt')); + } + + $datum = explode('.', $this->input->post('gebdatum')); + + if (!checkdate($datum[1], $datum[0], $datum[2])) + { + $this->terminateWithJsonError($this->p->t('infocenter', 'datumUngueltig')); + } + + $person_id = $this->input->post('personid'); + + $update = $this->PersonModel->update( + array + ( + 'person_id' => $person_id + ), + array + ( + 'titelpre' => isEmptyString($this->input->post('titelpre')) ? null : $this->input->post('titelpre'), + 'vorname' => isEmptyString($this->input->post('vorname')) ? null : $this->input->post('vorname'), + 'nachname' => $this->input->post('nachname'), + 'titelpost' => isEmptyString($this->input->post('titelpost')) ? null : $this->input->post('titelpost'), + 'gebdatum' => isEmptyString($this->input->post('gebdatum')) ? null : date("Y-m-d", strtotime($this->input->post('gebdatum'))), + 'svnr' => isEmptyString($this->input->post('svnr')) ? null : $this->input->post('svnr'), + 'staatsbuergerschaft' => isEmptyString($this->input->post('buergerschaft')) ? null : $this->input->post('buergerschaft'), + 'geschlecht' => $this->input->post('geschlecht'), + 'geburtsnation' => isEmptyString($this->input->post('gebnation')) ? null : $this->input->post('gebnation'), + 'gebort' => isEmptyString($this->input->post('gebort')) ? null : $this->input->post('gebort'), + 'updateamum' => date('Y-m-d H:i:s'), + 'updatevon' => $this->_uid + ) + ); + + if (isError($update)) + $this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern')); + + $kontakte = $this->input->post('kontakt'); + if($kontakte) { + + foreach ($kontakte as $kontakt) { + $kontaktExists = $this->KontaktModel->loadWhere(array( + 'kontakt_id' => $kontakt['id'], + 'person_id' => $person_id, + )); + + if (hasData($kontaktExists)) { + $kontaktExists = getData($kontaktExists)[0]; + + if ($kontaktExists->kontakt === $kontakt['value']) + continue; + + $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 (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')); + } + + } + } + } + + $this->outputJsonSuccess('Success'); + } + public function saveNachreichung($person_id) { $nachreichungAm = $this->input->post('nachreichungAm'); @@ -1358,7 +1405,6 @@ class InfoCenter extends Auth_Controller if($nachreichungAm < $today) $this->terminateWithJsonError($this->p->t('infocenter', 'nachreichDatumNichtVergangenheit')); - $akte = $this->AkteModel->loadWhere(array('person_id' => $person_id, 'dokument_kurzbz' => $allowedTypes[$typ])); if (hasData($akte)) { @@ -1505,6 +1551,7 @@ class InfoCenter extends Auth_Controller $freigegebenLink = site_url(self::INFOCENTER_URI.'/'.self::FREIGEGEBEN_PAGE); $reihungstestAbsolviertLink = site_url(self::INFOCENTER_URI.'/'.self::REIHUNGSTESTABSOLVIERT_PAGE); $abgewiesenLink = site_url(self::INFOCENTER_URI.'/'.self::ABGEWIESEN_PAGE); + $aufgenommenLink = site_url(self::INFOCENTER_URI.'/'.self::AUFGENOMMEN_PAGE); $currentFilterId = $this->input->get(self::FILTER_ID); if (isset($currentFilterId)) @@ -1512,6 +1559,7 @@ class InfoCenter extends Auth_Controller $freigegebenLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; $reihungstestAbsolviertLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; $abgewiesenLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; + $aufgenommenLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; } $this->navigationlib->setSessionMenu( @@ -1562,7 +1610,19 @@ class InfoCenter extends Auth_Controller null, // subscriptLinkValue '', // target 30 // sort - ) + ), + 'aufgenommen' => $this->navigationlib->oneLevel( + 'Aufgenommene', // description + $aufgenommenLink, // link + null, // children + 'check', // icon + null, // subscriptDescription + false, // expand + null, // subscriptLinkClass + null, // subscriptLinkValue + '', // target + 40 // sort + ), ) ); } @@ -1590,6 +1650,9 @@ class InfoCenter extends Auth_Controller if ($origin_page === self::ABGEWIESEN_PAGE) $link = site_url(self::INFOCENTER_URI.'/'.self::ABGEWIESEN_PAGE); + if ($origin_page === self::AUFGENOMMEN_PAGE) + $link = site_url(self::INFOCENTER_URI.'/'.self::AUFGENOMMEN_PAGE); + $prevFilterId = $this->input->get(self::PREV_FILTER_ID); if (isset($prevFilterId)) { @@ -1794,14 +1857,14 @@ class InfoCenter extends Auth_Controller if (!isset($stammdaten->retval)) return null; - $dokumente = $this->AkteModel->getAktenWithDokInfo($person_id, null, false); + $dokumente = $this->AkteModel->getAktenWithDokInfo($person_id, null, false, false); if (isError($dokumente)) { show_error(getError($dokumente)); } - $dokumente_nachgereicht = $this->AkteModel->getAktenWithDokInfo($person_id, null, true); + $dokumente_nachgereicht = $this->AkteModel->getAktenWithDokInfo($person_id, null, true, false); if (isError($dokumente_nachgereicht)) { @@ -1996,6 +2059,12 @@ class InfoCenter extends Auth_Controller $this->NationModel->addOrder('langtext'); $allNations = getData($this->NationModel->load()); + + $additional_stg = explode(',', ($this->config->item('infocenter_studiengang_kz'))); + + $this->GeschlechtModel->addOrder('sort'); + $allGenders = getData($this->GeschlechtModel->load()); + $data = array ( 'zgvpruefungen' => $zgvpruefungen, 'abwstatusgruende' => $abwstatusgruende, @@ -2004,6 +2073,8 @@ class InfoCenter extends Auth_Controller 'all_zgvs' => $allZGVs, 'all_zgvs_master' => $allZGVsMaster, 'all_nations' => $allNations, + 'additional_stg' => $additional_stg, + 'all_genders' => $allGenders ); return $data; @@ -2164,8 +2235,8 @@ class InfoCenter extends Auth_Controller $prestudentstatus = $prestudent->prestudentstatus; $person_id = $prestudent->person_id; $person = $this->PersonModel->getPersonStammdaten($person_id, true)->retval; - $dokumente = $this->AkteModel->getAktenWithDokInfo($person_id, null, false)->retval; - $dokumenteNachzureichen = $this->AkteModel->getAktenWithDokInfo($person_id, null, true)->retval; + $dokumente = $this->AkteModel->getAktenWithDokInfo($person_id, null, false, false)->retval; + $dokumenteNachzureichen = $this->AkteModel->getAktenWithDokInfo($person_id, null, true, false)->retval; //fill mail variables $interessentbez = $person->geschlecht == 'm' ? 'Ein Interessent' : 'Eine Interessentin'; @@ -2262,12 +2333,10 @@ class InfoCenter extends Auth_Controller public function getAbsageData() { - $studiengang_kz_all = $this->permissionlib->getSTG_isEntitledFor('infocenter'); - $stg_typ = $this->StudiengangModel->getStudiengangTyp($studiengang_kz_all, ['b', 'm']); + $stg_typ = $this->getStudienArtBerechtigung(['b', 'm']); - if (hasData($stg_typ)) + if (!is_null($stg_typ)) { - $stg_typ = getData($stg_typ); $statusgruende = $this->StatusgrundModel->getStatus(self::ABGEWIESENERSTATUS, true)->retval; $studienSemester = $this->variablelib->getVar('infocenter_studiensemester'); $studiengaenge = $this->StudiengangModel->getStudiengaengeWithOrgForm(array_column($stg_typ, 'typ'), $studienSemester); @@ -2283,15 +2352,16 @@ class InfoCenter extends Auth_Controller $this->outputJsonSuccess(null); } - public function getStudienArtBerechtigung() + public function getStudienArtBerechtigung($typ = null) { $studiengang_kz_all = $this->permissionlib->getSTG_isEntitledFor('infocenter'); - $stg_typ = $this->StudiengangModel->getStudiengangTyp($studiengang_kz_all, ['b', 'm', 'l']); + $stg_typ = $this->StudiengangModel->getStudiengangTyp($studiengang_kz_all, $typ); return getData($stg_typ); } + public function getStudienartData() { - $this->outputJsonSuccess($this->getStudienArtBerechtigung()); + $this->outputJsonSuccess($this->getStudienArtBerechtigung(['b', 'm', 'l'])); } public function saveAbsageForAll() @@ -2319,4 +2389,4 @@ class InfoCenter extends Auth_Controller $this->outputJsonSuccess("Success"); } -} +} \ No newline at end of file diff --git a/application/controllers/system/infocenter/Rueckstellung.php b/application/controllers/system/infocenter/Rueckstellung.php new file mode 100644 index 000000000..62af633ca --- /dev/null +++ b/application/controllers/system/infocenter/Rueckstellung.php @@ -0,0 +1,135 @@ + array('infocenter:r', 'lehre/zgvpruefung:r'), + 'set' => array('infocenter:r', 'lehre/zgvpruefung:r'), + 'delete' => array('infocenter:r', 'lehre/zgvpruefung:r'), + 'getStatus' => array('infocenter:rw', 'lehre/zgvpruefung:rw') + ) + ); + + $this->load->model('crm/Rueckstellung_model', 'RueckstellungModel'); + $this->load->model('crm/RueckstellungStatus_model', 'RueckstellungStatusModel'); + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->library('PersonLogLib'); + + $this->_setAuthUID(); // sets property uid + + $this->_ci =& get_instance(); // get code igniter instance + } + + public function get($person_id) + { + $result = null; + $rueckstellung = $this->_ci->RueckstellungModel->getByPersonId($person_id); + + if (isError($rueckstellung)) + $this->terminateWithJsonError($this->_ci->p->t('ui', 'fehlerBeimLesen')); + + if (hasData($rueckstellung)) + { + $rueckstellung = getData($rueckstellung)[0]; + $fullName = getData($this->_ci->PersonModel->getFullName($rueckstellung->insertvon)); + + $result = array( + 'von' => $fullName, + 'bezeichnung' => $rueckstellung->bezeichnung, + 'bis' => $rueckstellung->datum_bis, + 'status_kurzbz' => $rueckstellung->status_kurzbz + ); + + if ($rueckstellung->status_kurzbz === 'parked' && $rueckstellung->datum_bis < date('Y-m-d')) + { + $this->_ci->RueckstellungModel->delete(array('person_id' => $person_id, 'status_kurzbz' => 'parked')); + $result = null; + } + } + + $this->outputJsonSuccess($result); + } + + public function set() + { + $person_id = $this->input->post('person_id'); + $datum_bis = $this->input->post('datum_bis'); + $status_kurzbz = $this->input->post('status_kurzbz'); + + $result = $this->_ci->RueckstellungModel->insert( + array('person_id' => $person_id, + 'status_kurzbz' => $status_kurzbz, + 'datum_bis' => date_format(date_create($datum_bis), 'Y-m-d'), + 'insertvon' => $this->_uid + ) + ); + + if (isError($result)) + $this->terminateWithJsonError(getError($result)); + + $this->_log($person_id, $status_kurzbz); + + $this->outputJson($result); + } + + public function delete() + { + $person_id = $this->input->post('person_id'); + $status = $this->input->post('status'); + + $result = $this->_ci->RueckstellungModel->delete(array('person_id' => $person_id, 'status_kurzbz' => $status)); + + if (isError($result)) + $this->terminateWithJsonError($this->_ci->p->t('ui', 'fehlerBeimSpeichern')); + + $this->outputJson($result); + } + + public function getStatus($aktiv = true) + { + $this->_ci->RueckstellungStatusModel->addOrder('sort'); + $result = $this->_ci->RueckstellungStatusModel->loadWhere(array('aktiv' => $aktiv)); + + if (isError($result)) + $this->terminateWithJsonError($this->_ci->p->t('ui', 'fehlerBeimLesen')); + + $this->outputJsonSuccess(getData($result)); + } + + /** + * 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'); + } + + private function _log($person_id, $status_kurzbz) + { + $message = "Person $person_id set to $status_kurzbz"; + + $this->_ci->personloglib->log( + $person_id, + 'Action', + array( + 'name' => 'Person status set', + 'message' => $message, + 'success' => true + ), + 'bewerbung', + 'infocenter', + null, + $this->_uid + ); + } +} \ No newline at end of file diff --git a/application/controllers/system/issues/Issues.php b/application/controllers/system/issues/Issues.php index 6d959a024..44c2ff5d3 100644 --- a/application/controllers/system/issues/Issues.php +++ b/application/controllers/system/issues/Issues.php @@ -26,6 +26,7 @@ class Issues extends Auth_Controller // Load models $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + $this->load->model('system/Sprache_model', 'SpracheModel'); $this->loadPhrases( array( @@ -45,10 +46,11 @@ class Issues extends Auth_Controller public function index() { $oes_for_issues = $this->_getOesForIssues(); + $language_index = $this->_getLanguageIndex(); $this->load->view( 'system/issues/issues', - $oes_for_issues + array_merge($oes_for_issues, array('language_index' => $language_index)) ); } @@ -166,4 +168,28 @@ class Issues extends Auth_Controller 'all_oe_kurzbz_berechtigt' => $all_oe_kurzbz_berechtigt ); } + + /** + * Gets language index of currently logged in user. + * @return object int (the index, start at 1) + */ + private function _getLanguageIndex() + { + $idx = 1; + $this->SpracheModel->addSelect('sprache, index'); + $langRes = $this->SpracheModel->load(); + + if (hasData($langRes)) + { + $userLang = getUserLanguage(); + $lang = getData($langRes); + + foreach ($lang as $l) + { + if ($l->sprache == $userLang) $idx = $l->index; + } + } + + return $idx; + } } diff --git a/application/controllers/system/issues/IssuesKonfiguration.php b/application/controllers/system/issues/IssuesKonfiguration.php new file mode 100644 index 000000000..a19a2a93b --- /dev/null +++ b/application/controllers/system/issues/IssuesKonfiguration.php @@ -0,0 +1,305 @@ + 'admin:r', + 'getApps' => 'admin:r', + 'getFehlerKonfigurationByApp' => 'admin:r', + 'saveFehlerKonfiguration' => 'admin:rw', + 'deleteKonfiguration' => 'admin:rw', + 'deleteKonfigurationsWerte' => 'admin:rw' + ) + ); + + // Load libraries + $this->load->library('IssuesLib'); + $this->load->library('WidgetLib'); + + // Load models + $this->load->model('system/Fehlerkonfigurationstyp_model', 'FehlerkonfigurationstypModel'); + $this->load->model('system/Fehlerkonfiguration_model', 'FehlerkonfigurationModel'); + + $this->loadPhrases( + array( + 'global', + 'ui', + 'filter', + 'fehlermonitoring' + ) + ); + + $this->_setAuthUID(); // sets property uid + $this->setControllerId(); // sets the controller id + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Load initial view. + */ + public function index() + { + $this->load->view("system/issues/issuesKonfiguration.php"); + } + + /** + * Loads all Apps to which Fehler exist. + */ + public function getApps() + { + $this->FehlerModel->addDistinct(); + $this->FehlerModel->addSelect('app'); + $this->FehlerModel->addJoin('system.tbl_fehler_konfigurationstyp', 'app'); + $this->FehlerModel->addOrder('app'); + + $appRes = $this->FehlerModel->load(); + + $this->outputJson($appRes); + } + + /** + * Gets all fehlercodes, optionally by app. + */ + public function getFehlerKonfigurationByApp() + { + $app = $this->input->get('app'); + + // get all Konfiguration types, optionally filtered by app + $this->FehlerkonfigurationstypModel->addSelect('konfigurationstyp_kurzbz, konfigurationsdatentyp, beschreibung'); + $this->FehlerkonfigurationstypModel->addOrder('konfigurationstyp_kurzbz'); + $konfRes = isEmptyString($app) + ? $this->FehlerkonfigurationstypModel->load() + : $this->FehlerkonfigurationstypModel->loadWhere(array('app' => $app)); + + if (isError($konfRes)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlerFehlerKonfigurationLaden')); + + // get all Fehler, optionally filtered by app + $params = array('fehlercode_extern' => null); + $this->FehlerModel->addSelect('fehlercode, fehler_kurzbz, fehlertyp_kurzbz, fehlertext'); + $this->FehlerModel->addOrder('fehlercode'); + if (!isEmptyString($app)) $params['app'] = $app; + $fehlerRes = $this->FehlerModel->loadWhere($params); + + if (isError($fehlerRes)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlerFehlerLaden')); + + // return object with retrieved data + $konfObj = new StdClass(); + $konfObj->konfigurationstypen = array(); + $konfObj->fehler = array(); + + if (hasData($konfRes)) $konfObj->konfigurationstypen = getData($konfRes); + if (hasData($fehlerRes)) $konfObj->fehler = getData($fehlerRes); + + $this->outputJsonSuccess($konfObj); + } + + /** + * Saves a Fehler configuration, inserts new configuration or updates existing. + * Checks if datatype of passed configuration is correct. + */ + public function saveFehlerKonfiguration() + { + $result = null; + $konfigurationstyp_kurzbz = $this->input->post('konfigurationstyp_kurzbz'); + $fehlercode = $this->input->post('fehlercode'); + $konfigurationsWert = $this->input->post('konfigurationsWert'); + + // check if all params passed + if (isEmptyString($konfigurationstyp_kurzbz)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'ungueltigerKonfigurationstyp')); + + if (isEmptyString($fehlercode)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlercodeFehlt')); + + // separate by semicolon if multiple values passed + $konfigurationsWert = explode(';', $konfigurationsWert); + + // check konfigurationswert + + // get the expected data type + $dataType = self::STRING_DATA_TYPE; + $this->FehlerkonfigurationstypModel->addSelect('konfigurationsdatentyp'); + $konfigtypRes = $this->FehlerkonfigurationstypModel->loadWhere(array('konfigurationstyp_kurzbz' => $konfigurationstyp_kurzbz)); + + if (hasData($konfigtypRes)) + { + $konfigurationsdatentyp = getData($konfigtypRes)[0]->konfigurationsdatentyp; + foreach ($konfigurationsWert as $idx => $konfWert) + { + // check if data type correct + $valid = false; + switch ($konfigurationsdatentyp) + { + case self::INTEGER_DATA_TYPE: + $valid = (string)(int)$konfWert == $konfWert; + $konfigurationsWert[$idx] = (int) $konfWert; + break; + case self::FLOAT_DATA_TYPE: + $valid = (string)(float)$konfWert == $konfWert; + $konfigurationsWert[$idx] = (float) $konfWert; + break; + default: + $valid = is_string($konfWert) && preg_match('/^[A-Za-z0-9_]+$/', $konfWert); + } + if (!$valid) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'ungueltigerKonfigurationswert', array($konfigurationsdatentyp))); + } + } + + // check if konfiguration already set for the fehlercode + $this->FehlerkonfigurationModel->addSelect('konfiguration'); + $fehlerkonfigurationRes = $this->FehlerkonfigurationModel->loadWhere( + array( + 'konfigurationstyp_kurzbz' => $konfigurationstyp_kurzbz, + 'fehlercode' => $fehlercode + ) + ); + + if (isError($fehlerkonfigurationRes)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlerFehlerKonfigurationLaden')); + + // if konfiguration exists, update by add konfiguration values to existing + if (hasData($fehlerkonfigurationRes)) + { + $fehlerkonfiguration = getData($fehlerkonfigurationRes); + + $existingKonf = json_decode($fehlerkonfiguration[0]->konfiguration); + + if (!$existingKonf) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlerJsonDekodierung')); + + if (!is_array($existingKonf)) $existingKonf = array($existingKonf); + + $newKonf = json_encode(array_values(array_unique(array_merge($existingKonf, $konfigurationsWert)))); + if (!$newKonf) $this->terminateWithJsonError("error when encoding JSON"); + + $result = $this->FehlerkonfigurationModel->update( + array('konfigurationstyp_kurzbz' => $konfigurationstyp_kurzbz, 'fehlercode' => $fehlercode), + array('konfiguration' => $newKonf, 'updateamum' => 'NOW()', 'updatevon' => $this->_uid) + ); + } + else // if no konfiguration exists, add new konfiguration entry + { + $newKonf = json_encode($konfigurationsWert); + if (!$newKonf) $this->terminateWithJsonError("error when encoding JSON"); + + $result = $this->FehlerkonfigurationModel->insert( + array( + 'konfigurationstyp_kurzbz' => $konfigurationstyp_kurzbz, + 'fehlercode' => $fehlercode, + 'konfiguration' => $newKonf, + 'insertvon' => $this->_uid + ) + ); + } + + // output result (insert or update) + $this->outputJson($result); + } + + /** + * Deletes values of a Konfiguration. + */ + public function deleteKonfigurationsWerte() + { + $konfigurationstyp_kurzbz = $this->input->post('konfigurationstyp_kurzbz'); + $fehlercode = $this->input->post('fehlercode'); + $konfigurationsWert = $this->input->post('konfigurationsWert'); + + // check if Konfigurationstyp correctly passed + if (isEmptyString($konfigurationstyp_kurzbz)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'ungueltigerKonfigurationstyp')); + + // check if fehlercode correctly passed + if (isEmptyString($fehlercode)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlercodeFehlt')); + + // separate by semicolon if multiple values passed + $konfigurationsWert = explode(';', $konfigurationsWert); + + // check if konfiguration already set for the fehlercode + $this->FehlerkonfigurationModel->addSelect('konfiguration'); + $fehlerkonfigurationRes = $this->FehlerkonfigurationModel->loadWhere( + array( + 'konfigurationstyp_kurzbz' => $konfigurationstyp_kurzbz, + 'fehlercode' => $fehlercode + ) + ); + + if (!hasData($fehlerkonfigurationRes)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlerFehlerKonfigurationLaden')); + + // if konfiguration exists, update values + if (hasData($fehlerkonfigurationRes)) + { + $fehlerkonfiguration = getData($fehlerkonfigurationRes); + + $existingKonf = json_decode($fehlerkonfiguration[0]->konfiguration); + + if (!$existingKonf) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlerJsonDekodierung')); + + if (!is_array($existingKonf)) $existingKonf = array($existingKonf); + + $newKonfArr = array_values(array_diff($existingKonf, $konfigurationsWert)); + + // if no konfiguration values left, delete whole entry + if (isEmptyArray($newKonfArr)) + { + $this->outputJson( + $this->FehlerkonfigurationModel->delete( + array('konfigurationstyp_kurzbz' => $konfigurationstyp_kurzbz, 'fehlercode' => $fehlercode) + ) + ); + } + else + { + $newKonf = json_encode($newKonfArr); + if (!$newKonf) $this->terminateWithJsonError("error when encoding JSON"); + + // if there are still values, delete only part of the konfiguration + $this->outputJson( + $this->FehlerkonfigurationModel->update( + array('konfigurationstyp_kurzbz' => $konfigurationstyp_kurzbz, 'fehlercode' => $fehlercode), + array('konfiguration' => $newKonf, 'updateamum' => 'NOW()', 'updatevon' => $this->_uid) + ) + ); + } + } + } + + /** + * Deletes a Konfiguration. + */ + public function deleteKonfiguration() + { + $konfigurationstyp_kurzbz = $this->input->post('konfigurationstyp_kurzbz'); + $fehlercode = $this->input->post('fehlercode'); + + // check if Konfigurationstyp correctly passed + if (isEmptyString($konfigurationstyp_kurzbz)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'ungueltigerKonfigurationstyp')); + + // check if fehlercode correctly passed + if (isEmptyString($fehlercode)) $this->terminateWithJsonError($this->p->t('fehlermonitoring', 'fehlercodeFehlt')); + + $this->outputJson( + $this->FehlerkonfigurationModel->delete( + array('konfigurationstyp_kurzbz' => $konfigurationstyp_kurzbz, 'fehlercode' => $fehlercode) + ) + ); + } + + /** + * 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'); + } +} diff --git a/application/controllers/system/issues/IssuesZustaendigkeiten.php b/application/controllers/system/issues/IssuesZustaendigkeiten.php index fd3e6192a..d7bf9836e 100644 --- a/application/controllers/system/issues/IssuesZustaendigkeiten.php +++ b/application/controllers/system/issues/IssuesZustaendigkeiten.php @@ -26,7 +26,6 @@ class IssuesZustaendigkeiten extends Auth_Controller // Load models $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); $this->load->model('system/Fehler_model', 'FehlerModel'); - $this->load->model('system/Fehler_model', 'FehlerModel'); $this->load->model('system/Fehlerzustaendigkeiten_model', 'FehlerzustaendigkeitenModel'); $this->loadPhrases( @@ -70,7 +69,7 @@ class IssuesZustaendigkeiten extends Auth_Controller { $app = $this->input->get('app'); - //$this->FehlerModel->addSelect('fehlercode, fehler_kurzbz, fehlertext, fehlertyp_kurzbz'); + $this->FehlerModel->addSelect('fehlercode, fehler_kurzbz, fehlertext, fehlertyp_kurzbz, app'); $this->FehlerModel->addOrder('fehlercode'); $fehlerRes = isset($app) ? $this->FehlerModel->loadWhere(array('app' => $app)) : $this->FehlerModel->load(); diff --git a/application/controllers/system/issues/Plausichecks.php b/application/controllers/system/issues/Plausichecks.php new file mode 100644 index 000000000..53ff8afe8 --- /dev/null +++ b/application/controllers/system/issues/Plausichecks.php @@ -0,0 +1,194 @@ + array('system/issues_verwalten:r'), + 'runChecks' => array('system/issues_verwalten:r') + ) + ); + + // Load libraries + $this->load->library('issues/PlausicheckProducerLib', array('app' => 'core')); + $this->load->library('issues/PlausicheckDefinitionLib'); + $this->load->library('WidgetLib'); + + // Load models + $this->load->model('system/Fehler_model', 'FehlerModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + } + + /* + * Get data for filtering the plausichecks and load the view. + */ + public function index() + { + $filterData = $this->_getFilterData(); + $this->load->view('system/issues/plausichecks', $filterData); + } + + /** + * Initiate plausichecks run. + */ + public function runChecks() + { + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + $studiengang_kz = $this->input->get('studiengang_kz'); + $fehler_kurzbz = $this->input->get('fehler_kurzbz'); + + // issues array for passing issue texts + $allIssues = array(); + // all fehler kurzbz which are going to be checked + $fehlerKurzbz = !isEmptyString($fehler_kurzbz) ? array($fehler_kurzbz) : $this->plausicheckdefinitionlib->getFehlerKurzbz(); + $fehlerLibMappings = $this->plausicheckdefinitionlib->getFehlerLibMappings(); + // set Studiengang to null if not passed + if (isEmptyString($studiengang_kz)) $studiengang_kz = null; + + // get the data returned by Plausicheck + foreach ($fehlerKurzbz as $fehler_kurzbz) + { + // get Text and fehlercode of the Fehler + $this->FehlerModel->addSelect('fehlercode, fehlertext, fehlertyp_kurzbz'); + $fehlerRes = $this->FehlerModel->loadWhere(array('fehler_kurzbz' => $fehler_kurzbz)); + + if (isError($fehlerRes)) $this->terminateWithJsonError(getError($fehlerRes)); + + // do not check error if no data + if (!hasData($fehlerRes)) continue; + + // get the error data + $fehler = getData($fehlerRes)[0]; + + // initialize issue array + $allIssues[$fehler_kurzbz] = array('fehlercode' => $fehler->fehlercode, 'data' => array()); + + // get library name for producing issue + $libName = $fehlerLibMappings[$fehler_kurzbz]; + + // execute the check + $plausicheckRes = $this->plausicheckproducerlib->producePlausicheckIssue( + $libName, + $fehler_kurzbz, + array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $studiengang_kz + ) + ); + + if (isError($plausicheckRes)) $this->terminateWithJsonError(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; + + // optionally replace fehler parameters in text, output the fehlertext + if (!isEmptyString($fehler->fehlertext)) + { + $fehlercode = $fehler->fehlercode; + $fehlerText = $fehler->fehlertext; + $fehlerTyp = $fehler->fehlertyp_kurzbz; + + if (!isEmptyArray($fehlertext_params)) + { + // replace placeholder with params, if present + if (count($fehlertext_params) != substr_count($fehlerText, '%s')) + $this->terminateWithJsonError('Wrong number of parameters for Fehlertext, fehler_kurzbz ' . $fehler_kurzbz); + + $fehlerText = vsprintf($fehlerText, $fehlertext_params); + } + + if (isset($person_id)) $fehlerText .= "; person_id: $person_id"; + if (isset($oe_kurzbz)) $fehlerText .= "; oe_kurzbz: $oe_kurzbz"; + + $issueObj = new StdClass(); + $issueObj->fehlertext = $fehlerText; + $issueObj->type = $fehlerTyp; + $allIssues[$fehler_kurzbz]['data'][] = $issueObj; + } + else // if no issue text found, use generic text + { + $fehlerText = self::GENERIC_ISSUE_OCCURED_TEXT; + } + + // add generic parameters to issue text + if (isset($person_id)) $fehlerText .= "; person_id: $person_id"; + if (isset($oe_kurzbz)) $fehlerText .= "; oe_kurzbz: $oe_kurzbz"; + } + } + } + + $this->outputJsonSuccess($allIssues); + } + + /** + * Get the data needed for filtering for limiting checks. + */ + private function _getFilterData() + { + $this->StudiensemesterModel->addOrder('start', 'DESC'); + $studiensemesterRes = $this->StudiensemesterModel->load(); + + if (isError($studiensemesterRes)) show_error(getError($studiensemesterRes)); + + $currSemRes = $this->StudiensemesterModel->getAkt(); + + if (isError($currSemRes)) show_error(getError($currSemRes)); + + $this->StudiengangModel->addSelect('studiengang_kz, tbl_studiengang.bezeichnung, tbl_studiengang.typ, + tbl_studiengangstyp.bezeichnung AS typbezeichnung, UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel'); + $this->StudiengangModel->addJoin('public.tbl_studiengangstyp', 'typ'); + $this->StudiengangModel->addOrder('kuerzel, tbl_studiengang.bezeichnung, studiengang_kz'); + $studiengaengeRes = $this->StudiengangModel->loadWhere(array('aktiv' => true)); + + if (isError($studiengaengeRes)) show_error(getError($studiengaengeRes)); + + $fehlerKurzbz = $this->plausicheckdefinitionlib->getFehlerKurzbz(); + + $db = new DB_Model(); + + // get fehlercodes for fehler_kurzbz + $fehlerRes = $db->execReadOnlyQuery( + 'SELECT + fehler_kurzbz, fehlercode + FROM + system.tbl_fehler + WHERE + fehler_kurzbz IN ?', + array($fehlerKurzbz) + ); + + if (isError($fehlerRes)) show_error(getError($fehlerRes)); + + $fehlerKurzbzCodeMappings = array(); + if (hasData($fehlerRes)) + { + $fehler = getData($fehlerRes); + foreach ($fehler as $fe) + { + $fehlerKurzbzCodeMappings[$fe->fehler_kurzbz] = $fe->fehlercode; + } + } + + return array( + 'semester' => hasData($studiensemesterRes) ? getData($studiensemesterRes) : array(), + 'currsemester' => hasData($currSemRes) ? getData($currSemRes) : array(), + 'studiengaenge' => hasData($studiengaengeRes) ? getData($studiengaengeRes) : array(), + 'fehlerKurzbzCodeMappings' => $fehlerKurzbzCodeMappings + ); + } +} 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..37f6c3f21 --- /dev/null +++ b/application/core/CI3_Events.php @@ -0,0 +1,65 @@ +. + */ + +use \stdClass as stdClass; + if (!defined('BASEPATH')) exit('No direct script access allowed'); /** @@ -27,16 +46,28 @@ 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, ... protected $hasSequence; // False if this table has a composite primary key that is not using a sequence // True if this table has a primary key that uses a sequence + //protected $paginationOptions; // $page and $page_size together in an associative array + protected $page; + protected $page_size; private $executedQueryMetaData; private $executedQueryListFields; - private $debugMode; + private $debugMode; // Debug mode enable (true) or disabled (false) /** * Constructor @@ -46,20 +77,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 +119,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 +176,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 +203,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 +269,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 +290,7 @@ class DB_Model extends CI_Model $tmpId = array($this->pk => $id); } - return $this->loadWhere($tmpId); + return $this->loadWhere($tmpId, $encryptedColumns); } /** @@ -253,11 +298,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 +313,7 @@ class DB_Model extends CI_Model if ($result) { - return success($this->_toPhp($result)); + return success($this->_toPhp($result, $encryptedColumns)); } else { @@ -303,7 +351,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 +430,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; @@ -484,7 +534,7 @@ class DB_Model extends CI_Model if (!is_numeric($start) || (is_numeric($start) && $start <= 0)) return error('The start parameter is not valid', EXIT_MODEL); - if (is_numeric($end) && $end > $start) + if (is_numeric($end)) { $this->db->limit($start, $end); } @@ -758,14 +808,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 +824,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 +856,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 +881,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 +909,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 +921,213 @@ 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 = preg_replace_callback( + '/(? $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 = preg_replace_callback( + '/(?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 +1172,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 +1188,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 +1198,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 +1261,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}); + } + } } } } @@ -1073,5 +1368,51 @@ class DB_Model extends CI_Model return $udfs; } + + /** + * addPagination + * adds a limit and an optional offset depending on the arguments passed to the function + * @param int $page page to be queried + * @param int $page_size page_size used to calculate the offset of the pagination + * @param int | null $num_rows used to calculate the total amout of pages that are available with the $page and $page_size arguments + * + * @return void + */ + function addPagination( $page, $page_size, $num_rows=null) + { + if (isset($page) && is_numeric($page) && isset($page_size) && is_numeric($page_size) && $page > 0 && $page_size > 0) { + + if (isset($num_rows) && is_numeric($num_rows) && $num_rows > 0) { + $floatMaxPageCount = $num_rows / $page_size; + $maxPageCount = ceil($floatMaxPageCount); + if($page > $maxPageCount){ + $page = $maxPageCount; + } + } + $offset = (($page-1) * $page_size); + $this->addLimit($page_size, $offset); + + } else { + $this->addLimit($page_size); + } + } + + /** + * getQueryNumRows + * returns the number of rows of the current build query of the codeigniter query builder instance + * @param bool $reset resets the select of the query + * + * @return Result_object $num_rows + */ + function getNumRows($reset=false) + { + // returns the number of rows when executing the current query without reseting the select statement of the query + $num_rows = $this->db->count_all_results($this->dbTable,$reset); + if($num_rows){ + return success($num_rows); + }else{ + return error($this->db->error(), EXIT_DATABASE); + } + } } diff --git a/application/core/FHCAPI_Controller.php b/application/core/FHCAPI_Controller.php new file mode 100644 index 000000000..c1e57a0f2 --- /dev/null +++ b/application/core/FHCAPI_Controller.php @@ -0,0 +1,249 @@ +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 $key + * @return mixed + */ + public function getMeta($key) + { + if (!isset($this->returnObj['meta'])) + return null; + if (!isset($this->returnObj['meta'][$key])) + return null; + return $this->returnObj['meta'][$key]; + } + + /** + * @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 string|array|object $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 mixed + */ + 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 77d14f408..ea278ddb0 100755 --- a/application/core/IssueResolver_Controller.php +++ b/application/core/IssueResolver_Controller.php @@ -5,18 +5,18 @@ */ abstract class IssueResolver_Controller extends JOB_Controller { - const ISSUES_FOLDER = 'issues'; - 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'); } /** @@ -24,95 +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 = hasData($openIssuesRes) ? getData($openIssuesRes) : []; - $openIssues = getData($openIssuesRes); + $result = $this->plausicheckresolverlib->resolvePlausicheckIssues($openIssues); - foreach ($openIssues as $issue) - { - if (isset($this->_codeLibMappings[$issue->fehlercode])) - { - $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, otherwise it is the core library folder - $libRootPath = isset($this->_extensionName) ? 'extensions/' . $this->_extensionName . '/' : ''; - $issuesLibPath = $libRootPath . self::ISSUES_FOLDER . '/'; - $issuesLibFilePath = DOC_ROOT . 'application/' . $libRootPath . 'libraries/' . self::ISSUES_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 libary 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 new file mode 100644 index 000000000..5216d284c --- /dev/null +++ b/application/core/PlausiIssueProducer_Controller.php @@ -0,0 +1,28 @@ +load->library( + 'issues/PlausicheckProducerLib', + ['extensionName' => $this->_extensionName ?? null, 'app' => $this->_app, 'fehlerLibMappings' => $this->_fehlerLibMappings] + ); + + $this->logInfo("Plausicheck issue producer job started"); + + $result = $this->plausicheckproducerlib->producePlausicheckIssues($params); + + // 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/core/Tag_Controller.php b/application/core/Tag_Controller.php new file mode 100644 index 000000000..6f6cef31b --- /dev/null +++ b/application/core/Tag_Controller.php @@ -0,0 +1,187 @@ + self::BERECHTIGUNG_KURZBZ, + 'getTags' => self::BERECHTIGUNG_KURZBZ, + 'addTag' => self::BERECHTIGUNG_KURZBZ, + + 'updateTag' => self::BERECHTIGUNG_KURZBZ, + 'doneTag' => self::BERECHTIGUNG_KURZBZ, + 'deleteTag' => self::BERECHTIGUNG_KURZBZ, + ]; + + $merged_permissions = array_merge($default_permissions, $permissions); + + parent::__construct($merged_permissions); + + $this->_setAuthUID(); + $this->load->model('person/Notiz_model', 'NotizModel'); + $this->load->model('system/Notiztyp_model', 'NotiztypModel'); + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + } + + public function getTag() + { + $id = $this->input->get('id'); + + $this->NotizModel->addSelect( + 'tbl_notiz.titel, + tbl_notiz.text, + array_to_json(bezeichnung_mehrsprachig::varchar[])->>0 as bezeichnung, + tbl_notiz.notiz_id, + tbl_notiz_typ.style, + tbl_notiz.erledigt as done, + tbl_notiz.insertamum, + tbl_notiz.updateamum, + tbl_notiz.insertvon, + tbl_notiz.updatevon + ' + ); + $this->NotizModel->addJoin('public.tbl_notiz_typ', 'public.tbl_notiz.typ = public.tbl_notiz_typ.typ_kurzbz'); + $notiz = $this->NotizModel->loadWhere(array('notiz_id' => $id)); + + $this->terminateWithSuccess(hasData($notiz) ? getData($notiz)[0] : array()); + } + + public function getTags() + { + $this->NotiztypModel->addSelect( + 'typ_kurzbz as tag_typ_kurzbz, + array_to_json(bezeichnung_mehrsprachig::varchar[])->>0 as bezeichnung, + style, + beschreibung, + tag + ' + ); + $this->NotiztypModel->addOrder('prioritaet'); + $notiztypen = $this->NotiztypModel->loadWhere(array('aktiv' => true)); + $this->terminateWithSuccess(hasData($notiztypen) ? getData($notiztypen) : array()); + } + + public function addTag($withZuordnung = true) + { + $postData = $this->getPostJson(); + + $checkTyp = $this->NotiztypModel->loadWhere(array('typ_kurzbz' => $postData->tag_typ_kurzbz)); + + if (!hasData($checkTyp)) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + + if ($withZuordnung) + { + $return = array(); + $checkZuordnungType = $this->NotizzuordnungModel->isValidType($postData->zuordnung_typ); + if (!isSuccess($checkZuordnungType)) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + $values = array_unique($postData->values); + + foreach ($values as $value) + { + $insertResult = $this->addNotiz($postData); + + if (isError($insertResult)) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + $insertZuordnung = $this->NotizzuordnungModel->insert(array( + 'notiz_id' => $insertResult->retval, + $postData->zuordnung_typ => $value + )); + + if (isError($insertZuordnung)) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + $return[] = [$postData->zuordnung_typ => $value, 'id' => $insertResult->retval]; + } + $this->terminateWithSuccess($return); + } + else + { + $insertResult = $this->addNotiz($postData); + if (isError($insertResult)) + $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL); + + return $insertResult->retval; + } + } + + private function addNotiz($postData) + { + return $this->NotizModel->insert(array( + 'titel' => 'TAG', //TODO klären + 'text' => $postData->notiz, + 'verfasser_uid' => $this->_uid, + 'erledigt' => false, + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => $this->_uid, + 'typ' => $postData->tag_typ_kurzbz + )); + + } + public function updateTag() + { + $postData = $this->getPostJson(); + $updateData = $this->NotizModel->update(array('notiz_id' => $postData->id), + array('text' => $postData->notiz) + ); + $this->terminateWithSuccess($updateData); + } + public function doneTag() + { + $postData = $this->getPostJson(); + $updateData = $this->NotizModel->update(array('notiz_id' => $postData->id), + array('erledigt' => !$postData->done) + ); + + $this->terminateWithSuccess($updateData); + } + + public function deleteTag($withZuordnung = true) + { + $postData = $this->getPostJson(); + + $deleteNotiz = ""; + if ($withZuordnung) + { + $deleteZuordnung = $this->NotizzuordnungModel->delete(array( + 'notiz_id' => $postData->id + )); + + if (isSuccess($deleteZuordnung)) + { + $deleteNotiz = $this->NotizModel->delete(array( + 'notiz_id' => $postData->id + )); + } + } + else + { + $deleteNotiz = $this->NotizModel->delete(array( + 'notiz_id' => $postData->id + )); + } + $this->terminateWithSuccess($deleteNotiz); + } + + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) + show_error('User authentification failed'); + } + + +} \ No newline at end of file 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/helpers/hlp_return_object_helper.php b/application/helpers/hlp_return_object_helper.php index cc896856d..602008d3b 100644 --- a/application/helpers/hlp_return_object_helper.php +++ b/application/helpers/hlp_return_object_helper.php @@ -25,6 +25,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** * Used to create a return object, should not be used directly + * @return stdClass */ function _createReturnObject($code, $error, $retval) { @@ -39,7 +40,7 @@ function _createReturnObject($code, $error, $retval) /** * Success * - * @return array + * @return stdClass */ function success($retval = null, $code = null) { @@ -49,7 +50,7 @@ function success($retval = null, $code = null) /** * Error * - * @return array + * @return stdClass */ function error($retval = null, $code = null) { diff --git a/application/helpers/hlp_sancho_helper.php b/application/helpers/hlp_sancho_helper.php index d599e40bc..9a32f5e1a 100644 --- a/application/helpers/hlp_sancho_helper.php +++ b/application/helpers/hlp_sancho_helper.php @@ -23,9 +23,6 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); // Functions needed in the view FHC-Header // ------------------------------------------------------------------------ -const DEFAULT_SANCHO_HEADER_IMG = 'sancho_header_DEFAULT.jpg'; -const DEFAULT_SANCHO_FOOTER_IMG = 'sancho_footer_DEFAULT.jpg'; - /** * Send single Mail with Sancho Design and Layout. * @param string $vorlage_kurzbz Name of the template for specific mail content. @@ -38,27 +35,88 @@ const DEFAULT_SANCHO_FOOTER_IMG = 'sancho_footer_DEFAULT.jpg'; * @param string $bcc Sets BCC of mail. * @return void */ -function sendSanchoMail($vorlage_kurzbz, $vorlage_data, $to, $subject, $headerImg = DEFAULT_SANCHO_HEADER_IMG, $footerImg = DEFAULT_SANCHO_FOOTER_IMG, $from = null, $cc = null, $bcc = null) +function sendSanchoMail( + $vorlage_kurzbz, + $vorlage_data, + $to, + $subject, + $headerImg = '', + $footerImg = '', + $from = null, + $cc = null, + $bcc = null +) { $ci =& get_instance(); $ci->load->library('email'); $ci->load->library('MailLib'); - $sanchoHeader_img = 'skin/images/sancho/'. $headerImg; - $sanchoFooter_img = 'skin/images/sancho/'. $footerImg; + $sancho_mail_config = $ci->config->item('mail'); + if ($from == '') { - $from = 'sancho@'.DOMAIN; + $from = ((isset($sancho_mail_config['sancho_mail_default_sender']) + && $sancho_mail_config['sancho_mail_default_sender']) + ? $sancho_mail_config['sancho_mail_default_sender'] + : 'noreply') + . '@' . DOMAIN; } // Embed sancho header and footer image // reset important to ensure embedding of images when called in a loop $ci->email->clear(true); // clear vars and attachments - $ci->email->attach($sanchoHeader_img); - $ci->email->attach($sanchoFooter_img); - $cid_header = $ci->email->attachment_cid($sanchoHeader_img); // sets unique content id for embedding - $cid_footer = $ci->email->attachment_cid($sanchoFooter_img); // sets unique content id for embedding + + $cid_header = ''; + $cid_footer = ''; + + if (isset($sancho_mail_config['sancho_mail_use_images']) && $sancho_mail_config['sancho_mail_use_images']) + { + $sanchoHeader_img = ''; + $sanchoFooter_img = ''; + + if (isset($headerImg) && $headerImg != '') + { + // use provided header image + $sanchoHeader_img = $headerImg; + } + elseif (isset($sancho_mail_config['sancho_mail_header_img']) && $sancho_mail_config['sancho_mail_header_img']) + { + // use default header image + $sanchoHeader_img = $sancho_mail_config['sancho_mail_header_img']; + } + + if (isset($footerImg) && $footerImg != '') + { + // use provided footer image + $sanchoFooter_img = $footerImg; + } + elseif (isset($sancho_mail_config['sancho_mail_footer_img']) && $sancho_mail_config['sancho_mail_footer_img']) + { + // use default footer image + $sanchoFooter_img = $sancho_mail_config['sancho_mail_footer_img']; + } + + // add image file paths + if (isset($sancho_mail_config['sancho_mail_img_path'])) + { + if ($sanchoHeader_img != '') + { + $sanchoHeader_img = $sancho_mail_config['sancho_mail_img_path'].$sanchoHeader_img; + } + + if ($sanchoFooter_img != '') + { + $sanchoFooter_img = $sancho_mail_config['sancho_mail_img_path'].$sanchoFooter_img; + } + } + + // attach header and footer + $ci->email->attach($sanchoHeader_img, 'inline'); + $ci->email->attach($sanchoFooter_img, 'inline'); + $cid_header = $ci->email->attachment_cid($sanchoHeader_img); // sets unique content id for embedding + $cid_footer = $ci->email->attachment_cid($sanchoFooter_img); // sets unique content id for embedding + } // Set specific mail content into specific content template $content = _parseMailContent($vorlage_kurzbz, $vorlage_data); @@ -74,7 +132,18 @@ function sendSanchoMail($vorlage_kurzbz, $vorlage_data, $to, $subject, $headerIm $body = _parseMailContent('Sancho_Mail_Template', $layout); // Send mail - return $ci->maillib->send($from, $to, $subject, $body, $alias = '', $cc, $bcc, $altMessage = '', $bulk = true, $autogenerated = true); + return $ci->maillib->send( + $from, + $to, + $subject, + $body, + '', // alias + $cc, + $bcc, + '', // altMessage + true, // bulk + true // autogenerated + ); } /** 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->StudentModel->getUID($prestudent_id); - - // Get lehrveranstaltung data. Break, if course is not assigned to student. - if(!$lv = getData($this->ci->LehrveranstaltungModel->getLvByStudent($uid, $studiensemester_kurzbz, $lv_id))[0]) + + // If Anrechnung exists + if (is_numeric($anrechnung_id)) { - show_error('You are not assigned to this course yet.'); + // Just load LV by lv_id + $result = $this->ci->LehrveranstaltungModel->load($lv_id); + $lv = getData($result)[0]; } - + // If Anrechnung not exists + else + { + // Load LV, but check if student is assigned to that LV. Break, if not. + if(!$lv = getData($this->ci->LehrveranstaltungModel->getLvByStudent($uid, $studiensemester_kurzbz, $lv_id))[0]) + { + show_error('You are not assigned to this course yet.'); + } + } + // Get the students personal data if (!$person = getData($this->ci->PersonModel->getByUid($uid))[0]) { @@ -163,6 +174,8 @@ class AnrechnungLib $anrechnung_data->insertvon = ''; $anrechnung_data->studiensemester_kurzbz = ''; $anrechnung_data->empfehlung = ''; + $anrechnung_data->begruendung_ects = ''; + $anrechnung_data->begruendung_lvinhalt = ''; $anrechnung_data->status_kurzbz = ''; $anrechnung_data->status = getUserLanguage() == 'German' ? 'neu' : 'new'; $anrechnung_data->dokumentname = ''; @@ -274,14 +287,21 @@ class AnrechnungLib if (hasData($result)) { $empfehlung_data->empfehlungsanfrageAm = (new DateTime($result->retval[0]->insertamum))->format('d.m.Y'); - - // Get lectors who received request for recommendation - $lector_arr = self::getLectors($anrechnung_id); - - if (!isEmptyArray($lector_arr)) - { - $empfehlung_data->empfehlungsanfrageAn = implode(', ', array_column($lector_arr, 'fullname')); - } + + // Get users who received request for recommendation + if($this->ci->config->item('fbl') === TRUE) + { + $res = $this->getLeitungOfLvOe($anrechnung_id); + } + else + { + $res = $this->getLectors($anrechnung_id); + } + + if (!isEmptyArray($res)) + { + $empfehlung_data->empfehlungsanfrageAn = implode(', ', array_column($res, 'fullname')); + } } if (is_null($anrechnung->empfehlung_anrechnung)) @@ -741,6 +761,25 @@ class AnrechnungLib // Continue, if LV has no lector (there is no one to ask for recommendation) return hasData($result) ? true : false; } + + /** + * Check if user is allowed to recommend Anrechnung. + * + * @param $anrechnung_id + * @return bool + */ + public function isEmpfehlungsberechtigt($anrechnung_id) + { + if($this->ci->config->item('fbl') === TRUE) + { + return true; + } + // Get lv-leitungen or, if not present, all lectors of lv. + $lector_arr = $this->getLectors($anrechnung_id); + + // Return false if lv-leitung is present and user is not lv-leitung. Otherways return always true. + return in_array(getAuthUID(), array_column($lector_arr, 'uid')); + } /** * Get LV Leitung. If not present, get all LV lectors. @@ -774,11 +813,14 @@ class AnrechnungLib // Check if lv has LV-Leitung $key = array_search(true, array_column($result, 'lvleiter')); - - // If lv has LV-Leitung, keep only the one + + // If lv has 1 or more LV-Leitungen, keep only them if ($key !== false) { - $lector_arr[]= $result[$key]; + foreach ($result as $lector) + { + if ($lector->lvleiter) $lector_arr[]= $lector; + } } // ...otherwise keep all lectors else @@ -803,6 +845,40 @@ class AnrechnungLib return $lector_arr; } + /** + * Get Leitung of Lehrveranstaltungs-Organisationseinheit. + * + * @param $anrechnung_id + * @return false|mixed|null + */ + public function getLeitungOfLvOe($anrechnung_id) + { + $this->ci->AnrechnungModel->addSelect('lehrveranstaltung_id'); + $result = $this->ci->AnrechnungModel->load($anrechnung_id); + + $lehrveranstaltung_id = getData($result)[0]->lehrveranstaltung_id; + + // Get Leitungen + $result = $this->ci->LehrveranstaltungModel->getLeitungOfLvOe($lehrveranstaltung_id); + + if (!hasData($result)) + { + return false; + } + + $oeLeitung_arr = getData($result); + + foreach ($oeLeitung_arr as $oeLeitung) + { + $oeLeitung->fullname = $oeLeitung->vorname. ' '. $oeLeitung->nachname; + } + + // Now make the array unique + $oeLeitung_arr = array_unique($oeLeitung_arr, SORT_REGULAR); + + return $oeLeitung_arr; + } + // Return an object with Anrechnungdata private function _setAnrechnungDataObject($anrechnung) { @@ -820,6 +896,8 @@ class AnrechnungLib $anrechnung_data->insertvon= $anrechnung->insertvon; $anrechnung_data->studiensemester_kurzbz= $anrechnung->studiensemester_kurzbz; $anrechnung_data->empfehlung= $anrechnung->empfehlung_anrechnung; + $anrechnung_data->begruendung_ects = $anrechnung->begruendung_ects; + $anrechnung_data->begruendung_lvinhalt = $anrechnung->begruendung_lvinhalt; // Get last status_kurzbz $result = $this->ci->AnrechnungModel->getLastAnrechnungstatus($anrechnung->anrechnung_id); diff --git a/application/libraries/AntragLib.php b/application/libraries/AntragLib.php new file mode 100644 index 000000000..885acac90 --- /dev/null +++ b/application/libraries/AntragLib.php @@ -0,0 +1,2196 @@ +_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/AuthLib.php b/application/libraries/AuthLib.php index ae30d41fa..de9c15350 100644 --- a/application/libraries/AuthLib.php +++ b/application/libraries/AuthLib.php @@ -551,10 +551,7 @@ class AuthLib // Needed information $this->_ci->PersonModel->addSelect('person_id, vorname, nachname, uid'); // Retrieves the uid if it is possible for active users - $this->_ci->PersonModel->addJoin( - '(SELECT uid, person_id FROM public.tbl_benutzer WHERE aktiv = TRUE) tb', 'person_id', - 'LEFT' - ); + $this->_ci->PersonModel->addJoin('public.tbl_benutzer', 'person_id', 'LEFT'); // Execute query with where clause $personResult = $this->_ci->PersonModel->loadWhere($queryParamsArray); diff --git a/application/libraries/CmsLib.php b/application/libraries/CmsLib.php new file mode 100644 index 000000000..b65e2a71c --- /dev/null +++ b/application/libraries/CmsLib.php @@ -0,0 +1,297 @@ +ci =& get_instance(); + + // Load Models + $this->ci->load->model('content/Content_model', 'ContentModel'); + $this->ci->load->model('content/Contentgruppe_model', 'ContentgruppeModel'); + $this->ci->load->model('content/Template_model', 'TemplateModel'); + if (defined('LOG_CONTENT') && LOG_CONTENT) + $this->ci->load->model('system/Webservicelog_model', 'WebservicelogModel'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @param int $content_id + * @param int $version + * @param string $sprache + * @param boolean $sichtbar + * + * @return void + */ + public function getContent($content_id, $version = null, $sprache = null, $sichtbar = true) + { + if (!is_numeric($content_id)) + return error('ContentID ist ungueltig'); + + if ($sprache === null) + $sprache = getUserLanguage(); + + $islocked = $this->ci->ContentgruppeModel->loadWhere(['content_id' => $content_id]); + if (isError($islocked)) + return $islocked; + + if (getData($islocked)) { + $uid = getAuthUID(); + $isberechtigt = $this->ci->ContentgruppeModel->berechtigt($content_id, $uid); + if (isError($isberechtigt)) + return $isberechtigt; + + if (!getData($isberechtigt)) + return error('global/keineBerechtigungFuerDieseSeite'); + } + $content = $this->ci->ContentModel->getContent($content_id, $sprache, $version, $sichtbar, true); + + if (isError($content)) + return $content; + + // Legt einen Logeintrag für die Klickstatistik an + if (defined('LOG_CONTENT') && LOG_CONTENT) { + // Nur eingeloggte User werden geloggt, das sonst auch alle Infoscreenaufrufe und dgl. mitgeloggt werden + if (isLogged()) { + $request_data = 'content_id=' . $content_id; + if ($version !== null) + $request_data .= '&version=' . $version; + if ($sichtbar !== true) + $request_data .= '&sichtbar=' . $sichtbar; + $this->ci->WebservicelogModel->insert([ + 'webservicetyp_kurzbz' => 'content', + 'request_id' => $content_id, + 'beschreibung' => 'content', + 'request_data' => $request_data . '&sprache=' . $sprache, + 'execute_time' => 'now()', + 'execute_user' => getAuthUID() + ]); + } + } + + $content = getData($content); + + //XSLT Vorlage laden + $template = $this->ci->TemplateModel->load($content->template_kurzbz); + if (isError($template)) + return $template; + $template = current(getData($template)); + + $XML = new DOMDocument(); + $XML->loadXML($content->content); + + if($content->titel){ + $betreff = $content->titel; + }else{ + $betreff = $XML->getElementsByTagName('betreff'); + } + + $xsltemplate = new DOMDocument(); + $xsltemplate->loadXML($template->xslt_xhtml_c4); + + //Transformation + $processor = new XSLTProcessor(); + $processor->importStylesheet($xsltemplate); + + + $transformed_content = $processor->transformToXML($XML); + //replaces all the dms.php with the new CIS4 Controller + $transformed_content = str_replace('dms.php', APP_ROOT . 'cms/dms.php', $transformed_content); + //replaces all the cms.php with the new CIS4 Controller + $transformed_content = preg_replace('/content\.php\?content\_id\=([0-9]+)/', APP_ROOT.'cis.php/CisVue/Cms/content/$1', $transformed_content); + + return success([ + "betreff"=>$betreff, + "type"=>$content->template_kurzbz, + "content"=>$transformed_content + ]); + } + + /** + * @param stdClass $stg_obj + * + * @return stdClass + */ + protected function getNewsExtras($stg_obj, $semester) + { + $this->ci->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + + $stg_ltg = $this->ci->StudiengangModel->getLeitungDetailed($stg_obj->studiengang_kz); + if (isError($stg_ltg)) + return $stg_ltg; + $stg_ltg = getData($stg_ltg) ?: []; + + $gf_ltg = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('gLtg', $stg_obj->oe_kurzbz); + if (isError($gf_ltg)) + return $gf_ltg; + $gf_ltg = getData($gf_ltg) ?: []; + + $stv_ltg = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('stvLtg', $stg_obj->oe_kurzbz); + if (isError($stv_ltg)) + return $stv_ltg; + $stv_ltg = getData($stv_ltg) ?: []; + + $ass = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('ass', $stg_obj->oe_kurzbz); + if (isError($ass)) + return $ass; + $ass = getData($ass) ?: []; + + $hochschulvertr = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('hsv'); + if (isError($hochschulvertr)) + return $hochschulvertr; + $hochschulvertr = getData($hochschulvertr) ?: []; + + $stdv = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('stdv', $stg_obj->oe_kurzbz); + if (isError($stdv)) + return $stdv; + $stdv = getData($stdv) ?: []; + + $jahrgangsvertr = $this->ci->BenutzerfunktionModel->getBenutzerFunktionenDetailed('jgv', $stg_obj->oe_kurzbz, $semester); + if (isError($jahrgangsvertr)) + return $jahrgangsvertr; + $jahrgangsvertr = getData($jahrgangsvertr) ?: []; + + return success($this->ci->load->view('Cis/Cms/News/Xml/NewsExtras', [ + 'studiengang' => $stg_obj, + 'semester' => $semester, + 'stg_ltg' => $stg_ltg, + 'gf_ltg' => $gf_ltg, + 'stv_ltg' => $stv_ltg, + 'ass' => $ass, + 'hochschulvertr' => $hochschulvertr, + 'stdv' => $stdv, + 'jahrgangsvertr' => $jahrgangsvertr + ], true)); + } + + /** + * @param string $studiengang_kz + * @param string $semester + * + * @return array queried studiengang_kz and semester + */ + public function getStgAndSem($studiengang_kz, $semester) + { + $this->ci->load->model('crm/Student_model', 'StudentModel'); + + //Zum anzeigen der Studiengang-Details neben den News + $student = $this->ci->StudentModel->loadWhere(['student_uid' => getAuthUID()]); + if (isError($student)) + return $student; + if (getData($student)) { + $student = current(getData($student)); + if ($studiengang_kz === null) + $studiengang_kz = $student->studiengang_kz; + if ($semester === null) + $semester = $student->semester; + } + return [$studiengang_kz, $semester]; + } + + /** + * @param boolean $infoscreen + * @param string | null $studiengang_kz + * @param int | null $semester + * @param boolean $mischen + * @param string $titel + * @param boolean $edit + * @param boolean $sichtbar + * + * @return void + */ + public function getNews($infoscreen = false, $studiengang_kz = null, $semester = null, $mischen = true, $titel = '', $edit = false, $sichtbar = true, $page = 1, $page_size = 10) + { + $this->ci->load->model('organisation/Studiengang_model', 'StudiengangModel'); + list($studiengang_kz, $semester) = $this->getStgAndSem($studiengang_kz, $semester); + $all = $edit; + + $xml = ''; + + $this->ci->load->model('content/News_model', 'NewsModel'); + $news = $this->ci->NewsModel->getNewsWithContent(getSprache(), $studiengang_kz, $semester, null, $sichtbar, 0, $page, $page_size, $all, $mischen); + + if (isError($news)) + return $news; + + $news = getData($news); + //var_dump($news->maxPageCount); + foreach ($news as $newsobj) { + if ($studiengang_kz && $edit && !$newsobj->studiengang_kz) + continue; + $date = new DateTime($newsobj->datum); + $datum = 'format('d.m.Y') . ']]>'; + $datum .= 'format('Y-m-d H:i') . ']]>'; + $id = $edit ? 'news_id . ']]>' : ''; + $xml .= "" . $newsobj->content . $datum . $id . ""; + } + + if ($studiengang_kz != 0) { + $stg_obj = $this->ci->StudiengangModel->load($studiengang_kz); + if (isError($stg_obj)) + return $stg_obj; + $stg_obj = current(getData($stg_obj) ?: []); + + if ($stg_obj) { + if (!$edit && !$infoscreen) { + $extras = $this->getNewsExtras($stg_obj, $semester); + if (isError($extras)) + return $extras; + $xml .= getData($extras); + } + $xml .= 'bezeichnung . ']]>'; + } + } + + if ($titel != '') { + $xml .= '' . $titel . ''; + } + + $xml .= ''; + + //XSLT Vorlage laden + $template = $this->ci->TemplateModel->load($infoscreen ? 'news_infoscreen' : 'news'); + if (isError($template)) + return $template; + $template = current(getData($template)); + + $XML = new DOMDocument(); + $XML->loadXML($xml); + + $xsltemplate = new DOMDocument(); + $xsltemplate->loadXML($template->xslt_xhtml_c4); + + //Transformation + $processor = new XSLTProcessor(); + $processor->importStylesheet($xsltemplate); + + $content = $processor->transformToDoc($XML); + $content->formatOutput = true; + + $content = $content->saveHTML(); + $content = str_replace('dms.php', APP_ROOT . 'cms/dms.php', $content); + + return success($content); + } +} 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/DocsboxLib.php b/application/libraries/DocsboxLib.php new file mode 100644 index 000000000..f9167c379 --- /dev/null +++ b/application/libraries/DocsboxLib.php @@ -0,0 +1,304 @@ +attach(array('file' => $inputFileName)) + ->expectsJson() + ->send(); + + // Checks that: + // - the response is not empty + // - the reponse body has the property id + // - the property id is a valid string + // - the reponse body has the property status + // - docsbox queued the conversion of the posted file + if (is_object($postFileResponse) + && isset($postFileResponse->body) + && isset($postFileResponse->body->id) + && $postFileResponse->body->id != '' && $postFileResponse->body->id != null + && isset($postFileResponse->body->status) + && $postFileResponse->body->status == self::STATUS_QUEUED) + { + $queueId = $postFileResponse->body->id; + } + else + { + // If docsbox refused to convert the posted file + if (isset($postFileResponse->body->status) + && $postFileResponse->body->status != self::STATUS_QUEUED) + { + error_log( + 'Docsbox did not queue the posted file. Returned status: '. + $postFileResponse->body->status + ); + } + else // any other generic error + { + error_log( + 'An error occurred while posting to docsbox. Response: '. + print_r($postFileResponse, 1) + ); + } + } + } + catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception + { + error_log($cee->getMessage()); + } + catch (Exception $e) // any other exception + { + error_log($e->getMessage()); + } + + return $queueId; + } + + /** + * Check the status of the file convertion identified by the given queue element id + * A URL is returned with the path where it is possible to download the converted file + * If an error occurred then a null value is returned + */ + private static function _checkConvertion($queueId) + { + $resultUrl = null; + $startConvertionsTime = time(); // time when the file conversion has started + + // Until a timeout has occurred + while (time() - $startConvertionsTime <= DOCSBOX_CONVERSION_TIMEOUT) + { + sleep(DOCSBOX_WAITING_SLEEP_TIME); // takes a nap on every round + + try + { + // Calls the docsbox server to check the status of the + // file conversion using the provided queue id + // it expects a response in JSON format + $getStatusResponse = \Httpful\Request::get(DOCSBOX_SERVER.DOCSBOX_PATH_API.$queueId) + ->expectsJson() + ->send(); + + // Checks that: + // - the response is not empty + // - the reponse body has the property id + // - the property id is a valid string + // - the reponse body has the property status + // - docsbox is working the conversion of the posted file + if (is_object($getStatusResponse) + && isset($getStatusResponse->body->id) + && $getStatusResponse->body->id != '' && $getStatusResponse->body->id != null + && isset($getStatusResponse->body->status)) + { + // Checks that docsbox has finished working on the file conversion + // and that there is a valid resultUrl property + if ($getStatusResponse->body->status == self::STATUS_FINISHED + && isset($getStatusResponse->body->result_url) + && $getStatusResponse->body->result_url != '' + && $getStatusResponse->body->result_url != null) + { + $resultUrl = $getStatusResponse->body->result_url; + break; + } + // Just started or still working on it + elseif ($getStatusResponse->body->status == self::STATUS_WORKING + || $getStatusResponse->body->status == self::STATUS_STARTED) + { + // go on! + } + else // any other status is abnormal + { + error_log( + 'Not valid status for queue element: '.$queueId.'. Response: '. + print_r($getStatusResponse, 1) + ); + break; // interrupt the loop on error + } + } + else // if the response from the docsbox server is not valid + { + error_log( + 'An error occurred while checking the docsbox activity. Response: '. + print_r($getStatusResponse, 1) + ); + break; // interrupt the loop on error + } + } + catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception + { + error_log($cee->getMessage()); + break; // interrupt the loop on error + } + catch (Exception $e) // any other exception + { + error_log($e->getMessage()); + break; // interrupt the loop on error + } + } + + return $resultUrl; + } + + /** + * Download the converted file using the provided URL, unzip it, and renames it into the provided file name + */ + private static function _downloadFile($resultUrl, $outputFileName) + { + $downloaded = false; // pessimistic assumption + + try + { + // Download the file + $getFileResponse = \Httpful\Request::get(DOCSBOX_SERVER.$resultUrl)->send(); + + // If the downloaded file content is valid and not empty + if (isset($getFileResponse->body) + && $getFileResponse->body != null + && $getFileResponse->body != '') + { + // Output directory where to unzip the downloaded zip file + $outputDirectory = dirname($outputFileName); + // The path and name of the downloaded zip file + $temporaryDownloadedZip = sys_get_temp_dir().'/'.basename($resultUrl); + + // Write the file content into a temporary directory and file + if (file_put_contents($temporaryDownloadedZip, $getFileResponse->body) != false) + { + $zipArchive = new ZipArchive; + + // Open and extract the dowloaded zip file into the directory of the output file + if ($zipArchive->open($temporaryDownloadedZip) === true + && $zipArchive->extractTo($outputDirectory) === true + && $zipArchive->close() === true) + { + // Opened, extracted and closed! + + // Rename the extracted file to the given output file name + if (rename($outputDirectory.'/'.self::OUTPUT_FILENAME, $outputFileName)) + { + $downloaded = true; + } + else + { + error_log( + 'An error occurred while renaming the extracted file: '. + $outputDirectory.'/'.self::OUTPUT_FILENAME.' into: '. + $outputFileName + ); + } + } + else + { + error_log( + 'An error occurred while working the dowloaded zip file: '. + $temporaryDownloadedZip + ); + } + } + else // if an error occurred while writing + { + error_log( + 'An error occurred while writing the file content to: '. + $temporaryDownloadedZip + ); + } + } + else // if the downloaded file is not valid + { + error_log( + 'An error occurred while downloading the file from the docsbox server: '. + print_r($getFileResponse, 1) + ); + } + } + catch(\Httpful\Exception\ConnectionErrorException $cee) + { + error_log($cee->getMessage()); + } + catch (Exception $e) + { + error_log($e->getMessage()); + } + + return $downloaded; + } +} + diff --git a/application/libraries/DocumentLib.php b/application/libraries/DocumentLib.php index 98e546b4e..c1dd21c29 100644 --- a/application/libraries/DocumentLib.php +++ b/application/libraries/DocumentLib.php @@ -14,20 +14,28 @@ class DocumentLib // Gets CI instance $this->ci =& get_instance(); - exec('unoconv --version', $ret_arr); - - if(isset($ret_arr[0])) + // Which document converter has to be used + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) { - $hlp = explode(' ', $ret_arr[0]); - if(isset($hlp[1])) - { - $this->unoconv_version = $hlp[1]; - } - else - show_error('Could not get Unoconv Version'); + // Use docsbox!! } else - show_error('Unoconv not found - Please install Unoconv'); + { + exec('unoconv --version', $ret_arr); + + if(isset($ret_arr[0])) + { + $hlp = explode(' ', $ret_arr[0]); + if(isset($hlp[1])) + { + $this->unoconv_version = $hlp[1]; + } + else + show_error('Could not get Unoconv Version'); + } + else + show_error('Unoconv not found - Please install Unoconv'); + } } /** @@ -57,9 +65,16 @@ class DocumentLib case 'application/vnd.ms-word': case 'application/vnd.oasis.opendocument.text': case 'text/plain': - // Unoconv Version 0.6 seems to fail on converting TXT Files - if ($this->unoconv_version == '0.6') - return error(); + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) + { + // Use docsbox + } + else + { + // Unoconv Version 0.6 seems to fail on converting TXT Files + if ($this->unoconv_version == '0.6') + return error(); + } $ret = $this->convert($filename, $outFile, 'pdf'); if(isSuccess($ret)) @@ -105,6 +120,7 @@ class DocumentLib finfo_close($finfo); + $out = null; exec($cmd, $out, $ret); if ($ret != 0) { @@ -123,13 +139,26 @@ class DocumentLib */ public function convert($inFile, $outFile, $format) { - if ($this->unoconv_version == '0.6') - $command = 'unoconv -f %1$s %3$s > %2$s'; - else - $command = 'unoconv -f %s --output %s %s 2>&1'; - $command = sprintf($command, $format, $outFile, $inFile); + $ret = 0; - exec($command, $out, $ret); + // If it is set to use docsbox + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) + { + require_once(dirname(__FILE__).'/../application/libraries/DocsboxLib.php'); + + $ret = DocsboxLib::convert($inFile, $outFile, $format); + } + else // otherwise use unoconv + { + if ($this->unoconv_version == '0.6') + $command = 'unoconv -f %1$s %3$s > %2$s'; + else + $command = 'unoconv -f %s --output %s %s 2>&1'; + $command = sprintf($command, $format, $outFile, $inFile); + + $out = null; + exec($command, $out, $ret); + } if ($ret != 0) { @@ -191,6 +220,7 @@ class DocumentLib $cmd .= '/countspaces { [ exch { dup 32 ne { pop } if } forall ] length } bind def >> '; $cmd .= 'setpagedevice viewJPEG"'; + $out = null; exec($cmd, $out, $ret); if ($ret != 0) { diff --git a/application/libraries/FilterCmptLib.php b/application/libraries/FilterCmptLib.php index 9d6dfa681..c1a2b47cb 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; @@ -559,6 +565,7 @@ class FilterCmptLib getAuthPersonId() ); + // If filters were loaded if (hasData($filters)) { @@ -717,6 +724,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 +735,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 +1143,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; @@ -1159,5 +1173,4 @@ class FilterCmptLib return $filterName; } -} - +} \ No newline at end of file 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 d6488bc36..f38303b3c 100644 --- a/application/libraries/IssuesLib.php +++ b/application/libraries/IssuesLib.php @@ -169,6 +169,9 @@ class IssuesLib return $this->_changeIssueStatus($issue_id, $data, $user); } + // -------------------------------------------------------------------------------------------------------------- + // Private methods + /** * Changes status of an issue. * @param int $issue_id @@ -215,8 +218,15 @@ class IssuesLib * @param string $inhalt_extern * @return object success or error */ - private function _addIssue($fehlercode, $person_id = null, $oe_kurzbz = null, $fehlertext_params = null, $resolution_params = null, $fehlercode_extern = null, $inhalt_extern = null) - { + private function _addIssue( + $fehlercode, + $person_id = null, + $oe_kurzbz = null, + $fehlertext_params = null, + $resolution_params = null, + $fehlercode_extern = null, + $inhalt_extern = null + ) { if (isEmptyString($person_id) && isEmptyString($oe_kurzbz)) return error("Person_id or oe_kurzbz must be set."); @@ -226,9 +236,37 @@ class IssuesLib if (hasData($fehlerRes)) { $fehlertextVorlage = getData($fehlerRes)[0]->fehlertext; - $fehlertext = isEmptyArray($fehlertext_params) ? $fehlertextVorlage : vsprintf($fehlertextVorlage, $fehlertext_params); - $openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount($fehlercode, $person_id, $oe_kurzbz, $fehlercode_extern); + $fehlertext = $fehlertextVorlage; + if (!isEmptyArray($fehlertext_params)) + { + if (count($fehlertext_params) != substr_count($fehlertextVorlage, '%s')) + return error('Wrong number of parameters for Fehlertext, fehler_kurzbz ' . $fehlercode); + + $fehlertext = vsprintf($fehlertextVorlage, $fehlertext_params); + } + + 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)) { @@ -238,20 +276,7 @@ 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( 'fehlercode' => $fehlercode, @@ -267,8 +292,8 @@ class IssuesLib ) ); } - else - return success($openIssueCount); + else // return success if issue already exists + return success("Issue already exists"); } else return error("Number of open issues could not be determined"); diff --git a/application/libraries/MailLib.php b/application/libraries/MailLib.php index dbbc22f08..60dd52342 100644 --- a/application/libraries/MailLib.php +++ b/application/libraries/MailLib.php @@ -182,6 +182,7 @@ class MailLib { if ($this->sended == $this->email_number_per_time_range) { + $this->sended = 0; sleep($this->email_time_range); // Wait!!! } } diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index 09f89abee..c6e693666 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}); } } @@ -91,6 +95,33 @@ class PermissionLib return $isBerechtigt; } + /** + * Prueft ob die Berechtigung zumindest fuer eine der angegebenen OE vorhanden ist. + * @param $berechtigung_kurzbz + * @param $oe_kurzbz + * @param $art + * @param $kostenstelle_id + * @return boolean + */ + public function isBerechtigtMultipleOe($berechtigung_kurzbz, $oe_kurzbz, $art=null, $kostenstelle_id=null) + { + $results = array(); + + foreach($oe_kurzbz as $value) + { + $results[] = $this->isBerechtigt($berechtigung_kurzbz, $value, $art, $kostenstelle_id); + } + + if(!in_array(true, $results)) + { + return false; + } + else + { + return true; + } + } + /** * Checks if the caller is allowed to access to this content with the given permissions * - if it's called from command line than it's trusted @@ -143,19 +174,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 +185,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 +224,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/PersonLogLib.php b/application/libraries/PersonLogLib.php index fe9a82504..f4f434fad 100644 --- a/application/libraries/PersonLogLib.php +++ b/application/libraries/PersonLogLib.php @@ -7,9 +7,6 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class PersonLogLib { - const PARKED_LOGNAME = 'Parked'; - const ONHOLD_LOGNAME = 'Onhold'; - /** * Constructor */ @@ -78,168 +75,6 @@ class PersonLogLib else show_error(getError($result)); } - - /** - * Parks a person, i.e. marks a person so no actions are expected for the person (e.g. as a prestudent) - * Done by adding a logentry in the future - * @param $person_id - * @param $date - * @param $taetigkeit_kurzbz - * @param string $app - * @param null $oe_kurzbz - * @param null $user - * @return insert object - */ - public function park($person_id, $date, $taetigkeit_kurzbz, $app = 'core', $oe_kurzbz = null, $user = null) - { - $onhold = $this->getOnHoldDate($person_id); - - if (hasData($onhold)) - return error("Person already on hold"); - - $logjson = array( - 'name' => self::PARKED_LOGNAME - ); - - return $this->_savePsLog($person_id, $date, $taetigkeit_kurzbz, $logjson, $app, $oe_kurzbz, $user); - } - - /** - * Unparks a person, i.e. removes all log entries in the future with logname for parking - * @param $person_id - * @return array with deleted logids - */ - public function unPark($person_id) - { - $deleted = array(); - - $result = $this->ci->PersonLogModel->getLogsInFuture($person_id); - if (hasData($result)) - { - foreach ($result->retval as $log) - { - $logdata = json_decode($log->logdata); - if (isset($logdata->name) && $logdata->name === self::PARKED_LOGNAME) - { - $delresult = $this->ci->PersonLogModel->deleteLog($log->log_id); - if (isSuccess($delresult)) - { - $deleted[] = $log->log_id; - } - } - } - } - - return success($deleted); - } - - /** - * Gets date until which a person is parked - * @param $person_id - * @return the date if person is parked, null otherwise - */ - public function getParkedDate($person_id) - { - $result = $this->ci->PersonLogModel->getLogsInFuture($person_id); - - $parkeddate = null; - - if (hasData($result)) - { - foreach ($result->retval as $log) - { - $logdata = json_decode($log->logdata); - if (isset($logdata->name) && $logdata->name === self::PARKED_LOGNAME) - { - $parkeddate = $log->zeitpunkt; - break; - } - } - } - - return $parkeddate; - } - - /** - * Sets person on hold, i.e. marks a person so no actions are expected for the person (e.g. as a prestudent). - * Done by adding a logentry with a special name. can be undone only manually by clicking button. - * @param $person_id - * @param $date - * @param $taetigkeit_kurzbz - * @param string $app - * @param null $oe_kurzbz - * @param null $user - * @return array - */ - public function setOnHold($person_id, $date, $taetigkeit_kurzbz, $app = 'core', $oe_kurzbz = null, $user = null) - { - $parked = $this->getParkedDate($person_id); - - if (hasData($parked)) - return error("Person already parked"); - - $logjson = array( - 'name' => self::ONHOLD_LOGNAME - ); - - return $this->_savePsLog($person_id, $date, $taetigkeit_kurzbz, $logjson, $app, $oe_kurzbz, $user); - } - - /** - * Removes on hold status, i.e. removes all log entries with logname for on hold - * @param $person_id - * @return array - */ - public function removeOnHold($person_id) - { - $deleted = array(); - - $result = $this->ci->PersonLogModel->filterLog($person_id); - if (hasData($result)) - { - foreach ($result->retval as $log) - { - $logdata = json_decode($log->logdata); - if (isset($logdata->name) && $logdata->name === self::ONHOLD_LOGNAME) - { - $delresult = $this->ci->PersonLogModel->deleteLog($log->log_id); - if (isSuccess($delresult)) - { - $deleted[] = $log->log_id; - } - } - } - } - return success($deleted); - } - - /** - * Gets date until which a person is on hold - * @param $person_id - * @return the date if person is on hold, null otherwise - */ - public function getOnHoldDate($person_id) - { - $result = $this->ci->PersonLogModel->filterLog($person_id); - - $onholddate = null; - - if (hasData($result)) - { - foreach ($result->retval as $log) - { - $logdata = json_decode($log->logdata); - if (isset($logdata->name) && $logdata->name === self::ONHOLD_LOGNAME) - { - $onholddate = $log->zeitpunkt; - break; - } - } - } - - return $onholddate; - } - /** * Saves a processstate log with specified parameters, including a specified log date. * @param $person_id diff --git a/application/libraries/PhrasesLib.php b/application/libraries/PhrasesLib.php index dec3d54c0..ecd8094d6 100644 --- a/application/libraries/PhrasesLib.php +++ b/application/libraries/PhrasesLib.php @@ -200,6 +200,17 @@ class PhrasesLib return '<< PHRASE '.$phrase.' >>'; } + /** + * Workaround to reload the phrases array on an already constructed library. + * @parameters -> look for _setPhrases docs + */ + public function setPhrases($categories, $language) + { + if (count($categories) > 0) $this->_setPhrases($categories, $language); + + return $this->_phrases; + } + // ----------------------------------------------------------------------------------------------------------------- // Private methods @@ -319,6 +330,7 @@ class PhrasesLib { $this->_phrases = $phrases->retval; } + } /** @@ -329,4 +341,4 @@ class PhrasesLib { return json_encode($this->_phrases); } -} +} \ No newline at end of file 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..13b0efdbb 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','studentStv', 'prestudent', 'document', 'cms']; const PHOTO_IMG_URL = '/cis/public/bild.php?src=person&person_id='; @@ -108,6 +109,93 @@ 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) + { + $searchstr = preg_replace('/[[:punct:]]/', ' ', $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 +270,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 +298,16 @@ 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 + o.aktiv = true + AND (' . + $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 +361,91 @@ class SearchBarLib */ private function _student($searchstr, $type) { + $dbModel = new DB_Model(); + $gesperrtes_foto = base64_encode(file_get_contents(DOC_ROOT.'skin/images/profilbild_dummy.jpg')); + $students = $dbModel->execReadOnlyQuery(' + SELECT + \''.$type.'\' AS type, + s.student_uid AS uid, + CONCAT(s.student_uid,\'@'.DOMAIN.'\') AS email, + s.matrikelnr, + CONCAT(UPPER(stg.typ),UPPER(stg.kurzbz),\'-\',s.semester,s.verband) as verband, + stg.bezeichnung AS studiengang, + p.person_id AS person_id, + p.vorname || \' \' || p.nachname AS name, + CASE + when s.student_uid = \''.getAuthUID().'\' then p.foto + when p.foto IS NULL then \''.$gesperrtes_foto.'\' + when p.foto_sperre = false then p.foto + else \''.$gesperrtes_foto.'\' + end as foto, + b.aktiv + FROM public.tbl_student s + JOIN public.tbl_studiengang stg USING(studiengang_kz) + 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.aktiv = TRUE + AND (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, s.verband, s.semester, stg.bezeichnung, + stg.typ, stg.kurzbz, b.aktiv + ORDER BY b.aktiv DESC, p.nachname ASC, p.vorname ASC + '); + + // If something has been found then return it + if (hasData($students)) return getData($students); + + // Otherwise return an empty array + return array(); + } + + private function _studentStv($searchstr, $type) + { + $dbModel = new DB_Model(); + + $students = $dbModel->execReadOnlyQuery(' + SELECT + \''.$type.'\' AS type, + s.student_uid AS uid, + s.matrikelnr, + CONCAT(UPPER(stg.typ),UPPER(stg.kurzbz),\'-\',s.semester,s.verband) as verband, + stg.bezeichnung AS studiengang, + p.person_id AS person_id, + p.vorname || \' \' || p.nachname AS name, + k.kontakt AS email, + p.foto, + b.aktiv + FROM public.tbl_student s + JOIN public.tbl_studiengang stg USING(studiengang_kz) + 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, + k.kontakt, p.foto, s.verband, s.semester, stg.bezeichnung, + stg.typ, stg.kurzbz, b.aktiv + ORDER BY b.aktiv DESC, p.nachname ASC, p.vorname ASC + '); + + // If something has been found then return it + if (hasData($students)) return getData($students); + + // Otherwise return an empty array return array(); } @@ -268,6 +454,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(); } @@ -292,6 +513,80 @@ class SearchBarLib */ private function _raum($searchstr, $type) { + $dbModel = new DB_Model(); + + $rooms = $dbModel->execReadOnlyQuery(' + SELECT + \''.$type.'\' AS type, + COALESCE(ort.ort_kurzbz, \'N/A\') as ort_kurzbz, + COALESCE(ort.gebteil, \'N/A\') as building, + COALESCE(ort.ausstattung, \'N/A\') as austattung, + COALESCE(CAST(ort.stockwerk AS VARCHAR), \'N/A\') as floor, + COALESCE(CAST(ort.dislozierung AS VARCHAR), \'N/A\') as room_number, + COALESCE(CAST(ort.content_id AS VARCHAR), \'N/A\') as content_id, + + CASE + WHEN standort.plz IS NULL OR standort.ort IS NULL THEN + CASE + WHEN standort.strasse IS NULL THEN + CASE + WHEN ort.stockwerk IS NULL THEN \'N/A\' + ELSE CONCAT(ort.stockwerk,\' Stockwerk\') + END + ELSE + CASE + WHEN ort.stockwerk IS NULL THEN standort.strasse + ELSE CONCAT(standort.strasse,\' / \',ort.stockwerk,\' Stockwerk\') + END + END + ELSE + CASE + WHEN standort.strasse IS NULL THEN + CASE + WHEN ort.stockwerk IS NULL THEN CONCAT(standort.plz,\' \',standort.ort) + ELSE CONCAT(standort.plz,\' \',standort.ort,\' / \',ort.stockwerk,\' Stockwerk\') + END + ELSE + CASE + WHEN ort.stockwerk IS NULL THEN CONCAT(standort.plz,\' \',standort.ort,\' / \',standort.strasse) + ELSE CONCAT(standort.plz,\' \',standort.ort,\', \',standort.strasse,\' / \',ort.stockwerk,\' Stockwerk\') + END + END + END as standort, + + + CASE + WHEN ort.max_person IS NULL OR ort.arbeitsplaetze IS NULL THEN \'N/A\' + ELSE CONCAT(ort.max_person,\', davon \',ort.arbeitsplaetze,\' PC-Plätze\') + END as sitzplaetze + + FROM public.tbl_ort as ort + LEFT JOIN ( + select ort,standort_id,strasse, plz + FROM public.tbl_standort + LEFT JOIN public.tbl_adresse USING(adresse_id) + ) standort USING(standort_id) + WHERE + ort.aktiv = true + AND + ort.lehre = true + AND (' . + $this->buildSearchClause( + $dbModel, + array('ort.ort_kurzbz', 'ort.bezeichnung'), + $searchstr + ) . + ')' + ); + + // If something has been found + if (hasData($rooms)) + { + // Returns the dataset + return getData($rooms); + } + + // Otherwise return an empty array return array(); } } diff --git a/application/libraries/SignatureLib.php b/application/libraries/SignatureLib.php new file mode 100644 index 000000000..c44ffc5f6 --- /dev/null +++ b/application/libraries/SignatureLib.php @@ -0,0 +1,85 @@ + 30000000) + { + $returnObject = new stdClass(); + $returnObject->code = 1; + $returnObject->error = 1; + $returnObject->retval = 'File to big'; + + return $returnObject; + } + + // Get the content of the given file + $inputFileContent = file_get_contents($inputFileName); + if ($inputFileContent === false) // if failed + { + error_log('An error occurred while getting the content from: '.$inputFileName); + } + else + { + // Posts the given file content + file name and expects a response in JSON format + $resultPost = \Httpful\Request::post(SIGNATUR_URL.'/'.SIGNATUR_LIST_API) + ->sendsJson() + ->authenticateWith(SIGNATUR_USER, SIGNATUR_PASSWORD) + ->body('{"filename": "'.basename($inputFileName).'", "content": "'.base64_encode($inputFileContent).'"}') + ->expectsJson() + ->send(); + } + } + catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception + { + error_log($cee->getMessage()); + } + catch (Exception $e) // any other exception + { + error_log($e->getMessage()); + } + + // If the response is fine + if (isset($resultPost->body) && is_object($resultPost->body) + && isset($resultPost->body->retval) && is_array($resultPost->body->retval)) + { + return $resultPost->body->retval; + } + + // Otherwise return a null as error + return null; + } +} diff --git a/application/libraries/TableWidgetLib.php b/application/libraries/TableWidgetLib.php index dc746b6d5..feda0d67c 100644 --- a/application/libraries/TableWidgetLib.php +++ b/application/libraries/TableWidgetLib.php @@ -1,5 +1,22 @@ . + */ + if (! defined('BASEPATH')) exit('No direct script access allowed'); /** @@ -9,6 +26,8 @@ class TableWidgetLib { const TABLE_UNIQUE_ID = 'tableUniqueId'; // TableWidget unique id + const TABLE_BOOTSTRAP_VERSION = 'bootstrapVersion'; // TableWidget bootstrap version + // TableWidget session name const SESSION_NAME = 'FHC_TABLE_WIDGET'; @@ -16,6 +35,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 +69,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 +95,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 +198,7 @@ class TableWidgetLib /** * Retrieves the dataset from the DB */ - public function getDataset($datasetQuery) + public function getDataset($datasetQuery, $encryptedColumns) { $dataset = null; @@ -186,7 +207,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/dashboard/DashboardLib.php b/application/libraries/dashboard/DashboardLib.php new file mode 100644 index 000000000..edea7c310 --- /dev/null +++ b/application/libraries/dashboard/DashboardLib.php @@ -0,0 +1,232 @@ +_ci =& get_instance(); + + $this->_ci->load->model('dashboard/Dashboard_model', 'DashboardModel'); + $this->_ci->load->model('dashboard/Dashboard_Preset_model', 'DashboardPresetModel'); + $this->_ci->load->model('dashboard/Dashboard_Override_model', 'DashboardOverrideModel'); + } + + public function generateWidgetId($dashboard_kurzbz = '') + { + $dashboard_kurzbz = (!empty($dashboard_kurzbz)) ? $dashboard_kurzbz : self::DEFAULT_DASHBOARD_KURZBZ; + $widgetid_input = time() . '_' . $dashboard_kurzbz . '_' . bin2hex(random_bytes(self::WIDGET_ID_RANDOM_BYTES)); + $widgetid = md5($widgetid_input); + return $widgetid; + } + + public function getDashboardByKurzbz($dashboard_kurzbz) + { + $result = $this->_ci->DashboardModel->getDashboardByKurzbz($dashboard_kurzbz); + + if (hasData($result)) + { + return current(getData($result)); + } + + return null; + } + + public function getMergedConfig($dashboard_id, $uid) + { + $defaultconfig = $this->getDefaultConfig($dashboard_id, $uid); + $userconfig = $this->getUserConfig($dashboard_id, $uid); + + $mergedconfig = array_replace_recursive($defaultconfig, $userconfig); + + return $mergedconfig; + } + + public function getDefaultConfig($dashboard_id, $uid) + { + $res_presets = $this->_ci->DashboardPresetModel->getPresets($dashboard_id, $uid); + $defaultconfig = array(); + + if (hasData($res_presets)) + { + $presets = getData($res_presets); + foreach ($presets as $presetobj) + { + $preset = json_decode($presetobj->preset, true); + if (null !== $preset) + { + $defaultconfig = array_replace_recursive($defaultconfig, $preset); + } + } + } + + return $defaultconfig; + } + + public function getUserConfig($dashboard_id, $uid) + { + $res_userconfig = $this->_ci->DashboardOverrideModel->getOverride($dashboard_id, $uid); + + if (hasData($res_userconfig)) + { + $data = getData($res_userconfig); + $decodedconfig = json_decode(current($data)->override, true); + if (null !== $decodedconfig) + { + return $decodedconfig; + } + } + + return []; + } + + public function getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid) + { + $override = $this->getOverride($dashboard_kurzbz, $uid); + if (null !== $override) { + return $override; + } + + $dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz); + + $emptyoverride = new stdClass(); + $emptyoverride->dashboard_id = $dashboard->dashboard_id; + $emptyoverride->uid = $uid; + $emptyoverride->override = '{"widgets": {"' . self::USEROVERRIDE_SECTION . '": {}}}'; + + return $emptyoverride; + } + + public function getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz) + { + if ($funktion_kurzbz === self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL) + $funktion_kurzbz = null; + $preset = $this->getPreset($dashboard_kurzbz, $funktion_kurzbz); + if (null !== $preset) { + return $preset; + } + + $dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz); + + $emptypreset = new stdClass(); + $emptypreset->dashboard_id = $dashboard->dashboard_id; + $emptypreset->funktion_kurzbz = $funktion_kurzbz; + $section = ($funktion_kurzbz !== null) ? $funktion_kurzbz : self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL; + $emptypreset->preset = '{"widgets": {"' . $section . '": {}}}'; + + return $emptypreset; + } + + public function getPreset($dashboard_kurzbz, $section) + { + $dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz); + + $funktion_kurzbz = ($section === self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL) ? null : $section; + $result = $this->_ci->DashboardPresetModel + ->getPresetByDashboardAndFunktion($dashboard->dashboard_id, $funktion_kurzbz); + + if (hasData($result)) + { + return current(getData($result)); + } + + return null; + } + + public function getOverride($dashboard_kurzbz, $uid) + { + $dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz); + + $result = $this->_ci->DashboardOverrideModel + ->getOverride($dashboard->dashboard_id, $uid); + + if (hasData($result)) + { + return current(getData($result)); + } + + return null; + } + + public function insertOrUpdatePreset($preset) + { + if (isset($preset->preset_id) && $preset->preset_id > 0) + { + $result = $this->_ci->DashboardPresetModel->update($preset->preset_id, $preset); + } + else + { + $result = $this->_ci->DashboardPresetModel->insert($preset); + } + + return $result; + } + + public function insertOrUpdateOverride($override) + { + if (isset($override->override_id) && $override->override_id > 0) + { + $result = $this->_ci->DashboardOverrideModel->update($override->override_id, $override); + } + else + { + $result = $this->_ci->DashboardOverrideModel->insert($override); + } + + return $result; + } + + public function addWidgetsToWidgets(&$widgets, $dashboard_kurzbz, $section, $addwigets) + { + foreach ($addwigets as $widget) + { + if(!isset($widget->widgetid)) + { + $widget->widgetid = $this->generateWidgetId($dashboard_kurzbz); + } + $this->addWidgetToWidgets($widgets, $section, $widget, $widget->widgetid); + } + } + + public function addWidgetToWidgets(&$widgets, $section, $widget, $widgetid) + { + $section = ($section !== null) ? $section : self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL; + if (!isset($widgets[$section]) || !is_array($widgets[$section])) + { + $widgets[$section] = array(); + } + + $widgets[$section][$widgetid] = $widget; + } + + public function removeWidgetFromWidgets(&$widgets, $section, $widgetid) + { + $section = ($section !== null) ? $section : self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL; + if (isset($widgets[$section]) && isset($widgets[$section][$widgetid])) + { + unset($widgets[$section][$widgetid]); + if(empty($widgets[$section]) && $section !== self::USEROVERRIDE_SECTION) { + unset($widgets[$section]); + } + return true; + } + else { + return false; + } + } +} diff --git a/application/libraries/issues/PlausicheckDefinitionLib.php b/application/libraries/issues/PlausicheckDefinitionLib.php new file mode 100644 index 000000000..d8c26d43a --- /dev/null +++ b/application/libraries/issues/PlausicheckDefinitionLib.php @@ -0,0 +1,56 @@ + class (library) name for resolving + private $_fehlerLibMappings = array( + 'AbbrecherAktiv' => 'AbbrecherAktiv', + 'AbschlussstatusFehlt' => 'AbschlussstatusFehlt', + 'AktSemesterNull' => 'AktSemesterNull', + 'AktiverStudentOhneStatus' => 'AktiverStudentOhneStatus', + 'AusbildungssemPrestudentUngleichAusbildungssemStatus' => 'AusbildungssemPrestudentUngleichAusbildungssemStatus', + 'DatumAbschlusspruefungFehlt' => 'DatumAbschlusspruefungFehlt', + 'DatumSponsionFehlt' => 'DatumSponsionFehlt', + 'DatumStudiensemesterFalscheReihenfolge' => 'DatumStudiensemesterFalscheReihenfolge', + 'FalscheAnzahlAbschlusspruefungen' => 'FalscheAnzahlAbschlusspruefungen', + 'FalscheAnzahlHeimatadressen' => 'FalscheAnzahlHeimatadressen', + 'FalscheAnzahlZustelladressen' => 'FalscheAnzahlZustelladressen', + 'GbDatumWeitZurueck' => 'GbDatumWeitZurueck', + 'InaktiverStudentAktiverStatus' => 'InaktiverStudentAktiverStatus', + 'IncomingHeimatNationOesterreich' => 'IncomingHeimatNationOesterreich', + 'IncomingOhneIoDatensatz' => 'IncomingOhneIoDatensatz', + 'IncomingOrGsFoerderrelevant' => 'IncomingOrGsFoerderrelevant', + 'InskriptionVorLetzerBismeldung' => 'InskriptionVorLetzerBismeldung', + 'NationNichtOesterreichAberGemeinde' => 'NationNichtOesterreichAberGemeinde', + 'OrgformStgUngleichOrgformPrestudent' => 'OrgformStgUngleichOrgformPrestudent', + 'PrestudentMischformOhneOrgform' => 'PrestudentMischformOhneOrgform', + 'StgPrestudentUngleichStgStudienplan' => 'StgPrestudentUngleichStgStudienplan', + 'StgPrestudentUngleichStgStudent' => 'StgPrestudentUngleichStgStudent', + 'StudentstatusNachAbbrecher' => 'StudentstatusNachAbbrecher', + 'DualesStudiumOhneMarkierung' => 'DualesStudiumOhneMarkierung' + //'StudienplanUngueltig' => 'StudienplanUngueltig' + //'BewerberNichtZumRtAngetreten' => 'BewerberNichtZumRtAngetreten' + ); + + /** + * Gets all fehler_kurzbz-library mappings for fehler which need to be checked. + */ + public function getFehlerLibMappings() + { + return $this->_fehlerLibMappings; + } + + /** + * Gets all fehler_kurzbz for fehler which need to be checked. + */ + public function getFehlerKurzbz() + { + return array_keys($this->_fehlerLibMappings); + } +} diff --git a/application/libraries/issues/PlausicheckProducerLib.php b/application/libraries/issues/PlausicheckProducerLib.php new file mode 100644 index 000000000..cea9967fb --- /dev/null +++ b/application/libraries/issues/PlausicheckProducerLib.php @@ -0,0 +1,136 @@ +_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'); + + // get all configuration parameters for the application + $fehlerkonfigurationRes = $this->_ci->FehlerkonfigurationModel->getKonfiguration($app); + + if (hasData($fehlerkonfigurationRes)) + { + $fehlerkonfiguration = getData($fehlerkonfigurationRes); + + foreach ($fehlerkonfiguration as $fk) + { + $this->_konfiguration[$fk->fehler_kurzbz][$fk->konfigurationstyp_kurzbz] = $fk->konfiguration; + } + } + } + + /** + * 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 + * @param $fehler_kurzbz string unique short name of fehler, for which issue is produced + * @param $params parameters passed to issue production method + */ + public function producePlausicheckIssue($libName, $fehler_kurzbz, $params) + { + // 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::PLAUSI_ISSUES_FOLDER . '/'; + + // file path of library for check if file exists + $issuesLibFilePath = DOC_ROOT . self::CI_PATH + . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::PLAUSI_ISSUES_FOLDER . '/' . $libName . '.php'; + + // check if library file exists + if (!file_exists($issuesLibFilePath)) return error("Issue library file " . $issuesLibFilePath . " does not exist"); + + // load konfiguration parameters of the fehler_kurzbz + $config = isset($this->_konfiguration[$fehler_kurzbz]) ? $this->_konfiguration[$fehler_kurzbz] : null; + + // load library connected to fehlercode + $this->_ci->load->library( + $issuesLibPath . $libName, + ['configurationParams' => $config, 'isForResolutionCheck' => $this->_isForResolutionCheck] + ); + + $lowercaseLibName = mb_strtolower($libName); + + // check if method is defined in library class + if (!is_callable(array($this->_ci->{$lowercaseLibName}, self::EXECUTE_PLAUSI_CHECK_METHOD_NAME))) + return error("Method " . self::EXECUTE_PLAUSI_CHECK_METHOD_NAME . " is not defined in library $lowercaseLibName"); + + // call the function for checking for issue production + return $this->_ci->{$lowercaseLibName}->{self::EXECUTE_PLAUSI_CHECK_METHOD_NAME}($params); + } +} 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 new file mode 100644 index 000000000..464b77a30 --- /dev/null +++ b/application/libraries/issues/plausichecks/AbbrecherAktiv.php @@ -0,0 +1,29 @@ + " 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/AbschlussstatusFehlt.php b/application/libraries/issues/plausichecks/AbschlussstatusFehlt.php new file mode 100644 index 000000000..3690e1331 --- /dev/null +++ b/application/libraries/issues/plausichecks/AbschlussstatusFehlt.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->getAbschlussstatusFehlt( + $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), + 'resolution_params' => array('prestudent_id' => $prestudent->prestudent_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Prestudent should have a final status. + * @param studiensemester_kurzbz string if 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 getAbschlussstatusFehlt( + $studiensemester_kurzbz = null, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT + DISTINCT ON (pre.prestudent_id) + pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz, status.studiensemester_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_person USING(person_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiengang stg USING(studiengang_kz) + WHERE + NOT EXISTS( /*student does not study anymore*/ + SELECT + 1 + FROM + public.tbl_prestudentstatus ps + JOIN public.tbl_studiensemester USING(studiensemester_kurzbz) + WHERE + prestudent_id=pre.prestudent_id + /* 4 months: There might be Diplomanden, in summer months end status is often not entered yet */ + AND tbl_studiensemester.ende>now() - interval '4 months' + ) + /* check only valid begininng with 2018 */ + AND '2018-01-01'<(SELECT max(datum) FROM public.tbl_prestudentstatus WHERE prestudent_id=pre.prestudent_id) + AND NOT EXISTS( /* no end status */ + SELECT 1 + FROM public.tbl_prestudentstatus ps + WHERE + prestudent_id=pre.prestudent_id + AND status_kurzbz IN('Abbrecher','Abgewiesener','Absolvent','Incoming') + ) + AND stg.melderelevant + AND pre.bismelden"; + + if (isset($studiensemester_kurzbz)) + { + $prevStudiensemesterRes = $this->_ci->StudiensemesterModel->getPreviousFrom($studiensemester_kurzbz); + + if (isError($prevStudiensemesterRes)) return $prevStudiensemesterRes; + + if (hasData($prevStudiensemesterRes)) + { + // if Studiensemester given, check only if has status in current or previous semester + $prevStudiensemester = getData($prevStudiensemesterRes)[0]->studiensemester_kurzbz; + $qry .= " AND EXISTS ( + SELECT 1 + FROM public.tbl_prestudentstatus ps + WHERE studiensemester_kurzbz IN (?, ?) + AND ps.prestudent_id = pre.prestudent_id + )"; + $params[] = $prevStudiensemester; + $params[] = $studiensemester_kurzbz; + } + } + + 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/AktSemesterNull.php b/application/libraries/issues/plausichecks/AktSemesterNull.php new file mode 100644 index 000000000..1223a2720 --- /dev/null +++ b/application/libraries/issues/plausichecks/AktSemesterNull.php @@ -0,0 +1,100 @@ +_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->getAktSemesterNull($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, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Current Ausbildungssemester shouldn't be 0. + * @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 getAktSemesterNull($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, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz, prestat.studiensemester_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_prestudentstatus prestat USING(prestudent_id) + JOIN public.tbl_studiengang stg USING(studiengang_kz) + WHERE + prestat.status_kurzbz != 'Incoming' + AND prestat.studiensemester_kurzbz = ? + AND ausbildungssemester = 0 + AND stg.melderelevant + AND pre.bismelden"; + + 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/AktiverStudentOhneStatus.php b/application/libraries/issues/plausichecks/AktiverStudentOhneStatus.php new file mode 100644 index 000000000..94fe5cc8d --- /dev/null +++ b/application/libraries/issues/plausichecks/AktiverStudentOhneStatus.php @@ -0,0 +1,99 @@ +_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->getAktiverStudentOhneStatus($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); + } + + /** + * Students with active Benutzer should have a status in the current semester. + * @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 getAktiverStudentOhneStatus($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null) + { + $params = array(); + + $qry = " + SELECT + DISTINCT (student_uid), prestudent.person_id, prestudent.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_student student + JOIN public.tbl_benutzer benutzer on (benutzer.uid = student.student_uid) + JOIN public.tbl_prestudent prestudent USING(prestudent_id) + JOIN public.tbl_studiengang stg ON prestudent.studiengang_kz = stg.studiengang_kz + WHERE + benutzer.aktiv=TRUE + AND stg.melderelevant + AND prestudent.bismelden + AND NOT EXISTS ( + SELECT 1 + FROM public.tbl_prestudentstatus + JOIN public.tbl_studiensemester sem USING (studiensemester_kurzbz) + WHERE prestudent_id = prestudent.prestudent_id + /* buffer of four months, as status are often entered later */ + AND sem.ende::date > NOW() - interval '4 months' + )"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND prestudent.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/AktiverStudentstatusOhneKontobuchung.php b/application/libraries/issues/plausichecks/AktiverStudentstatusOhneKontobuchung.php new file mode 100644 index 000000000..28684388f --- /dev/null +++ b/application/libraries/issues/plausichecks/AktiverStudentstatusOhneKontobuchung.php @@ -0,0 +1,120 @@ +_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->getAktiverStudentstatusOhneKontobuchung( + $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, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Student with active status should have been charged, i.e. have a Kontobuchung with a negative or zero value. + * @param studiensemester_kurzbz string if 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 getAktiverStudentstatusOhneKontobuchung( + $studiensemester_kurzbz, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array($studiensemester_kurzbz); + + $qry = " + SELECT + DISTINCT ON (pre.prestudent_id) + pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz, status.studiensemester_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_person pers USING(person_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiengang stg USING(studiengang_kz) + WHERE + status.studiensemester_kurzbz = ? + AND status.status_kurzbz IN ('Student', 'Incoming') + AND NOT EXISTS ( + SELECT 1 + FROM + public.tbl_konto + WHERE + person_id = pers.person_id + AND studiensemester_kurzbz = status.studiensemester_kurzbz + AND buchungsnr_verweis IS NULL + AND betrag <= 0 + ) + AND stg.melderelevant + AND pre.bismelden"; + + 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/AusbildungssemPrestudentUngleichAusbildungssemStatus.php b/application/libraries/issues/plausichecks/AusbildungssemPrestudentUngleichAusbildungssemStatus.php new file mode 100644 index 000000000..00ff16ae0 --- /dev/null +++ b/application/libraries/issues/plausichecks/AusbildungssemPrestudentUngleichAusbildungssemStatus.php @@ -0,0 +1,116 @@ +_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->getAusbildungssemPrestudentUngleichAusbildungssemStatus( + $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( + 'status_ausbildungssemester' => $prestudent->status_ausbildungssemester, + 'student_ausbildungssemester' => $prestudent->student_ausbildungssemester, + 'student_uid' => $prestudent->student_uid, + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Ausbildungssemester of prestudent (lehrverband) must be the same as Ausbildungssemester of prestudentstatus. + * @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 getAusbildungssemPrestudentUngleichAusbildungssemStatus( + $studiensemester_kurzbz, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array($studiensemester_kurzbz, $studiensemester_kurzbz, $studiensemester_kurzbz); + + $qry = " + SELECT + DISTINCT(student.student_uid), student.student_uid, prestudent.person_id, prestudent.prestudent_id, + status.ausbildungssemester AS status_ausbildungssemester, lv.semester AS student_ausbildungssemester, status.studiensemester_kurzbz, + stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_student student + JOIN public.tbl_studentlehrverband lv USING(student_uid) + JOIN public.tbl_prestudent prestudent USING(prestudent_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiengang stg ON prestudent.studiengang_kz = stg.studiengang_kz + WHERE + status.studiensemester_kurzbz = ? + AND lv.studiensemester_kurzbz = ? + AND status.status_kurzbz NOT IN ('Interessent','Bewerber','Aufgenommener','Wartender','Abgewiesener','Unterbrecher') + AND get_rolle_prestudent (prestudent_id, ?)='Student' + AND status.ausbildungssemester != lv.semester"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND prestudent.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/BewerberNichtZumRtAngetreten.php b/application/libraries/issues/plausichecks/BewerberNichtZumRtAngetreten.php new file mode 100644 index 000000000..4a9655d13 --- /dev/null +++ b/application/libraries/issues/plausichecks/BewerberNichtZumRtAngetreten.php @@ -0,0 +1,123 @@ +_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->getBewerberNichtZumRtAngetreten( + $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), + 'resolution_params' => array( + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz, + 'prestudent_id' => $prestudent->prestudent_id + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Bewerber should have participated in Reihungstest. + * @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 getBewerberNichtZumRtAngetreten( + $studiensemester_kurzbz, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $previousStudiensemesterRes = $this->_ci->StudiensemesterModel->getPreviousFrom($studiensemester_kurzbz); + + if (isError($previousStudiensemesterRes)) return $previousStudiensemesterRes; + + $params = array($studiensemester_kurzbz); + + $qry = " + SELECT + prestudent.person_id, prestudent.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz, status.studiensemester_kurzbz + FROM + public.tbl_prestudent prestudent + JOIN public.tbl_prestudentstatus status ON(prestudent.prestudent_id=status.prestudent_id) + JOIN public.tbl_person USING(person_id) + LEFT JOIN bis.tbl_orgform USING(orgform_kurzbz) + JOIN public.tbl_studiengang stg USING(studiengang_kz) + WHERE + status_kurzbz='Bewerber' + AND reihungstestangetreten=false + AND stg.melderelevant + AND prestudent.bismelden"; + + if (hasData($previousStudiensemesterRes)) + { + $previousStudiensemester = getData($previousStudiensemesterRes)[0]->studiensemester_kurzbz; + $qry .= " AND (studiensemester_kurzbz=? OR studiensemester_kurzbz=?)"; + $params[] = $previousStudiensemester; + } + else + { + $qry .= " AND studiensemester_kurzbz=?"; + } + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND prestudent.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/DatumAbschlusspruefungFehlt.php b/application/libraries/issues/plausichecks/DatumAbschlusspruefungFehlt.php new file mode 100644 index 000000000..f606e2c8c --- /dev/null +++ b/application/libraries/issues/plausichecks/DatumAbschlusspruefungFehlt.php @@ -0,0 +1,123 @@ +_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->getDatumAbschlusspruefungFehlt( + $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, + 'abschlusspruefung_id' => $prestudent->abschlusspruefung_id + ), + 'resolution_params' => array('abschlusspruefung_id' => $prestudent->abschlusspruefung_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Date of final exam shouldn't be missing for Absolvent. + * @param studiensemester_kurzbz string if check is to be executed for certain Studiensemester + * @param studiengang_kz int if check is to be executed for certain Studiengang + * @param abschlusspruefung_id int if check is to be executed for a certain Abschlussprüfung + * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check + * @return success with prestudents or error + */ + public function getDatumAbschlusspruefungFehlt( + $studiensemester_kurzbz = null, + $studiengang_kz = null, + $abschlusspruefung_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT + pre.person_id, pre.prestudent_id, + pruefung.sponsion, pruefung.datum, pruefung.abschlusspruefung_id, + stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_student stud USING(prestudent_id) + JOIN public.tbl_prestudentstatus prestatus USING(prestudent_id) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + JOIN lehre.tbl_abschlusspruefung pruefung ON stud.student_uid = pruefung.student_uid + WHERE + status_kurzbz = 'Absolvent' + AND NOT EXISTS ( /* exclude gs */ + SELECT 1 + FROM bis.tbl_mobilitaet + WHERE prestudent_id = pre.prestudent_id + AND studiensemester_kurzbz = prestatus.studiensemester_kurzbz + ) + AND abschlussbeurteilung_kurzbz!='nicht' + AND abschlussbeurteilung_kurzbz IS NOT NULL + AND pruefung.datum IS NULL + AND pre.bismelden + AND stg.melderelevant"; + + if (isset($studiensemester_kurzbz)) + { + $qry .= " AND prestatus.studiensemester_kurzbz = ?"; + $params[] = $studiensemester_kurzbz; + } + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($abschlusspruefung_id)) + { + $qry .= " AND pruefung.abschlusspruefung_id = ?"; + $params[] = $abschlusspruefung_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/DatumSponsionFehlt.php b/application/libraries/issues/plausichecks/DatumSponsionFehlt.php new file mode 100644 index 000000000..210ae6f01 --- /dev/null +++ b/application/libraries/issues/plausichecks/DatumSponsionFehlt.php @@ -0,0 +1,123 @@ +_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->getDatumSponsionFehlt( + $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, + 'abschlusspruefung_id' => $prestudent->abschlusspruefung_id + ), + 'resolution_params' => array('abschlusspruefung_id' => $prestudent->abschlusspruefung_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Date of sponsion shouldn't be missing for Absolvent. + * @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 abschlusspruefung_id int if check is to be executed only for a certain Abschlussprüfung + * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check + * @return success with prestudents or error + */ + public function getDatumSponsionFehlt( + $studiensemester_kurzbz = null, + $studiengang_kz = null, + $abschlusspruefung_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT + pre.person_id, pre.prestudent_id, + pruefung.sponsion, pruefung.datum, pruefung.abschlusspruefung_id, + stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_student stud USING(prestudent_id) + JOIN public.tbl_prestudentstatus prestatus USING(prestudent_id) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + JOIN lehre.tbl_abschlusspruefung pruefung ON stud.student_uid = pruefung.student_uid + WHERE + status_kurzbz = 'Absolvent' + AND NOT EXISTS ( /* exclude gs */ + SELECT 1 + FROM bis.tbl_mobilitaet + WHERE prestudent_id = pre.prestudent_id + AND studiensemester_kurzbz = prestatus.studiensemester_kurzbz + ) + AND abschlussbeurteilung_kurzbz!='nicht' + AND abschlussbeurteilung_kurzbz IS NOT NULL + AND pruefung.sponsion IS NULL + AND pre.bismelden + AND stg.melderelevant"; + + if (isset($studiensemester_kurzbz)) + { + $qry .= " AND prestatus.studiensemester_kurzbz = ?"; + $params[] = $studiensemester_kurzbz; + } + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($abschlusspruefung_id)) + { + $qry .= " AND pruefung.abschlusspruefung_id = ?"; + $params[] = $abschlusspruefung_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/DatumStudiensemesterFalscheReihenfolge.php b/application/libraries/issues/plausichecks/DatumStudiensemesterFalscheReihenfolge.php new file mode 100644 index 000000000..381bea7df --- /dev/null +++ b/application/libraries/issues/plausichecks/DatumStudiensemesterFalscheReihenfolge.php @@ -0,0 +1,108 @@ +_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->getDatumStudiensemesterFalscheReihenfolge($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); + } + + /** + * Status Dates and status studysemester dates should be in correct order. + * @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 check is to be executed only for certain Studiengaenge + * @return success with prestudents or error + */ + public function getDatumStudiensemesterFalscheReihenfolge($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null) + { + $params = array(); + + // all active students with Status student in current semester + $qry = " + SELECT DISTINCT ON (prestudent_id) * + FROM ( + SELECT + prestudent.person_id, prestudent.prestudent_id, + stg.studiengang_kz, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz, + ROW_NUMBER () OVER ( + PARTITION BY prestudent.prestudent_id + ORDER BY sem.start DESC, status.datum DESC, status.insertamum DESC, status.ext_id DESC + ) AS reihenfolge_semester, + ROW_NUMBER () OVER ( + PARTITION BY prestudent.prestudent_id + ORDER BY status.datum DESC, status.insertamum DESC, status.ext_id DESC + ) AS reihenfolge_datum + FROM + public.tbl_student student + JOIN public.tbl_benutzer benutzer on(student.student_uid = benutzer.uid) + JOIN public.tbl_prestudent prestudent USING(prestudent_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiensemester sem USING(studiensemester_kurzbz) + JOIN public.tbl_studiengang stg ON prestudent.studiengang_kz = stg.studiengang_kz + WHERE + benutzer.aktiv=true + AND status.status_kurzbz='Student' + ) reihenfolge + WHERE reihenfolge_semester <> reihenfolge_datum"; + + if (isset($studiengang_kz)) + { + $qry .= " AND studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND prestudent_id = ?"; + $params[] = $prestudent_id; + } + + if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz)) + { + $qry .= " AND studiengang_kz NOT IN ?"; + $params[] = $exkludierte_studiengang_kz; + } + + return $this->_db->execReadOnlyQuery($qry, $params); + } +} 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/FalscheAnzahlAbschlusspruefungen.php b/application/libraries/issues/plausichecks/FalscheAnzahlAbschlusspruefungen.php new file mode 100644 index 000000000..1021fe85a --- /dev/null +++ b/application/libraries/issues/plausichecks/FalscheAnzahlAbschlusspruefungen.php @@ -0,0 +1,125 @@ +_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->getFalscheAnzahlAbschlusspruefungen( + $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), + 'resolution_params' => array('prestudent_id' => $prestudent->prestudent_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Students with finished studies should have exactly one final exam. + * @param studiensemester_kurzbz string if 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 getFalscheAnzahlAbschlusspruefungen( + $studiensemester_kurzbz = null, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT * FROM ( + SELECT + DISTINCT ON(pre.prestudent_id) pre.person_id, pre.prestudent_id, student_uid, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz, + ( + SELECT COUNT(*) + FROM lehre.tbl_abschlusspruefung + WHERE student_uid = stud.student_uid + AND abschlussbeurteilung_kurzbz != 'nicht' + AND abschlussbeurteilung_kurzbz IS NOT NULL + ) AS anzahl_abschlusspruefungen + FROM + public.tbl_prestudent pre + JOIN public.tbl_student stud USING(prestudent_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + WHERE + status_kurzbz = 'Absolvent' + AND pre.bismelden + AND stg.melderelevant + AND NOT EXISTS ( /* exclude gs */ + SELECT 1 + FROM bis.tbl_mobilitaet + WHERE prestudent_id = pre.prestudent_id + AND studiensemester_kurzbz = status.studiensemester_kurzbz + )"; + + if (isset($studiensemester_kurzbz)) + { + $qry .= " AND status.studiensemester_kurzbz = ?"; + $params[] = $studiensemester_kurzbz; + } + + 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; + } + + $qry .= ") studenten + WHERE anzahl_abschlusspruefungen != 1"; + + return $this->_db->execReadOnlyQuery($qry, $params); + } +} diff --git a/application/libraries/issues/plausichecks/FalscheAnzahlHeimatadressen.php b/application/libraries/issues/plausichecks/FalscheAnzahlHeimatadressen.php new file mode 100644 index 000000000..b3551904e --- /dev/null +++ b/application/libraries/issues/plausichecks/FalscheAnzahlHeimatadressen.php @@ -0,0 +1,113 @@ +_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 + $personRes = $this->getFalscheAnzahlHeimatadressen( + $studiensemester_kurzbz, + $studiengang_kz, + null, + $exkludierte_studiengang_kz + ); + + if (isError($personRes)) return $personRes; + + if (hasData($personRes)) + { + $persons = getData($personRes); + + // populate results with data necessary for writing issues + foreach ($persons as $person) + { + $results[] = array( + 'person_id' => $person->person_id, + 'resolution_params' => array('person_id' => $person->person_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Students should have exactly one home address. + * @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 person_id int if check is to be executed only for one person + * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check + * @return success with prestudents or error + */ + public function getFalscheAnzahlHeimatadressen( + $studiensemester_kurzbz = null, + $studiengang_kz = null, + $person_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT + DISTINCT person_id + FROM + ( + SELECT person_id, COUNT(adresse_id) AS anzahl_adressen + FROM public.tbl_adresse addr + WHERE heimatadresse IS TRUE + GROUP BY person_id + ) adressen + JOIN public.tbl_person USING(person_id) + JOIN public.tbl_prestudent pre USING(person_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_student USING(prestudent_id) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + WHERE + anzahl_adressen != 1 + AND stg.melderelevant + AND pre.bismelden"; + + if (isset($studiensemester_kurzbz)) + { + $qry .= " AND status.studiensemester_kurzbz = ?"; + $params[] = $studiensemester_kurzbz; + } + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($person_id)) + { + $qry .= " AND person_id = ?"; + $params[] = $person_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/FalscheAnzahlZustelladressen.php b/application/libraries/issues/plausichecks/FalscheAnzahlZustelladressen.php new file mode 100644 index 000000000..9d72b0236 --- /dev/null +++ b/application/libraries/issues/plausichecks/FalscheAnzahlZustelladressen.php @@ -0,0 +1,113 @@ +_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 + $personRes = $this->getFalscheAnzahlZustelladressen( + $studiensemester_kurzbz, + $studiengang_kz, + null, + $exkludierte_studiengang_kz + ); + + if (isError($personRes)) return $personRes; + + if (hasData($personRes)) + { + $persons = getData($personRes); + + // populate results with data necessary for writing issues + foreach ($persons as $person) + { + $results[] = array( + 'person_id' => $person->person_id, + 'resolution_params' => array('person_id' => $person->person_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Students should have exactly one delivery address. + * @param studiensemester_kurzbz string if check is to be executed for certain Studiensemester + * @param studiengang_kz int if check is to be executed for certain Studiengang + * @param person_id int if check is to be executed only for one person + * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check + * @return success with prestudents or error + */ + public function getFalscheAnzahlZustelladressen( + $studiensemester_kurzbz = null, + $studiengang_kz = null, + $person_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT + DISTINCT person_id + FROM + ( + SELECT person_id, COUNT(adresse_id) AS anzahl_adressen + FROM public.tbl_adresse addr + WHERE zustelladresse IS TRUE + GROUP BY person_id + ) adressen + JOIN public.tbl_person USING(person_id) + JOIN public.tbl_prestudent pre USING(person_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_student USING(prestudent_id) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + WHERE + anzahl_adressen != 1 + AND stg.melderelevant + AND pre.bismelden"; + + if (isset($studiensemester_kurzbz)) + { + $qry .= " AND status.studiensemester_kurzbz = ?"; + $params[] = $studiensemester_kurzbz; + } + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($person_id)) + { + $qry .= " AND person_id = ?"; + $params[] = $person_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/GbDatumWeitZurueck.php b/application/libraries/issues/plausichecks/GbDatumWeitZurueck.php new file mode 100644 index 000000000..04e1cf97b --- /dev/null +++ b/application/libraries/issues/plausichecks/GbDatumWeitZurueck.php @@ -0,0 +1,104 @@ +_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 + $personRes = $this->getGbDatumWeitZurueck($studiensemester_kurzbz, $studiengang_kz, null, $exkludierte_studiengang_kz); + + if (isError($personRes)) return $personRes; + + if (hasData($personRes)) + { + $persons = getData($personRes); + + // populate results with data necessary for writing issues + foreach ($persons as $person) + { + $results[] = array( + 'person_id' => $person->person_id, + 'resolution_params' => array('person_id' => $person->person_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Birthdate is too long ago. + * @param studiensemester_kurzbz string if check is to be executed for certain Studiensemester + * @param studiengang_kz int if check is to be executed for certain Studiengang + * @param person_id int if check is to be executed only for one person + * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check + * @return success with prestudents or error + */ + public function getGbDatumWeitZurueck( + $studiensemester_kurzbz = null, + $studiengang_kz = null, + $person_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT + pers.person_id + FROM + public.tbl_person pers + WHERE + pers.gebdatum < '1920-01-01' + AND EXISTS ( + SELECT 1 + FROM public.tbl_prestudent + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiengang stg USING(studiengang_kz) + WHERE person_id = pers.person_id"; + + if (isset($studiensemester_kurzbz)) + { + $qry .= " AND status.studiensemester_kurzbz = ?"; + $params[] = $studiensemester_kurzbz; + } + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz NOT IN ?"; + $params[] = $exkludierte_studiengang_kz; + } + + $qry .= ")"; + + if (isset($person_id)) + { + $qry .= " AND pers.person_id = ?"; + $params[] = $person_id; + } + + return $this->_db->execReadOnlyQuery($qry, $params); + } +} diff --git a/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php b/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php new file mode 100644 index 000000000..59965e238 --- /dev/null +++ b/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php @@ -0,0 +1,114 @@ +_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->getInaktiverStudentAktiverStatus( + $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), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Students with active status should have an active Benutzer. + * @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 getInaktiverStudentAktiverStatus( + $studiensemester_kurzbz, + $studiengang_kz = null, + $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; + + $studiensemester_kurzbz = hasData($aktStudiensemesterRes) ? getData($aktStudiensemesterRes)[0]->studiensemester_kurzbz : ''; + + $params = array($studiensemester_kurzbz); + + $qry = " + SELECT + DISTINCT(student.student_uid), prestudent.person_id, prestudent.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_benutzer benutzer + JOIN public.tbl_student student on(benutzer.uid = student.student_uid) + JOIN public.tbl_prestudent prestudent USING(prestudent_id) + JOIN public.tbl_studiengang stg ON prestudent.studiengang_kz = stg.studiengang_kz + WHERE + benutzer.aktiv=false + AND EXISTS (SELECT 1 FROM public.tbl_prestudentstatus WHERE prestudent_id = prestudent.prestudent_id AND studiensemester_kurzbz = ?) + AND get_rolle_prestudent(prestudent_id, NULL) IN ('Student', 'Diplomand', 'Unterbrecher', 'Praktikant') + AND stg.melderelevant + AND prestudent.bismelden"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND prestudent.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/IncomingHeimatNationOesterreich.php b/application/libraries/issues/plausichecks/IncomingHeimatNationOesterreich.php new file mode 100644 index 000000000..5276164dc --- /dev/null +++ b/application/libraries/issues/plausichecks/IncomingHeimatNationOesterreich.php @@ -0,0 +1,104 @@ +_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 + $personRes = $this->getIncomingHeimatNationOesterreich( + $studiensemester_kurzbz, + $studiengang_kz, + null, + $exkludierte_studiengang_kz + ); + + if (isError($personRes)) return $personRes; + + if (hasData($personRes)) + { + $persons = getData($personRes); + + // populate results with data necessary for writing issues + foreach ($persons as $person) + { + $results[] = array( + 'person_id' => $person->person_id, + 'resolution_params' => array('person_id' => $person->person_id, 'studiensemester_kurzbz' => $studiensemester_kurzbz) + ); + } + } + + // return the results + return success($results); + } + + /** + * Incoming shouldn't have austrian home address. + * @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 person_id int if check is to be executed only for one person + * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check + * @return success with prestudents or error + */ + public function getIncomingHeimatNationOesterreich( + $studiensemester_kurzbz, + $studiengang_kz = null, + $person_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array($studiensemester_kurzbz); + + $qry = " + SELECT + DISTINCT pers.person_id, status.studiensemester_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_person pers USING(person_id) + JOIN public.tbl_adresse addr USING(person_id) + JOIN public.tbl_studiengang stg USING(studiengang_kz) + WHERE + status.status_kurzbz = 'Incoming' + AND addr.nation = 'A' + AND addr.heimatadresse + AND status.studiensemester_kurzbz = ? + AND stg.melderelevant + AND pre.bismelden"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($person_id)) + { + $qry .= " AND pers.person_id = ?"; + $params[] = $person_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/IncomingOhneIoDatensatz.php b/application/libraries/issues/plausichecks/IncomingOhneIoDatensatz.php new file mode 100644 index 000000000..e08280f83 --- /dev/null +++ b/application/libraries/issues/plausichecks/IncomingOhneIoDatensatz.php @@ -0,0 +1,96 @@ +_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->getIncomingOhneIoDatensatz($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); + } + + /** + * Incoming should have IN/OUT data. + * @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 getIncomingOhneIoDatensatz($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null) + { + $params = array(); + + $qry = " + SELECT + DISTINCT ON(student_uid, nachname, vorname) + tbl_person.person_id, + tbl_prestudent.prestudent_id, + stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_student + JOIN public.tbl_benutzer ON(student_uid=uid) + JOIN public.tbl_person USING(person_id) + JOIN public.tbl_prestudent USING(prestudent_id) + JOIN public.tbl_prestudentstatus ON(tbl_prestudent.prestudent_id=tbl_prestudentstatus.prestudent_id) + JOIN public.tbl_studiengang stg ON(stg.studiengang_kz=tbl_student.studiengang_kz) + WHERE + bismelden=TRUE + AND status_kurzbz='Incoming' AND NOT EXISTS (SELECT 1 FROM bis.tbl_bisio WHERE student_uid=tbl_student.student_uid) + AND stg.melderelevant"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND tbl_prestudent.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/IncomingOrGsFoerderrelevant.php b/application/libraries/issues/plausichecks/IncomingOrGsFoerderrelevant.php new file mode 100644 index 000000000..4d789f71a --- /dev/null +++ b/application/libraries/issues/plausichecks/IncomingOrGsFoerderrelevant.php @@ -0,0 +1,125 @@ +_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->getIncomingOrGsFoerderrelevant( + $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), + 'resolution_params' => array('prestudent_id' => $prestudent->prestudent_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Incoming or gemeinsame Studien students should not receive funding (not be förderrelevant). + * @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 object success or error + */ + public function getIncomingOrGsFoerderrelevant( + $studiensemester_kurzbz = null, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT + DISTINCT ON(prestudent_id) + pers.person_id, + ps.prestudent_id, + stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_student stud + JOIN public.tbl_benutzer ON(student_uid=uid) + JOIN public.tbl_person pers USING(person_id) + JOIN public.tbl_prestudent ps USING(prestudent_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiengang stg ON(stg.studiengang_kz=stud.studiengang_kz) + WHERE + ( + status.status_kurzbz = 'Incoming' + OR EXISTS ( + SELECT 1 + FROM + bis.tbl_mobilitaet + JOIN public.tbl_prestudent USING(prestudent_id) + WHERE + prestudent_id = ps.prestudent_id + AND gsstudientyp_kurzbz = 'Extern' + ) + ) + AND (ps.foerderrelevant <> FALSE OR ps.foerderrelevant IS NULL) + AND bismelden=TRUE + AND stg.melderelevant"; + + if (isset($studiensemester_kurzbz)) + { + $qry .= " AND status.studiensemester_kurzbz = ?"; + $params[] = $studiensemester_kurzbz; + } + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND ps.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/InskriptionVorLetzerBismeldung.php b/application/libraries/issues/plausichecks/InskriptionVorLetzerBismeldung.php new file mode 100644 index 000000000..871b3b3d4 --- /dev/null +++ b/application/libraries/issues/plausichecks/InskriptionVorLetzerBismeldung.php @@ -0,0 +1,148 @@ +_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->getInskriptionVorLetzerBismeldung( + $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( + 'datum_bismeldung' => date_format(date_create($prestudent->datum_bismeldung), 'd.m.Y'), + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Students of a semester shouldn't start studies before the date of Bismeldung. + * e.g. If student studies in WS2022 datum of status shouldn't be before 15.4.2020 + * e.g. If student studies in SS2022 datum of status shouldn't be before 15.11.2022 + * @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 getInskriptionVorLetzerBismeldung( + $studiensemester_kurzbz, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + // get Bismeldedatum + $datumBis = $this->_getBisdateFromSemester($studiensemester_kurzbz); + + $params = array($datumBis, $studiensemester_kurzbz, $datumBis); + + // get active students + $qry = " + SELECT + DISTINCT ON (student.student_uid) ? AS datum_bismeldung, + prestudent.person_id, prestudent.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz, status.studiensemester_kurzbz + FROM + public.tbl_benutzer benutzer + JOIN public.tbl_student student on(benutzer.uid = student.student_uid) + JOIN public.tbl_prestudent prestudent USING(prestudent_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiengang stg ON prestudent.studiengang_kz = stg.studiengang_kz + WHERE + benutzer.aktiv=true + AND status.studiensemester_kurzbz = ? + /* inscription date before date of first student status */ + AND ( + SELECT datum + FROM public.tbl_prestudentstatus + WHERE prestudent_id = prestudent.prestudent_id + AND studiensemester_kurzbz = status.studiensemester_kurzbz + AND status_kurzbz = 'Student' + ORDER BY datum, insertamum, ext_id + LIMIT 1 + ) < ? + AND stg.melderelevant + AND prestudent.bismelden"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND prestudent.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); + } + + /** + * Gets Bismeldedate from Studiensemester. + * @param studiensemester_kurzbz string + */ + private function _getBisdateFromSemester($studiensemester_kurzbz) + { + $semesterYear = substr($studiensemester_kurzbz, 2, 6); + $semesterType = substr($studiensemester_kurzbz, 0, 2); + + if ($semesterType == 'SS') + { + return date_format(date_create(($semesterYear - 1)."-11-15"), 'Y-m-d'); + } + + if ($semesterType == 'WS') + { + return date_format(date_create($semesterYear."-04-15"), 'Y-m-d'); + } + } +} diff --git a/application/libraries/issues/plausichecks/NationNichtOesterreichAberGemeinde.php b/application/libraries/issues/plausichecks/NationNichtOesterreichAberGemeinde.php new file mode 100644 index 000000000..c04cd664c --- /dev/null +++ b/application/libraries/issues/plausichecks/NationNichtOesterreichAberGemeinde.php @@ -0,0 +1,94 @@ +_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 + $personRes = $this->getNationNichtOesterreichAberGemeinde( + $studiengang_kz, + null, + $exkludierte_studiengang_kz + ); + + if (isError($personRes)) return $personRes; + + if (hasData($personRes)) + { + $persons = getData($personRes); + + // populate results with data necessary for writing issues + foreach ($persons as $person) + { + $results[] = array( + 'person_id' => $person->person_id, + 'fehlertext_params' => array('gemeinde' => $person->gemeinde, 'adresse_id' => $person->adresse_id), + 'resolution_params' => array('adresse_id' => $person->adresse_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Nation is not Austria, but address has austrian Gemeinde. + * @param studiengang_kz int if check is to be executed for certain Studiengang + * @param person_id int if check is to be executed only for one person + * @return success with prestudents or error + */ + public function getNationNichtOesterreichAberGemeinde($studiengang_kz = null, $person_id = null, $exkludierte_studiengang_kz = null) + { + $params = array(); + + $qry = "SELECT DISTINCT tbl_person.person_id, adr.gemeinde, adr.adresse_id + FROM + public.tbl_adresse adr + JOIN public.tbl_prestudent USING(person_id) + JOIN public.tbl_person USING(person_id) + JOIN public.tbl_student USING(prestudent_id) + JOIN public.tbl_benutzer ON(uid=student_uid) + JOIN public.tbl_studiengang stg ON tbl_prestudent.studiengang_kz = stg.studiengang_kz + WHERE + adr.nation!='A' + AND tbl_benutzer.aktiv + AND gemeinde NOT IN ('Münster') + AND EXISTS(SELECT 1 FROM bis.tbl_gemeinde WHERE name = adr.gemeinde)"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($person_id)) + { + $qry .= " AND tbl_person.person_id = ?"; + $params[] = $person_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/OrgformStgUngleichOrgformPrestudent.php b/application/libraries/issues/plausichecks/OrgformStgUngleichOrgformPrestudent.php new file mode 100644 index 000000000..316e81072 --- /dev/null +++ b/application/libraries/issues/plausichecks/OrgformStgUngleichOrgformPrestudent.php @@ -0,0 +1,130 @@ +_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->getOrgformStgUngleichOrgformPrestudent( + $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( + 'student_studiengang' => $prestudent->student_studiengang, + 'student_orgform' => $prestudent->student_orgform, + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Orgform of a Studiengang in Studienplan should be the same as orgform of student. + * @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 getOrgformStgUngleichOrgformPrestudent( + $studiensemester_kurzbz, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array($studiensemester_kurzbz); + + $qry = " + SELECT + prestudent.person_id, prestudent.prestudent_id, status.studiensemester_kurzbz, + studiengang.orgform_kurzbz AS stg_orgform, status.orgform_kurzbz AS student_orgform, + prestudent.studiengang_kz AS student_studiengang, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_studiengang studiengang + JOIN public.tbl_student student USING(studiengang_kz) + JOIN public.tbl_prestudent prestudent USING(prestudent_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_benutzer benutzer on(benutzer.uid = student.student_uid) + JOIN public.tbl_studiengang stg ON prestudent.studiengang_kz = stg.studiengang_kz + LEFT JOIN lehre.tbl_studienplan stpl USING (studienplan_id) + WHERE + benutzer.aktiv = true + AND status.status_kurzbz IN ('Student', 'Unterbrecher', 'Abbrecher', 'Diplomand', 'Absolvent') + AND studiengang.studiengang_kz < 10000 + AND status.studiensemester_kurzbz = ? + AND NOT (status.orgform_kurzbz IS NULL AND studiengang.mischform = FALSE) + AND NOT EXISTS( + SELECT 1 + FROM + lehre.tbl_studienplan + JOIN + lehre.tbl_studienordnung USING(studienordnung_id) + WHERE + tbl_studienplan.studienplan_id = stpl.studienplan_id + AND tbl_studienordnung.studiengang_kz = prestudent.studiengang_kz + AND tbl_studienplan.orgform_kurzbz = status.orgform_kurzbz)"; + + if (isset($studiengang_kz)) + { + $qry .= " AND studiengang.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND prestudent.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; + } + + $qry .= " + ORDER BY student_uid"; + + return $this->_db->execReadOnlyQuery($qry, $params); + } +} diff --git a/application/libraries/issues/plausichecks/PlausiChecker.php b/application/libraries/issues/plausichecks/PlausiChecker.php new file mode 100644 index 000000000..7e5fe7db0 --- /dev/null +++ b/application/libraries/issues/plausichecks/PlausiChecker.php @@ -0,0 +1,117 @@ + [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 = $params['configurationParams'] ?? []; + + $this->_isForResolutionCheck = $params['isForResolutionCheck'] ?? false; + + // get database for queries + $this->_db = new DB_Model(); + } + + /** + * Executes a plausi check. + * @param $paramsForChecking array parameters needed for executing the check + * @return array with objects which failed the plausi check + */ + 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/plausichecks/PrestudentMischformOhneOrgform.php b/application/libraries/issues/plausichecks/PrestudentMischformOhneOrgform.php new file mode 100644 index 000000000..a4c3e2a4b --- /dev/null +++ b/application/libraries/issues/plausichecks/PrestudentMischformOhneOrgform.php @@ -0,0 +1,109 @@ +_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->getPrestudentMischformOhneOrgform( + $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, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Students in "mixed" Studiengang should have Orgform. + * @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 getPrestudentMischformOhneOrgform( + $studiensemester_kurzbz, + $studiengang_kz = null, + $prestudent_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array($studiensemester_kurzbz); + + $qry = " + SELECT + pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz, status.studiensemester_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_person USING(person_id) + JOIN public.tbl_prestudentstatus status USING(prestudent_id) + JOIN public.tbl_studiengang stg USING(studiengang_kz) + WHERE + status.status_kurzbz IN ('Bewerber', 'Student') + AND stg.mischform + AND (status.orgform_kurzbz='' OR status.orgform_kurzbz IS NULL) + AND status.studiensemester_kurzbz=?"; + + 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/StgPrestudentUngleichStgStudent.php b/application/libraries/issues/plausichecks/StgPrestudentUngleichStgStudent.php new file mode 100644 index 000000000..94bea2f35 --- /dev/null +++ b/application/libraries/issues/plausichecks/StgPrestudentUngleichStgStudent.php @@ -0,0 +1,90 @@ +_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->getStgPrestudentUngleichStgStudent($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); + } + + /** + * Studiengang should be the same for prestudent and student. + * @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 getStgPrestudentUngleichStgStudent($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null) + { + $params = array(); + + $qry = " + SELECT + pre.person_id, pre.prestudent_id, stg.oe_kurzbz prestudent_stg_oe_kurzbz, student_stg.oe_kurzbz student_stg_oe_kurzbz + FROM + public.tbl_prestudent pre + JOIN public.tbl_student stud USING(prestudent_id) + JOIN public.tbl_person pers USING(person_id) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + JOIN public.tbl_studiengang student_stg ON stud.studiengang_kz = student_stg.studiengang_kz + WHERE + stud.studiengang_kz != pre.studiengang_kz"; + + 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/StgPrestudentUngleichStgStudienplan.php b/application/libraries/issues/plausichecks/StgPrestudentUngleichStgStudienplan.php new file mode 100644 index 000000000..fc0f52f23 --- /dev/null +++ b/application/libraries/issues/plausichecks/StgPrestudentUngleichStgStudienplan.php @@ -0,0 +1,104 @@ +_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->getStgPrestudentUngleichStgStudienplan($studiengang_kz, null, 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, 'studienordnung_id' => $prestudent->studienordnung_id) + ); + } + } + + // return the results + return success($results); + } + + /** + * Studiengang should be the same for prestudent and studienplan. + * @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 studienordnung_id int if check is to be executed only for a certain studienordnung_id + * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check + * @return success with prestudents or error + */ + public function getStgPrestudentUngleichStgStudienplan( + $studiengang_kz = null, + $prestudent_id = null, + $studienordnung_id = null, + $exkludierte_studiengang_kz = null + ) { + $params = array(); + + $qry = " + SELECT + DISTINCT ON (ps.prestudent_id) ps.person_id, ps.prestudent_id, stordnung.studienordnung_id, + stplan.bezeichnung AS studienplan, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_prestudent ps + JOIN public.tbl_prestudentstatus USING(prestudent_id) + JOIN lehre.tbl_studienplan stplan USING(studienplan_id) + JOIN lehre.tbl_studienordnung stordnung USING(studienordnung_id) + JOIN public.tbl_person USING(person_id) + JOIN public.tbl_studiengang stg ON ps.studiengang_kz = stg.studiengang_kz + WHERE + ps.studiengang_kz<>stordnung.studiengang_kz + AND stg.melderelevant"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND ps.prestudent_id = ?"; + $params[] = $prestudent_id; + } + + if (isset($studienordnung_id)) + { + $qry .= " AND stordnung.studienordnung_id = ?"; + $params[] = $studienordnung_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/StudentstatusNachAbbrecher.php b/application/libraries/issues/plausichecks/StudentstatusNachAbbrecher.php new file mode 100644 index 000000000..87bb51d7e --- /dev/null +++ b/application/libraries/issues/plausichecks/StudentstatusNachAbbrecher.php @@ -0,0 +1,90 @@ +_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->getStudentstatusNachAbbrecher($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); + } + + /** + * There shouldn't be any status after Abbrecher status. + * @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 getStudentstatusNachAbbrecher($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null) + { + $params = array(); + + $qry = " + SELECT + prestudent.person_id, prestudent.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_student student + JOIN public.tbl_prestudent prestudent USING(prestudent_id) + JOIN public.tbl_prestudentstatus prestatus USING(prestudent_id) + JOIN public.tbl_studiengang stg ON prestudent.studiengang_kz = stg.studiengang_kz + WHERE + prestatus.status_kurzbz = 'Abbrecher' + AND get_rolle_prestudent(prestudent.prestudent_id, prestatus.studiensemester_kurzbz) <> 'Abbrecher'"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND prestudent.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/StudienplanUngueltig.php b/application/libraries/issues/plausichecks/StudienplanUngueltig.php new file mode 100644 index 000000000..9a306278e --- /dev/null +++ b/application/libraries/issues/plausichecks/StudienplanUngueltig.php @@ -0,0 +1,126 @@ +_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->getStudienplanUngueltig( + $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( + 'studienplan' => $prestudent->studienplan, + 'ausbildungssemester' => $prestudent->ausbildungssemester, + 'prestudent_id' => $prestudent->prestudent_id + ), + 'resolution_params' => array( + 'prestudent_id' => $prestudent->prestudent_id, + 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz + ) + ); + } + } + + // return the results + return success($results); + } + + /** + * Studienplan should be valid in current Ausbildungssemester of prestudent. + * @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 getStudienplanUngueltig( + $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, + tbl_studienplan.bezeichnung AS studienplan, + status.status_kurzbz, + 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 USING(studienplan_id) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + WHERE + status_kurzbz in('Student', 'Interessent','Bewerber','Aufgenommener') + AND NOT EXISTS ( + SELECT + 1 + FROM + lehre.tbl_studienplan_semester + WHERE + studienplan_id=status.studienplan_id + AND tbl_studienplan_semester.semester = status.ausbildungssemester + AND tbl_studienplan_semester.studiensemester_kurzbz = status.studiensemester_kurzbz + ) + AND status.studiensemester_kurzbz=? + AND pre.bismelden + AND stg.melderelevant"; + + if (isset($studiengang_kz)) + { + $qry .= " AND stg.studiengang_kz = ?"; + $params[] = $studiengang_kz; + } + + if (isset($prestudent_id)) + { + $qry .= " AND tbl_prestudent.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/CORE_INOUT_0001.php b/application/libraries/issues/resolvers/CORE_INOUT_0001.php similarity index 100% rename from application/libraries/issues/CORE_INOUT_0001.php rename to application/libraries/issues/resolvers/CORE_INOUT_0001.php diff --git a/application/libraries/issues/CORE_INOUT_0002.php b/application/libraries/issues/resolvers/CORE_INOUT_0002.php similarity index 100% rename from application/libraries/issues/CORE_INOUT_0002.php rename to application/libraries/issues/resolvers/CORE_INOUT_0002.php diff --git a/application/libraries/issues/CORE_INOUT_0003.php b/application/libraries/issues/resolvers/CORE_INOUT_0003.php similarity index 100% rename from application/libraries/issues/CORE_INOUT_0003.php rename to application/libraries/issues/resolvers/CORE_INOUT_0003.php diff --git a/application/libraries/issues/CORE_INOUT_0004.php b/application/libraries/issues/resolvers/CORE_INOUT_0004.php similarity index 100% rename from application/libraries/issues/CORE_INOUT_0004.php rename to application/libraries/issues/resolvers/CORE_INOUT_0004.php diff --git a/application/libraries/issues/CORE_INOUT_0005.php b/application/libraries/issues/resolvers/CORE_INOUT_0005.php similarity index 100% rename from application/libraries/issues/CORE_INOUT_0005.php rename to application/libraries/issues/resolvers/CORE_INOUT_0005.php diff --git a/application/libraries/issues/CORE_INOUT_0006.php b/application/libraries/issues/resolvers/CORE_INOUT_0006.php similarity index 93% rename from application/libraries/issues/CORE_INOUT_0006.php rename to application/libraries/issues/resolvers/CORE_INOUT_0006.php index a447a9625..6894c9878 100644 --- a/application/libraries/issues/CORE_INOUT_0006.php +++ b/application/libraries/issues/resolvers/CORE_INOUT_0006.php @@ -15,7 +15,6 @@ class CORE_INOUT_0006 implements IIssueResolvedChecker $this->_ci =& get_instance(); // get code igniter instance $this->_ci->load->model('codex/Bisio_model', 'BisioModel'); - //$this->_ci->load->model('codex/Aufenthaltfoerderung_model', 'AufenthaltfoerderungModel'); // get all Zwecke $this->_ci->BisioModel->addSelect('ects_erworben'); diff --git a/application/libraries/issues/resolvers/CORE_INOUT_0007.php b/application/libraries/issues/resolvers/CORE_INOUT_0007.php new file mode 100644 index 000000000..31ca79ffb --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_INOUT_0007.php @@ -0,0 +1,32 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/IncomingHeimatNationOesterreich'); + + // check if issue persists + $checkRes = $this->_ci->incomingheimatnationoesterreich->getIncomingHeimatNationOesterreich($params['studiensemester_kurzbz'], null, $params['issue_person_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/issues/resolvers/CORE_INOUT_0008.php b/application/libraries/issues/resolvers/CORE_INOUT_0008.php new file mode 100644 index 000000000..4fa090c6a --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_INOUT_0008.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/IncomingOhneIoDatensatz'); + + // check if issue persists + $checkRes = $this->_ci->incomingohneiodatensatz->getIncomingOhneIoDatensatz(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/issues/resolvers/CORE_INOUT_0009.php b/application/libraries/issues/resolvers/CORE_INOUT_0009.php new file mode 100644 index 000000000..c739d71c3 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_INOUT_0009.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/IncomingOrGsFoerderrelevant'); + + // check if issue persists + $checkRes = $this->_ci->incomingorgsfoerderrelevant->getIncomingOrGsFoerderrelevant(null, 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/issues/resolvers/CORE_PERSON_0001.php b/application/libraries/issues/resolvers/CORE_PERSON_0001.php new file mode 100644 index 000000000..d0ac0d3ed --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_PERSON_0001.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/GbDatumWeitZurueck'); + + // check if issue persists + $checkRes = $this->_ci->gbdatumweitzurueck->getGbDatumWeitZurueck(null, null, $params['issue_person_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/issues/resolvers/CORE_PERSON_0002.php b/application/libraries/issues/resolvers/CORE_PERSON_0002.php new file mode 100644 index 000000000..608dcf0ce --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_PERSON_0002.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/NationNichtOesterreichAberGemeinde'); + + // check if issue persists + $checkRes = $this->_ci->nationnichtoesterreichabergemeinde->getNationNichtOesterreichAberGemeinde(null, $params['issue_person_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/issues/resolvers/CORE_PERSON_0003.php b/application/libraries/issues/resolvers/CORE_PERSON_0003.php new file mode 100644 index 000000000..23a81b660 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_PERSON_0003.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/FalscheAnzahlHeimatadressen'); + + // check if issue persists + $checkRes = $this->_ci->falscheanzahlheimatadressen->getFalscheAnzahlHeimatadressen(null, null, $params['issue_person_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/issues/resolvers/CORE_PERSON_0004.php b/application/libraries/issues/resolvers/CORE_PERSON_0004.php new file mode 100644 index 000000000..ae3a855ec --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_PERSON_0004.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/FalscheAnzahlZustelladressen'); + + // check if issue persists + $checkRes = $this->_ci->falscheanzahlzustelladressen->getFalscheAnzahlZustelladressen(null, null, $params['issue_person_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/issues/resolvers/CORE_STG_0001.php b/application/libraries/issues/resolvers/CORE_STG_0001.php new file mode 100644 index 000000000..09c34be74 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STG_0001.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/StgPrestudentUngleichStgStudent'); + + // check if issue persists + $checkRes = $this->_ci->stgprestudentungleichstgstudent->getStgPrestudentUngleichStgStudent(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/issues/resolvers/CORE_STG_0002.php b/application/libraries/issues/resolvers/CORE_STG_0002.php new file mode 100644 index 000000000..999958042 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STG_0002.php @@ -0,0 +1,32 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/OrgformStgUngleichOrgformPrestudent'); + + // check if issue persists + $checkRes = $this->_ci->orgformstgungleichorgformprestudent->getOrgformStgUngleichOrgformPrestudent($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/issues/resolvers/CORE_STG_0003.php b/application/libraries/issues/resolvers/CORE_STG_0003.php new file mode 100644 index 000000000..22d6399be --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STG_0003.php @@ -0,0 +1,32 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/PrestudentMischformOhneOrgform'); + + // check if issue persists + $checkRes = $this->_ci->prestudentmischformohneorgform->getPrestudentMischformOhneOrgform($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/issues/resolvers/CORE_STG_0004.php b/application/libraries/issues/resolvers/CORE_STG_0004.php new file mode 100644 index 000000000..2eedfc7fe --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STG_0004.php @@ -0,0 +1,32 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/StgPrestudentUngleichStgStudienplan'); + + // check if issue persists + $checkRes = $this->_ci->stgprestudentungleichstgstudienplan->getStgPrestudentUngleichStgStudienplan(null, $params['prestudent_id'], $params['studienordnung_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/issues/resolvers/CORE_STUDENTSTATUS_0001.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0001.php new file mode 100644 index 000000000..c74cd38fb --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0001.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/AbbrecherAktiv'); + + // check if issue persists + $checkRes = $this->_ci->abbrecheraktiv->getAbbrecherAktiv(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/issues/resolvers/CORE_STUDENTSTATUS_0002.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0002.php new file mode 100644 index 000000000..36827684c --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0002.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/StudentstatusNachAbbrecher'); + + // check if issue persists + $checkRes = $this->_ci->studentstatusnachabbrecher->getStudentstatusNachAbbrecher(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/issues/resolvers/CORE_STUDENTSTATUS_0003.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0003.php new file mode 100644 index 000000000..f3b150d8d --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0003.php @@ -0,0 +1,36 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/AusbildungssemPrestudentUngleichAusbildungssemStatus'); + + // check if issue persists + $checkRes = $this->_ci->ausbildungssemprestudentungleichausbildungssemstatus->getAusbildungssemPrestudentUngleichAusbildungssemStatus( + $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/issues/resolvers/CORE_STUDENTSTATUS_0004.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0004.php new file mode 100644 index 000000000..cbce2b01e --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0004.php @@ -0,0 +1,36 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/InaktiverStudentAktiverStatus'); + + // check if issue persists + $checkRes = $this->_ci->inaktiverstudentaktiverstatus->getInaktiverStudentAktiverStatus( + $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/issues/resolvers/CORE_STUDENTSTATUS_0005.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0005.php new file mode 100644 index 000000000..f5e265194 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0005.php @@ -0,0 +1,32 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/InskriptionVorLetzerBismeldung'); + + // check if issue persists + $checkRes = $this->_ci->inskriptionvorletzerbismeldung->getInskriptionVorLetzerBismeldung($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/issues/resolvers/CORE_STUDENTSTATUS_0006.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0006.php new file mode 100644 index 000000000..94658ec9c --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0006.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/DatumStudiensemesterFalscheReihenfolge'); + + // check if issue persists + $checkRes = $this->_ci->datumstudiensemesterfalschereihenfolge->getDatumStudiensemesterFalscheReihenfolge(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/issues/resolvers/CORE_STUDENTSTATUS_0007.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0007.php new file mode 100644 index 000000000..3a2575e53 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0007.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/AktiverStudentOhneStatus'); + + // check if issue persists + $checkRes = $this->_ci->aktiverstudentohnestatus->getAktiverStudentOhneStatus(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/issues/resolvers/CORE_STUDENTSTATUS_0008.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0008.php new file mode 100644 index 000000000..53bfd72a6 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0008.php @@ -0,0 +1,32 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/StudienplanUngueltig'); + + // check if issue persists + $checkRes = $this->_ci->studienplanungueltig->getStudienplanUngueltig($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/issues/resolvers/CORE_STUDENTSTATUS_0009.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0009.php new file mode 100644 index 000000000..816b7e933 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0009.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/FalscheAnzahlAbschlusspruefungen'); + + // check if issue persists + $checkRes = $this->_ci->falscheanzahlabschlusspruefungen->getFalscheAnzahlAbschlusspruefungen(null, 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/issues/resolvers/CORE_STUDENTSTATUS_0010.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0010.php new file mode 100644 index 000000000..b31fb872a --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0010.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/DatumAbschlusspruefungFehlt'); + + // check if issue persists + $checkRes = $this->_ci->datumabschlusspruefungfehlt->getDatumAbschlusspruefungFehlt(null, null, $params['abschlusspruefung_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/issues/resolvers/CORE_STUDENTSTATUS_0011.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0011.php new file mode 100644 index 000000000..9dff0181e --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0011.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/DatumSponsionFehlt'); + + // check if issue persists + $checkRes = $this->_ci->datumsponsionfehlt->getDatumSponsionFehlt(null, null, $params['abschlusspruefung_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/issues/resolvers/CORE_STUDENTSTATUS_0012.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0012.php new file mode 100644 index 000000000..7fe5dbde4 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0012.php @@ -0,0 +1,36 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/BewerberNichtZumRtAngetreten'); + + // check if issue persists + $checkRes = $this->_ci->bewerbernichtzumrtangetreten->getBewerberNichtZumRtAngetreten( + $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/issues/resolvers/CORE_STUDENTSTATUS_0013.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0013.php new file mode 100644 index 000000000..86e8b75b1 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0013.php @@ -0,0 +1,32 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/AktSemesterNull'); + + // check if issue persists + $checkRes = $this->_ci->aktsemesternull->getAktSemesterNull($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/issues/resolvers/CORE_STUDENTSTATUS_0014.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0014.php new file mode 100644 index 000000000..4b542cf0a --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0014.php @@ -0,0 +1,29 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/AbschlussstatusFehlt'); + + // check if issue persists + $checkRes = $this->_ci->abschlussstatusfehlt->getAbschlussstatusFehlt(null, 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/issues/resolvers/CORE_STUDENTSTATUS_0015.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0015.php new file mode 100644 index 000000000..37e42ec0a --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0015.php @@ -0,0 +1,36 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->library('issues/plausichecks/AktiverStudentstatusOhneKontobuchung'); + + // check if issue persists + $checkRes = $this->_ci->aktiverstudentstatusohnekontobuchung->getAktiverStudentstatusOhneKontobuchung( + $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/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/issues/CORE_ZGV_0001.php b/application/libraries/issues/resolvers/CORE_ZGV_0001.php similarity index 100% rename from application/libraries/issues/CORE_ZGV_0001.php rename to application/libraries/issues/resolvers/CORE_ZGV_0001.php diff --git a/application/libraries/issues/CORE_ZGV_0002.php b/application/libraries/issues/resolvers/CORE_ZGV_0002.php similarity index 100% rename from application/libraries/issues/CORE_ZGV_0002.php rename to application/libraries/issues/resolvers/CORE_ZGV_0002.php diff --git a/application/libraries/issues/CORE_ZGV_0003.php b/application/libraries/issues/resolvers/CORE_ZGV_0003.php similarity index 100% rename from application/libraries/issues/CORE_ZGV_0003.php rename to application/libraries/issues/resolvers/CORE_ZGV_0003.php diff --git a/application/libraries/issues/CORE_ZGV_0004.php b/application/libraries/issues/resolvers/CORE_ZGV_0004.php similarity index 100% rename from application/libraries/issues/CORE_ZGV_0004.php rename to application/libraries/issues/resolvers/CORE_ZGV_0004.php diff --git a/application/libraries/issues/CORE_ZGV_0005.php b/application/libraries/issues/resolvers/CORE_ZGV_0005.php similarity index 100% rename from application/libraries/issues/CORE_ZGV_0005.php rename to application/libraries/issues/resolvers/CORE_ZGV_0005.php 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..1aaafa471 --- /dev/null +++ b/application/libraries/vertragsbestandteil/GehaltsbestandteilLib.php @@ -0,0 +1,157 @@ +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 fetchGehaltsbestandteileValorisiertForChart($dienstverhaeltnis_id, $stichtag=null, $includefuture=false) + { + return $this->GehaltsbestandteilModel->getGehaltsbestandteileValorisiertForChart($dienstverhaeltnis_id, $stichtag, $includefuture); + } + + public function fetchGehaltsbestandteile($dienstverhaeltnis_id, $stichtag=null, + $includefuture=false, $withvalorisationhistory=true) + { + return $this->GehaltsbestandteilModel->getGehaltsbestandteile( + $dienstverhaeltnis_id, $stichtag, $includefuture, $withvalorisationhistory + ); + } + + 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..2e6182957 --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilLib.php @@ -0,0 +1,519 @@ +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, $withvalorisationhistory=true) + { + $vbs = $this->VertragsbestandteilModel->getVertragsbestandteile( + $dienstverhaeltnis_id, $stichtag, $includefuture + ); + $gbs = $this->GehaltsbestandteilLib->fetchGehaltsbestandteile( + $dienstverhaeltnis_id, $stichtag, $includefuture, $withvalorisationhistory + ); + + $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/CL/Messages_model.php b/application/models/CL/Messages_model.php index b987102dd..04192a7b4 100644 --- a/application/models/CL/Messages_model.php +++ b/application/models/CL/Messages_model.php @@ -128,8 +128,8 @@ class Messages_model extends CI_Model { $ouOptions .= sprintf( "\n".'', - is_numeric($ou->prestudent_id) ? $ou->oe_kurzbz : self::ALT_OE, - $ou->bezeichnung . (is_numeric($ou->prestudent_id) ? '' : ' *') + ($ou->typ === 'l' ? $ou->oe_kurzbz : (is_numeric($ou->prestudent_id) ? $ou->oe_kurzbz : self::ALT_OE)), + $ou->bezeichnung . ((is_numeric($ou->prestudent_id) || $ou->typ === 'l' ) ? '' : ' *') ); } } diff --git a/application/models/accounting/Vertrag_model.php b/application/models/accounting/Vertrag_model.php index 8725cd98d..abc2114a6 100644 --- a/application/models/accounting/Vertrag_model.php +++ b/application/models/accounting/Vertrag_model.php @@ -299,6 +299,91 @@ class Vertrag_model extends DB_Model } } + /** + * Prueft ob ein Mitarbeiter einen erteilten Vertrag zu einer Lehrveranstaltung besitzt. + * @param $lehrveranstaltung_id ID der Lehrveranstaltung + * @param $studiensemester_kurzbz Studiensemester das geprueft wird + * @param $mitarbeiter_uid UID des Mitarbeiters + */ + public function isVertragErteiltLV($lehrveranstaltung_id, $studiensemester_kurzbz, $mitarbeiter_uid) + { + if (defined('CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON') + && CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON != '') + { + // Liegt das Studiensemester vor dem Pruefdatum, wird die LV immer als Erteilt angezeigt + $stsemquery = " + SELECT + tbl_studiensemester.start + FROM + public.tbl_studiensemester + WHERE + studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz)." + AND tbl_studiensemester.start < ( + SELECT + start + FROM + public.tbl_studiensemester stsem + WHERE + stsem.studiensemester_kurzbz = " . $this->escape(CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON)." + )"; + + if ($stsemresult = $this->execReadOnlyQuery($stsemquery)) + { + $stsemdata = getData($stsemresult); + if ($stsemdata && count($stsemdata) > 0) + { + // Wenn das Studiensemester vor dem Pruefdatum liegt, gilt der Vertrag immer als erteilt. + return true; + } + } + else + { + return false; + } + } + + $query = " + SELECT + 1 + FROM + lehre.tbl_lehreinheitmitarbeiter + JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) + JOIN lehre.tbl_vertrag USING(vertrag_id) + JOIN lehre.tbl_vertrag_vertragsstatus USING(vertrag_id) + WHERE + tbl_lehreinheitmitarbeiter.mitarbeiter_uid = " . $this->escape($mitarbeiter_uid) . " + AND tbl_lehreinheit.studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + AND tbl_lehreinheit.lehrveranstaltung_id = " . $this->escape(intval($lehrveranstaltung_id)) . " + AND tbl_vertrag_vertragsstatus.vertragsstatus_kurzbz='erteilt' + AND NOT EXISTS( + SELECT + 1 + FROM + lehre.tbl_vertrag_vertragsstatus vstatus + WHERE + vstatus.vertrag_id = tbl_vertrag.vertrag_id + AND vstatus.vertragsstatus_kurzbz = 'storno' + ) + "; + + if ($result = $this->execReadOnlyQuery($query)) + { + $data = getData($result); + if ($data && count($data) > 0) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + // ----------------------------------------------------------------------------------------------------------------- // Private methods diff --git a/application/models/codex/Abschluss_model.php b/application/models/codex/Abschluss_model.php new file mode 100644 index 000000000..2907deff1 --- /dev/null +++ b/application/models/codex/Abschluss_model.php @@ -0,0 +1,30 @@ +dbTable = 'bis.tbl_abschluss'; + $this->pk = 'ausbildung_code'; + } + + public function getActiveAbschluesse($languageIndex) + { + return $this->execQuery( + ' + SELECT + ausbildung_code, bezeichnung[?], in_oesterreich + FROM + bis.tbl_abschluss + WHERE + aktiv + ORDER BY + CASE WHEN in_oesterreich THEN 0 ELSE 1 END, ausbildung_code', + array($languageIndex) + ); + } +} 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..069037cee 100644 --- a/application/models/codex/Gemeinde_model.php +++ b/application/models/codex/Gemeinde_model.php @@ -19,4 +19,38 @@ class Gemeinde_model extends DB_Model return $this->loadWhere(array("plz" => $plz)); } -} \ No newline at end of file + + public function getGemeindeByNation($nation, $zip) + { + $this->addSelect(["name"]); + + if ($nation == "A") + { + if (isset($zip) && $zip > 999 && $zip < 32000) + { + $gemeinde_res = $this->GemeindeModel->loadWhere(['plz' => $zip]); + if (isError($gemeinde_res)) + { + show_error("error while trying to query bis.tbl_gemeinde"); + } + $gemeinde_res = hasData($gemeinde_res) ? getData($gemeinde_res) : null; + $gemeinde_res = array_map(function ($obj) { + return $obj->name; + }, $gemeinde_res); + echo json_encode($gemeinde_res); + + } else { + echo json_encode(error("ortschaftskennziffer code was not valid")); + } + } + } + + 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); + } +} diff --git a/application/models/codex/Uhstat1daten_model.php b/application/models/codex/Uhstat1daten_model.php new file mode 100644 index 000000000..9bca44b58 --- /dev/null +++ b/application/models/codex/Uhstat1daten_model.php @@ -0,0 +1,14 @@ +dbTable = 'bis.tbl_uhstat1daten'; + $this->pk = 'uhstat1daten_id'; + } +} diff --git a/application/models/content/Ampel_Benutzer_Bestaetigt_model.php b/application/models/content/Ampel_Benutzer_Bestaetigt_model.php new file mode 100644 index 000000000..72373c2d8 --- /dev/null +++ b/application/models/content/Ampel_Benutzer_Bestaetigt_model.php @@ -0,0 +1,14 @@ +dbTable = 'public.tbl_ampel_benutzer_bestaetigt'; + $this->pk = 'ampel_benutzer_bestaetigt_id'; + } + +} diff --git a/application/models/content/Ampel_model.php b/application/models/content/Ampel_model.php index c50025a12..1f6cf9f93 100644 --- a/application/models/content/Ampel_model.php +++ b/application/models/content/Ampel_model.php @@ -16,37 +16,95 @@ class Ampel_model extends DB_Model * 1. not after the deadline date * 2. not before the vorlaufszeit * @param bool $email If true, then only ampeln are retrieved that are marked to be sent by mail. - * @return array Returns array of objects. + * @return stdClass Returns array of objects. */ - public function active($email = false) + public function active($email = false, $uid = null) { - $parametersArray = null; - $query = ' - SELECT * - FROM public.tbl_ampel - WHERE'; - - if ($email === true) - { - $parametersArray['email'] = $email; - $query .= ' email = ? AND'; + $userLanguage = getUserLanguage(); + $selectStatement='*,beschreibung[('.$this->getLanguageIndex($this->escape($userLanguage)).')] as beschreibung_trans, buttontext[('.$this->getLanguageIndex($this->escape($userLanguage)).')] as buttontext_trans'; + + if($uid != null ){ + $selectStatement .= ', + COALESCE(( + SELECT true + FROM public.tbl_ampel_benutzer_bestaetigt a + WHERE a.ampel_id = ' . $this->dbTable . '.ampel_id + AND uid = ' . $this->escape($uid) . ' LIMIT 1), false) as bestaetigt'; } - $query .= '( - (NOW()<(deadline+(COALESCE(verfallszeit,0) || \' days\')::interval)::date) - OR (verfallszeit IS NULL) - AND (NOW()>(deadline-(COALESCE(vorlaufzeit,0) || \' days\')::interval)::date) - OR (vorlaufzeit IS NULL AND NOW() < deadline))'; + $this->addSelect($selectStatement); + $whereStatement=''; - $query .= ' ORDER BY deadline DESC'; + if ($email === true) { + $whereStatement .= ' email = '.$this->escape($email).' AND'; + } + + $whereStatement .= + '( + ( + (NOW()<(deadline+(COALESCE(verfallszeit,0) || \' days\')::interval)::date) + OR (verfallszeit IS NULL) + ) + AND + ( + (NOW()>(deadline-(COALESCE(vorlaufzeit,0) || \' days\')::interval)::date) + OR (vorlaufzeit IS NULL AND NOW() < deadline) + ) + )'; + + $this->addOrder('deadline', 'DESC'); + return $this->loadWhere($whereStatement); + + } + + public function openActive($uid, $email = false) + { + $userLanguage = getUserLanguage(); + $selectStatement = '*,beschreibung[(' . $this->getLanguageIndex($this->escape($userLanguage)) . ')] as beschreibung_trans, buttontext[(' . $this->getLanguageIndex($this->escape($userLanguage)) . ')] as buttontext_trans'; + + + $selectStatement .= ', + COALESCE(( + SELECT true + FROM public.tbl_ampel_benutzer_bestaetigt a + WHERE a.ampel_id = ' . $this->dbTable . '.ampel_id + AND uid = ' . $this->escape($uid) . ' LIMIT 1), false) as bestaetigt'; + + $this->addSelect($selectStatement); + $whereStatement = ''; + + if ($email === true) { + $whereStatement .= ' email = ' . $this->escape($email) . ' AND'; + } + + $whereStatement .= + ' + (COALESCE(( + SELECT true + FROM public.tbl_ampel_benutzer_bestaetigt a + WHERE a.ampel_id = ' . $this->dbTable . '.ampel_id + AND uid = ' . $this->escape($uid) . ' LIMIT 1), false) = FALSE) AND + ( + ( + (NOW()<(deadline+(COALESCE(verfallszeit,0) || \' days\')::interval)::date) + OR (verfallszeit IS NULL) + ) + AND + ( + (NOW()>(deadline-(COALESCE(vorlaufzeit,0) || \' days\')::interval)::date) + OR (vorlaufzeit IS NULL AND NOW() < deadline) + ) + )'; + + $this->addOrder('deadline', 'DESC'); + return $this->loadWhere($whereStatement); - return $this->execQuery($query, $parametersArray); } /** * Returns all Ampel-receiver of a specific Ampel. * @param string $benutzer_select SQL Statement which defines the Ampel-receiver. - * @return array Returns array of objects with property 'uid'. + * @return stdClass Returns array of objects with property 'uid'. */ public function execBenutzerSelect($benutzer_select) { @@ -90,4 +148,101 @@ class Ampel_model extends DB_Model else return $result; //will contain the error-msg from execQuery } + + /** + * checks if a user is assigned to an ampel + * @param string $uid userID + * @param string $benutzer_select the select query which gets all the user that are assigned to an ampel + * @return stdClass + */ + public function isZugeteilt($uid, $benutzer_select){ + $zugeteilt = $this->execReadOnlyQuery(" + SELECT + CASE WHEN ? IN (".$benutzer_select.") + THEN true + ELSE false + END as zugeteilt + ", [$uid]); + + if(isError($zugeteilt)){ + return $zugeteilt; + } + + $zugeteilt = getData($zugeteilt); + + return success(current($zugeteilt)->zugeteilt); + } + + // THIS FUNCTION IS NOT IN USE + // fetches all ampeln that were assigned to the user after the working start_date + function alleAmpeln($uid){ + $userLanguage = getUserLanguage(); + + $zugeteile_ampeln = []; + + $datum = new datum(); + $now = $datum->mktime_fromdate(date('Y-m-d')); + + // start date of user + $benutzerStartDate = $this->execReadOnlyQuery(" + SELECT insertamum FROM public.tbl_benutzer WHERE uid = ?", [$uid]); + $benutzerStartDate = $datum->mktime_fromdate(date(current(getData($benutzerStartDate))->insertamum)); + + $allAmpeln = $this->execReadOnlyQuery(" + SELECT *, beschreibung[(".$this->getLanguageIndex($this->escape($userLanguage)).")] as beschreibung_trans, buttontext[(".$this->getLanguageIndex($this->escape($userLanguage)).")] as buttontext_trans FROM + public.tbl_ampel"); + + if(isError($allAmpeln)) return error(getError($allAmpeln)); + + $allAmpeln = getData($allAmpeln); + foreach($allAmpeln as $ampel){ + + // check if the ampel is assigned to the user + $zugeteilt = $this->execReadOnlyQuery(" + SELECT + CASE WHEN ? IN (".$ampel->benutzer_select.") + THEN true + ELSE false + END as zugeteilt + ", [$uid]); + + if(isError($zugeteilt)) return error(getError($zugeteilt)); + + $zugeteilt = current(getData($zugeteilt))->zugeteilt; + + + // abgelaufen check + // $now > strtotime('+' . $ampel->verfallszeit . ' day', $ampel->deadline) + + if( + // aktuelles datum liegt vor der Vorlaufzeit der Ampel + (isset($ampel->vorlaufzeit) && $now < strtotime('-' . $ampel->vorlaufzeit . ' day', $datum->mktime_fromdate($ampel->deadline))) + || + // ampel ist vor Arbeitsstart abgelaufen + (isset($ampel->verfallszeit) && $benutzerStartDate > strtotime('+' . $ampel->verfallszeit . ' day', $datum->mktime_fromdate($ampel->deadline))) + || + // ampel ist vor Arbeitsstart abgelaufen (verfallszeit nicht vorhanden) + ($benutzerStartDate > strtotime('+' . $ampel->verfallszeit . ' day', $datum->mktime_fromdate($ampel->deadline))) + ){ + // continue iteration if ampel is expired before work start or shouldn't be visible yet + continue; + } + + $ampel->zugeteilt = $zugeteilt; + + if($zugeteilt) $zugeteile_ampeln[] = $ampel; + + } + + return success($zugeteile_ampeln); + } + + private function getLanguageIndex($userLanguage) + { + return " + SELECT index + FROM public.tbl_sprache + WHERE sprache = " . $userLanguage; + } + } diff --git a/application/models/content/Content_model.php b/application/models/content/Content_model.php index ee4315ebd..278022b59 100644 --- a/application/models/content/Content_model.php +++ b/application/models/content/Content_model.php @@ -11,4 +11,316 @@ class Content_model extends DB_Model $this->dbTable = 'campus.tbl_content'; $this->pk = 'content_id'; } + + /** + * Laedt den Content in der angegebenen Sprache + * Sollte der Content in dieser Sprache nicht vorhanden sein, wird der Content in der Default Sprache geladen + * + * @param integer $content_id + * @param string $sprache optional + * @param integer $version optional + * @param boolean | null $sichtbar optional + * + * @return stdClass + */ + public function getContent($content_id, $sprache = DEFAULT_LANGUAGE, $version = null, $sichtbar = null, $load_default_language = false) + { + $this->load->model('content/Contentsprache_model', 'ContentspracheModel'); + $spracheExists = $this->ContentspracheModel->exists($content_id, $sprache, $version, $sichtbar); + if (isError($spracheExists)) + return $spracheExists; + + if(!getData($spracheExists)) + { + if($load_default_language) + $sprache = DEFAULT_LANGUAGE; + else + return error('Der Content existiert in dieser Sprache nicht '); + } + + $condition = ['content_id' => $content_id, 'sprache' => $sprache]; + + if ($sichtbar === true || $sichtbar === false) + $condition['sichtbar'] = $sichtbar; + if ($version) + $condition['version'] = $version; + + $this->addSelect([ + '*', + 'tbl_contentsprache.insertamum', + 'tbl_contentsprache.insertvon', + 'tbl_contentsprache.updateamum', + 'tbl_contentsprache.updatevon' + ]); + $this->addJoin('campus.tbl_contentsprache', 'content_id'); + $this->addOrder('version', 'DESC'); + $this->addLimit(1); + + $result = $this->loadWhere($condition); + + if (isError($result)) + return $result; + if (!getData($result)) + return error('Dieser Eintrag wurde nicht gefunden'); + + return success(current(getData($result))); + } + + /** + * Sucht die content_id fuer den CIS4_Root Menu content + * + * @return integer|null content_id of the Cis4_Root Menu + */ + public function getMenuContentID(){ + // early return if the CIS4_MENU_ENTRY constant is defined + if(defined('CIS4_MENU_ENTRY')) + { + return CIS4_MENU_ENTRY; + } + + // load the CIS4 Menu content_id from the database using the column 'beschreibugn' of the campus.tbl_content table + $CIS4_ROOT_CONTENT = $this->loadWhere(["beschreibung"=>"CIS4_ROOT"]); + + if(isError($CIS4_ROOT_CONTENT)) + { + return null; + } + + $CIS4_ROOT_CONTENT = getData($CIS4_ROOT_CONTENT); + + if(count($CIS4_ROOT_CONTENT) > 0) + { + return current($CIS4_ROOT_CONTENT)->content_id ?? null; + } + else + { + return null; + } + } + + /** + * Laedt alle Content Eintraege unterhalb eines Contents + * (Ohne Newseintraege) + * + * @param integer $root_content_id + * @param string $uid + * @param string $sprache optional + * + * @return stdClass on success an array with menu objects + */ + public function getMenu($root_content_id, $uid, $sprache = DEFAULT_LANGUAGE) + { + + /*, + { + "content_id": 1000007, + "template_kurzbz": "redirect", + "titel": "Anrechnung", + "content": "", + "menu_open": false, + "aktiv": true, + "childs": [] + } + */ + + /* + { + "content_id": 1000003, + "template_kurzbz": "redirect", + "titel": "COVID-19", + "content": "", + "menu_open": false, + "aktiv": true, + "childs": [] + }, + */ + + if ($root_content_id === null) { + $res = json_decode('{ + "content_id": 1000000, + "template_kurzbz": "contentmittitel", + "titel": "CIS4", + "content": "", + "menu_open": true, + "aktiv": true, + "childs": [ + { + "content_id": 1000001, + "template_kurzbz": "redirect", + "titel": "News", + "content": "", + "menu_open": false, + "aktiv": true, + "childs": [] + }, + { + "content_id": 1000002, + "template_kurzbz": "redirect", + "titel": "Profil", + "content": "", + "menu_open": false, + "aktiv": true, + "childs": [] + }, + { + "content_id": 1000004, + "template_kurzbz": "redirect", + "titel": "Meine LV", + "content": "", + "menu_open": false, + "aktiv": true, + "childs": [] + }, + { + "content_id": 1000005, + "template_kurzbz": "redirect", + "titel": "Stundenplan", + "content": "", + "menu_open": false, + "aktiv": true, + "childs": [] + }, + { + "content_id": 1000006, + "template_kurzbz": "redirect", + "titel": "Dokumente", + "content": "", + "menu_open": false, + "aktiv": true, + "childs": [] + }, + { + "content_id": 1000007, + "template_kurzbz": "redirect", + "titel": "Studierendenstatus", + "content": "", + "menu_open": false, + "aktiv": true, + "childs": [] + } + + ] + }'); + return success($res); + } + $sql = " + SELECT + c.content_id, + c.template_kurzbz, + s.titel, + s.content, + c.menu_open, + c.aktiv, + k.child_content_id, + k.sort FROM ( + SELECT + c.content_id, + s.contentsprache_id + FROM + campus.tbl_content c + JOIN ( + SELECT + s5.content_id, + s5.contentsprache_id + FROM ( + SELECT + content_id, + sprache, + MAX(version) AS version + FROM ( + SELECT + c1.content_id, + COALESCE(s1.sprache, ?) AS sprache + FROM + campus.tbl_content c1 + LEFT JOIN + campus.tbl_contentsprache s1 ON c1.content_id=s1.content_id AND s1.sprache=? + WHERE + sichtbar=true + ) s2 + LEFT JOIN + campus.tbl_contentsprache s3 USING(content_id, sprache) + WHERE + sichtbar=true + GROUP BY + content_id, + sprache + ) s4 + LEFT JOIN + campus.tbl_contentsprache s5 USING(content_id, sprache, version) + WHERE + version IS NOT NULL + ) t USING (content_id) + JOIN + campus.tbl_contentsprache s USING (contentsprache_id) + WHERE + c.template_kurzbz<>'news' + AND + c.content_id IN ( + WITH RECURSIVE childs(content_id, child_content_id) as + ( + SELECT content_id, child_content_id FROM campus.tbl_contentchild + WHERE content_id=? + UNION ALL + SELECT cc.child_content_id, null FROM campus.tbl_contentchild cc, childs + WHERE cc.content_id=childs.content_id + ) + SELECT content_id + FROM childs + GROUP BY content_id + ) + GROUP BY c.content_id, + s.contentsprache_id + ) m + JOIN + campus.tbl_content c USING(content_id) + JOIN + campus.tbl_contentsprache s USING(contentsprache_id) + LEFT JOIN + campus.tbl_contentchild k ON(m.content_id=k.content_id) + WHERE EXISTS ( + SELECT 1 + FROM campus.tbl_contentgruppe + JOIN public.vw_gruppen USING(gruppe_kurzbz) + WHERE ( + tbl_contentgruppe.content_id=c.content_id + OR NOT EXISTS ( + SELECT 1 + FROM campus.tbl_contentgruppe + WHERE content_id=c.content_id + ) + ) + AND vw_gruppen.uid=? + ) + ORDER BY content_id, sort"; + + $result = $this->execQuery($sql, [DEFAULT_LANGUAGE, $sprache, $root_content_id, $uid]); + + if (isError($result)) + return $result; + + $contents = getData($result) ?? []; + $result = []; + foreach ($contents as $content) { + if (!isset($result[$content->content_id])) { + $result[$content->content_id] = clone($content); + unset($result[$content->content_id]->child_content_id); + unset($result[$content->content_id]->sort); + $result[$content->content_id]->childs = []; + } + if ($content->child_content_id !== null) + $result[$content->content_id]->childs[] = $content->child_content_id; + } + foreach ($result as $content) { + foreach ($content->childs as $k => $v) { + if (isset($result[$v])) { + $content->childs[$k] = $result[$v]; + } else { + unset($content->childs[$k]); + } + } + } + + return success(isset($result[$root_content_id]) ? $result[$root_content_id] : null); + } } diff --git a/application/models/content/Contentgruppe_model.php b/application/models/content/Contentgruppe_model.php index 03efc87b1..23dc897a1 100644 --- a/application/models/content/Contentgruppe_model.php +++ b/application/models/content/Contentgruppe_model.php @@ -11,4 +11,50 @@ class Contentgruppe_model extends DB_Model $this->dbTable = 'campus.tbl_contentgruppe'; $this->pk = array('gruppe_kurzbz', 'content_id'); } + + /** + * Prueft ob der Zugriff auf den Content eingeschraenkt ist auf + * eine bestimmte Benutzergruppe + * + * @param int $content_id + * + * @return stdClass success(true) wenn eingeschraenkt sonst success(false) + */ + public function islocked($content_id) + { + $islocked = $this->loadWhere(['content_id' => $content_id]); + + if (isError($islocked)) + return $islocked; + return success(!!getData($islocked)); + } + + /** + * Prueft ob ein User die Berechtigung fuer das Anzeigen des + * Contents besitzt + * + * @param int $content_id ID des Contents + * @param string $uid User der versucht auf den Content zuzugreifen + * + * @return stdClass + */ + public function berechtigt($content_id, $uid) + { + $islocked = $this->islocked($content_id); + if (isError($islocked)) + return $islocked; + + $condition = ['uid' => $uid]; + if (getData($islocked)) { + $condition['content_id'] = $content_id; + } + $this->addJoin('public.vw_gruppen', 'gruppe_kurzbz'); + + $result = $this->loadWhere($condition); + + if (isError($result)) + return $result; + return success(!!getData($result)); + } + } diff --git a/application/models/content/Contentsprache_model.php b/application/models/content/Contentsprache_model.php index eb7e257b2..80b053e28 100644 --- a/application/models/content/Contentsprache_model.php +++ b/application/models/content/Contentsprache_model.php @@ -11,4 +11,32 @@ class Contentsprache_model extends DB_Model $this->dbTable = 'campus.tbl_contentsprache'; $this->pk = 'contentsprache_id'; } + + /** + * Prueft ob der Content in der angegeben Sprache vorhanden ist + * + * @param int $content_id + * @param string $sprache + * @param int | null $version (optional) + * @param boolean | null $sichtbar (optional) + * @return stdClass + */ + public function exists($content_id, $sprache, $version=null, $sichtbar=null) + { + $condition = ['content_id' => $content_id, 'sprache' => $sprache]; + + if ($version) + $condition['version'] = $version; + + if ($sichtbar !== null) + $condition['sichtbar'] = $sichtbar; + + $result = $this->loadWhere($condition); + + if (isError($result)) + return $result; + + return success(!!getData($result)); + } + } diff --git a/application/models/content/News_model.php b/application/models/content/News_model.php index 8d636d808..0700a7057 100644 --- a/application/models/content/News_model.php +++ b/application/models/content/News_model.php @@ -11,4 +11,124 @@ class News_model extends DB_Model $this->dbTable = 'campus.tbl_news'; $this->pk = 'news_id'; } + + /** + * Get all News ordered by date. (most actual on top) + * @param null $limit Amount of news. + * @return array + */ + public function getAll($limit = null) + { + $this->addJoin("campus.tbl_content","content_id"); + return $this->execReadOnlyQuery(' + SELECT * + FROM campus.tbl_news + JOIN campus.tbl_content content ON content.content_id = campus.tbl_news.content_id + WHERE + --text IS NOT NULL AND + datum <= NOW() AND (datum_bis IS NULL OR datum_bis >= now()::date) + ORDER BY datum DESC + LIMIT ' . $this->escape($limit) + ); + } + + public function getNewsContentIDs($limit=10){ + $this->addSelect(['content_id']); + return $this->loadWhere("datum <= NOW() AND (datum_bis IS NULL OR datum_bis >= now()::date) + ORDER BY datum DESC + LIMIT " . $this->escape($limit)); + + } + + + + /** + * @param string $sprache + * @param string $studiengang_kz + * @param integer | null $semester + * @param string $fachbereich_kurzbz + * @param boolean $sichtbar + * @param integer $maxalter + * @param integer $page + * @param integer $page_size + * @param boolean $all + * @param boolean $mischen + * + * TODO(chris): this is not a good function -> the params are all over the place + * + */ + protected function prepareNewsWithContent($sprache, $studiengang_kz, $semester, $fachbereich_kurzbz = null, $sichtbar = true, $maxalter = 0, $page = 1, $page_size = 10, $all = false, $mischen = true) + { + + $this->addOrder('datum', 'DESC'); + + $studiengang_kz = trim($studiengang_kz); + $fachbereich_kurzbz = trim($fachbereich_kurzbz); + + $where = []; + if (trim($maxalter) != '0') { + $where[] = "(now()-datum) < interval " . $this->db->escape($maxalter) . " days"; + + } + if (!$all) { + $where[] = "datum <= now()"; + $where[] = "(datum_bis >= now()::date OR datum_bis IS NULL)"; + } + if ($fachbereich_kurzbz != '*') { + if ($fachbereich_kurzbz == '') { + $where[] = "fachbereich_kurzbz IS NULL"; + } else { + $where[] = "fachbereich_kurzbz = " . $this->db->escape($fachbereich_kurzbz); + + } + } + if ($studiengang_kz == '0') { + $where[] = "studiengang_kz = " . $this->db->escape($studiengang_kz); + + if ($semester === NULL) + $where[] = "semester IS NULL"; + elseif ($semester === 0) + $where[] = "semester = 0"; + } elseif ($studiengang_kz != '') { + $add = $mischen === true ? " OR (studiengang_kz = 0 AND semester IS NULL)" : ""; + $where[] = "((studiengang_kz = " . $this->db->escape($studiengang_kz) . " AND semester = " . $this->db->escape($semester) . ") OR (studiengang_kz = " . $this->db->escape($studiengang_kz) . " AND semester = 0) OR (studiengang_kz = 0 AND semester = " . $this->db->escape($semester) . ")" . $add . ")"; + + } + $this->addJoin('campus.tbl_contentsprache cs', 'content_id'); + + $where[] = "cs.sichtbar = " . ($sichtbar ? "true" : "false"); + + $where[] = "cs.sprache = (CASE WHEN EXISTS(SELECT 1 FROM campus.tbl_contentsprache cs2 WHERE cs2.content_id=" . $this->dbTable . ".content_id AND sprache=" . $this->db->escape($sprache) . ") THEN " . $this->db->escape($sprache) . " ELSE " . $this->db->escape(DEFAULT_LANGUAGE) . " END)"; + + + $where[] = "cs.version = (SELECT MAX(version) FROM campus.tbl_contentsprache cs3 WHERE cs3.content_id=" . $this->dbTable . ".content_id AND cs3.sprache = (CASE WHEN EXISTS(SELECT 1 FROM campus.tbl_contentsprache cs2 WHERE cs2.content_id=" . $this->dbTable . ".content_id AND sprache=" . $this->db->escape($sprache) . ") THEN " . $this->db->escape($sprache) . " ELSE " . $this->db->escape(DEFAULT_LANGUAGE) . " END))"; + + + $where = implode(" AND ", $where); + + $this->db->where($where, NULL, FALSE); + + } + + public function getNewsWithContent($sprache, $studiengang_kz, $semester, $fachbereich_kurzbz = null, $sichtbar = true, $maxalter = 0, $page = 1, $page_size = 10, $all = false, $mischen = true) + { + $this->prepareNewsWithContent($sprache, $studiengang_kz, $semester, $fachbereich_kurzbz, $sichtbar, $maxalter, $page, $page_size, $all, $mischen); + + // getting the number of rows of the query and adding pagination to the query result + $num_rows = $this->getNumRows(true); + $this->addPagination($page, $page_size, $num_rows); + + // preparing the query again because every call to get_compiled_select or cour_all_results will add the from clause to the query + $this->prepareNewsWithContent($sprache, $studiengang_kz, $semester, $fachbereich_kurzbz, $sichtbar, $maxalter, $page, $page_size, $all, $mischen); + + return $this->load(); + } + + public function countNewsWithContent($sprache, $studiengang_kz, $semester, $fachbereich_kurzbz = null, $sichtbar = true, $maxalter = 0, $page = 1, $page_size = 10, $all = false, $mischen = true) + { + $this->prepareNewsWithContent($sprache, $studiengang_kz, $semester, $fachbereich_kurzbz, $sichtbar, $maxalter, $page, $page_size, $all, $mischen); + return $this->getNumRows(); + } + + } diff --git a/application/models/crm/Akte_model.php b/application/models/crm/Akte_model.php index fe9db5330..57b6e0665 100644 --- a/application/models/crm/Akte_model.php +++ b/application/models/crm/Akte_model.php @@ -171,7 +171,7 @@ class Akte_model extends DB_Model * @param bool $nachgereicht if true, retrieves only nachgereichte Dokumente. if false, only not nachgereichte. default: null, all Dokumente * @return array */ - public function getAktenWithDokInfo($person_id, $dokument_kurzbz = null, $nachgereicht = null) + public function getAktenWithDokInfo($person_id, $dokument_kurzbz = null, $nachgereicht = null, $archiv = null) { $this->addSelect('public.tbl_akte.*, bezeichnung_mehrsprachig, dokumentbeschreibung_mehrsprachig, public.tbl_dokument.bezeichnung as dokument_bezeichnung, bis.tbl_nation.*, ausstellungsdetails'); $this->addJoin('public.tbl_dokument', 'dokument_kurzbz'); @@ -184,10 +184,64 @@ class Akte_model extends DB_Model if(is_bool($nachgereicht)) $where['nachgereicht'] = $nachgereicht; + if (is_bool($archiv)) + $where['archiv'] = $archiv; + $dokumente = $this->loadWhere($where); if($dokumente->error) return $dokumente; return success($dokumente->retval); } + + /** + * Liefert die Archivdokumente einer Person + * + * @param integer $person_id + * @param boolean|null $signiert Wenn true werden nur Dokumente geliefert die digital signiert wurden. + * @param boolean|null $stud_selfservice Wenn true werden nur Dokumente geliefert die Studierende selbst herunterladen duerfen. + * + * @return stdClass + */ + public function getArchiv($person_id, $signiert = null, $stud_selfservice = null) + { + $this->addSelect('akte_id'); + $this->addSelect('person_id'); + $this->addSelect('dokument_kurzbz'); + $this->addSelect('mimetype'); + $this->addSelect('erstelltam'); + $this->addSelect('gedruckt'); + $this->addSelect('titel_intern'); + $this->addSelect('anmerkung_intern'); + $this->addSelect('titel'); + $this->addSelect('bezeichnung'); + $this->addSelect('updateamum'); + $this->addSelect('insertamum'); + $this->addSelect('updatevon'); + $this->addSelect('insertvon'); + $this->addSelect('uid'); + $this->addSelect('dms_id'); + $this->addSelect('anmerkung'); + $this->addSelect('nachgereicht'); + $this->addSelect('CASE WHEN inhalt is not null THEN true ELSE false END as inhalt_vorhanden', false); + $this->addSelect('nachgereicht_am'); + $this->addSelect('ausstellungsnation'); + $this->addSelect('formal_geprueft_amum'); + $this->addSelect('archiv'); + $this->addSelect('signiert'); + $this->addSelect('stud_selfservice'); + $this->addSelect('akzeptiertamum'); + + if ($signiert !== null) + $this->db->where('signiert', (boolean)$signiert); + if ($stud_selfservice !== null) + $this->db->where('stud_selfservice', (boolean)$stud_selfservice); + + $this->addOrder('erstelltam', 'DESC'); + + return $this->loadWhere([ + 'person_id' => $person_id, + 'archiv' => true + ]); + } } diff --git a/application/models/crm/Konto_model.php b/application/models/crm/Konto_model.php index 4b2a259c9..51d3117bc 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,75 @@ 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); } + + /** + * @param integer $prestudent_id + * @param string $stsem + * @param array $buchungstypen + * + * @return stdClass + */ + public function checkStudienbeitragFromPrestudent($prestudent_id, $stsem, $buchungstypen) + { + $this->addSelect($this->dbTable . '.buchungsnr'); + $this->addSelect($this->dbTable . '.buchungsdatum'); + + $this->addJoin('public.tbl_prestudent s', $this->dbTable . '.person_id=s.person_id AND ' . $this->dbTable . '.studiengang_kz=s.studiengang_kz'); + + $this->db->where_in('buchungstyp_kurzbz', $buchungstypen); + $this->db->where('0 >= ( + SELECT sum(betrag) + FROM ' . $this->dbTable . ' skonto + WHERE skonto.buchungsnr = ' . $this->dbTable . '.buchungsnr_verweis + OR skonto.buchungsnr_verweis = ' . $this->dbTable . '.buchungsnr_verweis + )', null, false); + + return $this->loadWhere([ + 'prestudent_id' => $prestudent_id, + 'studiensemester_kurzbz' => $stsem + ]); + } + + /* + * 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 f37b715f4..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 */ @@ -309,13 +342,39 @@ class Prestudent_model extends DB_Model */ public function getLastPrestudent($person_id, $withzgv = false) { - $qry = 'SELECT * FROM public.tbl_prestudent - WHERE person_id = ? + $qry = 'SELECT * FROM public.tbl_prestudent ps %s + WHERE ps.person_id = ? ORDER BY updateamum DESC NULLS LAST, insertamum DESC NULLS LAST LIMIT 1'; - $zgvwhere = $withzgv === true ? 'AND zgv_code IS NOT NULL' : ''; + $zgvwhere = ''; + if ($withzgv === true) + { + $zgvwhere = ' + LEFT JOIN ( + SELECT ps2.zgvmas_code, + ps2.zgvmanation, + ps2.zgvmadatum, + ps2.zgvmaort, + ps2.zgvmas_erfuellt, + ps2.person_id + FROM tbl_prestudent ps2 + WHERE zgvmas_code IS NOT NULL + ORDER BY updateamum DESC NULLS LAST, insertamum DESC NULLS LAST + ) zgvmas ON zgvmas.person_id = ps.person_id + LEFT JOIN ( + SELECT ps2.zgv_code, + ps2.zgvnation, + ps2.zgvdatum, + ps2.zgvort, + ps2.zgv_erfuellt, + ps2.person_id + FROM tbl_prestudent ps2 + WHERE zgv_code IS NOT NULL + ORDER BY updateamum DESC NULLS LAST, insertamum DESC NULLS LAST + )zgv ON zgv.person_id = ps.person_id'; + } $qry = sprintf($qry, $zgvwhere); @@ -560,9 +619,10 @@ class Prestudent_model extends DB_Model o.bezeichnung, (CASE WHEN sg.typ = \'b\' THEN ps.prestudent_id - WHEN sg.typ = \'m\' THEN ps.prestudent_id + WHEN sg.typ = \'m\' THEN mps.prestudent_id ELSE NULL - END) AS prestudent_id + END) AS prestudent_id, + sg.typ FROM public.tbl_prestudent p JOIN public.tbl_studiengang sg USING(studiengang_kz) JOIN public.tbl_organisationseinheit o USING(oe_kurzbz) @@ -571,11 +631,17 @@ class Prestudent_model extends DB_Model FROM public.tbl_prestudentstatus WHERE status_kurzbz = \'Bewerber\' ) ps USING(prestudent_id) + LEFT JOIN ( + SELECT prestudent_id + FROM public.tbl_prestudentstatus + WHERE status_kurzbz = \'Interessent\' AND bestaetigtam IS NOT NULL + ) mps ON p.prestudent_id = mps.prestudent_id WHERE p.person_id = ? GROUP BY o.oe_kurzbz, o.bezeichnung, sg.typ, ps.prestudent_id, + mps.prestudent_id, p.prestudent_id ORDER BY o.bezeichnung'; @@ -667,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..5f3c8400e 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 */ @@ -13,6 +26,77 @@ class Prestudentstatus_model extends DB_Model $this->hasSequence = false; } + /** + * loadWhereUid + * + * loads all rows for a student_uid + * + * @param string $uid + * @param array $where Optional. Default empty array + * @param boolean $withPrestudent Optional. Default true + * + * @return stdClass + */ + public function loadWhereUid($uid, $where = null, $withPrestudent = false) + { + $this->addSelect($this->dbTable . '.*'); + $this->addJoin('public.tbl_student', 'prestudent_id'); + + if ($withPrestudent) { + $this->addJoin('public.tbl_prestudent s', 'prestudent_id'); + $this->addSelect('s.aufmerksamdurch_kurzbz'); + $this->addSelect('s.person_id'); + $this->addSelect('s.studiengang_kz'); + $this->addSelect('s.berufstaetigkeit_code'); + $this->addSelect('s.ausbildungcode'); + $this->addSelect('s.zgv_code'); + $this->addSelect('s.zgvort'); + $this->addSelect('s.zgvdatum'); + $this->addSelect('s.zgvmas_code'); + $this->addSelect('s.zgvmaort'); + $this->addSelect('s.zgvmadatum'); + $this->addSelect('s.aufnahmeschluessel'); + $this->addSelect('s.facheinschlberuf'); + $this->addSelect('s.reihungstest_id'); + $this->addSelect('s.anmeldungreihungstest'); + $this->addSelect('s.reihungstestangetreten'); + $this->addSelect('s.rt_gesamtpunkte'); + $this->addSelect('s.bismelden'); + $this->addSelect('s.dual'); + $this->addSelect('s.rt_punkte1'); + $this->addSelect('s.rt_punkte2'); + $this->addSelect('s.ausstellungsstaat'); + $this->addSelect('s.rt_punkte3'); + $this->addSelect('s.zgvdoktor_code'); + $this->addSelect('s.zgvdoktorort'); + $this->addSelect('s.zgvdoktordatum'); + $this->addSelect('s.mentor'); + $this->addSelect('s.zgvnation'); + $this->addSelect('s.zgvmanation'); + $this->addSelect('s.zgvdoktornation'); + $this->addSelect('s.gsstudientyp_kurzbz'); + $this->addSelect('s.aufnahmegruppe_kurzbz'); + $this->addSelect('s.udf_values'); + $this->addSelect('s.priorisierung'); + $this->addSelect('s.foerderrelevant'); + $this->addSelect('s.standort_code'); + $this->addSelect('s.zgv_erfuellt'); + $this->addSelect('s.zgvmas_erfuellt'); + $this->addSelect('s.zgvdoktor_erfuellt'); + } + + + $this->addOrder('datum'); + $this->addOrder('insertamum'); + + if (!$where) + $where = []; + + $where['student_uid'] = $uid; + + return $this->loadWhere($where); + } + /** * getLastStatus */ @@ -226,4 +310,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/RueckstellungStatus_model.php b/application/models/crm/RueckstellungStatus_model.php new file mode 100644 index 000000000..a4cb391f1 --- /dev/null +++ b/application/models/crm/RueckstellungStatus_model.php @@ -0,0 +1,14 @@ +dbTable = 'public.tbl_rueckstellung_status'; + $this->pk = 'status_kurzbz'; + } +} \ No newline at end of file diff --git a/application/models/crm/Rueckstellung_model.php b/application/models/crm/Rueckstellung_model.php new file mode 100644 index 000000000..c84c625eb --- /dev/null +++ b/application/models/crm/Rueckstellung_model.php @@ -0,0 +1,33 @@ +dbTable = 'public.tbl_rueckstellung'; + $this->pk = 'rueckstellung_id'; + $this->hasSequence = true; + } + + public function getByPersonId($person_id, $status = null) + { + $language_index = getUserLanguage() == 'German' ? 0 : 1; + + $this->addLimit(1); + $this->addJoin('tbl_rueckstellung_status', 'status_kurzbz'); + $this->addSelect('*, + array_to_json(bezeichnung_mehrsprachig::varchar[])->>'.$language_index . ' as bezeichnung'); + $this->addOrder('datum_bis', 'DESC'); + + $where['person_id'] = $person_id; + + if (!isEmptyString($status)) + $where['status_kurzbz'] = $status; + + return $this->loadWhere($where); + } +} \ No newline at end of file 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..539c3cf56 100644 --- a/application/models/crm/Student_model.php +++ b/application/models/crm/Student_model.php @@ -1,4 +1,8 @@ hasSequence = false; } + /** + * Checks if the user is a Student. + * @param string $uid + * @return array + */ + public function isStudent($uid) + { + $this->addSelect('1'); + + $result = $this->loadWhere(array('student_uid' => $uid)); + + + if(hasData($result)) + { + return success(true); + } + else + { + return success(false); + } + } + // **** // * Generiert die Matrikelnummer // * FORMAT: 0710254001 @@ -43,9 +69,169 @@ class Student_model extends DB_Model $max = 0; $max += 1; + return $matrikelnummer.sprintf("%03d", $max); } + /** + * Generiert die Matrikelnummer + * FORMAT: 0710254001 + * 07 = Jahr + * 1/2/0 = WS/SS/incoming + * 0254 = Studiengangskennzahl vierstellig + * 001 = Laufende Nummer + * copy of generateMatrikelnummer plus + * logic FH Burgenland + * + * TODO(chris): replace function above with this? + * TODO(chris): rename to generatePersonenkennzeichen? + * + * @param integer $studiengang_kz + * @param string $studiensemester_kurzbz + * @param string $typ + * + * @return stdClass + */ + public function generateMatrikelnummer2($studiengang_kz, $studiensemester_kurzbz, $typ = null) + { + $personenkennzeichen = false; + + Events::trigger( + 'generate_personenkennzeichen', + function ($value) use ($personenkennzeichen) { + $personenkennzeichen = $value; + }, + $studiengang_kz, + $studiensemester_kurzbz, + $typ + ); + + if ($personenkennzeichen !== false) + return success($personenkennzeichen); + + // Validierung der Eingabewerte + if (strlen($studiensemester_kurzbz) < 6) { + throw new InvalidArgumentException("Ungültiges studiensemester_kurzbz Format."); + } + + $jahr = mb_substr($studiensemester_kurzbz, 4); + $art = substr($studiensemester_kurzbz, 0, 2); + + if (($studiengang_kz < 0) || (isset($typ) && ($typ == 'l'))) + { + $studiengang_kz=abs($studiengang_kz); + //Lehrgang + switch($art) + { + case 'WS': + $art = '3'; + break; + case 'SS': + $art = '4'; + break; + default: + $art = '0'; + break; + } + } + else + { + //Studiengang + switch($art) + { + case 'WS': + $art = '1'; + break; + case 'SS': + $art = '2'; + break; + default: + $art = '0'; + break; + } + } + if($art=='2' || $art=='4') + $jahr = $jahr-1; + + //FH-Burgenland - weil leider die AO Studiengänge aufgeteilt sind + //(AO sind normal 9+erhalter Nummer, matrikelnr/personenkz wird auch im DVUH Extension berücksichtigt) + if ($studiengang_kz >= 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 +264,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/dashboard/Bookmark_model.php b/application/models/dashboard/Bookmark_model.php new file mode 100644 index 000000000..5efacc26b --- /dev/null +++ b/application/models/dashboard/Bookmark_model.php @@ -0,0 +1,18 @@ +dbTable = 'dashboard.tbl_bookmark'; + $this->pk = 'bookmark_id'; + } + + + + +} diff --git a/application/models/dashboard/Dashboard_Override_model.php b/application/models/dashboard/Dashboard_Override_model.php new file mode 100644 index 000000000..d7a12bb42 --- /dev/null +++ b/application/models/dashboard/Dashboard_Override_model.php @@ -0,0 +1,26 @@ +dbTable = 'dashboard.tbl_dashboard_benutzer_override'; + $this->pk = 'override_id'; + } + + + /** + * Get Overrides of given uid. + * @param integer dashboard_id + * @param string $uid + * @return array + */ + public function getOverride($dashboard_id, $uid) + { + return $this->loadWhere(array('dashboard_id' => $dashboard_id, 'uid'=> $uid)); + } +} diff --git a/application/models/dashboard/Dashboard_Preset_model.php b/application/models/dashboard/Dashboard_Preset_model.php new file mode 100644 index 000000000..ca10ce98a --- /dev/null +++ b/application/models/dashboard/Dashboard_Preset_model.php @@ -0,0 +1,67 @@ +dbTable = 'dashboard.tbl_dashboard_preset'; + $this->pk = 'preset_id'; + } + + /** + * Get Presets of given uid. + * @param integer dashboard_id + * @param string $uid + * @return array + */ + public function getPresets($dashboard_id, $uid) + { + // TODO: get Funktionen for uid and load all preset for all funktionen for uid + //return $this->loadWhere(array('dashboard_id' => $dashboard_id, 'funktion_kurzbz'=> null)); + $sql = <<execQuery($sql, array($dashboard_id, $uid)); + } + + /** + * Get Preset by Dashboard and Funktion + * @param integer dashboard_id + * @param string funktion_kurzbz + * @return array + */ + public function getPresetByDashboardAndFunktion($dashboard_id, $funktion_kurzbz) + { + return $this->loadWhere(array('dashboard_id' => $dashboard_id, 'funktion_kurzbz' => $funktion_kurzbz)); + } +} diff --git a/application/models/dashboard/Dashboard_Widget_model.php b/application/models/dashboard/Dashboard_Widget_model.php new file mode 100644 index 000000000..9e0a4c200 --- /dev/null +++ b/application/models/dashboard/Dashboard_Widget_model.php @@ -0,0 +1,15 @@ +dbTable = 'dashboard.tbl_dashboard_widget'; + $this->pk = ['dashboard_id', 'widget_id']; + $this->hasSequence = false; + } +} diff --git a/application/models/dashboard/Dashboard_model.php b/application/models/dashboard/Dashboard_model.php new file mode 100644 index 000000000..88946ed83 --- /dev/null +++ b/application/models/dashboard/Dashboard_model.php @@ -0,0 +1,25 @@ +dbTable = 'dashboard.tbl_dashboard'; + $this->pk = 'dashboard_id'; + } + + + /** + * Get Dashboard by kurzbz. + * @param string dashboard_kurzbz + * @return array + */ + public function getDashboardByKurzbz($dashboard_kurzbz) + { + return $this->loadWhere(array('dashboard_kurzbz' => $dashboard_kurzbz)); + } +} diff --git a/application/models/dashboard/Widget_model.php b/application/models/dashboard/Widget_model.php new file mode 100644 index 000000000..b1160e28f --- /dev/null +++ b/application/models/dashboard/Widget_model.php @@ -0,0 +1,32 @@ +dbTable = 'dashboard.tbl_widget'; + $this->pk = 'widget_id'; + } + + public function getWithAllowedForDashboard($dashboard_id) + { + $this->addSelect($this->dbTable . '.*'); + $this->addSelect('CASE WHEN dashboard_id IS NULL THEN 0 ELSE 1 END AS allowed', false); + $this->db->join('dashboard.tbl_dashboard_widget dw', $this->dbTable . '.widget_id=dw.widget_id AND dashboard_id = ?', 'LEFT', false); + + return $this->execQuery($this->db->get_compiled_select($this->dbTable), [$dashboard_id]); + } + + public function getForDashboard($db) + { + $this->addSelect($this->dbTable . '.*'); + $this->addJoin('dashboard.tbl_dashboard_widget', 'widget_id'); + $this->addJoin('dashboard.tbl_dashboard', 'dashboard_id'); + + return $this->loadWhere(['dashboard_kurzbz' => $db]); + } +} diff --git a/application/models/education/Anrechnung_model.php b/application/models/education/Anrechnung_model.php index ebecf4118..cbfdb6607 100644 --- a/application/models/education/Anrechnung_model.php +++ b/application/models/education/Anrechnung_model.php @@ -30,7 +30,7 @@ class Anrechnung_model extends DB_Model */ public function createAnrechnungsantrag( $prestudent_id, $studiensemester_kurzbz, $lehrveranstaltung_id, - $begruendung_id, $dms_id, $anmerkung_student = null + $begruendung_id, $dms_id, $anmerkung_student = null, $begruendung_ects = null, $begruendung_lvinhalt = null ) { // Start DB transaction @@ -44,6 +44,8 @@ class Anrechnung_model extends DB_Model 'dms_id' => $dms_id, 'studiensemester_kurzbz' => $studiensemester_kurzbz, 'anmerkung_student' => $anmerkung_student, + 'begruendung_ects' => $begruendung_ects, + 'begruendung_lvinhalt' => $begruendung_lvinhalt, 'insertvon' => $this->_uid )); diff --git a/application/models/education/Anrechnungszeitraum_model.php b/application/models/education/Anrechnungszeitraum_model.php new file mode 100644 index 000000000..e6f0f13d3 --- /dev/null +++ b/application/models/education/Anrechnungszeitraum_model.php @@ -0,0 +1,87 @@ +dbTable = 'lehre.tbl_anrechnungszeitraum'; + $this->pk = 'anrechnungszeitraum_id'; + } + + /** + * Save new Anrechnungszeitraum. + * + * @param $studiensemester_kurzbz + * @param $anrechnungstart + * @param $anrechnungende + * @return array|stdClass + */ + public function insertAzr($studiensemester_kurzbz, $anrechnungstart, $anrechnungende) + { + $result = $this->insert(array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'anrechnungstart' => $anrechnungstart, + 'anrechnungende' => $anrechnungende, + 'insertvon' => getAuthUID() + )); + + if (isError($result)) + { + return error('Fehler bei Anrechnungszeitraum speichern.'); + } + + // Return new anrechnungszeitraum_id + return success($result->retval); + } + + /** + * Delete Anrechnungszeitraum. + * + * @param $anrechnungszeitraum_id + * @return array|stdClass + */ + public function deleteAzr($anrechnungszeitraum_id) + { + $result = $this->delete(array('anrechnungszeitraum_id' => $anrechnungszeitraum_id)); + + if (isError($result)) + { + return error('Fehler bei Anrechnungszeitraum löschen.'); + } + + return success($result->retval); + } + + /** + * Update existing Anrechnungszeitraum. + * + * @param $anrechnungszeitraum_id + * @param $studiensemester_kurzbz + * @param $anrechnungstart + * @param $anrechnungende + * @return array|stdClass + */ + public function updateAzr($anrechnungszeitraum_id, $studiensemester_kurzbz, $anrechnungstart, $anrechnungende) + { + $result = $this->update( + $anrechnungszeitraum_id, + array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'anrechnungstart' => $anrechnungstart, + 'anrechnungende' => $anrechnungende + ) + ); + + if (isError($result)) + { + return error('Fehler bei Anrechnungszeitraum update.'); + } + + return success($result->retval); + } + +} 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/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php index 10c122b94..afad6870b 100644 --- a/application/models/education/Lehreinheit_model.php +++ b/application/models/education/Lehreinheit_model.php @@ -113,4 +113,135 @@ class Lehreinheit_model extends DB_Model return $this->execQuery($query, array($lehreinheit_id)); } + + /** + * Gets emails of all Studierende in a lehrveranstaltung + * @param int $lehreinheit_id + * @return array + */ + public function getStudentenMail($lehreinheit_id) + { + + // logic used from cis_menu_lv.inc.php line 335 + return $this->execReadOnlyQuery(" + SELECT + gruppe_kurzbz, + CASE + WHEN nomail = TRUE THEN 'nomail' + WHEN gruppe_kurzbz !='' THEN LOWER(gruppe_kurzbz || '@' || ?) + ELSE LOWER(stg_typ || stg_kurzbz || semester || TRIM(verband) || TRIM(gruppe) || '@' || ?) + END AS mail + + FROM + ( + SELECT + distinct vw_lehreinheit.studiensemester_kurzbz, vw_lehreinheit.stg_kurzbz, vw_lehreinheit.stg_typ, vw_lehreinheit.semester, + COALESCE(vw_lehreinheit.verband,'') as verband, COALESCE(vw_lehreinheit.gruppe,'') as gruppe, vw_lehreinheit.gruppe_kurzbz, tbl_gruppe.mailgrp, + CASE + WHEN mailgrp = TRUE OR mailgrp IS NULL THEN FALSE + ELSE TRUE + END as nomail + FROM campus.vw_lehreinheit + LEFT JOIN public.tbl_gruppe USING(gruppe_kurzbz) + WHERE + vw_lehreinheit.lehrveranstaltung_id= + (select distinct lehrveranstaltung_id from campus.vw_lehreinheit where lehreinheit_id=?) + AND + vw_lehreinheit.studiensemester_kurzbz = + (select distinct studiensemester_kurzbz from campus.vw_lehreinheit where lehreinheit_id=?) + AND (vw_lehreinheit.gruppe_kurzbz IS NULL OR + (vw_lehreinheit.gruppe_kurzbz IS NOT NULL AND (SELECT COUNT(*) FROM public.tbl_benutzergruppe where gruppe_kurzbz = vw_lehreinheit.gruppe_kurzbz AND studiensemester_kurzbz = vw_lehreinheit.studiensemester_kurzbz) > 0)) + + + ) AS subquery + ",[DOMAIN,DOMAIN,$lehreinheit_id,$lehreinheit_id ]); + } + + public function getLehreinheitenForStudentAndStudienSemester($lehrveranstaltung_id, $student_uid, $studiensemester_kurzbz) + { + $query = <<escape($lehrveranstaltung_id)} AND + vslv.uid = {$this->escape($student_uid)} AND + vslv.studiensemester_kurzbz = {$this->escape($studiensemester_kurzbz)} +EOSQL; + + $res = $this->execReadOnlyQuery($query); + return $res; + } + + public function getLehrfachIdMitarbeiter($angezeigtes_stsem,$user,$lvid) + { + $query = " + SELECT + distinct lehrfach_id + FROM + lehre.tbl_lehreinheit + JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id) + WHERE + studiensemester_kurzbz=" . $this->escape($angezeigtes_stsem) . " + AND mitarbeiter_uid=" . $this->escape($user)." + AND lehrveranstaltung_id=" . $this->escape(intval($lvid)); + + $res = $this->execReadOnlyQuery($query); + return $res; + } + + public function getLehrfachIdStudierender($angezeigtes_stsem,$user,$lvid) + { + $query = " + SELECT + distinct lehrfach_id + FROM + campus.vw_student_lehrveranstaltung + WHERE + lehrveranstaltung_id=" . $this->escape(intval($lvid))." + AND studiensemester_kurzbz=" . $this->escape($angezeigtes_stsem)." + AND uid=" . $this->escape($user); + + $res = $this->execReadOnlyQuery($query); + return $res; + } + + public function getLehreinheitInfo($lvid, $angezeigtes_stsem, $lehrfach_id) + { + $query = " + SELECT + * + FROM ( + SELECT + distinct on(uid) vorname, nachname, tbl_benutzer.uid as uid, + CASE + WHEN lehrfunktion_kurzbz='LV-Leitung' THEN true + ELSE false + END as lvleiter + FROM + lehre.tbl_lehreinheit, lehre.tbl_lehreinheitmitarbeiter, + public.tbl_benutzer, public.tbl_person + WHERE + tbl_lehreinheit.lehreinheit_id = tbl_lehreinheitmitarbeiter.lehreinheit_id + AND tbl_lehreinheitmitarbeiter.mitarbeiter_uid = tbl_benutzer.uid + AND tbl_person.person_id = tbl_benutzer.person_id + AND lehrveranstaltung_id = " . $this->escape(intval($lvid)) . " + AND tbl_lehreinheitmitarbeiter.mitarbeiter_uid NOT like '_Dummy%' + AND tbl_benutzer.aktiv = true + AND tbl_person.aktiv = true + AND studiensemester_kurzbz = " . $this->escape($angezeigtes_stsem); + + if($lehrfach_id != '') + { + $query .= " AND tbl_lehreinheit.lehrfach_id = " . $this->escape(intval($lehrfach_id)); + } + + $query .= " ORDER BY uid, lvleiter desc) as a ORDER BY lvleiter desc, nachname, vorname"; + + $res = $this->execReadOnlyQuery($query); + return $res; + } } diff --git a/application/models/education/Lehreinheitmitarbeiter_model.php b/application/models/education/Lehreinheitmitarbeiter_model.php index dd5c7c858..ae1ac55d2 100644 --- a/application/models/education/Lehreinheitmitarbeiter_model.php +++ b/application/models/education/Lehreinheitmitarbeiter_model.php @@ -41,4 +41,38 @@ class Lehreinheitmitarbeiter_model extends DB_Model return error ('Incorrect parameter type'); } } + + /** + * @param integer $lehrveranstaltung_id + * @param string $studiensemester_kurzbz + * + * @return stdClass + */ + public function getForLv($lehrveranstaltung_id, $studiensemester_kurzbz) + { + $this->addSelect('ma.uid, ma.vorname, ma.nachname, ma.titelpre, ma.titelpost, lehrfunktion_kurzbz'); + $this->addGroupBy('ma.uid, ma.vorname, ma.nachname, ma.titelpre, ma.titelpost, lehrfunktion_kurzbz'); + + $this->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->addJoin('campus.vw_mitarbeiter ma', $this->dbTable . '.mitarbeiter_uid=ma.uid'); + + $this->addOrder('nachname'); + $this->addOrder('vorname'); + + if (defined('CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON') && CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON != '') + { + $this->addJoin('(SELECT vertrag_id, CASE WHEN vertragsstatus_kurzbz=\'storno\' THEN 0 WHEN vertragsstatus_kurzbz=\'erteilt\' THEN 1 ELSE 2 END AS vertragsstatus_kurzbz FROM lehre.tbl_vertrag_vertragsstatus) v', 'vertrag_id', 'LEFT'); + $having = $this->db->compile_binds('(EXISTS (SELECT 1 FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=? AND tbl_studiensemester.start < (SELECT start FROM public.tbl_studiensemester stsem WHERE stsem.studiensemester_kurzbz=?)) OR MIN(vertragsstatus_kurzbz)=1)', [ + $studiensemester_kurzbz, + CIS_LV_LEKTORINNENZUTEILUNG_VERTRAGSPRUEFUNG_VON + ]); + $this->db->having($having); + } + + return $this->loadWhere([ + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); + } + } diff --git a/application/models/education/LehrveranstaltungFaktor_model.php b/application/models/education/LehrveranstaltungFaktor_model.php new file mode 100644 index 000000000..c8a0c8aa8 --- /dev/null +++ b/application/models/education/LehrveranstaltungFaktor_model.php @@ -0,0 +1,14 @@ +dbTable = 'lehre.tbl_lehrveranstaltung_faktor'; + $this->pk = 'lehrveranstaltung_faktor_id'; + } +} diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index f54443955..3f02f5ce7 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 @@ -200,6 +491,28 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($query, array($lehrveranstaltung_id, $studiensemester_kurzbz)); } + /** + * Gets all Leiter of Lehrveranstaltungsorganisationseinheit + * @param $lehrveranstaltung_id + * @return array|null + */ + public function getLeitungOfLvOe($lehrveranstaltung_id) + { + $query = "select distinct vorname, nachname, uid + FROM + lehre.tbl_lehrveranstaltung lv + JOIN public.tbl_organisationseinheit og using (oe_kurzbz) + JOIN public.tbl_benutzerfunktion bf using (oe_kurzbz) + join public.tbl_benutzer b using (uid) + join public.tbl_person p using (person_id) + where + bf.datum_von <= now()::date + and (bf.datum_bis >= now()::date or bf.datum_bis is null) + and bf.funktion_kurzbz = 'Leitung' -- Leitung of LV-OE + and lehrveranstaltung_id = ?"; + + return $this->execQuery($query, array($lehrveranstaltung_id)); + } /** * Gets Lehrveranstaltungen of a student @@ -231,6 +544,113 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($qry, $params); } + /** + * Gets Lehrveranstaltungen of a student with grades if available + * + * @param string $student_uid + * @param string $studiensemester_kurzbz + * @param string|null $sprache + * @param number|null $lvid - returns only information about that single lv if the parameter is set + * + * @return stdClass + */ + public function getLvsByStudentWithGrades($student_uid, $studiensemester_kurzbz, $sprache = null, $lvid=null) + { + if ($sprache) { + $sprache_qry = $this->db->compile_binds('SELECT index FROM public.tbl_sprache WHERE sprache = ?', [$sprache]); + $bezeichnung = 'bezeichnung_mehrsprachig[(' . $sprache_qry . ')]'; + $sgbezeichnung = $sprache == 'English' ? 'COALESCE(sg.english, sg.bezeichnung)' : 'sg.bezeichnung'; + $lvbezeichnung = $sprache == 'English' ? 'COALESCE(v.bezeichnung_english, v.bezeichnung)' : 'v.bezeichnung'; + } else { + $bezeichnung = 'bezeichnung'; + $sgbezeichnung = 'sg.bezeichnung'; + $lvbezeichnung = 'v.bezeichnung'; + } + + $this->addDistinct(); + // TODO(chris): selects + /* + semester (?) + module + bezeichnung + sg_bezeichnung + studiengang_kuerzel + lvnote + znote + studiengang_kz + lehrveranstaltung_id + benotung + lvinfo + farbe + + sprache (?) + ects (?) + incoming (?) + orgform_kurzbz (?) + */ + // TODO(chris): module or kf + #$this->addSelect($this->dbTable . '.*'); + #$this->addSelect('v.*'); + $this->addSelect($this->dbTable . '.benotung'); + $this->addSelect($this->dbTable . '.lvinfo'); + $this->addSelect($this->dbTable . '.farbe'); + $this->addSelect($this->dbTable . '.incoming'); + $this->addSelect($this->dbTable . '.orgform_kurzbz'); + $this->addSelect('v.studiengang_kz'); + $this->addSelect('v.lehrveranstaltung_id'); + $this->addSelect('v.semester'); + + $this->addSelect('v.sprache'); + $this->addSelect('v.ects'); + $this->addSelect('znn.positiv'); + + #$this->addSelect('splv.module'); + $this->addSelect($lvbezeichnung . ' AS bezeichnung'); + $this->addSelect($sgbezeichnung . ' AS sg_bezeichnung'); + $this->addSelect('UPPER(sg.typ::VARCHAR(1) || sg.kurzbz) AS studiengang_kuerzel'); + + $this->addSelect('COALESCE(gnn.' . $bezeichnung . ', gnn.bezeichnung, gn.note::text) AS lvnote'); + $this->addSelect('COALESCE(znn.' . $bezeichnung . ', znn.bezeichnung, zn.note::text) AS znote'); + + // TODO(chris): Potentielle Anpassung "Eine UID" + $this->addJoin('campus.vw_student_lehrveranstaltung v', 'lehrveranstaltung_id'); + $this->addJoin('public.tbl_studiengang sg', $this->dbTable . '.studiengang_kz = sg.studiengang_kz'); + $this->db->where("v.lehreverzeichnis<>''"); + if(isset($lvid)) + { + $this->db->where("v.lehrveranstaltung_id", $lvid); + } + + $this->addJoin('campus.tbl_lvgesamtnote gn', 'gn.lehrveranstaltung_id=v.lehrveranstaltung_id AND gn.student_uid=v.uid AND gn.studiensemester_kurzbz=v.studiensemester_kurzbz', 'LEFT'); + $this->addJoin('lehre.tbl_note gnn', 'gn.note=gnn.note', 'LEFT'); + + $this->addJoin('lehre.tbl_zeugnisnote zn', 'zn.lehrveranstaltung_id=v.lehrveranstaltung_id AND zn.student_uid=v.uid AND zn.studiensemester_kurzbz=v.studiensemester_kurzbz', 'LEFT'); + $this->addJoin('lehre.tbl_note znn', 'zn.note=znn.note', 'LEFT'); + + $this->addOrder('bezeichnung'); + + /*if (!defined("CIS_PROFIL_STUDIENPLAN_MODULE_AUSBLENDEN") || !CIS_PROFIL_STUDIENPLAN_MODULE_AUSBLENDEN) { + $modulebezeichnung = str_replace('v.', 'm.', $lvbezeichnung); + $modulesql = ' + LEFT JOIN lehre.tbl_studienplan_lehrveranstaltung p ON(lv.studienplan_lehrveranstaltung_id_parent=p.studienplan_lehrveranstaltung_id) + LEFT JOIN lehre.tbl_lehrveranstaltung m ON(m.lehrveranstaltung_id = p.lehrveranstaltung_id)'; + } else { + $modulebezeichnung = 'NULL'; + $modulesql = ''; + } + + $this->addJoin('( + SELECT lv.lehrveranstaltung_id, sps.studiensemester_kurzbz, so.studiengang_kz, lv.semester, ' . $modulebezeichnung . ' AS module + FROM lehre.tbl_studienplan_lehrveranstaltung lv + LEFT JOIN lehre.tbl_studienplan sp ON(sp.studienplan_id=lv.studienplan_id) + JOIN lehre.tbl_studienplan_semester sps ON(sp.studienplan_id=sps.studienplan_id AND sps.semester=lv.semester) + JOIN lehre.tbl_studienordnung so ON(so.studienordnung_id=sp.studienordnung_id) + ' . $modulesql . ' + ) splv', 'splv.lehrveranstaltung_id=v.lehrveranstaltung_id AND splv.studiensemester_kurzbz=v.studiensemester_kurzbz AND splv.studiengang_kz=v.studiengang_kz', 'LEFT');*/ + + return $this->loadWhere(['v.uid' => $student_uid, 'v.lehre' => true, 'v.studiensemester_kurzbz' => $studiensemester_kurzbz]); + } + /** * Gets valid Lehrveranstaltungen with incoming places for a Studiensemester. * Only @@ -471,4 +891,125 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($qry, array($student_uid)); } + + /** + * @param integer $lehrveranstaltung_id + * @param string $studiensemester_kurzbz + * + * @return stdClass + */ + public function getKoordinator($lehrveranstaltung_id, $studiensemester_kurzbz = null) + { + $binds = [ + $lehrveranstaltung_id, + $lehrveranstaltung_id, + $lehrveranstaltung_id, + $lehrveranstaltung_id + ]; + $qry = " + SELECT + a.uid, vorname, nachname, titelpre, titelpost + FROM ( + SELECT + koordinator as uid + FROM + lehre.tbl_lehrveranstaltung + WHERE + lehrveranstaltung_id = ? + UNION + SELECT + uid + FROM + lehre.tbl_lehreinheit + JOIN lehre.tbl_lehrveranstaltung AS lehrfach ON(tbl_lehreinheit.lehrfach_id = lehrfach.lehrveranstaltung_id) + JOIN public.tbl_fachbereich ON(lehrfach.oe_kurzbz=tbl_fachbereich.oe_kurzbz) + JOIN public.tbl_benutzerfunktion ON(tbl_fachbereich.fachbereich_kurzbz=tbl_benutzerfunktion.fachbereich_kurzbz) + WHERE + tbl_benutzerfunktion.funktion_kurzbz='fbk' + AND (tbl_benutzerfunktion.datum_von IS null OR tbl_benutzerfunktion.datum_von <= now()) + AND (tbl_benutzerfunktion.datum_bis IS null OR tbl_benutzerfunktion.datum_bis >= now()) + AND tbl_lehreinheit.lehrveranstaltung_id = ? + AND tbl_benutzerfunktion.oe_kurzbz = ( + SELECT + tbl_studiengang.oe_kurzbz + FROM + lehre.tbl_lehrveranstaltung + JOIN public.tbl_studiengang USING(studiengang_kz) + WHERE lehrveranstaltung_id = ? + ) + AND EXISTS ( + SELECT + lehrveranstaltung_id + FROM + lehre.tbl_lehrveranstaltung + WHERE + lehrveranstaltung_id = ? + AND koordinator IS null + ) + "; + + if ($studiensemester_kurzbz !== null) + { + $qry .= " AND tbl_lehreinheit.studiensemester_kurzbz = ?"; + $binds[] = $studiensemester_kurzbz; + } + + $qry .= " + ) AS a + JOIN campus.vw_mitarbeiter ON(a.uid=vw_mitarbeiter.uid) + WHERE vw_mitarbeiter.aktiv + "; + + return $this->execQuery($qry, $binds); + } + + public function getStg($lehrveranstaltung_id) + { + $this->addSelect('stg.*'); + $this->addJoin('public.tbl_studiengang stg', 'studiengang_kz'); + return $this->load($lehrveranstaltung_id); + } + + //Berechtigungen auf Fachbereichsebene + public function getBerechtigungenAufFachberechsebene($lvid, $angezeigtes_stsem) + { + $query = " + SELECT + DISTINCT lehrfach.oe_kurzbz + FROM + lehre.tbl_lehrveranstaltung + JOIN + lehre.tbl_lehreinheit USING(lehrveranstaltung_id) + JOIN + lehre.tbl_lehrveranstaltung as lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id) + WHERE + tbl_lehrveranstaltung.lehrveranstaltung_id = " . $this->escape(intval($lvid)); + + if(isset($angezeigtes_stsem) && $angezeigtes_stsem != ''){ + $query .= " AND studiensemester_kurzbz = " . $this->escape($angezeigtes_stsem); + } + + $res = $this->execReadOnlyQuery($query); + return $res; + } + + public function getStudentEMail($lvid, $angezeigtes_stsem) + { + $query = " + SELECT + DISTINCT vw_lehreinheit.stg_kurzbz, vw_lehreinheit.stg_typ, + vw_lehreinheit.semester, COALESCE(vw_lehreinheit.verband,'') as verband, + COALESCE(vw_lehreinheit.gruppe,'') as gruppe, + vw_lehreinheit.gruppe_kurzbz, tbl_gruppe.mailgrp + FROM + campus.vw_lehreinheit + LEFT JOIN + public.tbl_gruppe USING(gruppe_kurzbz) + WHERE + lehrveranstaltung_id = " . $this->escape(intval($lvid)) . " + AND studiensemester_kurzbz = " . $this->escape($angezeigtes_stsem); + + $res = $this->execReadOnlyQuery($query); + return $res; + } } diff --git a/application/models/education/Lvangebot_model.php b/application/models/education/Lvangebot_model.php index e16b726dd..8d5096fb0 100644 --- a/application/models/education/Lvangebot_model.php +++ b/application/models/education/Lvangebot_model.php @@ -11,4 +11,39 @@ class Lvangebot_model extends DB_Model $this->dbTable = 'lehre.tbl_lvangebot'; $this->pk = 'lvangebot_id'; } + +/** + * Prueft ob eine Abmeldung von einer Lehrveranstaltung moeglich ist + * und liefert die Gruppen von denen sich abgemeldet werden kann + * @param $lehrveranstaltung_id + * @param $studiensemester_kurzbz + * @param $uid + * @return $gruppen Array mit den Gruppen + */ + public function AbmeldungMoeglich($lehrveranstaltung_id, $studiensemester_kurzbz, $uid) + { + $query = "SELECT + gruppe_kurzbz + FROM + lehre.tbl_lvangebot + JOIN public.tbl_benutzergruppe USING(studiensemester_kurzbz, gruppe_kurzbz) + WHERE + tbl_lvangebot.studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz)." + AND tbl_benutzergruppe.uid = " . $this->escape($uid)." + AND (tbl_lvangebot.lehrveranstaltung_id = " . $this->escape(intval($lehrveranstaltung_id))." + OR tbl_lvangebot.lehrveranstaltung_id IN(SELECT lehrveranstaltung_id_kompatibel + FROM lehre.tbl_lehrveranstaltung_kompatibel + WHERE lehrveranstaltung_id = " . $this->escape(intval($lehrveranstaltung_id))." + ) + )"; + $res = $this->execReadOnlyQuery($query); + $rows = (hasData($res)) ? getData($res) : array(); + + $gruppen=array(); + foreach($rows as $row) + { + $gruppen[] = $row->gruppe_kurzbz; + } + return $gruppen; + } } 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 087c27663..5fb58cc81 100644 --- a/application/models/education/Paabgabe_model.php +++ b/application/models/education/Paabgabe_model.php @@ -1,7 +1,6 @@ dbTable = 'campus.tbl_paabgabe'; $this->pk = 'paabgabe_id'; } + + /** + * Gets last Endabgabe of a Projektarbeit, including filename. + * @param int $projektarbeit_id + * @return object + */ + public function getEndabgabe($projektarbeit_id) + { + $qry = "SELECT paabgabe_id, student_uid, paabg.datum, paabg.abgabedatum, projekttyp_kurzbz, titel, titel_english, + paabgabe_id || '_' || student_uid || '.pdf' AS filename + FROM campus.tbl_paabgabe paabg + JOIN lehre.tbl_projektarbeit USING (projektarbeit_id) + WHERE projektarbeit_id = ? + AND paabgabetyp_kurzbz = 'end' + AND paabg.abgabedatum IS NOT NULL + ORDER BY paabg.abgabedatum DESC, paabg.datum DESC + LIMIT 1"; + + return $this->execQuery($qry, array($projektarbeit_id)); + } } diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index 0200f6468..95950bf95 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -54,18 +54,28 @@ class Projektbetreuer_model extends DB_Model $qry = "SELECT DISTINCT ON (pers.person_id) pers.person_id, betreuerart_kurzbz, vorname, nachname, trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as voller_name, anrede, titelpre, titelpost, gebdatum, geschlecht, pa.projekttyp_kurzbz, - ben.uid, ben.alias, ma.personalnummer, mitarbeiter_uid, student_uid - FROM lehre.tbl_projektarbeit pa - JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id) - JOIN public.tbl_person pers USING (person_id) - LEFT JOIN public.tbl_benutzer ben USING (person_id) - LEFT JOIN public.tbl_mitarbeiter ma ON ben.uid = ma.mitarbeiter_uid - WHERE ben.aktiv - AND projektarbeit_id = ? - AND betreuerart_kurzbz = ? - ORDER BY pers.person_id, CASE WHEN ma.mitarbeiter_uid IS NULL THEN 1 ELSE 0 END, /*Mitarbeiter account first*/ - CASE WHEN ben.uid IS NULL THEN 1 ELSE 0 END, /*user with account first*/ - ben.insertamum"; + ben.uid, ben.alias, ma.personalnummer, mitarbeiter_uid, student_uid, + ( + SELECT kontakt + FROM public.tbl_kontakt + WHERE kontakttyp = 'email' + AND person_id = pers.person_id + ORDER BY + CASE WHEN zustellung THEN 0 ELSE 1 END, + insertamum DESC NULLS LAST + LIMIT 1 + ) AS private_email + FROM lehre.tbl_projektarbeit pa + JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id) + JOIN public.tbl_person pers USING (person_id) + LEFT JOIN public.tbl_benutzer ben USING (person_id) + LEFT JOIN public.tbl_mitarbeiter ma ON ben.uid = ma.mitarbeiter_uid + WHERE (ben.aktiv OR ben.aktiv IS NULL) + AND projektarbeit_id = ? + AND betreuerart_kurzbz = ? + ORDER BY pers.person_id, CASE WHEN ma.mitarbeiter_uid IS NULL THEN 1 ELSE 0 END, /*Mitarbeiter account first*/ + CASE WHEN ben.uid IS NULL THEN 1 ELSE 0 END, /*user with account first*/ + ben.insertamum"; return $this->execQuery($qry, array($projektarbeit_id, $betreuerart_kurzbz)); } @@ -77,14 +87,14 @@ class Projektbetreuer_model extends DB_Model */ public function getBetreuerByToken($zugangstoken) { - $qry = ' + $qry = " SELECT tbl_projektbetreuer.person_id, tbl_projektbetreuer.projektarbeit_id, student_uid FROM lehre.tbl_projektbetreuer JOIN lehre.tbl_projektarbeit USING (projektarbeit_id) WHERE zugangstoken = ? AND zugangstoken_gueltigbis >= NOW() ORDER BY tbl_projektbetreuer.insertamum DESC, projektarbeit_id DESC LIMIT 1 - '; + "; return $this->execQuery($qry, array($zugangstoken)); } @@ -96,31 +106,60 @@ class Projektbetreuer_model extends DB_Model * @param $student_uid string uid des Studenten der Arbeit abgibt * @return object | bool */ - public function getZweitbegutachterWithToken($erstbegutachter_person_id, $projektarbeit_id, $student_uid) + public function getZweitbegutachterWithToken($erstbegutachter_person_id, $projektarbeit_id, $student_uid, $zweitbegutachter_person_id = null) { - $qry_betr = "SELECT betr.person_id, betr.projektarbeit_id, pers.anrede, betr.zugangstoken, betr.zugangstoken_gueltigbis, tbl_benutzer.uid, kontakt, - trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as voller_name, - CASE WHEN tbl_benutzer.uid IS NULL THEN kontakt ELSE tbl_benutzer.uid || '@".DOMAIN."' END AS email, abg.abgabedatum - FROM lehre.tbl_projektbetreuer betr - JOIN lehre.tbl_projektarbeit parb ON betr.projektarbeit_id = parb.projektarbeit_id - JOIN public.tbl_person pers ON betr.person_id = pers.person_id - LEFT JOIN public.tbl_kontakt ON pers.person_id = tbl_kontakt.person_id AND kontakttyp = 'email' AND zustellung = true - LEFT JOIN public.tbl_benutzer ON pers.person_id = tbl_benutzer.person_id - LEFT JOIN campus.tbl_paabgabe abg ON betr.projektarbeit_id = abg.projektarbeit_id AND abg.paabgabetyp_kurzbz = 'end' - WHERE betr.betreuerart_kurzbz = 'Zweitbegutachter' - AND betr.projektarbeit_id = ? - AND parb.student_uid = ? - AND EXISTS ( - SELECT 1 FROM lehre.tbl_projektbetreuer - WHERE person_id = ? - AND betreuerart_kurzbz = 'Erstbegutachter' - AND projektarbeit_id = betr.projektarbeit_id - ) - AND (tbl_benutzer.aktiv OR tbl_benutzer.aktiv IS NULL) - ORDER BY betr.insertamum DESC - LIMIT 1"; + $params = array($erstbegutachter_person_id, $erstbegutachter_person_id, $projektarbeit_id, $student_uid); - return $this->execQuery($qry_betr, array($projektarbeit_id, $student_uid, $erstbegutachter_person_id)); + $qry_betr = "SELECT betr.person_id, betr.projektarbeit_id, pers.anrede, betr.zugangstoken, betr.zugangstoken_gueltigbis, tbl_benutzer.uid, + trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as voller_name, + CASE WHEN tbl_benutzer.uid IS NULL THEN kontakt ELSE tbl_benutzer.uid || '@".DOMAIN."' END AS email, kontakt, + abg.abgabedatum, betr.betreuerart_kurzbz + FROM lehre.tbl_projektbetreuer betr + JOIN lehre.tbl_projektarbeit parb ON betr.projektarbeit_id = parb.projektarbeit_id + JOIN public.tbl_person pers ON betr.person_id = pers.person_id + LEFT JOIN public.tbl_kontakt ON pers.person_id = tbl_kontakt.person_id AND kontakttyp = 'email' AND zustellung = true + LEFT JOIN public.tbl_benutzer ON pers.person_id = tbl_benutzer.person_id + LEFT JOIN campus.tbl_paabgabe abg ON betr.projektarbeit_id = abg.projektarbeit_id AND abg.paabgabetyp_kurzbz = 'end' + WHERE + ( + ( + betr.betreuerart_kurzbz = 'Zweitbegutachter' + AND EXISTS ( + SELECT 1 FROM lehre.tbl_projektbetreuer + WHERE person_id = ? + AND betreuerart_kurzbz = 'Erstbegutachter' + AND projektarbeit_id = betr.projektarbeit_id + ) + ) + OR /* either Zweitbegutachter of masterarbeit, or Kommissionsprüfer if Kommission */ + ( + betr.betreuerart_kurzbz = 'Senatsmitglied' + AND EXISTS ( + SELECT 1 FROM lehre.tbl_projektbetreuer + WHERE person_id = ? + AND betreuerart_kurzbz = 'Senatsvorsitz' + AND projektarbeit_id = betr.projektarbeit_id + ) + ) + ) + AND betr.projektarbeit_id = ? + AND parb.student_uid = ? + AND (tbl_benutzer.aktiv OR tbl_benutzer.aktiv IS NULL)"; + + if (isset($zweitbegutachter_person_id)) + { + $qry_betr .= " AND betr.person_id = ?"; + $params[] = $zweitbegutachter_person_id; + } + + $qry_betr .= " ORDER BY betr.person_id DESC, + (CASE WHEN EXISTS ( /* if multiple accounts, prioritize mitarbeiter */ + SELECT 1 FROM public.tbl_mitarbeiter ma + WHERE ma.mitarbeiter_uid = tbl_benutzer.uid + ) THEN 0 ELSE 1 END), betr.insertamum DESC + LIMIT 1"; + + return $this->execQuery($qry_betr, $params); } /** @@ -131,23 +170,23 @@ class Projektbetreuer_model extends DB_Model */ public function generateZweitbegutachterToken($zweitbegutachter_person_id, $projektarbeit_id) { - $betreuerUidQry = "SELECT uid, zugangstoken, zugangstoken_gueltigbis, tbl_projektbetreuer.person_id + $betreuerUidQry = "SELECT uid, zugangstoken, zugangstoken_gueltigbis, tbl_projektbetreuer.person_id, betreuerart_kurzbz FROM lehre.tbl_projektbetreuer JOIN public.tbl_person USING(person_id) LEFT JOIN public.tbl_benutzer USING(person_id) WHERE projektarbeit_id = ? AND tbl_projektbetreuer.person_id = ? - AND betreuerart_kurzbz = 'Zweitbegutachter' + AND betreuerart_kurzbz IN ('Zweitbegutachter', 'Senatsmitglied') LIMIT 1"; - $betreueruidres = $this->execQuery($betreuerUidQry, array($projektarbeit_id, $zweitbegutachter_person_id)); + $betreueruidRes = $this->execQuery($betreuerUidQry, array($projektarbeit_id, $zweitbegutachter_person_id)); - if (!hasData($betreueruidres)) + if (!hasData($betreueruidRes)) return error('Zweitbegutachter nicht gefunden'); - $row_betr = getData($betreueruidres)[0]; + $zweitbetreuer = getData($betreueruidRes)[0]; - if (!isset($row_betr->uid)) + if (!isset($zweitbetreuer->uid)) { do { $token = generateToken(16); @@ -156,8 +195,8 @@ class Projektbetreuer_model extends DB_Model $result = $this->update( array('projektarbeit_id' => $projektarbeit_id, - 'person_id' => $row_betr->person_id, - 'betreuerart_kurzbz' => 'Zweitbegutachter'), + 'person_id' => $zweitbetreuer->person_id, + 'betreuerart_kurzbz' => $zweitbetreuer->betreuerart_kurzbz), array('zugangstoken' => $token, 'zugangstoken_gueltigbis' => date('Y-m-d', strtotime('+1 year'))) ); @@ -167,4 +206,29 @@ class Projektbetreuer_model extends DB_Model else return success("Account vorhanden, kein Token benötigt"); } + + /** + * Gets betreuerart of a Betreuer for a Projektarbeit. + * Main Betreuer are prioritized (normally one Betreuer should be assigned to a Projektarbeit another time with a different Betreuerart). + * @param int projektarbeit_id + * @param int betreuer_person_id + * @return object success or error + */ + public function getBetreuerart($projektarbeit_id, $betreuer_person_id) + { + $qry = "SELECT betreuerart_kurzbz + FROM lehre.tbl_projektbetreuer + WHERE projektarbeit_id = ? + AND person_id = ? + ORDER BY CASE WHEN betreuerart_kurzbz = 'Senatsvorsitz' THEN 1 /*Senatsvorsitz has priority*/ + WHEN betreuerart_kurzbz = 'Begutachter' THEN 2 + WHEN betreuerart_kurzbz = 'Erstbegutachter' THEN 3 + WHEN betreuerart_kurzbz = 'Zweitbegutachter' THEN 4 + WHEN betreuerart_kurzbz = 'Senatsmitglied' THEN 5 + ELSE 5 + END, insertamum DESC + LIMIT 1"; + + return $this->execQuery($qry, array($projektarbeit_id, $betreuer_person_id)); + } } diff --git a/application/models/education/Pruefung_model.php b/application/models/education/Pruefung_model.php index e3776c4ad..927d83c82 100644 --- a/application/models/education/Pruefung_model.php +++ b/application/models/education/Pruefung_model.php @@ -29,11 +29,281 @@ 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)); } + + /** + * Gets Pruefungen of a student for a Lehrveranstaltung. + * + * @param string $uid + * @param string $lehrveranstaltung_id + * @param string|null $sprache + * + * @return object + */ + public function getByStudentAndLv($uid, $lehrveranstaltung_id, $sprache = null) + { + // TODO(chris): Potentielle Anpassung "Eine UID" + $this->dbTable = 'lehre.tbl_pruefung'; + + if ($sprache) { + $sprache_qry = $this->db->compile_binds('SELECT index FROM public.tbl_sprache WHERE sprache = ?', [$sprache]); + $bezeichnung = 'bezeichnung_mehrsprachig[(' . $sprache_qry . ')]'; + } else { + $bezeichnung = 'bezeichnung'; + } + + $this->addSelect($this->dbTable . '.pruefung_id, ' . $this->dbTable . '.pruefungstyp_kurzbz, ' . $this->dbTable . '.datum, COALESCE(n.' . $bezeichnung . ', n.note::text) AS note'); + + $this->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->addJoin('lehre.tbl_note n', 'note'); + + return $this->loadWhere(['lehrveranstaltung_id' => $lehrveranstaltung_id, 'student_uid' => $uid]); + } + + /** + * 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..1b1a826aa 100644 --- a/application/models/organisation/Organisationseinheit_model.php +++ b/application/models/organisation/Organisationseinheit_model.php @@ -188,4 +188,33 @@ class Organisationseinheit_model extends DB_Model } return $this->loadWhere($condition); } + + /** + * @param string $oe_kurzbz + * + * @return stdClass + */ + public function getWithType($oe_kurzbz) + { + $this->addSelect($this->dbTable . '.*, t.bezeichnung AS organisationseinheittyp'); + $this->addJoin('public.tbl_organisationseinheittyp t', 'organisationseinheittyp_kurzbz'); + + return $this->load($oe_kurzbz); + } + + /** + * 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 e848cb4c2..e306ce950 100644 --- a/application/models/organisation/Studiengang_model.php +++ b/application/models/organisation/Studiengang_model.php @@ -457,7 +457,7 @@ class Studiengang_model extends DB_Model */ public function getLeitung($studiengang_kz = null) { - $this->addSelect('uid, studiengang_kz, oe_kurzbz, vorname, nachname, email'); + $this->addSelect('uid, studiengang_kz, oe_kurzbz, vorname, nachname, email, titelpre, titelpost, alias'); $this->addJoin('public.tbl_benutzerfunktion', 'oe_kurzbz'); $this->addJoin('public.tbl_benutzer', 'uid'); $this->addJoin('public.tbl_person', 'person_id'); @@ -493,6 +493,53 @@ class Studiengang_model extends DB_Model return $this->loadWhere($condition); } + /** + * Get Studiengangsleitung/en of Studiengang/Studiengaenge. With Details + * + * @param null $studiengang_kz Numeric or Array + * @return array + */ + public function getLeitungDetailed($studiengang_kz = null) + { + $this->addSelect('studiengang_kz, email, f.oe_kurzbz, b.uid, b.alias, b.aktiv, p.vorname, p.nachname, p.titelpre, p.titelpost, m.telefonklappe, k.kontakt, o.planbezeichnung'); + $this->addJoin('public.tbl_benutzerfunktion f', 'oe_kurzbz'); + $this->addJoin('public.tbl_benutzer b', 'uid'); + $this->addJoin('public.tbl_person p', 'person_id'); + $this->addJoin('public.tbl_mitarbeiter m', 'mitarbeiter_uid=uid', 'LEFT'); + $this->addJoin('public.tbl_kontakt k', 'k.standort_id=m.standort_id AND kontakttyp=\'telefon\'', 'LEFT'); + $this->addJoin('public.tbl_ort o', 'ort_kurzbz', 'LEFT'); + + if (!is_numeric($studiengang_kz) && !is_array($studiengang_kz)) + { + return error('Studiengangskennzahl ungültig'); + } + + if (is_null($studiengang_kz)) + { + $condition = ' + funktion_kurzbz = \'Leitung\' + AND ( datum_von <= NOW() OR datum_von IS NULL ) + AND ( datum_bis >= NOW() OR datum_bis IS NULL ) + '; + } + elseif (is_numeric($studiengang_kz) || is_array($studiengang_kz)) + { + if (is_array($studiengang_kz)) + { + $studiengang_kz = array_map(array($this,'escape'), $studiengang_kz); + $studiengang_kz = implode(', ', $studiengang_kz); + } + $condition = ' + funktion_kurzbz = \'Leitung\' + AND ( datum_von <= NOW() OR datum_von IS NULL ) + AND ( datum_bis >= NOW() OR datum_bis IS NULL ) + AND studiengang_kz IN (' . $studiengang_kz. ')'; + ; + } + + return $this->loadWhere($condition); + } + public function getStudiengaengeWithOrgForm($typ, $semester) { $query = "SELECT DISTINCT (UPPER(so.studiengangkurzbzlang || ':' || sp.orgform_kurzbz)) AS Studiengang @@ -508,13 +555,96 @@ class Studiengang_model extends DB_Model return $this->execQuery($query, array($typ, $semester)); } - public function getStudiengangTyp($studiengang_kz, $typ) + public function getStudiengangTyp($studiengang_kz, $typ = null) { $query = "SELECT DISTINCT(sgt.*) - FROM tbl_studiengangstyp sgt JOIN tbl_studiengang sg on sgt.typ = sg.typ - WHERE studiengang_kz IN ? and sgt.typ IN ?"; + FROM tbl_studiengangstyp sgt JOIN tbl_studiengang sg on sgt.typ = sg.typ + WHERE studiengang_kz IN ?"; - return $this->execQuery($query, array($studiengang_kz, $typ)); + $params = [$studiengang_kz]; + if (!is_null($typ)) + { + $query .= " AND sgt.typ IN ?"; + $params[] = $typ; + } + + 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 bb9b94c92..291a010f9 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,8 +200,91 @@ 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)); } + + /** + * @param string $student_uid + * + * @return StdClass + */ + public function getWhereStudentHasLvs($student_uid) + { + $this->addDistinct(); + $this->addSelect($this->dbTable . '.*'); + + // TODO(chris): Potentielle Anpassung "Eine UID" + $this->addJoin('campus.vw_student_lehrveranstaltung v', 'studiensemester_kurzbz'); + $this->db->where("v.lehreverzeichnis<>''"); + + $this->addOrder($this->dbTable . '.start'); + + return $this->loadWhere(['uid' => $student_uid, 'v.lehre' => true]); + } + + public function getAktAndFutureSemester() + { + $query = 'SELECT studiensemester_kurzbz + 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; + } + + /** + * Holt Start und Ende des Studiensemester_kurzbz + * @param studiensemester_kurzbz + * @return stdClass + */ + public function getStartEndeFromStudiensemester($studiensemester_kurzbz) + { + return $this->execReadOnlyQuery(" + SELECT + start, ende + FROM public.tbl_studiensemester + WHERE studiensemester_kurzbz = ?",[$studiensemester_kurzbz]); + + } } 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..398ca765e 100644 --- a/application/models/person/Benutzerfunktion_model.php +++ b/application/models/person/Benutzerfunktion_model.php @@ -147,6 +147,38 @@ class Benutzerfunktion_model extends DB_Model return $this->execQuery($query, $parametersArray); } + /** + * Gets all Benutzer with details for a given Benutzerfunktion and optionally specified Oe and semester + * + * @param string $funktion_kurzbz + * @param string $oe_kurzbz + * @param integer | null $semester + * @return array|null + */ + public function getBenutzerFunktionenDetailed($funktion_kurzbz, $oe_kurzbz = null, $semester = null) + { + $this->addSelect($this->dbTable . '.funktion_kurzbz, ' . $this->dbTable . '.oe_kurzbz, ' . $this->dbTable . '.semester, ' . $this->dbTable . '.bezeichnung, f.beschreibung, b.uid, b.alias, b.aktiv, p.vorname, p.nachname, p.titelpre, p.titelpost, m.telefonklappe, k.kontakt, o.planbezeichnung'); + $this->addJoin('public.tbl_funktion f', 'funktion_kurzbz'); + $this->addJoin('public.tbl_benutzer b', 'uid'); + $this->addJoin('public.tbl_person p', 'person_id'); + $this->addJoin('public.tbl_mitarbeiter m', 'mitarbeiter_uid=uid', 'LEFT'); + $this->addJoin('public.tbl_kontakt k', 'k.standort_id=m.standort_id AND kontakttyp=\'telefon\'', 'LEFT'); + $this->addJoin('public.tbl_ort o', 'ort_kurzbz', 'LEFT'); + + $this->addOrder('LOWER(uid)'); + + $where = [$this->dbTable . '.funktion_kurzbz' => $funktion_kurzbz]; + if ($oe_kurzbz !== null) + $where[$this->dbTable . '.oe_kurzbz'] = $oe_kurzbz; + if ($semester !== null) + $where[$this->dbTable . '.semester'] = $semester; + + $this->db->where('(' . $this->dbTable . '.datum_bis >= NOW() OR ' . $this->dbTable . '.datum_bis IS NULL)', NULL, FALSE); + $this->db->where('(' . $this->dbTable . '.datum_von <= NOW() OR ' . $this->dbTable . '.datum_von IS NULL)', NULL, FALSE); + + return $this->loadWhere($where); + } + /** * Get active Studiengangsleitung(en) of the user by UID. * @param $uid @@ -180,4 +212,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/Benutzergruppe_model.php b/application/models/person/Benutzergruppe_model.php index e569094c4..fba797641 100644 --- a/application/models/person/Benutzergruppe_model.php +++ b/application/models/person/Benutzergruppe_model.php @@ -12,4 +12,25 @@ class Benutzergruppe_model extends DB_Model $this->pk = array('gruppe_kurzbz', 'uid'); $this->hasSequence = false; } + + /** + * Laedt die User in einer Benutzergruppe + * @param gruppe_kurzbz, stsem + * @return array + */ + public function getUids($gruppe_kurzbz, $stsem) + { + $query = " + SELECT + uid + FROM + public.tbl_benutzergruppe + WHERE + gruppe_kurzbz = " . $this->escape($gruppe_kurzbz) . " + AND studiensemester_kurzbz = " . $this->escape($stsem); + + $res = $this->execReadOnlyQuery($query); + $uids = (hasData($res)) ? getData($res) : array(); + return $uids; + } } diff --git a/application/models/person/Geschlecht_model.php b/application/models/person/Geschlecht_model.php new file mode 100644 index 000000000..60ac3ba15 --- /dev/null +++ b/application/models/person/Geschlecht_model.php @@ -0,0 +1,14 @@ +dbTable = 'public.tbl_geschlecht'; + $this->pk = 'geschlecht'; + } +} diff --git a/application/models/person/Gruppe_manager_model.php b/application/models/person/Gruppe_manager_model.php new file mode 100644 index 000000000..93d45bd1f --- /dev/null +++ b/application/models/person/Gruppe_manager_model.php @@ -0,0 +1,14 @@ +dbTable = 'public.tbl_gruppe_manager'; + $this->pk = 'gruppe_manager_id'; + } +} 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..2d1e054c3 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)); + return $this->loadWhere(array('person_id' => $person_id, 'tbl_notiz.typ' => NULL)); } + /** + * 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 8875fd4c5..997048972 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'); } @@ -266,19 +290,34 @@ class Person_model extends DB_Model return success($result->vorname. ' '. $result->nachname); } + /** + * Get first name of given uid. (Vorname Nachname) + * @param $uid + * @return array + */ + public function getFirstName($uid) + { + $result = getData($this->getByUid($uid))[0]; + if (!$result) { + show_error('Failed loading person'); + } + + return success($result->vorname); + } + public function checkDuplicate($person_id) { $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 +331,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 @@ -326,13 +365,62 @@ class Person_model extends DB_Model SELECT p2.person_id FROM tbl_person p1 + JOIN tbl_prestudent ps ON p1.person_id = ps.person_id INNER JOIN ( - SELECT vorname, nachname, gebdatum, person_id - FROM tbl_person - ) p2 + SELECT vorname, nachname, gebdatum, person.person_id + FROM tbl_person person + JOIN tbl_prestudent sps ON person.person_id = sps.person_id + ) p2 ON (lower(p1.vorname) = lower(p2.vorname) AND lower(p1.nachname) = lower(p2.nachname) AND p1.gebdatum = p2.gebdatum) WHERE p1.person_id != p2.person_id AND (p1.person_id = ?)"; 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/person/Profil_update_model.php b/application/models/person/Profil_update_model.php new file mode 100644 index 000000000..ffb04b7e7 --- /dev/null +++ b/application/models/person/Profil_update_model.php @@ -0,0 +1,187 @@ +dbTable = 'public.tbl_profil_update'; + $this->pk = ['profil_update_id']; + $this->hasSequence = true; + + + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $this->load->library('PermissionLib'); + } + + /** + * getTimestamp + * returns insert or update timestamp of a certain profil update + * + * @param boolean $update: conditional whether to return insertamum or updateamum + */ + //TODO: function wird nicht verwendet + public function getTimestamp($id, $update = false) + { + $selectStatement = $update ? 'updateamum' : 'insertamum'; + $this->addSelect([$selectStatement]); + $res = $this->load([$id]); + return hasData($res) ? getData($res)[0]->$selectStatement : null; + } + + /** + * getFilesFromChangeRequest + * + * returns all files associated to a profil update request in the following format: + * {dms_id:123 , name:"test"} + * + * @param boolean $profil_update_id primary key of the profil update request + * @return array + */ + //TODO: function wird nicht verwendet + public function getFilesFromChangeRequest($profil_update_id) + { + $this->addSelect(["requested_change"]); + $res = $this->load([$profil_update_id]); + $res = hasData($res) ? getData($res)[0] : null; + return json_decode($res->requested_change)->files ?: []; + } + + + //? queries the tbl_profil_updates without permissions of the user + public function getProfilUpdatesWhere($whereClause) + { + if (array_key_exists("uid", $whereClause)) { + $whereClause["public.tbl_profil_update.uid"] = $whereClause["uid"]; + unset($whereClause["uid"]); + } + $this->addSelect(["public.tbl_profil_update.*", "public.tbl_person.vorname"]); + $this->addJoin("public.tbl_benutzer", "public.tbl_benutzer.uid = public.tbl_profil_update.uid"); + $this->addJoin("public.tbl_person", "public.tbl_person.person_id = public.tbl_benutzer.person_id"); + $res = $this->loadWhere($whereClause); + if (isError($res)) { + return $res; + } + if (hasData($res)) { + foreach (getData($res) as $request) { + $this->formatProfilRequest($request); + } + } + + return $res; + + } + + //? remove File from the Profil Update + public function removeFileFromProfilUpdate($dms_id) + { + + if(!is_int($dms_id) || $dms_id < 0){ + return error("not valid dms_id"); + } + + return $this->execReadOnlyQuery(" + UPDATE public.tbl_profil_update + SET attachment_id = NULL + WHERE attachment_id = ?", [$dms_id]); + + } + + + /** + * getProfilUpdateWithPermission + * + * queries the profil updates and checks if the user trying to query the data has permissions to get the profil updates + * + * @param string $whereClause additional where clause that will be appended to the db query + * @return array array with all the profil updates that the user is eligible to see + */ + public function getProfilUpdateWithPermission($whereClause = null) + { + + $studentBerechtigung = $this->permissionlib->isBerechtigt('student/stammdaten', 's'); + $mitarbeiterBerechtigung = $this->permissionlib->isBerechtigt('mitarbeiter/stammdaten', 's'); + $oe_berechtigung = $this->permissionlib->getOE_isEntitledFor('student/stammdaten'); + + $lang = "select index from public.tbl_sprache where sprache =" . $this->escape(getUserLanguage()); + $res = []; + + if ($studentBerechtigung) { + + + //? Nur wenn der/die AssistentIn auch die Berechtigung in der gleichen Organisationseinheit des Studenten hat + $parameters = []; + $query = " + SELECT + profil_update_id, tbl_profil_update.uid, (tbl_person.vorname || ' ' || tbl_person.nachname) AS name , topic, requested_change, tbl_profil_update.updateamum, tbl_profil_update.updatevon, tbl_profil_update.insertamum, tbl_profil_update.insertvon, status, public.tbl_profil_update_status.bezeichnung_mehrsprachig[(" . $lang . ")] as status_translated, status_timestamp, status_message, attachment_id + FROM public.tbl_profil_update + JOIN public.tbl_profil_update_status ON public.tbl_profil_update_status.status_kurzbz = public.tbl_profil_update.status + JOIN public.tbl_student ON public.tbl_student.student_uid=public.tbl_profil_update.uid + JOIN public.tbl_benutzer ON public.tbl_benutzer.uid = public.tbl_student.student_uid + JOIN public.tbl_person ON public.tbl_benutzer.person_id=public.tbl_person.person_id + JOIN public.tbl_studiengang ON public.tbl_studiengang.studiengang_kz=public.tbl_student.studiengang_kz + Where public.tbl_studiengang.oe_kurzbz IN ? "; + $parameters[] = $oe_berechtigung; + if ($whereClause) { + foreach ($whereClause as $key => $value) { + $parameters[] = $value; + $query .= " AND " . $key . " = ?"; + } + } + + $studentRequests = $this->execReadOnlyQuery($query, $parameters); + + if (isError($studentRequests)) + return error("db error: " . getData($studentRequests)); + $studentRequests = getData($studentRequests) ?: []; + foreach ($studentRequests as $request) { + array_push($res, $request); + } + } + if ($mitarbeiterBerechtigung) { + $this->addSelect(["profil_update_id", "tbl_profil_update.uid", "(tbl_person.vorname || ' ' || tbl_person.nachname) AS name", "topic", "requested_change", "tbl_profil_update.updateamum", "tbl_profil_update.updatevon", "tbl_profil_update.insertamum", "tbl_profil_update.insertvon", "status", "public.tbl_profil_update_status.bezeichnung_mehrsprachig[(" . $lang . ")] AS status_translated", "status_timestamp", "status_message", "attachment_id"]); + $this->addJoin('tbl_profil_update_status', 'tbl_profil_update_status.status_kurzbz=tbl_profil_update.status'); + $this->addJoin('tbl_mitarbeiter', 'tbl_mitarbeiter.mitarbeiter_uid=tbl_profil_update.uid'); + $this->addJoin('tbl_benutzer', 'tbl_benutzer.uid=tbl_profil_update.uid'); + $this->addJoin('tbl_person', 'tbl_benutzer.person_id=tbl_person.person_id'); + $mitarbeiterRequests = $this->loadWhere($whereClause); + if (isError($mitarbeiterRequests)) + return error("db error: " . getData($mitarbeiterRequests)); + $mitarbeiterRequests = getData($mitarbeiterRequests) ?: []; + foreach ($mitarbeiterRequests as $request) { + array_push($res, $request); + } + } + if ($res) { + + foreach ($res as $request) { + $this->formatProfilRequest($request); + } + } + + return $res; + + } + + /** + * formatProfilRequest + * + * formats the the properties of a profilUpdate request row result + * + * @param stdClass $request unflitered profilUpdate row result from the database + * @return void + */ + private function formatProfilRequest($request) + { + $request->requested_change = json_decode($request->requested_change); + $request->insertamum = !is_null($request->insertamum) ? date_create($request->insertamum)->format('d.m.Y') : null; + $request->updateamum = !is_null($request->updateamum) ? date_create($request->updateamum)->format('d.m.Y') : null; + $request->status_timestamp = !is_null($request->status_timestamp) ? date_create($request->status_timestamp)->format('d.m.Y') : null; + } + +} diff --git a/application/models/person/Profil_update_status_model.php b/application/models/person/Profil_update_status_model.php new file mode 100644 index 000000000..e69f9a047 --- /dev/null +++ b/application/models/person/Profil_update_status_model.php @@ -0,0 +1,18 @@ +dbTable = 'public.tbl_profil_update_status'; + $this->pk = ['status_kurzbz']; + $this->hasSequence = false; + + + + } +} \ No newline at end of file diff --git a/application/models/person/Profil_update_topic_model.php b/application/models/person/Profil_update_topic_model.php new file mode 100644 index 000000000..0b7ad61e3 --- /dev/null +++ b/application/models/person/Profil_update_topic_model.php @@ -0,0 +1,16 @@ +dbTable = 'public.tbl_profil_update_topic'; + $this->pk = ['topic_kurzbz']; + $this->hasSequence = false; + + } +} \ No newline at end of file diff --git a/application/models/project/Projects_employees_model.php b/application/models/project/Projects_employees_model.php new file mode 100644 index 000000000..a12e3961c --- /dev/null +++ b/application/models/project/Projects_employees_model.php @@ -0,0 +1,22 @@ +dbTable = 'sync.tbl_projects_employees'; + $this->pk = 'projects_employees_id'; + } + + public function deleteByProjectTaskId($ids) + { + $qry = "DELETE FROM " . $this->dbTable . " + WHERE project_task_id IN ?"; + + return $this->execQuery($qry, array($ids)); + } +} 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/Lehretools_model.php b/application/models/ressource/Lehretools_model.php new file mode 100644 index 000000000..69d9f6555 --- /dev/null +++ b/application/models/ressource/Lehretools_model.php @@ -0,0 +1,62 @@ +dbTable = 'campus.tbl_lehre_tools'; + $this->pk = 'lehre_tools_id'; + } + + /** + * + * Laedt die Tools zu einer Lehrveranstaltung + * @param $lehrveranstaltung_id + * @param $studiensemester_kurzbz + */ + public function getTools($lehrveranstaltung_id, $studiensemester_kurzbz, $sprache) + { + $query = "SELECT + lehre_tools_id, + bezeichnung[(SELECT index FROM public.tbl_sprache WHERE sprache = " . $this->escape($sprache) . ")] AS bezeichnung, + kurzbz, + basis_url, + logo_dms_id + FROM + campus.tbl_lehre_tools + JOIN campus.tbl_lehre_tools_organisationseinheit USING(lehre_tools_id) + WHERE + campus.tbl_lehre_tools_organisationseinheit.aktiv AND + ( + oe_kurzbz IN( + SELECT + tbl_studiengang.oe_kurzbz + FROM + lehre.tbl_lehrveranstaltung + JOIN public.tbl_studiengang USING(studiengang_kz) + WHERE + tbl_lehrveranstaltung.lehrveranstaltung_id = " . $this->escape(intval($lehrveranstaltung_id)) . " + ) + OR + oe_kurzbz IN( + SELECT + lehrfach.oe_kurzbz + FROM + lehre.tbl_lehreinheit + JOIN lehre.tbl_lehrveranstaltung as lehrfach ON(lehrfach_id=lehrfach.lehrveranstaltung_id) + WHERE + tbl_lehreinheit.studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + AND tbl_lehreinheit.lehrveranstaltung_id = " . $this->escape(intval($lehrveranstaltung_id)) . " + ) + ) + ORDER BY lehre_tools_id"; + + $toolsres = $this->execReadOnlyQuery($query); + $tools = (hasData($toolsres)) ? getData($toolsres) : array(); + + return $tools; + } +} \ No newline at end of file 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/Ort_model.php b/application/models/ressource/Ort_model.php index 59b213a54..de0c8e331 100644 --- a/application/models/ressource/Ort_model.php +++ b/application/models/ressource/Ort_model.php @@ -20,4 +20,16 @@ class Ort_model extends DB_Model return $this->OrtModel->loadWhere(array("raumtyp_kurzbz" => $raumtyp_kurzbz)); } + + public function getContentID($ort_kurzbz) + { + + return $this->execReadOnlyQuery(" + SELECT content_id + FROM public.tbl_ort + WHERE ort_kurzbz = ?; + ",[$ort_kurzbz]); + + } + } \ No newline at end of file diff --git a/application/models/ressource/Reservierung_model.php b/application/models/ressource/Reservierung_model.php index 37d0cb376..fdfc9926b 100644 --- a/application/models/ressource/Reservierung_model.php +++ b/application/models/ressource/Reservierung_model.php @@ -11,4 +11,84 @@ class Reservierung_model extends DB_Model $this->dbTable = 'campus.tbl_reservierung'; $this->pk = 'reservierung_id'; } + + + /** + * @param $uid + * + * @return stdClass + */ + public function getReservierungen($start_date, $end_date, $ort_kurzbz = null) + { + + $stundenplan_reservierungen_query="SELECT r.* , stund.beginn, stund.ende, + CASE + WHEN r.gruppe_kurzbz IS NOT NULL THEN r.gruppe_kurzbz + ELSE CONCAT(UPPER(studg.typ),UPPER(studg.kurzbz),'-',COALESCE(CAST(r.semester AS varchar),'/'),COALESCE(CAST(r.verband AS varchar),'/')) + END as gruppen_kuerzel + FROM campus.vw_reservierung r + JOIN public.tbl_studiengang studg ON studg.studiengang_kz=r.studiengang_kz + JOIN lehre.tbl_stunde stund ON stund.stunde = r.stunde + LEFT JOIN public.tbl_benutzergruppe bg ON r.gruppe_kurzbz=bg.gruppe_kurzbz AND bg.uid=? + LEFT JOIN public.tbl_studiensemester ss1 ON bg.studiensemester_kurzbz=ss1.studiensemester_kurzbz AND ss1.start <= r.datum AND ss1.ende >= r.datum + LEFT JOIN public.tbl_studentlehrverband slv ON r.studiengang_kz=slv.studiengang_kz AND slv.student_uid=? AND (slv.semester=r.semester OR r.semester IS NULL) AND (slv.verband=r.verband OR r.verband IS NULL OR r.verband='' OR r.verband='0') AND (slv.gruppe=r.gruppe OR r.gruppe IS NULL OR r.gruppe ='' OR r.gruppe ='0') AND r.gruppe_kurzbz IS NULL + LEFT JOIN public.tbl_studiensemester ss2 ON slv.studiensemester_kurzbz = ss2.studiensemester_kurzbz AND ss2.start <=r.datum AND ss2.ende >= r.datum + WHERE datum >= ? AND datum <= ? AND (ss1.studiensemester_kurzbz IS NOT NULL + OR ss2.studiensemester_kurzbz IS NOT NULL)"; + + $raum_reservierungen_query = "SELECT res.*, beginn, ende, + CASE + WHEN res.gruppe_kurzbz IS NOT NULL THEN res.gruppe_kurzbz + ELSE CONCAT(UPPER(studg.typ),UPPER(studg.kurzbz),'-',COALESCE(CAST(res.semester AS varchar),'/'),COALESCE(CAST(res.verband AS varchar),'/')) + END as gruppen_kuerzel + FROM campus.vw_reservierung res + JOIN public.tbl_studiengang studg ON studg.studiengang_kz=res.studiengang_kz + JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = res.stunde + WHERE res.ort_kurzbz = ? AND datum >= ? AND datum <= ?"; + + $subquery = is_null($ort_kurzbz)? $stundenplan_reservierungen_query:$raum_reservierungen_query; + + $query_result= $this->execReadOnlyQuery(" + SELECT + 'reservierung' as type, beginn, ende, datum, + COALESCE(titel, beschreibung) as topic, + array_agg(DISTINCT mitarbeiter_kurzbz) as lektor, + array_agg(DISTINCT (gruppe,verband,semester,studiengang_kz,gruppen_kuerzel)) as gruppe, + + ort_kurzbz, 'FFFFFF' as farbe + + FROM + ( + ". $subquery ." + ) AS subquery + + GROUP BY datum, beginn, ende, ort_kurzbz, titel, beschreibung + + ORDER BY datum, beginn + ", is_null($ort_kurzbz) ?[getAuthUID(), getAuthUID(),$start_date,$end_date]: [$ort_kurzbz, $start_date, $end_date]); + + + return $query_result; + } + + /** + * @param $uid + * + * @return stdClass + */ + public function loadForUid($uid) + { + $this->addSelect('r.*'); + $this->db->join('public.tbl_benutzergruppe bg', 'r.gruppe_kurzbz=bg.gruppe_kurzbz AND bg.uid=?', 'LEFT', false); + $this->addJoin('public.tbl_studiensemester ss1', 'bg.studiensemester_kurzbz=ss1.studiensemester_kurzbz AND ss1.start<=r.datum AND ss1.ende>=r.datum', 'LEFT'); + $this->db->join('public.tbl_studentlehrverband slv', "r.studiengang_kz=slv.studiengang_kz AND slv.student_uid=? AND (slv.semester=r.semester OR r.semester IS NULL) AND (slv.verband=r.verband OR r.verband IS NULL OR r.verband='' OR r.verband='0') AND (slv.gruppe=r.gruppe OR r.gruppe IS NULL OR r.gruppe='' OR r.gruppe='0') AND r.gruppe_kurzbz IS NULL", 'LEFT', false); + $this->addJoin('public.tbl_studiensemester ss2', 'slv.studiensemester_kurzbz=ss2.studiensemester_kurzbz AND ss2.start<=r.datum AND ss2.ende>=r.datum', 'LEFT'); + $this->db->or_where('ss1.studiensemester_kurzbz IS NOT NULL', null, false); + $this->db->or_where('ss2.studiensemester_kurzbz IS NOT NULL', null, false); + + $query = $this->db->get_compiled_select('campus.vw_reservierung r'); + + return $this->execQuery($query, [$uid, $uid]); + } + } diff --git a/application/models/ressource/Stundenplan_model.php b/application/models/ressource/Stundenplan_model.php index be3d520b5..8cb07a3bb 100644 --- a/application/models/ressource/Stundenplan_model.php +++ b/application/models/ressource/Stundenplan_model.php @@ -11,4 +11,318 @@ class Stundenplan_model extends DB_Model $this->dbTable = 'lehre.tbl_stundenplan'; $this->pk = 'stundenplan_id'; } + + /** + * @param string $ort_kurzbz + * @param string $date + * + * @return stdClass + */ + public function getRoomDataOnInterval($ort_kurzbz,$start_date,$end_date){ + + + + /*$raum_stundenplan= $this->execReadOnlyQuery(" + -- merging all reservierungs information with the stundenplan information but with different types + SELECT 'stundenplan_eintrag' as eintrags_type, CONCAT(UPPER(sp.stg_typ),UPPER(sp.stg_kurzbz),'-',COALESCE(CAST(sp.semester AS varchar),'/'),COALESCE(CAST(sp.verband AS varchar),'/')) AS stg, CONCAT(lehrfach,'-',lehrform) AS lv_info, ort_kurzbz, studiengang_kz, uid, stunde, datum, titel, semester, verband, gruppe, gruppe_kurzbz, stg_kurzbz, * FROM lehre.vw_stundenplan sp + WHERE ort_kurzbz = ? AND datum >= ? AND datum <= ? + UNION ALL + SELECT 'reservierungs_eintrag' as eintrags_type, NULL, NULL, ort_kurzbz, studiengang_kz, uid, stunde, datum, titel, semester, verband, gruppe, gruppe_kurzbz, stg_kurzbz, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL FROM lehre.vw_reservierung res + WHERE ort_kurzbz = ? AND datum >= ? AND datum <= ? + ", [$ort_kurzbz, $start_date, $end_date,$ort_kurzbz, $start_date, $end_date]); + */ + + + $raum_stundenplan= $this->execReadOnlyQuery(" + SELECT CONCAT(UPPER(sp.stg_typ),UPPER(sp.stg_kurzbz),'-',COALESCE(CAST(sp.semester AS varchar),'/'),COALESCE(CAST(sp.verband AS varchar),'/')) AS stg, CONCAT(lehrfach,'-',lehrform) AS lv_info, * FROM lehre.vw_stundenplan sp + WHERE ort_kurzbz = ? AND datum >= ? AND datum <= ? + ", [$ort_kurzbz, $start_date, $end_date]); + + return $raum_stundenplan; + } + + /** + * @param string $ort_kurzbz The room to query the planning for + * @param string $start_date The start date of the query interval + * @param string $end_date The end date of the query interval + * + * @return stdClass + */ + public function groupedCalendarEvents($ort_kurzbz,$start_date,$end_date){ + + + $gruppierteEvents= $this->execReadOnlyQuery(" + SELECT + + 'reservierung' as type, + NULL as unr,datum, stunde, + titel AS topic, + beschreibung as beschreibung, + string_agg(DISTINCT gruppe, '/') as gruppe, + string_agg(DISTINCT lektor, '/') as lektor, + res.ort_kurzbz,res.studiengang_kz, res.titel, res.beschreibung,NULL as lehreinheit_id,NULL as lehrfach_id,NULL as anmerkung, NULL as fix,NULL as lehrveranstaltung_id,NULL as stg_kurzbzlang,NULL as stg_bezeichnung,NULL as stg_typ, NULL as fachbereich_kurzbz,NULL as lehrfach,NULL as lehrfach_bez,NULL as farbe,NULL as lehrform, NULL as anmerkung_lehreinheit + + FROM + + ( + SELECT + NULL as unr,datum, stunde, + CASE + WHEN gruppe_kurzbz IS NOT NULL THEN gruppe_kurzbz + ELSE CONCAT(UPPER(studg.typ),UPPER(res.stg_kurzbz),'-',COALESCE(CAST(res.semester AS varchar),'/'),COALESCE(CAST(res.verband AS varchar),'/')) + END as gruppe, + CASE + WHEN mit.kurzbz IS NOT NULL THEN mit.kurzbz + ELSE uid + END as lektor, + res.ort_kurzbz,res.studiengang_kz, res.titel, res.beschreibung,NULL as lehreinheit_id,NULL as lehrfach_id,NULL as anmerkung, NULL as fix,NULL as lehrveranstaltung_id,NULL as stg_kurzbzlang,NULL as stg_bezeichnung,NULL as stg_typ, NULL as fachbereich_kurzbz,NULL as lehrfach,NULL as lehrfach_bez,NULL as farbe,NULL as lehrform, NULL as anmerkung_lehreinheit + FROM lehre.vw_reservierung res + + LEFT JOIN public.tbl_mitarbeiter mit ON mit.mitarbeiter_uid=uid + JOIN public.tbl_studiengang studg ON studg.studiengang_kz=res.studiengang_kz + + WHERE + res.ort_kurzbz = ? + AND res.datum >= ? + AND res.datum <= ? + ) as res + + GROUP BY res.ort_kurzbz,res.studiengang_kz, res.datum, res.stunde, res.titel, res.beschreibung + + UNION ALL + + SELECT + + 'stundenplan' as type, + unr,datum, stunde, + CONCAT(lehrfach,'-',lehrform) as topic, + '' as beschreibung, + string_agg(DISTINCT gruppe, '/') as gruppe, + string_agg(DISTINCT lektor, '/') as lektor, + ort_kurzbz, studiengang_kz, titel,'' as beschreibung,lehreinheit_id,lehrfach_id,anmerkung,fix,lehrveranstaltung_id,stg_kurzbzlang,stg_bezeichnung,stg_typ,fachbereich_kurzbz,lehrfach,lehrfach_bez,farbe,lehrform,anmerkung_lehreinheit + + FROM + ( + SELECT + unr,datum, stunde, + CASE + WHEN gruppe_kurzbz IS NOT NULL THEN gruppe_kurzbz + ELSE CONCAT(UPPER(sp.stg_typ),UPPER(sp.stg_kurzbz),'-',COALESCE(CAST(sp.semester AS varchar),'/'),COALESCE(CAST(sp.verband AS varchar),'/')) + END as gruppe, + CASE + WHEN sp.mitarbeiter_kurzbz IS NOT NULL THEN sp.mitarbeiter_kurzbz + ELSE lektor + END as lektor, + ort_kurzbz, studiengang_kz, titel,'' as beschreibung,lehreinheit_id,lehrfach_id,anmerkung,fix,lehrveranstaltung_id,stg_kurzbzlang,stg_bezeichnung,stg_typ,fachbereich_kurzbz,lehrfach,lehrfach_bez,farbe,lehrform,anmerkung_lehreinheit + + FROM lehre.vw_stundenplan sp + + WHERE ort_kurzbz = ? + AND datum >= ? + AND datum <= ? + + ) as sp + + GROUP BY + + ort_kurzbz,unr, datum, stunde, lehreinheit_id, lehrfach_id,studiengang_kz,titel,anmerkung,fix,lehrveranstaltung_id,stg_kurzbzlang,stg_bezeichnung,stg_typ,fachbereich_kurzbz,lehrfach,lehrfach_bez,farbe,lehrform,anmerkung_lehreinheit + + ORDER BY datum, stunde + ", [$ort_kurzbz, $start_date, $end_date, $ort_kurzbz, $start_date, $end_date]); + + return $gruppierteEvents; + } + + + /** + * groups rows of a subquery that fetches data from the lehre.vw_stundenplan table + * @param string $stundenplanViewQuery the subquery used to group the result + * + * @return stdClass + */ + public function stundenplanGruppierung($stundenplanViewQuery) + { + $query_result = $this->execReadOnlyQuery(" + SELECT + 'lehreinheit' as type, beginn, ende, datum, + CONCAT(lehrfach,'-',lehrform) as topic, + array_agg(DISTINCT lektor) as lektor, + array_agg(DISTINCT (gruppe,verband,semester,studiengang_kz,gruppen_kuerzel)) as gruppe, + string_agg(DISTINCT ort_kurzbz, '/') as ort_kurzbz, + array_agg(DISTINCT lehreinheit_id) as lehreinheit_id, + + titel, lehrfach, lehrform, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id + + FROM + ( + SELECT unr,datum,beginn, ende, + CASE + WHEN sp.mitarbeiter_kurzbz IS NOT NULL THEN sp.mitarbeiter_kurzbz + ELSE lektor + END as lektor, + CASE + WHEN gruppe_kurzbz IS NOT NULL THEN gruppe_kurzbz + ELSE CONCAT(UPPER(sp.stg_typ),UPPER(sp.stg_kurzbz),'-',COALESCE(CAST(sp.semester AS varchar),'/'),COALESCE(CAST(sp.verband AS varchar),'/')) + END as gruppen_kuerzel, + (SELECT bezeichnung + FROM public.tbl_organisationseinheit + WHERE oe_kurzbz IN( + SELECT oe_kurzbz + FROM lehre.tbl_lehrveranstaltung + WHERE lehrveranstaltung_id = sp.lehrveranstaltung_id + )) as organisationseinheit, + ort_kurzbz, studiengang_kz, titel,lehreinheit_id,lehrfach_id,anmerkung,fix,lehrveranstaltung_id,stg_kurzbzlang,stg_bezeichnung,stg_typ,fachbereich_kurzbz,lehrfach,lehrfach_bez,farbe,lehrform,anmerkung_lehreinheit,gruppe, verband, semester,stg_kurzbz + + FROM (".$stundenplanViewQuery.") sp + JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = sp.stunde + + ) as subquery + + GROUP BY unr, datum, beginn, ende, ort_kurzbz, titel, lehrform, lehrfach, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id + + ORDER BY datum, beginn + "); + + return $query_result; + } + + /** + * NO STANDALONE FUNCTION - Generates a SQL query string to fetch 'stundenplan' events for a specific student within the current semester. + * @param string $uid the user id that is used to fetch the stundenplan rows from the lehre.vw_stundenplan table + * + * @return mixed + */ + public function getStundenplanQuery($start_date, $end_date,$semester,$gruppen,$studentlehrverbaende){ + + // helper function to check if either $gruppen or $studentlehrverbaende are empty for each semester + $emptyCheck = function($toBeCheckedArray) use ($semester){ + $result = true; + $sem = array_keys($semester); + foreach($sem as $s){ + if(count($toBeCheckedArray[$s]) > 0){ + $result = false; + break; + } + } + return $result; + }; + + // if both the gruppen and the studentlehrverbaende are empty we early return + if($emptyCheck($gruppen) && $emptyCheck($studentlehrverbaende)) + { + return false; + } + + $query = + "select sp.* + from lehre.vw_stundenplan sp + WHERE + sp.datum >= ".$this->escape($start_date)." + AND sp.datum <= ".$this->escape($end_date); + + // adds the AND sql chain only if both $gruppen and $studentlehrverbaende are not empty + if(!$emptyCheck($gruppen) || !$emptyCheck($studentlehrverbaende)) + { + $query .= " AND ( "; + } + + foreach($semester as $sem => $semester_date_range) + { + + foreach($semester_date_range as $sem_date => $sem_date_range) + { + // if there are not groups for the semester skip the iteration step + if(!array_key_exists($sem_date,$gruppen) || count($gruppen[$sem_date]) == 0) + { + continue; + } + // converts the array of gruppen strings into a sql IN (_,_,_) chain + $query .="(sp.gruppe_kurzbz IN (" .implode(',',$gruppen[$sem_date]).") AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende)." )"; + + $query .="OR"; + } + } + + // if there are no studentlehrverbaende and the gruppen are not empty, we can remove the last OR added after the groups + if($emptyCheck($studentlehrverbaende) && !$emptyCheck($gruppen)) + { + $query = substr($query, 0, -2); + } + + foreach($semester as $sem=>$semester_date_range) + { + foreach($semester_date_range as $sem_date => $sem_date_range) + { + if(!array_key_exists($sem_date,$studentlehrverbaende) || count($studentlehrverbaende[$sem_date]) == 0) + { + continue; + } + foreach($studentlehrverbaende[$sem_date] as $key=>$lehrverband) + { + $query .= "((sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND sp.gruppe = ".$this->escape($lehrverband->gruppe)." AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")"; + // Eintraege fuer den ganzen Verband + $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND (sp.gruppe is null OR sp.gruppe='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")"; + // Eintraege fuer das ganze Semester + $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).") AND gruppe_kurzbz is null)"; + + $query .="OR"; + + } + } + } + + // if the studentlehrverbaende is not empty we can remove the last OR that was added to the query + if(!$emptyCheck($studentlehrverbaende)) + { + $query = substr($query, 0, -2); + } + + // closes the AND sql chain only if it was opened previously + if(!$emptyCheck($gruppen) || !$emptyCheck($studentlehrverbaende)) + { + $query .= ")"; + } + + return $query; + } + + /** + * NO STANDALONE FUNCTION - Generates a SQL query string to fetch 'stundenplan' events for a specific room within a date range. + * @param string $ort_kurzbz the ort from which we want to query the stundenplan events + * @param string $start_date (inclusive) the minimum date that an event should have to be fetched + * @param string $end_date (inclusive) the maximum date that an event should not extend to be fetched + * + * @return string + */ + public function getRoomQuery($ort_kurzbz, $start_date, $end_date) + { + return + "select sp.* + FROM lehre.vw_stundenplan sp + WHERE ort_kurzbz = ".$this->escape($ort_kurzbz)." + AND datum >= ".$this->escape($start_date)." + AND datum <= ".$this->escape($end_date); + } + + /** + * @param string $uid + * + * @return stdClass + */ + public function loadForUid($uid) + { + $this->addSelect(['sp.*','le.studiensemester_kurzbz']); + $this->db->join('public.tbl_benutzergruppe bg', 'sp.gruppe_kurzbz=bg.gruppe_kurzbz AND bg.uid=?', 'LEFT', false); + $this->addJoin('public.tbl_studiensemester ss1', 'bg.studiensemester_kurzbz=ss1.studiensemester_kurzbz AND ss1.start<=sp.datum AND ss1.ende>=sp.datum', 'LEFT'); + $this->db->join('public.tbl_studentlehrverband slv', "sp.studiengang_kz=slv.studiengang_kz AND slv.student_uid=? AND (slv.semester=sp.semester OR sp.semester IS NULL) AND (slv.verband=sp.verband OR sp.verband IS NULL OR sp.verband='' OR sp.verband='0') AND (slv.gruppe=sp.gruppe OR sp.gruppe IS NULL OR sp.gruppe='' OR sp.gruppe='0') AND sp.gruppe_kurzbz IS NULL", 'LEFT', false); + $this->addJoin('public.tbl_studiensemester ss2', 'slv.studiensemester_kurzbz=ss2.studiensemester_kurzbz AND ss2.start<=sp.datum AND ss2.ende>=sp.datum', 'LEFT'); + $this->db->join('lehre.tbl_lehreinheit le', 'le.lehreinheit_id=sp.lehreinheit_id', 'LEFT'); + $this->db->or_where('ss1.studiensemester_kurzbz IS NOT NULL', null, false); + $this->db->or_where('ss2.studiensemester_kurzbz IS NOT NULL', null, false); + + $query = $this->db->get_compiled_select('lehre.vw_stundenplan sp'); + + return $this->execQuery($query, [$uid, $uid]); + } + } diff --git a/application/models/ressource/Stundenplandev_model.php b/application/models/ressource/Stundenplandev_model.php index a498e209b..800540d60 100644 --- a/application/models/ressource/Stundenplandev_model.php +++ b/application/models/ressource/Stundenplandev_model.php @@ -12,6 +12,8 @@ class Stundenplandev_model extends DB_Model $this->pk = 'stundenplandev_id'; } + + public function getMissingDirectGroups($studiensemester_kurzbz = null) { $qry = " diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php new file mode 100644 index 000000000..10f5a6aa1 --- /dev/null +++ b/application/models/ressource/Stundensatz_model.php @@ -0,0 +1,45 @@ +dbTable = 'hr.tbl_stundensatz'; + $this->pk = 'stundensatz_id'; + $this->hasSequence = true; + } + + public function getStundensatzByDatum($uid, $beginn, $ende = null, $typ = null) + { + $qry = "SELECT + * + FROM + hr.tbl_stundensatz + WHERE + uid = ? + AND (gueltig_bis >= ? OR gueltig_bis is null)"; + + $params = array($uid, $beginn); + + if (!is_null($ende)) + { + $qry .= " AND (gueltig_von <= ?)"; + $params[] = $ende; + } + + if (!is_null($typ)) + { + $qry .= " AND stundensatztyp = ?"; + $params[] = $typ; + } + + $qry .= " ORDER BY gueltig_bis DESC NULLS FIRST, gueltig_von DESC NULLS LAST LIMIT 1;"; + + return $this->execQuery($qry, $params); + } +} \ 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/Fehlerkonfiguration_model.php b/application/models/system/Fehlerkonfiguration_model.php new file mode 100644 index 000000000..bf8de4cde --- /dev/null +++ b/application/models/system/Fehlerkonfiguration_model.php @@ -0,0 +1,48 @@ +dbTable = 'system.tbl_fehler_konfiguration'; + $this->pk = array('konfigurationstyp_kurzbz', 'fehlercode'); + $this->hasSequence = false; + } + + /** + * Retrieve all set configuration parameters, optionally filtered by app. + * @param string $app + * @return object success or error + */ + public function getKonfiguration($app = null) + { + $fehlerkonfiguration = array(); + + $this->addSelect('fehlercode, konfigurationstyp_kurzbz, konfiguration, fehler_kurzbz'); + $this->addJoin('system.tbl_fehler_konfigurationstyp konftyp', 'konfigurationstyp_kurzbz'); + $this->addJoin('system.tbl_fehler fehler', 'fehlercode'); + $fehlerkonfigurationRes = isset($app) ? $this->loadWhere(array('fehler.app' => $app)) : $this->load(); + + if (isError($fehlerkonfigurationRes)) return $fehlerkonfigurationRes; + + if (hasData($fehlerkonfigurationRes)) + { + $fehlerkonfigurationData = getData($fehlerkonfigurationRes); + foreach ($fehlerkonfigurationData as $fk) + { + $konf = json_decode($fk->konfiguration); + if (is_array($konf)) + { + $fk->konfiguration = $konf; + $fehlerkonfiguration[] = $fk; + } + } + } + + return success($fehlerkonfiguration); + } +} diff --git a/application/models/system/Fehlerkonfigurationstyp_model.php b/application/models/system/Fehlerkonfigurationstyp_model.php new file mode 100644 index 000000000..dc1c7957f --- /dev/null +++ b/application/models/system/Fehlerkonfigurationstyp_model.php @@ -0,0 +1,47 @@ +dbTable = 'system.tbl_fehler_konfigurationstyp'; + $this->pk = array('konfigurationstyp_kurzbz'); + } + + /** + * Retrieve all set configuration parameters, optionally filtered by app. + * @param string $app + * @return object success or error + */ + public function getKonfiguration($app = null) + { + $fehlerkonfiguration = array(); + + $this->addSelect('fehlercode, konfigurationstyp_kurzbz, konfiguration, fehler_kurzbz'); + $this->addJoin('system.tbl_fehler_konfigurationstyp konftyp', 'konfigurationstyp_kurzbz'); + $this->addJoin('system.tbl_fehler fehler', 'fehlercode'); + $fehlerkonfigurationRes = isset($app) ? $this->loadWhere(array('fehler.app' => $app)) : $this->load(); + + if (isError($fehlerkonfigurationRes)) return $fehlerkonfigurationRes; + + if (hasData($fehlerkonfigurationRes)) + { + $fehlerkonfigurationData = getData($fehlerkonfigurationRes); + foreach ($fehlerkonfigurationData as $fk) + { + $konf = json_decode($fk->konfiguration); + if (is_array($konf)) + { + $fk->konfiguration = $konf; + $fehlerkonfiguration[] = $fk; + } + } + } + + return success($fehlerkonfiguration); + } +} 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/Notiztyp_model.php b/application/models/system/Notiztyp_model.php new file mode 100644 index 000000000..b173377e6 --- /dev/null +++ b/application/models/system/Notiztyp_model.php @@ -0,0 +1,14 @@ +dbTable = 'public.tbl_notiz_typ'; + $this->pk = 'typ_kurzbz'; + } +} 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/system/Sprache_model.php b/application/models/system/Sprache_model.php index 202157a83..fb12b91e9 100644 --- a/application/models/system/Sprache_model.php +++ b/application/models/system/Sprache_model.php @@ -11,4 +11,19 @@ class Sprache_model extends DB_Model $this->dbTable = 'public.tbl_sprache'; $this->pk = 'sprache'; } + + /** + * @param array $sprachen + * + * @return stdClass + */ + public function loadMultiple($sprachen) + { + $this->db->where_in('sprache', $sprachen); + + $this->addOrder('index'); + + return $this->load(); + } + } diff --git a/application/models/system/Variable_model.php b/application/models/system/Variable_model.php index 875fc8876..bfa1dcd98 100644 --- a/application/models/system/Variable_model.php +++ b/application/models/system/Variable_model.php @@ -66,6 +66,15 @@ class Variable_model extends DB_Model } } } + + if (!isset($vardata['emailadressentrennzeichen'])) + { + $vardata['emailadressentrennzeichen'] = + (defined('DEFAULT_EMAILADRESSENTRENNZEICHEN')) + ? DEFAULT_EMAILADRESSENTRENNZEICHEN + : ','; + } + $result = success($vardata); } 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..c50627697 --- /dev/null +++ b/application/models/vertragsbestandteil/Gehaltsbestandteil_model.php @@ -0,0 +1,339 @@ +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 = " +with gbt as ( + select + gb.gehaltsbestandteil_id, + gb.von, + gb.bis, + gb.anmerkung, + gb.dienstverhaeltnis_id, + gb.gehaltstyp_kurzbz, + gb.valorisierungssperre, + gb.valorisierung, + gb.grundbetrag as grund_betrag_decrypted, + coalesce(vh.betrag_valorisiert, gb.grundbetrag) as betrag_val_decrypted, + gb.vertragsbestandteil_id + from + hr.tbl_gehaltsbestandteil gb + LEFT JOIN + hr.tbl_valorisierung_historie vh ON vh.gehaltsbestandteil_id = gb.gehaltsbestandteil_id AND vh.valorisierungsdatum = ( + SELECT + vi.valorisierungsdatum + FROM + hr.tbl_valorisierung_instanz vi + JOIN + hr.tbl_dienstverhaeltnis d ON d.dienstverhaeltnis_id = ? + AND d.oe_kurzbz = vi.oe_kurzbz + WHERE + ? >= valorisierungsdatum + ORDER BY + valorisierungsdatum DESC + LIMIT 1 + ) + where + dienstverhaeltnis_id = ? + and ( + ? BETWEEN COALESCE(von, '1970-01-01'::date) AND COALESCE(bis, '2170-01-01'::date) + ) +) +select + gbt.gehaltsbestandteil_id, + gbt.von, + gbt.bis, + gbt.anmerkung, + gbt.dienstverhaeltnis_id, + gbt.gehaltstyp_kurzbz, + gbt.valorisierungssperre, + gbt.valorisierung, + gbt.grund_betrag_decrypted, + gbt.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 + 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) + "; + + return $this->execQuery($qry, + array($dienstverhaeltnis_id, $datestring, $dienstverhaeltnis_id, $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, $withvalorisationhistory=true) + { + if( !is_null($stichtag) && (time() > strtotime($stichtag)) + && $withvalorisationhistory !== false ) + { + $query = $this->getGehaltsbestandteileMitValorisierungsHistorie( + $dienstverhaeltnis_id, $stichtag, $includefuture + ); + } + else + { + $query = $this->getGehaltsbestandteileOhneValorisierungsHistorie( + $dienstverhaeltnis_id, $stichtag, $includefuture + ); + } + + $gehaltsbestandteile = array(); + if( null !== ($rows = getData($query)) ) + { + foreach( $rows as $row ) { + $tmpgb = new Gehaltsbestandteil(); + $tmpgb->hydrateByStdClass($row, true); + $gehaltsbestandteile[] = $tmpgb; + } + } + + return $gehaltsbestandteile; + } + + protected function getGehaltsbestandteileOhneValorisierungsHistorie($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; + + $result = $this->loadWhere( + $where, + $this->getEncryptedColumns() + ); + return $result; + } + + protected function getGehaltsbestandteileMitValorisierungsHistorie($dienstverhaeltnis_id, $stichtag, $includefuture=false) + { + $date = strftime('%Y-%m-%d', strtotime($stichtag)); + $includefuture_clause = ($includefuture) + ? ' OR COALESCE(von, \'1970-01-01\'::date) > ' . $this->escape($date) + : ''; + $sql = <<escape($dienstverhaeltnis_id)} + AND d.oe_kurzbz = vi.oe_kurzbz + WHERE + {$this->escape($date)} >= valorisierungsdatum + ORDER BY + valorisierungsdatum DESC + LIMIT 1 + ) +WHERE + g.dienstverhaeltnis_id = {$this->escape($dienstverhaeltnis_id)} + AND ( + {$this->escape($date)} BETWEEN COALESCE(von, '1970-01-01'::date) AND COALESCE(bis, '2170-01-01'::date) + {$includefuture_clause} + ) +EOSQL; + + $result = $this->execReadOnlyQuery($sql, array(), $this->getEncryptedColumns()); + return $result; + } + + public function getGehaltsbestandteileValorisiertForChart($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 .= ')'; + } + + // Note: replaced gb.betrag_valorisiert with vh.betrag_valorisiert! + $qry = " + SELECT + gb.gehaltsbestandteil_id,gb.dienstverhaeltnis_id,gb.vertragsbestandteil_id,gb.gehaltstyp_kurzbz, + gb.von,gb.bis,gb.anmerkung,gb.grundbetrag as grundbetrag,gb.valorisierungssperre,gb.insertamum, + gb.insertvon,gb.updateamum,gb.updatevon,gb.valorisierung,gb.auszahlungen, + vh.valorisierungsdatum, vh.betrag_valorisiert as betrag_valorisiert + FROM hr.tbl_gehaltsbestandteil gb LEFT JOIN hr.tbl_valorisierung_historie vh using (gehaltsbestandteil_id) + WHERE dienstverhaeltnis_id=? + $stichtagclause + ORDER BY gb.von,vh.valorisierungsdatum, gb.gehaltsbestandteil_id; + "; + + $query = $this->execQuery($qry, + array($dienstverhaeltnis_id), + $this->getEncryptedColumns()); + + $gehaltsbestandteile = array(); + if( null !== ($rows = getData($query)) ) + { + // store for preserving the last records of every gehaltsbestandteil_id + $lastRecords = array(); + + foreach( $rows as $row ) { + $tmpgb = new Gehaltsbestandteil(); + $tmpgb->hydrateByStdClass($row, true); + + // prevent duplication (caused by the join with historic values) + if (!isset($lastRecords[(string)$row->gehaltsbestandteil_id])) { + $gehaltsbestandteile[] = $tmpgb; + $lastRecords[(string)$row->gehaltsbestandteil_id] = $tmpgb; + } + + if ($row->betrag_valorisiert != null && $row->valorisierungsdatum != null + && $row->valorisierungsdatum != $row->von && $row->valorisierungsdatum != $row->bis) { + + // create additional row + $tmpgbv = new Gehaltsbestandteil(); + $tmpgbv->hydrateByStdClass($row, true); + $tmpgbv->setVon($row->valorisierungsdatum); + $tmpgbv->setBis($lastRecords[(string)$row->gehaltsbestandteil_id]->getBis()); + // overwrite Grundbetrag with the current valorized loan + // (otherwise the chart would show the wrong value) + $tmpgbv->setGrundbetrag($row->betrag_valorisiert); + $gehaltsbestandteile[] = $tmpgbv; + + // finish previous + $daybefore = new DateTimeImmutable($row->valorisierungsdatum); + $daybefore = $daybefore->sub(new \DateInterval('P1D')); + $lastRecords[(string)$row->gehaltsbestandteil_id]->setBis($daybefore->format('Y-m-d')); + + // preserve as last row, because there might be another valorization + $lastRecords[(string)$row->gehaltsbestandteil_id] = $tmpgbv; + + } + + } + } + + 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..cbc529d83 --- /dev/null +++ b/application/models/vertragsbestandteil/Vertragsbestandteil_model.php @@ -0,0 +1,211 @@ +dbTable = 'hr.tbl_vertragsbestandteil'; + $this->pk = 'vertragsbestandteil_id'; + } + + protected function getVertragsbestandteilSQL() + { + $sapInstalled = $this->_checkIfSAPSyncTableExists(); + + $oe_kurzbz_sap = $sapInstalled ? 'sap.oe_kurzbz_sap' : 'NULL AS oe_kurzbz_sap'; + $sap_join = $sapInstalled ? 'LEFT JOIN sync.tbl_sap_organisationsstruktur sap USING(oe_kurzbz)' : ''; + + $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; + } + + /** + * Checks if sap sync table exists. + * @return bool + */ + private function _checkIfSAPSyncTableExists() + { + $params = array( + DB_NAME, + 'sync', + 'tbl_sap_organisationsstruktur' + ); + + $sql = "SELECT + 1 AS exists + FROM + information_schema.tables + WHERE + table_catalog = ? AND + table_schema = ? AND + table_name = ?"; + + $res = $this->execReadOnlyQuery($sql, $params); + + return hasData($res); + } +} diff --git a/application/views/Cis/Cms/News/Xml/Address/Detailed.php b/application/views/Cis/Cms/News/Xml/Address/Detailed.php new file mode 100644 index 000000000..934b5ba93 --- /dev/null +++ b/application/views/Cis/Cms/News/Xml/Address/Detailed.php @@ -0,0 +1,11 @@ +aktiv) { ?> + uid; ?>]]> + titelpre . ' ' . $obj->vorname . ' ' . $obj->nachname . ' ' . $obj->titelpost; ?>]]> + alias ?: $obj->uid; ?>@]]> + telefonklappe !== null) { ?> + kontakt ?: ''; ?> - telefonklappe; ?>]]> + + planbezeichnung) { ?> + planbezeichnung; ?>]]> + + \ No newline at end of file diff --git a/application/views/Cis/Cms/News/Xml/Address/Short.php b/application/views/Cis/Cms/News/Xml/Address/Short.php new file mode 100644 index 000000000..61888fb7e --- /dev/null +++ b/application/views/Cis/Cms/News/Xml/Address/Short.php @@ -0,0 +1,6 @@ +aktiv) { ?> + uid; ?>]]> + uid; ?>@]]> + + titelpre . ' ' . $obj->vorname . ' ' . $obj->nachname . ' ' . $obj->titelpost; ?>bezeichnung != '' && $obj->bezeichnung != $obj->beschreibung) echo ' (' . $obj->bezeichnung . ')'; ?>]]> + diff --git a/application/views/Cis/Cms/News/Xml/NewsExtras.php b/application/views/Cis/Cms/News/Xml/NewsExtras.php new file mode 100644 index 000000000..b3b86e567 --- /dev/null +++ b/application/views/Cis/Cms/News/Xml/NewsExtras.php @@ -0,0 +1,46 @@ + + studiengang_kz; ?> + p->t('global', 'studiengangsleitung'); ?>]]>'; + + view('Cis/Cms/News/Xml/Address/Detailed', ['obj' => $item]); ?> + + p->t('global', 'geschaeftsfuehrendeltg'); ?>]]>'; + + view('Cis/Cms/News/Xml/Address/Detailed', ['obj' => $item]); ?> + + p->t('global', 'stellvertreter'); ?>]]>'; + + view('Cis/Cms/News/Xml/Address/Detailed', ['obj' => $item]); ?> + + p->t('global', 'sekretariat'); ?>]]>'; + + view('Cis/Cms/News/Xml/Address/Detailed', ['obj' => $item]); ?> + + + zusatzinfo_html; ?>]]> + + p->t('global', 'hochschulvertretung'); ?>]]>'; + + view('Cis/Cms/News/Xml/Address/Short', ['obj' => $item]); ?> + + + p->t('global', 'studentenvertreter'); ?> oe_kurzbz); ?>]]>'; + + view('Cis/Cms/News/Xml/Address/Short', ['obj' => $item]); ?> + + + p->t('global', 'jahrgangsvertretung'); ?> p->t('global', 'semester'); ?>]]>'; + + view('Cis/Cms/News/Xml/Address/Short', ['obj' => $item]); ?> + + + + + p->t('global', 'allgemeinerdownload'); ?>]]> + typ . $studiengang->kurzbz); ?>]]> + kurzbzlang); ?>]]> + studiengang_kz; ?>]]> + '; + + + diff --git a/application/views/Cis/Documents.php b/application/views/Cis/Documents.php new file mode 100644 index 000000000..f34ce3fc1 --- /dev/null +++ b/application/views/Cis/Documents.php @@ -0,0 +1,212 @@ + 'Documents', + 'tabulator5' => true, + 'customJSModules' => ['public/js/apps/Cis/Documents.js'] +); + +$this->load->view('templates/CISVUE-Header', $includesArray); +?> + +
+
+

p->t('tools', 'dokumente'); ?>p->t('tools', 'bestaetigungenZeugnisse'); ?>

+
+ +
+ +
+
+
+

p->t('tools', 'inskriptionsbestaetigung'); ?>p->t('tools', 'studienbuchblatt') : ''; ?>

+ +
+ +
+ +
+ +
+
+ + + + + + + + + + + + + studiensemester as $stsem => $sem) { ?> + inskriptionsbestaetigung) { ?> + + + + + + + + + + + + + + + + + + + + +
DokumentStudiengangStudiensemester
+ + PDF p->t('tools', 'inskriptionsbestaetigung'); ?> + + bezeichnung; ?>
+ + PDF p->t('tools', 'studienbuchblatt'); ?> + + bezeichnung; ?>
+
+ +
+
+

p->t('tools', 'studienerfolgsbestaetigung'); ?>

+ +
+ +
+ +
+ +
+
+ +
+
+ + + + + + + + + + + + + + $this->p->t('global', 'deutsch'), 'StudienerfolgEng' => $this->p->t('global', 'englisch')] as $lang_xsl => $lang) { ?> + + + + + + + + + + + + studiensemester as $stsem => $sem) { ?> + + + + + + + + + + + + + + +
DokumentStudiengangStudiensemesterSprachep->t('tools', 'vorlageWohnsitzfinanzamt'); ?>
+ + PDF p->t('tools', 'studienerfolgsbestaetigung'); ?> + + bezeichnung; ?>p->t('tools', 'alleStudiensemester'); ?>
+ + PDF p->t('tools', 'studienerfolgsbestaetigung'); ?> + + bezeichnung; ?>
+
+ + +
+
+

p->t('tools', 'abschlussdokumente'); ?>

+
+ + + + + + + + + + + + + + +
DokumentDatum
+ + PDF bezeichnung; ?> + + erstelltam))->format('d.m.Y'); ?>
+
+ +
+ +
+ +
+ + +
+
+ +load->view('templates/CISVUE-Footer', $includesArray); ?> diff --git a/application/views/Cis/Login.php b/application/views/Cis/Login.php new file mode 100644 index 000000000..68490e67e --- /dev/null +++ b/application/views/Cis/Login.php @@ -0,0 +1,42 @@ + 'FH-Complete', + 'bootstrap5' => true, + 'fontawesome6' => true + ); + + $this->load->view('templates/FHC-Header', $includesArray); +?> + + + + +load->view('templates/FHC-Footer', $includesArray); ?> + diff --git a/application/views/Cis/LvInfo.php b/application/views/Cis/LvInfo.php new file mode 100644 index 000000000..49a7b7a85 --- /dev/null +++ b/application/views/Cis/LvInfo.php @@ -0,0 +1,15 @@ + 'LvInfo', + 'customJSModules' => ['public/js/apps/Cis/LvInfo.js'] +); + +$this->load->view('templates/CISVUE-Header', $includesArray); +?> + +
+ + +
+ +load->view('templates/CISVUE-Footer', $includesArray); ?> diff --git a/application/views/Cis/MyLv.php b/application/views/Cis/MyLv.php new file mode 100644 index 000000000..d8d5026a1 --- /dev/null +++ b/application/views/Cis/MyLv.php @@ -0,0 +1,15 @@ + 'MyLv', + 'customJSModules' => ['public/js/apps/Cis/MyLv/Student.js'], + 'customCSSs' => ['public/css/components/MyLv.css'] +); + +$this->load->view('templates/CISVUE-Header', $includesArray); +?> + +
+ +
+ +load->view('templates/CISVUE-Footer', $includesArray); ?> diff --git a/application/views/Cis/Profil.php b/application/views/Cis/Profil.php new file mode 100644 index 000000000..788d44360 --- /dev/null +++ b/application/views/Cis/Profil.php @@ -0,0 +1,18 @@ + 'Stundenplan', + 'customJSModules' => ['public/js/apps/Cis/Profil.js'], + 'tabulator5' => true, + 'primevue3' => true, + 'customCSSs' => ['public/css/components/calendar.css', 'public/css/components/FilterComponent.css','public/css/components/Profil.css','public/css/components/FormUnderline.css'], + +); + +$this->load->view('templates/CISVUE-Header', $includesArray); +?> + +
+ +
+ +load->view('templates/CISVUE-Footer', $includesArray); ?> diff --git a/application/views/Cis/ProfilUpdate.php b/application/views/Cis/ProfilUpdate.php new file mode 100644 index 000000000..e797d436f --- /dev/null +++ b/application/views/Cis/ProfilUpdate.php @@ -0,0 +1,49 @@ + 'Profil Änderungen', + 'vue3' => true, + 'bootstrap5' => true, + 'fontawesome6'=> true, + 'axios027' => true, + 'tabulator5' => true, + 'customJSModules' => array( + 'public/js/apps/Cis/ProfilUpdateRequests.js' + ), + 'customCSSs' => array( + 'public/css/components/FilterComponent.css','public/css/components/FormUnderline.css' + ) +); + +if(defined("CIS4")) +{ + $this->load->view( + 'templates/CISVUE-Header', + $includesArray + ); +} +else +{ + $this->load->view( + 'templates/FHC-Header', + $includesArray + ); +} +?> + +
+ +
+ +load->view( + 'templates/CISVUE-Footer', + $includesArray + ); +} else { + $this->load->view( + 'templates/FHC-Footer', + $includesArray + ); +} +?> \ No newline at end of file diff --git a/application/views/Cis/Stundenplan.php b/application/views/Cis/Stundenplan.php new file mode 100644 index 000000000..bfab73109 --- /dev/null +++ b/application/views/Cis/Stundenplan.php @@ -0,0 +1,15 @@ + 'Stundenplan', + 'customJSModules' => ['public/js/apps/Cis/Stundenplan.js'], + 'customCSSs' => ['public/css/components/calendar.css'] +); + +$this->load->view('templates/CISVUE-Header', $includesArray); +?> + +
+ +
+ +load->view('templates/CISVUE-Footer', $includesArray); ?> diff --git a/application/views/CisVue/Cms/Content.php b/application/views/CisVue/Cms/Content.php new file mode 100644 index 000000000..f957bb7f9 --- /dev/null +++ b/application/views/CisVue/Cms/Content.php @@ -0,0 +1,32 @@ + ['public/js/apps/Cis/Cms.js'], + 'primevue3'=>true, + 'customCSSs' => [ + 'public/css/Cis4/Cms.css', + #'skin/style.css.php' + ] +); + +// adds the tabulator5 dependency for all templates to replace the tablesorter +$includesArray['tabulator5'] = true; + +if(defined('CIS4')){ + $this->load->view('templates/CISVUE-Header', $includesArray); +}else{ + $this->load->view('templates/FHC-Header', $includesArray); +} +?> + +
+' : ''); ?> +
+ +load->view('templates/CISVUE-Footer', $includesArray); +} else { + $this->load->view('templates/FHC-Footer', $includesArray); +} + ?> + diff --git a/application/views/CisVue/Cms/RoomInformation.php b/application/views/CisVue/Cms/RoomInformation.php new file mode 100644 index 000000000..e7b197504 --- /dev/null +++ b/application/views/CisVue/Cms/RoomInformation.php @@ -0,0 +1,20 @@ + 'RoomInformation', + 'customJSModules' => ['public/js/apps/Cis/RoomInformation.js'], + 'customCSSs' => ['public/css/components/calendar.css'] +); + +$this->load->view('templates/CISVUE-Header', $includesArray); +?> + +
+

Room Information:

+
+
+ +
+ +
+ +load->view('templates/CISVUE-Footer', $includesArray); ?> diff --git a/application/views/CisVue/Dashboard.php b/application/views/CisVue/Dashboard.php new file mode 100644 index 000000000..2f241af87 --- /dev/null +++ b/application/views/CisVue/Dashboard.php @@ -0,0 +1,20 @@ + 'Dashboard', + 'tabulator5'=>true, + 'primevue3' => true, + 'customJSModules' => ['public/js/apps/Dashboard/Fhc.js'], + 'customCSSs' => [ + 'public/css/components/dashboard.css' + ], +); + +$this->load->view('templates/CISVUE-Header', $includesArray); +?> + +
+ +
+ +load->view('templates/CISVUE-Footer', $includesArray); ?> + 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/oehbeitrag.php b/application/views/codex/oehbeitrag.php index feebeddef..ba99bbf0c 100644 --- a/application/views/codex/oehbeitrag.php +++ b/application/views/codex/oehbeitrag.php @@ -26,7 +26,6 @@ $this->load->view( ); ?> -
widgetlib->widget('NavigationWidget'); ?> @@ -63,6 +62,5 @@ $this->load->view(
- load->view('templates/FHC-Footer'); ?> diff --git a/application/views/codex/uhstat1.php b/application/views/codex/uhstat1.php new file mode 100644 index 000000000..a255781f1 --- /dev/null +++ b/application/views/codex/uhstat1.php @@ -0,0 +1,319 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'UHSTAT1Formular', + 'jquery3' => true, + 'bootstrap3' => true, + 'fontawesome4' => true, + 'phrases' => array( + 'ui' => array('speichern') + ), + 'customCSSs' => array('public/css/codex/uhstat1.css'), + 'customJSs' => array('public/js/codex/uhstat1.js') + ) +); +?> +mutter_geburtsjahr) ? $uhstatData->mutter_geburtsjahr : set_value('mutter_geburtsjahr'); +$mutter_geburtsstaat = isset($uhstatData->mutter_geburtsstaat) ? $uhstatData->mutter_geburtsstaat : set_value('mutter_geburtsstaat'); +$mutter_bildungsstaat = isset($uhstatData->mutter_bildungsstaat) ? $uhstatData->mutter_bildungsstaat : set_value('mutter_bildungsstaat'); +$mutter_bildungmax = isset($uhstatData->mutter_bildungmax) ? $uhstatData->mutter_bildungmax : set_value('mutter_bildungmax'); +$vater_geburtsjahr = isset($uhstatData->vater_geburtsjahr) ? $uhstatData->vater_geburtsjahr : set_value('vater_geburtsjahr'); +$vater_geburtsstaat = isset($uhstatData->vater_geburtsstaat) ? $uhstatData->vater_geburtsstaat : set_value('vater_geburtsstaat'); +$vater_bildungsstaat = isset($uhstatData->vater_bildungsstaat) ? $uhstatData->vater_bildungsstaat : set_value('vater_bildungsstaat'); +$vater_bildungmax = isset($uhstatData->vater_bildungmax) ? $uhstatData->vater_bildungmax : set_value('vater_bildungmax'); +$readOnly = isset($formMetaData['readOnly']); +$disabled = $readOnly ? ' disabled' : ''; +$editPermission = isset($formMetaData['editPermission']) && $formMetaData['editPermission'] === true; +$deletePermission = isset($formMetaData['deletePermission']) && $formMetaData['deletePermission'] === true; +$saved = isset($saved) && $saved === true; +?> + +
+

+ +

+
+ +

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

+

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

+

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

+

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

+
+ + +
+ + +
+ + +
+ + +
+ ' /> +
+ p->t('uhstat', 'angabenErziehungsberechtigte') ?> +

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

+
+

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

+
+ +
+
+ + + + +
+ +
+
+
+ +
+
+ + + + +
+ +
+
+
+ +
+
+ + + + +
+ +
+
+
+ +
+ + +
+
+
+

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

+
+ +
+
+ + + + +
+ +
+
+
+ +
+
+ + + + +
+ +
+
+
+ +
+
+ + + + +
+ +
+
+
+ +
+ + +
+
+
+ +
+
+
+
+ +
+
+
+ +
+ +
+ ' /> +
+
+ +
+
+
+ +
+
+ +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/dashboard/dashboard_demo.php b/application/views/dashboard/dashboard_demo.php new file mode 100644 index 000000000..8efc230b7 --- /dev/null +++ b/application/views/dashboard/dashboard_demo.php @@ -0,0 +1,32 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'FH-Complete', + 'bootstrap5' => true, + 'fontawesome6' => true, + 'axios027' => true, + 'restclient' => true, + 'vue3' => true, + 'customJSModules' => ['public/js/apps/Dashboard.js'], + 'customCSSs' => [ + 'public/css/components/dashboard.css' + ], + 'navigationcomponent' => true + ) +); +?> + +
+ + + +
+
+

Dashboard

+
+ +
+
+ +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/dashboard/dashboard_demo_admin.php b/application/views/dashboard/dashboard_demo_admin.php new file mode 100644 index 000000000..0d92146a8 --- /dev/null +++ b/application/views/dashboard/dashboard_demo_admin.php @@ -0,0 +1,32 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'FH-Complete', + 'bootstrap5' => true, + 'fontawesome6' => true, + 'axios027' => true, + 'restclient' => true, + 'vue3' => true, + 'customJSModules' => ['public/js/apps/DashboardAdmin.js'], + 'customCSSs' => [ + 'public/css/components/dashboard.css' + ], + 'navigationcomponent' => true + ) +); +?> + +
+ + + +
+
+

Dashboard

+
+ +
+
+ +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..00e41d1cd --- /dev/null +++ b/application/views/lehre/Antrag/Create.php @@ -0,0 +1,71 @@ + '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( + ) +); + +if(defined('CIS4')){ + $this->load->view( + 'templates/CISVUE-Header', + $sitesettings + ); +}else{ + $this->load->view( + 'templates/FHC-Header', + $sitesettings + ); +} + +?> + +

+
+

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

+
+ +
+
+ + +
+
+ + +
+
+
+ +load->view( + 'templates/CISVUE-Footer', + $sitesettings + ); +} else { + $this->load->view( + 'templates/FHC-Footer', + $sitesettings + ); +} 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..6d769dafe --- /dev/null +++ b/application/views/lehre/Antrag/Student/List.php @@ -0,0 +1,241 @@ + '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( + ) +); + +if(defined('CIS4')){ + $this->load->view( + 'templates/CISVUE-Header', + $sitesettings + ); +}else{ + $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/CISVUE-Footer', + $sitesettings + ); +} else { + $this->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..e51cfd1bc --- /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/adminAnrechnung.php b/application/views/lehre/anrechnung/adminAnrechnung.php new file mode 100644 index 000000000..df36b3598 --- /dev/null +++ b/application/views/lehre/anrechnung/adminAnrechnung.php @@ -0,0 +1,164 @@ + $this->p->t('anrechnung', 'anrechnungenVerwalten'), + 'jquery3' => true, + 'jqueryui1' => true, + 'bootstrap3' => true, + 'fontawesome6' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'tabulator5' => true, + 'tabulator5JQuery' => true, + 'tablewidget' => true, + 'sbadmintemplate3' => true, + 'navigationwidget' => true, + 'phrases' => array( + 'anrechnung' => array( + 'anrechnungenVerwalten', + 'anrechnungszeitraumFestlegen', + 'anrechnungszeitraumHinzufuegen', + 'anrechnungszeitraumSpeichern', + 'anrechnungszeitraumStart', + 'anrechnungszeitraumEnde' + ), + 'ui' => array( + 'aktion', + 'geloescht', + 'gespeichert', + 'frageSicherLoeschen', + 'spaltenEinstellen' + ), + 'lehre' => array('studiensemester'), + 'table' => array( + 'spaltenEinAusblenden', + 'spaltenEinAusblendenMitKlickOeffnen', + 'spaltenEinAusblendenAufEinstellungenKlicken', + 'spaltenEinAusblendenMitKlickAktivieren', + 'spaltenEinAusblendenMitKlickSchliessen', + 'spaltenbreiteVeraendern', + 'spaltenbreiteVeraendernText', + 'spaltenbreiteVeraendernInfotext', + 'zeilenAuswaehlen', + 'zeilenAuswaehlenEinzeln', + 'zeilenAuswaehlenBereich', + 'zeilenAuswaehlenAlle' + ) + ), + 'customJSs' => array( + 'public/js/bootstrapper.js', + 'public/js/lehre/anrechnung/adminAnrechnung.js' + ), + 'customCSSs' => array( + 'public/css/sbadmin2/tablesort_bootstrap.css', + 'public/css/lehre/anrechnung.css' + ) +); + +if (defined("CIS4")) { + $this->load->view( + 'templates/CISVUE-Header', + $includesArray + ); +} else { + $this->load->view( + 'templates/FHC-Header', + $includesArray + ); +} +?> + +
+ + widgetlib->widget('NavigationWidget'); ?> + +
+
+ + +
+ +
+
+ +
+
+ + +
+
+ load->view('lehre/anrechnung/adminAnrechnungData.php'); ?> +
+
+ + + + +
+
+
+ +load->view( + 'templates/CISVUE-Footer', + $includesArray + ); +} else { + $this->load->view( + 'templates/FHC-Footer', + $includesArray + ); +} +?> diff --git a/application/views/lehre/anrechnung/adminAnrechnungData.php b/application/views/lehre/anrechnung/adminAnrechnungData.php new file mode 100644 index 000000000..9f0cd5733 --- /dev/null +++ b/application/views/lehre/anrechnung/adminAnrechnungData.php @@ -0,0 +1,51 @@ + $query, + 'tableUniqueId' => 'adminAnrechnung', + 'requiredPermissions' => 'lehre/anrechnungszeitfenster', + 'datasetRepresentation' => 'tabulator', + 'columnsAliases' => array( + 'AzrID', + ucfirst($this->p->t('lehre', 'studiensemester')), + ucfirst($this->p->t('anrechnung', 'anrechnungszeitraumStart')), + ucfirst($this->p->t('anrechnung', 'anrechnungszeitraumEnde')), + ucfirst($this->p->t('ui', 'bearbeitetAm')), + ucfirst($this->p->t('ui', 'bearbeitetVon')), + ), + 'datasetRepOptions' => '{ + height: func_height(this), + layout: "fitDataFill", + persistentLayout:true, + autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated + index: "anrechnungszeitraum_id", // assign specific column as unique id (important for row indexing) + selectable: false, // allow row selection + tableWidgetHeader: true, + tableBuilt: function(){ + func_tableBuilt(this); + }, + columnDefaults:{ + headerFilterPlaceholder:" ", + }, + }', + 'datasetRepFieldsDefs' => '{ + anrechnungszeitraum_id: {visible: false, headerFilter:"input"}, + studiensemester_kurzbz: {headerFilter:"input"}, + anrechnungstart: {headerFilter:"input", formatter: formatDate}, + anrechnungende: {headerFilter:"input", formatter: formatDate}, + insertamum: {visible: false, headerFilter:"input"}, + insertvon: {visible: false, headerFilter:"input"} + }' +); +?> +
+widgetlib->widget('TableWidget', $filterWidgetArray); +?> +
\ No newline at end of file diff --git a/application/views/lehre/anrechnung/approveAnrechnungDetail.php b/application/views/lehre/anrechnung/approveAnrechnungDetail.php index bc3b6215a..d7c187ab0 100644 --- a/application/views/lehre/anrechnung/approveAnrechnungDetail.php +++ b/application/views/lehre/anrechnung/approveAnrechnungDetail.php @@ -1,176 +1,228 @@ load->view( - 'templates/FHC-Header', - array( - 'title' => $this->p->t('anrechnung', 'anrechnungenGenehmigen'), - 'jquery3' => true, - 'jqueryui1' => true, - 'bootstrap3' => true, - 'fontawesome4' => true, - 'ajaxlib' => true, - 'dialoglib' => true, - 'phrases' => array( - 'global' => array( - 'anerkennungNachgewiesenerKenntnisse', - 'antragStellen', - 'begruendung' - ), - 'ui' => array( - 'hilfeZuDieserSeite', - 'hochladen', - 'nichtSelektierbarAufgrundVon', - 'nichtSelektierbarAufgrundVon', - 'systemfehler', - 'bitteMindEinenAntragWaehlen', - 'bitteBegruendungAngeben', - 'empfehlungWurdeAngefordert', - 'anrechnungenWurdenGenehmigt', - 'anrechnungenWurdenAbgelehnt', - 'nurLeseberechtigung' - ), - 'person' => array( - 'student', - 'personenkennzeichen' - ), - 'lehre' => array( - 'studiensemester', - 'studiengang', - 'lehrveranstaltung', - 'ects', - 'lektor', - ), - 'anrechnung' => array( - 'genehmigungAblehnungWirklichZuruecknehmen', - 'empfehlungsanforderungWirklichZuruecknehmen', - 'erfolgreichZurueckgenommen', - 'empfehlungPositivConfirmed', - 'empfehlungNegativConfirmed', - 'anrechnungEctsTooltipTextBeiUeberschreitung' - ) - ), - 'customCSSs' => array( - 'public/css/Tabulator.css' - ), - 'customJSs' => array( - 'public/js/bootstrapper.js', - 'public/js/lehre/anrechnung/approveAnrechnungDetail.js' +$this->load->config('anrechnung'); +$includesArray = array( + 'title' => $this->p->t('anrechnung', 'anrechnungenGenehmigen'), + 'jquery3' => true, + 'jqueryui1' => true, + 'bootstrap5' => true, + 'cis' => true, + 'fontawesome4' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'phrases' => array( + 'global' => array( + 'anerkennungNachgewiesenerKenntnisse', + 'antragStellen', + 'begruendung' + ), + 'ui' => array( + 'hilfeZuDieserSeite', + 'hochladen', + 'nichtSelektierbarAufgrundVon', + 'nichtSelektierbarAufgrundVon', + 'systemfehler', + 'bitteMindEinenAntragWaehlen', + 'bitteBegruendungAngeben', + 'bitteBegruendungVervollstaendigen', + 'empfehlungWurdeAngefordert', + 'anrechnungenWurdenGenehmigt', + 'anrechnungenWurdenAbgelehnt', + 'nurLeseberechtigung' + ), + 'person' => array( + 'student', + 'personenkennzeichen' + ), + 'lehre' => array( + 'studiensemester', + 'studiengang', + 'lehrveranstaltung', + 'ects', + 'lektor', + ), + 'anrechnung' => array( + 'genehmigungAblehnungWirklichZuruecknehmen', + 'empfehlungsanforderungWirklichZuruecknehmen', + 'erfolgreichZurueckgenommen', + 'empfehlungPositivConfirmed', + 'empfehlungNegativConfirmed', + 'anrechnungEctsTooltipTextBeiUeberschreitung' ) + ), + 'customCSSs' => array( + 'public/css/lehre/anrechnung.css' + ), + 'customJSs' => array( + 'public/js/bootstrapper.js', + 'public/js/lehre/anrechnung/approveAnrechnungDetail.js' ) ); + +if (defined("CIS4")) { + $this->load->view( + 'templates/CISVUE-Header', + $includesArray + ); +} else { + $this->load->view( + 'templates/FHC-Header', + $includesArray + ); +} ?>
-
- -
- +
- -
-
+ +
+
-
+
-
-
- p->t('anrechnung', 'antrag'); ?>  - - - - p->t('anrechnung', 'antragdatum'); ?>: anrechnung_id) ? $anrechnungData->insertamum : '-' ?> +
+
+ p->t('anrechnung', 'antrag'); ?>  + + + + p->t('anrechnung', 'antragdatum'); ?>: anrechnung_id) ? $anrechnungData->insertamum : '-' ?>
-
+
-
- +
+
- - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
p->t('person', 'studentIn')); ?>vorname . ' ' . $antragData->nachname; ?>
p->t('person', 'personenkennzeichen'); ?>matrikelnr ?>
p->t('lehre', 'studiensemester')); ?>studiensemester_kurzbz ?>
p->t('lehre', 'studiengang')); ?>stg_bezeichnung ?>
p->t('lehre', 'lehrveranstaltung'); ?>lv_bezeichnung ?>
+ p->t('person', 'studentIn')); ?>vorname . ' ' . $antragData->nachname; ?> +
+ p->t('person', 'personenkennzeichen'); ?>matrikelnr ?>
+ p->t('lehre', 'studiensemester')); ?> + studiensemester_kurzbz ?>
+ p->t('lehre', 'studiengang')); ?>stg_bezeichnung ?>
+ p->t('lehre', 'lehrveranstaltung'); ?>lv_bezeichnung ?>
p->t('lehre', 'lektorInnen'); ?> + + lektoren) - 1 ?> + lektoren as $key => $lektor): ?> + vorname . ' ' . $lektor->nachname; + echo $key === $len ? '' : ', ' ?> + +
p->t('lehre', 'ects'); ?>ects ?>
+ p->t('anrechnung', 'bisherAngerechneteEcts'); ?> + + + + + Total: sumEctsSchulisch + $antragData->sumEctsBeruflich, 1) ?> + [Schulisch: sumEctsSchulisch ?> + / + Beruflich: sumEctsBeruflich ?> + ] +
+
-
- +
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + config->item('explain_equivalence')): ?> + + + + + + + + +
p->t('lehre', 'ects'); ?>ects ?>
- p->t('anrechnung', 'bisherAngerechneteEcts'); ?> - - - - - Total: sumEctsSchulisch + $antragData->sumEctsBeruflich, 1) ?> - [Schulisch: sumEctsSchulisch ?> / - Beruflich: sumEctsBeruflich ?> ] - -
p->t('lehre', 'lektorInnen'); ?> - lektoren) - 1 ?> - lektoren as $key => $lektor): ?> - vorname . ' ' . $lektor->nachname; - echo $key === $len ? '' : ', ' ?> - -
p->t('global', 'zgv')); ?>zgv ?>
p->t('anrechnung', 'herkunftDerKenntnisse'); ?>anmerkung ?>
p->t('anrechnung', 'nachweisdokumente'); ?> - dokumentname) ?> -
p->t('global', 'begruendung'); ?>begruendung ?>
+ p->t('global', 'zgv')); ?>zgv ?>
+ p->t('anrechnung', 'herkunftDerKenntnisse'); ?> + anmerkung ?>
+ p->t('anrechnung', 'nachweisdokumente'); ?> + + dokumentname) ?> +
+ p->t('global', 'begruendung'); ?>begruendung ?> +
+ p->t('anrechnung', 'begruendungEctsLabel'); ?> + begruendung_ects ?> +
+ p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> + begruendung_lvinhalt ?> +
@@ -182,86 +234,105 @@ $this->load->view(
-
-
- p->t('anrechnung', 'empfehlung'); ?>  -
- p->t('anrechnung', 'empfehlungVon'); ?>: - empfehlung_von ?> -  |  - p->t('anrechnung', 'empfehlungdatum'); ?>: - empfehlung_am ?> -
+
+
+ p->t('anrechnung', 'empfehlung'); ?>  +
+ p->t('anrechnung', 'empfehlungVon'); ?>: + empfehlung_von ?> +  |  + p->t('anrechnung', 'empfehlungdatum'); ?>: + empfehlung_am ?>
-
-
-
-
- - - - - - + +
+
+
+ + + + + +
+ - - + - - + - + - + - - + + - + - -
p->t('anrechnung', 'empfehlungsanfrageAm')); ?> + + p->t('anrechnung', 'empfehlungsanfrageAm')); ?> + empfehlungsanfrageAm; ?>
p->t('anrechnung', 'empfehlungsanfrageAn'); ?> + + p->t('anrechnung', 'empfehlungsanfrageAn'); ?> + empfehlungsanfrageAn; ?>
p->t('anrechnung', 'empfehlungAm')); ?> + p->t('anrechnung', 'empfehlungAm')); ?> + empfehlung_am ?>
p->t('anrechnung', 'empfehlungVon')); ?> + p->t('anrechnung', 'empfehlungVon')); ?> + empfehlung_von ?>
p->t('anrechnung', 'empfehlung'); ?> + p->t('anrechnung', 'empfehlung'); ?> +
p->t('global', 'begruendung'); ?> + p->t('global', 'begruendung'); ?> begruendung) ?>
-
-
-
-
- - -
- - -
- -
-
+ + + +
+
+
+ + +
+ + +
+ +
- -
-
+ +
+
-

+
-
-
- p->t('anrechnung', 'genehmigung'); ?>  -
+
+
+ p->t('anrechnung', 'genehmigung'); ?>  +
p->t('anrechnung', 'abgeschlossenVon'); ?>: - abgeschlossen_von ?> + abgeschlossen_von ?>  |  p->t('anrechnung', 'abschlussdatum'); ?>: - abgeschlossen_am ?> + abgeschlossen_am ?>
-
+
-
+
p->t('anrechnung', 'nochKeineGenehmigung'); ?>
-
+
p->t('anrechnung', 'genehmigungPositiv'); ?>
-
-
+
+
p->t('anrechnung', 'genehmigungNegativ'); ?>
-
p->t('global', 'begruendung'); ?> +
+ p->t('global', 'begruendung'); ?> : - notiz) ?> + notiz) ?>
- -
- - - -
- - -
- +
-
- - -
-



-
-
+
+ +
-
- Status: - status; ?> - -
-
+
+ Status: + status; ?> + +
+ load->view('lehre/anrechnung/reviewAnrechnungInfo'); ?> -
-
+
+
-
+
-load->view('templates/FHC-Footer'); ?> +load->view( + 'templates/CISVUE-Footer', + $includesArray + ); +} else { + $this->load->view( + 'templates/FHC-Footer', + $includesArray + ); +} +?> diff --git a/application/views/lehre/anrechnung/approveAnrechnungUebersicht.php b/application/views/lehre/anrechnung/approveAnrechnungUebersicht.php index f5d1e8214..d53941113 100644 --- a/application/views/lehre/anrechnung/approveAnrechnungUebersicht.php +++ b/application/views/lehre/anrechnung/approveAnrechnungUebersicht.php @@ -1,108 +1,126 @@ load->view( - 'templates/FHC-Header', - array( - 'title' => $this->p->t('anrechnung', 'anrechnungenGenehmigen'), - 'jquery3' => true, - 'jqueryui1' => true, - 'bootstrap3' => true, - 'fontawesome4' => true, - 'tabulator4' => true, - 'ajaxlib' => true, - 'dialoglib' => true, - 'tablewidget' => true, - 'phrases' => array( - 'global' => array( - 'begruendung', - 'zgv' - ), - 'anrechnung' => array( - 'nachweisdokumente', - 'empfehlung', - 'empfehlungsanfrageAn', - 'empfehlungsanfrageAm', - 'confirmTextAntragHatBereitsEmpfehlung', - 'herkunft' - ), - 'ui' => array( - 'anzeigen', - 'alleAnzeigen', - 'hilfeZuDieserSeite', - 'hochladen', - 'spaltenEinstellen', - 'hilfeZuDieserSeite', - 'alleAuswaehlen', - 'alleAbwaehlen', - 'ausgewaehlteZeilen', - 'hilfe', - 'tabelleneinstellungen', - 'keineDatenVorhanden', - 'spaltenEinstellen', - 'ja', - 'nein', - 'nichtSelektierbarAufgrundVon', - 'nichtSelektierbarAufgrundVon', - 'systemfehler', - 'bitteMindEinenAntragWaehlen', - 'bitteBegruendungAngeben', - 'empfehlungWurdeAngefordert', - 'empfehlungWurdeAngefordertAusnahmeWoKeineLektoren', - 'anrechnungenWurdenGenehmigt', - 'anrechnungenWurdenAbgelehnt', - 'nurLeseberechtigung' - ), - 'person' => array( - 'student', - 'personenkennzeichen', - 'vorname', - 'nachname' - ), - 'lehre' => array( - 'studiensemester', - 'studiengang', - 'lehrveranstaltung', - 'ects', - 'lektor', - ), - 'table' => array( - 'spaltenEinAusblenden', - 'spaltenEinAusblendenMitKlickOeffnen', - 'spaltenEinAusblendenAufEinstellungenKlicken', - 'spaltenEinAusblendenMitKlickAktivieren', - 'spaltenEinAusblendenMitKlickSchliessen', - 'spaltenbreiteVeraendern', - 'spaltenbreiteVeraendernText', - 'spaltenbreiteVeraendernInfotext', - 'zeilenAuswaehlen', - 'zeilenAuswaehlenEinzeln', - 'zeilenAuswaehlenBereich', - 'zeilenAuswaehlenAlle' - ) + +$includesArray = array( + 'title' => $this->p->t('anrechnung', 'anrechnungenGenehmigen'), + 'jquery3' => true, + 'jqueryui1' => true, + 'bootstrap5' => true, + 'fontawesome4' => true, + 'tabulator5' => true, + 'tabulator5JQuery' => true, + 'ajaxlib' => true, + 'dialoglib' => true, + 'cis'=>true, + 'tablewidget' => true, + 'phrases' => array( + 'global' => array( + 'begruendung', + 'zgv' ), - 'customJSs' => array( - 'public/js/bootstrapper.js', - 'public/js/lehre/anrechnung/approveAnrechnungUebersicht.js' + 'anrechnung' => array( + 'nachweisdokumente', + 'empfehlung', + 'empfehlungsanfrageAn', + 'empfehlungsanfrageAm', + 'confirmTextAntragHatBereitsEmpfehlung', + 'herkunft' + ), + 'ui' => array( + 'anzeigen', + 'alleAnzeigen', + 'hilfeZuDieserSeite', + 'hochladen', + 'spaltenEinstellen', + 'hilfeZuDieserSeite', + 'alleAuswaehlen', + 'alleAbwaehlen', + 'ausgewaehlteZeilen', + 'hilfe', + 'tabelleneinstellungen', + 'keineDatenVorhanden', + 'spaltenEinstellen', + 'ja', + 'nein', + 'nichtSelektierbarAufgrundVon', + 'nichtSelektierbarAufgrundVon', + 'systemfehler', + 'bitteMindEinenAntragWaehlen', + 'bitteBegruendungAngeben', + 'empfehlungWurdeAngefordert', + 'empfehlungWurdeAngefordertAusnahmeWoKeineLektoren', + 'anrechnungenWurdenGenehmigt', + 'anrechnungenWurdenAbgelehnt', + 'nurLeseberechtigung' + ), + 'person' => array( + 'student', + 'personenkennzeichen', + 'vorname', + 'nachname' + ), + 'lehre' => array( + 'studiensemester', + 'studiengang', + 'lehrveranstaltung', + 'ects', + 'lektor', + ), + 'table' => array( + 'spaltenEinAusblenden', + 'spaltenEinAusblendenMitKlickOeffnen', + 'spaltenEinAusblendenAufEinstellungenKlicken', + 'spaltenEinAusblendenMitKlickAktivieren', + 'spaltenEinAusblendenMitKlickSchliessen', + 'spaltenbreiteVeraendern', + 'spaltenbreiteVeraendernText', + 'spaltenbreiteVeraendernInfotext', + 'zeilenAuswaehlen', + 'zeilenAuswaehlenEinzeln', + 'zeilenAuswaehlenBereich', + 'zeilenAuswaehlenAlle' ) + ), + 'customJSs' => array( + //'public/js/bootstrapper5.js', + 'public/js/lehre/anrechnung/approveAnrechnungUebersicht.js' + ), + 'customCSSs' => array( + 'public/css/lehre/anrechnung.css' ) ); + +if (defined("CIS4")) { + $this->load->view( + 'templates/CISVUE-Header', + $includesArray + ); +} else { + $this->load->view( + 'templates/FHC-Header', + $includesArray + ); +} ?>
- +
- + + +
-
-
+ +
widgetlib->widget( 'Studiensemester_widget', @@ -111,81 +129,81 @@ $this->load->view( ), array( 'name' => 'studiensemester', - 'id' => 'studiensemester' + 'id'=>'studiensemester', + 'class'=>'form-select w-auto ', ) ); ?>
+ + class="btn btn-outline-secondary col-auto">p->t('ui', 'anzeigen')); ?>
-
-
- load->view('lehre/anrechnung/approveAnrechnungUebersichtData.php'); ?> +
+
+ load->view('lehre/anrechnung/approveAnrechnungUebersichtData.php'); ?>
-