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 = '
+
+
+ Name
+ UID
+
+
+ ';
+
+ foreach($uid_arr as $uid)
+ {
+ $person = $this->PersonModel->getByUid($uid);
+ $lektorenTabelle.= '
+
+ '. getData($person)[0]->vorname. ' '. getData($person)[0]->nachname. '
+ ['. $uid. ']
+
+ ';
+ }
+
+ $lektorenTabelle.= '
';
+
+ $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 = '
+
+
+ Name
+ UID
+
+
+ ';
+
+ foreach($uid_arr as $uid)
+ {
+ $person = $this->PersonModel->getByUid($uid);
+ $lektorenTabelle.= '
+
+ '. getData($person)[0]->vorname. ' '. getData($person)[0]->nachname. '
+ ['. $uid. ']
+
+ ';
+ }
+
+ $lektorenTabelle.= '
';
+
+ $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 = '
+
+
+ Name
+ UID
+
+
+ ';
+
+ foreach($data_arr as $lector)
+ {
+ $person = $this->PersonModel->getByUid($lector);
+ $lektorenTabelle.= '
+
+ '. getData($person)[0]->vorname. ' '. getData($person)[0]->nachname. '
+ ['. $lector. ']
+
+ ';
+ }
+
+ $lektorenTabelle.= '
';
+
+ $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 .= ''.$bewerber.' ';
+ }
+ $mailcontent .= '
';
+ $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".'%s ',
- 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; ?>@= DOMAIN; ?>]]>
+ telefonklappe !== null) { ?>
+ kontakt ?: ''; ?> - = $obj->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; ?>@= DOMAIN; ?>]]>
+
+ 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->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'); ?> = strtoupper($studiengang->oe_kurzbz); ?>]]> ';
+
+ view('Cis/Cms/News/Xml/Address/Short', ['obj' => $item]); ?>
+
+
+ p->t('global', 'jahrgangsvertretung'); ?>= $semester; ?> = $this->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);
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dokument
+
+ Studiengang
+
+ Studiensemester
+ Sprache
+ = $this->p->t('tools', 'vorlageWohnsitzfinanzamt'); ?>
+
+
+
+ $this->p->t('global', 'deutsch'), 'StudienerfolgEng' => $this->p->t('global', 'englisch')] as $lang_xsl => $lang) { ?>
+
+
+
+
+
+ = $this->p->t('tools', 'studienerfolgsbestaetigung'); ?>
+
+
+
+ = $stg->bezeichnung; ?>
+
+ = $this->p->t('tools', 'alleStudiensemester'); ?>
+ = $lang; ?>
+ = $finance; ?>
+
+ studiensemester as $stsem => $sem) { ?>
+
+
+
+ = $this->p->t('tools', 'studienerfolgsbestaetigung'); ?>
+
+
+
+ = $stg->bezeichnung; ?>
+
+ = $stsem; ?>
+ = $lang; ?>
+ = $finance; ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->p->t('tools', 'warnungDruckDigitaleSignatur'); ?>
+
+
+
+
+
+
+
+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);
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ sem.studiensemester_kurzbz }}
+
+
+
+
+
+ p->t('bismeldestichtag', 'stichtagHinzufuegen') ?>
+
+
+
+
+
+
+
+
+
+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') ?>
+
+
+
+
+
+ x
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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
+ )
+);
+?>
+
+
+
+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
+ )
+);
+?>
+
+
+
+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
+ );
+}
+
+?>
+
+
+
+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
+);
+?>
+
+
+
+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
+ );
+}
+?>
+
+
+
+
+
+
+
+
+ $array){ ?>
+
= $array['bezeichnungStg']; ?> (= $array['bezeichnungOrgform']; ?>)
+
+
+
+
+
+
+
+
+ #
+ = $this->p->t('studierendenantrag', 'antrag_typ'); ?>
+ = $this->p->t('studierendenantrag', 'antrag_status'); ?>
+ = $this->p->t('studierendenantrag', 'antrag_studiensemester'); ?>
+ = $this->p->t('studierendenantrag', 'antrag_erstelldatum'); ?>
+ = $this->p->t('studierendenantrag', 'antrag_datum_wiedereinstieg'); ?>
+ = $this->p->t('studierendenantrag', 'antrag_grund'); ?>
+ = $this->p->t('studierendenantrag', 'antrag_dateianhaenge'); ?>
+
+
+
+
+
+
+ = $antrag->studierendenantrag_id; ?>
+ = $this->p->t('studierendenantrag', 'antrag_typ_' . $antrag->typ); ?>
+
+ =
+ (
+ $antrag->status == Studierendenantragstatus_model::STATUS_PAUSE
+ && $antrag->status_insertvon == Studierendenantragstatus_model::INSERTVON_DEREGISTERED
+ )
+ ? $this->p->t('studierendenantrag', 'status_stop')
+ : $antrag->status_bezeichnung;
+ ?>
+
+ = $antrag->studiensemester_kurzbz; ?>
+ = (new DateTime($antrag->datum))->format('d.m.Y'); ?>
+ = $antrag->datum_wiedereinstieg ? (new DateTime($antrag->datum_wiedereinstieg))->format('d.m.Y') : ''; ?>
+
+ grund){ ?>
+
+ = $this->p->t('studierendenantrag', 'antrag_grund'); ?>
+
+
+
+
+
+
+
+ dms_id) {?>
+
+ = $this->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
+ ) { ?>
+
+ = $this->p->t('studierendenantrag', 'btn_show_lvs'); ?>
+
+
+ = $this->p->t('studierendenantrag', 'my_lvs'); ?>
+
+
+
+
+
+
+
+
+
+
+ = $this->p->t('studierendenantrag', 'error_no_student'); ?>
+
+
+
+
+
+
+
+
+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
+);
+?>
+
+
+
+
+ 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 @@
+
+
+
+
+
+ = $return ? 'true' : 'false'; ?>
+ ]]>
+
+
+
+
+
+
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'); ?>
+
+
+
+
+
+
+
+
+
+
+
+ p->t('anrechnung', 'anrechnungszeitraumHinzufuegen'); ?>
+
+
+
+
+
+
+
+ load->view('lehre/anrechnung/adminAnrechnungData.php'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Studiensemester
+ widgetlib->widget(
+ 'Studiensemester_widget',
+ array(
+ DropdownWidget::SELECTED_ELEMENT => $studiensemester_kurzbz
+ ),
+ array(
+ 'name' => 'studiensemester',
+ 'id' => 'studiensemester'
+ )
+ );
+ ?>
+
+
+ Anr.-Zeitraum Start
+
+
+
+ Anr.-Zeitraum Ende
+
+
+
+
+
+
+
+
+
+
+
+
+
+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('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 ?>
+ ]
+
+
+
+
-
-
+
+
-
-
- 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 ?>
+
+
+ config->item('explain_equivalence')): ?>
+
+
+ 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', 'genehmigung'); ?>
-
+
+
-
+
-
+
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
+ );
+}
?>
-
-
+
-
+
+
+
-
-
- load->view('lehre/anrechnung/approveAnrechnungUebersichtData.php'); ?>
+
+
+ load->view('lehre/anrechnung/approveAnrechnungUebersichtData.php'); ?>
-
-
-
p->t('anrechnung', 'genehmigungenNegativQuestion'); ?>
-
p->t('anrechnung', 'bitteBegruendungAngeben'); ?>
-
- p->t('anrechnung', 'genehmigungNegativPruefungNichtMoeglich'); ?>
-
+
+ p->t('anrechnung', 'genehmigungenNegativQuestion'); ?>
+
+ p->t('anrechnung', 'bitteBegruendungAngeben'); ?>
+
+ p->t('anrechnung', 'begruendungWirdFuerAlleUebernommen'); ?>
+
+
+
+ p->t('anrechnung', 'genehmigungNegativPruefungNichtMoeglich'); ?>
+
-
+
- p->t('anrechnung', 'genehmigungNegativKenntnisseNichtGleichwertig'); ?>
-
-
+ p->t('anrechnung', 'genehmigungNegativEctsHoechstgrenzeUeberschritten'); ?>
+
+
- p->t('anrechnung', 'andereBegruendung'); ?>
+ p->t('anrechnung', 'genehmigungNegativKenntnisseNichtGleichwertigWeilHinweis'); ?>
-
-
- p->t('anrechnung', 'begruendungWirdFuerAlleUebernommen'); ?>
-
+ rows="2"
+ placeholder="p->t('anrechnung', 'textUebernehmenOderEigenenBegruendungstext'); ?>" required>
-
+
-
+
+ class="me-1 btn btn-outline-secondary btn-w200 " type="reset">
p->t('ui', 'abbrechen')); ?>
+ class="btn btn-primary btn-w200 " type="button">
p->t('ui', 'bestaetigen')); ?>
-
-
-
p->t('anrechnung', 'genehmigungenPositivQuestion'); ?>
- p->t('anrechnung', 'genehmigungenPositiv'); ?>
+
+
p->t('anrechnung', 'genehmigungenPositivQuestion'); ?>
+
p->t('anrechnung', 'genehmigungenPositiv'); ?>
-
+
-
+
+ class="me-1 btn btn-outline-secondary btn-w200" type="reset">
p->t('ui', 'abbrechen')); ?>
load->view(
-
-
-
-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/approveAnrechnungUebersichtData.php b/application/views/lehre/anrechnung/approveAnrechnungUebersichtData.php
index 31e848481..acfcbd907 100644
--- a/application/views/lehre/anrechnung/approveAnrechnungUebersichtData.php
+++ b/application/views/lehre/anrechnung/approveAnrechnungUebersichtData.php
@@ -3,8 +3,9 @@ const ANRECHNUNGSTATUS_PROGRESSED_BY_STGL = 'inProgressDP';
const ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR = 'inProgressLektor';
$STUDIENSEMESTER = $studiensemester_selected;
-$STUDIENGAENGE_ENTITLED = implode(', ', $studiengaenge_entitled);
-$LANGUAGE_INDEX = getUserLanguage() == 'German' ? '0' : '1';
+$STUDIENGAENGE_ENTITLED = implode(', ', $studiengaenge_entitled); // alle STG mit Lese- und Schreibberechtigung
+$ORGANISATIONSEINHEITEN_SCHREIBBERECHTIGT = "'" . implode('\',\'', $oes_schreibberechtigt) . "'"; // alle OE nur mit Schreibberechtigung; singlequote für jeden string notwendig
+$LANGUAGE_INDEX = getUserLanguage() == 'German' ? '1' : '2';
$query = '
WITH anrechnungen AS
@@ -14,24 +15,33 @@ $query = '
anrechnung.lehrveranstaltung_id,
anrechnung.begruendung_id,
anrechnung.dms_id,
+ CASE
+ WHEN stg.typ || stg.kurzbz IN (' . $ORGANISATIONSEINHEITEN_SCHREIBBERECHTIGT . ') THEN TRUE
+ ELSE FALSE
+ END "schreibberechtigt",
anrechnung.studiensemester_kurzbz,
stg.studiengang_kz,
- stg.bezeichnung AS "stg_bezeichnung",
+ stg.bezeichnung AS stg_bezeichnung,
lv.orgform_kurzbz,
(SELECT ausbildungssemester
FROM public.tbl_prestudentstatus press
WHERE press.prestudent_id = anrechnung.prestudent_id
AND press.studiensemester_kurzbz = anrechnung.studiensemester_kurzbz
- AND press.status_kurzbz = \'Student\'),
- lv.bezeichnung AS "lv_bezeichnung",
- lv.ects,
+ AND press.status_kurzbz = \'Student\'
+ ORDER BY press.datum DESC
+ LIMIT 1
+ ),
+ lv.bezeichnung AS lv_bezeichnung,
+ lv.ects::numeric(4,1),
+ get_ects_summe_schulisch(student.student_uid, anrechnung.prestudent_id, stg.studiengang_kz) AS ectsSumSchulisch,
+ get_ects_summe_beruflich(student.student_uid) AS ectsSumBeruflich,
(person.nachname || \' \' || person.vorname) AS "student",
begruendung.bezeichnung AS "begruendung",
dmsversion.name AS "dokument_bezeichnung",
anrechnung.anmerkung_student,
(SELECT COALESCE(
- array_to_json(zgvmaster.bezeichnung::varchar[])->>' . $LANGUAGE_INDEX . ',
- array_to_json(zgv.bezeichnung::varchar[])->>' . $LANGUAGE_INDEX . '
+ zgvmaster.bezeichnung[' . $LANGUAGE_INDEX . '],
+ zgv.bezeichnung[' . $LANGUAGE_INDEX . ']
) AS zgv
FROM public.tbl_prestudent
LEFT JOIN bis.tbl_zgv zgv USING (zgv_code)
@@ -46,7 +56,9 @@ $query = '
WHERE anrechnung_id = anrechnung.anrechnung_id
ORDER BY insertamum DESC
LIMIT 1
- ) AS status_kurzbz
+ ) AS status_kurzbz,
+ student.student_uid,
+ anrechnung.prestudent_id
FROM lehre.tbl_anrechnung AS anrechnung
JOIN public.tbl_prestudent USING (prestudent_id)
JOIN public.tbl_person AS person USING (person_id)
@@ -55,45 +67,101 @@ $query = '
LEFT JOIN campus.tbl_dms_version AS dmsversion USING (dms_id)
JOIN lehre.tbl_anrechnung_anrechnungstatus USING (anrechnung_id)
JOIN lehre.tbl_anrechnung_begruendung AS begruendung USING (begruendung_id)
+ JOIN public.tbl_student student USING (prestudent_id)
+ WHERE anrechnung.studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
+ AND stg.studiengang_kz IN (' . $STUDIENGAENGE_ENTITLED . ')
)
-
- SELECT anrechnungen.*,
- array_to_json(anrechnungstatus.bezeichnung_mehrsprachig::varchar[])->>' . $LANGUAGE_INDEX . ' AS "status_bezeichnung",
- CASE
- WHEN (anrechnungen.empfehlung_anrechnung IS NULL AND anrechnungen.status_kurzbz = \'' . ANRECHNUNGSTATUS_PROGRESSED_BY_STGL . '\') THEN NULL
- ELSE
- (SELECT insertamum::date
- FROM lehre.tbl_anrechnungstatus
- JOIN lehre.tbl_anrechnung_anrechnungstatus USING (status_kurzbz)
- WHERE anrechnung_id = anrechnungen.anrechnung_id
- AND status_kurzbz = \'' . ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR . '\'
- ORDER BY insertamum DESC
- LIMIT 1)
- END "empfehlungsanfrageAm",
- CASE
- WHEN (anrechnungen.empfehlung_anrechnung IS NULL AND anrechnungen.status_kurzbz = \'' . ANRECHNUNGSTATUS_PROGRESSED_BY_STGL . '\') THEN NULL
- ELSE
- (SELECT COALESCE(
- STRING_AGG(CONCAT_WS(\' \', vorname, nachname), \', \') FILTER (WHERE lvleiter = TRUE),
- STRING_AGG(CONCAT_WS(\' \', vorname, nachname), \', \') FILTER (WHERE lvleiter = FALSE)
- ) empfehlungsanfrageAn
- FROM (
- SELECT DISTINCT ON (benutzer.uid) uid, vorname, nachname,
- CASE WHEN lehrfunktion_kurzbz = \'LV-Leitung\' THEN TRUE ELSE FALSE END AS lvleiter
- FROM lehre.tbl_lehreinheit
- JOIN lehre.tbl_lehreinheitmitarbeiter lema USING (lehreinheit_id)
- JOIN public.tbl_benutzer benutzer ON lema.mitarbeiter_uid = benutzer.uid
- JOIN public.tbl_person USING (person_id)
- WHERE studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
- AND lehrveranstaltung_id = anrechnungen.lehrveranstaltung_id
- AND lema.mitarbeiter_uid NOT like \'_Dummy%\'
- AND benutzer.aktiv = TRUE
- AND tbl_person.aktiv = TRUE
- ORDER BY benutzer.uid, lvleiter DESC, nachname, vorname
- ) as tmp_lvlektoren
- )
- END "empfehlungsanfrageAn"
- FROM anrechnungen
+
+ SELECT anrechnungen.anrechnung_id,
+ anrechnungen.lehrveranstaltung_id,
+ anrechnungen.begruendung_id,
+ anrechnungen.dms_id,
+ anrechnungen.schreibberechtigt,
+ anrechnungen.studiensemester_kurzbz,
+ anrechnungen.studiengang_kz,
+ anrechnungen.stg_bezeichnung,
+ anrechnungen.orgform_kurzbz,
+ anrechnungen.ausbildungssemester,
+ anrechnungen.lv_bezeichnung,
+ anrechnungen.ects::float4 AS ects,
+ NULL AS "ectsSumBisherUndNeu",
+ anrechnungen.ectsSumSchulisch::float4 AS "ectsSumSchulisch",
+ anrechnungen.ectsSumBeruflich::float4 AS "ectsSumBeruflich",
+ anrechnungen.begruendung,
+ anrechnungen.student,
+ anrechnungen.dokument_bezeichnung,
+ anrechnungen.anmerkung_student,
+ anrechnungen.zgv,
+ anrechnungen.antragsdatum,
+ anrechnungen.empfehlung_anrechnung,
+ anrechnungen.status_kurzbz,
+ anrechnungstatus.bezeichnung_mehrsprachig[' . $LANGUAGE_INDEX . '] AS "status_bezeichnung",
+ anrechnungen.prestudent_id,
+ CASE
+ WHEN (anrechnungen.empfehlung_anrechnung IS NULL AND anrechnungen.status_kurzbz = \'' . ANRECHNUNGSTATUS_PROGRESSED_BY_STGL . '\') THEN NULL
+ ELSE
+ (SELECT insertamum::date
+ FROM lehre.tbl_anrechnungstatus
+ JOIN lehre.tbl_anrechnung_anrechnungstatus USING (status_kurzbz)
+ WHERE anrechnung_id = anrechnungen.anrechnung_id
+ AND status_kurzbz = \'' . ANRECHNUNGSTATUS_PROGRESSED_BY_LEKTOR . '\'
+ ORDER BY insertamum DESC
+ LIMIT 1)
+ END "empfehlungsanfrageAm",';
+
+if ($configFachbereichsleitung === TRUE) {
+ $query .= ' CASE
+ WHEN (anrechnungen.empfehlung_anrechnung IS NULL AND anrechnungen.status_kurzbz = \'' . ANRECHNUNGSTATUS_PROGRESSED_BY_STGL . '\') THEN NULL
+ ELSE
+ (SELECT COALESCE(
+ STRING_AGG(CONCAT_WS(\' \', vorname, nachname), \', \')
+ ) empfehlungsanfrageAn
+ FROM (
+ SELECT DISTINCT ON (benutzer.uid) bf.uid, vorname, nachname
+ FROM lehre.tbl_lehreinheit
+ JOIN lehre.tbl_lehrveranstaltung lv using (lehrveranstaltung_id)
+ JOIN public.tbl_organisationseinheit og using (oe_kurzbz)
+ JOIN public.tbl_benutzerfunktion bf using (oe_kurzbz)
+ JOIN public.tbl_benutzer benutzer ON bf.uid = benutzer.uid
+ JOIN public.tbl_person USING (person_id)
+ WHERE studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
+ and bf.datum_von <= now()
+ and (bf.datum_bis >= now() or bf.datum_bis is null)
+ AND bf.funktion_kurzbz = \'Leitung\'
+ AND lehrveranstaltung_id = anrechnungen.lehrveranstaltung_id
+ AND benutzer.aktiv = TRUE
+ AND tbl_person.aktiv = TRUE
+ ORDER BY benutzer.uid, nachname, vorname
+ ) as tmp_empfehlungsanfrageEmpfaenger
+ )
+ END "empfehlungsanfrageAn"';
+} else {
+ $query .= ' CASE
+ WHEN (anrechnungen.empfehlung_anrechnung IS NULL AND anrechnungen.status_kurzbz = \'' . ANRECHNUNGSTATUS_PROGRESSED_BY_STGL . '\') THEN NULL
+ ELSE
+ (SELECT COALESCE(
+ STRING_AGG(CONCAT_WS(\' \', vorname, nachname), \', \') FILTER (WHERE lvleiter = TRUE),
+ STRING_AGG(CONCAT_WS(\' \', vorname, nachname), \', \') FILTER (WHERE lvleiter = FALSE)
+ ) empfehlungsanfrageAn
+ FROM (
+ SELECT DISTINCT ON (benutzer.uid) uid, vorname, nachname,
+ CASE WHEN lehrfunktion_kurzbz = \'LV-Leitung\' THEN TRUE ELSE FALSE END AS lvleiter
+ FROM lehre.tbl_lehreinheit
+ JOIN lehre.tbl_lehreinheitmitarbeiter lema USING (lehreinheit_id)
+ JOIN public.tbl_benutzer benutzer ON lema.mitarbeiter_uid = benutzer.uid
+ JOIN public.tbl_person USING (person_id)
+ WHERE studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
+ AND lehrveranstaltung_id = anrechnungen.lehrveranstaltung_id
+ AND lema.mitarbeiter_uid NOT like \'_Dummy%\'
+ AND benutzer.aktiv = TRUE
+ AND tbl_person.aktiv = TRUE
+ ORDER BY benutzer.uid, lvleiter DESC, nachname, vorname
+ ) as tmp_empfehlungsanfrageEmpfaenger
+ )
+ END "empfehlungsanfrageAn"';
+}
+
+$query .= ' FROM anrechnungen
JOIN lehre.tbl_anrechnungstatus as anrechnungstatus ON (anrechnungstatus.status_kurzbz = anrechnungen.status_kurzbz)
WHERE studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
AND studiengang_kz IN (' . $STUDIENGAENGE_ENTITLED . ')
@@ -101,6 +169,7 @@ $query = '
$filterWidgetArray = array(
'query' => $query,
+ 'bootstrapVersion' => 5,
'tableUniqueId' => 'approveAnrechnungUebersicht',
'requiredPermissions' => 'lehre/anrechnung_genehmigen',
'datasetRepresentation' => 'tabulator',
@@ -109,15 +178,19 @@ $filterWidgetArray = array(
'lehrveranstaltung_id',
'begruendung_id',
'dms_id',
+ 'Schreibberechtigt',
'studiensemester_kurzbz',
'studiengang_kz',
ucfirst($this->p->t('lehre', 'studiengang')),
ucfirst($this->p->t('lehre', 'organisationsform')),
'Semester',
ucfirst($this->p->t('lehre', 'lehrveranstaltung')),
- 'ECTS',
- ucfirst($this->p->t('person', 'studentIn')),
+ 'ECTS (LV)',
+ 'ECTS (LV + Bisher)',
+ 'ECTS (Bisher schulisch)',
+ 'ECTS (Bisher beruflich',
ucfirst($this->p->t('global', 'begruendung')),
+ ucfirst($this->p->t('person', 'studentIn')),
ucfirst($this->p->t('anrechnung', 'nachweisdokumente')),
ucfirst($this->p->t('anrechnung', 'herkunft')),
ucfirst($this->p->t('global', 'zgv')),
@@ -125,66 +198,69 @@ $filterWidgetArray = array(
ucfirst($this->p->t('anrechnung', 'empfehlung')),
'status_kurzbz',
'Status',
+ 'PrestudentID',
ucfirst($this->p->t('anrechnung', 'empfehlungsanfrageAm')),
ucfirst($this->p->t('anrechnung', 'empfehlungsanfrageAn'))
),
+
'datasetRepOptions' => '{
+
height: func_height(this),
layout: "fitColumns", // fit columns to width of table
- persistentLayout:true,
- persistentSort:true,
- persistentFilter:true,
+ persistenceID: "approveAnrechnungUebersicht_V1",
autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated
- headerFilterPlaceholder: " ",
- index: "anrechnung_id", // assign specific column as unique id (important for row indexing)
+ index: "anrechnung_id", // assign specific column as unique id (important for row indexing)
selectable: true, // allow row selection
selectableRangeMode: "click", // allow range selection using shift end click on end of range
selectablePersistence:false, // deselect previously selected rows when table is filtered, sorted or paginated
- tableBuilt: function(){
- func_tableBuilt(this);
- },
tableWidgetFooter: {
- selectButtons: true
+ selectButtons: true // tableWidgetFooter properties are checked in _renderTabulatorFooterHTML function
},
selectableCheck: function(row){
return func_selectableCheck(row);
},
- rowFormatter:function(row){
- func_rowFormatter(row);
- },
- rowUpdated:function(row){
- func_rowUpdated(row);
- },
- tooltips: function(cell){
- return func_tooltips(cell);
- }
+ rowFormatter:function(row){
+ return func_rowFormatter(row);
+ },
+
+ columnDefaults:{
+ tooltip:func_tooltips,
+ headerFilterPlaceholder: " ",
+ }
+
}', // tabulator properties
+
'datasetRepFieldsDefs' => '{
anrechnung_id: {visible: false, headerFilter:"input"},
lehrveranstaltung_id: {visible: false, headerFilter:"input"},
begruendung_id: {visible: false, headerFilter:"input"},
dms_id: {visible: false, headerFilter:"input"},
+ schreibberechtigt: {
+ formatter:"tickCross", hozAlign:"center",
+ headerFilter:"tickCross", headerFilterParams:{tristate: true}, headerFilterFunc: hf_schreibberechtigt
+ },
studiensemester_kurzbz: {visible: false, headerFilter:"input"},
studiengang_kz: {visible: false, headerFilter:"input"},
stg_bezeichnung: {headerFilter:"input"},
orgform_kurzbz: {headerFilter:"input"},
ausbildungssemester: {headerFilter:"input"},
lv_bezeichnung: {headerFilter:"input"},
- ects: {headerFilter:"input", align:"center"},
+ ects: {headerFilter:"input", hozAlign:"center"},
+ ectsSumBisherUndNeu: {formatter: format_ectsSumBisherUndNeu},
+ ectsSumSchulisch: {visible: false, headerFilter:"input", hozAlign:"right"},
+ ectsSumBeruflich: {visible: false, headerFilter:"input", hozAlign:"right"},
+ begruendung: {headerFilter:"input", visible: true},
+
student: {headerFilter:"input"},
- begruendung: {headerFilter:"input"},
- zgv: {visible: false, headerFilter:"input"},
- dokument_bezeichnung: {headerFilter:"input", formatter:"link", formatterParams:{
- labelField:"dokument_bezeichnung",
- url:function(cell){return "'. current_url() .'/download?dms_id=" + cell.getData().dms_id},
- target:"_blank"
- }},
+ zgv: {headerFilter:"input"},
+ dokument_bezeichnung: {headerFilter:"input", formatter:"link", formatterParams: paramLookup_dokBez},
anmerkung_student: {headerFilter:"input"},
- antragsdatum: {align:"center", headerFilter:"input", mutator: mut_formatStringDate},
- empfehlung_anrechnung: {headerFilter:"input", align:"center", formatter: format_empfehlung_anrechnung, headerFilterFunc: hf_filterTrueFalse},
+ antragsdatum: {hozAlign:"center", headerFilter:"input", mutator: mut_formatStringDate},
+ empfehlung_anrechnung: {headerFilter:"input", hozAlign:"center", formatter: format_empfehlung_anrechnung, headerFilterFunc: hf_filterTrueFalse},
status_kurzbz: {visible: false, headerFilter:"input"},
status_bezeichnung: {headerFilter:"input"},
- empfehlungsanfrageAm: {visible: false, align:"center", headerFilter:"input", mutator: mut_formatStringDate},
+ prestudent_id: {visible: false, headerFilter:"input"},
+ empfehlungsanfrageAm: {visible: false, hozAlign:"center", headerFilter:"input", mutator: mut_formatStringDate},
empfehlungsanfrageAn: {visible: false, headerFilter:"input"}
}', // col properties
);
diff --git a/application/views/lehre/anrechnung/createAnrechnung.php b/application/views/lehre/anrechnung/createAnrechnung.php
index 58b0757b9..0258b85e1 100644
--- a/application/views/lehre/anrechnung/createAnrechnung.php
+++ b/application/views/lehre/anrechnung/createAnrechnung.php
@@ -1,173 +1,200 @@
load->view(
- 'templates/FHC-Header',
- array(
- 'title' => $this->p->t('anrechnung', 'neueAnrechnung'),
- 'jquery' => true,
- 'jqueryui' => true,
- 'bootstrap' => true,
- 'fontawesome' => true,
- 'ajaxlib' => true,
- 'dialoglib' => true,
- 'tabulator' => true,
- 'tablewidget' => true,
- 'phrases' => array(
- 'global' => array(
- 'anerkennungNachgewiesenerKenntnisse',
- 'antragWurdeGestellt',
- 'antragBereitsGestellt',
- 'antragBearbeiten'
- ),
- 'ui' => array(
- 'hochladen'
- ),
- 'lehre' => array(
- 'studiensemester',
- 'studiengang',
- 'lehrveranstaltung'
- )
+
+$includesArray = array(
+ 'title' => $this->p->t('anrechnung', 'neueAnrechnung'),
+ 'jquery3' => true,
+ 'jqueryui1' => true,
+ 'bootstrap5' => true,
+ 'fontawesome4' => true,
+ 'ajaxlib' => true,
+ 'dialoglib' => true,
+ 'tabulator5' => true,
+ 'tabulator5JQuery' => true,
+ 'cis' => true,
+ 'tablewidget' => true,
+ 'phrases' => array(
+ 'global' => array(
+ 'anerkennungNachgewiesenerKenntnisse',
+ 'antragWurdeGestellt',
+ 'antragBereitsGestellt',
+ 'antragBearbeiten'
),
- 'customJSs' => array(
- 'public/js/bootstrapper.js',
- 'public/js/lehre/anrechnung/createAnrechnung.js'
+ 'ui' => array(
+ 'hochladen'
),
- 'customCSSs' => array(
- 'public/css/lehre/anrechnung.css'
+ 'lehre' => array(
+ 'studiensemester',
+ 'studiengang',
+ 'lehrveranstaltung'
)
+ ),
+ 'customJSs' => array(
+ 'public/js/bootstrapper.js',
+ 'public/js/lehre/anrechnung/createAnrechnung.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
+ );
+}
?>
-
-
+
-
-
-
-
-
-
-
-
-
-
-
- load->view('lehre/anrechnung/createAnrechnungData.php'); ?>
-
-
-
-
-
-
-
-
-
-
-
-
- p->t('person', 'studentIn'); ?>
-
-
-
-
- p->t('lehre', 'lehrveranstaltung'); ?> *
-
-
- >
- p->t('ui', 'bitteWaehlen'); ?>
-
-
-
-
-
-
- p->t('global', 'begruendung'); ?> *
-
-
- >
- p->t('ui', 'bitteWaehlen'); ?>
-
-
- begruendung_id); ?> >
- bezeichnung) ?>
-
-
-
-
-
-
-
- p->t('anrechnung', 'herkunftDerKenntnisse'); ?>
-
- 'herkunftKenntnisse',
- 'rows' => 1
- )); ?>
-
-
-
-
- p->t('anrechnung', 'nachweisdokumente'); ?> *
-
- 'uploadfile',
- 'accept' => '.pdf',
- 'size' => '50',
- 'required' => 'required',
- 'enctype' => "multipart/form-data"
- )); ?>
+
+
+
+
+
+ widgetlib->widget(
+ 'Studiensemester_widget',
+ array(
+ DropdownWidget::SELECTED_ELEMENT => $studiensemester_selected
+ ),
+ array(
+ 'name' => 'studiensemester',
+ 'id' => 'studiensemester',
+ 'class' => 'form-select w-auto ',
+ )
+ );
+ ?>
-
-
-
-
+
+ p->t('ui', 'anzeigen')); ?>
+
+
+
+
+
+
+
+
+ load->view('lehre/anrechnung/createAnrechnungData.php'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ p->t('global', 'antragAnlegen'); ?>
+
+
+
+
+
+
+
+
+
-
-
-
-
-
- p->t('global', 'antragAnlegen'); ?>
-
-
-
-
-
-
-
-
-
-
-
-
+load->view(
+ 'templates/CISVUE-Footer',
+ $includesArray
+ );
+} else {
+ $this->load->view(
+ 'templates/FHC-Footer',
+ $includesArray
+ );
+}
+?>
diff --git a/application/views/lehre/anrechnung/createAnrechnungData.php b/application/views/lehre/anrechnung/createAnrechnungData.php
index 643c64626..e1c27d2d4 100644
--- a/application/views/lehre/anrechnung/createAnrechnungData.php
+++ b/application/views/lehre/anrechnung/createAnrechnungData.php
@@ -2,7 +2,7 @@
$STUDIENSEMESTER = $studiensemester_selected;
$STUDIENGAENGE_ENTITLED = implode(', ', $studiengaenge_entitled);
-$LANGUAGE_INDEX = getUserLanguage() == 'German' ? '0' : '1';
+$LANGUAGE_INDEX = getUserLanguage() == 'German' ? '1' : '2';
$query = '
SELECT pst.prestudent_id,
@@ -14,8 +14,8 @@ $query = '
nachname,
vorname,
(SELECT COALESCE(
- array_to_json(zgvmaster.bezeichnung::varchar[])->>' . $LANGUAGE_INDEX . ',
- array_to_json(zgv.bezeichnung::varchar[])->>' . $LANGUAGE_INDEX . '
+ zgvmaster.bezeichnung[' . $LANGUAGE_INDEX . '],
+ zgv.bezeichnung[' . $LANGUAGE_INDEX . ']
) AS zgv
FROM public.tbl_prestudent
LEFT JOIN bis.tbl_zgv zgv USING (zgv_code)
@@ -37,6 +37,7 @@ $query = '
$filterWidgetArray = array(
'query' => $query,
+ 'bootstrapVersion'=>5,
'tableUniqueId' => 'createAnrechnung',
'requiredPermissions' => 'lehre/anrechnung_anlegen',
'datasetRepresentation' => 'tabulator',
@@ -56,17 +57,13 @@ $filterWidgetArray = array(
layout: "fitColumns", // fit columns to width of table
persistentLayout:true,
autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated
- headerFilterPlaceholder: " ",
index: "prestudent_id", // assign specific column as unique id (important for row indexing)
selectable: 1, // allow row selection
selectablePersistence:false, // deselect previously selected rows when table is filtered, sorted or paginated
- rowSelected: function(row) {
- func_rowSelected(row);
- },
- rowSelectionChanged:function(data, rows){
- func_rowSelectionChanged(data, rows);
- },
- tableWidgetHeader: false
+ tableWidgetHeader: false,
+ columnDefaults:{
+ headerFilterPlaceholder: " ",
+ }
}',
'datasetRepFieldsDefs' => '{
prestudent_id: {visible: false, headerFilter:"input"},
diff --git a/application/views/lehre/anrechnung/requestAnrechnung.php b/application/views/lehre/anrechnung/requestAnrechnung.php
index 978dd5606..81b07b1ee 100644
--- a/application/views/lehre/anrechnung/requestAnrechnung.php
+++ b/application/views/lehre/anrechnung/requestAnrechnung.php
@@ -1,57 +1,82 @@
load->view(
- 'templates/FHC-Header',
- array(
- 'title' => $this->p->t('anrechnung', 'antragStellen'),
- 'jquery' => true,
- 'jqueryui' => true,
- 'bootstrap' => true,
- 'fontawesome' => true,
- 'ajaxlib' => true,
- 'dialoglib' => true,
- 'phrases' => array(
- 'global' => array(
- 'anerkennungNachgewiesenerKenntnisse',
- 'antragStellen',
- 'antragWurdeGestellt',
- 'antragBereitsGestellt',
- 'bearbeitungGesperrt'
- ),
- 'ui' => array(
- 'hilfeZuDieserSeite',
- 'hochladen',
- 'inBearbeitung',
- 'neu',
- 'maxZeichen',
- 'errorBestaetigungFehlt',
- 'systemfehler',
- 'errorDokumentZuGross'
- ),
- 'anrechnung' => array(
- 'deadlineUeberschritten',
- 'benotungDerLV'
- ),
- 'person' => array(
- 'student',
- 'personenkennzeichen'
- ),
- 'lehre' => array(
- 'studiensemester',
- 'studiengang',
- 'lehrveranstaltung',
- 'ects',
- 'lektor',
- )
+$this->load->config('anrechnung');
+
+$includesArray = array(
+ 'title' => $this->p->t('anrechnung', 'antragStellen'),
+ 'jquery3' => true,
+ 'jqueryui1' => true,
+ 'bootstrap5' => true,
+ 'fontawesome4' => true,
+ 'ajaxlib' => true,
+ 'dialoglib' => true,
+ 'cis'=>true,
+ 'phrases' => array(
+ 'global' => array(
+ 'anerkennungNachgewiesenerKenntnisse',
+ 'antragStellen',
+ 'antragWurdeGestellt',
+ 'antragBereitsGestellt',
+ 'bearbeitungGesperrt'
),
- 'customJSs' => array(
- 'public/js/bootstrapper.js',
- 'public/js/lehre/anrechnung/requestAnrechnung.js'
-
+ 'ui' => array(
+ 'hilfeZuDieserSeite',
+ 'hochladen',
+ 'inBearbeitung',
+ 'neu',
+ 'maxZeichen',
+ 'errorBestaetigungFehlt',
+ 'systemfehler',
+ 'errorDokumentZuGross'
+ ),
+ 'anrechnung' => array(
+ 'deadlineUeberschritten',
+ 'benotungDerLV',
+ 'anrechnungEctsTextBeiUeberschreitung',
+ 'anrechnungEctsTooltipTextBeiUeberschreitung'
+ ),
+ 'person' => array(
+ 'student',
+ 'personenkennzeichen'
+ ),
+ 'lehre' => array(
+ 'studiensemester',
+ 'studiengang',
+ 'lehrveranstaltung',
+ 'ects',
+ 'lektor',
)
+ ),
+ 'customJSs' => array(
+ 'public/js/bootstrapper.js',
+ 'public/js/lehre/anrechnung/requestAnrechnung.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
+ );
+}
+
+
?>
-
-
+
-
-
+
-
+
+
-
-
+
+
+
+
+
-
-
-
p->t('anrechnung', 'antrag'); ?>
-
+
+