diff --git a/.gitignore b/.gitignore index bd98c9b59..84957a801 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ documents/ vendor/ /nbproject/ +.vscode +composer.phar /.idea/ .settings .project @@ -24,6 +26,7 @@ application/logs/ application/models/extensions/ application/views/extensions/ application/widgets/extensions/ +application/components/extensions/ public/extensions/ diff --git a/include/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html b/application/components/extensions/.placeholder similarity index 100% rename from include/fckeditor/editor/dialog/fck_spellerpages/spellerpages/blank.html rename to application/components/extensions/.placeholder diff --git a/application/components/filters/LogsViewer.php b/application/components/filters/LogsViewer.php new file mode 100644 index 000000000..3a5390273 --- /dev/null +++ b/application/components/filters/LogsViewer.php @@ -0,0 +1,19 @@ + 'core', + 'datasetName' => 'logs', + //'filterKurzbz' => 'jobs48hours', // REMOVE ME + 'query' => ' + SELECT wsl.webservicelog_id AS "LogId", + wsl.request_id AS "RequestId", + wsl.execute_time AS "ExecutionTime", + wsl.execute_user AS "ExecutedBy", + wsl.beschreibung AS "Description", + wsl.request_data AS "Data", + wsl.webservicetyp_kurzbz AS "WebserviceType" + FROM system.tbl_webservicelog wsl + ORDER BY wsl.execute_time DESC + ', + 'requiredPermissions' => 'admin' + ); + diff --git a/application/config/Events.php b/application/config/Events.php new file mode 100644 index 000000000..3e0a5248f --- /dev/null +++ b/application/config/Events.php @@ -0,0 +1,37 @@ + APP_ROOT.'public/js/components/Cis/Renderer/Lehreinheit/calendarEvent.js', + 'modalTitle' => APP_ROOT.'public/js/components/Cis/Renderer/Lehreinheit/modalTitle.js', + 'modalContent' => APP_ROOT.'public/js/components/Cis/Renderer/Lehreinheit/modalContent.js', + 'calendarEventStyles' => APP_ROOT.'public/css/Cis4/CoreCalendarEvents.css' + ); +}); + +Events::on('loadRenderers', function ($renderers) { + $fhc_core_renderers =& $renderers(); + $fhc_core_renderers["reservierung"] = array( + 'calendarEvent' => APP_ROOT.'public/js/components/Cis/Renderer/Reservierungen/calendarEvent.js', + 'modalTitle' => APP_ROOT.'public/js/components/Cis/Renderer/Reservierungen/modalTitle.js', + 'modalContent' => APP_ROOT.'public/js/components/Cis/Renderer/Reservierungen/modalContent.js', + 'calendarEventStyles' => APP_ROOT.'public/css/Cis4/CoreCalendarEvents.css' + ); +}); + +Events::on('loadRenderers', function ($renderers) { + $fhc_core_renderers =& $renderers(); + $fhc_core_renderers["ferien"] = array( + 'calendarEvent' => APP_ROOT.'public/js/components/Cis/Renderer/Feiertage/calendarEvent.js', + 'modalTitle' => APP_ROOT.'public/js/components/Cis/Renderer/Feiertage/modalTitle.js', + 'modalContent' => APP_ROOT.'public/js/components/Cis/Renderer/Feiertage/modalContent.js', + 'calendarEventStyles' => APP_ROOT.'public/css/Cis4/CoreCalendarEvents.css' + ); +}); + + + diff --git a/application/config/anrechnung.php b/application/config/anrechnung.php index d1f4f0958..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/calendar.php b/application/config/calendar.php new file mode 100644 index 000000000..99bb9b2c6 --- /dev/null +++ b/application/config/calendar.php @@ -0,0 +1,6 @@ +. + */ + +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/issueList.php b/application/config/issueList.php new file mode 100644 index 000000000..e4e4f278c --- /dev/null +++ b/application/config/issueList.php @@ -0,0 +1,11 @@ +. + */ + +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 78fe6c9cf..f6daaee8d 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -1,6 +1,12 @@ array( 'fhcomplete' => array( @@ -15,7 +21,7 @@ $config['navigation_header'] = array( 'description' => 'Organisation', 'sort' => 20, 'requiredPermissions' => 'basis/vilesci:r', - 'children'=> array( + 'children' => array( 'vilesci' => array( 'link' => base_url('vilesci'), 'icon' => '', @@ -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' ) ) ), @@ -40,13 +54,19 @@ $config['navigation_header'] = array( 'description' => 'Lehre', 'sort' => 30, 'requiredPermissions' => 'basis/vilesci:r', - 'children'=> array( + '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', @@ -71,6 +91,16 @@ $config['navigation_header'] = array( 'lehre/lehrauftrag_erteilen:r' ) ), + 'zverfueg' => array( + 'link' => site_url('lehre/lvplanung/AdminZeitverfuegbarkeit'), + 'description' => 'Zeitverfügbarkeit', + 'expand' => true, + 'sort' => 45, + 'requiredPermissions' => array( + 'lehre/zeitverfuegbarkeit:rw', + 'lehre/zeitverfuegbarkeit:rw' + ) + ), 'zgvueberpruefung' => array( 'link' => site_url('system/infocenter/ZGVUeberpruefung'), 'description' => 'ZGV Überprüfung', @@ -88,7 +118,7 @@ $config['navigation_header'] = array( 'description' => 'Personen', 'sort' => 40, 'requiredPermissions' => 'basis/vilesci:r', - 'children'=> array( + 'children' => array( 'messages' => array( 'link' => site_url('system/messages/MessageClient/read'), 'icon' => '', @@ -109,6 +139,20 @@ $config['navigation_header'] = array( 'expand' => true, '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' => 50, + 'requiredPermissions' => 'lehre/gruppenmanager:r' ) ) ), @@ -119,7 +163,7 @@ $config['navigation_header'] = array( 'expand' => false, 'sort' => 50, 'requiredPermissions' => 'admin:r', - 'children'=> array( + 'children' => array( 'extensions' => array( 'link' => site_url('system/extensions/Manager'), 'description' => 'Extensions Manager', @@ -147,7 +191,14 @@ $config['navigation_header'] = array( 'expand' => true, 'sort' => 40, 'requiredPermissions' => 'system/developer:r' - ) + ), + 'anrechnungen' => array( + 'link' => site_url('lehre/anrechnung/AdminAnrechnung'), + 'description' => 'Anrechnungen', + 'expand' => true, + 'sort' => 30, + 'requiredPermissions' => 'lehre/anrechnungszeitfenster:rw' + ) ) ) ) @@ -167,6 +218,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'), @@ -176,7 +236,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, @@ -191,7 +251,8 @@ $config['navigation_menu']['lehre/lehrauftrag/Lehrauftrag/*'] = array( 'icon' => 'dashboard', 'sort' => 1, 'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r','lehre/lehrauftrag_erteilen:r') - ),'lehrauftragBestellen' => array( + ), + 'lehrauftragBestellen' => array( 'link' => site_url('lehre/lehrauftrag/Lehrauftrag'), 'description' => 'Lehrauftrag bestellen', 'icon' => '', @@ -213,6 +274,7 @@ $config['navigation_menu']['lehre/lehrauftrag/Lehrauftrag/*'] = array( 'requiredPermissions' => array('lehre/lehrauftrag_erteilen:r') ) ); + $config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array( 'lehrauftragDashboard' => array( 'link' => site_url('lehre/lehrauftrag/Lehrauftrag/Dashboard'), @@ -220,7 +282,8 @@ $config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array( 'icon' => 'dashboard', 'sort' => 1, 'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r','lehre/lehrauftrag_erteilen:r') - ),'lehrauftragBestellen' => array( + ), + 'lehrauftragBestellen' => array( 'link' => site_url('lehre/lehrauftrag/Lehrauftrag'), 'description' => 'Lehrauftrag bestellen', 'icon' => '', @@ -242,3 +305,31 @@ $config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array( 'requiredPermissions' => array('lehre/lehrauftrag_erteilen:r') ) ); + +$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' => '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') + ), +); diff --git a/application/config/raumsuche.php b/application/config/raumsuche.php new file mode 100644 index 000000000..afc4beaf8 --- /dev/null +++ b/application/config/raumsuche.php @@ -0,0 +1,25 @@ + 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 @@ -60,3 +60,82 @@ $route['api/v1/organisation/[G|g]eschaeftsjahr/(:any)'] = 'api/v1/organisation/g $route['api/v1/organisation/[O|o]rganisationseinheit/(:any)'] = 'api/v1/organisation/organisationseinheit2/$1'; $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['Cis/LvPlan/.*'] = 'Cis/LvPlan/index/$1'; +$route['Cis/MyLvPlan/.*'] = 'Cis/MyLvPlan/index/$1'; +$route['Cis/MyLv/.*'] = 'Cis/MyLv/index/$1'; + +// Studierendenverwaltung List Routes +$route['api/frontend/v1/stv/[sS]tudents/inout'] = 'api/frontend/v1/stv/Students/index'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/index'; + +// (studiensemester_kurzbz)/inout[/(incoming|outgoing|gemeinsamestudien)] +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout'] = 'api/frontend/v1/stv/Students/index'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/incoming'] = 'api/frontend/v1/stv/Students/getIncoming'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/outgoing'] = 'api/frontend/v1/stv/Students/getOutgoing'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/gemeinsamestudien'] = 'api/frontend/v1/stv/Students/getGemeinsamestudien'; + +// (studiengang_kz)/prestudent[/(studiensemester_kurzbz)[/(filter)[/(otherfilter)]]] +$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent'] = 'api/frontend/v1/stv/Students/getPrestudents/$1'; +$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2'; +$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2/$3'; +$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/prestudent/([WS]S[0-9]{4})/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudents/$1/$2/$4'; + +// (studiengang_kz)/(orgform)/prestudent[/(studiensemester_kurzbz)[/(filter)[/(otherfilter)]]] +$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2'; +$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3'; +$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3/$4'; +$route['api/frontend/v1/stv/[sS]tudents/(-?[0-9]+)/([A-Z]{2,3})/prestudent/([WS]S[0-9]{4})/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getPrestudentsOrgform/$1/$2/$3/$5'; + +// (studiensemester_kurzbz)/(studiengang_kz)/(semester)/grp/(gruppe) +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/grp/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsSpezialgruppe/$1/$2/$3/$4'; + +// (studiensemester_kurzbz)/(studiengang_kz)[/(semester)[/(verband)[/(gruppe)]]] +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/(:any)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3/$4'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/(:num)/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getStudents/$1/$2/$3/$4/$5'; + +// (studiensemester_kurzbz)/(studiengang_kz)/(orgform)/(semester)/grp/(gruppe) +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/grp/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgformSpezialgruppe/$1/$2/$3/$4/$5'; + +// (studiensemester_kurzbz)/(studiengang_kz)/(orgform)[/(semester)[/(verband)[/(gruppe)]]] +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4/$5'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/(-?[0-9]+)/([A-Z]{2,3})/(:num)/(:any)/(:any)'] = 'api/frontend/v1/stv/Students/getStudentsOrgform/$1/$2/$3/$4/$5/$6'; + +// // (studiensemester_kurzbz)/uid/(uid) +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/uid/(:any)'] = 'api/frontend/v1/stv/Students/getStudent/$1/$2'; +// // (studiensemester_kurzbz)/prestudent/(prestudent_id) +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/prestudent/(:num)'] = 'api/frontend/v1/stv/Students/getPrestudent/$1/$2'; +// // (studiensemester_kurzbz)/person/(person_id) +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/person/(:num)'] = 'api/frontend/v1/stv/Students/getPerson/$1/$2'; + +// load routes from extensions, also look for environment-specific configs +$subdirs = ['application/config/extensions', 'application/config/' . ENVIRONMENT . '/extensions']; + +foreach($subdirs as $subdir) +{ + if(is_dir($subdir)) + { + $dirlist = scandir($subdir); + if ($dirlist) + { + $files = array_diff($dirlist, array('.','..')); + + foreach ($files as &$item) + { + if (is_dir($subdir . DIRECTORY_SEPARATOR . $item)) + { + $routes_file = $subdir . DIRECTORY_SEPARATOR . $item . DIRECTORY_SEPARATOR . 'routes.php'; + + if (file_exists($routes_file)) + { + require($routes_file); + } + } + } + } + } +} diff --git a/application/config/search.php b/application/config/search.php new file mode 100644 index 000000000..bedf8d888 --- /dev/null +++ b/application/config/search.php @@ -0,0 +1,874 @@ + 'person_id', + 'table' => 'public.tbl_person', + 'searchfields' => [ + 'uid' => [ + 'comparison' => 'equals', + 'field' => 'uid', + 'join' => [ + 'table' => "public.tbl_benutzer", + 'using' => "person_id" + ], + '1-n' => true + ], + 'vorname' => [ + 'alias' => ['firstname'], + 'comparison' => 'similar', + 'field' => 'vorname' + ], + 'nachname' => [ + 'alias' => ['lastname', 'surename'], + 'comparison' => 'similar', + 'field' => 'nachname' + ], + 'name' => [ + 'comparison' => 'similar', + 'field' => "(vorname || ' ' || nachname)" + ], + 'email' => [ + 'comparison' => 'similar', + 'field' => 'kontakt', + 'join' => [ + 'table' => "public.tbl_kontakt", + 'on' => "kontakttyp = 'email' AND tbl_kontakt.person_id = tbl_person.person_id" + ], + "1-n" => true + ], + 'tel' => [ + 'alias' => ['phone', 'telefon'], + 'comparison' => 'similar', + 'field' => 'kontakt', + 'join' => [ + 'table' => "public.tbl_kontakt", + 'on' => "kontakttyp IN ('telefon', 'so.tel', 'mobil') AND tbl_kontakt.person_id = tbl_person.person_id" + ], + "1-n" => true + ], + 'preid' => [ + 'alias' => ['prestudent_id'], + 'comparison' => 'equal-int', + 'field' => 'prestudent_id', + 'join' => [ + 'table' => "public.tbl_prestudent", + 'using' => "person_id" + ], + '1-n' => true + ], + 'pid' => [ + 'alias' => ['person_id'], + 'comparison' => 'equal-int', + 'field' => 'person_id' + ] + ], + 'resultfields' => [ + "ARRAY( SELECT uid FROM public.tbl_benutzer WHERE person_id = p.person_id ) AS uids", + "p.person_id", + "(p.vorname || ' ' || p.nachname) AS name", + "ARRAY( SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp = 'email' AND person_id=p.person_id ) AS email", + "CASE + WHEN p.foto IS NOT NULL THEN 'data:image/jpeg' || CONVERT_FROM(DECODE('3b','hex'), 'UTF8') || 'base64,' || p.foto + ELSE NULL END + AS photo_url" + ], + 'resultjoin' => " + JOIN public.tbl_person p USING (person_id)" +]; + +$config['student'] = [ + 'primarykey' => 'student_uid', + 'table' => 'public.tbl_student', + 'searchfields' => [ + 'uid' => [ + 'comparison' => 'equals', + 'field' => 'student_uid' + ], + 'vorname' => [ + 'alias' => ['firstname'], + 'comparison' => 'similar', + 'field' => 'vorname', + 'join' => [ + [ + 'table' => "public.tbl_prestudent", + 'using' => "prestudent_id" + ], + [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ] + ], + 'nachname' => [ + 'alias' => ['lastname', 'surename'], + 'comparison' => 'similar', + 'field' => 'nachname', + 'join' => [ + [ + 'table' => "public.tbl_prestudent", + 'using' => "prestudent_id" + ], + [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ] + ], + 'name' => [ + 'comparison' => 'similar', + 'field' => "(vorname || ' ' || nachname)", + 'join' => [ + [ + 'table' => "public.tbl_prestudent", + 'using' => "prestudent_id" + ], + [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ] + ], + 'email' => [ + 'comparison' => 'similar', + 'field' => 'kontakt', + 'join' => [ + [ + 'table' => "public.tbl_prestudent", + 'using' => "prestudent_id" + ], + [ + 'table' => "public.tbl_kontakt", + 'on' => "kontakttyp = 'email' AND tbl_kontakt.person_id = tbl_prestudent.person_id" + ] + ], + "1-n" => true + ], + 'tel' => [ + 'alias' => ['phone', 'telefon'], + 'comparison' => 'similar', + 'field' => 'kontakt', + 'join' => [ + [ + 'table' => "public.tbl_prestudent", + 'using' => "prestudent_id" + ], + [ + 'table' => "public.tbl_kontakt", + 'on' => "kontakttyp IN ('telefon', 'so.tel', 'mobil') AND tbl_kontakt.person_id = tbl_prestudent.person_id" + ] + ], + "1-n" => true + ], + 'stg' => [ + 'alias' => ['studiengang'], + 'comparison' => 'equals', + 'field' => "typ || kurzbz", + 'join' => [ + [ + 'table' => "public.tbl_prestudent", + 'using' => "prestudent_id" + ], + [ + 'table' => "public.tbl_studiengang", + 'on' => "tbl_studiengang.studiengang_kz = tbl_prestudent.studiengang_kz" + ] + ] + ], + 'preid' => [ + 'alias' => ['prestudent_id'], + 'comparison' => 'equal-int', + 'field' => 'prestudent_id' + ], + 'pid' => [ + 'alias' => ['person_id'], + 'comparison' => 'equal-int', + 'field' => 'person_id', + 'join' => [ + 'table' => "public.tbl_prestudent", + 'using' => "prestudent_id" + ] + ] + ], + 'resultfields' => [ + "s.student_uid AS uid", + "s.matrikelnr", + "p.person_id", + "(p.vorname || ' ' || p.nachname) AS name", + "(s.student_uid || '@" . DOMAIN . "') || ARRAY( SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp = 'email' AND person_id=p.person_id ) AS email", + "CASE + WHEN p.foto IS NOT NULL THEN 'data:image/jpeg' || CONVERT_FROM(DECODE('3b','hex'), 'UTF8') || 'base64,' || p.foto + ELSE NULL END + AS photo_url", + "b.aktiv" + ], + 'resultjoin' => " + JOIN public.tbl_student s USING (student_uid) + JOIN public.tbl_benutzer b ON(b.uid = s.student_uid) + JOIN public.tbl_person p USING(person_id)" +]; + +$prestudent_sort = [ + "Student", + "Incoming", + "Outgoing", + "Diplomand", + "Unterbrecher", + "Aufgenommener", + "Wartender", + "Bewerber", + "Interessent", + "Abgewiesener", + "Absolvent", + "Abbrecher", + "Ausserordentlicher", + "Praktikant" +]; +$prestudent_sort_array = "array['" . implode("','", $prestudent_sort) . "']"; +$config['prestudent'] = [ + 'primarykey' => 'prestudent_id', + 'table' => 'public.tbl_prestudent', + 'searchfields' => [ + 'uid' => [ + 'comparison' => 'equals', + 'field' => 'student_uid', + 'join' => [ + 'table' => "public.tbl_student", + 'using' => "prestudent_id" + ] + ], + 'vorname' => [ + 'alias' => ['firstname'], + 'comparison' => 'similar', + 'field' => 'vorname', + 'join' => [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ], + 'nachname' => [ + 'alias' => ['lastname', 'surename'], + 'comparison' => 'similar', + 'field' => 'nachname', + 'join' => [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ], + 'name' => [ + 'comparison' => 'similar', + 'field' => "(vorname || ' ' || nachname)", + 'join' => [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ], + 'email' => [ + 'comparison' => 'similar', + 'field' => 'kontakt', + 'join' => [ + 'table' => "public.tbl_kontakt", + 'on' => "kontakttyp = 'email' AND tbl_kontakt.person_id = tbl_prestudent.person_id" + ], + "1-n" => true + ], + 'tel' => [ + 'alias' => ['phone', 'telefon'], + 'comparison' => 'similar', + 'field' => 'kontakt', + 'join' => [ + 'table' => "public.tbl_kontakt", + 'on' => "kontakttyp IN ('telefon', 'so.tel', 'mobil') AND tbl_kontakt.person_id = tbl_prestudent.person_id" + ], + "1-n" => true + ], + 'stg' => [ + 'alias' => ['studiengang'], + 'comparison' => 'equals', + 'field' => "typ || kurzbz", + 'join' => [ + 'table' => "public.tbl_studiengang", + 'using' => "studiengang_kz" + ] + ], + 'preid' => [ + 'alias' => ['prestudent_id'], + 'comparison' => 'equal-int', + 'field' => 'prestudent_id' + ], + 'pid' => [ + 'alias' => ['person_id'], + 'comparison' => 'equal-int', + 'field' => 'person_id', + 'join' => [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ] + ], + 'resultfields' => [ + "ps.prestudent_id", + "ps.studiengang_kz", + "s.matrikelnr", + "p.person_id", + "b.uid", + "(p.vorname || ' ' || p.nachname) AS name", + "(b.uid || '@" . DOMAIN . "') || ARRAY( SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp = 'email' AND person_id=p.person_id ) AS email", + "CASE + WHEN p.foto IS NOT NULL THEN 'data:image/jpeg' || CONVERT_FROM(DECODE('3b','hex'), 'UTF8') || 'base64,' || p.foto + ELSE NULL END + AS photo_url", + "UPPER(sg.typ || sg.kurzbz) AS stg_kuerzel", + "sg.bezeichnung", + "( + SELECT bezeichnung_mehrsprachig[(TABLE lang)] + FROM public.tbl_status + WHERE status_kurzbz = public.get_rolle_prestudent(ps.prestudent_id, NULL) + LIMIT 1 + ) AS status", + "COALESCE( + ( + SELECT COALESCE(plan.orgform_kurzbz, pss.orgform_kurzbz) + FROM public.tbl_prestudentstatus pss + LEFT JOIN lehre.tbl_studienplan plan USING (studienplan_id) + WHERE pss.prestudent_id=ps.prestudent_id + ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC + LIMIT 1 + ), + sg.orgform_kurzbz + ) AS orgform", + "b.aktiv", + "array_position(" . $prestudent_sort_array . ", public.get_rolle_prestudent(ps.prestudent_id, NULL)) AS sort" + ], + 'resultjoin' => " + LEFT JOIN public.tbl_prestudent ps USING (prestudent_id) + LEFT JOIN public.tbl_student s ON (ps.prestudent_id = s.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)" +]; + +$config['employee'] = [ + 'alias' => ['ma', 'mitarbeiter'], + 'primarykey' => 'mitarbeiter_uid', + 'table' => 'public.tbl_mitarbeiter', + 'searchfields' => [ + 'uid' => [ + 'alias' => ['mitarbeiter_uid'], + 'comparison' => 'equals', + 'field' => "mitarbeiter_uid" + ], + 'vorname' => [ + 'alias' => ['firstname'], + 'comparison' => 'similar', + 'field' => "vorname", + 'join' => [ + [ + 'table' => "public.tbl_benutzer", + 'on' => "uid = mitarbeiter_uid" + ], + [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ] + ], + 'nachname' => [ + 'alias' => ['lastname', 'surename'], + 'comparison' => 'similar', + 'field' => "nachname", + 'join' => [ + [ + 'table' => "public.tbl_benutzer", + 'on' => "uid = mitarbeiter_uid" + ], + [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ] + ], + 'name' => [ + 'comparison' => 'similar', + 'field' => "(vorname || ' ' || nachname)", + 'join' => [ + [ + 'table' => "public.tbl_benutzer", + 'on' => "uid = mitarbeiter_uid" + ], + [ + 'table' => "public.tbl_person", + 'using' => "person_id" + ] + ] + ], + 'email' => [ + 'comparison' => 'similar', + 'field' => "COALESCE(alias, uid) || '" . '@' . DOMAIN . "'", + 'join' => [ + 'table' => "public.tbl_benutzer", + 'on' => "uid = mitarbeiter_uid" + ] + ], + 'tel' => [ + 'alias' => ['phone', 'telefon'], + 'comparison' => 'similar', + 'field' => "TRIM(COALESCE(kontakt, '') || ' ' || COALESCE(telefonklappe, ''))", + 'join' => [ + 'table' => "public.tbl_kontakt", + 'on' => "kontakttyp = 'telefon' AND tbl_kontakt.standort_id = tbl_mitarbeiter.standort_id" + ], + "1-n" => true + ], + 'pid' => [ + 'alias' => ['person_id'], + 'comparison' => 'equal-int', + 'field' => "person_id", + 'join' => [ + 'table' => "public.tbl_benutzer", + 'on' => "uid = mitarbeiter_uid" + ] + ], + 'oe' => [ + 'alias' => ['ou', 'organisationseinheit', 'organisationunit'], + 'comparison' => 'vector', + 'field' => "fts_bezeichnung", + 'join' => [ + [ + 'table' => "public.tbl_benutzerfunktion", + 'on' => "mitarbeiter_uid = uid + AND funktion_kurzbz = 'oezuordnung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW())" + ], + [ + 'table' => "public.tbl_organisationseinheit", + 'using' => "oe_kurzbz" + ] + ], + '1-n' => true + ], + 'kst' => [ + 'comparison' => 'vector', + 'field' => "fts_bezeichnung", + 'join' => [ + [ + 'table' => "public.tbl_benutzerfunktion", + 'on' => "mitarbeiter_uid = uid + AND funktion_kurzbz = 'kstzuordnung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW())" + ], + [ + 'table' => "public.tbl_organisationseinheit", + 'using' => "oe_kurzbz" + ] + ], + '1-n' => true + ] + ], + 'resultfields' => [ + "b.uid", + "p.person_id", + "(p.vorname || ' ' || p.nachname) AS name", + "ARRAY( + SELECT + '[' || ot.bezeichnung || '] ' || o.bezeichnung AS bezeichnung + 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()) + AND bf.uid = b.uid + GROUP BY o.bezeichnung, ot.bezeichnung + ) AS organisationunit_name", + "COALESCE(b.alias, b.uid) || '" . '@' . DOMAIN . "' AS email", + "TRIM(COALESCE(k.kontakt, '') || ' ' || COALESCE(m.telefonklappe, '')) AS phone", + "'" . base_url("/cis/public/bild.php?src=person&person_id=") . "' || p.person_id AS photo_url", + "ARRAY( + SELECT + '[' || ot.bezeichnung || '] ' || o.bezeichnung AS bezeichnung + 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()) + AND bf.uid = b.uid + GROUP BY o.bezeichnung, ot.bezeichnung + ) AS standardkostenstelle" + ], + 'resultjoin' => " + JOIN public.tbl_mitarbeiter m USING (mitarbeiter_uid) + JOIN public.tbl_benutzer b ON (b.uid = m.mitarbeiter_uid) + JOIN public.tbl_person p USING(person_id) + LEFT JOIN ( + SELECT kontakt, standort_id + FROM public.tbl_kontakt + WHERE kontakttyp = 'telefon' + ) k ON (k.standort_id = m.standort_id)" +]; + +// TODO(chris): move to searchpv21.php +$config['unassigned_employee'] = $config['employee']; +$config['unassigned_employee']['alias'] = ['mitarbeiter_ohne_zuordnung']; +$config['unassigned_employee']['prepare'] = "unassigned_employee AS ( + SELECT tbl_mitarbeiter.* + FROM public.tbl_mitarbeiter + LEFT JOIN public.tbl_benutzerfunktion ON ( + uid = mitarbeiter_uid + AND funktion_kurzbz = 'kstzuordnung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + ) + WHERE tbl_benutzerfunktion.bezeichnung IS NULL + UNION + SELECT tbl_mitarbeiter.* + FROM public.tbl_mitarbeiter + LEFT JOIN public.tbl_benutzerfunktion ON ( + uid = mitarbeiter_uid + AND funktion_kurzbz = 'oezuordnung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + ) + WHERE tbl_benutzerfunktion.bezeichnung IS NULL +)"; +$config['unassigned_employee']['table'] = "unassigned_employee"; +$config['unassigned_employee']['searchfields']['tel']['join']['on'] = " + kontakttyp = 'telefon' + AND tbl_kontakt.standort_id = unassigned_employee.standort_id +"; +$config['unassigned_employee']['renderer'] = 'employee'; + +$config['organisationunit'] = [ + 'alias' => ['ou', 'organisationseinheit', 'oe'], + 'primarykey' => 'oe_kurzbz', + 'table' => 'public.tbl_organisationseinheit', + 'searchfields' => [ + 'uid' => [ + 'comparison' => 'equals', + 'field' => 'uid', + 'prepare' => "organisationunit_leader(oe_kurzbz, uid, vorname, nachname) AS ( + SELECT oe_kurzbz, vorname, nachname, uid + FROM public.tbl_benutzerfunktion + JOIN public.tbl_benutzer USING (uid) + JOIN public.tbl_person USING (person_id) + WHERE funktion_kurzbz = 'Leitung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + AND tbl_benutzer.aktiv = TRUE + )", + 'join' => [ + 'table' => "organisationunit_leader", + 'using' => "oe_kurzbz" + ], + '1-n' => true + ], + 'vorname' => [ + 'alias' => ['firstname'], + 'comparison' => 'similar', + 'field' => 'vorname', + 'prepare' => "organisationunit_leader(oe_kurzbz, uid, vorname, nachname) AS ( + SELECT oe_kurzbz, vorname, nachname, uid + FROM public.tbl_benutzerfunktion + JOIN public.tbl_benutzer USING (uid) + JOIN public.tbl_person USING (person_id) + WHERE funktion_kurzbz = 'Leitung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + AND tbl_benutzer.aktiv = TRUE + )", + 'join' => [ + 'table' => "organisationunit_leader", + 'using' => "oe_kurzbz" + ], + '1-n' => true + ], + 'nachname' => [ + 'alias' => ['lastname', 'surename'], + 'comparison' => 'similar', + 'field' => 'nachname', + 'prepare' => "organisationunit_leader(oe_kurzbz, uid, vorname, nachname) AS ( + SELECT oe_kurzbz, vorname, nachname, uid + FROM public.tbl_benutzerfunktion + JOIN public.tbl_benutzer USING (uid) + JOIN public.tbl_person USING (person_id) + WHERE funktion_kurzbz = 'Leitung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + AND tbl_benutzer.aktiv = TRUE + )", + 'join' => [ + 'table' => "organisationunit_leader", + 'using' => "oe_kurzbz" + ], + '1-n' => true + ], + 'name' => [ + 'comparison' => 'similar', + 'field' => "(vorname || ' ' || nachname)", + 'prepare' => "organisationunit_leader(oe_kurzbz, uid, vorname, nachname) AS ( + SELECT oe_kurzbz, vorname, nachname, uid + FROM public.tbl_benutzerfunktion + JOIN public.tbl_benutzer USING (uid) + JOIN public.tbl_person USING (person_id) + WHERE funktion_kurzbz = 'Leitung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + AND tbl_benutzer.aktiv = TRUE + )", + 'join' => [ + 'table' => "organisationunit_leader", + 'using' => "oe_kurzbz" + ], + '1-n' => true + ], + 'oe' => [ + 'alias' => ['ou', 'organisationseinheit', 'organisationunit'], + 'comparison' => 'vector', + 'field' => "fts_bezeichnung" + ], + 'kurzbz' => [ + 'alias' => ['oe_kurzbz'], + 'comparison' => 'equals', + 'field' => "oe_kurzbz" + ] + ], + 'resultfields' => [ + "oe.oe_kurzbz", + "('[' || type.bezeichnung || '] ' || oe.bezeichnung) AS name", + "oe_parent.oe_kurzbz AS parentoe_kurzbz", + "(CASE WHEN oe_parent.bezeichnung IS NOT NULL THEN '[' || type_parent.bezeichnung || '] ' || oe_parent.bezeichnung END) AS parentoe_name", + "ARRAY( + SELECT JSON_BUILD_OBJECT('uid', b.uid, 'vorname', p.vorname, 'nachname', p.nachname, 'name', (p.vorname || ' ' || p.nachname)) + FROM public.tbl_benutzerfunktion bf + JOIN public.tbl_benutzer b USING (uid) + JOIN public.tbl_person p USING (person_id) + WHERE funktion_kurzbz = 'Leitung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + AND b.aktiv = TRUE + AND oe_kurzbz = oe.oe_kurzbz + ) AS leaders", + "( + SELECT COUNT(*) + FROM public.tbl_benutzerfunktion + WHERE funktion_kurzbz = 'oezuordnung' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + AND oe_kurzbz = oe.oe_kurzbz + ) AS number_of_people", + "(CASE WHEN oe.mailverteiler THEN oe.oe_kurzbz || '" . '@' . DOMAIN . "' END) AS mailgroup" + ], + 'resultjoin' => " + JOIN public.tbl_organisationseinheit oe + USING (oe_kurzbz) + JOIN public.tbl_organisationseinheittyp type + USING (organisationseinheittyp_kurzbz) + LEFT JOIN public.tbl_organisationseinheit oe_parent + ON (oe_parent.oe_kurzbz = oe.oe_parent_kurzbz) + LEFT JOIN public.tbl_organisationseinheittyp type_parent + ON (oe_parent.organisationseinheittyp_kurzbz = type_parent.organisationseinheittyp_kurzbz)" +]; + +$config['room'] = [ + 'alias' => ['raum'], + 'primarykey' => 'ort_kurzbz', + 'table' => 'public.tbl_ort', + 'searchfields' => [ + 'name' => [ + 'comparison' => 'similar', + 'field' => 'ort_kurzbz' + ] + ], + 'resultfields' => [ + "ort.ort_kurzbz", + "ort.gebteil AS building", + "ort.ausstattung AS equipment", + "ort.stockwerk AS floor", + "ort.dislozierung AS room_number", + "ort.content_id", + "address.ort AS city", + "address.plz AS zip", + "address.strasse AS street", + "ort.max_person", + "ort.arbeitsplaetze AS workplaces" + ], + 'resultjoin' => " + JOIN public.tbl_ort ort + USING (ort_kurzbz) + LEFT JOIN public.tbl_standort + USING (standort_id) + LEFT JOIN public.tbl_adresse address + USING (adresse_id)" +]; +$sprache = getUserLanguage(); +$config['cms'] = [ + 'primarykey' => 'contentsprache_id', + 'table' => 'campus.tbl_contentsprache', + 'prepare' => " + cms_auth (content_id) AS ( + SELECT content_id + FROM campus.tbl_content c + WHERE NOT EXISTS (SELECT 1 FROM campus.tbl_contentgruppe g WHERE g.content_id=c.content_id) + UNION + SELECT content_id + FROM public.vw_gruppen g + JOIN campus.tbl_contentgruppe c USING (gruppe_kurzbz) + WHERE uid = (TABLE auth) + ), + cms_active (content_id, template_kurzbz) AS ( + SELECT content_id, template_kurzbz + FROM cms_auth + JOIN campus.tbl_content USING (content_id) + WHERE aktiv = TRUE + ), + cms_active_redirect (content_id) AS ( + SELECT content_id + FROM cms_active + WHERE template_kurzbz = 'redirect' + ), + cms_active_redirect_linked (content_id) AS ( + SELECT content_id + FROM cms_active_redirect + JOIN campus.tbl_contentsprache USING (content_id) + WHERE LEFT((xpath('string(/content/url)', content))[1]::text, 1) <> '#' + ), + cms_active_others (content_id) AS ( + SELECT content_id + FROM cms_active + WHERE template_kurzbz IN ('contentmittitel', 'contentohnetitel', 'contentmittitel_filterwidget') + ) + ", + 'searchfields' => [ + 'content' => [ + 'alias' => ['inhalt'], + 'comparison' => "vector", + 'field' => "( + setweight(to_tsvector('simple', COALESCE(titel, '')), 'A') + || + setweight(to_tsvector('simple', COALESCE(content, '')::text), 'B') + )" + ], + 'content_id' => [ + 'alias' => ['id'], + 'comparison' => "equal-int", + 'field' => "content_id" + ], + 'lang' => [ + 'alias' => ['language', 'sprache'], + 'comparison' => "equals", + 'field' => "sprache" + ] + ], + 'resultfields' => [ + "contentsprache.content_id", + "content.template_kurzbz", + "contentsprache.version", + "contentsprache.sprache AS language", + "contentsprache.titel AS title", + "contentsprache.content", + "(xpath('string(/content/url)', contentsprache.content))[1] AS content_url" + ], + 'resultjoin' => " + JOIN campus.tbl_contentsprache contentsprache + USING (contentsprache_id) + JOIN campus.tbl_content content + USING (content_id) + WHERE content_id IN ( + SELECT content_id + FROM cms_active_redirect_linked + UNION + SELECT content_id + FROM cms_active_others + ) + AND version = campus.get_highest_content_version(content_id) + AND contentsprache.sprache = '{$sprache}'" +]; + +$config['dms'] = [ + 'primarykey' => 'dms_id, version', + 'table' => 'campus.tbl_dms_version', + 'searchfields' => [ + 'keywords' => [ + 'alias' => ['keyword', 'keywords', 'schlagwort', 'schlagworte'], + 'comparison' => "vector", + 'field' => "(to_tsvector('simple', COALESCE(schlagworte, '')))" + ] + ], + 'resultfields' => [ + "v.dms_id", + "v.version", + "v.filename", + "v.mimetype", + "v.name", + "v.beschreibung AS description", + "v.schlagworte AS keywords" + ], + 'resultjoin' => " + JOIN campus.tbl_dms_version v + USING (dms_id, version) + WHERE cis_suche = TRUE + AND version=(SELECT MAX(version) FROM campus.tbl_dms_version WHERE dms_id=v.dms_id) + AND NOT EXISTS ( + SELECT + 1 + FROM + fue.tbl_projekt_dokument p + WHERE p.dms_id = v.dms_id + ) AND ( + NOT EXISTS ( + WITH RECURSIVE categories (kategorie_kurzbz) AS ( + SELECT + kategorie_kurzbz + FROM + campus.tbl_dms c + WHERE c.dms_id = v.dms_id + UNION ALL + SELECT + cat.parent_kategorie_kurzbz AS kategorie_kurzbz + FROM + categories + JOIN campus.tbl_dms_kategorie cat USING (kategorie_kurzbz) + ) + SELECT + 1 + FROM + categories + JOIN campus.tbl_dms_kategorie_gruppe USING (kategorie_kurzbz) + UNION + SELECT + 1 + FROM + categories + JOIN campus.tbl_dms_kategorie USING (kategorie_kurzbz) + WHERE + berechtigung_kurzbz IS NOT NULL + ) OR EXISTS ( + WITH RECURSIVE categories (kategorie_kurzbz) AS ( + SELECT + kategorie_kurzbz + FROM + campus.tbl_dms c + WHERE c.dms_id = v.dms_id + UNION ALL + SELECT + cat.parent_kategorie_kurzbz AS kategorie_kurzbz + FROM + categories + JOIN campus.tbl_dms_kategorie cat USING (kategorie_kurzbz) + ) + SELECT + 1 + FROM + categories + JOIN campus.tbl_dms_kategorie_gruppe USING (kategorie_kurzbz) + JOIN public.tbl_benutzergruppe USING(gruppe_kurzbz) + WHERE + uid = (TABLE auth) + ) + )" +]; diff --git a/application/config/searchcis.php b/application/config/searchcis.php new file mode 100644 index 000000000..12bad025d --- /dev/null +++ b/application/config/searchcis.php @@ -0,0 +1,48 @@ +config->item('employee', 'search'); +$config['employee']['resultjoin'] = " + JOIN public.tbl_mitarbeiter m USING (mitarbeiter_uid) + JOIN public.tbl_benutzer b ON (b.uid = m.mitarbeiter_uid AND b.aktiv = true) + JOIN public.tbl_person p USING(person_id) + LEFT JOIN ( + SELECT kontakt, standort_id + FROM public.tbl_kontakt + WHERE kontakttyp = 'telefon' + ) k ON (k.standort_id = m.standort_id)"; + +$config['student'] = $CI->config->item('student', 'search'); +unset($config['student']['searchfields']['email']); +unset($config['student']['searchfields']['tel']); +$config['student']['resultfields'] = [ + "s.student_uid AS uid", + "s.matrikelnr", + "p.person_id", + "(p.vorname || ' ' || p.nachname) AS name", + "ARRAY[s.student_uid || '@' || '" . DOMAIN . "'] AS email", + "CASE + WHEN (p.foto_sperre = false AND p.foto IS NOT NULL) THEN 'data:image/jpeg' || CONVERT_FROM(DECODE('3b','hex'), 'UTF8') || 'base64,' || p.foto + ELSE NULL END + AS photo_url", + "b.aktiv" +]; +$config['student']['resultjoin'] = " + JOIN public.tbl_student s USING (student_uid) + JOIN public.tbl_benutzer b ON(b.uid = s.student_uid AND b.aktiv = true) + JOIN public.tbl_person p USING(person_id)"; + +$config['organisationunit'] = $CI->config->item('organisationunit', 'search'); +$config['organisationunit']['prepare'] = 'active_organisationseinheit AS (SELECT * FROM public.tbl_organisationseinheit WHERE aktiv = true AND organisationseinheittyp_kurzbz <> \'Container\')'; +$config['organisationunit']['table'] = 'active_organisationseinheit'; + +$config['room'] = $CI->config->item('room', 'search'); + +$config['cms'] = $CI->config->item('cms', 'search'); + +$config['dms'] = $CI->config->item('dms', 'search'); diff --git a/application/config/searchfunctions.php b/application/config/searchfunctions.php new file mode 100644 index 000000000..276652997 --- /dev/null +++ b/application/config/searchfunctions.php @@ -0,0 +1,35 @@ + 4, + 'rank' => "0", + 'compare' => "{field}::text = {word}::text", + 'force_integer' => true +]; + +$config['equals'] = [ + 'priority' => 3, + 'rank' => "0", + 'compare' => "LOWER({field}) = {word}" +]; + +$config['similar'] = [ + 'priority' => 2, + 'rank' => "(COALESCE({field}, '') <->> {word})", + 'compare' => "COALESCE({field}, '') %> {word}", + 'compare_boolean' => "COALESCE({field}, '') ILIKE {like:word}" +]; + +$config['vector'] = [ + 'priority' => 1, + 'rank' => "ts_rank({field}, to_tsquery('simple', {word}))", + 'compare' => "to_tsquery('simple', {word}) @@ {field}" +]; + diff --git a/application/config/searchstv.php b/application/config/searchstv.php new file mode 100644 index 000000000..96c118ac8 --- /dev/null +++ b/application/config/searchstv.php @@ -0,0 +1,11 @@ +config->item('student', 'search'); + +$config['prestudent'] = $CI->config->item('prestudent', 'search'); 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/config/stv.php b/application/config/stv.php new file mode 100644 index 000000000..42afc318c --- /dev/null +++ b/application/config/stv.php @@ -0,0 +1,115 @@ + [ + //all fields can be configured to be hidden, see class attribute stv-details-details-name for name + 'hiddenFields' => [], + 'hideUDFs' => false + ], + + 'prestudent' => [ + + //all fields can be configured to be hidden, see class attribute stv-details-prestudent-name for name + 'hiddenFields' => [ + + //propably used by FH-Communities + 'aufnahmeschluessel', 'standort_code', 'facheinschlaegigBerufstaetig' + + ], + 'hideUDFs' => false + ], + 'finalexam' => [ + 'documents' => [ + 'pruefungsprotokoll' => [ + 'de' => [ + 'Bakk' => 'PrProtBA', + 'Master' => 'PrProtMA', + ], + 'en' => [ + 'Bakk' => 'PrProtBAEng', + 'Master' => 'PrProtMAEng', + ], + ], + 'pruefungszeugnis' => [ + 'de' => [ + 'Bakk' => 'Bakkzeugnis', + 'Master' => 'Diplomzeugnis', + ], + 'en' => [ + 'Bakk' => 'BakkzeugnisEng', + 'Master' => 'DiplomzeugnisEng', + ], + ], + 'urkunde' => [ + 'de' => [ + 'Bakk' => 'Bakkurkunde', + 'Master' => 'Diplomurkunde', + ], + 'en' => [ + 'Bakk' => 'BakkurkundeEng', + 'Master' => 'DiplomurkundeEng', + ], + ], + ], + ], + 'exemptions' => [ + //if true, Anrechnungen can be added and edited in tab Anrechnungen + 'editableAnrechnungen' => false, + ], + 'notes' => [ + //if true, the count of Messages will be shown in the header of the Tab Messages + 'showCountNotes' => true + ] + ]; + +// List of fields to show when ZGV_DOKTOR_ANZEIGEN is defined +$fieldsZgvDoktor = ['zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', 'zgvdoktor_erfuellt', 'zgvdoktor_code']; + +// List of fields to show when ZGV_ERFUELLT_ANZEIGEN is defined +$fieldsZgvErfuellt = ['zgv_erfuellt', 'zgvmas_erfuellt','zgvdoktor_erfuellt']; + +//order important: to show zgf_erfuellt_doktor just in case visibility of doktor is true +if (!defined('ZGV_ERFUELLT_ANZEIGEN') || !ZGV_ERFUELLT_ANZEIGEN) { + $config['tabs']['prestudent']['hiddenFields'] = array_merge( + $config['tabs']['prestudent']['hiddenFields'], $fieldsZgvErfuellt + ); +} + +if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) { + $config['tabs']['prestudent']['hiddenFields'] = array_merge( + $config['tabs']['prestudent']['hiddenFields'], + $fieldsZgvDoktor + ); +} + +$config['student_tab_order'] = [ + 'details', + 'notes', + 'messages', + 'contact', + 'prestudent', + 'status', + 'documents', + 'archive', + 'banking', + 'grades', + 'exam', + 'exemptions', + 'finalexam', + 'mobility', + 'jointstudies', + 'admissionDates', + 'groups', + 'functions', + 'coursedates', + 'resources', +]; +$config['students_tab_order'] = [ + 'banking', + 'status', + 'groups', + 'finalexam', + 'archive', +]; diff --git a/application/config/theme.php b/application/config/theme.php new file mode 100644 index 000000000..715c4e39c --- /dev/null +++ b/application/config/theme.php @@ -0,0 +1,11 @@ + self::PERM_LOGGED, + 'getStudentProjektarbeitAbgabeFile' => self::PERM_LOGGED, + 'Mitarbeiter' => self::PERM_LOGGED, + 'Student' => self::PERM_LOGGED, + 'Deadlines' => self::PERM_LOGGED + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + + $viewData = array( + 'uid'=>getAuthUID(), + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Abgabetool']); + } + + public function Student() + { + + $viewData = array( + 'uid'=>getAuthUID(), + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolStudent']); + } + + public function Mitarbeiter() + { + + $viewData = array( + 'uid'=>getAuthUID(), + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolMitarbeiter']); + } + + public function Deadlines() + { + + $viewData = array( + 'uid'=>getAuthUID(), + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'DeadlinesOverview']); + } + + + public function getStudentProjektarbeitAbgabeFile() + { + $this->_ci =& get_instance(); + $this->_ci->load->helper('download'); + + $paabgabe_id = $this->_ci->input->get('paabgabe_id'); + $student_uid = $this->_ci->input->get('student_uid'); + + if (!isset($paabgabe_id) || isEmptyString($paabgabe_id) || !isset($student_uid) || isEmptyString($student_uid)) + $this->terminateWithJsonError($this->p->t('global', 'wrongParameters'), 'general'); + + $this->_ci->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $isZugeteilterBetreuer = count($this->_ci->ProjektarbeitModel->checkZuordnung($student_uid, getAuthUID())->retval) > 0; + + if(getAuthUID() == $student_uid || $isZugeteilterBetreuer) { + $file_path = PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'; + if(file_exists($file_path)) { + + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + header('Content-Disposition: attachment; filename="'.basename($file_path).'"'); + header('Content-Length: ' . filesize($file_path)); + + flush(); // send headers first just in case + readfile($file_path); // read file content to output buffer + + } else { + $this->terminateWithJsonError('File not found'); + } + } else { + $this->terminateWithJsonError('Keine Zuordnung!'); + } + } +} diff --git a/application/controllers/Cis/Auth.php b/application/controllers/Cis/Auth.php new file mode 100644 index 000000000..67267ebf6 --- /dev/null +++ b/application/controllers/Cis/Auth.php @@ -0,0 +1,78 @@ +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(); + setcookie('fhclogout', 'fhclogout', 0, '/'); + redirect(base_url('/cis/private/logout.php'), '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/InfoTerminal.php b/application/controllers/Cis/InfoTerminal.php new file mode 100644 index 000000000..13dea1367 --- /dev/null +++ b/application/controllers/Cis/InfoTerminal.php @@ -0,0 +1,30 @@ + ['basis/cis:r'], + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + $this->load->view('Cis/InfoTerminal.php', []); + } +} diff --git a/application/controllers/Cis/LvPlan.php b/application/controllers/Cis/LvPlan.php new file mode 100644 index 000000000..884c8a9a0 --- /dev/null +++ b/application/controllers/Cis/LvPlan.php @@ -0,0 +1,39 @@ + ['basis/cis:r'] + ]); + + // Load Config + $this->load->config('calendar'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + + $viewData = array( + 'uid'=>getAuthUID(), + 'timezone' => $this->config->item('timezone') + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'LvPlan']); + } +} diff --git a/application/controllers/Cis/MyLv.php b/application/controllers/Cis/MyLv.php new file mode 100644 index 000000000..49a938553 --- /dev/null +++ b/application/controllers/Cis/MyLv.php @@ -0,0 +1,41 @@ + ['basis/cis:r'], + 'Info' => [self::PERM_LOGGED] + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + + $viewData = array( + + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'MyLv']); + } + + public function Info($studien_semester,$lvid) + { + $this->load->view('Cis/LvInfo',['lvid'=> $lvid, 'studien_semester' => $studien_semester]); + } +} diff --git a/application/controllers/Cis/MyLvPlan.php b/application/controllers/Cis/MyLvPlan.php new file mode 100644 index 000000000..366ce8e65 --- /dev/null +++ b/application/controllers/Cis/MyLvPlan.php @@ -0,0 +1,39 @@ + ['basis/cis:r'] + ]); + + // Load Config + $this->load->config('calendar'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + + $viewData = array( + 'uid'=>getAuthUID(), + 'timezone' => $this->config->item('timezone') + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'MyLvPlan']); + } +} diff --git a/application/controllers/Cis/Profil.php b/application/controllers/Cis/Profil.php new file mode 100644 index 000000000..c287d87d0 --- /dev/null +++ b/application/controllers/Cis/Profil.php @@ -0,0 +1,755 @@ + ['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->library('ProfilLib'); + $profil_data = $this->profillib->getView(getAuthUID()); + $profil_data = hasData($profil_data) ? getData($profil_data) : null; + $viewData = array( + 'editable'=>true, + 'profil_data' => $profil_data, + ); + $this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'profilIndex']); + } + + /** + * redirects to the index function (needed to allow calling this URI) + * @access public + * @return void + */ + public function View($uid) + { + $this->load->library('ProfilLib'); + $profil_data = $this->profillib->getView($uid); + $profil_data = hasData($profil_data) ? getData($profil_data) : null; + $viewData = array ( + 'uid' => $uid, + 'profil_data'=>$profil_data, + ); + if($uid == getAuthUID()){ + $viewData['editable'] = true; + } + $this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'profilViewUid']); + } + + /** + * 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..74641d748 --- /dev/null +++ b/application/controllers/Cis/ProfilUpdate.php @@ -0,0 +1,86 @@ + ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'], + 'show' => ['basis/cis:r'], + 'id' => ['student/stammdaten:r', 'mitarbeiter/stammdaten:r'] + ]); + + $this->load->model('person/Profil_update_model', 'ProfilUpdateModel'); + $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + + // Load language phrases + $this->loadPhrases( + array( + 'profilUpdate' + ) + ); + + $this->load->library('DmsLib'); + $this->load->library('PermissionLib'); + + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + } + + 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 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; + } + } +} 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/Raumsuche.php b/application/controllers/Cis/Raumsuche.php new file mode 100644 index 000000000..055038275 --- /dev/null +++ b/application/controllers/Cis/Raumsuche.php @@ -0,0 +1,35 @@ + ['basis/cis:r'] + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + + $viewData = array( + 'uid'=>getAuthUID(), + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Raumsuche']); + } +} diff --git a/application/controllers/Cis/Studium.php b/application/controllers/Cis/Studium.php new file mode 100644 index 000000000..a298de648 --- /dev/null +++ b/application/controllers/Cis/Studium.php @@ -0,0 +1,40 @@ + ['basis/cis:r'], + + ]); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + + /** + * index loads the Studium view + * @access public + * @return void + */ + public function index() + { + $viewData = array( + + ); + $this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'studium']); + } + + + +} diff --git a/application/controllers/Cis4.php b/application/controllers/Cis4.php new file mode 100644 index 000000000..b7ba2029d --- /dev/null +++ b/application/controllers/Cis4.php @@ -0,0 +1,45 @@ + 'basis/cis:r' + ) + ); + + // Load Config + $this->load->config('calendar'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // 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, + 'timezone' => $this->config->item('timezone') + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'FhcDashboard']); + } +} diff --git a/application/controllers/CisVue/Cms.php b/application/controllers/CisVue/Cms.php new file mode 100644 index 000000000..aa07b919f --- /dev/null +++ b/application/controllers/CisVue/Cms.php @@ -0,0 +1,101 @@ + '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); + + $viewData = array( + 'content_id' => $content_id, + 'template_kurzbz' => $content->template_kurzbz, + 'version' => $version, + 'sichtbar' => $sichtbar + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Content']); + } + + /** + * @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) + { + $viewData = array(); + $this->load->view('CisRouterView/CisRouterView.php', ['viewData'=>$viewData, 'route' => 'News']); + } + + public function getRoomInformation($ort_kurzbz) + { + // Load Config + $this->load->config('calendar'); + + $viewData = array( + 'ort_kurzbz' => $ort_kurzbz, + 'timezone' => $this->config->item('timezone') + ); + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'CmsRoom']); + } +} diff --git a/application/controllers/CisVue/Dashboard.php b/application/controllers/CisVue/Dashboard.php new file mode 100644 index 000000000..ee830cb8b --- /dev/null +++ b/application/controllers/CisVue/Dashboard.php @@ -0,0 +1,43 @@ + 'dashboard/benutzer: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('CisRouterView/CisRouterView.php', ['viewData' => $viewData]); + + } +} \ No newline at end of file diff --git a/application/controllers/Documents.php b/application/controllers/Documents.php new file mode 100644 index 000000000..47aae7ed1 --- /dev/null +++ b/application/controllers/Documents.php @@ -0,0 +1,294 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller handles output and access to documents. + * It creates a XML file, transforms it with the XSL-FO Vorlage from the + * database and generates a PDF file with unoconv or docsbox. + * This file is then outputted as download. + * + * It is the CodeIgniter version of content/pdfExport.php when not using the + * get paremeters: "archivdokument" and "archive". + * Use exportSigned() instead of providing the "sign" get parameter and + * export() otherwise. + */ +class Documents extends Auth_Controller +{ + public function __construct() + { + parent::__construct([ + 'export' => self::PERM_LOGGED, + 'exportSigned' => self::PERM_LOGGED + ]); + + // Load Phrases + $this->loadPhrases([ + 'stv' + ]); + } + + /** + * Download a not signed document. + * + * @param string $xml + * @param string $xsl + * + * @return void + */ + public function export($xml, $xsl) + { + return $this->_export($xml, $xsl); + } + + /** + * Download a signed document. + * + * @param string $xml + * @param string $xsl + * + * @return void + */ + public function exportSigned($xml, $xsl) + { + return $this->_export($xml, $xsl, getAuthUID()); + } + + /** + * Helper function for export() and exportSigned() + * + * @param string $xml + * @param string $xsl + * @param string $sign_user (optional) + * + * @return void + */ + protected function _export($xml, $xsl, $sign_user = null) + { + $xsl_oe_kurzbz = null; + $version = $this->input->post_get('version') ?: null; + + // Get the OE or STG of the document + $xsl_oe_kurzbz = $this->input->post_get('xsl_oe_kurzbz') + ?: $this->input->post_get('xsl_stg_kz') + ?: $this->input->post_get('stg_kz'); + if (is_null($xsl_oe_kurzbz)) { + $uid = $this->input->post_get('uid'); + if ($uid) { + $uid = current(explode(';', $uid)); + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->load([$uid]); + if (!isError($result) && hasData($result)) + $xsl_oe_kurzbz = current(getData($result))->studiengang_kz; + } + } + if (is_null($xsl_oe_kurzbz)) { + $prestudent_id = $this->input->post_get('prestudent_id'); + if ($prestudent_id) { + $prestudent_id = current(explode(';', $prestudent_id)); + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->load($prestudent_id); + if (!isError($result) && hasData($result)) + $xsl_oe_kurzbz = current(getData($result))->studiengang_kz; + } + } + if (is_null($xsl_oe_kurzbz)) + $xsl_oe_kurzbz = 0; + + // Access rights + if ($xsl == 'AccountInfo') { + $this->load->model('resource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $uids = $this->input->post_get('uid'); + if ($uids) { + $uids = explode(';', $uids); + foreach ($uids as $uid) { + $result = $this->MitarbeiterModel->load($uid); + if (!isError($result) && hasData($result)) { + if (!$this->permissionlib->isBerechtigt('admin', 'suid', 0) + && !$this->permissionlib->isBerechtigt('mitarbeiter', 'suid', 0)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'mitarbeiter:rw']]); + } else { + $result = $this->StudentModel->load([$uid]); + if (!isError($result) && hasData($result)) { + $student = current(getData($result)); + if (!$this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz) + && !$this->permissionlib->isBerechtigt('admin', 'suid', 0) + && !$this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz) + && !$this->permissionlib->isBerechtigt('assistenz', 'suid', 0) + && !$this->permissionlib->isBerechtigt('support', 'suid', 0)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw', 'support:rw']]); + } + } + } + } + } else { + $this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); + + $result = $this->VorlagestudiengangModel->getCurrent($xsl, $xsl_oe_kurzbz, $version); + if (isError($result)) + return show_error(getError($result)); + if (!hasData($result)) + return show_404(); + + $access_rights = current(getData($result))->berechtigung; + if (!$access_rights) + return show_404(); + $allowed = false; + foreach ($access_rights as $access_right) { + if ($this->permissionlib->isBerechtigt($access_right)) { + $allowed = true; + break; + } + } + if (!$allowed) + return $this->_outputAuthError([$this->router->method => $access_rights]); + } + + // Output format + $outputformat = $this->input->post_get('output') ?: 'pdf'; + if ($outputformat != 'pdf' + // An der FHTW darf das Studienblatt und das Prüfungsprotokoll auch in anderen Formaten exportiert werden + && !(CAMPUS_NAME == 'FH Technikum Wien' + && ($xsl == 'Studienblatt' + || $xsl == 'StudienblattEng' + || $xsl == 'PrProtBA' + || $xsl == 'PrProtBAEng' + || $xsl == 'PrProtMA' + || $xsl == 'PrProtMAEng' + ) + ) + && !$this->permissionlib->isBerechtigt('system/change_outputformat', null, $xsl_oe_kurzbz) + ) { + $outputformat = 'pdf'; + } + + // XML Params + $params = 'xmlformat=xml'; + foreach ([ + 'uid', + 'stg_kz', + 'person_id', + 'id', + 'prestudent_id', + 'buchungsnummern', + 'ss', + 'abschlusspruefung_id', + 'typ', + 'all', + 'preoutgoing_id', + 'lvid', + 'projekt_kurzbz', + 'von', + 'bis', + 'stundevon', + 'stundebis', + 'sem', + 'lehreinheit', + 'mitarbeiter_uid', + 'studienordnung_id', + 'fixangestellt', + 'standort', + 'abrechnungsmonat', + 'form', + 'projektarbeit_id', + 'betreuerart_kurzbz', + 'studiensemester_kurzbz' + ] as $key) { + $value = $this->input->post_get($key); + if ($value !== null) + $params .= '&' . $key . '=' . urlencode($value); + } + $value = $this->input->post_get('vertrag_id'); + if ($value !== null) { + foreach ($value as $id) + $params .= '&vertrag_id[]=' . urlencode($id); + } + + $this->load->library('DocumentExportLib'); + $this->load->model('system/Vorlage_model', 'VorlageModel'); + + $result = $this->VorlageModel->load($xsl); + if (isError($result)) + return show_error(getError($result)); + if (!hasData($result)) + show_404(); + + $vorlage = current(getData($result)); + if ($sign_user && !$vorlage->signierbar) + return show_error($this->p->t("stv", "grades_error_sign")); + + + // Filename + $filename = ($vorlage->bezeichnung ?: $vorlage->vorlage_kurzbz); + switch ($xsl) { + case 'LV_Informationen': + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $result = $this->StudiengangModel->load($this->input->post_get('stg_kz')); + if (!isError($result) && hasData($result)) + $filename .= '_' . sanitizeProblemChars(current(getData($result))->kurzbzlang); + + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $result = $this->StudiensemesterModel->load($this->input->post_get('ss')); + if (!isError($result) && hasData($result)) + $filename .= '_' . sanitizeProblemChars(current(getData($result))->studiensemester_kurzbz); + break; + case 'Honorarvertrag': + $uid = str_replace(';', '', $this->input->post_get('uid') ?: ''); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->BenutzerModel->addJoin('public.tbl_person', 'person_id', 'LEFT'); + $result = $this->BenutzerModel->load([$uid]); + if (!isError($result) && hasData($result)) { + $user = current(getData($result)); + $filename .= '_' . sanitizeProblemChars($user->nachname) . '_' . sanitizeProblemChars($user->vorname); + } + break; + case 'Studienordnung': + $filename = 'Studienordnung-Studienplan-'; + + $this->load->model('organisation/Studienordnung_model', 'StudienordnungModel'); + $result = $this->StudienordnungModel->load($this->input->post_get('studienordnung_id')); + if (!isError($result) && hasData($result)) { + $so = current(getData($result)); + $filename .= sprintf("%'.04d", $so->studiengang_kz) . '-' . $so->studiengangkurzbzlang; + } + break; + default: + $uid = str_replace(';', '', $this->input->post_get('uid') ?: ''); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->BenutzerModel->addJoin('public.tbl_person', 'person_id', 'LEFT'); + $result = $this->BenutzerModel->load([$uid]); + if (!isError($result) && hasData($result)) { + $user = current(getData($result)); + $filename .= '_' . sanitizeProblemChars($user->nachname); + } + break; + } + + // XML Data + $result = $this->documentexportlib->getDataURL($xml, $params); + if (isError($result)) + return show_error(getError($result)); + + $data = getData($result); + + // Output + $this->documentexportlib->showContent($filename, $vorlage, $data, $xsl_oe_kurzbz, $version, $outputformat, $sign_user); + } +} diff --git a/application/controllers/NeueNachricht.php b/application/controllers/NeueNachricht.php new file mode 100644 index 000000000..9b61b78ef --- /dev/null +++ b/application/controllers/NeueNachricht.php @@ -0,0 +1,30 @@ +method] = ['vertrag/mitarbeiter:r']; + parent::__construct($permissions); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + } + + /** + * @return void + */ + public function _remap() + { + //now working + $this->load->view('Nachrichten', [ + 'permissions' => [ + 'assistenz_schreibrechte' => $this->permissionlib->isBerechtigt('assistenz','suid'), + ] + ]); + } +} diff --git a/application/controllers/Studentenverwaltung.php b/application/controllers/Studentenverwaltung.php new file mode 100644 index 000000000..2ce19c58a --- /dev/null +++ b/application/controllers/Studentenverwaltung.php @@ -0,0 +1,41 @@ +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'), + 'system/change_outputformat' => $this->permissionlib->getOE_isEntitledFor('system/change_outputformat'), + ], + '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/AuthInfo.php b/application/controllers/api/frontend/v1/AuthInfo.php new file mode 100644 index 000000000..72f396b4f --- /dev/null +++ b/application/controllers/api/frontend/v1/AuthInfo.php @@ -0,0 +1,70 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +class AuthInfo extends FHCAPI_Controller +{ + protected $uid; + protected $pid; + protected $isMitarbeiter; + protected $isStudent; + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getAuthUID' => self::PERM_LOGGED, + 'getAuthInfo' => self::PERM_LOGGED, + ]); + + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + $this->isMitarbeiter = getData($this->MitarbeiterModel->isMitarbeiter($this->uid)) ?? false; + $this->isStudent = getData($this->StudentModel->isStudent($this->uid)) ?? false; + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * returns the uid of the currently logged in user + * @access public + * + */ + public function getAuthUID() + { + $this->terminateWithSuccess(['uid'=>$this->uid]); + } + + public function getAuthInfo() + { + $data = (object) array( + 'uid' => $this->uid, + 'isMitarbeiter' => $this->isMitarbeiter, + 'isStudent' => $this->isStudent + ); + $this->terminateWithSuccess($data); + } +} + diff --git a/application/controllers/api/frontend/v1/Bookmark.php b/application/controllers/api/frontend/v1/Bookmark.php new file mode 100644 index 000000000..3e646bb51 --- /dev/null +++ b/application/controllers/api/frontend/v1/Bookmark.php @@ -0,0 +1,138 @@ +. + */ + +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, + 'update' => 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() + { + $this->BookmarkModel->addOrder("bookmark_id"); + $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); + + } + + /** + * updates bookmark in the bookmark table + * @access public + * @return void + */ + public function update($bookmark_id) + { + // 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); + + $now = new DateTime(); + $now = $now->format('Y-m-d H:i:s'); + + $update_result = $this->BookmarkModel->update($bookmark_id,['url'=>$url, 'title'=>$title,'updateamum'=>$now]); + + $update_result = $this->getDataOrTerminateWithError($update_result); + + $this->terminateWithSuccess($update_result); + + } +} + diff --git a/application/controllers/api/frontend/v1/Cis4FhcApi.php b/application/controllers/api/frontend/v1/Cis4FhcApi.php new file mode 100644 index 000000000..372e4bfaa --- /dev/null +++ b/application/controllers/api/frontend/v1/Cis4FhcApi.php @@ -0,0 +1,58 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +class Cis4FhcApi extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getViewData' => self::PERM_LOGGED, + ]); + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * fetches ViewData + */ + public function getViewData() + { + $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->terminateWithSuccess($viewData); + } + + + +} + diff --git a/application/controllers/api/frontend/v1/CisMenu.php b/application/controllers/api/frontend/v1/CisMenu.php new file mode 100644 index 000000000..4f4f2573e --- /dev/null +++ b/application/controllers/api/frontend/v1/CisMenu.php @@ -0,0 +1,58 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + + +class CisMenu extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getMenu' => self::PERM_LOGGED, + ]); + + + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * fetches the menu for CIS from the database based on the userLanguage + */ + public function getMenu() + { + $this->load->model('content/Content_model', 'ContentModel'); + $this->load->config('cis'); + $cis4_content_id =$this->config->item('cis_menu_root_content_id'); + $result = $this->ContentModel->getMenu($cis4_content_id, getAuthUID(),getUserLanguage()); + $result = $this->getDataOrTerminateWithError($result); + $menu = $result->childs ?? []; + $this->terminateWithSuccess($menu); + } + + + +} + diff --git a/application/controllers/api/frontend/v1/Cms.php b/application/controllers/api/frontend/v1/Cms.php new file mode 100644 index 000000000..b8937a1f4 --- /dev/null +++ b/application/controllers/api/frontend/v1/Cms.php @@ -0,0 +1,207 @@ +. + */ + +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); + } + + 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); + // array that keeps track of which news don't have a betreff and have to be removed from the news array + $newsToRemove = array(); + // collect the content of the news + foreach($news as $index=>$news_element){ + + $this->NewsModel->resetQuery(); + $content = $this->cmslib->getContent($news_element->content_id); + if(isError($content)) + { + // removes the news from the news array, so that the response does not include a invalid news + array_push($newsToRemove,$index); + //add the error to the api response? visual feedback + //$this->addError(print_r($content->retval,true)); + continue; + } + $content = getData($content); + $news_element->content_obj = $content; + } + + //removes all news that don't have a betreff + foreach($newsToRemove as $removeNewsIndex) + { + unset($news[$removeNewsIndex]); + } + + $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)); + $sprache = $this->input->get('sprache', true); + if(!$sprache) + { + $sprache = getUserLanguage(); + } + + // 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, $sprache); + $news = $this->getDataOrTerminateWithError($news); + + $this->addMeta('phrases', json_decode($this->p->getJson())); + $this->terminateWithSuccess($news); + + } + + +} + diff --git a/application/controllers/api/frontend/v1/Documents.php b/application/controllers/api/frontend/v1/Documents.php new file mode 100644 index 000000000..2d2c410cf --- /dev/null +++ b/application/controllers/api/frontend/v1/Documents.php @@ -0,0 +1,489 @@ +. + */ + +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 documents + * Listens to ajax post calls to change the documents data + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + * + * This controller handles output and access to documents. + * It checks permissions to render documents in an alternative format + * or it creates a XML file, transforms it with the XSL-FO Vorlage from the + * database and generates a PDF file with unoconv or docsbox. + * This file is then archivated in the database. + * + * The last part is the CodeIgniter version of content/pdfExport.php when not + * using the get paremeter: "archivdokument" but using the get parameter: + * "archive". + * Use archiveSigned() instead of providing the "sign" get parameter and + * archive() otherwise. + */ +class Documents extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'permissionAlternativeFormat' => self::PERM_LOGGED, + 'archive' => ['admin:rw', 'assistenz:rw'], + 'archiveSigned' => ['admin:rw', 'assistenz:rw'], + 'download' => ['admin:rw', 'assistenz:rw'] + ]); + + // Load Phrases + $this->loadPhrases([ + 'stv' + ]); + } + + /** + * Checks if the current user has permission to render documents in an + * alternative format. + * + * @param string $oe_kurzbz Or studiengang_kz + * + * @return void + */ + public function permissionAlternativeFormat($oe_kurzbz) + { + $this->terminateWithSuccess($this->permissionlib->isBerechtigt('system/change_outputformat', null, $oe_kurzbz)); + } + + /** + * Archive a not signed document. + * + * @param string $xml (optional) + * @param string $xsl (optional) + * + * @return void + */ + public function archive($xml = null, $xsl = null) + { + return $this->_archive($xml, $xsl); + } + + /** + * Archive a signed document. + * + * @param string $xml (optional) + * @param string $xsl (optional) + * + * @return void + */ + public function archiveSigned($xml = null, $xsl = null) + { + return $this->_archive($xml, $xsl, getAuthUID()); + } + + /** + * + * @return void + */ + public function download($xml, $xsl, $sign_user = null) + { + $akteExportData = $this->_getAkteExportData($xml, $xsl, $sign_user); + + $akteData = $akteData['akteData']; + $exportData = $akteData['exportData']; + + /** + * [ + 'vorlage' => $vorlage, + 'xml_data' => $data, + 'oe_kurzbz' => $xsl_oe_kurzbz, + 'version' => $version, + 'outputformat' => $outputformat, + 'sign_user' => $sign_user + ] + */ + + // Output + $result = $this->documentexportlib->showContent( + $akteData['akteData']['inhalt'], + $exportData['vorlage'], + $exportData['xml_data'], + $exportData['oe_kurzbz'], + $exportData['version'], + $exportData['outputformat'], + $exportData['sign_user'] + ); + + $this->terminateWithSuccess(true); + } + + /** + * Helper function for archive() and archiveSigned() + * + * @param string $xml + * @param string $xsl + * @param string $sign_user (optional) + * + * @return void + */ + private function _archive($xml, $xsl, $sign_user = null) + { + $akteData = $this->_getAkteExportData($xml, $xsl, $sign_user); + + $this->load->model('crm/Akte_model', 'AkteModel'); + $result = $this->AkteModel->insert($akteData['akteData']); + $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(true); + } + + /** + * @param string $xml + * @param string $xsl + * @param string $sign_user (optional) + * + * @return array with Akte data and export data + */ + private function _getAkteExportData($xml, $xsl, $sign_user = null) + { + if (!$xml || !$xsl) { + $this->load->library('form_validation'); + if (!$xml) { + $xml = $this->input->post_get('xml'); + $this->addMeta('xml', $xml); + $this->form_validation->set_rules('xml', 'xml', 'required'); + } + if (!$xsl) { + $xsl = $this->input->post_get('xsl'); + $this->addMeta('xsl', $xsl); + $this->form_validation->set_rules('xsl', 'xsl', 'required'); + } + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $xsl_oe_kurzbz = null; + $version = $this->input->post_get('version') ?: null; + + // Get the OE or STG of the document + $xsl_oe_kurzbz = $this->input->post_get('xsl_oe_kurzbz') + ?: $this->input->post_get('xsl_stg_kz') + ?: $this->input->post_get('stg_kz'); + if (is_null($xsl_oe_kurzbz)) { + $uid = $this->input->post_get('uid'); + if ($uid) { + $uid = current(explode(';', $uid)); + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->load([$uid]); + if (!isError($result) && hasData($result)) + $xsl_oe_kurzbz = current(getData($result))->studiengang_kz; + } + } + if (is_null($xsl_oe_kurzbz)) { + $prestudent_id = $this->input->post_get('prestudent_id'); + if ($prestudent_id) { + $prestudent_id = current(explode(';', $prestudent_id)); + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->load($prestudent_id); + if (!isError($result) && hasData($result)) + $xsl_oe_kurzbz = current(getData($result))->studiengang_kz; + } + } + if (is_null($xsl_oe_kurzbz)) + $xsl_oe_kurzbz = 0; + + // Vorlage + $this->load->model('system/Vorlage_model', 'VorlageModel'); + + $result = $this->VorlageModel->load($xsl); + $this->addMeta("ress", $result); + $vorlage = current($this->getDataOrTerminateWithError($result)); + if (!$vorlage) + show_404(); + + // Akte Data + $akteData = [ + 'dokument_kurzbz' => $vorlage->dokument_kurzbz ?: 'Zeugnis', + 'mimetype' => 'application/pdf', + 'erstelltam' => date('Y-m-d'), + 'gedruckt' => true, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID(), + 'uid' => $this->input->post_get('uid') ?: '', + 'archiv' => true, + 'signiert' => !!$sign_user, + 'stud_selfservice' => $vorlage->stud_selfservice + ]; + $studiengang_kz = null; + if ($akteData['uid']) { + $this->load->model('crm/Student_model', 'StudentModel'); + $this->StudentModel->addSelect('tbl_student.*, UPPER(typ || kurzbz) AS kuerzel'); + $this->StudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT'); + $result = $this->StudentModel->load([$akteData['uid']]); + $student = current($this->getDataOrTerminateWithError($result)); + + $ss = $this->input->post_get('ss'); + + if ($ss !== null) { + $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel'); + $result = $this->PrestudentstatusModel->getLastStatus($student->prestudent_id, $ss); + $status = current($this->getDataOrTerminateWithError($result)); + if (!$status) + $this->terminateWithError($this->p->t("stv", "grades_error_prestudentstatus")); + $semester = $status->ausbildungssemester; + + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $this->StudentlehrverbandModel->addJoin('public.tbl_benutzer', 'uid = student_uid'); + $this->StudentlehrverbandModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + $result = $this->StudentlehrverbandModel->load([ + 'studiensemester_kurzbz' => $ss, + 'student_uid' => $akteData['uid'] + ]); + $res = current($this->getDataOrTerminateWithError($result)); + + $studiengang_kz = $res->studiengang_kz; + $akteData['person_id'] = $res->person_id; + switch ($xsl) { + case 'Ausbildungsver': + case 'AusbVerEng': + $akteData['titel'] = mb_substr($xsl . + "_" . + strtoupper($res->typ) . + strtoupper($res->kurzbz) . + "_" . + $semester . + "_" . + $ss, 0, 64); + $akteData['bezeichnung'] = mb_substr($vorlage->bezeichnung . " " . $student->kuerzel, 0, 64); + break; + case 'LVZeugnisEng': + case 'LVZeugnis': + case 'Zertifikat': + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $result = $this->LehrveranstaltungModel->load($this->input->post_get('lvid')); + $lv = current($this->getDataOrTerminateWithError($result)); + $akteData['dokument_kurzbz'] = $xsl; + $akteData['titel'] = mb_substr($xsl . + "_" . + strtoupper($res->typ) . + strtoupper($res->kurzbz) . + "_" . + $semester . + '_' . + $ss . + '_' . + str_replace(' ', '_', $lv->bezeichnung), 0, 60); + $akteData['bezeichnung'] = mb_substr($xsl . + " " . + strtoupper($res->typ) . + strtoupper($res->kurzbz) . + " " . + $semester . + ". Semester" . + ' ' . + $ss . + ' ' . + $lv->bezeichnung, 0, 64); + break; + case 'SZeugnis': + $akteData['titel'] = mb_substr($vorlage->bezeichnung . " " . $student->kuerzel, 0, 64); + $akteData['bezeichnung'] = mb_substr($vorlage->bezeichnung . " " . $student->kuerzel, 0, 64); + break; + default: + $akteData['titel'] = mb_substr($xsl . + "_" . + strtoupper($res->typ) . + strtoupper($res->kurzbz) . + "_" . + $semester . + "_" . + $ss, 0, 64); + $akteData['bezeichnung'] = mb_substr($xsl . + " " . + strtoupper($res->typ) . + strtoupper($res->kurzbz) . + " " . + $semester . + ". Semester" . + ' ' . + $ss, 0, 64); + break; + } + } else { + $studiengang_kz = $student->studiengang_kz; + $akteData['person_id'] = $student->person_id; + $akteData['titel'] = $vorlage->bezeichnung . '_' . $student->kuerzel; + $akteData['bezeichnung'] = mb_substr($vorlage->bezeichnung . " " . $student->kuerzel, 0, 64); + } + } else { + $prestudent_id = $this->input->post_get('prestudent_id'); + if ($prestudent_id) { + $this->load->model('crm/prestudent_model', 'PrestudentModel'); + $this->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT'); + $result = $this->PrestudentModel->load($prestudent_id); + $prestudent = current($this->getDataOrTerminateWithError($result)); + + $studiengang_kz = $prestudent->studiengang_kz; + $akteData['person_id'] = $prestudent->person_id; + $akteData['titel'] = mb_substr($xsl . "_" . $prestudent->kuerzel, 0, 64); + $akteData['bezeichnung'] = mb_substr($vorlage->bezeichnung . " " . $prestudent->kuerzel, 0, 64); + } + } + + // Access rights + if (!$this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz) + && !$this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + if ($xsl == 'AccountInfo') { + $this->load->model('resource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $uids = $this->input->post_get('uid'); + if ($uids) { + $uids = explode(';', $uids); + foreach ($uids as $uid) { + $result = $this->MitarbeiterModel->load($uid); + if (!isError($result) && hasData($result)) { + if (!$this->permissionlib->isBerechtigt('admin', 'suid', 0) + && !$this->permissionlib->isBerechtigt('mitarbeiter', 'suid', 0)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'mitarbeiter:rw']]); + } else { + $result = $this->StudentModel->load([$uid]); + if (!isError($result) && hasData($result)) { + $student = current(getData($result)); + if (!$this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz) + && !$this->permissionlib->isBerechtigt('admin', 'suid', 0) + && !$this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz) + && !$this->permissionlib->isBerechtigt('assistenz', 'suid', 0) + && !$this->permissionlib->isBerechtigt('support', 'suid', 0)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw', 'support:rw']]); + } + } + } + } + } else { + $this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); + + $result = $this->VorlagestudiengangModel->getCurrent($xsl, $xsl_oe_kurzbz, $version); + $access_rights = current($this->getDataOrTerminateWithError($result)); + // TODO: was bedeutet wenn keine berechtigung? + if (!$access_rights || !$access_rights->berechtigung) + return show_404(); + + $allowed = false; + foreach ($access_rights->berechtigung as $access_right) { + if ($this->permissionlib->isBerechtigt($access_right)) { + $allowed = true; + break; + } + } + if (!$allowed) + return $this->_outputAuthError([$this->router->method => $access_rights]); + } + + // Output format + $outputformat = $this->input->post_get('output') ?: 'pdf'; + if ($outputformat != 'pdf' + // An der FHTW darf das Studienblatt und das Prüfungsprotokoll auch in anderen Formaten exportiert werden + && !(CAMPUS_NAME == 'FH Technikum Wien' + && ($xsl == 'Studienblatt' + || $xsl == 'StudienblattEng' + || $xsl == 'PrProtBA' + || $xsl == 'PrProtBAEng' + || $xsl == 'PrProtMA' + || $xsl == 'PrProtMAEng' + ) + ) + && !$this->permissionlib->isBerechtigt('system/change_outputformat', null, $xsl_oe_kurzbz) + ) { + $outputformat = 'pdf'; + } + + // XML Params + $params = 'xmlformat=xml'; + foreach ([ + 'uid', + 'stg_kz', + 'person_id', + 'id', + 'prestudent_id', + 'buchungsnummern', + 'ss', + 'abschlusspruefung_id', + 'typ', + 'all', + 'preoutgoing_id', + 'lvid', + 'projekt_kurzbz', + 'von', + 'bis', + 'stundevon', + 'stundebis', + 'sem', + 'lehreinheit', + 'mitarbeiter_uid', + 'studienordnung_id', + 'fixangestellt', + 'standort', + 'abrechnungsmonat', + 'form', + 'projektarbeit_id', + 'betreuerart_kurzbz', + 'studiensemester_kurzbz' + ] as $key) { + $value = $this->input->post_get($key); + if ($value !== null) + $params .= '&' . $key . '=' . urlencode($value); + } + $value = $this->input->post_get('vertrag_id'); + if ($value !== null) { + foreach ($value as $id) + $params .= '&vertrag_id[]=' . urlencode($id); + } + + if (!$vorlage->archivierbar) + $this->terminateWithError($this->p->t("stv", "grades_error_archive")); + + if ($sign_user && !$vorlage->signierbar) + $this->terminateWithError($this->p->t("stv", "grades_error_sign")); + + + $this->load->library('DocumentExportLib'); + + // XML Data + $result = $this->documentexportlib->getDataURL($xml, $params); + $data = $this->getDataOrTerminateWithError($result); + $this->documentexportlib->addArchiveToData($data); + + // Output + $result = $this->documentexportlib->getContent($vorlage, $data, $xsl_oe_kurzbz, $version, $outputformat, $sign_user); + + $content = $this->getDataOrTerminateWithError($result); + $akteData['titel'] .= '.pdf'; + $akteData['inhalt'] = base64_encode($content); + + return [ + 'akteData' => $akteData, + 'exportData' => + [ + 'vorlage' => $vorlage, + 'xml_data' => $data, + 'oe_kurzbz' => $xsl_oe_kurzbz, + 'version' => $version, + 'outputformat' => $outputformat, + 'sign_user' => $sign_user + ] + ]; + } +} diff --git a/application/controllers/api/frontend/v1/Filter.php b/application/controllers/api/frontend/v1/Filter.php new file mode 100644 index 000000000..b195e0012 --- /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/Language.php b/application/controllers/api/frontend/v1/Language.php new file mode 100644 index 000000000..797af4804 --- /dev/null +++ b/application/controllers/api/frontend/v1/Language.php @@ -0,0 +1,47 @@ +. + */ + +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 languages + * This controller works with JSON calls on the HTTP GET and the output is always JSON + */ +class Language extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'get' => self::PERM_LOGGED + ]); + + // Load models + $this->load->model('system/Sprache_model', 'SpracheModel'); + } + + public function get() + { + $this->SpracheModel->addOrder('sprache'); + + $result = $this->SpracheModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} diff --git a/application/controllers/api/frontend/v1/Lehre.php b/application/controllers/api/frontend/v1/Lehre.php new file mode 100644 index 000000000..d5d0282bd --- /dev/null +++ b/application/controllers/api/frontend/v1/Lehre.php @@ -0,0 +1,681 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +//require_once('../../../include/studiengang.class.php'); +//require_once('../../../include/student.class.php'); +//require_once('../../../include/datum.class.php'); +//require_once('../../../include/mail.class.php'); +//require_once('../../../include/benutzerberechtigung.class.php'); +//require_once('../../../include/phrasen.class.php'); +//require_once('../../../include/projektarbeit.class.php'); +//require_once('../../../include/projektbetreuer.class.php'); + +class Lehre extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'lvStudentenMail' => self::PERM_LOGGED, + 'LV' => self::PERM_LOGGED, + 'Pruefungen' => self::PERM_LOGGED, + 'getStudentProjektarbeiten' => self::PERM_LOGGED, // TODO: abgabetool berechtigung? + 'getStudentProjektabgaben' => self::PERM_LOGGED, + 'postStudentProjektarbeitZwischenabgabe' => self::PERM_LOGGED, + 'postStudentProjektarbeitEndupload' => self::PERM_LOGGED, + 'getMitarbeiterProjektarbeiten' => self::PERM_LOGGED, + 'postProjektarbeitAbgabe' => self::PERM_LOGGED, + 'deleteProjektarbeitAbgabe' => self::PERM_LOGGED, + 'postSerientermin' => self::PERM_LOGGED, + 'fetchDeadlines' => self::PERM_LOGGED // TODO: mitarbeiter recht prüfen + ]); + + $this->load->library('PhrasesLib'); + + $this->loadPhrases( + array( + 'global', + 'ui', + 'abgabetool' + ) + ); + + $this->load->helper('hlp_sancho_helper'); + + require_once(FHCPATH . 'include/studiengang.class.php'); + require_once(FHCPATH . 'include/student.class.php'); + require_once(FHCPATH . 'include/projektarbeit.class.php'); + require_once(FHCPATH . 'include/projektbetreuer.class.php'); + } + + //------------------------------------------------------------------------------------------------------------------ + // 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); + } + + /** + * fetches all Pruefungen of a student for a specific lehrveranstaltung + * if the student passed the Pruefung on the first attempt, no information about the Pruefungen is stored in the database + * @param mixed $lehrveranstaltung_id + * @return void + */ + public function Pruefungen($lehrveranstaltung_id) + { + $this->load->model('education/Pruefung_model', 'PruefungModel'); + + $result = $this->PruefungModel->getByStudentAndLv(getAuthUID(), $lehrveranstaltung_id, getUserLanguage()); + + $result = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($result); + } + + /** + * fetches all projektabgabetermine for a given projektarbeit_id used in cis4 student abgabetool + */ + public function getStudentProjektabgaben() { + $projektarbeit_id = $this->input->get("projektarbeit_id",TRUE); + + // TODO: error messages + + if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $projektarbeit_obj = new projektarbeit(); + if($projektarbeit_id==-1) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + if(!$projektarbeit_obj->load($projektarbeit_id)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $paIsCurrent = $projektarbeit_obj->projektarbeitIsCurrent($projektarbeit_id); + + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $ret = $this->ProjektarbeitModel->getProjektarbeitAbgabetermine($projektarbeit_id); + + // TODO: fetch zweitbetreuer + + $this->terminateWithSuccess(array($ret, $paIsCurrent)); + } + + /** + * fetches all projektarbeiten and betreuer for a given student_uid used in cis4 student abgabetool + */ + public function getStudentProjektarbeiten($uid) + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + if (!isset($uid) || isEmptyString($uid)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $isZugeteilterBetreuer = count($this->ProjektarbeitModel->checkZuordnung($uid, getAuthUID())->retval) > 0; + $this->addMeta('isZugeteilterBetreuer', $isZugeteilterBetreuer); + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID()); + + if ($isMitarbeiter && $isZugeteilterBetreuer){ + $projektarbeiten = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer($uid); + } else { + $projektarbeiten = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer(getAuthUID()); + } + + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN, $uid)); + } + + + + /** + * projektarbeit - upload for zwischenabgaben in cis4 student abgabetool + */ + public function postStudentProjektarbeitZwischenabgabe() + { + + $projektarbeit_id = $_POST['projektarbeit_id']; + $paabgabe_id = $_POST['paabgabe_id']; + $student_uid = $_POST['student_uid']; + $bperson_id = $_POST['bperson_id']; + $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; + + if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) + || !isset($paabgabe_id) || isEmptyString($paabgabe_id) + || !isset($student_uid) || isEmptyString($student_uid) + || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + if ((isset($_FILES) and isset($_FILES['file']) and ! $_FILES['file']['error'])) { + move_uploaded_file($_FILES['file']['tmp_name'], PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); + + if(file_exists(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf')) { + + exec('chmod 640 "'.PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'.'"'); + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $res = $this->PaabgabeModel->update($paabgabe_id, array( + 'abgabedatum' => date('Y-m-d'), + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + )); + + $this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid); + $this->terminateWithSuccess($res); + } else { + $this->terminateWithError('Error moving File'); + } + + } else { + $this->terminateWithError('File missing'); + } + + } + + /** + * upload für finale abgaben aka Endupload in cis4 student abgabetool + */ + public function postStudentProjektarbeitEndupload() + { + + $projektarbeit_id = $_POST['projektarbeit_id']; + $paabgabe_id = $_POST['paabgabe_id']; + $student_uid = $_POST['student_uid']; + $sprache = $_POST['sprache']; + $abstract = $_POST['abstract']; + $abstract_en = $_POST['abstract_en']; + $schlagwoerter = $_POST['schlagwoerter']; + $schlagwoerter_en = $_POST['schlagwoerter_en']; + $seitenanzahl = $_POST['seitenanzahl']; + $bperson_id = $_POST['bperson_id']; + $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; + + if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) + || !isset($paabgabe_id) || isEmptyString($paabgabe_id) + || !isset($student_uid) || isEmptyString($student_uid) + || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + // TODO: maybe check for other params aswell? + + if ((isset($_FILES) and isset($_FILES['file']) and ! $_FILES['file']['error'])) { + move_uploaded_file($_FILES['file']['tmp_name'], PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); + + if(file_exists(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf')) { + + // Loads Libraries + $this->load->library('SignatureLib'); + + // Check if the document is signed + $signaturVorhanden = true; + $signList = SignatureLib::list(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); + if (is_array($signList) && count($signList) > 0) + { + // The document is signed + $uploadedDocumentSigned = 'The document is signed'; + } + elseif ($signList === null) + { + $uploadedDocumentSigned = 'WARNING: signature server error'; + } + else + { + $signaturVorhanden = false; + $uploadedDocumentSigned = 'No document signature found'; + } + $this->addMeta('signaturInfo', $uploadedDocumentSigned); + + if ($signaturVorhanden === false) + { + $this->signaturFehltEmail($student_uid); + } + + // TODO error handle get data has data the updates + // update projektarbeit cols + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->ProjektarbeitModel->updateProjektarbeit($projektarbeit_id,$sprache,$abstract,$abstract_en + ,$schlagwoerter, $schlagwoerter_en, $seitenanzahl); + + + // update paabgabe datum + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $res = $this->PaabgabeModel->update($paabgabe_id, array( + 'abgabedatum' => date('Y-m-d'), + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + )); + + $this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid); + + $this->terminateWithSuccess($res); + } else { + $this->terminateWithError('Error moving File'); + } + + } else { + $this->terminateWithError('File missing'); + } + + } + + private function signaturFehltEmail($student_uid) { + + + // Mail an Studiengang wenn keine Signatur gefunden wurde + $student = new student(); + if(!$student->load($student_uid)) + $this->terminateWithError($this->p->t('global','userNichtGefunden'), 'general'); + + $stg_obj = new studiengang(); + if(!$stg_obj->load($student->studiengang_kz)) + $this->terminateWithError($this->p->t('global','fehlerBeimLesenAusDatenbank'), 'general'); + + $subject = 'Abgabe ohne Signatur'; + $tomail = $stg_obj->email; + $data = array( + 'vorname' => $student->vorname, + 'nachname' => $student->nachname, + 'studiengang' => $stg_obj->bezeichnung + ); + + $mailres = sendSanchoMail( + 'ParbeitsbeurteilungSiganturFehlt', + $data, + $tomail, + $subject, + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + ); + } + + private function sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid) { + + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $resBetr = $this->ProjektarbeitModel->getProjektbetreuerAnrede($bperson_id); + + $projektarbeit_obj = new projektarbeit(); + + if(!$projektarbeit_obj->load($projektarbeit_id)) + $this->terminateWithError('Ungueltiger Eintrag'); + + $num_rows_sem = $projektarbeit_obj->projektarbeitIsCurrent($projektarbeit_id); + + if( null === $num_rows_sem || false === $num_rows_sem ) + { + $this->terminateWithError($this->p->t('abgabetool','fehlerAktualitaetProjektarbeit'), 'general'); + } + + foreach($resBetr->retval as $betreuerRow) { + + // query student benutzer view for every betreuer row + $studentUser = $this->ProjektarbeitModel->getProjektarbeitBenutzer($student_uid)->retval[0]; + + // TODO: hasdata, getData etc + + // 1. Begutachter mail ohne Token + $mail_baselink = APP_ROOT."index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/ProjektarbeitsbeurteilungErstbegutachter"; + $mail_fulllink = "$mail_baselink?projektarbeit_id=".$projektarbeit_id."&uid=".$studentUser->uid; + $projekttyp_kurzbz = $projektarbeit_obj->projekttyp_kurzbz; + $subject = $projektarbeit_obj->projekttyp_kurzbz == 'Diplom' ? 'Masterarbeitsbetreuung' : 'Bachelorarbeitsbetreuung'; + $abgabetyp = $paabgabetyp_kurzbz == 'end' ? 'Endabgabe' : 'Zwischenabgabe'; + + $maildata = array(); + $maildata['geehrt'] = "geehrte".($betreuerRow->anrede=="Herr"?"r":""); + $maildata['anrede'] = $betreuerRow->anrede; + $maildata['betreuer_voller_name'] = $betreuerRow->first; + $maildata['student_anrede'] = $studentUser->anrede; + $maildata['student_voller_name'] = trim($studentUser->titelpre." ".$studentUser->vorname." ".$studentUser->nachname." ".$studentUser->titelpost); + $maildata['abgabetyp'] = $abgabetyp; + $maildata['parbeituebersichtlink'] = "

Zur Projektarbeitsübersicht

"; + $maildata['bewertunglink'] = $num_rows_sem >= 1 && $paabgabetyp_kurzbz == 'end' ? "

Zur Beurteilung der Arbeit

" : ""; + $maildata['token'] = ""; + + $mailres = sendSanchoMail( + 'ParbeitsbeurteilungEndupload', + $maildata, + $betreuerRow->mitarbeiter_uid."@".DOMAIN, + $subject, + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg', + get_uid()."@".DOMAIN); + + if(!$mailres) + { + $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); + } + + // 2. Begutachter mail, wenn Endabgabe, mit Token wenn extern + if ($paabgabetyp_kurzbz == 'end') + { + // Zweitbegutachter holen + $zweitbegutachter = new projektbetreuer(); + $zweitbegutachterRes = $zweitbegutachter->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid); + + if ($zweitbegutachterRes) + { + $zweitbegutachterResults = $zweitbegutachter->result; + + foreach ($zweitbegutachterResults as $begutachter) + { + // token generieren, wenn noch nicht vorhanden und notwendig (wird in methode überprüft) + $tokenGenRes = $zweitbegutachter->generateZweitbegutachterToken($begutachter->person_id, $projektarbeit_id); + + if (!$tokenGenRes) + { + $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailZweitBegutachter'), 'general'); + } + + // Zweitbegutachter (evtl. mit Token) holen + $zweitbegutachterMitToken = new projektbetreuer(); + $begutachterMitTokenRes = $zweitbegutachterMitToken->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid, $begutachter->person_id); + + if (!$begutachterMitTokenRes) + { + $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailZweitBegutachter'), 'general'); + } + + // Email an Zweitbegutachter senden + if (isset($zweitbegutachterMitToken->result[0])) + { + $begutachterMitToken = $zweitbegutachterMitToken->result[0]; + + $path = $begutachterMitToken->betreuerart_kurzbz == 'Zweitbegutachter' ? 'ProjektarbeitsbeurteilungZweitbegutachter' : 'ProjektarbeitsbeurteilungErstbegutachter'; + $mail_baselink = APP_ROOT."index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/$path"; + $mail_fulllink = "$mail_baselink?projektarbeit_id=".$projektarbeit_id."&uid=".$studentUser->uid; + $intern = isset($begutachterMitToken->uid); + $mail_link = $intern ? $mail_fulllink : $mail_baselink; + + $zweitbetmaildata = array(); + $zweitbetmaildata['geehrt'] = "geehrte" . ($begutachterMitToken->anrede == "Herr" ? "r" : ""); + $zweitbetmaildata['anrede'] = $begutachterMitToken->anrede; + $zweitbetmaildata['betreuer_voller_name'] = $begutachterMitToken->voller_name; + $zweitbetmaildata['student_anrede'] = $maildata['student_anrede']; + $zweitbetmaildata['student_voller_name'] = $maildata['student_voller_name']; + $zweitbetmaildata['abgabetyp'] = $abgabetyp; + $zweitbetmaildata['parbeituebersichtlink'] = $intern ? $maildata['parbeituebersichtlink'] : ""; + $zweitbetmaildata['bewertunglink'] = $num_rows_sem >= 1 ? "

Zur Beurteilung der Arbeit

" : ""; + $zweitbetmaildata['token'] = $num_rows_sem >= 1 && isset($begutachterMitToken->zugangstoken) && !$intern ? "

Zugangstoken: " . $begutachterMitToken->zugangstoken . "

" : ""; + + $mailres = sendSanchoMail( + 'ParbeitsbeurteilungEndupload', + $zweitbetmaildata, + $begutachterMitToken->email, + $subject, + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg', + get_uid()."@".DOMAIN + ); + + if (!$mailres) + { + $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); + } + } + } + } + } + } + } + + public function getMitarbeiterProjektarbeiten() { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $boolParamStr = $this->input->get('showall'); + $trueStrings = ['true', '1']; + $falseStrings = ['false', '0']; + + // Handle missing or invalid parameter + if ($boolParamStr === null) { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + $boolParamStrLower = strtolower($boolParamStr); + + if (in_array($boolParamStrLower, $trueStrings, true)) { + $showAllBool = true; + } elseif (in_array($boolParamStrLower, $falseStrings, true)) { + $showAllBool = false; + } else { +// $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $projektarbeiten = $this->ProjektarbeitModel->getMitarbeiterProjektarbeiten(getAuthUID(), $showAllBool); + + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN)); + } + + public function postProjektarbeitAbgabe() { + $projektarbeit_id = $_POST['projektarbeit_id']; + $paabgabe_id = $_POST['paabgabe_id']; + $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; + $datum = $_POST['datum']; + $fixtermin = $_POST['fixtermin']; + $kurzbz = $_POST['kurzbz']; + + if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) + || !isset($paabgabe_id) || isEmptyString($paabgabe_id) + || !isset($datum) || isEmptyString($datum) + || !isset($datum) || isEmptyString($datum) + || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + + if($paabgabe_id == -1) { + $result = $this->PaabgabeModel->insert( + array( + 'projektarbeit_id' => $projektarbeit_id, + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'fixtermin' => $fixtermin, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'insertvon' => getAuthUID(), + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + + $this->terminateWithSuccess($result); + } else { + $result = $this->PaabgabeModel->update( + $paabgabe_id, + array( + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + ) + ); + + $this->terminateWithSuccess($result); + } + } + + public function deleteProjektarbeitAbgabe() { + $paabgabe_id = $_POST['paabgabe_id']; + + if (!isset($paabgabe_id) || isEmptyString($paabgabe_id)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + + $result = $this->PaabgabeModel->load($paabgabe_id); + $result = $this->getDataOrTerminateWithError($result); + + if(count($result) == 0) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + // TODO: berechtigung? + if($result[0]->insertvon === getAuthUID()) { + $result = $this->PaabgabeModel->delete($paabgabe_id); + $result = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($result); + } + + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + /** + * endpoint for adding the same paabgabe for multiple projektarbeiten + * can be slow for large n since it queries twice per projektarbeit_id + */ + public function postSerientermin() { + $projektarbeit_ids = $_POST['projektarbeit_ids']; + $datum = $_POST['datum']; + $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; + $bezeichnung = $_POST['bezeichnung']; + $kurzbz = $_POST['kurzbz']; + + if (!isset($projektarbeit_ids) || !is_array($projektarbeit_ids) || empty($projektarbeit_ids) + || !isset($datum) || isEmptyString($datum) + || !isset($kurzbz) || isEmptyString($kurzbz) + || !isset($bezeichnung) || isEmptyString($bezeichnung) + || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + // old script checks if there already are tbl_paabgabe entries with exact date, type & kurzbz + // for each termin - good to check that in principle but should not matter in this place. if necessary + // duplicate abgabetermine can be easily deleted manually, also via cronjob@night. + + // since this entry includes the kurzbz string match, it should have only ever mattered when there were + // multiple users entering the exact same set of (date, type, kurzbz) - which is a much more narrow case than the + // general "saveMultiple" function should handle + + // old script afterwards again queries if user is not the zweitbetreuer of any id - this is blocked in the ui + // and should never unintentionally happen + + // TODO: check berechtigung &/|| zuordnung? + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $res = []; + foreach ($projektarbeit_ids as $projektarbeit_id) { + + $result = $this->PaabgabeModel->insert( + array( + 'projektarbeit_id' => $projektarbeit_id, + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'fixtermin' => false, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'insertvon' => getAuthUID(), + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + +// $res[] = $data; + + // send mail to student + $result = $this->ProjektarbeitModel->getStudentInfoForProjektarbeitId($projektarbeit_id); + $data = $this->getDataOrTerminateWithError($result); + +// $this->addMeta('emaildata'.$projektarbeit_id, $data); + + $datetime = new DateTime($datum); + $dateEmailFormatted = $datetime->format('d.m.Y'); + + $anredeFillString = $data[0]->anrede=="Herr"?"r":""; + + $fullFormattedNameString = trim($data[0]->titelpre." ".$data[0]->vorname." ".$data[0]->nachname." ".$data[0]->titelpost); + $res[] = $fullFormattedNameString; + + // Prepare mail content + $body_fields = array( + 'anrede' => $data[0]->anrede, + 'anredeFillString' => $anredeFillString, + 'datum' => $dateEmailFormatted, + 'bezeichnung' => $bezeichnung, + 'fullFormattedNameString' => $fullFormattedNameString, + 'kurzbz' => $kurzbz + ); + + $email = $data[0]->uid."@".DOMAIN; + + sendSanchoMail( + 'neuerAbgabetermin', + $body_fields, + $email, + $this->p->t('abgabetool', 'neuerTerminBachelorMasterbetreuung') + ); + } + + $this->terminateWithSuccess($res); + + } + + public function fetchDeadlines() { + $person_id = $_POST['person_id']; + + if (!isset($person_id) || isEmptyString($person_id)) + $person_id = getAuthPersonId(); + + + if($person_id !== getAuthPersonId()) { + $this->load->library('PermissionLib'); + $isAdmin = $this->permissionlib->isBerechtigt('admin'); + if(!$isAdmin) $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'), 'general'); + } + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $result = $this->PaabgabeModel->getDeadlines($person_id); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} + diff --git a/application/controllers/api/frontend/v1/LvMenu.php b/application/controllers/api/frontend/v1/LvMenu.php new file mode 100644 index 000000000..45936d9f5 --- /dev/null +++ b/application/controllers/api/frontend/v1/LvMenu.php @@ -0,0 +1,544 @@ +. + */ + +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", null, 'PhrasesLib'); + $this->loadPhrases(array('global', 'lehre')); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + + /** + * alternative function to get multiple lvMenus with a single http request + */ + public function getMultipleLvMenu($lvMenuOptionList){ + $result =[]; + foreach($lvMenuOptionList as $lvMenuOptions){ + $lvMenu = $this->getLvMenu($lvMenuOptions['lvid'],$lvMenuOptions['studiensemester_kurzbz']); + if(isError($lvMenu)){ + // TODO: some lvMenu threw an error, handle error here + } + $result[$lvMenuOptions['lvid']]=$lvMenu; + } + $this->terminateWithSuccess($result); + } + + /** + * + */ + 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]; + $this->addMeta('lvInfo',$lv); + // define studiengang_kz / semester / lehrverzeichnis + $studiengang_kz = $lv->studiengang_kz; + $semester = $lv->semester; + $short = $lv->lehreverzeichnis; + // return empty menu for studiengang_kz = 0 + if($studiengang_kz == 0){ + $this->terminateWithSuccess("organisatorische_einheit"); + } + + // load studiengang + $stgres = $this->Studiengang_model->load(strval($studiengang_kz)); + if(!hasData($stgres)) + { + $this->terminateWithError('Stg ' . $lv->studiengang_kz . ' not 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, + 'permissionLib' => &$this->PermissionLib, + 'phrasesLib' => &$this->PhrasesLib + ]; + + 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_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'), + 'phrase' => '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'), + 'phrase' => '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'), + 'phrase' => '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'), + 'phrase'=>'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'), + 'phrase' => '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'), + 'phrase'=>'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'), + 'phrase' => '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'), + 'phrase' => '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/ReviewAnrechnungUebersicht?studiensemester='.urlencode($angezeigtes_stsem)) + ); + } + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/LvPlan.php b/application/controllers/api/frontend/v1/LvPlan.php new file mode 100644 index 000000000..28b48e3f1 --- /dev/null +++ b/application/controllers/api/frontend/v1/LvPlan.php @@ -0,0 +1,363 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use CI3_Events as Events; +use \DateTime as DateTime; +use \DateTimeZone as DateTimeZone; + +class LvPlan extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + + parent::__construct([ + 'getRoomplan' => self::PERM_LOGGED, + 'Stunden' => self::PERM_LOGGED, + 'getReservierungen' => self::PERM_LOGGED, + 'LvPlanEvents' => self::PERM_LOGGED, + 'eventsPersonal' => self::PERM_LOGGED, + 'eventsLv' => self::PERM_LOGGED, + 'getLehreinheitStudiensemester' => self::PERM_LOGGED, + 'studiensemesterDateInterval' => self::PERM_LOGGED, + 'getLvPlanForStudiensemester' => self::PERM_LOGGED, + 'getLv' => 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'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * fetches LvPlan and Moodle events together + * @access public + * + */ + public function LvPlanEvents() + { + $hasLv = $this->input->post('lv_id'); + + return $hasLv ? $this->eventsLv() : $this->eventsPersonal(); + } + + /** + * fetches LvPlan, Moodle and Ferien events together for the logged in user + * + * @access public + */ + public function eventsPersonal() + { + $this->load->library('StundenplanLib'); + + // form validation + $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()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // storing the post parameter in local variables + $start_date = $this->input->post('start_date', true); + $end_date = $this->input->post('end_date', true); + + // fetching lvplan events + $result = $this->stundenplanlib->getEventsUser($start_date, $end_date); + $lvplanEvents = $this->getDataOrTerminateWithError($result); + + // fetching moodle events + $moodleEvents = $this->fetchMoodleEvents($start_date, $end_date); + + // fetching ferien events + $ferienEvents = $this->fetchFerienEvents($start_date, $end_date); + + + $this->terminateWithSuccess(array_merge( + $lvplanEvents, + $moodleEvents, + $ferienEvents + )); + } + + /** + * fetches LvPlan and Ferien events together for the lv + * + * @access public + */ + public function eventsLv() + { + $this->load->library('StundenplanLib'); + + // form validation + $this->form_validation->set_rules('start_date', "start_date", "required"); + $this->form_validation->set_rules('end_date', "end_date", "required"); + $this->form_validation->set_rules('lv_id', "lv_id", "required|integer"); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // storing the post parameter in local variables + $start_date = $this->input->post('start_date', true); + $end_date = $this->input->post('end_date', true); + $lv_id = $this->input->post('lv_id', true); + + // fetching lvplan events + $result = $this->stundenplanlib->getEventsLv($lv_id, $start_date, $end_date); + $lvplanEvents = $this->getDataOrTerminateWithError($result); + + // fetching ferien events + $ferienEvents = $this->fetchFerienEvents($start_date, $end_date); + + + $this->terminateWithSuccess(array_merge( + $lvplanEvents, + $ferienEvents + )); + } + + //TODO: delete this function if we don't use the old calendar export endpoints anymore + public function studiensemesterDateInterval($date){ + $this->load->model('organisation/Studiensemester_model','StudiensemesterModel'); + $studiensemester =$this->StudiensemesterModel->getByDate(date_format(date_create($date),'Y-m-d')); + $studiensemester =current($this->getDataOrTerminateWithError($studiensemester)); + $this->terminateWithSuccess($studiensemester); + } + + public function getLvPlanForStudiensemester($studiensemester,$lvid){ + $this->load->library('StundenplanLib'); + $this->load->model('organisation/Studiensemester_model','StudiensemesterModel'); + + $studiensemester_result = $this->StudiensemesterModel->loadWhere(["studiensemester_kurzbz"=>$studiensemester]); + $studiensemester_result = current($this->getDataOrTerminateWithError($studiensemester_result)); + $timespan_start = new DateTime($studiensemester_result->start); + $timespan_ende = new DateTime($studiensemester_result->ende); + $lvplan = $this->stundenplanlib->getStundenplan(date_format($timespan_start, 'Y-m-d'),date_format($timespan_ende, 'Y-m-d'), $lvid); + $this->terminateWithSuccess($lvplan); + + } + + + /** + * fetches Stunden layout from database + * @access public + * + */ + public function Stunden() + { + $this->load->model('ressource/Stunde_model', 'StundeModel'); + + $this->StundeModel->addOrder('stunde', 'ASC'); + $stunden = $this->StundeModel->load(); + + $stunden = $this->getDataOrTerminateWithError($stunden); + + $this->terminateWithSuccess($stunden); + } + + /** + * fetches room events from a certain date + * @access public + * + * @return void + */ + public function getRoomplan() + { + $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()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // storing the post parameter in local variables + $ort_kurzbz = $this->input->post('ort_kurzbz', true); + $start_date = $this->input->post('start_date', true); + $end_date = $this->input->post('end_date', true); + + // get data + $this->load->library('StundenplanLib'); + + $roomplan_data = $this->stundenplanlib->getRoomplan($ort_kurzbz, $start_date, $end_date); + + $roomplan_data = $this->getDataOrTerminateWithError($roomplan_data); + + $this->terminateWithSuccess($roomplan_data); + } + + /** + * gets the reservierungen of a room if the ort_kurzbz parameter is + * supplied otherwise gets the reservierungen of the lvplan of a student + * @access public + * + * @param string $ort_kurzbz + * @return void + */ + public function getReservierungen($ort_kurzbz = null) + { + $this->form_validation->set_rules('start_date', "StartDate", "required"); + $this->form_validation->set_rules('end_date', "EndDate", "required"); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // storing the post parameter in local variables + $start_date = $this->input->post('start_date', true); + $end_date = $this->input->post('end_date', true); + + // get data + $this->load->library('StundenplanLib'); + + $result = $this->stundenplanlib->getReservierungen($start_date, $end_date, $ort_kurzbz); + + $result = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($result); + } + + 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); + } + + /** + * get details for a lv + * @access public + * + * @param integer $lehrveranstaltung_id + * @return void + */ + public function getLv($lehrveranstaltung_id) + { + if (!$lehrveranstaltung_id && $lehrveranstaltung_id !== 0 && $lehrveranstaltung_id !== '0') + return show_404(); + + // Load Phrases + $this->loadPhrases(['lehre']); + + // Validation + $this->form_validation->set_data([ + 'lehrveranstaltung_id' => $lehrveranstaltung_id + ]); + + $this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung_id'), 'integer'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // Get Data + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id); + + $result = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess(current($result)); + } + + /** + * fetch moodle events + * + * @param string $start_date + * @param string $end_date + * @return array + */ + private function fetchMoodleEvents($start_date, $end_date) + { + $this->load->config('calendar'); + + $tz = new DateTimeZone($this->config->item('timezone')); + + $start = new DateTime($start_date); + $start->setTimezone($tz); + + $end = new DateTime($end_date); + $end->setTimezone($tz); + $end->modify('+1 day -1 second'); + + $moodle_events = []; + + Events::trigger( + 'moodleCalendarEvents', + function & () use (&$moodle_events) { + return $moodle_events; + }, + [ + 'start_date' => $start->format('c'), + 'end_date' => $end->format('c'), + 'username' => getAuthUID() + ] + ); + + return $moodle_events; + } + + /** + * fetch ferien events + * + * @param string $start_date + * @param string $end_date + * @return array + */ + private function fetchFerienEvents($start_date, $end_date) + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('education/Studentlehrverband_model', 'StudentLehrverbandModel'); + + $currentStudiensemester = $this->StudiensemesterModel->getByDate($start_date); + $currentStudiensemester = $this->getDataOrTerminateWithError($currentStudiensemester); + + if ($currentStudiensemester) { + $studentsemester_kurzbz = current($currentStudiensemester)->studiensemester_kurzbz; + + $studiengang = $this->StudentLehrverbandModel->loadWhere([ + "student_uid" => getAuthUID(), + "studiensemester_kurzbz" => $studentsemester_kurzbz + ]); + $studiengang = $this->getDataOrTerminateWithError($studiengang); + + if ($studiengang) + $studiengang_kz = current($studiengang)->studiengang_kz; + else + $studiengang_kz = 0; + } else { + $studiengang_kz = 0; + } + + $ferienEvents = $this->stundenplanlib->fetchFerienTageEvents($start_date, $end_date, $studiengang_kz); + + return $this->getDataOrTerminateWithError($ferienEvents); + } +} 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..0d8074fa9 --- /dev/null +++ b/application/controllers/api/frontend/v1/Ort.php @@ -0,0 +1,178 @@ +. + */ + +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, + 'getRooms' => self::PERM_LOGGED, + 'getTypes' => self::PERM_LOGGED + ]); + + $this->load->model('ressource/Ort_model', 'OrtModel'); + $this->config->load('raumsuche'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Retrieves all Ort entries filtered by the provided parameters + */ + public function getRooms() + { + $this->load->library('form_validation'); + $this->form_validation->set_data($_GET); + $this->form_validation->set_rules('datum','Datum','required'); + $this->form_validation->set_rules('von','Uhrzeit Von','required|regex_match[/^[0-9]{2}:[0-9]{2}$/]'); + $this->form_validation->set_rules('bis','Uhrzeit Bis','required|regex_match[/^[0-9]{2}:[0-9]{2}$/]'); + if($this->form_validation->run() == FALSE) { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $datum = $this->input->get('datum', TRUE); + $von = $this->input->get('von', TRUE); + $bis = $this->input->get('bis', TRUE); + $typ = $this->input->get('typ', TRUE); + $personenanzahl = $this->input->get('personenanzahl', TRUE); + + + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID())->retval; + + $this->load->model('ressource/Stunde_model', 'StundeModel'); + $vonStunde = getData($this->StundeModel->getStundeForTime($von))[0]->stunde; + $bisStunde = getData($this->StundeModel->getStundeForTime($bis))[0]->stunde; + + $params = array(); + $qry = "SELECT DISTINCT tbl_ort.* + FROM public.tbl_ort JOIN public.tbl_ortraumtyp USING(ort_kurzbz) + WHERE aktiv AND lehre AND ort_kurzbz NOT LIKE '\\\\_%'"; + if($typ) { + $params[] = $typ; + $qry.= "AND raumtyp_kurzbz = ?"; + } + + if(!$isMitarbeiter) { // students are only allowed to get a subset defined by config + $qry.= ' AND raumtyp_kurzbz IN ?'; + $params[] = $this->config->item('roomtypes_student'); + $this->addMeta('config', $this->config->item('roomtypes_student')); + } + + $qry.= "AND (max_person>= ? OR max_person is null)"; + $params[] = $personenanzahl; + + $qry.=" AND ort_kurzbz NOT IN + ( + SELECT ort_kurzbz FROM lehre.tbl_stundenplandev WHERE datum = ? AND stunde >= ? AND stunde <= ? + UNION + SELECT ort_kurzbz FROM campus.tbl_reservierung WHERE datum= ? AND stunde >= ? AND stunde <= ? + ) + "; + $params = array_merge($params, [$datum, $vonStunde, $bisStunde, $datum, $vonStunde, $bisStunde]); +// $this->addMeta('qry', $qry); +// $this->addMeta('params', $params); + $result = $this->OrtModel->execReadOnlyQuery($qry, $params); + + $this->terminateWithSuccess($result); + } + + public function getTypes() + { + $this->load->model('ressource/Raumtyp_model', 'RaumtypModel'); + $qry = "SELECT * FROM public.tbl_raumtyp WHERE aktiv = true"; + $params = array(); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID())->retval; + if(!$isMitarbeiter) { // students are only allowed to get a subset defined by config + $qry.= ' AND raumtyp_kurzbz IN ?'; + $params[] = $this->config->item('roomtypes_student'); + } + + $qry .= " ORDER BY raumtyp_kurzbz;"; + + $result = $this->OrtModel->execReadOnlyQuery($qry, $params); + + $this->terminateWithSuccess(getData($result)); + } + + /** + * 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..7cc652c71 --- /dev/null +++ b/application/controllers/api/frontend/v1/Phrasen.php @@ -0,0 +1,95 @@ +. + */ + +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() + { + $this->load->model('system/Sprache_model', 'SprachenModel'); + + // Add order clause by index and select the sprache,bezeichnung and index column + $this->SprachenModel->addOrder('index'); + $this->SprachenModel->addSelect('sprache, bezeichnung, index'); + + // Retrieves from public.tbl_sprache + $langs = $this->SprachenModel->loadWhere(array('content' => true)); + $langs = $this->getDataOrTerminateWithError($langs); + $langs = array_map(function($lang){ + $data = new stdClass(); + $data->sprache = $lang->sprache; + $data->bezeichnung = $lang->bezeichnung[($lang->index-1)]; + return $data; + }, $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..3133b107a --- /dev/null +++ b/application/controllers/api/frontend/v1/Profil.php @@ -0,0 +1,172 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +class Profil extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'fotoSperre' => self::PERM_LOGGED, + 'getGemeinden' => self::PERM_LOGGED, + 'getAllNationen' => self::PERM_LOGGED, + 'isMitarbeiter' => self::PERM_LOGGED, + 'profilViewData' => self::PERM_LOGGED, + ]); + + $this->load->library('PermissionLib'); + + $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('person/Person_model', 'PersonModel'); + + + //? put the uid and pid inside the controller for reusability + $this->uid = getAuthUID(); + $this->pid = getAuthPersonID(); + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + public function profilViewData($uid=null){ + $this->load->library('ProfilLib'); + $editable = false; + if(isset($uid) && $uid != null){ + $profil_data = $this->profillib->getView($uid); + if($uid == getAuthUID()){ + $editable = true; + } + }else{ + $editable = true; + $profil_data = $this->profillib->getView(getAuthUID()); + } + + $profil_data = hasData($profil_data) ? getData($profil_data) : null; + $viewData = array( + 'editable'=>$editable, + 'profil_data' => $profil_data, + ); + $this->terminateWithSuccess($viewData); + } + + /** + * 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)) { + $this->terminateWithError("error while trying to update table public.tbl_person"); + } + $this->PersonModel->addSelect("foto_sperre"); + $res = $this->PersonModel->load($this->pid); + + $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); + + } + + + /** + * 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); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Private methods + + +} + diff --git a/application/controllers/api/frontend/v1/ProfilUpdate.php b/application/controllers/api/frontend/v1/ProfilUpdate.php new file mode 100644 index 000000000..bbfed651c --- /dev/null +++ b/application/controllers/api/frontend/v1/ProfilUpdate.php @@ -0,0 +1,930 @@ +. + */ + +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, + 'updateProfilbild' => 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 updateProfilbild() + { + + $resize = function($filename, $width, $height){ + // Hoehe und Breite neu berechnen + list($width_orig, $height_orig) = getimagesize($filename); + + if ($width && ($width_orig < $height_orig)) + { + $width = ($height / $height_orig) * $width_orig; + } + else + { + $height = ($width / $width_orig) * $height_orig; + } + + $image_p = imagecreatetruecolor($width, $height); + + $image = imagecreatefromjpeg($filename); + + //Bild nur verkleinern aber nicht vergroessern + if($width_orig>$width || $height_orig>$height) + imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig); + else + $image_p = $image; + + imagejpeg($image_p, $filename, 80); + + @imagedestroy($image_p); + @imagedestroy($image); + }; + + if (!count($_FILES)) { + $this->terminateWithError("No file available for upload"); + } + + $files = $_FILES['files']; + + $_FILES['files']['name'] = current($files['name']); + $_FILES['files']['type'] = current($files['type']); + $_FILES['files']['tmp_name'] = current($files['tmp_name']); + $_FILES['files']['error'] = current($files['error']); + $_FILES['files']['size'] = current($files['size']); + $_FILES['files']['tmp_name'] = current($files['tmp_name']); + + $filename = $_FILES['files']['tmp_name']; + + $ext = substr(current($files['name']), strrpos(current($files['name']), '.') + 1); + if($ext!='jpg' && $ext!='jpeg'){ + $this->terminateWithError("Only jpg and jpeg files are allowed for profilbild upload"); + } + + // resize + $resize($filename, 827, 1063); + + //akte + $fp = fopen($filename,'r'); + //auslesen + $content = fread($fp, filesize($filename)); + $base64_content = base64_encode($content); + $this->load->library('AkteLib'); + $aktenInsertResult = $this->aktelib->add($this->pid,'Lichtbil',"Lichtbild_".$this->pid.".jpg","image/jpg",$fp,"Lichtbild gross"); + fclose($fp); + if (isError($aktenInsertResult)) { + $this->terminateWithError(getError($aktenInsertResult)); + } + + // in person abspeichern + $resize($filename, 101, 130); + $fp = fopen($filename,'r'); + $content = fread($fp, filesize($filename)); + fclose($fp); + $base64_content = base64_encode($content); + $this->load->model('person/Person_model','PersonModel'); + $personUpdate = $this->PersonModel->update($this->pid, ["foto"=>$base64_content]); + if(isError($personUpdate)){ + $this->terminateWithError(getError($personUpdate)); + } + + + // update foto status + $this->load->model('person/Fotostatusperson_model','FotostatusModel'); + $fotoInsert = $this->FotostatusModel->insert(["person_id"=>$this->pid,"fotostatus_kurzbz"=>"hochgeladen","datum"=>date('Y-m-d'),"insertamum"=>date('Y-m-d H:i:s'),"insertvon"=>$this->uid,"updateamum"=>date('Y-m-d H:i:s'),"updatevon"=>$this->uid]); + if(isError($fotoInsert)){ + $this->terminateWithError(getError($fotoInsert)); + } + + $this->terminateWithSuccess(); + } + + public function getProfilUpdateWithPermission($status = null) + { + // early return if no status has been passed as argument + if (!isset($status)) { + $this->terminateWithSuccess($this->ProfilUpdateModel->getProfilUpdateWithPermission()); + } + + // 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); + + $this->terminateWithSuccess($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"); + $this->StudentModel->addGroupBy(["public.tbl_studiengang.email"]); + //* 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) + { + $href = $this->config->item('cis_vilesci_base_url') . $this->config->item('cis_vilesci_index_page') . '/Cis/ProfilUpdate/id/' . $profil_update_id; + array_push($mail_res, sendSanchoMail("profil_update", ['uid' => $uid, 'topic' => $topic, 'href' => $href], $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)) + { + $href = $this->config->item('cis_base_url') . $this->config->item('cis_index_page') . '/Cis/Profil'; + $mail_res = sendSanchoMail("profil_update_response", ['topic' => $topic, 'status_de' => $status_translation->status_de, 'status_en' => $status_translation->status_en, 'href' => $href], $email, ("Profil Änderung " . $status_translation->status_de . ' / Profile Update ' . $status_translation->status_en)); + 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/RendererLoader.php b/application/controllers/api/frontend/v1/RendererLoader.php new file mode 100644 index 000000000..dc16bb3fc --- /dev/null +++ b/application/controllers/api/frontend/v1/RendererLoader.php @@ -0,0 +1,72 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use CI3_Events as Events; + +class RendererLoader extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + + parent::__construct([ + 'GetRenderers' => self::PERM_LOGGED, + + ]); + + $this->load->library('LogLib'); + $this->loglib->setConfigs(array( + 'classIndex' => 5, + 'functionIndex' => 5, + 'lineIndex' => 4, + 'dbLogType' => 'API', // required + 'dbExecuteUser' => 'RESTful API' + )); + + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * fetches Stundenplan and Moodle events together + * @access public + * + */ + public function GetRenderers(){ + $renderer_paths = []; + Events::trigger( + 'loadRenderers', + function & () use (&$renderer_paths) + { + return $renderer_paths; + } + ); + $this->terminateWithSuccess($renderer_paths); + } + + + + +} diff --git a/application/controllers/api/frontend/v1/RouteInfo.php b/application/controllers/api/frontend/v1/RouteInfo.php new file mode 100644 index 000000000..78db3ba2c --- /dev/null +++ b/application/controllers/api/frontend/v1/RouteInfo.php @@ -0,0 +1,60 @@ +. + */ +if (!defined('BASEPATH')) + exit('No direct script access allowed'); + +class RouteInfo extends FHCAPI_Controller +{ + + public function __construct() + { + parent::__construct([ + 'info' => self::PERM_LOGGED, + ]); + + $this->load->model('system/Webservicelog_model', 'WebservicelogModel'); + } + + public function info() + { + $payload = json_decode($this->input->raw_input_stream); + + if (isset($payload->app) && isset($payload->path) && $this->isValidApp($payload->app) && $this->isValidPath($payload->path)) + { + $this->WebservicelogModel->insert(array( + 'webservicetyp_kurzbz' => 'content', + 'beschreibung' => $payload->app, + 'request_data' => $payload->path, + 'execute_user' => getAuthUID(), + 'execute_time' => 'NOW()' + )); + } + $this->terminateWithSuccess(true); + } + + protected function isValidApp($app) + { + return preg_match("/^[A-Za-z0-9\-_]+$/", $app); + } + + protected function isValidPath($path) + { + return preg_match("/^[\/A-Za-z0-9_.\-~?%=&;]+$/", $path); + } +} diff --git a/application/controllers/api/frontend/v1/Searchbar.php b/application/controllers/api/frontend/v1/Searchbar.php new file mode 100644 index 000000000..b4c251555 --- /dev/null +++ b/application/controllers/api/frontend/v1/Searchbar.php @@ -0,0 +1,128 @@ +. + */ + +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, + 'searchCis' => self::PERM_LOGGED, + 'searchStv' => self::PERM_LOGGED + ]); + + $this->load->model('system/Webservicelog_model', 'WebservicelogModel'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Gets a JSON body via HTTP POST and provides the parameters + */ + public function search() + { + $this->load->library('SearchBarLib'); + $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->addMeta('mode', 'simple'); + + $this->terminateWithSuccess($result->data); + } + + /** + * Gets a JSON body via HTTP POST and provides the parameters + */ + public function searchCis() + { + return $this->searchAdvanced([ 'config' => 'searchcis' ]); + } + + /** + * Gets a JSON body via HTTP POST and provides the parameters + */ + public function searchStv() + { + return $this->searchAdvanced([ 'config' => 'searchstv' ]); + } + + /** + * Gets a JSON body via HTTP POST and provides the parameters + */ + private function searchAdvanced($config) + { + $this->load->library('SearchLib', $config); + $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->terminateWithValidationErrors($this->form_validation->error_array()); + + // Convert to json the result from searchlib->search + $result = $this->searchlib->search($this->input->post(self::SEARCHSTR_PARAM), $this->input->post(self::TYPES_PARAM)); + + $this->WebservicelogModel->insert(array( + 'webservicetyp_kurzbz' => 'content', + 'beschreibung' => $config['config'], + 'request_data' => json_encode(array( + self::SEARCHSTR_PARAM => $this->input->post(self::SEARCHSTR_PARAM), + self::TYPES_PARAM => $this->input->post(self::TYPES_PARAM) + )), + 'execute_user' => getAuthUID(), + 'execute_time' => 'NOW()' + )); + + $data = $this->getDataOrTerminateWithError($result); + + $this->addMeta('time', $result->meta['time']); + $this->addMeta('searchstring', $result->meta['searchstring']); + $this->addMeta('mode', 'advanced'); + + $this->terminateWithSuccess($data); + } +} + diff --git a/application/controllers/api/frontend/v1/Studgang.php b/application/controllers/api/frontend/v1/Studgang.php new file mode 100644 index 000000000..82aebb666 --- /dev/null +++ b/application/controllers/api/frontend/v1/Studgang.php @@ -0,0 +1,65 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); +class Studgang extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getStudiengangInfo'=> self::PERM_LOGGED, + + ]); + + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel'); + + // Loads phrases system + $this->loadPhrases([ + 'global' + ]); + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + public function getStudiengangInfo(){ + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID()); + $isMitarbeiter = $this->getDataOrTerminateWithError($isMitarbeiter); + if($isMitarbeiter) { + $this->terminateWithSuccess(null); + } + + // fetches the Studiengang Information which is used next to the news + $studiengangInfo = $this->StudiengangModel->getStudiengangInfoForNews(); + $studiengangInfo= $this->getDataOrTerminateWithError($studiengangInfo); + $this->terminateWithSuccess($studiengangInfo); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + + +} + diff --git a/application/controllers/api/frontend/v1/Studium.php b/application/controllers/api/frontend/v1/Studium.php new file mode 100644 index 000000000..d17f0c1a1 --- /dev/null +++ b/application/controllers/api/frontend/v1/Studium.php @@ -0,0 +1,329 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use CI3_Events as Events; + +class Studium extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getStudienAllSemester'=> self::PERM_LOGGED, + 'getStudiengaengeForStudienSemester'=> self::PERM_LOGGED, + 'getStudienplaeneBySemester'=> self::PERM_LOGGED, + 'getLvEvaluierungInfo'=> self::PERM_LOGGED, + ]); + + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $this->load->model('organisation/Studienordnung_model','StudienordnungModel'); + $this->load->model('organisation/Studiensemester_model',"StudiensemesterModel"); + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->load->model('codex/Orgform_model','OrgformModel'); + $this->load->model('person/Person_model','PersonModel'); + + + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + public function getStudienAllSemester(){ + + $parameter_studiensemester = $this->input->get('studiensemester',true); + $parameter_studiengang = $this->input->get('studiengang',true); + $parameter_semester = $this->input->get('semester',true); + $parameter_studienplan = $this->input->get('studienplan',true); + + $aktuelles_studiensemester = current($this->getDataOrTerminateWithError($this->StudiensemesterModel->getAktOrNextSemester())); + + if($this->getDataOrTerminateWithError($this->StudentModel->isStudent(getAuthUID()))){ + $studentLehrverband =$this->StudentlehrverbandModel->loadWhere(["student_uid" => getAuthUID(), "studiensemester_kurzbz" => $aktuelles_studiensemester->studiensemester_kurzbz]); + $studentLehrverband = current($this->getDataOrTerminateWithError($studentLehrverband)); + + $student_studiensemester = $studentLehrverband->studiensemester_kurzbz; + $student_studiengang = $studentLehrverband->studiengang_kz; + $student_semester = $studentLehrverband->semester; + $student_studienplan = $this->getStudienPlanFromPrestudentStatus(getAuthPersonId())->studienplan_id; + + if(!isset($parameter_studiensemester)) + $parameter_studiensemester = $student_studiensemester; + if(!isset($parameter_studiengang)) + $parameter_studiengang = $student_studiengang; + if(!isset($parameter_semester)) + $parameter_semester = $student_semester; + if(!isset($parameter_studienplan)) + $parameter_studienplan = $student_studienplan; + } + + if(isset($parameter_studiensemester)){ + $parameter_studiensemester = current($this->getDataOrTerminateWithError($this->StudiensemesterModel->loadWhere(["studiensemester_kurzbz" => $parameter_studiensemester]))); + } + + if(isset($parameter_studiengang)){ + $parameter_studiengang = current($this->getDataOrTerminateWithError($this->StudiengangModel->loadWhere(["studiengang_kz" => $parameter_studiengang]))); + } + + if(isset($parameter_studienplan)){ + $this->StudienplanModel->addJoin("lehre.tbl_studienordnung", "studienordnung_id"); + $this->StudienplanModel->addJoin("lehre.tbl_studienplan_semester", "studienplan_id"); + $parameter_studienplan = $this->StudienplanModel->loadWhere(["studienplan_id" => $parameter_studienplan, "aktiv" => TRUE]); + $parameter_studienplan = current($this->getDataOrTerminateWithError($parameter_studienplan)); + } + + // fetch studiensemester + $allStudienSemester = $this->getDataOrTerminateWithError($this->StudiensemesterModel->load()); + + + if(isset($parameter_studiensemester) && !empty(array_filter($allStudienSemester, function($studiensemester) use($parameter_studiensemester){ + return $studiensemester->studiensemester_kurzbz == $parameter_studiensemester->studiensemester_kurzbz; + }))){ + $aktuelles_studiensemester = $parameter_studiensemester; + } + + // fetch studiengaenge + $studiengaenge = $this->computeStudiengaenge($aktuelles_studiensemester->studiensemester_kurzbz); + $aktuelles_studiengang = current($studiengaenge); + if(!$aktuelles_studiengang){ + $aktuelles_studiengang = null; + } + if(isset($parameter_studiengang) && !empty(array_filter( $studiengaenge,function($studiengang)use($parameter_studiengang){ + return $studiengang->studiengang_kz == $parameter_studiengang->studiengang_kz; + }))){ + $aktuelles_studiengang = $parameter_studiengang; + } + + // compute semester and studienplaene + if($aktuelles_studiengang){ + $studienplaene = $this->computeStudienplaene($aktuelles_studiengang->studiengang_kz, $aktuelles_studiensemester->studiensemester_kurzbz); + }else{ + $studienplaene =[]; + } + + $semester = array_values(array_unique(array_map(function($item){ + return $item->semester; + }, $studienplaene))); + $aktuelles_semester = current($semester); + if(!$aktuelles_semester){ + $aktuelles_semester = null; + } + if(isset($parameter_semester) && in_array($parameter_semester, $semester)){ + $aktuelles_semester = $parameter_semester; + } + + $semester_studienplan = array_filter($studienplaene, function($item) use($aktuelles_semester){ + return $item->semester == $aktuelles_semester; + }); + + // fetch current studienplan based on semester + $aktuelles_studienplan = current($semester_studienplan); + if(!$aktuelles_studienplan){ + $aktuelles_studienplan = null; + } + if(isset($parameter_studienplan) && !empty(array_filter( $semester_studienplan, function($studienplan) use($parameter_studienplan){ + return $studienplan->studienplan_id == $parameter_studienplan->studienplan_id; + }))){ + $aktuelles_studienplan = $parameter_studienplan ; + } + + // fetch studienplan lehrveranstaltungen + if($aktuelles_studienplan){ + $lehrveranstaltungen = $this->computeStudienplanLehrveranstaltungen($aktuelles_studienplan->studienplan_id, $aktuelles_semester); + foreach($lehrveranstaltungen as $lehrv){ + foreach($lehrv->lehrveranstaltungen as $lv){ + $lvLektoren =$this->computeLektorenFromLehrveranstaltung($lv->lehrveranstaltung_id,$aktuelles_semester, $aktuelles_studiengang->studiengang_kz, $aktuelles_studiensemester->studiensemester_kurzbz); + $lv->lektoren = $lvLektoren; + } + + } + $aktuelles_lehrveranstaltungen = $lehrveranstaltungen; + }else{ + $aktuelles_lehrveranstaltungen = []; + } + + // result object + $result = new stdClass(); + $result->studienSemester = []; + $result->studienSemester["all"]= $allStudienSemester; + $result->studienSemester["preselected"]=$aktuelles_studiensemester; + $result->studiengang["all"]=$studiengaenge; + $result->studiengang["preselected"]=$aktuelles_studiengang; + $result->semester["all"] =$semester; + $result->semester["preselected"] =$aktuelles_semester; + $result->studienplan["all"]=$semester_studienplan; + $result->studienplan["preselected"]=$aktuelles_studienplan; + $result->lehrveranstaltungen=$aktuelles_lehrveranstaltungen; + + + $this->terminateWithSuccess($result); + } + + public function getLvEvaluierungInfo($studiensemester_kurzbz, $lehrveranstaltung_id){ + $result = []; + Events::trigger('lvEvaluierungsInfo', function & () use (&$result) { + return $result; + },$lehrveranstaltung_id, $studiensemester_kurzbz); + $this->terminateWithSuccess($result); + } + + public function getStudiengaengeForStudienSemester($studiensemester){ + $studiengaenge = $this->computeStudiengaenge($studiensemester); + $this->terminateWithSuccess($studiengaenge); + } + + public function getStudienplaeneBySemester(){ + $this->load->library('form_validation'); + $this->form_validation->set_data($this->input->get()); + $this->form_validation->set_rules('studiengang', 'studiengang', 'required'); + $this->form_validation->set_rules('studiensemester', 'studiensemester', 'required'); + if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $studiengang = $this->input->get('studiengang',true); + $studiensemester = $this->input->get('studiensemester',true); + $studienplaene = $this->computeStudienplaene($studiengang, $studiensemester); + $this->terminateWithSuccess($studienplaene); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + private function computeStudienplaene($studiengang, $studiensemester){ + $studienplaene = $this->StudienplanModel->getStudienplaeneBySemester($studiengang, $studiensemester); + $studienplaene = $this->getDataOrTerminateWithError($studienplaene); + $studienplaene = array_map(function($studienplan){ + $orgform = current($this->getDataOrTerminateWithError($this->OrgformModel->loadWhere(["orgform_kurzbz" => $studienplan->orgform_kurzbz]))); + $studienplan->orgform_bezeichnung = $orgform->bezeichnung; + return $studienplan; + },$studienplaene); + return $studienplaene; + } + + private function computeStudienplanLehrveranstaltungen($studienplan_id, $semester){ + +/* +SELECT tbl_lehrveranstaltung.*, + tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id, + tbl_studienplan_lehrveranstaltung.semester as stpllv_semester, + tbl_studienplan_lehrveranstaltung.pflicht as stpllv_pflicht, + tbl_studienplan_lehrveranstaltung.koordinator as stpllv_koordinator, + tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent, + tbl_studienplan_lehrveranstaltung.sort stpllv_sort, + tbl_studienplan_lehrveranstaltung.curriculum, + tbl_studienplan_lehrveranstaltung.export, + tbl_studienplan_lehrveranstaltung.genehmigung + FROM lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_studienplan_lehrveranstaltung + USING(lehrveranstaltung_id) + WHERE tbl_studienplan_lehrveranstaltung.studienplan_id=" . $this->db_add_param($studienplan_id, FHC_INTEGER); + if (defined("CIS_PROFIL_STUDIENPLAN_MODULE_AUSBLENDEN") && CIS_PROFIL_STUDIENPLAN_MODULE_AUSBLENDEN) + $qry .= " AND tbl_lehrveranstaltung.lehrtyp_kurzbz != 'modul'"; + if (!is_null($semester)) + { + $qry.=" AND tbl_studienplan_lehrveranstaltung.semester=" . $this->db_add_param($semester, FHC_INTEGER); + } */ + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $query = " + SELECT tbl_lehrveranstaltung.*, + tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id, + tbl_studienplan_lehrveranstaltung.semester as stpllv_semester, + tbl_studienplan_lehrveranstaltung.pflicht as stpllv_pflicht, + tbl_studienplan_lehrveranstaltung.koordinator as stpllv_koordinator, + tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent, + tbl_studienplan_lehrveranstaltung.sort stpllv_sort, + tbl_studienplan_lehrveranstaltung.curriculum, + tbl_studienplan_lehrveranstaltung.export, + tbl_studienplan_lehrveranstaltung.genehmigung + FROM lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_studienplan_lehrveranstaltung + USING(lehrveranstaltung_id) + WHERE + tbl_lehrveranstaltung.lehre = true AND + tbl_studienplan_lehrveranstaltung.studienplan_id=? AND tbl_studienplan_lehrveranstaltung.semester=?"; + + if (defined("CIS_PROFIL_STUDIENPLAN_MODULE_AUSBLENDEN") && CIS_PROFIL_STUDIENPLAN_MODULE_AUSBLENDEN) + $query .= " AND tbl_lehrveranstaltung.lehrtyp_kurzbz != 'modul'"; + + $lehrveranstaltungen = $this->LehrveranstaltungModel->execReadOnlyQuery($query,[$studienplan_id, $semester]); + + $lehrveranstaltungen = $this->getDataOrTerminateWithError($lehrveranstaltungen); + usort($lehrveranstaltungen, function($a, $b){ + if($a->lehrtyp_kurzbz == "modul"){ + return -1; + } + else if($b->lehrtyp_kurzbz == "modul"){ + return 1; + } + return 0; + }); + $lehrveranstaltungen= array_reduce($lehrveranstaltungen,function($carry, $lehrv){ + if($lehrv->lehrtyp_kurzbz == "modul"){ + $lehrv->lehrveranstaltungen = []; + array_push($carry, $lehrv); + } + else{ + $parent =array_filter($carry, function($item)use($lehrv){ + return $item->studienplan_lehrveranstaltung_id == $lehrv->studienplan_lehrveranstaltung_id_parent; + }); + $parent = current($parent); + if($parent){ + $parent->lehrveranstaltungen[] = $lehrv; + } + } + return $carry; + }, []); + return $lehrveranstaltungen; + } + + private function computeStudiengaenge($studiensemester){ + $studiengang_studiensemester_result = $this->StudiengangModel->getStudiengaengeByStudiensemester($studiensemester); + $studiengang_studiensemester_result = $this->getDataOrTerminateWithError($studiengang_studiensemester_result); + return $studiengang_studiensemester_result; + } + + private function getStudienPlanFromPrestudentStatus($person_id){ + $studienplan_id = current($this->getDataOrTerminateWithError($this->PrestudentstatusModel->getLastStatusPerson($person_id)))->studienplan_id; + $studienplan =current($this->getDataOrTerminateWithError($this->StudienplanModel->loadWhere(["studienplan_id"=>$studienplan_id]))); + return $studienplan; + } + + private function computeLektorenFromLehrveranstaltung($lehreinheit_id, $semester, $studiengang, $studiensemester){ + $this->load->library('StundenplanLib'); + $lektoren = $this->stundenplanlib->getLektorenFromLehrveranstaltung($lehreinheit_id,$semester, $studiengang,$studiensemester); + $lektoren = $this->getDataOrTerminateWithError($lektoren) ?? []; + + $lektoren = array_map(function($lektor){ + return ["name"=>$this->getDataOrTerminateWithError($this->PersonModel->getFullName($lektor)), "email"=>$lektor."@".DOMAIN]; + },$lektoren); + + return $lektoren; + } + + + + +} + 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..7486f44f0 --- /dev/null +++ b/application/controllers/api/frontend/v1/betriebsmittel/BetriebsmittelP.php @@ -0,0 +1,421 @@ + ['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) + { + $betriebsmitteltypes = null; + if ($this->input->get('betriebsmitteltypes') !== null && !isEmptyArray($this->input->get('betriebsmitteltypes'))) + $betriebsmitteltypes = $this->input->get('betriebsmitteltypes'); + + $result = $this->BetriebsmittelpersonModel->getBetriebsmittelData($id, $type_id, $betriebsmitteltypes); + + 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', 'callback_valid_number|callback_not_less_than_equal', [ + 'valid_number' => $this->p->t('ui', 'error_fieldNoValidNumber'), + 'not_less_than_equal' => $this->p->t('ui', 'error_fieldLessThan1000'), + ]); + + $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'); + if($kaution) $kaution = str_replace(',', '.', $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'); + if($kaution) $kaution = str_replace(',', '.', $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); + } + + return $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); + } + $this->terminateWithSuccess(current(getData($result))); + } + + public function getTypenBetriebsmittel() + { + $this->load->model('ressource/Betriebsmitteltyp_model', 'BetriebsmitteltypModel'); + + $this->BetriebsmitteltypModel->addOrder('beschreibung', 'ASC'); + + if ($this->input->get('betriebsmitteltypes') !== null && !isEmptyArray($this->input->get('betriebsmitteltypes'))) + { + $this->BetriebsmitteltypModel->db->where_in('betriebsmitteltyp', $this->input->get('betriebsmitteltypes')); + } + + $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); + } + + public function valid_number($number) + { + if(is_null($number)) return true; + $number = str_replace(',', '.', $number); + if (!is_numeric($number)) + { + return false; + } + return true; + } + + public function not_less_than_equal($number) + { + $number = str_replace(',', '.', $number); + if ($number < 1000) + return true; + return false; + + } +} + + 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/funktionen/Funktionen.php b/application/controllers/api/frontend/v1/funktionen/Funktionen.php new file mode 100644 index 000000000..b2787072b --- /dev/null +++ b/application/controllers/api/frontend/v1/funktionen/Funktionen.php @@ -0,0 +1,328 @@ + ['admin:r', 'assistenz:r'], + 'getAllUserFunctions' => ['admin:r', 'assistenz:r'], + 'getOrgHeads' => ['admin:r', 'assistenz:r'], + 'getOrgetsForCompany' => ['admin:r', 'assistenz:r'], + 'getAllOrgUnits' => ['admin:r', 'assistenz:r'], + 'loadFunction' => ['admin:r', 'assistenz:r'], + 'insertFunction' => ['admin:rw', 'assistenz:rw'], + 'updateFunction' => ['admin:rw', 'assistenz:rw'], + 'deleteFunction' => ['admin:rw', 'assistenz:rw'], + ) + ); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + ]); + + // Load models + $this->load->model('extensions/FHC-Core-Personalverwaltung/Api_model', 'ApiModel'); + $this->load->model('ressource/Funktion_model', 'FunktionModel'); + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + + $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + } + + public function getAllFunctions() + { + $this->FunktionModel->addSelect("funktion_kurzbz"); + $this->FunktionModel->addSelect("beschreibung"); + $this->FunktionModel->addSelect("aktiv"); + $this->FunktionModel->addSelect("beschreibung AS label"); + $this->FunktionModel->addOrder("beschreibung"); + $result = $this->FunktionModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getOrgHeads() + { + $result = $this->OrganisationseinheitModel->getHeads(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getAllUserFunctions($uid) + { + if(!$uid) + { + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'UID']), self::ERROR_TYPE_GENERAL); + } + + $sql = " + SELECT + dv.dienstverhaeltnis_id, + un.bezeichnung || ' (' || TO_CHAR(dv.von, 'DD.MM.YYYY') || CASE WHEN dv.bis IS NOT NULL THEN ' - ' + || TO_CHAR(dv.bis, 'DD.MM.YYYY') ELSE '' END || ')' AS dienstverhaeltnis_unternehmen , + '[' || oet.bezeichnung || '] ' || oe.bezeichnung AS funktion_oebezeichnung, + f.beschreibung AS funktion_beschreibung, + bf.*, + fb.bezeichnung AS fachbereich_bezeichnung, + CASE + WHEN + bf.datum_bis IS NOT NULL AND bf.datum_bis::date < now()::date + THEN + false + ELSE + true + END aktiv + FROM + public.tbl_benutzerfunktion bf + JOIN + public.tbl_organisationseinheit oe ON oe.oe_kurzbz = bf.oe_kurzbz + JOIN + public.tbl_organisationseinheittyp oet ON oe.organisationseinheittyp_kurzbz = oet.organisationseinheittyp_kurzbz + JOIN + public.tbl_funktion f ON f.funktion_kurzbz = bf.funktion_kurzbz + LEFT JOIN + hr.tbl_vertragsbestandteil_funktion vf ON vf.benutzerfunktion_id = bf.benutzerfunktion_id + LEFT JOIN + hr.tbl_vertragsbestandteil v ON vf.vertragsbestandteil_id = v.vertragsbestandteil_id + LEFT JOIN + hr.tbl_dienstverhaeltnis dv ON v.dienstverhaeltnis_id = dv.dienstverhaeltnis_id + LEFT JOIN + public.tbl_organisationseinheit un ON dv.oe_kurzbz = un.oe_kurzbz + LEFT JOIN + public.tbl_fachbereich fb ON fb.fachbereich_kurzbz = bf.fachbereich_kurzbz + WHERE + bf.uid = ? + ORDER BY + bf.datum_von, bf.datum_von ASC"; + + $benutzerfunktionen = $this->BenutzerfunktionModel->execReadOnlyQuery($sql, array($uid)); + $data = $this->getDataOrTerminateWithError($benutzerfunktionen); + + $this->terminateWithSuccess($data); + } + + /* + * returns list of all organisation units + * as key value list to be used in select or autocomplete + */ + public function getAllOrgUnits() + { + $sql = " + SELECT + oe.oe_kurzbz, oe.aktiv, + '[' || COALESCE(oet.bezeichnung, oet.organisationseinheittyp_kurzbz) || + '] ' || COALESCE(oe.bezeichnung, oe.oe_kurzbz) AS label + FROM public.tbl_organisationseinheit oe + JOIN public.tbl_organisationseinheittyp oet ON oe.organisationseinheittyp_kurzbz = oet.organisationseinheittyp_kurzbz + ORDER BY oet.bezeichnung ASC, oe.bezeichnung ASC"; + + $result = $this->OrganisationseinheitModel->execReadOnlyQuery($sql); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /* + * return list of child orgets for a given company orget_kurzbz + * as key value list to be used in select or autocomplete + */ + public function getOrgetsForCompany($companyOrgetkurzbz = null) + { + $sql = " + SELECT + oe.oe_kurzbz, oe.aktiv, + '[' || COALESCE(oet.bezeichnung, oet.organisationseinheittyp_kurzbz) || + '] ' || COALESCE(oe.bezeichnung, oe.oe_kurzbz) AS label + FROM ( + WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) as + ( + SELECT oe_kurzbz, oe_parent_kurzbz FROM public.tbl_organisationseinheit + WHERE oe_kurzbz=? + UNION ALL + SELECT o.oe_kurzbz, o.oe_parent_kurzbz FROM public.tbl_organisationseinheit o, oes + WHERE o.oe_parent_kurzbz=oes.oe_kurzbz + ) + SELECT oe_kurzbz + FROM oes + GROUP BY oe_kurzbz + ) c + JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = c.oe_kurzbz + JOIN public.tbl_organisationseinheittyp oet ON oe.organisationseinheittyp_kurzbz = oet.organisationseinheittyp_kurzbz + ORDER BY oet.bezeichnung ASC, oe.bezeichnung ASC"; + + $childorgets = $this->OrganisationseinheitModel->execReadOnlyQuery($sql, array($companyOrgetkurzbz)); + $data = $this->getDataOrTerminateWithError($childorgets); + + $this->terminateWithSuccess($data); + } + + public function loadFunction($benutzerfunktion_id) + { + $this->BenutzerfunktionModel->addSelect("*"); + $result = $this->BenutzerfunktionModel->loadWhere( + array('benutzerfunktion_id' => $benutzerfunktion_id) + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function insertFunction() + { + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $uid = $this->input->post('uid'); + + if(!$uid) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'UID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + + $datum_von = $formData['datum_von'] ?? null; + $datum_bis = $formData['datum_bis'] ?? null; + $formData['oe_kurzbz'] = is_array($formData['oe_kurzbz']) ? $formData['oe_kurzbz']['oe_kurzbz'] : $formData['oe_kurzbz']; + $formData['funktion_kurzbz'] = is_array($formData['funktion_kurzbz']) + ? $formData['funktion_kurzbz']['funktion_kurzbz'] + : $formData['funktion_kurzbz']; + $bezeichnung = $formData['bezeichnung'] ?? null; + $wochenstunden = $formData['wochenstunden'] ?? null; + + $this->form_validation->set_data($formData); + $this->form_validation->set_rules('datum_von', 'VonDatum', 'required|is_valid_date', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'VonDatum']), + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum']) + ]); + $this->form_validation->set_rules('datum_bis', 'BisDatum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'BisDatum']) + ]); + $this->form_validation->set_rules('oe_kurzbz', 'Organisationseinheit', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Organisationseinheit']) + ]); + $this->form_validation->set_rules('funktion_kurzbz', 'Funktion', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Funktion']) + ]); + $this->form_validation->set_rules('wochenstunden', 'Wochenstunden', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Wochenstunden']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->BenutzerfunktionModel->insert([ + 'uid' => $uid, + 'datum_von' => $datum_von, + 'datum_bis' => $datum_bis , + 'oe_kurzbz' => $formData['oe_kurzbz'], + 'funktion_kurzbz' => $formData['funktion_kurzbz'], + 'bezeichnung' => $bezeichnung, + 'wochenstunden' => $wochenstunden, + 'insertamum' => date('c'), + 'insertvon' => $authUID, + ]); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function updateFunction() + { + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $uid = $this->input->post('uid'); + + if(!$uid) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'UID']), self::ERROR_TYPE_GENERAL); + } + $benutzerfunktion_id = $this->input->post('benutzerfunktion_id'); + + if(!$benutzerfunktion_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Benutzerfunktion ID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + + $datum_von = $formData['datum_von'] ?? null; + $datum_bis = $formData['datum_bis'] ?? null; + $formData['oe_kurzbz'] = is_array($formData['oe_kurzbz']) ? $formData['oe_kurzbz']['oe_kurzbz'] : $formData['oe_kurzbz']; + $formData['funktion_kurzbz'] = is_array($formData['funktion_kurzbz']) + ? $formData['funktion_kurzbz']['funktion_kurzbz'] + : $formData['funktion_kurzbz']; + $bezeichnung = $formData['bezeichnung'] ?? null; + $wochenstunden = $formData['wochenstunden'] ?? null; + + $this->form_validation->set_data($formData); + $this->form_validation->set_rules('datum_von', 'VonDatum', 'required|is_valid_date', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'VonDatum']), + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum']) + ]); + $this->form_validation->set_rules('datum_bis', 'BisDatum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'BisDatum']) + ]); + $this->form_validation->set_rules('oe_kurzbz', 'Organisationseinheit', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Organisationseinheit']) + ]); + $this->form_validation->set_rules('funktion_kurzbz', 'Funktion', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Funktion']) + ]); + $this->form_validation->set_rules('wochenstunden', 'Wochenstunden', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Wochenstunden']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->BenutzerfunktionModel->update( + [ + 'benutzerfunktion_id' => $benutzerfunktion_id, + ], + [ + 'uid' => $uid, + 'datum_von' => $datum_von, + 'datum_bis' => $datum_bis , + 'oe_kurzbz' => $formData['oe_kurzbz'], + 'funktion_kurzbz' => $formData['funktion_kurzbz'], + 'bezeichnung' => $bezeichnung, + 'wochenstunden' => $wochenstunden, + 'updateamum' => date('c'), + 'updatevon' => $authUID, + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function deleteFunction($benutzerfunktion_id) + { + $result = $this->BenutzerfunktionModel->delete( + array('benutzerfunktion_id' => $benutzerfunktion_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } +} diff --git a/application/controllers/api/frontend/v1/messages/Messages.php b/application/controllers/api/frontend/v1/messages/Messages.php new file mode 100644 index 000000000..fa6748f6a --- /dev/null +++ b/application/controllers/api/frontend/v1/messages/Messages.php @@ -0,0 +1,466 @@ + ['admin:r', 'assistenz:r'], + 'getVorlagen' => ['admin:r', 'assistenz:r'], + 'getMessageVarsPerson' => ['admin:r', 'assistenz:r'], + 'getMsgVarsPrestudent' => ['admin:r', 'assistenz:r'], + 'getMsgVarsLoggedInUser' => ['admin:r', 'assistenz:r'], + 'getNameOfDefaultRecipient' => ['admin:r', 'assistenz:r'], + 'sendMessage' => ['admin:r', 'assistenz:r'], + 'deleteMessage' => ['admin:r', 'assistenz:r'], + 'getVorlagentext' => ['admin:r', 'assistenz:r'], + 'getPreviewText' => ['admin:r', 'assistenz:r'], + 'getReplyData' => ['admin:r', 'assistenz:r'], + 'getPersonId' => ['admin:r', 'assistenz:r'], + 'getUid' => ['admin:r', 'assistenz:r'], + ]); + + //Load Models + $this->load->model('system/Message_model', 'MessageModel'); + $this->load->model('CL/Messages_model', 'MessagesModel'); + + // Additional Permission Checks + //TODO(manu) check permissions + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + $this->load->library('MessageLib'); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + public function getMessages($id, $type_id, $size, $page) + { + if($type_id != 'person_id'){ + $id = $this->_getPersonId($id, $type_id); + } + + $offset = $size * ($page - 1); + $limit = $size; + + $result = $this->MessageModel->getMessagesForTable($id, $offset, $limit); + + $data = $this->getDataOrTerminateWithError($result); + + $this->addMeta('count', $data['count']); + + $this->terminateWithSuccess($data['data']); + } + + public function getVorlagen() + { + //get oe of user + $uid = getAuthUID(); + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $result = $this->BenutzerfunktionModel->getBenutzerfunktionByUid($uid, 'oezuordnung'); + + $data = $this->getDataOrTerminateWithError($result); + $oe_kurzbz = current($data); + + $this->load->model('system/Vorlage_model', 'VorlageModel'); + + $result = $this->VorlageModel->getAllVorlagenByOe($oe_kurzbz->oe_kurzbz); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + + //If admin + $this->VorlageModel->addOrder('vorlage_kurzbz', 'ASC'); + $result = $this->VorlageModel->loadWhere( + array( + 'mimetype' => 'text/html' + )); + + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getVorlagentext($vorlage_kurzbz) + { + //$this->terminateWithError("vor " . $vorlage_kurzbz, self::ERROR_TYPE_GENERAL); + //$studiengang_kz = 227; //TODO(Manu) dynamisieren NULL + $studiengang_kz = 0; + $this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); + $this->VorlagestudiengangModel->addOrder('version', 'DESC'); + + $result = $this->VorlagestudiengangModel->loadWhere( + [ + 'vorlage_kurzbz' =>$vorlage_kurzbz, + 'studiengang_kz' => $studiengang_kz + ]); + + $data = $this->getDataOrTerminateWithError($result); + + //not correct with Vorlage + $vorlage = current($data); + + //$this->terminateWithSuccess($data); + $this->terminateWithSuccess($vorlage->text); + } + + public function getMessageVarsPerson($id, $typeId) + { + $person_id = ($typeId == 'mitarbeiter_uid') ? $this->_getPersonId($id, $typeId) : $id; + $result = $this->MessageModel->getMsgVarsDataByPersonId($person_id); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getMsgVarsPrestudent($id, $typeId) + { + $prestudent_id = ($typeId == 'uid') ? $this->_getPrestudentIdFromUid($id) : $id; + $result = $this->MessageModel->getMsgVarsDataByPrestudentId($prestudent_id); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getMsgVarsLoggedInUser() + { + $result = $this->MessageModel->getMsgVarsLoggedInUser(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getNameOfDefaultRecipient($id, $type_id) + { + $id = ($type_id != 'person_id') ? $this->_getPersonId($id, $type_id) : $id; + + $this->load->model('person/Person_model', 'PersonModel'); + + $result = $this->PersonModel->load($id); + $data = $this->getDataOrTerminateWithError($result); + $name = current($data); + + $this->terminateWithSuccess($name->vorname . " " . $name->nachname ); + } + + public function sendMessage($recipient_id) + { + //has to be uid + // $this->terminateWithError("uid", $recipient_id, self::ERROR_TYPE_GENERAL); + + //default setting + $receiversPersonId = $this->_getPersonId($recipient_id, 'uid'); + + $uid = getAuthUID(); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $result = $this->BenutzerModel->loadWhere( + ['uid' => $uid] + ); + + $data = $this->getDataOrTerminateWithError($result); + $benutzer = current($data); + + if (isset($_POST['data'])) + { + $data = json_decode($_POST['data']); + unset($_POST['data']); + foreach ($data as $k => $v) { + $_POST[$k] = $v; + } + } + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('subject', 'Betreff', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Betreff']) + ]); + + $this->form_validation->set_rules('body', 'Text', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Text']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $subject = $this->input->post('subject'); + $body = $this->input->post('body'); + $relationmessage_id = $this->input->post('relationmessage_id'); + + $typeId = $this->input->post('type_id'); + $id = $this->input->post('id'); + + if($typeId == 'uid') + { + $prestudent_id = $this-> _getPrestudentIdFromUid($id); + + //parseMessagetext for variables Prestudent + $result = $this->MessagesModel->parseMessageTextPrestudent($prestudent_id, $body); + $bodyParsed = $this->getDataOrTerminateWithError($result); + } + if($typeId == 'mitarbeiter_uid') + { + $person_id = $this->_getPersonId($id, $typeId); + + $result = $this->MessagesModel->parseMessageTextPerson($person_id, $body); + $bodyParsed = $this->getDataOrTerminateWithError($result); + $this->terminateWithError($bodyParsed, self::ERROR_TYPE_GENERAL); + + } + elseif($typeId == 'person_id') + { + $result = $this->MessagesModel->parseMessageTextPerson($id, $body); + $bodyParsed = $this->getDataOrTerminateWithError($result); + } + elseif($typeId == 'prestudent_id') + { + // $this->terminateWithError("prestudent_id ", self::ERROR_TYPE_GENERAL); + + $result = $this->MessagesModel->parseMessageTextPrestudent($id, $body); + $bodyParsed = $this->getDataOrTerminateWithError($result); + } + else + { + $this->terminateWithError("type_id " . $typeId . " not valid", self::ERROR_TYPE_GENERAL); + } + + $result = $this->messagelib->sendMessageUser($receiversPersonId, $subject, $bodyParsed, $benutzer->person_id, null, $relationmessage_id); + + $this->terminateWithSuccess($result); + } + + public function getPreviewText($id, $type_id) + { + if (isset($_POST['data'])) + { + $data = json_decode($_POST['data']); + unset($_POST['data']); + } + else + $this->terminateWithError("Textbody missing ", self::ERROR_TYPE_GENERAL); + + switch($type_id) + { + case 'uid': + $prestudent_id = $this->_getPrestudentIdFromUid($id); + $result = $this->MessagesModel->parseMessageTextPrestudent($prestudent_id, $data); + break; + case 'prestudent_id': + $result = $this->MessagesModel->parseMessageTextPrestudent($id, $data); + break; + case 'person_id': + $result = $this->MessagesModel->parseMessageTextPerson($id, $data); + break; + case 'mitarbeiter_uid': + { + $person_id = $this->_getPersonId($id, $type_id); + $result = $this->MessagesModel->parseMessageTextPerson($person_id, $data); + } + break; + default: + $this->terminateWithError("MESSAGES::getPreviewText logic for type_id " . $type_id . " not defined yet", self::ERROR_TYPE_GENERAL); + break; + } + + $bodyParsed = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($bodyParsed); + } + + public function getReplyData($messageId) + { + //TODO(Manu) validation of messageId: if number + + $this->MessageModel->addSelect('public.tbl_msg_message.*'); + $this->MessageModel->addSelect('r.*'); + $this->MessageModel->addSelect('p.nachname'); + $this->MessageModel->addSelect('p.vorname'); + $this->MessageModel->addJoin('public.tbl_msg_recipient r', 'ON (r.message_id = public.tbl_msg_message.message_id)'); + $this->MessageModel->addJoin('public.tbl_person p', 'ON (p.person_id = public.tbl_msg_message.person_id)'); + + $result = $this->MessageModel->loadWhere( + array('r.message_id' => $messageId) + ); + + $dataMessage = $this->getDataOrTerminateWithError($result); + $prefix = "Re: "; // reply subject prefix + + $subject = $dataMessage[0]->subject; + $body = $dataMessage[0]->body; + + + $replyBody = $this->_getReplyBody($body, $dataMessage[0]->nachname, $dataMessage[0]->vorname, $dataMessage[0]->insertamum); + + $dataMessage[0]->replyBody = $replyBody; + $dataMessage[0]->rest = "Help Manu"; + $dataMessage[0]->replySubject = $prefix . $subject; + + $this->terminateWithSuccess($dataMessage); + } + + public function deleteMessage($messageId) + { + // Start DB transaction + $this->db->trans_begin(); + + $result = $this->MessageModel->deleteMessageRecipient($messageId); + if (isError($result)) { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + + } + + $result = $this->MessageModel->deleteMessageStatus($messageId); + if (isError($result)) { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + $result = $this->MessageModel->deleteMessage($messageId); + if (isError($result)) { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + $this->db->trans_commit(); + + $this->terminateWithSuccess($result); + } + + public function getPersonId($id, $typeId) + { + if ($typeId == 'uid' || $typeId == 'mitarbeiter_uid') + { + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $result = $this->BenutzerModel->loadWhere( + ['uid' => $id] + ); + } + elseif($typeId == 'prestudent_id') + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->loadWhere( + ['prestudent_id' => $id] + ); + } + + $data = $this->getDataOrTerminateWithError($result); + $person = current($data); + + $this->terminateWithSuccess($person->person_id); + } + + public function getUid($id, $typeId) + { + if (!$typeId) + { + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Type ID']), self::ERROR_TYPE_GENERAL); + } + elseif ($typeId == 'person_id') + { + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $result = $this->BenutzerModel->loadWhere( + ['person_id' => $id] + ); + } + elseif($typeId == 'prestudent_id') + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->loadWhere( + ['prestudent_id' => $id] + ); + + $data = $this->getDataOrTerminateWithError($result); + $person = current($data); + $person_id = $person->person_id; + + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $result = $this->BenutzerModel->loadWhere( + ['person_id' => $person_id] + ); + } + elseif($typeId == 'uid' || $typeId == 'mitarbeiter_uid') + { + $this->terminateWithSuccess($id); + } + else + { + $this->terminateWithError("MESSAGES::getUID logic for type_id " . $typeId . " not defined yet", self::ERROR_TYPE_GENERAL); + } + + $data = $this->getDataOrTerminateWithError($result); + $benutzer = current($data); + + $this->terminateWithSuccess($benutzer->uid); + } + + private function _getPersonId($id, $typeId) + { + if ($typeId == 'uid' || $typeId == 'mitarbeiter_uid') + { + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $result = $this->BenutzerModel->loadWhere( + ['uid' => $id] + ); + } + elseif($typeId == 'prestudent_id') + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->loadWhere( + ['prestudent_id' => $id] + ); + } + + $data = $this->getDataOrTerminateWithError($result); + if (count($data) < 1) + { + $this->terminateWithError('Error: Messages API no person_id found.'); + } + $person = current($data); + + return $person->person_id; + } + + private function _getPrestudentIdFromUid($uid) + { + // $this->terminateWithError($uid, self::ERROR_TYPE_GENERAL); + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->loadWhere( + ['student_uid' => $uid] + ); + + $data = $this->getDataOrTerminateWithError($result); + if (count($data) < 1) + { + $this->terminateWithError('Error: Messages API no prestudent_id found.'); + } + $student = current($data); + + return $student->prestudent_id; + } + + private function _getReplyBody($body, $receiverName, $receiverSurname, $sentDate) + { + // To quote a reply body message + $bodyFormat = "
+
+
+ + On %s %s %s wrote: + +
+
+ %s +
"; + return sprintf( + $bodyFormat, + date_format(date_create($sentDate), 'd.m.Y H:i'), $receiverName, $receiverSurname, $body + ); + } +} \ No newline at end of file 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..23a8fd199 --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizPerson.php @@ -0,0 +1,52 @@ + ['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'], + 'getCountNotes' => ['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/StudiengangEP.php b/application/controllers/api/frontend/v1/organisation/StudiengangEP.php new file mode 100644 index 000000000..463243f57 --- /dev/null +++ b/application/controllers/api/frontend/v1/organisation/StudiengangEP.php @@ -0,0 +1,57 @@ + self::PERM_LOGGED + ) + ); + // Load model StudiengangModel + $this->load->model('organisation/studiengang_model', 'StudiengangModel'); + } + + /** + * @return void + */ + public function getStudiengangByKz() + { + $studiengang_kz = intval($this->input->get('studiengang_kz')); + + $this->StudiengangModel->addSelect('studiengang_kz, kurzbz, kurzbzlang, ' + . 'typ, bezeichnung, english, aktiv, orgform_kurzbz, sprache, ' + . 'oe_kurzbz'); + $result = $this->StudiengangModel->load($studiengang_kz); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $stg = null; + if(hasData($result)) + { + $stg = (getData($result))[0]; + } + $this->terminateWithSuccess($stg); + } +} diff --git a/application/controllers/api/frontend/v1/organisation/Studienjahr.php b/application/controllers/api/frontend/v1/organisation/Studienjahr.php new file mode 100644 index 000000000..cdbb524c7 --- /dev/null +++ b/application/controllers/api/frontend/v1/organisation/Studienjahr.php @@ -0,0 +1,80 @@ + self::PERM_LOGGED, + 'getNext' => self::PERM_LOGGED + ) + ); + // Load model StudiensemesterModel + $this->load->model('organisation/studienjahr_model', 'StudienjahrModel'); + } + + /** + * Get all Studienjahre. + * + * @param null|string $order Sorting order for the Studienjahr, 'asc' or 'desc'. Defaults to 'asc'. + * @param null|string $start Starting Studienjahre with given studienjahr_kurzbz + */ + public function getAll() + { + $order = $this->input->get('order'); + $start = $this->input->get('studienjahr_kurzbz'); + + if (strcasecmp($order, 'DESC') == 0) { + $this->StudienjahrModel->addOrder('studienjahr_kurzbz', 'DESC'); + } else { + $this->StudienjahrModel->addOrder('studienjahr_kurzbz', 'ASC'); + } + + if ($start) { + $result = $this->StudienjahrModel->loadWhere([ + 'studienjahr_kurzbz >= ' => $start + ]); + } else { + $result = $this->StudienjahrModel->load(); + } + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function getNext() + { + $this->StudienjahrModel->addJoin('public.tbl_studiensemester', 'studienjahr_kurzbz'); + $this->StudienjahrModel->addOrder('start'); + $this->StudienjahrModel->addLimit(1); + + $result = $this->StudienjahrModel->loadWhere(['start >' => 'NOW()']); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess(current(getData($result))); + } +} 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..bb56ea71a --- /dev/null +++ b/application/controllers/api/frontend/v1/organisation/Studiensemester.php @@ -0,0 +1,155 @@ + self::PERM_LOGGED, + 'getAktNext' => self::PERM_LOGGED, + 'getStudienjahrByStudiensemester' => 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) ?: '')); + } + + /** + * Get Studienjahr by Studiensemester. + * input param semester: studiensemester_kurzbz + */ + public function getStudienjahrByStudiensemester() + { + $semester = $this->input->get('semester'); + + $studienjahrObj = null; + + if (!is_numeric($semester)) + { + $this->StudiensemesterModel->addSelect('studienjahr_kurzbz'); + $result = $this->StudiensemesterModel->loadWhere(array('studiensemester_kurzbz =' => $semester)); + } + + if (hasData($result)) + { + $studienjahr = getData($result)[0]->studienjahr_kurzbz; + $startstudienjahr = substr($studienjahr, 0, 4); + $endstudienjahr = substr($studienjahr, 0, 2) . substr($studienjahr, -2); + + $studienjahrObj = new StdClass(); + + $studienjahrObj->studienjahr_kurzbz = $studienjahr; + $studienjahrObj->startstudienjahr = $startstudienjahr; + $studienjahrObj->endstudienjahr= $endstudienjahr; + } + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess((getData(success($studienjahrObj)))); + } +} 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/Abschlusspruefung.php b/application/controllers/api/frontend/v1/stv/Abschlusspruefung.php new file mode 100644 index 000000000..d8bc067f9 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Abschlusspruefung.php @@ -0,0 +1,501 @@ + ['admin:r', 'assistenz:r'], + 'loadAbschlusspruefung' => ['admin:r', 'assistenz:r'], + 'insertAbschlusspruefung' => ['admin:rw', 'assistenz:rw'], + 'updateAbschlusspruefung' => ['admin:rw', 'assistenz:rw'], + 'deleteAbschlusspruefung' => ['admin:rw', 'assistenz:rw'], + 'getTypenAbschlusspruefung' => ['admin:rw', 'assistenz:rw'], + 'getNoten' => ['admin:rw', 'assistenz:rw'], + 'getTypenAntritte' => ['admin:rw', 'assistenz:rw'], + 'getBeurteilungen' => ['admin:rw', 'assistenz:rw'], + 'getAkadGrade' => ['admin:rw', 'assistenz:rw'], + 'getMitarbeiter' => ['admin:rw', 'assistenz:rw'], + 'getAllMitarbeiter' => ['admin:rw', 'assistenz:rw'], + 'getAllPersons' => ['admin:rw', 'assistenz:rw'], + 'getPruefer' => ['admin:rw', 'assistenz:rw'], + 'getTypStudiengang' => ['admin:rw', 'assistenz:rw'], + 'checkForExistingExams' => ['admin:rw', 'assistenz:rw'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'abschlusspruefung' + ]); + + // Load models + $this->load->model('education/Abschlusspruefung_model', 'AbschlusspruefungModel'); + + + //Permission checks for Studiengangsarray + $allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []; + + if ($this->router->method == 'insertAbschlusspruefung' || $this->router->method == 'updateAbschlusspruefung') + { + $student_uid = $this->input->post('uid') ?: ($this->input->post('formData')['student_uid'] ?? null); + + if(!$student_uid) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkAllowedStgsFromUid($student_uid, $allowedStgs); + } + + if ($this->router->method == 'deleteAbschlusspruefung') + { + $abschlusspruefung_id = $this->input->post('id'); + + if(!$abschlusspruefung_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Abschlusspruefung ID']), self::ERROR_TYPE_GENERAL); + } + $result = $this->AbschlusspruefungModel->load( + array('abschlusspruefung_id' => $abschlusspruefung_id) + ); + $data = $this->getDataOrTerminateWithError($result); + $student_uid = current($data)->student_uid; + + $this->_checkAllowedStgsFromUid($student_uid, $allowedStgs); + } + } + + private function _checkAllowedStgsFromUid($student_uid, $allowedStgs) + { + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->loadWhere(['student_uid' => $student_uid]); + $data = $this->getDataOrTerminateWithError($result); + $studiengang_kz = current($data)->studiengang_kz; + + if (!in_array($studiengang_kz, $allowedStgs)) + { + return $this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL); + } + } + + public function getAbschlusspruefung($student_uid) + { + $result = $this->AbschlusspruefungModel->getAbschlusspruefungForPrestudent($student_uid); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function loadAbschlusspruefung() + { + $abschlusspruefung_id = $this->input->post('id'); + + $this->AbschlusspruefungModel->addSelect('lehre.tbl_abschlusspruefung.*'); + $this->AbschlusspruefungModel->addSelect(" + CASE + WHEN pruefer1 IS NOT NULL + THEN CONCAT(p1.nachname, ' ', p1.vorname, COALESCE(' ' || p1.titelpre, '')) + ELSE NULL + END AS p1 + "); + $this->AbschlusspruefungModel->addSelect(" + CASE + WHEN pruefer2 IS NOT NULL + THEN CONCAT(p2.nachname, ' ', p2.vorname, COALESCE(' ' || p2.titelpre, '')) + ELSE NULL + END AS p2 + "); + $this->AbschlusspruefungModel->addSelect(" + CASE + WHEN pruefer3 IS NOT NULL + THEN CONCAT(p3.nachname, ' ', p3.vorname, COALESCE(' ' || p3.titelpre, '')) + ELSE NULL + END AS p3 + "); + $this->AbschlusspruefungModel->addSelect(" + CASE + WHEN vorsitz IS NOT NULL + THEN CONCAT(pv.nachname, ' ', pv.vorname, COALESCE(' ' || pv.titelpre, ''), ' (', ben.uid , ')' ) + ELSE NULL + END AS pv + "); + $this->AbschlusspruefungModel->addJoin('public.tbl_benutzer ben', 'ON (ben.uid = lehre.tbl_abschlusspruefung.vorsitz)', 'LEFT'); + $this->AbschlusspruefungModel->addJoin('public.tbl_person pv', 'ON (pv.person_id = ben.person_id)', 'LEFT'); + $this->AbschlusspruefungModel->addJoin('public.tbl_person p1', 'ON (p1.person_id = lehre.tbl_abschlusspruefung.pruefer1)', 'LEFT'); + $this->AbschlusspruefungModel->addJoin('public.tbl_person p2', 'ON (p2.person_id = lehre.tbl_abschlusspruefung.pruefer2)', 'LEFT'); + $this->AbschlusspruefungModel->addJoin('public.tbl_person p3', 'ON (p3.person_id = lehre.tbl_abschlusspruefung.pruefer3)', 'LEFT'); + $result = $this->AbschlusspruefungModel->loadWhere( + array('abschlusspruefung_id' => $abschlusspruefung_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function getTypenAbschlusspruefung() + { + $this->load->model('education/Pruefungstyp_model', 'PruefungstypModel'); + + $result = $this->PruefungstypModel->loadWhere( + array('abschluss' => true) + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getTypenAntritte() + { + $this->load->model('education/Pruefungsantritt_model', 'PruefungsantrittModel'); + + $result = $this->PruefungsantrittModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getBeurteilungen() + { + $this->load->model('education/Abschlussbeurteilung_model', 'AbschlussbeurteilungModel'); + + $result = $this->AbschlussbeurteilungModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getAkadGrade() + { + $studiengang_kz= $this->input->post('studiengang_kz'); + + + $this->load->model('education/Akadgrad_model', 'AkadgradModel'); + + $result = $this->AkadgradModel->loadWhere( + array('studiengang_kz' => $studiengang_kz) + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getTypStudiengang() + { + $studiengang_kz= $this->input->post('studiengang_kz'); + + /* 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()); + }*/ + + + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $result = $this->StudiengangModel->loadWhere( + array('studiengang_kz' => $studiengang_kz) + ); + $data = $this->getDataOrTerminateWithError($result); + + $typStudiengang = current($data)->typ; + + $this->terminateWithSuccess($typStudiengang); + } + + public function getMitarbeiter($searchString) + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $result = $this->MitarbeiterModel->searchMitarbeiter($searchString, 'mitAkadGrad'); + + if (isError($result)) { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess($result ?: []); + } + + public function getPruefer($searchString) + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $result = $this->MitarbeiterModel->searchMitarbeiter($searchString, 'ohneMaUid'); + + if (isError($result)) { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + $this->terminateWithSuccess($result ?: []); + } + + public function getNoten() + { + $this->load->model('education/Note_model', 'NoteModel'); + + $this->NoteModel->addOrder('note', 'ASC'); + $result = $this->NoteModel->load(); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function insertAbschlusspruefung() + { + $this->load->library('form_validation'); + + $student_uid = $this->input->post('uid'); + + if(!$student_uid) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('pruefungstyp_kurzbz', 'Typ', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Typ']) + ]); + + $this->form_validation->set_rules('akadgrad_id', 'AkadGrad', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'AkadGrad']) + ]); + + $this->form_validation->set_rules('datum', 'Datum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Datum']) + ]); + + $this->form_validation->set_rules('sponsion', 'Sponsion', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Sponsion']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->AbschlusspruefungModel->insert([ + 'student_uid' => $student_uid, + 'pruefungstyp_kurzbz' => $formData['pruefungstyp_kurzbz'], + 'akadgrad_id' => $formData['akadgrad_id'], + 'vorsitz' => $formData['vorsitz'], + 'pruefungsantritt_kurzbz' => $formData['pruefungsantritt_kurzbz'], + 'abschlussbeurteilung_kurzbz' => $formData['abschlussbeurteilung_kurzbz'], + 'datum' => $formData['datum'], //TODO(Manu) check if minute format like FAS + 'sponsion' => $formData['sponsion'], + 'pruefer1' => $formData['pruefer1'], + 'pruefer2' => $formData['pruefer2'], + 'pruefer3' => $formData['pruefer3'], + 'protokoll' => $formData['protokoll'], + 'note' => $formData['note'], + 'anmerkung' => $formData['anmerkung'], + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function updateAbschlusspruefung() + { + $this->load->library('form_validation'); + + $abschlusspruefung_id = $this->input->post('id'); + + if(!$abschlusspruefung_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Abschlussprüfung ID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + $vorsitz = isset($formData['vorsitz']['mitarbeiter_uid']) ? $formData['vorsitz']['mitarbeiter_uid'] : $formData['vorsitz']; + $pruefer1 = isset($formData['pruefer1']['person_id']) ? $formData['pruefer1']['person_id'] : $formData['pruefer1']; + $pruefer2 = isset($formData['pruefer2']['person_id']) ? $formData['pruefer2']['person_id'] : $formData['pruefer2']; + $pruefer3 = isset($formData['pruefer3']['person_id']) ? $formData['pruefer3']['person_id'] : $formData['pruefer3']; + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('pruefungstyp_kurzbz', 'Typ', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Typ']) + ]); + + $this->form_validation->set_rules('akadgrad_id', 'AkadGrad', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'AkadGrad']) + ]); + + $this->form_validation->set_rules('datum', 'Datum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Datum']) + ]); + + $this->form_validation->set_rules('sponsion', 'Sponsion', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Sponsion']) + ]); + + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->AbschlusspruefungModel->update( + [ + 'abschlusspruefung_id' => $abschlusspruefung_id + ], + [ + 'student_uid' => $formData['student_uid'], + 'pruefungstyp_kurzbz' => $formData['pruefungstyp_kurzbz'], + 'akadgrad_id' => $formData['akadgrad_id'], + 'vorsitz' => $vorsitz, + 'pruefungsantritt_kurzbz' => $formData['pruefungsantritt_kurzbz'], + 'abschlussbeurteilung_kurzbz' => $formData['abschlussbeurteilung_kurzbz'], + 'datum' => $formData['datum'], + 'sponsion' => $formData['sponsion'], + 'pruefer1' => $pruefer1, + 'pruefer2' => $pruefer2, + 'pruefer3' => $pruefer3, + 'protokoll' => $formData['protokoll'], + 'note' => $formData['note'], + 'anmerkung' => $formData['anmerkung'], + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteAbschlusspruefung() + { + $abschlusspruefung_id = $this->input->post('id'); + + $result = $this->AbschlusspruefungModel->delete( + array('abschlusspruefung_id' => $abschlusspruefung_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 checkForExistingExams() + { + $warning = false; + $output = []; + + $student_uids = $this->input->post('uids'); + + if (empty($student_uids)) { + throw new InvalidArgumentException("Keine UID(s) übergeben."); + } + + if( !is_array($student_uids) ) + { + $student_uids = array($student_uids); + } + + foreach ($student_uids as $uid) + { + $result = $this->AbschlusspruefungModel->loadWhere( + array('student_uid' => $uid) + ); + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) + { + $warning = true; + $output[] = $uid; + } + } + if($warning) + { + $uids = is_array($output) ? implode(", ", $output) : $output; + return $this->terminateWithError($this->p->t('abschlusspruefung', 'error_studentOhneFinalExam', ['id'=> $uids]), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess('step3'); + } + + /* + * returns list of all Mitarbeiter + * as key value list to be used in select or autocomplete + */ + public function getAllMitarbeiter() + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $sql = " + SELECT + ma.mitarbeiter_uid as mitarbeiter_uid, + CONCAT(p.nachname, ' ', p.vorname, ' (', ma.mitarbeiter_uid, ')') as label + FROM + public.tbl_mitarbeiter ma + JOIN public.tbl_benutzer bn ON (bn.uid = ma.mitarbeiter_uid) + JOIN public.tbl_person p ON (p.person_id = bn.person_id) + ORDER BY + p.nachname ASC + "; + + $result = $this->MitarbeiterModel->execReadOnlyQuery($sql); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /* + * returns list of all Persons + * as key value list to be used in select or autocomplete + */ + public function getAllPersons() + { + $this->load->model('person/Person_model', 'PersonModel'); + + $sql = " + SELECT + p.vorname, p.nachname, p.person_id, + CONCAT(p.nachname, ' ', p.vorname) as label + FROM + public.tbl_person p + -- JOIN public.tbl_benutzer bn ON (p.person_id = bn.person_id) + -- and bn.aktiv = 'true' + ORDER BY + p.nachname ASC + "; + + //TODO(manu) check if filter active benutzer + + $result = $this->PersonModel->execReadOnlyQuery($sql); + $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..d14111e99 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Address.php @@ -0,0 +1,75 @@ +. + */ + +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 + ]); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + 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 = null) + { + $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', 'required|numeric|less_than[10000]', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ']), + 'less_than' => $this->p->t('ui', 'error_fieldLessThan10000', ['field' => 'PLZ']) + ]); + + 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/Akte.php b/application/controllers/api/frontend/v1/stv/Akte.php new file mode 100644 index 000000000..1d38c96d4 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Akte.php @@ -0,0 +1,70 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * Controller for downloading Akte + */ +class Akte extends Auth_Controller +{ + /** + * Calls the parent's constructor and prepares libraries and phrases + */ + public function __construct() + { + parent::__construct([ + 'download' => ['admin:w', 'assistenz:w'], + ]); + + // Load models + $this->load->model('crm/Akte_model', 'AkteModel'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * + * Downloads an Akte + */ + public function download() + { + $akte_id = $this->input->get('akte_id'); + + if (!is_numeric($akte_id)) $this->terminateWithError('akte Id missing'); + + $result = $this->AkteModel->load($akte_id); + + if (!hasData($result)) $this->terminateWithError('Akte not found'); + + $data = getData($result)[0]; + + if (isset($data->inhalt) && $data->inhalt != '') + { + header('Content-Description: File Transfer'); + header('Content-Type: '. $data->mimetype); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + header('Content-Disposition: attachment; filename="'.$data->titel.'"'); + echo base64_decode($data->inhalt); + die(); + } + } +} diff --git a/application/controllers/api/frontend/v1/stv/Anrechnungen.php b/application/controllers/api/frontend/v1/stv/Anrechnungen.php new file mode 100644 index 000000000..251e2d5bd --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Anrechnungen.php @@ -0,0 +1,256 @@ + ['admin:r', 'assistenz:r'], + 'deleteAnrechnung' => ['admin:rw', 'assistenz:rw'], + 'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'], + 'getBegruendungen' => ['admin:r', 'assistenz:r'], + 'getLektoren' => ['admin:r', 'assistenz:r'], + 'getLvsKompatibel' => ['admin:r', 'assistenz:r'], + 'insertAnrechnung' => ['admin:rw', 'assistenz:rw'], + 'loadAnrechnung' => ['admin:rw', 'assistenz:rw'], + 'updateAnrechnung' => ['admin:rw', 'assistenz:rw'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui', 'lehre' + ]); + + // Load models + $this->load->model('education/Anrechnung_model', 'AnrechnungsModel'); + } + + public function getAnrechnungen($prestudent_id) + { + $result = $this->AnrechnungsModel->getAnrechnungsData($prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getBegruendungen() + { + $this->load->model('education/Anrechnungbegruendung_model', 'AnrechnungbegrueundungsModel'); + + $result = $this->AnrechnungbegrueundungsModel->load(); + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getLehrveranstaltungen($prestudent_id) + { + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $result = $this->PrestudentstatusModel->getLastStatus($prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + $studienplan_id = current($data)->studienplan_id; + + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $result = $this->LehrveranstaltungModel->getLvsByStudienplanId($studienplan_id); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getLvsKompatibel($lehrveranstaltung_id) + { + $this->AnrechnungsModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'ON (lv.lehrveranstaltung_id = lehre.tbl_anrechnung.lehrveranstaltung_id)'); + $result = $this->AnrechnungsModel->loadWhere( + ['lehrveranstaltung_id_kompatibel' => $lehrveranstaltung_id] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getLektoren($studiengang_kz) + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $result = $this->MitarbeiterModel->getLektoren($studiengang_kz); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function insertAnrechnung() + { + $this->load->library('form_validation'); + + $prestudent_id = $this->input->post('prestudent_id'); + + if(!$prestudent_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + $_POST['lehrveranstaltung_id'] = + (isset($formData['lehrveranstaltung_id']) && !empty($formData['lehrveranstaltung_id'])) + ? $formData['lehrveranstaltung_id'] + : null; + $_POST['lehrveranstaltung_id_kompatibel'] = + (isset($formData['lehrveranstaltung_id_kompatibel']) && !empty($formData['lehrveranstaltung_id_kompatibel'])) + ? $formData['lehrveranstaltung_id_kompatibel'] + : null; + $_POST['begruendung'] = + (isset($formData['begruendung_id']) && !empty($formData['begruendung_id'])) + ? $formData['begruendung_id'] + : null; + $_POST['genehmigtVon'] = (isset($formData['genehmigt_von']) && !empty($formData['genehmigt_von'])) + ? $formData['genehmigt_von'] + : null; + + $this->form_validation->set_rules('lehrveranstaltung_id', 'Lehrveranstaltung_id', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehrveranstaltung']) + ]); + + $this->form_validation->set_rules('begruendung', 'Begruendung', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Begruendung']) + ]); + + if($_POST['begruendung'] == 2) + { + $this->form_validation->set_rules('lehrveranstaltung_id_kompatibel', 'Lehrveranstaltung_id', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehrveranstaltung Kompatibel']) + ]); + } + + $this->form_validation->set_rules('genehmigtVon', 'GenehmigtVon', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'GenehmigtVon']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->AnrechnungsModel->insert( + [ + 'prestudent_id' => $prestudent_id, + 'lehrveranstaltung_id' => $_POST['lehrveranstaltung_id'], + 'lehrveranstaltung_id_kompatibel' => $_POST['lehrveranstaltung_id_kompatibel'], + 'begruendung_id' => $_POST['begruendung'], + 'genehmigt_von' => $_POST['genehmigtVon'] + ] + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function loadAnrechnung($anrechnung_id) + { + $this->AnrechnungsModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'ON (lv.lehrveranstaltung_id = lehre.tbl_anrechnung.lehrveranstaltung_id)'); + $result = $this->AnrechnungsModel->loadWhere( + array('anrechnung_id' => $anrechnung_id) + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function updateAnrechnung() + { + $this->load->library('form_validation'); + + $anrechnung_id = $this->input->post('anrechnung_id'); + + if(!$anrechnung_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Anrechnung UID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + $_POST['lehrveranstaltung_id'] = + (isset($formData['lehrveranstaltung_id']) && !empty($formData['lehrveranstaltung_id'])) + ? $formData['lehrveranstaltung_id'] + : null; + $_POST['lehrveranstaltung_id_kompatibel'] = + (isset($formData['lehrveranstaltung_id_kompatibel']) && !empty($formData['lehrveranstaltung_id_kompatibel'])) + ? $formData['lehrveranstaltung_id_kompatibel'] + : null; + $_POST['begruendung'] = (isset($formData['begruendung_id']) && !empty($formData['begruendung_id'])) ? $formData['begruendung_id'] : null; + $_POST['genehmigtVon'] = (isset($formData['genehmigt_von']) && !empty($formData['genehmigt_von'])) ? $formData['genehmigt_von'] : null; + + $this->form_validation->set_rules('lehrveranstaltung_id', 'Lehrveranstaltung_id', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehrveranstaltung']) + ]); + + $this->form_validation->set_rules('begruendung', 'Begruendung', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Begruendung']) + ]); + + if($_POST['begruendung'] == 2) + { + $this->form_validation->set_rules('lehrveranstaltung_id_kompatibel', 'Lehrveranstaltung_id', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehrveranstaltung Kompatibel']) + ]); + } + + $this->form_validation->set_rules('genehmigtVon', 'GenehmigtVon', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'GenehmigtVon']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->AnrechnungsModel->update( + [ + 'anrechnung_id' => $anrechnung_id, + ], + [ + + 'lehrveranstaltung_id' => $_POST['lehrveranstaltung_id'], + 'lehrveranstaltung_id_kompatibel' => $_POST['lehrveranstaltung_id_kompatibel'], + 'begruendung_id' => $_POST['begruendung'], + 'genehmigt_von' => $_POST['genehmigtVon'] + ] + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteAnrechnung($anrechnung_id) + { + // Start DB transaction + $this->db->trans_begin(); + + //delete anrechnung_id of table tbl_anrechnung_anrechnungstatus + $this->load->model('education/Anrechnunganrechnungstatus_model','AnrechnungAnrechnungstatusModel'); + $result = $this->AnrechnungAnrechnungstatusModel->delete( + array('anrechnung_id' => $anrechnung_id) + ); + $this->getDataOrTerminateWithError($result); + + //delete anrechnung_id of table tbl_anrechnung + $result = $this->AnrechnungsModel->delete( + array('anrechnung_id' => $anrechnung_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->db->trans_commit(); + + $this->terminateWithSuccess($data); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Archiv.php b/application/controllers/api/frontend/v1/stv/Archiv.php new file mode 100644 index 000000000..cc636951d --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Archiv.php @@ -0,0 +1,272 @@ +. + */ + +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 archive documents + * Listens to ajax post calls to change the archive documents + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Archiv extends FHCAPI_Controller +{ + /** + * Calls the parent's constructor and prepares libraries and phrases + */ + public function __construct() + { + parent::__construct([ + 'getArchiv' => ['admin:r', 'assistenz:r'], + 'getArchivVorlagen' => ['admin:r', 'assistenz:r'], + 'archive' => ['admin:w', 'assistenz:w'], + 'download' => ['admin:w', 'assistenz:w'], + 'update' => ['admin:w'], + 'delete' => ['admin:w', 'assistenz:w'] + ]); + + // Load models + $this->load->model('crm/Akte_model', 'AkteModel'); + $this->load->model('system/Vorlage_model', 'VorlageModel'); + + // Load language phrases + $this->loadPhrases([ + 'archiv' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Get archive documents for a person + + * @return void + */ + public function getArchiv() + { + $person_id = $this->input->get('person_id'); + + $this->load->library('form_validation'); + + 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()); + } + + $result = $this->AkteModel->getArchiv($person_id); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * Get Vorlagen for archiving documents + * @return void + */ + public function getArchivVorlagen() + { + $result = $this->VorlageModel->getArchivVorlagen(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * + * @param + * @return object success or error + */ + public function download() + { + $akte_id = $this->input->get('akte_id'); + + if (!is_numeric($akte_id)) $this->terminateWithError('akte Id missing'); + + $result = $this->AkteModel->load($akte_id); + + + if (!hasData($result)) $this->terminateWithError('Akte not found'); + + $data = $this->getDataOrTerminateWithError($result); + + $data = getData($result)[0]; + //$this->addMeta("daa", $data->inhalt); + + $fileObj = new stdClass(); + if (isset($data->inhalt) && $data->inhalt != '') + { + // Define handle to output stream + $tmpFilePointer = fopen("php://output", 'w'); + $meta_data = stream_get_meta_data($tmpFilePointer); + $filename = $meta_data["uri"]; + fwrite($tmpFilePointer, $data->inhalt); + + header('Content-Description: File Transfer'); + header('Content-Type: '. $data->mimetype); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + //header('Content-Length: ' . filesize($fileObj->file)); + //header("Content-type: $data->mimetype"); + header('Content-Disposition: attachment; filename="'.$data->titel.'"'); + readfile($filename); + //echo base64_decode($data->inhalt); + die(); + //~ $fileObj->file = $data->inhalt; + //~ $fileObj->name = $data->titel; + //~ $fileObj->mimetype = $data->mimetype; + //~ $fileObj->disposition = 'attachment'; + } + else + { + $this->load->library('AkteLib'); + + $result = $this->aktelib->get($akte_id); + } + + /* $fileObj->filename + * $fileObj->file + * $fileObj->name + * $fileObj->mimetype + * $fileObj->disposition*/ + } + + /** + * Updating an Akte + * @return void + */ + public function update() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('akte_id', 'Akte Id', 'required'); + $this->form_validation->set_rules('signiert', 'Signiert', 'is_bool'); + $this->form_validation->set_rules('stud_selfservice', 'Self-Service', 'is_bool'); + + //Events::trigger('konto_update_validation', $this->form_validation); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $id = $this->input->post('akte_id'); + + // get the akte + $result = $this->AkteModel->load($id); + + if (!hasData($result)) $this->terminateWithError("Akte not found!"); + + $akte = getData($result)[0]; + + $allowed = [ + 'signiert', + 'stud_selfservice' + ]; + + $data = [ + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ]; + + // if Akte has Inhalt directly in Akte table + if (isset($_FILES['datei']['tmp_name'])) + { + $this->addMeta('read', "read"); + // update inhalt directly + + // get tmp file + $filename = $_FILES['datei']['tmp_name']; + // open it + $fp = fopen($filename,'r'); + // read it + $content = fread($fp, filesize($filename)); + fclose($fp); + // encode it + $data['inhalt'] = base64_encode($content); + $this->addMeta('content', base64_encode($content)); + } + + + foreach ($allowed as $field) + if ($this->input->post($field) !== null) + $data[$field] = $this->input->post($field); + + $this->addMeta("data", $data); + + $result = $this->AkteModel->update($id, $data); + + $this->getDataOrTerminateWithError($result); + + $result = null; + + $this->terminateWithSuccess($result); + } + + + /** + * Delete archived Akte + * + * @return void + */ + public function delete() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('akte_id', 'Akte ID', 'required'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'has_permissions_for_stg[admin:rw,assistenz:rw]'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $akte_id = $this->input->post('akte_id'); + + $result = $this->AkteModel->load($akte_id); + + if (!hasData($result)) + { + $this->terminateWithError($this->p->t('archiv', 'error_missing', [ + 'akte_id' => $akte_id + ])); + } + + $result = getData($result)[0]; + + if ($result->dokument_kurzbz == 'Ausbvert' + && isset($result->akzeptiertamum) + && !isEmptyString($result->akzeptiertamum) + && !has_permissions_for_stg($this->input->post('studiengang_kz'), 'admin:rw') + ) + { + $this->terminateWithError($this->p->t('archiv', 'nur_admins_loschen_ausbildungsvertraege', [ + 'akte_id' => $akte_id + ])); + } + + $result = $this->AkteModel->delete($akte_id); + if (isError($result)) $this->terminateWithError(getError($result)); + + $this->terminateWithSuccess(); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Aufnahmetermine.php b/application/controllers/api/frontend/v1/stv/Aufnahmetermine.php new file mode 100644 index 000000000..86b739c90 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Aufnahmetermine.php @@ -0,0 +1,413 @@ + ['admin:r', 'assistenz:r'], + 'loadAufnahmetermin' => ['admin:r', 'assistenz:r'], + 'insertAufnahmetermin' => ['admin:rw', 'assistenz:rw'], + 'updateAufnahmetermin' => ['admin:rw', 'assistenz:rw'], + 'deleteAufnahmetermin' => ['admin:rw', 'assistenz:rw'], + 'getListPlacementTests' => ['admin:r', 'assistenz:r'], + 'getListStudyPlans' => ['admin:r', 'assistenz:r'], + 'loadDataRtPrestudent' => ['admin:r', 'assistenz:r'], + 'insertOrUpdateDataRtPrestudent' => ['admin:r', 'assistenz:r'], + 'loadAufnahmegruppen' => ['admin:r', 'assistenz:r'], + 'getResultReihungstest' => ['admin:r', 'assistenz:r'], + 'getZukuenftigeReihungstestStg' => ['admin:r', 'assistenz:r'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'admission' + ]); + + // Load models + $this->load->model('crm/Reihungstest_model', 'ReihungstestModel'); + $this->load->model('crm/RtPerson_model', 'RtPersonModel'); + } + + public function getAufnahmetermine($person_id) + { + $result = $this->ReihungstestModel->getReihungstestPerson($person_id); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function insertAufnahmetermin() + { + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $formData = $this->input->post('formData'); + $person_id = $this->input->post('person_id'); + + if(!$person_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL); + } + + + $rt_id = (isset($formData['rt_id']) && !empty($formData['rt_id'])) ? $formData['rt_id'] : null; + $anmeldedatum = (isset($formData['anmeldedatum']) && !empty($formData['anmeldedatum'])) ? $formData['anmeldedatum'] : null; + $teilgenommen = (isset($formData['teilgenommen']) && !empty($formData['teilgenommen'])) ? $formData['teilgenommen'] : false; + $studienplan_id = (isset($formData['studienplan_id']) && !empty($formData['studienplan_id'])) ? $formData['studienplan_id'] : null; + $punkte = (isset($formData['punkte']) && !empty($formData['punkte'])) ? $formData['punkte'] : null; + + //validation if there is already an RT with chosen data existing + $result = $this->RtPersonModel->loadWhere( + array( + 'rt_id' => $rt_id, + 'person_id' => $person_id, + 'studienplan_id' => $studienplan_id, + ) + ); + $data = getData($result); + if($data) + return $this->terminateWithError("Error", self::ERROR_TYPE_GENERAL); + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('punkte', 'Punkte', 'numeric', [ + 'required' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Punkte']) + ]); + $this->form_validation->set_rules('studienplan_id', 'studienplan_id', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Studienplan']) + ]); + $this->form_validation->set_rules('rt_id', 'Reihungstest_id', 'required', [ + 'is_valid_date' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Reihungstest']) + ]); + $this->form_validation->set_rules('anmeldedatum', 'AnmeldeDatum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Anmeldedatum']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->RtPersonModel->insert([ + 'person_id' => $person_id, + 'rt_id' => $rt_id, + 'anmeldedatum' => $anmeldedatum, + 'teilgenommen' => $teilgenommen, + 'studienplan_id' => $studienplan_id, + 'punkte' => $punkte, + 'insertamum' => date('c'), + 'insertvon' => $authUID, + ]); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function loadAufnahmetermin($rt_person_id) + { + $result = $this->RtPersonModel->loadWhere( + array('rt_person_id' => $rt_person_id) + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function updateAufnahmetermin() + { + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $formData = $this->input->post('formData'); + $rt_person_id = $this->input->post('rt_person_id'); + $person_id = (isset($formData['person_id']) && !empty($formData['person_id'])) ? $formData['person_id'] : null; + + + if(!$person_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL); + } + if(!$rt_person_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'RT_Person ID']), self::ERROR_TYPE_GENERAL); + } + + $rt_id = (isset($formData['rt_id']) && !empty($formData['rt_id'])) ? $formData['rt_id'] : null; + $anmeldedatum = (isset($formData['anmeldedatum']) && !empty($formData['anmeldedatum'])) ? $formData['anmeldedatum'] : null; + $teilgenommen = (isset($formData['teilgenommen']) && !empty($formData['teilgenommen'])) ? $formData['teilgenommen'] : false; + $studienplan_id = (isset($formData['studienplan_id']) && !empty($formData['studienplan_id'])) ? $formData['studienplan_id'] : null; + $punkte = (isset($formData['punkte']) && !empty($formData['punkte'])) ? $formData['punkte'] : null; + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('punkte', 'Punkte', 'numeric', [ + 'required' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Punkte']) + ]); + $this->form_validation->set_rules('studienplan_id', 'studienplan_id', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Studienplan']) + ]); + $this->form_validation->set_rules('rt_id', 'Reihungstest_id', 'required', [ + 'is_valid_date' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Reihungstest']) + ]); + + $this->form_validation->set_rules('anmeldedatum', 'AnmeldeDatum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Anmeldedatum']) + ]); + + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->RtPersonModel->update( + [ + 'rt_person_id' => $rt_person_id, + ], + [ + 'rt_id' => $rt_id, + 'anmeldedatum' => $anmeldedatum, + 'teilgenommen' => $teilgenommen, + 'studienplan_id' => $studienplan_id, + 'punkte' => $punkte, + 'insertamum' => date('c'), + 'insertvon' => $authUID, + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteAufnahmetermin($rt_person_id) + { + $result = $this->RtPersonModel->delete( + array('rt_person_id' => $rt_person_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function getListPlacementTests($prestudent_id) + { + if(!$prestudent_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + } + + //get studienplan array + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + + $this->PrestudentstatusModel->addSelect('*'); + $this->PrestudentstatusModel->addSelect('sp.studienplan_id'); + + $this->PrestudentstatusModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); + + $result = $this->PrestudentstatusModel->loadWhere( + array( + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => 'Interessent' + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $studienplan_arr = []; + $include_ids = []; + foreach ($data as $item) + { + if($item->studienplan_id != null) + $studienplan_arr[] = $item->studienplan_id; + } + + //get Placementtests Person + $person_id = $this->_getPersonId($prestudent_id); + $resultRt = $this->ReihungstestModel->getReihungstestPerson($person_id); + + $dataRt = $this->getDataOrTerminateWithError($resultRt); + + foreach ($dataRt as $item) + { + if(!in_array($item->studienplan_id, $studienplan_arr)) + $studienplan_arr[] = $item->studienplan_id; + if(!in_array($item->rt_id, $include_ids) && ($item->rt_id != null)) + $include_ids[] = $item->rt_id; + } + + $result = $this->ReihungstestModel->getReihungstestByStudyPlanAndIds($studienplan_arr, $include_ids); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getListStudyPlans($person_id) + { + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $result = $this->StudienplanModel->getStudienplaeneForPerson($person_id); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function loadDataRtPrestudent($prestudent_id) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $this->PrestudentModel->addSelect(["reihungstestangetreten"]); + $this->PrestudentModel->addSelect(["rt_gesamtpunkte"]); + $this->PrestudentModel->addSelect(["aufnahmegruppe_kurzbz"]); + $result = $this->PrestudentModel->loadWhere( + array('prestudent_id' => $prestudent_id) + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function insertOrUpdateDataRtPrestudent() + { + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $formData = $this->input->post('formData'); + $prestudent_id = $this->input->post('prestudent_id'); + + if(!$prestudent_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + } + $rt_gesamtpunkte = + (isset($formData['rt_gesamtpunkte']) && !empty($formData['rt_gesamtpunkte'])) + ? $formData['rt_gesamtpunkte'] + : null; + $reihungstestangetreten = + (isset($formData['reihungstestangetreten']) && !empty($formData['reihungstestangetreten'])) + ? $formData['reihungstestangetreten'] + : null; + $aufnahmegruppe_kurzbz = + (isset($formData['aufnahmegruppe_kurzbz']) && !empty($formData['aufnahmegruppe_kurzbz'])) + ? $formData['aufnahmegruppe_kurzbz'] + : null; + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('rt_gesamtpunkte', 'Rt_gesamtpunkte', 'numeric', [ + 'required' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Rt_gesamtpunkte']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $result = $this->PrestudentModel->update( + [ + 'prestudent_id' => $prestudent_id, + ], + [ + 'reihungstestangetreten' => $reihungstestangetreten, + 'rt_gesamtpunkte' => $rt_gesamtpunkte, + 'aufnahmegruppe_kurzbz' => $aufnahmegruppe_kurzbz, + 'updateamum' => date('c'), + 'updatevon' => $authUID, + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function loadAufnahmegruppen() + { + $uid = $this->input->get('uid'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + + $this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + + $result = $this->BenutzergruppeModel->loadAufnahmegruppen($uid, $studiensemester_kurzbz); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(($data)); + } + + public function getResultReihungstest() + { + $person_id = $this->input->get('person_id'); + $punkte = $this->input->get('punkte'); + $reihungstest_id = $this->input->get('reihungstest_id'); + + if(!$reihungstest_id) + { + $this->terminateWithSuccess(null); + } + + //for gewichtung + $studiengang_kz = $this->input->get('studiengang_kz'); + + $this->load->model('testtool/Ablauf_model', 'AblaufModel'); + $result = $this->AblaufModel->getAblaufGebieteAndGewichte($studiengang_kz); + $data = $this->getDataOrTerminateWithError($result); + + $weightedArray = []; + foreach ($data as $abl) + { + $weightedArray[$abl->gebiet_id] = $abl->gewicht; + } + + $result = $this->ReihungstestModel->getReihungstestErgebnisPerson($person_id, $punkte, $reihungstest_id, $weightedArray); + +/* if (isError($result)) + { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + }*/ + + $this->terminateWithSuccess($result); + } + + public function getZukuenftigeReihungstestStg() + { + $studiengang_kz = $this->input->get('studiengang_kz'); + if(!$studiengang_kz) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Studiengang_kz']), self::ERROR_TYPE_GENERAL); + } + + $result = $this->ReihungstestModel->getZukuenftigeReihungstestStg($studiengang_kz); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + private function _getPersonId($prestudent_id) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->loadWhere( + ['prestudent_id' => $prestudent_id] + ); + + $data = $this->getDataOrTerminateWithError($result); + $person = current($data); + + return $person->person_id; + } +} 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..d52016943 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -0,0 +1,544 @@ +. + */ + +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', + 'abschlusspruefung' + ]); + + // Load Config + $this->load->config('stv'); + } + + public function student() + { + $result = []; + $config = $this->config->item('tabs'); + + $result['details'] = [ + 'title' => $this->p->t('stv', 'tab_details'), + 'component' => './Stv/Studentenverwaltung/Details/Details.js', + 'config' => $config['details'] + ]; + + $result['notes'] = [ + 'title' => $this->p->t('stv', 'tab_notes'), + 'component' => './Stv/Studentenverwaltung/Details/Notizen.js', + 'config' => $config['notes'], + 'showSuffix' => ($config['notes']['showCountNotes'] ?? false), + 'suffixhelper' => APP_ROOT . 'public/js/helpers/Stv/Studentenverwaltung/Details/Notizen/NotizenSuffixHelper.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', + 'config' => $config['prestudent'] + ]; + $result['status'] = [ + 'title' => 'Status', + 'component' => './Stv/Studentenverwaltung/Details/MultiStatus.js' + ]; + $result['documents'] = [ + 'title' => $this->p->t('stv', 'tab_documents'), + 'component' => './Stv/Studentenverwaltung/Details/Dokumente.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' + ]; + $result['groups'] = [ + 'title' => $this->p->t('stv', 'tab_groups'), + 'component' => './Stv/Studentenverwaltung/Details/Gruppen.js' + ]; + $result['messages'] = [ + 'title' => $this->p->t('stv', 'tab_messages'), + 'component' => './Stv/Studentenverwaltung/Details/Messages.js' + ]; + + $result['grades'] = [ + 'title' => $this->p->t('stv', 'tab_grades'), + 'component' => './Stv/Studentenverwaltung/Details/Noten.js', + 'showOnlyWithUid' => true, + 'config' => [ + 'usePoints' => defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE, + 'edit' => 'both', // Possible values: both|header|inline + 'delete' => 'both', // Possible values: both|header|inline + 'documents' => 'both', // Possible values: both|header|inline + 'documentslist' => $this->gradesDocumentsList() + ] + ]; + + $result['exam'] = [ + 'title' => $this->p->t('stv', 'tab_exam'), + 'component' => './Stv/Studentenverwaltung/Details/Pruefung.js' + ]; + + $result['exemptions'] = [ + 'title' => $this->p->t('lehre', 'anrechnungen'), + 'component' => './Stv/Studentenverwaltung/Details/Anrechnungen.js', + 'config' => $config['exemptions'] + ]; + + $result['finalexam'] = [ + 'title' => $this->p->t('stv', 'tab_finalexam'), + 'component' => './Stv/Studentenverwaltung/Details/Abschlusspruefung.js', + 'config' => $config['finalexam'] + ]; + + $result['mobility'] = [ + 'title' => $this->p->t('stv', 'tab_mobility'), + 'component' => './Stv/Studentenverwaltung/Details/Mobility.js' + ]; + + $result['archive'] = [ + 'title' => $this->p->t('stv', 'tab_archive'), + 'component' => './Stv/Studentenverwaltung/Details/Archiv.js', + 'config' => [ + 'showEdit' => $this->permissionlib->isBerechtigt('admin') + ] + ]; + + $result['jointstudies'] = [ + 'title' => $this->p->t('stv', 'tab_jointstudies'), + 'component' => './Stv/Studentenverwaltung/Details/JointStudies.js' + ]; + + $result['coursedates'] = [ + 'title' => $this->p->t('stv', 'tab_courseDates'), + 'component' => './Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine.js' + ]; + + $result['admissionDates'] = [ + 'title' => $this->p->t('stv', 'tab_admissionDates'), + 'component' => './Stv/Studentenverwaltung/Details/Aufnahmetermine.js' + ]; + + $result['functions'] = [ + 'title' => $this->p->t('stv', 'tab_functions'), + 'component' => './Stv/Studentenverwaltung/Details/Funktionen.js' + ]; + + Events::trigger('stv_conf_student', function & () use (&$result) { + return $result; + }); + + $sortConfig = $this->config->item('student_tab_order'); + + $this->terminateWithSuccess($this->sortTabList($result, $sortConfig)); + } + + public function students() + { + $result = []; + $config = $this->config->item('tabs'); + $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') + ] + ]; + $result['finalexam'] = [ + 'title' => $this->p->t('stv', 'tab_finalexam'), + 'component' => './Stv/Studentenverwaltung/Details/Abschlusspruefung.js', + 'config' => $config['finalexam'] + ]; + $result['archive'] = [ + 'title' => $this->p->t('stv', 'tab_archive'), + 'component' => './Stv/Studentenverwaltung/Details/Archiv.js', + 'config' => [ + 'showEdit' => $this->permissionlib->isBerechtigt('admin') + ] + ]; + + Events::trigger('stv_conf_students', function & () use (&$result) { + return $result; + }); + + $sortConfig = $this->config->item('students_tab_order'); + + $this->terminateWithSuccess($this->sortTabList($result, $sortConfig)); + } + + 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(); + } + + /** + * Helper function to generate the default documentslist config for the + * grades tab. + * + * The resulting array consists of elements which are associative arrays + * that can have the following entries: + * title (required) on the first level this can be HTML code. + * permissioncheck (optional) an URL to an FHCAPI endpoint which returns + * true or false. + * link (optional) an URL that will be called if "action" and + * "children" are not defined. + * action (optional) an associative array that describes an + * POST action that will be called if "children" is + * not defined. + * It can have the following entries: + * - url (required) an URL to an FHCAPI endpoint. + * - post (optional) an associative array with the POST data to + * be sent. + * - response (optional) a string that will be displayed on success. + * children (optional) an array of child elements + * + * All strings that start with { and end with } in the URLs and the + * actions post parameter will be replaced with the corresponding + * attribute of the current dataset (e.G: {uid} will be replaced with the + * uid of the current dataset) + * + * @return array + */ + protected function gradesDocumentsList() + { + $permissioncheck = site_url("api/frontend/v1/documents/permissionAlternativeFormat/{studiengang_kz}"); + + $title_ger = $this->p->t("global", "deutsch"); + $title_eng = $this->p->t("global", "englisch"); + $title_ff = $this->p->t("stv", "document_certificate"); + $title_lv = $this->p->t("stv", "document_coursecertificate"); + + $link_ff = "documents/export/" . + "zertifikat.rdf.php/" . + "Zertifikat" . + "?stg_kz={studiengang_kz_lv}" . + "&uid={uid}" . + "&ss={studiensemester_kurzbz}" . + "&lvid={lehrveranstaltung_id}"; + $link_lv_ger = "documents/export/" . + "lehrveranstaltungszeugnis.rdf.php/" . + "LVZeugnis" . + "?stg_kz={studiengang_kz}" . + "&uid={uid}" . + "&ss={studiensemester_kurzbz}" . + "&lvid={lehrveranstaltung_id}"; + $link_lv_eng = "documents/export/" . + "lehrveranstaltungszeugnis.rdf.php/" . + "LVZeugnisEng" . + "?stg_kz={studiengang_kz}" . + "&uid={uid}" . + "&ss={studiensemester_kurzbz}" . + "&lvid={lehrveranstaltung_id}"; + + $archive_url = "api/frontend/v1/documents/archiveSigned"; + $archive_response = $this->p->t("stv", "document_signed_and_archived"); + $archive_post_ff = [ + "xml" => "zertifikat.rdf.php", + "xsl" => "Zertifikat", + "stg_kz" => "{studiengang_kz_lv}", + "uid" => "{uid}", + "ss" => "{studiensemester_kurzbz}", + "lvid" => "{lehrveranstaltung_id}" + ]; + $archive_post_lv_ger = [ + "xml" => "lehrveranstaltungszeugnis.rdf.php", + "xsl" => "LVZeugnis", + "stg_kz" => "{studiengang_kz}", + "uid" => "{uid}", + "ss" => "{studiensemester_kurzbz}", + "lvid" => "{lehrveranstaltung_id}" + ]; + $archive_post_lv_eng = [ + "xml" => "lehrveranstaltungszeugnis.rdf.php", + "xsl" => "LVZeugnisEng", + "stg_kz" => "{studiengang_kz}", + "uid" => "{uid}", + "ss" => "{studiensemester_kurzbz}", + "lvid" => "{lehrveranstaltung_id}" + ]; + + $list = [ + [ + 'title' => '', + 'children' => [ + [ + 'title' => $title_ff, + 'link' => site_url($link_ff) + ], + [ + 'title' => $title_lv, + 'children' => [ + [ + 'title' => $title_ger, + 'link' => site_url($link_lv_ger), + 'children' => [ + [ + 'title' => 'PDF', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_ger) + ], + [ + 'title' => 'DOC', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_ger . "&output=doc") + ], + [ + 'title' => 'ODT', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_ger . "&output=odt") + ] + ] + ], + [ + 'title' => $title_eng, + 'link' => site_url($link_lv_eng), + 'children' => [ + [ + 'title' => 'PDF', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_eng) + ], + [ + 'title' => 'DOC', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_eng . "&output=doc") + ], + [ + 'title' => 'ODT', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_eng . "&output=odt") + ] + ] + ] + ] + ] + ] + ], + [ + 'title' => '', + 'children' => [ + [ + 'title' => $title_ff, + 'action' => [ + 'url' => site_url($archive_url), + 'post' => $archive_post_ff, + 'response' => $archive_response + ] + ], + [ + 'title' => $title_lv, + 'children' => [ + [ + 'title' => $title_ger, + 'action' => [ + 'url' => site_url($archive_url), + 'post' => $archive_post_lv_ger, + 'response' => $archive_response + ] + ], + [ + 'title' => $title_eng, + 'action' => [ + 'url' => site_url($archive_url), + 'post' => $archive_post_lv_eng, + 'response' => $archive_response + ] + ] + ] + ] + ] + ] + ]; + + return $list; + } + + /** + * Sort tab list + * + * @param array $input + * @param array $config + * + * @return array + */ + protected function sortTabList($input, $config) + { + // prepare config + if (!$config || !is_array($config)) + $config = []; + else + $config = array_flip($config); + + // fill missing items in config + foreach (array_keys($input) as $key) { + if (!isset($config[$key])) + $config[$key] = count($config); + } + + // do the sorting + uksort($input, function ($a, $b) use ($config) { + return $config[$a] - $config[$b]; + }); + + return $input; + } +} diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php new file mode 100644 index 000000000..18c976eb6 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -0,0 +1,569 @@ + ['admin:r', 'assistenz:r'], + 'getDocumentsAccepted' => ['admin:r', 'assistenz:r'], + 'deleteZuordnung' => ['admin:rw', 'assistenz:rw'], + 'createZuordnung' => ['admin:rw', 'assistenz:rw'], + 'loadAkte' => ['admin:rw', 'assistenz:rw'], + 'deleteAkte' => ['admin:rw', 'assistenz:rw'], + 'updateAkte' => ['admin:rw', 'assistenz:rw'], + 'getDoktypen' => ['admin:r', 'assistenz:r'], + 'uploadDokument' => ['admin:rw', 'assistenz:rw'], + 'download' => ['admin:rw', 'assistenz:rw'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + $this->load->library('DmsLib', array('who' => getAuthUID())); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'dokumente' + ]); + + // Load models + $this->load->model('crm/Akte_model', 'AkteModel'); + $this->load->model('crm/Dokument_model', 'DokumentModel'); + $this->load->model('crm/Dokumentprestudent_model', 'DokumentprestudentModel'); + + //TODO(Manu) check additional Berechtigungen + //TODO(Manu) check if using dokument lib instead of dokument model? + } + + public function getDocumentsUnaccepted($prestudent_id, $studiengang_kz) + { + if(!$prestudent_id) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + + if (!is_numeric($prestudent_id)) + $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + + if(!$studiengang_kz) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiengang_kz']), self::ERROR_TYPE_GENERAL); + + $person_id = $this->_getPersonId($prestudent_id); + $result = $this->DokumentModel->getUnacceptedDocuments($prestudent_id, $person_id); + + $dataAkteUnaccepted = $this->getDataOrTerminateWithError($result); + $resultMd = $this->_getMissingDocuments($studiengang_kz, $prestudent_id); + + $data = $this->_mergeDocuments($dataAkteUnaccepted, $resultMd); + + $this->terminateWithSuccess($data); + } + + public function getDocumentsAccepted($prestudent_id, $studiengang_kz) + { + if(!$prestudent_id) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + + if (!is_numeric($prestudent_id)) + $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + + if(!$studiengang_kz) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiengang_kz']), self::ERROR_TYPE_GENERAL); + + $resultPreDoc = $this->_getPrestudentDokumente($prestudent_id); + + $arrayAccepted = []; + $person_id = $this->_getPersonId($prestudent_id); + + $docNames = array_map(function ($item) { + return $item->dokument_kurzbz; + }, $resultPreDoc); + + foreach($docNames as $doc) + { + $result = $this->AkteModel->getAktenFAS($person_id, $doc, $studiengang_kz, $prestudent_id, true); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (hasData($result)) + { + $data = getData($result); + foreach ($data as $value) + { + array_push($arrayAccepted, $value); + } + } + } + + //Mapping with document_kurzbz + $preDocMap = []; + foreach ($resultPreDoc as $pre) { + $preDocMap[$pre->dokument_kurzbz] = $pre; + } + + $mergedArray = []; + foreach ($arrayAccepted as $doc) { + $merged = clone $doc; + + if (isset($preDocMap[$doc->dokument_kurzbz])) { + $merged->docdatum = $preDocMap[$doc->dokument_kurzbz]->docdatum; + $merged->insertvonma = $preDocMap[$doc->dokument_kurzbz]->insertvonma; + $merged->bezeichnung = $preDocMap[$doc->dokument_kurzbz]->bezeichnung; + } else { + $merged->akzeptiertdatum = null; + $merged->akzeptiertvon = null; + } + + $mergedArray[] = $merged; + } + + $this->terminateWithSuccess($mergedArray); + } + + public function deleteZuordnung($prestudent_id, $dokument_kurzbz) + { + if(!$prestudent_id) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + + if (!is_numeric($prestudent_id)) + $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + + if(!$dokument_kurzbz) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Dokument_kurzbz']), self::ERROR_TYPE_GENERAL); + + $result = $this->DokumentprestudentModel->delete( + [ + 'prestudent_id' => $prestudent_id, + 'dokument_kurzbz' => $dokument_kurzbz + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function loadAkte($akte_id) + { + if (!$akte_id) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Akte ID']), self::ERROR_TYPE_GENERAL); + + $this->AkteModel->addSelect('public.tbl_akte.*'); + $this->AkteModel->addSelect("CONCAT(public.tbl_person.vorname, ' ' , public.tbl_person.nachname) AS namePerson"); + $this->AkteModel->addJoin('public.tbl_person', 'person_id'); + $result = $this->AkteModel->loadWhere( + [ + 'akte_id' => $akte_id, + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + $data = current($data); + $this->terminateWithSuccess($data); + } + + public function updateAkte() + { + $this->form_validation->set_rules('akte_id', 'Akte ID', 'required', [ + 'required' => $this->p->t('dokumente', 'err_updateNotAllowed') + ]); + + $this->form_validation->set_rules('dokument_kurzbz', 'Dokumenttyp', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Dokumenttyp']) + ]); + + $this->form_validation->set_rules('nachreichung_am', 'Nachreichung am', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Nachreichung am']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $uid = getAuthUID(); + + $result = $this->AkteModel->update( + [ + 'akte_id' => $this->input->post('akte_id'), + ], + [ + 'dokument_kurzbz' => $this->input->post('dokument_kurzbz'), + 'anmerkung_intern' => $this->input->post('anmerkung_intern'), + 'titel_intern' => $this->input->post('titel_intern'), + 'nachgereicht_am' => $this->input->post('nachgereicht_am'), + 'updateamum' => date('c'), + 'updatevon' => $uid, + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function createZuordnung($prestudent_id, $dokument_kurzbz) + { + if (!$prestudent_id) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + + if(!$dokument_kurzbz) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Dokument_kurzbz']), self::ERROR_TYPE_GENERAL); + + $uid = getAuthUid(); + + //check if more than 1 dokumentkurzbz + //if() + + $result = $this->DokumentprestudentModel->insert( + [ + 'prestudent_id' => $prestudent_id, + 'dokument_kurzbz' => $dokument_kurzbz, + 'mitarbeiter_uid' => $uid, + 'datum' => date('c'), + 'insertamum' => date('c'), + 'insertvon' => $uid, + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteAkte($akte_id) + { + if (!$akte_id) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Akte ID']), self::ERROR_TYPE_GENERAL); + + $result = $this->AkteModel->load($akte_id); + $dataAkte = $this->getDataOrTerminateWithError($result); + + $logdata_akte = var_export($dataAkte, true); + + $dms_id = current($dataAkte)->dms_id; + $nachgereicht = current($dataAkte)->nachgereicht; + $inhalt = current($dataAkte)->inhalt; + $inhaltVorhanden = $inhalt != ''; + $uid = getAuthUid(); + + $this->db->trans_start(); + + if($dms_id) + { + $this->load->model('content/Dms_model', 'DmsModel'); + $result = $this->DmsModel->load($dms_id); + $data = $this->getDataOrTerminateWithError($result); + + $logdata_dms = (array)$data; + $logdata_dms = "Logdata: " . var_export($logdata_dms, true); + + //delete from dmsLib + $this->load->library('DmsLib'); + $person_id = current($dataAkte)->person_id; + $result = $this->dmslib->delete($person_id, $dms_id); + $this->getDataOrTerminateWithError($result); + + //LOGGING Dms ID + $this->load->model('system/Log_model', 'LogModel'); + $result = $this->LogModel->insert([ + 'executetime' => date('c'), + 'mitarbeiter_uid' => $uid, + 'beschreibung' => "Löschen der DMS_ID ". $dms_id, + 'sql' => $logdata_dms + ]); + $this->getDataOrTerminateWithError($result); + + //delete akte + $result = $this->AkteModel->delete( + [ + 'akte_id' => $akte_id + ] + ); + $data = $this->getDataOrTerminateWithError($result); + + //Logging Deletion Akte + $result = $this->LogModel->insert([ + 'executetime' => date('c'), + 'mitarbeiter_uid' => $uid, + 'beschreibung' => "Löschen der Akte ". $akte_id, + 'sql' => "DELETE FROM public.tbl_akte WHERE akte_id=" .$akte_id. " LogData: ". $logdata_akte + ]); + $this->getDataOrTerminateWithError($result); + $this->db->trans_complete(); + $this->terminateWithSuccess($data); + } + elseif (!!$dms_id || ($nachgereicht && !$inhaltVorhanden)) + { + $result = $this->AkteModel->delete( + [ + 'akte_id' => $akte_id + ] + ); + $data = $this->getDataOrTerminateWithError($result); + + $result = $this->LogModel->insert([ + 'executetime' => date('c'), + 'mitarbeiter_uid' => $uid, + 'beschreibung' => "Löschen der Akte ". $akte_id, + 'sql' => "DELETE FROM public.tbl_akte WHERE akte_id=" .$akte_id. " LogData: ". $logdata_akte + ]); + $this->getDataOrTerminateWithError($result); + + $this->db->trans_complete(); + $this->terminateWithSuccess($data); + } + else + $this->terminateWithError($this->p->t('dokumente', 'err_deleteDokHere'), self::ERROR_TYPE_GENERAL); + } + + public function uploadDokument() + { + $this->load->library('DmsLib'); + $prestudent_id = $this->input->post('prestudent_id'); + $anmerkung_intern = $this->input->post('anmerkung_intern'); + $titel_intern = $this->input->post('titel_intern'); + $dokument_kurzbz = $this->input->post('dokument_kurzbz'); + + $this->form_validation->set_rules('prestudent_id', 'Prestudent_id', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Prestudent ID']) + ]); + + $this->form_validation->set_rules('dokument_kurzbz', 'Dokumenttyp', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Dokumenttyp']) + ]); + + //validation if attachment was added + $this->form_validation->set_rules('anhang', 'Attachment', 'callback_file_check'); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->db->trans_start(); + $uid = getAuthUID(); + + $dms = array( + 'kategorie_kurzbz' => 'Akte', + 'version' => 0, + 'name' => $_FILES['anhang']['name'], + 'mimetype' => $_FILES['anhang']['type'], + 'insertamum' => date('c'), + 'insertvon' => $uid + ); + + $result = $this->dmslib->upload($dms, 'anhang', array("jpg", "png", "pdf")); + + if (isError($result)) + { + return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $dms_id = $result->retval['dms_id']; + + $person_id = $this->_getPersonId($prestudent_id); + + $result = $this->DokumentModel->load($dokument_kurzbz); + $data = $this->getDataOrTerminateWithError($result); + + $bezeichnung = current($data)->bezeichnung; + + //save entry in akte + if($dms_id) + { + $result = $this->AkteModel->insert([ + 'person_id' => $person_id, + 'dms_id' => $dms_id, + 'dokument_kurzbz' => $dokument_kurzbz, + 'mimetype' => $_FILES['anhang']['type'], + 'insertamum' => date('c'), + 'erstelltam' => date('c'), + 'insertvon' => $uid, + 'anmerkung_intern' => $anmerkung_intern, + 'titel_intern' => $titel_intern, + 'bezeichnung' => $bezeichnung, + 'titel' => $_FILES['anhang']['name'] + ]); + + $data = $this->getDataOrTerminateWithError($result); + $this->db->trans_complete(); + $this->terminateWithSuccess($data); + } + $this->db->trans_complete(); + $this->terminateWithSuccess($data); + } + + public function getDoktypen() + { + $this->DokumentModel->addSelect('dokument_kurzbz'); + $this->DokumentModel->addSelect('bezeichnung'); + $this->DokumentModel->addOrder('dokument_kurzbz', 'ASC'); + $result = $this->DokumentModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function download() + { + //TODO(Manu) check filetype, Decoding + $akte_id = $this->input->get('akte_id'); + + if(!$akte_id) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Akte ID']), self::ERROR_TYPE_GENERAL); + + if (!is_numeric($akte_id)) + $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value' => 'Akte ID']), self::ERROR_TYPE_GENERAL); + + + $result = $this->AkteModel->load($akte_id); + if (!hasData($result)) $this->terminateWithError('Akte not found'); + $data = getData($result)[0]; + + $mimetype = $data->mimetype; + $filecontentbase64 = $data->inhalt; + $filename = $data->titel; + + if(intval($data->dms_id) > 0) + { + $dmsdokres = $this->dmslib->read($data->dms_id); + if (!hasData($dmsdokres)) $this->terminateWithError('DMS File not found'); + $dmsdok = getData($dmsdokres)[0]; + + $mimetype = $dmsdok->mimetype; + $filecontentbase64 = $dmsdok->file_content; + $filename = $dmsdok->name; + } + + $filecontent = ''; + + if (!empty($filecontentbase64)) { + $filecontent = base64_decode($filecontentbase64, true); + + if ($filecontent === false) { + $this->terminateWithError('Base64-Dekodierung failed.'); + } + } + + $this->terminateWithFileOutput($mimetype, $filecontent, $filename); + } + + private function _getMissingDocuments($studiengang_kz, $prestudent_id) + { + $result = $this->DokumentModel->getMissingDocuments($studiengang_kz, $prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + + return $data; + } + + private function _getUnacceptedDocuments($prestudent_id) + { + $person_id = $this->_getPersonId($prestudent_id); + $result = $this->DokumentModel->getUnacceptedDocuments($prestudent_id, $person_id); + + $data = $this->getDataOrTerminateWithError($result); + + return $data; + } + + /** + * helper function for merging objects + * sorts object after merging according to dokument_kurzbz + * @param $original object of documents of akte + * @param object $toMerge documents to merge (of dokumentprestudent, dokumentstudiengang) + * @return Array mergedObject + */ + private function _mergeDocuments($original, $toMerge) + { + $existingKurzbez = []; + foreach ($original as $doc) { + $existingKurzbez[$doc->dokument_kurzbz] = true; + } + + foreach ($toMerge as $doc) { + if (!isset($existingKurzbez[$doc->dokument_kurzbz])) { + $original[] = $doc; + $existingKurzbez[$doc->dokument_kurzbz] = true; + } + else + { + foreach($original as $docOriginal) + { + if ($docOriginal->dokument_kurzbz == $doc->dokument_kurzbz) + { + $docOriginal->pflicht = $doc->pflicht; + $docOriginal->onlinebewerbung = $doc->onlinebewerbung; + } + } + } + } + + usort($original, function ($a, $b) { + return strcmp($a->dokument_kurzbz, $b->dokument_kurzbz); + }); + + return $original; + } + + private function _getDocumentsOfAkte($person_id) + { + $result = $this->AkteModel->getAktenFAS($person_id); + + $data = $this->getDataOrTerminateWithError($result); + + return $data; + } + + private function _getPrestudentDokumente($prestudent_id) + { + $result = $this->DokumentprestudentModel->getPrestudentDokumente($prestudent_id); + + $data = $this->getDataOrTerminateWithError($result); + + return $data; + } + + private function _getPersonId($prestudent_id) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $result = $this->PrestudentModel->loadWhere( + ['prestudent_id' => $prestudent_id] + ); + + $data = $this->getDataOrTerminateWithError($result); + $person = current($data); + + return $person->person_id; + } + + public function file_check($str) + { + if (isset($_FILES['anhang']) && $_FILES['anhang']['size'] > 0) + { + $allowed_mime_types = ['image/jpeg', 'image/png', 'application/pdf']; + $mime = mime_content_type($_FILES['anhang']['tmp_name']); + + if (in_array($mime, $allowed_mime_types)) + { + return true; + } else + { + $this->form_validation->set_message('file_check', $this->p->t('dokumente', 'error_fileType')); + return false; + } + } + else + { + $this->form_validation->set_message('file_check', $this->p->t('dokumente', 'error_fileMissing')); + return false; + } + } +} 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..ca8b62da6 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Favorites.php @@ -0,0 +1,80 @@ +. + */ + +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'); + } + + 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'] ?? null); + } + + 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'); + + $removed = []; + while (strlen($favorites) > 64) { + $favObj = json_decode($favorites); + if (!$favObj->list) + break; + $removed[] = array_shift($favObj->list); + $favorites = json_encode($favObj); + } + if ($removed) + $this->addMeta('removed', $removed); + + $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/GemeinsameStudien.php b/application/controllers/api/frontend/v1/stv/GemeinsameStudien.php new file mode 100644 index 000000000..97dad48fd --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/GemeinsameStudien.php @@ -0,0 +1,287 @@ + ['admin:r', 'assistenz:r'], + 'loadStudie' => ['admin:r', 'assistenz:r'], + 'insertStudie' => ['admin:rw', 'assistenz:rw'], + 'updateStudie' => ['admin:rw', 'assistenz:rw'], + 'deleteStudie' => ['admin:rw', 'assistenz:rw'], + 'getProgramsStudien' => ['admin:r', 'assistenz:r'], + 'getTypenMobility' => ['admin:r', 'assistenz:r'], + 'getStudiensemester' => ['admin:r', 'assistenz:r'], + 'getStudienprogramme' => ['admin:r', 'assistenz:r'], + 'getPartnerfirmen' => ['admin:r', 'assistenz:r'], + 'getStatiPrestudent' => ['admin:r', 'assistenz:r'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'jointstudies' + ]); + + // Load models + $this->load->model('codex/Mobilitaet_model', 'MobilitaetModel'); + + //TODO(check if additional Permissions necessary): 'student/stammdaten' + } + + public function getStudien($prestudent_id) + { + $this->MobilitaetModel->addSelect('mobilitaet_id'); + $this->MobilitaetModel->addSelect('mobilitaetstyp_kurzbz'); + $this->MobilitaetModel->addSelect('prestudent_id'); + $this->MobilitaetModel->addSelect('studiensemester_kurzbz'); + $this->MobilitaetModel->addSelect('bis.tbl_mobilitaet.mobilitaetsprogramm_code'); + $this->MobilitaetModel->addSelect('bis.tbl_mobilitaet.gsprogramm_id'); + $this->MobilitaetModel->addSelect('bis.tbl_mobilitaet.firma_id'); + $this->MobilitaetModel->addSelect('status_kurzbz'); + $this->MobilitaetModel->addSelect('ausbildungssemester'); + $this->MobilitaetModel->addSelect('bis.tbl_mobilitaet.insertvon'); + $this->MobilitaetModel->addSelect('bis.tbl_mobilitaet.insertamum'); + $this->MobilitaetModel->addSelect('bis.tbl_mobilitaet.updatevon'); + $this->MobilitaetModel->addSelect('bis.tbl_mobilitaet.updateamum'); + $this->MobilitaetModel->addSelect('mp.kurzbz'); + $this->MobilitaetModel->addSelect('gp.gsprogrammtyp_kurzbz'); + $this->MobilitaetModel->addSelect('gp.bezeichnung as studienprogramm'); + $this->MobilitaetModel->addSelect('f.name as partner'); + + $this->MobilitaetModel->addJoin('bis.tbl_mobilitaetsprogramm mp', 'ON (mp.mobilitaetsprogramm_code = bis.tbl_mobilitaet.mobilitaetsprogramm_code)', 'LEFT'); + $this->MobilitaetModel->addJoin('bis.tbl_gsprogramm gp', 'ON (gp.gsprogramm_id = bis.tbl_mobilitaet.gsprogramm_id)', 'LEFT'); + $this->MobilitaetModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = bis.tbl_mobilitaet.firma_id)', 'LEFT'); + + $result = $this->MobilitaetModel->loadWhere([ + 'prestudent_id' => $prestudent_id, + ]); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function getTypenMobility() + { + $this->load->model('codex/Mobilitaetstyp_model', 'MobilitaetstypModel'); + + $result = $this->MobilitaetstypModel->load(); + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function getStudiensemester() + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addOrder('studienjahr_kurzbz', 'DESC'); + $result = $this->StudiensemesterModel->load(); + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function getStudienprogramme() + { + $this->load->model('codex/Gsprogramm_model', 'GsprogrammModel'); + + $result = $this->GsprogrammModel->load(); + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function getPartnerfirmen() + { + $this->load->model('ressource/Firma_model', 'FirmaModel'); + + $result = $this->FirmaModel->loadWhere( + ['partner_code !=' => null] + ); + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function getStatiPrestudent() + { + $this->load->model('crm/Status_model', 'StatusModel'); + + $result = $this->StatusModel->load(); + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function loadStudie($mobilitaet_id) + { + $result = $this->MobilitaetModel->load($mobilitaet_id); + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess(current($data)); + } + + public function insertStudie() + { + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $prestudent_id = $this->input->post('prestudent_id'); + if(!$prestudent_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + $ausbildungssemester = (isset($formData['ausbildungssemester']) && !empty($formData['ausbildungssemester'])) + ? $formData['ausbildungssemester'] + : null; + $mobilitaetstyp_kurzbz = (isset($formData['mobilitaetstyp_kurzbz']) && !empty($formData['mobilitaetstyp_kurzbz'])) + ? $formData['mobilitaetstyp_kurzbz'] + : null; + $studiensemester_kurzbz = (isset($formData['studiensemester_kurzbz']) && !empty($formData['studiensemester_kurzbz'])) + ? $formData['studiensemester_kurzbz'] : null; + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('mobilitaetstyp_kurzbz', 'Typ', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Typ']) + ]); + + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Studiensemester']) + ]); + + $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'required|numeric', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Ausbildungssemester']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ausbildungssemester']), + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $status_kurzbz = (isset($formData['status_kurzbz']) && !empty($formData['status_kurzbz'])) + ? $formData['status_kurzbz'] + : null; + $mobilitaetsprogramm_code = (isset($formData['mobilitaetsprogramm_code']) && !empty($formData['mobilitaetsprogramm_code'])) + ? $formData['mobilitaetsprogramm_code'] + : null; + $gsprogramm_id = (isset($formData['gsprogramm_id']) && !empty($formData['gsprogramm_id'])) + ? $formData['gsprogramm_id'] + : null; + $firma_id= (isset($formData['firma_id']) && !empty($formData['firma_id'])) ? $formData['firma_id'] : null; + + $result = $this->MobilitaetModel->insert([ + 'prestudent_id' => $prestudent_id, + 'mobilitaetstyp_kurzbz' =>$mobilitaetstyp_kurzbz, + 'status_kurzbz' => $status_kurzbz, + 'studiensemester_kurzbz' =>$studiensemester_kurzbz, + 'mobilitaetsprogramm_code' => $mobilitaetsprogramm_code, + 'gsprogramm_id' => $gsprogramm_id, + 'firma_id' => $firma_id, + 'ausbildungssemester' =>$ausbildungssemester, + 'insertvon' => $authUID, + 'insertamum' => date('c'), + ]); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function updateStudie() + { + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $prestudent_id = $this->input->post('prestudent_id'); + if(!$prestudent_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + + $mobilitaet_id = (isset($formData['mobilitaet_id']) && !empty($formData['mobilitaet_id'])) + ? $formData['mobilitaet_id'] : + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Mobilitaet ID']), self::ERROR_TYPE_GENERAL); + $ausbildungssemester = (isset($formData['ausbildungssemester']) && !empty($formData['ausbildungssemester'])) + ? $formData['ausbildungssemester'] + : null; + $mobilitaetstyp_kurzbz = (isset($formData['mobilitaetstyp_kurzbz']) && !empty($formData['mobilitaetstyp_kurzbz'])) + ? $formData['mobilitaetstyp_kurzbz'] + : null; + $studiensemester_kurzbz = (isset($formData['studiensemester_kurzbz']) && !empty($formData['studiensemester_kurzbz'])) + ? $formData['studiensemester_kurzbz'] + : null; + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('mobilitaetstyp_kurzbz', 'Typ', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Typ']) + ]); + + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Studiensemester']) + ]); + + $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'required|numeric', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Ausbildungssemester']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ausbildungssemester']), + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $status_kurzbz = (isset($formData['status_kurzbz']) && !empty($formData['status_kurzbz'])) ? $formData['status_kurzbz'] : null; + $mobilitaetsprogramm_code = (isset($formData['mobilitaetsprogramm_code']) && !empty($formData['mobilitaetsprogramm_code'])) + ? $formData['mobilitaetsprogramm_code'] + : null; + $gsprogramm_id = (isset($formData['gsprogramm_id']) && !empty($formData['gsprogramm_id'])) + ? $formData['gsprogramm_id'] + : null; + $firma_id= (isset($formData['firma_id']) && !empty($formData['firma_id'])) ? $formData['firma_id'] : null; + + $result = $this->MobilitaetModel->update( + [ + 'mobilitaet_id' => $mobilitaet_id, + ], + [ + 'prestudent_id' => $prestudent_id, + 'mobilitaetstyp_kurzbz' => $mobilitaetstyp_kurzbz, + 'status_kurzbz' => $status_kurzbz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'mobilitaetsprogramm_code' => $mobilitaetsprogramm_code, + 'gsprogramm_id' => $gsprogramm_id, + 'firma_id' => $firma_id, + 'ausbildungssemester' => $ausbildungssemester, + 'updatevon' => $authUID, + 'updateamum' => date('c'), + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + public function deleteStudie($mobilitaet_id) + { + if(!$mobilitaet_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Mobilität ID']), self::ERROR_TYPE_GENERAL); + } + $result = $this->MobilitaetModel->delete( + array('mobilitaet_id' => $mobilitaet_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Grades.php b/application/controllers/api/frontend/v1/stv/Grades.php new file mode 100644 index 000000000..dd8f53a27 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Grades.php @@ -0,0 +1,699 @@ +. + */ + +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 grades + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Grades extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'list' => 'student/noten:r', + 'getCertificate' => 'student/noten:r', + 'getTeacherProposal' => 'student/noten:r', + 'getRepeaterGrades' => 'student/noten:r', + 'updateCertificate' => ['admin:w', 'assistenz:w'], + 'deleteCertificate' => ['admin:w', 'assistenz:w'], + 'copyTeacherProposalToCertificate' => 'student/noten:w', + 'copyRepeaterGradeToCertificate' => 'student/noten:w', + 'getGradeFromPoints' => 'student/noten:r' + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load Phrases + $this->loadPhrases([ + 'stv', + 'person', + 'lehre' + ]); + } + + /** + * List all possible grades + * (Entries in lehre.tbl_note) + * + * @return void + */ + public function list() + { + $this->load->model('codex/Note_model', 'NoteModel'); + + $this->NoteModel->addOrder('note'); + + $result = $this->NoteModel->load(); + + $grades = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($grades); + } + + /** + * List grades for the certificate of a prestudent. + * (Entries in lehre.tbl_zeugnisnote) + * + * @param string $prestudent_id + * @param string|null $studiensemester_kurzbz If studiensemester_kurzbz only this semesters grades will be loaded, otherwise all semesters grades will be loaded. + * + * @return void + */ + public function getCertificate($prestudent_id, $studiensemester_kurzbz = null) + { + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $result = $this->StudentModel->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + + $student = $this->getDataOrTerminateWithError($result); + if (!$student) + $this->terminateWithSuccess([]); + + $student_uid = current($student)->student_uid; + + if ($studiensemester_kurzbz !== null && !$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $result = $this->ZeugnisnoteModel->getZeugnisnoten($student_uid, $studiensemester_kurzbz); + + $grades = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($grades); + } + + /** + * List grades of a prestudent that teachers gave. + * (Entries in campus.tbl_lvgesamtnote) + * + * @param string $prestudent_id + * @param string|null $studiensemester_kurzbz If studiensemester_kurzbz only this semesters grades will be loaded, otherwise all semesters grades will be loaded. + * + * @return void + */ + public function getTeacherProposal($prestudent_id, $studiensemester_kurzbz = null) + { + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('education/Lvgesamtnote_model', 'LvgesamtnoteModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $result = $this->StudentModel->loadWhere([ + 'prestudent_id' => $prestudent_id + ]); + + $student = $this->getDataOrTerminateWithError($result); + if (!$student) + $this->terminateWithSuccess([]); + + + $student_uid = current($student)->student_uid; + + if ($studiensemester_kurzbz !== null && !$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $result = $this->LvgesamtnoteModel->getLvGesamtNoten(null, $student_uid, $studiensemester_kurzbz); + + $grades = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($grades); + } + + /** + * List grades of a prestudent that an assistant marked as already done + * or as not allowed because of the repeating of a semester. + * + * @param string $prestudent_id + * @param string|false $studiensemester_kurzbz If studiensemester_kurzbz only this semesters grades will be loaded, otherwise all semesters grades will be loaded. + * + * @return void + */ + public function getRepeaterGrades($prestudent_id, $studiensemester_kurzbz = false) + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->library('AntragLib'); + + if ($studiensemester_kurzbz !== false && !$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $result = $this->antraglib->getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz); + + $grades = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($grades); + } + + /** + * Update or Insert a grade for the certificate of a prestudent. + * (Entry in lehre.tbl_zeugnisnote) + * + * @return void + */ + public function updateCertificate() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules("lehrveranstaltung_id", $this->p->t('lehre', 'lehrveranstaltung'), "required|integer"); + $this->form_validation->set_rules("student_uid", $this->p->t('person', 'student'), "required"); + $this->form_validation->set_rules("studiensemester_kurzbz", $this->p->t('lehre', 'studiensemester'), "required"); + $this->form_validation->set_rules('note', $this->p->t('lehre', 'note'), 'required|numeric'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $student_uid = $this->input->post('student_uid'); + $lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id'); + $note = $this->input->post('note'); + $authUID = getAuthUID(); + $now = date('c'); + + // NOTE(chris): Stg Permissions + if (!$this->hasPermissionUpdate($lehrveranstaltung_id, $student_uid)) + return $this->_outputAuthError([$this->router->method => ['admin', 'assistenz']]); + + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $result = $this->ZeugnisnoteModel->load([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student_uid, + 'lehrveranstaltung_id' => $lehrveranstaltung_id + ]); + $current = $this->getDataOrTerminateWithError($result); + + if ($current) { + $result = $this->ZeugnisnoteModel->update([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student_uid, + 'lehrveranstaltung_id' => $lehrveranstaltung_id + ], [ + 'note' => $note, + 'benotungsdatum' => $now, + 'updateamum' => $now, + 'updatevon' => $authUID + ]); + } else { + $result = $this->ZeugnisnoteModel->insert([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student_uid, + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'note' => $note, + 'benotungsdatum' => $now, + 'insertamum' => $now, + 'insertvon' => $authUID + ]); + } + $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(true); + } + + /** + * Delete a grade from the certificate of a prestudent. + * (Entry in lehre.tbl_zeugnisnote) + * + * @return void + */ + public function deleteCertificate() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules("lehrveranstaltung_id", $this->p->t('lehre', 'lehrveranstaltung'), "required|integer"); + $this->form_validation->set_rules("student_uid", $this->p->t('person', 'student'), "required"); + $this->form_validation->set_rules("studiensemester_kurzbz", $this->p->t('lehre', 'studiensemester'), "required"); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $student_uid = $this->input->post('student_uid'); + $lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id'); + + // NOTE(chris): Stg Permissions + if (!$this->hasPermissionDelete($lehrveranstaltung_id, $student_uid)) + return $this->_outputAuthError([$this->router->method => ['admin', 'assistenz']]); + + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $result = $this->ZeugnisnoteModel->delete([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student_uid, + 'lehrveranstaltung_id' => $lehrveranstaltung_id + ]); + $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(true); + } + + /** + * Copy a grade that teachers gave to the certificate of a prestudent. + * (Entry in campus.tbl_lvgesamtnote to an entry in lehre.tbl_zeugnisnote) + * + * @return void + */ + public function copyTeacherProposalToCertificate() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules("lehrveranstaltung_id", $this->p->t('lehre', 'lehrveranstaltung'), "required|integer"); + $this->form_validation->set_rules("student_uid", $this->p->t('person', 'student'), "required"); + $this->form_validation->set_rules("studiensemester_kurzbz", $this->p->t('lehre', 'studiensemester'), "required"); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id'); + $student_uid = $this->input->post('student_uid'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $authUID = getAuthUID(); + + // NOTE(chris): Stg Permissions + if (!$this->hasPermissionCopy($lehrveranstaltung_id, $student_uid)) + return $this->_outputAuthError([$this->router->method => 'student/noten']); + + $this->load->model('education/Lvgesamtnote_model', 'LvgesamtnoteModel'); + + $result = $this->LvgesamtnoteModel->load([ + 'student_uid' => $student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'lehrveranstaltung_id' => $lehrveranstaltung_id + ]); + $teacherGrade = $this->getDataOrTerminateWithError($result); + + if (!$teacherGrade) + show_404(); + + $teacherGrade = current($teacherGrade); + + $data = [ + 'note' => $teacherGrade->note, + 'punkte' => $teacherGrade->punkte, + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $teacherGrade->benotungsdatum, + 'bemerkung' => $teacherGrade->bemerkung + ]; + + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $this->ZeugnisnoteModel->addJoin('lehre.tbl_note n', 'note'); + $result = $this->ZeugnisnoteModel->load([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student_uid, + 'lehrveranstaltung_id' => $lehrveranstaltung_id + ]); + $certificateGrade = $this->getDataOrTerminateWithError($result); + + if ($certificateGrade) { + $certificateGrade = current($certificateGrade); + + if (!$certificateGrade->lkt_ueberschreibbar) + $this->terminateWithError($this->p->t("stv", "grades_error_overwrite")); + + // NOTE(chris): update + $data['updateamum'] = $data['uebernahmedatum']; + $data['updatevon'] = $authUID; + + $this->ZeugnisnoteModel->update([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student_uid, + 'lehrveranstaltung_id' => $lehrveranstaltung_id + ], $data); + } else { + // NOTE(chris): insert + $data['insertamum'] = $data['uebernahmedatum']; + $data['insertvon'] = $authUID; + $data['lehrveranstaltung_id'] = $lehrveranstaltung_id; + $data['student_uid'] = $student_uid; + $data['studiensemester_kurzbz'] = $studiensemester_kurzbz; + + $this->ZeugnisnoteModel->insert($data); + + if (defined('FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN') + && FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN) { + $result = $this->addTestsForGrade( + $studiensemester_kurzbz, + $student_uid, + $lehrveranstaltung_id, + $teacherGrade->note, + $teacherGrade->punkte + ); + $this->getDataOrTerminateWithError($result); + } + } + + + $this->terminateWithSuccess(true); + } + + /** + * Copy a grade that was marked by an assistant as already done or not + * allowed because of the repeating of a semester to the certificate of a + * prestudent. + * + * @return void + */ + public function copyRepeaterGradeToCertificate() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules("studierendenantrag_lehrveranstaltung_id", "studierendenantrag_lehrveranstaltung_id", "required|integer"); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $id = $this->input->post('studierendenantrag_lehrveranstaltung_id'); + $authUID = getAuthUID(); + + $this->load->model('education/Studierendenantraglehrveranstaltung_model', 'StudierendenantraglehrveranstaltungModel'); + + $this->StudierendenantraglehrveranstaltungModel->addSelect("tbl_studierendenantrag_lehrveranstaltung.*"); + $this->StudierendenantraglehrveranstaltungModel->addSelect("student_uid"); + $this->StudierendenantraglehrveranstaltungModel->addJoin("campus.tbl_studierendenantrag", "studierendenantrag_id"); + $this->StudierendenantraglehrveranstaltungModel->addJoin("public.tbl_student", "prestudent_id", "LEFT"); + + $result = $this->StudierendenantraglehrveranstaltungModel->load($id); + $repeaterGrade = $this->getDataOrTerminateWithError($result); + + if (!$repeaterGrade) + show_404(); + + $repeaterGrade = current($repeaterGrade); + + // NOTE(chris): Stg Permissions + if (!$this->hasPermissionCopy($repeaterGrade->lehrveranstaltung_id, $repeaterGrade->student_uid)) + return $this->_outputAuthError([$this->router->method => 'student/noten']); + + $data = [ + 'note' => $repeaterGrade->note, + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $repeaterGrade->insertamum, + 'bemerkung' => $repeaterGrade->anmerkung + ]; + + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $result = $this->ZeugnisnoteModel->load([ + $repeaterGrade->studiensemester_kurzbz, + $repeaterGrade->student_uid, + $repeaterGrade->lehrveranstaltung_id + ]); + $certificateGrade = $this->getDataOrTerminateWithError($result); + + if ($certificateGrade) { + // NOTE(chris): update + $data['updateamum'] = $data['uebernahmedatum']; + $data['updatevon'] = $authUID; + + $this->ZeugnisnoteModel->update([ + $repeaterGrade->studiensemester_kurzbz, + $repeaterGrade->student_uid, + $repeaterGrade->lehrveranstaltung_id + ], $data); + } else { + // NOTE(chris): insert + $data['insertamum'] = $data['uebernahmedatum']; + $data['insertvon'] = $authUID; + $data['lehrveranstaltung_id'] = $repeaterGrade->lehrveranstaltung_id; + $data['student_uid'] = $repeaterGrade->student_uid; + $data['studiensemester_kurzbz'] = $repeaterGrade->studiensemester_kurzbz; + + $this->ZeugnisnoteModel->insert($data); + } + + + $this->terminateWithSuccess(true); + } + + /** + * Loads the grade from the points using the gradingkey + * + * @return void + */ + public function getGradeFromPoints() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules("lehrveranstaltung_id", $this->p->t('lehre', 'lehrveranstaltung'), "required|integer"); + $this->form_validation->set_rules("points", $this->p->t("stv", "grades_points"), "required|numeric"); + $this->form_validation->set_rules("studiensemester_kurzbz", $this->p->t("lehre", "studiensemester"), "required|regex_match[/^[WS]S[0-9]{4}$/]"); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $this->load->model('education/Notenschluesselaufteilung_model', 'NotenschluesselaufteilungModel'); + + $result = $this->NotenschluesselaufteilungModel->getNote( + $this->input->post('points'), + $this->input->post('lehrveranstaltung_id'), + $studiensemester_kurzbz + ); + + $note = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($note); + } + + /** + * Helper function that adds tests for a student + * (Entries in lehre.tbl_pruefung) + * + * @param string $studiensemester_kurzbz + * @param string $student_uid + * @param integer $lehrveranstaltung_id + * @param integer $note + * @param numeric $punkte + * + * @return stdClass + */ + protected function addTestsForGrade($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id, $note, $punkte) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + // Get Lehreinheit + $result = $this->LehrveranstaltungModel->getLeByStudent($student_uid, $studiensemester_kurzbz, $lehrveranstaltung_id); + + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->p->t("stv", "grades_error_lehreinheit_id")); + $le = current(getData($result)); + + // Prepare + $this->load->model('education/LePruefung_model', 'LePruefungModel'); + $data = [ + "student_uid" => $student_uid, + "lehreinheit_id" => $le->lehreinheit_id, + "datum" => date('Y-m-d'), + "pruefungstyp_kurzbz" => "Termin1", + "note" => $note + ]; + + if (defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE) + $data["punkte"] = $punkte; + + // Get Anwesenheit + $this->load->model('education/Anwesenheit_model', 'AnwesenheitModel'); + $result = $this->AnwesenheitModel->loadAnwesenheitStudiensemester($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id); + if (isError($result)) + return $result; + $anwesenheit = getData($result); + + if ($anwesenheit && (float)current($anwesenheit)->prozent < FAS_ANWESENHEIT_ROT) { + // Get Anwesenheitsbefreiung + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $result = $this->BenutzerfunktionModel->getBenutzerFunktionByUidInStdsem($student_uid, $studiensemester_kurzbz, 'awbefreit'); + + if (isError($result)) + return $result; + + $anwesenheitsbefreit = hasData($result); + + // Wenn nicht Anwesenheitsbefreit und Anwesenheit unter einem bestimmten Prozentsatz fällt dann wird ein Pruefungsantritt abgezogen + if (!$anwesenheitsbefreit) { + $data2 = $data; + $data2["note"] = 7; + if (isset($data2["punkte"])) + unset($data2["punkte"]); + + $result = $this->LePruefungModel->insert($data2); + + if (isError($result)) + return $result; + + $data["pruefungstyp_kurzbz"] = "Termin2"; + } + } + + return $this->LePruefungModel->insert($data); + } + + /** + * Helper function to check permissions for updateCertificate() + * + * @param integer $lehrveranstaltung_id + * @param string $student_uid + * + * @return boolean + */ + protected function hasPermissionUpdate($lehrveranstaltung_id, $student_uid) + { + if ($lehrveranstaltung_id === null || $student_uid === null) + return true; + + $this->load->model('crm/Student_model', 'StudentModel'); + + $result = $this->StudentModel->load([$student_uid]); + if (isError($result) || !hasData($result)) + return false; + + $student = current(getData($result)); + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz)) + return true; + + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $result = $this->StudienplanModel->getAllOesForLv($lehrveranstaltung_id); + if (isError($result)) + return false; + + $oes = getData($result) ?: []; + + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getStg($lehrveranstaltung_id); + if (isError($result)) + return false; + + if (hasData($result)) + $oes[] = current(getData($result)); + + foreach ($oes as $oe) { + if ($this->permissionlib->isBerechtigt('admin', 'suid', $oe->oe_kurzbz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $oe->oe_kurzbz)) + return true; + } + + return false; + } + + /** + * Helper function to check permissions for deleteCertificate() + * + * @param integer $lehrveranstaltung_id + * @param string $student_uid + * + * @return boolean + */ + protected function hasPermissionDelete($lehrveranstaltung_id, $student_uid) + { + if ($lehrveranstaltung_id === null || $student_uid === null) + return true; + + $this->load->model('crm/Student_model', 'StudentModel'); + + $result = $this->StudentModel->load([$student_uid]); + if (isError($result) || !hasData($result)) + return false; + + $student = current(getData($result)); + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz)) + return true; + + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id); + if (isError($result) || !hasData($result)) + return false; + + $oe = current(getData($result)); + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $oe->oe_kurzbz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $oe->oe_kurzbz)) + return true; + + return false; + } + + /** + * Helper function to check permissions for + * copyTeacherProposalToCertificate() and copyRepeaterGradeToCertificate() + * + * @param integer $lehrveranstaltung_id + * @param string $student_uid + * + * @return boolean + */ + protected function hasPermissionCopy($lehrveranstaltung_id, $student_uid) + { + if ($lehrveranstaltung_id === null || $student_uid === null) + return true; + + $this->load->model('crm/Student_model', 'StudentModel'); + + $result = $this->StudentModel->load([$student_uid]); + if (isError($result) || !hasData($result)) + return false; + + $student = current(getData($result)); + + if ($this->permissionlib->isBerechtigt('student/noten', 'suid', $student->studiengang_kz)) + return true; + + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id); + if (isError($result) || !hasData($result)) + return false; + + $oe = current(getData($result)); + + if ($this->permissionlib->isBerechtigt('student/noten', 'suid', $oe->oe_kurzbz)) + return true; + + return false; + } +} diff --git a/application/controllers/api/frontend/v1/stv/Gruppen.php b/application/controllers/api/frontend/v1/stv/Gruppen.php new file mode 100644 index 000000000..c30816f2a --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Gruppen.php @@ -0,0 +1,80 @@ + ['admin:r', 'assistenz:r'], + 'deleteGruppe' => ['admin:rw', 'assistenz:rw'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui', 'gruppenmanagement' + ]); + + // Load models + $this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + $this->load->model('organisation/Gruppe_model', 'GruppeModel'); + } + + public function getGruppen($student_uid) + { + $this->BenutzergruppeModel ->addSelect('gruppe_kurzbz'); + $this->BenutzergruppeModel ->addSelect('bezeichnung'); + $this->BenutzergruppeModel ->addSelect('generiert'); + $this->BenutzergruppeModel ->addSelect('uid'); + $this->BenutzergruppeModel ->addSelect('studiensemester_kurzbz'); + $this->BenutzergruppeModel ->addJoin('public.tbl_gruppe', 'gruppe_kurzbz'); + $this->BenutzergruppeModel-> addOrder('bezeichnung', 'ASC'); + + $result = $this->BenutzergruppeModel->loadWhere( + array( + 'uid' => $student_uid + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteGruppe() + { + $student_uid = $this->input->post('id'); + $gruppe_kurzbz = $this->input->post('gruppe_kurzbz'); + + //Validate if automatic group generation + $result = $this->GruppeModel-> loadWhere( + array( + 'gruppe_kurzbz' => $gruppe_kurzbz + ) + ); + $data = $this->getDataOrTerminateWithError($result); + $generation = current($data); + + if($generation->generiert) + { + $this->terminateWithError($this->p->t('gruppenmanagement', 'error_deleteGeneratedGroups'), self::ERROR_TYPE_GENERAL); + } + + $result = $this->BenutzergruppeModel->delete( + array( + 'gruppe_kurzbz' => $gruppe_kurzbz, + 'uid' => $student_uid + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($data); + } +} 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..9b713b5f9 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Kontakt.php @@ -0,0 +1,810 @@ + ['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'], + 'getAllFirmen' => ['admin:r', 'assistenz: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'); + $this->load->model('person/Kontakttyp_model', 'KontakttypModel'); + + // 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)); + + if (is_null($person_id) || !ctype_digit((string)$person_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $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' + ) { + if($this->input->post('address_id')) + $id = $this->input->post('address_id'); + if($this->input->post('adresse_id')) + $id = $this->input->post('adresse_id'); + if($this->input->post('bankverbindung_id')) + $id = $this->input->post('bankverbindung_id'); + if($this->input->post('kontakt_id')) + $id = $this->input->post('kontakt_id'); + + $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'; + } + + if (!isset($id) || !ctype_digit((string)$id)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $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.*, + (CASE + WHEN public.tbl_adresse.updateamum >= public.tbl_adresse.insertamum + THEN public.tbl_adresse.updateamum + ELSE public.tbl_adresse.insertamum + END) AS lastUpdate"); + $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_data(['address.plz' => $_POST['plz']]); + + $this->form_validation->set_rules('address.plz', 'PLZ', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']), + ]); + + if(isset($_POST['nation']) && $_POST['nation'] == 'A') + { + $this->form_validation->set_rules('address.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']) && isset($_POST['nation']) && $_POST['nation'] == 'A') + { + $this->form_validation->set_rules('address.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; + $firma_id = isset($_POST['firma_id']) ? $_POST['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 + + ] + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function updateAddress() + { + $address_id = $this->input->post('adresse_id'); + + $this->form_validation->set_data(['address.plz' => $_POST['plz']]); + + $uid = getAuthUID(); + + $this->form_validation->set_rules('address.plz', 'PLZ', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']), + ]); + + if(isset($_POST['nation']) && $_POST['nation'] == 'A') + { + $this->form_validation->set_rules('address.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']) && isset($_POST['nation']) && $_POST['nation'] == 'A') + { + $this->form_validation->set_rules('address.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); + } + + $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; + $firma_id = isset($_POST['firma_id']) ? $_POST['firma_id'] : 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 + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function loadAddress() + { + $adresse_id = $this->input->post('address_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->input->post('address_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 = null) + { + if (is_null($searchString)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $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 = null) + { + if (is_null($searchString)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->load->model('organisation/standort_model', 'StandortModel'); + + $result = $this->StandortModel->searchStandorte($searchString); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getStandorteByFirma($firma_id = null) + { + if (is_null($firma_id) || !ctype_digit((string)$firma_id)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $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.*, + (CASE + WHEN public.tbl_kontakt.updateamum >= public.tbl_kontakt.insertamum + THEN public.tbl_kontakt.updateamum + ELSE public.tbl_kontakt.insertamum + END) AS lastUpdate, st.bezeichnung, f.name"); + $this->KontakttypModel->addSelect("kt.beschreibung as kontakttypbeschreibung"); + $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'); + $this->KontakttypModel->addJoin('public.tbl_kontakttyp kt', 'ON (public.tbl_kontakt.kontakttyp = kt.kontakttyp)'); + $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->input->post('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->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); + } + $this->terminateWithSuccess($result); + } + + public function updateContact() + { + $kontakt_id = $this->input->post('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()); + } + + $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'); + + $result = $this->KontaktModel->update( + [ + 'kontakt_id' => $kontakt_id + ], + [ + 'person_id' => $person_id, + 'kontakttyp' => $kontakttyp, + 'anmerkung' => $anmerkung, + 'kontakt' => $kontakt, + 'zustellung' => $_POST['zustellung'], + 'updatevon' => $uid, + 'updateamum' => date('c'), + 'standort_id' => $standort_id, + 'ext_id' => $ext_id + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteContact() + { + $kontakt_id = $this->input->post('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'); + $iban = $this->input->post('iban'); + $typ = $this->input->post('typ'); + $verrechnung = $this->input->post('verrechnung'); + $uid = getAuthUID(); + + $result = $this->BankverbindungModel->insert( + [ + 'person_id' => $person_id, + 'name' => $name, + 'anschrift' => $anschrift, + 'bic' => $bic, + 'iban' => $iban, + 'blz' => $blz, + 'kontonr' => $kontonr, + 'insertvon' => $uid, + 'insertamum' => date('c'), + 'typ' => $typ, + 'verrechnung' => $verrechnung, + 'ext_id' => $ext_id, + 'oe_kurzbz' => $oe_kurzbz, + 'orgform_kurzbz' => $orgform_kurzbz + ] + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function loadBankverbindung() + { + $bankverbindung_id = $this->input->post('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'] + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteBankverbindung() + { + $bankverbindung_id = $this->input->post('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)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Bankverbindung_id']), self::ERROR_TYPE_GENERAL); + } + 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']); + } + + /* + * returns list of all companies + * as key value list to be used in select or autocomplete + */ + public function getAllFirmen() + { + $sql = " + SELECT + f.firma_id, f.name, + f.name AS label + FROM public.tbl_firma f + ORDER BY f.name ASC"; + + $result = $this->FirmaModel->execReadOnlyQuery($sql); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + +} 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..a33680ea0 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Konto.php @@ -0,0 +1,497 @@ +. + */ + +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'); + + $this->BuchungstypModel->addOrder('beschreibung'); + + $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/LvTermine.php b/application/controllers/api/frontend/v1/stv/LvTermine.php new file mode 100644 index 000000000..c29f56964 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/LvTermine.php @@ -0,0 +1,408 @@ + ['admin:r', 'assistenz:r'], + 'getStudiensemester' => ['admin:r', 'assistenz:r'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + ]); + + // Load models + $this->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + //query verwenden wie im Cis endpoint + $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'); + } + + //TODO Build own lib or combine with Controller Stundenplan.php + //here use of logic of Stundenplan.php, extended with parameters uid, grouping, and used dbTable + public function getStundenplan($uid, $start_date = null, $end_date = null, $groupConsecutiveHours = false, $dbStundenplanTable = "stundenplan") + { + $student_uid = $uid; + $semester_range = $this->studienSemesterErmitteln($start_date, $end_date); + + $this->sortStudienSemester($semester_range); + $this->applyLoadUeberSemesterHaelfte($semester_range); + + $benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($semester_range, $student_uid); + $student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($semester_range, $student_uid); + + if(!$groupConsecutiveHours) + $stundenplan_query = $this->StundenplanModel->getStundenplanQuery( + $start_date, + $end_date, + $semester_range, + $benutzer_gruppen, + $student_lehrverband + ); + else + $stundenplan_query = $this->StundenplanModel->getStundenplanQuery( + $start_date, + $end_date, + $semester_range, + $benutzer_gruppen, + $student_lehrverband, + true, + $dbStundenplanTable + ); + + if(!$stundenplan_query) + { + $this->terminateWithSuccess([]); + } + + if($groupConsecutiveHours) + { + $stundenplan_data = $this->StundenplanModel->stundenplanGruppierungConsecutive($stundenplan_query); + } + else + { + $stundenplan_data = $this->StundenplanModel->stundenplanGruppierung($stundenplan_query); + } + + $stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? []; + $this->terminateWithSuccess($stundenplan_data); + + $this->expand_object_information($stundenplan_data); + + $this->returnObj['$stundenplan_query'] = $stundenplan_query; + $this->returnObj['$student_lehrverband'] = $student_lehrverband; + $this->returnObj['$benutzer_gruppen'] = $benutzer_gruppen; + $this->terminateWithSuccess($stundenplan_data); + } + + public function getStudiensemester() + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addOrder('studienjahr_kurzbz', 'DESC'); + $result = $this->StudiensemesterModel->load(); + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + //copied from Stundenplan.php + private function studienSemesterErmitteln($start_date, $end_date) + { + // gets all studiensemester from the student from start_date to end_date + $semester_range = $this->StudiensemesterModel->getByDateRange($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; + } + + //copied from Stundenplan.php + 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; + } + elseif($year_first > $year_second) + { + return 1; + } + elseif($year_first == $year_second && $sem_first > $sem_second) + { + return 1; + } + elseif($year_first == $year_second && $sem_first < $sem_second) + { + return -1; + } + return 0; + } + ); + } + + //copied from Stundenplan.php + 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; + } + } + + //copied from Stundenplan.php, extended with $student_uid + private function fetchBenutzerGruppenFromStudiensemester($semester_range, $student_uid) + { + //$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; + } + + //copied from Stundenplan.php, extended with $student_uid + private function fetchStudentlehrverbandFromStudiensemester($semester_range, $student_uid) + { + //$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; + } +} diff --git a/application/controllers/api/frontend/v1/stv/Mobility.php b/application/controllers/api/frontend/v1/stv/Mobility.php new file mode 100644 index 000000000..f61816086 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Mobility.php @@ -0,0 +1,559 @@ + ['admin:r', 'assistenz:r'], + 'loadMobility' => ['admin:r', 'assistenz:r'], + 'insertMobility' => ['admin:rw', 'assistenz:rw'], + 'updateMobility' => ['admin:rw', 'assistenz:rw'], + 'deleteMobility' => ['admin:rw', 'assistenz:rw'], + 'getProgramsMobility' => ['admin:r', 'assistenz:r'], + 'getLVList' => ['admin:r', 'assistenz:r'], + 'getAllLehreinheiten' => ['admin:r', 'assistenz:r'], + 'getLvsandLesByStudent' => ['admin:r', 'assistenz:r'], + 'getPurposes' => ['admin:r', 'assistenz:r'], + 'getSupports' => ['admin:r', 'assistenz:r'], + 'getListPurposes' => ['admin:r', 'assistenz:r'], + 'getListSupports' => ['admin:r', 'assistenz:r'], + 'deleteMobilityPurpose' => ['admin:r', 'assistenz:r'], + 'addMobilityPurpose' => ['admin:r', 'assistenz:r'], + 'deleteMobilitySupport' => ['admin:r', 'assistenz:r'], + 'addMobilitySupport' => ['admin:r', 'assistenz:r'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'mobility' + ]); + + // Load models + $this->load->model('codex/Bisio_model', 'BisioModel'); + + //Permission checks for Studiengangsarray + $allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []; + + if ($this->router->method == 'insertMobility' || $this->router->method == 'updateMobility') + { + $student_uid = $this->input->post('uid'); + if(!$student_uid) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkAllowedStgsFromUid($student_uid, $allowedStgs); + } + + if ($this->router->method == 'deleteMobility') { + $bisio_id = $this->input->post('bisio_id'); + if(!$bisio_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Bisio ID']), self::ERROR_TYPE_GENERAL); + } + $result = $this->BisioModel->load( + array('bisio_id' => $bisio_id) + ); + $data = $this->getDataOrTerminateWithError($result); + $student_uid = current($data)->student_uid; + + $this->_checkAllowedStgsFromUid($student_uid, $allowedStgs); + } + } + + private function _checkAllowedStgsFromUid($student_uid, $allowedStgs) + { + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->loadWhere(['student_uid' => $student_uid]); + $data = $this->getDataOrTerminateWithError($result); + $studiengang_kz = current($data)->studiengang_kz; + + if (!in_array($studiengang_kz, $allowedStgs)) + { + return $this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL); + } + } + + public function getMobilitaeten($student_uid) + { + $this->BisioModel->addSelect("*"); + $this->BisioModel->addJoin('bis.tbl_mobilitaetsprogramm mp', 'ON (mp.mobilitaetsprogramm_code = bis.tbl_bisio.mobilitaetsprogramm_code)', 'LEFT'); + $this->BisioModel->addJoin('lehre.tbl_lehreinheit le', 'ON (le.lehreinheit_id = bis.tbl_bisio.lehreinheit_id)', 'LEFT'); + $this->BisioModel->addOrder('von', 'DESC'); + $this->BisioModel->addOrder('bis', 'DESC'); + $this->BisioModel->addOrder('bisio_id', 'DESC'); + $result = $this->BisioModel->loadWhere( + array('student_uid' => $student_uid) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getProgramsMobility() + { + $this->load->model('codex/Mobilitaetsprogramm_model', 'MobilitaetsprogrammModel'); + + $result = $this->MobilitaetsprogrammModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function insertMobility() + { + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $student_uid = $this->input->post('uid'); + + if(!$student_uid) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + + $von = $formData['von'] ?? null; + $bis = $formData['bis'] ?? null; + $nation_code = $formData['nation_code'] ?? null; + $mobilitaetsprogramm_code = $formData['mobilitaetsprogramm_code'] ?? null; + $herkunftsland_code = $formData['herkunftsland_code'] ?? null; + $ects_erworben = $formData['ects_erworben'] ?? null; + $ects_angerechnet = $formData['ects_angerechnet'] ?? null; + $lehreinheit_id = $formData['lehreinheit_id'] ?? null; + $ort = $formData['ort'] ?? null; + $universitaet = $formData['universitaet'] ?? null; + $localPurposes = $formData['localPurposes'] ?? null; + $localSupports = $formData['localSupports'] ?? null; + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('nation_code', 'Nation_code', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Nation_code']) + ]); + $this->form_validation->set_rules('herkunftsland_code', 'Herkunftsland_code', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Herkunftsland_code']) + ]); + $this->form_validation->set_rules('mobilitaetsprogramm_code', 'Mobilitaetsprogramm_code', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Mobilitaetsprogramm_code']) + ]); + $this->form_validation->set_rules('von', 'VonDatum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum']) + ]); + + $this->form_validation->set_rules('bis', 'VBisDatum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VBisDatum']) + ]); + + $this->form_validation->set_rules('ects_erworben', 'Ects_erworben', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ects_erworben']) + ]); + + $this->form_validation->set_rules('ects_angerechnet', 'Ects_angerechnet', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ects_angerechnet']) + ]); + + $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->BisioModel->insert([ + 'student_uid' => $student_uid, + 'von' => $von, + 'bis' => $bis, + 'mobilitaetsprogramm_code' => $mobilitaetsprogramm_code, + 'nation_code' => $nation_code, + 'herkunftsland_code' => $herkunftsland_code, + 'lehreinheit_id' => $lehreinheit_id, + 'ort' => $ort, + 'universitaet' => $universitaet, + 'ects_erworben' => $ects_erworben , + 'ects_angerechnet' => $ects_angerechnet, + 'insertamum' => date('c'), + 'insertvon' => $authUID, + ]); + + $bisio_id = $this->getDataOrTerminateWithError($result); + + //check if localData (purposes) + if(count($localPurposes) > 0){ + foreach ($localPurposes as $zweck){ + $zweck = (int)$zweck; + $this->addMobilityPurpose($bisio_id, $zweck); + } + } + + //check if localData (supports) + if(count($localSupports) > 0){ + foreach ($localSupports as $support){ + $this->addMobilitySupport($bisio_id, $support); + } + } + + $this->terminateWithSuccess($bisio_id); + } + + public function loadMobility($bisio_id) + { + $this->BisioModel->addSelect("*"); + $this->BisioModel->addJoin('bis.tbl_mobilitaetsprogramm mp', 'ON (mp.mobilitaetsprogramm_code = bis.tbl_bisio.mobilitaetsprogramm_code)', 'LEFT'); + $this->BisioModel->addJoin('lehre.tbl_lehreinheit le', 'ON (le.lehreinheit_id = bis.tbl_bisio.lehreinheit_id)', 'LEFT'); + $result = $this->BisioModel->loadWhere( + array('bisio_id' => $bisio_id) + ); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function updateMobility() + { + + $this->load->library('form_validation'); + $authUID = getAuthUID(); + + $student_uid = $this->input->post('uid'); + + if(!$student_uid) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + } + $formData = $this->input->post('formData'); + + $von = $formData['von'] ?? null; + $bis = $formData['bis'] ?? null; + $nation_code = $formData['nation_code'] ?? null; + $mobilitaetsprogramm_code = $formData['mobilitaetsprogramm_code'] ?? null; + $herkunftsland_code = $formData['herkunftsland_code'] ?? null; + $ects_erworben = $formData['ects_erworben'] ?? null; + $ects_angerechnet = $formData['ects_angerechnet'] ?? null; + $lehreinheit_id = $formData['lehreinheit_id'] ?? null; + $ort = $formData['ort'] ?? null; + $universitaet = $formData['universitaet'] ?? null; + + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('nation_code', 'Nation_code', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Nation_code']) + ]); + $this->form_validation->set_rules('herkunftsland_code', 'Herkunftsland_code', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Herkunftsland_code']) + ]); + + $this->form_validation->set_rules('mobilitaetsprogramm_code', 'Mobilitaetsprogramm_code', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Mobilitaetsprogramm_code']) + ]); + $this->form_validation->set_rules('von', 'VonDatum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum']) + ]); + + $this->form_validation->set_rules('bis', 'VBisDatum', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VBisDatum']) + ]); + + $this->form_validation->set_rules('ects_erworben', 'Ects_erworben', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ects_erworben']) + ]); + + $this->form_validation->set_rules('ects_angerechnet', 'Ects_angerechnet', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Ects_angerechnet']) + ]); + + $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->BisioModel->update( + [ + 'bisio_id' => $formData['bisio_id'] + ], + [ + 'student_uid' => $student_uid, + + 'von' => $von, + 'bis' => $bis, + 'mobilitaetsprogramm_code' => $mobilitaetsprogramm_code, + 'nation_code' => $nation_code, + 'herkunftsland_code' => $herkunftsland_code, + 'lehreinheit_id' => $lehreinheit_id, + 'ort' => $ort, + 'universitaet' => $universitaet, + 'ects_erworben' => $ects_erworben , + 'ects_angerechnet' => $ects_angerechnet, + 'updateamum' => date('c'), + 'updatevon' => $authUID, + ] + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function deleteMobility() + { + $bisio_id = $this->input->post('bisio_id'); + + //check if entry in MobilityOnline extension exists + Events::trigger('mobility_delete', $bisio_id); + + $result = $this->BisioModel->delete( + array('bisio_id' => $bisio_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + + } + + public function getLVList($studiengang_kz) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getLvsByStudiengangkz($studiengang_kz); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getAllLehreinheiten() + { + $lv_id = $this->input->post('lv_id'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + $result = $this->LehreinheitModel->getLesFromLvIds($lv_id, $studiensemester_kurzbz); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getLvsandLesByStudent($student_uid) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getLvsByStudent($student_uid); + + $data = $this->getDataOrTerminateWithError($result); + + $lv_ids = array(); + $allData = array(); + + foreach ($data as $lehrveranstaltung) { + $lv_ids[] = $lehrveranstaltung->lehrveranstaltung_id; + } + + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + foreach ($lv_ids as $id) + { + $result = $this->LehreinheitModel->getLesFromLvIds($id); + $data = $this->getDataOrTerminateWithError($result); + + if (is_array($data)) { + $allData = array_merge($allData, $data); + } + } + + return $this->terminateWithSuccess($allData); + } + + public function getPurposes($bisio_id) + { + $bisio_id = (int)$bisio_id; + + $this->load->model('codex/Bisiozweck_model', 'BisiozweckModel'); + + $this->BisiozweckModel->addSelect("*"); + $this->BisiozweckModel->addJoin('bis.tbl_zweck zw', 'ON (zw.zweck_code = bis.tbl_bisio_zweck.zweck_code)'); + + $result = $this->BisiozweckModel->loadWhere( + array('bisio_id' => $bisio_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getSupports($bisio_id) + { + $bisio_id = (int)$bisio_id; + + $this->load->model('codex/Bisioaufenthaltfoerderung_model', 'BisioaufenthaltfoerderungModel'); + + $this->BisioaufenthaltfoerderungModel->addSelect("*"); + $this->BisioaufenthaltfoerderungModel->addJoin('bis.tbl_aufenthaltfoerderung af', 'ON (af.aufenthaltfoerderung_code = bis.tbl_bisio_aufenthaltfoerderung.aufenthaltfoerderung_code)'); + + $result = $this->BisioaufenthaltfoerderungModel->loadWhere( + array('bisio_id' => $bisio_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getListPurposes() + { + $this->load->model('codex/Zweck_model', 'ZweckModel'); + + $result = $this->ZweckModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getListSupports() + { + $this->load->model('codex/Aufenthaltfoerderung_model', 'AufenthaltfoerderungModel'); + + $result = $this->AufenthaltfoerderungModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function addMobilityPurpose($bisio_id, $local_purpose = null) + { + $zweck_code = $this->input->post('zweck_code'); + + if($local_purpose){ + $zweck_code = $local_purpose; + } + + $this->load->model('codex/Bisiozweck_model', 'BisiozweckModel'); + if(!$local_purpose) + { + $check = $this->BisiozweckModel->loadWhere( + [ + 'bisio_id' => $bisio_id, + 'zweck_code' => $zweck_code, + ] + ); + if (hasData($check)) + { + $this->terminateWithError($this->p->t('ui', 'error_entryExisting'), self::ERROR_TYPE_GENERAL); + } + } + + $result = $this->BisiozweckModel->insert( + array( + 'bisio_id' => $bisio_id, + 'zweck_code' => $zweck_code + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + + if($local_purpose) + { + return $data; + } + + return $this->terminateWithSuccess(current($data)); + } + + public function deleteMobilityPurpose($bisio_id) + { + $zweck_code = $this->input->post('zweck_code'); + + $this->load->model('codex/Bisiozweck_model', 'BisiozweckModel'); + + + $result = $this->BisiozweckModel->delete( + array( + 'bisio_id' => $bisio_id, + 'zweck_code' => $zweck_code + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess(current($data)); + } + + public function addMobilitySupport($bisio_id, $local_support = null) + { + $aufenthaltfoerderung_code = $this->input->post('aufenthaltfoerderung_code'); + + if($local_support){ + $aufenthaltfoerderung_code = $local_support; + } + $this->load->model('codex/Bisioaufenthaltfoerderung_model', 'BisioaufenthaltfoerderungModel'); + + if(!$local_support) + { + $check = $this->BisioaufenthaltfoerderungModel->loadWhere( + [ + 'bisio_id' => $bisio_id, + 'aufenthaltfoerderung_code' => $aufenthaltfoerderung_code, + ] + ); + if (hasData($check)) + { + $this->terminateWithError($this->p->t('ui', 'error_entryExisting'), self::ERROR_TYPE_GENERAL); + } + } + + $result = $this->BisioaufenthaltfoerderungModel->insert( + array( + 'bisio_id' => $bisio_id, + 'aufenthaltfoerderung_code' => $aufenthaltfoerderung_code + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + + if($local_support) + { + return $data; + } + + return $this->terminateWithSuccess(current($data)); + } + + public function deleteMobilitySupport($bisio_id) + { + $aufenthaltfoerderung_code = $this->input->post('aufenthaltfoerderung_code'); + + $this->load->model('codex/Bisioaufenthaltfoerderung_model', 'BisioaufenthaltfoerderungModel'); + + $result = $this->BisioaufenthaltfoerderungModel->delete( + array( + 'bisio_id' => $bisio_id, + 'aufenthaltfoerderung_code' => $aufenthaltfoerderung_code + ) + ); + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess(current($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..ba7cd1928 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Notiz.php @@ -0,0 +1,385 @@ + ['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'], + 'getCountNotes' => ['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..4d0aa5fe1 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Prestudent.php @@ -0,0 +1,334 @@ + ['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'], + 'getBisstandort' => ['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, true); + + if ($val !== null || $prop === 'foerderrelevant') { + $update_prestudent[$prop] = $val; + } + + // allowed to be null, but has to be in postparameter + if ( + in_array($prop, ['zgvdatum', 'zgvmadatum', 'zgvdoktordatum', 'zgv_code', 'zgvmas_code', 'zgvdoktor_code']) + && !isset($update_prestudent[$prop]) + && array_key_exists($prop, $_POST) + ) + { + $update_prestudent[$prop] = null; + } + } + + $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->addSelect('zgv_code'); + $this->ZgvModel->addSelect('zgv_bez'); + $this->ZgvModel->addSelect('aktiv'); + $this->ZgvModel->addSelect('zgv_bez as label'); + $this->ZgvModel->addOrder('zgv_bez'); + + $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->addSelect('zgvdoktor_code'); + $this->ZgvdoktorModel->addSelect('zgvdoktor_bez'); + $this->ZgvdoktorModel->addSelect('aktiv'); + $this->ZgvdoktorModel->addSelect('zgvdoktor_bez as label'); + $this->ZgvdoktorModel->addOrder('zgvdoktor_bez'); + + $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->addSelect('zgvmas_code'); + $this->ZgvmasterModel->addSelect('zgvmas_bez'); + $this->ZgvmasterModel->addSelect('aktiv'); + $this->ZgvmasterModel->addSelect('zgvmas_bez as label'); + $this->ZgvmasterModel->addOrder('zgvmas_bez'); + + $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 getBisstandort() + { + $this->load->model('codex/Bisstandort_model', 'BisstandortModel'); + + $result = $this->BisstandortModel->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/Pruefung.php b/application/controllers/api/frontend/v1/stv/Pruefung.php new file mode 100644 index 000000000..e205c85b8 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Pruefung.php @@ -0,0 +1,577 @@ +. + */ + +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 Pruefung extends FHCAPI_Controller +{ + public function __construct() + { + parent::__construct([ + 'getPruefungen' => ['admin:r', 'assistenz:r'], + 'loadPruefung' => ['admin:r', 'assistenz:r'], + 'getTypenPruefungen' => ['admin:r', 'assistenz:r'], + 'getLehreinheiten' => ['admin:r', 'assistenz:r'], + 'getAllLehreinheiten' => ['admin:r', 'assistenz:r'], + 'getLvsByStudent' => ['admin:r', 'assistenz:r'], + 'getLvsandLesByStudent' => ['admin:r', 'assistenz:r'], + 'getLvsAndMas' => ['admin:r', 'assistenz:r'], + 'getMitarbeiterLv' => ['admin:r', 'assistenz:r'], + 'getNoten' => ['admin:r', 'assistenz:r'], + 'checkZeugnisnoteLv' => ['admin:r', 'assistenz:r'], + 'checkTermin1' => ['admin:r', 'assistenz:r'], + 'insertPruefung' => self::PERM_LOGGED, + 'updatePruefung' =>self::PERM_LOGGED, + 'deletePruefung' =>self::PERM_LOGGED, + ]); + + //Load Models + $this->load->model('education/LePruefung_model', 'PruefungModel'); + + //version with postParameter + if ($this->router->method == 'insertPruefung') + { + $student_uid = $this->input->post('student_uid'); + + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->load([$student_uid]); + $student = $this->getDataOrTerminateWithError($result); + + $prestudent_id = current($student)->prestudent_id; + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:w', 'assistenz:w']); + } + + // parameter from uri + if ($this->router->method == 'updatePruefung' || $this->router->method == 'deletePruefung') + { + $pruefung_id = current(array_slice($this->uri->rsegments, 2)); + + $result = $this->PruefungModel->load($pruefung_id); + $pruefung = $this->getDataOrTerminateWithError($result); + $student_uid = current($pruefung)->student_uid; + + + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->load([$student_uid]); + $student = $this->getDataOrTerminateWithError($result); + $prestudent_id = current($student)->prestudent_id; + + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:rw', 'assistenz:rw']); + } + + if ($this->router->method == 'loadPruefung') + { + $pruefung_id = current(array_slice($this->uri->rsegments, 2)); + + $result = $this->PruefungModel->load($pruefung_id); + $pruefung = $this->getDataOrTerminateWithError($result); + + + $student_uid = current($pruefung)->student_uid; + + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->load([$student_uid]); + $student = $this->getDataOrTerminateWithError($result); + $prestudent_id = current($student)->prestudent_id; + + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:r', 'assistenz:r']); + } + + if ($this->router->method == 'getPruefungen') + { + $student_uid = current(array_slice($this->uri->rsegments, 2)); + + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->load([$student_uid]); + $student = $this->getDataOrTerminateWithError($result); + $prestudent_id = current($student)->prestudent_id; + + $this->checkPermissionsForPrestudent($prestudent_id, ['admin:r', 'assistenz:r']); + } + + // Load language phrases + $this->loadPhrases([ + 'global', 'ui','lehre' + ]); + } + + public function getPruefungen($student_uid, $studiensemester_kurzbz = null) + { + $result = $this->PruefungModel->getPruefungenByStudentuid($student_uid); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function loadPruefung($pruefung_id) + { + $this->PruefungModel->addSelect('tbl_pruefung.datum'); + $this->PruefungModel->addSelect("TO_CHAR(tbl_pruefung.datum::timestamp, 'DD.MM.YYYY') AS format_datum"); + $this->PruefungModel->addSelect('tbl_pruefung.anmerkung'); + $this->PruefungModel->addSelect('tbl_pruefung.pruefungstyp_kurzbz'); + $this->PruefungModel->addSelect('tbl_pruefung.pruefung_id'); + $this->PruefungModel->addSelect('tbl_pruefung.lehreinheit_id'); + $this->PruefungModel->addSelect('tbl_pruefung.student_uid'); + $this->PruefungModel->addSelect('tbl_pruefung.mitarbeiter_uid'); + $this->PruefungModel->addSelect('tbl_pruefung.punkte'); + $this->PruefungModel->addSelect('tbl_pruefung.note'); + + $this->PruefungModel->addSelect('tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung'); + $this->PruefungModel->addSelect('tbl_lehrveranstaltung.lehrveranstaltung_id'); + $this->PruefungModel->addSelect('tbl_lehrveranstaltung.semester'); + $this->PruefungModel->addSelect('tbl_lehrveranstaltung.lehrform_kurzbz'); + $this->PruefungModel->addSelect('tbl_note.bezeichnung as note_bezeichnung'); + $this->PruefungModel->addSelect('tbl_pruefungstyp.beschreibung as typ_beschreibung'); + $this->PruefungModel->addSelect('tbl_lehreinheit.studiensemester_kurzbz as studiensemester_kurzbz'); + + $this->PruefungModel->addJoin('lehre.tbl_lehreinheit', 'lehre.tbl_pruefung.lehreinheit_id = lehre.tbl_lehreinheit.lehreinheit_id'); + $this->PruefungModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id'); + $this->PruefungModel->addJoin('lehre.tbl_note', 'note'); + $this->PruefungModel->addJoin('lehre.tbl_pruefungstyp', 'pruefungstyp_kurzbz'); + + + $this->PruefungModel->addLimit(1); + + $result = $this->PruefungModel->loadWhere( + array('pruefung_id' => $pruefung_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'=> 'Pruefung_id']), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + /** + * Inserts a pruefung + * + * @param lehrveranstaltung_id, student_uid, lehreinheit_id + * + * @return values on success + * retval 0: pruefung inserted + * reval 1: pruefung and zeugnisnote inserted + * retval 2: pruefung inserted, no insert Zeugnisnote + * (change after date of examination) + * retval 3: pruefung of type Termin2 inserted + * and pruefung of type Termin1 as well + * retval 5: prueufungen Termin 2 and 1 inserted + * and no insert Zeugnisnote (change after date of examination) + */ + public function insertPruefung() + { + $authUID = getAuthUID(); + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehrveranstaltung')]), + ]); + $this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]), + ]); + $this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]), + ]); + $this->form_validation->set_rules( + 'datum', + $this->p->t('global', 'datum'), + ['is_valid_date'] + ); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + //calculate studiensemester_kurzbz this from lehreinheit (case newPruefung) + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + if (!$studiensemester_kurzbz) + { + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + $result = $this->LehreinheitModel->load($this->input->post('lehreinheit_id')); + + $lehreinheit = $this->getDataOrTerminateWithError($result); + $studiensemester_kurzbz = current($lehreinheit)->studiensemester_kurzbz; + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + } + + $result = $this->PruefungModel->insert([ + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'datum' => $this->input->post('datum'), + 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), + 'note' => $this->input->post('note'), + 'anmerkung' => $this->input->post('anmerkung'), + 'insertamum' => date('c'), + 'insertvon' => $authUID, + ]); + + $this->getDataOrTerminateWithError($result); + + //check if existing zeugnisnote + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $result = $this->ZeugnisnoteModel->loadWhere(array( + 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), + 'student_uid' => $this->input->post('student_uid'), + 'studiensemester_kurzbz' => $studiensemester_kurzbz)); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) + { + //insert zeugnisnote, if not existing + $result = $this->ZeugnisnoteModel->insert(array( + 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), + 'student_uid' => $this->input->post('student_uid'), + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'note' => $this->input->post('note'), + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $this->input->post('datum'), + 'insertamum' => date('c'), + 'insertvon' => $authUID + )); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(1); + } + + $return_code = 0; + + //handling Termin1 if not existing + if($this->input->post('pruefungstyp_kurzbz') == "Termin2") + { + $resultP = $this->PruefungModel->loadWhere(array( + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'pruefungstyp_kurzbz' => 'Termin1')); + + if (isError($resultP)) + { + $this->terminateWithError(getError($resultP), self::ERROR_TYPE_GENERAL); + } + if(!hasData($resultP)) + { + //check if existing Zeugnisnote + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + $this->ZeugnisnoteModel->addJoin('lehre.tbl_lehreinheit', 'lehrveranstaltung_id'); + + $resultP = $this->ZeugnisnoteModel->loadWhere(array( + 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), + 'student_uid' => $this->input->input->post('student_uid'), + 'lehre.tbl_zeugnisnote.studiensemester_kurzbz' => $studiensemester_kurzbz)); + if (isError($resultP)) + { + $this->terminateWithError(getError($resultP), self::ERROR_TYPE_GENERAL); + } + if (!hasData($resultP)) + { + $this->terminateWithError("Zeugnisnote existiert nicht", self::ERROR_TYPE_GENERAL); + } + $dataNote = current(getData($resultP)); + + $resultN = $this->PruefungModel->insert([ + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'datum' => $dataNote->benotungsdatum, + 'pruefungstyp_kurzbz' => 'Termin1', + 'note' => $dataNote->note, + 'punkte' => $dataNote->punkte, + 'anmerkung' => 'automatisiert aus Zeugnisnote erstellt', + 'insertamum' => date('c'), + 'insertvon' => $authUID, + ]); + + if (isError($resultN)) { + $this->terminateWithError(getError($resultN), self::ERROR_TYPE_GENERAL); + } + $return_code = 3; + } + } + + $note = current(getData($result)); + $uebernahmedatum = new DateTime($note->uebernahmedatum); + $benotungsdatum = new DateTime($note->benotungsdatum); + + $checkDate = $uebernahmedatum === '' || $benotungsdatum > $uebernahmedatum + ? $benotungsdatum + : $uebernahmedatum; + + if ($checkDate >= $this->input->post('datum') && $note !== $note->note) + { + $this->terminateWithSuccess($return_code + 2); + } + $this->terminateWithSuccess($return_code + 2); + } + + /** + * Updates a pruefung + * + * @param pruefung_id + * + * @return success or error + * + * no impact on lehre.tbl_zeugnisnote + */ + public function updatePruefung($pruefung_id) + { + $result = $this->PruefungModel->load($pruefung_id); + + $oldpruefung = $this->getDataOrTerminateWithError($result); + if (!$oldpruefung) + show_404(); // Pruefung that should be updated does not exist + + $authUID = getAuthUID(); + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehrveranstaltung')]), + ]); + $this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]), + ]); + $this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]), + ]); + $this->form_validation->set_rules( + 'datum', + $this->p->t('global', 'datum'), + ['is_valid_date'] + ); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->PruefungModel->update( + [ + 'pruefung_id' => $pruefung_id + ], + [ 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'note' => $this->input->post('note'), + 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), + 'datum' => $this->input->post('datum'), + 'anmerkung' => $this->input->post('anmerkung'), + 'updatevon' => $authUID, + 'updateamum' => date('c'), + ] + ); + $this->getDataOrTerminateWithError($result); + + return $this->outputJsonSuccess(true); + } + + /** + * Deletes a pruefung + * + * @param pruefung_id + * + * @return success or error + * + * no impact on lehre.tbl_zeugnisnote + */ + public function deletePruefung($pruefung_id) + { + $result = $this->PruefungModel->load($pruefung_id); + + $oldpruefung = $this->getDataOrTerminateWithError($result); + if (!$oldpruefung) + show_404(); // Pruefung that should be deleted does not exist + + $result = $this->PruefungModel->delete( + [ + 'pruefung_id' => $pruefung_id + ] + ); + + $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess(true); + } + + public function getTypenPruefungen() + { + $this->load->model('education/Pruefungstyp_model', 'PruefungtypModel'); + + //TODO(Manu) sort Termin3 + $this->PruefungtypModel->addOrder('sort', 'ASC'); + $result = $this->PruefungtypModel->loadWhere( + array('abschluss' => 'false') + ); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getAllLehreinheiten() + { + $lv_id = $this->input->post('lv_id'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + $result = $this->LehreinheitModel->getLesFromLvIds($lv_id, $studiensemester_kurzbz); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getLvsandLesByStudent($student_uid, $semester_kurzbz=null) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getLvsByStudent($student_uid, $semester_kurzbz); + + $data = $this->getDataOrTerminateWithError($result); + + $lv_ids = array(); + $allData = array(); + + foreach ($data as $lehrveranstaltung) { + $lv_ids[] = $lehrveranstaltung->lehrveranstaltung_id; + } + + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + foreach ($lv_ids as $id) + { + $result = $this->LehreinheitModel->getLesFromLvIds($id, $semester_kurzbz); + $data = $this->getDataOrTerminateWithError($result); + + if (is_array($data)) { + $allData = array_merge($allData, $data); + } + } + + return $this->terminateWithSuccess($allData); + } + + public function getLvsAndMas($student_uid) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getLvsByStudent($student_uid); + + $data = $this->getDataOrTerminateWithError($result); + + $lv_ids = array(); + $allDataMa = array(); + + foreach ($data as $lehrveranstaltung) + { + $lv_ids[] = $lehrveranstaltung->lehrveranstaltung_id; + } + + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + foreach ($lv_ids as $id) + { + $resultMa = $this->MitarbeiterModel->getMitarbeiterFromLV($id); + $dataMa = $this->getDataOrTerminateWithError($resultMa); + + if (is_array($dataMa)) + { + $allDataMa = array_merge($allDataMa, $dataMa); + } + } + return $this->terminateWithSuccess($allDataMa); + } + + public function getLvsByStudent($student_uid, $studiensemester_kurzbz = null) + { + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->getLvsByStudent($student_uid, $studiensemester_kurzbz); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($data); + } + + public function getMitarbeiterLv($lv_id) + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $result = $this->MitarbeiterModel->getMitarbeiterFromLV($lv_id); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($data); + } + + public function getNoten() + { + $this->load->model('education/Note_model', 'NoteModel'); + + $this->NoteModel->addOrder('note', 'ASC'); + $result = $this->NoteModel->load(); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(getData($result) ?: []); + } + + public function checkZeugnisnoteLv() + { + $student_uid = $this->input->post('student_uid'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $lehrveranstaltung_id = $this->input->post('lehrveranstaltung_id'); + + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $result = $this->ZeugnisnoteModel->loadWhere(array( + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'student_uid' => $student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz)); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($data); + } +} 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..665fb620f --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Status.php @@ -0,0 +1,1774 @@ + ['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'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + // 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 + ) + { + $studiensemester_kurzbz = $this->input->post('currentSemester'); + if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + } + + $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($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester) + { + $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 Studentlehrverband if no Status left in this semester + $cilsresult = $this->PrestudentstatusModel->checkIfLastStatusEntry($prestudent_id, $studiensemester_kurzbz); + $isLastPrestudentStatusForSemester = $this->getDataOrTerminateWithError($cilsresult); + + //Delete Status + $delpsresult = $this->PrestudentstatusModel->delete( + [ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'ausbildungssemester' => $ausbildungssemester, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ] + ); + $this->getDataOrTerminateWithError($delpsresult); + + if ($isLastPrestudentStatusForSemester) + { + //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 + + $checkres = $this->StudentlehrverbandModel->load(array( + 'student_uid' => $studentlvb->student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + )); + if(hasData($checkres)) + { + $result = $this->StudentlehrverbandModel->update( + array( + 'student_uid' => $studentlvb->student_uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ), + array( + 'studiengang_kz' => $studentlvb->studiengang_kz, + 'semester' => $studentlvb->semester, + 'verband' => $studentlvb->verband, + 'gruppe' => $studentlvb->gruppe, + 'updateamum' => $now, + 'updatevon' => $authUID + ) + ); + } + else + { + //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..0cfd82c36 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Student.php @@ -0,0 +1,717 @@ +. + */ + +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', 'lehre' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Get details for a prestudent + * + * @param string $prestudent_id + * @return void + */ + public function get($prestudent_id, $studiensemester_kurzbz) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $this->PrestudentModel->addSelect('p.person_id'); + $this->PrestudentModel->addSelect('p.titelpre'); + $this->PrestudentModel->addSelect('p.nachname'); + $this->PrestudentModel->addSelect('p.vorname'); + $this->PrestudentModel->addSelect('p.wahlname'); + $this->PrestudentModel->addSelect('p.vornamen'); + $this->PrestudentModel->addSelect('p.titelpost'); + $this->PrestudentModel->addSelect('p.svnr'); + $this->PrestudentModel->addSelect('p.ersatzkennzeichen'); + $this->PrestudentModel->addSelect('p.gebdatum'); + $this->PrestudentModel->addSelect('p.geschlecht'); + $this->PrestudentModel->addSelect('p.foto'); + $this->PrestudentModel->addSelect('p.foto_sperre'); + $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'); + $this->PrestudentModel->addSelect('p.geburtsnation'); + $this->PrestudentModel->addSelect('p.sprache'); + $this->PrestudentModel->addSelect('p.gebort'); + $this->PrestudentModel->addSelect('p.homepage'); + $this->PrestudentModel->addSelect('p.anmerkung'); + $this->PrestudentModel->addSelect('p.familienstand'); + $this->PrestudentModel->addSelect('p.staatsbuergerschaft'); + $this->PrestudentModel->addSelect('p.matr_nr'); + $this->PrestudentModel->addSelect('p.anrede'); + $this->PrestudentModel->addSelect('p.zugangscode'); + + 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->addSelect( + "( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus pss + WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY GREATEST(pss.datum, '0001-01-01') DESC + LIMIT 1 + ) AS statusofsemester" + ); + + $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'); +/* $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pss', 'pss.prestudent_id = tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = ' . $this->PrestudentModel->escape($studiensemester_kurzbz), + 'LEFT');*/ + + $result = $this->PrestudentModel->loadWhere(['tbl_prestudent.prestudent_id' => $prestudent_id]); + + $student = $this->getDataOrTerminateWithError($result); + + if (!$student) + return show_404(); + + + $this->terminateWithSuccess(current($student)); + } + + protected function isLaufendesSemester($selectedSemester) + { + $laufendesStudiensemester = ''; + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $result = $this->StudiensemesterModel->getAktOrNextSemester(); + if(hasData($result)) { + $laufendesStudiensemester = (getData($result))[0]->studiensemester_kurzbz; + } + + $islaufendesSemester = $selectedSemester === $laufendesStudiensemester; + return $islaufendesSemester; + } + + /** + * Saves data to a prestudent + * + * @param string $prestudent_id + * @return void + */ + public function save($prestudent_id, $studiensemester_kurzbz) + { + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $this->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->load->library('form_validation'); + + if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $authuid = getAuthUID(); + $now = date('c'); + + $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'is_valid_date'); + + $this->form_validation->set_rules('semester', 'Semester', 'integer', [ + 'integer' => $this->p->t('ui', 'error_fieldNotInteger') + ] + ); + + $this->form_validation->set_rules('alias', 'Alias', 'regex_match[/^[-a-z0-9\_\.]*[a-z0-9]{1,}\.[-a-z0-9\_]{1,}$/]', + [ + 'regex_match' => $this->p->t('ui', 'error_fieldInvalidAlias') + ]); + + $this->load->library('UDFLib'); + + $result = $this->udflib->getCiValidations($this->PersonModel, $this->input->post()); + + $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; + + $studiengang_kz = $student ? current($student)->studiengang_kz : 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', + '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']; + if($this->isLaufendesSemester($studiensemester_kurzbz)) + { + $array_allowed_props_student = ['matrikelnr', 'verband', 'semester', 'gruppe']; + } + $update_student = array(); + foreach ($array_allowed_props_student as $prop) { + $val = $this->input->post($prop); + if ($val !== null) { + $update_student[$prop] = $val; + } + } + + $array_allowed_props_benutzer = ['aktiv', 'alias']; + $update_benutzer = array(); + foreach ($array_allowed_props_benutzer as $prop) { + $val = $this->input->post($prop); + if ($val !== null) { + $update_benutzer[$prop] = $val; + } + } + + // Check PKs + if (count($update_lehrverband) + count($update_student) && $uid === null) { + $this->terminateWithValidationErrors(['' => $this->p->t('lehre', 'error_no_student')]); + } + if (count($update_person) && $person_id === null) { + $this->terminateWithValidationErrors(['' => $this->p->t('lehre', 'error_no_person')]); + } + if (count($update_benutzer) && $uid === null) { + $this->terminateWithValidationErrors(['' => $this->p->t('lehre', 'error_no_student')]); + } + + // Do Updates + if (count($update_lehrverband)) { + + $curstudlvb = $this->StudentlehrverbandModel->load([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $uid + ]); + + $data = $this->getDataOrTerminateWithError($curstudlvb); + $data = current($data); + + $verbandCurrent = $data->verband; + $studiengang_kz = $data->studiengang_kz; + $semesterCurrent = $data->semester; + $gruppeCurrent = $data->gruppe; + + $verband = isset($update_lehrverband['verband']) ? $update_lehrverband['verband'] : $verbandCurrent; + $gruppe = isset($update_lehrverband['gruppe']) ? $update_lehrverband['gruppe'] : $gruppeCurrent; + $semester = isset($update_lehrverband['semester']) ? $update_lehrverband['semester'] : $semesterCurrent; + + //check if existing Lehrverband of new data to avoid Error + $result = $this->LehrverbandModel->loadWhere([ + 'verband' => $verband, + 'gruppe' => $gruppe, + 'semester' => $semester, + 'studiengang_kz' => $studiengang_kz, + ]); + + if(!hasData($result)) + { + $this->terminateWithError($this->p->t('lehre', 'error_noLehrverband'), self::ERROR_TYPE_GENERAL); + } + + if(hasData($curstudlvb) && count(getData($curstudlvb)) > 0 ) + { + $update_lehrverband['updatevon'] = $authuid; + $update_lehrverband['updateamum'] = $now; + $result = $this->StudentlehrverbandModel->update([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $uid + ], $update_lehrverband); + } + else + { + $update_lehrverband['insertvon'] = $authuid; + $update_lehrverband['insertamum'] = $now; + $result = $this->StudentlehrverbandModel->insert(array_merge([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $uid, + 'studiengang_kz' => $studiengang_kz + ], $update_lehrverband)); + } + + $this->getDataOrTerminateWithError($result); + } + + if (count($update_person)) { + $update_person['updatevon'] = $authuid; + $update_person['updateamum'] = $now; + $result = $this->PersonModel->update( + $person_id, + $update_person + ); + $this->getDataOrTerminateWithError($result); + } + + + if (count($update_student)) { + $update_student['updatevon'] = $authuid; + $update_student['updateamum'] = $now; + $result = $this->StudentModel->update( + [$uid], + $update_student + ); + $this->getDataOrTerminateWithError($result); + } + + if (count($update_benutzer)) { + $update_benutzer['updatevon'] = $authuid; + $update_benutzer['updateamum'] = $now; + if (array_key_exists("aktiv", $update_benutzer)) + { + $update_benutzer['updateaktivvon'] = $authuid; + $update_benutzer['updateaktivam'] = $now; + } + $result = $this->BenutzerModel->update( + [$uid], + $update_benutzer + ); + $this->getDataOrTerminateWithError($result); + } + + $this->terminateWithSuccess(array_fill_keys(array_merge( + array_keys($update_lehrverband), + array_keys($update_person), + array_keys($update_student), + array_keys($update_benutzer) + ), '')); + } + + 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; + }*/ + + return success(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; + } + + public function isValidDate($value) + { + return isValidDate($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..9de0c29b1 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -0,0 +1,893 @@ +. + */ + +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()]); + $this->load->library('PhrasesLib'); + $this->loadPhrases( + array( + 'lehre' + ) + ); + + } + + /** + * Routing + * + * /inout => index + * /(studiensemester_kurzbz) => index + * /(studiensemester_kurzbz)/inout => index + * + * /(studiensemester_kurzbz)/inout/incoming => getIncoming + * /(studiensemester_kurzbz)/inout/outgoing => getOutgoing + * /(studiensemester_kurzbz)/inout/gemeinsamestudien => getGemeinsamestudien + * + * /(studiengang_kz)/prestudent => getPrestudents + * /(studiengang_kz)/prestudent/(studiensemester_kurzbz) => getPrestudents + * /(studiengang_kz)/prestudent/(studiensemester_kurzbz)/(filter) => getPrestudents + * /(studiengang_kz)/prestudent/(studiensemester_kurzbz)/(filter)/(otherfilter) => getPrestudents + * + * /(studiengang_kz)/(orgform)/prestudent => getPrestudentsOrgform + * /(studiengang_kz)/(orgform)/prestudent/(studiensemester_kurzbz) => getPrestudentsOrgform + * /(studiengang_kz)/(orgform)/prestudent/(studiensemester_kurzbz)/(filter) => getPrestudentsOrgform + * /(studiengang_kz)/(orgform)/prestudent/(studiensemester_kurzbz)/(filter)/(otherfilter) => getPrestudentsOrgform + * + * /(studiensemester_kurzbz)/(studiengang_kz)/(semester)/grp/(gruppe) => getStudentsSpezialguppe + * + * /(studiensemester_kurzbz)/(studiengang_kz) => getStudents + * /(studiensemester_kurzbz)/(studiengang_kz)/(semester) => getStudents + * /(studiensemester_kurzbz)/(studiengang_kz)/(semester)/(verband) => getStudents + * /(studiensemester_kurzbz)/(studiengang_kz)/(semester)/(verband)/(gruppe) => getStudents + * + * /(studiensemester_kurzbz)/(studiengang_kz)/(orgform)/(semester)/grp/(gruppe) => getStudentsOrgformSpezialgruppe + * + * /(studiensemester_kurzbz)/(studiengang_kz)/(orgform) => getStudentsOrgform + * /(studiensemester_kurzbz)/(studiengang_kz)/(orgform)/(semester) => getStudentsOrgform + * /(studiensemester_kurzbz)/(studiengang_kz)/(orgform)/(semester)/(verband) => getStudentsOrgform + * /(studiensemester_kurzbz)/(studiengang_kz)/(orgform)/(semester)/(verband)/(gruppe) => getStudentsOrgform + * + * /(studiensemester_kurzbz)/uid/(student_uid) => getStudent + * /(studiensemester_kurzbz)/prestudent/(prestudent_id) => getPrestudent + * /(studiensemester_kurzbz)/person/(person_id) => getPerson + */ + + public function index() + { + $this->addMeta('ci_method', __FUNCTION__); + $this->terminateWithSuccess([]); + } + + /** + * @return void + */ + public function getIncoming() + { + $this->addMeta('ci_method', __FUNCTION__); + // TODO(chris): IMPLEMENT! + $this->terminateWithSuccess([]); + } + + /** + * @return void + */ + public function getOutgoing() + { + $this->addMeta('ci_method', __FUNCTION__); + // TODO(chris): IMPLEMENT! + $this->terminateWithSuccess([]); + } + + /** + * @return void + */ + public function getGemeinsamestudien() + { + $this->addMeta('ci_method', __FUNCTION__); + // TODO(chris): IMPLEMENT! + $this->terminateWithSuccess([]); + } + + public function getPrestudents($studiengang_kz, + $studiensemester_kurzbz = null, $filter = null + ) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiengang_kz' => $studiengang_kz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'filter' => $filter + )); + + $this->fetchPrestudents($studiengang_kz, $studiensemester_kurzbz, $filter); + } + + public function getPrestudentsOrgform($studiengang_kz, $orgform_kurzbz, + $studiensemester_kurzbz = null, $filter = null + ) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiengang_kz' => $studiengang_kz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'filter' => $filter, + 'orgform_kurzbz' => $orgform_kurzbz + )); + + $this->fetchPrestudents($studiengang_kz, $studiensemester_kurzbz, $filter, $orgform_kurzbz); + } + + /** + * @param integer $studiengang_kz + * @param string $studiensemester_kurzbz (optional) + * @param string $filter (optional) + * @param string $orgform_kurzbz (optional) + * + * @return void + */ + protected function fetchPrestudents($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['ps.bewerbung_abgeschicktamum'] = null; + break; + case "bewerbungabgeschickt": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['ps.bewerbung_abgeschicktamum IS NOT NULL'] = null; + $where['ps.bestaetigtam'] = null; + break; + case "statusbestaetigt": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['ps.bestaetigtam IS NOT NULL'] = null; + break; + case "statusbestaetigtrtnichtangemeldet": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['ps.bestaetigtam IS NOT NULL'] = null; + $this->PrestudentModel->db->where('NOT EXISTS(' . $selectRT . ')', null, false); + break; + case "statusbestaetigtrtangemeldet": + $where['ps.status_kurzbz'] = 'Interessent'; + $where['ps.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(); + + //add status per semester + $this->PrestudentModel->addSelect( + "( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus pss + WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY GREATEST(pss.datum, '0001-01-01') DESC + LIMIT 1 + ) AS statusofsemester" + ); + + $this->addFilter($studiensemester_kurzbz); + + $result = $this->PrestudentModel->loadWhere($where); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getStudents($studiensemester_kurzbz, + $studiengang_kz, $semester = null, $verband = null, $gruppe = null + ) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $studiengang_kz, + 'semester' => $semester, + 'verband' => $verband, + 'gruppe' => $gruppe + )); + + $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, null); + } + + public function getStudentsOrgform($studiensemester_kurzbz, + $studiengang_kz, $orgform_kurzbz, $semester = null, $verband = null, $gruppe = null + ) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $studiengang_kz, + 'orgform_kurzbz' => $orgform_kurzbz, + 'semester' => $semester, + 'verband' => $verband, + 'gruppe' => $gruppe + )); + + $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, $orgform_kurzbz); + } + + public function getStudentsSpezialgruppe($studiensemester_kurzbz, + $studiengang_kz, $semester, $gruppe_kurzbz, + $orgform_kurzbz = null) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $studiengang_kz, + 'semester' => $semester, + 'gruppe_kurzbz' => $gruppe_kurzbz + )); + + $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, null, null, $gruppe_kurzbz, null); + } + + public function getStudentsOrgformSpezialgruppe($studiensemester_kurzbz, + $orgform_kurzbz, $studiengang_kz, $semester, $gruppe_kurzbz + ) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'orgform_kurzbz' => $orgform_kurzbz, + 'studiengang_kz' => $studiengang_kz, + 'semester' => $semester, + 'gruppe_kurzbz' => $gruppe_kurzbz + )); + + $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, null, null, $gruppe_kurzbz, $orgform_kurzbz); + } + + /** + * @param integer $studiengang_kz + * @param string $studiensemester_kurzbz + * @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 fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester = null, $verband = null, $gruppe = null, $gruppe_kurzbz = null, $orgform_kurzbz = null) + { + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + /* + $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"); + + //add status per semester + $this->PrestudentModel->addSelect( + "( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus pss + WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY GREATEST(pss.datum, '0001-01-01') DESC + LIMIT 1 + ) AS statusofsemester" + ); + + + $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 + */ + public function getPrestudent($studiensemester_kurzbz, $prestudent_id) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'prestudent_id' => $prestudent_id, + )); + + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $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'); + + //add status per semester + $this->PrestudentModel->addSelect( + "( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus pss + WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY GREATEST(pss.datum, '0001-01-01') DESC + LIMIT 1 + ) AS statusofsemester" + ); + + $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 + */ + public function getStudent($studiensemester_kurzbz, $student_uid) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'student_uid' => $student_uid, + )); + + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $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'); + + //add status per semester + $this->PrestudentModel->addSelect( + "( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus pss + WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY GREATEST(pss.datum, '0001-01-01') DESC + LIMIT 1 + ) AS statusofsemester" + ); + + $this->addSelectPrioRel(); + + + + $this->addFilter($studiensemester_kurzbz); + + $result = $this->PrestudentModel->loadWhere([ + 's.student_uid' => $student_uid + ]); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * @param string $studiensemester_kurzbz + * @param integer $person_id + * + * @return void + */ + public function getPerson($studiensemester_kurzbz, $person_id) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'person_id' => $person_id, + )); + + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + if (!$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $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'); + + //add status per semester + $this->PrestudentModel->addSelect( + "( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus pss + WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY GREATEST(pss.datum, '0001-01-01') DESC + LIMIT 1 + ) AS statusofsemester" + ); + + $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('ersatzkennzeichen'); + $this->PrestudentModel->addSelect('gebdatum'); + $this->PrestudentModel->addSelect('geschlecht'); + $this->PrestudentModel->addSelect('foto'); + $this->PrestudentModel->addSelect('foto_sperre'); + + // semester + // verband + // gruppe + + $this->PrestudentModel->addSelect('UPPER(stg.typ || stg.kurzbz) AS studiengang'); + $this->PrestudentModel->addSelect('tbl_prestudent.studiengang_kz'); + $this->PrestudentModel->addSelect('stg.bezeichnung AS stg_bezeichnung'); + $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 CONCAT(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 = json_decode($this->input->get('filter'), true); + if (!is_array($filter)) + { + $this->addMeta('addfilter', 'invalid filter: ' . $this->input->get('filter')); + return; + } + 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..6487b6263 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Verband.php @@ -0,0 +1,498 @@ +. + */ + +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', + 'stg_kz' => (int)$studiengang_kz, + '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); + + $this->load->config('stv'); + $number_displayed_past_studiensemester_default = $this->config->item('number_displayed_past_studiensemester_default'); + + $number_displayed_past_studiensemester = $data['number_displayed_past_studiensemester'] ?? $number_displayed_past_studiensemester_default; + + $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/frontend/v1/vertraege/Vertraege.php b/application/controllers/api/frontend/v1/vertraege/Vertraege.php new file mode 100644 index 000000000..bb14bc511 --- /dev/null +++ b/application/controllers/api/frontend/v1/vertraege/Vertraege.php @@ -0,0 +1,720 @@ + ['vertrag/mitarbeiter:r'], + 'getAllContractsNotAssigned' => ['vertrag/mitarbeiter:r'], + 'getAllContractsAssigned' => ['vertrag/mitarbeiter:r'], + 'getAllContractTypes' => ['vertrag/mitarbeiter:r'], + 'getAllContractStati' => ['vertrag/mitarbeiter:r'], + 'getStatiOfContract' => ['vertrag/mitarbeiter:r'], + 'loadContract' => ['vertrag/mitarbeiter:r'], + 'loadContractStatus' => ['vertrag/mitarbeiter:r'], + 'updateContract' =>['vertrag/mitarbeiter:w'], + 'addNewContract' =>['vertrag/mitarbeiter:w'], + 'deleteContract' =>['vertrag/mitarbeiter:w'], + 'insertContractStatus' =>['vertrag/mitarbeiter:w'], + 'deleteContractStatus' =>['vertrag/mitarbeiter:w'], + 'updateContractStatus' =>['vertrag/mitarbeiter:w'], + 'deleteLehrauftrag' =>['vertrag/mitarbeiter:w'], + 'deleteBetreuung' =>['vertrag/mitarbeiter:w'], + 'getMitarbeiter' => ['vertrag/mitarbeiter:r'], + 'getHeader' => ['vertrag/mitarbeiter:r'], + 'getPersonAbteilung' => ['vertrag/mitarbeiter:r'], + 'getLeitungOrg' => ['vertrag/mitarbeiter:r'], + ]); + + //Load Models and Libraries + $this->load->model('accounting/Vertrag_model', 'VertragModel'); + $this->load->model('accounting/Vertragsstatus_model', 'VertragsstatusModel'); + $this->load->model('accounting/Vertragstyp_model', 'VertragstypModel'); + $this->load->model('accounting/Vertragvertragsstatus_model', 'VertragvertragsstatusModel'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'vertrag' + ]); + } + + public function getAllVertraege($person_id) + { + $result = $this->VertragModel->loadContractsOfPerson($person_id); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function getAllContractsNotAssigned($person_id) + { + $result = $this->VertragModel->loadContractsOfPersonNotAssigned($person_id); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function getAllContractsAssigned($person_id, $vertrag_id) + { + $result = $this->VertragModel->loadContractsOfPersonAssigned($person_id, $vertrag_id); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function getStatiOfContract($person_id, $vertrag_id) + { + //check if vertrag_id corresponds with person_id and return null if not + $result = $this->VertragModel->loadWhere( + array( + 'vertrag_id' => $vertrag_id, + 'person_id' => $person_id + ) + ); + if(!hasData($result)) + { + $this->terminateWithSuccess([]); + } + + $result = $this->VertragModel->getStatiOfContract($vertrag_id); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess((getData($result) ?: [])); + } + + public function getAllContractTypes() + { + $result = $this->VertragstypModel->load(); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(getData($result) ?: []); + } + + public function getAllContractStati() + { + $result = $this->VertragsstatusModel->load(); + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess(getData($result) ?: []); + } + + public function addNewContract() + { + $this->load->library('form_validation'); + + $person_id = $this->input->post('person_id'); + + if(!$person_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person_id']), self::ERROR_TYPE_GENERAL); + } + + $formData = $this->input->post('formData'); + $vertragstyp_kurzbz = $formData['vertragstyp_kurzbz'] ?? null; + $vertragsdatum = $formData['vertragsdatum'] ?? null; + $bezeichnung = $formData['bezeichnung'] ?? null; + $betrag = $formData['betrag'] ?? null; + $vertragsstunden = $formData['vertragsstunden'] ?? null; + $vertragsstunden_studiensemester_kurzbz = $formData['vertragsstunden_studiensemester_kurzbz'] ?? null; + $anmerkung = $formData['anmerkung'] ?? null; + + $this->form_validation->set_data($formData); + $this->form_validation->set_rules('bezeichnung', 'Bezeichnung', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Bezeichnung']) + ]); + + $this->form_validation->set_rules('vertragstyp_kurzbz', 'Vertragstyp', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Vertragstyp']) + ]); + $this->form_validation->set_rules('vertragsdatum', 'Vertragsdatum', 'required|is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Vertragsdatum']), + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Vertragsdatum']) + ]); + $this->form_validation->set_rules('betrag', 'Betrag', 'required|numeric', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Betrag']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Betrag']) + ]); + $this->form_validation->set_rules('vertragsstunden', 'Stunden(Vertrags-Urfassung)', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Stunden(Vertrags-Urfassung)']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $lehrauftraege = $this->input->post('clickedRows'); + + $this->db->trans_start(); + + $result = $this->VertragModel->insert([ + 'person_id' => $person_id, + 'vertragsdatum' => $vertragsdatum, + 'bezeichnung' => $bezeichnung, + 'vertragstyp_kurzbz' => $vertragstyp_kurzbz, + 'betrag' => $betrag, + 'vertragsstunden' => $vertragsstunden, + 'vertragsstunden_studiensemester_kurzbz' => $vertragsstunden_studiensemester_kurzbz, + 'anmerkung' => $anmerkung, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]); + + $this->getDataOrTerminateWithError($result); + $vertrag_id = $result->retval; + + $status_result = $this->VertragvertragsstatusModel->insert([ + 'vertrag_id' => $vertrag_id, + 'uid' => getAuthUID(), + 'vertragsstatus_kurzbz' => 'neu', + 'insertamum' => date('c'), + 'insertvon' => getAuthUID(), + 'datum' => date('c') + ]); + + if (!$status_result) { + $this->db->trans_rollback(); + $this->terminateWithError($this->p->t('vertrag', 'error_insertOrUpdateStatusVertrag'), self::ERROR_TYPE_GENERAL); + } + + //Hinzufügen der Lehraufträge + foreach ($lehrauftraege as $row) + { + if ($row['type'] == 'Lehrauftrag') + { + $this->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + + $result_lehrauftrag = $this->LehreinheitmitarbeiterModel->update( + [ + 'lehreinheit_id' => $row['lehreinheit_id'], + 'mitarbeiter_uid' => $row['mitarbeiter_uid'] + ], + [ + 'vertrag_id' => $vertrag_id + ] + ); + + if (!$result_lehrauftrag) { + $this->db->trans_rollback(); + $this->terminateWithError($this->p->t('vertrag', 'error_addOrUpdateLehrauftraege'), self::ERROR_TYPE_GENERAL); + } + } + + if ($row['type'] == 'Betreuung') + { + $this->load->model('education/Projektbetreuer_model', 'Projektbetreuermodel'); + + $result_projektbetreuer = $this->Projektbetreuermodel->update( + [ + 'person_id' => $person_id, + 'projektarbeit_id' => $row['projektarbeit_id'], + 'betreuerart_kurzbz' => $row['betreuerart_kurzbz'] + ], + [ + 'vertrag_id' => $vertrag_id + ] + ); + + if (!$result_projektbetreuer) + { + $this->db->trans_rollback(); + $this->terminateWithError($this->p->t('vertrag', 'error_addOrUpdateLehrauftraege'), self::ERROR_TYPE_GENERAL); + } + } + } + $this->db->trans_complete(); + $this->terminateWithSuccess(true); + } + + public function updateContract() + { + $this->load->library('form_validation'); + + $vertrag_id = $this->input->post('vertrag_id'); + $person_id = $this->input->post('person_id'); + $formData = $this->input->post('formData'); + $lehrauftraege = $this->input->post('clickedRows'); + + $vertragstyp_kurzbz = $formData['vertragstyp_kurzbz'] ?? null; + $vertragsdatum = $formData['vertragsdatum'] ?? null; + $bezeichnung = $formData['bezeichnung'] ?? null; + $betrag = $formData['betrag'] ?? null; + $vertragsstunden = $formData['vertragsstunden'] ?? null; + $vertragsstunden_studiensemester_kurzbz = $formData['vertragsstunden_studiensemester_kurzbz'] ?? null; + $anmerkung = $formData['anmerkung'] ?? null; + + + $this->form_validation->set_data($formData); + $this->form_validation->set_rules('bezeichnung', 'Bezeichnung', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Bezeichnung']) + ]); + + $this->form_validation->set_rules('vertragstyp_kurzbz', 'Vertragstyp', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Vertragstyp']) + ]); + $this->form_validation->set_rules('vertragsdatum', 'Vertragsdatum', 'required|is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Vertragsdatum']), + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Vertragsdatum']) + ]); + $this->form_validation->set_rules('betrag', 'Betrag', 'required|numeric', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Betrag']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Betrag']) + ]); + $this->form_validation->set_rules('vertragsstunden', 'Stunden(Vertrags-Urfassung)', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Stunden(Vertrags-Urfassung)']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->db->trans_start(); + + $result = $this->VertragModel->update( + $vertrag_id, + [ + 'person_id' => $person_id, + 'vertragsdatum' => $vertragsdatum, + 'bezeichnung' => $bezeichnung, + 'vertragstyp_kurzbz' => $vertragstyp_kurzbz, + 'betrag' => $betrag, + 'vertragsstunden' => $vertragsstunden, + 'vertragsstunden_studiensemester_kurzbz' => $vertragsstunden_studiensemester_kurzbz, + 'anmerkung' => $anmerkung, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ] + ); + + $this->getDataOrTerminateWithError($result); + + //Adding of Lehraufträge + foreach ($lehrauftraege as $row) + { + if ($row['type'] == 'Lehrauftrag') + { + $this->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + + $result_lehrauftrag = $this->LehreinheitmitarbeiterModel->update( + [ + 'lehreinheit_id' => $row['lehreinheit_id'], + 'mitarbeiter_uid' => $row['mitarbeiter_uid'] + ], + [ + 'vertrag_id' => $vertrag_id, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ] + ); + + if (!$result_lehrauftrag) { + $this->db->trans_rollback(); + $this->terminateWithError($this->p->t('vertrag', 'error_addOrUpdateLehrauftraege'), self::ERROR_TYPE_GENERAL); + } + } + + if ($row['type'] == 'Betreuung') + { + $this->load->model('education/Projektbetreuer_model', 'Projektbetreuermodel'); + + $result_projektbetreuer = $this->Projektbetreuermodel->update( + [ + 'person_id' => $person_id, + 'projektarbeit_id' => $row['projektarbeit_id'], + 'betreuerart_kurzbz' => $row['betreuerart_kurzbz'] + ], + [ + 'vertrag_id' => $vertrag_id, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ] + ); + + if (!$result_projektbetreuer) + { + $this->db->trans_rollback(); + $this->terminateWithError($this->p->t('vertrag', 'error_addOrUpdateLehrauftraege'), self::ERROR_TYPE_GENERAL); + } + } + } + $this->db->trans_complete(); + + $this->terminateWithSuccess(true); + } + + public function loadContract($vertrag_id) + { + $result = $this->VertragModel->load($vertrag_id); + + if (isError($result)) { + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) { + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Vertrag_id']), self::ERROR_TYPE_GENERAL); + } + + $this->terminateWithSuccess(current(getData($result))); + } + + public function deleteContract($vertrag_id) + { + $this->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + + //check if attached Lehrauftrag + $resultLehrauftrag = $this->LehreinheitmitarbeiterModel->load([ + 'vertrag_id' => $vertrag_id + ]); + + if(hasData($resultLehrauftrag)) + { + $resultLehrauftrag = getData($resultLehrauftrag); + foreach($resultLehrauftrag as $lehrauftrag) + { + $result = $this->LehreinheitmitarbeiterModel->update( + [ + 'lehreinheit_id' => $lehrauftrag->lehreinheit_id, + 'mitarbeiter_uid' => $lehrauftrag->mitarbeiter_uid, + 'vertrag_id' => $vertrag_id + ], + [ + 'vertrag_id' => null, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ] + ); + + $this->getDataOrTerminateWithError($result); + } + } + + //if attached Betreuung + $this->load->model('education/Projektbetreuer_model', 'Projektbetreuermodel'); + + //if attached Betreuung + $resultBetreuung = $this->Projektbetreuermodel->load([ + 'vertrag_id' => $vertrag_id + ]); + + if(hasData($resultBetreuung)) + { + $resultBetreuung = getData($resultBetreuung); + foreach($resultBetreuung as $betreuung) + { + $result = $this->Projektbetreuermodel->update( + [ + 'person_id' => $betreuung->person_id, + 'projektarbeit_id' => $betreuung->projektarbeit_id, + 'betreuerart_kurzbz' => $betreuung->betreuerart_kurzbz, + 'vertrag_id' => $vertrag_id + ], + [ + 'vertrag_id' => null, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + + ] + ); + + $this->getDataOrTerminateWithError($result); + } + } + + $result = $this->VertragvertragsstatusModel->load([ + 'vertrag_id' => $vertrag_id + ]); + + if(hasData($result)) + { + $data = getData($result); + foreach ($data as $item) + { + //delete all entries in lehre.tbl_vertrag_vertragsstatus + $result = $this->VertragvertragsstatusModel->delete([ + 'vertrag_id' => $vertrag_id, + 'vertragsstatus_kurzbz' => $item->vertragsstatus_kurzbz, + 'uid' => $item->uid + ]); + if(isError($result)) + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + } + + //delete Contract + $result = $this->VertragModel->delete( + array('vertrag_id' => $vertrag_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' => 'Vertrag_id']), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(current(getData($result))); + } + + public function insertContractStatus() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('vertragsstatus_kurzbz', 'vertragsstatus_kurzbz', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'vertragsstatus_kurzbz']) + ]); + $this->form_validation->set_rules('datum', 'Datum', 'required|is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Datum']), + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Datum']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->VertragvertragsstatusModel->loadWhere( + array( + 'vertrag_id' => $this->input->post('vertrag_id'), + 'vertragsstatus_kurzbz' => $this->input->post('vertragsstatus_kurzbz') + ) + ); + + if (hasData($result)) + { + $this->terminateWithError($this->p->t('vertrag', 'error_statusVorhanden'), self::ERROR_TYPE_GENERAL); + } + + $status_result = $this->VertragvertragsstatusModel->insert([ + 'vertrag_id' => $this->input->post('vertrag_id'), + 'uid' => getAuthUID(), + 'vertragsstatus_kurzbz' => $this->input->post('vertragsstatus_kurzbz'), + 'insertamum' => date('c'), + 'insertvon' => getAuthUID(), + 'datum' => $this->input->post('datum') + ]); + + if (!$status_result) { + $this->terminateWithError('Fehler beim Hinzufügen des Vertragsstatus.'); + } + + return $this->terminateWithSuccess(current(getData($status_result))); + } + + public function deleteContractStatus() + { + $status = $this->input->post('vertragsstatus_kurzbz'); + $vertrag_id = $this->input->post('vertrag_id'); + + $result = $this->VertragvertragsstatusModel->delete( + array( + 'vertrag_id' => $vertrag_id, + 'vertragsstatus_kurzbz' => $status + ) + ); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'vertragsstatus_kurzb']), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(current(getData($result))); + } + + public function loadContractStatus() + { + $status = $this->input->get('vertragsstatus_kurzbz'); + $vertrag_id = $this->input->get('vertrag_id'); + + $result = $this->VertragvertragsstatusModel->loadWhere( + array( + 'vertrag_id' => $vertrag_id, + 'vertragsstatus_kurzbz' => $status + ) + ); + if (!$result) { + $this->terminateWithError('Status not existing'); + } + return $this->terminateWithSuccess(current(getData($result))); + } + + public function updateContractStatus() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('vertragsstatus_kurzbz', 'vertragsstatus_kurzbz', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'vertragsstatus_kurzbz']) + ]); + $this->form_validation->set_rules('datum', 'Datum', 'required|is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Datum']), + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Datum']) + ]); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $status_result = $this->VertragvertragsstatusModel->update( + [ + 'vertrag_id' => $this->input->post('vertrag_id'), + 'vertragsstatus_kurzbz' => $this->input->post('vertragsstatus_kurzbz') + ], + [ + 'uid' => getAuthUID(), + 'updateamum' => date('c'), + 'updatevon' => getAuthUID(), + 'datum' => $this->input->post('datum') + ] + ); + + if (!$status_result) { + $this->terminateWithError('Fehler beim Updaten des Vertragsstatus.'); + } + + return $this->terminateWithSuccess(current(getData($status_result))); + } + + public function deleteLehrauftrag() + { + $lehreinheit_id = $this->input->post('lehreinheit_id'); + $mitarbeiter_uid = $this->input->post('mitarbeiter_uid'); + $vertrag_id = $this->input->post('vertrag_id'); + + $this->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); + + //kein delete: ein update, bei dem die vertrag_id auf null gesetzt wird + $result = $this->LehreinheitmitarbeiterModel->update( + [ + 'lehreinheit_id' => $lehreinheit_id, + 'mitarbeiter_uid' => $mitarbeiter_uid, + 'vertrag_id' => $vertrag_id + ], + [ + 'vertrag_id' => null, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ] + ); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Id_Lehrauftrag']), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(current(getData($result))); + } + + public function deleteBetreuung() + { + $person_id= $this->input->post('person_id'); + $projektarbeit_id = $this->input->post('projektarbeit_id'); + $betreuerart_kurzbz = $this->input->post('betreuerart_kurzbz'); + $vertrag_id = $this->input->post('vertrag_id'); + + $this->load->model('education/Projektbetreuer_model', 'Projektbetreuermodel'); + + $result = $this->Projektbetreuermodel->update( + [ + 'person_id' => $person_id, + 'projektarbeit_id' => $projektarbeit_id, + 'betreuerart_kurzbz' => $betreuerart_kurzbz, + 'vertrag_id' => $vertrag_id + ], + [ + 'vertrag_id' => null, + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ] + ); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Id_Projektbetreuung']), self::ERROR_TYPE_GENERAL); + } + return $this->terminateWithSuccess(current(getData($result))); + } + + public function getMitarbeiter() + { + $this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel'); + + $result = $this->Mitarbeitermodel->getPersonenWithContractDetails(); + + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + if (!hasData($result)) + { + //return data before PV21 (with filter fix angestellt, active and with bisverwendung) + $result = $this->Mitarbeitermodel->getPersonal(true, true, true); + if (isError($result)) + { + return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + } + return $this->terminateWithSuccess(getData($result)); + } + + public function getPersonAbteilung($mitarbeiter_uid) + { + $this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel'); + + $result = $this->Mitarbeitermodel->getPersonAbteilung($mitarbeiter_uid); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function getLeitungOrg($oekurzbz) + { + $this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel'); + + $result = $this->Mitarbeitermodel->getLeitungOrg($oekurzbz); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function getHeader($person_id) + { + $this->load->model('ressource/Mitarbeiter_model', 'Mitarbeitermodel'); + + $result = $this->Mitarbeitermodel->getHeader($person_id); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } +} diff --git a/application/controllers/api/frontend/v1/vorlagen/Vorlagen.php b/application/controllers/api/frontend/v1/vorlagen/Vorlagen.php new file mode 100644 index 000000000..01edb33d1 --- /dev/null +++ b/application/controllers/api/frontend/v1/vorlagen/Vorlagen.php @@ -0,0 +1,63 @@ + ['admin:r', 'assistenz:r'], + 'getVorlagenByLoggedInUser' => ['admin:r', 'assistenz:r'], + ]); + + //Load Models + $this->load->model('system/Vorlage_model', 'VorlageModel'); + + // Additional Permission Checks + //TODO(manu) check permissions + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + $this->load->library('VorlageLib'); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + public function getVorlagen() + { + $this->load->model('system/Vorlage_model', 'VorlageModel'); + + $this->VorlageModel->addOrder('vorlage_kurzbz', 'ASC'); + + $result = $this->VorlageModel->loadWhere( + array( + 'mimetype' => 'text/html' + )); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function getVorlagenByLoggedInUser() + { + //get oe of user + $uid = getAuthUID(); + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $result = $this->BenutzerfunktionModel->getBenutzerfunktionByUid($uid, 'oezuordnung'); + + $data = $this->getDataOrTerminateWithError($result); + $oe_kurzbz = current($data); + + $result = $this->VorlageModel->getAllVorlagenByOe($oe_kurzbz->oe_kurzbz); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + +} \ No newline at end of file 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..c1d4d0abf --- /dev/null +++ b/application/controllers/codex/UHSTAT1.php @@ -0,0 +1,503 @@ +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('person/Benutzer_model', 'BenutzerModel'); + $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->_getUHSTATPersonId('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->_getUHSTATPersonId('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->_getUHSTATPersonId('s'); + + // read only display param + $readOnly = $this->input->get('readOnly'); + + // checking permissions for form + + // saving is possible if there permission or student log in (but not from application tool) + $savePermission = $this->_checkPermission('sui') || ($this->_getUserPersonId() && !$this->_getApplicationToolPersonId()); + + // deleting only possible with permission + $deletePermission = $this->_checkPermission('suid'); + + $languageIdx = $this->_getLanguageIndex(); + + $formMetaData = array( + 'nation' => array(), + 'abschluss_oesterreich' => array(), + 'abschluss_nicht_oesterreich' => array(), + 'jahre' => array(), + 'person_id' => $person_id, + 'savePermission' => $savePermission, + '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)) + { + $dropdownNations = []; + $nations = getData($nationRes); + + foreach ($nations as $nation) + { + // put austria in beginning of selection + if ($nation->nation_code == self::CODEX_OESTERREICH) + array_unshift($dropdownNations, $nation); + elseif (!in_array($nation->nation_code, self::CODEX_EXCLUDED_NATIONS)) // add nation if not excluded + $dropdownNations[] = $nation; + } + + $formMetaData['nation'] = $dropdownNations; + } + + // 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->_getUHSTATPersonId('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, for which UHSTAT1 data is edited. + * Can be passed as parameter, id of logged in person, or be in session. + * @param berechtigungsArt type of permission (suid) + * @return int person_id + */ + private function _getUHSTATPersonId($berechtigungsArt) + { + // if coming from bewerbungstool - person id is in session (person must be logged in bewerbungstool) + $applicationToolPersonId = $this->_getApplicationToolPersonId(); + if (isset($applicationToolPersonId) && is_numeric($applicationToolPersonId)) return $applicationToolPersonId; + + // if successfully logged in + $loggedInPersonId = $this->_getUserPersonId(); + if (isset($loggedInPersonId) && is_numeric($loggedInPersonId)) + { + // 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)) + { + if (!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; + } + + // if no id passed, use logged in person id + return $loggedInPersonId; + } + + show_error("No permission"); + } + + /** + * Gets person Id if there is a application tool login. + * @return person Id or null + */ + private function _getApplicationToolPersonId() + { + // if coming from aplication tool - 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]; + + return null; + } + + /** + * Gets person Id if there is a user login. + * @return person Id or null + */ + private function _getUserPersonId() + { + $loggedInPersonId = getAuthPersonId(); + if (isset($loggedInPersonId) && is_numeric($loggedInPersonId)) + { + // check if the the user is a student and if the benutzer is active + $this->BenutzerModel->addSelect('1'); + $res = $this->BenutzerModel->loadWhere(["public.tbl_benutzer.person_id" => $loggedInPersonId, "public.tbl_benutzer.aktiv" => TRUE]); + if (hasData($res)) return $loggedInPersonId; + } + return null; + } + + /** + * 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/LvPlan.php b/application/controllers/components/Cis/LvPlan.php new file mode 100644 index 000000000..d4cf63520 --- /dev/null +++ b/application/controllers/components/Cis/LvPlan.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/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/Filter.php b/application/controllers/components/Filter.php new file mode 100644 index 000000000..617edd69f --- /dev/null +++ b/application/controllers/components/Filter.php @@ -0,0 +1,211 @@ +load->library('AuthLib'); + + // 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() + { + $this->outputJsonSuccess($this->filtercmptlib->getSession()); + } + + /** + * Remove an applied filter (SQL where condition) from the current filter + */ + public function removeFilterField() + { + $request = $this->getPostJSON(); + + if (property_exists($request, 'filterField') + && $this->filtercmptlib->removeFilterField($request->filterField) == true) + { + $this->outputJsonSuccess('Field removed'); + } + else + { + $this->outputJsonError('Error occurred'); + } + } + + /** + * Add a filter (SQL where clause) to be applied to the current filter + */ + public function addFilterField() + { + $request = $this->getPostJSON(); + + if (property_exists($request, 'filterField') + && $this->filtercmptlib->addFilterField($request->filterField) == true) + { + $this->outputJsonSuccess('Field added'); + } + else + { + $this->outputJsonError('Error occurred'); + } + } + + /** + * Apply the filter changes + */ + public function applyFilterFields() + { + $request = $this->getPostJSON(); + + if (property_exists($request, 'filterFields') + && $this->filtercmptlib->applyFilterFields($request->filterFields) == true) + { + $this->outputJsonSuccess('Applied'); + } + else + { + $this->outputJsonError('Error occurred'); + } + } + + /** + * Save the current filter as a custom filter for this user with the given description + */ + public function saveCustomFilter() + { + $request = $this->getPostJSON(); + + if (property_exists($request, 'customFilterName') + && $this->filtercmptlib->saveCustomFilter($request->customFilterName) == true) + { + $this->outputJsonSuccess('Saved'); + } + else + { + $this->outputJsonError('An error occurred while saving a custom filter'); + } + } + + /** + * Remove a custom filter by its filterId + */ + public function removeCustomFilter() + { + $request = $this->getPostJSON(); + + if (property_exists($request, 'filterId') + && $this->filtercmptlib->removeCustomFilter($request->filterId) == true) + { + $this->outputJsonSuccess('Removed'); + } + else + { + $this->outputJsonError('Wrong parameter'); + } + } + + /** + * Reloads the dataset + */ + public function reloadDataset() + { + $this->filtercmptlib->reloadDataset(); + + $this->outputJsonSuccess('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; + + // Try to get the POSTed JSON + $postJSON = $this->getPostJSON(); + + // POSTed JSON + if ($postJSON != null) + { + // If the mandatory parameters FILTER_UNIQUE_ID and FILTER_TYPE have been provided + if (property_exists($postJSON, self::FILTER_UNIQUE_ID) && property_exists($postJSON, self::FILTER_TYPE)) + { + // Retrives them from the POSTed JSON + $filterUniqueId = $postJSON->{self::FILTER_UNIQUE_ID}; + $filterType = $postJSON->{self::FILTER_TYPE}; + } + + // If the optional parameter FILTER_ID has been provided + if (property_exists($postJSON, self::FILTER_ID)) $filterId = $postJSON->{self::FILTER_ID}; + } + else // otherwise it is an HTTP GET call + { + // If the mandatory parameters FILTER_UNIQUE_ID and FILTER_TYPE have been provided + if (isset($_GET[self::FILTER_UNIQUE_ID]) && isset($_GET[self::FILTER_TYPE])) + { + // Retrives them from the HTTP GET + $filterUniqueId = $this->input->get(self::FILTER_UNIQUE_ID); + $filterType = $this->input->get(self::FILTER_TYPE); + } + + // If the optional parameter FILTER_ID has been provided + if (isset($_GET[self::FILTER_ID])) $filterId = $filterId = $this->input->get(self::FILTER_ID); + } + + // If the mandatory parameters have _not_ been provided, then terminate the execution and return an error + if ($filterUniqueId == null) $this->terminateWithJsonError('Parameter "'.self::FILTER_UNIQUE_ID.'" not provided!'); + if ($filterType == null) $this->terminateWithJsonError('Parameter "'.self::FILTER_TYPE.'" not provided!'); + + // 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/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 new file mode 100644 index 000000000..eac1a4cbc --- /dev/null +++ b/application/controllers/components/SearchBar.php @@ -0,0 +1,60 @@ +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); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Gets a JSON body via HTTP POST and provides the parameters + */ + public function search() + { + $json = json_decode($this->input->raw_input_stream); + + // Checks if the searchstr and the types parameters are in the POSTed JSON + if (isset($json->{self::SEARCHSTR_PARAM}) && isset($json->{self::TYPES_PARAM})) + { + // Convert to json the result from searchbarlib->search + $this->outputJson( + $this->searchbarlib->search( + $json->{self::SEARCHSTR_PARAM}, + $json->{self::TYPES_PARAM} + ) + ); + } + else // otherwise return an error in JSON format + { + $this->outputJsonError(SearchBarLib::ERROR_WRONG_JSON); + } + } +} + 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..f6db9509f --- /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, $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, $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, $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, $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[$funktion]) || !isset($preset[$funktion]['widgets'])) + $result[$funktion] = []; + else + $result[$funktion] = $preset[$funktion]['widgets']; + } + 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 f32a8268a..52bf972e3 100644 --- a/application/controllers/jobs/AnrechnungJob.php +++ b/application/controllers/jobs/AnrechnungJob.php @@ -16,9 +16,11 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); class AnrechnungJob extends JOB_Controller { const APPROVE_ANRECHNUNG_URI = '/lehre/anrechnung/ApproveAnrechnungUebersicht'; + const REVIEW_ANRECHNUNG_URI = '/lehre/anrechnung/ReviewAnrechnungUebersicht'; const ANRECHNUNGSTATUS_APPROVED = 'approved'; const ANRECHNUNGSTATUS_REJECTED = 'rejected'; + const ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR = 'inProgressLektor'; const ANRECHNUNG_NOTIZTITEL_NOTIZ_BY_STGL = 'AnrechnungNotizSTGL'; /** @@ -33,6 +35,11 @@ class AnrechnungJob extends JOB_Controller $this->load->helper('url'); $this->load->helper('hlp_sancho_helper'); + + $this->load->library('AnrechnungLib'); + + // Load configs + $this->load->config('anrechnung'); } /** @@ -188,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 = @@ -209,7 +216,7 @@ class AnrechnungJob extends JOB_Controller 'datentabelle' => $anrechnungen_table, 'link' => anchor($url, 'Anrechnungsanträge Übersicht') ); - + // Send mail sendSanchoMail( 'AnrechnungAntragStellen', @@ -223,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. */ @@ -304,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)) { @@ -342,6 +425,79 @@ html; } + /** + * Send Sancho mail to remind lecturers to provide their recommendation if not done until one week after request. + */ + public function sendMailRemindRecommendation(){ + + $this->logInfo('Start AnrechnungJob sendMailRemindRecommendation to remind lecturers to provide their recommendation.'); + + // Get Anrechnungen with pending recommendations, that were requested 1 week before today. + // Restrict query for Anrechnungen of actual semester. + $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 week\') -- eine Woche nach Empfehlungsanfrage + ORDER BY astat.anrechnung_id, astat.datum DESC, astat.insertamum DESC -- nur letzten status dabei prüfen + '); + + // Exit if there are no pending recommendations + if (!hasData($result)) + { + $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(); + foreach ($anrechnung_id_arr as $anrechnung_id) + { + $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, + 'Erinnerung: Deine Empfehlung wird benötigt zur Anerkennung nachgewiesener Kenntnisse' + ); + } + } + + $this->logInfo('SUCCEDED AnrechnungJob sendMailRemindRecommendation'); + + } + // Get STGL mail address private function _getSTGLMailAddress($studiengang_kz) { @@ -358,8 +514,6 @@ html; 'vorname' => $stgl->vorname ); } - - return $stglMailAdress_arr; } // If not available, get assistance mail address else @@ -368,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..debcfe391 --- /dev/null +++ b/application/controllers/jobs/AntragJob.php @@ -0,0 +1,710 @@ +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; + } + + $leitungen = getData($result); + foreach ($leitungen as $leitung) + { + 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..fe7ee21f5 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,41 @@ 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', + 'CORE_PERSON_0005' => 'CORE_PERSON_0005', + 'CORE_PERSON_0006' => 'CORE_PERSON_0006' + ); + + // 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/LVPlanJob.php b/application/controllers/jobs/LVPlanJob.php index 2688e5cc9..c3fe5495a 100644 --- a/application/controllers/jobs/LVPlanJob.php +++ b/application/controllers/jobs/LVPlanJob.php @@ -19,7 +19,7 @@ */ if (!defined('BASEPATH')) exit('No direct script access allowed'); -class LVPlanJob extends CLI_Controller +class LVPlanJob extends JOB_Controller { /** * Initialize LVPlanJob Class @@ -149,4 +149,315 @@ class LVPlanJob extends CLI_Controller echo "Failed ".$fail."\n"; } } + + /** + * Send Mail to STGL, Kompetenzfeld and LV Planung about todays updated Zeitwuensche. + * STGL gets list only of lectors who updated future assigend courses concerning their STG. + * Kompetenzleitung gets list only of lectors who updated future assigend courses concerning their KF. + * LVPlanung gets list of lectors who updated future assigend courses. + */ + public function mailUpdatedZeitwuensche() + { + // Load models + $this->load->model('ressource/Stundenplandev_model', 'StundenplandevModel'); + $this->load->model('organisation/Studiensemester_model', 'StundiensemesterModel'); + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('person/Person_model', 'PersonModel'); + + // Load libs + $this->load->library('MailLib'); + + // Load helpers + $this->load->helper('hlp_sancho_helper'); + + // Start Log Message + $this->logInfo('Mail updated Zeitwuensche started.'); + + // Get all lectors, who updated their Zeitwunsch today + $db = new DB_Model(); + $result = $db->execReadOnlyQuery(' + SELECT + zwg.mitarbeiter_uid, tbl_lehrveranstaltung.studiengang_kz, tbl_lehrveranstaltung.oe_kurzbz + FROM + campus.tbl_zeitwunsch_gueltigkeit zwg + JOIN lehre.tbl_stundenplandev stpl + ON( + stpl.mitarbeiter_uid=zwg.mitarbeiter_uid + AND stpl.datum BETWEEN zwg.von AND COALESCE(zwg.bis, \'2999-12-31\') + AND (zwg.insertamum::date = (NOW()-\'1 days\'::interval)::date + OR + zwg.updateamum::date = (NOW()-\'1 days\'::interval)::date) + AND stpl.datum > now() + ) + JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + GROUP BY + zwg.mitarbeiter_uid, tbl_lehrveranstaltung.studiengang_kz, tbl_lehrveranstaltung.oe_kurzbz + '); + + if (!hasData($result)) + { + return; // No updated Zeitwuensche today + } + + $uidByStg_arr = array(); // Mail data for Studiengang + $uidByOe_arr = array(); // Mail data for Kompetenzfeld + $uid_arr = array(); // Mail data for Kompetenzfeld + + // Loop through lectors, who updated their Zeitwunsch today + $changed_arr = getData($result); + foreach ($changed_arr as $row) + { + + // Add unique lector array + if (!in_array($row->mitarbeiter_uid, $uid_arr)) + { + $uid_arr[]= $row->mitarbeiter_uid; + } + + // Build unique Studiengang array + if (!array_key_exists($row->studiengang_kz, $uidByStg_arr)) + { + $uidByStg_arr[$row->studiengang_kz] = array($row->mitarbeiter_uid); + + } + elseif (!in_array($row->mitarbeiter_uid, $uidByStg_arr[$row->studiengang_kz])) + { + $uidByStg_arr[$row->studiengang_kz][]= $row->mitarbeiter_uid; + } + + // Build unique Kompetenzfeld array + if (!array_key_exists($row->oe_kurzbz, $uidByOe_arr)) + { + $uidByOe_arr[$row->oe_kurzbz] = array($row->mitarbeiter_uid); + + } + elseif (!in_array($row->mitarbeiter_uid, $uidByOe_arr[$row->oe_kurzbz])) + { + $uidByOe_arr[$row->oe_kurzbz][]= $row->mitarbeiter_uid; + } + } + + // Send mail to STG Assistenz + /* + $result = $this->_sendMailToStg($uidByStg_arr); + if (isError($result)) + { + $this->logError(getError($result)); + } + */ + + // Send mail to Kompetenzfeld Leitung + $result = $this->_sendMailToKF($uidByOe_arr); + if (isError($result)) + { + $this->logError(getError($result)); + } + + // Send mail to LV Planung + $result = $this->_sendMailToLvPlanung($uid_arr); + if (isError($result)) + { + $this->logError(getError($result)); + } + + // End Log Message + $this->logInfo('Mail updated Zeitwuensche ended.'); + } + + /** + * Send Mail to STGL Assistance about lectors, who teach LV assigend to the STG, and who updated Zeitwuensche. + * + * @param $data_arr + * @param $stg_bezeichnung + */ + private function _sendMailToStg($data_arr) + { + foreach ($data_arr as $stg_kurzbz => $uid_arr) + { + // Get STG eMail + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $result = $this->StudiengangModel->load($stg_kurzbz); + $stgMail = $result->retval[0]->email; + + $lektorenTabelle = ' + + + + + + + '; + + foreach($uid_arr as $uid) + { + $person = $this->PersonModel->getByUid($uid); + $lektorenTabelle.= ' + + + + + '; + } + + $lektorenTabelle.= '
NameUID
'. getData($person)[0]->vorname. ' '. getData($person)[0]->nachname. '['. $uid. ']
'; + + $contentData_arr = array( + 'datentabelle' => $lektorenTabelle + ); + + // Send mail + if (!sendSanchoMail( + 'ZeitwunschUpdateMail', + $contentData_arr, + $stgMail, + 'Änderung von Zeitwünschen', + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + )) + { + $errorReceiverUid_arr[]= $stgMail; + } + } + + if (isset($errorReceiverUid_arr)) + { + return error('Mail updated Zeitwuensche could not be sent to :'. implode($errorReceiverUid_arr, ',')); + } + + return success(); + } + + /** + * Send Mail to Kompetenzfeld about lectors, who teach LV assigend to the Kompetenzfeld, and who updated Zeitwuensche. + * + * @param $data_arr + * @param $stg_bezeichnung + */ + private function _sendMailToKF($data_arr) + { + // Send mail to Komepetenzfeld Leitung + foreach ($data_arr as $oe_kurzbz => $uid_arr) + { + // Get KF Leitung eMail + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $result = $this->BenutzerfunktionModel->getBenutzerFunktionen( + 'Leitung', + $oe_kurzbz, + $activeoeonly = true, + $activebenonly = true + ); + + if(isSuccess($result) && hasData($result)) + { + $empfaenger = array(); + + foreach(getData($result) as $row) + $empfaenger[] = $row->uid. '@'. DOMAIN; + $kfMail = implode(',',$empfaenger); + + $lektorenTabelle = ' + + + + + + + '; + + foreach($uid_arr as $uid) + { + $person = $this->PersonModel->getByUid($uid); + $lektorenTabelle.= ' + + + + + '; + } + + $lektorenTabelle.= '
NameUID
'. getData($person)[0]->vorname. ' '. getData($person)[0]->nachname. '['. $uid. ']
'; + + $contentData_arr = array( + 'datentabelle' => $lektorenTabelle + ); + + // Send mail + if (!sendSanchoMail( + 'ZeitwunschUpdateMail', + $contentData_arr, + $kfMail, + 'Änderung von Zeitwünschen', + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + )) + { + $errorReceiverUid_arr[]= $kfMail; + } + } + } + + if (isset($errorReceiverUid_arr)) + { + return error('Mail updated Zeitwuensche could not be sent to :'. implode($errorReceiverUid_arr, ',')); + } + + return success(); + } + + /** + * Send Mail to LV Planung about all lectors who updated Zeitwuensche. + * + * @param $data_arr + * @param $stg_bezeichnung + */ + private function _sendMailToLvPlanung($data_arr) + { + $lektorenTabelle = ' + + + + + + + '; + + foreach($data_arr as $lector) + { + $person = $this->PersonModel->getByUid($lector); + $lektorenTabelle.= ' + + + + + '; + } + + $lektorenTabelle.= '
NameUID
'. getData($person)[0]->vorname. ' '. getData($person)[0]->nachname. '['. $lector. ']
'; + + $contentData_arr = array( + 'datentabelle' => $lektorenTabelle + ); + + // Send mail + if (!sendSanchoMail( + 'ZeitwunschUpdateMail', + $contentData_arr, + MAIL_LVPLAN, + 'Änderung von Zeitwünschen', + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + )) + { + $errorReceiver = MAIL_LVPLAN; + } + + if (isset($errorReceiver)) + { + return error('Mail updated Zeitwuensche could not be sent to :'. $errorReceiver); + } + + return success(); + } } diff --git a/application/controllers/jobs/LehrauftragJob.php b/application/controllers/jobs/LehrauftragJob.php index 7f5754595..f1974c8a5 100644 --- a/application/controllers/jobs/LehrauftragJob.php +++ b/application/controllers/jobs/LehrauftragJob.php @@ -359,7 +359,7 @@ class LehrauftragJob extends JOB_Controller for ($i = 0; $i < $data_len; $i++) { // Get all users entitled by organisational unit - $result = $this->BenutzerrolleModel->getBenutzerByBerechtigung(self::BERECHTIGUNG_LEHRAUFTRAG_ERTEILEN, $data[$i]['oe_kurzbz']); + $result = $this->BenutzerrolleModel->getBenutzerByBerechtigung(self::BERECHTIGUNG_LEHRAUFTRAG_ERTEILEN, $data[$i]['oe_kurzbz'], 'suid'); if ($berechtigung_arr = getData($result)) { diff --git a/application/controllers/jobs/OneTimeMessages.php b/application/controllers/jobs/OneTimeMessages.php index 58bc1fb7c..0e49ca8a5 100644 --- a/application/controllers/jobs/OneTimeMessages.php +++ b/application/controllers/jobs/OneTimeMessages.php @@ -51,7 +51,8 @@ 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.status_kurzbz = \'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..6dd214fbb 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)) { @@ -822,11 +821,11 @@ class ReihungstestJob extends JOB_Controller JOIN lehre.tbl_studienordnung USING (studienordnung_id) JOIN PUBLIC.tbl_studiengang ON (tbl_studienordnung.studiengang_kz = tbl_studiengang.studiengang_kz) WHERE get_rolle_prestudent (tbl_prestudent.prestudent_id, ?) IN ('Aufgenommener','Bewerber','Wartender','Abgewiesener') - AND studiensemester_kurzbz = ? + AND studiensemester_kurzbz = ? 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' @@ -862,13 +861,14 @@ class ReihungstestJob extends JOB_Controller { // Alle niedrigeren Prios laden $qryNiedrPrios = " - SELECT DISTINCT + SELECT DISTINCT ON(prestudent_id) get_rolle_prestudent (tbl_prestudent.prestudent_id, '".$row_ps->studiensemester_kurzbz."') AS laststatus, tbl_studienplan.orgform_kurzbz, 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,11 +876,11 @@ 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." - ORDER BY studiengang_kz, laststatus + ORDER BY prestudent_id, studiengang_kz, laststatus, tbl_prestudentstatus.datum DESC "; // Wenn der letzte Status "Aufgenommener" ist, alle niedrigeren Prios auf "Abgewiesen" setzen @@ -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 @@ -966,7 +976,7 @@ class ReihungstestJob extends JOB_Controller FROM public.tbl_konto WHERE person_id = " . $row_ps->person_id . " AND studiensemester_kurzbz = '" . $row_ps->studiensemester_kurzbz . "' - AND buchungstyp_kurzbz = 'StudiengebuehrAnzahlung'"; + AND buchungstyp_kurzbz IN ('StudiengebuehrAnzahlung','KautionDrittStaat')"; $resultKautionExists = $db->execReadOnlyQuery($qryKautionExists); if (hasdata($resultKautionExists)) @@ -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 28edf4824..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); + } } /** @@ -395,8 +392,12 @@ class approveAnrechnungDetail extends Auth_Controller // Set filename to be used on downlaod $filename = $this->anrechnunglib->setFilenameOnDownload($dms_id); + // Get file to be downloaded from DMS + $download = $this->dmslib->download($dms_id, $filename); + if (isError($download)) return $download; + // Download file - $this->dmslib->download($dms_id, $filename); + $this->outputFile(getData($download)); } /** @@ -463,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'); @@ -533,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 @@ -580,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'); @@ -602,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 053988848..b5a44b8f6 100644 --- a/application/controllers/lehre/anrechnung/ApproveAnrechnungUebersicht.php +++ b/application/controllers/lehre/anrechnung/ApproveAnrechnungUebersicht.php @@ -8,13 +8,13 @@ class approveAnrechnungUebersicht extends Auth_Controller const BERECHTIGUNG_ANRECHNUNG_ANLEGEN = 'lehre/anrechnung_anlegen'; const REVIEW_ANRECHNUNG_URI = '/lehre/anrechnung/ReviewAnrechnungUebersicht'; - + const ANRECHNUNGSTATUS_PROGRESSED_BY_STGL = 'inProgressDP'; const ANRECHNUNGSTATUS_PROGRESSED_BY_KF = 'inProgressKF'; const ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR = 'inProgressLektor'; const ANRECHNUNGSTATUS_APPROVED = 'approved'; const ANRECHNUNGSTATUS_REJECTED = 'rejected'; - + public function __construct() { // Set required permissions @@ -27,23 +27,26 @@ class approveAnrechnungUebersicht extends Auth_Controller 'requestRecommendation' => 'lehre/anrechnung_genehmigen:rw' ) ); - + + // Load configs + $this->load->config('anrechnung'); + // Load models $this->load->model('education/Anrechnung_model', 'AnrechnungModel'); $this->load->model('education/Anrechnungstatus_model', 'AnrechnungstatusModel'); $this->load->model('content/DmsVersion_model', 'DmsVersionModel'); - + // Load libraries $this->load->library('WidgetLib'); $this->load->library('PermissionLib'); $this->load->library('AnrechnungLib'); $this->load->library('DmsLib'); - + // Load helpers $this->load->helper('form'); $this->load->helper('url'); $this->load->helper('hlp_sancho_helper'); - + // Load language phrases $this->loadPhrases( array( @@ -55,29 +58,42 @@ class approveAnrechnungUebersicht extends Auth_Controller 'table' ) ); - + $this->_setAuthUID(); - + $this->setControllerId(); } - + public function index() { // Get study semester $studiensemester_kurzbz = $this->input->get('studiensemester'); - + if (isEmptyString($studiensemester_kurzbz)) { $result = $this->StudiensemesterModel->getNearest(); $studiensemester_kurzbz = getData($result)[0]->studiensemester_kurzbz; } - + // Get studiengaenge the user is entitled for if (!$studiengang_kz_arr = $this->permissionlib->getSTG_isEntitledFor(self::BERECHTIGUNG_ANRECHNUNG_GENEHMIGEN)) { 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,14 +103,16 @@ 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); } - + /** * Approve Anrechnungen. */ @@ -107,22 +125,30 @@ class approveAnrechnungUebersicht extends Auth_Controller { return $this->outputJsonError('Fehler beim Übertragen der Daten.'); } - + + $json = array( + 'status_kurzbz' => self::ANRECHNUNGSTATUS_APPROVED, + 'status_bezeichnung' => $this->anrechnunglib->getStatusbezeichnung(self::ANRECHNUNGSTATUS_APPROVED), + 'prestudenten' => [] + ); + // Approve Anrechnung foreach ($data as $item) { - if ($this->anrechnunglib->approveAnrechnung($item['anrechnung_id'])) + // Get Prestudent + $this->AnrechnungModel->addSelect('prestudent_id'); + $result = $this->AnrechnungModel->load($item['anrechnung_id']); + $prestudent_id = getData($result)[0]->prestudent_id; + + // Approve + if ($this->anrechnunglib->approveAnrechnung($item['anrechnung_id'])) { - $json[]= array( - 'anrechnung_id' => $item['anrechnung_id'], - 'status_kurzbz' => self::ANRECHNUNGSTATUS_APPROVED, - 'status_bezeichnung' => $this->anrechnunglib->getStatusbezeichnung(self::ANRECHNUNGSTATUS_APPROVED) - ); + $json['prestudenten'][$prestudent_id][] = $item['anrechnung_id']; } } - + // Output json to ajax - if (isset($json) && !isEmptyArray($json)) + if (isset($json) && !isEmptyArray($json['prestudenten'])) { return $this->outputJsonSuccess($json); } @@ -131,20 +157,20 @@ class approveAnrechnungUebersicht extends Auth_Controller return $this->outputJsonError('Es wurden keine Anrechnungen genehmigt.'); } } - + /** * Reject Anrechnungen. */ public function reject() { $data = $this->input->post('data'); - + // Validate data if (isEmptyArray($data)) { return $this->outputJsonError('Fehler beim Übertragen der Daten.'); } - + // Reject Anrechnung foreach ($data as $item) { @@ -157,7 +183,7 @@ class approveAnrechnungUebersicht extends Auth_Controller ); } } - + // Output json to ajax if (isset($json) && !isEmptyArray($json)) { @@ -168,22 +194,22 @@ class approveAnrechnungUebersicht extends Auth_Controller return $this->outputJsonError('Es wurden keine Anrechnungen genehmigt.'); } } - + /** * Request recommendation for Anrechnungen. */ public function requestRecommendation() { $data = $this->input->post('data'); - + if(isEmptyArray($data)) { return $this->outputJsonError('Fehler beim Übertragen der Daten.'); } - + $retval = array(); $counter = 0; - + foreach ($data as $item) { // Check if Anrechnungs-LV has lector @@ -191,7 +217,7 @@ class approveAnrechnungUebersicht extends Auth_Controller { // Count up LV with no lector $counter++; - + // Continue loop, if LV has no lector continue; } @@ -199,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')) - : ''; - - $retval[]= array( + // 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']); + } + + $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), @@ -216,26 +248,21 @@ 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); } - + /** * Download and open uploaded document (Nachweisdokument). */ @@ -250,25 +277,28 @@ class approveAnrechnungUebersicht extends Auth_Controller // Check if user is entitled to read dms doc $this->_checkIfEntitledToReadDMSDoc($dms_id); - + // Set filename to be used on downlaod $filename = $this->anrechnunglib->setFilenameOnDownload($dms_id); - + + // Get file to be downloaded from DMS + $download = $this->dmslib->download($dms_id, $filename); + if (isError($download)) return $download; + // Download file - $this->dmslib->download($dms_id, $filename); + $this->outputFile(getData($download)); } - - + /** * 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'); } - + /** * Check if user is entitled to read dms doc * @param $dms_id @@ -276,41 +306,40 @@ class approveAnrechnungUebersicht extends Auth_Controller private function _checkIfEntitledToReadDMSDoc($dms_id) { $result = $this->AnrechnungModel->loadWhere(array('dms_id' => $dms_id)); - + if(!$result = getData($result)[0]) { show_error('Failed retrieving Anrechnung'); } - + $result = $this->LehrveranstaltungModel->loadWhere(array( 'lehrveranstaltung_id' => $result->lehrveranstaltung_id )); - - + if(!$result = getData($result)[0]) { show_error('Failed loading Lehrveranstaltung'); } $studiengang_kz = $result->studiengang_kz; - + // Check if user is entitled if (!$this->permissionlib->isBerechtigt(self::BERECHTIGUNG_ANRECHNUNG_GENEHMIGEN, 's', $studiengang_kz)) { show_error('You are not entitled to read this document'); } } - + /** * Send mail to lectors asking for recommendation. (first to LV-Leitung, if not present to all lectors of lv) * @param $mail_params * @return bool */ - private function _sendSanchoMailToLectors($mail_params) + private function _sendSanchoMail($mail_params) { // Get Lehrveranstaltungen $anrechnung_arr = array(); - + foreach ($mail_params as $item) { $this->AnrechnungModel->addSelect('lehrveranstaltung_id, studiensemester_kurzbz'); @@ -319,42 +348,49 @@ class approveAnrechnungUebersicht extends Auth_Controller 'studiensemester_kurzbz' => $this->AnrechnungModel->load($item['anrechnung_id'])->retval[0]->studiensemester_kurzbz ); } - + $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'); if (!$stgl_name = getData($this->PersonModel->getFullName($this->_uid))) { show_error ('Failed retrieving person'); } - + // Link to Antrag genehmigen $url = CIS_ROOT. 'cis/index.php?menu='. CIS_ROOT. 'cis/menu.php?content_id=&content='. CIS_ROOT. index_page(). self::REVIEW_ANRECHNUNG_URI; - + // Prepare mail content $body_fields = array( 'vorname' => $vorname, 'stgl_name' => $stgl_name, 'link' => anchor($url, 'Anrechnungsanträge Übersicht') ); - + sendSanchoMail( 'AnrechnungEmpfehlungAnfordern', $body_fields, @@ -364,7 +400,7 @@ class approveAnrechnungUebersicht extends Auth_Controller } return true; } - + /** * 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. @@ -374,18 +410,18 @@ class approveAnrechnungUebersicht extends Auth_Controller private function _getLectors($anrechnung_arr) { $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']); - + if (!hasData($result)) { show_error('Failed retrieving lectors of Lehrveranstaltung'); } - + $lecturersByLv = getData($result); // Check if lv has LV-Leitung @@ -401,7 +437,7 @@ class approveAnrechnungUebersicht extends Auth_Controller $lector_arr = array_merge($lector_arr, $lecturersByLv); } } - + /** * NOTE: This step is only done to make the array unique by uid, vorname and nachname in the following step * (e.g. if same lector is ones LV-Leitung and another time not, then array_unique would leave both. @@ -411,10 +447,40 @@ class approveAnrechnungUebersicht extends Auth_Controller { unset($lector->lvleiter); } - + // Now make the lector array aka mail receivers unique $lector_arr = array_unique($lector_arr, SORT_REGULAR); - + return $lector_arr; } -} \ No newline at end of file + + /** + * 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 bf98e1c59..ebc272e3e 100644 --- a/application/controllers/lehre/anrechnung/RequestAnrechnung.php +++ b/application/controllers/lehre/anrechnung/RequestAnrechnung.php @@ -6,13 +6,13 @@ class requestAnrechnung extends Auth_Controller { const REQUEST_ANRECHNUNG_URI = '/lehre/anrechnung/RequestAnrechnung'; const APPROVE_ANRECHNUNG_URI = '/lehre/anrechnung/ApproveAnrechnungUebersicht'; - + const ANRECHNUNGSTATUS_PROGRESSED_BY_STGL = 'inProgressDP'; const ANRECHNUNGSTATUS_PROGRESSED_BY_KF = 'inProgressKF'; const ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR = 'inProgressLektor'; const ANRECHNUNGSTATUS_APPROVED = 'approved'; const ANRECHNUNGSTATUS_REJECTED = 'rejected'; - + public function __construct() { // Set required permissions @@ -23,22 +23,22 @@ class requestAnrechnung extends Auth_Controller 'download' => 'student/anrechnung_beantragen:rw', ) ); - + // Load models $this->load->model('education/Anrechnung_model', 'AnrechnungModel'); $this->load->model('content/DmsVersion_model', 'DmsVersionModel'); - + // Load libraries $this->load->library('WidgetLib'); $this->load->library('PermissionLib'); $this->load->library('AnrechnungLib'); $this->load->library('DmsLib'); - + // Load helpers $this->load->helper('form'); $this->load->helper('url'); $this->load->helper('hlp_sancho_helper'); - + // Load configs $this->load->config('anrechnung'); @@ -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)) @@ -205,9 +212,14 @@ class requestAnrechnung extends Auth_Controller } // Check if user is entitled to read dms doc - self::_checkIfEntitledToReadDMSDoc($dms_id); + $this->_checkIfEntitledToReadDMSDoc($dms_id); - $this->dmslib->download($dms_id); + // Get file to be downloaded from DMS + $download = $this->dmslib->download($dms_id); + if (isError($download)) return $download; + + // Download file + $this->outputFile(getData($download)); } /** @@ -216,10 +228,10 @@ class requestAnrechnung extends Auth_Controller private function _setAuthUID() { $this->_uid = getAuthUID(); - + if (!$this->_uid) show_error('User authentification failed'); } - + /** * Check if application deadline is expired. * @@ -229,34 +241,32 @@ 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'); - - // 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; - } - - // 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; - } - - $today = new DateTime('today midnight'); - $start = new DateTime($start); - $ende = new DateTime($ende); - - // True if expired - return ($today < $start || $today > $ende); + $today = new DateTime('today midnight'); + + // Load all Anrechnungszeitfenster for this Studiensemester + $this->load->model('education/Anrechnungszeitraum_model', 'AnrechnungszeitraumModel'); + $result = $this->AnrechnungszeitraumModel->loadWhere(array('studiensemester_kurzbz' => $studiensemester_kurzbz)); + + if (hasData($result)) + { + // Loop through Anrechnungszeitfenster + foreach (getData($result) as $azrObj) + { + $start = new DateTime($azrObj->anrechnungstart); + $ende = new DateTime($azrObj->anrechnungende); + + // Return false if today is at least within one Anrechnungszeitraum + if (($today >= $start && $today <= $ende)) return false; + + } + } + + // Return true if today is in none Anrechnungszeitraum + return true; } - + /** * Check if user is entitled to read dms doc. * @@ -268,9 +278,9 @@ class requestAnrechnung extends Auth_Controller { show_error('Failed loading Student'); } - + $result = $this->AnrechnungModel->loadWhere(array('dms_id' => $dms_id)); - + if($result = getData($result)[0]) { if ($result->prestudent_id == $student->prestudent_id) @@ -278,10 +288,10 @@ class requestAnrechnung extends Auth_Controller return; } } - + show_error('You are not entitled to read this document'); } - + /** * Check if application already exists. * @@ -297,30 +307,33 @@ class requestAnrechnung extends Auth_Controller 'studiensemester_kurzbz' => $studiensemester_kurzbz, 'prestudent_id' => $prestudent_id )); - + if (isError($result)) { show_error(getError($result)); } - + return hasData($result); } - + /** - * 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; - - return $studiensemester_kurzbz == $actual_ss; + $actual_ss = getData($result)[0]; + + $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) { // Get Note of Lehrveranstaltung @@ -331,12 +344,12 @@ class requestAnrechnung extends Auth_Controller 'lehrveranstaltung_id' => $lehrveranstaltung_id ) ); - + // If Lehrveranstaltung has Note if (hasData($result)) { $note = getData($result)[0]->note; - + // Check if Note is a blocking grade if (in_array($note, $this->config->item('grades_blocking_application'))) { @@ -345,7 +358,7 @@ class requestAnrechnung extends Auth_Controller } return false; } - + /** * Upload file via DMS library. * @@ -362,8 +375,8 @@ class requestAnrechnung extends Auth_Controller 'insertamum' => (new DateTime())->format('Y-m-d H:i:s'), 'insertvon' => $this->_uid ); - + // Upload document return $this->dmslib->upload($dms, 'uploadfile', array('pdf')); } -} \ No newline at end of file +} diff --git a/application/controllers/lehre/anrechnung/ReviewAnrechnungDetail.php b/application/controllers/lehre/anrechnung/ReviewAnrechnungDetail.php index 7981f0ac8..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); } @@ -217,15 +231,18 @@ class reviewAnrechnungDetail extends Auth_Controller } // Check if user is entitled to read dms doc - self::_checkIfEntitledToReadDMSDoc($dms_id); + $this->_checkIfEntitledToReadDMSDoc($dms_id); // Set filename to be used on downlaod $filename = $this->anrechnunglib->setFilenameOnDownload($dms_id); - // Download file - $this->dmslib->download($dms_id, $filename); - } + // Get file to be downloaded from DMS + $download = $this->dmslib->download($dms_id, $filename); + if (isError($download)) return $download; + // Download file + $this->outputFile(getData($download)); + } /** * Retrieve the UID of the logged user and checks if it is valid @@ -250,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)) { @@ -279,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; } @@ -319,20 +348,10 @@ class reviewAnrechnungDetail extends Auth_Controller // Send mail to STGL of each studiengang foreach ($studiengang_kz_arr as $studiengang_kz) { - // Get STGL mail address, if available, otherwise get assistance mail address - $stgmail = $this->_getSTGLMailAddress($studiengang_kz); - - if(isSuccess($stgmail) && hasData($stgmail)) - list ($to, $vorname) = getData($stgmail)[0]; - else - show_error ('Failed retrieving DegreeProgram Mail'); - // Get full name of lector $this->load->model('person/Person_model', 'PersonModel'); - if (!$lector_name = getData($this->PersonModel->getFullName($this->_uid))) - { - show_error ('Failed retrieving person'); - } + $result = $this->PersonModel->getFullName($this->_uid); + $lector_name = hasData($result) ? getData($result) : 'Ein Lektor'; // Link to Antrag genehmigen $url = @@ -340,22 +359,26 @@ class reviewAnrechnungDetail extends Auth_Controller CIS_ROOT. 'cis/menu.php?content_id=&content='. CIS_ROOT. index_page(). self::APPROVE_ANRECHNUNG_URI; - // Prepare mail content - $body_fields = array( - 'vorname' => $vorname, - 'lektor_name' => $lector_name, - 'empfehlung' => $empfehlung ? 'positive' : 'negative', - 'link' => anchor($url, 'Anrechnungsanträge Übersicht') - ); + // Get STGL mail address, if available, otherwise get assistance mail address + if( !$result = $this->_getSTGLMailAddress($studiengang_kz)) return false; + foreach ($result as $stgl) + { + // Prepare mail content + $body_fields = array( + 'vorname' => $stgl['vorname'], + 'lektor_name' => $lector_name, + 'empfehlung' => $empfehlung ? 'positive' : 'negative', + 'link' => anchor($url, 'Anrechnungsanträge Übersicht') + ); - sendSanchoMail( - 'AnrechnungEmpfehlungAbgeben', - $body_fields, - $to, - 'Anerkennung nachgewiesener Kenntnisse: Empfehlung wurde abgegeben' - ); + sendSanchoMail( + 'AnrechnungEmpfehlungAbgeben', + $body_fields, + $stgl['to'], + 'Anerkennung nachgewiesener Kenntnisse: Empfehlung wurde abgegeben' + ); + } } - return true; } @@ -366,28 +389,33 @@ class reviewAnrechnungDetail extends Auth_Controller $result = $this->StudiengangModel->getLeitung($stg_kz); // Get STGL mail address, if available - if (isSuccess($result) && hasData($result)) - { - return success(array( - $result->retval[0]->uid. '@'. DOMAIN, - $result->retval[0]->vorname - )); - } + if (hasData($result)) + { + foreach (getData($result) as $stgl) + { + $stglMailAdress_arr[]= array( + 'to' => $stgl->uid. '@'. DOMAIN, + 'vorname' => $stgl->vorname + ); + } + + return $stglMailAdress_arr; + } // ...otherwise get assistance mail address else { $result = $this->StudiengangModel->load($stg_kz); - if (isSuccess($result) && hasData($result)) + if (hasData($result)) { - return success(array( + return array( $result->retval[0]->email, '' - )); + ); } else { - return error('Keine E-Mail für diesen Stg gefunden'); + return false; } } } diff --git a/application/controllers/lehre/anrechnung/ReviewAnrechnungUebersicht.php b/application/controllers/lehre/anrechnung/ReviewAnrechnungUebersicht.php index e5475d0d0..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); } @@ -180,13 +190,17 @@ class reviewAnrechnungUebersicht extends Auth_Controller } // Check if user is entitled to read dms doc - self::_checkIfEntitledToReadDMSDoc($dms_id); + $this->_checkIfEntitledToReadDMSDoc($dms_id); // Set filename to be used on downlaod $filename = $this->anrechnunglib->setFilenameOnDownload($dms_id); + // Get file to be downloaded from DMS + $download = $this->dmslib->download($dms_id, $filename); + if (isError($download)) return $download; + // Download file - $this->dmslib->download($dms_id, $filename); + $this->outputFile(getData($download)); } @@ -213,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; } @@ -253,20 +273,10 @@ class reviewAnrechnungUebersicht extends Auth_Controller // Send mail to STGL of each studiengang foreach ($studiengang_kz_arr as $studiengang_kz) { - // Get STGL mail address, if available, otherwise get assistance mail address - $stgmail = $this->_getSTGLMailAddress($studiengang_kz); - - if(isSuccess($stgmail) && hasData($stgmail)) - list ($to, $vorname) = getData($stgmail)[0]; - else - show_error ('Failed retrieving DegreeProgram Mail'); - // Get full name of lector $this->load->model('person/Person_model', 'PersonModel'); - if (!$lector_name = getData($this->PersonModel->getFullName($this->_uid))) - { - show_error ('Failed retrieving person'); - } + $result = $this->PersonModel->getFullName($this->_uid); + $lector_name = hasData($result) ? getData($result) : 'Ein Lektor'; // Link to Antrag genehmigen $url = @@ -274,22 +284,26 @@ class reviewAnrechnungUebersicht extends Auth_Controller CIS_ROOT. 'cis/menu.php?content_id=&content='. CIS_ROOT. index_page(). self::APPROVE_ANRECHNUNG_URI; - // Prepare mail content - $body_fields = array( - 'vorname' => $vorname, - 'lektor_name' => $lector_name, - 'empfehlung' => $empfehlung ? 'positive' : 'negative', - 'link' => anchor($url, 'Anrechnungsanträge Übersicht') - ); + // Get STGL mail address, if available, otherwise get assistance mail address + if (!$result = $this->_getSTGLMailAddress($studiengang_kz)) return false; + foreach ($result as $stgl) + { + // Prepare mail content + $body_fields = array( + 'vorname' => $stgl['vorname'], + 'lektor_name' => $lector_name, + 'empfehlung' => $empfehlung ? 'positive' : 'negative', + 'link' => anchor($url, 'Anrechnungsanträge Übersicht') + ); - sendSanchoMail( - 'AnrechnungEmpfehlungAbgeben', - $body_fields, - $to, - 'Anerkennung nachgewiesener Kenntnisse: Empfehlung wurde abgegeben' - ); + sendSanchoMail( + 'AnrechnungEmpfehlungAbgeben', + $body_fields, + $stgl['to'], + 'Anerkennung nachgewiesener Kenntnisse: Empfehlung wurde abgegeben' + ); + } } - return true; } @@ -300,28 +314,33 @@ class reviewAnrechnungUebersicht extends Auth_Controller $result = $this->StudiengangModel->getLeitung($stg_kz); // Get STGL mail address, if available - if (isSuccess($result) && hasData($result)) - { - return success(array( - $result->retval[0]->uid. '@'. DOMAIN, - $result->retval[0]->vorname - )); - } + if (hasData($result)) + { + foreach (getData($result) as $stgl) + { + $stglMailAdress_arr[]= array( + 'to' => $stgl->uid. '@'. DOMAIN, + 'vorname' => $stgl->vorname + ); + } + + return $stglMailAdress_arr; + } // ...otherwise get assistance mail address else { $result = $this->StudiengangModel->load($stg_kz); - if (isSuccess($result) && hasData($result)) + if (hasData($result)) { - return success(array( + return array( $result->retval[0]->email, '' - )); + ); } else { - return error('Keine E-Mail für diesen Stg gefunden'); + return false; } } } 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/AdminZeitverfuegbarkeit.php b/application/controllers/lehre/lvplanung/AdminZeitverfuegbarkeit.php new file mode 100644 index 000000000..007b6974d --- /dev/null +++ b/application/controllers/lehre/lvplanung/AdminZeitverfuegbarkeit.php @@ -0,0 +1,310 @@ + 'lehre/zeitverfuegbarkeit:rw', + 'saveZeitverfuegbarkeit' => 'lehre/zeitverfuegbarkeit:rw', + 'deleteZeitverfuegbarkeit' => 'lehre/zeitverfuegbarkeit:rw' + ) + ); + + // Load models + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel'); + + // Load libraries + $this->load->library('PermissionLib'); + $this->load->library('AuthLib'); + $this->load->library('WidgetLib'); + + // Load helpers + $this->load->helper('array'); + + // Load language phrases + $this->loadPhrases( + array( + 'global', + 'ui', + 'lehre' + ) + ); + + $this->_setAuthUID(); // sets property uid + + $this->setControllerId(); // sets the controller id + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + public function index() + { + // Get Studiengaenge the user is entitled for + $result = $this->permissionlib->getSTG_isEntitledFor(self::BERECHTIGUNG_ZEITVERFUEGBARKEIT); + $studiengang_kz_arr = !isEmptyArray($result) ? $result : array(); + + // Get lectors of that Studiengaenge + $result = $this->_getLehreinheitmitarbeiterByStg($studiengang_kz_arr); + $lektor_arr = hasData($result) ? getData($result) : array(); + + // Get available Stundenplan Stunden + $result = $this->_getStunden(); + $stunde_arr = hasData($result) ? getData($result) : array(); + + // Get actual Studiensemester to set min-limit Datepicker + $result = $this->StudiensemesterModel->getAkt(); + $studsemStart = hasData($result) ? getData($result)[0]->start : ''; + + $view_data = array( + 'studiengang_kz_arr' => $studiengang_kz_arr, + 'lektor_arr' => $lektor_arr, + 'stunde_arr' => $stunde_arr, + 'studsemStart' => $studsemStart + ); + + $this->load->view('lehre/lvplanung/adminZeitverfuegbarkeit.php', $view_data); + } + + /** + * Save or update Zeitverfuegbarkeit. + */ + public function saveZeitverfuegbarkeit() + { + $zeitsperre_id = $this->input->post('zeitsperre_id'); + $mitarbeiter_uid = $this->input->post('mitarbeiter_uid'); + $zeitsperretyp_kurzbz = $this->input->post('zeitsperretyp_kurzbz'); + $bezeichnung = $this->input->post('bezeichnung'); + $vonDatum = $this->input->post('vondatum'); + $vonStunde = isEmptyString($this->input->post('vonstunde')) ? null : $this->input->post('vonstunde'); + $bisDatum = $this->input->post('bisdatum'); + $bisStunde = isEmptyString($this->input->post('bisstunde')) ? null : $this->input->post('bisstunde'); + + $result = $this->_validate($this->input->post()); + if (isSuccess($result)) + { + if (is_numeric($zeitsperre_id)) + { + $result = $this->ZeitsperreModel->update( + $zeitsperre_id, + array( + 'vondatum' => $vonDatum, + 'vonstunde' => $vonStunde, + 'bisdatum' => $bisDatum, + 'bisstunde' => $bisStunde, + 'bezeichnung' => $bezeichnung + ) + ); + } + else + { + $result = $this->ZeitsperreModel->save( + $zeitsperretyp_kurzbz, + $mitarbeiter_uid, + $vonDatum, + $bisDatum, + $vonStunde, + $bisStunde, + $bezeichnung + ); + } + } + + if (isError($result)) + { + $this->terminateWithJsonError(getError($result)); + } + + $zeitsperre_id = getData($result); + + // Success response to AJAX + $this->outputJsonSuccess(array( + 'zeitsperre_id' => $zeitsperre_id, + 'msg' => $this->p->t('ui', 'gespeichert') + )); + } + + /** + * Delete Zeitverfuegbarkeit. + */ + public function deleteZeitverfuegbarkeit() + { + $zeitsperre_id = $this->input->post('zeitsperre_id'); + + if (!is_numeric($zeitsperre_id)) + { + $this->terminateWithJsonError('Wählen Sie einen Lehrenden aus der Zeitverfügbarkeit-Tabelle aus.'); + } + + // Load Zeitsperre + $result = $this->ZeitsperreModel->load($zeitsperre_id); + $delZsp = getData($result)[0]; + + // Delete + $result = $this->ZeitsperreModel->delete($zeitsperre_id); + + if (isError($result)) + { + $this->terminateWithJsonError(getError($result)); + } + + // Store Deletion query + $delQry = $this->db->last_query(); + + // Log deletion + $this->_logDeletion($delZsp, $delQry); + + $this->outputJsonSuccess(array('msg' => $this->p->t('ui', 'geloescht'))); + } + + // ----------------------------------------------------------------------------------------------------------------- + // 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'); + } + + /** + * Get all lectors that are assigend to Lehreinheiten in actual or future semester. + * + * @param $studiengang_kz_arr Restrict only to given stg- + * @return mixed + */ + private function _getLehreinheitmitarbeiterByStg($studiengang_kz_arr) + { + $this->MitarbeiterModel->addSelect('lema.mitarbeiter_uid, nachname, vorname'); + $this->MitarbeiterModel->addDistinct('lema.mitarbeiter_uid'); + $this->MitarbeiterModel->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_mitarbeiter.mitarbeiter_uid = lema.mitarbeiter_uid'); + $this->MitarbeiterModel->addJoin('public.tbl_benutzer b', 'lema.mitarbeiter_uid = b.uid'); + $this->MitarbeiterModel->addJoin('public.tbl_person p', 'person_id'); + $this->MitarbeiterModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->MitarbeiterModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->MitarbeiterModel->addJoin('public.tbl_studiensemester ss', 'studiensemester_kurzbz'); + $this->MitarbeiterModel->addOrder('lema.mitarbeiter_uid'); + + // Return lektoren assigned to actual or future lehreinheiten + return $this->MitarbeiterModel->loadWhere(' + lv.studiengang_kz IN (' . implode(', ', $studiengang_kz_arr) . ') + AND b.aktiv + AND personalnummer > 0 + AND NOW() <= ss.ende' + ); + } + + /** + * Get all available Stunden of Stundentabelle. + * + * @return mixed + */ + private function _getStunden() + { + $this->load->model('ressource/Stunde_model', 'StundeModel'); + $this->StundeModel->addOrder('stunde'); + + return $this->StundeModel->load(); + } + + /** + * Validaton checks performed on post data. + * + * @param $post + * @return array|stdClass + * @throws Exception + */ + private function _validate($post) + { + if (isEmptyString($post['mitarbeiter_uid'])) + { + return (error('LektorIn fehlt')); + } + + if (isEmptyString($post['bezeichnung'])) + { + return (error('Notiz fehlt')); + } + + if (isEmptyString($post['vondatum'])) + { + return error('Startdatum fehlt'); + } + + if (isEmptyString($post['bisdatum'])) + { + return error('Endedatum fehlt'); + } + + if (new DateTime($post['bisdatum']) < new DateTime($post['vondatum'])) + { + return error('Endedatum darf nicht VOR dem Startdatum liegen'); + } + + // Check bisstunde not after vonstunde within same day + if (new DateTime($post['bisdatum']) == new DateTime($post['vondatum'])) + { + if (is_numeric($post['vonstunde']) && is_numeric($post['bisstunde']) + && $post['bisstunde'] < $post['vonstunde']) + { + return error('Am gleichen Tag darf Endstunde nicht VOR der Startstunde liegen'); + } + } + + // Check dates are > then start of actual Studiensemester + $result = $this->StudiensemesterModel->getAkt(); + $studsemStart = hasData($result) ? getData($result)[0]->start : ''; + + if (new DateTime($post['vondatum']) < new DateTime($studsemStart) || + new DateTime($post['bisdatum']) < new DateTime($studsemStart)) + { + return error('Start- und Endedatum können nur für das aktuelle oder künftige Studiensemester geplant werden'); + } + + return success(); + } + + /** + * Log information of deleted Zeitsperre into log table. + * + * @param $delZsp object of deleted Zeitsperre + * @param $delQry string of performed delete query + * @return mixed + * @throws Exception + */ + private function _logDeletion($delZsp, $delQry) + { + $beschreibung = 'Zeitverfügbarkeitlöschung ' + . $delZsp->mitarbeiter_uid. ' ' + . (new DateTime($delZsp->vondatum))->format('d.m.Y') + . (is_null($delZsp->vonstunde) ? '(*)' : '('. $delZsp->vonstunde. ')') + . '-' + . (new DateTime($delZsp->bisdatum))->format('d.m.Y') + . (is_null($delZsp->bisstunde) ? '(*)' : '('. $delZsp->bisstunde. ')') + . ''; + + $this->load->model('system/Log_model', 'LogModel'); + return $this->LogModel->insert(array( + 'mitarbeiter_uid' => $this->_uid, + 'beschreibung' => substr($beschreibung, 0, 64), + 'sql' => $delQry + )); + } +} 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/organisation/Studiensemester.php b/application/controllers/organisation/Studiensemester.php index 10fa5b3ad..685c8cd7c 100644 --- a/application/controllers/organisation/Studiensemester.php +++ b/application/controllers/organisation/Studiensemester.php @@ -138,7 +138,7 @@ class Studiensemester extends Auth_Controller $start = $this->input->post("semstart"); $ende = $this->input->post("semende"); $studienjahr_kurzbz = $this->input->post("studienjahrkurzbz"); - $beschreibung = $this->input->post("beschreibung"); + $beschreibung = isEmptyString($this->input->post("beschreibung")) ? null : $this->input->post("beschreibung"); $onlinebewerbung = $this->input->post("onlinebewerbung"); $onlinebewerbung = isset($onlinebewerbung); diff --git a/application/controllers/person/BPKWartung.php b/application/controllers/person/BPKWartung.php index 52cb09c5c..0d96f8a12 100644 --- a/application/controllers/person/BPKWartung.php +++ b/application/controllers/person/BPKWartung.php @@ -7,8 +7,6 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class BPKWartung extends Auth_Controller { - private $_uid; // contains the UID of the logged user - /** * Constructor */ @@ -46,7 +44,7 @@ class BPKWartung extends Auth_Controller // Public methods /** - * Main page of the InfoCenter tool + * Main page of the bPK Wartung. */ public function index() { @@ -56,9 +54,7 @@ class BPKWartung extends Auth_Controller } /** - * Personal details page of the InfoCenter tool - * Initialization function, gets person and prestudent data and loads the view with the data - * @param $person_id + * bPK Details initialization function, gets person data and loads the view with the data. */ public function showDetails() { @@ -85,8 +81,7 @@ class BPKWartung extends Auth_Controller } /** - * Saves a ZGV for a prestudent, includes Ort, Datum, Nation for bachelor and master - * @param $prestudent_id + * Saves a bPK for a person. */ public function saveBPK() { @@ -112,7 +107,7 @@ class BPKWartung extends Auth_Controller // Private methods /** - * Loads all necessary Person data: Stammdaten (name, svnr, contact, ...), Dokumente, Logs and Notizen + * Loads all necessary Person data. * @param $person_id * @return array */ diff --git a/application/controllers/person/Gruppenmanagement.php b/application/controllers/person/Gruppenmanagement.php new file mode 100644 index 000000000..099871676 --- /dev/null +++ b/application/controllers/person/Gruppenmanagement.php @@ -0,0 +1,296 @@ + 'lehre/gruppenmanager:r', + 'showBenutzergruppe' => 'lehre/gruppenmanager:r', + 'getBenutzer' => 'lehre/gruppenmanager:r', + 'getAllBenutzer' => 'lehre/gruppenmanager:r', + 'addBenutzer' => 'lehre/gruppenmanager:rw', + 'removeBenutzer' => 'lehre/gruppenmanager:rw' + ) + ); + + // Loads models + $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'); + $this->loadPhrases( + array( + 'global', + 'person', + 'lehre', + 'ui', + 'filter', + 'gruppenmanagement' + ) + ); + + $this->setControllerId(); // sets the controller id + $this->_setAuthUID(); // sets property uid + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Main page + */ + public function index() + { + $this->load->view( + 'person/gruppenmanagement/gruppenmanagement.php', + array('uid' => $this->_uid) + ); + } + + /** + * Shows Benutzergruppe overview page. + */ + public function showBenutzergruppe() + { + $this->_setNavigationMenuShowDetails(); + $gruppe_kurzbz = $this->input->get('gruppe_kurzbz'); + + $data[self::FHC_CONTROLLER_ID] = $this->getControllerId(); + + $this->load->view( + 'person/gruppenmanagement/benutzergruppe.php', + array('gruppe_kurzbz' => $gruppe_kurzbz) + ); + } + + /** + * Gets Benutzer assigned to a Gruppe + */ + public function getBenutzer() + { + $gruppe_kurzbz = $this->input->get('gruppe_kurzbz'); + + $this->BenutzergruppeModel->addSelect('uid, vorname, nachname, ben.aktiv'); + $this->BenutzergruppeModel->addJoin('public.tbl_benutzer ben', 'uid'); + $this->BenutzergruppeModel->addJoin('public.tbl_person', 'person_id'); + $benutzerRes = $this->BenutzergruppeModel->loadWhere(array('gruppe_kurzbz' => $gruppe_kurzbz)); + + $this->outputJson($benutzerRes); + } + + /** + * Gets all Benutzer for assignment to Gruppe + */ + public function getAllBenutzer() + { + $this->BenutzerModel->addSelect('uid, vorname, nachname'); + $this->BenutzerModel->addJoin('public.tbl_person', 'person_id'); + $benutzerRes = $this->BenutzerModel->loadWhere( + array('tbl_benutzer.aktiv' => true) + ); + $this->outputJson($benutzerRes); + } + + /** + * Adds a Benutzer to Gruppe + */ + public function addBenutzer() + { + $uid = $this->input->post('uid'); + $gruppe_kurzbz = $this->input->post('gruppe_kurzbz'); + + if (isEmptyString($uid)) + $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, + 'gruppe_kurzbz' => $gruppe_kurzbz + ) + ); + + if (isError($benutzerExistsRes)) + { + $this->outputJsonError(getError($benutzerExistsRes)); + return; + } + + if (hasData($benutzerExistsRes)) + { + $this->outputJsonError($this->p->t('gruppenmanagement', 'benutzerSchonZugewiesen')); + return; + } + + $result = $this->BenutzergruppeModel->insert( + array( + 'uid' => $uid, + 'gruppe_kurzbz' => $gruppe_kurzbz, + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => $this->_uid + ) + ); + + // log the group add + $lastQry = $this->db->last_query(); + + if (isSuccess($result)) + { + $beschreibung = 'Gruppenmanagement: Nutzer zu Gruppe hinzugefügt'; + $this->_writeLog($this->_uid, $beschreibung, $lastQry); + } + } + + $this->outputJson($result); + } + + /** + * Removes Benutzer from Gruppe + */ + public function removeBenutzer() + { + $uid = $this->input->post('uid'); + $gruppe_kurzbz = $this->input->post('gruppe_kurzbz'); + + if (isEmptyString($uid)) + $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, + 'gruppe_kurzbz' => $gruppe_kurzbz + ) + ); + } + + // log the group remove + $lastQry = $this->db->last_query(); + + if (isSuccess($result)) + { + $beschreibung = 'Gruppenmanagement: Nutzer aus Gruppe entfernt'; + $this->_writeLog($this->_uid, $beschreibung, $lastQry); + } + + $this->outputJson($result); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Private methods + + /** + * Define the navigation menu for the showDetails page + */ + private function _setNavigationMenuShowDetails() + { + $this->load->library('NavigationLib', array('navigation_page' => 'person/Gruppenmanagement/showBenutzergruppe')); + + $link = site_url('person/Gruppenmanagement'); + + $this->navigationlib->setSessionMenu( + array( + 'back' => $this->navigationlib->oneLevel( + 'Zurück', // description + $link, // link + array(), // children + 'angle-left', // icon + true, // expand + null, // subscriptDescription + null, // subscriptLinkClass + null, // subscriptLinkValue + '', // target + 1 // sort + ) + ) + ); + } + + /** + * Set uid of authentificated user + */ + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) show_error('User authentification failed'); + } + + /** + * Writes an entry in the log table + */ + private function _writeLog($uid, $beschreibung, $lastQry) + { + $mitarbeiterResult = $this->MitarbeiterModel->load(array('mitarbeiter_uid'=>$this->_uid)); + + if(!isSuccess($mitarbeiterResult) || !hasData($mitarbeiterResult)) + { + $uid = DUMMY_LEKTOR_UID; + $beschreibung .= ': '.$this->_uid; + $beschreibung = mb_substr($beschreibung, 0, 64); + } + + $this->LogModel->insert(array( + 'mitarbeiter_uid' => $uid, + 'beschreibung' => $beschreibung, + 'sql' => $lastQry + )); + } + +} 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 190f84acd..71ab1c81b 100644 --- a/application/controllers/system/Navigation.php +++ b/application/controllers/system/Navigation.php @@ -1,4 +1,20 @@ . + */ if (! defined('BASEPATH')) exit('No direct script access allowed'); @@ -6,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/Variables.php b/application/controllers/system/Variables.php index c56407416..3cc246301 100644 --- a/application/controllers/system/Variables.php +++ b/application/controllers/system/Variables.php @@ -18,10 +18,10 @@ class Variables extends Auth_Controller { parent::__construct( array( - 'setVar' => 'basis/variable:rw', - 'getVar' => 'basis/variable:rw', - 'changeStudiensemesterVar' => 'basis/variable:rw', - 'changeStudengangsTypVar' => 'basis/variable:rw' + 'setVar' => array('basis/variable:rw','basis/variable_persoenlich:rw'), + 'getVar' => array('basis/variable:rw','basis/variable_persoenlich:rw'), + 'changeStudiensemesterVar' => array('basis/variable:rw','basis/variable_persoenlich:rw'), + 'changeStudengangsTypVar' => array('basis/variable:rw','basis/variable_persoenlich:rw') ) ); diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index 25ee96b60..1fc49c72f 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'; @@ -88,6 +89,12 @@ class InfoCenter extends Auth_Controller 'message' => 'Type of Document %s was updated, set to %s', 'success' => null ), + 'deletedoc' => array( + 'logtype' => 'Action', + 'name' => 'Document deleted', + 'message' => 'Document %s deleted', + 'success' => null + ), ); // Name of Interessentenstatus @@ -109,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', @@ -125,24 +134,21 @@ class InfoCenter extends Auth_Controller 'zgvStatusUpdate' => 'lehre/zgvpruefung:rw', 'saveAbsage' => 'infocenter:rw', 'saveFreigabe' => 'infocenter:rw', - 'getNotiz' => 'infocenter:r', + 'getNotiz' => array('infocenter:r', 'lehre/zgvpruefung:r'), 'saveNotiz' => array('infocenter:rw', 'lehre/zgvpruefung:rw'), - 'updateNotiz' => 'infocenter:rw', + 'updateNotiz' => array('infocenter:rw', 'lehre/zgvpruefung:rw'), 'reloadZgvPruefungen' => 'infocenter:r', 'reloadMessages' => 'infocenter:r', 'reloadDoks' => 'infocenter:r', + 'reloadUebersichtDoks' => 'infocenter:r', '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' + 'saveAbsageForAll' => 'infocenter:rw', + 'deleteDoc' => 'infocenter:rw', + 'getStudienartData' => 'infocenter:rw' ) ); @@ -154,16 +160,26 @@ 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'); $this->load->model('system/Filters_model', 'FiltersModel'); $this->load->model('system/PersonLock_model', 'PersonLockModel'); + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $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', @@ -214,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'); + } /** * @@ -300,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); @@ -311,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); @@ -325,7 +354,8 @@ class InfoCenter extends Auth_Controller $persondata, $prestudentdata, $dokumentdata, - $duplicate + $duplicate, + $unruly ); $data[self::FHC_CONTROLLER_ID] = $this->getControllerId(); @@ -345,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'; @@ -398,6 +435,35 @@ class InfoCenter extends Auth_Controller $this->outputJsonSuccess(array($json)); } + public function deleteDoc($person_id) + { + $akte_id = $this->input->post('akteid'); + + if (isset($akte_id) && isset($person_id)) + { + $this->load->library('AkteLib'); + $akte = $this->aktelib->get($akte_id); + + if (hasData($akte)) + { + $akte = getData($akte); + if ($akte->person_id === (int)$person_id) + { + $result = $this->aktelib->remove($akte_id); + + if (isError($result)) + { + $this->terminateWithJsonError('Error deleting document'); + } + + $this->_log($person_id, 'deletedoc', array($akte->bezeichnung)); + + $this->outputJsonSuccess('success'); + } + } + } + } + /** * Gets prestudent data for a person in json format * @param $person_id @@ -558,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( @@ -649,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() { @@ -703,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( @@ -733,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( @@ -1069,11 +1136,22 @@ 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, false); + + $this->DokumentModel->addOrder('bezeichnung'); + $dokumentdata = array('dokumententypen' => (getData($this->DokumentModel->load()))); + $data = array_merge($dokumentdata, ['dokumente' => $dokumente->retval]); + + $this->load->view('system/infocenter/dokpruefung.php', $data); + } + /** * Outputs content of an Akte, sends appropriate headers (so the document can be downloaded) * @param $akte_id @@ -1103,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 @@ -1267,6 +1245,127 @@ 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'))), + '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'); @@ -1305,7 +1404,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)) { @@ -1452,6 +1550,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)) @@ -1459,6 +1558,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( @@ -1509,7 +1609,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 + ), ) ); } @@ -1537,6 +1649,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)) { @@ -1700,7 +1815,7 @@ class InfoCenter extends Auth_Controller } /** - * Loads all necessary Person data: Stammdaten (name, svnr, contact, ...), Dokumente, Logs and Notizen + * Loads all necessary Person data: Stammdaten (name, contact, ...), Dokumente, Logs and Notizen * @param $person_id * @return array */ @@ -1741,14 +1856,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)) { @@ -1932,10 +2047,33 @@ class InfoCenter extends Auth_Controller $abwstatusgruende = $this->StatusgrundModel->getStatus(self::ABGEWIESENERSTATUS, true)->retval; $intstatusgruende = $this->StatusgrundModel->getStatus(self::INTERESSENTSTATUS)->retval; + $studienArtBerechtigung = array_column($this->getStudienArtBerechtigung(), 'typ'); + + $this->ZgvModel->addOrder('zgv_bez'); + $allZGVs = getData($this->ZgvModel->load()); + + $this->ZgvModel->addOrder('zgvmas_bez'); + $allZGVsMaster = getData($this->ZgvmasterModel->load()); + + $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, - 'intstatusgruende' => $intstatusgruende + 'intstatusgruende' => $intstatusgruende, + 'studienArtBerechtigung' => $studienArtBerechtigung, + 'all_zgvs' => $allZGVs, + 'all_zgvs_master' => $allZGVsMaster, + 'all_nations' => $allNations, + 'additional_stg' => $additional_stg, + 'all_genders' => $allGenders ); return $data; @@ -2096,8 +2234,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'; @@ -2194,18 +2332,35 @@ class InfoCenter extends Auth_Controller public function getAbsageData() { - $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $stg_typ = $this->getStudienArtBerechtigung(['b', 'm']); - $statusgruende = $this->StatusgrundModel->getStatus(self::ABGEWIESENERSTATUS, true)->retval; - $studienSemester = $this->variablelib->getVar('infocenter_studiensemester'); - $studiengaenge = $this->StudiengangModel->getStudiengaengeWithOrgForm(['b', 'm'], $studienSemester); + if (!is_null($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); - $data = array ( - 'statusgruende' => $statusgruende, - 'studiengaenge' => $studiengaenge->retval - ); + $data = array ( + 'statusgruende' => $statusgruende, + 'studiengaenge' => $studiengaenge->retval + ); - $this->outputJsonSuccess($data); + $this->outputJsonSuccess($data); + } + else + $this->outputJsonSuccess(null); + } + + public function getStudienArtBerechtigung($typ = null) + { + $studiengang_kz_all = $this->permissionlib->getSTG_isEntitledFor('infocenter'); + $stg_typ = $this->StudiengangModel->getStudiengangTyp($studiengang_kz_all, $typ); + return getData($stg_typ); + } + + public function getStudienartData() + { + $this->outputJsonSuccess($this->getStudienArtBerechtigung(['b', 'm', 'l'])); } public function saveAbsageForAll() @@ -2219,18 +2374,52 @@ class InfoCenter extends Auth_Controller if ($statusgrund === 'null' || $studiengang === 'null' || $abgeschickt === 'null' || empty($personen)) $this->terminateWithJsonError("Bitte füllen Sie alle Felder aus"); - foreach($personen as $person) + if ($studiengang === 'all' && $abgeschickt === 'all') { - $prestudent = $this->PrestudentModel->getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt); + foreach($personen as $person) + { + $prestudenten = $this->PrestudentModel->getByPersonWithoutLehrgang($person, $studienSemester); - if (!hasData($prestudent)) - continue; + if (!hasData($prestudenten)) + continue; - $prestudentData = getData($prestudent); + $prestudentenData = getData($prestudenten); + + foreach ($prestudentenData as $prestudent) + { + $this->saveAbsage($prestudent->prestudent_id, $statusgrund); + } + } + } + else + { + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $this->StudienplanModel->addSelect('1'); + $this->StudienplanModel->addJoin('lehre.tbl_studienordnung so', 'studienordnung_id'); + $escaped = $this->StudienplanModel->db->escape(strtoupper($studiengang)); + $this->StudienplanModel->db->where("UPPER(so.studiengangkurzbzlang || ':' || tbl_studienplan.orgform_kurzbz) = $escaped"); + $this->StudienplanModel->addLimit(1); + $studiengangResult = $this->StudienplanModel->load(); + + if (hasData($studiengangResult)) + { + foreach($personen as $person) + { + $prestudent = $this->PrestudentModel->getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt, $abgeschickt === 'all'); + + if (!hasData($prestudent)) + continue; + + $prestudentData = getData($prestudent); + $this->saveAbsage($prestudentData[0]->prestudent_id, $statusgrund); + } + } + else + $this->terminateWithJsonError("Falschen Studiengang übergeben!"); - $this->saveAbsage($prestudentData[0]->prestudent_id, $statusgrund); } $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..b1f2b60b7 --- /dev/null +++ b/application/controllers/system/infocenter/Rueckstellung.php @@ -0,0 +1,163 @@ + 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'), + 'setForPersonen' => 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 setForPersonen() + { + $personen = $this->input->post('personen'); + $datum_bis = $this->input->post('datum_bis'); + $status_kurzbz = $this->input->post('status_kurzbz'); + + foreach ($personen as $person) + { + $rueckstellung = $this->_ci->RueckstellungModel->loadWhere(array('person_id' => $person)); + if (hasData($rueckstellung)) + continue; + + $result = $this->_ci->RueckstellungModel->insert( + array('person_id' => $person, + '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, $status_kurzbz); + } + $this->outputJsonSuccess("Erfolgreich gespeichert!"); + } + + 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/infocenter/ZGVUeberpruefung.php b/application/controllers/system/infocenter/ZGVUeberpruefung.php index bb0c36b66..7d178a529 100644 --- a/application/controllers/system/infocenter/ZGVUeberpruefung.php +++ b/application/controllers/system/infocenter/ZGVUeberpruefung.php @@ -4,6 +4,8 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); class ZGVUeberpruefung extends Auth_Controller { + const BERECHTIGUNG_KURZBZ = 'lehre/zgvpruefung'; + /** * Constructor */ @@ -12,14 +14,15 @@ class ZGVUeberpruefung extends Auth_Controller // Set required permissions parent::__construct( array( - 'index' => 'lehre/zgvpruefung:r', - 'getZgvStatusByPrestudent' => 'lehre/zgvpruefung:r' + 'index' => self::BERECHTIGUNG_KURZBZ.':r', + 'getZgvStatusByPrestudent' => self::BERECHTIGUNG_KURZBZ.':r' ) ); $this->load->model('crm/ZGVPruefungStatus_model', 'ZGVPruefungStatusModel'); $this->load->model('crm/ZGVPruefung_model', 'ZGVPruefungModel'); $this->load->library('WidgetLib'); + $this->load->library('PermissionLib'); $this->setControllerId(); $this->loadPhrases( @@ -31,7 +34,14 @@ class ZGVUeberpruefung extends Auth_Controller public function index() { - $this->load->view('system/infocenter/infocenterZgvUeberpruefung.php'); + $oeKurzbz = $this->permissionlib->getOE_isEntitledFor(self::BERECHTIGUNG_KURZBZ); + + if (!$oeKurzbz) + show_error('Keine Berechtigung.'); + + $data['oeKurz'] = $oeKurzbz; + + $this->load->view('system/infocenter/infocenterZgvUeberpruefung.php', $data); } public function getZgvStatusByPrestudent() diff --git a/application/controllers/system/issues/Issues.php b/application/controllers/system/issues/Issues.php index e0103cfec..27a928fb4 100644 --- a/application/controllers/system/issues/Issues.php +++ b/application/controllers/system/issues/Issues.php @@ -6,7 +6,6 @@ class Issues extends Auth_Controller { private $_uid; - const FUNKTION_KURZBZ = 'ass'; // // user having this funktion can see issues for oes assigned with this funktion const BERECHTIGUNG_KURZBZ = 'system/issues_verwalten'; // user having this permission can see issues for oes assigned with this permission public function __construct() @@ -26,6 +25,10 @@ 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'); + + // load config + $this->load->config('issueList'); $this->loadPhrases( array( @@ -39,15 +42,19 @@ class Issues extends Auth_Controller ); $this->_setAuthUID(); // sets property uid + $this->setControllerId(); // sets the controller id } public function index() { $oes_for_issues = $this->_getOesForIssues(); + $language_index = $this->_getLanguageIndex(); + $apps = $this->config->item('issues_list_apps'); + $status = $this->config->item('issues_list_status'); $this->load->view( 'system/issues/issues', - $oes_for_issues + array_merge($oes_for_issues, array('language_index' => $language_index, 'apps' => $apps, 'status' => $status)) ); } @@ -80,7 +87,7 @@ class Issues extends Auth_Controller } if (isEmptyString($changeIssueMethod)) - $errors[] = error("Invalid issue status given"); + $errors[] = "Invalid issue status given"; else { $issueRes = $this->issueslib->{$changeIssueMethod}($issue_id, $user); @@ -118,6 +125,8 @@ class Issues extends Auth_Controller $oe_kurzbz_for_funktion = array(); $benutzerfunktionRes = $this->BenutzerfunktionModel->getBenutzerFunktionByUid($this->_uid, null, date('Y-m-d'), date('Y-m-d')); + $functions = $this->config->item('issues_list_functions'); + if (isError($benutzerfunktionRes)) show_error(getError($benutzerfunktionRes)); @@ -127,8 +136,8 @@ class Issues extends Auth_Controller { $all_funktionen_oe_kurzbz[$benutzerfunktion->oe_kurzbz][] = $benutzerfunktion->funktion_kurzbz; - // separate oes for the funktion needed for displaying issues - if ($benutzerfunktion->funktion_kurzbz == self::FUNKTION_KURZBZ) + // separate oes for the additional functions which enables displaying issues + if (in_array($benutzerfunktion->funktion_kurzbz, $functions)) { $oe_kurzbz_for_funktion[] = $benutzerfunktion->oe_kurzbz; @@ -153,7 +162,9 @@ class Issues extends Auth_Controller } // add oes for which there is the "manage issues" Berechtigung - if (!$oe_kurzbz_berechtigt = $this->permissionlib->getOE_isEntitledFor(self::BERECHTIGUNG_KURZBZ)) + $oe_kurzbz_berechtigt = $this->permissionlib->getOE_isEntitledFor(self::BERECHTIGUNG_KURZBZ); + + if (!$oe_kurzbz_berechtigt) show_error('No permission or error when checking permissions'); $all_oe_kurzbz_berechtigt = array_unique(array_merge($oe_kurzbz_for_funktion, $oe_kurzbz_berechtigt)); @@ -163,4 +174,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 new file mode 100644 index 000000000..d7bf9836e --- /dev/null +++ b/application/controllers/system/issues/IssuesZustaendigkeiten.php @@ -0,0 +1,216 @@ + 'admin:r', + 'getApps' => 'admin:r', + 'getFehlercodes' => 'admin:r', + 'getNonAssignedZustaendigkeiten' => 'admin:r', + 'addZustaendigkeit' => 'admin:rw', + 'deleteZustaendigkeit' => 'admin:rw' + ) + ); + + // Load libraries + $this->load->library('IssuesLib'); + $this->load->library('WidgetLib'); + + // Load models + $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + $this->load->model('system/Fehler_model', 'FehlerModel'); + $this->load->model('system/Fehlerzustaendigkeiten_model', 'FehlerzustaendigkeitenModel'); + + $this->loadPhrases( + array( + 'global', + 'ui', + 'filter', + 'lehre', + 'person', + 'fehlermonitoring' + ) + ); + + $this->_setAuthUID(); // sets property uid + $this->setControllerId(); // sets the controller id + } + + public function index() + { + $this->load->view("system/issues/issuesZustaendigkeiten.php"); + } + + /** + * Loads all Apps to which Fehler exist. + */ + public function getApps() + { + $this->FehlerModel->addDistinct(); + $this->FehlerModel->addSelect('app'); + $this->FehlerModel->addOrder('app'); + + $appRes = $this->FehlerModel->load(); + + $this->outputJson($appRes); + } + + /** + * Gets all fehlercodes, optionally by app. + */ + public function getFehlercodes() + { + $app = $this->input->get('app'); + + $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(); + + $this->outputJson($fehlerRes); + } + + /** + * Gets all Mitarbeiter, Organisationseinheiten, Funktionen not assigned to a Fehler yet. + */ + public function getNonAssignedZustaendigkeiten() + { + $fehlercode = $this->input->get('fehlercode'); + + $mitarbeiterRes = $this->FehlerzustaendigkeitenModel->getNonAssignedMitarbeiter($fehlercode); + + if (isError($mitarbeiterRes)) + { + $this->outputJsonError(getError($mitarbeiterRes)); + return; + } + + $this->OrganisationseinheitModel->addSelect('oe_kurzbz, bezeichnung, organisationseinheittyp_kurzbz'); + $this->OrganisationseinheitModel->addOrder('organisationseinheittyp_kurzbz, bezeichnung'); + $oeRes = $this->OrganisationseinheitModel->loadWhere(array('aktiv' => true)); + + if (isError($oeRes)) + { + $this->outputJsonError(getError($oeRes)); + return; + } + + $oe_funktionen = array(); + + if (hasData($oeRes)) + { + $oes = getData($oeRes); + + foreach ($oes as $oe) + { + $oe->funktionen = array(); + $funktionRes = $this->FehlerzustaendigkeitenModel->getNonAssignedFunktionen($fehlercode, $oe->oe_kurzbz); + + if (isError($funktionRes)) + { + $this->outputJsonError(getError($oeRes)); + return; + } + + $funktionData = getData($funktionRes); + $oe->funktionen = $funktionData; + $oe_funktionen[] = $oe; + } + } + + if (isError($funktionRes)) + { + $this->outputJsonError(getError($funktionRes)); + return; + } + + $result = array( + 'mitarbeiter' => getData($mitarbeiterRes), + 'oe_funktionen' => $oe_funktionen + ); + + $this->outputJsonSuccess($result); + } + + /** + * Adds a Zuständigkeit after performing error checks. + */ + public function addZustaendigkeit() + { + $fehlercode = $this->input->post('fehlercode'); + $mitarbeiter_person_id = $this->input->post('mitarbeiter_person_id'); + $oe_kurzbz = $this->input->post('oe_kurzbz'); + $funktion_kurzbz = $this->input->post('funktion_kurzbz'); + + if (isEmptyString($fehlercode)) + $this->outputJsonError($this->p->t('fehlermonitoring', 'fehlercodeFehlt')); + elseif (isEmptyString($mitarbeiter_person_id) && isEmptyString($oe_kurzbz)) + $this->outputJsonError($this->p->t('fehlermonitoring', 'mitarbeiterUndOeFehlt')); + elseif (!isEmptyString($mitarbeiter_person_id) && !isEmptyString($oe_kurzbz)) + $this->outputJsonError($this->p->t('fehlermonitoring', 'nurOeOderMitarbeiterSetzen')); + elseif (isset($mitarbeiter_person_id) && !is_numeric($mitarbeiter_person_id)) + $this->outputJsonError($this->p->t('fehlermonitoring', 'ungueltigeMitarbeiterId')); + else + { + $data = array( + 'fehlercode' => $fehlercode + ); + + if (!isEmptyString($mitarbeiter_person_id)) + $data['person_id'] = $mitarbeiter_person_id; + + if (!isEmptyString($oe_kurzbz)) + $data['oe_kurzbz'] = $oe_kurzbz; + + if (!isEmptyString($funktion_kurzbz)) + $data['funktion_kurzbz'] = $funktion_kurzbz; + + $zustaendigkeitExistsRes = $this->FehlerzustaendigkeitenModel->loadWhere($data); + + if (isError($zustaendigkeitExistsRes)) + $this->outputJsonError(getError($zustaendigkeitExistsRes)); + elseif (hasData($zustaendigkeitExistsRes)) + $this->outputJsonError($this->p->t('fehlermonitoring', 'zustaendigkeitExistiert')); + else + { + $data['insertvon'] = $this->_uid; + + $this->outputJson($this->FehlerzustaendigkeitenModel->insert($data)); + } + } + } + + /** + * Deletes a Zuständigkeit. + */ + public function deleteZustaendigkeit() + { + $fehlerzustaendigkeiten_id = $this->input->post('fehlerzustaendigkeiten_id'); + + // check if Id correctly passed + if (!isset($fehlerzustaendigkeiten_id) || !is_numeric($fehlerzustaendigkeiten_id)) + { + $this->outputJsonError($this->p->t('fehlermonitoring', 'ungueltigeZustaendigkeitenId')); + return; + } + + $this->outputJson($this->FehlerzustaendigkeitenModel->delete($fehlerzustaendigkeiten_id)); + } + + /** + * 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/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'); /** @@ -22,16 +41,33 @@ class DB_Model extends CI_Model const PGSQL_BOOLEAN_FALSE = 'f'; const PGSQL_BOOLEAN_TYPE = 'bool'; const PGSQL_BOOLEAN_ARRAY_TYPE = '_bool'; + const PGSQL_INT2_TYPE = 'int2'; + const PGSQL_INT4_TYPE = 'int4'; + 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 $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 + // 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 @@ -41,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; } // ------------------------------------------------------------------------------------------ @@ -80,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); @@ -130,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; @@ -156,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); @@ -219,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); @@ -240,7 +290,7 @@ class DB_Model extends CI_Model $tmpId = array($this->pk => $id); } - return $this->loadWhere($tmpId); + return $this->loadWhere($tmpId, $encryptedColumns); } /** @@ -248,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); @@ -260,7 +313,7 @@ class DB_Model extends CI_Model if ($result) { - return success($this->_toPhp($result)); + return success($this->_toPhp($result, $encryptedColumns)); } else { @@ -271,11 +324,6 @@ class DB_Model extends CI_Model /** * Load data and convert a record into a list of data from the main table, * and linked to every element, the data from the side tables - * - * TODO: - * - Adding support for composed primary key - * - Adding support for cascading side tables (useful?) - * * NOTE: sub queries are not supported in the from clause * * @return array @@ -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); } @@ -598,6 +648,28 @@ class DB_Model extends CI_Model return $val; } + /** + * Convert PG-Int* to PHP-Integer + */ + public function pgIntPhp($val) + { + // If it is null, let it be null + if ($val == null) return $val; + + return intval($val); + } + + /** + * Convert PG-Float* to PHP-Float + */ + public function pgFloatPhp($val) + { + // If it is null, let it be null + if ($val == null) return $val; + + return floatval($val); + } + /** * Converts from PostgreSQL array to php array * It also takes care about array of booleans @@ -736,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) @@ -753,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 @@ -768,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) { @@ -790,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 { @@ -818,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); @@ -829,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); } } @@ -873,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 @@ -889,9 +1188,17 @@ 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 + || $eqmd->type == DB_Model::PGSQL_INT4_TYPE + || $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 @@ -941,6 +1248,34 @@ class DB_Model extends CI_Model { $resultElement->{$toBeConverted->name} = $this->pgBoolPhp($resultElement->{$toBeConverted->name}); } + // Integer type + elseif ($toBeConverted->type == DB_Model::PGSQL_INT2_TYPE + || $toBeConverted->type == DB_Model::PGSQL_INT4_TYPE + || $toBeConverted->type == DB_Model::PGSQL_INT8_TYPE) + { + $resultElement->{$toBeConverted->name} = $this->pgIntPhp($resultElement->{$toBeConverted->name}); + } + // Float type + elseif ($toBeConverted->type == DB_Model::PGSQL_FLOAT4_TYPE + || $toBeConverted->type == DB_Model::PGSQL_FLOAT8_TYPE) + { + $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}); + } + } } } } @@ -1033,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..dad56334d --- /dev/null +++ b/application/core/FHCAPI_Controller.php @@ -0,0 +1,290 @@ +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->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; + } elseif (array_is_list($data)) { + foreach ($data as $d) + $this->addError($d, $type); + return; + } 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; + } + + protected function terminateWithFileOutput($contenttype, $content, $filename=null) + { + $this->clearOutputBuffering(); + $this->output->set_status_header(200) + ->set_content_type($contenttype) + ->set_header('Expires: 0') + ->set_header('Cache-Control: no-store, no-cache, must-revalidate') + ->set_header('Pragma: public') + ->set_header('Content-Length: ' . strlen($content)); + + if($filename) + { + $cleanedfilename = preg_replace('/[^a-zA-Z0-9\-_.]/', '_', $filename); + $this->output->set_header('Content-Disposition: attachment; filename="' + . $cleanedfilename . '"'); + } + else + { + $this->output->set_header('Content-Disposition: inline'); + } + + $this->output->set_output($content) + ->_display(); + exit(); + } + + private function clearOutputBuffering() + { + while(ob_get_level() > 0) + { + ob_end_clean(); + } + } + + // --------------------------------------------------------------- + // 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/FHC_Controller.php b/application/core/FHC_Controller.php index ce8748c5a..dcd693cb1 100644 --- a/application/core/FHC_Controller.php +++ b/application/core/FHC_Controller.php @@ -121,7 +121,7 @@ abstract class FHC_Controller extends CI_Controller protected function terminateWithJsonError($message) { header('Content-Type: application/json'); - echo json_encode(error($message)); + echo json_encode(error($message)); // KEEP IT!!! exit; } @@ -132,31 +132,50 @@ abstract class FHC_Controller extends CI_Controller { $this->output->set_content_type('application/json')->set_output(json_encode($mixed)); } - + + /** + * To download the given file represented by the fileObj parameter. + * fileObj has the following structure: + * $fileObj->filename + * $fileObj->file + * $fileObj->name + * $fileObj->mimetype + * $fileObj->disposition + */ protected function outputFile($fileObj) { - if (file_exists($fileObj->file)) + // If the file exists + if (isset($fileObj->file) && !isEmptyString($fileObj->file) && file_exists($fileObj->file)) { - $finfo = new finfo(FILEINFO_MIME); - header('Content-Description: File Transfer'); - header('Content-Type: '. $finfo->file($fileObj->file)); + header('Content-Type: '. $fileObj->mimetype); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($fileObj->file)); - - if (isset($fileObj->disposition) && ($fileObj->disposition == 'inline' || $fileObj->disposition == 'attachment')) + + if (isset($fileObj->disposition) + && ($fileObj->disposition == 'inline' || $fileObj->disposition == 'attachment')) { header('Content-Disposition: '. $fileObj->disposition. '; filename="'. $fileObj->name. '"'); } - - readfile($fileObj->file); - - exit; + + readfile($fileObj->file); // reads the file content to the output buffer } - - return false; + else + { + // Otherwise print an error + show_error('The provided file does not exist: '.(isset($fileObj->file) ? $fileObj->file : 'file not given')); + } + } + + /** + * Return the JSON decoded HTTP POST request + * If the request is not in JSON format then a null value is returned + */ + protected function getPostJSON() + { + return json_decode($this->input->raw_input_stream); } //------------------------------------------------------------------------------------------------------------------ @@ -175,3 +194,4 @@ abstract class FHC_Controller extends CI_Controller } } } + diff --git a/application/core/FS_Model.php b/application/core/FS_Model.php index 03a0ee095..0d696d378 100644 --- a/application/core/FS_Model.php +++ b/application/core/FS_Model.php @@ -3,113 +3,238 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); /** - * + * Model to work with the filesystem, it represents a directory + * It could be extended or could be used directly to work on the given path */ -abstract class FS_Model extends CI_Model +class FS_Model extends CI_Model { - protected $filepath; // Path of the file + const READ_MODE = 'r'; + const READ_WRITE_MODE = 'w+'; + const READ_APPEND_MODE = 'a+'; + const BLOCK_SIZE = 8192; + const META_URI = 'uri'; + + private $_path; // Directory where this model can operate /** - * Loads FilesystemLib and set properties + * Set properties */ - public function __construct($filepath = null) + public function __construct($path) { parent::__construct(); - // Load the filesystem library - $this->load->library('FilesystemLib'); + $this->_path = $path; + } - $this->filepath = $filepath; + // ------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Opens a file in read mode and returns its file handle + */ + public function openRead($filename) + { + return $this->_open($filename, self::READ_MODE); } /** - * Read data from file system - * - * @return array + * Opens a file in read and write mode and returns its file handle + * If the file does not exist then it is created */ - public function read($filename) + public function openReadWrite($filename) { - // Check Class-Attributes - if (is_null($this->filepath)) return error('The given filepath in not valid', EXIT_ERROR); - - // Check method parameters - if (is_null($filename)) return error('The given filename is not valid', EXIT_ERROR); - - if (!is_null($data = $this->filesystemlib->read($this->filepath, $filename))) - { - return success(base64_encode($data)); - } - else - { - return error('An error occurred while reading a file', EXIT_ERROR); - } + return $this->_open($filename, self::READ_WRITE_MODE); } /** - * Writing data to file system - * - * @param string $fileContent File content - * @return object + * Opens a file in read and append mode and returns its file handle + * If the file does not exist then it is created */ - public function write($filename, $content) + public function openReadAppend($filename) { - // Check Class-Attributes - if (is_null($this->filepath)) return error('The given filepath in not valid', EXIT_ERROR); + return $this->_open($filename, self::READ_APPEND_MODE); + } - // Check method parameters - if (is_null($content)) return error('The given file content is not valid', EXIT_ERROR); - if (is_null($filename)) return error('The given filename is not valid', EXIT_ERROR); + /** + * Closes a file handle + */ + public function close($fileHandle) + { + return fclose($fileHandle) === true ? success() : error('Error while closing the file handler'); + } - if ($this->filesystemlib->write($this->filepath, $filename, base64_decode($content)) === true) + /** + * Reads a block of bytes from the given file + * Returns a success that contains the block + * On failure returns an error + */ + public function readBlock($fileHandle) + { + // Reads a block of bytes from the file + $block = fread($fileHandle, self::BLOCK_SIZE); + + // If an error occurred + if ($block === false) + { + // Prepare the error message + $errorMsg = 'An error occurred while reading a file'; + + // Tries to get the file name and to concatenate it to the error message + $fileMetaData = stream_get_meta_data($fileHandle); + if (isset($fileMetaData[self::META_URI])) $errorMsg .= ': '.$fileMetaData[self::META_URI]; + + return error($errorMsg); // returns the error + } + + return success($block); // return success if everything was fine + } + + /** + * Writes/appends (depending on how the file was opened) a content into a file + * Returns a success that contains the written number of bytes + * On failure returns an error + */ + public function write($fileHandle, $content) + { + // Writes the provided content to the file + $writeResult = fwrite($fileHandle, $content); + + // If an error occurred + if ($writeResult === false) + { + $errorMsg = 'An error occurred while writing a file'; + + // Tries to get the file name and to concatenate it to the error message + $fileMetaData = stream_get_meta_data($fileHandle); + if (isset($fileMetaData[self::META_URI])) $errorMsg .= ': '.$fileMetaData[self::META_URI]; + + return error($errorMsg); // returns the error + } + + return success($writeResult); + } + + /** + * Removes a given file + */ + public function remove($filename) + { + // Check if the property _path represents a valid directory + $checkResult = $this->_checkPath(); + + if (isError($checkResult)) return $checkResult; // If not then return the error + + // Check filename + if (isEmptyString($filename)) return error('The given filename is not valid'); + + // remove file + if (unlink($this->_path.DIRECTORY_SEPARATOR.$filename) === true) { return success(); } else { - return error('An error occurred while writing a file', EXIT_ERROR); + return error('An error occurred while removing a file'); } } + // ------------------------------------------------------------------------------------------------------------------ + // Old public methods that work with the base64 encoding, not to be used! + /** - * Append data to a file - * - * @param array $data File content - * @return array + * Read data from the given file and encode its content to base64 */ - public function append($filename, $content) + public function readBase64($filename) { - // Check Class-Attributes - if (is_null($this->filepath)) return error('The given filepath in not valid', EXIT_ERROR); + // Open the file in read mode + $openReadResult = $this->openRead($filename); + if (isError($openReadResult)) return $openReadResult; // if an error occurred then return it - // Check method parameters - if (is_null($content)) return error('The given file content is not valid', EXIT_ERROR); - if (is_null($filename)) return error('The given filename is not valid', EXIT_ERROR); + $fileContent = ''; // to store the file content + $fileHandle = getData($openReadResult); // get the file handle - if ($this->filesystemlib->append($this->filepath, $filename, base64_decode($content)) === true) + // While the end of the file is not reached and the read does not fail + while (!feof($fileHandle) && isSuccess($readBlockResult = $this->readBlock($fileHandle))) { - return success(); - } - else - { - return error('An error occurred while appending to a file', EXIT_ERROR); + // Concatenate the content of the file + $fileContent .= getData($readBlockResult); } + + // If an error occurred while reading then return it + if (isError($readBlockResult)) return $readBlockResult; + + // Close the file handler + $closeResult = $this->close($fileHandle); + if (isError($closeResult)) return $closeResult; // if it fails then return the error + + // If everything was fine encode the file content into base64 and return it as a success + return success(base64_encode($fileContent)); + } + + /** + * Writes the given content into the given file. The content is base64 encoded + */ + public function writeBase64($filename, $content) + { + // Open the file in read and write mode + $openWriteResult = $this->openReadWrite($filename); + if (isError($openWriteResult)) return $openWriteResult; // if an error occurred then return it + + $fileHandle = getData($openWriteResult); // get the file handle + + // Writes the given base64 encoded content into to given file + $writeResult = $this->write($fileHandle, base64_decode($content)); + // If an error occurred while writing then return it + if (isError($writeResult)) return $writeResult; + + // Close the file handler + $closeResult = $this->close($fileHandle); + if (isError($closeResult)) return $closeResult; // if it fails then return the error + + // If everything was fine + return success(); + } + + /** + * Appends the given content into the given file. The content is base64 encoded + */ + public function appendBase64($filename, $content) + { + // Open the file in read and append mode + $openWriteResult = $this->openReadAppend($filename); + if (isError($openWriteResult)) return $openWriteResult; // if an error occurred then return it + + $fileHandle = getData($openWriteResult); // get the file handle + + // Writes the given base64 encoded content into to given file + $writeResult = $this->write($fileHandle, base64_decode($content)); + // If an error occurred while writing then return it + if (isError($writeResult)) return $writeResult; + + // Close the file handler + $closeResult = $this->close($fileHandle); + if (isError($closeResult)) return $closeResult; // if it fails then return the error + + // If everything was fine + return success(); } /** * Delete data from file system + * NOTE: it does not work with the base64 encoding but it has been kept for retro compatibility * * @param string $id Primary Key for DELETE * @return array */ - public function remove($filename) + public function removeBase64($filename) { // Check Class-Attributes - if (is_null($this->filepath)) return error('The given filepath in not valid', EXIT_ERROR); + if (is_null($this->_path)) return error('The given _path in not valid', EXIT_ERROR); // Check method parameters if (is_null($filename)) return error('The given filename is not valid', EXIT_ERROR); - if ($this->filesystemlib->remove($this->filepath, $filename) === true) + if (unlink($this->_path.DIRECTORY_SEPARATOR.$filename) === true) { return success(); } @@ -121,20 +246,21 @@ abstract class FS_Model extends CI_Model /** * Rename a file + * NOTE: it does not work with the base64 encoding but it has been kept for retro compatibility * * @param string $id Primary Key for DELETE * @return array */ - public function rename($filename, $newFilename) + public function renameBase64($filename, $newFilename) { // Check Class-Attributes - if (is_null($this->filepath)) return error('The given filepath in not valid', EXIT_ERROR); + if (is_null($this->_path)) return error('The given _path in not valid', EXIT_ERROR); // Check method parameters if (is_null($filename)) return error('The given filename is not valid', EXIT_ERROR); if (is_null($newFilename)) return error('The given new filename is not valid', EXIT_ERROR); - if ($this->filesystemlib->rename($this->filepath, $filename, $this->filepath, $newFilename) === true) + if (rename($this->_path.DIRECTORY_SEPARATOR.$filename, $this->_path.DIRECTORY_SEPARATOR.$newFilename) === true) { return success(); } @@ -143,4 +269,67 @@ abstract class FS_Model extends CI_Model return error('An error occurred while renaming a file', EXIT_ERROR); } } + + // ------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks if the given $this->_path is a valid directory + */ + private function _checkPath() + { + // If _path... + if (!isEmptyString($this->_path) // ...is a not empty string... + && file_exists($this->_path) && is_dir($this->_path)) // ...exists on the file system and it is a directory... + { + return success(); // return a success + } + + // If not a valid path return an error + return error('The given path is not valid: '.$this->_path); + } + + /** + * Open a file using the provided mode + * It returns a file handle + * Or write and append if the file does not exist then creates it + */ + private function _open($filename, $mode) + { + // Check if the property _path represents a valid directory + $checkResult = $this->_checkPath(); + if (isError($checkResult)) return $checkResult; // If not then return the error + + // Full file path: path + filename + $fileFullPath = $this->_path.DIRECTORY_SEPARATOR.$filename; + + // If needed then check if the file exists and really it is a file + if ($mode == self::READ_MODE && (!file_exists($fileFullPath) || !is_file($fileFullPath))) + { + return error('Trying to read a not existing file'); + } + + // If needed then check if it is possible to read from the path and the file + if ($mode == self::READ_MODE && (!is_readable($this->_path) || !is_readable($fileFullPath))) + { + return error('The given path or filename are not readable: '.$fileFullPath); + } + + // If needed then check if the path and the filename are writable + if (($mode == self::READ_WRITE_MODE || $mode == self::READ_APPEND_MODE) + && (!is_writable($this->_path) || (file_exists($fileFullPath) && !is_writable($fileFullPath)))) + { + return error('The given path or filename are not writable: '.$fileFullPath); + } + + // Open the file in read mode + $fileHandle = fopen($fileFullPath, $mode); + + // If it was a failure the return the error + if ($fileHandle === false) return error('An error occurred while opening a file in '.$mode.' mode'); + + // Otherwise return the file handle + return success($fileHandle); + } } + 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..c2bb03267 --- /dev/null +++ b/application/core/Notiz_Controller.php @@ -0,0 +1,479 @@ + 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, + 'getCountNotes' => 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 + $dms_id_arr = []; + $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); + } + + public function getCountNotes($person_id) + { + $this->NotizzuordnungModel->addSelect('COUNT(*) AS anzahl', false); + + $result = $this->NotizzuordnungModel->loadWhere( + array('person_id' => $person_id) + ); + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $anzahl = current(getData($result)); + return $this->terminateWithSuccess($anzahl->anzahl ?: 0); + } + +} \ 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..10e54780e --- /dev/null +++ b/application/core/Tag_Controller.php @@ -0,0 +1,212 @@ + 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() + { + $language = $this->_getLanguageIndex(); + $id = $this->input->get('id'); + + $this->NotizModel->addSelect( + "tbl_notiz.titel, + tbl_notiz.text, + array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $language. " as bezeichnung, + tbl_notiz.notiz_id, + tbl_notiz_typ.style, + tbl_notiz.erledigt as done, + tbl_notiz.insertamum, + tbl_notiz.updateamum, + (verfasserperson.vorname || ' ' || verfasserperson.nachname || ' ' || '(' || verfasserbenutzer.uid || ')') as verfasser, + (bearbeiterperson.vorname || ' ' || bearbeiterperson.nachname || ' ' || '(' || bearbeiterbenutzer.uid || ')') as bearbeiter + " + ); + $this->NotizModel->addJoin('public.tbl_notiz_typ', 'public.tbl_notiz.typ = public.tbl_notiz_typ.typ_kurzbz'); + + $this->NotizModel->addJoin('public.tbl_benutzer verfasserbenutzer', 'tbl_notiz.verfasser_uid = verfasserbenutzer.uid', 'LEFT'); + $this->NotizModel->addJoin('public.tbl_person verfasserperson', 'verfasserbenutzer.person_id = verfasserperson.person_id', 'LEFT'); + + $this->NotizModel->addJoin('public.tbl_benutzer bearbeiterbenutzer', 'tbl_notiz.verfasser_uid = bearbeiterbenutzer.uid', 'LEFT'); + $this->NotizModel->addJoin('public.tbl_person bearbeiterperson', 'bearbeiterbenutzer.person_id = bearbeiterperson.person_id', 'LEFT'); + + $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, + 'updateamum' => date('Y-m-d H:i:s'), + 'updatevon' => $this->_uid, + 'bearbeiter_uid' => $this->_uid, + ) + ); + $this->terminateWithSuccess($updateData); + } + public function doneTag() + { + $postData = $this->getPostJson(); + $updateData = $this->NotizModel->update(array('notiz_id' => $postData->id), + array('erledigt' => !$postData->done, + 'updateamum' => date('Y-m-d H:i:s'), + 'updatevon' => $this->_uid, + 'bearbeiter_uid' => $this->_uid, + ) + ); + + $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'); + } + + private function _getLanguageIndex() + { + $this->load->model('system/Sprache_model', 'SpracheModel'); + $this->SpracheModel->addSelect('index'); + $result = $this->SpracheModel->loadWhere(array('sprache' => getUserLanguage())); + + return hasData($result) ? getData($result)[0]->index : 1; + } + + +} \ No newline at end of file diff --git a/application/helpers/hlp_common_helper.php b/application/helpers/hlp_common_helper.php index 7b937d73d..00c0a1b93 100644 --- a/application/helpers/hlp_common_helper.php +++ b/application/helpers/hlp_common_helper.php @@ -1,24 +1,25 @@ . */ if (! defined('BASEPATH')) exit('No direct script access allowed'); +use \DateTime as DateTime; + // ------------------------------------------------------------------------ // Collection of utility functions for general purpose // ------------------------------------------------------------------------ @@ -42,15 +43,19 @@ function generateToken($length = 64) { $firstGeneratedToken = random_bytes($length); // try to generates cryptographically secure pseudo-random bytes... } - catch (Exception $e) { $firstGeneratedToken = null; } // if fails $firstGeneratedToken is set to null + catch (Exception $e) + { + // If fails $firstGeneratedToken is set to null + $firstGeneratedToken = null; + } } // For PHP >= 5.3 and < 7 and openssl is available elseif (function_exists('openssl_random_pseudo_bytes')) { $firstGeneratedToken = openssl_random_pseudo_bytes($length, $strong); // If the token generation ended with errors OR the generated token is NOT strong enough - if ($firstGeneratedToken == false || $strong == false) $firstGeneratedToken = null; // $firstGeneratedToken is set to null - } + if ($firstGeneratedToken == false || $strong == false) $firstGeneratedToken = null; // $firstGeneratedToken is set to null + } if ($firstGeneratedToken != null) // If everything was fine { @@ -107,10 +112,7 @@ function var_dump_to_error_log($parameter) function loadResource($path, $resources = null, $subdir = false) { // Place a / character at the and of the string if not present - if (strrpos($path, '/') < strlen($path) - 1) - { - $path .= '/'; - } + if (strrpos($path, '/') < strlen($path) - 1) $path .= '/'; // Loads in $tmpResources all the given resources $tmpResources = $resources; @@ -125,28 +127,36 @@ function loadResource($path, $resources = null, $subdir = false) // Loads in $tmpPaths path and eventually the subdirectories $tmpPaths = array($path); - // NOTE: Used @ to prevent ugly error messages - if (is_dir($path) && ($dirHandler = @opendir($path)) !== false) + + // If path is a directory + if (is_dir($path)) { - // Reads all file system entries present in path - while (($entry = readdir($dirHandler)) !== false) + // NOTE: Used @ to prevent ugly error messages + $dirHandler = @opendir($path); + + // Successfully opened + if ($dirHandler !== false) { - // If entry is a directory but not the current and subdirectories should be loaded - if ($subdir === true && $entry != '.' && $entry != '..' && is_dir($entry)) + // Reads all file system entries present in path + while (($entry = readdir($dirHandler)) !== false) { - $tmpPaths[] = $entry; - } - // If no resources are specified and the current file system entry is a file - if ($resources == null && is_file($path.$entry)) - { - // If the current entry is a php file store the name without extension - if ($entry != ($tmpName = str_replace('.php', '', $entry))) + // If entry is a directory but not the current and subdirectories should be loaded + if ($subdir === true && $entry != '.' && $entry != '..' && is_dir($path.$entry)) { - $tmpResources[] = $tmpName; + $tmpPaths[] = $path.$entry.'/'; + } + // If no resources are specified and the current file system entry is a file + if ($resources == null && is_file($path.$entry)) + { + // Name without php extension + $tmpName = str_replace('.php', '', $entry); + + // If the current entry is a php file store the name without extension + if ($entry != $tmpName) $tmpResources[] = $tmpName; } } + closedir($dirHandler); } - closedir($dirHandler); } // Loops through the resources @@ -156,10 +166,7 @@ function loadResource($path, $resources = null, $subdir = false) foreach ($tmpPaths as $tmpPath) { $fileName = $tmpPath.$tmpResource.'.php'; // Php extension - if (file_exists($fileName)) - { - include_once($fileName); - } + if (file_exists($fileName)) include_once($fileName); } } } @@ -349,5 +356,162 @@ 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); +} + +/** + * + */ +function findResource($path, $resource, $subdir = false, $extraDir = null) +{ + // Place a / character at the and of the string if not present + if (strrpos($path, '/') < strlen($path) - 1) $path .= '/'; + + // Loads in $tmpPaths path and eventually the subdirectories + $tmpPaths = array($path); + if (is_dir($path)) + { + // NOTE: Used @ to prevent ugly error messages + $dirHandler = @opendir($path); + + // Successfully opened + if ($dirHandler !== false) + { + // Reads all file system entries present in path + while (($entry = readdir($dirHandler)) !== false) + { + // If entry is a directory but not the current and subdirectories should be loaded + if ($subdir === true && $entry != '.' && $entry != '..' && is_dir($path.$entry)) + { + if ($extraDir == null) + { + $tmpPaths[] = $path.$entry.'/'; + } + else + { + $tmpPaths[] = $path.$entry.'/'.$extraDir.'/'; + } + } + } + closedir($dirHandler); + } + } + + // Loops through the paths + foreach ($tmpPaths as $tmpPath) + { + $fileName = $tmpPath.$resource.'.php'; // Php extension + if (file_exists($fileName)) return $fileName; + } + + 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; + } +} + + +// ------------------------------------------------------------------------ +// PHP functions that don't exist in older versions +// ------------------------------------------------------------------------ + +/** + * Returns true if the given array is sequential + */ +if (!function_exists('array_is_list')) { + function array_is_list(array $arr) + { + if ($arr === []) { + return true; + } + return array_keys($arr) === range(0, count($arr) - 1); + } +} + +// ------------------------------------------------------------------------ +// 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 5d4836d5f..1bdc57739 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -1,12 +1,20 @@ load->config('theme'); + $ci->load->model('system/Sprache_model','SpracheModel'); + $server_language = getData($ci->SpracheModel->loadWhere(['content' => true])); + $server_language = array_map(function($language){ + return ['sprache'=>$language->sprache, 'LC_Time'=>$language->locale, 'bezeichnung'=>$language->bezeichnung[$language->index-1]]; + }, $server_language); + $user_language = getUserLanguage(); + + $ci->load->config('javascript'); + $systemerror_mailto = $ci->config->item('systemerror_mailto'); + + $FHC_JS_DATA_STORAGE_OBJECT = array( + 'app_root' => APP_ROOT, + 'ci_router' => $indexPage, + 'called_path' => $calledPath, + 'called_method' => $calledMethod, + 'server_languages' => $server_language, + 'user_language' => $user_language, + 'timezone' => date_default_timezone_get(), + 'systemerror_mailto' => $systemerror_mailto, + 'theme' => [ + 'name'=>$ci->config->item('theme_name'), + 'modes'=>$ci->config->item('theme_modes'), + ] + ); + $toPrint = "\n"; $toPrint .= ''; $toPrint .= "\n\n"; @@ -139,6 +169,31 @@ function generateJSsInclude($JSs) } } +/** + * Generates tags for the javascript modules you want to include, the parameter could by a string or an array of strings + */ +function generateJSModulesInclude($JSModules) +{ + $jsInclude = ''; + + $ci =& get_instance(); + $cachetoken = '?'.$ci->config->item('fhcomplete_build_version'); + + if (isset($JSModules)) + { + $tmpJSs = is_array($JSModules) ? $JSModules : array($JSModules); + + for ($tmpJSsCounter = 0; $tmpJSsCounter < count($tmpJSs); $tmpJSsCounter++) + { + $toPrint = sprintf($jsInclude, base_url($tmpJSs[$tmpJSsCounter].$cachetoken)).PHP_EOL; + + if ($tmpJSsCounter > 0) $toPrint = "\t\t".$toPrint; + + echo $toPrint; + } + } +} + /** * Generates all the includes needed by the Addons */ @@ -146,19 +201,26 @@ function generateAddonsJSsInclude($calledFrom) { $aktive_addons = array_filter(explode(";", ACTIVE_ADDONS)); + // For each active addon foreach ($aktive_addons as $addon) { + // Build the path to the hook file $hookfile = DOC_ROOT.'addons/'.$addon.'/hooks.config.inc.php'; + + // If the hook file exists if (file_exists($hookfile)) { - $js_hooks = null; // declare variable + $js_hooks = array(); // default value - include($hookfile); // include the hook file + include($hookfile); // include the hook file where the array js_hooks should be setup - if (array_key_exists($calledFrom, $js_hooks)) + // If it contains the provided key calledFrom + if (key_exists($calledFrom, $js_hooks)) { foreach ($js_hooks[$calledFrom] as $js_file) + { generateJSsInclude('addons/'.$addon.'/'.$js_file); + } } } } @@ -174,3 +236,14 @@ function generateBackwardCompatibleJSMsIe($js) echo "\n"; } +/** + * Constructs an accessibility skipLink https://www.w3schools.com/accessibility/accessibility_skip_links.php + */ +function generateSkipLink($skipID) +{ + $toPrint = ''; + echo $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 1653c44e7..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 - $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 =& get_instance(); + + // Set the the _who property + $this->_who = 'Akte system'; // default + // It is possible to set it using the who parameter + if (!isEmptyArray($params) && isset($params['who']) && !isEmptyString($params['who'])) $this->_who = $params['who']; + + $this->_ci->load->model('crm/Akte_model', 'AkteModel'); + $this->_ci->load->model('content/DmsFS_model', 'DmsFSModel'); + + $this->_ci->load->library('DmsLib'); + } + + /** + * Writes a new file, adds a new dms entry with given akte data, + * adds a new dms version 0 for the written file, and adds Akte if dms add was successfull + * Returns success with inserted akte id or error + */ + public function add( + $person_id, $dokument_kurzbz, $titel, $mimetype, $fileHandle, // Required parameters + $bezeichnung = null, $archiv = false, $signiert = false, $stud_selfservice = false + ) + { + // add new dms entry and new dms version for the Akte, using Akte data (title, mimetype, file content as handle) + $dmsAddResult = $this->_ci->dmslib->add($titel, $mimetype, $fileHandle, self::AKTE_KATEGORIE_KURZBZ, $dokument_kurzbz, $bezeichnung); + + if (isError($dmsAddResult)) return $dmsAddResult; + + if (!hasData($dmsAddResult)) return error("Dms document could not be added"); + + $dmsAddData = getData($dmsAddResult); + + // insert the Akte + return $this->_ci->AkteModel->insert( + array( + 'person_id' => $person_id, + 'dokument_kurzbz' => $dokument_kurzbz, + 'titel' => $titel, + 'mimetype' => $mimetype, + 'bezeichnung' => $bezeichnung, + 'erstelltam' => date('Y-m-d'), + 'dms_id' => $dmsAddData->dms_id, + 'archiv' => $archiv, + 'signiert' => $signiert, + 'stud_selfservice' => $stud_selfservice, + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => $this->_who + ) + ); + } + + /** + * Writes a new file, adds a new dms version 0 for the written file, and updates Akte if dms version add was successfull + * Returns success with updated akte id or error + */ + public function update($akte_id, $titel, $mimetype, $fileHandle, $bezeichnung = null, $archiv = false, $signiert = false, $stud_selfservice = false) + { + // check if Akte with dms exists + $this->_ci->AkteModel->addSelect('dms_id'); + $akteResult = $this->_ci->AkteModel->load($akte_id); + + if (isError($akteResult)) return $akteResult; + + if (!hasData($akteResult)) return error("Akte not found"); + + $dms_id = getData($akteResult)[0]->dms_id; + + if (isEmptyString($dms_id)) return error("Akte has no dms document"); + + // if Akte with dms found, update the last dms version + $dmsUpdateResult = $this->_ci->dmslib->updateLastVersion($dms_id, $fileHandle, $titel, $mimetype, $bezeichnung); + + if (isError($dmsUpdateResult)) return $dmsUpdateResult; + + if (!hasData($dmsUpdateResult)) return error("Dms document could not be updated"); + + // update the Akte + return $this->_ci->AkteModel->update( + $akte_id, + array( + 'titel' => $titel, + 'mimetype' => $mimetype, + 'bezeichnung' => $bezeichnung, + 'erstelltam' => date('Y-m-d'), + 'dms_id' => $dms_id, + 'archiv' => $archiv, + 'signiert' => $signiert, + 'stud_selfservice' => $stud_selfservice, + 'updateamum' => date('Y-m-d H:i:s'), + 'updatevon' => $this->_who + ) + ); + } + + /** + * Gets akte data and associated dms data by akte Id + * Returns success with akte and dms data or error + */ + public function get($akte_id) + { + // get Akte data + $this->_ci->AkteModel->addSelect('person_id, dokument_kurzbz, mimetype, erstelltam, titel, bezeichnung, + gedruckt, uid, dms_id, nachgereicht, nachgereicht_am, anmerkung, + ausstellungsnation, formal_geprueft_amum, archiv, signiert, + stud_selfservice, akzeptiertamum, insertvon, insertamum, updatevon, updateamum'); + $this->_ci->AkteModel->load($akte_id); + $akteResult = $this->_ci->AkteModel->load($akte_id); + + if (isError($akteResult)) return $akteResult; + + if (!hasData($akteResult)) return error("Akte not found"); + + $resultObject = getData($akteResult)[0]; + + // set properties with same name in Akte and Dms table + $resultObject->akte_mimetype = $resultObject->mimetype; + + // get dms data + $dmsResult = $this->_ci->dmslib->getLastVersion($resultObject->dms_id); + + if (isError($dmsResult)) return $dmsResult; + + // properties to retrieve from dms + $dmsProperties = array('version', 'filename', 'mimetype', 'name', 'beschreibung', 'cis_suche', 'schlagworte', DmsLib::FILE_CONTENT_PROPERTY); + + // set dms properties + if (hasData($dmsResult)) + { + $dmsData = getData($dmsResult); + + foreach ($dmsProperties as $dmsProperty) + { + $resultObject->{$dmsProperty} = $dmsData->{$dmsProperty}; + } + } + else + { + // set null if no dms result found + foreach ($dmsProperties as $dmsProperty) + { + $resultObject->{$dmsProperty} = null; + } + } + + // return the object containing akte and dms data + return success($resultObject); + } + + /** + * Gets Akte data and associated dms data by person Id and dokument_kurzbz + * Returns success with result array with akte and dms data or error + */ + public function getByPersonIdAndDocumentType($person_id, $dokument_kurzbz) + { + // load all Akte entries for given person and dokument_kurzbz + $this->_ci->AkteModel->addSelect('akte_id'); + $akteResult = $this->_ci->AkteModel->loadWhere( + array( + 'person_id' => $person_id, + 'dokument_kurzbz' => $dokument_kurzbz + ) + ); + + if (!hasData($akteResult)) return error("Akte not found"); + + $akteData = getData($akteResult); + + $resultArr = array(); + + // for each found akte entry + foreach ($akteData as $akte) + { + // get dms and akte data from akte Id + $getAkteDmsResult = $this->get($akte->akte_id); + + if (isError($getAkteDmsResult)) return $getAkteDmsResult; + + $resultArr[] = getData($getAkteDmsResult); + } + + // return all found entries + return success($resultArr); + } + + /** + * Removes Akte by akte Id, removes all associated dms entries and versions, and deletes all associated files + * Returns success with removed version numbers or error + */ + public function remove($akte_id) + { + // get dms_id for akte + $this->_ci->AkteModel->addSelect('dms_id'); + $akteResult = $this->_ci->AkteModel->load($akte_id); + + if (isError($akteResult)) return $akteResult; + + if (!hasData($akteResult)) return error("Akte not found"); + + $dms_id = getData($akteResult)[0]->dms_id; + $error = null; + + // Start DB transaction to avoid deleting only part of the data + $this->_ci->db->trans_begin(); + + // delete Akte + $deleteResult = $this->_ci->AkteModel->delete($akte_id); + + if (isError($deleteResult)) + { + $error = $deleteResult; + } + else + { + // remove all dms entry for dms of the akte + $removeAllResult = $this->_ci->dmslib->removeAll($dms_id); + + if (isError($removeAllResult)) + $error = $removeAllResult; + } + + // Transaction complete! + $this->_ci->db->trans_complete(); + + // Check if everything went ok during the transaction + if ($this->_ci->db->trans_status() === false || isset($error)) + { + $this->_ci->db->trans_rollback(); + + // return occured error + if (isset($error)) + return $error; + else + return error("Error occured when deleting, rolled back"); + } + else + { + $this->_ci->db->trans_commit(); + + // return removed dms entry data + return $removeAllResult; + } + } +} diff --git a/application/libraries/AnrechnungLib.php b/application/libraries/AnrechnungLib.php index ee197ab05..8ee1891b5 100644 --- a/application/libraries/AnrechnungLib.php +++ b/application/libraries/AnrechnungLib.php @@ -37,19 +37,30 @@ class AnrechnungLib * @param $lv_id * @return StdClass */ - public function getAntragData($prestudent_id, $studiensemester_kurzbz, $lv_id) + public function getAntragData($prestudent_id, $studiensemester_kurzbz, $lv_id, $anrechnung_id = null) { $antrag_data = new StdClass(); // Get students UID. $uid = $this->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]) { @@ -80,14 +91,24 @@ class AnrechnungLib // Get latest ZGV $result = $this->ci->PrestudentModel->getLatestZGVBezeichnung($prestudent_id); $latest_zgv_bezeichnung = hasData($result) ? getData($result)[0]->bezeichnung : ''; - + + // Get Sum of berufliche and schulische ECTS + $result = $this->ci->LehrveranstaltungModel->getEctsSumSchulisch($uid, $prestudent_id, $lv->studiengang_kz); + $sumEctsSchulisch = getData($result)[0]->ectssumschulisch; + + $result = $this->ci->LehrveranstaltungModel->getEctsSumBeruflich($uid); + $sumEctsBeruflich = getData($result)[0]->ectssumberuflich; + // Set the given studiensemester $antrag_data->lv_id = $lv_id; $antrag_data->lv_bezeichnung = $lv->bezeichnung; $antrag_data->ects = $lv->ects; + $antrag_data->sumEctsSchulisch = $sumEctsSchulisch; + $antrag_data->sumEctsBeruflich = $sumEctsBeruflich; $antrag_data->studiensemester_kurzbz = $studiensemester_kurzbz; $antrag_data->vorname = $person->vorname; $antrag_data->nachname = $person->nachname; + $antrag_data->student_uid = $uid; $antrag_data->matrikelnr = $student->matrikelnr; $antrag_data->studiengang_kz = $studiengang->studiengang_kz; $antrag_data->stg_bezeichnung = $studiengang->bezeichnung; @@ -112,6 +133,7 @@ class AnrechnungLib $anrechnung_data = new StdClass(); + $this->ci->AnrechnungModel->addJoin('lehre.tbl_anrechnung_begruendung', 'begruendung_id'); $result = $this->ci->AnrechnungModel->load($anrechnung_id); if (isError($result)) @@ -145,16 +167,20 @@ class AnrechnungLib $anrechnung_data->prestudent_id = ''; $anrechnung_data->lehrveranstaltung = ''; $anrechnung_data->begruendung_id = ''; + $anrechnung_data->begruendung = ''; $anrechnung_data->anmerkung = ''; $anrechnung_data->dms_id = ''; $anrechnung_data->insertamum = ''; $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 = ''; + $this->ci->AnrechnungModel->addJoin('lehre.tbl_anrechnung_begruendung', 'begruendung_id'); $result = $this->ci->AnrechnungModel->loadWhere( array( 'lehrveranstaltung_id' => $lehrveranstaltung_id, @@ -261,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)) @@ -728,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. @@ -761,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 @@ -790,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) { @@ -800,12 +889,15 @@ class AnrechnungLib $anrechnung_data->prestudent_id = $anrechnung->prestudent_id; $anrechnung_data->lehrveranstaltung_id = $anrechnung->lehrveranstaltung_id; $anrechnung_data->begruendung_id = $anrechnung->begruendung_id; + $anrechnung_data->begruendung = $anrechnung->bezeichnung; $anrechnung_data->anmerkung = $anrechnung->anmerkung_student; $anrechnung_data->dms_id = $anrechnung->dms_id; $anrechnung_data->insertamum = (new DateTime($anrechnung->insertamum))->format('d.m.Y'); $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); @@ -823,4 +915,110 @@ class AnrechnungLib return $anrechnung_data; } + + /** + * If Student is a Quereinsteiger, get ECTS Summe of all angerechnete Studiensemester. + * + * @param $prestudent_id + * @param $studiengang_kz Studiengang_kz der LV + * @return int|mixed + */ + public function getQuereinsteigerEctsSumme($prestudent_id, $studiengang_kz) + { + $sumEctsQuereinsteiger = 0; + + // Check, if student is Quereinsteiger + $this->ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $result = $this->ci->PrestudentstatusModel->getFirstStatus($prestudent_id, 'Student'); + + $prestudentFirstStudentStatus = getData($result)[0]; + + // If Prestudent is not a Quereinsteiger + if ($prestudentFirstStudentStatus->ausbildungssemester == 1) + { + return $sumEctsQuereinsteiger; // return 0 + } + + $anzahlAngerechneteStudiensemester = $prestudentFirstStudentStatus->ausbildungssemester - 1; + + // If Prestudent is a Quereinsteiger + if ($prestudentFirstStudentStatus->ausbildungssemester > 1) + { + // Get the 'angerechnete Studiensemester' + $this->ci->load->model('organisations/Studiensemester_model', 'StudiensemesterModel'); + $result = $this->ci->StudiensemesterModel->getPreviousFrom( + $prestudentFirstStudentStatus->studiensemester_kurzbz, + $anzahlAngerechneteStudiensemester + ); + + // Get ECTS Summe of each 'angerechnetes Studiensemester' + foreach (getData($result) as $studiensemester) + { + $result = $this->ci->LehrveranstaltungModel->getSumQuereinstiegsECTSProSemester( + $studiengang_kz, + $studiensemester->studiensemester_kurzbz, + $anzahlAngerechneteStudiensemester--, + $prestudentFirstStudentStatus->orgform_kurzbz + ); + + if (hasData($result)) + { + $sumEctsQuereinsteiger = $sumEctsQuereinsteiger + getData($result)[0]->sum_ects; + } + } + } + return $sumEctsQuereinsteiger; // return sum of ects of all 'angerechnete Studiensemester' + } + + /** + * Get ECTS Summe of all Anrechnungen based on schulische Kenntnisse. + * + * @param $student_uid + * @return int|mixed + */ + public function getSchulischeAnrechnungenEctsSumme($student_uid) + { + $sumEctsSchule = 0; + + $result = $this->ci->LehrveranstaltungModel->getSumAngerechneteECTSByBegruendung($student_uid); + + if (hasData($result)) + { + foreach (getData($result) as $ects) + { + if ($ects->begruendung_id != 4) + { + $sumEctsSchule = $sumEctsSchule + $ects->sum; + } + } + } + + return $sumEctsSchule; + } + + /** + * Get ECTS Summe of all Anrechnungen based on berufliche Kenntnisse. + * + * @param $student_uid + * @return int + */ + public function getBeruflicheAnrechnungenEctsSumme($student_uid) + { + $sumEctsBeruflich = 0; + + $result = $this->ci->LehrveranstaltungModel->getSumAngerechneteECTSByBegruendung($student_uid); + + if (hasData($result)) + { + foreach (getData($result) as $ects) + { + if ($ects->begruendung_id == 4) + { + $sumEctsBeruflich = $ects->sum; + } + } + } + + return $sumEctsBeruflich; + } } diff --git a/application/libraries/AntragLib.php b/application/libraries/AntragLib.php new file mode 100644 index 000000000..d90a98241 --- /dev/null +++ b/application/libraries/AntragLib.php @@ -0,0 +1,2201 @@ +_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, + 'updateamum' => date('c'), + 'updatevon' => $insertvon + ]); + } + } + + 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 + ], [ + 'updateamum' => $insertam, + 'updatevon' => $insertvon + ]); + 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..355cf7c56 --- /dev/null +++ b/application/libraries/CmsLib.php @@ -0,0 +1,309 @@ +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 stdClass + */ + 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{ + //DomDocument getElementsByTagName returns a DomNodeList + $betreff = $XML->getElementsByTagName('betreff'); + //check if any betreff was found and if it is not empty + if($betreff->length > 0 && !empty($betreff->item(0)->nodeValue)) + { + //DomNodeList item() return a DomNode, property nodeValue contains the value of the node + $betreff = $betreff->item(0)->nodeValue; + + } + else + { + return error('no betreff found for the content'); + } + } + + $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, $sprache) + { + $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($sprache, $studiengang_kz, $semester, null, $sichtbar, 0, $page, $page_size, $all, $mischen); + + if (isError($news)) + return $news; + + $news = getData($news); + + 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 eae1a9ac4..c6c16a866 100644 --- a/application/libraries/DmsLib.php +++ b/application/libraries/DmsLib.php @@ -1,26 +1,483 @@ ci =& get_instance(); + $this->_ci =& get_instance(); - $this->ci->load->model('crm/Akte_model', 'AkteModel'); - $this->ci->load->model('content/Dms_model', 'DmsModel'); - $this->ci->load->model('content/DmsVersion_model', 'DmsVersionModel'); - $this->ci->load->model('content/DmsFS_model', 'DmsFSModel'); + // Set the the _who property + $this->_who = 'DMS system'; // default + // It is possible to set it using the who parameter + if (!isEmptyArray($params) && isset($params['who']) && !isEmptyString($params['who'])) $this->_who = $params['who']; + + $this->_ci->load->model('crm/Akte_model', 'AkteModel'); // deprecated, should not be used here! + $this->_ci->load->model('content/Dms_model', 'DmsModel'); + $this->_ci->load->model('content/DmsVersion_model', 'DmsVersionModel'); + $this->_ci->load->model('content/DmsFS_model', 'DmsFSModel'); } - + + // ----------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Writes a new file, adds a new dms entry and a new dms version 0 for the written file + * Returns success info of added dms entry (dms_id, version, filename) or error + */ + public function add( + $name, $mimetype, $fileHandle, // Required parameters + $kategorie_kurzbz = null, $dokument_kurzbz = null, $beschreibung = null, $cis_suche = false, $schlagworte = null + ) + { + // create unique filename, using original document name to detect file extension + $filename = $this->_getUniqueFilename($name); + + // copy file from fileHandle to dms folder + $copyFileResult = $this->_copyFile($fileHandle, $filename); + + if (isError($copyFileResult)) return $copyFileResult; + + // if file written successful, insert dms + $dmsResult = $this->_ci->DmsModel->insert( + array( + 'kategorie_kurzbz' => $kategorie_kurzbz, + 'dokument_kurzbz' => $dokument_kurzbz + ) + ); + + if (isError($dmsResult)) return $dmsResult; + + if (hasData($dmsResult)) + { + $dms_id = getData($dmsResult); + $version = 0; + + // insert dms version + $dmsVersion = array( + 'dms_id' => $dms_id, + 'version' => $version, + 'filename' => $filename, + 'mimetype' => $mimetype, + 'name' => $name, + 'beschreibung' => $beschreibung, + 'cis_suche' => $cis_suche, + 'schlagworte' => $schlagworte, + 'insertvon' => $this->_who, + 'insertamum' => date('Y-m-d H:i:s') + ); + + $dmsVersionResult = $this->_ci->DmsVersionModel->insert($dmsVersion); + + if (isError($dmsVersionResult)) return $dmsVersionResult; + + // return dms info + $resObj = new stdClass(); + $resObj->dms_id = $dms_id; + $resObj->version = $version; + $resObj->filename = $filename; + + return success($resObj); + } + else + return error("error when inserting DMS"); + } + + /** + * Writes a new file with content of fileHandle, adds a new dms version (max version number + 1) for the written file + * Returns success with info of added dms version (version, filename) or error + */ + public function addNewVersion($dms_id, $fileHandle, $name = null, $mimetype = null, $beschreibung = null, $cis_suche = false, $schlagworte = null) + { + // get the latest version + $lastVersionResult = $this->getLastVersion($dms_id); + + if (isError($lastVersionResult)) return $lastVersionResult; + + if (hasData($lastVersionResult)) + { + $lastVersion = getData($lastVersionResult); + + $originalName = isset($name) ? $name : $lastVersion->name; + + // create unique filename, using original document name to detect file extension + $filename = $this->_getUniqueFilename($originalName); + + // copy file from fileHandle to dms folder + $copyFileResult = $this->_copyFile($fileHandle, $filename); + + if (isError($copyFileResult)) return $copyFileResult; + + // insert new version + $newVersionNumber = $lastVersion->version + 1; + + // if new parameters given, use them, otherwise use parameters from last version + $newVersion = array( + 'dms_id' => $dms_id, + 'name' => $originalName, + 'filename' => $filename, + 'version' => $newVersionNumber, + 'mimetype' => isset($mimetype) ? $mimetype : $lastVersion->mimetype, + 'beschreibung' => isset($beschreibung) ? $beschreibung : $lastVersion->beschreibung, + 'cis_suche' => isset($cis_suche) ? $cis_suche : $lastVersion->cis_suche, + 'schlagworte' => isset($schlagworte) ? $schlagworte : $lastVersion->schlagworte, + 'insertvon' => $this->_who, + 'insertamum' => date('Y-m-d H:i:s') + ); + + $addVersionResult = $this->_ci->DmsVersionModel->insert($newVersion); + + if (isError($addVersionResult)) return $addVersionResult; + + // return dms info + $resObj = new stdClass(); + $resObj->version = $newVersionNumber; + $resObj->filename = $filename; + + return success($resObj); + } + else + return error("last version not found"); + } + + /** + * Updates the last version (max version number) of a dms entry + * Overwrites the file associated with this version with content read from fileHandle + * Returns success with info of added dms version (version, filename) or error + */ + public function updateLastVersion($dms_id, $fileHandle, $name = null, $mimetype = null, $beschreibung = null, $cis_suche = false, $schlagworte = null) + { + // get the latest version + $lastVersionResult = $this->getLastVersion($dms_id); + + if (isError($lastVersionResult)) return $lastVersionResult; + + if (hasData($lastVersionResult)) + { + $lastVersion = getData($lastVersionResult); + $filename = $lastVersion->filename; + + // update file in filesystem + $copyFileResult = $this->_copyFile($fileHandle, $filename); + + if (isError($copyFileResult)) return $copyFileResult; + + // if new parameters given, use them, otherwise use parameters from last version + $newVersion = array( + 'name' => isset($name) ? $name : $lastVersion->name, + 'filename' => $filename, + 'mimetype' => isset($mimetype) ? $mimetype : $lastVersion->mimetype, + 'beschreibung' => isset($beschreibung) ? $beschreibung : $lastVersion->beschreibung, + 'cis_suche' => isset($cis_suche) ? $cis_suche : $lastVersion->cis_suche, + 'schlagworte' => isset($schlagworte) ? $schlagworte : $lastVersion->schlagworte, + ); + + // update last dms version + $addVersionResult = $this->_ci->DmsVersionModel->update( + array($dms_id, $lastVersion->version), + $newVersion + ); + + if (isError($addVersionResult)) return $addVersionResult; + + // return dms info + $resObj = new stdClass(); + $resObj->version = $lastVersion->version; + $resObj->filename = $filename; + + return success($resObj); + } + else + return error("last version not found"); + } + + /** + * Gets dms version with highest number + * Returns success with dms data and fileHandle with file content or error + */ + public function getLastVersion($dms_id) + { + // get the latest version number + $this->_ci->DmsVersionModel->addSelect('version'); + $this->_ci->DmsVersionModel->addOrder('version', 'DESC'); + $this->_ci->DmsVersionModel->addOrder('insertamum', 'DESC'); + $this->_ci->DmsVersionModel->addLimit(1); + $lastDmsVersionResult = $this->_ci->DmsVersionModel->loadWhere( + array('dms_id' => $dms_id) + ); + + if (isError($lastDmsVersionResult)) return $lastDmsVersionResult; + + if (hasData($lastDmsVersionResult)) + { + $lastDmsVersionData = getData($lastDmsVersionResult)[0]; + $lastDmsVersion = $lastDmsVersionData->version; + + // call get Version with last version number + return $this->getVersion($dms_id, $lastDmsVersion); + } + else + return error("Dms last version not found"); + } + + /** + * Gets specified dms version + * Returns success with dms data and fileHandle with file content or error + */ + public function getVersion($dms_id, $version) + { + $this->_ci->DmsVersionModel->addSelect('dms_id, version, filename, mimetype, name, beschreibung, cis_suche, schlagworte'); + $dmsVersionResult = $this->_ci->DmsVersionModel->loadWhere( + array( + 'dms_id' => $dms_id, + 'version' => $version + ) + ); + + if (isError($dmsVersionResult)) return $dmsVersionResult; + + if (hasData($dmsVersionResult)) + { + $dmsVersion = getData($dmsVersionResult)[0]; + + // get file content as file pointer + $fileHandleResult = $this->_ci->DmsFSModel->openRead($dmsVersion->filename); + + if (isError($fileHandleResult)) return $fileHandleResult; + + if (hasData($fileHandleResult)) + { + $fileHandle = getData($fileHandleResult); + $dmsVersion->{self::FILE_CONTENT_PROPERTY} = $fileHandle; + + // close file pointer + $closeResult = $this->_ci->DmsFSModel->close($fileHandle); + + if (isError($closeResult)) return $closeResult; + + return success($dmsVersion); + } + else + return error("File could not be opened"); + } + else + return error("Dms version not found"); + } + + /** + * Removes dms entry and all its versions, deletes all associated files + * Returns success with removed version numbers or error + */ + public function removeAll($dms_id) + { + $versionsRemoved = array(); + + $this->_ci->DmsVersionModel->addSelect('version, filename'); + $allVersionsResult = $this->_ci->DmsVersionModel->loadWhere(array('dms_id' => $dms_id)); + + if (hasData($allVersionsResult)) + { + $allVersionsData = getData($allVersionsResult); + + $error = null; + + // Start DB transaction to avoid deleting only part of the data + $this->_ci->db->trans_begin(); + + // remove all versions of the dms Id + foreach ($allVersionsData as $version) + { + $removeVersionResult = $this->removeVersion($dms_id, $version->version); + + if (isError($removeVersionResult)) + { + $error = $removeVersionResult; + break; + } + else + $versionsRemoved[] = $version; // return removed versions + } + + // Transaction complete! + $this->_ci->db->trans_complete(); + + // Check if everything went ok during the transaction + if ($this->_ci->db->trans_status() === false || isset($error)) + { + $this->_ci->db->trans_rollback(); + + if (isset($error)) + return $error; + else + return error("Error occured when deleting, rolled back"); + } + else + { + $this->_ci->db->trans_commit(); + } + } + + return success($versionsRemoved); + } + + /** + * Removes latest version and its associated file + * Returns success with removed dms version data (dms_id, version, filename) or error + */ + public function removeLastVersion($dms_id) + { + $lastVersionNumber = 0; + // get the latest version + $lastVersionResult = $this->getLastVersion($dms_id); + + if (isError($lastVersionResult)) return $lastVersionResult; + + if (hasData($lastVersionResult)) + { + $lastVersion = getData($lastVersionResult); + $lastVersionNumber = $lastVersion->version; + } + + // call remove method for latest version + return $this->removeVersion($dms_id, $lastVersionNumber); + } + + /** + * Removes latest version and its associated file + * Returns success with removed dms version data (dms_id, version, filename) or error + */ + public function removeVersion($dms_id, $version) + { + $removeVersionResultObj = new stdClass(); + $removeVersionResultObj->dms_id = null; + $removeVersionResultObj->version = null; + $removeVersionResultObj->filename = null; + + // load dms version and check how many versions there are + $db = new DB_Model(); + + $checkDeleteResult = $db->execReadOnlyQuery( + "SELECT filename, + (SELECT count(version) + FROM campus.tbl_dms_version dv_anzahl + WHERE dv_anzahl.dms_id = dv.dms_id) AS anzahl_versionen + FROM campus.tbl_dms_version dv + WHERE dms_id=? + AND version=?", + array($dms_id, $version) + ); + + if (isError($checkDeleteResult)) return $checkDeleteResult; + + if (hasData($checkDeleteResult)) + { + $checkDeleteData = getData($checkDeleteResult)[0]; + + // delete version + $deleteVersionResult = $this->_ci->DmsVersionModel->delete(array($dms_id, $version)); + + if (isError($deleteVersionResult)) return $deleteVersionResult; + + $removeVersionResultObj->version = $version; + $removeVersionResultObj->filename = $checkDeleteData->filename; + + // delete dms too if no versions left + if ($checkDeleteData->anzahl_versionen <= 1) + { + $deleteDmsResult = $this->_ci->DmsModel->delete($dms_id); + + if (isError($deleteDmsResult)) return $deleteDmsResult; + + $removeVersionResultObj->dms_id = $dms_id; + } + + // delete file from file system + $removeResult = $this->_ci->DmsFSModel->remove($checkDeleteData->filename); + + if (isError($removeResult)) return $removeResult; + } + + return success($removeVersionResultObj); + } + + // ----------------------------------------------------------------------------------------------------------- + // Private methods + + /** + * Copies file from sourceFileHandle to destinationFilename in DMS folder + * Returns success or error on fail + */ + private function _copyFile($sourceFileHandle, $destinationFilename) + { + // get file location from file handle + $metaData = stream_get_meta_data($sourceFileHandle); + + if (isset($metaData['uri']) && !isEmptyString($metaData['uri'])) + { + // if file location determined, copy file + $source = $metaData['uri']; + + if (copy($source, DMS_PATH.$destinationFilename)) + { + return success(); + } + else + { + // error if copy returned false + return error('error occured while copying file'); + } + } + else + { + // error when source location could not be determined + return error('error occured while getting source file name'); + } + + return success($resObj); + } + + /** + * Generates unique filename, appends file extension from document name + * Returns the filename string + */ + private function _getUniqueFilename($dokname) + { + // create unique id + $uniqueFilename = uniqid(); + + // getting extension of file from document name + $fileExtension = pathinfo($dokname, PATHINFO_EXTENSION); + + // if file extension found, append it + if (!isEmptyString($fileExtension)) + $uniqueFilename .= '.'.$fileExtension; + + return $uniqueFilename; + } + + // ----------------------------------------------------------------------------------------------------------- + // Deprecated methods, not to be used + /** * Load a DMS Document. * If no version is particularly given, the latest version is loaded. @@ -33,19 +490,20 @@ class DmsLib extends FHC_Controller { if (is_numeric($dms_id)) { - $this->ci->DmsModel->addJoin('campus.tbl_dms_version', 'dms_id'); - $this->ci->DmsModel->addOrder('version', 'DESC'); - $this->ci->DmsModel->addLimit(1); - + $this->_ci->DmsModel->addJoin('campus.tbl_dms_version', 'dms_id'); + $this->_ci->DmsModel->addOrder('version', 'DESC'); + $this->_ci->DmsModel->addLimit(1); + if (!is_numeric($version)) { - return $this->ci->DmsModel->load($dms_id); + return $this->_ci->DmsModel->load($dms_id); } else { - return $this->ci->DmsModel->loadWhere(array('dms_id' => $dms_id, 'version' => $version)); + return $this->_ci->DmsModel->loadWhere(array('dms_id' => $dms_id, 'version' => $version)); } } + return error('The parameter DMS ID must be a number'); } @@ -57,34 +515,30 @@ class DmsLib extends FHC_Controller */ public function read($dms_id, $version = null) { - $result = null; + $result = error('Wrong dms_id parameter'); if (isset($dms_id)) { - $this->ci->DmsModel->addJoin('campus.tbl_dms_version', 'dms_id'); - $this->ci->DmsModel->addOrder('version', 'DESC'); - $this->ci->DmsModel->addLimit(1); + $this->_ci->DmsModel->addJoin('campus.tbl_dms_version', 'dms_id'); + $this->_ci->DmsModel->addOrder('version', 'DESC'); + $this->_ci->DmsModel->addLimit(1); if (!isset($version)) { - $result = $this->ci->DmsModel->load($dms_id); + $result = $this->_ci->DmsModel->load($dms_id); } else { - $result = $this->ci->DmsModel->loadWhere(array('dms_id' => $dms_id, 'version' => $version)); + $result = $this->_ci->DmsModel->loadWhere(array('dms_id' => $dms_id, 'version' => $version)); } - } - if (hasData($result)) - { - $resultFS = $this->ci->DmsFSModel->read($result->retval[0]->filename); - if (isSuccess($resultFS)) + // If a dms has been found + if (hasData($result)) { - $result->retval[0]->{DmsLib::FILE_CONTENT_PROPERTY} = $resultFS->retval; - } - else - { - $result = $resultFS; + $resultFS = $this->_ci->DmsFSModel->readBase64(getData($result)[0]->filename); + if (isError($resultFS)) return $resultFS; // if an error occurred return it + + $result->retval[0]->{self::FILE_CONTENT_PROPERTY} = getData($resultFS); } } @@ -101,28 +555,22 @@ class DmsLib extends FHC_Controller */ public function getAktenAcceptedDms($person_id, $dokument_kurzbz = null, $no_file = null) { - $result = $this->ci->AkteModel->getAktenAcceptedDms($person_id, $dokument_kurzbz); + $result = $this->_ci->AkteModel->getAktenAcceptedDms($person_id, $dokument_kurzbz); if (hasData($result) && $no_file == null) { - $cnt = count($result->retval); - for ($i = 0; $i < $cnt; $i++) + for ($i = 0; $i < count(getData($result)); $i++) { - $resultFS = $this->ci->DmsFSModel->read($result->retval[$i]->filename); - if (isSuccess($resultFS)) - { - $result->retval[$i]->{DmsLib::FILE_CONTENT_PROPERTY} = $resultFS->retval; - } - else - { - $result = $resultFS; - } + $resultFS = $this->_ci->DmsFSModel->readBase64(getData($result)[$i]->filename); + if (isError($resultFS)) return $resultFS; // if an error occurred return it + + $result->retval[$i]->{self::FILE_CONTENT_PROPERTY} = getData($resultFS); } } return $result; } - + /** * Uploads a document and saves it to DMS * @param $dms DMS assoc array @@ -135,32 +583,35 @@ class DmsLib extends FHC_Controller // Init upload configs $this->_loadUploadLibrary($allowed_types); - if (!$this->ci->upload->do_upload($field_name)) + if (!$this->_ci->upload->do_upload($field_name)) { - return error($this->ci->upload->display_errors()); + return error($this->_ci->upload->display_errors()); } - $upload_data = $this->ci->upload->data(); // data about the uploaded file - $filename = $upload_data['file_name']; + $upload_data = $this->_ci->upload->data(); // data about the uploaded file // Insert to DMS table - if (!$result = $this->ci->DmsModel->insert($this->ci->DmsModel->filterFields($dms))) - { - return error('Failed inserting to DMS'); - } - $upload_data['dms_id'] = $result->retval; + $insDmsResult = $this->_ci->DmsModel->insert($this->_ci->DmsModel->filterFields($dms)); + 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 - if (!$result = $this->ci->DmsVersionModel->insert( - $this->ci->DmsVersionModel->filterFields($dms, $result->retval, $filename))) - { - return error('Failed inserting DMS version'); - } + $insVersionResult = $this->_ci->DmsVersionModel->insert( + $this->_ci->DmsVersionModel->filterFields( + $dms, + $upload_data['dms_id'], + $upload_data['file_name'] + ) + ); + if (isError($insVersionResult)) return $insVersionResult; - // return result of uploaded data - return success($upload_data); // data about the uploaded file + // Return result of uploaded data + return success($upload_data); } - + /** * Download a document. * @@ -171,38 +622,31 @@ class DmsLib extends FHC_Controller */ public function download($dms_id, $filename = null, $disposition = 'inline') { - $result = $this->getFileInfo($dms_id); - - if (isError($result)) + // Retrieves info about the given dms + $fileInfoResult = $this->getFileInfo($dms_id); + if (isError($fileInfoResult)) return error(getError($fileInfoResult)); + + // If data have been found + if (hasData($fileInfoResult)) { - return error(getError($result)); + $fileObj = getData($fileInfoResult); + + // Change filename, if filename is provided + if (!isEmptyString($filename)) $fileObj->name = $filename; + + // Add file disposition if disposition has a valid value + if ($disposition == 'attachment' || $disposition == 'inline') + { + $fileObj->disposition = $disposition; + } + + return success($fileObj); } - $fileObj = getData($result); - - // Change filename, if filename is provided - if (is_string($filename)) - { - $fileObj->name = $filename; - } - - // Add file disposition - if ($disposition == 'attachment') - { - $fileObj->disposition = 'attachment'; - } - else - { - $fileObj->disposition = 'inline'; - } - - // Output file - if(!$this->outputFile($fileObj)) - { - return error('Error on file output'); - } + // If no data have been found then return an empty success + return success(); } - + /** * Get file information. * @@ -212,28 +656,28 @@ class DmsLib extends FHC_Controller */ public function getFileInfo($dms_id, $version = null) { - if (!is_numeric($dms_id)) - { - return error('Wrong parameter'); - } - - // Load file + // Checks the dms_id parameter + if (!is_numeric($dms_id)) return error('Wrong parameter'); + + // Load DMS from database $result = $this->load($dms_id, $version); + if (isError($result)) return error(getError($result)); - if (isError($result)) + // If data have been found + if (hasData($result)) { - return error(getError($result)); + // Store file information in fileObj + $fileObj = new stdClass(); + $fileObj->filename = getData($result)[0]->filename; + $fileObj->file = DMS_PATH.getData($result)[0]->filename; + $fileObj->name = getData($result)[0]->name; // original user filename + $fileObj->mimetype = getData($result)[0]->mimetype; + + return success($fileObj); } - // Store file information in fileObj - $fileObj = new StdClass(); - $fileObj->filename = getData($result)[0]->filename; - $fileObj->file = DMS_PATH. getData($result)[0]->filename; - $fileObj->name = DMS_PATH. getData($result)[0]->name; // original users filename - $fileObj->mimetype = DMS_PATH. getData($result)[0]->mimetype; - - return success($fileObj); - + // If no data have been found return an empty success + return success(); } /** @@ -253,20 +697,20 @@ class DmsLib extends FHC_Controller $result = $this->_saveFileOnInsert($dms); if (isSuccess($result)) { - $filename = $result->retval; + $filename = getData($result); if (isset($dms['dms_id']) && $dms['dms_id'] != '') { - $result = $this->ci->DmsVersionModel->insert( - $this->ci->DmsVersionModel->filterFields($dms, $dms['dms_id'], $filename) + $result = $this->_ci->DmsVersionModel->insert( + $this->_ci->DmsVersionModel->filterFields($dms, $dms['dms_id'], $filename) ); } else { - $result = $this->ci->DmsModel->insert($this->ci->DmsModel->filterFields($dms)); + $result = $this->_ci->DmsModel->insert($this->_ci->DmsModel->filterFields($dms)); if (isSuccess($result)) { - $result = $this->ci->DmsVersionModel->insert( - $this->ci->DmsVersionModel->filterFields($dms, $result->retval, $filename) + $result = $this->_ci->DmsVersionModel->insert( + $this->_ci->DmsVersionModel->filterFields($dms, getData($result), $filename) ); } } @@ -277,15 +721,15 @@ class DmsLib extends FHC_Controller $result = $this->_saveFileOnUpdate($dms); if (isSuccess($result)) { - $result = $this->ci->DmsModel->update($dms['dms_id'], $this->ci->DmsModel->filterFields($dms)); + $result = $this->_ci->DmsModel->update($dms['dms_id'], $this->_ci->DmsModel->filterFields($dms)); if (isSuccess($result)) { - $result = $this->ci->DmsVersionModel->update( + $result = $this->_ci->DmsVersionModel->update( array( $dms['dms_id'], $dms['version'] ), - $this->ci->DmsVersionModel->filterFields($dms) + $this->_ci->DmsVersionModel->filterFields($dms) ); } } @@ -308,56 +752,54 @@ class DmsLib extends FHC_Controller if (is_numeric($person_id) && is_numeric($dms_id)) { // Start DB transaction - $this->ci->db->trans_start(false); + $this->_ci->db->trans_start(false); // Get akte_id from table tbl_akte - $result = $this->ci->AkteModel->loadWhere(array('person_id' => $person_id, 'dms_id' => $dms_id)); + $result = $this->_ci->AkteModel->loadWhere(array('person_id' => $person_id, 'dms_id' => $dms_id)); if (isSuccess($result)) { // Delete all entries in tbl_akte - $cnt = count($result->retval); - for ($i = 0; $i < $cnt; $i++) + for ($i = 0; $i < count(getData($result)); $i++) { - $this->ci->AkteModel->delete($result->retval[$i]->akte_id); + $this->_ci->AkteModel->delete(getData($result)[$i]->akte_id); } // Get all filenames related to this dms - $resultFileNames = $this->ci->DmsVersionModel->loadWhere(array('dms_id' => $dms_id)); + $resultFileNames = $this->_ci->DmsVersionModel->loadWhere(array('dms_id' => $dms_id)); if (isSuccess($resultFileNames)) { // Delete from tbl_dms_version - $result = $this->ci->DmsVersionModel->delete(array('dms_id' => $dms_id)); + $result = $this->_ci->DmsVersionModel->delete(array('dms_id' => $dms_id)); if (isSuccess($result)) { // Delete from tbl_dms - $result = $this->ci->DmsModel->delete($dms_id); + $result = $this->_ci->DmsModel->delete($dms_id); } } } // Transaction complete! - $this->ci->db->trans_complete(); + $this->_ci->db->trans_complete(); // Check if everything went ok during the transaction - if ($this->ci->db->trans_status() === false || isError($result)) + if ($this->_ci->db->trans_status() === false || isError($result)) { - $this->ci->db->trans_rollback(); + $this->_ci->db->trans_rollback(); $result = error('An error occurred while performing a delete operation', EXIT_ERROR); } else { - $this->ci->db->trans_commit(); + $this->_ci->db->trans_commit(); $result = success('Dms successfully removed from DB'); } // If everything is ok if (isSuccess($result)) { - $cnt = count($resultFileNames->retval); // Remove all files related to this person and dms - for ($i = 0; $i < $cnt; $i++) + for ($i = 0; $i < count(getData($resultFileNames)); $i++) { - $this->ci->DmsFSModel->remove($resultFileNames->retval[$i]->filename); + $this->_ci->DmsFSModel->removeBase64(getData($resultFileNames)[$i]->filename); } } } @@ -376,19 +818,19 @@ class DmsLib extends FHC_Controller */ public function getAkteContent($akte_id) { - $akte = $this->ci->AkteModel->load($akte_id); + $akte = $this->_ci->AkteModel->load($akte_id); if (hasData($akte)) { - if ($akte->retval[0]->inhalt != '') + if (getData($akte)[0]->inhalt != '') { - return success(base64_decode($akte->retval[0]->inhalt)); + return success(base64_decode(getData($akte)[0]->inhalt)); } - elseif ($akte->retval[0]->dms_id != '') + elseif (getData($akte)[0]->dms_id != '') { - $dmscontent = $this->read($akte->retval[0]->dms_id); + $dmscontent = $this->read(getData($akte)[0]->dms_id); if (isSuccess($dmscontent)) { - return success(base64_decode($dmscontent->retval[0]->file_content)); + return success(base64_decode(getData($dmscontent)[0]->file_content)); } else { @@ -415,10 +857,10 @@ class DmsLib extends FHC_Controller { $filename = uniqid().'.'.pathinfo($dms['name'], PATHINFO_EXTENSION); - $result = $this->ci->DmsFSModel->write($filename, $dms['file_content']); + $result = $this->_ci->DmsFSModel->writeBase64($filename, $dms['file_content']); if (isSuccess($result)) { - $result->retval = $filename; + $result = success($filename); } return $result; @@ -439,7 +881,7 @@ class DmsLib extends FHC_Controller if (hasData($result)) { - $result = $this->ci->DmsFSModel->write($result->retval[0]->filename, $dms['file_content']); + $result = $this->_ci->DmsFSModel->writeBase64(getData($result)[0]->filename, $dms['file_content']); } } @@ -451,12 +893,13 @@ class DmsLib extends FHC_Controller */ private function _loadUploadLibrary($allowed_types) { - $config['upload_path'] = $this->UPLOAD_PATH; - $config['allowed_types'] = implode('|', $allowed_types); - $config['overwrite'] = true; - $config['file_name'] = uniqid().'.pdf'; + $config = array(); + $config['upload_path'] = DMS_PATH; + $config['allowed_types'] = implode('|', $allowed_types); + $config['overwrite'] = true; + $config['file_name'] = uniqid().'.pdf'; - $this->ci->load->library('upload', $config); - $this->ci->upload->initialize($config); + $this->_ci->load->library('upload', $config); + $this->_ci->upload->initialize($config); } } 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/DocumentExportLib.php b/application/libraries/DocumentExportLib.php new file mode 100644 index 000000000..a75047cf9 --- /dev/null +++ b/application/libraries/DocumentExportLib.php @@ -0,0 +1,719 @@ +vorlage_kurzbz, $oe_kurzbz, $version); + * $doc->setFilename($filename); + * $doc->addDataXML($data); + * $doc->addImage($imagepath, $imagename, $imagecontenttype); + * $doc->create($outputformat); + * $doc->output(true); + * $doc->close(); + * + * New: + * $xml_data = $this->documentexportlib->getDataXML($data); + * $images = [[ + * 'path' => $imagepath, + * 'name' => $imagename, + * 'contenttype' => $imagecontenttype + * ]]; + * $this->documentexportlib->showContent( + * $filename, + * $vorlage, + * $xml_data, + * $oe_kurzbz, + * $version, + * $outputformat, + * null, + * null, + * $images + * ); + */ +class DocumentExportLib +{ + private $unoconv_version; + + /** + * Constructor + */ + public function __construct() + { + // Gets CI instance + $this->ci =& get_instance(); + + // Load Phrases + $this->ci->load->library('PhrasesLib', ['document_export', null], 'documentExportPhrases'); + + // Which document converter has to be used + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) + { + // Use docsbox!! + } + else + { + 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($this->ci->documentExportPhrases->t("document_export", "error_unoconv_version")); + } + else + show_error($this->ci->documentExportPhrases->t("document_export", "error_unoconv")); + } + } + + /** + * Laedt die XML Daten fuer die XSL Transformation anhand eines Arrays + * + * @param array $data Array mit Daten + * @param string $root Bezeichnung des Root Nodes + * + * @return DOMDocument + */ + public function getDataArray($data, $root) + { + $xml_data = new DOMDocument(); + $xml_data->loadXML($this->convertArrayToXML($data, $root)); + return $xml_data; + } + + /** + * XML Daten fuer die XSL Transformation + * + * @param string $xml + * + * @return DOMDocument + */ + public function getDataXML($xml) + { + $xml_data = new DOMDocument(); + $xml_data->loadXML($xml); + return $xml_data; + } + + /** + * URL zu XML Datei die fuer XSLTransformation verwendet werden soll + * + * @param string $xml URL to XML + * @param string $params GET parameter + * + * @return stdClass + */ + public function getDataURL($xml, $params) + { + $xml_found = false; + + $aktive_addons = array_filter(array_map('trim', explode(";", ACTIVE_ADDONS))); + foreach($aktive_addons as $addon) { + $xmlfile = DOC_ROOT . 'addons/' . $addon . '/rdf/' . $xml; + if (file_exists($xmlfile)) { + $xml_found = true; + $xml_url = XML_ROOT . '../addons/' . $addon . '/rdf/' . $xml . '?' . $params; + break; + } + } + if (!$xml_found) + $xml_url = XML_ROOT . $xml . '?' . $params; + + + // Load the XML source + $xml_data = new DOMDocument; + + if (!$xml_data->load($xml_url)) + return error($this->ci->documentExportPhrases->t("document_export", "error_xml_load", [ + "url" => $xml_url, + "xml" => $xml, + "params" => $params + ])); + + return success($xml_data); + } + + /** + * Adds a XML Tag for signatur to the document + * + * @param DomDocument $xml_data + * + * @return void + */ + protected function addSignToData($xml_data) + { + $signblock = $xml_data->createElement("signed", "true"); + $xml_data->documentElement->appendChild($signblock); + } + + /** + * Adds a XML Tag for archive to the document + * + * @param DomDocument $xml_data + * + * @return void + */ + public function addArchiveToData($xml_data) + { + $archiv = $xml_data->createElement("archivierbar", "true"); + $xml_data->documentElement->appendChild($archiv); + } + + /** + * Get the contents of a Document + * + * @param stdClass $vorlage A db entry from tbl_vorlage + * @param DomDocument $xml_data + * @param string $oe_kurzbz + * @param integer|null $version (optional) + * @param string $outputformat (optional) + * @param string $sign_user (optional) Must be a valid uid + * @param string $sign_profile (optional) Signatureprofile for signing + * @param array $images (optional) Each element should have a property path, name & contenttype which are all strings + * + * @return stdClass + */ + public function getContent( + $vorlage, + $xml_data, + $oe_kurzbz, + $version = null, + $outputformat = null, + $sign_user = null, + $sign_profile = null, + $images = [] + ) { + $source_folder = getcwd(); + $temp_folder = sys_get_temp_dir() . '/fhcunoconv-' . uniqid(); + + $outputformat = $this->getDefaultOutputFormat($outputformat, $vorlage->mimetype); + + $result = $this->createAndSignContent( + $temp_folder, + $outputformat, + $vorlage, + $oe_kurzbz, + $version, + $xml_data, + $images, + $sign_user, + $sign_profile + ); + if (isError($result)) { + $this->close($temp_folder, $source_folder); + return $result; + } + $temp_filename = getData($result); + + $fsize = filesize($temp_filename); + $handle = fopen($temp_filename, 'r'); + if (!$handle) + return error($this->ci->documentExportPhrases->t("document_export", "error_file_load")); + $result = fread($handle, $fsize); + fclose($handle); + + $this->close($temp_folder, $source_folder); + + return success($result); + } + + /** + * Sets the headers and displays the Document. + * On failure the exit() function will be called + * + * @param string $filename + * @param stdClass $vorlage A db entry from tbl_vorlage + * @param DomDocument $xml_data + * @param string $oe_kurzbz + * @param integer|null $version (optional) + * @param string $outputformat (optional) + * @param string $sign_user (optional) Must be a valid uid + * @param string $sign_profile (optional) Signatureprofile for signing + * @param array $images (optional) Each element should have a property path, name & contenttype which are all strings + * + * @return void + */ + public function showContent( + $filename, + $vorlage, + $xml_data, + $oe_kurzbz, + $version = null, + $outputformat = null, + $sign_user = null, + $sign_profile = null, + $images = [] + ) { + $source_folder = getcwd(); + $temp_folder = sys_get_temp_dir() . '/fhcunoconv-' . uniqid(); + + $outputformat = $this->getDefaultOutputFormat($outputformat, $vorlage->mimetype); + + $result = $this->createAndSignContent( + $temp_folder, + $outputformat, + $vorlage, + $oe_kurzbz, + $version, + $xml_data, + $images, + $sign_user, + $sign_profile + ); + if (isError($result)) { + $this->close($temp_folder, $source_folder); + exit(getError($result)); + } + $temp_filename = getData($result); + + $fsize = filesize($temp_filename); + $handle = fopen($temp_filename, 'r'); + if (!$handle) { + $this->close($temp_folder, $source_folder); + exit($this->ci->documentExportPhrases->t("document_export", "error_file_load")); + } + + if (headers_sent()) { + $this->close($temp_folder, $source_folder); + exit($this->ci->documentExportPhrases->t("document_export", "error_headers")); + } + + switch ($outputformat) { + case 'pdf': + header('Content-type: application/pdf'); + header('Content-Disposition: attachment; filename="' . $filename . '.pdf"'); + header('Content-Length: ' . $fsize); + break; + + case 'doc': + header('Content-type: application/vnd.ms-word'); + header('Content-Disposition: attachment; filename="' . $filename . '.doc"'); + header('Content-Length: ' . $fsize); + break; + + case 'odt': + header('Content-type: application/vnd.oasis.opendocument.text'); + header('Content-Disposition: attachment; filename="' . $filename . '.odt"'); + header('Content-Length: ' . $fsize); + break; + default: + $this->close($temp_folder, $source_folder); + exit($this->ci->documentExportPhrases->t("document_export", "error_outputformat_missing")); + } + + while (!feof($handle)) { + echo fread($handle, 8192); + } + fclose($handle); + + $this->close($temp_folder, $source_folder); + } + + /** + * Helper function for getContent and showContent. + * Creates the temp folder and calls create and sign functions. + * + * @param string $temp_folder + * @param string $outputformat + * @param stdClass $vorlage + * @param string $oe_kurzbz + * @param integer $version + * @param DomDocument $xml_data + * @param array $images Each element should have a property path, name and contenttype which are all strings + * @param string $sign_user Must be a valid uid + * @param string $sign_profile Signatureprofile for signing + * + * @return stdClass + */ + protected function createAndSignContent( + $temp_folder, + $outputformat, + $vorlage, + $oe_kurzbz, + $version, + $xml_data, + $images, + $sign_user, + $sign_profile + ) { + mkdir($temp_folder); + chdir($temp_folder); + + $this->ci->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); + + $result = $this->ci->VorlagestudiengangModel->getCurrent($vorlage->vorlage_kurzbz, $oe_kurzbz, $version); + if (isError($result)) + return $result; + if (!hasData($result)) + return error($this->ci->documentExportPhrases->t("document_export", "error_template_missing")); + $vorlage_stg = current(getData($result)); + foreach ($vorlage_stg as $k => $v) + $vorlage->$k = $v; + + if ($sign_user) + { + $this->addSignToData($xml_data); + } + + $result = $this->create($temp_folder, $outputformat, $vorlage, $xml_data, $images); + if (isError($result)) + return $result; + + $temp_filename = getData($result); + + if ($sign_user) + { + $result = $this->sign($temp_folder, $temp_filename, $outputformat, $sign_user, $sign_profile); + if (isError($result)) + return $result; + + $temp_filename = getData($result); + } + + return success($temp_filename); + } + + /** + * Helper function for createAndSignContent. + * Creates the files in the temp folder. + * + * @param string $temp_folder + * @param string $outputformat + * @param stdClass $vorlage + * @param DomDocument $xml_data + * @param array $images Each element should have a property path, name and contenttype which are all strings + * + * @return stdClass + */ + protected function create($temp_folder, $outputformat, $vorlage, $xml_data, $images) + { + $content_xsl = new DOMDocument(); + if (!$content_xsl->loadXML($vorlage->text)) + return error($this->ci->documentExportPhrases->t("document_export", "error_xsl_load")); + + $proc = new XSLTProcessor(); + $proc->importStyleSheet($content_xsl); + + $contentbuffer = $proc->transformToXml($xml_data); + + file_put_contents($temp_folder . '/content.xml', $contentbuffer); + + if ($xml_data->firstChild->tagName == 'error') + return error($xml_data->firstChild->textContent); + + $styles_xsl = null; + // styles.xml erstellen + if ($vorlage->style) { + $styles_xsl = new DOMDocument(); + if (!$styles_xsl->loadXML($vorlage->style)) + return error($this->ci->documentExportPhrases->t("document_export", "error_styles_load")); + $style_proc = new XSLTProcessor(); + $style_proc->importStyleSheet($styles_xsl); + + $stylesbuffer = $style_proc->transformToXml($xml_data); + + file_put_contents($temp_folder . '/styles.xml', $stylesbuffer); + } + + // Template holen + $vorlage_found = false; + $vorlage_filename = $vorlage->vorlage_kurzbz . ($vorlage->mimetype == 'application/vnd.oasis.opendocument.spreadsheet' ? '.ods' : '.odt'); + + $aktive_addons = array_filter(array_map('trim', explode(";", ACTIVE_ADDONS))); + foreach($aktive_addons as $addon) { + $zipfile = DOC_ROOT . 'addons/' . $addon . '/system/vorlage_zip/' . $vorlage_filename; + + if (file_exists($zipfile)) { + $vorlage_found = true; + break; + } + } + if (!$vorlage_found) + $zipfile = DOC_ROOT . 'system/vorlage_zip/' . $vorlage_filename; + + $tempname_zip = $temp_folder . '/out.zip'; + + if (!copy($zipfile, $tempname_zip)) + return error($this->ci->documentExportPhrases->t("document_export", "error_file_copy")); + + exec("zip $tempname_zip content.xml"); + if (!is_null($styles_xsl)) + exec("zip $tempname_zip styles.xml"); + + // bilder hinzufuegen + if (count($images) > 0) + { + // Unterordner fuer die Bilder erstellen + mkdir('Pictures'); + + // Manifest Datei holen + exec('unzip ' . $tempname_zip . ' META-INF/manifest.xml'); + + // Bild zur Manifest Datei hinzufuegen + $manifest = file_get_contents('META-INF/manifest.xml'); + + $manifest_xml = new DOMDocument; + if (!$manifest_xml->loadXML($manifest)) + return error($this->ci->documentExportPhrases->t("document_export", "error_manifest")); + + //root-node holen + $root = $manifest_xml->getElementsByTagName('manifest')->item(0); + + foreach ($images as $bild) { + copy($bild['path'], 'Pictures/' . $bild['name']); + + //Neues Element unterhalb des Root Nodes anlegen + $node = $manifest_xml->createElement("manifest:file-entry"); + $node->setAttribute("manifest:full-path", 'Pictures/' . $bild['name']); + $node->setAttribute("manifest:media-type", $bild['contenttype']); + $root->appendChild($node); + } + + $out = $manifest_xml->saveXML(); + + //geaenderte Manifest Datei speichern und wieder ins Zip packen + file_put_contents('META-INF/manifest.xml', $out); + exec('zip ' . $tempname_zip . ' META-INF/*'); + + // Bilder zum ZIP-File hinzufuegen + exec('zip ' . $tempname_zip . ' Pictures/*'); + } + + clearstatcache(); + + switch ($outputformat) { + case 'pdf': + case 'doc': + $ret = 0; + $temp_filename = $temp_folder . '/out.' . $outputformat; + + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) { + // Use docsbox + + $this->ci->load->library("DocsboxLib"); + + $docboxlib = get_class($this->ci->docboxlib); + + $ret = $docboxlib::convert($tempname_zip, $temp_filename, $outputformat); + } else { + // Use unoconv + + // Unoconv Version 0.6 hat eine Bug wodurch die Berechtigungen des PDF/Doc nicht korrekt gesetzt + // werden. Deshalb wird dies hier speziell behandelt. + // Die 2. Variante hat den Vorteil dass hier eine bessere Fehlerbehandlung moeglich ist + if ($this->unoconv_version == '0.6') + $command = 'unoconv -e IsSkipEmptyPages=false -f ' . $outputformat . ' %2$s > %1$s'; + else + $command = 'unoconv -e IsSkipEmptyPages=false -f ' . $outputformat . ' --output %s %s 2>&1'; + + $command = sprintf($command, $temp_filename, $tempname_zip); + + exec($command, $out, $ret); + } + + if ($ret) + return error($this->ci->documentExportPhrases->t("document_export", "error_conv_timeout")); + break; + case 'odt': + default: + $temp_filename = $tempname_zip; + } + + return success($temp_filename); + } + + /** + * Helper function for createAndSignContent. + * Signs the main file in the temp folder. + * + * @param string $temp_folder + * @param string $temp_filename + * @param string $outputformat + * @param string $user Must be a valid uid + * @param string $profile Signatureprofile for signing + * + * @return stdClass + */ + protected function sign($temp_folder, $temp_filename, $outputformat, $user, $profile) + { + if ($outputformat != 'pdf') + return error($this->ci->documentExportPhrases->t("document_export", "error_sign_pdf")); + + // Load the File + $file_data = file_get_contents($temp_filename); + + $data = new stdClass(); + $data->document = base64_encode($file_data); + + // Signatur Profil + if (!is_null($profile)) + $data->profile = $profile; + else + $data->profile = SIGNATUR_DEFAULT_PROFILE; + + // Username des Endusers der die Signatur angefordert hat + $data->user = $user; + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, SIGNATUR_URL . '/' . SIGNATUR_SIGN_API); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 7); + curl_setopt($ch, CURLOPT_USERAGENT, "FH-Complete"); + + // SSL Zertifikatsprüfung deaktivieren + // Besser ist es das Zertifikat am Server zu installieren! + //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + + $data_string = json_encode($data, JSON_FORCE_OBJECT); + + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + 'Content-Length:' . mb_strlen($data_string), + 'Authorization: Basic ' . base64_encode(SIGNATUR_USER . ":" . SIGNATUR_PASSWORD) + ]); + + $result = curl_exec($ch); + if (curl_errno($ch)) { + curl_close($ch); + return error($this->ci->documentExportPhrases->t("document_export", "error_sign_timeout")); + } + curl_close($ch); + $resultdata = json_decode($result); + + // If it is success + if (isset($resultdata->error) && $resultdata->error == 0) { + $signed_filename = $temp_folder . '/signed.pdf'; + file_put_contents($signed_filename, base64_decode($resultdata->retval)); + return success($signed_filename); + } + + // otherwise if it is an error + return error($resultdata->retval ?? $this->ci->documentExportPhrases->t("global", "unknown_error", ["error" => $result])); + } + + /** + * Deletes all files in the $temp_folder and changes back to the source_folder + * + * @param string $temp_folder + * @param string $source_folder + * + * @return void + */ + protected function close($temp_folder, $source_folder) + { + $files = glob($temp_folder . '/*'); // get all file names + foreach ($files as $file) + if (is_file($file)) + unlink($file); + + chdir($source_folder); + rmdir($temp_folder); + } + + /** + * Convert an array to XML + * + * @param array $data + * @param string $root + * @param SimpleXMLElement $xml_data + * + * @return string|boolean + */ + private function convertArrayToXML($data, $root = null, $xml_data = null) + { + $_xml_data = $xml_data; + if ($_xml_data === null) + $_xml_data = new SimpleXMLElement($root !== null ? '<' . $root . ' />' : ''); + + foreach ($data as $key => $value) { + if (is_array($value)) { + if (is_numeric($key)) { + $key = 'item' . $key; // dealing with <0/>.. issues + $this->convertArrayToXML($value, null, $_xml_data); + } else { + $subnode = $_xml_data->addChild($key); + $this->convertArrayToXML($value, null, $subnode); + } + } else { + // Remove UTF8 Control Characters (breaking XML) + $value = preg_replace('/[\x00-\x1F\x7F]/u', '', $value); + $_xml_data->addChild((string)$key, htmlspecialchars("$value")); + } + } + + return $_xml_data->asXML(); + } + + /** + * Get default outputformat from mimetype if its not set + * + * @param string $outputformat + * @param string $mimetype + * + * @return string + */ + private function getDefaultOutputFormat($outputformat, $mimetype) + { + if ($outputformat) + return $outputformat; + + if ($mimetype == 'application/vnd.oasis.opendocument.spreadsheet') + return 'ods'; + if ($mimetype == 'application/vnd.oasis.opendocument.text') + return 'odt'; + + return 'pdf'; + } +} 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/ExtensionsLib.php b/application/libraries/ExtensionsLib.php index df9a1c29a..873d35a14 100644 --- a/application/libraries/ExtensionsLib.php +++ b/application/libraries/ExtensionsLib.php @@ -1,4 +1,20 @@ . + */ if (! defined('BASEPATH')) exit('No direct script access allowed'); @@ -28,7 +44,7 @@ class ExtensionsLib // Directories that are part of the extension archive private $SOFTLINK_TARGET_DIRECTORIES = array( - APPPATH => array('config', 'controllers', 'helpers', 'hooks', 'libraries', 'models', 'views', 'widgets'), + APPPATH => array('config', 'components', 'controllers', 'helpers', 'hooks', 'libraries', 'models', 'views', 'widgets'), DOC_ROOT => array('public') ); @@ -195,16 +211,15 @@ class ExtensionsLib // Select all the version of this extension $this->_ci->ExtensionsModel->addSelect('extension_id'); $result = $this->_ci->ExtensionsModel->loadWhere(array('name' => $extensionName)); - if (hasData($result)) // if something was found + // If something was found + if (hasData($result)) { - foreach ($result->retval as $extension) // loops on them + // Loops on them + foreach ($result->retval as $extension) { // Remove them all $result = $this->_ci->ExtensionsModel->delete($extension->extension_id); - if (isSuccess($result)) - { - $delExtension = true; - } + if (isSuccess($result)) $delExtension = true; } } } @@ -446,9 +461,13 @@ class ExtensionsLib // If no errors occurred if ($extensionJson != null) { + // Default value + $fhcomplete_version = 0; + require_once('version.php'); // get the core version + // Checks if the required core version of the extension is the same of this system - if (isset($extensionJson->core_version) && $extensionJson->core_version == $fhcomplete_version) + if (isset($extensionJson->core_version) && version_compare($extensionJson->core_version, $fhcomplete_version,'<=')) { $this->_printMessage('Required core version: '.$extensionJson->core_version); $this->_printMessage('Current core version: '.$fhcomplete_version); @@ -604,6 +623,7 @@ class ExtensionsLib $files = glob($pkgSQLsPath.'/'.$sqlDir.'/*'.ExtensionsLib::SQL_FILE_EXTENSION); // If found + $files = glob($pkgSQLsPath.'/'.$sqlDir.'/*'.ExtensionsLib::SQL_FILE_EXTENSION); if ($files != false) { // Loads every sql files @@ -615,8 +635,10 @@ class ExtensionsLib $this->_printMessage($sql); // Try to execute that - $result = @$this->_ci->ExtensionsModel->executeQuery($sql); - if (!isSuccess($result)) + $resultQuery = @$this->_ci->ExtensionsModel->executeQuery($sql); + + // If _not_ a success + if (!isSuccess($resultQuery)) { $this->_errorOccurred = true; $this->_printFailure(' error occurred while executing the query'); @@ -626,7 +648,7 @@ class ExtensionsLib else { $this->_printMessage('Query result:'); - var_dump($result->retval); // KEEP IT!!! + var_dump(getData($resultQuery)); // KEEP IT!!! $this->_ci->eprintflib->printEOL(); } } diff --git a/application/libraries/FilesystemLib.php b/application/libraries/FilesystemLib.php deleted file mode 100644 index c940acede..000000000 --- a/application/libraries/FilesystemLib.php +++ /dev/null @@ -1,142 +0,0 @@ -checkParameters($filepath, $filename)) - { - $resource = $filepath.DIRECTORY_SEPARATOR.$filename; - if (file_exists($resource) && $fileHandle = fopen($resource, 'r')) - { - $result = ''; - while (!feof($fileHandle)) - { - $result .= fread($fileHandle, 8192); - } - fclose($fileHandle); - } - } - - return $result; - } - - /** - * write - */ - public function write($filepath, $filename, $content) - { - $result = null; - - if ($this->checkParameters($filepath, $filename) && isset($content)) - { - $resource = $filepath.DIRECTORY_SEPARATOR.$filename; - if (is_writable($filepath) && $fileHandle = fopen($resource, 'w')) - { - if (fwrite($fileHandle, $content) !== false) - { - $result = true; - } - fclose($fileHandle); - } - } - - return $result; - } - - /** - * append - */ - public function append($filepath, $filename, $content) - { - $result = null; - - if ($this->checkParameters($filepath, $filename) && isset($content)) - { - $resource = $filepath.DIRECTORY_SEPARATOR.$filename; - if (is_writable($resource) && $fileHandle = fopen($resource, 'a')) - { - if (fwrite($fileHandle, $content) !== false) - { - $result = true; - } - fclose($fileHandle); - } - } - - return $result; - } - - /** - * remove - */ - public function remove($filepath, $filename) - { - $result = null; - - if ($this->checkParameters($filepath, $filename)) - { - if (is_writable($filepath)) - { - $resource = $filepath.DIRECTORY_SEPARATOR.$filename; - $result = unlink($resource); - } - } - - return $result; - } - - /** - * rename - */ - public function rename($filepath, $filename, $newFilepath, $newFilename) - { - $result = null; - - if ($this->checkParameters($filepath, $filename) && $this->checkParameters($newFilepath, $newFilename)) - { - $resource = $filepath.DIRECTORY_SEPARATOR.$filename; - if (is_writable($filepath) && is_writable($newFilepath) && file_exists($resource)) - { - $destination = $newFilepath.DIRECTORY_SEPARATOR.$newFilename; - $result = rename($resource, $destination); - } - } - - return $result; - } -} diff --git a/application/libraries/FilterCmptLib.php b/application/libraries/FilterCmptLib.php new file mode 100644 index 000000000..272899de6 --- /dev/null +++ b/application/libraries/FilterCmptLib.php @@ -0,0 +1,1176 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use \stdClass as stdClass; + +/** + * Filter component logic + */ +class FilterCmptLib +{ + // FilterCmpt session name + const SESSION_NAME = 'FHC_FILTER_COMPONENT'; + + // Session elements + const SESSION_FILTER_NAME = 'filterName'; + const SESSION_FIELDS = 'fields'; + const SESSION_SELECTED_FIELDS = 'selectedFields'; + const SESSION_FILTERS = 'filters'; + const SESSION_METADATA = 'datasetMetadata'; + const SESSION_ROW_NUMBER = 'rowNumber'; + const SESSION_TIMEOUT = 'sessionTimeout'; + const SESSION_ENCRYPTED_COLUMNS = 'encryptedColumns'; + + // Session dataset elements + const SESSION_DATASET = 'dataset'; + const SESSION_DATASET_RELOAD = 'reloadDataset'; + + const SESSION_SIDE_MENU = 'sideMenu'; + + // Default session timeout + const SESSION_DEFAULT_TIMEOUT = 30; + + // Alias for the dynamic table used to retrieve the dataset + const DATASET_TABLE_ALIAS = 'datasetFilterTable'; + + // Parameters names... + // ...to identify a single filter component in the session + const FHC_CONTROLLER_ID = 'fhc_controller_id'; + + // ...to identify a single filter component in the DB + const FILTER_ID = 'filter_id'; + const APP = 'app'; + const DATASET_NAME = 'datasetName'; + const FILTER_KURZBZ = 'filterKurzbz'; + const DATASET_RELOAD = 'reloadDataset'; + + // ...to specify permissions that are needed to use this FilterCmpt + const REQUIRED_PERMISSIONS = 'requiredPermissions'; + const ENCRYPTED_COLUMNS = 'encryptedColumns'; + + // ...stament to retrieve the dataset + const QUERY = 'query'; + + // Filter operations values + const OP_EQUAL = 'equal'; + const OP_NOT_EQUAL = 'nequal'; + const OP_GREATER_THAN = 'gt'; + const OP_LESS_THAN = 'lt'; + const OP_IS_TRUE = 'true'; + const OP_IS_FALSE = 'false'; + const OP_CONTAINS = 'contains'; + const OP_NOT_CONTAINS = 'ncontains'; + const OP_SET = 'set'; + const OP_NOT_SET = 'nset'; + + // Filter options values + const OPT_MINUTES = 'minutes'; + const OPT_HOURS = 'hours'; + const OPT_DAYS = 'days'; + const OPT_MONTHS = 'months'; + + const FILTER_PHRASES_CATEGORY = 'FilterWidget'; // The category used to store phrases for the FilterCmpt + + const FILTER_UNIQUE_ID = 'filterUniqueId'; // Filter page parameter name + + const PERMISSION_FILTER_METHOD = 'FilterCmpt'; // Name for fake method to be checked by the PermissionLib + const PERMISSION_TYPE = 'r'; + + private $_ci; // Code igniter instance + + private $_filterUniqueId; // Unique id for this filter component + private $_filterType; // + private $_filterId; // + + private $_app; + private $_datasetName; + private $_filterKurzbz; + private $_query; + private $_requiredPermissions; + private $_encryptedColumns; + private $_reloadDataset; + private $_sessionTimeout; + + /** + * Gets the CI instance and loads message helper + */ + public function __construct($params) + { + $this->_ci =& get_instance(); // get code igniter instance + + // Set parameters + $this->_setParameters($params); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Wrapper method to the session helper funtions to retrieve the whole session for this filter + */ + public function getSession() + { + return getSessionElement(self::SESSION_NAME, $this->_filterUniqueId); + } + + /** + * Contains all the logic used to load all the data needed to the FilterCmpt + */ + public function start() + { + // + if (!$this->_checkJSParameters()) return; + + $filterCmptArray = array(); // default value + + // + $filePath = findResource(APPPATH.'components/filters/', $this->_filterType, true); + if (!isEmptyString($filePath)) + { + // Gets the filter configuration from the file system + require_once($filePath); + } + else + { + $filePath = findResource(APPPATH.'components/extensions/', $this->_filterType, true, 'filters'); + if (!isEmptyString($filePath)) require_once($filePath); + } + + // + if (!isset($filterCmptArray) && isEmptyArray($filterCmptArray)) + { + $this->_setSession(error('Component definition file '.$this->_filterType.' not found')); + return; + } + + // + if (!$this->_checkPHPParameters($filterCmptArray)) return; + + // + $this->_initFilterCmpt($filterCmptArray); + + // + if (!$this->_isAllowed()) return; + + // Looks for expired filter components in session and drops them + $this->_dropExpiredFilterCmpts(); + + // Read the all session for this filter component + $session = $this->getSession(); + + // If session is NOT empty -> a filter was already loaded + if ($session != null) + { + // Retrieve the filterId stored in the session + $sessionFilterId = $this->_getSessionElement(FilterCmptLib::FILTER_ID); + + // If the filter loaded in session is NOT the same that is being requested then empty the session + if ($this->_filterId != $sessionFilterId) + { + $this->_setSession(null); + $session = null; + } + else // else if the filter loaded in session is the same that is being requested + { + // Get SESSION_DATASET_RELOAD from the session + $sessionReloadDataset = $this->_getSessionElement(FilterCmptLib::SESSION_DATASET_RELOAD); + + // if Filter changed or reload is forced by parameter then reload the Dataset + if ($this->_reloadDataset === true || $sessionReloadDataset === true) + { + // Set as false to stop changing the dataset + $this->_setSessionElement(FilterCmptLib::SESSION_DATASET_RELOAD, false); + + // Generate dataset query using filters from the session + $datasetQuery = $this->_generateDatasetQuery( + $this->_query, + $this->_getSessionElement(FilterCmptLib::SESSION_FILTERS) + ); + + // Then retrieve dataset from DB + $dataset = $this->_getDataset($datasetQuery); + + // Save changes into session if data are valid + if (!isError($dataset)) + { + // Set the new dataset and its attributes in the session + $this->_setSessionElement(FilterCmptLib::SESSION_METADATA, $this->_ci->FiltersModel->getExecutedQueryMetaData()); + $this->_setSessionElement(FilterCmptLib::SESSION_ROW_NUMBER, count($dataset->retval)); + $this->_setSessionElement(FilterCmptLib::SESSION_DATASET, $dataset->retval); + } + } + } + } + + // If the session is empty -> first time that this filter is loaded + if ($session == null) + { + // Load filter definition data from DB + $definition = $this->_loadDefinition( + $this->_filterId, + $this->_app, + $this->_datasetName, + $this->_filterKurzbz + ); + + // Checks and parse json present into the definition + $parsedFilterJson = $this->_parseFilterJson($definition); + if ($parsedFilterJson != null) // if the json is valid + { + // Generate dataset query + $datasetQuery = $this->_generateDatasetQuery($this->_query, $parsedFilterJson->filters); + + // Then retrieve dataset from DB + $dataset = $this->_getDataset($datasetQuery); + + // Try to load the name of the filter using the PhrasesLib + $filterName = $this->_getFilterName($parsedFilterJson); + + // Save changes into session if data are valid + if (!isError($dataset)) + { + // Stores an array that contains all the data useful for + $this->_setSession( + array( + FilterCmptLib::FILTER_ID => $this->_filterId, // the current filter id + FilterCmptLib::APP => $this->_app, // the current app parameter + FilterCmptLib::DATASET_NAME => $this->_datasetName, // the carrent dataset name + FilterCmptLib::SESSION_FILTER_NAME => $filterName, // the current filter name + FilterCmptLib::SESSION_FIELDS => $this->_ci->FiltersModel->getExecutedQueryListFields(), // all the fields of the dataset + FilterCmptLib::SESSION_SELECTED_FIELDS => $this->_getColumnsNames($parsedFilterJson->columns), // all the selected fields + FilterCmptLib::SESSION_FILTERS => $parsedFilterJson->filters, // all the filters used to filter the dataset + FilterCmptLib::SESSION_METADATA => $this->_ci->FiltersModel->getExecutedQueryMetaData(), // the metadata of the dataset + FilterCmptLib::SESSION_ROW_NUMBER => count($dataset->retval), // the number of loaded rows by this filter + FilterCmptLib::SESSION_DATASET => $dataset->retval, // the entire dataset + FilterCmptLib::SESSION_DATASET_RELOAD => false, // if the dataset must be reloaded, not needed the first time + FilterCmptLib::SESSION_SIDE_MENU => $this->_generateFilterMenu($this->_app, $this->_datasetName) + ) + ); + } + } + } + + // NOTE: latest operations to be performed in the session to be shure that they are always present + // To be always stored in the session, otherwise is not possible to load data from Filters controller + $this->_setSessionElement(FilterCmptLib::REQUIRED_PERMISSIONS, $this->_requiredPermissions); + // Renew or set the session expiring time + $this->_setSessionElement(FilterCmptLib::SESSION_TIMEOUT, strtotime('+'.$this->_sessionTimeout.' minutes', time())); + } + + /** + * Add a filter (SQL where clause) to be applied to the current filter + */ + public function addFilterField($filterField) + { + $addFilterField = false; + + // Checks the parameter filter + if (!isEmptyString($filterField)) + { + // Retrieves all the used fields by the current filter + $fields = $this->_getSessionElement(self::SESSION_FIELDS); + // Retrieves the applied filters by the current filter + $filters = $this->_getSessionElement(self::SESSION_FILTERS); + + // Checks that the given applied filter is present in the list of all the used fields by the current filter + if (in_array($filterField, $fields)) + { + // Search in what position the given applied filter is + $pos = $this->_searchFilterByName($filters, $filterField); + if ($pos === false) // If NOT found then add it + { + // New filter definition + $filterDefinition = new stdClass(); + // Sets filter definition required properties + $filterDefinition->name = $filterField; + // Sets filter definition optional properties + $filterDefinition->operation = null; + $filterDefinition->condition = null; + $filterDefinition->option = null; + // Place the new applied filter at the end of the applied filters list + array_push($filters, $filterDefinition); + } + + $this->_setSessionElement(self::SESSION_FILTERS, $filters); // write changes into the session + + $addFilterField = true; + } + } + + return $addFilterField; + } + + /** + * Remove an applied filter (SQL where condition) from the current filter + */ + public function removeFilterField($filterField) + { + $removeFilterField = false; + + // Checks the parameter filterField + if (!isEmptyString($filterField)) + { + // Retrieves all the used fields by the current filter + $fields = $this->_getSessionElement(self::SESSION_FIELDS); + // Retrieves the applied filters by the current filter + $filters = $this->_getSessionElement(self::SESSION_FILTERS); + + // Checks that the given applied filter is present in the list of all the used fields by the current filter + if (in_array($filterField, $fields)) + { + // Search in what position the given applied filter is + $pos = $this->_searchFilterByName($filters, $filterField); + if ($pos !== false) // If found + { + array_splice($filters, $pos, 1); // Then remove it and shift the rest of elements by one if needed + } + + // Write changes into the session + $this->_setSessionElement(self::SESSION_FILTERS, $filters); + $this->_setSessionElement(self::SESSION_DATASET_RELOAD, true); // the dataset must be reloaded + + $removeFilterField = true; + } + } + + return $removeFilterField; + } + + /** + * Apply all the applied filters (SQL where conditions) to the current filter + */ + public function applyFilterFields($filterFields) + { + $applyFilters = false; + + // Check if the parameter is an array and it is not empty + if (!isEmptyArray($filterFields)) + { + $filters = array(); + + // Check if the parameter is fine + $fine = true; + foreach ($filterFields as $filterField) + { + // If not an empty array + if (!isEmptyArray($filterField)) + { + // + if (isset($filterField['name']) && isset($filterField['operation']) && isset($filterField['condition']) + && !isEmptyString($filterField['name']) && !isEmptyString($filterField['operation']) + && !isEmptyString((string)$filterField['condition'])) + { + // Fine + $filter = new stdClass(); + $filter->name = $filterField['name']; + $filter->operation = $filterField['operation']; + $filter->condition = $filterField['condition']; + if (isset($filterField['option']) && !isEmptyString($filterField['option'])) + { + $filter->option = $filterField['option']; + } + else + { + $filter->option = null; + } + $filters[] = $filter; + } + else // otherwise is not fine and stop checking + { + $fine = false; + break; + } + } + else // + { + $fine = false; + break; + } + } + + // + if ($fine) + { + // Write changes into the session + $this->_setSessionElement(self::SESSION_FILTERS, $filters); + $this->_setSessionElement(self::SESSION_DATASET_RELOAD, true); // the dataset must be reloaded + + $applyFilters = true; + } + } + + return $applyFilters; + } + + /** + * Reloads dataset by setting session variable to true + */ + public function reloadDataset() + { + $this->_setSessionElement(self::SESSION_DATASET_RELOAD, true); + } + + /** + * Save the current filter as a custom filter for this user with the given description + */ + public function saveCustomFilter($customFilterDescription) + { + $saveCustomFilter = false; // by default returns a failure + + // Checks parameter customFilterDescription if not valid stop the execution + if (isEmptyString($customFilterDescription)) return $saveCustomFilter; + + $this->_ci->load->model('system/Filters_model', 'FiltersModel'); // to load the filter definitions + $this->_ci->FiltersModel->resetQuery(); // reset any previous built query + + // person_id of the authenticated user + $authPersonId = getAuthPersonId(); + // Postgres array for the description + $descPGArray = str_replace('%desc%', $customFilterDescription, '{"%desc%", "%desc%", "%desc%", "%desc%"}'); + + // Loads the definition to check if is already present in the DB + $definition = $this->_ci->FiltersModel->loadWhere(array( + 'app' => $this->_getSessionElement(self::APP), + 'dataset_name' => $this->_getSessionElement(self::DATASET_NAME), + 'description' => $descPGArray, + 'person_id' => $authPersonId + )); + + // New definition to be json encoded + $jsonDeifinition = new stdClass(); + $jsonDeifinition->name = $customFilterDescription; // name of the filter + + // Generates the "column" property + $jsonDeifinition->columns = array(); + $selectedFields = $this->_getSessionElement(self::SESSION_SELECTED_FIELDS); // retrieved the selected fields + for ($i = 0; $i < count($selectedFields); $i++) + { + // Each element is an object with a property called "name" + $jsonDeifinition->columns[$i] = new stdClass(); + $jsonDeifinition->columns[$i]->name = $selectedFields[$i]; + } + + // List of applied filters + $jsonDeifinition->filters = $this->_getSessionElement(self::SESSION_FILTERS); + + // If it is already present + if (hasData($definition)) + { + // update it + $this->_ci->FiltersModel->update( + array( + 'app' => $this->_getSessionElement(self::APP), + 'dataset_name' => $this->_getSessionElement(self::DATASET_NAME), + 'description' => $descPGArray, + 'person_id' => $authPersonId + ), + array( + 'filter' => json_encode($jsonDeifinition) + ) + ); + + $saveCustomFilter = true; + } + else // otherwise insert a new one + { + $this->_ci->FiltersModel->insert( + array( + 'app' => $this->_getSessionElement(self::APP), + 'dataset_name' => $this->_getSessionElement(self::DATASET_NAME), + 'filter_kurzbz' => uniqid($authPersonId, true), + 'description' => $descPGArray, + 'person_id' => $authPersonId, + 'sort' => null, + 'default_filter' => false, + 'filter' => json_encode($jsonDeifinition), + 'oe_kurzbz' => null + ) + ); + + $saveCustomFilter = true; + } + + if ($saveCustomFilter === true) + { + $this->_setSessionElement( + FilterCmptLib::SESSION_SIDE_MENU, + $this->_generateFilterMenu($this->_app, $this->_datasetName) + ); + } + + return $saveCustomFilter; + } + + /** + * Remove a custom filter by its filter_id + */ + public function removeCustomFilter($filterId) + { + $removeCustomFilter = false; + + // Checks the parameter filterId + if (isset($filterId) && is_numeric($filterId) && $filterId > 0) + { + $this->_ci->load->model('system/Filters_model', 'FiltersModel'); // to remove the filter definitions from DB + + // Delete it from database + $this->_ci->FiltersModel->delete(array(self::FILTER_ID => $filterId)); + + // Delete it from session + $this->_dropFromSessionFilterCmptById($filterId); + + $removeCustomFilter = true; + } + + return $removeCustomFilter; + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Generates the filters menu structure array and stores it into the session + */ + private function _generateFilterMenu($app, $datasetName) + { + $filterMenu = new stdClass(); + $filterMenu->filters = array(); + $filterMenu->personalFilters = array(); + + // Loads the Filters model + $this->_ci->load->model('system/Filters_model', 'FiltersModel'); + + // Loads all the filters related to this page (same dataset_name and same app name) + $filters = $this->_ci->FiltersModel->getFiltersByAppDatasetNamePersonId( + $app, + $datasetName, + getAuthPersonId() + ); + + + // If filters were loaded + if (hasData($filters)) + { + // Loops through loaded filters + foreach (getData($filters) as $filter) + { + $menuEntry = new stdClass(); + $menuEntry->desc = $filter->description[0]; + $menuEntry->filter_id = $filter->filter_id; + + // If it is NOT a personal filter + if ($filter->person_id == null) + { + $filterMenu->filters[] = $menuEntry; + } + else // otherwise + { + $menuEntry->subscriptDescription = '(Remove)'; + $menuEntry->subscriptLinkClass = 'remove-custom-filter'; + $menuEntry->subscriptLinkValue = $filter->{self::FILTER_ID}; + + $filterMenu->personalFilters[] = $menuEntry; // adds to personal filters menu array + } + } + } + + return $filterMenu; + } + + /** + * Wrapper method to the session helper funtions to retrieve one element from the session of this filter + */ + private function _getSessionElement($name) + { + $session = getSessionElement(self::SESSION_NAME, $this->_filterUniqueId); + + if (isset($session[$name])) + { + return $session[$name]; + } + + return null; + } + + /** + * Checks if at least one of the permissions given as parameter (requiredPermissions) belongs + * to the authenticated user, if confirmed then is allowed to use this FilterCmpt. + * If the parameter requiredPermissions is NOT given or is not present in the session, + * then NO one is allow to use this FilterCmpt + * Wrapper method to permissionlib->hasAtLeastOne + */ + private function _isAllowed() + { + $this->_ci->load->library('PermissionLib'); // Load permission library + + if (!$this->_ci->permissionlib->hasAtLeastOne($this->_requiredPermissions, self::PERMISSION_FILTER_METHOD, self::PERMISSION_TYPE)) + { + $this->_setSession(error('The required permission is not help by the logged user')); + return false; + } + + return true; + } + + /** + * + */ + private function _setParameters($params) + { + if (isset($params['filterUniqueId'])) $this->_filterUniqueId = $params['filterUniqueId']; + if (isset($params['filterType'])) $this->_filterType = $params['filterType']; + if (isset($params['filterId'])) $this->_filterId = $params['filterId']; + } + + /** + * Checks the required parameters used to call this FilterCmpt + */ + private function _checkJSParameters() + { + // + if (isEmptyString($this->_filterUniqueId)) + { + $this->_setSession(error('Parameter "filterUniqueId" not provided')); + return false; + } + + // + if (isEmptyString($this->_filterType)) + { + $this->_setSession(error('Parameter "filterType" not provided')); + return false; + } + + return true; + } + + /** + * Checks the required parameters used to call this FilterCmpt + */ + private function _checkPHPParameters($filterCmptArray) + { + // If no options are given to this component... + if (!is_array($filterCmptArray) || (is_array($filterCmptArray) && count($filterCmptArray) == 0)) + { + $this->_setSession(error('No parameters provided')); + return false; + } + else // ...otherwise + { + // Parameters app AND dataset name + if (!isset($filterCmptArray[FilterCmptLib::APP]) && !isset($filterCmptArray[FilterCmptLib::DATASET_NAME])) + { + $this->_setSession( + error( + 'The parameters "'.FilterCmptLib::APP.'" AND "'.FilterCmptLib::DATASET_NAME.' must be specified' + ) + ); + return false; + } + + // The query parameter is mandatory + if (!isset($filterCmptArray[FilterCmptLib::QUERY])) + { + $this->_setSession(error('The parameter "'.FilterCmptLib::QUERY.'" must be specified')); + return false; + } + + // + if (!isset($filterCmptArray[FilterCmptLib::DATASET_NAME])) + { + $this->_setSession(error('The parameter "'.FilterCmptLib::DATESET_NAME.'" must be specified')); + return false; + } + + // + if (!isset($filterCmptArray[FilterCmptLib::REQUIRED_PERMISSIONS])) + { + $this->_setSession(error('The parameter "'.FilterCmptLib::REQUIRED_PERMISSIONS.'" must be specified')); + return false; + } + } + + return true; + } + + /** + * Checks parameters and initialize all the properties of this FilterCmpt + */ + private function _initFilterCmpt($filterCmptArray) + { + // If here then everything is ok + + // Initialize class properties + $this->_app = null; + $this->_datasetName = null; + $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; + + // Retrieved the required permissions parameter if present + if (isset($filterCmptArray[FilterCmptLib::REQUIRED_PERMISSIONS])) + { + $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])) + { + $this->_app = $filterCmptArray[FilterCmptLib::APP]; + } + + if (isset($filterCmptArray[FilterCmptLib::DATASET_NAME])) + { + $this->_datasetName = $filterCmptArray[FilterCmptLib::DATASET_NAME]; + } + + if (isset($filterCmptArray[FilterCmptLib::FILTER_KURZBZ])) + { + $this->_filterKurzbz = $filterCmptArray[FilterCmptLib::FILTER_KURZBZ]; + } + + // How to retrieve data for the filter: SQL statement or a result from DB + if (isset($filterCmptArray[FilterCmptLib::QUERY])) + { + $this->_query = $filterCmptArray[FilterCmptLib::QUERY]; + } + } + + /** + * Generates a condition for a SQL where clause using the given applied filter definition. + * By default an empty string is returned. + */ + private function _getDatasetQueryCondition($filterDefinition) + { + $condition = ''; // starts building the condition + + $this->_ci->load->model('system/Filters_model', 'FiltersModel'); + + // "operation" is a required property for the applied filter definition + if (!isEmptyString($filterDefinition->operation)) + { + // Checks what operation is required + switch ($filterDefinition->operation) + { + // comparison (==) + case self::OP_EQUAL: + // Numeric + if (is_numeric($filterDefinition->condition)) + { + $condition = '= '.$filterDefinition->condition; + } + else // string type + { + $condition = '= \''.$this->_ci->FiltersModel->escapeLike($filterDefinition->condition).'\''; + } + break; + // not equal (!=) + case self::OP_NOT_EQUAL: + // Numeric + if (is_numeric($filterDefinition->condition)) + { + $condition = '!= '.$filterDefinition->condition; + } + else // string type + { + $condition = '!= \''.$this->_ci->FiltersModel->escapeLike($filterDefinition->condition).'\''; + } + break; + // greater than (>) + case self::OP_GREATER_THAN: + // If it's a date type + if (is_numeric($filterDefinition->condition) + && isset($filterDefinition->option) + && ($filterDefinition->option == self::OPT_HOURS + || $filterDefinition->option == self::OPT_DAYS + || $filterDefinition->option == self::OPT_MONTHS + || $filterDefinition->option == self::OPT_MINUTES)) + { + $condition = '< (NOW() - \''.$filterDefinition->condition.' '.$filterDefinition->option.'\'::interval)'; + } + else // otherwise is a number + { + $condition = '> '.$filterDefinition->condition; + } + break; + // less than (<) + case self::OP_LESS_THAN: + // If it's a date type + if (is_numeric($filterDefinition->condition) + && isset($filterDefinition->option) + && ($filterDefinition->option == self::OPT_HOURS + || $filterDefinition->option == self::OPT_DAYS + || $filterDefinition->option == self::OPT_MONTHS + || $filterDefinition->option == self::OPT_MINUTES)) + { + $condition = '> (NOW() - \''.$filterDefinition->condition.' '.$filterDefinition->option.'\'::interval)'; + } + else // otherwise is a number + { + $condition = '< '.$filterDefinition->condition; + } + break; + // contains (ILIKE) + case self::OP_CONTAINS: + $condition = 'ILIKE \'%'.$this->_ci->FiltersModel->escapeLike($filterDefinition->condition).'%\''; + break; + // not contains (NOT ILIKE) + case self::OP_NOT_CONTAINS: + $condition = 'NOT ILIKE \'%'.$this->_ci->FiltersModel->escapeLike($filterDefinition->condition).'%\''; + break; + // is true (=== true) + case self::OP_IS_TRUE: + $condition = 'IS TRUE'; + break; + // is false (=== false) + case self::OP_IS_FALSE: + $condition = 'IS FALSE'; + break; + // is set + case self::OP_SET: + $condition = 'IS NOT NULL'; + break; + // is NOT set + case self::OP_NOT_SET: + $condition = 'IS NULL'; + break; + // by default must not be null (!= null) + default: + $condition = 'IS NOT NULL'; + break; + } + } + + // if the condition is valid + if (!isEmptyString($condition)) $condition = ' '.$condition; // add a white space before + + return $condition; + } + + /** + * Search for a filter inside a list of filters by the given filter name + * Returns false if NOT found, otherwise the position inside the list + */ + private function _searchFilterByName($filters, $filterName) + { + $pos = false; + + for($i = 0; $i < count($filters); $i++) + { + if ($filters[$i]->name == $filterName) + { + $pos = $i; + break; + } + } + + return $pos; + } + + /** + * Remove from the session the given filter component + */ + private function _dropFromSessionFilterCmptById($filterId) + { + // Loads the session for all the filter components + $filterCmptsSession = getSession(self::SESSION_NAME); + + // If something is present in session + if ($filterCmptsSession != null) + { + // Loops in the session for all the filter components + foreach ($filterCmptsSession as $filterCmpt => $filterCmptData) + { + // If this filter component is not the one that we are looking for + if ($filterCmptData[self::FILTER_ID] == $filterId) + { + cleanSessionElement(self::SESSION_NAME, $filterCmpt); // ...remove it + break; // stop to search + } + } + } + } + + /** + * Utility method that retrieves the name of the columns present in a filter JSON definition + */ + private function _getColumnsNames($columns) + { + $columnsNames = array(); + + // For each column + foreach ($columns as $obj) + { + // If it is set the property name of the column + if (isset($obj->name)) $columnsNames[] = $obj->name; + } + + return $columnsNames; + } + + /** + * Wrapper method to the session helper funtions to set the whole session for this filter + */ + private function _setSession($data) + { + setSessionElement(self::SESSION_NAME, $this->_filterUniqueId, $data); + } + + /** + * Wrapper method to the session helper funtions to set one element in the session for this filter + */ + private function _setSessionElement($name, $value) + { + $session = getSessionElement(self::SESSION_NAME, $this->_filterUniqueId); + + $session[$name] = $value; + + setSessionElement(self::SESSION_NAME, $this->_filterUniqueId, $session); // stores the single value + } + + /** + * + */ + private function _dropExpiredFilterCmpts() + { + // Loads the session for all the filter components + $filterCmptsSession = getSession(self::SESSION_NAME); + + // If something is present in session + if ($filterCmptsSession != null) + { + // Loops in the session for all the filter components + foreach ($filterCmptsSession as $filterCmpt => $filterCmptData) + { + // If this filter component is not the current used filter component and the it is expired... + if ($this->_filterUniqueId != $filterCmpt && $filterCmptData[self::SESSION_TIMEOUT] <= time()) + { + cleanSessionElement(self::SESSION_NAME, $filterCmpt); // ...remove it + } + } + } + } + + /** + * Loads the definition data from DB for a filter component + */ + private function _loadDefinition($filterId, $app, $datasetName, $filterKurzbz) + { + // Loads the needed models + $this->_ci->load->model('system/Filters_model', 'FiltersModel'); + $this->_ci->FiltersModel->resetQuery(); // reset any previous built query + + $this->_ci->FiltersModel->addSelect('system.tbl_filters.*'); // select only from table filters + $this->_ci->FiltersModel->addOrder('sort', 'ASC'); // sort on column sort + $this->_ci->FiltersModel->addLimit(1); // if more than one filter is set as default only one will be retrieved + + $definition = null; + $whereParameters = null; // where clause parameters + + // If we have a good filterId then use it! + if ($filterId != null && is_numeric($filterId) && $filterId > 0) + { + $whereParameters = array( + self::FILTER_ID => $filterId + ); + } + else + { + // If we can univocally retrieve a filter + if ($app != null && $datasetName != null && $filterKurzbz != null) + { + $whereParameters = array( + 'app' => $app, + 'dataset_name' => $datasetName, + 'filter_kurzbz' => $filterKurzbz + ); + } + // Else if we have only app and datasetName + elseif ($app != null && $datasetName != null && $filterKurzbz == null) + { + // Try to load the custom filter (person_id = logged user person_id) with the given "app" and "dataset_name" + // that is set as default filter (default_filter = true) + $whereParameters = array( + 'app' => $app, + 'dataset_name' => $datasetName, + 'person_id' => getAuthPersonId(), + 'default_filter' => true + ); + + $definition = $this->_ci->FiltersModel->loadWhere($whereParameters); + if (!hasData($definition)) // If a custom filter is NOT found + { + // Try to load the global filter (person_id = null) with the given "app" and "dataset_name" that is set as + // default filter (default_filter = true) + $whereParameters = array( + 'app' => $app, + 'dataset_name' => $datasetName, + 'person_id' => null, + 'default_filter' => true + ); + + $definition = $this->_ci->FiltersModel->loadWhere($whereParameters); + } + } + } + + // If no definition where loaded and where parameters were set + if ($definition == null && $whereParameters != null) + { + $definition = $this->_ci->FiltersModel->loadWhere($whereParameters); + + // Last chance!!! + if (!hasData($definition)) // If no data have been found until now the tries the most desperate query + { + $this->_ci->FiltersModel->addOrder('filter_id', 'ASC'); // sort on column filter_id to get the oldest + $whereParameters = array( + 'app' => $app, + 'dataset_name' => $datasetName + ); + + $definition = $this->_ci->FiltersModel->loadWhere($whereParameters); + } + } + + return $definition; + } + + /** + * Checks if the json definition of this filter is valid + */ + private function _parseFilterJson($definition) + { + $jsonEncodedFilter = null; + + // If the definition contains data and they are valid + if (hasData($definition) && isset(getData($definition)[0]->filter) && trim(getData($definition)[0]->filter) != '') + { + // Get the json definition of the filter + $tmpJsonEncodedFilter = json_decode(getData($definition)[0]->filter); + + // Checks required filter's properies + if (isset($tmpJsonEncodedFilter->name) + && isset($tmpJsonEncodedFilter->columns) + && is_array($tmpJsonEncodedFilter->columns) + && isset($tmpJsonEncodedFilter->filters) + && is_array($tmpJsonEncodedFilter->filters)) + { + $jsonEncodedFilter = $tmpJsonEncodedFilter; + } + } + + return $jsonEncodedFilter; + } + + /** + * Generate the query to retrieve the dataset for a filter + */ + private function _generateDatasetQuery($query, $filters) + { + $datasetQuery = 'SELECT * FROM ('.$query.') '.self::DATASET_TABLE_ALIAS; + + // If the given query is valid and the parameter filters is an array + if (!isEmptyString($query) && $filters != null && is_array($filters)) + { + $where = ''; // starts building the SQL where clause + + // Loops through the given applied filters + for ($filtersCounter = 0; $filtersCounter < count($filters); $filtersCounter++) + { + $filterDefinition = $filters[$filtersCounter]; // definition of one filter + + // If the name of the applied filter is valid + if (!isEmptyString($filterDefinition->name)) + { + // Build the query conditions + $datasetQueryCondition = $this->_getDatasetQueryCondition($filterDefinition); + + // If the built condition is valid then add it to the query clause + if (!isEmptyString($datasetQueryCondition)) + { + // If this is NOT the first one + if ($filtersCounter > 0) $where .= ' AND '; + + $where .= '"'.$filterDefinition->name.'"'.$datasetQueryCondition; + } + } + } + + // If the SQL where clause was built + if ($where != '') $datasetQuery .= ' WHERE '.$where; + } + + return $datasetQuery; + } + + /** + * Retrieves the dataset from the DB + */ + private function _getDataset($datasetQuery) + { + $dataset = null; + + if ($datasetQuery != null) + { + $this->_ci->load->model('system/Filters_model', 'FiltersModel'); + + // Execute the given SQL statement suppressing error messages + $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $this->_encryptedColumns); + } + + return $dataset; + } + + /** + * Get the filter name, the default is the "name" property of the JSON definition + * If the property namePhrase is present into the JSON definition, then try to load that from the phrases system + * NOTE: filterJson should be already checked using the method _parseFilterJson + */ + private function _getFilterName($filterJson) + { + $filterName = $filterJson->name; // always present, used as default + + // Filter name from phrases system + if (isset($filterJson->namePhrase) && !isEmptyString($filterJson->namePhrase)) + { + // Loads the library to use the phrases system + $this->_ci->load->library('PhrasesLib', array(self::FILTER_PHRASES_CATEGORY)); + + $tmpFilterNamePhrase = $this->_ci->phraseslib->t(self::FILTER_PHRASES_CATEGORY, $filterJson->namePhrase); + if (!isEmptyString($tmpFilterNamePhrase)) // if is not null or an empty string + { + $filterName = $tmpFilterNamePhrase; + } + } + + return $filterName; + } +} diff --git a/application/libraries/FilterWidgetLib.php b/application/libraries/FilterWidgetLib.php index d9a3428a0..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 } @@ -340,20 +361,25 @@ class FilterWidgetLib { $filterDefinition = $filters[$filtersCounter]; // definition of one filter - if ($filtersCounter > 0) - $where .= ' AND '; // if it's NOT the last one - - if (!isEmptyString($filterDefinition->name)) // if the name of the applied filter is valid + // If the name of the applied filter is valid + if (!isEmptyString($filterDefinition->name)) { - // ...build the condition - $where .= '"'.$filterDefinition->name.'"'.$this->_getDatasetQueryCondition($filterDefinition); + // Build the query conditions + $datasetQueryCondition = $this->_getDatasetQueryCondition($filterDefinition); + + // If the built condition is valid then add it to the query clause + if (!isEmptyString($datasetQueryCondition)) + { + // // If this is NOT the first one + if ($filtersCounter > 0) $where .= ' AND '; + + $where .= '"'.$filterDefinition->name.'"'.$datasetQueryCondition; + } } } - if ($where != '') // if the SQL where clause was built - { - $datasetQuery .= ' WHERE '.$where; - } + // If the SQL where clause was built + if ($where != '') $datasetQuery .= ' WHERE '.$where; } return $datasetQuery; @@ -362,7 +388,7 @@ class FilterWidgetLib /** * Retrieves the dataset from the DB */ - public function getDataset($datasetQuery) + public function getDataset($datasetQuery, $encryptedColumns) { $dataset = null; @@ -371,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; @@ -385,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)) { @@ -446,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); @@ -745,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/NavigationLib.php b/application/libraries/NavigationLib.php index e2492cef4..95ce67610 100644 --- a/application/libraries/NavigationLib.php +++ b/application/libraries/NavigationLib.php @@ -1,4 +1,20 @@ . + */ if (! defined('BASEPATH')) exit('No direct script access allowed'); @@ -37,7 +53,7 @@ class NavigationLib // Loads library ExtensionsLib $this->_ci->load->library('ExtensionsLib'); - $this->_navigationPage = $this->_getNavigationtPage($params); // sets the id for the related navigation widget + $this->_navigationPage = $this->_getNavigationPage($params); // sets the id for the related navigation widget } //------------------------------------------------------------------------------------------------------------------ @@ -67,9 +83,19 @@ class NavigationLib * Returns the structure for one level of the menu */ public function oneLevel( - $description, $link = '#', $children = null, $icon = '', $expand = false, - $subscriptDescription = null, $subscriptLinkClass = null, $subscriptLinkValue = null, $target = '', - $sort = null, $requiredPermissions = null, $subscriptLinkHref = '#') + $description, + $link = '#', + $children = null, + $icon = '', + $expand = false, + $subscriptDescription = null, + $subscriptLinkClass = null, + $subscriptLinkValue = null, + $target = '', + $sort = null, + $requiredPermissions = null, + $subscriptLinkHref = '#' + ) { return array( 'description' => $description, @@ -223,7 +249,8 @@ class NavigationLib $filename = APPPATH.'config/'.ExtensionsLib::EXTENSIONS_DIR_NAME.'/'.$ext->name.'/'.self::CONFIG_NAVIGATION_FILENAME; if (file_exists($filename)) { - unset($config); + $config = array(); // default value + include($filename); if (isset($config[$configName]) && is_array($config[$configName])) @@ -278,7 +305,7 @@ class NavigationLib } else { - foreach ($navigationArray as $key=>$row) + foreach ($navigationArray as $key => $row) { // Search for * Entries if (mb_strpos($key, '*') === 0 || mb_strpos($key, '*') === mb_strlen($key) - 1) @@ -300,7 +327,7 @@ class NavigationLib * Return an unique string that identify this navigation widget * NOTE: The default value is the URI where the NavigationWidget is called */ - private function _getNavigationtPage($params) + private function _getNavigationPage($params) { if ($params != null && is_array($params) diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index 09f89abee..42502f999 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, $art, $value, $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 a202f57fd..1330b1449 100644 --- a/application/libraries/PhrasesLib.php +++ b/application/libraries/PhrasesLib.php @@ -1,6 +1,6 @@ ', ''], '', $tmpText); $result->retval[$i]->text = $tmpText; } @@ -275,6 +276,17 @@ class PhrasesLib } } + /* + * 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 diff --git a/application/libraries/PrestudentLib.php b/application/libraries/PrestudentLib.php new file mode 100644 index 000000000..2d795369f --- /dev/null +++ b/application/libraries/PrestudentLib.php @@ -0,0 +1,929 @@ +_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)); + + // 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' => $studiensemester_kurzbz + ], [ + '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/ProfilLib.php b/application/libraries/ProfilLib.php new file mode 100644 index 000000000..50b8bc264 --- /dev/null +++ b/application/libraries/ProfilLib.php @@ -0,0 +1,600 @@ +ci =& get_instance(); + + + } + + public function getView($uid) + { + // loading required models + $this->ci->load->model("ressource/Mitarbeiter_model","MitarbeiterModel"); + $this->ci->load->model("person/Person_model","PersonModel"); + + $res = new stdClass(); + + // checking the uid + if ($uid == getAuthUID()) { + $isMitarbeiter = $this->ci->MitarbeiterModel->isMitarbeiter(getAuthUID()); + if(isError($isMitarbeiter)) + { + return error(getData($isMitarbeiter)); + } + $isMitarbeiter = getData($isMitarbeiter); + if ($isMitarbeiter) { + $res->view = "MitarbeiterProfil"; + $res->data = $this->mitarbeiterProfil(); + $res->data->pid = getAuthPersonId(); + } else { + $res->view = "StudentProfil"; + $res->data = $this->studentProfil(); + $res->data->pid = getAuthPersonId(); + } + $res->data->fotoStatus=$this->isFotoAkzeptiert(getAuthPersonId()); + } + // UID is availabe when accessing Profil/View/:uid + else { + $isMitarbeiter = $this->ci->MitarbeiterModel->isMitarbeiter($uid); + if(isError($isMitarbeiter)) + { + return error(getData($isMitarbeiter)); + } + $isMitarbeiter = getData($isMitarbeiter); + if ($isMitarbeiter) { + $res->view = "ViewMitarbeiterProfil"; + $res->data = $this->viewMitarbeiterProfil($uid); + + } else { + $res->view = "ViewStudentProfil"; + $res->data = $this->viewStudentProfil($uid); + } + } + + return success($res); + } + + //PRIVATE METHODS ############################################### + + /** + * function that returns the data used for the student profile + * @access private + * @return stdClass student data + */ + private function studentProfil() + { + $pid = getAuthPersonId(); + $uid = getAuthUID(); + $betriebsmittelperson_res = $this->getBetriebsmittelInfo($pid); + $kontakte_res = $this->getKontaktInfo($pid); + $zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($uid); + $adresse_res = $this->getAdressenInfo($pid); + $mailverteiler_res = $this->getMailverteiler($uid); + $person_res = $this->getPersonInfo($uid, true); + $zutrittsgruppe_res = $this->getZutrittsgruppen($uid); + $student_res = $this->getStudentInfo($uid); + $matr_res = $this->getMatrikelNummer($uid); + $profilUpdates = $this->getProfilUpdates($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 = trim($value); + } + + $intern_email = array(); + $intern_email["type"] = "intern"; + $intern_email["email"] = DOMAIN? $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; + } + + /** + * function that returns the data used for the mitarbeiter profile + * @access private + * @return stdClass mitarbeiter data + */ + private function mitarbeiterProfil() + { + $pid = getAuthPersonId(); + $uid = getAuthUID(); + $zutrittskarte_ausgegebenam = $this->getZutrittskarteDatum($uid); + $adresse_res = $this->getAdressenInfo($pid); + $kontakte_res = $this->getKontaktInfo($pid); + $mailverteiler_res = $this->getMailverteiler($uid); + $person_res = $this->getPersonInfo($uid, true); + $benutzer_funktion_res = $this->getBenutzerFunktion($uid); + $betriebsmittelperson_res = $this->getBetriebsmittelInfo($pid); + $profilUpdates = $this->getProfilUpdates($uid); + $telefon_res = $this->getTelefonInfo($uid); + $mitarbeiter_res = $this->getMitarbeiterInfo($uid); + + $res = new stdClass(); + $res->username = $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"] = DOMAIN? $uid . "@" . DOMAIN : ""; + $extern_email = array(); + $extern_email["type"] = "alias"; + + $extern_email["email"] = $mitarbeiter_res->alias? ($mitarbeiter_res->alias . "@" . DOMAIN) : null; + $res->emails = $extern_email["email"]?[$intern_email, $extern_email]:[$intern_email]; + + $res->funktionen = $benutzer_funktion_res; + $res->standort_telefon = $telefon_res; + $res->profilUpdates = $profilUpdates; + + return $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) + { + $this->ci->load->model("ressource/Betriebsmittelperson_model","BetriebsmittelpersonModel"); + $zutrittskarte_ausgegebenam = $this->ci->BetriebsmittelpersonModel->getBetriebsmittelByUid($uid, "Zutrittskarte"); + + if(isError($zutrittskarte_ausgegebenam)){ + return error(getData($zutrittskarte_ausgegebenam)); + } + $zutrittskarte_ausgegebenam = getData($zutrittskarte_ausgegebenam); + $zutrittskarte_ausgegebenam = $zutrittskarte_ausgegebenam ? current($zutrittskarte_ausgegebenam)->ausgegebenam : null; + + //? formats date from 01-01-2000 to 01.01.2000 + $zutrittskarte_ausgegebenam = str_replace("-", ".", $zutrittskarte_ausgegebenam); + return $zutrittskarte_ausgegebenam; + } + + /** + * 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) + { + $this->ci->load->model("person/Adresse_model","AdresseModel"); + $adresse_res = $this->ci->AdresseModel->addSelect(["adresse_id", "strasse", "tbl_adressentyp.bezeichnung as typ", "plz", "ort", "zustelladresse", "gemeinde", "nation"]); + $adresse_res = $this->ci->AdresseModel->addOrder("zustelladresse", "DESC"); + $adresse_res = $this->ci->AdresseModel->addJoin("tbl_adressentyp", "typ=adressentyp_kurzbz"); + + $adresse_res = $this->ci->AdresseModel->loadWhere(["person_id" => $pid]); + if(isError($adresse_res)){ + return error(getData($adresse_res)); + } + $adresse_res = getData($adresse_res) ?? []; + 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->ci->load->model("person/Kontakt_model","KontaktModel"); + $this->ci->KontaktModel->addSelect(['kontakttyp', 'kontakt_id', 'kontakt', 'tbl_kontakt.anmerkung', 'tbl_kontakt.zustellung']); + $this->ci->KontaktModel->addJoin('public.tbl_standort', 'standort_id', 'LEFT'); + $this->ci->KontaktModel->addJoin('public.tbl_firma', 'firma_id', 'LEFT'); + $this->ci->KontaktModel->addOrder('kontakttyp, kontakt, tbl_kontakt.updateamum, tbl_kontakt.insertamum'); + + $kontakte_res = $this->ci->KontaktModel->loadWhere(['person_id' => $pid]); + if(isError($kontakte_res)){ + return error(getData($kontakte_res)); + } + $kontakte_res = getData($kontakte_res); + return $kontakte_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->ci->load->model("person/Person_model","PersonModel"); + $this->ci->PersonModel->addSelect('gruppe_kurzbz, beschreibung'); + $this->ci->PersonModel->addJoin('tbl_benutzer', 'person_id'); + $this->ci->PersonModel->addJoin('tbl_benutzergruppe', 'uid'); + $this->ci->PersonModel->addJoin('tbl_gruppe', 'gruppe_kurzbz'); + + $mailverteiler_res = $this->ci->PersonModel->loadWhere(array('mailgrp' => true, 'uid' => $uid)); + if(isError($mailverteiler_res)){ + return error(getData($mailverteiler_res)); + } + $mailverteiler_res = getData($mailverteiler_res) ?? []; + $mailverteiler_res = gettype($mailverteiler_res) === 'array' ? $mailverteiler_res : []; + $mailverteiler_res = array_map(function ($element) { + $element->mailto = "mailto:" . $element->gruppe_kurzbz . "@" . DOMAIN; + return $element; + }, $mailverteiler_res); + return $mailverteiler_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) + { + $this->ci->load->model("person/Benutzer_model","BenutzerModel"); + $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, "TO_CHAR(gebdatum, 'DD.MM.YYYY') as gebdatum"); + } + $this->ci->BenutzerModel->addSelect($selectClause); + $this->ci->BenutzerModel->addJoin("tbl_person", "person_id"); + + $person_res = $this->ci->BenutzerModel->load([$uid]); + if(isError($person_res)){ + return error(getData($person_res)); + } + $person_res = getData($person_res); + $person_res = $person_res ? current($person_res) : null; + + if(isset($person_res)){ + if( ($person_res->foto === null) || ((getAuthUID() !== $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 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->ci->load->model("person/Benutzerfunktion_model","BenutzerfunktionModel"); + $this->ci->BenutzerfunktionModel->addSelect([ + "CASE WHEN (tbl_benutzerfunktion.bezeichnung IS NOT NULL AND tbl_benutzerfunktion.bezeichnung <> '' AND tbl_benutzerfunktion.bezeichnung <> tbl_funktion.beschreibung) THEN tbl_funktion.beschreibung || ' - ' || tbl_benutzerfunktion.bezeichnung ELSE tbl_funktion.beschreibung END as \"Bezeichnung\"", + "tbl_organisationseinheit.bezeichnung as Organisationseinheit", + "datum_von as Gültig_von", + "datum_bis as Gültig_bis", + "COALESCE(wochenstunden, '0'::numeric(5,2)) AS \"Wochenstunden\"" + ]); + $this->ci->BenutzerfunktionModel->addJoin("tbl_funktion", "funktion_kurzbz"); + $this->ci->BenutzerfunktionModel->addJoin("tbl_organisationseinheit", "oe_kurzbz"); + + $benutzer_funktion_res = $this->ci->BenutzerfunktionModel->loadWhere( + array( + 'uid' => $uid, + 'NOW()::date BETWEEN COALESCE(datum_von, \'1970-01-01\'::date) AND COALESCE(datum_bis, \'2170-12-01\'::date)' => null + ) + ); + if(isError($benutzer_funktion_res)){ + return error(getData($benutzer_funktion_res)); + } + $benutzer_funktion_res = getData($benutzer_funktion_res); + 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->ci->load->model("ressource/Betriebsmittelperson_model","BetriebsmittelpersonModel"); + $this->ci->BetriebsmittelpersonModel->addSelect(["CONCAT(betriebsmitteltyp, ' ' ,beschreibung) as Betriebsmittel", "nummer as Nummer", "ausgegebenam as Ausgegeben_am"]); + + //? betriebsmittel are not needed in a view + $betriebsmittelperson_res = $this->ci->BetriebsmittelpersonModel->getBetriebsmittel($pid); + if(isError($betriebsmittelperson_res)){ + return error(getData($betriebsmittelperson_res)); + } + $betriebsmittelperson_res = getData($betriebsmittelperson_res); + return $betriebsmittelperson_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) + { + $this->ci->load->model("person/Profil_update_model","ProfilUpdateModel"); + $profilUpdates = $this->ci->ProfilUpdateModel->getProfilUpdatesWhere(['uid' => $uid]); + if(isError($profilUpdates)){ + return error(getData($profilUpdates)); + } + $profilUpdates = getData($profilUpdates); + return $profilUpdates; + } + + /** + * 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->ci->load->model("ressource/Mitarbeiter_model","MitarbeiterModel"); + $this->ci->MitarbeiterModel->addSelect(["kontakt"]); + $this->ci->MitarbeiterModel->addJoin("tbl_kontakt", "tbl_mitarbeiter.standort_id = tbl_kontakt.standort_id"); + $this->ci->MitarbeiterModel->addLimit(1); + $telefon_res = $this->ci->MitarbeiterModel->loadWhere(["mitarbeiter_uid" => $uid, "kontakttyp" => "telefon"]); + if(isError($telefon_res)){ + return error(getData($telefon_res)); + } + $telefon_res = getData($telefon_res); + $telefon_res = $telefon_res ? current($telefon_res) : null; + return $telefon_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->ci->load->model("ressource/Mitarbeiter_model","MitarbeiterModel"); + $this->ci->MitarbeiterModel->addSelect(["kurzbz", "telefonklappe", "alias", "ort_kurzbz"]); + $this->ci->MitarbeiterModel->addJoin("tbl_benutzer", "tbl_benutzer.uid = tbl_mitarbeiter.mitarbeiter_uid"); + $mitarbeiter_res = $this->ci->MitarbeiterModel->load($uid); + if(isError($mitarbeiter_res)){ + return error(getData($mitarbeiter_res)); + } + $mitarbeiter_res = getData($mitarbeiter_res); + $mitarbeiter_res = $mitarbeiter_res ? current($mitarbeiter_res) : null; + + return $mitarbeiter_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->ci->load->model("person/Benutzergruppe_model","BenutzergruppeModel"); + $this->ci->BenutzergruppeModel->addSelect(['bezeichnung']); + $this->ci->BenutzergruppeModel->addJoin('tbl_gruppe', 'gruppe_kurzbz'); + + $zutrittsgruppe_res = $this->ci->BenutzergruppeModel->loadWhere(array("uid" => $uid, "zutrittssystem" => true)); + if(isError($zutrittsgruppe_res)){ + return error(getData($zutrittsgruppe_res)); + } + $zutrittsgruppe_res = getData($zutrittsgruppe_res); + return $zutrittsgruppe_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->ci->load->model("crm/Student_model","StudentModel"); + $this->ci->StudentModel->addSelect(['tbl_studiengang.bezeichnung as studiengang', 'tbl_studiengang.studiengang_kz as studiengang_kz', 'tbl_student.semester', 'tbl_student.verband', 'tbl_student.gruppe', 'tbl_student.matrikelnr as personenkennzeichen']); + $this->ci->StudentModel->addJoin('tbl_studiengang', "tbl_studiengang.studiengang_kz=tbl_student.studiengang_kz"); + + $student_res = $this->ci->StudentModel->load([$uid]); + + if(isError($student_res)){ + return error(getData($student_res)); + } + $student_res = getData($student_res); + $student_res = $student_res ? current($student_res) : null; + return $student_res; + } + + /** + * gets the Matrikelnummer corresponding to a user + * @access private + * @param integer $uid the userID used to get the Matrikelnummer + * @return object the Matrikelnummer corresponding to a userID + */ + private function getMatrikelNummer($uid) + { + $this->ci->load->model("person/Benutzer_model","BenutzerModel"); + $this->ci->BenutzerModel->addSelect(["matr_nr"]); + $this->ci->BenutzerModel->addJoin("tbl_person", "person_id"); + + $matr_res = $this->ci->BenutzerModel->load([$uid]); + + if(isError($matr_res)){ + return error(getData($matr_res)); + } + $matr_res = getData($matr_res); + $matr_res = $matr_res ? current($matr_res) : []; + return $matr_res; + } + + /** + * checks whether the foto of a user is accepted or not + * @access private + * @param integer $pid the personId of the student or mitarbeiter + * @return bool whether the foto is accepted or not + */ + private function isFotoAkzeptiert($pid) + { + $this->ci->load->model('person/Fotostatusperson_model','FotostatusModel'); + $fotostatus = $this->ci->FotostatusModel->execReadOnlyQuery(" + select distinct on (person_id) person_id, insertamum, fotostatus_kurzbz + from public.tbl_person_fotostatus + where person_id = ? + order by person_id, insertamum desc",[$pid]); + if(isError($fotostatus)){ + return error(getData($fotostatus)); + } + $fotostatus = getData($fotostatus); + if(is_array($fotostatus) && count($fotostatus) > 0){ + $fotostatus = current($fotostatus)->fotostatus_kurzbz == 'akzeptiert'; + } + else + $fotostatus = false; + return $fotostatus; + } + + /** + * 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"] = DOMAIN? $uid . "@" . DOMAIN:""; + $extern_email = array(); + $extern_email["type"] = "alias"; + + $extern_email["email"] = $benutzer_res->alias ? ($benutzer_res->alias . "@" . DOMAIN) : null; + $res->emails = $extern_email?[$intern_email, $extern_email]:[$intern_email]; + + $res->funktionen = $benutzer_funktion_res; + $res->mailverteiler = $mailverteiler_res; + $res->standort_telefon = isset($telefon_res) ? $telefon_res->kontakt : null; + + return $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->ci->load->model("person/Benutzer_model","BenutzerModel"); + $this->ci->BenutzerModel->addSelect(["alias"]); + $benutzer_res = $this->ci->BenutzerModel->load([$uid]); + if(isError($benutzer_res)){ + return error(getData($benutzer_res)); + } + + $benutzer_res = getData($benutzer_res); + $benutzer_res = $benutzer_res ? current($benutzer_res) : null; + + return $benutzer_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"] = DOMAIN? $uid . "@" . DOMAIN:""; + + $res->emails = [$intern_email]; + $res->matrikelnummer = $matr_res->matr_nr; + $res->mailverteiler = $mailverteiler_res; + + return $res; + } +} \ No newline at end of file diff --git a/application/libraries/SearchBarLib.php b/application/libraries/SearchBarLib.php new file mode 100644 index 000000000..f19365c02 --- /dev/null +++ b/application/libraries/SearchBarLib.php @@ -0,0 +1,600 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use \stdClass as stdClass; + +/** + * + */ +class SearchBarLib +{ + // Error constats + const ERROR_WRONG_JSON = 'ERR001'; + 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', 'mitarbeiter_ohne_zuordnung', 'organisationunit', 'raum', 'person', 'student','studentStv', 'prestudent', 'document', 'cms']; + + const PHOTO_IMG_URL = '/cis/public/bild.php?src=person&person_id='; + + private $_ci; // Code igniter instance + + /** + * Gets the CI instance and loads model + */ + public function __construct() + { + $this->_ci =& get_instance(); // get code igniter instance + + // It is loaded only to have the DB_Model available + $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * It performes the search of the given search string using the specified search types + */ + public function search($searchstr, $types) + { + // Checks if the given parameters are fine + $search = $this->_checkParameters($searchstr, $types); + + // If the check was successful then perform the search + if (isSuccess($search)) $search = $this->_search($searchstr, $types); + + return $search; // return the result + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks: + * - The given searchstr is a not empty string + * - The given types is a not empty array and contains allowed search types + */ + private function _checkParameters($searchstr, $types) + { + // If searchstr is empty + if (isEmptyString($searchstr)) return error(self::ERROR_WRONG_SEARCHSTR); + + // If types is not an array or it is empty + if (isEmptyArray($types)) return error(self::ERROR_NO_TYPES); + + // If all the elements in types are allowed search types + if (!isEmptyArray(array_diff($types, self::ALLOWED_TYPES))) return error(self::ERROR_WRONG_TYPES); + + return success(); // The check is fine! + } + + /** + * Loops on types and perform the search of that type using searchstr + * Then it collects all the returned data into an array as property of an object + */ + private function _search($searchstr, $types) + { + // Object to be returned + $result = new stdClass(); + $result->data = array(); + + // For each search type + foreach ($types as $type) + { + // Perform the search and then add the result to data + $result->data = array_merge($result->data, $this->{'_'.$type}($searchstr, $type)); + } + + return $result; + } + + private function _mitarbeiter_ohne_zuordnung($searchstr, $type) + { + $dbModel = new DB_Model(); + + $sql = ' + SELECT + \'employee\' AS renderer, + \''.$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 = <<execReadOnlyQuery(' + SELECT + \'employee\' AS renderer, + \''.$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) + 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) + 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 ' . + $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 + '); + + // If something has been found then return it + if (hasData($employees)) return getData($employees); + + // Otherwise return an empty array + return array(); + } + + /** + * Seach for organisation units + */ + private function _organisationunit($searchstr, $type) + { + $dbModel = new DB_Model(); + + $ous = $dbModel->execReadOnlyQuery(' + SELECT + \'' . $type . '\' AS renderer, + \''.$type.'\' AS type, + o.oe_kurzbz AS oe_kurzbz, + \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS name, + oParent.oe_kurzbz AS parentoe_kurzbz, + (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 + WHERE funktion_kurzbz = \'oezuordnung\' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + ) bfCount ON(bfCount.oe_kurzbz = o.oe_kurzbz) + LEFT JOIN ( + SELECT bf.oe_kurzbz, bf.uid, p.vorname, p.nachname + FROM public.tbl_benutzerfunktion bf + JOIN public.tbl_benutzer b USING(uid) + JOIN public.tbl_person p USING(person_id) + WHERE funktion_kurzbz = \'Leitung\' + AND (datum_von IS NULL OR datum_von <= NOW()) + AND (datum_bis IS NULL OR datum_bis >= NOW()) + AND b.aktiv = TRUE + ) bfLeader ON(bfLeader.oe_kurzbz = o.oe_kurzbz) + 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 + if (hasData($ous)) + { + // Loop through the returned dataset + foreach (getData($ous) as $ou) + { + // Create the new property leaders as an empty array + $ou->leaders = array(); + + // Loop through the found leaders for this organisation unit + for ($i = 0; $i < count($ou->leader_uid); $i++) + { + // If a leader exists for this organisationunit and has a name :D + if (!isEmptyString($ou->leader_uid[$i]) && !isEmptyString($ou->leader_name[$i])) + { + // Empty object that will contains the leader uid and name + $leader = new stdClass(); + // Set the properties name and uid + $leader->uid = $ou->leader_uid[$i]; + $leader->name = $ou->leader_name[$i]; + // Add the leader object to the leaders array + $ou->leaders[] = $leader; + } + } + + // Remove the not needed properties leader_uid and leader_name + unset($ou->leader_uid); + unset($ou->leader_name); + } + + // Returns the changed dataset + return getData($ous); + } + + // Otherwise return an empty array + return array(); + } + + /** + * Search for persons + */ + private function _person($searchstr, $type) + { + return array(); + } + + /** + * Search for students + */ + 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 renderer, + \''.$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 + \'student\' AS renderer, + \''.$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(); + } + + /** + * Search for prestudents + */ + private function _prestudent($searchstr, $type) + { + $dbModel = new DB_Model(); + + $prestudent = $dbModel->execReadOnlyQuery(' + SELECT + \'' . $type . '\' AS renderer, + \''.$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(); + } + + /** + * Search for documents + */ + private function _document($searchstr, $type) + { + return array(); + } + + /** + * Search for CMSs + */ + private function _cms($searchstr, $type) + { + return array(); + } + + /** + * Search for rooms + */ + private function _raum($searchstr, $type) + { + $dbModel = new DB_Model(); + + $rooms = $dbModel->execReadOnlyQuery(' + SELECT + \'room\' AS renderer, + \''.$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/SearchLib.php b/application/libraries/SearchLib.php new file mode 100644 index 000000000..24894eab5 --- /dev/null +++ b/application/libraries/SearchLib.php @@ -0,0 +1,1091 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use \stdClass as stdClass; + +/** + * This is a alternative for SearchBarLib for advanced searches + */ +class SearchLib +{ + // Error constats + const ERROR_WRONG_JSON = 'ERR001'; + const ERROR_WRONG_SEARCHSTR = 'ERR002'; + const ERROR_NO_TYPES = 'ERR003'; + const ERROR_WRONG_TYPES = 'ERR004'; + const ERROR_NOT_AUTH = 'ERR005'; + + private $_ci; // Code igniter instance + + private $_searchfunction_priorities = []; + private $_numeric_searchfunctions = []; + private $_allowed_searchfunctions = []; + + /** + * Gets the CI instance and loads model + * + * @param array $params + * @return void + */ + public function __construct($params = null) + { + $this->_ci =& get_instance(); // get code igniter instance + + $config = $params['config'] ?? null; + // It is loaded only to have the DB functions available + $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel'); + + // Load Config + $this->_ci->load->config('search', true, (boolean)$config); + $this->_ci->load->config('searchfunctions', true); + if ($config) { + $this->_ci->load->config($config, true); + $this->_ci->config->set_item('search', $this->_ci->config->item($config)); + } + + $this->_ci->load->library('PhrasesLib', [['search'], null], 'search_phrases'); + + // Precompute helper arrays + foreach ($this->_ci->config->item('searchfunctions') as $key => $arr) { + $this->_searchfunction_priorities[$key] = $arr['priority']; + if ($arr['force_integer'] ?? false) + $this->_numeric_searchfunctions[] = $key; + $this->_allowed_searchfunctions[] = $key; + } + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * It performes the search of the given search string using the specified search types + * + * @param string $searchstring + * @param array $types (optional) + * + * @return stdClass containing an array with the result on index 0 + * and the overall query time on index 1. + */ + public function search($searchstring, $types = []) + { + if (!$types) { + $types = $this->_ci->config->item('search'); + } else { + $tmp = []; + $missing = []; + foreach ($types as $type) { + $typeconfig = $this->_ci->config->item($type, 'search'); + if (!$typeconfig) { + $missing[] = $type; + } else { + $tmp[$type] = $typeconfig; + } + } + if ($missing) { + $p = $this->_ci->search_phrases; + return error(array_map(function ($type) use ($p) { + return $p->t('search', 'error_missing_config', [ + 'type' => $type + ]); + }, $missing)); + } + $types = $tmp; + } + + + // Convert searchstring into array + list($searchArray, $searchstring) = $this->_convertQuery($searchstring, $types); + + + $sql = $this->getDynamicSearchSqls($searchArray, array_keys($types)); + if (isError($sql)) + return $sql; + if (!hasData($sql)) { + $retval = success([]); + $retval->meta = ['time' => 0, 'searchstring' => $searchstring]; + return $retval; + } + + $msc = microtime(true); + $result = $this->_ci->BenutzerModel->execReadOnlyQuery(getData($sql)); + $msc = microtime(true) - $msc; + + if (isError($result)) + return $result; + + $retval = success($result->retval); + $retval->meta = [ + 'time' => $msc, + 'searchstring' => $searchstring + ]; + + return $retval; + } + + /** + * Generates the search query for the given search string and the + * specified search type. + * + * @param array $searchArray + * @param string $table + * + * @return stdClass containing the query string. + */ + public function getDynamicSearchSql($searchArray, $table) + { + $res = $this->checkConfig($table); + if (isError($res)) + return $res; + $table_config = getData($res); + + $sql_with = []; + + $sql_select = $this->prepareDynamicSearchSql($sql_with, $searchArray, $table); + + if (!$sql_select) + return success(""); + + $lang = getUserLanguage(); + + $output = "WITH"; + if ($sql_with && $sql_with[0] === 'RECURSIVE') { + $output .= " RECURSIVE"; + array_shift($sql_with); + } + + $output .= " + lang (index) AS ( + SELECT index + FROM public.tbl_sprache + WHERE sprache=" . $this->_ci->db->escape($lang) . " + LIMIT 1 + ), + auth (uid) AS ( + SELECT " . $this->_ci->db->escape(getAuthUID()) . " AS uid + )"; + + if ($sql_with) { + $sql_with = array_unique($sql_with); + $output .= ", " . implode(", ", $sql_with); + } + + $other_selects = ""; + if (isset($table_config['resultfields'])) + $other_selects = implode(", ", $table_config['resultfields']); + if ($other_selects) + $other_selects = ", " . $other_selects; + + $output .= " + , q (" . $this->_formatPrimarykeys($table_config['primarykey']) . ", rank) AS ( + SELECT " . $this->_formatPrimarykeys($table_config['primarykey']) . ", MAX(rank) + FROM (" . implode(" UNION ", $sql_select) . ") q + GROUP BY " . $this->_formatPrimarykeys($table_config['primarykey']) . " + ) + SELECT + " . $this->_ci->db->escape($table) . " AS type, + q.rank + " . $other_selects . " + FROM q + " . ($table_config['resultjoin'] ?? "") . " + ORDER BY rank DESC + "; + + return success($output); + } + + /** + * Generates the search query for the given search string and the + * specified search types. + * + * @param array $searchArray + * @param array $types + * + * @return stdClass containing the query string. + */ + public function getDynamicSearchSqls($searchArray, $types) + { + $with = []; + $selects = []; + foreach ($types as $type) { + $res = $this->checkConfig($type); + if (isError($res)) + return $res; + $table_config = getData($res); + + $select = $this->prepareDynamicSearchSql($with, $searchArray, $type); + if (!$select) + continue; + + $with[] = "final_" . $type . " (" . $this->_formatPrimarykeys($table_config['primarykey']) . ", rank) AS ( + SELECT " . $this->_formatPrimarykeys($table_config['primarykey']) . ", MAX(rank) + FROM (" . implode(" UNION ", $select) . ") q + GROUP BY " . $this->_formatPrimarykeys($table_config['primarykey']) . " + )"; + + $renderer = $table_config['renderer'] ?? $type; + $selects[] = " + SELECT + " . $this->_ci->db->escape($renderer) . " AS renderer, + " . $this->_ci->db->escape($type) . " AS type, + rank, + TO_JSONB((SELECT x FROM (SELECT " . implode(", ", $table_config['resultfields'] ?? ['*']) . ") x)) AS data + FROM final_" . $type . " + " . ($table_config['resultjoin'] ?? ""); + } + + if (!$selects) + return success(""); + + $recursive = ""; + if ($with && $with[0] === "RECURSIVE") { + $recursive = "RECURSIVE "; + array_shift($with); + } + + $with = array_unique($with); + + $lang = getUserLanguage(); + array_unshift($with, "lang (index) AS ( + SELECT index + FROM public.tbl_sprache + WHERE sprache=" . $this->_ci->db->escape($lang) . " + LIMIT 1 + )"); + array_unshift($with, "auth (uid) AS ( + SELECT " . $this->_ci->db->escape(getAuthUID()) . " AS uid + )"); + + return success(" + WITH " . $recursive . implode(", ", $with) . " + SELECT * + FROM (" . implode(" UNION ", $selects) . ") q + ORDER BY rank DESC + LIMIT 100 + "); + } + + //------------------------------------------------------------------------------------------------------------------ + // Protected methods + + /** + * Check config + * + * @param string $name + * + * @return stdClass + */ + protected function checkConfig($name) + { + $table_config = $this->_ci->config->item($name, 'search'); + + if (!$table_config) + return error($this->_ci->search_phrases->t('search', 'error_missing_config', [ + 'type' => $name + ])); + + $errors = []; + if (!isset($table_config['table']) + || !is_string($table_config['table']) + || !$table_config['table'] + ) { + $errors[] = $this->_ci->search_phrases->t('search', 'error_invalid_config', [ + 'type' => $name, + 'field' => 'table' + ]); + } + if (!isset($table_config['primarykey']) + || !is_string($table_config['primarykey']) + || !$table_config['primarykey'] + ) { + $errors[] = $this->_ci->search_phrases->t('search', 'error_invalid_config', [ + 'type' => $name, + 'field' => 'primarykey' + ]); + } + if (!isset($table_config['resultfields']) + || !is_array($table_config['resultfields']) + || !$table_config['resultfields'] + ) { + $errors[] = $this->_ci->search_phrases->t('search', 'error_invalid_config', [ + 'type' => $name, + 'field' => 'resultfields' + ]); + } + if (!isset($table_config['searchfields']) + || !is_array($table_config['searchfields']) + || !$table_config['searchfields'] + ) { + $errors[] = $this->_ci->search_phrases->t('search', 'error_invalid_config', [ + 'type' => $name, + 'field' => 'searchfields' + ]); + } else { + foreach ($table_config['searchfields'] as $searchfield => $config) { + if (!isset($config['field']) + || !is_string($config['field']) + || !$config['field'] + ) { + $errors[] = $this->_ci->search_phrases->t('search', 'error_invalid_config_searchfield', [ + 'type' => $name, + 'searchfield' => $searchfield, + 'field' => 'field' + ]); + } + if (!isset($config['comparison']) + || !is_string($config['comparison']) + || !in_array($config['comparison'], $this->_allowed_searchfunctions) + ) { + $errors[] = $this->_ci->search_phrases->t('search', 'error_invalid_config_searchfield', [ + 'type' => $name, + 'searchfield' => $searchfield, + 'field' => 'comparison' + ]); + } + } + } + + if ($errors) + return error($errors); + + return success($table_config); + } + + /** + * Generates the with statements for the given search string and the + * specified search type. + * + * @param array &$sqlWith + * @param array $searchArray + * @param string $table + * + * @return string a query string or the name of the prepared select. + */ + protected function prepareDynamicSearchSql(&$sqlWith, $searchArray, $table) + { + $table_config = $this->_ci->config->item($table, 'search'); + + $id_offset = count($sqlWith); + + + $allowed_codes_w_order = ['' => 0, '!' => -1]; + $max = max($this->_searchfunction_priorities); + foreach ($table_config['searchfields'] as $code => $config) { + $allowed_codes_w_order[$code] = $this->_searchfunction_priorities[$config['comparison']]; + $allowed_codes_w_order['!' . $code] = $this->_searchfunction_priorities[$config['comparison']] - $max - 2; + } + + $check_order = $this->_searchfunction_priorities; + uasort($table_config['searchfields'], function ($a, $b) use ($check_order) { + return $check_order[$b['comparison']] - $check_order[$a['comparison']]; + }); + + $integer_functions = $this->_numeric_searchfunctions; + $integer_fields = array_keys(array_filter($table_config['searchfields'], function ($a) use ($integer_functions) { + return in_array($a['comparison'], $integer_functions); + })); + + $only_integer_fields = count($integer_fields) == count($table_config['searchfields']); + + $aliases = []; + foreach ($table_config['searchfields'] as $field => $config) { + if (isset($config['alias'])) { + foreach ($config['alias'] as $alias) { + $aliases[$alias] = $field; + $aliases['!' . $alias] = '!' . $field; + } + } + } + + $sql_select = []; + + if (isset($table_config['prepare'])) { + $this->_addPreparesToSqlWith($sqlWith, $table_config['prepare']); + } + + foreach ($searchArray as $or_search) { + if (isset($or_search['-filter']) && !in_array($table, $or_search['-filter'])) + continue; + unset($or_search['-filter']); + + foreach ($aliases as $alias => $field) { + if (isset($or_search[$alias])) { + $or_search[$field] = array_merge($or_search[$alias], $or_search[$field] ?? []); + unset($or_search[$alias]); + } + } + + // NOTE(chris): early out if not allowed fields are in the search array + $used_codes = array_keys($or_search); + if (count(array_intersect($used_codes, array_keys($allowed_codes_w_order))) != count($used_codes)) + continue; + + // NOTE(chris): expand general excludes to all fields + if (isset($or_search['!'])) { + $not = $or_search['!']; + unset($or_search['!']); + foreach ($table_config['searchfields'] as $code => $config) { + if (isset($or_search['!' . $code])) + $or_search['!' . $code] = array_unique(array_merge($or_search['!' . $code], $not)); + else + $or_search['!' . $code] = $not; + } + } + + // NOTE(chris): early out if all searchfields require an integer and at least one searchword is not a number + if ($only_integer_fields + && isset($or_search[""]) + && $this->_hasAtLeastOneNaN($or_search[""]) + ) { + continue; + } + + $skip = false; + foreach ($integer_fields as $code) { + // NOTE(chris): filter non integer for integer fields + if (isset($or_search['!' . $code])) { + $or_search['!' . $code] = array_filter($or_search['!' . $code], function ($a) { + return is_numeric($a); + }); + if (!$or_search['!' . $code]) + unset($or_search['!' . $code]); + } + // NOTE(chris): early out if a searchword that is not a number is compared to a searchfield that requires an integer + if (isset($or_search[$code]) + && $this->_hasAtLeastOneNaN($or_search[$code]) + ) { + $skip = true; + break; + } + } + if ($skip) + continue; + + // NOTE(chris): sort for performance reasons + uksort($or_search, function ($a, $b) use ($allowed_codes_w_order) { + return $allowed_codes_w_order[$b] - $allowed_codes_w_order[$a]; + }); + + $or_with = []; + $or_select = []; + $or_prepare = []; + + if (substr(key($or_search), 0, 1) == '!') { + // NOTE(chris): only negative searchwords + $sql = []; + foreach ($or_search as $code => $words) { + $code = substr($code, 1); + // NOTE(chris): sort for performance reasons + usort($words, function ($a, $b) { + return strlen($b) - strlen($a); + }); + $field_config = $table_config['searchfields'][$code]; + + if (isset($field_config['prepare'])) { + $this->_addPreparesToSqlWith($or_with, $field_config['prepare']); + $or_prepare[$code] = $field_config['prepare']; + unset($table_config['searchfields'][$code]['prepare']); + unset($field_config['prepare']); + } + $field_sql = " + SELECT + " . $this->_formatPrimarykeys($table_config['primarykey'], $table_config['table']) . " + FROM " . $table_config['table'] . " + " . $this->_makeJoin($field_config['join'] ?? '') . " + WHERE "; + foreach ($words as $word) { + $sql[] = $field_sql . $this->_makeCompareBool($field_config['comparison'], $field_config['field'], $word); + } + } + + $or_select[] = " + SELECT + " . $this->_formatPrimarykeys($table_config['primarykey'], $table_config['table']) . ", + 1.0 AS rank + FROM " . $table_config['table'] . " + WHERE " . $table_config['primarykey'] . " NOT IN (" . implode(" UNION ", $sql) . ")"; + } else { + $current_select = false; + $count = 0; + $skip = false; + foreach ($or_search as $code => $words) { + // NOTE(chris): sort for performance reasons + if ($code && substr($code, 0, 1) == '!') { + usort($words, function ($a, $b) { + return strlen($a) - strlen($b); + }); + } else { + usort($words, function ($a, $b) { + return strlen($b) - strlen($a); + }); + } + if ($code == '') { + foreach ($words as $i => $word) { + $field_sql = []; + foreach ($table_config['searchfields'] as $c => $field_config) { + if (in_array($field_config['comparison'], $integer_functions) && !is_numeric($word)) + continue; + + $word_from = $table_config['table']; + $word_join = ""; + $word_rank = "0"; + if ($current_select) { + $word_from = $current_select; + if ($this->_needBasicTableJoin($field_config['field'], $table_config['primarykey'])) { + $word_join .= " " . $this->_makeJoin($table_config); + } + $word_rank = "rank"; + } + if (isset($field_config['prepare'])) { + $this->_addPreparesToSqlWith($or_with, $field_config['prepare']); + $or_prepare[$c] = $field_config['prepare']; + unset($table_config['searchfields'][$c]['prepare']); + unset($field_config['prepare']); + } + if (isset($field_config['join'])) { + $word_join .= " " . $this->_makeJoin($field_config['join']); + } + $field_sql[] = " + SELECT + " . $this->_formatPrimarykeys($table_config['primarykey'], $word_from) . ", + " . $word_rank . " AS w_rank, + " . $this->_makeRank($field_config['comparison'], $field_config['field'], $word) . " AS rank + FROM " . $word_from . " + " . $word_join . " + WHERE " . $this->_makeCompare($field_config['comparison'], $field_config['field'], $word); + } + // NOTE(chris): skip because the word is not numeric but all searchfields require integers + if (!$field_sql) { + $or_with = []; + $or_select = []; + $count = 0; + $skip = true; + foreach ($or_prepare as $k => $v) + $table_config['searchfields'][$k]['prepare'] = $v; + break; + } + + $id = "w" . ($id_offset + count($or_with)); + $or_with[] = " + " . $id . " (" . $this->_formatPrimarykeys($table_config['primarykey']) . ", rank) AS ( + SELECT + " . $this->_formatPrimarykeys($table_config['primarykey']) . ", + (w_rank + 1.0 - CASE " . + "WHEN MIN(rank) = 0 THEN 0 " . + "ELSE EXP(SUM(LN(CASE WHEN rank = 0 THEN 1 ELSE rank " . + "END))) END) AS rank + FROM (" . implode(' UNION ALL ', $field_sql) . ") " . $id . " + GROUP BY " . $this->_formatPrimarykeys($table_config['primarykey']) . ", w_rank + )"; + $current_select = $id; + } + } else { + foreach ($words as $i => $word) { + $where = ""; + $rank = ""; + $jointype = ""; + if (substr($code, 0, 1) == '!') { + $c = substr($code, 1); + $field_config = $table_config['searchfields'][$c]; + + $rank = "1"; + + $jointype = "LEFT"; + + $where = $field_config['field'] . + " IS NULL OR NOT (" . + $this->_makeCompareBool( + $field_config['comparison'], + $field_config['field'], + $word + ) . + ")"; + if ($field_config['1-n'] ?? false) { + $where = "GROUP BY " . + $this->_formatPrimarykeys($table_config['primarykey'], $current_select ?: $table_config['table']) . + ", rank HAVING MIN(CASE WHEN " . + $where . + " THEN 1 ELSE 0 END) = 1"; + } else { + $where = "WHERE " . $where; + } + } else { + $field_config = $table_config['searchfields'][$code]; + + $rank = $this->_makeRank($field_config['comparison'], $field_config['field'], $word); + + $where = $this->_makeCompare($field_config['comparison'], $field_config['field'], $word); + $where = "WHERE " . $where; + } + $word_from = $table_config['table']; + $word_join = ""; + $word_rank = ""; + if ($current_select) { + $word_from = $current_select; + if ($this->_needBasicTableJoin($field_config['field'], $table_config['primarykey'])) { + $word_join .= " " . $this->_makeJoin($table_config); + } + $word_rank = "rank + "; + } + if (isset($field_config['prepare'])) { + $this->_addPreparesToSqlWith($or_with, $field_config['prepare']); + $or_prepare[$code] = $field_config['prepare']; + unset($table_config['searchfields'][$code]['prepare']); + unset($field_config['prepare']); + } + if (isset($field_config['join'])) { + $word_join .= " " . $this->_makeJoin($field_config['join'], $jointype); + } + + $id = "w" . ($id_offset + count($or_with)); + $or_with[] = " + " . $id . " (" . $this->_formatPrimarykeys($table_config['primarykey']) . ", rank) AS ( + SELECT + " . $this->_formatPrimarykeys($table_config['primarykey'], $word_from) . ", + " . $word_rank . $rank . " AS rank + FROM " . $word_from . " + " . $word_join . " + " . $where . " + )"; + $current_select = $id; + } + } + if ($skip) + break; + $count += count($words); + } + + if (!$count || !$current_select) + continue; + + $or_select[] = " + SELECT " . $this->_formatPrimarykeys($table_config['primarykey']) . ", rank / " . $count . " AS rank FROM " . $current_select; + } + + if ($or_with[0] === "RECURSIVE") + { + if (empty($sqlWith) || $sqlWith[0] !== "RECURSIVE") + array_unshift($sqlWith, "RECURSIVE"); + array_shift($or_with); + } + + $sqlWith = array_merge($sqlWith, $or_with); + $sql_select = array_merge($sql_select, $or_select); + $id_offset += count($or_with); + } + + return $sql_select; + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks if the field is not one of the primarykeys. + * + * @param string $field + * @param array|string $primarykeys + * + * @return boolean + */ + private function _needBasicTableJoin($field, $primarykeys) + { + if (!is_array($primarykeys) && strpos($primarykeys, ",") !== false) { + return $field != $primarykeys; + } + if (!is_array($primarykeys)) + $primarykeys = explode(",", $primarykeys); + + foreach ($primarykeys as $key) { + if ($field == trim($key)) + return false; + } + return true; + } + + /** + * Returns comma separated primarykeys. Optionally with table prefix + * + * @param array|string $primarykeys + * @param string $prefix + * + * @return string + */ + private function _formatPrimarykeys($primarykeys, $prefix = "") + { + if (is_array($primarykeys)) { + if ($prefix) + $prefix .= "."; + return $prefix . implode(", " . $prefix, $primarykeys); + } + if (!$prefix) + return $primarykeys; + + return $prefix . "." . implode(", " . $prefix . ".", explode(",", $primarykeys)); + } + + /** + * Adds the prepare statement to the sqlWith stack and handles the + * "RECURSIVE" modifier + * + * @param array &$sqlWith + * @param array $prepares + * + * @return void + */ + private function _addPreparesToSqlWith(&$sqlWith, $prepares) + { + $recursive = $sqlWith[0] ?? "" === "RECURSIVE"; + if (!is_array($prepares)) + $prepares = [$prepares]; + + foreach ($prepares as $prep) { + $prep = trim($prep); + if (strtoupper(substr($prep, 0, 10)) === "RECURSIVE ") { + $recursive = true; + $sqlWith[] = substr($prep, 10); + } else { + $sqlWith[] = $prep; + } + } + if ($recursive && $sqlWith[0] !== "RECURSIVE") { + array_unshift($sqlWith, "RECURSIVE"); + } + } + + /** + * Checks if an array has at least on non numeric value. + * + * @param array $arr + * + * @return boolean + */ + private function _hasAtLeastOneNaN($arr) + { + foreach ($arr as $value) + if (!is_numeric($value)) + return true; + return false; + } + + /** + * Helper function for getDynamicSearchSql + * + * @param array $join + * @param string $prefix + * + * @return string + */ + private function _makeJoin($join, $prefix = "") + { + if (!is_array($join)) + return ""; + if (!isset($join['table'])) { + $output = []; + foreach ($join as $j) + $output[] = trim($this->_makeJoin($j, $prefix)); + return implode(" ", $output); + } + if (!isset($join['on']) && !isset($join['using']) && !isset($join['primarykey'])) + return ""; + $output = $prefix . " JOIN " . $join['table']; + + if (isset($join['using'])) + return $output . " USING (" . $join['using'] . ")"; + + if (isset($join['primarykey'])) + return $output . " USING (" . $join['primarykey'] . ")"; + + return $output . " ON (" . $join['on'] . ")"; + } + + /** + * Helper function for _makeRank, _makeCompare and _makeCompareBool + * + * @param string $function + * @param string $mode + * @param string $field + * @param string $word + * + * @return string + */ + private function _makeFunction($function, $mode, $field, $word) + { + $searchfunction = $this->_ci->config->item($mode, 'searchfunctions'); + + if (!$searchfunction) + return ""; + $tpl = $searchfunction[$function] ?? ""; + + if (strstr($tpl, '{field}')) + $tpl = str_replace('{field}', $field, $tpl); + + if (strstr($tpl, '{word}')) + $tpl = str_replace('{word}', $this->_ci->db->escape($word), $tpl); + if (strstr($tpl, '{like:word}')) + $tpl = str_replace('{like:word}', "'%" . $this->_ci->db->escape_like_str($word) . "%'", $tpl); + + return $tpl; + } + + /** + * Helper function for getDynamicSearchSql + * + * @param string $mode + * @param string $field + * @param string $word + * + * @return string + */ + private function _makeRank($mode, $field, $word) + { + return $this->_makeFunction('rank', $mode, $field, $word); + } + + /** + * Helper function for getDynamicSearchSql + * + * @param string $mode + * @param string $field + * @param string $word + * + * @return string + */ + private function _makeCompare($mode, $field, $word) + { + return $this->_makeFunction('compare', $mode, $field, $word); + } + + /** + * Helper function for getDynamicSearchSql + * + * @param string $mode + * @param string $field + * @param string $word + * + * @return string + */ + private function _makeCompareBool($mode, $field, $word) + { + $searchfunction = $this->_ci->config->item($mode, 'searchfunctions'); + + if (!$searchfunction) + return ""; + $function = isset($searchfunction['compare_boolean']) ? 'compare_boolean' : 'compare'; + return $this->_makeFunction($function, $mode, $field, $word); + } + + /** + * Converts the search string to an array. + * First level should be joined with an OR. + * Second level should be joined with an AND or AND NOT. + * It is an associative array where the key is a code for the field + * which the words should be compared with and the value is the array + * of words. + * Use AND NOT if the first letter in the key is "!". + * Use AND if the first letter in the key is not "!". + * E.g: + * If the key is: + * "": the words should be compared to all fields with AND. + * "!": the words should be compared to all fields with AND NOT. + * "somefield": the words should be compared to the field somefield with + * AND. + * "!somefield": the words should be compared to the field somefield with + * AND NOT. + * + * @param string $searchstring + * @param array $types + * + * @return array + */ + private function _convertQuery($searchstring, $types) + { + $searchAllTypes = count($types) == count($this->_ci->config->item('search')); + $allowedTypes = array_keys($types); + + $currentArray = []; + $outputArray = []; + $cleanStrings = []; + $cleanSearchstring = ''; + $filter = ['+' => [], '-' => []]; + $typeAliases = []; + + $tmp = explode(' ', strtolower($searchstring)); + while ($tmp) { + $chunk = trim(array_shift($tmp)); + if ($chunk == '') + continue; + + if (strpos($chunk, '"') !== false) { + $test = explode('"', $chunk); + if (count($test) > 2) { + $rest = implode('"', array_slice($test, 2)); + if ($rest) { + array_unshift($tmp, $rest); + $chunk = implode('"', array_slice($test, 0, 2)) . '"'; + } + } + if (count($test) == 2) { + while ($tmp && strpos($test[1], '"') === false) { + $test[1] .= ' ' . trim(array_shift($tmp)); + } + if (strpos($test[1], '"') === false) { + $chunk = implode('"', $test) . '"'; + } else { + $test2 = explode('"', $test[1], 2); + $chunk = $test[0] . '"' . $test2[0] . '"'; + if ($test2[1]) { + array_unshift($tmp, $test2[1]); + } + } + } + if (strpos($chunk, ' ') === false) { + $chunk = str_replace('"', '', $chunk); + } + } + + if ($chunk == 'or') { + $this->_convertQueryCleanupOr($currentArray, $cleanStrings, $filter, $searchAllTypes, $allowedTypes); + $filter = ['+' => [], '-' => []]; + if ($currentArray) { + $cleanSearchstring .= ($cleanSearchstring ? ' or ' : '') . implode(' ', $cleanStrings); + $cleanStrings = []; + $outputArray[] = $currentArray; + $currentArray = []; + } + continue; + } + + if ($chunk == ':' || $chunk == '-' || substr($chunk, -1) == ':') + continue; + + if ($chunk[0] == ':' || ($chunk[0] == '-' && $chunk[1] == ':')) { + if (!$typeAliases) { + foreach ($types as $type => $config) { + $typeAliases[$type] = $type; + if (isset($config['alias'])) { + foreach ($config['alias'] as $alias) { + if (!isset($typeAliases[$alias])) + $typeAliases[$alias] = $type; + } + } + } + } + + $test = explode(':', $chunk, 2); + if (isset($typeAliases[$test[1]])) + $chunk = $test[0] . ':' . $typeAliases[$test[1]]; + elseif ($test[0] == '-') + continue; + } + + if (in_array($chunk, $cleanStrings)) + continue; + + $cleanStrings[] = $chunk; + + $chunk = str_replace('"', '', $chunk); + $code = ''; + + if ($chunk[0] == '-') { + $code = '!'; + $chunk = substr($chunk, 1); + } + if (strpos($chunk, ':') !== false) { + $chunk = explode(':', $chunk, 2); + if (!$chunk[0]) { + $filter[$code ? '-' : '+'][] = $chunk[1]; + continue; + } + $code .= $chunk[0]; + $chunk = $chunk[1]; + } + + if (!isset($currentArray[$code])) + $currentArray[$code] = []; + + $currentArray[$code][] = $chunk; + } + + $this->_convertQueryCleanupOr($currentArray, $cleanStrings, $filter, $searchAllTypes, $allowedTypes); + if ($currentArray) { + $cleanSearchstring .= ($cleanSearchstring ? ' or ' : '') . implode(' ', $cleanStrings); + $outputArray[] = $currentArray; + } + return [$outputArray, $cleanSearchstring]; + } + + private function _convertQueryCleanupOr(&$currentArray, &$cleanStrings, $filter, $searchAllTypes, $allowedTypes) + { + if ($filter['+'] && $filter['-']) { + $double = array_intersect($filter['+'], $filter['-']); + if ($double) { + foreach ($double as $type) { + array_splice($cleanStrings, array_search(':' . $type, $cleanStrings), 1); + array_splice($cleanStrings, array_search('-:' . $type, $cleanStrings), 1); + } + $filter['+'] = array_diff($filter['+'], $double); + $filter['-'] = array_diff($filter['-'], $double); + } + if (!$filter['+'] && !$filter['-']) { + // All filters cancel each other out + $currentArray = []; + $cleanStrings = []; + return; + } + if ($filter['+']) { + foreach ($filter['-'] as $type) { + array_splice($cleanStrings, array_search('-:' . $type, $cleanStrings), 1); + } + $filter['-'] = []; + } + } + if ($filter['+']) { + $cleanFilter = array_intersect($allowedTypes, $filter['+']); + if (!$cleanFilter) { + // All filters are forbidden + $currentArray = []; + $cleanStrings = []; + return; + } + $forbiddenFilter = array_diff($cleanFilter, $filter['+']); + foreach ($forbiddenFilter as $type) { + array_splice($cleanStrings, array_search(':' . $type, $cleanStrings), 1); + } + $filter['+'] = $cleanFilter; + } elseif ($filter['-']) { + $filter['+'] = array_diff($allowedTypes, $filter['-']); + if (!$searchAllTypes) { + foreach ($filter['+'] as $type) + $cleanStrings[] = ':' . $type; + foreach ($filter['-'] as $type) + array_splice($cleanStrings, array_search('-:' . $type, $cleanStrings), 1); + } + } else { + if (!$searchAllTypes) { + foreach ($allowedTypes as $type) + $cleanStrings[] = ':' . $type; + } + } + + if ($filter['+']) { + $currentArray['-filter'] = $filter['+']; + } + } +} 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/StundenplanLib.php b/application/libraries/StundenplanLib.php new file mode 100644 index 000000000..6d53a2e2e --- /dev/null +++ b/application/libraries/StundenplanLib.php @@ -0,0 +1,791 @@ +getEventsUser($start, $end); + + return $this->getEventsLv($lehrveranstaltung_id, $start, $end); + } + + /** + * fetches Stundenplan events for the loggedin user between start and end + * + * @param string $start + * @param string $end + * @return stdClass + * @access public + */ + public function getEventsUser($start, $end) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + + $uid = getAuthUID(); + if (is_null($uid)) + return error("No UID"); + + $is_mitarbeiter = getData($this->_ci->MitarbeiterModel->isMitarbeiter($uid)); + + if ($is_mitarbeiter) + return $this->getEventsEmployee($uid, $start, $end); + + return $this->getEventsStudent($uid, $start, $end); + } + + /** + * fetches Stundenplan events for a student between start and end + * + * @param string $student_uid + * @param string $start + * @param string $end + * @return stdClass + * @access public + */ + public function getEventsStudent($student_uid, $start, $end) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + $semester_range = $this->studienSemesterErmitteln($start, $end); + if (isError($semester_range)) + return $semester_range; + $semester_range = getData($semester_range); + + $this->sortStudienSemester($semester_range); + + $function_error = $this->applyLoadUeberSemesterHaelfte($semester_range); + if ($function_error) + return $function_error; + + // getting the gruppen_kurzbz of the student in the different studiensemester + $benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($student_uid, $semester_range); + if (isError($benutzer_gruppen)) + return $benutzer_gruppen; + $benutzer_gruppen = getData($benutzer_gruppen); + + // getting the student_lehrverbaende of the student in the different studiensemester + $student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($student_uid, $semester_range); + if (isError($student_lehrverband)) + return $student_lehrverband; + $student_lehrverband = getData($student_lehrverband); + + $stundenplan_query = $this->_ci->StundenplanModel->getStundenplanQuery( + $start, + $end, + $semester_range, + $benutzer_gruppen, + $student_lehrverband + ); + if (!$stundenplan_query) + return success([]); + + $stundenplan_data = $this->_ci->StundenplanModel->stundenplanGruppierung($stundenplan_query); + if (isError($stundenplan_data)) + return $stundenplan_data; + $stundenplan_data = getData($stundenplan_data) ?? []; + + $function_error = $this->expandObjectInformation($stundenplan_data); + if ($function_error) + return $function_error; + + return success($stundenplan_data); + } + + /** + * fetches Stundenplan events for an employee between start and end + * + * @param string $uid + * @param string $start + * @param string $end + * @return stdClass + * @access public + */ + public function getEventsEmployee($uid, $start, $end) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + $stundenplan_data = $this->_ci->StundenplanModel->getStundenplanMitarbeiter($start, $end, $uid); + if (isError($stundenplan_data)) + return $stundenplan_data; + $stundenplan_data = getData($stundenplan_data) ?? []; + + $function_error = $this->expandObjectInformation($stundenplan_data); + if ($function_error) + return $function_error; + + return success($stundenplan_data); + } + + /** + * fetches Stundenplan events for a LV between start and end + * + * @param integer $lehrveranstaltung_id + * @param string $start + * @param string $end + * @return stdClass + * @access public + */ + public function getEventsLv($lehrveranstaltung_id, $start, $end) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + $stundenplan_data = $this->_ci->StundenplanModel->getStundenplanLVA($start, $end, $lehrveranstaltung_id); + if (isError($stundenplan_data)) + return $stundenplan_data; + $stundenplan_data = getData($stundenplan_data) ?? []; + + $function_error = $this->expandObjectInformation($stundenplan_data); + if ($function_error) + return $function_error; + + // query lv itself in case its Stundenplan is being queried and it has no entries + $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $lv_result = $this->_ci->LehrveranstaltungModel->load($lehrveranstaltung_id); + if (isError($lv_result)) + return $lv_result; + if (!hasData($lv_result)) + return error('LV not found'); + + return success($stundenplan_data); + } + + /** + * Get stundenplan for a room + * + * @param string $ort_kurzbz + * @param string $start_date + * @param string $end_date + * @return stdClass + */ + public function getRoomplan($ort_kurzbz, $start_date, $end_date) + { + $this->_ci =& get_instance(); + + // Load Config + $this->_ci->load->config('calendar'); + // Load Models + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + $query = $this->_ci->StundenplanModel->getRoomQuery($ort_kurzbz, $start_date, $end_date); + $roomplan_data = $this->_ci->StundenplanModel->stundenplanGruppierung($query); + + if (isError($roomplan_data)) + return $roomplan_data; + + $this->expandObjectInformation($roomplan_data->retval); + + return $roomplan_data; + } + + /** + * Get reservations (for a room or all) + * + * @param string $start_date + * @param string $end_date + * @param string $ort_kurzbz + * @return stdClass + */ + public function getReservierungen($start_date, $end_date, $ort_kurzbz = '') + { + $this->_ci =& get_instance(); + + // Load Config + $this->_ci->load->config('calendar'); + // Load Models + $this->_ci->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->_ci->load->model('ressource/Reservierung_model', 'ReservierungModel'); + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + $is_mitarbeiter = getData($this->_ci->MitarbeiterModel->isMitarbeiter(getAuthUID())); + + if ($is_mitarbeiter) { + $reservierungen = $this->_ci->ReservierungModel->getReservierungenMitarbeiter($start_date, $end_date, $ort_kurzbz); + } else { + // querying the reservierungen + $reservierungen = $this->_ci->ReservierungModel->getReservierungen($start_date, $end_date, $ort_kurzbz); + } + + if (isError($reservierungen)) + return $reservierungen; + + $function_error = $this->expandObjectInformation($reservierungen->retval); + + if (!is_null($function_error)) + return $function_error; + + return $reservierungen; + } + + public function getLektorenFromLehrveranstaltung($lehrveranstaltung_id, $semester, $studiengang_kz, $studiensemester_kurzbz){ + $this->_ci =& get_instance(); + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + $this->_ci->load->model('organisation/Studiensemester_model','StudiensemesterModel'); + + $studiensemester = $this->_ci->StudiensemesterModel->loadWhere(["studiensemester_kurzbz"=>$studiensemester_kurzbz]); + if(isError($studiensemester)) + { + return error(getData($studiensemester)); + } + $studiensemester = current(getData($studiensemester)); + $lektoren = $this->_ci->StundenplanModel->execReadOnlyQuery(" + SELECT DISTINCT uid + FROM campus.vw_stundenplan + WHERE lehrveranstaltung_id = ? AND + studiengang_kz = ? AND + semester = ? AND + (datum BETWEEN ? AND ?) + ",[$lehrveranstaltung_id, $studiengang_kz, $semester, $studiensemester->start, $studiensemester->ende]); + + if(isError($lektoren)) + { + return error(getData($lektoren)); + } + $lektoren = getData($lektoren); + if(isset($lektoren)){ + $lektoren = array_map(function($lektor){ + return $lektor->uid; + },$lektoren); + + } + return success($lektoren); + } + + public function expandObjectInformation($data) + { + $this->_ci =& get_instance(); + + // Load Config + $this->_ci->load->config('calendar'); + // Load Model + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + foreach ($data as $item) + { + $tz = new DateTimeZone($this->_ci->config->item('timezone')); + $isostart = new DateTime($item->datum . ' ' . $item->beginn, $tz); + $item->isostart = $isostart->format(DateTime::ATOM); + + $isoend = new DateTime($item->datum . ' ' . $item->ende, $tz); + $item->isoend = $isoend->format(DateTime::ATOM); + + $lektor_obj_array = array(); + $gruppe_obj_array = array(); + + // load lektor object + foreach ($item->lektor as $lv_lektor) + { + $this->_ci->StundenplanModel->addLimit(1); + $lektor_object = $this->_ci->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->_ci->show_error(getError($lektor_object)); + } + if(isError($lektor_object)) + { + return error(getData($lektor_object)); + } + $lektor_object = getData($lektor_object); + if(count($lektor_object) == 0) + { + return error("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; + } + + if($item->ort_kurzbz) { + + $ort_content_object = $this->_ci->StundenplanModel->execReadOnlyQuery(" + SELECT content_id + FROM public.tbl_ort + WHERE ort_kurzbz = ?", [$item->ort_kurzbz]); + if (isError($ort_content_object)) { + return error(getData($ort_content_object)); + } + $ort_content_object = getData($ort_content_object)[0]; + if($ort_content_object) { + $item->ort_content_id = $ort_content_object->content_id; + } + + + } + + $item->gruppe = $gruppe_obj_array; + $item->lektor = $lektor_obj_array; + + } + } + + public function fetchFerienTageEvents($start_date, $end_date, $studiengang_kz) + { + $this->_ci =& get_instance(); + + // Load Config + $this->_ci->load->config('calendar'); + + $this->_ci->load->model('organisation/Ferien_model', 'FerienModel'); + + $tz = new DateTimeZone($this->_ci->config->item('timezone')); + + $ferienEvents = $this->_ci->FerienModel->execReadOnlyQuery(" + SELECT * + FROM lehre.tbl_ferien + WHERE (bisdatum >= ? AND vondatum < ?) AND (studiengang_kz = 0 OR studiengang_kz = ?) + ", [$start_date, $end_date, $studiengang_kz]); + + if (isError($ferienEvents)) + return $ferienEvents; + + $ferienEvents = getData($ferienEvents); + + if (!$ferienEvents) + return success([]); + + $ferienEvents = array_map(function ($event) { + $event_start = new DateTime($event->vondatum); + $event_end = new DateTime($event->bisdatum); + $event_end->modify('+1 day'); + + $interval = new DateInterval('P1D'); + $period = new DatePeriod($event_start, $interval, $event_end); + $event->dates = iterator_to_array($period); + return $event; + }, $ferienEvents); + + $start_date = new DateTime($start_date); + $start_date->setTime(0, 0, 0); + $end_date = new DateTime($end_date); + $end_date->setTime(23, 59, 59); + + $ferienEventsFlattened = []; + foreach ($ferienEvents as $ferien_event) { + foreach ($ferien_event->dates as $date) { + if ($date < $start_date || $date > $end_date) + continue; + $event = new stdClass(); + $event->bezeichnung = $ferien_event->bezeichnung; + $event->datum = $date->format('Y-m-d'); + $event->type = 'ferien'; + $ferienEventsFlattened[] = $event; + } + }; + + $today = new DateTime(); + $ferienEventsFlattened = array_map(function ($event) use ($today, $tz) { + $ferien_event = (object)array( + 'type' => 'ferien', + 'beginn' => $today->format('H:i:s'), + 'ende' => $today->format('H:i:s'), + 'isostart' => (new DateTime($event->datum . ' 00:00:00', $tz))->format('c'), + 'isoend' => (new DateTime($event->datum . ' 23:59:59', $tz))->format('c'), + 'allDayEvent' => true, + 'datum' => $event->datum, + 'topic' => $event->bezeichnung, + 'titel' => $event->bezeichnung, + 'farbe' => '00689E' + ); + return $ferien_event; + }, $ferienEventsFlattened); + + return success($ferienEventsFlattened); + } + + // start of the private functions ######################################################################################################## + + // 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($student_uid, $semester_range) + { + $this->_ci->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + + $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->_ci->BenutzergruppeModel->execReadOnlyQuery(" + SELECT * FROM tbl_benutzergruppe where uid = ? AND studiensemester_kurzbz = ?",[$student_uid, $semester]); + if(isError($benutzer_query)){ + return error(getData($benutzer_query)); + } + $benutzer_query_result = getData($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 success($benutzer_gruppen); + } + + private function fetchStudentlehrverbandFromStudiensemester($student_uid, $semester_range) + { + $this->_ci->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + + $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->_ci->BenutzergruppeModel->execReadOnlyQuery(" + SELECT * FROM tbl_studentlehrverband where student_uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]); + if(isError($lehrverband_query)){ + return error(getData($lehrverband_query)); + } + $lehrverband_query_result = getData($lehrverband_query)??[]; + + $converted_studentLehrverband= 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); + + array_push($student_lehrverband[$semester_key], $converted_studentLehrverband); + + } + + } + + // 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 success($student_lehrverband); + } + + private function applyLoadUeberSemesterHaelfte(&$semester_range) + { + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + /* + @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->_ci->StudiensemesterModel->getPreviousFrom($studiensemester); + if(isError($previous_studiensemester)) + { + return error(getData($previous_studiensemester)); + } + $previous_studiensemester = getData($previous_studiensemester); + if (count($previous_studiensemester) == 0) { + return error('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->_ci->StudiensemesterModel->getStartEndeFromStudiensemester($semester_original); + if(isError($semester_start_ende)) + { + return error(getData($semester_start_ende)); + } + $semester_start_ende = current(getData($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) + { + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + // gets all studiensemester from the student from start_date to end_date + $semester_range = $this->_ci->StudiensemesterModel->getByDateRange($start_date, $end_date); + if (isError($semester_range)) + return $semester_range; + + $semester_range = array_map( + function ($sem) { + return $sem->studiensemester_kurzbz; + }, + getData($semester_range) ?: [] + ); + + // if no studiensemester is found for the given timespan, get the nearest studiensemester + if (count($semester_range) == 0) + { + $aktuelle_studiensemester = $this->_ci->StudiensemesterModel->getNearest(); + if (isError($aktuelle_studiensemester)) + return $aktuelle_studiensemester; + + $aktuelle_studiensemester = getData($aktuelle_studiensemester); + if (count($aktuelle_studiensemester) == 0) { + return error("No aktuelles semester"); + } + $aktuelle_studiensemester = current($aktuelle_studiensemester)->studiensemester_kurzbz; + // push aktuelles semester in active semester array + array_push($semester_range, $aktuelle_studiensemester); + } + + return success($semester_range); + } +} 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..f6d7d6599 --- /dev/null +++ b/application/libraries/dashboard/DashboardLib.php @@ -0,0 +1,233 @@ +_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 = '{"' . self::USEROVERRIDE_SECTION . '": {"widgets":{}}, "custom": { "widgets" : {}}}'; + + 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 = '{"' . $section . '": { "widgets" : {}},"custom": { "widgets" : {}}}'; + + 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]) || !isset($widgets[$section]["widgets"]) || !is_array($widgets[$section])) + { + $widgets[$section] = array(); + $widgets[$section]["widgets"] = array(); + } + + $widgets[$section]["widgets"][$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]["widgets"][$widgetid])) + { + unset($widgets[$section]["widgets"][$widgetid]); + if(empty($widgets[$section]["widgets"]) && $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..2b20a7d93 --- /dev/null +++ b/application/libraries/issues/PlausicheckResolverLib.php @@ -0,0 +1,137 @@ +_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])) // check if it is an issue without explicit resolver, "self-resolving" + { + $libName = $this->_codeProducerLibMappings[$issue->fehlercode]; + + // execute same check as used for issue production + $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_PERSON_0005.php b/application/libraries/issues/resolvers/CORE_PERSON_0005.php new file mode 100644 index 000000000..1d768e70c --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_PERSON_0005.php @@ -0,0 +1,36 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->model('person/Person_model', 'PersonModel'); + + // load geburtsnation for the given person + $this->_ci->PersonModel->addSelect('geburtsnation'); + $personRes = $this->_ci->PersonModel->load($params['issue_person_id']); + + if (isError($personRes)) return $personRes; + + if (hasData($personRes)) + { + // get person data + $personData = getData($personRes)[0]; + + // if geburtsnation present, issue is resolved + return success(!isEmptyString($personData->geburtsnation)); + } + else + return success(false); // if no person found, not resolved + } +} \ No newline at end of file diff --git a/application/libraries/issues/resolvers/CORE_PERSON_0006.php b/application/libraries/issues/resolvers/CORE_PERSON_0006.php new file mode 100644 index 000000000..8b7ff9c56 --- /dev/null +++ b/application/libraries/issues/resolvers/CORE_PERSON_0006.php @@ -0,0 +1,37 @@ +_ci =& get_instance(); // get code igniter instance + + $this->_ci->load->model('codex/Uhstat1daten_model', 'UhstatModel'); + + $personRes = $this->_ci->UhstatModel->getUHSTAT1PersonData([$params['issue_person_id']]); + + if (isError($personRes)) return $personRes; + + if (hasData($personRes)) + { + // get person data + $personData = getData($personRes)[0]; + + // if person identification data present, issue is resolved + return success( + !isEmptyString($personData->ersatzkennzeichen) + || (!isEmptyString($personData->vbpkAs) && !isEmptyString($personData->vbpkBf)) + ); + } + else + return success(false); // if no person found, not resolved + } +} \ No newline at end of file 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..c1238c13d --- /dev/null +++ b/application/libraries/vertragsbestandteil/GehaltsbestandteilLib.php @@ -0,0 +1,152 @@ +loggedInUser = getAuthUID(); + $this->CI = get_instance(); + $this->CI->load->model('vertragsbestandteil/Gehaltsbestandteil_model', + 'GehaltsbestandteilModel'); + $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(); + + $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..1ecb9ac60 --- /dev/null +++ b/application/libraries/vertragsbestandteil/VertragsbestandteilLib.php @@ -0,0 +1,524 @@ +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 fetchLastVertragsbestandteilStundenBeforeAltersteilzeit($dienstverhaeltnis_id) + { + return $this->VertragsbestandteilModel->getLastVertragsbestanteilStundenBeforeAltersteilzeit($dienstverhaeltnis_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 4975af382..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' ) ? '' : ' *') ); } } @@ -528,6 +528,13 @@ class Messages_model extends CI_Model */ public function sendReply($receiver_id, $subject, $body, $relationmessage_id, $token) { + // Checks that the receiver_id, relationmessage_id and token belongs to the same message + $crossedDataResult = $this->MessageTokenModel->crossClientData($token, $relationmessage_id, $receiver_id); + if (isError($crossedDataResult)) show_error(getError($crossedDataResult)); + if (!hasData($crossedDataResult)) show_error( + 'The parameters token, relationmessage_id and receiver_id do not belong to the same message' + ); + // Retrieves message sender information $senderResult = $this->MessageTokenModel->getSenderData($receiver_id); if (isError($senderResult)) show_error(getError($senderResult)); 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/accounting/Vertragvertragsstatus_model.php b/application/models/accounting/Vertragvertragsstatus_model.php index 609394321..78a065540 100644 --- a/application/models/accounting/Vertragvertragsstatus_model.php +++ b/application/models/accounting/Vertragvertragsstatus_model.php @@ -135,7 +135,7 @@ class Vertragvertragsstatus_model extends DB_Model /** * Get all contracts, where the status had been set to 'bestellt' on given date - * @param string $string_date e.g. '01.11.2019' or special Date/Time inputs like 'YESTERDAY', 'TODAY', 'NOW' + * @param string $string_date e.g. 'YYYY-MM-DD' or special Date/Time inputs like 'YESTERDAY', 'TODAY', 'NOW' * @param bool $further_processed If true, ALL ordered contracts of that day are retrieved, even if they were * were ALSO approved/accepted/cancelled (further processed) on that same day. * @return array 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/Bisstandort_model.php b/application/models/codex/Bisstandort_model.php new file mode 100644 index 000000000..9c7e9e45b --- /dev/null +++ b/application/models/codex/Bisstandort_model.php @@ -0,0 +1,14 @@ +dbTable = 'bis.tbl_bisstandort'; + $this->pk = 'standort_code'; + } +} 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/Gsprogramm_model.php b/application/models/codex/Gsprogramm_model.php new file mode 100644 index 000000000..4fd0694dd --- /dev/null +++ b/application/models/codex/Gsprogramm_model.php @@ -0,0 +1,15 @@ +dbTable = 'bis.tbl_gsprogramm'; + $this->pk = 'gsprogramm_id'; + } + +} diff --git a/application/models/codex/Mobilitaet_model.php b/application/models/codex/Mobilitaet_model.php new file mode 100644 index 000000000..13f966d50 --- /dev/null +++ b/application/models/codex/Mobilitaet_model.php @@ -0,0 +1,14 @@ +dbTable = 'bis.tbl_mobilitaet'; + $this->pk = 'mobilitaet_id'; + } +} diff --git a/application/models/codex/Mobilitaetstyp_model.php b/application/models/codex/Mobilitaetstyp_model.php new file mode 100644 index 000000000..f93f588a0 --- /dev/null +++ b/application/models/codex/Mobilitaetstyp_model.php @@ -0,0 +1,14 @@ +dbTable = 'bis.tbl_mobilitaetstyp'; + $this->pk = 'mobilitaetstyp_kurzbz'; + } +} diff --git a/application/models/codex/Nation_model.php b/application/models/codex/Nation_model.php index 239639795..ee38c9051 100644 --- a/application/models/codex/Nation_model.php +++ b/application/models/codex/Nation_model.php @@ -3,7 +3,7 @@ class Nation_model extends DB_Model { /** - * + * */ public function __construct() { @@ -11,4 +11,4 @@ class Nation_model extends DB_Model $this->dbTable = 'bis.tbl_nation'; $this->pk = 'nation_code'; } -} \ No newline at end of file +} diff --git a/application/models/codex/Uhstat1daten_model.php b/application/models/codex/Uhstat1daten_model.php new file mode 100644 index 000000000..899f037ef --- /dev/null +++ b/application/models/codex/Uhstat1daten_model.php @@ -0,0 +1,54 @@ +dbTable = 'bis.tbl_uhstat1daten'; + $this->pk = 'uhstat1daten_id'; + } + + /** + * Gets person data needed for sending as UHSTAT1 data. + * @param array $person_id_arr + * @param string $studiensemester + * @param array $status_kurzbz + * @return object success with prestudents or error + */ + public function getUHSTAT1PersonData($person_id_arr) + { + if (!isset($person_id_arr) || isEmptyArray($person_id_arr)) return success([]); + + $params = array($person_id_arr); + + $prstQry = "SELECT + DISTINCT ON (pers.person_id) + pers.person_id, uhstat_daten.uhstat1daten_id, pers.svnr, pers.ersatzkennzeichen, pers.geburtsnation, + uhstat_daten.mutter_geburtsstaat, uhstat_daten.mutter_bildungsstaat, uhstat_daten.mutter_geburtsjahr, + uhstat_daten.mutter_bildungmax, uhstat_daten.vater_geburtsstaat, uhstat_daten.vater_bildungsstaat, + uhstat_daten.vater_geburtsjahr, uhstat_daten.vater_bildungmax, + kzVbpkAs.inhalt AS \"vbpkAs\", kzVbpkBf.inhalt AS \"vbpkBf\" + FROM + public.tbl_person pers + JOIN public.tbl_prestudent ps USING (person_id) + JOIN public.tbl_studiengang stg USING (studiengang_kz) + JOIN bis.tbl_uhstat1daten uhstat_daten USING (person_id) + LEFT JOIN public.tbl_kennzeichen kzVbpkAs ON kzVbpkAs.kennzeichentyp_kurzbz = 'vbpkAs'AND kzVbpkAs.person_id = pers.person_id AND kzVbpkAs.aktiv + LEFT JOIN public.tbl_kennzeichen kzVbpkBf ON kzVbpkBf.kennzeichentyp_kurzbz = 'vbpkBf'AND kzVbpkBf.person_id = pers.person_id AND kzVbpkBf.aktiv + WHERE + ps.bismelden + AND stg.melderelevant + AND pers.person_id IN ? + ORDER BY + pers.person_id"; + + return $this->execReadOnlyQuery( + $prstQry, + $params + ); + } +} 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/DmsFS_model.php b/application/models/content/DmsFS_model.php index 38a72d853..81443805f 100644 --- a/application/models/content/DmsFS_model.php +++ b/application/models/content/DmsFS_model.php @@ -7,7 +7,7 @@ class DmsFS_model extends FS_Model */ public function __construct() { - parent::__construct(); - $this->filepath = DMS_PATH; + parent::__construct(DMS_PATH); } -} \ No newline at end of file +} + diff --git a/application/models/content/News_model.php b/application/models/content/News_model.php index 8d636d808..ad8ecab99 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 *, TO_CHAR(campus.tbl_news.datum, ?) as datumformatted + 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) + , ['DD/MM/YYYY']); + } + + 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/content/TempFS_model.php b/application/models/content/TempFS_model.php new file mode 100644 index 000000000..ac55a24d7 --- /dev/null +++ b/application/models/content/TempFS_model.php @@ -0,0 +1,16 @@ +execQuery($query, $parametersArray); } + /** + * getAktenAccepted FAS + */ + public function getAktenFAS($person_id, $dokument_kurzbz = null, $stg_kz = null, $prestudent_id = null, $returnInhalt = false) + { + $query = 'SELECT + a.akte_id, + a.bezeichnung, + a.dokument_kurzbz, + a.titel_intern, + a.anmerkung_intern, + a.insertamum as hochgeladenamum, + a.updatevon, a.insertvon, a.uid, + a.dms_id, a.anmerkung as infotext, + a.nachgereicht, + CASE + WHEN inhalt IS NOT NULL OR a.dms_id IS NOT NULL + THEN true + ELSE false + END AS vorhanden, + a.nachgereicht_am, + ausstellungsnation, formal_geprueft_amum, archiv, + signiert, stud_selfservice, akzeptiertamum, inhalt + FROM public.tbl_akte a + WHERE a.person_id = ?'; + + $parametersArray = array($person_id); + + if (!isEmptyString($dokument_kurzbz)) + { + $query .= " AND dokument_kurzbz = ? + AND dokument_kurzbz NOT IN ('Zeugnis','DiplSupp','Bescheid')"; + array_push($parametersArray, $dokument_kurzbz); + } + + if($stg_kz != null && $prestudent_id != null) + { + $query.= " AND dokument_kurzbz not in ( + SELECT dokument_kurzbz + FROM public.tbl_dokument + JOIN public.tbl_dokumentstudiengang USING(dokument_kurzbz) + WHERE studiengang_kz= ? + AND dokument_kurzbz NOT IN( + SELECT dokument_kurzbz FROM public.tbl_dokumentprestudent + JOIN public.tbl_dokument USING(dokument_kurzbz) + WHERE prestudent_id=?))"; + array_push($parametersArray, $stg_kz); + array_push($parametersArray, $prestudent_id); + } + + $query .= ' ORDER BY erstelltam'; + + return $this->execQuery($query, $parametersArray); + } + /** * getAktenAcceptedDms */ @@ -171,7 +226,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 +239,69 @@ 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/mehrerer Personen + * + * @param integer/array $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); + + if (is_array($person_id)) + $this->db->where_in('person_id', $person_id); + else + $this->db->where('person_id', $person_id); + + $this->addOrder('erstelltam', 'DESC'); + $this->addOrder('akte_id', 'DESC'); + + return $this->loadWhere([ + 'archiv' => true + ]); + } } diff --git a/application/models/crm/Dokument_model.php b/application/models/crm/Dokument_model.php index 7ef2be716..8008202c1 100644 --- a/application/models/crm/Dokument_model.php +++ b/application/models/crm/Dokument_model.php @@ -11,4 +11,91 @@ class Dokument_model extends DB_Model $this->dbTable = 'public.tbl_dokument'; $this->pk = 'dokument_kurzbz'; } + + /** + * Loads all missing Documents of a Studiengang + * a Prestudent has not submitted + * @param integer studiengang_kz + * @param integer prestudent_id + * @param boolean archivdokumente + * Default: true. + * If false, documents that are archivable (tbl_vorlage.archivierbar e.g. certificate, notice, ...) not retrieved + * @return Array of Documents || error + */ + public function getMissingDocuments($studiengang_kz, $prestudent_id = null, $archivdokumente = false, $person_id = null) + { + $parametersArray = array($studiengang_kz); + + $qry = "SELECT + tbl_dokument.* , + tbl_dokumentstudiengang.* + FROM public.tbl_dokument + JOIN public.tbl_dokumentstudiengang USING(dokument_kurzbz) + LEFT JOIN public.tbl_vorlage ON (tbl_dokument.dokument_kurzbz = tbl_vorlage.vorlage_kurzbz) + WHERE studiengang_kz = ? "; + + if($prestudent_id) + { + array_push($parametersArray, $prestudent_id); + $qry.=" AND tbl_dokument.dokument_kurzbz NOT IN ( + SELECT dokument_kurzbz FROM public.tbl_dokumentprestudent WHERE prestudent_id= ?)"; + } + + if(!$archivdokumente) + { + $qry.=" AND (tbl_vorlage.archivierbar = FALSE OR tbl_vorlage.archivierbar IS NULL)"; + } + + $qry.=" ORDER BY tbl_dokument.dokument_kurzbz;"; + + return $this->execQuery($qry, $parametersArray); + } + + public function getUnacceptedDocuments($prestudent_id, $person_id) + { + $parametersArray = array($person_id, $prestudent_id); + + $qry = " SELECT + a.akte_id, + a.bezeichnung, + a.dokument_kurzbz, + a.titel_intern, + a.anmerkung_intern, + a.insertamum as hochgeladenamum, + a.updatevon, + a.insertvon, + a.uid, + a.dms_id, + a.anmerkung as infotext, + a.nachgereicht, + CASE + WHEN inhalt IS NOT NULL + OR a.dms_id IS NOT NULL THEN true + ELSE false + END AS vorhanden, + a.nachgereicht_am, + ausstellungsnation, + formal_geprueft_amum, + archiv, + signiert, + stud_selfservice, + akzeptiertamum, + inhalt + FROM + public.tbl_akte a + WHERE + a.person_id = ? + AND a.dokument_kurzbz NOT IN ( + SELECT + dokument_kurzbz + FROM + public.tbl_dokumentprestudent + WHERE + prestudent_id = ? + ) + AND a.dokument_kurzbz NOT IN ('Zeugnis','DiplSupp','Bescheid') + ORDER BY a.dokument_kurzbz;"; + + return $this->execQuery($qry, $parametersArray); + } } diff --git a/application/models/crm/Dokumentprestudent_model.php b/application/models/crm/Dokumentprestudent_model.php index ab4764479..6b1c222a8 100644 --- a/application/models/crm/Dokumentprestudent_model.php +++ b/application/models/crm/Dokumentprestudent_model.php @@ -10,6 +10,7 @@ class Dokumentprestudent_model extends DB_Model parent::__construct(); $this->dbTable = 'public.tbl_dokumentprestudent'; $this->pk = array('prestudent_id', 'dokument_kurzbz'); + $this->hasSequence = false; } /** @@ -68,4 +69,41 @@ class Dokumentprestudent_model extends DB_Model return $result; } + + /** + * Loads all Documents of Prestudent, already submitted + * @param integer prestudent_id + * @param boolean archivdokumente Default true. if false, archivable Documents (tbl_vorlage.archivierbar zB Zeugnis, Bescheid, ...) not retrieved + * @return Array of Documents || error + */ + public function getPrestudentDokumente($prestudent_id, $archivdokumente = true) + { + $parametersArray = array($prestudent_id); + + $qry = "SELECT + d.bezeichnung, + d.dokument_kurzbz, + dp.datum as Docdatum, + dp.mitarbeiter_uid as DocMitarbeiter_uid, + dp.insertamum as Docinsertamum, + dp.prestudent_id, + CONCAT(p.vorname, ' ', p.nachname) as insertvonma + FROM + public.tbl_dokumentprestudent dp + JOIN public.tbl_dokument d USING(dokument_kurzbz) + LEFT JOIN public.tbl_vorlage v ON (d.dokument_kurzbz = v.vorlage_kurzbz) + LEFT JOIN public.tbl_benutzer bn ON (bn.uid = dp.mitarbeiter_uid) + LEFT JOIN public.tbl_person p ON (p.person_id = bn.person_id) + WHERE + prestudent_id = ?"; + + if(!$archivdokumente) + { + $qry.=" AND (v.archivierbar = FALSE OR v.archivierbar IS NULL)"; + } + + $qry.=" ORDER BY d.bezeichnung ASC"; + + return $this->execQuery($qry, $parametersArray); + } } diff --git a/application/models/crm/Konto_model.php b/application/models/crm/Konto_model.php index 840bb290c..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 */ @@ -73,4 +288,119 @@ class Konto_model extends DB_Model return error('Failed to load Payment'); } } + + public function getStudienbeitraege($uid, $buchungstypen) + { + $query = 'SELECT konto.studiensemester_kurzbz + FROM public.tbl_konto konto + JOIN public.tbl_studiensemester studiensemester ON konto.studiensemester_kurzbz = studiensemester.studiensemester_kurzbz, + public.tbl_benutzer, + public.tbl_student + WHERE tbl_benutzer.uid = \'' . $uid . '\' + AND tbl_benutzer.uid = tbl_student.student_uid + AND tbl_benutzer.person_id = konto.person_id + AND konto.studiengang_kz = tbl_student.studiengang_kz + AND konto.buchungstyp_kurzbz IN (\'' . $buchungstypen . '\') + AND 0 = ( + SELECT sum(betrag) + FROM public.tbl_konto skonto + WHERE skonto.buchungsnr = konto.buchungsnr_verweis + OR skonto.buchungsnr_verweis = konto.buchungsnr_verweis + ) + ORDER BY studiensemester.start DESC; + '; + + return $this->execQuery($query); + } + + public function checkStudienbeitrag($uid, $stsem, $buchungstypen) + { + $query = 'SELECT tbl_konto.buchungsnr, + tbl_konto.buchungsdatum + FROM public.tbl_konto, + public.tbl_benutzer, + public.tbl_student + WHERE + tbl_konto.studiensemester_kurzbz = \'' . $stsem . '\' + AND tbl_benutzer.uid = \'' . $uid . '\' + AND tbl_benutzer.uid = tbl_student.student_uid + AND tbl_benutzer.person_id = tbl_konto.person_id + AND tbl_konto.studiengang_kz=tbl_student.studiengang_kz + AND tbl_konto.buchungstyp_kurzbz IN (\'' . $buchungstypen . '\') + AND 0 >= ( + SELECT sum(betrag) + 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 b7804952e..ff56c3268 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); @@ -556,13 +615,14 @@ class Prestudent_model extends DB_Model */ public function getOrganisationunitsByPersonId($person_id) { - $query = 'SELECT o.oe_kurzbz, + $query = 'SELECT DISTINCT o.oe_kurzbz, 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'; @@ -611,7 +677,7 @@ class Prestudent_model extends DB_Model )); } - public function getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt) + public function getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt, $ignoreAbgeschickt = false) { $query = "SELECT ps.prestudent_id FROM public.tbl_prestudentstatus pss @@ -621,22 +687,42 @@ class Prestudent_model extends DB_Model JOIN lehre.tbl_studienordnung so USING(studienordnung_id) WHERE ps.person_id = ? AND UPPER(so.studiengangkurzbzlang || ':' || sp.orgform_kurzbz) = ? - AND pss.studiensemester_kurzbz = ? - AND"; + AND pss.studiensemester_kurzbz = ?"; - if ($abgeschickt === 'true') - $query .= " EXISTS"; - else - $query .= " NOT EXISTS"; + if (!$ignoreAbgeschickt) + { + $query .= "AND"; - $query .= " (SELECT 1 FROM public.tbl_prestudentstatus spss + if ($abgeschickt === 'true') + $query .= " EXISTS"; + else + $query .= " NOT EXISTS"; + + $query .= " (SELECT 1 FROM public.tbl_prestudentstatus spss JOIN public.tbl_prestudent sps USING(prestudent_id) WHERE sps.prestudent_id = ps.prestudent_id AND spss.bewerbung_abgeschicktamum IS NOT NULL)"; + } return $this->execQuery($query, array($person, $studiengang, $studienSemester)); } + public function getByPersonWithoutLehrgang($person, $studienSemester) + { + $query = "SELECT DISTINCT(ps.prestudent_id) + FROM public.tbl_prestudentstatus pss + JOIN public.tbl_prestudent ps USING(prestudent_id) + JOIN public.tbl_studiengang sg USING(studiengang_kz) + JOIN lehre.tbl_studienplan sp USING(studienplan_id) + JOIN lehre.tbl_studienordnung so USING(studienordnung_id) + WHERE ps.person_id = ? + AND (sg.typ = 'b' OR sg.typ = 'm') + AND pss.studiensemester_kurzbz = ?"; + + return $this->execQuery($query, array($person, $studienSemester)); + } + + /** * Gets förderrelevant flag for a prestudent, from prestudent, or, if not set on prestudent level, from studiengang * @param int $prestudent_id @@ -667,4 +753,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 3335de021..de91319b9 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 */ @@ -52,6 +136,24 @@ class Prestudentstatus_model extends DB_Model return $this->execQuery($query, $parametersArray); } + /** + * Liefert den Ersten Status eines Prestudenten mit der übergebenen Statuskurzbezeichnung. + * + * @param $prestudent_id + * @param $status_kurzbz + * @return array + */ + public function getFirstStatus($prestudent_id, $status_kurzbz) + { + $this->addOrder('datum, insertamum, ext_id'); + $this->addLimit(1); + + return $this->loadWhere(array( + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz + )); + } + /** * updateStufe */ @@ -208,4 +310,350 @@ 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('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('tbl_prestudentstatus.bestaetigtvon'); + $this->addSelect('tbl_prestudentstatus.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..a685b01cd 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 @@ -511,4 +511,250 @@ class Reihungstest_model extends DB_Model return $this->execQuery($query, array($date, $studiengang_kz)); } -} \ No newline at end of file + + /** + * Loads all placement tests of a given person + * @param integer $person_id + * @return array Returns object array with data of placement tests + */ + public function getReihungstestPerson($person_id) + { + $query = ' + SELECT + tbl_rt_person.*, + tbl_reihungstest.studiengang_kz, + tbl_reihungstest.anmerkung, + tbl_reihungstest.datum, + tbl_reihungstest.uhrzeit, + tbl_reihungstest.ext_id, + tbl_reihungstest.max_teilnehmer, + tbl_reihungstest.oeffentlich, + tbl_reihungstest.freigeschaltet, + tbl_reihungstest.studiensemester_kurzbz as studiensemester, + tbl_reihungstest.stufe, + tbl_reihungstest.anmeldefrist, + tbl_reihungstest.aufnahmegruppe_kurzbz, + tbl_studiengang.typ, + UPPER(typ::varchar(1) || kurzbz) AS stg_kuerzel, + so.studiengangbezeichnung, + so.studiengangbezeichnung_englisch, + so.studiengangkurzbzlang + FROM + public.tbl_rt_person + JOIN public.tbl_reihungstest ON (rt_id=reihungstest_id) + JOIN public.tbl_studiengang ON tbl_reihungstest.studiengang_kz = tbl_studiengang.studiengang_kz + JOIN lehre.tbl_studienplan sp USING(studienplan_id) + JOIN lehre.tbl_studienordnung so USING(studienordnung_id) + WHERE + tbl_rt_person.person_id = ? + ORDER BY datum, uhrzeit ASC'; + + return $this->execQuery($query, array($person_id)); + } + + /** + * Calculates Result of Placement Test for a given Person and given placementtest + * and with taking account of weighting per area + * + * @param $person_id ID of Person + * @param $punkte if true result is points else result is percentage of sum + * @param $reihungstest_id ID of Placementtest + * @param $weightedArray array of weighting per area (gewicht per gebiet_id) + * @return float result + */ + public function getReihungstestErgebnisPerson($person_id, $punkte, $reihungstest_id, $weightedArray = null) + { + $parametersArray = array($reihungstest_id); + + $qry = " + SELECT DISTINCT ON (vw_auswertung_ablauf.gebiet_id) gebiet_id, + vw_auswertung_ablauf.*, + tbl_studiengang.typ + FROM + testtool.vw_auswertung_ablauf + JOIN + public.tbl_studiengang USING (studiengang_kz) + WHERE + reihungstest_id = ? "; + + //using prestudent Status to avoid to get the sum of more than 1 placement tests + $qry .= " + AND prestudent_id = ( + SELECT + prestudent_id + FROM + public.tbl_rt_person + JOIN + public.tbl_prestudent USING(person_id) + JOIN + public.tbl_prestudentstatus USING (prestudent_id, studienplan_id) + JOIN + tbl_reihungstest ON ( + tbl_rt_person.rt_id = tbl_reihungstest.reihungstest_id + ) + WHERE + tbl_rt_person.person_id = ? + AND + tbl_rt_person.rt_id = ? + AND + tbl_prestudentstatus.status_kurzbz = 'Interessent' + AND + tbl_prestudentstatus.studiensemester_kurzbz = tbl_reihungstest.studiensemester_kurzbz + ORDER BY tbl_reihungstest.datum DESC, tbl_prestudent.priorisierung ASC LIMIT 1 + ) + "; + array_push($parametersArray, $person_id); + array_push($parametersArray, $reihungstest_id); + + $resultRtPerson = $this->execQuery($qry, $parametersArray); + + $ergebnis = 0; + $summeGewicht = 0; + + foreach ($resultRtPerson->retval as $row) + { + $prozent = 0; + if($row->punkte>=$row->maxpunkte) + { + $prozent = 100; + $row->punkte = $row->maxpunkte; + } + else + $prozent = (($row->punkte + $row->offsetpunkte)/($row->maxpunkte + $row->offsetpunkte))*100; + + if($punkte == 'true') + { + if($row->punkte) + { + $ergebnis += $row->punkte; + } + } + else + { + if ($row->punkte) + { + $gew = isset($weightedArray[$row->gebiet_id]) ? $weightedArray[$row->gebiet_id] : 1; + $ergebnis += $prozent * $gew; + $summeGewicht += $gew; + } + } + } + $return = $summeGewicht > 0 + ? number_format($ergebnis/$summeGewicht, 4, '.', '') + : number_format($ergebnis, 4, '.', ''); + + return $return; + } + + /** + * returns Reihungstests for given studyplans and include_ids + * + * @param Array $studienplan_arr array of studienplaene + * @param Array $include_ids array of include_ids + * @return Array List of Reihungstests + */ + public function getReihungstestByStudyPlanAndIds($studienplan_arr, $include_ids = null) + { + $studienplan_ids_string = implode(',', $studienplan_arr); + $studienplan_arr = explode(',', $studienplan_ids_string); + + $parametersArray = array($studienplan_arr); + + $qry = " + SELECT + distinct a.*, + CASE EXTRACT(DOW FROM a.datum) + WHEN 0 THEN 'So' + WHEN 1 THEN 'Mo' + WHEN 2 THEN 'Di' + WHEN 3 THEN 'Mi' + WHEN 4 THEN 'Do' + WHEN 5 THEN 'Fr' + WHEN 6 THEN 'Sa' + END AS wochentag, + sg.kurzbzlang as stg, + ( + SELECT count(*) FROM public.tbl_rt_person + WHERE rt_id = a.reihungstest_id + ) as angemeldete_teilnehmer + FROM + public.tbl_reihungstest a + JOIN public.tbl_rt_studienplan USING(reihungstest_id) + JOIN public.tbl_studiengang sg USING(studiengang_kz) + WHERE studienplan_id IN ?"; + + if($include_ids && is_array($include_ids) && count($include_ids) > 0) + { + $include_ids_string = implode(',', $include_ids); + $include_ids = explode(',', $include_ids_string); + + array_push($parametersArray, $include_ids); + + $qry .= "OR reihungstest_id in ?"; + } + $qry .= "ORDER BY a.datum DESC"; + + return $this->execQuery($qry, $parametersArray); + } + /** + * returns Reihungstests for given studyplans and include_ids + * + * @param Integer $studiengang_kz + * @param $include_id optional (here null) + * @return Array List of Reihungstests + */ + public function getZukuenftigeReihungstestStg($studiengang_kz, $include_id = null) + { + $parametersArray = array($studiengang_kz, $studiengang_kz, $include_id); + + $qry = " + SELECT *, + CASE EXTRACT(DOW FROM a.datum) + WHEN 0 THEN 'So' + WHEN 1 THEN 'Mo' + WHEN 2 THEN 'Di' + WHEN 3 THEN 'Mi' + WHEN 4 THEN 'Do' + WHEN 5 THEN 'Fr' + WHEN 6 THEN 'Sa' + END AS wochentag, + ( + SELECT count(*) FROM public.tbl_prestudent + WHERE reihungstest_id=a.reihungstest_id + ) as angemeldete_teilnehmer + FROM + ( + SELECT *, '1' as sortierung, + ( + SELECT upper(typ || kurzbz) FROM public.tbl_studiengang + WHERE studiengang_kz=tbl_reihungstest.studiengang_kz + ) as stg + FROM + public.tbl_reihungstest + WHERE + datum>=now()-'1 days'::interval AND studiengang_kz=? + UNION + SELECT *, '2' as sortierung, + ( + SELECT upper(typ || kurzbz) FROM public.tbl_studiengang + WHERE studiengang_kz=tbl_reihungstest.studiengang_kz + ) as stg + FROM + public.tbl_reihungstest + WHERE datum>=now()-'1 days'::interval AND studiengang_kz!=? + UNION + SELECT *, '0' as sortierung, + ( + SELECT upper(typ || kurzbz) FROM public.tbl_studiengang + WHERE studiengang_kz=tbl_reihungstest.studiengang_kz + ) as stg + FROM + public.tbl_reihungstest + WHERE reihungstest_id=? + ORDER BY sortierung, stg, datum + ) a + "; + + return $this->execQuery($qry, $parametersArray); + } +} 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 4d1c84521..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 @@ -66,4 +252,31 @@ class Student_model extends DB_Model return $result->retval[0]->student_uid; } + + public function searchStudent($filter) + { + $this->addSelect('vorname, nachname, gebdatum, person.person_id, student_uid'); + $this->addJoin('public.tbl_prestudent ps', 'prestudent_id'); + $this->addJoin('public.tbl_person person', 'person_id'); + + $result = $this->loadWhere( + "lower(student_uid) like ".$this->db->escape('%'.$filter.'%')." + 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.'%') + ); + + 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/Abgabe_model.php b/application/models/education/Abgabe_model.php index c68bc55f4..5a18c4fe3 100644 --- a/application/models/education/Abgabe_model.php +++ b/application/models/education/Abgabe_model.php @@ -11,4 +11,5 @@ class Abgabe_model extends DB_Model $this->dbTable = 'campus.tbl_abgabe'; $this->pk = 'abgabe_id'; } + } diff --git a/application/models/education/Abschlusspruefung_model.php b/application/models/education/Abschlusspruefung_model.php index 268e786cb..0ba8fd55c 100644 --- a/application/models/education/Abschlusspruefung_model.php +++ b/application/models/education/Abschlusspruefung_model.php @@ -113,4 +113,61 @@ class Abschlusspruefung_model extends DB_Model return success($abschlusspruefungdata); } + + /** + * Gets data of an Abschlusspruefung + * @param $student_uid + * @return object + */ + public function getAbschlusspruefungForPrestudent($student_uid) + { + $qry = " + SELECT + exam.*, + CONCAT( + person_pruefer1.nachname || ' ', + person_pruefer1.vorname, + COALESCE(' ' || person_pruefer1.titelpre) + ) AS person_pruefer1, + CONCAT( + person_pruefer2.nachname || ' ', + person_pruefer2.vorname, + COALESCE(' ' || person_pruefer2.titelpre) + ) AS person_pruefer2, + CONCAT( + person_pruefer3.nachname || ' ', + person_pruefer3.vorname, + COALESCE(' ' || person_pruefer3.titelpre) + ) AS person_pruefer3, + CONCAT( + person_vorsitzender.nachname || ' ', + person_vorsitzender.vorname, + COALESCE(' ' || person_vorsitzender.titelpre) + ) AS person_vorsitzender, + datum, + freigabedatum, + sponsion, + uhrzeit, + person_pruefer1.nachname as p1_nachname, + person_pruefer2.nachname as p2_nachname, + person_pruefer3.nachname as p3_nachname, + person_vorsitzender.nachname as vorsitz_nachname, + beurteilung.bezeichnung as beurteilung_bezeichnung, + antritt.bezeichnung as antritt_bezeichnung + FROM + lehre.tbl_abschlusspruefung exam + JOIN lehre.tbl_pruefungstyp USING (pruefungstyp_kurzbz) + LEFT JOIN public.tbl_benutzer ben_vorsitzender ON (ben_vorsitzender.uid = vorsitz) + LEFT JOIN public.tbl_person person_vorsitzender ON (ben_vorsitzender.person_id = person_vorsitzender.person_id) + LEFT JOIN public.tbl_person person_pruefer1 ON (person_pruefer1.person_id = pruefer1) + LEFT JOIN public.tbl_person person_pruefer2 ON (person_pruefer2.person_id = pruefer2) + LEFT JOIN public.tbl_person person_pruefer3 ON (person_pruefer3.person_id = pruefer3) + LEFT JOIN lehre.tbl_abschlussbeurteilung beurteilung USING (abschlussbeurteilung_kurzbz) + LEFT JOIN lehre.tbl_abschlusspruefung_antritt antritt USING (pruefungsantritt_kurzbz) + WHERE student_uid = ? + ORDER BY exam.datum DESC + "; + + return $this->execQuery($qry, array('student_uid' => $student_uid)); + } } diff --git a/application/models/education/Akadgrad_model.php b/application/models/education/Akadgrad_model.php new file mode 100644 index 000000000..92762a525 --- /dev/null +++ b/application/models/education/Akadgrad_model.php @@ -0,0 +1,14 @@ +dbTable = 'lehre.tbl_akadgrad'; + $this->pk = 'akadgrad_id'; + } +} \ No newline at end of file diff --git a/application/models/education/Anrechnung_model.php b/application/models/education/Anrechnung_model.php index ebecf4118..0b81be80c 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 )); @@ -200,4 +202,66 @@ class Anrechnung_model extends DB_Model return success(); } + + /** + * Get Anrechnungsdata for Table Anrechnungen + * + * @param $prestudent_id + * @return array + */ + public function getAnrechnungsData($prestudent_id) + { + $qry = ' + SELECT + lehre.tbl_anrechnung.anrechnung_id, + lehre.tbl_anrechnung.prestudent_id, + lehre.tbl_anrechnung.lehrveranstaltung_id, + lehre.tbl_lehrveranstaltung.bezeichnung AS bez_lehrveranstaltung, + lehre.tbl_anrechnung_begruendung.bezeichnung AS begruendung, + lehre.tbl_anrechnung_anrechnungstatus.status_kurzbz AS status, + genehmigt_von, + lehre.tbl_anrechnung.insertamum, + lehre.tbl_anrechnung.insertvon, + lehre.tbl_anrechnung.updateamum, + lehre.tbl_anrechnung.updatevon, + lehrveranstaltung_id_kompatibel, + lv_comp.bezeichnung as lehrveranstaltung_bez_kompatibel, + count(nz.notizzuordnung_id) AS notizen_anzahl + FROM + lehre.tbl_anrechnung + JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) + LEFT JOIN lehre.tbl_lehrveranstaltung lv_comp ON (lehre.tbl_anrechnung.lehrveranstaltung_id_kompatibel = lv_comp.lehrveranstaltung_id) + JOIN lehre.tbl_anrechnung_begruendung USING (begruendung_id) + LEFT JOIN lehre.tbl_anrechnung_anrechnungstatus ON (lehre.tbl_anrechnung_anrechnungstatus.anrechnung_id = lehre.tbl_anrechnung.anrechnung_id) + AND lehre.tbl_anrechnung_anrechnungstatus.insertamum = ( + SELECT MAX(insertamum) + FROM lehre.tbl_anrechnung_anrechnungstatus + WHERE anrechnung_id = lehre.tbl_anrechnung.anrechnung_id + ) + LEFT JOIN lehre.tbl_anrechnungstatus USING (status_kurzbz) + LEFT JOIN public.tbl_notizzuordnung nz ON (nz.anrechnung_id = lehre.tbl_anrechnung.anrechnung_id) + WHERE + lehre.tbl_anrechnung.prestudent_id = ? + GROUP BY + nz.anrechnung_id, + lehre.tbl_anrechnung.anrechnung_id, + lehre.tbl_anrechnung.prestudent_id, + lehre.tbl_anrechnung.lehrveranstaltung_id, + bez_lehrveranstaltung, + begruendung, + status, + genehmigt_von, + lehre.tbl_anrechnung.insertamum, + lehre.tbl_anrechnung.insertvon, + lehre.tbl_anrechnung.updateamum, + lehre.tbl_anrechnung.updatevon, + lehrveranstaltung_id_kompatibel, + lehrveranstaltung_bez_kompatibel + ORDER BY + lehre.tbl_anrechnung.updateamum ASC + '; + + return $this->execQuery($qry, array($prestudent_id)); + + } } diff --git a/application/models/education/Anrechnunganrechnungstatus_model.php b/application/models/education/Anrechnunganrechnungstatus_model.php new file mode 100644 index 000000000..68b319506 --- /dev/null +++ b/application/models/education/Anrechnunganrechnungstatus_model.php @@ -0,0 +1,14 @@ +dbTable = 'lehre.tbl_anrechnung_anrechnungstatus'; + $this->pk = 'anrechnungstatus_id'; + } +} 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/Anwesenheit_model.php b/application/models/education/Anwesenheit_model.php index 80a1fc111..b2c78fe02 100644 --- a/application/models/education/Anwesenheit_model.php +++ b/application/models/education/Anwesenheit_model.php @@ -11,4 +11,193 @@ class Anwesenheit_model extends DB_Model $this->dbTable = 'campus.tbl_anwesenheit'; $this->pk = 'anwesenheit_id'; } + + /** + * Laedt die Anwesenheiten in Prozent von Studierenden bei Lehrveranstaltungen + * Wenn die StudentUID uebergeben wird, werden alle Lehrveranstaltungen zu denen der Studierenden zugeteilt ist inkl Prozent der Anwesenheit + * Wenn die LehrveranstaltungID uebergeben wird, werden alle Studierenden geholt die zugeteilt sind inkl Prozent der Anwesenheit + * Es werden pro Student die Anwesenheiten berechnet aufgrund der Lehreinheit zu der sie zugeordnet sind + * + * @param string $studiensemester_kurzbz + * @param string|null (optional) $student_uid + * @param integer|null (optional) $lehrveranstaltung_id + * + * @return stdClass + */ + public function loadAnwesenheitStudiensemester($studiensemester_kurzbz, $student_uid = null, $lehrveranstaltung_id = null) + { + $this->addSelect("vorname"); + $this->addSelect("nachname"); + $this->addSelect("wahlname"); + $this->addSelect("lehrveranstaltung_id"); + $this->addSelect("bezeichnung"); + $this->addSelect("gruppe"); + $this->addSelect("student_uid AS uid"); + $this->addSelect("COUNT(stundenplan_id) AS gesamtstunden"); + $this->addSelect("COALESCE(anwesend.summe, 0) AS anwesend"); + $this->addSelect("COALESCE(nichtanwesend.summe, 0) AS nichtanwesend"); + $this->addSelect("COALESCE(anwesend.summe, 0) + COALESCE(nichtanwesend.summe, 0) AS erfassteanwesenheit"); + $this->addSelect("CASE + WHEN COUNT(stundenplan_id) = 0 OR COALESCE(anwesend.summe, 0) + COALESCE(nichtanwesend.summe, 0) = 0 + THEN 100 + ELSE TRUNC(100-(100/COUNT(stundenplan_id)*COALESCE(nichtanwesend.summe, 0)), 2) + END AS prozent"); + + + $this->db->join("( + SELECT + semester::text AS gruppe, + public.tbl_studentlehrverband.studiensemester_kurzbz, + student_uid, + studiengang_kz + FROM public.tbl_studentlehrverband + WHERE studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + + UNION + + SELECT + semester || verband AS gruppe, + public.tbl_studentlehrverband.studiensemester_kurzbz, + student_uid, + studiengang_kz + FROM public.tbl_studentlehrverband + WHERE studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + + UNION + + SELECT + semester || verband || gruppe AS gruppe, + public.tbl_studentlehrverband.studiensemester_kurzbz, + student_uid, + studiengang_kz + FROM public.tbl_studentlehrverband + WHERE studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + + UNION + + SELECT + gruppe_kurzbz AS gruppe, + public.tbl_benutzergruppe.studiensemester_kurzbz, + uid AS student_uid, + studiengang_kz + FROM public.tbl_benutzergruppe + JOIN public.tbl_gruppe USING (gruppe_kurzbz) + WHERE studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + ) a", "gruppe,studiensemester_kurzbz,studiengang_kz", "", false); + $this->addJoin("public.tbl_benutzer b", "b.uid = student_uid"); + $this->addJoin("public.tbl_person p", "person_id"); + $this->db->join("( + SELECT + lehrveranstaltung_id, + studiensemester_kurzbz, uid AS student_uid, + SUM(einheiten) AS summe + FROM campus.tbl_anwesenheit a + JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + WHERE anwesend = TRUE + AND studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + GROUP BY + lehrveranstaltung_id, + bezeichnung, + uid, + studiensemester_kurzbz + ) anwesend", "lehrveranstaltung_id,student_uid,studiensemester_kurzbz", "LEFT", false); + $this->db->join("( + SELECT + lehrveranstaltung_id, + studiensemester_kurzbz, + uid AS student_uid, + SUM(einheiten) AS summe + FROM campus.tbl_anwesenheit a + JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + WHERE anwesend = FALSE + AND studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + GROUP BY + lehrveranstaltung_id, bezeichnung, uid, studiensemester_kurzbz + ) nichtanwesend", "lehrveranstaltung_id,student_uid,studiensemester_kurzbz", "LEFT", false); + + $this->addGroupBy("vorname"); + $this->addGroupBy("nachname"); + $this->addGroupBy("wahlname"); + $this->addGroupBy("lehrveranstaltung_id"); + $this->addGroupBy("bezeichnung"); + $this->addGroupBy("gruppe"); + $this->addGroupBy("student_uid"); + $this->addGroupBy("anwesend.summe"); + $this->addGroupBy("nichtanwesend.summe"); + + + $where = [ + "lehrveranstaltung_id >" => 0 + ]; + + if ($student_uid) + $where["student_uid"] = $student_uid; + + if ($lehrveranstaltung_id) + $where["lehrveranstaltung_id"] = $lehrveranstaltung_id; + + if ($lehrveranstaltung_id) { + $this->addOrder("nachname"); + $this->addOrder("vorname"); + } elseif ($student_uid) { + $this->addOrder("bezeichnung"); + } + + + $tmp = $this->dbTable; + + $this->dbTable = "( + SELECT + SUM(stundenplan_id) AS stundenplan_id, + datum, + stunde, + lehrveranstaltung_id, + bezeichnung, + studiensemester_kurzbz, + studiengang_kz, + TRIM( + CASE + WHEN stp.gruppe_kurzbz IS NOT NULL + THEN stp.gruppe_kurzbz + ELSE stp.semester || ( + CASE + WHEN verband IS NULL + THEN '' + ELSE stp.verband + END + ) || ( + CASE + WHEN stp.gruppe IS NULL + THEN '' + ELSE stp.gruppe + END + ) + END + ) AS gruppe + FROM lehre.tbl_lehrveranstaltung lv + JOIN lehre.tbl_lehreinheit le USING (lehrveranstaltung_id) + JOIN lehre.tbl_stundenplan stp USING (lehreinheit_id,studiengang_kz) + WHERE studiensemester_kurzbz = " . $this->escape($studiensemester_kurzbz) . " + AND (titel NOT LIKE '%Nebenprüfung%' OR titel IS NULL) + GROUP BY + datum, + stunde, + lehrveranstaltung_id, + bezeichnung, + studiensemester_kurzbz, + studiengang_kz, + stp.gruppe_kurzbz, + stp.semester, + stp.verband, + stp.gruppe + ) x"; + + $result = $this->loadWhere($where); + + $this->dbTable = $tmp; + + return $result; + } } 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/LePruefung_model.php b/application/models/education/LePruefung_model.php index ac6c7f9b2..6e51f1975 100644 --- a/application/models/education/LePruefung_model.php +++ b/application/models/education/LePruefung_model.php @@ -11,4 +11,45 @@ class LePruefung_model extends DB_Model $this->dbTable = 'lehre.tbl_pruefung'; $this->pk = 'pruefung_id'; } + + /** + * gets all Pruefungen for a student_uid + * @param string $student_uid + * @param string $studiensemester_kurzbz + * + * @return stdClass + */ + public function getPruefungenByStudentuid($student_uid, $studiensemester_kurzbz = null) + { + $this->addSelect('tbl_pruefung.datum'); + $this->addSelect("TO_CHAR(tbl_pruefung.datum::timestamp, 'DD.MM.YYYY') AS format_datum"); + $this->addSelect('tbl_pruefung.anmerkung'); + $this->addSelect('tbl_pruefung.pruefungstyp_kurzbz'); + $this->addSelect('tbl_pruefung.pruefung_id'); + $this->addSelect('tbl_pruefung.lehreinheit_id'); + $this->addSelect('tbl_pruefung.student_uid'); + $this->addSelect('tbl_pruefung.mitarbeiter_uid'); + $this->addSelect('tbl_pruefung.punkte'); + + $this->addSelect('tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung'); + $this->addSelect('tbl_lehrveranstaltung.lehrveranstaltung_id'); + $this->addSelect('tbl_note.bezeichnung as note_bezeichnung'); + $this->addSelect('tbl_pruefungstyp.beschreibung as typ_beschreibung'); + $this->addSelect('tbl_lehreinheit.studiensemester_kurzbz as studiensemester_kurzbz'); + + $this->addJoin('lehre.tbl_lehreinheit', 'lehre.tbl_pruefung.lehreinheit_id=lehre.tbl_lehreinheit.lehreinheit_id'); + $this->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id'); + $this->addJoin('lehre.tbl_note', 'note'); + $this->addJoin('lehre.tbl_pruefungstyp', 'pruefungstyp_kurzbz'); + + if ($studiensemester_kurzbz) + $this->db->where("tbl_lehreinheit.studiensemester_kurzbz = ", $studiensemester_kurzbz); + + $this->addOrder('tbl_pruefung.datum', 'DESC'); + $this->addOrder('tbl_pruefung.pruefung_id', 'DESC'); + + return $this->loadWhere([ + 'student_uid' => $student_uid + ]); + } } diff --git a/application/models/education/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php index 10c122b94..fadb7e113 100644 --- a/application/models/education/Lehreinheit_model.php +++ b/application/models/education/Lehreinheit_model.php @@ -28,10 +28,15 @@ class Lehreinheit_model extends DB_Model { $lehreinheiten = array(); + $this->addSelect( + 'lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrform_kurzbz, + stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, + sprache, lehre, unr, lvnr, lehrfach_id, gewicht' + ); $this->addOrder('lehreinheit_id'); $les = $this->loadWhere( array('lehrveranstaltung_id' => $lehrveranstaltung_id, - 'studiensemester_kurzbz' => $studiensemester) + 'studiensemester_kurzbz' => $studiensemester) ); if (hasData($les)) @@ -113,4 +118,194 @@ 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; + } + + /** + * Gets Lehreinheiten for Lehrveranstaltungen in a Studiensemester. + * Without using tbl_lehrfach: bezeichnung and kurzbz ALWAYS from lehrveranstaltung + * @param $lehrveranstaltung_id + * @param $studiensemester + * @return array with Lehreinheiten and their Lehreinheitgruppen + */ + public function getLesFromLvIds($lehrveranstaltung_id, $studiensemester_kurzbz = null) + { + $params = array($lehrveranstaltung_id); + + $query = " + SELECT + lv.lehrveranstaltung_id, + le.lehreinheit_id, + le.lehrform_kurzbz, + lv.kurzbz, + lv.bezeichnung, + lv.semester, + ( + SELECT + STRING_AGG(CONCAT(leg.semester, leg.verband, leg.gruppe), ' ') + FROM lehre.tbl_lehreinheitgruppe leg + WHERE leg.lehreinheit_id = le.lehreinheit_id + ) AS gruppe, + STRING_AGG(tma.kurzbz, ' ') as kuerzel + FROM + lehre.tbl_lehreinheit le + JOIN + lehre.tbl_lehrveranstaltung lv ON lv.lehrveranstaltung_id = le.lehrveranstaltung_id + JOIN + lehre.tbl_lehreinheitmitarbeiter ma USING (lehreinheit_id) + JOIN + public.tbl_mitarbeiter tma USING (mitarbeiter_uid) + WHERE + lv.lehrveranstaltung_id = ? + "; + + if (isset($studiensemester_kurzbz)) + { + $query .= " AND le.studiensemester_kurzbz = ?"; + $params[] = $studiensemester_kurzbz; + } + + $query .=" + GROUP BY + lv.lehrveranstaltung_id, + le.lehreinheit_id, + le.lehrform_kurzbz, + lv.kurzbz, + lv.bezeichnung, + lv.semester + ORDER BY + le.lehreinheit_id; + "; + + return $this->execQuery($query, $params); + } } 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 8517d7f9d..3eb4d33a2 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -15,6 +15,192 @@ class Lehrveranstaltung_model extends DB_Model $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); } + /** + * Get all Templates and its assigned Lehrveranstaltungen of given Studiensemester and Oes. + * Lvs are queried via actual Studienordnung and Studienplan. + * + * @param null|string $studiensemester_kurzbz + * @param null|array $oes + * @param null $lehrveranstaltung_id Queries certain LV only + * @return array|stdClass|null + */ + public function getTemplateLvTree($studiensemester_kurzbz = null, $oes = null, $studienjahr_kurzbz = null){ + + if (is_string($studiensemester_kurzbz) && is_string($studienjahr_kurzbz)) + { + return error('Query not possible for both studiensemester and studienjahr'); + } + + $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_string($studienjahr_kurzbz)) { + /* filter by studiensemester */ + $params[] = $studienjahr_kurzbz; + $qry .= ' + AND stplsem.studiensemester_kurzbz IN ( + SELECT studiensemester_kurzbz + FROM public.tbl_studiensemester + WHERE studienjahr_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 + -- Sort by lv.bezeichnung + lv.bezeichnung, + -- Within each group, ensure templates appear first + CASE + WHEN lv.lehrtyp_kurzbz = \'tpl\' THEN 0 + ELSE 1 + END, + -- Ensure assigend lvs follow their template, grouped by lehrveranstaltung_template_id + COALESCE(lv.lehrveranstaltung_template_id, lv.lehrveranstaltung_id) + '; + + return $this->execQuery($qry, $params); + } + /** * Gets unique Groupstrings for Lehrveranstaltungen, e.g. WS2018_BIF_1_PRJM_VZ_LV12345 * @param string $studiensemester_kurzbz @@ -200,37 +386,165 @@ 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 * @param $student_uid - * @param null $studiensemester_kurzbz + * @param $studiensemester_kurzbz * @return array|null */ public function getLvsByStudent($student_uid, $studiensemester_kurzbz = null) { $params = array($student_uid); - $qry = "SELECT * FROM lehre.tbl_lehrveranstaltung - WHERE lehrveranstaltung_id IN(SELECT lehrveranstaltung_id FROM campus.vw_student_lehrveranstaltung - WHERE uid=?"; + WHERE lehrveranstaltung_id IN( + SELECT lehrveranstaltung_id FROM campus.vw_student_lehrveranstaltung + WHERE uid=?"; + if (isset($studiensemester_kurzbz)) { - $qry .= " AND studiensemester_kurzbz=?"; $params[] = $studiensemester_kurzbz; + $qry .= " AND studiensemester_kurzbz=?"; } - $qry .= ") OR lehrveranstaltung_id IN(SELECT lehrveranstaltung_id FROM lehre.tbl_zeugnisnote WHERE student_uid=?"; + $qry .= ")"; + + $qry .= " OR lehrveranstaltung_id IN( + SELECT lehrveranstaltung_id FROM lehre.tbl_zeugnisnote + WHERE student_uid=?"; $params[] = $student_uid; - if (isset($studiensemester_kurzbz)) - { - $qry .= " AND studiensemester_kurzbz=?"; - $params[] = $studiensemester_kurzbz; - } + $qry .= ") ORDER BY semester, bezeichnung"; 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) + { + + $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('v.bezeichnung AS bezeichnung'); + $this->addSelect('v.bezeichnung_english AS bezeichnung_eng'); + $this->addSelect('sg.bezeichnung AS sg_bezeichnung'); + $this->addSelect('sg.english AS sg_bezeichnung_eng'); + $this->addSelect('UPPER(sg.typ::VARCHAR(1) || sg.kurzbz) AS studiengang_kuerzel'); + + //also adds returns the index of the grade + //TODO: ist zeugnissnote immer gleich wie die lvgesamtnote + $this->addSelect('COALESCE(zn.note::numeric,gn.note::numeric) as note_index'); + $this->addSelect('COALESCE(znn.positiv,gnn.positiv) as positiv'); + $this->addSelect('gnn.bezeichnung_mehrsprachig AS lvnotebez'); + $this->addSelect('gnn.note AS lvnote'); + $this->addSelect('znn.bezeichnung_mehrsprachig AS znotebez'); + $this->addSelect('znn.note 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 @@ -309,4 +623,400 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($query, array($uid, $studiensemester_kurzbz, $lehrveranstaltung_id)); } + + /** + * Get Lehreinheit. + * + * @param string $student_uid + * @param string $studiensemester_kurzbz + * @param integer $lehrveranstaltung_id + * + * @return stdClass + */ + public function getLeByStudent($student_uid, $studiensemester_kurzbz, $lehrveranstaltung_id) + { + $this->addSelect("lehreinheit_id"); + + $this->addOrder("lehreinheit_id", "ASC"); + + $this->addLimit(1); + + $tmp = $this->dbTable; + $this->dbTable = "campus.vw_student_lehrveranstaltung"; + + $result = $this->loadWhere([ + "uid" => $student_uid, + "lehrveranstaltung_id" => $lehrveranstaltung_id, + "studiensemester_kurzbz" => $studiensemester_kurzbz + ]); + + $this->dbTable = $tmp; + + return $result; + } + + /** + * Sucht nach LV Templates und gibt Id und Label ("bezeichnung [kurzbz]") aus + * Diese funktion ist für autocomplete gedacht + * + * @param string $filter Suchfilter + * @return \stdClass A return object + */ + public function loadTemplates($filter) + { + $filter = strtolower($filter); + $qry = "SELECT + tbl_lehrveranstaltung.lehrveranstaltung_id, tbl_lehrveranstaltung.bezeichnung, tbl_lehrveranstaltung.kurzbz + FROM + lehre.tbl_lehrveranstaltung + WHERE + tbl_lehrveranstaltung.lehrtyp_kurzbz = 'tpl' AND ( + CAST(tbl_lehrveranstaltung.lehrveranstaltung_id AS TEXT) LIKE '%".$this->db_escape($filter)."%' OR + LOWER(tbl_lehrveranstaltung.bezeichnung) LIKE '%".$this->db_escape($filter). "%' OR + LOWER(tbl_lehrveranstaltung.kurzbz) LIKE '%".$this->db_escape($filter). "%' + ) + "; + return $this->execQuery($qry); + } + + /** + * Lädt Template und gibt Id und Label ("bezeichnung [kurzbz]") zurück + * Diese funktion ist für autocomplete gedacht + * + * @param string $name + * @return \stdClass A return object + */ + public function loadTemplateByName($name) + { + $qry = "SELECT + tbl_lehrveranstaltung.lehrveranstaltung_id as id, CONCAT(tbl_lehrveranstaltung.bezeichnung, ' [', tbl_lehrveranstaltung.kurzbz, ']') as label + FROM + lehre.tbl_lehrveranstaltung + WHERE + tbl_lehrveranstaltung.lehrtyp_kurzbz = 'tpl' AND ( + CAST(tbl_lehrveranstaltung.lehrveranstaltung_id AS TEXT) = '".($name ? $this->db_escape($name) : 0)."' OR tbl_lehrveranstaltung.bezeichnung = '".$this->db_escape($name). "' OR tbl_lehrveranstaltung.kurzbz = '".$this->db_escape($name). "' + ) + "; + return $this->execQuery($qry); + } + + /** + * Check if given LV is a template (Quellkurs) + * + * @param $lehrveranstaltung_id + * @return array|stdClass|void + */ + public function checkIsTemplate($lehrveranstaltung_id) + { + $this->addSelect('lehrtyp_kurzbz, lehrveranstaltung_template_id'); + $result = $this->load($lehrveranstaltung_id); + + if (isError($result)) + return error(getError($result)); + + if (hasData($result)) + { + return success( + getData($result)[0]->lehrtyp_kurzbz === 'tpl' && + getData($result)[0]->lehrveranstaltung_template_id === null + ); + } + } + + /** + * Get ECTS Summe pro angerechnetes Quereinstiegssemester. + * + * @param $studiengang_kz + * @param $studiensemester_kurzbz + * @param $ausbildungssemester + * @param $orgform_kurzbz + * @return array|stdClass|null + */ + public function getSumQuereinstiegsECTSProSemester($studiengang_kz, $studiensemester_kurzbz, $ausbildungssemester, $orgform_kurzbz) + { + $qry = ' + SELECT + sum(tbl_lehrveranstaltung.ects) as "sum_ects" + FROM + lehre.tbl_studienplan + JOIN lehre.tbl_studienplan_lehrveranstaltung USING (studienplan_id) + JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) + WHERE + tbl_studienplan.studienplan_id = ( + SELECT + studienplan_id + FROM + lehre.tbl_studienordnung + JOIN lehre.tbl_studienplan USING (studienordnung_id) + JOIN lehre.tbl_studienplan_semester USING (studienplan_id) + WHERE tbl_studienordnung.studiengang_kz = ? + AND tbl_studienplan_semester.semester = ? + AND tbl_studienplan_semester.studiensemester_kurzbz = ? + AND tbl_studienplan.orgform_kurzbz = ? + + LIMIT 1 + ) + AND tbl_studienplan_lehrveranstaltung.semester = ? + AND studienplan_lehrveranstaltung_id_parent IS NULL -- auf Modulebene + AND tbl_studienplan_lehrveranstaltung.export = TRUE + '; + + return $this->execQuery($qry, array( + $studiengang_kz, $ausbildungssemester, $studiensemester_kurzbz, $orgform_kurzbz, $ausbildungssemester) + ); + } + + /** + * Get ECTS Summe aller bisher angerechneten LVs. + * Wenn keine explizite Begruendung angegeben ist, wird eine schulische Begruendung angenommen. + * + * @param $student_uid + * @return array|stdClass|null + */ + public function getSumAngerechneteECTSByBegruendung($student_uid) + { + $qry = ' + SELECT sum(ects), begruendung_id FROM ( + SELECT + lehrveranstaltung_id, studiensemester_kurzbz, ects, COALESCE(begruendung_id, 1) as begruendung_id -- fallback auf externes Zeugnis + FROM + lehre.tbl_zeugnisnote + LEFT JOIN lehre.tbl_anrechnung USING(lehrveranstaltung_id, studiensemester_kurzbz) + JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + JOIN public.tbl_student USING(student_uid) + WHERE + tbl_zeugnisnote.note = 6 + AND student_uid = ? + AND (lehre.tbl_anrechnung.prestudent_id = tbl_student.prestudent_id + OR lehre.tbl_anrechnung.prestudent_id is null) + + UNION + + SELECT + lehrveranstaltung_id, studiensemester_kurzbz, ects, begruendung_id -- fallback auf externes Zeugnis + FROM + lehre.tbl_anrechnung + JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + JOIN public.tbl_student USING(prestudent_id) + WHERE + genehmigt_von is not null + AND student_uid = ? + ) lvsangerechnet + GROUP BY begruendung_id + '; + + return $this->execQuery($qry, array($student_uid, $student_uid)); + } + + /** + * Get ECTS Summe aller bisher schulisch begruendeten angerechneten LVs. + * Derzeit wird auch jede Anrechnung, die nicht beruflich ist, als schulisch angenommen. + * + * @param $student_uid + * @return array|stdClass|null + */ + public function getEctsSumSchulisch($student_uid, $prestudent_id, $studiengang_kz) + { + $qry = ' + SELECT get_ects_summe_schulisch(?, ?, ?) AS ectsSumSchulisch + '; + + return $this->execQuery($qry, array($student_uid, $prestudent_id, $studiengang_kz)); + } + + /** + * Get ECTS Summe aller bisher beruflich angerechneten LVs. + * + * @param $student_uid + * @return array|stdClass|null + */ + public function getEctsSumBeruflich($student_uid) + { + $qry = ' + SELECT get_ects_summe_beruflich(?) AS ectsSumBeruflich + '; + + 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; + } + + /** + * Gets lehrveranstaltungen of a studiengang + * @param integer $studiengang_kz + * @return array|null + */ + public function getLvsByStudiengangkz($studiengang_kz) + { + $params = array($studiengang_kz); + + $qry = "SELECT + * + FROM + lehre.tbl_lehrveranstaltung + WHERE lehrveranstaltung_id IN + (SELECT lehrveranstaltung_id + FROM campus.vw_student_lehrveranstaltung + WHERE studiengang_kz = ?"; + + $qry .= ") ORDER BY semester, bezeichnung"; + + return $this->execQuery($qry, $params); + } + + /** + * Gets lehrveranstaltungen of Studienplan + * @param $studienplan_id ID des Studienplans + * @param $semester Semester optional + * @return array|null + */ + public function getLvsByStudienplanId($studienplan_id, $semester = null) + { + $params = array($studienplan_id); + + $qry = "SELECT tbl_lehrveranstaltung.*, + tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id, + tbl_studienplan_lehrveranstaltung.semester as stpllv_semester, + tbl_studienplan_lehrveranstaltung.pflicht as stpllv_pflicht, + tbl_studienplan_lehrveranstaltung.koordinator as stpllv_koordinator, + tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent, + tbl_studienplan_lehrveranstaltung.sort stpllv_sort, + tbl_studienplan_lehrveranstaltung.curriculum, + tbl_studienplan_lehrveranstaltung.export, + tbl_studienplan_lehrveranstaltung.genehmigung + FROM lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_studienplan_lehrveranstaltung + USING(lehrveranstaltung_id) + WHERE tbl_studienplan_lehrveranstaltung.studienplan_id = ? + "; + + if ($semester !== null) + { + $qry.= " AND tbl_studienplan_lehrveranstaltung.semester = ?"; + $params[] = $semester; + } + + $qry .= " ORDER BY stpllv_sort, semester, sort"; + + return $this->execQuery($qry, $params); + } } 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..c30045ff0 100644 --- a/application/models/education/Lvgesamtnote_model.php +++ b/application/models/education/Lvgesamtnote_model.php @@ -10,5 +10,40 @@ 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; + } + + /** + * Laedt die Noten + * + * @param integer $lehrveranstaltung_id + * @param string $student_uid + * @param string $studiensemester_kurzbz + * + * @return stdClass + */ + public function getLvGesamtNoten($lehrveranstaltung_id, $student_uid, $studiensemester_kurzbz) + { + $this->addSelect($this->dbTable . ".*"); + $this->addSelect("n.bezeichnung AS note_bezeichnung"); + $this->addSelect("lv.bezeichnung AS lehrveranstaltung_bezeichnung"); + $this->addSelect("lv.studiengang_kz"); + $this->addSelect("UPPER(stg.typ || stg.kurzbz) AS studiengang"); + + $this->addJoin("lehre.tbl_note n", "note"); + $this->addJoin("lehre.tbl_lehrveranstaltung lv", "lehrveranstaltung_id"); + $this->addJoin("public.tbl_studiengang stg", "studiengang_kz"); + + $this->db->where($this->dbTable . ".freigabedatum <", "NOW()", false); + + $where = []; + if ($studiensemester_kurzbz) + $where[$this->dbTable . ".studiensemester_kurzbz"] = $studiensemester_kurzbz; + if ($lehrveranstaltung_id) + $where[$this->dbTable . ".lehrveranstaltung_id"] = $lehrveranstaltung_id; + if ($student_uid) + $where[$this->dbTable . ".student_uid"] = $student_uid; + + return $this->loadWhere($where); } } diff --git a/application/models/education/Note_model.php b/application/models/education/Note_model.php new file mode 100644 index 000000000..80b454398 --- /dev/null +++ b/application/models/education/Note_model.php @@ -0,0 +1,14 @@ +dbTable = 'lehre.tbl_note'; + $this->pk = 'note'; + } +} \ No newline at end of file diff --git a/application/models/education/Notenschluesselaufteilung_model.php b/application/models/education/Notenschluesselaufteilung_model.php index 5e0f2f05c..d48e16b0b 100644 --- a/application/models/education/Notenschluesselaufteilung_model.php +++ b/application/models/education/Notenschluesselaufteilung_model.php @@ -11,4 +11,34 @@ class Notenschluesselaufteilung_model extends DB_Model $this->dbTable = 'lehre.tbl_notenschluesselaufteilung'; $this->pk = 'notenschluesselaufteilung_id'; } + + /** + * Liefert die Note zu Punkten einer Lehrveranstaltung + * + * @param number $points + * @param integer $lehrveranstaltung_id + * @param string $studiensemester_kurzbz + * + * @return stdClass returns success(null) if no entry is found + */ + public function getNote($points, $lehrveranstaltung_id, $studiensemester_kurzbz) + { + $this->load->model('education/Notenschluesselzuordnung_model', 'NotenschluesselzuordnungModel'); + $notenschluessel_kurzbz = $this->NotenschluesselzuordnungModel->getKurzbzForLv($lehrveranstaltung_id, $studiensemester_kurzbz); + + $this->addSelect("note"); + $this->addOrder("punkte", "DESC"); + $this->addLimit(1); + + $result = $this->loadWhere([ + "notenschluessel_kurzbz" => $notenschluessel_kurzbz, + "punkte <=" => $points + ]); + + if (isError($result)) + return $result; + if (!hasData($result)) + return success(null); + return success(current(getData($result))->note); + } } diff --git a/application/models/education/Notenschluesselzuordnung_model.php b/application/models/education/Notenschluesselzuordnung_model.php index e6881e12b..9eb46b290 100644 --- a/application/models/education/Notenschluesselzuordnung_model.php +++ b/application/models/education/Notenschluesselzuordnung_model.php @@ -11,4 +11,71 @@ class Notenschluesselzuordnung_model extends DB_Model $this->dbTable = 'lehre.tbl_notenschluesselzuordnung'; $this->pk = 'notenschluesselzuordnung_id'; } + + /** + * Liefert den passenden Notenschluessel zu einer Lehrveranstaltung + * + * @param integer $lehrveranstaltung_id + * @param string $studiensemester_kurzbz + * + * @return integer|null + */ + public function getKurzbzForLv($lehrveranstaltung_id, $studiensemester_kurzbz) + { + $this->addSelect("notenschluessel_kurzbz"); + + $this->db->where("lehrveranstaltung_id", $lehrveranstaltung_id); + if ($studiensemester_kurzbz) { + $this->db->where("studiensemester_kurzbz", $studiensemester_kurzbz); + $this->db->or_where("studiensemester_kurzbz", null); + } else { + $this->db->where("studiensemester_kurzbz", null); + } + + $result = $this->load(); + + if (!isError($result) && hasData($result)) + return current(getData($result))->notenschluessel_kurzbz; + + + $this->addSelect("notenschluessel_kurzbz"); + + $this->addJoin("( + WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz, depth) AS ( + SELECT oe_kurzbz, oe_parent_kurzbz, 1 + FROM public.tbl_organisationseinheit + WHERE oe_kurzbz = ( + SELECT + oe_kurzbz + FROM + lehre.tbl_lehrveranstaltung + WHERE + lehrveranstaltung_id = " . $this->escape($lehrveranstaltung_id) . " + ) + UNION ALL + SELECT o.oe_kurzbz, o.oe_parent_kurzbz, oes.depth+1 AS depth + FROM public.tbl_organisationseinheit o, oes + WHERE o.oe_kurzbz = oes.oe_parent_kurzbz + AND aktiv = true + ) + SELECT * FROM oes + ) oes", "oe_kurzbz"); + + $this->addOrder("depth", "ASC"); + $this->addLimit(1); + + if ($studiensemester_kurzbz) { + $this->db->where_in("studiensemester_kurzbz", [$studiensemester_kurzbz, null]); + $result = $this->load(); + } else { + $result = $this->loadWhere([ + "studiensemester_kurzbz" => null + ]); + } + + if (isError($result) || !hasData($result)) + return null; + + return current(getData($result))->notenschluessel_kurzbz; + } } diff --git a/application/models/education/Paabgabe_model.php b/application/models/education/Paabgabe_model.php index 087c27663..343a86706 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)); + } + + /** + * Gets all Paabgabe Termin Deadlines of zugewiesene Projektarbeiten as a Mitarbeiter for Terminübersicht Abgabetool. + * @param int $person_id + * @return object + */ + public function getDeadlines($person_id) + { + $qry = "SELECT + DISTINCT TO_CHAR(tbl_paabgabe.datum, 'DD.MM.YYYY') as datum, tbl_paabgabe.fixtermin, tbl_paabgabe.kurzbz, + person_student.vorname as stud_vorname, person_student.nachname as stud_nachname, + person_student.titelpre as stud_titelpre, person_student.titelpost as stud_titelpost, + tbl_lehrveranstaltung.semester, UPPER(tbl_studiengang.typ || tbl_studiengang.kurzbz) as stg, + tbl_paabgabetyp.bezeichnung as typ_bezeichnung + FROM + campus.tbl_paabgabe + JOIN lehre.tbl_projektarbeit USING(projektarbeit_id) + JOIN lehre.tbl_projektbetreuer USING(projektarbeit_id) + JOIN public.tbl_benutzer bn_student ON(tbl_projektarbeit.student_uid=bn_student.uid) + JOIN public.tbl_person person_student ON(bn_student.person_id=person_student.person_id) + JOIN lehre.tbl_lehreinheit ON(tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung ON(tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id) + JOIN public.tbl_studiengang ON(tbl_lehrveranstaltung.studiengang_kz=tbl_studiengang.studiengang_kz) + JOIN campus.tbl_paabgabetyp USING(paabgabetyp_kurzbz) + WHERE + tbl_projektbetreuer.person_id= ? AND tbl_paabgabe.datum>=now() AND bn_student.aktiv + ORDER BY datum"; + + return $this->execReadOnlyQuery($qry, array($person_id)); + } + } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 109e23373..4083dbf6e 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -69,4 +69,196 @@ class Projektarbeit_model extends DB_Model return $this->execQuery($qry, $params); } + + /** + * Update a Projektarbeit of a student by projektarbeit_id with + * the paramenters used by the student endupload page in cis4 abgabetool. + */ + public function updateProjektarbeit($projektarbeit_id,$sprache,$abstract,$abstract_en, + $schlagwoerter, $schlagwoerter_en,$seitenanzahl) + { + $qry = "UPDATE lehre.tbl_projektarbeit SET + seitenanzahl = ?, + abgabedatum = now(), + sprache = ?, + schlagwoerter_en = ?, + schlagwoerter = ?, + abstract = ?, + abstract_en = ? + WHERE projektarbeit_id = ?"; + + return $this->execQuery($qry, array($seitenanzahl, $sprache, $schlagwoerter_en, + $schlagwoerter, $abstract, $abstract_en, $projektarbeit_id)); + } + + /** + * Get a List of Projektarbeiten of a student with betreuer + * used by the student cis4 abgabetool. + */ + public function getStudentProjektarbeitenWithBetreuer($studentUID) + { + $betreuerQuery = " + SELECT + vorname as bvorname, + nachname as bnachname, + titelpre as btitelpre, + titelpost AS btitelpost, + titelpost AS btitelpost, + tbl_betreuerart.beschreibung AS betreuerart_beschreibung, + + (SELECT person_id + FROM lehre.tbl_projektbetreuer + WHERE projektarbeit_id=tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') LIMIT 1) AS zweitbetreuer_person_id, + (SELECT betreuerart_kurzbz + FROM lehre.tbl_projektbetreuer + WHERE projektarbeit_id=tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') LIMIT 1) AS zweitbetreuer_betreuerart_kurzbz, + (SELECT tbl_betreuerart.beschreibung + FROM lehre.tbl_projektbetreuer JOIN lehre.tbl_betreuerart USING(betreuerart_kurzbz) + WHERE projektarbeit_id=tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied') LIMIT 1) AS zweitbetreuer_betreuerart_beschreibung, + + tbl_betreuerart.betreuerart_kurzbz, + person_id as bperson_id, + projektarbeit_id, + lehre.tbl_projekttyp.bezeichnung as projekttypbezeichnung, + lehre.tbl_lehreinheit.studiensemester_kurzbz, + lehre.tbl_lehrveranstaltung.studiengang_kz, + public.tbl_studiengang.kurzbzlang, + lehre.tbl_projektbetreuer.note as note, + public.tbl_mitarbeiter.mitarbeiter_uid, + lehre.tbl_projektarbeit.titel as titel, + lehre.tbl_projektarbeit.sprache as sprache, + lehre.tbl_projektarbeit.seitenanzahl as seitenanzahl, + lehre.tbl_projektarbeit.kontrollschlagwoerter as kontrollschlagwoerter, + lehre.tbl_projektarbeit.schlagwoerter as schlagwoerter, + lehre.tbl_projektarbeit.schlagwoerter_en as schlagwoerter_en, + lehre.tbl_projektarbeit.abstract as abstract, + lehre.tbl_projektarbeit.abstract_en as abstract_en, + (SELECT abgeschicktvon FROM extension.tbl_projektarbeitsbeurteilung WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id AND betreuer_person_id = tbl_projektbetreuer.person_id) AS babgeschickt, + (SELECT abgeschicktvon FROM extension.tbl_projektarbeitsbeurteilung WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') LIMIT 1) AS zweitbetreuer_abgeschickt, + (SELECT datum FROM campus.tbl_paabgabe WHERE paabgabetyp_kurzbz = 'end' AND abgabedatum IS NOT NULL AND projektarbeit_id = tbl_projektarbeit.projektarbeit_id LIMIT 1) AS abgegeben + + FROM lehre.tbl_projektarbeit + LEFT JOIN lehre.tbl_projektbetreuer USING(projektarbeit_id) + LEFT JOIN public.tbl_person USING(person_id) + LEFT JOIN public.tbl_benutzer USING(person_id) + LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) + LEFT JOIN lehre.tbl_betreuerart USING(betreuerart_kurzbz) + LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) + LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + LEFT JOIN public.tbl_mitarbeiter ON(public.tbl_mitarbeiter.mitarbeiter_uid = public.tbl_benutzer.uid) + LEFT JOIN public.tbl_studiengang USING(studiengang_kz) + WHERE + tbl_projektarbeit.student_uid = ? AND + (projekttyp_kurzbz='Bachelor' OR projekttyp_kurzbz='Diplom') + AND betreuerart_kurzbz IN ('Betreuer', 'Begutachter', 'Erstbegutachter', 'Senatsvorsitz')"; + + return $this->execReadOnlyQuery($betreuerQuery, array($studentUID)); + } + + /** + * Get a List of Projektarbeit Abgabetermin used by the student cis4 abgabetool. + */ + public function getProjektarbeitAbgabetermine($projektarbeit_id) { + $qry ="SELECT campus.tbl_paabgabe.paabgabe_id, + campus.tbl_paabgabe.projektarbeit_id, + campus.tbl_paabgabe.fixtermin, + campus.tbl_paabgabe.kurzbz, + campus.tbl_paabgabe.datum, + campus.tbl_paabgabetyp.paabgabetyp_kurzbz, + campus.tbl_paabgabetyp.bezeichnung, + campus.tbl_paabgabe.abgabedatum, + campus.tbl_paabgabe.insertvon + FROM campus.tbl_paabgabe JOIN campus.tbl_paabgabetyp USING(paabgabetyp_kurzbz) + WHERE campus.tbl_paabgabe.projektarbeit_id = ? + ORDER BY campus.tbl_paabgabe.datum"; + + return $this->execReadOnlyQuery($qry, array($projektarbeit_id)); + } + + public function getProjektbetreuerAnrede($bperson_id) { + $qry_betr="SELECT distinct trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as first, + public.tbl_mitarbeiter.mitarbeiter_uid, anrede + FROM public.tbl_person JOIN lehre.tbl_projektbetreuer ON(lehre.tbl_projektbetreuer.person_id=public.tbl_person.person_id) + JOIN public.tbl_benutzer ON(public.tbl_benutzer.person_id=public.tbl_person.person_id) + JOIN public.tbl_mitarbeiter ON(public.tbl_benutzer.uid=public.tbl_mitarbeiter.mitarbeiter_uid) + WHERE public.tbl_person.person_id= ?"; + + return $this->execReadOnlyQuery($qry_betr, [$bperson_id]); + + } + + public function getProjektarbeitBenutzer($uid) { + $qry="SELECT * FROM campus.vw_benutzer where uid=?"; + return $this->execReadOnlyQuery($qry, [$uid]); + } + + /** + * Checks if mitarbeiter has a projektbetreuer zuordnung to student. + */ + public function checkZuordnung($studentUID, $maUID) { + //oder Lektor mit Betreuung dieses Studenten + $qry = " + SELECT 1 + FROM + lehre.tbl_projektarbeit + JOIN lehre.tbl_projektbetreuer USING(projektarbeit_id) + JOIN campus.vw_benutzer on(vw_benutzer.person_id=tbl_projektbetreuer.person_id) + WHERE + tbl_projektarbeit.student_uid = ? AND + vw_benutzer.uid = ?"; + + return $this->execReadOnlyQuery($qry, array($studentUID, $maUID)); + } + + /** + * Get a List of Projektarbeiten of a mitarbeiter with zuordnung + * used by the mitarbeiter cis4 abgabetool. + */ + public function getMitarbeiterProjektarbeiten($uid, $showAll){ + $qry = "SELECT + * + FROM + (SELECT tbl_person.vorname, tbl_person.nachname, tbl_studiengang.typ, tbl_studiengang.kurzbz, + tbl_projektarbeit.projekttyp_kurzbz, tbl_projekttyp.bezeichnung, tbl_projektarbeit.titel, tbl_projektarbeit.projektarbeit_id, + tbl_projektbetreuer.betreuerart_kurzbz, tbl_betreuerart.beschreibung AS betreuerart_beschreibung, + tbl_benutzer.uid, tbl_student.matrikelnr, tbl_lehreinheit.studiensemester_kurzbz + FROM lehre.tbl_projektarbeit + LEFT JOIN lehre.tbl_projektbetreuer using(projektarbeit_id) + LEFT JOIN lehre.tbl_betreuerart using(betreuerart_kurzbz) + LEFT JOIN public.tbl_benutzer on(uid=student_uid) + LEFT JOIN public.tbl_student on(public.tbl_benutzer.uid=public.tbl_student.student_uid) + LEFT JOIN public.tbl_person on(tbl_benutzer.person_id=tbl_person.person_id) + LEFT JOIN lehre.tbl_lehreinheit using(lehreinheit_id) + LEFT JOIN lehre.tbl_lehrveranstaltung using(lehrveranstaltung_id) + LEFT JOIN public.tbl_studiengang on(lehre.tbl_lehrveranstaltung.studiengang_kz=public.tbl_studiengang.studiengang_kz) + LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) + WHERE (projekttyp_kurzbz='Bachelor' OR projekttyp_kurzbz='Diplom') + AND tbl_projektbetreuer.person_id IN (SELECT person_id FROM public.tbl_benutzer + WHERE public.tbl_benutzer.person_id=lehre.tbl_projektbetreuer.person_id + AND public.tbl_benutzer.uid= ? ) + ".($showAll?'':' AND public.tbl_benutzer.aktiv AND lehre.tbl_projektarbeit.note IS NULL ')." + AND betreuerart_kurzbz IN ('Betreuer', 'Begutachter', 'Erstbegutachter', 'Zweitbegutachter', 'Erstbetreuer', 'Senatsvorsitz', 'Senatsmitglied') + ORDER BY tbl_projektarbeit.projektarbeit_id, betreuerart_kurzbz desc) as xy + ORDER BY nachname;"; + + return $this->execReadOnlyQuery($qry, array($uid)); + } + + /** + * Fetch Student info relevant to a projektarbeit_id + */ + public function getStudentInfoForProjektarbeitId($projektarbeit_id) { + + $qry = "SELECT * + FROM campus.vw_student + WHERE uid IN( + SELECT student_uid + FROM lehre.tbl_projektarbeit + WHERE projektarbeit_id = ? )"; + + return $this->execReadOnlyQuery($qry, array($projektarbeit_id)); + } } diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index 4da88e344..95950bf95 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -42,6 +42,44 @@ class Projektbetreuer_model extends DB_Model } } + /** + * Gets Betreuer of a certain Type of a Projektarbeit. + * Returns one row for each person. + * @param int $projektarbeit_id + * @param string $betreuerart_kurzbz + * @return array success with number of Betreuer or error + */ + public function getBetreuerOfProjektarbeit($projektarbeit_id, $betreuerart_kurzbz) + { + $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, + ( + 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)); + } + /** * Get Projektbetreuer data by authentification token * @param $zugangstoken @@ -49,15 +87,148 @@ 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)); } + + /** + * Holt Zweitbegutachter einer Projektarbeit mit Mail. + * @param $erstbegutachter_person_id int person_id des Erstbegutachters + * @param $projektarbeit_id int + * @param $student_uid string uid des Studenten der Arbeit abgibt + * @return object | bool + */ + public function getZweitbegutachterWithToken($erstbegutachter_person_id, $projektarbeit_id, $student_uid, $zweitbegutachter_person_id = null) + { + $params = array($erstbegutachter_person_id, $erstbegutachter_person_id, $projektarbeit_id, $student_uid); + + $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); + } + + /** + * Generiert neuen Token für externen Zweitbetreuer. + * @param int $zweitbegutachter_person_id + * @param int $projektarbeit_id + * @return array + */ + public function generateZweitbegutachterToken($zweitbegutachter_person_id, $projektarbeit_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 IN ('Zweitbegutachter', 'Senatsmitglied') + LIMIT 1"; + + $betreueruidRes = $this->execQuery($betreuerUidQry, array($projektarbeit_id, $zweitbegutachter_person_id)); + + if (!hasData($betreueruidRes)) + return error('Zweitbegutachter nicht gefunden'); + + $zweitbetreuer = getData($betreueruidRes)[0]; + + if (!isset($zweitbetreuer->uid)) + { + do { + $token = generateToken(16); + $qry_tokencheck = $this->load(array('zugangstoken' => $token)); + } while(hasData($qry_tokencheck)); + + $result = $this->update( + array('projektarbeit_id' => $projektarbeit_id, + 'person_id' => $zweitbetreuer->person_id, + 'betreuerart_kurzbz' => $zweitbetreuer->betreuerart_kurzbz), + array('zugangstoken' => $token, + 'zugangstoken_gueltigbis' => date('Y-m-d', strtotime('+1 year'))) + ); + + return $result; + } + 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/Pruefungsantritt_model.php b/application/models/education/Pruefungsantritt_model.php new file mode 100644 index 000000000..f22633117 --- /dev/null +++ b/application/models/education/Pruefungsantritt_model.php @@ -0,0 +1,14 @@ +dbTable = 'lehre.tbl_abschlusspruefung_antritt'; + $this->pk = 'pruefungsantritt_kurzbz'; + } +} \ No newline at end of file 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..927343a3e --- /dev/null +++ b/application/models/education/Studierendenantraglehrveranstaltung_model.php @@ -0,0 +1,127 @@ +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); + } + } + + /** + * Gets all LVs for a repeating prestudent that are either not allowed or + * already done. + * + * @param string $prestudent_id + * @param string $studiensemester_kurzbz + * + * @return stdClass + */ + 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'); + + + $this->load->config('studierendenantrag'); + $note_intern_angerechntet = $this->config->item('wiederholung_note_angerechnet'); + + $where = [ + 'ps.prestudent_id' => $prestudent_id, + 'a.typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG, + 'stat.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED, + 'n.note <> ' => 0, + // NOTE(chris): grade "intern angerechnet" needs an official grade beforehand (the subquery gets the last positive offical grade) + "(n.note<>" . $this->db->escape($note_intern_angerechntet) . " OR EXISTS ( + SELECT + 1 + 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 + ) + JOIN lehre.tbl_note zn USING (note) + WHERE + z.lehrveranstaltung_id = lv.lehrveranstaltung_id + AND z.student_uid = s.student_uid + AND zn.positiv + ))" => null + ]; + + if ($studiensemester_kurzbz !== false) + $where[$this->dbTable . '.studiensemester_kurzbz'] = $studiensemester_kurzbz; + + return $this->loadWhere($where); + } +} 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..f32713dec 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,101 @@ 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 + a.*, + lv.lehrform_kurzbz AS lehrveranstaltung_lehrform, + lv.kurzbz AS lehrveranstaltung_kurzbz, + UPPER(stg1.typ || stg1.kurzbz) AS studiengang, + s.studiengang_kz AS studiengang_kz, + UPPER(stg2.typ || stg2.kurzbz) AS studiengang_lv, + lv.studiengang_kz AS studiengang_kz_lv, + lv.semester AS semester_lv, + lv.ects AS ects_lv, + lv.zeugnis, + lv.bezeichnung_english AS lehrveranstaltung_bezeichnung_english + FROM ( + 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 + ) a + LEFT JOIN public.tbl_student s ON (a.uid = s.student_uid) + LEFT JOIN public.tbl_studiengang stg1 ON (s.studiengang_kz = stg1.studiengang_kz) + LEFT JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + LEFT JOIN public.tbl_studiengang stg2 ON (lv.studiengang_kz = stg2.studiengang_kz)"; + + 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..ba91964f6 100644 --- a/application/models/organisation/Organisationseinheit_model.php +++ b/application/models/organisation/Organisationseinheit_model.php @@ -188,4 +188,29 @@ 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 highest organisation units + */ + public function getHeads() + { + $this->addSelect('*'); + $this->addSelect('oe_kurzbz as head'); + $result = $this->loadWhere(array('oe_parent_kurzbz' => null, 'aktiv' => true)); + + return $result; + } } 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 0d0c248a6..02f972690 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 @@ -507,4 +554,251 @@ class Studiengang_model extends DB_Model return $this->execQuery($query, array($typ, $semester)); } + + 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 ?"; + + $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(); + } + + /** + * @return stdClass + */ + public function getStudiengangInfoForNews() + { + + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + + $addEmailProperty= function(&$benutzerfunktionen){ + if(count($benutzerfunktionen) && defined('DOMAIN')) + { + $benutzerfunktionen = array_map(function($benutzer) + { + $benutzer->email = $benutzer->alias."@".DOMAIN; + return $benutzer; + },$benutzerfunktionen) ; + } + + }; + $addFotoProperty= function(&$collection){ + $collection = array_map(function($item){ + $person_id = $this->PersonModel->getByUid($item->uid); + if(isError($person_id)) + return error($person_id); + $person_id = current(getData($person_id))->person_id; + $this->PersonModel->addSelect('foto'); + $foto = $this->PersonModel->loadWhere(array('person_id'=>$person_id)); + if(isError($foto)) + return error($foto); + $foto = current(getData($foto))->foto; + $item->foto = $foto; + return $item; + },$collection); + }; + + + $this->load->model('crm/Student_model', 'StudentModel'); + + $student = $this->StudentModel->loadWhere(['student_uid' => getAuthUID()]); + if (isError($student)) + return error($student); + if (getData($student)) { + $student = current(getData($student)); + $studiengang_kz = $student->studiengang_kz; + $semester = $student->semester; + } + + $stg_obj = $this->load($studiengang_kz); + if(isError($stg_obj)) + return error($stg_obj); + if(getData($stg_obj)) + { + $stg_obj = current(getData($stg_obj)); + } + + $stg_ltg = $this->getLeitungDetailed($stg_obj->studiengang_kz); + if (isError($stg_ltg)) + return $stg_ltg; + $stg_ltg = getData($stg_ltg) ?: []; + $stg_ltg = array_values(array_filter($stg_ltg, function($stg_leitung){ + return $stg_leitung->aktiv; + })); + $addFotoProperty($stg_ltg); + + $gf_ltg = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('gLtg', $stg_obj->oe_kurzbz); + if (isError($gf_ltg)) + return $gf_ltg; + $gf_ltg = getData($gf_ltg) ?: []; + $gf_ltg = array_values(array_filter($gf_ltg, function($gf_leitung){ + return $gf_leitung->aktiv; + })); + $addEmailProperty($gf_ltg); + $addFotoProperty($gf_ltg); + + $stv_ltg = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('stvLtg', $stg_obj->oe_kurzbz); + if (isError($stv_ltg)) + return $stv_ltg; + $stv_ltg = getData($stv_ltg) ?: []; + $stv_ltg = array_values(array_filter($stv_ltg, function($stv_leitung){ + return $stv_leitung->aktiv; + })); + $addEmailProperty($stv_ltg); + $addFotoProperty($stv_ltg); + + $ass = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('ass', $stg_obj->oe_kurzbz); + if (isError($ass)) + return $ass; + $ass = getData($ass) ?: []; + $ass = array_values(array_filter($ass, function($assistenz){ + return $assistenz->aktiv; + })); + $addEmailProperty($ass); + $addFotoProperty($ass); + + $hochschulvertr = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('hsv'); + if (isError($hochschulvertr)) + return $hochschulvertr; + $hochschulvertr = getData($hochschulvertr) ?: []; + $hochschulvertr = array_values(array_filter($hochschulvertr, function($hochschul_vertreter){ + return $hochschul_vertreter->aktiv; + })); + $addEmailProperty($hochschulvertr); + + + $stdv = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('stdv', $stg_obj->oe_kurzbz); + if (isError($stdv)) + return $stdv; + $stdv = getData($stdv) ?: []; + $stdv = array_values(array_filter($stdv, function($std_vertreter){ + return $std_vertreter->aktiv; + })); + $addEmailProperty($stdv); + + + $jahrgangsvertr = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('jgv', $stg_obj->oe_kurzbz, $semester); + if (isError($jahrgangsvertr)) + return $jahrgangsvertr; + $jahrgangsvertr = getData($jahrgangsvertr) ?: []; + $jahrgangsvertr = array_values(array_filter($jahrgangsvertr, function($jahrgang_vertreter){ + return $jahrgang_vertreter->aktiv; + })); + $addEmailProperty($jahrgangsvertr); + + + $result_object = new stdClass(); + $result_object->studiengang = $stg_obj; + $result_object->semester = $semester; + $result_object->stg_ltg = $stg_ltg; + $result_object->gf_ltg = $gf_ltg; + $result_object->stv_ltg = $stv_ltg; + $result_object->ass = $ass; + $result_object->hochschulvertr = $hochschulvertr; + $result_object->stdv = $stdv; + $result_object->jahrgangsvertr = $jahrgangsvertr; + + return success($result_object); + } + + public function getLvaForStudiengangInStudiensemester($studiengang_kz, $orgform_kurzbz, $studiensemester_kurzbz) { + $qry = ' + SELECT DISTINCT ON (lehre.tbl_lehrveranstaltung.lehrveranstaltung_id, + kurzbz, bezeichnung, semester, + lehre.tbl_lehrveranstaltung.sprache, orgform_kurzbz, + lehre.tbl_lehrveranstaltung.lehrform_kurzbz) + lehre.tbl_lehrveranstaltung.lehrveranstaltung_id, kurzbz, bezeichnung, + semester, lehre.tbl_lehrveranstaltung.sprache, orgform_kurzbz, lehre.tbl_lehrveranstaltung.lehrform_kurzbz + FROM lehre.tbl_lehrveranstaltung JOIN lehre.tbl_lehreinheit USING(lehrveranstaltung_id) JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id) + WHERE aktiv = TRUE AND studiengang_kz = ? AND orgform_kurzbz = ? AND tbl_lehreinheit.studiensemester_kurzbz IN ?'; + + return $this->execReadOnlyQuery($qry, array($studiengang_kz, $orgform_kurzbz, $studiensemester_kurzbz)); + } } diff --git a/application/models/organisation/Studienjahr_model.php b/application/models/organisation/Studienjahr_model.php index 3bbe3a07f..1686ddc48 100644 --- a/application/models/organisation/Studienjahr_model.php +++ b/application/models/organisation/Studienjahr_model.php @@ -1,4 +1,5 @@ execQuery($query); + } + public function getNextStudienjahr() + { + $this->addJoin('public.tbl_studiensemester', 'studienjahr_kurzbz'); + $this->addOrder('start'); + $this->addLimit(1); + + return $this->loadWhere(['start >' => 'NOW()']); + } + public function getNextFrom($studienjahr_kurzbz) + { + $this->addLimit(1); + + return $this->loadWhere([ + 'studienjahr_kurzbz >' => $studienjahr_kurzbz + ]); + } + + /** + * 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..569aebd0b 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,98 @@ 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 + ]); + } + + public function getStudienplaeneForPerson($person_id) + { + $this->addDistinct(); + $this->addSelect($this->dbTable . '.*'); + $this->addSelect('ps.*'); + $this->addJoin('public.tbl_prestudentstatus pss', 'studienplan_id'); + $this->addJoin('public.tbl_prestudent ps', 'prestudent_id'); + + return $this->loadWhere([ + 'person_id' => $person_id + ]); + } } diff --git a/application/models/organisation/Studiensemester_model.php b/application/models/organisation/Studiensemester_model.php index 07783cf0d..5fa6ffb14 100644 --- a/application/models/organisation/Studiensemester_model.php +++ b/application/models/organisation/Studiensemester_model.php @@ -13,21 +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 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 @@ -91,7 +105,7 @@ class Studiensemester_model extends DB_Model /** * getPreviousFrom */ - public function getPreviousFrom($studiensemester_kurzbz) + public function getPreviousFrom($studiensemester_kurzbz, $limit = 1) { $query = 'SELECT studiensemester_kurzbz, start, @@ -103,9 +117,9 @@ class Studiensemester_model extends DB_Model WHERE studiensemester_kurzbz = ? ) ORDER BY start DESC - LIMIT 1'; + LIMIT ?'; - return $this->execQuery($query, array($studiensemester_kurzbz)); + return $this->execQuery($query, array($studiensemester_kurzbz, $limit)); } /** @@ -156,26 +170,42 @@ class Studiensemester_model extends DB_Model return $this->execQuery($query, array($studiensemester_kurzbz, $studiengang_kz)); } + /** + * Gets a Studiensemester for a date + * @param $date + * @return string + */ + public function getByDate($date) + { + // gets the studiensemster of a date or the next closest previous studiensemester if a date is not within a studiensemester + $query = " + SELECT studiensemester_kurzbz, start, ende + FROM public.tbl_studiensemester + WHERE ( ende >= ?::date AND start <= ?::date ) OR ( ende >= ?::date + '-45 days'::interval AND start <= ?::date + '-45 days'::interval ) + ORDER BY start DESC + LIMIT 1"; + + return $this->execQuery($query, array($date,$date,$date,$date)); + } + /** * Gets all Studiensemester between two dates * @param $from * @param $to * @return array|null */ - public function getByDate($from, $to) + public function getByDateRange($from, $to) { if (date_format(date_create($from), 'Y-m-d') > (date_format(date_create($to), 'Y-m-d'))) return success(array()); - $query = "SELECT * - FROM public.tbl_studiensemester - WHERE - (ende > ?::date AND start < ?::date) - OR start = ?::date - OR ende = ?::date - ORDER BY start DESC"; + $query = " + SELECT * + FROM public.tbl_studiensemester + WHERE ( ?::date < ende AND ?::date > start ) + ORDER BY start DESC"; - return $this->execQuery($query, array($from, $to, $from, $to)); + return $this->execQuery($query, array($from, $to)); } /** @@ -188,8 +218,133 @@ 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; + } + + /** + * Get Studienjahr by Studiensemester. + * + * @param $studiensemester_kurzbz + * @return array|stdClass + */ + public function getStudienjahrByStudiensemester($studiensemester_kurzbz) + { + $studienjahrObj = null; + + if (!is_numeric($studiensemester_kurzbz)) + { + $this->StudiensemesterModel->addSelect('studienjahr_kurzbz'); + $result = $this->StudiensemesterModel->loadWhere(array('studiensemester_kurzbz =' => $studiensemester_kurzbz)); + } + + if (hasData($result)) + { + $studienjahr = getData($result)[0]->studienjahr_kurzbz; + $startstudienjahr = substr($studienjahr, 0, 4); + $endstudienjahr = substr($studienjahr, 0, 2) . substr($studienjahr, -2); + + $studienjahrObj = new StdClass(); + + $studienjahrObj->studienjahr_kurzbz = $studienjahr; + $studienjahrObj->startstudienjahr = $startstudienjahr; + $studienjahrObj->endstudienjahr= $endstudienjahr; + } + + if (isError($result)) { + return error(getError($result)); + } + + return success($studienjahrObj); + } + + /** + * 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]); + + } + + public function isValidStudiensemester($studiensemester_kurzbz) + { + $result = $this->load($studiensemester_kurzbz); + return hasData($result); + } } 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/Adressentyp_model.php b/application/models/person/Adressentyp_model.php new file mode 100644 index 000000000..94a8c6048 --- /dev/null +++ b/application/models/person/Adressentyp_model.php @@ -0,0 +1,14 @@ +dbTable = 'public.tbl_adressentyp'; + $this->pk = 'adressentyp_kurzbz'; + } +} 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..8c43e4f84 100644 --- a/application/models/person/Benutzerfunktion_model.php +++ b/application/models/person/Benutzerfunktion_model.php @@ -50,6 +50,53 @@ class Benutzerfunktion_model extends DB_Model return $this->execQuery($qry, $params); } + /** + * Lädt alle Benutzerfunktionen zu einer UID im Zeitraum eines Studiensemesters + * + * @param string $uid + * @param string $stdsem + * @param string $funktion_kurzbz (optional) + * + * @return stdClass + */ + public function getBenutzerFunktionByUidInStdsem($uid, $stdsem, $funktion_kurzbz = null) + { + $stdsemEscaped = $this->escape($stdsem); + $this->addSelect($this->dbTable . ".*"); + $this->addSelect("oe.bezeichnung AS organisationseinheit_bezeichnung"); + $this->addSelect("oe.organisationseinheittyp_kurzbz"); + + $this->addJoin("public.tbl_organisationseinheit oe", "oe_kurzbz"); + + $this->db->where("uid", $uid); + + if ($funktion_kurzbz !== null) + $this->db->where("funktion_kurzbz", $funktion_kurzbz); + + $this->db->group_start(); + $this->db->where("datum_bis IS NULL"); + $this->db->or_where("datum_bis >=", "( + SELECT start + FROM public.tbl_studiensemester + WHERE studiensemester_kurzbz = " . $stdsemEscaped . " + )", false); + $this->db->group_end(); + + $this->db->group_start(); + $this->db->where("datum_von IS NULL"); + $this->db->or_where("datum_von <=", "( + SELECT ende + FROM public.tbl_studiensemester + WHERE studiensemester_kurzbz = " . $stdsemEscaped . " + )", false); + $this->db->group_end(); + + $this->addOrder("datum_bis", "NULLS LAST"); + $this->addOrder("datum_von", "NULLS LAST"); + + return $this->load(); + } + /** * Get the Benutzerfunktion using the person_id */ @@ -147,6 +194,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 +259,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..271402ffe 100644 --- a/application/models/person/Benutzergruppe_model.php +++ b/application/models/person/Benutzergruppe_model.php @@ -12,4 +12,37 @@ 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; + } + + /** + * Laedt die Aufnahmegruppe(n) in Abhängigkeit von User und Studiensemester + * @param uid, gruppe_kurzbz, studiensemester_kurzbz + * @return array + */ + public function loadAufnahmegruppen($uid, $stsem) + { + $query = " + SELECT * FROM tbl_gruppe WHERE aufnahmegruppe=true;"; + return $this->execReadOnlyQuery($query); + } } diff --git a/application/models/person/Fotostatusperson_model.php b/application/models/person/Fotostatusperson_model.php new file mode 100644 index 000000000..7f701063d --- /dev/null +++ b/application/models/person/Fotostatusperson_model.php @@ -0,0 +1,22 @@ +dbTable = 'public.tbl_person_fotostatus'; + $this->pk = 'person_fotostatus_id'; + } + + public function getLastFotoStatus($person_id) + { + $this->addOrder('datum', 'DESC'); + $this->addOrder('person_fotostatus_id', 'DESC'); + $this->addLimit(1); + + return $this->loadWhere(array('person_id' => $person_id)); + } + +} \ No newline at end of file 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..1835296fe 100644 --- a/application/models/person/Notiz_model.php +++ b/application/models/person/Notiz_model.php @@ -139,12 +139,74 @@ 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.*, + CASE + WHEN person_verfasser.vorname IS NOT NULL AND person_verfasser.vorname != '' + OR person_verfasser.nachname IS NOT NULL AND person_verfasser.nachname != '' + THEN CONCAT(person_verfasser.vorname, ' ', person_verfasser.nachname) + ELSE NULL + END AS verfasser, + CASE + WHEN person_bearbeiter.vorname IS NOT NULL AND person_bearbeiter.vorname != '' + OR person_bearbeiter.nachname IS NOT NULL AND person_bearbeiter.nachname != '' + THEN CONCAT(person_bearbeiter.vorname, ' ', person_bearbeiter.nachname) + ELSE NULL + END AS bearbeiter, + count(dms_id) as countDoc, z.notizzuordnung_id, + (CASE + WHEN n.updateamum >= n.insertamum THEN n.updateamum + ELSE n.insertamum + END) 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) + LEFT JOIN + public.tbl_benutzer p_verfasser ON (p_verfasser.uid = n.verfasser_uid) + LEFT JOIN + public.tbl_person person_verfasser ON (person_verfasser.person_id = p_verfasser.person_id) + LEFT JOIN + public.tbl_benutzer p_bearbeiter ON (p_bearbeiter.uid = n.bearbeiter_uid) + LEFT JOIN + public.tbl_person person_bearbeiter ON (person_bearbeiter.person_id = p_bearbeiter.person_id) + WHERE + z.$type = ? + GROUP BY + notiz_id, z.notizzuordnung_id, + person_verfasser.vorname, person_verfasser.nachname, + person_bearbeiter.vorname, person_bearbeiter.nachname + "; + + return $this->execQuery($qry, array($type, $id)); + + } + + /** * gets all Notizen for a person with a specific title * @param $person_id @@ -231,6 +293,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 559700390..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']) ); @@ -82,7 +100,7 @@ class Person_model extends DB_Model } else { - $person['svnr'] = $person['svnr'] . 'v' . ($result->retval[0]->svnr{11} + 1); + $person['svnr'] = $person['svnr'] . 'v' . ($result->retval[0]->svnr[11] + 1); } } } @@ -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'); @@ -193,7 +216,7 @@ class Person_model extends DB_Model */ public function getByUid($uid) { - $this->addSelect('vorname, nachname, gebdatum, person_id, bpk, matr_nr'); + $this->addSelect('vorname, nachname, gebdatum, person_id, bpk, matr_nr, foto'); $this->addJoin('tbl_benutzer', 'person_id'); return $this->loadWhere(array('uid' => $uid)); @@ -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,25 +290,40 @@ 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 JOIN public.tbl_person p2 - ON p.vorname = p2.vorname - AND p.nachname = p2.nachname + ON lower(p.vorname) = lower(p2.vorname) + AND lower(p.nachname) = lower(p2.nachname) AND p.gebdatum = p2.gebdatum AND p.person_id = ? ) @@ -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 @@ -310,8 +349,8 @@ class Person_model extends DB_Model SELECT p2.person_id FROM public.tbl_person p JOIN public.tbl_person p2 - ON p.vorname = p2.vorname - AND p.nachname = p2.nachname + ON lower(p.vorname) = lower(p2.vorname) + AND lower(p.nachname) = lower(p2.nachname) AND p.gebdatum = p2.gebdatum AND p.person_id = ? ) @@ -321,8 +360,67 @@ class Person_model extends DB_Model JOIN public.tbl_status USING(status_kurzbz) WHERE status_kurzbz = 'Abbrecher' ) - "; - return $this->execQuery($qry, array($person_id, $person_id)); + UNION + + 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.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 1a97d9e38..219af51b8 100644 --- a/application/models/ressource/Betriebsmittelperson_model.php +++ b/application/models/ressource/Betriebsmittelperson_model.php @@ -55,4 +55,104 @@ class Betriebsmittelperson_model extends DB_Model return $this->loadWhere($condition); } + + public function getBetriebsmittelZuordnung($cardIdentifier, $typ = 'Zutrittskarte', $ausgegeben = true) + { + $this->addJoin('wawi.tbl_betriebsmittel', 'betriebsmittel_id'); + + $where = 'wawi.tbl_betriebsmittel.nummer2 = \'' . $cardIdentifier . '\' + AND wawi.tbl_betriebsmittel.betriebsmitteltyp = \''. $typ .'\' + AND (retouram >= now() OR retouram IS NULL) + '; + + if ($ausgegeben) + $where .= 'AND ausgegebenam <= now()'; + else + $where .= 'AND (ausgegebenam <= now() OR ausgegebenam IS NULL)'; + + return $this->loadWhere($where); + } + + public function getBetriebsmittelByUid($uid, $betriebsmitteltyp = null, $isRetourniert = false) + { + $this->addJoin('wawi.tbl_betriebsmittel', 'betriebsmittel_id'); + + $condition = ' wawi.tbl_betriebsmittelperson.uid = '. $this->escape($uid); + + if (is_string($betriebsmitteltyp)) + { + $condition .= ' AND betriebsmitteltyp = ' . $this->escape($betriebsmitteltyp); + } + + if ($isRetourniert === true) { + $condition .= ' AND retouram IS NOT NULL'; + } + elseif ($isRetourniert === false) + { + $condition .= ' AND retouram IS NULL'; + } + + $this->addOrder('ausgegebenam', 'DESC'); + + return $this->loadWhere($condition); + } + + public function getBetriebsmittelData($id, $type_id, $betriesmitteltypes = null) + { + 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"); + } + + $cond .= " = ? "; + $params[] = $id; + + if ($betriesmitteltypes && !isEmptyArray($betriesmitteltypes)) + { + $cond .= " AND bm.betriebsmitteltyp IN ?"; + $params[] = $betriesmitteltypes; + } + + $query = " + SELECT + bm.nummer, bmp.person_id, bm.betriebsmitteltyp, bmp.anmerkung as anmerkung, + bmp.retouram, + bmp.ausgegebenam, + 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, $params); + } + + /** + * 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..bf4672070 100644 --- a/application/models/ressource/Mitarbeiter_model.php +++ b/application/models/ressource/Mitarbeiter_model.php @@ -12,34 +12,34 @@ class Mitarbeiter_model extends DB_Model $this->pk = 'mitarbeiter_uid'; } - /** - * Checks if the user is a Mitarbeiter. - * @param string $uid - * @param boolean null $fixangestellt - * @return array - */ - public function isMitarbeiter($uid, $fixangestellt = null) - { - $this->addSelect('1'); + /** + * Checks if the user is a Mitarbeiter. + * @param string $uid + * @param boolean null $fixangestellt + * @return array + */ + public function isMitarbeiter($uid, $fixangestellt = null) + { + $this->addSelect('1'); - if (is_bool($fixangestellt)) - { - $result = $this->loadWhere(array('mitarbeiter_uid' => $uid, 'fixangestellt' => $fixangestellt)); - } - else // default - { - $result = $this->loadWhere(array('mitarbeiter_uid' => $uid)); - } + if (is_bool($fixangestellt)) + { + $result = $this->loadWhere(array('mitarbeiter_uid' => $uid, 'fixangestellt' => $fixangestellt)); + } + else // default + { + $result = $this->loadWhere(array('mitarbeiter_uid' => $uid)); + } - if(hasData($result)) - { - return success(true); - } - else - { - return success(false); - } - } + if(hasData($result)) + { + return success(true); + } + else + { + return success(false); + } + } /** * Laedt das Personal @@ -98,6 +98,129 @@ class Mitarbeiter_model extends DB_Model return $this->execQuery($qry, $params); } + /** + * gibt Personen mit Übersicht von Vertragsdaten aus + * + * @return array + */ + public function getPersonenWithContractDetails($person_id = null) + { + $qry = " + SELECT + b.uid , p.person_id, + p.vorname, p.nachname, + gebdatum, + COALESCE(b.alias, b.uid) AS email, + STRING_AGG(DISTINCT va.bezeichnung, ', ') AS Vertragsarten, + STRING_AGG(DISTINCT u.bezeichnung, ', ') AS Unternehmen, + STRING_AGG(d.dienstverhaeltnis_id::TEXT, ', ') AS ids, + b.aktiv + FROM + hr.tbl_dienstverhaeltnis d + JOIN + public.tbl_benutzer b ON d.mitarbeiter_uid = b.uid + JOIN + public.tbl_person p ON p.person_id = b.person_id + JOIN + public.tbl_organisationseinheit u ON d.oe_kurzbz = u.oe_kurzbz + JOIN + hr.tbl_vertragsart va ON d.vertragsart_kurzbz = va.vertragsart_kurzbz + "; + + if($person_id) + { + $qry .= " WHERE p.person_id = ?"; + } + + $qry.= " + GROUP BY + b.uid, p.person_id, p.vorname, p.nachname, b.alias + ORDER BY + p.nachname, p.vorname; + "; + + $params = array($person_id); + + return $this->execQuery($qry, $params); + } + + /** + * get current disciplinary Abteilung of person + * + * @param $person_id + * + * @return Array benutzerfunktionsdata + */ + public function getPersonAbteilung($uid) + { + $qry = " + SELECT + bf.benutzerfunktion_id, bf.fachbereich_kurzbz, bf.uid, bf.funktion_kurzbz, bf.updateamum, + bf.updatevon, bf.insertamum, bf.insertvon, bf.ext_id, bf.semester, bf.oe_kurzbz, + bf.datum_von, bf.datum_bis, bf.bezeichnung, bf.wochenstunden, + oe.oe_kurzbz, oe.oe_parent_kurzbz, oe.bezeichnung, + oe.organisationseinheittyp_kurzbz, oe.aktiv, oe.mailverteiler, + oe.freigabegrenze, oe.kurzzeichen, oe.lehre, oe.standort, + oe.warn_semesterstunden_frei, oe.warn_semesterstunden_fix, oe.standort_id + FROM tbl_benutzerfunktion bf + JOIN public.tbl_organisationseinheit oe USING(oe_kurzbz) + WHERE uid = ? + AND funktion_kurzbz = 'oezuordnung' + AND datum_von <= NOW() + AND (datum_bis IS NULL OR datum_bis >= NOW()) + "; + $result = $this->execQuery($qry, [$uid]); + + return $result; + } + + /** + * get Leitung / Vorgesetzten of current OE + * + * @param $oe_kurzbz + * + * @return Array persondata / benutzerfunktionsdata + */ + public function getLeitungOrg($oe_kurzbz) + { + $qry = " + SELECT bf.benutzerfunktion_id,bf.fachbereich_kurzbz,bf.uid,bf.funktion_kurzbz, + bf.updateamum,bf.updatevon,bf.insertamum,bf.insertvon,bf.ext_id,bf.semester, + bf.oe_kurzbz,bf.datum_von,bf.datum_bis,bf.bezeichnung,bf.wochenstunden, + p.person_id, p.vorname,p.nachname,p.titelpre,p.titelpost + FROM public.tbl_benutzerfunktion bf JOIN public.tbl_organisationseinheit oe USING(oe_kurzbz) + JOIN public.tbl_benutzer b USING (uid) JOIN public.tbl_mitarbeiter ma ON(b.uid=ma.mitarbeiter_uid) + JOIN public.tbl_person p USING(person_id) + WHERE funktion_kurzbz='Leitung' AND oe.oe_kurzbz = ? + AND datum_von<=now() AND (datum_bis is null OR datum_bis>=now()); + "; + + return $this->execQuery($qry, array($oe_kurzbz)); + } + + /** + * get persondata for person_id + * + * @param $oe_kurzbz + * + * @return Array persondata + */ + public function getHeader($person_id) + { + $qry = " + SELECT + titelpre, vorname, nachname, titelpost, foto, foto_sperre, person_id, alias, telefonklappe + FROM + public.tbl_person + JOIN public.tbl_benutzer b USING(person_id) + JOIN public.tbl_mitarbeiter ma ON (ma.mitarbeiter_uid = b.uid) + WHERE + person_id = ? + "; + + return $this->execQuery($qry, array($person_id)); + } + /** * Gibt ein Array mit den UIDs der Vorgesetzten zurück * @return object @@ -144,10 +267,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 +299,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 +308,126 @@ 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); } + + /** + * Search function for mitarbeiter + * @param $filter searchstring: searches for nachname, vorname, mitarbeiter_uid + * $param $mode gives the resultobject in different version: + * null : "[mitarbeiter_uid], Nachname, Vorname, (mitarbeiter_uid)" + * 'mitAkadGrad': "[mitarbeiter_uid], Nachname, Vorname, Titelpre, Titelpost (mitarbeiter_uid)" + * 'ohneMaUid' : "[mitarbeiter_uid], Nachname, Vorname, Titelpre, Titelpost" + * @return object in 3 versions + */ + public function searchMitarbeiter($filter, $mode=null) + { + $filter = strtoLower($filter); + + if ($mode == "mitAkadGrad") + $returnwert = "ma.mitarbeiter_uid, CONCAT(p.nachname, ' ', p.vorname, ' ', p.titelpost, ' ', p.titelpre, ' (', ma.mitarbeiter_uid , ')') as mitarbeiter"; + elseif ($mode == "ohneMaUid") + $returnwert = "p.person_id, CONCAT(p.nachname, ' ', p.vorname, ' ', p.titelpost, ' ', p.titelpre) as mitarbeiter"; + else + $returnwert = "ma.mitarbeiter_uid, CONCAT(p.nachname, ' ', p.vorname, ' (', ma.mitarbeiter_uid , ')') as mitarbeiter"; + + $qry = " + SELECT " . $returnwert . " + 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); + } + + /** + * Gets Mitarbeiter for a certain Lehrveranstaltung. + * + * @param $lehrveranstaltung_id + * @return array with Mitarbeiter and their Lehreinheiten + */ + public function getMitarbeiterFromLV($lehrveranstaltung_id) + { + $qry = "SELECT DISTINCT + lehrveranstaltung_id, uid, vorname, wahlname, vornamen, nachname, titelpre, titelpost, kurzbz, mitarbeiter_uid + FROM + lehre.tbl_lehreinheitmitarbeiter, campus.vw_mitarbeiter, lehre.tbl_lehreinheit + WHERE + lehrveranstaltung_id= ? + AND + mitarbeiter_uid=uid + AND + tbl_lehreinheitmitarbeiter.lehreinheit_id=tbl_lehreinheit.lehreinheit_id;"; + + $parametersArray = array($lehrveranstaltung_id); + + return $this->execQuery($qry, $parametersArray); + } + + /** + * Get Lektoren by studiengang_kz + * + * @param $studiengang_kz + * @return array with Mitarbeiter + */ + public function getLektoren($studiengang_kz) + { + $qry = " + SELECT DISTINCT + campus.vw_mitarbeiter.uid, + campus.vw_mitarbeiter.vorname, + campus.vw_mitarbeiter.nachname, + studiengang_kz, + tbl_studiengang.typ, + tbl_studiengang.kurzbz AS stg_kurzbz + FROM + campus.vw_mitarbeiter + JOIN public.tbl_benutzerfunktion USING (uid) + JOIN public.tbl_studiengang USING(oe_kurzbz) + WHERE studiengang_kz = ? + AND lektor is true + ORDER BY campus.vw_mitarbeiter.nachname"; + + $parametersArray = array($studiengang_kz); + + return $this->execQuery($qry, $parametersArray); + } } 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..789ff3d9c 100644 --- a/application/models/ressource/Reservierung_model.php +++ b/application/models/ressource/Reservierung_model.php @@ -11,4 +11,129 @@ 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) + { + + $lvplan_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)? $lvplan_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 getReservierungenMitarbeiter($start_date, $end_date, $ort_kurzbz = 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.uid = ? AND datum >= ? AND datum <= ?"; + +// $subquery = is_null($ort_kurzbz)? $lvplan_reservierungen_query:$raum_reservierungen_query; + $subquery = $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 + ", [getAuthUID(), $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/Stunde_model.php b/application/models/ressource/Stunde_model.php index 05a9cddff..0203163f7 100644 --- a/application/models/ressource/Stunde_model.php +++ b/application/models/ressource/Stunde_model.php @@ -11,4 +11,19 @@ class Stunde_model extends DB_Model $this->dbTable = 'lehre.tbl_stunde'; $this->pk = 'stunde'; } + + /** + * $time needs to be of PGSQL TIME format + */ + public function getStundeForTime($time) { + $query = " + SELECT min(stunde) as stunde FROM ( + SELECT stunde, extract(epoch from (beginn-?)) AS delta FROM lehre.tbl_stunde + UNION + SELECT stunde, extract(epoch from (ende-?)) AS delta FROM lehre.tbl_stunde + ) foo WHERE delta>=0 + "; + + return $this->execReadOnlyQuery($query, [$time, $time]); + } } diff --git a/application/models/ressource/Stundenplan_model.php b/application/models/ressource/Stundenplan_model.php index be3d520b5..389be582d 100644 --- a/application/models/ressource/Stundenplan_model.php +++ b/application/models/ressource/Stundenplan_model.php @@ -11,4 +11,528 @@ 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, titel, lehrform, lehrfach, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id + + ORDER BY datum, beginn + "); + + return $query_result; + } + + /** + * groups rows of a subquery that fetches data from the lehre.vw_stundenplan table or lehre.vw_stundenplandev + * @param string $stundenplanViewQuery the subquery used to group the result regarding consecutive hours (Tab LV Termine) + * + * @return stdClass + */ + public function stundenplanGruppierungConsecutive($stundenplanViewQuery) + { + $query_result = $this->execReadOnlyQuery(" + SELECT + distinct lehrveranstaltung_id, + datum, + MIN(beginn) as beginn, + MAX(ende) as ende, + type, + topic, + gruppe, + ort_kurzbz, + lehreinheit_id, + lehrfach_bez, + lektor, + lektorname, + gruppen_kuerzel, + farbe + FROM + ( + SELECT + 'lehreinheit' as type, beginn, ende, datum, + CONCAT(lehrfach,'-',lehrform) as topic, + array_agg(DISTINCT lektor) as lektor, + array_agg(DISTINCT lektorname) as lektorname, + array_agg(DISTINCT (gruppe,verband,semester,studiengang_kz,gruppen_kuerzel)) as gruppe, + array_agg(DISTINCT (gruppen_kuerzel)) as gruppen_kuerzel, + 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 (SELECT UPPER(typ || kurzbz) + FROM public.tbl_studiengang + WHERE studiengang_kz=sp.studiengang_kz) || COALESCE(sp.semester,'0') || COALESCE(sp.verband,'') || COALESCE(sp.gruppe,'') + 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,sp.anmerkung,fix,lehrveranstaltung_id, + stg_kurzbzlang,stg_bezeichnung,stg_typ,fachbereich_kurzbz,lehrfach,lehrfach_bez,farbe,lehrform, + anmerkung_lehreinheit,gruppe, verband, semester,stg_kurzbz, + CONCAT(p.nachname, ' ', p.vorname) as lektorname + + FROM (".$stundenplanViewQuery.") sp + JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = sp.stunde + LEFT JOIN public.tbl_benutzer bn ON bn.uid = sp.uid + LEFT JOIN public.tbl_person p ON p.person_id = bn.person_id + ) as subquery + + GROUP BY unr, datum, beginn, ende, ort_kurzbz, titel, lehrform, lehrfach, lehrfach_bez, organisationseinheit, + farbe, lehrveranstaltung_id + + ORDER BY datum, beginn) t + + GROUP BY + lehrveranstaltung_id, + type, + datum, + topic, + lektor, + lehrfach_bez, + gruppe, + ort_kurzbz, + lehreinheit_id, + lektorname, + gruppen_kuerzel, + farbe + ORDER BY + datum, beginn + " + ); + return $query_result; + } + + /** + * queries Stundenplan but for a whole lva, irrespective of who is requesting it + * + * @return void + */ + public function getStundenplanLVA($start_date, $end_date, $lv_id) { + return $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 ( + SELECT sp.* + FROM lehre.vw_stundenplan sp + WHERE + sp.datum >= ? + AND sp.datum <= ? AND sp.lehrveranstaltung_id = ? + ) sp + JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = sp.stunde + + ) as subquery + + GROUP BY unr, datum, beginn, ende, titel, lehrform, lehrfach, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id + + ORDER BY datum, beginn + ", [$start_date, $end_date, $lv_id]); + } + + /** + * queries Stundenplan and filters by assigned ma_kurzbz, very similar to get by LVA + * + * @return void + */ + public function getStundenplanMitarbeiter($start_date, $end_date, $ma_uid) { + return $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 sp.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, + sp.ort_kurzbz, sp.studiengang_kz, sp.titel,sp.lehreinheit_id,sp.lehrfach_id,sp.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 ( + SELECT sp.* + FROM lehre.vw_stundenplan sp + WHERE + sp.datum >= ? + AND sp.datum <= ? + ) sp + JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = sp.stunde + JOIN public.tbl_mitarbeiter ON public.tbl_mitarbeiter.kurzbz = sp.mitarbeiter_kurzbz + WHERE mitarbeiter_uid = ? + + ) as subquery + + GROUP BY unr, datum, beginn, ende, titel, lehrform, lehrfach, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id + + ORDER BY datum, beginn", [$start_date, $end_date, $ma_uid]); + } + + /** + * NO STANDALONE FUNCTION - Generates a SQL query string to fetch 'stundenplan' events for a specific student within the current semester. + * + * @param isLvList if condition needed for Tab LV Termine is given + * @param db_stpl_table enables switch to db 'stundenplandev' + * + * @return mixed + */ + public function getStundenplanQuery($start_date, $end_date, $semester, $gruppen, $studentlehrverbaende, $isLvList=false, $db_stpl_table='stundenplan'){ + + // 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_".$db_stpl_table." 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); + } + + //Condition for showLVList FHC4 + if(!$isLvList) + $stringGroupLv = "AND gruppe_kurzbz is null"; + else + $stringGroupLv =""; + + 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).")". $stringGroupLv. ")"; + + $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 9fa92ae5e..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 = " @@ -61,4 +63,98 @@ class Stundenplandev_model extends DB_Model return $this->execQuery($qry, $parametersArray); } + + /** + * Get Stundenplan data. + * + * @param null $lehrveranstaltung_id + * @param null $studiensemester_kurzbz + * @param null $lehreinheit_id + * @param null $mitarbeiter_uid + * @param null $student_uid + * @param false $nurBevorstehende If true, only future data is retrieved. + * @return array|false|stdClass|null + */ + public function getStundenplanData($lehrveranstaltung_id=null, $studiensemester_kurzbz=null, $lehreinheit_id=null, $mitarbeiter_uid=null, $student_uid=null, $nurBevorstehende = false) + { + $params = array(); + + $qry = "SELECT + stpl.datum, min(stpl.stunde) as stundevon, max(stpl.stunde) as stundebis, + stpl.lehreinheit_id, lehrfach.bezeichnung as lehrfach_bezeichnung, + array_agg( + CASE WHEN gruppe_kurzbz is not null THEN gruppe_kurzbz + ELSE (SELECT UPPER(typ || kurzbz) FROM public.tbl_studiengang WHERE studiengang_kz=stpl.studiengang_kz) || COALESCE(stpl.semester,'0') || COALESCE(stpl.verband,'') || COALESCE(stpl.gruppe,'') + END) as gruppen, array_agg(mitarbeiter_uid) as lektoren, + array_agg(ort_kurzbz) as orte, + array_agg(titel) as titel + FROM + lehre.tbl_stundenplandev as stpl + JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung as lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id) + WHERE "; + + if ($lehrveranstaltung_id != '') + { + $qry.=" + lehreinheit_id IN ( + SELECT lehreinheit_id FROM lehre.tbl_lehreinheit + WHERE lehrveranstaltung_id = ? + AND studiensemester_kurzbz = ? + )"; + + $params[]= $lehrveranstaltung_id; + $params[]= $studiensemester_kurzbz; + + } + elseif ($lehreinheit_id!='') + { + $qry.=" lehreinheit_id = ?"; + + $params[]= $lehreinheit_id; + } + elseif ($mitarbeiter_uid != '') + { + $qry.= " + mitarbeiter_uid = ? + AND lehreinheit_id IN ( + SELECT lehreinheit_id + FROM lehre.tbl_lehreinheitmitarbeiter + JOIN lehre.tbl_lehreinheit USING (lehreinheit_id) + WHERE mitarbeiter_uid = ? + AND studiensemester_kurzbz IN ( ? ) + )"; + $params[] = $mitarbeiter_uid; + $params[] = $mitarbeiter_uid; + $params[] = $studiensemester_kurzbz; + } + elseif ($student_uid != '') + { + $qry.=" + lehreinheit_id IN ( + SELECT lehreinheit_id + FROM campus.vw_student_lehrveranstaltung + WHERE uid = ? + AND studiensemester_kurzbz = ? + )"; + + $params[] = $student_uid; + $params[] = $studiensemester_kurzbz; + } + else + return false; + + if($nurBevorstehende) + { + $qry.= " AND stpl.datum >= NOW()::date "; + } + + $qry.= " + GROUP BY stpl.datum, stpl.unr, stpl.lehreinheit_id, lehrfach.bezeichnung + ORDER BY stpl.datum, min(stpl.stunde), stpl.unr, stpl.lehreinheit_id + "; + + return $this->execQuery($qry, $params); + } + } 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/ressource/Zeitsperre_model.php b/application/models/ressource/Zeitsperre_model.php index 350a7be58..078d29d8b 100644 --- a/application/models/ressource/Zeitsperre_model.php +++ b/application/models/ressource/Zeitsperre_model.php @@ -12,6 +12,47 @@ class Zeitsperre_model extends DB_Model $this->pk = 'zeitsperre_id'; } + /** + * Save or update Zeitsperre. + * + * @param $zeitsperretyp_kurzbz + * @param $mitarbeiter_uid + * @param $vonDatum + * @param $bisDatum + * @param null $vonStunde + * @param null $bisStunde + * @param null $bezeichnung + * @param null $vertretung_uid + * @param null $erreichbarkeit_kurzbz + * @param null $freigabeamum + * @param null $freigabevon + * @return array + */ + public function save($zeitsperretyp_kurzbz, $mitarbeiter_uid, $vonDatum, $bisDatum, + $vonStunde = null, $bisStunde = null, $bezeichnung = null, $vertretung_uid = null, + $erreichbarkeit_kurzbz = null, $freigabeamum = null, $freigabevon = null) + { + return $this->insert(array( + 'zeitsperretyp_kurzbz' => $zeitsperretyp_kurzbz, + 'mitarbeiter_uid' => $mitarbeiter_uid, + 'vondatum' => $vonDatum, + 'bisdatum' => $bisDatum, + 'vonstunde' => $vonStunde, + 'bisstunde' => $bisStunde, + 'bezeichnung' => $bezeichnung, + 'vertretung_uid' => $vertretung_uid, + 'insertvon' => getAuthUID(), + 'insertamum' => (new DateTime())->format('Y-m-d H:i:s'), + 'erreichbarkeit_kurzbz' => $erreichbarkeit_kurzbz, + 'freigabeamum' => $freigabeamum, + 'freigabevon' => $freigabevon + )); + } + + /** + * Delete Zeitsperre. + * @return array|stdClass|null + */ public function deleteEntriesForCurrentDay() { $today = date('Y-m-d'); diff --git a/application/models/ressource/Zeitwunsch_gueltigkeit_model.php b/application/models/ressource/Zeitwunsch_gueltigkeit_model.php new file mode 100644 index 000000000..f26e06d3c --- /dev/null +++ b/application/models/ressource/Zeitwunsch_gueltigkeit_model.php @@ -0,0 +1,14 @@ +dbTable = 'campus.tbl_zeitwunsch_gueltigkeit'; + $this->pk = 'zeitwunsch_gueltigkeit_id'; + } +} \ No newline at end of file diff --git a/application/models/system/Benutzerrolle_model.php b/application/models/system/Benutzerrolle_model.php index 765ad9bd4..0714a1f8f 100644 --- a/application/models/system/Benutzerrolle_model.php +++ b/application/models/system/Benutzerrolle_model.php @@ -43,7 +43,7 @@ class Benutzerrolle_model extends DB_Model * @param null $oe_kurzbz * @return array */ - public function getBenutzerByBerechtigung($berechtigung_kurzbz, $oe_kurzbz = null) + public function getBenutzerByBerechtigung($berechtigung_kurzbz, $oe_kurzbz = null, $art = null) { $params = array(); $query = ' @@ -62,6 +62,12 @@ class Benutzerrolle_model extends DB_Model $params[] = $oe_kurzbz; } + if (!is_null($art)) + { + $query .= ' AND art = ?'; + $params[] = $art; + } + return $this->execQuery($query, $params); } } 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/Fehlerzustaendigkeiten_model.php b/application/models/system/Fehlerzustaendigkeiten_model.php new file mode 100644 index 000000000..9277f3609 --- /dev/null +++ b/application/models/system/Fehlerzustaendigkeiten_model.php @@ -0,0 +1,58 @@ +dbTable = 'system.tbl_fehler_zustaendigkeiten'; + $this->pk = 'fehlerzustaendigkeiten_id'; + } + + /** + * Gets active Mitarbeiter not assigned to a Fehler. + * @param $fehlercode + * @return object + */ + public function getNonAssignedMitarbeiter($fehlercode) + { + $query = "SELECT person_id, ben.uid, vorname, nachname, titelpre, titelpost, personalnummer + FROM public.tbl_mitarbeiter + JOIN public.tbl_benutzer ben ON tbl_mitarbeiter.mitarbeiter_uid = ben.uid + JOIN public.tbl_person pers USING (person_id) + WHERE ben.aktiv + AND NOT EXISTS ( + SELECT 1 FROM system.tbl_fehler_zustaendigkeiten + WHERE person_id = pers.person_id + AND fehlercode = ? + ) + ORDER BY nachname, vorname, uid"; + + return $this->execReadOnlyQuery($query, array($fehlercode)); + } + + /** + * Gets Funktionen not assigned to a Fehler (over an organisational unit). + * @param $fehlercode + * @param $oe_kurzbz + * @return object + */ + public function getNonAssignedFunktionen($fehlercode, $oe_kurzbz) + { + $query = "SELECT funktion_kurzbz, beschreibung + FROM public.tbl_funktion funk + WHERE aktiv + AND NOT EXISTS ( + SELECT 1 FROM system.tbl_fehler_zustaendigkeiten + WHERE funktion_kurzbz = funk.funktion_kurzbz + AND fehlercode = ? + AND oe_kurzbz = ? + ) + ORDER BY beschreibung"; + + return $this->execReadOnlyQuery($query, array($fehlercode, $oe_kurzbz)); + } +} 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/MessageToken_model.php b/application/models/system/MessageToken_model.php index cd3d8f7d9..af7794fdb 100644 --- a/application/models/system/MessageToken_model.php +++ b/application/models/system/MessageToken_model.php @@ -176,4 +176,20 @@ class MessageToken_model extends DB_Model return $this->execQuery($sql, array($oe_kurzbz)); } + + /** + * + */ + public function crossClientData($token, $relationmessage_id, $receiver_id) + { + $sql = 'SELECT mm.message_id + FROM public.tbl_msg_message mm + JOIN public.tbl_msg_recipient mr USING(message_id) + WHERE mr.token = ? + AND mm.message_id = ? + AND mm.person_id = ?'; + + return $this->execQuery($sql, array($token, $relationmessage_id, $receiver_id)); + } } + diff --git a/application/models/system/Message_model.php b/application/models/system/Message_model.php index d9f8585ed..e0a185f9b 100644 --- a/application/models/system/Message_model.php +++ b/application/models/system/Message_model.php @@ -85,7 +85,7 @@ class Message_model extends DB_Model */ public function getMessagesOfPerson($person_id, $status = null) { - $sql = 'SELECT m.message_id, + $sql = "SELECT m.message_id, m.person_id, m.subject, m.body, @@ -122,7 +122,7 @@ class Message_model extends DB_Model ) s ON (m.message_id = s.message_id AND re.person_id = s.person_id) WHERE se.person_id = ? OR re.person_id = ? - '; + "; if (is_numeric($status)) { @@ -230,4 +230,135 @@ class Message_model extends DB_Model return $this->execQuery($query, $params); } + + /** + * Gets messages for a person for tableMessages. + * @param $person_id + * paginationInitialPage: 1, + * @param $offset number to skip, calculated by tabulatorParam paginationInitialPage and paginationSize, refers to specified numer of skipped items + * and page + * @param $limit refers to tabulatorParam paginationSize + * @return array|null + */ + public function getMessagesForTable($person_id, $offset, $limit) + { + $sql_base = " + SELECT + m.message_id AS message_id, + m.subject AS subject, + m.body AS body, + m.insertamum AS insertamum, + m.relationmessage_id AS relationmessage_id, + (SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = m.person_id) as sender, + (SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = r.person_id) as recipient, + m.person_id as sender_id, + r.person_id as recipient_id, + MAX(ss.status) as status, + MAX(ss.insertamum) as statusdatum + FROM public.tbl_msg_message m + JOIN public.tbl_msg_recipient r USING(message_id) + JOIN public.tbl_msg_status ss ON(r.message_id = ss.message_id AND ss.person_id = r.person_id) + WHERE m.person_id = ? + GROUP BY m.message_id, m.subject, m.body, m.insertamum, m.relationmessage_id, sender, recipient, sender_id, recipient_id + UNION ALL + SELECT + m.message_id AS message_id, + m.subject AS subject, + m.body AS body, + m.insertamum AS insertamum, + m.relationmessage_id AS relationmessage_id, + (SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = m.person_id) as sender, + (SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = r.person_id) as recipient, + m.person_id as sender_id, + r.person_id as recipient_id, + MAX(ss.status) as status, + MAX(ss.insertamum) as statusdatum + FROM public.tbl_msg_recipient r + JOIN public.tbl_msg_status ss USING(message_id, person_id) + JOIN public.tbl_msg_message m USING(message_id) + WHERE r.person_id = ? + GROUP BY m.message_id, m.subject, m.body, m.insertamum, m.relationmessage_id, sender, recipient, sender_id, recipient_id + "; + $sql = " + SELECT COUNT(*) AS count FROM ( + " . $sql_base . " + ) a + "; + + $parametersArray = array($person_id, $person_id); + + $count = $this->execQuery($sql, $parametersArray); + + if (isError($count)) + return $count; + + $count = ceil(current(getData($count))->count/$limit); + $sql = " + SELECT * FROM ( + " . $sql_base . " + ) a + ORDER BY insertamum DESC + LIMIT ? + OFFSET ? + "; + + $parametersArray = array($person_id, $person_id, $limit, $offset); + + $data = $this->execQuery($sql, $parametersArray); + + if (isError($data)) + return $data; + + $data = getData($data); + + return success(['data' => $data, 'count' => $count]); + } + + /** + * Deletes entry in dependency table tbl_msg_recipient + * + * @param $message_id + * @return boolean success + */ + public function deleteMessageRecipient($message_id) + { + $sql = " + DELETE FROM public.tbl_msg_recipient + WHERE message_id = ?; + "; + + return $this->execQuery($sql, array($message_id)); + } + + /** + * Deletes entry in dependency table tbl_msg_status + * + * @param $message_id + * @return boolean success + */ + public function deleteMessageStatus($message_id) + { + $sql = " + DELETE FROM public.tbl_msg_status + WHERE message_id = ?; + "; + + return $this->execQuery($sql, array($message_id)); + } + /** + * Deletes entry in dependency table tbl_msg_message + * + * @param $message_id + * @return boolean success + */ + public function deleteMessage($message_id) + { + $sql = " + DELETE FROM public.tbl_msg_message + WHERE message_id = ?; + "; + + return $this->execQuery($sql, array($message_id)); + } + } 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/system/Variablenname_model.php b/application/models/system/Variablenname_model.php index 869a03275..33ace3c8d 100644 --- a/application/models/system/Variablenname_model.php +++ b/application/models/system/Variablenname_model.php @@ -12,7 +12,14 @@ class Variablenname_model extends DB_Model ) sem WHERE start > now() LIMIT 1;', - 'infocenter_studiensgangtyp' => 'SELECT infocenter_studiensgangtyp FROM public.tbl_variablenname LIMIT 1' + 'infocenter_studiensgangtyp' => 'SELECT infocenter_studiensgangtyp FROM public.tbl_variablenname LIMIT 1;', + 'projektuebersicht_studiensemester' => 'SELECT studiensemester_kurzbz FROM ( + SELECT DISTINCT ON (studienjahr_kurzbz) start, studiensemester_kurzbz + FROM public.tbl_studiensemester + ORDER BY studienjahr_kurzbz, start + ) sem + WHERE start > now() + LIMIT 1;' ); /** diff --git a/application/models/system/Vorlage_model.php b/application/models/system/Vorlage_model.php index 8022e71fc..e3c00818a 100644 --- a/application/models/system/Vorlage_model.php +++ b/application/models/system/Vorlage_model.php @@ -13,7 +13,7 @@ class Vorlage_model extends DB_Model } /** - * Returns mume types + * Returns mime types */ public function getMimeTypes() { @@ -21,4 +21,130 @@ class Vorlage_model extends DB_Model return $this->execQuery($query); } + + /** + * Returns all Vorlagen for archive + */ + public function getArchivVorlagen() + { + $query ="SELECT * FROM public.tbl_vorlage WHERE archivierbar=true ORDER BY bezeichnung"; + + return $this->execQuery($query); + } + + /** + * Returns all Vorlagen + * that belongs to the organisation units of the user + * and the parents of those organisation units until the root of the + * @param Array Array of $oe_kurzbz + * @return object Array of Vorlagen + */ + public function getAllVorlagenByOe($oe_kurzbz) + { + // Loads library OrganisationseinheitLib + $this->load->library('OrganisationseinheitLib'); + + $vorlage = success(array()); // Default value + + $table = '( + SELECT v.vorlage_kurzbz, + v.bezeichnung, + vs.version, + vs.oe_kurzbz, + vs.aktiv, + vs.subject, + vs.text, + v.mimetype + FROM tbl_vorlagestudiengang vs + JOIN tbl_vorlage v USING(vorlage_kurzbz) + ) templates'; + + $alias = 'templates'; + + $fields = array( + 'templates.vorlage_kurzbz AS id', + 'templates.bezeichnung || \' (\' || UPPER(templates.oe_kurzbz) || \')\' AS description' + ); + + $where = 'templates.aktiv = TRUE + AND templates.subject IS NOT NULL + AND templates.text IS NOT NULL + AND templates.mimetype = \'text/html\' + GROUP BY 1, 2, 3'; + + $order_by = 'description ASC'; + + if (!is_array($oe_kurzbz)) + { + $vorlage = $this->organisationseinheitlib->treeSearchEntire( + $table, + $alias, + $fields, + $where, + $order_by, + $oe_kurzbz + ); + } + else // is an array + { + // Get the vorlage for each organisation unit + foreach($oe_kurzbz as $val) + { + $tmpVorlage = $this->organisationseinheitlib->treeSearchEntire( + $table, + $alias, + $fields, + $where, + $order_by, + $val + ); + + // Everything is ok and data are inside + if (hasData($tmpVorlage)) + { + // If it's the first vorlage copy it + if (!hasData($vorlage)) + { + for ($j = 0; $j < count(getData($tmpVorlage)); $j++) + { + if (getData($tmpVorlage)[$j]->id != '') + { + array_push($vorlage->retval, getData($tmpVorlage)[$j]); + } + } + } + else // checks for duplicates, if it's not already present push it into the array getData($vorlage) + { + for ($j = 0; $j < count(getData($tmpVorlage)); $j++) + { + $found = false; + $currentTmpVorlageData = null; + + for ($i = 0; $i < count(getData($vorlage)); $i++) + { + $currentTmpVorlageData = getData($tmpVorlage)[$j]; + + if (getData($vorlage)[$i]->id == getData($tmpVorlage)[$j]->id + && getData($vorlage)[$i]->_pk == getData($tmpVorlage)[$j]->_pk + && getData($vorlage)[$i]->_ppk == getData($tmpVorlage)[$j]->_ppk + && getData($vorlage)[$i]->_jtpk == getData($tmpVorlage)[$j]->_jtpk) + { + $found = true; + break; + } + } + + if (!$found && $currentTmpVorlageData->id != '') + { + array_push($vorlage->retval, $currentTmpVorlageData); + } + } + } + } + } + } + + return $vorlage; + } + } diff --git a/application/models/system/Vorlagestudiengang_model.php b/application/models/system/Vorlagestudiengang_model.php index 24af7353c..613d88226 100644 --- a/application/models/system/Vorlagestudiengang_model.php +++ b/application/models/system/Vorlagestudiengang_model.php @@ -11,4 +11,49 @@ class Vorlagestudiengang_model extends DB_Model $this->dbTable = 'public.tbl_vorlagestudiengang'; $this->pk = 'vorlagestudiengang_id'; } + + /** + * Gets the Current Vorlagestudiengang + * + * @param string $vorlage_kurzbz + * @param string $oe_kurzbz Or studiengang_kz + * @param integer $version (optional) + * @param boolean|null $active (optional) + * + * @return stdClass + */ + public function getCurrent($vorlage_kurzbz, $oe_kurzbz, $version = null, $active = true) + { + if (is_numeric($oe_kurzbz)) { + $initselect = "SELECT oe_kurzbz, 1 AS l FROM public.tbl_studiengang WHERE studiengang_kz = " . $this->escape($oe_kurzbz); + } else { + $initselect = "SELECT oe_kurzbz, 1 AS l FROM public.tbl_organisationseinheit WHERE oe_kurzbz = " . $this->escape($oe_kurzbz); + } + + $this->addJoin("( + WITH RECURSIVE tmp (oe_kurzbz, l) AS ( + " . $initselect . " + UNION ALL + SELECT o.oe_parent_kurzbz AS oe_kurzbz, l+1 AS l + FROM tmp + JOIN public.tbl_organisationseinheit o USING (oe_kurzbz) + WHERE o.oe_parent_kurzbz IS NOT NULL + ) SELECT * FROM tmp + ) oe", "oe_kurzbz"); + + if (!is_null($version)) + $this->db->where('version', $version); + if ($active) + $this->db->where('aktiv', true); + + $this->addOrder('l', 'ASC'); + $this->addOrder('version', 'DESC'); + $this->addLimit(1); + + $result = $this->loadWhere([ + 'vorlage_kurzbz' => $vorlage_kurzbz + ]); + + return $result; + } } diff --git a/application/models/testtool/Ablauf_model.php b/application/models/testtool/Ablauf_model.php index 748926658..d6d6ebe74 100644 --- a/application/models/testtool/Ablauf_model.php +++ b/application/models/testtool/Ablauf_model.php @@ -11,4 +11,31 @@ class Ablauf_model extends DB_Model $this->dbTable = 'testtool.tbl_ablauf'; $this->pk = 'ablauf_id'; } + + /** + * Returns Weighting of the respective ranking test areas + * @param $studiengang_kz Studiengang_kz + * @param $semester Integer optional + * @return array of weightings per ranking test areas of given studiengang + */ + public function getAblaufGebieteAndGewichte($studiengang_kz, $semester = null) + { + $parametersArray = array($studiengang_kz); + + $qry = " + SELECT + tbl_ablauf.gebiet_id, tbl_ablauf.gewicht + FROM + testtool.tbl_ablauf + WHERE + tbl_ablauf.studiengang_kz= ?"; + + if($semester) + { + $qry .= " AND semester = ?"; + array_push($parametersArray, $semester); + + } + return $this->execQuery($qry, $parametersArray); + } } diff --git a/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php b/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php new file mode 100644 index 000000000..f81a2d518 --- /dev/null +++ b/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php @@ -0,0 +1,256 @@ +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 + CASE + WHEN (COALESCE(dv.bis, '2999-12-31'::date) - NOW()::date) < 0 THEN NULL + ELSE + (COALESCE(dv.bis, '2999-12-31'::date) - NOW()::date) + END ASC NULLS LAST, + COALESCE(dv.bis, '2999-12-31'::date) DESC, + 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..ce741268d --- /dev/null +++ b/application/models/vertragsbestandteil/Vertragsbestandteil_model.php @@ -0,0 +1,251 @@ +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; + } + + public function getLastVertragsbestanteilStundenBeforeAltersteilzeit($dienstverhaeltnis_id) + { + $sql = <<execReadOnlyQuery($sql, array($dienstverhaeltnis_id)); + $data = getData($query); + + if ($data == null) + { + return null; + } + + $vertragsbestandteil = null; + try + { + $vertragsbestandteil = VertragsbestandteilFactory::getVertragsbestandteil($data[0], true); + } + catch (Exception $ex) + { + echo $ex->getMessage() . "\n"; + } + return $vertragsbestandteil; + } + + /** + * 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/InfoTerminal.php b/application/views/Cis/InfoTerminal.php new file mode 100644 index 000000000..7e89b9f0c --- /dev/null +++ b/application/views/Cis/InfoTerminal.php @@ -0,0 +1,16 @@ + 'Infoterminal', + 'tabulator5' => true, + 'primevue3' => true, +); +$this->load->view( + 'templates/CISVUE-Header', + $includesArray +); +?> + + +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..90f78f123 --- /dev/null +++ b/application/views/Cis/Login.php @@ -0,0 +1,43 @@ + 'FH-Complete', + 'bootstrap5' => true, + 'fontawesome6' => true, + 'customJSs' => 'public/js/helpers/ColorThemeSetting.js' + ); + + $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/Profil.php b/application/views/Cis/Profil.php new file mode 100644 index 000000000..f66ebf8a9 --- /dev/null +++ b/application/views/Cis/Profil.php @@ -0,0 +1,18 @@ + 'Profil', + '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/CisRouterView/CisRouterView.php b/application/views/CisRouterView/CisRouterView.php new file mode 100644 index 000000000..ab22fbb81 --- /dev/null +++ b/application/views/CisRouterView/CisRouterView.php @@ -0,0 +1,48 @@ + 'Cis4', + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'tabulator5' => true, // TODO: upgrade to 6 when available + 'vue3' => true, + 'primevue3' => true, + 'skipID' => '#fhccontent', + 'vuedatepicker11' => true, + 'customCSSs' => array( + 'public/css/components/verticalsplit.css', + 'public/css/components/searchbar/searchbar.css', + 'public/css/Fhc.css', + 'public/css/components/dashboard.css', + //'public/css/components/calendar.css', <= imported in dashboard.css + 'public/css/components/Sprachen.css', + 'public/css/components/MyLv.css', + 'public/css/components/FilterComponent.css', + 'public/css/components/Profil.css', + 'public/css/components/FormUnderline.css', + 'public/css/Cis4/Cms.css', + 'public/css/Cis4/Studium.css', + ), + 'customJSs' => array( + 'vendor/npm-asset/primevue/accordion/accordion.min.js', + 'vendor/npm-asset/primevue/accordiontab/accordiontab.min.js', + 'vendor/npm-asset/primevue/inputnumber/inputnumber.min.js', + 'vendor/npm-asset/primevue/textarea/textarea.min.js', + 'vendor/npm-asset/primevue/checkbox/checkbox.min.js', + 'vendor/moment/luxonjs/luxon.min.js' + ), + 'customJSModules' => array( + 'public/js/apps/Dashboard/Fhc.js' + ), + +); + +$this->load->view('templates/CISVUE-Header', $includesArray); +?> +
> + +
+load->view('templates/CISVUE-Footer', $includesArray); ?> diff --git a/application/views/Nachrichten.php b/application/views/Nachrichten.php new file mode 100644 index 000000000..cf34bfd53 --- /dev/null +++ b/application/views/Nachrichten.php @@ -0,0 +1,48 @@ + 'Nachrichten', + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'vue3' => true, + 'primevue3' => true, + #'filtercomponent' => true, + 'tabulator5' => true, + 'tinymce5' => true, + 'phrases' => array( + 'global', + 'ui', + ), + 'customCSSs' => [ + 'public/css/components/vue-datepicker.css', + 'public/css/components/primevue.css', + ], + 'customJSs' => [ + #'vendor/npm-asset/primevue/tree/tree.min.js', + #'vendor/npm-asset/primevue/toast/toast.min.js' + ], + 'customJSModules' => [ + 'public/js/apps/Nachrichten.js' + ] +); + +$this->load->view('templates/FHC-Header', $includesArray); +?> + + !defined('DOMAIN') ? 'notDefined' : DOMAIN, +]; +?> + +
+ + +
+ +load->view('templates/FHC-Footer', $includesArray); ?> + diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php new file mode 100644 index 000000000..01e611657 --- /dev/null +++ b/application/views/Studentenverwaltung.php @@ -0,0 +1,63 @@ + 'Studentenverwaltung', + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'vue3' => true, + 'primevue3' => true, + #'filtercomponent' => true, + 'tabulator5' => true, + 'tinymce5' => true, + 'phrases' => array( + 'global', + 'ui', + 'notiz', + ), + 'customCSSs' => [ + #datepicker fuer component functions + 'public/css/components/vue-datepicker.css', + 'public/css/components/primevue.css', + 'public/css/Studentenverwaltung.css', + 'public/css/components/function.css' + ], + 'customJSs' => [ + 'vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js' + #'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, + //replaced by possibility to hide each formular field via config stv.php + #'showZgvDoktor' => !defined('ZGV_DOKTOR_ANZEIGEN') ? false : ZGV_DOKTOR_ANZEIGEN, + #'showZgvErfuellt' => !defined('ZGV_ERFUELLT_ANZEIGEN') ? false : ZGV_ERFUELLT_ANZEIGEN + 'showHintKommPrfg' => !defined('FAS_STUDSTATUS_SHOW_KOMM_PRFG_HINT') ? false : FAS_STUDSTATUS_SHOW_KOMM_PRFG_HINT, + 'showAufnahmegruppen' => !defined('FAS_REIHUNGSTEST_AUFNAHMEGRUPPEN') ? false : FAS_REIHUNGSTEST_AUFNAHMEGRUPPEN, + 'allowUebernahmePunkte' => !defined('FAS_REIHUNGSTEST_PUNKTEUEBERNAHME') ? true : FAS_REIHUNGSTEST_PUNKTEUEBERNAHME, + 'useReihungstestPunkte' => !defined('FAS_REIHUNGSTEST_PUNKTE') ? true : FAS_REIHUNGSTEST_PUNKTE, +]; +?> + +
+ + +
+ +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 8a697129e..ba99bbf0c 100644 --- a/application/views/codex/oehbeitrag.php +++ b/application/views/codex/oehbeitrag.php @@ -3,12 +3,12 @@ $this->load->view( 'templates/FHC-Header', array( 'title' => 'ÖH-Beitragsverwaltung', - 'jquery' => true, - 'jqueryui' => true, - 'bootstrap' => true, - 'fontawesome' => true, - 'sbadmintemplate' => true, - 'tablesorter' => true, + 'jquery3' => true, + 'jqueryui1' => true, + 'bootstrap3' => true, + 'fontawesome4' => true, + 'sbadmintemplate3' => true, + 'tablesorter2' => true, 'dialoglib' => true, 'ajaxlib' => true, 'navigationwidget' => true, @@ -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..cb2f219f8 --- /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' : ''; +$savePermission = isset($formMetaData['savePermission']) && $formMetaData['savePermission'] === 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/home.php b/application/views/home.php index 79669dd88..eb7ef0406 100644 --- a/application/views/home.php +++ b/application/views/home.php @@ -1,42 +1,36 @@ load->view('templates/FHC-Header', - array( + $includesArray = array( 'title' => 'FH-Complete', - 'jquery' => true, - 'jqueryui' => true, - 'bootstrap' => true, - 'fontawesome' => true, - 'sbadmintemplate' => true, + 'jquery3' => true, + 'jqueryui1' => true, + 'bootstrap3' => true, + 'fontawesome4' => true, + 'sbadmintemplate3' => true, 'ajaxlib' => true, + 'bootstrapper' => true, // to be used only if you know what you are doing! 'addons' => true, 'navigationwidget' => true - ) -); + ); + + $this->load->view('templates/FHC-Header', $includesArray); ?> - -

- - widgetlib->widget('NavigationWidget'); ?> - -
-
-
-
- +
+ + widgetlib->widget('NavigationWidget'); ?> + +
+
+
+
+ +
+ +
+
- -
-
-
- - -load->view('templates/FHC-Footer'); ?> + +load->view('templates/FHC-Footer', $includesArray); ?> + 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 cd38fd9ac..d7c187ab0 100644 --- a/application/views/lehre/anrechnung/approveAnrechnungDetail.php +++ b/application/views/lehre/anrechnung/approveAnrechnungDetail.php @@ -1,156 +1,228 @@ load->view( - 'templates/FHC-Header', - array( - 'title' => $this->p->t('anrechnung', 'anrechnungenGenehmigen'), - 'jquery' => true, - 'jqueryui' => true, - 'bootstrap' => true, - 'fontawesome' => 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' - ) - ), - '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('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', '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 ?> +
@@ -162,84 +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 308f702a3..d53941113 100644 --- a/application/views/lehre/anrechnung/approveAnrechnungUebersicht.php +++ b/application/views/lehre/anrechnung/approveAnrechnungUebersicht.php @@ -1,109 +1,126 @@ load->view( - 'templates/FHC-Header', - array( - 'title' => $this->p->t('anrechnung', 'anrechnungenGenehmigen'), - 'jquery' => true, - 'jqueryui' => true, - 'bootstrap' => true, - 'fontawesome' => true, - 'tabulator' => 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', @@ -112,75 +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'); ?>
-