diff --git a/application/config/Events.php b/application/config/Events.php
new file mode 100644
index 000000000..191a1eb98
--- /dev/null
+++ b/application/config/Events.php
@@ -0,0 +1,14 @@
+ 'TEST',
+ 'component' => './Stv/Studentenverwaltung/Details/Notizen.js'
+ ];
+ });
+ */
diff --git a/application/config/anrechnung.php b/application/config/anrechnung.php
index 768ec3197..2466d2bb1 100644
--- a/application/config/anrechnung.php
+++ b/application/config/anrechnung.php
@@ -21,3 +21,6 @@ $config['grades_blocking_application'] = array(
$config['fbl'] = FALSE;
//Enables Info Mails
$config['send_mail'] = TRUE;
+
+// Display fields to explain equivalence of ECTS and LV-Inhalte
+$config['explain_equivalence'] = TRUE;
diff --git a/application/config/db_crypt.php b/application/config/db_crypt.php
new file mode 100644
index 000000000..b9360861b
--- /dev/null
+++ b/application/config/db_crypt.php
@@ -0,0 +1,29 @@
+.
+ */
+
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+// NOTE: if database encryption is _not_ used then leave this array empty!
+$config['encryption_passwords'] = array(
+ // 'password name 1' => 'password 1'
+ // 'password name 2' => 'password 2'
+ // 'password name ...' => 'password ...'
+ // 'password name N' => 'password N'
+);
+
diff --git a/application/config/migratecontract.php b/application/config/migratecontract.php
new file mode 100644
index 000000000..75ba2f505
--- /dev/null
+++ b/application/config/migratecontract.php
@@ -0,0 +1,36 @@
+.
+ */
+
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+$config['migratecontract_oe_default'] = 'TODO_OE_DEFAULT';
+
+$config['migratecontract_matching_ba1_vertragsart'] = array(
+ '101'=>'dvbund',
+ '102'=>'dvanderengk',
+ '103'=>'echterdv',
+ '104'=>'studentischehilfskr',
+ '105'=>'externerlehrender',
+ '106'=>'dvanderenbet',
+ '107'=>'werkvertrag',
+ '108'=>'studentischehilfskr',
+ '109'=>'ueberlassungsvertrag',
+ '110'=>'echterfreier',
+ '111'=>'echterdv' //All-In
+);
\ No newline at end of file
diff --git a/application/config/navigation.php b/application/config/navigation.php
index 56d142d08..d57cd697a 100644
--- a/application/config/navigation.php
+++ b/application/config/navigation.php
@@ -31,6 +31,14 @@ $config['navigation_header'] = array(
'expand' => true,
'sort' => 20,
'requiredPermissions' => 'admin:w'
+ ),
+ 'bismeldestichtagsverwaltung' => array(
+ 'link' => site_url('codex/Bismeldestichtag'),
+ 'icon' => '',
+ 'description' => 'BIS-Meldestichtagsverwaltung',
+ 'expand' => true,
+ 'sort' => 30,
+ 'requiredPermissions' => 'admin:w'
)
)
),
@@ -47,6 +55,12 @@ $config['navigation_header'] = array(
'description' => 'CIS',
'sort' => 10
),
+ 'lehrveranstaltungen' => array(
+ 'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'),
+ 'icon' => '',
+ 'description' => 'Lehrveranstaltungen',
+ 'sort' => 15
+ ),
'reihungstest' => array(
'link' => site_url('organisation/Reihungstest'),
'description' => 'Reihungstests',
@@ -279,6 +293,15 @@ $config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array(
)
);
+$config['navigation_menu']['lehre/lvplanung/LvTemplateUebersicht/index'] = array(
+ 'lvTemplateUebersicht' => array(
+ 'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'),
+ 'description' => 'LV Template Übersicht',
+ 'icon' => '',
+ 'sort' => 1
+ )
+);
+
$config['navigation_menu']['system/issues/Issues/*'] = array(
'fehlerzustaendigkeiten' => array(
'link' => site_url('system/issues/IssuesZustaendigkeiten'),
diff --git a/application/config/studierendenantrag.php b/application/config/studierendenantrag.php
new file mode 100644
index 000000000..4e25aef28
--- /dev/null
+++ b/application/config/studierendenantrag.php
@@ -0,0 +1,170 @@
+ null, 'dokument_kurzbz' => null, 'kategorie_kurzbz' => null];
+$config['unterbrechung_dms'] = ['oe_kurzbz' => null, 'dokument_kurzbz' => null, 'kategorie_kurzbz' => 'Akte'];
+
+/**
+ * UPLOAD
+ */
+
+/**
+ * Allowed filetypes for attachment upload in unterbrechung antrag
+ *
+ * @var array An array of fileextensions
+ */
+$config['unterbrechung_dms_filetypes'] = ['jpg', 'pdf'];
+
+
+/**
+ * GRADES
+ */
+
+/**
+ * On wiederholung the student must repeat certain lvs.
+ * This lvs will be graded with this id
+ *
+ * @var integer tbl_note.note
+ */
+$config['wiederholung_note_angerechnet'] = 19;
+
+/**
+ * On wiederholung the student can not attend certain lvs.
+ * Those lvs will be graded with this id
+ *
+ * @var integer tbl_note.note
+ */
+$config['wiederholung_note_nicht_zugelassen'] = 20;
+
+
+/**
+ * JOBS
+ */
+
+/**
+ * The Job will remind for every Unterbrecher who has a
+ * wiedereinstieg_datum between the date the Job is run
+ * and the modified date
+ * e.g.: If the Job is running on 2023-04-20 and the modifier
+ * is '+3 days' it will remind of everyone that
+ * has a wiedereinstiegs_datum between 2023-04-20 and 2023-04-23
+ *
+ * @var string A string formated as PHP DateTime modifier
+ * @see https://www.php.net/manual/de/datetime.modify.php
+ */
+$config['unterbrechung_job_remind_wiedereinstieg_date_modifier'] = '+3 days';
+
+/**
+ * The Job will sent a request to everyone who faild the 3rd committee exam
+ * and respecting the given conditions (not repeated yet, stg not in blacklist)
+ * to decide if he/she will repeat or not
+ *
+ * First request
+ *
+ * @var string A string formated as PHP DateTime modifier
+ * @see https://www.php.net/manual/de/datetime.modify.php
+ */
+$config['wiederholung_job_request_1_date_modifier'] = '+0 days';
+
+/**
+ * Second request
+ *
+ * @var string A string formated as PHP DateTime modifier
+ * @see https://www.php.net/manual/de/datetime.modify.php
+ */
+$config['wiederholung_job_request_2_date_modifier'] = '+3 weeks';
+
+/**
+ * Final deadline - after this the student will be abgemeldet if he hasn't chosen yet
+ *
+ * @var string A string formated as PHP DateTime modifier
+ * @see https://www.php.net/manual/de/datetime.modify.php
+ */
+$config['wiederholung_job_deadline_date_modifier'] = '+1 month';
+
+/**
+ * before this exam dates for Wiederholer will be ignored
+ *
+ * @var string A string formated as Date
+ *
+ */
+$config['digitalization_start'] = '2022-07-01';
+
+
+
+
+/**
+ * Objection period - the student will be abgemeldet if he hasn't objected in this period
+ *
+ * @var string A string formated as PHP DateTime modifier
+ * @see https://www.php.net/manual/de/datetime.modify.php
+ */
+$config['abmeldung_job_deadline_date_modifier'] = '+2 weeks';
+
+
+
+/**
+ * System User - uid of a user that is allowed to set prestudentstatus
+ *
+ * @var string
+ */
+$config['antrag_job_systemuser'] = '';
+
+
+/**
+ * WHITELISTS
+ */
+
+/**
+ * List of stati who entitle a prestudent to create an Antrag
+ *
+ * @var array Array of tbl_status.status_kurzbz's
+ */
+$config['antrag_prestudentstatus_whitelist'] = ['Student', 'Diplomand'];
+$config['antrag_prestudentstatus_whitelist_abmeldung'] = ['Student', 'Diplomand', 'Unterbrecher'];
+
+
+/**
+ * BLACKLISTS
+ */
+
+/**
+ * List of Statusgründe that prevent a prestudent from create an Wiederholungsantrag
+ *
+ * @var array An array of tbl_status_grund.statusgrund_id's
+ */
+$config['status_gruende_wiederholer'] = [16, 15];
+
+/**
+ * Blacklisted for abmeldung anträge
+ *
+ * @var array An array of tbl_studiengang.studiengang_kz's
+ */
+$config['stgkz_blacklist_abmeldung'] = [];
+
+/**
+ * Blacklisted for unterbrechung anträge
+ *
+ * @var array An array of tbl_studiengang.studiengang_kz's
+ */
+$config['stgkz_blacklist_unterbrechung'] = [];
+
+/**
+ * Blacklisted for wiederholung anträge
+ *
+ * @var array An array of tbl_studiengang.studiengang_kz's
+ */
+$config['stgkz_blacklist_wiederholung'] = [];
+
+/**
+ * Blacklisted noten for negative committee exams
+ * noten with this ids won't be seen as negative
+ *
+ * @var array An array of noten ids
+ */
+$config['note_blacklist_wiederholung'] = [];
diff --git a/application/controllers/Studentenverwaltung.php b/application/controllers/Studentenverwaltung.php
new file mode 100644
index 000000000..e09d04c6a
--- /dev/null
+++ b/application/controllers/Studentenverwaltung.php
@@ -0,0 +1,40 @@
+method] = ['admin:r', 'assistenz:r'];
+ parent::__construct($permissions);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ }
+
+ /**
+ * @return void
+ */
+ public function _remap()
+ {
+ $this->load->view('Studentenverwaltung', [
+ 'permissions' => [
+ 'student/bpk' => $this->permissionlib->isBerechtigt('student/bpk'),
+ 'student/alias' => $this->permissionlib->isBerechtigt('student/alias'),
+ 'basis/prestudent' => $this->permissionlib->isBerechtigt('basis/prestudent'),
+ 'basis/prestudentstatus' => $this->permissionlib->isBerechtigt('basis/prestudentstatus'),
+ 'assistenz_stgs' => $this->permissionlib->getSTG_isEntitledFor('assistenz'),
+ 'admin' => $this->permissionlib->isBerechtigt('admin'),
+ 'assistenz_schreibrechte' => $this->permissionlib->isBerechtigt('assistenz','suid'),
+ 'student/keine_studstatuspruefung' => $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'),
+ 'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht')
+ ],
+ 'variables' => [
+ 'semester_aktuell' => $this->variablelib->getVar('semester_aktuell')
+ ]
+ ]);
+ }
+}
diff --git a/application/controllers/Test.php b/application/controllers/Test.php
new file mode 100644
index 000000000..2a7aa4e4e
--- /dev/null
+++ b/application/controllers/Test.php
@@ -0,0 +1,16 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+
+/**
+ * This controller operates between (interface) the JS (FAS) and the AntragLib (back-end)
+ * This controller works with calls on the HTTP GET or POST and the output is always RDF
+ */
+class Wiederholung extends Auth_Controller
+{
+
+ /**
+ * Calls the parent's constructor and loads the FilterCmptLib
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getLvs' => ['student/studierendenantrag:r', 'student/noten:r'],
+ 'moveLvsToZeugnis' => ['student/studierendenantrag:w', 'student/noten:w']
+ ]);
+
+ // Libraries
+ $this->load->library('AntragLib');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'global',
+ 'studierendenantrag'
+ ]);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ public function getLvs($prestudent_id)
+ {
+ // header für no cache
+ $this->output->set_header("Cache-Control: no-cache");
+ $this->output->set_header("Cache-Control: post-check=0, pre-check=0", false);
+ $this->output->set_header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
+ $this->output->set_header("Pragma: no-cache");
+ $this->output->set_header("Content-type: application/xhtml+xml");
+
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ $sem_akt = $this->variablelib->getVar('semester_aktuell');
+
+
+ $result = $this->antraglib->getLvsForPrestudent($prestudent_id, $sem_akt);
+ if (isError($result))
+ return $result;
+ $lvs = $result->retval;
+
+ $rdf_url = 'http://www.technikum-wien.at/antragnote';
+
+ $this->load->view('lehre/Antrag/Wiederholung/getLvs.rdf.php', [
+ 'url' => $rdf_url,
+ 'lvs' => $lvs
+ ]);
+ }
+
+ public function moveLvsToZeugnis()
+ {
+ $anzahl = $this->input->post('anzahl');
+ $student_uid = $this->input->post('student_uid');
+ $this->load->model('education/Studierendenantraglehrveranstaltung_model', 'StudierendenantraglehrveranstaltungModel');
+ $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
+
+ $errormsg = array();
+
+ for($i=0; $i<$anzahl; $i++)
+ {
+ $id = $this->input->post('studierendenantrag_lehrveranstaltung_id_' . $i);
+ $result =$this->StudierendenantraglehrveranstaltungModel->load($id);
+ if(isError($result))
+ {
+ $errormsg[] = getError($result);
+ }
+ elseif(!hasData($result))
+ {
+ $errormsg[] = $this->p->t('studierendenantrag', 'error_no_lv_in_application');
+ }
+ else
+ {
+ $antragLv = getData($result)[0];
+ $result= $this->ZeugnisnoteModel->load([
+ 'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
+ 'student_uid'=> $student_uid,
+ 'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz
+ ]);
+ if(isError($result))
+ {
+ $errormsg[] = getError($result);
+ }
+ else
+ {
+ if (hasData($result))
+ {
+ $result = $this->ZeugnisnoteModel->update(
+ [
+ 'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
+ 'student_uid'=> $student_uid,
+ 'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz
+ ],
+ [
+ 'note'=> $antragLv->note,
+ 'uebernahmedatum' => date('c'),
+ 'benotungsdatum' => $antragLv->insertamum,
+ 'updateamum' => date('c'),
+ 'bemerkung'=>$antragLv->anmerkung,
+ 'updatevon'=>getAuthUID()
+ ]
+ );
+ }
+ else
+ {
+ $result = $this->ZeugnisnoteModel->insert([
+ 'lehrveranstaltung_id'=> $antragLv->lehrveranstaltung_id,
+ 'student_uid'=> $student_uid,
+ 'studiensemester_kurzbz' => $antragLv->studiensemester_kurzbz,
+ 'note'=> $antragLv->note,
+ 'uebernahmedatum' => date('c'),
+ 'benotungsdatum' => $antragLv->insertamum,
+ 'insertamum' => date('c'),
+ 'bemerkung'=>$antragLv->anmerkung,
+ 'insertvon'=>getAuthUID()
+ ]);
+ }
+ if(isError($result))
+ {
+ $errormsg[] = getError($result);
+ }
+ }
+ }
+ }
+
+ if($errormsg)
+ $return = false;
+ else
+ $return = true;
+
+ $this->load->view('lehre/Antrag/Wiederholung/moveLvs.rdf.php', [
+ 'return' => $return,
+ 'errormsg' => $errormsg
+ ]);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/Filter.php b/application/controllers/api/frontend/v1/Filter.php
new file mode 100644
index 000000000..45838fc5f
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Filter.php
@@ -0,0 +1,231 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the FilterCmptLib (back-end)
+ * Provides data to the ajax get calls about the filter component
+ * Listens to ajax post calls to change the filter data
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Filter extends FHCAPI_Controller
+{
+ const FILTER_UNIQUE_ID = 'filterUniqueId'; // Name of the filter cmpt unique id (mandatory)
+ const FILTER_TYPE = 'filterType'; // The filter type (PHP filter definition) used (mandatory)
+ const FILTER_ID = 'filterId'; // The id of the used filter (optional)
+
+ /**
+ * Calls the parent's constructor and loads the FilterCmptLib
+ */
+ public function __construct()
+ {
+ // NOTE: FilterCmpt has its own permissions checks
+ parent::__construct([
+ 'getFilter' => self::PERM_LOGGED,
+ 'removeFilterField' => self::PERM_LOGGED,
+ 'addFilterField' => self::PERM_LOGGED,
+ 'applyFilterFields' => self::PERM_LOGGED,
+ 'removeCustomFilter' => self::PERM_LOGGED,
+ 'saveCustomFilter' => self::PERM_LOGGED,
+ 'reloadDataset' => self::PERM_LOGGED
+ ]);
+
+ // Loads the FiltersModel
+ $this->load->model('system/Filters_model', 'FiltersModel');
+
+ // Loads the FilterCmptLib with HTTP GET/POST parameters
+ $this->_startFilterCmptLib();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Retrieves data about the current filter from the session and will be written on the output in JSON format
+ */
+ public function getFilter()
+ {
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $session = $this->filtercmptlib->getSession();
+ if (is_object($session)) {
+ // If stdClass it is an retval object
+ $session = $this->getDataOrTerminateWithError($session);
+ }
+ $this->terminateWithSuccess($session);
+ }
+
+ /**
+ * Remove an applied filter (SQL where condition) from the current filter
+ */
+ public function removeFilterField()
+ {
+ $this->form_validation->set_rules('filterField', 'filterField', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $result = $this->filtercmptlib->removeFilterField($this->input->post('filterField'));
+
+ if (!$result)
+ $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
+
+ $this->terminateWithSuccess('Field removed');
+ }
+
+ /**
+ * Add a filter (SQL where clause) to be applied to the current filter
+ */
+ public function addFilterField()
+ {
+ $this->form_validation->set_rules('filterField', 'filterField', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $result = $this->filtercmptlib->addFilterField($this->input->post('filterField'));
+
+ if (!$result)
+ $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
+
+ $this->terminateWithSuccess('Field added');
+ }
+
+ /**
+ * Apply the filter changes
+ */
+ public function applyFilterFields()
+ {
+ $this->form_validation->set_rules('filterFields', 'filterFields', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $result = $this->filtercmptlib->applyFilterFields($this->input->post('filterFields'));
+
+ if (!$result)
+ $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
+
+ $this->terminateWithSuccess('Applied');
+ }
+
+ /**
+ * Save the current filter as a custom filter for this user with the given description
+ */
+ public function saveCustomFilter()
+ {
+ $this->form_validation->set_rules('customFilterName', 'customFilterName', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $result = $this->filtercmptlib->saveCustomFilter($this->input->post('customFilterName'));
+
+ if (!$result)
+ $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
+
+ $this->terminateWithSuccess('Saved');
+ }
+
+ /**
+ * Remove a custom filter by its filterId
+ */
+ public function removeCustomFilter()
+ {
+ $this->form_validation->set_rules('filterId', 'filterId', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $result = $this->filtercmptlib->removeCustomFilter($this->input->post('filterId'));
+
+ if (!$result)
+ $this->terminateWithError('Error occurred', self::ERROR_TYPE_GENERAL);
+
+ $this->terminateWithSuccess('Removed');
+ }
+
+ /**
+ * Reloads the dataset
+ */
+ public function reloadDataset()
+ {
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $this->filtercmptlib->reloadDataset();
+
+ $this->terminateWithSuccess('Success');
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Private methods
+
+ /**
+ * Loads the FilterCmptLib with the FILTER_UNIQUE_ID parameter
+ * If the parameter FILTER_UNIQUE_ID is not given then the execution of the controller is terminated and
+ * an error message is printed
+ */
+ private function _startFilterCmptLib()
+ {
+ $filterUniqueId = null;
+ $filterType = null;
+ $filterId = null;
+
+ $validations = [
+ [
+ 'field' => self::FILTER_UNIQUE_ID,
+ 'label' => self::FILTER_UNIQUE_ID,
+ 'rules' => 'required'
+ ],
+ [
+ 'field' => self::FILTER_TYPE,
+ 'label' => self::FILTER_TYPE,
+ 'rules' => 'required'
+ ],
+ ];
+
+ $this->load->library('form_validation');
+
+ if ($this->input->method() == 'get')
+ $this->form_validation->set_data($this->input->get());
+ $this->form_validation->set_rules($validations);
+
+ if ($this->form_validation->run()) {
+ $filterUniqueId = $this->input->post_get(self::FILTER_UNIQUE_ID);
+ $filterType = $this->input->post_get(self::FILTER_TYPE);
+ $filterId = $this->input->post_get(self::FILTER_ID);
+
+ // Loads the FilterCmptLib that contains all the used logic
+ $this->load->library(
+ 'FilterCmptLib',
+ array(
+ 'filterUniqueId' => $filterUniqueId,
+ 'filterType' => $filterType,
+ 'filterId' => $filterId
+ )
+ );
+
+ // Start the component
+ $this->filtercmptlib->start();
+ }
+ }
+}
+
diff --git a/application/controllers/api/frontend/v1/Navigation.php b/application/controllers/api/frontend/v1/Navigation.php
new file mode 100644
index 000000000..6cbbbd385
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Navigation.php
@@ -0,0 +1,101 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the NavigationLib (back-end)
+ * Provides data to the ajax get calls about the filter
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Navigation extends FHCAPI_Controller
+{
+ const NAVIGATION_PAGE_PARAM = 'navigation_page'; // Navigation page parameter name
+
+ /**
+ * Loads the NavigationLib where the used logic lies
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'menu' => self::PERM_LOGGED,
+ 'header' => self::PERM_LOGGED
+ ]);
+
+ $this->_loadNavigationLib(); // Loads the NavigationLib with parameters
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * This function creates the left Menu for each Page
+ * @param NAVIGATION_PAGE_PARAM GET Parameter witch holds the currently called Page
+ * @return JSON object with the Menu Entries
+ */
+ public function menu()
+ {
+ $menuArray = $this->navigationlib->getMenuArray($this->input->get(self::NAVIGATION_PAGE_PARAM));
+
+ $this->terminateWithSuccess($menuArray);
+ }
+
+ /**
+ * This function creates the Top Menu for each Page
+ * @param NAVIGATION_PAGE_PARAM GET Parameter witch holds the currently called Page
+ * @return JSON object with the Menu Entries
+ */
+ public function header()
+ {
+ $headerArray = $this->navigationlib->getHeaderArray($this->input->get(self::NAVIGATION_PAGE_PARAM));
+
+ $this->terminateWithSuccess($headerArray);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Private methods
+
+ /**
+ * Loads the NavigationLib with the NAVIGATION_PAGE_PARAM parameter
+ * If the parameter NAVIGATION_PAGE_PARAM is not given then the execution of the controller is terminated and
+ * an error message is printed
+ */
+ private function _loadNavigationLib()
+ {
+ // If the parameter NAVIGATION_PAGE_PARAM is present in the HTTP GET or POST
+ if (isset($_GET[self::NAVIGATION_PAGE_PARAM]) || isset($_POST[self::NAVIGATION_PAGE_PARAM]))
+ {
+ // If it is present in the HTTP GET
+ if (isset($_GET[self::NAVIGATION_PAGE_PARAM]))
+ {
+ $navigationPage = $this->input->get(self::NAVIGATION_PAGE_PARAM); // is retrieved from the HTTP GET
+ }
+ elseif (isset($_POST[self::NAVIGATION_PAGE_PARAM])) // Else if it is present in the HTTP POST
+ {
+ $navigationPage = $this->input->post(self::NAVIGATION_PAGE_PARAM); // is retrieved from the HTTP POST
+ }
+
+ // Loads the NavigationLib that contains all the used logic
+ $this->load->library('NavigationLib', array(self::NAVIGATION_PAGE_PARAM => $navigationPage));
+ }
+ else // Otherwise an error will be written in the output
+ {
+ show_error('Parameter "' . self::NAVIGATION_PAGE_PARAM . '" not provided!');
+ }
+ }
+}
diff --git a/application/controllers/api/frontend/v1/Phrasen.php b/application/controllers/api/frontend/v1/Phrasen.php
new file mode 100644
index 000000000..472308d2b
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Phrasen.php
@@ -0,0 +1,46 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the PhrasesLib (back-end)
+ * Provides data to the ajax get calls about the Phrasen plugin
+ * This controller works with JSON calls on the HTTP GET and the output is always JSON
+ */
+class Phrasen extends FHCAPI_Controller
+{
+ public function __construct()
+ {
+ parent::__construct([
+ 'loadModule' => self::PERM_ANONYMOUS
+ ]);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * @param string $module
+ */
+ public function loadModule($module)
+ {
+ $this->load->library('PhrasesLib', [$module], 'pj');
+ $this->terminateWithSuccess(json_decode($this->pj->getJSON()));
+ }
+}
diff --git a/application/controllers/api/frontend/v1/Searchbar.php b/application/controllers/api/frontend/v1/Searchbar.php
new file mode 100644
index 000000000..8b383e042
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Searchbar.php
@@ -0,0 +1,69 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the SearchBarLib (back-end)
+ * Provides data to the ajax get calls about the searchbar component
+ * This controller works with JSON calls on the HTTP GET and the output is always JSON
+ */
+class Searchbar extends FHCAPI_Controller
+{
+ const SEARCHSTR_PARAM = 'searchstr';
+ const TYPES_PARAM = 'types';
+
+ /**
+ * Object initialization
+ */
+ public function __construct()
+ {
+ // NOTE(chris): additional permission checks will be done in SearchBarLib
+ parent::__construct([
+ 'search' => self::PERM_LOGGED
+ ]);
+
+ // Load the library SearchBarLib
+ $this->load->library('SearchBarLib');
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Gets a JSON body via HTTP POST and provides the parameters
+ */
+ public function search()
+ {
+ $this->load->library('form_validation');
+
+ // Checks if the searchstr and the types parameters are in the POSTed JSON
+ $this->form_validation->set_rules(self::SEARCHSTR_PARAM, null, 'required');
+ $this->form_validation->set_rules(self::TYPES_PARAM . '[]', null, 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithError(SearchBarLib::ERROR_WRONG_JSON, self::ERROR_TYPE_GENERAL);
+
+ // Convert to json the result from searchbarlib->search
+ $result = $this->searchbarlib->search($this->input->post(self::SEARCHSTR_PARAM), $this->input->post(self::TYPES_PARAM));
+ if (property_exists($result, 'error'))
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ $this->terminateWithSuccess($result);
+ }
+}
+
diff --git a/application/controllers/api/frontend/v1/Udf.php b/application/controllers/api/frontend/v1/Udf.php
new file mode 100644
index 000000000..4bdc613e0
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Udf.php
@@ -0,0 +1,133 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the UDFLib (back-end)
+ * Provides data to the ajax get calls about the Udf component
+ * Listens to ajax post calls to change the Udf data
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Udf extends FHCAPI_Controller
+{
+ /**
+ * Calls the parent's constructor and prepares the UDFLib
+ */
+ public function __construct()
+ {
+ // NOTE: UdfLib has its own permissions checks
+ parent::__construct([
+ 'load' => self::PERM_LOGGED,
+ 'save' => self::PERM_LOGGED
+ ]);
+
+ // Libraries
+ $this->load->library('form_validation');
+ $this->load->library('UDFLib');
+
+ // Models
+ $this->load->model($this->getTargetModelPath(), 'TargetModel');
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Load all UDFs for a dataset
+ *
+ * @return void
+ */
+ public function load()
+ {
+ $pks = $this->TargetModel->getPks();
+ foreach ($pks as $id)
+ $this->form_validation->set_rules($id, $id, 'required');
+
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ $id = [];
+ foreach ($pks as $pk)
+ $id[$pk] = $this->input->post($pk);
+ if (!is_array($this->TargetModel->getPk()))
+ $id = current($id);
+
+ $result = $this->udflib->getFieldArray($this->TargetModel, $id);
+
+ $fields = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($fields);
+ }
+
+ /**
+ * Saves UDFs to a dataset
+ *
+ * @return void
+ */
+ public function save()
+ {
+ $pks = $this->TargetModel->getPks();
+ foreach ($pks as $id)
+ $this->form_validation->set_rules($id, $id, 'required');
+
+ $result = $this->udflib->getCiValidations($this->TargetModel, $this->input->post());
+
+ $fieldValidations = $this->getDataOrTerminateWithError($result);
+
+ $this->form_validation->set_rules($fieldvalidations);
+
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ $id = [];
+ $fields = $this->input->post();
+ foreach ($pks as $pk) {
+ $id[$pk] = $fields[$pk];
+ unset($fields[$pk]);
+ }
+ if (!is_array($this->TargetModel->getPk()))
+ $id = current($id);
+
+ $result = $this->TargetModel->update($id, $fields);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess(array_fill_keys(array_keys($fields), ''));
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Private methods
+
+ /**
+ * Get the path to the target model from the url
+ *
+ * @return string
+ */
+ private function getTargetModelPath()
+ {
+ $ci_model_path = array_slice($this->uri->rsegments, 2);
+ if ($ci_model_path)
+ $ci_model_path[] = ucfirst(array_pop($ci_model_path)) . '_model';
+ return implode(DIRECTORY_SEPARATOR, $ci_model_path);
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/betriebsmittel/BetriebsmittelP.php b/application/controllers/api/frontend/v1/betriebsmittel/BetriebsmittelP.php
new file mode 100644
index 000000000..8e44b2326
--- /dev/null
+++ b/application/controllers/api/frontend/v1/betriebsmittel/BetriebsmittelP.php
@@ -0,0 +1,387 @@
+ ['admin:r', 'assistenz:r'],
+ 'addNewBetriebsmittel' => self::PERM_LOGGED,
+ 'updateBetriebsmittel' => self::PERM_LOGGED,
+ 'loadBetriebsmittel' => ['admin:r', 'assistenz:r'],
+ 'deleteBetriebsmittel' => self::PERM_LOGGED,
+ 'getTypenBetriebsmittel' => ['admin:r', 'assistenz:r'],
+ 'loadInventarliste' => ['admin:r', 'assistenz:r']
+ ]);
+
+ //Load Models
+ $this->load->model('ressource/Betriebsmittel_model', 'BetriebsmittelModel');
+ $this->load->model('ressource/Betriebsmittelperson_model', 'BetriebsmittelpersonModel');
+
+ // Additional Permission Checks
+ if ($this->router->method == 'addNewBetriebsmittel') {
+ $this->person_id = current(array_slice($this->uri->rsegments, 2));
+
+ $this->checkPermissionsForPerson(
+ $this->person_id,
+ ['admin:rw', 'mitarbeiter:rw', 'basis/betriebsmittel:rw'],
+ ['admin:rw', 'assistenz:rw', 'basis/betriebsmittel:rw']
+ );
+ } elseif ($this->router->method == 'updateBetriebsmittel' || $this->router->method == 'deleteBetriebsmittel') {
+ $betriebsmittelperson_id = current(array_slice($this->uri->rsegments, 2));
+ $result = $this->BetriebsmittelpersonModel->load($betriebsmittelperson_id);
+ if (!hasData($result))
+ show_404();
+ $this->person_id = current(getData($result))->person_id;
+
+ $this->checkPermissionsForPerson(
+ $this->person_id,
+ ['admin:rw', 'mitarbeiter:rw', 'basis/betriebsmittel:rw'],
+ ['admin:rw', 'assistenz:rw', 'basis/betriebsmittel:rw']
+ );
+ }
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ $this->load->library('form_validation');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui',
+ 'wawi'
+ ]);
+ }
+
+ public function getAllBetriebsmittel($type_id, $id)
+ {
+ $result = $this->BetriebsmittelpersonModel->getBetriebsmittelData($id, $type_id);
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ protected function validateNewOrUpdate()
+ {
+ $this->form_validation->set_rules('betriebsmitteltyp', 'Typ', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired')
+ ]);
+
+ $this->form_validation->set_rules('kaution', 'Kaution', 'numeric|less_than_equal_to[9999.99]', [
+ 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric')
+ ]);
+
+ $this->form_validation->set_rules('ausgegebenam', 'Ausgegeben am', 'required|is_valid_date', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired')
+ ]);
+
+ if ($this->input->post('ausgegebenam') && $this->input->post('retouram')) {
+ $this->form_validation->set_rules('retouram', 'Retour am', [
+ 'is_valid_date',
+ ['is_not_before_ausgegebenam', function ($value) {
+ return (new DateTime($value) >= new DateTime($this->input->post('ausgegebenam')));
+ }]
+ ], [
+ 'is_not_before_ausgegebenam' => $this->p->t('wawi', 'error_retourdatumVorAusgabe')
+ ]);
+ } else {
+ $this->form_validation->set_rules('retouram', 'Retour am', 'is_valid_date');
+ }
+
+ $this->form_validation->set_rules('anmerkung', 'Anmerkung', 'max_length[256]');
+
+ if ($this->input->post('betriebsmitteltyp') == 'Inventar') {
+ // Inventar
+ $this->form_validation->set_rules('betriebsmittel_id', 'Inventarnummer', 'required');
+ } elseif ($this->input->post('betriebsmitteltyp') == 'Zutrittskarte') {
+ // Zutrittskarte
+ if ($this->input->post('nummer') === null && $this->input->post('nummer') === null) {
+ $this->form_validation->set_rules('nummer', 'Nummer', 'required', [
+ 'required' => $this->p->t('wawi', 'error_zutrittskarteOhneNummer')
+ ]);
+ $this->form_validation->set_rules('nummer2', 'Nummer2', 'required', [
+ 'required' => $this->p->t('wawi', 'error_zutrittskarteOhneNummer')
+ ]);
+ } else {
+ if ($this->input->post('nummer') === null) {
+ $result = $this->BetriebsmittelpersonModel->loadViewWhere([
+ 'betriebsmitteltyp' => $this->input->post('betriebsmitteltyp'),
+ 'nummer2' => $this->input->post('nummer2'),
+ 'person_id !=' => $this->person_id,
+ 'retouram IS NULL' => null
+ ]);
+ if (hasData($result))
+ $this->form_validation->set_rules('nummer2', 'Nummer2', 'is_array', [
+ 'is_array' => $this->p->t('wawi', 'error_bmZutrittskarteOccupied', (array)current(getData($result)))
+ ]);
+ } else {
+ $result = $this->BetriebsmittelpersonModel->loadViewWhere([
+ 'betriebsmitteltyp' => $this->input->post('betriebsmitteltyp'),
+ 'nummer' => $this->input->post('nummer'),
+ 'person_id !=' => $this->person_id,
+ 'retouram IS NULL' => null
+ ]);
+ if (hasData($result))
+ $this->form_validation->set_rules('nummer', 'Nummer', 'is_array', [
+ 'is_array' => $this->p->t('wawi', 'error_bmZutrittskarteOccupied', (array)current(getData($result)))
+ ]);
+ }
+ }
+ }
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ public function addNewBetriebsmittel($person_id)
+ {
+ $this->form_validation->set_rules('uid', 'UID', [
+ ['uid_in_person', function ($value) use ($person_id) {
+ if ($value === null)
+ return true;
+ $this->load->model('person/Benutzer_model', 'BenutzerModel');
+ $result = $this->BenutzerModel->loadWhere([
+ 'uid' => $value,
+ 'person_id' => $person_id
+ ]);
+
+ return hasData($result);
+ }]
+ ], [
+ 'uid_in_person' => $this->p->t('person', 'error_uidNotInPerson')
+ ]);
+ $this->validateNewOrUpdate();
+
+ $betriebsmitteltyp = $this->input->post('betriebsmitteltyp');
+ $nummer = $this->input->post('nummer');
+ $nummer2 = $this->input->post('nummer2');
+ $beschreibung = $this->input->post('beschreibung');
+ $betriebsmittel_id = $this->input->post('betriebsmittel_id');
+ $anmerkung = $this->input->post('anmerkung');
+ $kaution = $this->input->post('kaution');
+ $ausgegebenam = $this->input->post('ausgegebenam');
+ $retouram = $this->input->post('retouram');
+ $uid = $this->input->post('uid');
+
+ // NOTE(chris): transform_kartennummer
+ if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer)
+ $nummer = is_numeric($nummer) ? ltrim($nummer, "0") : hexdec(implode("", array_reverse(str_split(trim($nummer)))));
+
+ $this->db->trans_start();
+
+ if ($betriebsmitteltyp != 'Inventar') {
+ $this->BetriebsmittelModel->addOrder('updateamum', 'DESC');
+ if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer === null) {
+ $result = $this->BetriebsmittelModel->loadWhere([
+ 'betriebsmitteltyp' => $betriebsmitteltyp,
+ 'nummer2' => $nummer2
+ ]);
+ } else {
+ $result = $this->BetriebsmittelModel->loadWhere([
+ 'betriebsmitteltyp' => $betriebsmitteltyp,
+ 'nummer' => $nummer
+ ]);
+ }
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if ($data) {
+ $data = current($data);
+ if ($data->nummer !== $nummer || $data->nummer2 !== $nummer2 || $data->beschreibung !== $beschreibung) {
+ $result = $this->BetriebsmittelModel->update($data->betriebsmittel_id, [
+ 'nummer' => $nummer,
+ 'nummer2' => $nummer2,
+ 'beschreibung' => $beschreibung,
+ 'updateamum' => date('c'),
+ 'updatevon' => getAuthUID()
+ ]);
+ $this->getDataOrTerminateWithError($result);
+ }
+ $betriebsmittel_id = $data->betriebsmittel_id;
+ } else {
+ $result = $this->BetriebsmittelModel->insert([
+ 'betriebsmitteltyp' => $betriebsmitteltyp,
+ 'nummer' => $nummer,
+ 'nummer2' => $nummer2,
+ 'beschreibung' => $beschreibung,
+ 'reservieren' => false,
+ 'ort_kurzbz' => null,
+ 'insertamum' => date('c'),
+ 'insertvon' => getAuthUID(),
+ ]);
+ $betriebsmittel_id = $this->getDataOrTerminateWithError($result);
+ }
+ }
+
+ $result = $this->BetriebsmittelpersonModel->insert([
+ 'person_id' => $person_id,
+ 'betriebsmittel_id' => $betriebsmittel_id,
+ 'anmerkung' => $anmerkung,
+ 'kaution' => $kaution,
+ 'ausgegebenam' => $ausgegebenam,
+ 'retouram' => $retouram,
+ 'uid' => $uid,
+ 'insertamum' => date('c'),
+ 'insertvon' => getAuthUID()
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->db->trans_complete();
+
+ $this->terminateWithSuccess(true);
+ }
+
+ public function updateBetriebsmittel($betriebsmittelperson_id)
+ {
+ $this->validateNewOrUpdate();
+
+ $betriebsmitteltyp = $this->input->post('betriebsmitteltyp');
+ $nummer = $this->input->post('nummer');
+ $nummer2 = $this->input->post('nummer2');
+ $beschreibung = $this->input->post('beschreibung');
+ $betriebsmittel_id = $this->input->post('betriebsmittel_id');
+ $anmerkung = $this->input->post('anmerkung');
+ $kaution = $this->input->post('kaution');
+ $ausgegebenam = $this->input->post('ausgegebenam');
+ $retouram = $this->input->post('retouram');
+
+ // NOTE(chris): transform_kartennummer
+ if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer)
+ $nummer = is_numeric($nummer) ? ltrim($nummer, "0") : hexdec(implode("", array_reverse(str_split(trim($nummer)))));
+
+ $this->db->trans_start();
+
+ if ($betriebsmitteltyp != 'Inventar') {
+ $found = false;
+ if ($nummer !== null && $betriebsmittel_id !== null) {
+ $result = $this->BetriebsmittelModel->load($betriebsmittel_id);
+ $data = $this->getDataOrTerminateWithError($result);
+ if ($data && current($data)->nummer == $nummer) {
+ $found = true;
+ }
+ }
+
+ if (!$found) {
+ $this->BetriebsmittelModel->addOrder('updateamum', 'DESC');
+ if ($betriebsmitteltyp == 'Zutrittskarte' && $nummer === null) {
+ $result = $this->BetriebsmittelModel->loadWhere([
+ 'betriebsmitteltyp' => $betriebsmitteltyp,
+ 'nummer2' => $nummer2
+ ]);
+ } else {
+ $result = $this->BetriebsmittelModel->loadWhere([
+ 'betriebsmitteltyp' => $betriebsmitteltyp,
+ 'nummer' => $nummer
+ ]);
+ }
+ $data = $this->getDataOrTerminateWithError($result);
+ }
+
+ if ($data) {
+ $data = current($data);
+ if ($data->nummer !== $nummer || $data->nummer2 !== $nummer2 || $data->beschreibung !== $beschreibung) {
+ $result = $this->BetriebsmittelModel->update($data->betriebsmittel_id, [
+ 'nummer' => $nummer,
+ 'nummer2' => $nummer2,
+ 'beschreibung' => $beschreibung,
+ 'updateamum' => date('c'),
+ 'updatevon' => getAuthUID()
+ ]);
+ $this->getDataOrTerminateWithError($result);
+ }
+ $betriebsmittel_id = $data->betriebsmittel_id;
+ } else {
+ $result = $this->BetriebsmittelModel->insert([
+ 'betriebsmitteltyp' => $betriebsmitteltyp,
+ 'nummer' => $nummer,
+ 'nummer2' => $nummer2,
+ 'beschreibung' => $beschreibung,
+ 'reservieren' => false,
+ 'ort_kurzbz' => null,
+ 'insertamum' => date('c'),
+ 'insertvon' => getAuthUID(),
+ ]);
+ $betriebsmittel_id = $this->getDataOrTerminateWithError($result);
+ }
+ }
+
+ $result = $this->BetriebsmittelpersonModel->update($betriebsmittelperson_id, [
+ 'betriebsmittel_id' => $betriebsmittel_id,
+ 'anmerkung' => $anmerkung,
+ 'kaution' => $kaution,
+ 'ausgegebenam' => $ausgegebenam,
+ 'retouram' => $retouram,
+ 'updateamum' => date('c'),
+ 'updatevon' => getAuthUID()
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->db->trans_complete();
+
+ $this->terminateWithSuccess(true);
+ }
+
+ public function loadBetriebsmittel($betriebsmittelperson_id)
+ {
+ $result = $this->BetriebsmittelpersonModel->getBetriebsmittelData($betriebsmittelperson_id, 'betriebsmittelperson_id');
+
+ if (isError($result)) {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+
+ if (!hasData($result)) {
+ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Betriebsmittelperson_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ $this->terminateWithSuccess(current(getData($result)));
+ }
+
+ public function deleteBetriebsmittel($betriebsmittelperson_id)
+ {
+ $result = $this->BetriebsmittelpersonModel->delete(
+ array('betriebsmittelperson_id' => $betriebsmittelperson_id,
+ )
+ );
+
+ if (isError($result)) {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ if (!hasData($result)) {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Betriebsmittelperson_id']), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->outputJsonSuccess(current(getData($result)));
+ }
+
+ public function getTypenBetriebsmittel()
+ {
+ $this->load->model('ressource/Betriebsmitteltyp_model', 'BetriebsmitteltypModel');
+
+ $this->BetriebsmitteltypModel->addOrder('beschreibung', 'ASC');
+ $result = $this->BetriebsmitteltypModel->load(); // load All
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function loadInventarliste($searchString)
+ {
+ $result = $this->BetriebsmittelModel->loadInventarliste($searchString);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+}
+
+
diff --git a/application/controllers/api/frontend/v1/checkperson/CheckPerson.php b/application/controllers/api/frontend/v1/checkperson/CheckPerson.php
new file mode 100644
index 000000000..321893610
--- /dev/null
+++ b/application/controllers/api/frontend/v1/checkperson/CheckPerson.php
@@ -0,0 +1,141 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+class CheckPerson extends FHCAPI_Controller
+{
+ public function __construct()
+ {
+ parent::__construct([
+ 'updatePersonUnrulyStatus' => array('basis/mitarbeiter:rw', 'student/antragfreigabe:rw', 'student/studierendenantrag:rw'),
+ 'filterPerson' => array('basis/mitarbeiter:rw', 'student/antragfreigabe:rw', 'student/studierendenantrag:rw'),
+ 'checkUnruly' => array('basis/mitarbeiter:r', 'student/antragfreigabe:r', 'student/studierendenantrag:r', 'infocenter:r'),
+ 'checkDuplicate' => array('infocenter:r'),
+ ]);
+
+ $this->_ci =& get_instance();
+ $this->_ci->load->model('person/Person_model', 'PersonModel');
+ }
+
+ public function updatePersonUnrulyStatus()
+ {
+ $data = json_decode($this->input->raw_input_stream, true);
+
+ $person_id = $data['person_id'];
+ $unruly = $data['unruly'];
+
+ $result = $this->_ci->PersonModel->updateUnruly($person_id, $unruly);
+
+ if(isError($result)) {
+ $this->terminateWithError($result);
+ } else if (isSuccess($result)) {
+ $this->terminateWithSuccess($result);
+ }
+
+ }
+
+ public function checkDuplicate() {
+
+ $person_id = $this->input->post('person_id');
+
+ $result = $this->_ci->PersonModel->checkDuplicate($person_id);
+
+ if (isSuccess($result))
+ $this->terminateWithSuccess($result);
+ else
+ $this->terminateWithError('Error when searching for person');
+
+ }
+
+ // performs strict check over vorname, nachname, gebdatum
+ public function checkUnruly() {
+
+ $vorname = $this->input->post('vorname');
+ $nachname = $this->input->post('nachname');
+ $gebdatum = $this->input->post('gebdatum');
+
+ $result = $this->_ci->PersonModel->checkUnruly($vorname, $nachname, $gebdatum);
+
+ if (isSuccess($result))
+ $this->terminateWithSuccess($result);
+ else
+ $this->terminateWithError('Error when searching for person');
+ }
+
+ // filters nachname on similarity and vorname/gebdatum are optional
+ public function filterPerson() {
+ $payload = json_decode($this->input->raw_input_stream, TRUE);
+
+ $nachnameString = '';
+ $vornameString = '';
+ $filterUnruly = true;
+ $birthdateString = '';
+
+ if(array_key_exists( 'nachname', $payload) ) {
+ $nachnameString = $payload['nachname'];
+ }
+
+ if(array_key_exists('vorname', $payload)) {
+ $vornameString = $payload['vorname'];
+ }
+
+ if(array_key_exists('unruly', $payload)){
+ $filterUnruly = $payload['unruly'];
+ }
+
+ if(array_key_exists('gebdatum', $payload)) {
+ // TODO: enable if gebdatum filter for unrulys is desired
+// $birthdateString = $payload['gebdatum'];
+ }
+
+ $parametersArray = array($nachnameString);
+ $where ="p.nachname~* ? ";
+ if (mb_strlen($nachnameString) == 2)
+ {
+ $where = "p.nachname=? ";
+ }
+
+ if(isset($vornameString) && $vornameString != '')
+ {
+ $where.= " AND p.vorname~*?";
+ $parametersArray[] = $vornameString;
+ }
+
+ if(isset($birthdateString) && $birthdateString != '')
+ {
+ $where.=" AND p.gebdatum=?";
+ $parametersArray[] = $birthdateString;
+ }
+
+ if(isset($filterUnruly))
+ {
+ $where.=" AND p.unruly=?";
+ $parametersArray[] = $filterUnruly;
+ }
+
+ $result = $this->_ci->PersonModel->checkUnrulyWhere($where, $parametersArray);
+
+ if (isSuccess($result))
+ $this->terminateWithSuccess($result);
+ else
+ $this->terminateWithError('Error when searching for person');
+
+
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php
new file mode 100644
index 000000000..636c8e3f3
--- /dev/null
+++ b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php
@@ -0,0 +1,65 @@
+ array(
+ 'lehre/lehrveranstaltung:rw'
+ )
+ ));
+
+ // Load model LehrveranstaltungModel
+ $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
+ }
+
+ /**
+ * Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes of given Berechtigung,
+ * that are assigned to a template. This data structure can be used for nested tabulators' data tree.
+ *
+ * @param null|string $studiensemester_kurzbz
+ * @param null|string $berechtigung
+ * @return array|stdClass|null
+ */
+ public function getTemplateLvTree()
+ {
+ $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz');
+ $berechtigung = $this->input->get('berechtigung');
+
+ if ($berechtigung)
+ {
+ $oe_permissions = $this->permissionlib->getOE_isEntitledFor($berechtigung);
+ if(!$oe_permissions) $oe_permissions = [];
+
+ $result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz, $oe_permissions);
+ }
+ else
+ {
+ $result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz);
+ }
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
+ }
+
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+}
diff --git a/application/controllers/api/frontend/v1/notiz/NotizPerson.php b/application/controllers/api/frontend/v1/notiz/NotizPerson.php
new file mode 100644
index 000000000..cb9d31024
--- /dev/null
+++ b/application/controllers/api/frontend/v1/notiz/NotizPerson.php
@@ -0,0 +1,51 @@
+ ['admin:r', 'assistenz:r'],
+ 'getNotizen' => ['admin:r', 'assistenz:r'],
+ 'loadNotiz' => ['admin:r', 'assistenz:r'],
+ 'addNewNotiz' => ['admin:rw', 'assistenz:rw'],
+ 'updateNotiz' => ['admin:rw', 'assistenz:rw'],
+ 'deleteNotiz' => ['admin:rw', 'assistenz:rw'],
+ 'loadDokumente' => ['admin:r', 'assistenz:r'],
+ 'getMitarbeiter' => ['admin:r', 'assistenz:r'],
+ 'isBerechtigt' => ['admin:r', 'assistenz:r'],
+ ]);
+ }
+
+ public function isBerechtigt($id, $typeId)
+ {
+ if($typeId != "person_id")
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL);
+ }
+
+ //TODO define permission
+ if (!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
+ {
+ $result = $this->p->t('lehre', 'error_keineSchreibrechte');
+
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+
+ return $this->outputJsonSuccess(true);
+ }
+
+ public function loadDokumente()
+ {
+ $notiz_id = $this->input->post('notiz_id');
+
+ // TODO(chris): make CI variant of endpoint
+ $this->NotizModel->addSelect($this->NotizModel->escape(base_url('content/notizdokdownload.php?id=')) . ' || campus.tbl_dms_version.dms_id AS preview');
+
+ return parent::loadDokumente();
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/organisation/Studiensemester.php b/application/controllers/api/frontend/v1/organisation/Studiensemester.php
new file mode 100644
index 000000000..72a449aaa
--- /dev/null
+++ b/application/controllers/api/frontend/v1/organisation/Studiensemester.php
@@ -0,0 +1,118 @@
+ self::PERM_LOGGED,
+ 'getAktNext' => self::PERM_LOGGED
+ )
+ );
+ // Load model StudiensemesterModel
+ $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
+ }
+
+ /**
+ * Get all Studiensemester.
+ *
+ * @param null|string $order Sorting order for the Studiensemester, 'asc' or 'desc'. Defaults to 'asc'.
+ * @param null|string $start Start date of the displayed Studiensemester in the format 'YYYY-MM-DD'.
+ * If provided, only Studiensemester starting from this date onwards will be returned.
+ * eg. '2020-09-01' will start with WS2020.
+ */
+ public function getAll()
+ {
+ $order = $this->input->get('order');
+ $start = $this->input->get('start');
+
+ if (strcasecmp($order, 'DESC') == 0)
+ {
+ $this->StudiensemesterModel->addOrder('ende', 'DESC');
+ }
+ else
+ {
+ $this->StudiensemesterModel->addOrder('ende', 'ASC');
+ }
+
+ if ($start)
+ {
+ $result = $this->StudiensemesterModel->loadWhere([
+ 'start >= ' => $start
+ ]);
+ }
+ else
+ {
+ $result = $this->StudiensemesterModel->load();
+ }
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
+ }
+
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ /**
+ * @return void
+ */
+ public function getAktNext()
+ {
+ $semester = $this->input->get('semester');
+
+ $result = null;
+
+ if (!is_numeric($semester))
+ {
+ $result = $this->StudiensemesterModel->loadWhere(array('start <=' => 'NOW()', 'ende >=' => 'NOW()'));
+ }
+
+ if (!hasData($result))
+ {
+ $this->StudiensemesterModel->addOrder('ende');
+ $this->StudiensemesterModel->addLimit(1);
+
+ $whereArray = array('ende >=' => 'NOW()');
+
+ if (is_numeric($semester))
+ {
+ if ($semester % 2 == 0)
+ {
+ $ss = 'SS';
+ }
+ else
+ {
+ $ss = 'WS';
+ }
+
+ $whereArray['SUBSTRING(studiensemester_kurzbz FROM 1 FOR 2) ='] = $ss;
+ }
+
+ $result = $this->StudiensemesterModel->loadWhere($whereArray);
+ }
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
+ }
+
+ $this->terminateWithSuccess((getData($result) ?: ''));
+ }
+}
diff --git a/application/controllers/api/frontend/v1/studstatus/Abmeldung.php b/application/controllers/api/frontend/v1/studstatus/Abmeldung.php
new file mode 100644
index 000000000..aada1f436
--- /dev/null
+++ b/application/controllers/api/frontend/v1/studstatus/Abmeldung.php
@@ -0,0 +1,187 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+use \REST_Controller as REST_Controller;
+use \Studierendenantrag_model as Studierendenantrag_model;
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the AntragLib (back-end)
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Abmeldung extends FHCAPI_Controller
+{
+
+ /**
+ * Calls the parent's constructor and loads the AntragLib
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getDetailsForNewAntrag' => self::PERM_LOGGED,
+ 'getDetailsForAntrag' => self::PERM_LOGGED,
+ 'createAntrag' => self::PERM_LOGGED,
+ 'cancelAntrag' => self::PERM_LOGGED
+ ]);
+
+ // Libraries
+ $this->load->library('AntragLib');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'studierendenantrag'
+ ]);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Retrieves data of the current studiengang for the current user
+ */
+
+ public function getDetailsForNewAntrag($prestudent_id)
+ {
+ if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, true))
+ $this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN);
+
+ $result = $this->antraglib->getPrestudentAbmeldeBerechtigt($prestudent_id);
+ $result = $this->getDataOrTerminateWithError($result);
+
+ if (!$result) {
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_no_student'),
+ self::ERROR_TYPE_AUTH,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+ } elseif ($result == -3) {
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_stg_blacklist'),
+ self::ERROR_TYPE_AUTH,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+ } elseif ($result == -1) {
+ $result = $this->antraglib->getDetailsForLastAntrag(
+ $prestudent_id,
+ [
+ Studierendenantrag_model::TYP_ABMELDUNG,
+ Studierendenantrag_model::TYP_ABMELDUNG_STGL
+ ]
+ );
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $data->canCancel = (
+ $data->status == Studierendenantragstatus_model::STATUS_CREATED &&
+ $this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id)
+ );
+
+ $this->terminateWithSuccess($data);
+ }
+
+ $result = $this->antraglib->getDetailsForNewAntrag($prestudent_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getDetailsForAntrag($studierendenantrag_id)
+ {
+ if (!$this->antraglib->isEntitledToShowAntrag($studierendenantrag_id))
+ return show_404();
+
+ $result = $this->antraglib->getDetailsForAntrag($studierendenantrag_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if ($data->typ !== Studierendenantrag_model::TYP_ABMELDUNG_STGL && $data->typ !== Studierendenantrag_model::TYP_ABMELDUNG)
+ return show_404();
+
+ $data->canCancel = (
+ $data->status == Studierendenantragstatus_model::STATUS_CREATED &&
+ $this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id)
+ );
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function createAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
+ $this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required');
+ $this->form_validation->set_rules('grund', 'Grund', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $grund = $this->input->post('grund');
+ $studiensemester = $this->input->post('studiensemester');
+ $prestudent_id = $this->input->post('prestudent_id');
+
+ $result = $this->antraglib->getPrestudentAbmeldeBerechtigt($prestudent_id);
+ $result = $this->getDataOrTerminateWithError($result);
+ if (!$result)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL);
+ elseif ($result == -3)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL);
+ elseif ($result < 0)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL);
+
+ $result = $this->antraglib->createAbmeldung($prestudent_id, $studiensemester, getAuthUID(), $grund);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $result = $this->antraglib->getDetailsForAntrag($data);
+ if (!hasData($result))
+ return $this->terminateWithSuccess(true);
+
+ $data = getData($result);
+ $data->canCancel = (boolean)$this->antraglib->isEntitledToCancelAntrag($data->studierendenantrag_id);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function cancelAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('antrag_id', 'Antrag ID', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $antrag_id = $this->input->post('antrag_id');
+
+ if (!$this->antraglib->isEntitledToCancelAntrag($antrag_id))
+ $this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN);
+
+ $result = $this->antraglib->cancelAntrag($antrag_id, getAuthUID());
+ $this->getDataOrTerminateWithError($result);
+
+ $result = $this->antraglib->getDetailsForAntrag($antrag_id);
+ if (!hasData($result))
+ $this->terminateWithSuccess($antrag_id);
+
+ $data = getData($result);
+
+ $this->terminateWithSuccess($data);
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/studstatus/Leitung.php b/application/controllers/api/frontend/v1/studstatus/Leitung.php
new file mode 100644
index 000000000..87099ad74
--- /dev/null
+++ b/application/controllers/api/frontend/v1/studstatus/Leitung.php
@@ -0,0 +1,429 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+use \stdClass as stdClass;
+use \Studierendenantrag_model as Studierendenantrag_model;
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the AntragLib (back-end)
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Leitung extends FHCAPI_Controller
+{
+
+ /**
+ * Calls the parent's constructor and loads the AntragLib
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getActiveStgs' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'],
+ 'getAntraege' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'],
+ 'getHistory' => ['student/antragfreigabe:r', 'student/studierendenantrag:r'],
+ 'getPrestudents' => 'student/studierendenantrag:w',
+ 'approveAntrag' => 'student/antragfreigabe:w',
+ 'rejectAntrag' => 'student/antragfreigabe:w',
+ 'reopenAntrag' => 'student/studierendenantrag:w',
+ 'pauseAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'],
+ 'unpauseAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'],
+ 'objectAntrag' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'],
+ 'approveObjection' => ['student/antragfreigabe:w', 'student/studierendenantrag:w'],
+ 'denyObjection' => ['student/antragfreigabe:w', 'student/studierendenantrag:w']
+ ]);
+
+ // Libraries
+ $this->load->library('AntragLib');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'studierendenantrag',
+ 'lehre'
+ ]);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ public function getActiveStgs()
+ {
+ $studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe') ?: [];
+ $studiengaenge = array_merge($studiengaenge, $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag') ?: []);
+
+ $result = $this->StudierendenantragModel->loadStgsWithAntraege($studiengaenge);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getAntraege($studiengang = null, $extra = null)
+ {
+ if ($studiengang && $studiengang == 'todo') {
+ $studiengang = $extra;
+ $extra = true;
+ } else {
+ $extra = false;
+ }
+
+ $studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe');
+ if(!is_array($studiengaenge))
+ $studiengaenge = [];
+
+
+ $stgsNeuanlage = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
+ if(!is_array($stgsNeuanlage))
+ $stgsNeuanlage = [];
+
+ $studiengaenge = array_unique(array_merge($studiengaenge, $stgsNeuanlage));
+
+ if ($studiengang) {
+ if (!in_array($studiengang, $studiengaenge))
+ $this->terminateWithError(
+ 'Forbidden',
+ self::ERROR_TYPE_AUTH,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+ $studiengaenge = [$studiengang];
+ }
+
+ $antraege = [];
+ if ($studiengaenge) {
+ $result = $extra
+ ? $this->StudierendenantragModel->loadActiveForStudiengaenge($studiengaenge)
+ : $this->StudierendenantragModel->loadForStudiengaenge($studiengaenge);
+
+ $antraege = $this->getDataOrTerminateWithError($result);
+ }
+
+ $this->terminateWithSuccess($antraege ?: []);
+ }
+
+ public function getHistory($studierendenantrag_id)
+ {
+ if (!$this->antraglib->isEntitledToSeeHistoryForAntrag($studierendenantrag_id))
+ $this->terminateWithError(
+ 'Forbidden',
+ self::ERROR_TYPE_AUTH,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+
+ $result = $this->antraglib->getAntragHistory($studierendenantrag_id);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data ?: []);
+ }
+
+ public function getPrestudents()
+ {
+ $query = $this->input->post('query');
+
+ $studiengaenge = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
+
+ $result = $this->antraglib->getAktivePrestudentenInStgs($studiengaenge, $query);
+ $result = $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($result ?: []);
+ }
+
+ public function approveAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'studierendenantrag_id',
+ 'Studierenden Antrag',
+ [
+ 'required',
+ ['isEntitledToApproveAntrag', [$this->antraglib, 'isEntitledToApproveAntrag']],
+ ],
+ [
+ 'isEntitledToApproveAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
+ ]
+ );
+ $this->form_validation->set_rules(
+ 'typ',
+ 'Typ',
+ 'required|in_list[' . implode(',', [
+ Studierendenantrag_model::TYP_ABMELDUNG,
+ Studierendenantrag_model::TYP_ABMELDUNG_STGL,
+ Studierendenantrag_model::TYP_UNTERBRECHUNG,
+ Studierendenantrag_model::TYP_WIEDERHOLUNG
+ ]) . ']'
+ );
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $studierendenantrag_id = $this->input->post('studierendenantrag_id');
+ switch ($this->input->post('typ')) {
+ case Studierendenantrag_model::TYP_ABMELDUNG:
+ case Studierendenantrag_model::TYP_ABMELDUNG_STGL:
+ $result = $this->antraglib->approveAbmeldung([$studierendenantrag_id], getAuthUID());
+ break;
+ case Studierendenantrag_model::TYP_UNTERBRECHUNG:
+ $result = $this->antraglib->approveUnterbrechung([$studierendenantrag_id], getAuthUID());
+ break;
+ case Studierendenantrag_model::TYP_WIEDERHOLUNG:
+ $result = $this->antraglib->approveWiederholung($studierendenantrag_id, getAuthUID());
+ break;
+ }
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($studierendenantrag_id);
+ }
+
+ public function rejectAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'studierendenantrag_id',
+ 'Studierenden Antrag',
+ [
+ 'required',
+ ['isEntitledToRejectAntrag', [$this->antraglib, 'isEntitledToRejectAntrag']],
+ ],
+ [
+ 'isEntitledToRejectAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
+ ]
+ );
+ $this->form_validation->set_rules('grund', 'Grund', 'required');
+ $this->form_validation->set_rules(
+ 'typ',
+ 'Typ',
+ 'required|in_list[' . implode(',', [
+ Studierendenantrag_model::TYP_UNTERBRECHUNG
+ ]) . ']'
+ );
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $studierendenantrag_id = $this->input->post('studierendenantrag_id');
+ $grund = $this->input->post('grund');
+
+ $result = $this->antraglib->rejectUnterbrechung([$studierendenantrag_id], getAuthUID(), $grund);
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($studierendenantrag_id);
+ }
+
+ public function reopenAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'studierendenantrag_id',
+ 'Studierenden Antrag',
+ [
+ 'required',
+ ['isEntitledToReopenAntrag', [$this->antraglib, 'isEntitledToReopenAntrag']],
+ ],
+ [
+ 'isEntitledToReopenAntrag' => $this->p->t('studierendenantrag', 'error_no_right')
+ ]
+ );
+ $this->form_validation->set_rules(
+ 'typ',
+ 'Typ',
+ 'required|in_list[' . implode(',', [
+ Studierendenantrag_model::TYP_WIEDERHOLUNG
+ ]) . ']'
+ );
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $studierendenantrag_id = $this->input->post('studierendenantrag_id');
+
+ $result = $this->antraglib->reopenWiederholung($studierendenantrag_id, getAuthUID());
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($studierendenantrag_id);
+ }
+
+ public function pauseAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'studierendenantrag_id',
+ 'Studierenden Antrag',
+ [
+ 'required',
+ ['isEntitledToPauseAntrag', [$this->antraglib, 'isEntitledToPauseAntrag']],
+ ['antragCanBeManualPaused', [$this->antraglib, 'antragCanBeManualPaused']]
+ ],
+ [
+ 'isEntitledToPauseAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
+ 'antragCanBeManualPaused' => $this->p->t(
+ 'studierendenantrag',
+ 'error_not_pauseable',
+ ['id' => $this->input->post('studierendenantrag_id')]
+ )
+ ]
+ );
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $studierendenantrag_id = $this->input->post('studierendenantrag_id');
+
+ $result = $this->antraglib->pauseAntrag($studierendenantrag_id, getAuthUID());
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($studierendenantrag_id);
+ }
+
+ public function unpauseAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'studierendenantrag_id',
+ 'Studierenden Antrag',
+ [
+ 'required',
+ ['isEntitledToUnpauseAntrag', [$this->antraglib, 'isEntitledToUnpauseAntrag']],
+ ['antragCanBeManualUnpaused', [$this->antraglib, 'antragCanBeManualUnpaused']]
+ ],
+ [
+ 'isEntitledToUnpauseAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
+ 'antragCanBeManualUnpaused' => $this->p->t(
+ 'studierendenantrag',
+ 'error_not_paused',
+ ['id' => $this->input->post('studierendenantrag_id')]
+ )
+ ]
+ );
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $studierendenantrag_id = $this->input->post('studierendenantrag_id');
+
+ $result = $this->antraglib->unpauseAntrag($studierendenantrag_id, getAuthUID());
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($studierendenantrag_id);
+ }
+
+ public function objectAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'studierendenantrag_id',
+ 'Studierenden Antrag',
+ [
+ 'required',
+ ['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']],
+ ['canBeObjected', function ($a) {
+ return $this->antraglib->hasType($a, Studierendenantrag_model::TYP_ABMELDUNG_STGL);
+ }]
+ ],
+ [
+ 'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
+ 'canBeObjected' => $this->p->t(
+ 'studierendenantrag',
+ 'error_no_objection'
+ )
+ ]
+ );
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $studierendenantrag_id = $this->input->post('studierendenantrag_id');
+
+ $result = $this->antraglib->objectAbmeldung($studierendenantrag_id, getAuthUID());
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($studierendenantrag_id);
+ }
+
+ public function approveObjection()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'studierendenantrag_id',
+ 'Studierenden Antrag',
+ [
+ 'required',
+ ['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']],
+ ['isObjected', function ($a) {
+ return $this->antraglib->hasStatus($a, Studierendenantragstatus_model::STATUS_OBJECTED);
+ }]
+ ],
+ [
+ 'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
+ 'isObjected' => $this->p->t(
+ 'studierendenantrag',
+ 'error_not_objected'
+ )
+ ]
+ );
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $studierendenantrag_id = $this->input->post('studierendenantrag_id');
+
+ $result = $this->antraglib->cancelAntrag($studierendenantrag_id, getAuthUID());
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($studierendenantrag_id);
+ }
+
+ public function denyObjection()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'studierendenantrag_id',
+ 'Studierenden Antrag',
+ [
+ 'required',
+ ['isEntitledToObjectAntrag', [$this->antraglib, 'isEntitledToObjectAntrag']],
+ ['isObjected', function ($a) {
+ return $this->antraglib->hasStatus($a, Studierendenantragstatus_model::STATUS_OBJECTED);
+ }]
+ ],
+ [
+ 'isEntitledToObjectAntrag' => $this->p->t('studierendenantrag', 'error_no_right'),
+ 'isObjected' => $this->p->t(
+ 'studierendenantrag',
+ 'error_not_objected'
+ )
+ ]
+ );
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $studierendenantrag_id = $this->input->post('studierendenantrag_id');
+ $grund = $this->input->post('grund');
+
+ $result = $this->antraglib->denyObjectionAbmeldung($studierendenantrag_id, getAuthUID(), $grund);
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($studierendenantrag_id);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/studstatus/Unterbrechung.php b/application/controllers/api/frontend/v1/studstatus/Unterbrechung.php
new file mode 100644
index 000000000..abf58cf4f
--- /dev/null
+++ b/application/controllers/api/frontend/v1/studstatus/Unterbrechung.php
@@ -0,0 +1,226 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+use \Studierendenantrag_model as Studierendenantrag_model;
+use \DateTime as DateTime;
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the AntragLib (back-end)
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Unterbrechung extends FHCAPI_Controller
+{
+
+ /**
+ * Calls the parent's constructor and loads the AntragLib
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getDetailsForNewAntrag' => self::PERM_LOGGED,
+ 'getDetailsForAntrag' => self::PERM_LOGGED,
+ 'createAntrag' => self::PERM_LOGGED,
+ 'cancelAntrag' => self::PERM_LOGGED
+ ]);
+
+ // Configs
+ $this->load->config('studierendenantrag');
+
+ // Libraries
+ $this->load->library('AntragLib');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'studierendenantrag',
+ 'ui'
+ ]);
+ }
+
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ public function getDetailsForNewAntrag($prestudent_id)
+ {
+ if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, false))
+ $this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN);
+
+ $result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($prestudent_id);
+ $result = $this->getDataOrTerminateWithError($result);
+
+ if (!$result) {
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_no_student'),
+ self::ERROR_TYPE_AUTH,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+ } elseif ($result == -1) {
+ $result = $this->antraglib->getDetailsForLastAntrag($prestudent_id, Studierendenantrag_model::TYP_UNTERBRECHUNG);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($data);
+ } elseif ($result == -2) {
+ $result = $this->antraglib->getDetailsForLastAntrag($prestudent_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_pending', [
+ 'typ' => $this->p->t('studierendenantrag', 'antrag_typ_' . $result->typ)
+ ]));
+ } elseif ($result == -3) {
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_stg_blacklist'),
+ self::ERROR_TYPE_AUTH,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+ }
+
+ $result = $this->antraglib->getDetailsForNewAntrag($prestudent_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $data->studiensemester = $this->antraglib->getSemesterForUnterbrechung($prestudent_id, null);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getDetailsForAntrag($studierendenantrag_id)
+ {
+ if (!$this->antraglib->isEntitledToShowAntrag($studierendenantrag_id))
+ return show_404();
+
+ $result = $this->antraglib->getDetailsForAntrag($studierendenantrag_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if ($data->typ !== Studierendenantrag_model::TYP_UNTERBRECHUNG)
+ return show_404();
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function createAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
+ $this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required');
+ $this->form_validation->set_rules('grund', 'Grund', 'required');
+ $this->form_validation->set_rules(
+ 'datum_wiedereinstieg',
+ 'Datum Wiedereinstieg',
+ 'required|callback_isValidDate|callback_isDateInFuture',
+ [
+ 'isValidDate' => $this->p->t('ui', 'error_invalid_date'),
+ 'isDateInFuture' => $this->p->t('ui', 'error_invalid_date')
+ ]
+ );
+
+ if (!$this->form_validation->run()) {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $grund = $this->input->post('grund');
+ $studiensemester = $this->input->post('studiensemester');
+ $prestudent_id = $this->input->post('prestudent_id');
+ $datum_wiedereinstieg = $this->input->post('datum_wiedereinstieg');
+ $dms_id = null;
+
+ $result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($prestudent_id, $studiensemester, $datum_wiedereinstieg);
+
+ $result = $this->getDataOrTerminateWithError($result);
+
+ if (!$result)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL);
+ elseif ($result == -3)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL);
+ elseif ($result < 0)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL);
+
+ if (isset($_FILES['attachment']) && (!isset($_FILES['attachment']['error']) || $_FILES['attachment']['error'] != UPLOAD_ERR_NO_FILE)) {
+ $this->load->library('DmsLib');
+
+ $dms = $this->config->item('unterbrechung_dms');
+ if (!count(array_filter($dms, function ($v) {
+ return $v !== null;
+ })))
+ $dms = ['kategorie_kurzbz' => 'Akte'];
+ $dms['version'] = 0;
+
+ $allowed_filetypes = $this->config->item('unterbrechung_dms_filetypes') ?: ['*'];
+ $result = $this->dmslib->upload($dms, 'attachment', $allowed_filetypes);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $dms_id = $data['dms_id'];
+ }
+
+ $result = $this->antraglib->createUnterbrechung($prestudent_id, $studiensemester, getAuthUID(), $grund, $datum_wiedereinstieg, $dms_id);
+
+ $antragId = $this->getDataOrTerminateWithError($result);
+
+ $result = $this->antraglib->getDetailsForAntrag($antragId);
+
+ if (!hasData($result))
+ $this->terminateWithSuccess($antragId);
+
+ $this->terminateWithSuccess(getData($result));
+ }
+
+ public function cancelAntrag()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('antrag_id', 'Antrag ID', 'required');
+
+ if (!$this->form_validation->run()) {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $antrag_id = $this->input->post('antrag_id');
+
+ $result = $this->antraglib->cancelAntrag($antrag_id, getAuthUID());
+
+ $this->getDataOrTerminateWithError($result);
+
+ $result = $this->antraglib->getDetailsForAntrag($antrag_id);
+
+ if (!hasData($result))
+ return $this->terminateWithSuccess($antrag_id);
+
+ $this->terminateWithSuccess(getData($result));
+ }
+
+ public function isValidDate($date)
+ {
+ try {
+ new DateTime($date);
+ } catch (Exception $e) {
+ return false;
+ }
+ return true;
+ }
+
+ public function isDateInFuture($date)
+ {
+ return new DateTime() < new DateTime($date);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/studstatus/Wiederholung.php b/application/controllers/api/frontend/v1/studstatus/Wiederholung.php
new file mode 100644
index 000000000..1a8f70d52
--- /dev/null
+++ b/application/controllers/api/frontend/v1/studstatus/Wiederholung.php
@@ -0,0 +1,258 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+use \REST_Controller as REST_Controller;
+use \Studierendenantragstatus_model as Studierendenantragstatus_model;
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the AntragLib (back-end)
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Wiederholung extends FHCAPI_Controller
+{
+
+ /**
+ * Calls the parent's constructor and loads the FilterCmptLib
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getDetailsForNewAntrag' => self::PERM_LOGGED,
+ 'createAntrag' => self::PERM_LOGGED,
+ 'cancelAntrag' => self::PERM_LOGGED,
+ 'getLvs' => self::PERM_LOGGED,
+ 'saveLvs' => ['student/studierendenantrag:w']
+ ]);
+
+ // Libraries
+ $this->load->library('AntragLib');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'global',
+ 'studierendenantrag'
+ ]);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Retrieves data of the current studiengang for the current user
+ */
+
+ public function getDetailsForNewAntrag($prestudent_id)
+ {
+ if (!$this->antraglib->isEntitledToCreateAntragFor($prestudent_id, false))
+ $this->terminateWithError('Forbidden', self::ERROR_TYPE_AUTH, REST_Controller::HTTP_FORBIDDEN);
+
+ $result = $this->antraglib->getPrestudentWiederholungsBerechtigt($prestudent_id);
+ $result = $this->getDataOrTerminateWithError($result);
+
+ if (!$result) {
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_no_student_no_failed_exam'),
+ self::ERROR_TYPE_AUTH,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+ } elseif ($result == -1) {
+ $result = $this->antraglib->getDetailsForLastAntrag($prestudent_id, Studierendenantrag_model::TYP_WIEDERHOLUNG);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $result = $this->antraglib->getFailedExamForPrestudent($prestudent_id, $data->datum, $data->studiensemester_kurzbz);
+ // NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
+ $pruefungsdata = current(getData($result));
+
+ $data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
+ $data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
+ $data->pruefungsdatum = $pruefungsdata->datum;
+
+ $this->terminateWithSuccess($data);
+ } elseif ($result == -2) {
+ $result = $this->antraglib->getDetailsForLastAntrag($prestudent_id);
+ $result = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_antrag_pending', [
+ 'typ' => $this->p->t('studierendenantrag', 'antrag_typ_' . $result->typ)
+ ]),
+ self::ERROR_TYPE_GENERAL,
+ REST_Controller::HTTP_BAD_REQUEST
+ );
+ } elseif ($result == -3) {
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_stg_blacklist'),
+ self::ERROR_TYPE_GENERAL,
+ REST_Controller::HTTP_BAD_REQUEST
+ );
+ }
+
+ $result = $this->antraglib->getDetailsForNewAntrag($prestudent_id);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $result = $this->antraglib->getFailedExamForPrestudent($prestudent_id);
+ // NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
+ $pruefungsdata = current(getData($result));
+
+ $data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
+ $data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
+ $data->pruefungsdatum = $pruefungsdata->datum;
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function createAntrag()
+ {
+ $this->createAntragWithStatus(true);
+ }
+
+ public function cancelAntrag()
+ {
+ $this->createAntragWithStatus(false);
+ }
+
+ protected function createAntragWithStatus($repeat)
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('prestudent_id', 'Prestudent ID', 'required');
+ $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $prestudent_id = $this->input->post('prestudent_id');
+ $studiensemester = $this->input->post('studiensemester');
+
+ $result = $this->antraglib->getPrestudentWiederholungsBerechtigt($prestudent_id);
+ $result = $this->getDataOrTerminateWithError($result);
+
+ if (!$result) {
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL);
+ } elseif ($result == -1) {
+ $result = $this->PrestudentstatusModel->getLastStatus($prestudent_id);
+ $result = $this->getDataOrTerminateWithError($result);
+ if (!$result)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_prestudentstatus', [
+ 'prestudent_id' => $prestudent_id
+ ]), self::ERROR_TYPE_GENERAL);
+ if (!in_array(current($result)->status_kurzbz, $this->config->item('antrag_prestudentstatus_whitelist')))
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student'), self::ERROR_TYPE_GENERAL);
+ } elseif ($result == -2) {
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_antrag_exists'), self::ERROR_TYPE_GENERAL);
+ } elseif ($result == -3) {
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_stg_blacklist'), self::ERROR_TYPE_GENERAL);
+ }
+
+ $result = $this->antraglib->createWiederholung($prestudent_id, $studiensemester, getAuthUID(), $repeat);
+ $antragId = $this->getDataOrTerminateWithError($result);
+
+ $result = $this->antraglib->getDetailsForAntrag($antragId);
+
+ if (!hasData($result))
+ $this->terminateWithSuccess(true);
+
+ $data = getData($result);
+
+ $result = $this->antraglib->getFailedExamForPrestudent($prestudent_id);
+ // NOTE(chris): error handling for this function should already happenden in antraglib->getPrestudentWiederholungsBerechtigt()
+ $pruefungsdata = current(getData($result));
+
+ $data->studiensemester_kurzbz = $pruefungsdata->studiensemester_kurzbz;
+ $data->lvbezeichnung = $pruefungsdata->lvbezeichnung;
+ $data->pruefungsdatum = $pruefungsdata->datum;
+
+ $this->terminateWithSuccess($data);
+ }
+
+
+ public function getLvs($antrag_id)
+ {
+ $result = $this->antraglib->getLvsForAntrag($antrag_id);
+ if (isError($result)) {
+ $error = getError($result);
+ if ($error == 'Forbidden')
+ $this->terminateWithError(
+ $error,
+ self::ERROR_TYPE_AUTH,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+ $this->terminateWithError(
+ $error,
+ self::ERROR_TYPE_GENERAL
+ );
+ }
+ $lvs = getData($result);
+
+ $this->terminateWithSuccess($lvs);
+ }
+
+ public function saveLvs()
+ {
+ $forbiddenLvs = $this->input->post('forbiddenLvs');
+ $mandatoryLvs = $this->input->post('mandatoryLvs');
+ $antragsLvs = array_merge($forbiddenLvs, $mandatoryLvs);
+
+ if (!$antragsLvs)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_lv'), self::ERROR_TYPE_GENERAL);
+
+ $insert = array_map(function ($lv) {
+ return [
+ 'studierendenantrag_id' => $lv['studierendenantrag_id'],
+ 'lehrveranstaltung_id' => $lv['lehrveranstaltung_id'],
+ 'note' => $lv['zugelassen']
+ ? ($lv['zugelassen'] == 1 ? 0 : $this->config->item('wiederholung_note_angerechnet'))
+ : $this->config->item('wiederholung_note_nicht_zugelassen'),
+ 'anmerkung' => $lv['anmerkung'],
+ 'insertvon' => getAuthUID(),
+ 'studiensemester_kurzbz' => $lv['studiensemester_kurzbz']
+ ];
+ }, $antragsLvs);
+
+ $antrag_ids = array_unique(array_map(function ($lv) {
+ return $lv['studierendenantrag_id'];
+ }, $insert));
+
+ foreach ($antrag_ids as $antrag_id) {
+ $result = $this->StudierendenantragModel->loadIdAndStatusWhere([
+ 'studierendenantrag_id' => $antrag_id
+ ]);
+ $antrag = $this->getDataOrTerminateWithError($result);
+ if (!$antrag)
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $antrag_id]),
+ self::ERROR_TYPE_GENERAL
+ );
+ $antrag = current($antrag);
+
+ if ($antrag->status != Studierendenantragstatus_model::STATUS_CREATED
+ && $antrag->status != Studierendenantragstatus_model::STATUS_LVSASSIGNED)
+ $this->terminateWithError(
+ $this->p->t('studierendenantrag', 'error_antrag_locked'),
+ self::ERROR_TYPE_GENERAL
+ );
+ }
+
+ $result = $this->antraglib->saveLvs($insert);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Address.php b/application/controllers/api/frontend/v1/stv/Address.php
new file mode 100644
index 000000000..7685fcd04
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Address.php
@@ -0,0 +1,66 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about addresses
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Address extends FHCAPI_Controller
+{
+ public function __construct()
+ {
+ parent::__construct([
+ 'getNations' => self::PERM_LOGGED,
+ 'getPlaces' => self::PERM_LOGGED
+ ]);
+ }
+
+ public function getNations()
+ {
+ $this->load->model('codex/Nation_model', 'NationModel');
+
+ $this->NationModel->addOrder('kurztext');
+
+ $result = $this->NationModel->load();
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getPlaces($plz)
+ {
+ $this->load->model('codex/Gemeinde_model', 'GemeindeModel');
+
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_data(['address.plz' => $plz]);
+
+ $this->form_validation->set_rules('address.plz', 'PLZ', 'numeric|less_than[10000]');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $result = $this->GemeindeModel->getGemeindeByPlz($plz);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php
new file mode 100644
index 000000000..c28c49485
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Config.php
@@ -0,0 +1,233 @@
+.
+ */
+
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+use CI3_Events as Events;
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about the StV Config
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Config extends FHCAPI_Controller
+{
+
+
+ public function __construct()
+ {
+ // TODO(chris): permissions
+ parent::__construct([
+ 'student' => ['admin:r', 'assistenz:r'],
+ 'students' => ['admin:r', 'assistenz:r']
+ ]);
+
+
+ // Load Phrases
+ $this->loadPhrases([
+ 'global',
+ 'person',
+ 'lehre',
+ 'stv',
+ 'konto'
+ ]);
+ }
+
+ public function student()
+ {
+ $result = [];
+ $result['details'] = [
+ 'title' => $this->p->t('stv', 'tab_details'),
+ 'component' => './Stv/Studentenverwaltung/Details/Details.js'
+ ];
+ $result['notes'] = [
+ 'title' => $this->p->t('stv', 'tab_notes'),
+ 'component' => './Stv/Studentenverwaltung/Details/Notizen.js'
+ ];
+ $result['contact'] = [
+ 'title' => $this->p->t('stv', 'tab_contact'),
+ 'component' => './Stv/Studentenverwaltung/Details/Kontakt.js',
+ 'config' => [
+ 'showBankaccount' => $this->permissionlib->isBerechtigt('mitarbeiter/bankdaten')
+ || $this->permissionlib->isBerechtigt('student/bankdaten')
+ ]
+ ];
+ $result['prestudent'] = [
+ 'title' => $this->p->t('stv', 'tab_prestudent'),
+ 'component' => './Stv/Studentenverwaltung/Details/Prestudent.js'
+ ];
+ $result['status'] = [
+ 'title' => 'Status',
+ 'component' => './Stv/Studentenverwaltung/Details/MultiStatus.js'
+ ];
+ $result['banking'] = [
+ 'title' => $this->p->t('stv', 'tab_banking'),
+ 'component' => './Stv/Studentenverwaltung/Details/Konto.js',
+ 'config' => [
+ 'showZahlungsbestaetigung' => (defined('ZAHLUNGSBESTAETIGUNG_ANZEIGEN') && ZAHLUNGSBESTAETIGUNG_ANZEIGEN),
+ 'showBuchungsnr' => $this->permissionlib->isBerechtigt('admin'),
+ 'showMahnspanne' => (!defined('FAS_KONTO_SHOW_MAHNSPANNE') || FAS_KONTO_SHOW_MAHNSPANNE===true),
+ 'showCreditpoints' => (defined('FAS_KONTO_SHOW_CREDIT_POINTS') && FAS_KONTO_SHOW_CREDIT_POINTS == 'true'),
+ 'columns' => $this->kontoColumns(),
+ 'additionalCols' => []
+ ]
+ ];
+ $result['resources'] = [
+ 'title' => $this->p->t('stv', 'tab_resources'),
+ 'component' => './Stv/Studentenverwaltung/Details/Betriebsmittel.js'
+ ];
+ /* TODO(chris): Ausgeblendet für Testing
+ $result['grades'] = [
+ 'title' => $this->p->t('stv', 'tab_grades'),
+ 'component' => './Stv/Studentenverwaltung/Details/Noten.js'
+ ];
+ */
+
+ Events::trigger('stv_conf_student', function & () use (&$result) {
+ return $result;
+ });
+
+ $this->terminateWithSuccess($result);
+ }
+
+ public function students()
+ {
+ $result = [];
+ $result['banking'] = [
+ 'title' => $this->p->t('stv', 'tab_banking'),
+ 'component' => './Stv/Studentenverwaltung/Details/Konto.js',
+ 'config' => [
+ 'showZahlungsbestaetigung' => (defined('ZAHLUNGSBESTAETIGUNG_ANZEIGEN') && ZAHLUNGSBESTAETIGUNG_ANZEIGEN),
+ 'showBuchungsnr' => $this->permissionlib->isBerechtigt('admin'),
+ 'showMahnspanne' => (!defined('FAS_KONTO_SHOW_MAHNSPANNE') || FAS_KONTO_SHOW_MAHNSPANNE===true),
+ 'showCreditpoints' => (defined('FAS_KONTO_SHOW_CREDIT_POINTS') && FAS_KONTO_SHOW_CREDIT_POINTS == 'true'),
+ 'columns' => $this->kontoColumnsMultiPerson(),
+ 'additionalCols' => []
+ ]
+ ];
+ $result['status'] = [
+ 'title' => 'Status',
+ 'component' => './Stv/Studentenverwaltung/Details/MultiStatus.js',
+ 'config' => [
+ 'changeStatusToAbbrecherStgl' => $this->permissionlib->isBerechtigt('admin'),
+ 'changeStatusToAbbrecherStud' => $this->permissionlib->isBerechtigt('admin'),
+ 'changeStatusToUnterbrecher' => $this->permissionlib->isBerechtigt('admin'),
+ 'changeStatusToDiplomand' => $this->permissionlib->isBerechtigt('admin'),
+ 'changeStatusToAbsolvent' => $this->permissionlib->isBerechtigt('admin')
+ ]
+ ];
+
+ Events::trigger('stv_conf_students', function & () use (&$result) {
+ return $result;
+ });
+
+ $this->terminateWithSuccess($result);
+ }
+
+ protected function kontoColumns()
+ {
+ return [
+ 'buchungsdatum' => [
+ 'field' => "buchungsdatum",
+ 'title' => $this->p->t('konto', 'buchungsdatum')
+ ],
+ 'buchungstext' => [
+ 'field' => "buchungstext",
+ 'title' => $this->p->t('konto', 'buchungstext')
+ ],
+ 'betrag' => [
+ 'field' => "betrag",
+ 'title' => $this->p->t('konto', 'betrag')
+ ],
+ 'studiensemester_kurzbz' => [
+ 'field' => "studiensemester_kurzbz",
+ 'title' => $this->p->t('lehre', 'studiensemester')
+ ],
+ 'buchungstyp_kurzbz' => [
+ 'field' => "buchungstyp_kurzbz",
+ 'title' => $this->p->t('konto', 'buchungstyp'),
+ 'visible' => false
+ ],
+ 'buchungsnr' => [
+ 'field' => "buchungsnr",
+ 'title' => $this->p->t('konto', 'buchungsnr'),
+ 'visible' => false
+ ],
+ 'insertvon' => [
+ 'field' => "insertvon",
+ 'title' => $this->p->t('global', 'insertvon'),
+ 'visible' => false
+ ],
+ 'insertamum' => [
+ 'field' => "insertamum",
+ 'title' => $this->p->t('global', 'insertamum'),
+ 'visible' => false
+ ],
+ 'kuerzel' => [
+ 'field' => "kuerzel",
+ 'title' => $this->p->t('lehre', 'studiengang'),
+ 'visible' => false
+ ],
+ 'anmerkung' => [
+ 'field' => "anmerkung",
+ 'title' => $this->p->t('global', 'anmerkung')
+ ],
+ 'actions' => [
+ 'title' => $this->p->t('global', 'actions'),
+ 'frozen' => true
+ ]
+ ];
+ }
+ protected function kontoColumnsMultiPerson()
+ {
+ return [
+ 'person_id' => [
+ 'field' => "person_id",
+ 'title' => $this->p->t('person', 'person_id')
+ ],
+ 'anrede' => [
+ 'field' => "anrede",
+ 'title' => $this->p->t('person', 'anrede'),
+ 'visible' => false
+ ],
+ 'titelpost' => [
+ 'field' => "titelpost",
+ 'title' => $this->p->t('person', 'titelpost'),
+ 'visible' => false
+ ],
+ 'titelpre' => [
+ 'field' => "titelpre",
+ 'title' => $this->p->t('person', 'titelpre'),
+ 'visible' => false
+ ],
+ 'vorname' => [
+ 'field' => "vorname",
+ 'title' => $this->p->t('person', 'vorname')
+ ],
+ 'vornamen' => [
+ 'field' => "vornamen",
+ 'title' => $this->p->t('person', 'vornamen'),
+ 'visible' => false
+ ],
+ 'nachname' => [
+ 'field' => "nachname",
+ 'title' => $this->p->t('person', 'nachname')
+ ]
+ ] + $this->kontoColumns();
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Favorites.php b/application/controllers/api/frontend/v1/stv/Favorites.php
new file mode 100644
index 000000000..8d7a6cd14
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Favorites.php
@@ -0,0 +1,71 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about favorite verbände
+ * Listens to ajax post calls to change the favorite verbände data
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Favorites extends FHCAPI_Controller
+{
+ public function __construct()
+ {
+ parent::__construct([
+ 'index' => self::PERM_LOGGED,
+ 'set' => self::PERM_LOGGED
+ ]);
+
+ // Load models
+ $this->load->model('system/Variable_model', 'VariableModel');
+
+ // TODO(chris): variable table might be to small to store favorites!
+ }
+
+ public function index()
+ {
+ $result = $this->VariableModel->getVariables(getAuthUID(), ['stv_favorites']);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if (!$data)
+ $this->terminateWithSuccess(null);
+ else
+ $this->terminateWithSuccess($data['stv_favorites']);
+ }
+
+ public function set()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('favorites', 'Favorites', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $favorites = $this->input->post('favorites');
+
+ $result = $this->VariableModel->setVariable(getAuthUID(), 'stv_favorites', $favorites);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess(true);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Filter.php b/application/controllers/api/frontend/v1/stv/Filter.php
new file mode 100644
index 000000000..dbf70e4fb
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Filter.php
@@ -0,0 +1,84 @@
+.
+ */
+
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about the Studiengang filter
+ * Listens to ajax post calls to change the Studiengang filter data
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Filter extends FHCAPI_Controller
+{
+ /**
+ * Calls the parent's constructor and prepares libraries and phrases
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getStg' => self::PERM_LOGGED,
+ 'setStg' => self::PERM_LOGGED
+ ]);
+
+ // Load models
+ $this->load->model('system/Variable_model', 'VariableModel');
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Get current setting
+ *
+ * @return void
+ */
+ public function getStg()
+ {
+ $result = $this->VariableModel->getVariables(getAuthUID(), ['kontofilterstg']);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data['kontofilterstg'] == 'true');
+ }
+
+ /**
+ * Set current setting
+ *
+ * @return void
+ */
+ public function setStg()
+ {
+ $this->load->library('form_validation');
+
+ $studiengang_kz = $this->input->post('studiengang_kz');
+
+ if ($studiengang_kz === null) {
+ $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $result = $this->VariableModel->setVariable(getAuthUID(), 'kontofilterstg', $studiengang_kz ? 'true' : 'false');
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess(true);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Kontakt.php b/application/controllers/api/frontend/v1/stv/Kontakt.php
new file mode 100644
index 000000000..379184ee0
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Kontakt.php
@@ -0,0 +1,754 @@
+ ['admin:r', 'assistenz:r'],
+ 'addNewAddress' => ['admin:rw', 'assistenz:rw'],
+ 'addNewContact' => ['admin:rw', 'assistenz:rw'],
+ 'addNewBankverbindung' => ['mitarbeiter/bankdaten:rw', 'student/bankdaten:rw'],
+ 'updateAddress' => ['admin:rw', 'assistenz:rw'],
+ 'updateContact' => ['admin:rw', 'assistenz:rw'],
+ 'updateBankverbindung' => ['mitarbeiter/bankdaten:rw', 'student/bankdaten:rw'],
+ 'loadAddress' => ['admin:r', 'assistenz:r'],
+ 'loadContact' => ['admin:r', 'assistenz:r'],
+ 'loadBankverbindung' => ['mitarbeiter/bankdaten:r', 'student/bankdaten:r'],
+ 'deleteAddress' => ['admin:rw', 'assistenz:rw'],
+ 'deleteContact' => ['admin:rw','assistenz:rw'],
+ 'deleteBankverbindung' => ['mitarbeiter/bankdaten:rw','astudent/bankdaten:rw'],
+ 'getAdressentypen' => ['admin:r', 'assistenz:r'],
+ 'getKontakttypen' => ['admin:r', 'assistenz:r'],
+ 'getFirmen' => ['admin:r', 'assistenz:r'],
+ 'getStandorte' => ['admin:r', 'assistenz:r'],
+ 'getStandorteByFirma' => ['admin:r', 'assistenz:r'],
+ 'getKontakte' => ['admin:r', 'assistenz:r'],
+ 'getBankverbindung' => ['mitarbeiter/bankdaten:r', 'student/bankdaten:r']
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ $this->load->library('form_validation');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui',
+ 'person'
+ ]);
+
+ // Load models
+ $this->load->model('person/Adresse_model', 'AdresseModel');
+ $this->load->model('organisation/standort_model', 'StandortModel');
+ $this->load->model('ressource/firma_model', 'FirmaModel');
+ $this->load->model('person/Kontakt_model', 'KontaktModel');
+
+ // Extra Permissionchecks
+ $permsMa = [];
+ $permsStud = [];
+ switch ($this->router->method) {
+ case 'getBankverbindung':
+ case 'loadBankverbindung':
+ $permsMa = ['mitarbeiter/bankdaten:r'];
+ $permsStud = ['student/bankdaten:r'];
+ break;
+ case 'addNewBankverbindung':
+ case 'updateBankverbindung':
+ case 'deleteBankverbindung':
+ $permsMa = ['mitarbeiter/bankdaten:rw'];
+ $permsStud = ['student/bankdaten:rw'];
+ break;
+ case 'getAdressen':
+ case 'getKontakte':
+ case 'loadAddress':
+ case 'loadContact':
+ $permsMa = $permsStud = ['admin:r', 'assistenz:r'];
+ break;
+ case 'addNewAddress':
+ case 'addNewContact':
+ case 'updateAddress':
+ case 'updateContact':
+ case 'deleteAddress':
+ case 'deleteContact':
+ $permsMa = $permsStud = ['admin:rw', 'assistenz:rw'];
+ break;
+ }
+ if ($this->router->method == 'getAdressen'
+ || $this->router->method == 'getKontakte'
+ || $this->router->method == 'getBankverbindung'
+ || $this->router->method == 'addNewAddress'
+ || $this->router->method == 'addNewContact'
+ || $this->router->method == 'addNewBankverbindung'
+ ) {
+ $person_id = current(array_slice($this->uri->rsegments, 2));
+
+ $this->checkPermissionsForPerson($person_id, $permsMa, $permsStud);
+ } elseif ($this->router->method == 'loadAddress'
+ || $this->router->method == 'loadContact'
+ || $this->router->method == 'loadBankverbindung'
+ || $this->router->method == 'updateAddress'
+ || $this->router->method == 'updateContact'
+ || $this->router->method == 'updateBankverbindung'
+ || $this->router->method == 'deleteAddress'
+ || $this->router->method == 'deleteContact'
+ || $this->router->method == 'deleteBankverbindung'
+ ) {
+ $id = current(array_slice($this->uri->rsegments, 2));
+
+ $model = 'person/Adresse_model';
+ if ($this->router->method == 'loadContact'
+ || $this->router->method == 'updateContact'
+ || $this->router->method == 'deleteContact'
+ ) {
+ $model = 'person/Kontakt_model';
+ } elseif ($this->router->method == 'loadBankverbindung'
+ || $this->router->method == 'updateBankverbindung'
+ || $this->router->method == 'deleteBankverbindung'
+ ) {
+ $model = 'person/Bankverbindung_model';
+ }
+
+ $this->load->model($model, 'TempModel');
+ $result = $this->TempModel->load($id);
+ $data = $this->getDataOrTerminateWithError($result);
+ if (!$result)
+ show_404();
+
+ $person_id = current($data)->person_id;
+
+ $this->checkPermissionsForPerson($person_id, $permsMa, $permsStud);
+ }
+ }
+ public function getAdressen($person_id)
+ {
+ $this->AdresseModel->addSelect('public.tbl_adresse.*');
+ $this->AdresseModel->addSelect('t.*');
+ $this->AdresseModel->addSelect('f.firma_id');
+ $this->AdresseModel->addSelect('f.name as firmenname');
+ $this->AdresseModel->addJoin('public.tbl_adressentyp t', 'ON (t.adressentyp_kurzbz = public.tbl_adresse.typ)');
+ $this->AdresseModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = public.tbl_adresse.firma_id)', 'LEFT');
+
+ $result = $this->AdresseModel->loadWhere(
+ array('person_id' => $person_id)
+ );
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function addNewAddress($person_id)
+ {
+ $this->form_validation->set_rules('plz', 'PLZ', 'required|numeric', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']),
+ 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ'])
+ ]);
+
+ if(isset($_POST['gemeinde']) && isset($_POST['ort']))
+ $this->form_validation->set_rules('plz', 'Postleitzahl', 'callback_validateLocationCombination', [
+ 'validateLocationCombination' => $this->p->t('ui', 'error_location_combination')
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $uid = getAuthUID();
+ $co_name = isset($_POST['co_name']) ? $_POST['co_name'] : null;
+ $strasse = isset($_POST['strasse']) ? $_POST['strasse'] : null;
+ $ort = isset($_POST['ort']) ? $_POST['ort'] : null;
+ $gemeinde = isset($_POST['gemeinde']) ? $_POST['gemeinde'] : null;
+ $nation = isset($_POST['nation']) ? $_POST['nation'] : null;
+ $name = isset($_POST['name']) ? $_POST['name'] : null;
+ $typ = isset($_POST['typ']) ? $_POST['typ'] : null;
+ $anmerkung = isset($_POST['anmerkung']) ? $_POST['anmerkung'] : null;
+
+ if(isset($_POST['firma']))
+ {
+ $firma_id = $_POST['firma']['firma_id'];
+ }
+ else
+ $firma_id = null;
+
+ $result = $this->AdresseModel->insert(
+ [
+ 'person_id' => $person_id,
+ 'strasse' => $strasse,
+ 'insertvon' => $uid,
+ 'insertamum' => date('c'),
+ 'plz' => $_POST['plz'],
+ 'ort' => $ort,
+ 'gemeinde' => $gemeinde,
+ 'nation' => $nation,
+ 'heimatadresse' => $_POST['heimatadresse'],
+ 'zustelladresse' => $_POST['zustelladresse'],
+ 'co_name' => $co_name,
+ 'typ' => $typ,
+ 'firma_id' => $firma_id,
+ 'name' => $name,
+ 'rechnungsadresse' => $_POST['rechnungsadresse'],
+ 'anmerkung' => $anmerkung
+
+ ]
+ );
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->outputJsonSuccess(true);
+ }
+
+ public function updateAddress($address_id)
+ {
+ $uid = getAuthUID();
+ $this->form_validation->set_rules('plz', 'PLZ', 'required|numeric', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'PLZ']),
+ 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'PLZ'])
+ ]);
+
+ if(isset($_POST['gemeinde']) && isset($_POST['ort']))
+ $this->form_validation->set_rules('plz', 'Postleitzahl', 'callback_validateLocationCombination', [
+ 'validateLocationCombination' => $this->p->t('ui', 'error_location_combination')
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $this->load->model('person/Adresse_model', 'AdresseModel');
+
+ if(!$address_id)
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Adresse_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ if(isset($_POST['firma']))
+ {
+ $firma_id = $_POST['firma']['firma_id'];
+ }
+ elseif(isset($_POST['firma_id']))
+ {
+ $firma_id = $_POST['firma_id'];
+ }
+ else
+ $firma_id = null;
+
+ $person_id = isset($_POST['person_id']) ? $_POST['person_id'] : null;
+ $co_name = isset($_POST['co_name']) ? $_POST['co_name'] : null;
+ $strasse = isset($_POST['strasse']) ? $_POST['strasse'] : null;
+ $ort = isset($_POST['ort']) ? $_POST['ort'] : null;
+ $gemeinde = isset($_POST['gemeinde']) ? $_POST['gemeinde'] : null;
+ $nation = isset($_POST['nation']) ? $_POST['nation'] : null;
+ $name = isset($_POST['name']) ? $_POST['name'] : null;
+ $typ = isset($_POST['typ']) ? $_POST['typ'] : null;
+ $anmerkung = isset($_POST['anmerkung']) ? $_POST['anmerkung'] : null;
+
+ $result = $this->AdresseModel->update(
+ [
+ 'adresse_id' => $address_id
+ ],
+ [ 'person_id' => $person_id,
+ 'strasse' => $strasse,
+ 'updatevon' => $uid,
+ 'updateamum' => date('c'),
+ 'plz' => $_POST['plz'],
+ 'ort' => $ort,
+ 'gemeinde' => $gemeinde,
+ 'nation' => $nation,
+ 'heimatadresse' => $_POST['heimatadresse'],
+ 'zustelladresse' => $_POST['zustelladresse'],
+ 'co_name' => $co_name,
+ 'typ' => $typ,
+ 'firma_id' => $firma_id,
+ 'name' => $name,
+ 'rechnungsadresse' => $_POST['rechnungsadresse'],
+ 'anmerkung' => $anmerkung
+ ]
+ );
+
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->outputJsonSuccess(true);
+ }
+
+ public function loadAddress($adresse_id)
+ {
+ $this->load->model('person/Adresse_model', 'AdresseModel');
+
+ $this->AdresseModel->addSelect('public.tbl_adresse.*');
+ $this->AdresseModel->addSelect('t.*');
+ $this->AdresseModel->addSelect('f.firma_id');
+ $this->AdresseModel->addSelect('f.name as firmenname');
+ $this->AdresseModel->addJoin('public.tbl_adressentyp t', 'ON (t.adressentyp_kurzbz = public.tbl_adresse.typ)');
+ $this->AdresseModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = public.tbl_adresse.firma_id)', 'LEFT');
+
+ $this->AdresseModel->addLimit(1);
+
+ $result = $this->AdresseModel->loadWhere(
+ array('adresse_id' => $adresse_id)
+ );
+ if (isError($result)) {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+
+ if (!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Adresse_id']), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess(current(getData($result)) ? : null);
+ }
+
+ public function deleteAddress($adresse_id)
+ {
+ $this->load->model('person/Adresse_model', 'AdresseModel');
+ $result = $this->AdresseModel->load([
+ 'adresse_id'=> $adresse_id,
+ ]);
+ if(isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $result = current(getData($result));
+
+ if($result->heimatadresse)
+
+ $this->terminateWithError($this->p->t('person', 'error_deleteHomeAdress'), self::ERROR_TYPE_GENERAL);
+
+ $result = $this->AdresseModel->delete(
+ array('adresse_id' => $adresse_id)
+ );
+
+ if (isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ if (!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Adresse_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ return $this->terminateWithSuccess(current(getData($result)) ? : null);
+ }
+
+ public function getAdressentypen()
+ {
+ $this->load->model('person/Adressentyp_model', 'AdressentypModel');
+
+ $result = $this->AdressentypModel->load();
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getFirmen($searchString)
+ {
+ $this->load->model('ressource/firma_model', 'FirmaModel');
+
+ $result = $this->FirmaModel->searchFirmen($searchString);
+ if (isError($result)) {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess($result ?: []);
+ }
+
+ public function getStandorte($searchString)
+ {
+ $this->load->model('organisation/standort_model', 'StandortModel');
+
+ $result = $this->StandortModel->searchStandorte($searchString);
+ if (isError($result)) {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess($result ?: []);
+ }
+
+ public function getStandorteByFirma($firma_id)
+ {
+ $this->load->model('organisation/standort_model', 'StandortModel');
+
+ $result = $this->StandortModel->getStandorteByFirma($firma_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getKontakte($person_id)
+ {
+ $this->KontaktModel->addSelect("public.tbl_kontakt.*,
+ TO_CHAR (CASE
+ WHEN public.tbl_kontakt.updateamum >= public.tbl_kontakt.insertamum
+ THEN public.tbl_kontakt.updateamum
+ ELSE public.tbl_kontakt.insertamum
+ END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate, st.bezeichnung, f.name");
+ $this->StandortModel->addJoin('public.tbl_standort st', 'ON (public.tbl_kontakt.standort_id = st.standort_id)', 'LEFT');
+ $this->FirmaModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = st.firma_id)', 'LEFT');
+ $result = $this->KontaktModel->loadWhere(
+ array('person_id' => $person_id)
+ );
+
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function getKontakttypen()
+ {
+ $this->load->model('person/Kontakttyp_model', 'KontakttypModel');
+
+ $result = $this->KontakttypModel->load();
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ else
+ {
+ $this->terminateWithSuccess(getData($result) ?: []);
+ }
+ }
+
+ public function loadContact($kontakt_id)
+ {
+ $this->load->model('person/Kontakt_model', 'KontaktModel');
+
+ $this->KontaktModel->addSelect('*, public.tbl_kontakt.*');
+ $this->KontaktModel->addSelect('st.kurzbz');
+ $this->KontaktModel->addJoin('public.tbl_standort st', 'ON (public.tbl_kontakt.standort_id = st.standort_id)', 'LEFT');
+ $this->FirmaModel->addJoin('public.tbl_firma f', 'ON (f.firma_id = st.firma_id)', 'LEFT');
+
+ $this->KontaktModel->addLimit(1);
+
+ $result = $this->KontaktModel->loadWhere(
+ array('kontakt_id' => $kontakt_id)
+ );
+ if (isError($result)) {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ if (!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Kontakt_id']), self::ERROR_TYPE_GENERAL);
+ }
+ // $this->outputJsonSuccess(current(getData($result)));
+ $this->terminateWithSuccess(current(getData($result)));
+ }
+
+ public function addNewContact($person_id)
+ {
+ if(($_POST['kontakttyp'] == 'email' && isset($_POST['kontakt'])))
+ {
+ $this->form_validation->set_rules('kontakt', 'Kontakt', 'required|valid_email', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Kontakt']),
+ 'valid_email' => $this->p->t('ui', 'error_fieldNoValidEmail', ['field' => 'Kontakt'])
+ ]);
+ }
+ else
+ {
+ $this->form_validation->set_rules('kontakt', 'Kontakt', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Kontakt'])
+ ]);
+ }
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $this->load->model('person/Kontakt_model', 'KontaktModel');
+
+ $uid = getAuthUID();
+
+ $kontakttyp = $this->input->post('kontakttyp');
+ $anmerkung = $this->input->post('anmerkung');
+ $kontakt = $this->input->post('kontakt');
+ $ext_id = $this->input->post('ext_id');
+ $standort_id = $this->input->post('standort_id');
+
+ $result = $this->KontaktModel->insert(
+ [
+ 'person_id' => $person_id,
+ 'kontakttyp' => $kontakttyp,
+ 'anmerkung' => $anmerkung,
+ 'kontakt' => $kontakt,
+ 'zustellung' => $_POST['zustellung'],
+ 'insertvon' => $uid,
+ 'insertamum' => date('c'),
+ 'standort_id' => $standort_id,
+ 'ext_id' => $ext_id
+ ]
+ );
+
+ if (isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ return $this->outputJsonSuccess(true);
+ }
+
+ public function updateContact($kontakt_id)
+ {
+ $this->load->model('person/Kontakt_model', 'KontaktModel');
+
+ if(!$kontakt_id)
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Kontakt_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ if(($_POST['kontakttyp'] == 'email' && isset($_POST['kontakt'])))
+ {
+ $this->form_validation->set_rules('kontakt', 'Kontakt', 'required|valid_email', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Kontakt']),
+ 'valid_email' => $this->p->t('ui', 'error_fieldNoValidEmail', ['field' => 'Kontakt'])
+ ]);
+ }
+ else
+ {
+ $this->form_validation->set_rules('kontakt', 'Kontakt', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Kontakt'])
+ ]);
+ }
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+/* if(isset($_POST['standort']))
+ {
+ $standort_id = $_POST['standort']['standort_id'];
+ }
+ else
+ $standort_id = null;*/
+
+ $uid = getAuthUID();
+ $kontakttyp = $this->input->post('kontakttyp');
+ $anmerkung = $this->input->post('anmerkung');
+ $kontakt = $this->input->post('kontakt');
+ $ext_id = $this->input->post('ext_id');
+ $person_id = $this->input->post('person_id');
+ $standort_id = $this->input->post('standort_id');
+
+ //return $this->terminateWithError("in update " . $standort_id, self::ERROR_TYPE_GENERAL);
+
+ $result = $this->KontaktModel->update(
+ [
+ 'kontakt_id' => $kontakt_id
+ ],
+ [
+ 'person_id' => $person_id,
+ 'kontakttyp' => $kontakttyp,
+ 'anmerkung' => $anmerkung,
+ 'kontakt' => $kontakt,
+ 'zustellung' => $_POST['zustellung'],
+ 'insertvon' => $uid,
+ 'insertamum' => date('c'),
+ 'standort_id' => $standort_id,
+ 'ext_id' => $ext_id
+ ]
+ );
+
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->outputJsonSuccess(true);
+ }
+
+ public function deleteContact($kontakt_id)
+ {
+ $this->load->model('person/Kontakt_model', 'KontaktModel');
+
+ $result = $this->KontaktModel->delete(
+ array('kontakt_id' => $kontakt_id)
+ );
+
+ if (isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ elseif (!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Kontakt_id']), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(current(getData($result)) ? : null);
+ }
+
+ public function getBankverbindung($person_id)
+ {
+ $this->load->model('person/Bankverbindung_model', 'BankverbindungModel');
+
+ $this->BankverbindungModel->addSelect('*');
+
+ $result = $this->BankverbindungModel->loadWhere(
+ array('person_id' => $person_id)
+ );
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function addNewBankverbindung($person_id)
+ {
+ $this->form_validation->set_rules('iban', 'IBAN', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'IBAN'])
+ ]);
+
+ $this->form_validation->set_rules('typ', 'TYP', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'TYP'])
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $this->load->model('person/Bankverbindung_model', 'BankverbindungModel');
+
+ $ext_id = $this->input->post('ext_id');
+ $oe_kurzbz = $this->input->post('oe_kurzbz');
+ $orgform_kurzbz = $this->input->post('orgform_kurzbz');
+ $name = $this->input->post('name');
+ $anschrift = $this->input->post('anschrift');
+ $bic = $this->input->post('bic');
+ $blz = $this->input->post('blz');
+ $kontonr = $this->input->post('kontonr');
+
+ $result = $this->BankverbindungModel->insert(
+ [
+ 'person_id' => $person_id,
+ 'name' => $name,
+ 'anschrift' => $anschrift,
+ 'bic' => $bic,
+ 'iban' => $_POST['iban'],
+ 'blz' => $blz,
+ 'kontonr' => $kontonr,
+ 'insertvon' => 'uid',
+ 'insertamum' => date('c'),
+ 'typ' => $_POST['typ'],
+ 'verrechnung' => $_POST['verrechnung'],
+ 'ext_id' => $ext_id,
+ 'oe_kurzbz' => $oe_kurzbz,
+ 'orgform_kurzbz' => $orgform_kurzbz
+ ]
+ );
+ if (isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ return $this->outputJsonSuccess(true);
+ }
+
+ public function loadBankverbindung($bankverbindung_id)
+ {
+ $this->load->model('person/Bankverbindung_model', 'BankverbindungModel');
+
+ $this->BankverbindungModel->addSelect('*');
+
+ $this->BankverbindungModel->addLimit(1);
+
+ $result = $this->BankverbindungModel->loadWhere(
+ array('bankverbindung_id' => $bankverbindung_id)
+ );
+ if (isError($result))
+ {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+
+ if (!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Bankverbindung_id']), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess(current(getData($result)));
+ }
+
+ public function updateBankverbindung($bankverbindung_id)
+ {
+ $this->form_validation->set_rules('iban', 'IBAN', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'IBAN'])
+ ]);
+
+ $this->form_validation->set_rules('typ', 'TYP', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'TYP'])
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $this->load->model('person/Bankverbindung_model', 'BankverbindungModel');
+
+ if(!$bankverbindung_id)
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Bankverbindung_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ $uid = getAuthUID();
+
+ $result = $this->BankverbindungModel->update(
+ [
+ 'bankverbindung_id' => $bankverbindung_id
+ ],
+ [
+ 'person_id' => $_POST['person_id'],
+ 'name' => $_POST['name'],
+ 'anschrift' => $_POST['anschrift'],
+ 'bic' => $_POST['bic'],
+ 'iban' => $_POST['iban'],
+ 'blz' => $_POST['blz'],
+ 'kontonr' => $_POST['kontonr'],
+ 'updatevon' => $uid,
+ 'updateamum' => date('c'),
+ 'typ' => $_POST['typ'],
+ 'verrechnung' => $_POST['verrechnung'],
+ 'ext_id' => $_POST['ext_id'],
+ 'oe_kurzbz' => $_POST['oe_kurzbz'],
+ 'orgform_kurzbz' => $_POST['orgform_kurzbz']
+ ]
+ );
+
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->outputJsonSuccess(true);
+ }
+
+ public function deleteBankverbindung($bankverbindung_id)
+ {
+ $this->load->model('person/Bankverbindung_model', 'BankverbindungModel');
+
+ $result = $this->BankverbindungModel->delete(
+ array('bankverbindung_id' => $bankverbindung_id)
+ );
+
+ if (isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ if (!hasData($result))
+ {
+ $this->outputJson($result);
+ }
+ return $this->terminateWithSuccess(current(getData($result)) ? : null);
+ }
+
+ public function validateLocationCombination()
+ {
+ $this->load->model('codex/Gemeinde_model', 'GemeindeModel');
+
+ return $this->GemeindeModel->checkLocation($_POST['plz'], $_POST['gemeinde'], $_POST['ort']);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Konto.php b/application/controllers/api/frontend/v1/stv/Konto.php
new file mode 100644
index 000000000..ac36b5d8f
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Konto.php
@@ -0,0 +1,495 @@
+.
+ */
+
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+use CI3_Events as Events;
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about a Konto
+ * Listens to ajax post calls to change the Konto data
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Konto extends FHCAPI_Controller
+{
+ /**
+ * Calls the parent's constructor and prepares libraries and phrases
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'get' => 'student/stammdaten:r',
+ 'getBuchungstypen' => self::PERM_LOGGED,
+ 'checkDoubles' => ['admin:r', 'assistenz:r'],
+ 'insert' => ['admin:w', 'assistenz:w'],
+ 'counter' => ['admin:w', 'assistenz:w'],
+ 'update' => ['admin:w', 'assistenz:w'],
+ 'delete' => ['admin:w', 'assistenz:w']
+ ]);
+
+ // Load models
+ $this->load->model('crm/Konto_model', 'KontoModel');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'konto'
+ ]);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Get details for a prestudent
+ *
+ * @return void
+ */
+ public function get()
+ {
+ $this->load->library('form_validation');
+
+ $person_id = $this->input->post('person_id');
+ if (!$person_id || !is_array($person_id)) {
+ $this->form_validation->set_rules('person_id', 'Person ID', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+
+ $studiengang_kz = $this->input->post('studiengang_kz');
+
+ if ($this->input->post('only_open')) {
+ $result = $this->KontoModel->getOffeneBuchungen($person_id, $studiengang_kz);
+ } else {
+ $result = $this->KontoModel->getAlleBuchungen($person_id, $studiengang_kz);
+ }
+
+ $result = $this->getDataOrTerminateWithError($result);
+
+ // sort into tree
+ $childs = [];
+ $data = [];
+ foreach ($result as $entry) {
+ if ($entry->buchungsnr_verweis) {
+ if (isset($data[$entry->buchungsnr_verweis])) {
+ if (!isset($data[$entry->buchungsnr_verweis]->_children))
+ $data[$entry->buchungsnr_verweis]->_children = [];
+ $data[$entry->buchungsnr_verweis]->_children[] = $entry;
+ } else {
+ if (!isset($childs[$entry->buchungsnr_verweis]))
+ $childs[$entry->buchungsnr_verweis] = [];
+ $childs[$entry->buchungsnr_verweis][] = $entry;
+ }
+ } else {
+ $data[$entry->buchungsnr] = $entry;
+ if (isset($childs[$entry->buchungsnr]))
+ $entry->_children = $childs[$entry->buchungsnr];
+ }
+ }
+
+ $this->terminateWithSuccess(array_values($data));
+ }
+
+ /**
+ * Get list of Buchungstypen
+ *
+ * @return void
+ */
+ public function getBuchungstypen()
+ {
+ $this->load->model('crm/Buchungstyp_model', 'BuchungstypModel');
+
+ $result = $this->BuchungstypModel->load();
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * Check double Buchungen
+ *
+ * @return void
+ */
+ public function checkDoubles()
+ {
+ if (!defined('FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK') || !FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK)
+ $this->terminateWithSuccess(false);
+
+ $this->load->library('form_validation');
+
+ $person_ids = $this->input->post('person_id');
+
+ if (!$person_ids || !is_array($person_ids)) {
+ $person_ids = [$person_ids];
+ $this->form_validation->set_rules('person_id', 'Person ID', 'required');
+ }
+ $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required');
+ $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ $buchungstypen = unserialize(FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK);
+ $buchung = $this->input->post('buchungstyp_kurzbz');
+
+ if (!isset($buchungstypen[$buchung]))
+ $this->terminateWithSuccess(false);
+
+ $result = $this->KontoModel->checkDoubleBuchung($person_ids, $this->input->post('studiensemester_kurzbz'), $buchungstypen[$buchung]);
+
+ $result = $this->getDataOrTerminateWithError($result);
+
+ if (!$result)
+ $this->terminateWithSuccess(false);
+
+ $persons = array_map(function ($row) {
+ return $row->nachname . ' ' . $row->vorname;
+ }, $result);
+
+ $result = $this->p->t('konto', 'confirm_overwrite') . "\n";
+ if (count($persons) > 10) {
+ $result .= "-" . implode("\n-", array_slice($persons, 0, 10)) . "\n";
+
+ if (count($persons) == 11) {
+ $result .= "\n" . $this->p->t('konto', 'confirm_overwrite_1_add_pers');
+ } else {
+ $result .= "\n" . $this->p->t('konto', 'confirm_overwrite_x_add_pers', [
+ 'x' => count($persons) - 10
+ ]);
+ }
+ } else {
+ $result .= "-" . implode("\n-", $persons) . "\n";
+ }
+ $result .= $this->p->t('konto', 'confirm_overwrite_proceed');
+
+ $this->addError($result, 'confirm');
+
+ $this->terminateWithSuccess(true);
+ }
+
+
+ /**
+ * Save Buchung
+ *
+ * @return void
+ */
+ public function insert()
+ {
+ $this->load->library('form_validation');
+
+ $person_ids = $this->input->post('person_id');
+
+ if (!$person_ids || !is_array($person_ids)) {
+ $person_ids = [$person_ids];
+ $this->form_validation->set_rules('person_id', 'Person ID', 'required');
+ }
+ $this->form_validation->set_rules('betrag', 'Betrag', 'numeric');
+ $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date');
+ $this->form_validation->set_rules('buchungstext', 'Buchungstext', 'max_length[256]');
+ $this->form_validation->set_rules('mahnspanne', 'Mahnspanne', 'integer');
+ $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required|max_length[32]');
+ $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required|max_length[16]');
+ $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required|has_permissions_for_stg[admin:rw,assistenz:rw]');
+ $this->form_validation->set_rules('credit_points', 'Credit Points', 'numeric');
+
+ Events::trigger('konto_insert_validation', $this->form_validation);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ $allowed = [
+ 'betrag',
+ 'buchungsdatum',
+ 'buchungstext',
+ 'mahnspanne',
+ 'buchungstyp_kurzbz',
+ 'studiensemester_kurzbz',
+ 'studiengang_kz',
+ 'credit_points',
+ 'anmerkung'
+ ];
+ $data = [
+ 'insertamum' => date('c'),
+ 'insertvon' => getAuthUID()
+ ];
+ foreach ($allowed as $field)
+ if ($this->input->post($field) !== null)
+ $data[$field] = $this->input->post($field);
+
+ if (defined('FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE') && isset(unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']])) {
+ $data['kostenstelle'] = unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']];
+ }
+
+ $result = [];
+ foreach ($person_ids as $person_id) {
+ $id = $this->KontoModel->insert(array_merge($data, ['person_id' => $person_id]));
+ if (isError($id)) {
+ $this->addError(getError($id), self::ERROR_TYPE_DB);
+ } else {
+ $kontodata = $this->KontoModel->withAdditionalInfo()->load(getData($id));
+ if (isError($kontodata))
+ $this->addError(getError($kontodata), self::ERROR_TYPE_DB);
+ else
+ $result[] = current(getData($kontodata));
+ }
+ }
+
+ if ($result)
+ $this->terminateWithSuccess($result);
+
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ /**
+ * Save Counter Buchung
+ *
+ * @return void
+ */
+ public function counter()
+ {
+ $this->load->library('form_validation');
+
+ $buchungsnrs = $this->input->post('buchungsnr');
+
+ if (!$buchungsnrs || !is_array($buchungsnrs)) {
+ $buchungsnrs = $buchungsnrs ? [$buchungsnrs] : [];
+ $this->form_validation->set_rules('buchungsnr', 'Buchungsnr', 'required');
+ }
+ $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $data = [];
+ $rules = [];
+ foreach ($buchungsnrs as $k => $buchungsnr) {
+ $result = $this->KontoModel->load($buchungsnr);
+ if (isError($result)) {
+ $rules[] = [
+ 'field' => 'buchung[' . $k . ']',
+ 'label' => 'Buchung #' . $buchungsnr,
+ 'rules' => 'required',
+ 'errors' => [
+ 'required' => getError($result)
+ ]
+ ];
+ } elseif (!hasData($result)) {
+ $rules[] = [
+ 'field' => 'buchung[' . $k . ']',
+ 'label' => 'Buchung #' . $buchungsnr,
+ 'rules' => 'required'
+ ];
+ } else {
+ $data[$k] = get_object_vars(current(getData($result)));
+ $rules[] = [
+ 'field' => 'buchung[' . $k . '][buchungsnr]',
+ 'label' => 'Buchung # ' . $buchungsnr,
+ 'rules' => 'required|numeric'
+ ];
+ $rules[] = [
+ 'field' => 'buchung[' . $k . '][studiengang_kz]',
+ 'label' => 'Buchung # ' . $buchungsnr,
+ 'rules' => 'required|has_permissions_for_stg[admin:rw,assistenz:rw]'
+ ];
+ $rules[] = [
+ 'field' => 'buchung[' . $k . '][buchungsnr_verweis]',
+ 'label' => 'Buchung # ' . $buchungsnr,
+ 'rules' => 'regex_match[/^$/]',
+ 'errors' => [
+ 'regex_match' => $this->p->t('konto', 'error_counter_level')
+ ]
+ ];
+ }
+ }
+
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_data(['buchung' => $data]);
+ $this->form_validation->set_rules($rules);
+
+ Events::trigger('konto_counter_validation', $this->form_validation);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $buchungsdatum = $this->input->post('buchungsdatum');
+
+ $newItems = [];
+ foreach ($data as $buchung) {
+ $result = $this->KontoModel->getDifferenz($buchung['buchungsnr']);
+ if (isError($result)) {
+ $this->addError(getError($result), self::ERROR_TYPE_GENERAL);
+ continue;
+ }
+ $betrag = $result->retval;
+ if ($betrag === null) {
+ $this->addError($this->p->t(
+ 'konto',
+ 'error_missing',
+ $buchung
+ ), self::ERROR_TYPE_GENERAL);
+ continue;
+ }
+
+
+ $result = $this->KontoModel->insert([
+ 'person_id' => $buchung['person_id'],
+ 'studiengang_kz' => $buchung['studiengang_kz'],
+ 'studiensemester_kurzbz' => $buchung['studiensemester_kurzbz'],
+ 'buchungstext' => $buchung['buchungstext'],
+ 'buchungstyp_kurzbz' => $buchung['buchungstyp_kurzbz'],
+ 'credit_points' => $buchung['credit_points'],
+ 'zahlungsreferenz' => $buchung['zahlungsreferenz'],
+ 'betrag' => $betrag,
+ 'buchungsdatum' => $buchungsdatum,
+ 'mahnspanne' => '0',
+ 'buchungsnr_verweis' => $buchung['buchungsnr'],
+ 'insertamum' => date('c'),
+ 'insertvon' => getAuthUID(),
+ 'anmerkung' => ''
+ ]);
+ if (isError($result)) {
+ $this->addError(getError($result), self::ERROR_TYPE_GENERAL);
+ continue;
+ }
+
+ $newItems = null;
+ // TODO(chris): get as tree?
+ /*$result = $this->KontoModel->withAdditionalInfo()->load($result->retval);
+ if (!hasData($result))
+ $newItems = null;
+ elseif ($newItems !== null)
+ $newItems[] = current(getData($result));*/
+ }
+
+ $this->terminateWithSuccess($newItems);
+ }
+
+ /**
+ * Save Buchung
+ *
+ * @return void
+ */
+ public function update()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('buchungsnr', 'Buchungsnr', 'required');
+ $this->form_validation->set_rules('betrag', 'Betrag', 'numeric');
+ $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date');
+ $this->form_validation->set_rules('buchungstext', 'Buchungstext', 'max_length[256]');
+ $this->form_validation->set_rules('mahnspanne', 'Mahnspanne', 'integer');
+ $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required|max_length[32]');
+ $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required|max_length[16]');
+ $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required|has_permissions_for_stg[admin:rw,assistenz:rw]');
+ $this->form_validation->set_rules('credit_points', 'Credit Points', 'numeric');
+
+ Events::trigger('konto_update_validation', $this->form_validation);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ $id = $this->input->post('buchungsnr');
+ $allowed = [
+ 'betrag',
+ 'buchungsdatum',
+ 'buchungstext',
+ 'mahnspanne',
+ 'buchungstyp_kurzbz',
+ 'studiensemester_kurzbz',
+ 'studiengang_kz',
+ 'credit_points',
+ 'anmerkung'
+ ];
+ $data = [
+ 'updateamum' => date('c'),
+ 'updatevon' => getAuthUID()
+ ];
+ foreach ($allowed as $field)
+ if ($this->input->post($field) !== null)
+ $data[$field] = $this->input->post($field);
+
+ $result = $this->KontoModel->update($id, $data);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $result = null;
+ // TODO(chris): get as tree?
+ /*$result = $this->KontoModel->withAdditionalInfo()->load($id);
+
+ #$result = $this->getDataOrTerminateWithError($result);
+ if (isError($result))
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ $result = $result->retval;*/
+
+ $this->terminateWithSuccess($result);
+ }
+
+ /**
+ * Delete Buchung
+ *
+ * @return void
+ */
+ public function delete()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('buchungsnr', 'Buchungsnr', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ $buchungsnr = $this->input->post('buchungsnr');
+
+ $result = $this->KontoModel->load($buchungsnr);
+
+ $result = $this->getDataOrTerminateWithError($result);
+
+ if (!$result)
+ $this->terminateWithError($this->p->t('konto', 'error_missing', [
+ 'buchungsnr' => $buchungsnr
+ ]));
+
+ $_POST['studiengang_kz'] = current($result)->studiengang_kz;
+
+ $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'has_permissions_for_stg[admin:rw,assistenz:rw]');
+
+ Events::trigger('konto_delete_validation', $this->form_validation);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ Events::trigger('konto_delete', $buchungsnr);
+
+ $result = $this->KontoModel->delete($buchungsnr);
+ if (isError($result)) {
+ if (getCode($result) != 42)
+ $this->terminateWithError(getError($result));
+ $this->terminateWithError($this->p->t('konto', 'error_delete_level'));
+ }
+
+ $this->terminateWithSuccess();
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Lists.php b/application/controllers/api/frontend/v1/stv/Lists.php
new file mode 100644
index 000000000..1c0c25db7
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Lists.php
@@ -0,0 +1,147 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about generally used lists
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Lists extends FHCAPI_Controller
+{
+ public function __construct()
+ {
+ parent::__construct([
+ 'getStudiensemester' => self::PERM_LOGGED,
+ 'getStgs' => self::PERM_LOGGED,
+ 'getSprachen' => self::PERM_LOGGED,
+ 'getGeschlechter' => self::PERM_LOGGED,
+ 'getAusbildungen' => self::PERM_LOGGED,
+ 'getOrgforms' => self::PERM_LOGGED,
+ 'getStati' => self::PERM_LOGGED
+ ]);
+ }
+
+ public function getStudiensemester()
+ {
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+
+ $this->StudiensemesterModel->addOrder('ende');
+
+ $result = $this->StudiensemesterModel->load();
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getStgs()
+ {
+ $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
+
+ $this->StudiengangModel->addSelect('*');
+ $this->StudiengangModel->addSelect('UPPER(typ || kurzbz) AS kuerzel');
+
+ $this->StudiengangModel->addOrder('typ');
+ $this->StudiengangModel->addOrder('kurzbz');
+
+ $result = $this->StudiengangModel->load();
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getSprachen()
+ {
+ $this->load->model('system/Sprache_model', 'SpracheModel');
+
+ $this->SpracheModel->addOrder('sprache');
+
+ $result = $this->SpracheModel->load();
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getGeschlechter()
+ {
+ $this->load->model('person/Geschlecht_model', 'GeschlechtModel');
+
+ $this->GeschlechtModel->addOrder('sort');
+ $this->GeschlechtModel->addOrder('geschlecht');
+
+ $this->GeschlechtModel->addSelect('*');
+ #$this->GeschlechtModel->addTranslatedSelect("bezeichnung_mehrsprachig", "bezeichnung");
+ $this->GeschlechtModel->addSelect("bezeichnung_mehrsprachig[(SELECT index FROM public.tbl_sprache WHERE sprache=" . $this->GeschlechtModel->escape(DEFAULT_LANGUAGE) . " LIMIT 1)] AS bezeichnung");
+
+ $result = $this->GeschlechtModel->load();
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getAusbildungen()
+ {
+ $this->load->model('codex/Ausbildung_model', 'AusbildungModel');
+
+ $this->AusbildungModel->addOrder('ausbildungcode');
+
+ $result = $this->AusbildungModel->load();
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getOrgforms()
+ {
+ $this->load->model('codex/Orgform_model', 'OrgformModel');
+
+ $this->OrgformModel->addOrder('bezeichnung');
+
+ $result = $this->OrgformModel->loadWhere(['rolle' => true]);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getStati()
+ {
+ $lang = getUserLanguage();
+ $this->load->model('crm/Status_model', 'StatusModel');
+
+ $this->StatusModel->addSelect('*');
+ #$this->StatusModel->addTranslatedSelect('bezeichnung_mehrsprachig', 'bezeichnung');
+ $this->StatusModel->addSelect(
+ 'bezeichnung_mehrsprachig[(
+ SELECT index
+ FROM public.tbl_sprache
+ WHERE sprache=' . $this->StatusModel->escape($lang) . '
+ LIMIT 1
+ )] AS bezeichnung',
+ false
+ );
+ #$this->StatusModel->addOrder('ext_id');
+
+ $result = $this->StatusModel->load();
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Notiz.php b/application/controllers/api/frontend/v1/stv/Notiz.php
new file mode 100644
index 000000000..19e568f33
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Notiz.php
@@ -0,0 +1,384 @@
+ ['admin:r', 'assistenz:r'],
+ 'getNotizen' => ['admin:r', 'assistenz:r'],
+ 'loadNotiz' => ['admin:r', 'assistenz:r'], // TODO(manu): self::PERM_LOGGED
+ 'addNewNotiz' => ['admin:rw', 'assistenz:rw'], // TODO(manu): self::PERM_LOGGED
+ 'updateNotiz' => ['admin:rw', 'assistenz:rw'], // TODO(manu): self::PERM_LOGGED
+ 'deleteNotiz' => ['admin:r', 'assistenz:r'],
+ 'loadDokumente' => ['admin:r', 'assistenz:r'],
+ 'getMitarbeiter' => ['admin:r', 'assistenz:r']
+ ]);
+
+ //Load Models
+ $this->load->model('person/Notiz_model', 'NotizModel');
+ $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui'
+ ]);
+ }
+
+/* public function getUid()
+ {
+ $this->terminateWithSuccess(getAuthUID());
+ }*/
+
+
+ public function getNotizen($id, $type)
+ {
+
+ //check if valid type
+ $result = $this->NotizzuordnungModel->isValidType($type);
+ if(isError($result))
+ $this->terminateWithError($result->retval, self::ERROR_TYPE_GENERAL);
+
+ //$this->terminateWithError(" after check type not valid", self::ERROR_TYPE_GENERAL);
+ $result = $this->NotizModel->getNotizWithDocEntries($id, $type);
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+
+ // return $this->terminateWithError("type not valid", self::ERROR_TYPE_GENERAL);
+
+ }
+
+/* public function loadNotiz()
+ {
+ $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
+
+ $notiz_id = $this->input->post('notiz_id');
+
+ //$this->load->model('person/Notiz_model', 'NotizModel');
+ $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'notiz_id', 'LEFT');
+ $this->NotizModel->addSelect('*');
+ $this->NotizModel->addSelect("TO_CHAR(CASE WHEN public.tbl_notiz.updateamum >= public.tbl_notiz.insertamum
+ THEN public.tbl_notiz.updateamum ELSE public.tbl_notiz.insertamum END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate");
+ $this->NotizModel->addLimit(1);
+
+ $result = $this->NotizModel->loadWhere(
+ array('notiz_id' => $notiz_id)
+ );
+ if (isError($result))
+ {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ elseif (!hasData($result))
+ {
+ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL);
+ }
+ else
+ {
+ $this->terminateWithSuccess(current(getData($result)));
+ }
+ }
+
+
+ public function updateNotiz()
+ {
+ $this->load->library('form_validation');
+ $this->load->library('DmsLib');
+
+ if (isset($_POST['data']))
+ {
+ $data = json_decode($_POST['data']);
+ unset($_POST['data']);
+ foreach ($data as $k => $v) {
+ $_POST[$k] = $v;
+ }
+ }
+
+ $notiz_id = $this->input->post('notiz_id');
+
+ if(!$notiz_id)
+ {
+ $this->terminateWithError($this->p->t('ui','error_missingId',['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ //Form Validation
+ $this->form_validation->set_rules('titel', 'Titel', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel'])
+ ]);
+
+ $this->form_validation->set_rules('text', 'Text', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Text'])
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ //update Notiz
+ $uid = getAuthUID();
+ $titel = $this->input->post('titel');
+ $text = $this->input->post('text');
+ $verfasser_uid = $this->input->post('verfasser');
+ $bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : $uid;
+ $erledigt = $this->input->post('erledigt');
+ $start = $this->input->post('start');
+ $ende = $this->input->post('ende');
+
+ $result = $this->NotizModel->update(
+ [
+ 'notiz_id' => $notiz_id
+ ],
+ [
+ 'titel' => $titel,
+ 'updatevon' => $uid,
+ 'updateamum' => date('c'),
+ 'text' => $text,
+ 'verfasser_uid' => $verfasser_uid,
+ 'bearbeiter_uid' => $bearbeiter_uid,
+ 'start' => $start,
+ 'ende' => $ende,
+ 'erledigt' => $erledigt
+ ]
+ );
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ //update(1) laden aller bereits mit dieser notiz_id verknüpften DMS-Einträge
+ $this->load->model('person/Notizdokument_model', 'NotizdokumentModel');
+ $this->NotizdokumentModel->addJoin('campus.tbl_dms_version', 'dms_id');
+ $dms_uploaded = null;
+
+ $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id));
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ elseif (!hasData($result))
+ {
+ $dms_id_arr = null;
+ }
+ else
+ {
+ $result = getData($result);
+ foreach($result as $doc) {
+ $dms_id_arr[] = array(
+ 'name' => $doc->name,
+ 'dms_id' => $doc->dms_id
+ );
+ }
+ }
+
+ foreach ($_FILES as $k => $file)
+ {
+ //update(2) alle neuen files (alle außer type application/x.fhc-dms+json) anhängen
+ if($file["type"] == 'application/x.fhc-dms+json')
+ {
+ $dms_uploaded[] = array(
+ 'name' => $file["name"]
+ );
+ }
+ else
+ {
+ $dms = array(
+ 'kategorie_kurzbz' => 'notiz',
+ 'version' => 0,
+ 'name' => $file["name"],
+ 'mimetype' => $file["type"],
+ 'insertamum' => date('c'),
+ 'insertvon' => $uid
+ );
+
+ //Todo(manu) check if filetypes weiter eingeschränkt werden sollen
+ //Todo(manu)check name files: nicht gleiches file 2mal hochladen
+ $result = $this->dmslib->upload($dms, $k, array('*'));
+
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $dms_id = $result->retval['dms_id'];
+
+ $result = $this->NotizdokumentModel->insert(array('notiz_id' => $notiz_id, 'dms_id' => $dms_id));
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ }
+ }
+
+ //update(3) check if Dateien gelöscht wurden
+ if(count($dms_uploaded) != count($dms_id_arr))
+ {
+ if (count($dms_uploaded) == 0)
+ {
+ $filesDeleted = $dms_id_arr;
+ }
+ else
+ {
+ $upload_new_names = array_column($dms_uploaded, "name");
+
+ $filesDeleted = array_filter($dms_id_arr, function ($file) use ($upload_new_names) {
+ return !in_array($file["name"], $upload_new_names);
+ });
+ }
+
+ foreach ($filesDeleted as $file)
+ {
+ $result = $this->dmslib->removeAll($file['dms_id']);
+
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ else
+ $this->outputJson($result);
+ }
+ }
+ return $this->terminateWithSuccess($result);
+ }*/
+
+
+/* public function deleteNotiz()
+ {
+ $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
+ $notiz_id = $this->input->post('notiz_id');
+ $type = $this->input->post('type_id');
+ $id = $this->input->post('id');
+
+ //dms_id auslesen aus notizdokument wenn vorhanden
+ $dms_id_arr = [];
+ $this->load->model('person/Notizdokument_model', 'NotizdokumentModel');
+
+ $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id));
+
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ if(hasData($result))
+ {
+ $result = getData($result);
+ foreach ($result as $doc) {
+ $dms_id_arr[] = $doc->dms_id;
+ }
+ }
+
+ if($dms_id_arr)
+ {
+ $this->load->library('DmsLib');
+ foreach($dms_id_arr as $dms_id)
+ {
+ $result = $this->dmslib->removeAll($dms_id);
+
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ $this->outputJson($result);
+ }
+ }
+
+ //delete Notizzuordnung
+ if($type == "software_id")
+ {
+ // Loads extension Model
+ $this->load->model('extensions/FHC-Core-Softwarebereitstellung/Softwarenotizzuordnung_model', 'ExtensionnotizzuordnungModel');
+ $result = $this->ExtensionnotizzuordnungModel->delete([
+ 'notiz_id' => $notiz_id,
+ 'id' => strval($id)
+ ],
+ [
+ 'type_id' => $type
+ ]);
+
+ }
+ else
+ {
+ //notizzuordnungsid!
+ $result = $this->NotizzuordnungModel->delete(['notiz_id' => $notiz_id, $type => $id]);
+ }
+
+
+ $this->load->model('person/Notiz_model', 'NotizModel');
+ //$this->NotizModel->addJoin('public.tbl_notizzuordnung', 'notiz_id');
+
+ //TODO (erweitern um Type_id) für Extensions, damit auch Notizzuordnung gelöscht werden kann
+
+ //Löschen von Notiz
+ $result = $this->NotizModel->delete(
+ array('notiz_id' => $notiz_id)
+ );
+
+ if (isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ if(!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ return $this->terminateWithSuccess(current(getData($result)));
+ }*/
+
+/* public function loadDokumente()
+ {
+ $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
+ $notiz_id = $this->input->post('notiz_id');
+
+ $this->NotizModel->addSelect('campus.tbl_dms_version.*');
+
+ $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'ON (public.tbl_notiz_dokument.notiz_id = public.tbl_notiz.notiz_id)');
+ $this->NotizModel->addJoin('campus.tbl_dms_version', 'ON (public.tbl_notiz_dokument.dms_id = campus.tbl_dms_version.dms_id)');
+
+ $result = $this->NotizModel->loadWhere(
+ array('public.tbl_notiz.notiz_id' => $notiz_id)
+ );
+ if (isError($result)) {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+
+ if(!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result));
+ }*/
+
+/* public function getMitarbeiter($searchString)
+ {
+ $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
+ $result = $this->MitarbeiterModel->searchMitarbeiter($searchString);
+ if (isError($result)) {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess($result);
+ }*/
+
+ public function isBerechtigt($id, $typeId)
+ {
+ if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid'))
+ {
+ $result = $this->p->t('lehre','error_keineSchreibrechte');
+
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ return success("berechtigt in überschreibender Funktion");
+/* return $this->terminateWithError('keine Berechtigung bro', self::ERROR_TYPE_GENERAL);*/
+ }
+
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/stv/Prestudent.php b/application/controllers/api/frontend/v1/stv/Prestudent.php
new file mode 100644
index 000000000..ef9aeb111
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Prestudent.php
@@ -0,0 +1,299 @@
+ ['admin:r', 'assistenz:r'],
+ 'updatePrestudent' => ['admin:rw', 'assistenz:rw'],
+ 'getHistoryPrestudents' => ['admin:r', 'assistenz:r'],
+ 'getBezeichnungZGV' => ['admin:r', 'assistenz:r'],
+ 'getBezeichnungDZgv' => ['admin:r', 'assistenz:r'],
+ 'getBezeichnungMZgv' => ['admin:r', 'assistenz:r'],
+ 'getAusbildung' => ['admin:r', 'assistenz:r'],
+ 'getAufmerksamdurch' => ['admin:r', 'assistenz:r'],
+ 'getBerufstaetigkeit' => ['admin:r', 'assistenz:r'],
+ 'getTypenStg' => ['admin:r', 'assistenz:r'],
+ 'getStudienplaene' => ['admin:r', 'assistenz:r'],
+ 'getStudiengang' => ['admin:r', 'assistenz:r']
+ ]);
+
+ if ($this->router->method == 'updatePrestudent') {
+ $prestudent_id = current(array_slice($this->uri->rsegments, 2));
+ $this->checkPermissionsForPrestudent($prestudent_id, ['admin:rw', 'assistenz:rw']);
+ } elseif ($this->router->method == 'get'
+ || $this->router->method == 'getStudienplaene'
+ || $this->router->method == 'getStudiengang'
+ ) {
+ $prestudent_id = current(array_slice($this->uri->rsegments, 2));
+ $this->checkPermissionsForPrestudent($prestudent_id, ['admin:r', 'assistenz:r']);
+ } elseif ($this->router->method == 'getHistoryPrestudents') {
+ $person_id = current(array_slice($this->uri->rsegments, 2));
+ $this->checkPermissionsForPerson($person_id, ['admin:r', 'assistenz:r'], ['admin:r', 'assistenz:r']);
+ }
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui', 'studierendenantrag', 'lehre'
+ ]);
+ }
+
+ public function get($prestudent_id)
+ {
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ $this->PrestudentModel->addSelect('*');
+ $result = $this->PrestudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
+
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ if(!hasData($result))
+ {
+ return show_404();
+ }
+ $this->terminateWithSuccess(current(getData($result)));
+ }
+
+ public function updatePrestudent($prestudent_id)
+ {
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ // UDF
+ $this->load->library('UDFLib');
+
+ $result = $this->udflib->getCiValidations($this->PrestudentModel, $this->input->post());
+ $udf_field_validations = $this->getDataOrTerminateWithError($result);
+
+ //Form validation
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules($udf_field_validations);
+
+ $this->form_validation->set_rules('priorisierung', 'Priorisierung', 'numeric', [
+ 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Priorisierung'])
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $uid = getAuthUID();
+
+ $array_allowed_props_prestudent = [
+ 'aufmerksamdurch_kurzbz',
+ 'studiengang_kz',
+ 'gsstudientyp_kurzbz',
+ 'person_id',
+ 'berufstaetigkeit_code',
+ 'ausbildungcode',
+ 'zgv_code',
+ 'zgvort',
+ 'zgvdatum',
+ 'zgvnation',
+ 'zgvmas_code',
+ 'zgvmaort',
+ 'zgvmadatum',
+ 'zgvmanation',
+ 'facheinschlberuf',
+ 'bismelden',
+ 'anmerkung',
+ 'dual',
+ 'zgvdoktor_code',
+ 'zgvdoktorort',
+ 'zgvdoktordatum',
+ 'zgvdoktornation',
+ 'aufnahmegruppe_kurzbz',
+ 'priorisierung',
+ 'foerderrelevant',
+ 'zgv_erfuellt',
+ 'zgvmas_erfuellt',
+ 'zgvdoktor_erfuellt',
+ 'mentor',
+ 'aufnahmeschluessel',
+ 'standort_code'
+ ];
+
+ // add UDFs
+ $result = $this->udflib->getDefinitionForModel($this->PrestudentModel);
+
+ $definitions = $this->getDataOrTerminateWithError($result);
+
+ foreach ($definitions as $def)
+ $array_allowed_props_prestudent[] = $def['name'];
+
+ $update_prestudent = array();
+ foreach ($array_allowed_props_prestudent as $prop)
+ {
+ $val = $this->input->post($prop);
+ if ($val !== null || $prop == 'foerderrelevant') {
+ $update_prestudent[$prop] = $val;
+ }
+ }
+
+ $update_prestudent['updateamum'] = date('c');
+ $update_prestudent['updatevon'] = $uid;
+
+ if (count($update_prestudent))
+ {
+ $result = $this->PrestudentModel->update(
+ $prestudent_id,
+ $update_prestudent
+ );
+ $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess(true);
+ }
+ return $this->terminateWithSuccess(false);
+ }
+
+ public function getHistoryPrestudents($person_id)
+ {
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ $result = $this->PrestudentModel->getHistoryPrestudents($person_id);
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getBezeichnungZGV()
+ {
+ $this->load->model('codex/Zgv_model', 'ZgvModel');
+
+ $this->ZgvModel->addOrder('zgv_code');
+
+ $result = $this->ZgvModel->load();
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getBezeichnungDZgv()
+ {
+ $this->load->model('codex/Zgvdoktor_model', 'ZgvdoktorModel');
+
+ $this->ZgvdoktorModel->addOrder('zgvdoktor_code');
+
+ $result = $this->ZgvdoktorModel->load();
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getBezeichnungMZgv()
+ {
+ $this->load->model('codex/Zgvmaster_model', 'ZgvmasterModel');
+
+ $this->ZgvmasterModel->addOrder('zgvmas_code');
+
+ $result = $this->ZgvmasterModel->load();
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getAusbildung()
+ {
+ $this->load->model('codex/Ausbildung_model', 'AusbildungModel');
+
+ $this->AusbildungModel->addOrder('ausbildungcode');
+
+ $result = $this->AusbildungModel->load();
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getAufmerksamdurch()
+ {
+ $this->load->model('codex/Aufmerksamdurch_model', 'AufmerksamdurchModel');
+
+ $this->AufmerksamdurchModel->addOrder('aufmerksamdurch_kurzbz');
+
+ $result = $this->AufmerksamdurchModel->load();
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getBerufstaetigkeit()
+ {
+ $this->load->model('codex/Berufstaetigkeit_model', 'BerufstaetigkeitModel');
+
+ $this->BerufstaetigkeitModel->addOrder('berufstaetigkeit_code');
+
+ $result = $this->BerufstaetigkeitModel->load();
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getTypenStg()
+ {
+ $this->load->model('education/Gsstudientyp_model', 'GsstudientypModel');
+
+ $this->GsstudientypModel->addOrder('gsstudientyp_kurzbz');
+
+ $result = $this->GsstudientypModel->load();
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+ public function getStudienplaene($prestudent_id)
+ {
+ $this->load->model('organisation/Studienplan_model', 'StudienplanModel');
+ $result = $this->StudienplanModel->getStudienplaeneByPrestudents($prestudent_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * Gets details for the Studiengang of the Prestudent
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function getStudiengang($prestudent_id)
+ {
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ $this->PrestudentModel->addSelect('stg.*');
+
+ $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz');
+
+ $result = $this->PrestudentModel->load($prestudent_id);
+
+ $stg = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess(current($stg));
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Status.php b/application/controllers/api/frontend/v1/stv/Status.php
new file mode 100644
index 000000000..074f4029e
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Status.php
@@ -0,0 +1,1753 @@
+ ['admin:r', 'assistenz:r'],
+ 'getMaxSemester' => ['admin:r', 'assistenz:r'],
+ 'changeStatus' => ['admin:rw', 'assistenz:rw'],
+ 'addStudent' => ['admin:rw', 'assistenz:rw'],
+ 'getStatusgruende' => self::PERM_LOGGED,
+ 'getLastBismeldestichtag' => self::PERM_LOGGED,
+ 'isLastStatus' => self::PERM_LOGGED,
+ 'getStatusarray' => self::PERM_LOGGED,
+ 'deleteStatus' => ['admin:rw','assistenz:rw'],
+ 'loadStatus' => ['admin:r', 'assistenz:r'],
+ 'insertStatus' => ['admin:rw', 'assistenz:rw'],
+ 'updateStatus' => ['admin:rw', 'assistenz:rw'],
+ 'advanceStatus' => ['admin:rw', 'assistenz:rw'],
+ 'confirmStatus' => ['admin:rw', 'assistenz:rw'],
+
+ ]);
+
+ //Load Models
+ $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
+ $this->load->model('person/Person_model', 'PersonModel');
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ $this->load->library('PrestudentstatusCheckLib');
+
+ // Additional Permission Checks
+ if ($this->router->method == 'insertStatus'
+ || $this->router->method == 'updateStatus'
+ || $this->router->method == 'confirmStatus'
+ || $this->router->method == 'deleteStatus'
+ || $this->router->method == 'advanceStatus'
+ || $this->router->method == 'changeStatus'
+ || $this->router->method == 'addStudent'
+ ) {
+ $prestudent_id = current(array_slice($this->uri->rsegments, 2));
+ $this->checkPermissionsForPrestudent($prestudent_id, ['admin:rw', 'assistenz:rw']);
+ }
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'global', 'ui', 'bismeldestichtag','lehre','studierendenantrag'
+ ]);
+ }
+
+ public function getHistoryPrestudent($prestudent_id)
+ {
+ $result = $this->PrestudentstatusModel->getHistoryPrestudent($prestudent_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * Gets the maximum possible semester for one or more Studiengaenge.
+ * If there are more than one Studiengang each maximum is calculated and
+ * the smallest result is returned.
+ *
+ * @return void
+ */
+ public function getMaxSemester()
+ {
+ $studiengang_kzs = $this->input->post('studiengang_kzs');
+
+ if (!$studiengang_kzs || !is_array($studiengang_kzs)) {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('studiengang_kzs', '', 'required|is_null', [
+ 'is_null' => $this->p->t('ui', 'error_fieldMustBeArray')
+ ]);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+
+ if (defined('VORRUECKUNG_STATUS_MAX_SEMESTER') && VORRUECKUNG_STATUS_MAX_SEMESTER == false)
+ $this->terminateWithSuccess(100);
+
+ $this->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
+
+ $result = $this->LehrverbandModel->getMaxSemester($studiengang_kzs);
+
+ $maxsem = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($maxsem ? current($maxsem)->maxsem : 10);
+ }
+
+ public function getStatusgruende()
+ {
+ $this->load->model('crm/Statusgrund_model', 'StatusgrundModel');
+
+ $result = $this->StatusgrundModel->getAktiveGruende();
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getLastBismeldestichtag()
+ {
+ $this->load->model('codex/Bismeldestichtag_model', 'BismeldestichtagModel');
+
+ $result = $this->BismeldestichtagModel->getLastReachedMeldestichtag();
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function isLastStatus($prestudent_id)
+ {
+ $result = $this->PrestudentstatusModel->checkIfLastStatusEntry($prestudent_id);
+
+ $result = $this->getDataOrTerminateWithError($result);
+
+ return $this->terminateWithSuccess($result);
+ }
+
+ public function getStudiensemesterOfStatus($prestudent_id, $status)
+ {
+ $result = $this->PrestudentstatusModel->loadWhere([
+ "prestudent_id" => $prestudent_id,
+ "status_kurzbz" => $status
+ ]);
+ $this->PrestudentstatusModel->addLimit(1);
+ if (isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ $studiensem = current(getData($result));
+
+ return $studiensem->studiensemester_kurzbz;
+ }
+
+ public function getStatusarray()
+ {
+ $this->load->model('crm/Status_model', 'StatusModel');
+ $result = $this->StatusModel->getAllStatiWithStatusgruende();
+
+ if(isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * Changes the status of a prestudent with full additional logic.
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function changeStatus($prestudent_id)
+ {
+ $isBerechtigtNoStudstatusCheck = $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung');
+
+ //GET lastStatus
+ $result = $this->PrestudentstatusModel->getLastStatus($prestudent_id);
+
+ $lastStatusData = $this->getDataOrTerminateWithError($result);
+ $lastStatusData = current($lastStatusData);
+
+ $this->load->model('person/Person_model', 'PersonModel');
+ $this->PersonModel->addJoin('public.tbl_prestudent', 'person_id');
+ $result = $this->PersonModel->loadWhere(['prestudent_id' => $prestudent_id]);
+ $prestudent_person = $this->getDataOrTerminateWithError($result);
+ $prestudent_person = current($prestudent_person);
+
+ $studentName = trim($prestudent_person->vorname . ' ' . $prestudent_person->nachname);
+
+ $status_kurzbz = $this->input->post('status_kurzbz');
+
+ $studiensemester_kurzbz = $lastStatusData->studiensemester_kurzbz;
+ if ($status_kurzbz == Prestudentstatus_model::STATUS_ABSOLVENT
+ || $status_kurzbz == Prestudentstatus_model::STATUS_DIPLOMAND
+ ) {
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
+ }
+
+ $ausbildungssemester = $lastStatusData->ausbildungssemester;
+ if ($status_kurzbz == Prestudentstatus_model::STATUS_STUDENT) {
+ $ausbildungssemester = $this->input->post('ausbildungssemester');
+ }
+
+ $statusgrund_id = $this->input->post('statusgrund_id');
+ $datum_string = date('c');
+ $datum = new DateTime($datum_string);
+
+ //Form Validation
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules(
+ 'status_kurzbz',
+ $this->p->t('global', 'status'),
+ [
+ 'required',
+ //Check Reihungstest
+ ['reihungstest_check', function ($value) use ($prestudent_person) {
+ if (!REIHUNGSTEST_CHECK)
+ return true;
+ if ($value != Prestudentstatus_model::STATUS_BEWERBER)
+ return true;
+ $result = $this->prestudentstatuschecklib->checkIfAngetreten($prestudent_person);
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ //Check ZGV
+ ['checkIfZGV', function ($value) use ($prestudent_person) {
+ if (defined("ZGV_CHECK") && !ZGV_CHECK)
+ return true;
+ if ($value != Prestudentstatus_model::STATUS_BEWERBER)
+ return true;
+ $result = $this->prestudentstatuschecklib->checkIfZGVEingetragen($prestudent_person);
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ //Check ZGV Master
+ ['checkIfZGVMaster', function ($value) use ($prestudent_person) {
+ if (defined("ZGV_CHECK") && !ZGV_CHECK)
+ return true;
+ if ($value != Prestudentstatus_model::STATUS_BEWERBER)
+ return true;
+ $result = $this->prestudentstatuschecklib->checkIfZGVEingetragenMaster($prestudent_person);
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ //Check Bewerberstatus
+ ['checkIfExistingBewerberstatus', function ($value) use ($prestudent_id) {
+ if ($value != Prestudentstatus_model::STATUS_AUFGENOMMENER
+ && $value != Prestudentstatus_model::STATUS_WARTENDER
+ )
+ return true;
+ $result = $this->prestudentstatuschecklib->checkIfExistingBewerberstatus($prestudent_id);
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ //Check If Student
+ ['status_stud_exists', function ($value) use ($prestudent_id) {
+ if ($value != Prestudentstatus_model::STATUS_STUDENT
+ && $value != Prestudentstatus_model::STATUS_ABBRECHER
+ )
+ return true; // Only test if new status is Student
+
+ $result = $this->prestudentstatuschecklib->checkIfExistingStudent($prestudent_id);
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ],
+ [
+ 'reihungstest_check' => $this->p->t('lehre', 'error_keinReihungstestverfahren', ['name' => $studentName]),
+ 'checkIfExistingBewerberstatus' => $this->p->t('lehre', 'error_keinBewerber', ['name' => $studentName]),
+ 'checkIfZGV' => $this->p->t('lehre', 'error_ZGVNichtEingetragen', ['name' => $studentName]),
+ 'checkIfZGVMaster' => $this->p->t('lehre', 'error_ZGVMasterNichtEingetragen', ['name' => $studentName]),
+ 'status_stud_exists' => $this->p->t('lehre', 'error_noStudstatus')
+ ]
+ );
+
+ if ($status_kurzbz == Prestudentstatus_model::STATUS_STUDENT)
+ $this->form_validation->set_rules('ausbildungssemester', $this->p->t('lehre', 'ausbildungssemester'), 'required|integer', [
+ 'integer' => $this->p->t('ui', 'error_fieldNotInteger')
+ ]);
+ else
+ $this->form_validation->set_rules('ausbildungssemester', $this->p->t('lehre', 'ausbildungssemester'), 'integer', [
+ 'integer' => $this->p->t('ui', 'error_fieldNotInteger')
+ ]);
+
+ $this->form_validation->set_rules('statusgrund_id', $this->p->t('international', 'grund'), 'integer', [
+ 'integer' => $this->p->t('ui', 'error_fieldNotInteger')
+ ]);
+
+ $this->form_validation->set_rules('_default', '', [
+ ['meldestichtag_not_exceeded', function () use ($datum, $isBerechtigtNoStudstatusCheck) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+
+ $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($datum);
+
+ return !$this->getDataOrTerminateWithError($result);
+ }],
+ //Check if Rolle already exists
+ ['rolle_doesnt_exist', function () use ($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester) {
+ if (!$status_kurzbz || !$studiensemester_kurzbz || !$ausbildungssemester)
+ return true; // Error will be handled by the required statements above
+
+ $result = $this->PrestudentstatusModel->load([$ausbildungssemester, $studiensemester_kurzbz, $status_kurzbz, $prestudent_id]);
+
+ return !$this->getDataOrTerminateWithError($result);
+ }],
+ ['history_timesequence', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz)
+ return true; // Error will be handled by the required statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryTimesequence(
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_laststatus', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz)
+ return true; // Error will be handled by the required statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryLaststatus(
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_unterbrecher', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz)
+ return true; // Error will be handled by the required statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryUnterbrechersemester(
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_abbrecher', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz)
+ return true; // Error will be handled by the required statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryAbbrechersemester(
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_diplomant', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz)
+ return true; // Error will be handled by the required statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryDiplomant(
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }]
+ ], [
+ 'meldestichtag_not_exceeded' => $this->p->t('lehre', 'error_dataVorMeldestichtag'),
+ 'rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhandenMitNamen', ['name' => $studentName]),
+ 'history_timesequence' => $this->p->t('lehre', 'error_statuseintrag_zeitabfolge'),
+ 'history_laststatus' => $this->p->t('lehre', 'error_endstatus'),
+ 'history_unterbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecher'),
+ 'history_abbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecherAbbrecher'),
+ 'history_diplomant' => $this->p->t('lehre', 'error_consecutiveDiplomandStudent')
+ ]);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ $this->load->library('PrestudentLib');
+
+ $this->db->trans_start();
+
+ switch($status_kurzbz){
+ case Prestudentstatus_model::STATUS_ABBRECHER:
+ $result = $this->prestudentlib->setAbbrecher(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ null,
+ $statusgrund_id,
+ $datum_string,
+ null,
+ null
+ );
+ break;
+ case Prestudentstatus_model::STATUS_UNTERBRECHER:
+ $result = $this->prestudentlib->setUnterbrecher(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ null,
+ null,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ break;
+ case Prestudentstatus_model::STATUS_STUDENT:
+ $result = $this->prestudentlib->setStudent(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ break;
+ case Prestudentstatus_model::STATUS_DIPLOMAND:
+ $result = $this->prestudentlib->setDiplomand(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ break;
+ case Prestudentstatus_model::STATUS_ABSOLVENT:
+ $result = $this->prestudentlib->setAbsolvent(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ break;
+ case Prestudentstatus_model::STATUS_BEWERBER:
+ $result = $this->prestudentlib->setBewerber(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ break;
+ case Prestudentstatus_model::STATUS_AUFGENOMMENER:
+ $result = $this->prestudentlib->setAufgenommener(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ break;
+ case Prestudentstatus_model::STATUS_ABGEWIESENER:
+ $result = $this->prestudentlib->setAbgewiesener(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ break;
+ case Prestudentstatus_model::STATUS_WARTENDER:
+ $result = $this->prestudentlib->setWartender(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ break;
+ default:
+ $this->terminateWithError("Action not yet defined in Prestudentlib", self::ERROR_TYPE_GENERAL);
+ }
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->db->trans_complete();
+
+ $this->terminateWithSuccess($prestudent_id);
+ }
+
+ public function addStudent($prestudent_id)
+ {
+ // Prepare lastAufgenommener Status
+ $this->PrestudentstatusModel->addOrder('datum', 'DESC');
+ $this->PrestudentstatusModel->addOrder('insertamum', 'DESC');
+ $this->PrestudentstatusModel->addLimit(1);
+ $result = $this->PrestudentstatusModel->loadWhere([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_AUFGENOMMENER
+ ]);
+ $lastAufgenommener = $this->getDataOrTerminateWithError($result);
+
+ if ($lastAufgenommener)
+ $lastAufgenommener = current($lastAufgenommener);
+
+ //get studentname for validations
+ $this->load->model('person/Person_model', 'PersonModel');
+ $this->PersonModel->addJoin('public.tbl_prestudent', 'person_id');
+ $result = $this->PersonModel->loadWhere(['prestudent_id' => $prestudent_id]);
+ $prestudent_person = $this->getDataOrTerminateWithError($result);
+ $prestudent_person = current($prestudent_person);
+
+ $studentName = trim($prestudent_person->vorname . ' ' . $prestudent_person->nachname);
+
+
+ //Form Validation
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('statusgrund_id', $this->p->t('international', 'grund'), 'integer', [
+ 'integer' => $this->p->t('ui', 'error_fieldNotInteger')
+ ]);
+
+ $this->form_validation->set_rules('_default', '', [
+ //Check ZGV
+ ['checkIfZGV', function () use ($prestudent_person) {
+ if (defined("ZGV_CHECK") && !ZGV_CHECK)
+ return true;
+ $result = $this->prestudentstatuschecklib->checkIfZGVEingetragen($prestudent_person);
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ //Check ZGV Master
+ ['checkIfZGVMaster', function () use ($prestudent_person) {
+ if (defined("ZGV_CHECK") && !ZGV_CHECK)
+ return true;
+ $result = $this->prestudentstatuschecklib->checkIfZGVEingetragenMaster($prestudent_person);
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ //Check Bewerberstatus
+ ['checkIfExistingBewerberstatus', function () use ($prestudent_id) {
+ $result = $this->prestudentstatuschecklib->checkIfExistingBewerberstatus($prestudent_id);
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ //Check Aufgenommenerstatus
+ ['checkIfExistingAufgenommenerstatus', function () use ($lastAufgenommener) {
+ return !!$lastAufgenommener;
+ }],
+ //Check Bewerberstatus & Aufgenommenerstatus semester
+ ['checkIfLastBewerberAndAufgenommenerShareSemesters', function () use ($prestudent_id) {
+ $result = $this->prestudentstatuschecklib->checkIfLastBewerberAndAufgenommenerShareSemesters($prestudent_id);
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ //Check If FirstStudent
+ ['check_isFirstStudStatus', function () use ($prestudent_id) {
+ $result = $this->prestudentstatuschecklib->checkIfExistingStudent($prestudent_id);
+
+ return !$this->getDataOrTerminateWithError($result);
+ }],
+ //Check if Rolle already exists
+ ['rolle_doesnt_exist', function () use ($prestudent_id, $lastAufgenommener) {
+ if (!$lastAufgenommener)
+ return true; // Error will be handled by the checkIfExistingAufgenommenerstatus statement above
+
+ $result = $this->PrestudentstatusModel->loadWhere([
+ 'studiensemester_kurzbz' => $lastAufgenommener->studiensemester_kurzbz,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_STUDENT,
+ 'prestudent_id' => $prestudent_id
+ ]);
+
+ return !$this->getDataOrTerminateWithError($result);
+ }]
+ ], [
+ 'reihungstest_check' => $this->p->t('lehre', 'error_keinReihungstestverfahren', ['name' => $studentName]),
+ 'checkIfExistingBewerberstatus' => $this->p->t('lehre', 'error_keinBewerber', ['name' => $studentName]),
+ 'checkIfExistingAufgenommenerstatus' => $this->p->t('lehre', 'error_keinAufgenommener', ['name' => $studentName]),
+ 'checkIfLastBewerberAndAufgenommenerShareSemesters' => $this->p->t('lehre', 'error_lastBewerberAndAufgenommenerSemesters'),
+ 'checkIfZGV' => $this->p->t('lehre', 'error_ZGVNichtEingetragen', ['name' => $studentName]),
+ 'checkIfZGVMaster' => $this->p->t('lehre', 'error_ZGVMasterNichtEingetragen', ['name' => $studentName]),
+ 'check_isFirstStudStatus' => $this->p->t('lehre', 'error_personBereitsStudent', ['name' => $studentName]),
+ 'rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhandenMitNamen', ['name' => $studentName])
+ ]);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ // Start DB transaction
+ $this->db->trans_start();
+
+ $this->load->library('PrestudentLib');
+
+ $this->prestudentlib->setFirstStudent(
+ $prestudent_id,
+ $lastAufgenommener->studiensemester_kurzbz,
+ $lastAufgenommener->ausbildungssemester,
+ $lastAufgenommener->orgform_kurzbz,
+ $lastAufgenommener->studienplan_id,
+ $this->input->post('statusgrund_id')
+ );
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->db->trans_commit();
+
+ return $this->outputJsonSuccess(true);
+ }
+
+ public function loadStatus()
+ {
+ $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
+
+ $prestudent_id = $this->input->post('prestudent_id');
+ $status_kurzbz = $this->input->post('status_kurzbz');
+ $ausbildungssemester = $this->input->post('ausbildungssemester');
+ $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
+
+ $result = $this->PrestudentstatusModel->loadWhere(
+ array(
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => $status_kurzbz,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ )
+ );
+ if (isError($result))
+ {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+
+ elseif (!hasData($result))
+ {
+ $this->terminateWithError($this->p->t('lehre', 'error_noStatusFound'), self::ERROR_TYPE_GENERAL);
+ }
+ else
+ {
+ $this->terminateWithSuccess(current(getData($result)));
+ }
+ }
+
+ /**
+ * Delete a status entry
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param string $studiensemester_kurzbz
+ * @param integer $ausbildungssemester
+ *
+ * @return void
+ */
+ public function deleteStatus($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester)
+ {
+ $result = $this->PrestudentstatusModel->load([
+ $ausbildungssemester,
+ $studiensemester_kurzbz,
+ $status_kurzbz,
+ $prestudent_id
+ ]);
+ $oldstatus = $this->getDataOrTerminateWithError($result);
+ if (!$oldstatus)
+ show_404(); // Status that should be updated does not exist
+
+ $oldstatus = current($oldstatus);
+
+
+ $erweiterteBerechtigung =
+ $this->permissionlib->isBerechtigt('admin', null, 'suid')
+ || $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung', null, 'suid');
+
+
+ //check if last status
+ $result = $this->PrestudentstatusModel->checkIfLastStatusEntry($prestudent_id);
+
+ $result = $this->getDataOrTerminateWithError($result);
+
+ $deletePrestudent = $result;
+
+
+ //Berechtigungen nach Check prüfen!
+ if (!$erweiterteBerechtigung) {
+ if ($status_kurzbz == Prestudentstatus_model::STATUS_STUDENT)
+ $this->terminateWithError(
+ $this->p->t('lehre', 'error_onlyAdminDeleteRolleStudent'),
+ self::ERROR_TYPE_GENERAL,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+
+ if ($deletePrestudent)
+ $this->terminateWithError(
+ $this->p->t('lehre', 'error_onlyAdminDeleteLastStatus'),
+ self::ERROR_TYPE_GENERAL,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+
+ $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($oldstatus->datum);
+
+ if (!$this->getDataOrTerminateWithError($result))
+ $this->terminateWithError(
+ $this->p->t('lehre', 'error_dataVorMeldestichtag'),
+ self::ERROR_TYPE_GENERAL,
+ REST_Controller::HTTP_FORBIDDEN
+ );
+ }
+
+ // Start DB transaction
+ $this->db->trans_begin();
+
+ //Delete Status
+ $result = $this->PrestudentstatusModel->delete(
+ [
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => $status_kurzbz,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ ]
+ );
+
+ $this->getDataOrTerminateWithError($result);
+
+ //Delete Studentlehrverband if no Status left in this semester
+ $result = $this->PrestudentstatusModel->checkIfLastStatusEntry($prestudent_id, $studiensemester_kurzbz);
+
+ $result = $this->getDataOrTerminateWithError($result);
+ if ($result)
+ {
+ //get student_uid
+ $this->load->model('crm/Student_model', 'StudentModel');
+ $result = $this->StudentModel->loadWhere([
+ 'prestudent_id' => $prestudent_id
+ ]);
+
+ $student = $this->getDataOrTerminateWithError($result);
+ if ($student)
+ {
+ $student = current($student);
+ $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel');
+ $result = $this->StudentlehrverbandModel->delete(
+ array(
+ 'student_uid' => $student->student_uid,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ )
+ );
+
+ $this->getDataOrTerminateWithError($result);
+ }
+ }
+
+ //Delete Prestudent if no data is left
+ if ($deletePrestudent)
+ {
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+ $result = $this->PrestudentModel->delete($prestudent_id);
+
+ $this->getDataOrTerminateWithError($result);
+ }
+
+ $this->db->trans_commit();
+
+ return $this->terminateWithSuccess(true);
+ }
+
+ /**
+ * Inserts a status with less validations and extra logic for manual
+ * manipulation
+ *
+ * @param integer $prestudent_id
+ *
+ * @return void
+ */
+ public function insertStatus($prestudent_id)
+ {
+ $isBerechtigtNoStudstatusCheck = $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung');
+ $isBerechtigtBasisPrestudentstatus = $this->permissionlib->isBerechtigt('basis/prestudentstatus');
+
+
+ $authUID = getAuthUID();
+ $status_kurzbz = $this->input->post('status_kurzbz');
+ $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
+ $ausbildungssemester = $this->input->post('ausbildungssemester');
+ $datum = $this->input->post('datum');
+ $bestaetigtam = $this->input->post('bestaetigtam');
+ $orgform_kurzbz = $this->input->post('orgform_kurzbz');
+ $anmerkung = $this->input->post('anmerkung');
+ $bewerbung_abgeschicktamum = $this->input->post('bewerbung_abgeschicktamum');
+ $studienplan_id = $this->input->post('studienplan_id');
+ $rt_stufe = $this->input->post('rt_stufe');
+ $statusgrund_id = $this->input->post('statusgrund_id');
+
+
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('statusgrund_id', $this->p->t('international', 'grund'), 'integer', [
+ 'integer' => $this->p->t('ui', 'error_fieldNotInteger')
+ ]);
+
+ if (!$isBerechtigtBasisPrestudentstatus)
+ $this->form_validation->set_rules(
+ 'bewerbung_abgeschicktamum',
+ $this->p->t('lehre', 'bewerbung_abgeschickt_am'),
+ 'is_null',
+ [
+ 'is_null' => $this->p->t('ui', 'error_fieldWriteAccess')
+ ]
+ );
+
+ $this->form_validation->set_rules(
+ 'datum',
+ $this->p->t('global', 'datum'),
+ [
+ 'required', // In FAS empty datum results in todays
+ 'is_valid_date',
+ ['is_date_not_before_today', function ($value) {
+ if (!is_valid_date($value))
+ return true; // Error will be handled by the is_valid_date statement above
+ $today = new DateTime('today');
+ return (new DateTime($value) >= $today);
+ }],
+ ['meldestichtag_not_exceeded', function ($value) use ($isBerechtigtNoStudstatusCheck) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$value)
+ return true; // Error will be handled by the required statement above
+
+ $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($value);
+
+ return !$this->getDataOrTerminateWithError($result);
+ }]
+ ],
+ [
+ 'meldestichtag_not_exceeded' => $this->p->t('lehre', 'error_dataVorMeldestichtag'),
+ 'is_date_not_before_today' => $this->p->t('lehre', 'error_entryInPast')
+ ]
+ );
+
+ $this->form_validation->set_rules(
+ 'status_kurzbz',
+ $this->p->t('lehre', 'status_rolle'),
+ [
+ 'required',
+ ['status_stud_exists', function ($value) use ($prestudent_id) {
+ if ($value != Prestudentstatus_model::STATUS_STUDENT)
+ return true; // Only test if new status is Student
+
+ $result = $this->prestudentstatuschecklib->checkIfExistingStudent($prestudent_id);
+
+ return $this->getDataOrTerminateWithError($result);
+ }]
+ ],
+ [
+ 'status_stud_exists' => $this->p->t('lehre', 'error_noStudstatus')
+ ]
+ );
+
+ $this->form_validation->set_rules('studiensemester_kurzbz', $this->p->t('lehre', 'studiensemester'), 'required');
+
+ $this->form_validation->set_rules('ausbildungssemester', $this->p->t('lehre', 'ausbildungssemester'), 'required');
+
+ $this->form_validation->set_rules('bestaetigtam', $this->p->t('lehre', 'bestaetigt_am'), 'is_valid_date');
+
+ // Set Datum to null to prevent multiple is_valid_date checks in the following validation rules
+ if (!$datum || !is_valid_date($datum))
+ $datum = null;
+
+ $this->form_validation->set_rules('_default', '', [
+ ['rolle_doesnt_exist', function () use ($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester) {
+ if (!$status_kurzbz || !$studiensemester_kurzbz || !$ausbildungssemester)
+ return true; // Error will be handled by the required statements above
+
+ $result = $this->PrestudentstatusModel->load([$ausbildungssemester, $studiensemester_kurzbz, $status_kurzbz, $prestudent_id]);
+
+ return !$this->getDataOrTerminateWithError($result);
+ }],
+ ['history_timesequence', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester)
+ return true; // Error will be handled by the required statements above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryTimesequence(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_laststatus', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester)
+ return true; // Error will be handled by the required statements above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryLaststatus(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_unterbrecher', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester)
+ return true; // Error will be handled by the required statements above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryUnterbrechersemester(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_abbrecher', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester)
+ return true; // Error will be handled by the required statements above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryAbbrechersemester(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_diplomant', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$status_kurzbz || !$datum || !$studiensemester_kurzbz || !$ausbildungssemester)
+ return true; // Error will be handled by the required statements above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryDiplomant(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ '',
+ ''
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }]
+ ], [
+ 'rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhanden'),
+ 'history_timesequence' => $this->p->t('lehre', 'error_statuseintrag_zeitabfolge'),
+ 'history_laststatus' => $this->p->t('lehre', 'error_endstatus'),
+ 'history_unterbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecher'),
+ 'history_abbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecherAbbrecher'),
+ 'history_diplomant' => $this->p->t('lehre', 'error_consecutiveDiplomandStudent')
+ ]);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ // Start DB transaction
+ $this->db->trans_start();
+
+ $this->updateLehrverbandForInsertAndUpdate($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $authUID);
+
+ //insert status
+ $result = $this->PrestudentstatusModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => $status_kurzbz,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'datum' => $datum,
+ 'insertamum' => date('c'),
+ 'insertvon' => $authUID,
+ 'orgform_kurzbz' => $orgform_kurzbz,
+ 'bestaetigtam' => $bestaetigtam,
+ 'bestaetigtvon' => $bestaetigtam ? $authUID : null,
+ 'anmerkung' => $anmerkung,
+ 'bewerbung_abgeschicktamum' => $bewerbung_abgeschicktamum,
+ 'studienplan_id' => $studienplan_id,
+ 'rt_stufe' => $rt_stufe,
+ 'statusgrund_id' => $statusgrund_id
+ ]);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->db->trans_complete();
+
+ $this->terminateWithSuccess(true);
+ }
+
+ /**
+ * Updates a status entry
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param string $key_studiensemester_kurzbz
+ * @param integer $key_ausbildungssemester
+ *
+ * @return void
+ */
+ public function updateStatus($prestudent_id, $status_kurzbz, $key_studiensemester_kurzbz, $key_ausbildungssemester)
+ {
+ $result = $this->PrestudentstatusModel->load([
+ $key_ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $status_kurzbz,
+ $prestudent_id
+ ]);
+ $oldstatus = $this->getDataOrTerminateWithError($result);
+ if (!$oldstatus)
+ show_404(); // Status that should be updated does not exist
+
+ $oldstatus = current($oldstatus);
+
+
+ $isBerechtigtNoStudstatusCheck = $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung');
+ $isBerechtigtBasisPrestudentstatus = $this->permissionlib->isBerechtigt('basis/prestudentstatus');
+
+
+ $authUID = getAuthUID();
+ $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz') ?: $oldstatus->studiensemester_kurzbz;
+ $ausbildungssemester = $this->input->post('ausbildungssemester') ?: $oldstatus->ausbildungssemester;
+ $datum = $this->input->post('datum') ?: $oldstatus->datum;
+
+
+ //Form Validation
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('statusgrund_id', $this->p->t('international', 'grund'), 'integer', [
+ 'integer' => $this->p->t('ui', 'error_fieldNotInteger')
+ ]);
+
+ if (!$isBerechtigtBasisPrestudentstatus)
+ $this->form_validation->set_rules(
+ 'bewerbung_abgeschicktamum',
+ $this->p->t('lehre', 'bewerbung_abgeschickt_am'),
+ 'is_null',
+ [
+ 'is_null' => $this->p->t('ui', 'error_fieldWriteAccess')
+ ]
+ );
+
+ $this->form_validation->set_rules(
+ 'datum',
+ $this->p->t('global', 'datum'),
+ [
+ 'is_valid_date',
+ ['meldestichtag_not_exceeded', function ($value) use ($isBerechtigtNoStudstatusCheck) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$value)
+ return true; // Error will be handled by the required statement above
+
+ $result = $this->prestudentstatuschecklib->checkIfMeldestichtagErreicht($value);
+
+ return !$this->getDataOrTerminateWithError($result);
+ }]
+ ],
+ [
+ 'meldestichtag_not_exceeded' => $this->p->t('lehre', 'error_dataVorMeldestichtag')
+ ]
+ );
+
+ $this->form_validation->set_rules('bestaetigtam', $this->p->t('lehre', 'bestaetigt_am'), 'is_valid_date');
+
+ if (!is_valid_date($datum))
+ $datum = null;
+
+ // Set Datum to null to prevent multiple is_valid_date checks in the following validation rules
+ $this->form_validation->set_rules('_default', '', [
+ //Check if Rolle already exists
+ ['new_rolle_doesnt_exist', function () use (
+ $prestudent_id,
+ $status_kurzbz,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ ) {
+ if ($key_studiensemester_kurzbz == $studiensemester_kurzbz
+ && $key_ausbildungssemester == $ausbildungssemester
+ )
+ return true; // Primary key has not change we update in place
+
+ $result = $this->PrestudentstatusModel->load([
+ $ausbildungssemester,
+ $studiensemester_kurzbz,
+ $status_kurzbz,
+ $prestudent_id
+ ]);
+ return !$this->getDataOrTerminateWithError($result);
+ }],
+ ['history_timesequence', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$datum)
+ return true; // Error will be handled by the is_valid_date statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryTimesequence(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_laststatus', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$datum)
+ return true; // Error will be handled by the is_valid_date statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryLaststatus(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_unterbrecher', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$datum)
+ return true; // Error will be handled by the is_valid_date statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryUnterbrechersemester(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_abbrecher', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$datum)
+ return true; // Error will be handled by the is_valid_date statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryAbbrechersemester(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }],
+ ['history_diplomant', function () use (
+ $isBerechtigtNoStudstatusCheck,
+ $prestudent_id,
+ $status_kurzbz,
+ $datum,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ ) {
+ if ($isBerechtigtNoStudstatusCheck)
+ return true; // Skip if access right says so
+ if (!$datum)
+ return true; // Error will be handled by the is_valid_date statement above
+
+ $result = $this->prestudentstatuschecklib->checkStatusHistoryDiplomant(
+ $prestudent_id,
+ $status_kurzbz,
+ new DateTime($datum),
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $key_ausbildungssemester
+ );
+
+ return $this->getDataOrTerminateWithError($result);
+ }]
+ ], [
+ 'new_rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhanden'),
+ 'history_timesequence' => $this->p->t('lehre', 'error_statuseintrag_zeitabfolge'),
+ 'history_laststatus' => $this->p->t('lehre', 'error_endstatus'),
+ 'history_unterbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecher'),
+ 'history_abbrecher' => $this->p->t('lehre', 'error_consecutiveUnterbrecherAbbrecher'),
+ 'history_diplomant' => $this->p->t('lehre', 'error_consecutiveDiplomandStudent')
+ ]);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ // Start DB transaction
+ $this->db->trans_start();
+
+ $this->updateLehrverbandForInsertAndUpdate($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $authUID);
+
+ //update status
+ $updateData = [
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'datum' => $datum,
+ 'updateamum' => date('c'),
+ 'updatevon' => $authUID
+ ];
+ foreach ([
+ 'orgform_kurzbz',
+ 'anmerkung',
+ 'bewerbung_abgeschicktamum',
+ 'studienplan_id',
+ 'rt_stufe',
+ 'statusgrund_id'
+ ] as $key)
+ if ($this->input->post($key))
+ $updateData[$key] = $this->input->post($key);
+
+ if ($this->input->post('bestaetigtam')) {
+ $updateData['bestaetigtam'] = $this->input->post('bestaetigtam');
+ $updateData['bestaetigtvon'] = $authUID;
+ }
+
+ $result = $this->PrestudentstatusModel->update([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => $status_kurzbz,
+ 'studiensemester_kurzbz' => $key_studiensemester_kurzbz,
+ 'ausbildungssemester' => $key_ausbildungssemester,
+ ], $updateData);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->db->trans_commit();
+
+ return $this->outputJsonSuccess(true);
+ }
+
+ /**
+ * Advances a status entry
+ * must be of type Student, Diplomand or Unterbrecher
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param string $key_studiensemester_kurzbz
+ * @param integer $key_ausbildungssemester
+ *
+ * @return void
+ */
+ public function advanceStatus($prestudent_id, $status_kurzbz, $key_studiensemester_kurzbz, $key_ausbildungssemester)
+ {
+ $result = $this->PrestudentstatusModel->load([
+ $key_ausbildungssemester,
+ $key_studiensemester_kurzbz,
+ $status_kurzbz,
+ $prestudent_id
+ ]);
+ $oldstatus = $this->getDataOrTerminateWithError($result);
+ if (!$oldstatus)
+ show_404(); // Status that should be updated does not exist
+
+ $oldstatus = current($oldstatus);
+
+
+ //Target studiensemester_kurzbz
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+ $result = $this->StudiensemesterModel->getNextFrom($key_studiensemester_kurzbz);
+
+ $studiensemester_kurzbz = $this->getDataOrTerminateWithError($result);
+ $studiensemester_kurzbz = current($studiensemester_kurzbz)->studiensemester_kurzbz;
+
+
+ //Target ausbildungssemester
+ $ausbildungssemester = $key_ausbildungssemester + 1;
+
+
+ //Form Validation
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_data([
+ 'status_kurzbz' => $status_kurzbz
+ ]);
+
+ $this->form_validation->set_rules('status_kurzbz', $this->p->t('lehre', 'status_rolle'), [
+ 'in_list[' .
+ Prestudentstatus_model::STATUS_STUDENT . ',' .
+ Prestudentstatus_model::STATUS_DIPLOMAND . ',' .
+ Prestudentstatus_model::STATUS_UNTERBRECHER . ']',
+ ['status_stud_exists', function ($value) use ($prestudent_id) {
+ if ($value != Prestudentstatus_model::STATUS_STUDENT)
+ return true;
+
+ $result = $this->prestudentstatuschecklib->checkIfExistingStudent($prestudent_id);
+
+ return $this->getDataOrTerminateWithError($result);
+ }]
+ ], [
+ 'status_stud_exists' => $this->p->t('lehre', 'error_noStudstatus')
+ ]);
+
+ $this->form_validation->set_rules('_default', '', [
+ //Check if Rolle already exists
+ ['rolle_doesnt_exist', function () use (
+ $prestudent_id,
+ $status_kurzbz,
+ $studiensemester_kurzbz,
+ $ausbildungssemester
+ ) {
+ $result = $this->PrestudentstatusModel->load([$ausbildungssemester, $studiensemester_kurzbz, $status_kurzbz, $prestudent_id]);
+
+ return !$this->getDataOrTerminateWithError($result);
+ }]
+ ], [
+ 'rolle_doesnt_exist' => $this->p->t('lehre', 'error_rolleBereitsVorhanden')
+ ]);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ // Start DB transaction
+ $this->db->trans_begin();
+
+ $authUID = getAuthUID();
+ $now = date('c');
+
+ //insert prestudentstatus
+ $result = $this->PrestudentstatusModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => $status_kurzbz,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'datum' => $now,
+ 'insertamum' => $now,
+ 'insertvon' => $authUID,
+ 'orgform_kurzbz' => $oldstatus->orgform_kurzbz,
+ 'studienplan_id' => $oldstatus->studienplan_id,
+ 'bestaetigtam' => $now,
+ 'bestaetigtvon' => $authUID,
+ 'anmerkung' => $oldstatus->anmerkung
+ ]);
+
+ $this->getDataOrTerminateWithError($result);
+
+
+ //get student_uid
+ $this->load->model('crm/Student_model', 'StudentModel');
+ $result = $this->StudentModel->loadWhere([
+ 'prestudent_id' => $prestudent_id
+ ]);
+
+ $student = $this->getDataOrTerminateWithError($result);
+
+ if (!$student)
+ $this->terminateWithError($this->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id]));
+ $student = current($student);
+
+
+ //process studentlehrverband
+ $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel');
+ $result = $this->StudentlehrverbandModel->load([
+ $key_studiensemester_kurzbz,
+ $student->student_uid
+ ]);
+
+ $studentlvb = $this->getDataOrTerminateWithError($result);
+ if (!$studentlvb)
+ $this->terminateWithError($this->p->t('lehre', 'error_noStudentlehrverband'));
+
+ //Data of current Semester
+ $studentlvb = current($studentlvb);
+
+
+ $newStudentlvb = [
+ 'student_uid' => $studentlvb->student_uid,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'studiengang_kz' => $studentlvb->studiengang_kz,
+ 'semester' => $studentlvb->semester,
+ 'verband' => $studentlvb->verband,
+ 'gruppe' => $studentlvb->gruppe,
+ 'insertamum' => $now,
+ 'insertvon' => $authUID,
+ 'ext_id' => $studentlvb->ext_id
+
+ ];
+
+
+ $this->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
+
+ $result = $this->LehrverbandModel->load([
+ $student->gruppe,
+ $student->verband,
+ $ausbildungssemester,
+ $student->studiengang_kz
+ ]);
+
+ $lv = $this->getDataOrTerminateWithError($result);
+ if ($lv) {
+ $newStudentlvb['semester'] = $ausbildungssemester;
+ } // If there is no lehrverband just use the same as in the previous studiensemester
+
+
+ //add studentlehrverband
+ $result = $this->StudentlehrverbandModel->insert($newStudentlvb);
+
+ $this->getDataOrTerminateWithError($result);
+
+ $this->db->trans_commit();
+
+ return $this->outputJsonSuccess(true);
+ }
+
+ /**
+ * Confirms a status entry
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param string $key_studiensemester_kurzbz
+ * @param integer $key_ausbildungssemester
+ *
+ * @return void
+ */
+ public function confirmStatus($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester)
+ {
+ $result = $this->PrestudentstatusModel->load([
+ $ausbildungssemester,
+ $studiensemester_kurzbz,
+ $status_kurzbz,
+ $prestudent_id
+ ]);
+ $oldstatus = $this->getDataOrTerminateWithError($result);
+ if (!$oldstatus)
+ show_404(); // Status that should be updated does not exist
+
+ $oldstatus = current($oldstatus);
+
+
+ $authUID = getAuthUID();
+ $now = date('c');
+
+ //Form Validation
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('Status', '', [
+ ['status_not_yet_confirmed', function () use ($oldstatus) {
+ return !$oldstatus->bestaetigtam;
+ }],
+ ['bewerbung_abgeschickt', function () use ($oldstatus) {
+ return !!$oldstatus->bewerbung_abgeschicktamum;
+ }]
+ ], [
+ 'status_not_yet_confirmed' => $this->p->t('lehre', 'error_statusConfirmedYet'),
+ 'bewerbung_abgeschickt' => $this->p->t('lehre', 'error_bewerbungNochNichtAbgeschickt')
+ ]);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+
+ //update status
+ $result = $this->PrestudentstatusModel->update([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => $status_kurzbz,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'ausbildungssemester' => $ausbildungssemester,
+ ], [
+ 'bestaetigtam' => $now,
+ 'bestaetigtvon' => $authUID,
+ 'updateamum' => $now,
+ 'updatevon' => $authUID
+ ]);
+
+ $this->getDataOrTerminateWithError($result);
+
+
+ //Send Message
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ $this->PrestudentModel->addSelect('p.*');
+ $this->PrestudentModel->addSelect('stg.oe_kurzbz');
+ $this->PrestudentModel->addSelect('stg.bezeichnung AS stg_bezeichnung');
+ $this->PrestudentModel->addSelect('stg.email AS stg_email');
+ $this->PrestudentModel->addSelect('plan.orgform_kurzbz');
+ $this->PrestudentModel->addSelect('typ.bezeichnung AS typ_bezeichnung');
+
+ $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
+ $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz');
+ $this->PrestudentModel->addJoin('public.tbl_studiengangstyp typ', 'typ');
+ $this->PrestudentModel->addJoin('public.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+
+ $result = $this->PrestudentModel->load($prestudent_id);
+
+ $studentdata = $this->getDataOrTerminateWithError($result);
+
+ $this->load->library('MessageLib');
+ $result = $this->messagelib->sendMessageUserTemplate(
+ $studentdata->person_id, // receiversPersonId
+ 'MailStatConfirm' . $status_kurzbz, // vorlage
+ [
+ 'anrede' => $studentdata->anrede,
+ 'vorname' => $studentdata->vorname,
+ 'nachname' => $studentdata->nachname,
+ 'typ' => $studentdata->typ_bezeichnung,
+ 'studiengang' => $studentdata->stg_bezeichnung,
+ 'orgform' => $studentdata->orgform_kurzbz ?: $oldstatus->orgform_kurzbz,
+ 'stgMail' => $studentdata->stg_email
+ ], // parseData
+ null, // orgform
+ 1, // TODO
+ $studentdata->oe_kurzbz, // senderOU
+ null, // relationmessage_id
+ MSG_PRIORITY_NORMAL, // priority
+ true // multiPartMime
+ );
+
+
+ $this->terminateWithSuccess(true);
+ }
+
+ /**
+ * Helper function for insertStatus and updateStatus.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param string $studiensemester_kurzbz
+ * @param integer $ausbildungssemester
+ * @param string $authUID
+ *
+ * @return void
+ */
+ private function updateLehrverbandForInsertAndUpdate($prestudent_id, $status_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $authUID)
+ {
+ if (!in_array($status_kurzbz, [
+ Prestudentstatus_model::STATUS_STUDENT,
+ Prestudentstatus_model::STATUS_DIPLOMAND,
+ Prestudentstatus_model::STATUS_ABSOLVENT,
+ Prestudentstatus_model::STATUS_INCOMING,
+ Prestudentstatus_model::STATUS_ABBRECHER,
+ Prestudentstatus_model::STATUS_UNTERBRECHER
+ ]))
+ return; // No Update necessary
+
+ $result = $this->StudentModel->loadWhere([
+ 'prestudent_id' => $prestudent_id
+ ]);
+
+ $student = $this->getDataOrTerminateWithError($result);
+
+ if (!$student)
+ return; // No Update necessary
+
+ $student = current($student);
+
+ $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel');
+ $result = $this->StudentlehrverbandModel->loadWhere([
+ 'student_uid' => $student->student_uid,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ ]);
+
+ $studentlvb = $this->getDataOrTerminateWithError($result);
+
+
+ $this->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
+
+ $this->LehrverbandModel->addLimit(1);
+ $result = $this->LehrverbandModel->load([
+ $student->gruppe,
+ $student->verband,
+ $ausbildungssemester,
+ $student->studiengang_kz
+ ]);
+ $lv = $this->getDataOrTerminateWithError($result);
+
+
+ if ($studentlvb && !$lv)
+ return; // No Update necessary
+
+ if ($studentlvb) // Update current Student-Lehrverband entry
+ $this->StudentlehrverbandModel->update([
+ 'student_uid' => $student->student_uid,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ ], [
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => $ausbildungssemester,
+ 'verband' => $student->verband,
+ 'gruppe' => $student->gruppe,
+ 'updateamum' => date('c'),
+ 'updatevon' => $authUID
+ ]);
+ else // Add new Student-Lehrverband entry
+ $this->StudentlehrverbandModel->insert([
+ 'student_uid' => $student->student_uid,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => $lv ? $ausbildungssemester : $student->semester,
+ 'verband' => $student->verband,
+ 'gruppe' => $student->gruppe,
+ 'insertamum' => date('c'),
+ 'insertvon' => $authUID
+ ]);
+ }
+
+ /**
+ * Helper function for sanitizing Alias Name
+ * replaces empty spaces with underlines
+ *
+ * @param string $str
+ *
+ * @return string
+ */
+ private function _sanitizeAliasName($str)
+ {
+ $str = sanitizeProblemChars($str);
+ return mb_strtolower(str_replace(' ', '_', $str));
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Student.php b/application/controllers/api/frontend/v1/stv/Student.php
new file mode 100644
index 000000000..89c317ae4
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Student.php
@@ -0,0 +1,562 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+use \DateTime as DateTime;
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about a Student
+ * Listens to ajax post calls to change the Student data
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Student extends FHCAPI_Controller
+{
+ /**
+ * Calls the parent's constructor and prepares libraries and phrases
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'get' => ['admin:r', 'assistenz:r'],
+ 'save' => ['admin:rw', 'assistenz:rw'],
+ 'check' => ['admin:rw', 'assistenz:rw'],
+ 'add' => ['admin:rw', 'assistenz:rw'] // TODO(chris): extra permissions
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+
+ if ($this->router->method == 'get'
+ || $this->router->method == 'save'
+ ) {
+ $prestudent_id = current(array_slice($this->uri->rsegments, 2));
+ if ($this->router->method == 'get')
+ $this->checkPermissionsForPrestudent($prestudent_id, ['admin:r', 'assistenz:r']);
+ else
+ $this->checkPermissionsForPrestudent($prestudent_id, ['admin:rw', 'assistenz:rw']);
+ }
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui'
+ ]);
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Get details for a prestudent
+ *
+ * @param string $prestudent_id
+ * @return void
+ */
+ public function get($prestudent_id)
+ {
+ $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
+
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ $this->PrestudentModel->addSelect('p.*');
+ $this->PrestudentModel->addSelect('s.student_uid');
+ $this->PrestudentModel->addSelect('matrikelnr');
+ $this->PrestudentModel->addSelect('b.aktiv');
+ $this->PrestudentModel->addSelect('v.semester');
+ $this->PrestudentModel->addSelect('v.verband');
+ $this->PrestudentModel->addSelect('v.gruppe');
+ $this->PrestudentModel->addSelect('b.alias');
+
+ if (defined('ACTIVE_ADDONS') && strpos(ACTIVE_ADDONS, 'bewerbung') !== false) {
+ $this->PrestudentModel->addSelect(
+ "(
+ SELECT kontakt
+ FROM public.tbl_kontakt
+ WHERE kontakttyp='email'
+ AND person_id=p.person_id
+ AND zustellung
+ ORDER BY kontakt_id
+ LIMIT 1
+ ) AS email_privat",
+ false
+ );
+ }
+
+ $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_benutzer b', 'student_uid = uid', 'LEFT');
+ $this->PrestudentModel->addJoin(
+ 'public.tbl_studentlehrverband v',
+ 'b.uid = v.student_uid AND v.studiensemester_kurzbz = ' . $this->PrestudentModel->escape($studiensemester_kurzbz),
+ 'LEFT'
+ );
+ $this->PrestudentModel->addJoin('public.tbl_person p', 'p.person_id = tbl_prestudent.person_id');
+
+ $result = $this->PrestudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
+
+ $student = $this->getDataOrTerminateWithError($result);
+
+ if (!$student)
+ return show_404();
+
+ $this->terminateWithSuccess(current($student));
+ }
+
+ /**
+ * Saves data to a prestudent
+ *
+ * @param string $prestudent_id
+ * @return void
+ */
+ public function save($prestudent_id)
+ {
+ $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
+
+ $this->load->model('person/Person_model', 'PersonModel');
+ $this->load->model('crm/Student_model', 'StudentModel');
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+ $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel');
+
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'is_valid_date');
+
+ $this->form_validation->set_rules('semester', 'Semester', 'integer');
+
+ $this->load->library('UDFLib');
+
+ $result = $this->udflib->getCiValidations($this->PersonModel, $this->input->post());
+
+ //TODO(Manu) check with Chris: input number not allowed
+ $udf_field_validations = $this->getDataOrTerminateWithError($result);
+
+ $this->form_validation->set_rules($udf_field_validations);
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $result = $this->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
+
+ $student = $this->getDataOrTerminateWithError($result);
+
+ $uid = $student ? current($student)->student_uid : null;
+
+ $result = $this->PrestudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
+
+ $person = $this->getDataOrTerminateWithError($result);
+
+ $person_id = $person ? current($person)->person_id : null;
+
+
+ $array_allowed_props_lehrverband = ['verband', 'semester', 'gruppe'];
+ $update_lehrverband = array();
+ foreach ($array_allowed_props_lehrverband as $prop) {
+ $val = $this->input->post($prop);
+ if ($val !== null) {
+ $update_lehrverband[$prop] = $val;
+ }
+ }
+
+ $array_allowed_props_person = [
+ 'anrede',
+ 'bpk',
+ 'titelpre',
+ 'titelpost',
+ 'nachname',
+ 'vorname',
+ 'vornamen',
+ 'wahlname',
+ 'gebdatum',
+ 'gebort',
+ 'geburtsnation',
+ 'svnr',
+ 'ersatzkennzeichen',
+ 'staatsbuergerschaft',
+ 'matr_nr',
+ 'sprache',
+ 'geschlecht',
+ 'familienstand',
+ 'foto',
+ 'anmerkung',
+ 'homepage'
+ ];
+
+ // add UDFs
+ $result = $this->udflib->getDefinitionForModel($this->PersonModel);
+
+ $definitions = $this->getDataOrTerminateWithError($result);
+
+ foreach ($definitions as $def)
+ $array_allowed_props_person[] = $def['name'];
+
+ $update_person = array();
+ foreach ($array_allowed_props_person as $prop) {
+ $val = $this->input->post($prop);
+ if ($val !== null) {
+ $update_person[$prop] = $val;
+ }
+ }
+
+ $array_allowed_props_student = ['matrikelnr'];
+ $update_student = array();
+ foreach ($array_allowed_props_student as $prop) {
+ $val = $this->input->post($prop);
+ if ($val !== null) {
+ $update_student[$prop] = $val;
+ }
+ }
+
+ // Check PKs
+ if (count($update_lehrverband) + count($update_student) && $uid === null) {
+ // TODO(chris): phrase
+ $this->terminateWithValidationErrors(['' => "Kein/e StudentIn vorhanden!"]);
+ }
+ if (count($update_person) && $person_id === null) {
+ // TODO(chris): phrase
+ $this->terminateWithValidationErrors(['' => "Keine Person vorhanden!"]);
+ }
+
+ // Do Updates
+ if (count($update_lehrverband)) {
+ $result = $this->StudentlehrverbandModel->update([
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'student_uid' => $uid
+ ], $update_lehrverband);
+ $this->getDataOrTerminateWithError($result);
+ }
+
+ if (count($update_person)) {
+ $result = $this->PersonModel->update(
+ $person_id,
+ $update_person
+ );
+ $this->getDataOrTerminateWithError($result);
+ }
+
+
+ if (count($update_student)) {
+ $result = $this->StudentModel->update(
+ [$uid],
+ $update_student
+ );
+ $this->getDataOrTerminateWithError($result);
+ }
+
+ $this->terminateWithSuccess(array_fill_keys(array_merge(
+ array_keys($update_lehrverband),
+ array_keys($update_person),
+ array_keys($update_student)
+ ), ''));
+ }
+
+ public function check()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'is_valid_date');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $vorname = $this->input->post('vorname');
+ $nachname = $this->input->post('nachname');
+ $gebdatum = $this->input->post('gebdatum');
+
+ if (!$vorname && !$nachname && !$gebdatum)
+ $this->terminateWithValidationErrors(['At least one of vorname, nachname or gebdatum must be set']);
+
+ $this->load->model('person/Person_model', 'PersonModel');
+
+ if ($gebdatum)
+ $this->PersonModel->db->where('gebdatum', (new DateTime($gebdatum))->format('Y-m-d'));
+ if ($vorname && $nachname) {
+ $this->PersonModel->db->or_group_start();
+ $this->PersonModel->db->where('LOWER(nachname)', 'LOWER(' . $this->PersonModel->db->escape($nachname) . ')', false);
+ $this->PersonModel->db->where('LOWER(vorname)', 'LOWER(' . $this->PersonModel->db->escape($vorname) . ')', false);
+ $this->PersonModel->db->group_end();
+ } elseif ($nachname) {
+ $this->PersonModel->db->or_where('LOWER(nachname)', 'LOWER(' . $this->PersonModel->escape($nachname) . ')', false);
+ }
+
+ $result = $this->PersonModel->load();
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function add()
+ {
+ if (!$this->input->post('person_id')) {
+ if (!isset($_POST['address']) || !is_array($_POST['address']))
+ $_POST['address'] = [];
+ $_POST['address']['func'] = 1;
+ }
+ if ($this->input->post('incoming')) {
+ $_POST['ausbildungssemester'] = 0;
+ }
+
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('nachname', 'Nachname', 'callback_requiredIfNotPersonId', [
+ 'requiredIfNotPersonId' => $this->p->t('ui', 'error_required')
+ ]);
+ $this->form_validation->set_rules('geschlecht', 'Geschlecht', 'callback_requiredIfNotPersonId', [
+ 'requiredIfNotPersonId' => $this->p->t('ui', 'error_required')
+ ]);
+ $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'callback_isValidDate', [
+ 'isValidDate' => $this->p->t('ui', 'error_invalid_date')
+ ]);
+ $this->form_validation->set_rules('address[func]', 'Address', 'required|integer|less_than[2]|greater_than[-2]');
+ $this->form_validation->set_rules('address[plz]', 'PLZ', 'callback_requiredIfAddressFunc', [
+ 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required')
+ ]);
+ $this->form_validation->set_rules('address[gemeinde]', 'Gemeinde', 'callback_requiredIfAddressFunc', [
+ 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required')
+ ]);
+ $this->form_validation->set_rules('address[ort]', 'Ort', 'callback_requiredIfAddressFunc', [
+ 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required')
+ ]);
+ $this->form_validation->set_rules('address[address]', 'Adresse', 'callback_requiredIfAddressFunc', [
+ 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required')
+ ]);
+ $this->form_validation->set_rules('email', 'E-Mail', 'valid_email');
+ $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required');
+ $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required');
+ $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'required|integer|less_than[9]|greater_than[-1]');
+ // TODO(chris): validate studienplan with studiengang, semester and orgform?
+ // TODO(chris): validate person_id, studiengang_kz, studiensemester_kurzbz, orgform_kurzbz, nation, gemeinde, ort, geschlecht?
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ // TODO(chris): This should be in a library
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+ $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
+
+ $this->db->trans_start();
+
+ $result = $this->addInteressent();
+
+ $this->db->trans_complete();
+
+ if ($this->db->trans_status() === FALSE)
+ $this->terminateWithError('TODO(chris): TEXT', self::ERROR_TYPE_GENERAL);
+
+ $this->terminateWithSuccess($result);
+ }
+
+ protected function addInteressent()
+ {
+ // Person anlegen wenn nötig
+ $person_id = $this->input->post('person_id');
+ if (!$person_id) {
+ $this->load->model('person/Person_model', 'PersonModel');
+
+ $data = [
+ 'nachname' => $this->input->post('nachname'),
+ 'insertamum' => date('c'),
+ 'insertvon' => getAuthUID(),
+ 'zugangscode' => uniqid(),
+ 'aktiv' => true
+ ];
+ if ($this->input->post('anrede'))
+ $data['anrede'] = $this->input->post('anrede');
+ if ($this->input->post('titelpre'))
+ $data['titelpre'] = $this->input->post('titelpre');
+ if ($this->input->post('titelpost'))
+ $data['titelpost'] = $this->input->post('titelpost');
+ if ($this->input->post('vorname'))
+ $data['vorname'] = $this->input->post('vorname');
+ if ($this->input->post('vornamen'))
+ $data['vornamen'] = $this->input->post('vornamen');
+ if ($this->input->post('wahlname'))
+ $data['wahlname'] = $this->input->post('wahlname');
+ if ($this->input->post('geschlecht'))
+ $data['geschlecht'] = $this->input->post('geschlecht');
+ if ($this->input->post('gebdatum'))
+ $data['gebdatum'] = (new DateTime($this->input->post('datum_obj')))->format('Y-m-d');
+ if ($this->input->post('geburtsnation'))
+ $data['geburtsnation'] = $this->input->post('geburtsnation');
+ if ($this->input->post('staatsbuergerschaft'))
+ $data['staatsbuergerschaft'] = $this->input->post('staatsbuergerschaft');
+
+ $result = $this->PersonModel->insert($data);
+ $person_id = $this->getDataOrTerminateWithError($result);
+ }
+
+ // Addresse anlegen
+ $anlegen = $this->input->post('address[func]');
+ if ($anlegen) {
+ $this->load->model('person/Adresse_model', 'AdresseModel');
+
+ $data = [
+ 'nation' => $this->input->post('address[nation]'),
+ 'strasse' => $this->input->post('address[address]'),
+ 'plz' => $this->input->post('address[plz]'),
+ 'ort' => $this->input->post('address[ort]'),
+ 'gemeinde' => $this->input->post('address[gemeinde]'),
+ 'typ' => 'h',
+ 'zustelladresse' => true,
+ ];
+ if ($anlegen < 0) { // Überschreiben
+ $this->AdresseModel->addOrder('zustelladresse', 'DESC');
+ $this->AdresseModel->addOrder('sort');
+ $result = $this->AdresseModel->loadWhere([
+ 'person_id' => $person_id
+ ]);
+ $address = $this->getDataOrTerminateWithError($result);
+ if ($address) {
+ $address = current($address);
+
+ $data['updateamum'] = date('c');
+ $data['updatevon'] = getAuthUID();
+
+ $result = $this->AdresseModel->update($address->adresse_id, $data);
+ $this->getDataOrTerminateWithError($result);
+ } else {
+ //Wenn keine Adrese vorhanden ist dann eine neue Anlegen
+ $anlegen = 1;
+ $data['heimatadresse'] = true;
+ }
+ }
+ if ($anlegen > 0) {
+ $data['person_id'] = $person_id;
+ $data['insertamum'] = date('c');
+ $data['insertvon'] = getAuthUID();
+ if (!isset($data['heimatadresse']))
+ $data['heimatadresse'] = !$this->input->post('person_id');
+
+ $result = $this->AdresseModel->insert($data);
+ $this->getDataOrTerminateWithError($result);
+ }
+ }
+
+ // Kontaktdaten
+ $kontaktdaten = [];
+ foreach (['email', 'telefon', 'mobil'] as $k) {
+ $v = $this->input->post($k);
+ if ($v)
+ $kontaktdaten[$k] = $v;
+ }
+ if (count($kontaktdaten)) {
+ $this->load->model('person/Kontakt_model', 'KontaktModel');
+
+ foreach ($kontaktdaten as $typ => $kontakt) {
+ $data = [
+ 'person_id' => $person_id,
+ 'kontakttyp' => $typ,
+ 'kontakt' => $kontakt,
+ 'zustellung' => true,
+ 'insertamum' => date('c'),
+ 'insertvon' => getAuthUID()
+ ];
+ $result = $this->KontaktModel->insert($data);
+ $this->getDataOrTerminateWithError($result);
+ }
+ }
+
+ // Prestudent anlegen
+ $data = [
+ 'aufmerksamdurch_kurzbz' => 'k.A.',
+ 'person_id' => $person_id,
+ 'studiengang_kz' => $this->input->post('studiengang_kz'),
+ 'ausbildungcode' => $this->input->post('letzteausbildung'),
+ 'anmerkung' => $this->input->post('anmerkungen'),
+ 'reihungstestangetreten' => false,
+ 'bismelden' => true
+ ];
+ $ausbildungsart = $this->input->post('ausbildungsart');
+ if ($ausbildungsart)
+ $data['anmerkung'] .= ' Ausbildungsart:' . $ausbildungsart;
+ // Incomings und ausserordentliche sind bei Meldung nicht förderrelevant
+ $incoming = $this->input->post('incoming');
+ if ($incoming || substr($data['studiengang_kz'], 0, 1) == '9')
+ $data['foerderrelevant'] = false;
+ // Wenn die Person schon im System erfasst ist, dann die ZGV des Datensatzes uebernehmen
+ $this->PrestudentModel->addOrder('zgvmas_code');
+ $this->PrestudentModel->addOrder('zgv_code', 'DESC');
+ $this->PrestudentModel->addLimit(1);
+ $result = $this->PrestudentModel->loadWhere([
+ 'person_id' => $person_id
+ ]);
+ $prestudent = $this->getDataOrTerminateWithError($result);
+ if ($prestudent) {
+ $prestudent = current($prestudent);
+ if ($prestudent->zgv_code) {
+ $data['zgv_code'] = $prestudent->zgv_code;
+ $data['zgvort'] = $prestudent->zgvort;
+ $data['zgvdatum'] = $prestudent->zgvdatum;
+
+ $data['zgvmas_code'] = $prestudent->zgvmas_code;
+ $data['zgvmaort'] = $prestudent->zgvmaort;
+ $data['zgvmadatum'] = $prestudent->zgvmadatum;
+ }
+ }
+ // Prestudent speichern
+ $result = $this->PrestudentModel->insert($data);
+ $prestudent_id = $this->getDataOrTerminateWithError($result);
+
+ // Prestudent Rolle Anlegen
+ $data = [
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => $incoming ? 'Incoming' : 'Interessent',
+ 'studiensemester_kurzbz' => $this->input->post('studiensemester_kurzbz'),
+ 'ausbildungssemester' => $this->input->post('ausbildungssemester') ?: 0,
+ 'orgform_kurzbz' => $this->input->post('orgform_kurzbz') ?: null,
+ 'studienplan_id' => $this->input->post('studienplan_id') ?: null,
+ 'datum' => date('Y-m-d'),
+ 'insertamum' => date('c'),
+ 'insertvon' => getAuthUID()
+ ];
+ $result = $this->PrestudentstatusModel->insert($data);
+ $this->getDataOrTerminateWithError($result);
+
+ if ($incoming) {
+ // TODO(chris): IMPLEMENT!
+ //Matrikelnummer und UID generieren
+ //Benutzerdatensatz anlegen
+ //Studentendatensatz anlegen
+ //StudentLehrverband anlegen
+ }
+
+ // TODO(chris): DEBUG
+ /*$result = $this->PrestudentModel->loadWhere([
+ 'pestudent_id' => 1
+ ]);
+ if (isError($result)) {
+ return $result;
+ }*/
+
+ $this->terminateWithSuccess(true);
+ }
+
+ public function requiredIfNotPersonId($value)
+ {
+ if (isset($_POST['person_id']))
+ return true;
+ return !!$value;
+ }
+
+ public function requiredIfAddressFunc($value)
+ {
+ if (!$_POST['address']['func'])
+ return true;
+ return !!$value;
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php
new file mode 100644
index 000000000..5fb7b592c
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Students.php
@@ -0,0 +1,743 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about listing students
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Students extends FHCAPI_Controller
+{
+ private $allowedStgs = [];
+
+
+ public function __construct()
+ {
+ $permissions = [];
+ $router = load_class('Router');
+ $permissions[$router->method] = ['admin:r', 'assistenz:r'];
+ parent::__construct($permissions);
+
+ $this->allowedStgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: [];
+ $this->allowedStgs = array_merge($this->allowedStgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
+
+ if (!$this->allowedStgs) {
+ $this->_outputAuthError([$router->method => ['admin:r', 'assistenz:r']]);
+ exit;
+ }
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ }
+
+ /**
+ * Remap calls:
+ * / => return []
+ * /inout => return []
+ * /inout/incoming => getIncoming
+ * /inout/outgoing => getOutgoing
+ * /inout/gemeinsamestudien => getGemeinsamestudien
+ * /(studiengang_kz) => getStudents
+ * /(studiengang_kz)/prestudent => getPrestudents
+ * /(studiengang_kz)/prestudent/* => getPrestudents
+ * /(studiengang_kz)/(semester) => getStudents
+ * /(studiengang_kz)/(semester)/grp/(gruppe_kurzbz) => getStudents
+ * /(studiengang_kz)/(semester)/(verband) => getStudents
+ * /(studiengang_kz)/(semester)/(verband)/(gruppe) => getStudents
+ * /(studiengang_kz)/(org_form) => getStudents
+ * /(studiengang_kz)/(org_form)/prestudent => getPrestudents
+ * /(studiengang_kz)/(org_form)/prestudent/* => getPrestudents
+ * /(studiengang_kz)/(org_form)/(semester) => getStudents
+ * /(studiengang_kz)/(org_form)/(semester)/grp/(gruppe_kurzbz)
+ * => getStudents
+ * /(studiengang_kz)/(org_form)/(semester)/(verband) => getStudents
+ * /(studiengang_kz)/(org_form)/(semester)/(verband)/(gruppe)
+ * => getStudents
+ * /uid/(student_uid) => getStudent
+ * /prestudent/(prestudent_id) => getPrestudent
+ * /person/(person_id) => getPerson
+ *
+ * @param string $method
+ * @param array $params (optional)
+ *
+ * @return void
+ */
+ public function _remap($method, $params = [])
+ {
+ if ($method == '' || $method == 'index')
+ return $this->terminateWithSuccess([]);
+
+ if ($method == 'inout') {
+ if (!count($params))
+ return $this->terminateWithSuccess([]);
+ switch ($params[0]) {
+ case 'incoming':
+ return $this->getIncoming();
+ case 'outgoing':
+ return $this->getOutgoing();
+ case 'gemeinsamestudien':
+ return $this->getGemeinsamestudien();
+ default:
+ return show_404();
+ }
+ }
+
+ $count = count($params);
+ if (!$count)
+ return $this->getStudents($method);
+
+ if ($method == 'uid' && $count == 1)
+ return $this->getStudent($params[0]);
+
+ if ($method == 'prestudent' && $count == 1)
+ return $this->getPrestudent($params[0]);
+
+ if ($method == 'person' && $count == 1)
+ return $this->getPerson($params[0]);
+
+ if (is_numeric($params[0])) {
+ $sem = $params[0];
+ if ($count == 3 && $params[1] == 'grp') {
+ $g = $params[2];
+ $ver = null;
+ $grp = null;
+ } else {
+ $g = null;
+ $ver = $count > 1 ? $params[1] : null;
+ $grp = $count > 2 ? $params[2] : null;
+ }
+ return $this->getStudents($method, $sem, $ver, $grp, $g);
+ } elseif ($params[0] == 'prestudent') {
+ if ($count == 1)
+ return $this->getPrestudents($method);
+ if ($count == 2)
+ return $this->getPrestudents($method, $params[1]);
+ return $this->getPrestudents($method, $params[1], $params[$count-1]);
+ } else {
+ $org = $params[0];
+ if ($count > 1 && $params[1] == 'prestudent') {
+ if ($count == 2)
+ return $this->getPrestudents($method, null, null, $org);
+ if ($count == 3)
+ return $this->getPrestudents($method, $params[2], null, $org);
+ return $this->getPrestudents($method, $params[2], $params[$count-1], $org);
+ }
+ $sem = $count > 1 ? $params[1] : null;
+ if ($count == 4 && $params[2] == 'grp') {
+ $g = $params[3];
+ $ver = null;
+ $grp = null;
+ } else {
+ $g = null;
+ $ver = $count > 2 ? $params[2] : null;
+ $grp = $count > 3 ? $params[3] : null;
+ }
+
+ return $this->getStudents($method, $sem, $ver, $grp, $g, $org);
+ }
+
+ show_404();
+ }
+
+ /**
+ * @return void
+ */
+ protected function getIncoming()
+ {
+ // TODO(chris): IMPLEMENT!
+ $this->terminateWithSuccess([]);
+ }
+
+ /**
+ * @return void
+ */
+ protected function getOutgoing()
+ {
+ // TODO(chris): IMPLEMENT!
+ $this->terminateWithSuccess([]);
+ }
+
+ /**
+ * @return void
+ */
+ protected function getGemeinsamestudien()
+ {
+ // TODO(chris): IMPLEMENT!
+ $this->terminateWithSuccess([]);
+ }
+
+ /**
+ * @param integer $studiengang_kz
+ * @param string $studiensemester_kurzbz (optional)
+ * @param string $filter (optional)
+ * @param string $orgform_kurzbz (optional)
+ *
+ * @return void
+ */
+ protected function getPrestudents($studiengang_kz, $studiensemester_kurzbz = null, $filter = null, $orgform_kurzbz = null)
+ {
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ $stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
+
+ $selectRT = "
+ SELECT 1
+ FROM public.tbl_rt_person
+ JOIN public.tbl_reihungstest r ON (rt_id = reihungstest_id)
+ WHERE person_id=p.person_id
+ AND studienplan_id IN (
+ SELECT studienplan_id
+ FROM lehre.tbl_studienplan
+ JOIN lehre.tbl_studienordnung o USING(studienordnung_id)
+ WHERE o.studiengang_kz=tbl_prestudent.studiengang_kz
+ )
+ AND r.studiensemester_kurzbz=" . $stdsemEsc;
+
+
+ $where = ['tbl_prestudent.studiengang_kz' => $studiengang_kz];
+
+ if ($orgform_kurzbz) {
+ $where['ps.orgform_kurzbz'] = $orgform_kurzbz;
+ }
+
+ switch ($filter) {
+ case "interessenten":
+ $where['ps.status_kurzbz'] = 'Interessent';
+ break;
+ case "bewerbungnichtabgeschickt":
+ $where['ps.status_kurzbz'] = 'Interessent';
+ $where['bewerbung_abgeschicktamum'] = null;
+ break;
+ case "bewerbungabgeschickt":
+ $where['ps.status_kurzbz'] = 'Interessent';
+ $where['bewerbung_abgeschicktamum IS NOT NULL'] = null;
+ $where['bestaetigtam'] = null;
+ break;
+ case "statusbestaetigt":
+ $where['ps.status_kurzbz'] = 'Interessent';
+ $where['bestaetigtam IS NOT NULL'] = null;
+ break;
+ case "statusbestaetigtrtnichtangemeldet":
+ $where['ps.status_kurzbz'] = 'Interessent';
+ $where['bestaetigtam IS NOT NULL'] = null;
+ $this->PrestudentModel->db->where('NOT EXISTS(' . $selectRT . ')', null, false);
+ break;
+ case "statusbestaetigtrtangemeldet":
+ $where['ps.status_kurzbz'] = 'Interessent';
+ $where['bestaetigtam IS NOT NULL'] = null;
+ $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false);
+ break;
+ case "zgv":
+ $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
+
+ $result = $this->StudiengangModel->load($studiengang_kz);
+
+ $stg = $this->getDataOrTerminateWithError($result);
+ if (!$stg)
+ $this->terminateWithValidationErrors(['' => 'Studiengang does not exist']); // TODO(chris): phrase
+ $stg = current($stg);
+
+ $where['ps.status_kurzbz'] = 'Interessent';
+
+ if ($stg->typ == 'm') {
+ $where['zgvmas_code IS NOT NULL'] = null;
+ if (defined('ZGV_ERFUELLT_ANZEIGEN') && ZGV_ERFUELLT_ANZEIGEN)
+ $where['zgvmas_erfuellt'] = true;
+ } elseif ($stg->typ == 'p') {
+ $where['zgvdoktor_code IS NOT NULL'] = null;
+ if (defined('ZGV_DOKTOR_ANZEIGEN') && ZGV_DOKTOR_ANZEIGEN)
+ $where['zgvdoktor_erfuellt'] = true;
+ } else {
+ $where['zgv_code IS NOT NULL'] = null;
+ if (defined('ZGV_ERFUELLT_ANZEIGEN') && ZGV_ERFUELLT_ANZEIGEN)
+ $where['zgv_erfuellt'] = true;
+ }
+ break;
+ case "reihungstestangemeldet":
+ $where['ps.status_kurzbz'] = 'Interessent';
+ $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false);
+ break;
+ case "reihungstestnichtangemeldet":
+ $where['ps.status_kurzbz'] = 'Interessent';
+ $this->PrestudentModel->db->where('NOT EXISTS(' . $selectRT . ')', null, false);
+ break;
+ case "bewerber":
+ $where['ps.status_kurzbz'] = 'Bewerber';
+ break;
+ case "bewerberrtnichtangemeldet":
+ $where['ps.status_kurzbz'] = 'Bewerber';
+ $this->PrestudentModel->db->where('NOT EXISTS(' . $selectRT . ')', null, false);
+ break;
+ case "bewerberrtangemeldet":
+ $where['ps.status_kurzbz'] = 'Bewerber';
+ $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false);
+ break;
+ case "bewerberrtangemeldetteilgenommen":
+ $where['ps.status_kurzbz'] = 'Bewerber';
+ $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false);
+ $where['reihungstestangetreten'] = true;
+ break;
+ case "bewerberrtangemeldetnichtteilgenommen":
+ $where['ps.status_kurzbz'] = 'Bewerber';
+ $this->PrestudentModel->db->where('EXISTS(' . $selectRT . ')', null, false);
+ $where['reihungstestangetreten'] = false;
+ break;
+ case "aufgenommen":
+ $where['ps.status_kurzbz'] = 'Aufgenommener';
+ break;
+ case "warteliste":
+ $where['ps.status_kurzbz'] = 'Wartender';
+ break;
+ case "absage":
+ $where['ps.status_kurzbz'] = 'Abgewiesener';
+ break;
+ case "incoming":
+ // NOTE(chris): in FAS it was not filtered for studiengang_kz
+ $where['ps.status_kurzbz'] = 'Incoming';
+ break;
+ case "absolvent":
+ $where['ps.status_kurzbz'] = 'Absolvent';
+ break;
+ case "diplomand":
+ $where['ps.status_kurzbz'] = 'Diplomand';
+ break;
+ default:
+ if (!$studiensemester_kurzbz) {
+ // TODO(chris): this does not work with $orgform_kurzbz != null
+ $where['ps.status_kurzbz'] = null;
+ } else {
+ $this->PrestudentModel->db->where_in('ps.status_kurzbz', [
+ 'Interessent',
+ 'Bewerber',
+ 'Aufgenommener',
+ 'Wartender',
+ 'Abgewiesener'
+ ]);
+ }
+ break;
+ }
+
+ /*
+ $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
+ $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', '
+ pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.prestudent_id=tbl_prestudent.prestudent_id
+ AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT');
+ $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_prestudentstatus ps', '
+ ps.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')
+ AND ps.prestudent_id=tbl_prestudent.prestudent_id
+ AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')
+ AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT');*/
+ $this->prepareQuery($studiensemester_kurzbz);
+
+ $this->PrestudentModel->addSelect("
+ CASE WHEN ps.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent')
+ THEN ps.ausbildungssemester::text
+ ELSE ''::text END AS semester", false);
+ $this->PrestudentModel->addSelect("'' AS verband");
+ $this->PrestudentModel->addSelect("'' AS gruppe");
+ $this->addSelectPrioRel();
+
+ $this->addFilter($studiensemester_kurzbz);
+
+ $result = $this->PrestudentModel->loadWhere($where);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * @param integer $studiengang_kz
+ * @param integer $semester (optional)
+ * @param string $verband (optional)
+ * @param integer $gruppe (optional)
+ * @param string $gruppe_kurzbz (optional)
+ * @param string $orgform_kurzbz (optional)
+ *
+ * @return void
+ */
+ protected function getStudents($studiengang_kz, $semester = null, $verband = null, $gruppe = null, $gruppe_kurzbz = null, $orgform_kurzbz = null)
+ {
+ $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
+
+
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ /*
+ $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
+ $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id');
+ $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', '
+ pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.prestudent_id=tbl_prestudent.prestudent_id
+ AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT');
+ $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid');
+ $this->PrestudentModel->addJoin(
+ 'public.tbl_studentlehrverband v',
+ 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz)
+ );*/
+ $this->prepareQuery($studiensemester_kurzbz, '');
+
+ $this->PrestudentModel->addSelect('v.semester');
+ $this->PrestudentModel->addSelect('v.verband');
+ $this->PrestudentModel->addSelect('v.gruppe');
+ $this->PrestudentModel->addSelect("'' AS priorisierung_relativ");
+
+
+ $where = [];
+
+ if ($gruppe_kurzbz !== null) {
+ $this->PrestudentModel->addJoin('public.tbl_benutzergruppe g', 'uid');
+ $where['g.gruppe_kurzbz'] = $gruppe_kurzbz;
+ $where['g.studiensemester_kurzbz'] = $studiensemester_kurzbz;
+ } else {
+ $where['v.studiengang_kz'] = $studiengang_kz;
+
+ if ($semester !== null)
+ $where['v.semester'] = $semester;
+
+ if ($verband !== null)
+ $where['v.verband'] = $verband;
+
+ if ($gruppe !== null)
+ $where['v.gruppe'] = $gruppe;
+
+ if (!$verband && !$gruppe && $orgform_kurzbz !== null) {
+ $this->PrestudentModel->db->where(
+ "(
+ SELECT orgform_kurzbz
+ FROM public.tbl_prestudentstatus
+ WHERE prestudent_id=tbl_prestudent.prestudent_id
+ AND studiensemester_kurzbz=" . $this->PrestudentModel->escape($studiensemester_kurzbz) . "
+ ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1
+ ) =",
+ $this->PrestudentModel->escape($orgform_kurzbz),
+ false
+ );
+ }
+
+ }
+
+ $this->addFilter($studiensemester_kurzbz);
+
+ $result = $this->PrestudentModel->loadWhere($where);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * @param string $prestudent_id
+ *
+ * @return void
+ */
+ protected function getPrestudent($prestudent_id)
+ {
+ $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
+
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ /*
+ $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
+ $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', '
+ pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.prestudent_id=tbl_prestudent.prestudent_id
+ AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT');
+ $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid', 'LEFT');
+ $this->PrestudentModel->addJoin(
+ 'public.tbl_studentlehrverband v',
+ 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz),
+ 'LEFT'
+ );*/
+ $this->prepareQuery($studiensemester_kurzbz);
+
+ $this->PrestudentModel->addSelect("COALESCE(v.semester::text, CASE WHEN public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') THEN public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)::text ELSE ''::text END) AS semester", false);
+ $this->PrestudentModel->addSelect('v.verband');
+ $this->PrestudentModel->addSelect('v.gruppe');
+ $this->addSelectPrioRel();
+
+ $this->addFilter($studiensemester_kurzbz);
+
+ $result = $this->PrestudentModel->loadWhere([
+ 'tbl_prestudent.prestudent_id' => $prestudent_id
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * @param string $student_uid
+ *
+ * @return void
+ */
+ protected function getStudent($student_uid)
+ {
+ $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
+
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ /*
+ $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
+ $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id');
+ $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', '
+ pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.prestudent_id=tbl_prestudent.prestudent_id
+ AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT');
+ $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid');
+ $this->PrestudentModel->addJoin(
+ 'public.tbl_studentlehrverband v',
+ 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz),
+ 'LEFT'
+ );*/
+ $this->prepareQuery($studiensemester_kurzbz);
+
+ $this->PrestudentModel->addSelect('v.semester');
+ $this->PrestudentModel->addSelect('v.verband');
+ $this->PrestudentModel->addSelect('v.gruppe');
+ $this->addSelectPrioRel();
+
+ $this->addFilter($studiensemester_kurzbz);
+
+ $result = $this->PrestudentModel->loadWhere([
+ 's.student_uid' => $student_uid
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * @param integer $person_id
+ *
+ * @return void
+ */
+ protected function getPerson($person_id)
+ {
+ $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
+
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+
+ /*
+ $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
+ $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id');
+ $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid');
+ $this->PrestudentModel->addJoin(
+ 'public.tbl_studentlehrverband v',
+ 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz),
+ 'LEFT'
+ );*/
+ $this->prepareQuery($studiensemester_kurzbz);
+
+ $this->PrestudentModel->addSelect('v.semester');
+ $this->PrestudentModel->addSelect('v.verband');
+ $this->PrestudentModel->addSelect('v.gruppe');
+ $this->addSelectPrioRel();
+
+ $this->addFilter($studiensemester_kurzbz);
+
+ $result = $this->PrestudentModel->loadWhere([
+ 'p.person_id' => $person_id
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ /**
+ * @param string|null $studiensemester_kurzbz
+ * @param string $type
+ *
+ * @return void
+ */
+ protected function prepareQuery($studiensemester_kurzbz, $type = 'LEFT')
+ {
+ $stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
+
+
+ $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
+ $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', $type);
+ $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', '
+ pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.prestudent_id=tbl_prestudent.prestudent_id
+ AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL)
+ AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT');
+ $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT');
+ $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid', 'LEFT');
+ $this->PrestudentModel->addJoin(
+ 'public.tbl_studentlehrverband v',
+ 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz' . ($studiensemester_kurzbz ? '=' . $stdsemEsc : ' IS NULL'),
+ $type
+ );
+ $this->PrestudentModel->addJoin('public.tbl_prestudentstatus ps', '
+ ps.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')
+ AND ps.prestudent_id=tbl_prestudent.prestudent_id
+ AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')
+ AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT');
+
+
+ $this->PrestudentModel->addSelect("b.uid");
+ $this->PrestudentModel->addSelect('titelpre');
+ $this->PrestudentModel->addSelect('nachname');
+ $this->PrestudentModel->addSelect('vorname');
+ $this->PrestudentModel->addSelect('wahlname');
+ $this->PrestudentModel->addSelect('vornamen');
+ $this->PrestudentModel->addSelect('titelpost');
+ $this->PrestudentModel->addSelect('svnr');
+ $this->PrestudentModel->addSelect('ersatzkennzeichen');
+ $this->PrestudentModel->addSelect('gebdatum');
+ $this->PrestudentModel->addSelect('geschlecht');
+
+ // semester
+ // verband
+ // gruppe
+
+ $this->PrestudentModel->addSelect('UPPER(stg.typ || stg.kurzbz) AS studiengang');
+ $this->PrestudentModel->addSelect('tbl_prestudent.studiengang_kz');
+ $this->PrestudentModel->addSelect("s.matrikelnr");
+ $this->PrestudentModel->addSelect('p.person_id');
+ $this->PrestudentModel->addSelect('pls.status_kurzbz AS status');
+ $this->PrestudentModel->addSelect('pls.datum AS status_datum');
+ $this->PrestudentModel->addSelect('pls.bestaetigtam AS status_bestaetigung');
+ $this->PrestudentModel->addSelect(
+ "(SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp='email' AND person_id=p.person_id AND zustellung LIMIT 1) AS mail_privat",
+ false
+ );
+ $this->PrestudentModel->addSelect("
+ CASE WHEN b.uid IS NOT NULL AND b.uid<>''
+ THEN b.uid || " . $this->PrestudentModel->escape(DOMAIN) . "
+ ELSE '' END AS mail_intern", false);
+ $this->PrestudentModel->addSelect('p.anmerkung AS anmerkungen');
+ $this->PrestudentModel->addSelect('tbl_prestudent.anmerkung');
+ $this->PrestudentModel->addSelect('pls.orgform_kurzbz');
+ $this->PrestudentModel->addSelect('aufmerksamdurch_kurzbz');
+ $this->PrestudentModel->addSelect(
+ "(SELECT rt_gesamtpunkte AS punkte FROM public.tbl_prestudent WHERE prestudent_id=ps.prestudent_id) AS punkte",
+ false
+ );
+ $this->PrestudentModel->addSelect('tbl_prestudent.aufnahmegruppe_kurzbz');
+ $this->PrestudentModel->addSelect('tbl_prestudent.dual');
+ $this->PrestudentModel->addSelect('p.matr_nr');
+ $this->PrestudentModel->addSelect('sp.bezeichnung AS studienplan_bezeichnung');
+ $this->PrestudentModel->addSelect('tbl_prestudent.prestudent_id');
+
+ // priorisierung_relativ
+
+ $this->PrestudentModel->addSelect('mentor');
+ $this->PrestudentModel->addSelect('b.aktiv AS bnaktiv');
+
+ /*$this->PrestudentModel->addSelect('tbl_prestudent.reihungstest_id');
+ $this->PrestudentModel->addSelect('tbl_prestudent.anmeldungreihungstest');
+ $this->PrestudentModel->addSelect('tbl_prestudent.gsstudientyp_kurzbz');
+ $this->PrestudentModel->addSelect('tbl_prestudent.priorisierung');
+ $this->PrestudentModel->addSelect('p.zugangscode');
+ $this->PrestudentModel->addSelect('p.bpk');*/
+
+ $this->PrestudentModel->db->where_in('tbl_prestudent.studiengang_kz', $this->allowedStgs);
+
+ $this->PrestudentModel->addOrder('nachname');
+ $this->PrestudentModel->addOrder('vorname');
+ }
+
+ /**
+ * @return void
+ */
+ protected function addSelectPrioRel()
+ {
+ $this->PrestudentModel->addSelect("(
+ SELECT count(*)
+ FROM (
+ SELECT *, public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) AS laststatus
+ FROM PUBLIC.tbl_prestudent pss
+ JOIN PUBLIC.tbl_prestudentstatus USING (prestudent_id)
+ WHERE person_id = p.person_id
+ AND studiensemester_kurzbz = (
+ SELECT studiensemester_kurzbz
+ FROM PUBLIC.tbl_prestudentstatus
+ WHERE prestudent_id = tbl_prestudent.prestudent_id
+ AND status_kurzbz = 'Interessent'
+ LIMIT 1
+ )
+ AND status_kurzbz = 'Interessent'
+ ) prest
+ WHERE laststatus NOT IN ('Abbrecher', 'Abgewiesener', 'Absolvent')
+ AND priorisierung <= tbl_prestudent.priorisierung
+ ) || ' (' || tbl_prestudent.priorisierung || ')' AS priorisierung_relativ", false);
+ }
+
+ /**
+ * Adds additional filters to the query
+ *
+ * @param string $studiensemester_kurzbz
+ *
+ * @return void
+ */
+ protected function addFilter($studiensemester_kurzbz)
+ {
+ $filter = $this->input->get('filter');
+ if (isset($filter['konto_count_0'])) {
+ $bt = $this->PrestudentModel->escape($filter['konto_count_0']);
+ $stdsem = $this->PrestudentModel->escape($studiensemester_kurzbz);
+
+ $this->PrestudentModel->db->where('(
+ SELECT count(*)
+ FROM public.tbl_konto
+ WHERE person_id=tbl_prestudent.person_id
+ AND buchungstyp_kurzbz=' . $bt . '
+ AND studiensemester_kurzbz=' . $stdsem . '
+ ) =', 0);
+ $this->PrestudentModel->db->where('get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) !=', 'Incoming');
+ }
+ if (isset($filter['konto_missing_counter'])) {
+ $bt = $this->PrestudentModel->escape($filter['konto_missing_counter']);
+ $stg = '';
+ if ($this->variablelib->getVar('kontofilterstg') == 'true')
+ $stg = ' AND studiengang_kz=tbl_prestudent.studiengang_kz';
+
+ $bt = $bt == 'alle' ? '' : ' AND buchungstyp_kurzbz=' . $bt;
+
+ $this->PrestudentModel->db->where('(
+ SELECT sum(betrag)
+ FROM public.tbl_konto
+ WHERE person_id=tbl_prestudent.person_id' .
+ $bt .
+ $stg . '
+ ) !=', 0);
+ }
+ }
+}
diff --git a/application/controllers/api/frontend/v1/stv/Verband.php b/application/controllers/api/frontend/v1/stv/Verband.php
new file mode 100644
index 000000000..e8c532652
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Verband.php
@@ -0,0 +1,493 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * Provides data to the ajax get calls about verbände
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Verband extends FHCAPI_Controller
+{
+ public function __construct()
+ {
+ $permissions = [];
+ $router = load_class('Router');
+ $permissions[$router->method] = ['admin:r', 'assistenz:r'];
+ parent::__construct($permissions);
+
+ // Load Models
+ $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ }
+
+ /**
+ * Remap calls:
+ * /
+ * /(studiengang_kz) => getStudiengang
+ * /(studiengang_kz)/(semester) => getSemester
+ * /(studiengang_kz)/(semester)/(verband) => getVerband
+ * /(studiengang_kz)/(org_form) => getStudiengang
+ * /(studiengang_kz)/(org_form)/(semester) => getSemester
+ * /(studiengang_kz)/(org_form)/(semester)/(verband) => getVerband
+ *
+ * @param string $method
+ * @param array $params (optional)
+ *
+ * @return void
+ */
+ public function _remap($method, $params = [])
+ {
+ if ($method == '' || $method == 'index')
+ return $this->getBase();
+
+ // NOTE(chris): Test if access is allowed ($method is the Studiengang)
+ if (!$this->permissionlib->isBerechtigt('assistenz', 's', $method)
+ && !$this->permissionlib->isBerechtigt('admin', 's', $method)
+ ) {
+ return $this->_outputAuthError([$method => ['admin:r', 'assistenz:r']]);
+ }
+
+ $count = count($params);
+ if (!$count)
+ return $this->getStudiengang($method);
+
+ if ($count == 1) {
+ if (is_numeric($params[0]))
+ return $this->getSemester($method, $params[0]);
+ elseif ($params[0] == 'prestudent')
+ return $this->terminateWithSuccess($this->getStdSem($method . '/prestudent/', $method));
+ else
+ return $this->getStudiengang($method, $params[0]);
+ }
+ if ($count == 2) {
+ if (is_numeric($params[0]))
+ return $this->getVerband($method, $params[0], $params[1]);
+ elseif ($params[1] == 'prestudent')
+ return $this->terminateWithSuccess($this->getStdSem($method . '/' . $params[0] . '/prestudent/', $method));
+ else
+ return $this->getSemester($method, $params[1], $params[0]);
+ }
+ if ($count == 3 && !is_numeric($params[0]) && is_numeric($params[1]) && !is_numeric($params[2]))
+ return $this->getVerband($method, $params[1], $params[2], $params[0]);
+
+ show_404();
+ }
+
+ /**
+ * @return void
+ */
+ protected function getBase()
+ {
+ $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
+
+ $this->StudiengangModel->addDistinct();
+ $this->StudiengangModel->addSelect("v.studiengang_kz AS link");
+ $this->StudiengangModel->addSelect(
+ "CONCAT(kurzbzlang, ' (', UPPER(CONCAT(typ, kurzbz)), ') - ', tbl_studiengang.bezeichnung) AS name",
+ false
+ );
+ $this->StudiengangModel->addSelect('erhalter_kz');
+ $this->StudiengangModel->addSelect('typ');
+ $this->StudiengangModel->addSelect('kurzbz');
+ $this->StudiengangModel->addSelect('studiengang_kz');
+ $this->StudiengangModel->addSelect('studiengang_kz AS stg_kz');
+
+ $this->StudiengangModel->addOrder('erhalter_kz');
+ $this->StudiengangModel->addOrder('typ');
+ $this->StudiengangModel->addOrder('kurzbz');
+
+ $stgs = $this->permissionlib->getSTG_isEntitledFor('admin') ?: [];
+ $stgs = array_merge($stgs, $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []);
+
+ if (!$stgs)
+ $this->terminateWithSuccess([]);
+
+ $this->StudiengangModel->db->where_in('studiengang_kz', $stgs);
+
+ $result = $this->StudiengangModel->loadWhere(['v.aktiv' => true]);
+
+ $list = $this->getDataOrTerminateWithError($result);
+
+ if ($this->permissionlib->isBerechtigt('inout/uebersicht'))
+ $list[] = [
+ 'name' => 'International',
+ 'link' => 'inout',
+ 'children' => [
+ [
+ 'name' => 'Incoming',
+ 'link' => 'inout/incoming',
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Outgoing',
+ 'link' => 'inout/outgoing',
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Gemeinsame Studien',
+ 'link' => 'inout/gemeinsamestudien',
+ 'leaf' => true
+ ]
+ ]
+ ];
+ $this->terminateWithSuccess($list);
+ }
+
+ /**
+ * @param integer $studiengang_kz
+ * @param string $orgform (optional)
+ *
+ * @return void
+ */
+ protected function getStudiengang($studiengang_kz, $org_form = null)
+ {
+ $link = $studiengang_kz . '/';
+ if ($org_form !== null)
+ $link .= $org_form . '/';
+
+ $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
+
+ $this->StudiengangModel->addDistinct();
+ $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", semester) AS link", false);
+ $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester ORDER BY verband, gruppe LIMIT 1)) AS name", false);
+
+ $this->StudiengangModel->addSelect('semester');
+ $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
+
+ $this->StudiengangModel->addOrder('semester');
+
+ if ($org_form !== null) {
+ $this->StudiengangModel->db->group_start();
+ $this->StudiengangModel->db->where('v.semester', 0);
+ $this->StudiengangModel->db->or_where('v.orgform_kurzbz', $org_form);
+ $this->StudiengangModel->db->group_end();
+ }
+
+ $result = $this->StudiengangModel->loadWhere([
+ 'v.studiengang_kz' => $studiengang_kz,
+ 'v.aktiv' => true
+ ]);
+ $list = $this->getDataOrTerminateWithError($result);
+
+ array_unshift($list, [
+ 'name' => 'PreStudent',
+ 'link' => $link . 'prestudent',
+ 'children' => $this->getStdSem($link . 'prestudent/', $studiengang_kz)
+ ]);
+
+ if ($org_form === null) {
+ // NOTE(chris): if mischform show orgforms
+ $result = $this->StudiengangModel->load($studiengang_kz);
+ $result = $this->getDataOrTerminateWithError($result);
+ if ($result) {
+ if (current($result)->mischform) {
+ $this->load->model('organisation/Studienordnung_model', 'StudienordnungModel');
+
+ $this->StudienordnungModel->addDistinct();
+ $this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link");
+ $this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name");
+
+ $this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id');
+
+ $result = $this->StudienordnungModel->loadWhere([
+ 'aktiv' => true,
+ 'studiengang_kz' => $studiengang_kz,
+ 'p.orgform_kurzbz !=' => 'DDP'
+ ]);
+ $result = $this->getDataOrTerminateWithError($result);
+
+ $list = array_merge($list, $result);
+ }
+ }
+
+ }
+ $this->terminateWithSuccess($list);
+ }
+
+ /**
+ * @param integer $studiengang_kz
+ * @param integer $semester
+ * @param string $orgform
+ *
+ * @return void
+ */
+ protected function getSemester($studiengang_kz, $semester, $org_form = null)
+ {
+ $link = $studiengang_kz . '/';
+ if ($org_form !== null)
+ $link .= $org_form . '/';
+ $link .= $semester . '/';
+
+
+ $this->load->model('organisation/Gruppe_model', 'GruppeModel');
+
+ $this->GruppeModel->addDistinct();
+ $this->GruppeModel->addSelect("CONCAT(" . $this->GruppeModel->escape($link . 'grp/') . ", gruppe_kurzbz) AS link", false);
+ $this->GruppeModel->addSelect("CONCAT(gruppe_kurzbz, ' (', bezeichnung, ')') AS name", false);
+ $this->GruppeModel->addSelect("TRUE AS leaf", false);
+
+ $this->GruppeModel->addSelect('sort');
+ $this->GruppeModel->addSelect('gruppe_kurzbz');
+ $this->GruppeModel->addSelect($this->GruppeModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
+
+ $this->GruppeModel->addOrder('sort');
+ $this->GruppeModel->addOrder('gruppe_kurzbz');
+
+ $where = [
+ 'studiengang_kz' => $studiengang_kz,
+ 'semester' => $semester,
+ 'lehre' => true,
+ 'sichtbar' => true,
+ 'aktiv' => true,
+ 'direktinskription' => false
+ ];
+
+ if ($org_form !== null)
+ $where['orgform_kurzbz'] = $org_form;
+
+ $result = $this->GruppeModel->loadWhere($where);
+
+ $list = $this->getDataOrTerminateWithError($result);
+
+ $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
+
+ $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", verband) AS link", false);
+ $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, verband, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester AND verband=v.verband ORDER BY gruppe LIMIT 1)) AS name", false);
+ $this->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
+
+ $this->StudiengangModel->addSelect('verband');
+ $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
+
+ $this->StudiengangModel->addOrder('verband');
+
+ $this->StudiengangModel->addGroupBy('link, name, verband');
+
+ $where = [
+ 'v.studiengang_kz' => $studiengang_kz,
+ 'v.semester' => $semester,
+ 'v.verband !=' => '',
+ 'v.aktiv' => true
+ ];
+
+ if ($org_form !== null && $semester) // NOTE(chris): on semester 0 show all?
+ $where['v.orgform_kurzbz'] = $org_form;
+
+ $result = $this->StudiengangModel->loadWhere($where);
+ $result = $this->getDataOrTerminateWithError($result);
+
+ $list = array_merge($list, $result);
+
+ $this->terminateWithSuccess($list);
+ }
+
+ /**
+ * @param integer $studiengang_kz
+ * @param integer $semester
+ * @param integer $verband
+ * @param string $orgform
+ *
+ * @return void
+ */
+ protected function getVerband($studiengang_kz, $semester, $verband, $org_form = null)
+ {
+ $link = $studiengang_kz . '/';
+ if ($org_form !== null)
+ $link .= $org_form . '/';
+ $link .= $semester . '/'. $verband . '/';
+
+
+ $this->StudiengangModel->addJoin('public.tbl_lehrverband v', 'studiengang_kz');
+
+ $this->StudiengangModel->addDistinct();
+ $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", gruppe) AS link", false);
+ $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, verband, gruppe, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester AND verband=v.verband AND gruppe=v.gruppe ORDER BY gruppe LIMIT 1)) AS name", false);
+ $this->StudiengangModel->addSelect("TRUE AS leaf", false);
+
+ $this->StudiengangModel->addSelect('gruppe');
+ $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false);
+
+ $this->StudiengangModel->addOrder('gruppe');
+
+ $where = [
+ 'v.studiengang_kz' => $studiengang_kz,
+ 'v.semester' => $semester,
+ 'v.verband' => $verband,
+ 'v.gruppe !=' => '',
+ 'v.aktiv' => true
+ ];
+
+ if ($org_form !== null && $semester) // NOTE(chris): on semester 0 show all?
+ $where['v.orgform_kurzbz'] = $org_form;
+
+ $result = $this->StudiengangModel->loadWhere($where);
+
+ $list = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($list);
+ }
+
+ /**
+ * @param string $link
+ * @param integer $studiengang_kz
+ *
+ * @return array
+ */
+ protected function getStdSem($link, $studiengang_kz)
+ {
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+
+ $this->load->model('system/Variable_model', 'VariableModel');
+ $result = $this->VariableModel->getVariables(getAuthUID(), ['number_displayed_past_studiensemester']);
+ $data = $this->getDataOrTerminateWithError($result);
+ $number_displayed_past_studiensemester = $data['number_displayed_past_studiensemester'] ?? null;
+
+ $this->StudiensemesterModel->addPlusMinus(null, $number_displayed_past_studiensemester);
+ $this->StudiensemesterModel->addOrder('ende');
+ $result = $this->StudiensemesterModel->load();
+
+ $studiensemester = $this->getDataOrTerminateWithError($result);
+ $result = [];
+
+ $studiengang_kz = (int)$studiengang_kz;
+
+ foreach ($studiensemester as $sem) {
+ $semlink = $link . $sem->studiensemester_kurzbz;
+ $intlink = $semlink . '/interessenten';
+ $result[] = [
+ 'name' => $sem->studiensemester_kurzbz,
+ 'link' => $semlink,
+ 'stg_kz' => $studiengang_kz,
+ 'children' => [
+ [
+ 'name' => 'Interessenten',
+ 'link' => $intlink,
+ 'stg_kz' => $studiengang_kz,
+ 'children' => [
+ [
+ 'name' => 'Bewerbung nicht abgeschickt',
+ 'link' => $intlink . '/bewerbungnichtabgeschickt',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Bewerbung abgeschickt, Status unbestätigt',
+ 'link' => $intlink . '/bewerbungabgeschickt',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'ZGV erfüllt',
+ 'link' => $intlink . '/zgv',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Status bestätigt',
+ 'link' => $intlink . '/statusbestaetigt',
+ 'stg_kz' => $studiengang_kz,
+ 'children' => [
+ [
+ 'name' => 'Nicht zum Reihungstest angemeldet',
+ 'link' => $intlink . '/statusbestaetigtrtnichtangemeldet',
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Reihungstest angemeldet',
+ 'link' => $intlink . '/statusbestaetigtrtangemeldet',
+ 'leaf' => true
+ ]
+ ]
+ ],
+ [
+ 'name' => 'Nicht zum Reihungstest angemeldet',
+ 'link' => $intlink . '/reihungstestnichtangemeldet',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Reihungstest angemeldet',
+ 'link' => $intlink . '/reihungstestangemeldet',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ]
+ ]
+ ],
+ [
+ 'name' => 'Bewerber',
+ 'link' => $semlink . '/bewerber',
+ 'stg_kz' => $studiengang_kz,
+ 'children' => [
+ [
+ 'name' => 'Nicht zum Reihungstest angemeldet',
+ 'link' => $intlink . '/bewerberrtnichtangemeldet',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Reihungstest angemeldet',
+ 'link' => $intlink . '/bewerberrtangemeldet',
+ 'stg_kz' => $studiengang_kz,
+ 'children' => [
+ [
+ 'name' => 'Teilgenommen',
+ 'link' => $intlink . '/bewerberrtangemeldetteilgenommen',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Nicht teilgenommen',
+ 'link' => $intlink . '/bewerberrtangemeldetnichtteilgenommen',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ]
+ ]
+ ]
+ ]
+ ],
+ [
+ 'name' => 'Aufgenommen',
+ 'link' => $semlink . '/aufgenommen',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Warteliste',
+ 'link' => $semlink . '/warteliste',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Absage',
+ 'link' => $semlink . '/absage',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Incoming',
+ 'link' => $semlink . '/incoming',
+ 'stg_kz' => $studiengang_kz,
+ 'leaf' => true
+ ]
+ ]
+ ];
+ }
+
+ return $result;
+ }
+}
diff --git a/application/controllers/api/v1/person/Person.php b/application/controllers/api/v1/person/Person.php
index a686f6060..6a373137f 100644
--- a/application/controllers/api/v1/person/Person.php
+++ b/application/controllers/api/v1/person/Person.php
@@ -264,4 +264,4 @@ class Person extends API_Controller
return success('Input data are valid');
}
-}
+}
\ No newline at end of file
diff --git a/application/controllers/codex/Bismeldestichtag.php b/application/controllers/codex/Bismeldestichtag.php
new file mode 100644
index 000000000..2723b2f7c
--- /dev/null
+++ b/application/controllers/codex/Bismeldestichtag.php
@@ -0,0 +1,140 @@
+ 'admin:r',
+ 'getStudiensemester' => 'admin:r',
+ 'getBismeldestichtage' => 'admin:r',
+ 'addBismeldestichtag' => 'admin:rw',
+ 'deleteBismeldestichtag' => 'admin:rw'
+ )
+ );
+
+ // Load models
+ $this->load->model('codex/Bismeldestichtag_model', 'BismeldestichtagModel');
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+
+ // Loads phrases system
+ $this->loadPhrases(
+ array(
+ 'bismeldestichtag'
+ )
+ );
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Everything has a beginning
+ */
+ public function index()
+ {
+ $this->load->view('codex/bismeldestichtag.php');
+ }
+
+ public function getStudiensemester()
+ {
+ // load semester list
+ $semList = array();
+ $this->StudiensemesterModel->addSelect('studiensemester_kurzbz');
+ $this->StudiensemesterModel->addOrder('start', 'DESC');
+ $semRes = $this->StudiensemesterModel->load();
+
+ if (hasData($semRes))
+ {
+ $semList = getData($semRes);
+ }
+
+ // load current semester
+ $currSem = null;
+ $semRes = $this->StudiensemesterModel->getAkt();
+
+ if (hasData($semRes))
+ {
+ $currSem = getData($semRes)[0]->studiensemester_kurzbz;
+ }
+
+ // output data
+ $this->outputJsonSuccess(
+ array('semList' => $semList, 'currSem' => $currSem)
+ );
+ }
+
+ public function getBismeldestichtage()
+ {
+ $this->BismeldestichtagModel->addSelect(
+ 'meldestichtag_id, meldestichtag,
+ tbl_bismeldestichtag.studiensemester_kurzbz, sem.start AS semester_start,
+ tbl_bismeldestichtag.insertamum, tbl_bismeldestichtag.insertvon, tbl_bismeldestichtag.updateamum, tbl_bismeldestichtag.updatevon'
+ );
+ $this->BismeldestichtagModel->addJoin('public.tbl_studiensemester sem', 'studiensemester_kurzbz', 'LEFT');
+ $this->BismeldestichtagModel->addOrder('semester_start');
+ $this->BismeldestichtagModel->addOrder('meldestichtag', 'DESC');
+ $this->BismeldestichtagModel->addOrder('meldestichtag_id', 'DESC');
+ $this->outputJson($this->BismeldestichtagModel->load());
+ }
+
+ public function addBismeldestichtag()
+ {
+ // get request data
+ $request = $this->getPostJSON();
+
+ // check request data
+ if (!property_exists($request, 'meldestichtag') || isEmptyString($request->meldestichtag))
+ $this->terminateWithJsonError('Error occured: Meldestichtag missing');
+ if (!property_exists($request, 'studiensemester_kurzbz') || isEmptyString($request->studiensemester_kurzbz))
+ $this->terminateWithJsonError('Error occured: Studiensemester missing');
+
+ $meldestichtag = $request->meldestichtag;
+ $studiensemester_kurzbz = $request->studiensemester_kurzbz;
+
+ // check if Bismeldestichtag already exists
+ $this->BismeldestichtagModel->addSelect('1');
+ $bismeldestichtagRes = $this->BismeldestichtagModel->loadWhere(
+ array('meldestichtag' => $meldestichtag, 'studiensemester_kurzbz' => $studiensemester_kurzbz)
+ );
+
+ // return success if already exists
+ if (hasData($bismeldestichtagRes))
+ $this->outputJsonSuccess('Bismeldestichtag already exists');
+ else
+ {
+ // insert new if Stichtag does not exist
+ $this->outputJson($this->BismeldestichtagModel->insert(
+ array(
+ 'meldestichtag' => $request->meldestichtag,
+ 'studiensemester_kurzbz' => $request->studiensemester_kurzbz,
+ 'insertvon' => getAuthUID()
+ )
+ ));
+ }
+ }
+
+ public function deleteBismeldestichtag()
+ {
+ // get request data
+ $request = $this->getPostJSON();
+
+ // check request data
+ if (!property_exists($request, 'meldestichtag_id'))
+ $this->terminateWithJsonError('Error occured: Meldestichtag Id missing');
+
+ $meldestichtag_id = $request->meldestichtag_id;
+
+ // deletetion
+ $this->outputJson($this->BismeldestichtagModel->delete($meldestichtag_id));
+ }
+}
diff --git a/application/controllers/codex/UHSTAT1.php b/application/controllers/codex/UHSTAT1.php
index 6bbd4d4f8..ff59ef41a 100644
--- a/application/controllers/codex/UHSTAT1.php
+++ b/application/controllers/codex/UHSTAT1.php
@@ -5,8 +5,12 @@ if (! defined("BASEPATH")) exit("No direct script access allowed");
class UHSTAT1 extends FHC_Controller
{
const BERECHTIGUNG_UHSTAT_VERWALTEN = 'student/uhstat1daten_verwalten';
+ const LOGIN_SESSION_INDEX = 'bewerbung/user';
const PERSON_ID_SESSION_INDEX = 'bewerbung/personId';
const CODEX_OESTERREICH = 'A';
+ const CODEX_UNKNOWN_YEAR = 9999;
+ const CODEX_UNKNOWN_NATION = 'XXX';
+ const CODEX_UNKNOWN_BILDUNGMAX = 999;
const LOWER_BOUNDARY_YEARS = 160;
const UPPER_BOUNDARY_YEARS = 20;
@@ -210,7 +214,9 @@ class UHSTAT1 extends FHC_Controller
else
return true;
- if (!isset($bildungsstaat)) return true;
+ // if no Bildungsstaat or Bildungmax unknown - valid
+ if (!isset($bildungsstaat) || $bildungmax == self::CODEX_UNKNOWN_BILDUNGMAX) return true;
+
// find out if abschluss is in Austria
$this->AbschlussModel->addSelect("in_oesterreich");
@@ -219,8 +225,11 @@ class UHSTAT1 extends FHC_Controller
if (hasData($abschlussRes))
{
$in_oesterreich = getData($abschlussRes)[0]->in_oesterreich;
- // invalid if abschluss in Austria, but not Bildungsstaat, or abschluss not in Austria, but Bildungsstaat in Austria
- return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH) || (!$in_oesterreich && $bildungsstaat != self::CODEX_OESTERREICH);
+
+ // valid if Bildungsstaat and Abschluss in Austria, or Bildungsstaat and Abschluss not in Austria
+ // (or Abschluss not in Austria and Bildungsstaat unknown)
+ return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH)
+ || (!$in_oesterreich && ($bildungsstaat != self::CODEX_OESTERREICH || $bildungsstaat == self::CODEX_UNKNOWN_NATION));
}
return false;
@@ -321,7 +330,7 @@ class UHSTAT1 extends FHC_Controller
$this->NationModel->addSelect("nation_code, $nationTextFieldName AS nation_text");
$this->NationModel->addOrder("nation_text");
- $nationRes = $this->NationModel->load();
+ $nationRes = $this->NationModel->loadWhere('sperre IS NULL OR sperre = FALSE');
if (isError($nationRes)) return $nationRes;
@@ -363,7 +372,11 @@ class UHSTAT1 extends FHC_Controller
// get realistic birth years, dated back from current year
$currYear = date("Y");
- $formMetaData['jahre'] = range($currYear - self::UPPER_BOUNDARY_YEARS, $currYear - self::LOWER_BOUNDARY_YEARS);
+ $yearRange = range($currYear - self::UPPER_BOUNDARY_YEARS, $currYear - self::LOWER_BOUNDARY_YEARS);
+ $formMetaData['jahre'] = array_combine($yearRange, $yearRange);
+
+ // add "unknown" option
+ $formMetaData['jahre'][self::CODEX_UNKNOWN_YEAR] = 'unbekannt';
return success($formMetaData);
}
@@ -411,7 +424,10 @@ class UHSTAT1 extends FHC_Controller
private function _getValidPersonId($berechtigungsArt)
{
// if coming from bewerbungstool - person id is in session (person must be logged in bewerbungstool)
- if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX]) && is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX]))
+ if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX])
+ && is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX])
+ && isset($_SESSION[self::LOGIN_SESSION_INDEX])
+ )
return $_SESSION[self::PERSON_ID_SESSION_INDEX];
// if person id passed directly...
diff --git a/application/controllers/components/Filter.php b/application/controllers/components/Filter.php
index ab7e1493e..617edd69f 100644
--- a/application/controllers/components/Filter.php
+++ b/application/controllers/components/Filter.php
@@ -9,6 +9,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
* NOTE: extends the FHC_Controller instead of the Auth_Controller because the FilterCmpt has its
* own permissions check
+ * TODO(chris): deprecated
*/
class Filter extends FHC_Controller
{
@@ -26,6 +27,9 @@ class Filter extends FHC_Controller
// Loads authentication library and starts authentication
$this->load->library('AuthLib');
+ // Loads the FiltersModel
+ $this->load->model('system/Filters_model', 'FiltersModel');
+
// Loads the FilterCmptLib with HTTP GET/POST parameters
$this->_startFilterCmptLib();
}
diff --git a/application/controllers/components/Phrasen.php b/application/controllers/components/Phrasen.php
new file mode 100644
index 000000000..3ac35a652
--- /dev/null
+++ b/application/controllers/components/Phrasen.php
@@ -0,0 +1,22 @@
+load->library('PhrasesLib', [$module], 'pj');
+ $this->outputJsonSuccess(json_decode($this->pj->getJSON()));
+ }
+}
diff --git a/application/controllers/components/SearchBar.php b/application/controllers/components/SearchBar.php
index dd3c22690..eac1a4cbc 100644
--- a/application/controllers/components/SearchBar.php
+++ b/application/controllers/components/SearchBar.php
@@ -3,7 +3,7 @@
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
- *
+ * TODO(chris): deprecated
*/
class SearchBar extends FHC_Controller
{
@@ -17,11 +17,17 @@ class SearchBar extends FHC_Controller
{
parent::__construct();
- // Loads the AuthLib and starts the authentication
+ // Loads the AuthLib _without_ starting the authentication
+ // NOTE:
+ // - A user must be authenticated via another controller to access this one
+ // - It is loaded to be able to call the isLogged function later
$this->load->library('AuthLib');
// Load the library SearchBarLib
$this->load->library('SearchBarLib');
+
+ // Checks if the user is authenticated, otherwise returns an error code in JSON format
+ if (!isLogged()) $this->terminateWithJsonError(SearchBarLib::ERROR_NOT_AUTH);
}
//------------------------------------------------------------------------------------------------------------------
diff --git a/application/controllers/components/stv/Noten.php b/application/controllers/components/stv/Noten.php
new file mode 100644
index 000000000..fb61de065
--- /dev/null
+++ b/application/controllers/components/stv/Noten.php
@@ -0,0 +1,168 @@
+ 'student/noten:r',
+ 'getZeugnis' => 'student/noten:r',
+ 'update' => ['admin:w', 'assistenz:w']
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ }
+
+ public function get()
+ {
+ $this->load->model('codex/Note_model', 'NoteModel');
+
+ $result = $this->NoteModel->addOrder('note');
+
+ $result = $this->NoteModel->load();
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ return $this->outputJson($result);
+ }
+
+ public function getZeugnis($prestudent_id, $all = null)
+ {
+ $this->load->model('crm/Student_model', 'StudentModel');
+ $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
+
+ $result = $this->StudentModel->loadWhere([
+ 'prestudent_id' => $prestudent_id
+ ]);
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ return $this->outputJson($result);
+ }
+ if (!hasData($result))
+ return $this->outputJsonSuccess(null);
+
+ $student_uid = current(getData($result))->student_uid;
+
+ $studiensemester_kurzbz = ($all === null) ? $this->variablelib->getVar('semester_aktuell') : null;
+
+ $result = $this->ZeugnisnoteModel->getZeugnisnoten($student_uid, $studiensemester_kurzbz);
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ return $this->outputJson($result);
+ }
+
+ public function update()
+ {
+ $this->load->model('crm/Student_model', 'StudentModel');
+ $this->load->model('organisation/Studienplan_model', 'StudienplanModel');
+ $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
+ $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
+
+ $this->load->library('form_validation');
+
+ $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
+
+ if (empty($_POST) || !is_array(current($_POST))) {
+ $result = $this->hasPermissionUpdate($this->input->post('lehrveranstaltung_id'), $this->input->post('student_uid'));
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN);
+ return $this->outputJson($result);
+ }
+
+ $this->form_validation->set_rules('lehrveranstaltung_id', 'Lehrverantaltung ID', 'required|numeric');
+ $this->form_validation->set_rules('student_uid', 'Student UID', 'required');
+ $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester Kurzbezeichnung', 'required');
+ $this->form_validation->set_rules('note', 'Note', 'required|numeric');
+ $post = [$_POST];
+ } else {
+ foreach ($_POST as $i => $data) {
+ $lvid = isset($data['lehrveranstaltung_id']) ? $data['lehrveranstaltung_id'] : null;
+ $uid = isset($data['student_uid']) ? $data['student_uid'] : null;
+ $result = $this->hasPermissionUpdate($lvid, $uid);
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN);
+ return $this->outputJson($result);
+ }
+
+ $this->form_validation->set_rules($i . '[lehrveranstaltung_id]', '#' . $i . ' Lehrverantaltung ID', 'required|numeric');
+ $this->form_validation->set_rules($i . '[student_uid]', '#' . $i . ' Student UID', 'required');
+ $this->form_validation->set_rules($i . '[studiensemester_kurzbz]', '#' . $i . ' Studiensemester Kurzbezeichnung', 'required');
+ $this->form_validation->set_rules($i . '[note]', '#' . $i . ' Note', 'required|numeric');
+ }
+ $post = $_POST;
+ }
+ if ($this->form_validation->run() == false) {
+ $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
+ return $this->outputJsonError($this->form_validation->error_array());
+ }
+
+ $final_result = success();
+ $this->ZeugnisnoteModel->db->trans_start();
+
+ foreach ($post as $i => $data) {
+ $note = $data['note'];
+ unset($data['note']);
+ $result = $this->ZeugnisnoteModel->update($data, [
+ 'note' => $note,
+ 'benotungsdatum' => date('c'),
+ 'updateamum' => date('c'),
+ 'updatevon' => getAuthUID()
+ ]);
+ if (isError($result)) {
+ $final_result = $result;
+ break;
+ }
+ }
+
+ $this->ZeugnisnoteModel->db->trans_complete();
+
+ if (isError($final_result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ $this->outputJson($final_result);
+ }
+
+ protected function hasPermissionUpdate($lehrveranstaltung_id, $student_uid)
+ {
+ // TODO(chris): error phrases!
+ if ($lehrveranstaltung_id === null || $student_uid === null)
+ return success();
+ $result = $this->StudentModel->load([$student_uid]);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error('Fehler beim Ermitteln des Studenten');
+ $student = current(getData($result));
+
+ if ($this->permissionlib->isBerechtigt('admin', 'suid', $student->studiengang_kz))
+ return success();
+ if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $student->studiengang_kz))
+ return success();
+
+ $result = $this->StudienplanModel->getAllOesForLv($lehrveranstaltung_id);
+ if (isError($result))
+ return $result;
+ $oes = getData($result) ?: [];
+ $result = $this->LehrveranstaltungModel->getStg($lehrveranstaltung_id);
+ if (isError($result))
+ return $result;
+ if (hasData($result))
+ $oes[] = current(getData($result));
+
+ foreach ($oes as $oe) {
+ if ($this->permissionlib->isBerechtigt('admin', 'suid', $oe->oe_kurzbz))
+ return success();
+ if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $oe->oe_kurzbz))
+ return success();
+ }
+
+ return error('Forbidden');
+ }
+}
diff --git a/application/controllers/components/stv/Studienplan.php b/application/controllers/components/stv/Studienplan.php
new file mode 100644
index 000000000..b60388ac1
--- /dev/null
+++ b/application/controllers/components/stv/Studienplan.php
@@ -0,0 +1,43 @@
+ self::PERM_LOGGED
+ ]);
+ }
+
+ public function get()
+ {
+ $this->load->model('organisation/Studienplan_model', 'StudienplanModel');
+
+ $_POST = json_decode($this->input->raw_input_stream, true);
+
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('studiengang_kz', 'StudiengangKz', 'required|numeric');
+ $this->form_validation->set_rules('studiensemester_kurzbz', 'StudiensemesterKurbz', 'required');
+ $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'numeric');
+
+ if ($this->form_validation->run() == false) {
+ $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
+ return $this->outputJsonError($this->form_validation->error_array());
+ }
+
+ $studiengang_kz = $this->input->post('studiengang_kz');
+ $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
+ $ausbildungssemester = $this->input->post('ausbildungssemester') ?: null;
+ $orgform_kurzbz = $this->input->post('orgform_kurzbz') ?: null;
+
+ $result = $this->StudienplanModel->getStudienplaeneBySemester($studiengang_kz, $studiensemester_kurzbz, $ausbildungssemester, $orgform_kurzbz);
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ }
+ $this->outputJson($result);
+ }
+}
diff --git a/application/controllers/components/stv/Studiensemester.php b/application/controllers/components/stv/Studiensemester.php
new file mode 100644
index 000000000..c3db99686
--- /dev/null
+++ b/application/controllers/components/stv/Studiensemester.php
@@ -0,0 +1,78 @@
+ self::PERM_LOGGED,
+ 'now' => self::PERM_LOGGED,
+ 'set' => self::PERM_LOGGED
+ ]);
+ }
+
+ public function index()
+ {
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+
+ $this->StudiensemesterModel->addOrder('start');
+
+ $result = $this->StudiensemesterModel->load();
+
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ }
+ $this->outputJson($result);
+ }
+
+ public function now()
+ {
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+
+ $result = $this->StudiensemesterModel->getNearest();
+
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ $this->outputJson(getError($result));
+ }
+ $result = getData($result) ?: [];
+
+ if (count($result) != 1) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ $this->outputJsonError(count($result) ? 'Mehrere Studiensemester aktiv' : 'Kein Studiensemester aktiv');
+ } else {
+ $this->outputJsonSuccess(current($result)->studiensemester_kurzbz);
+ }
+ }
+
+ public function set()
+ {
+ $this->load->library('AuthLib');
+ $this->load->library('form_validation');
+
+ $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
+
+ $this->form_validation->set_rules('studiensemester', 'Studiensemester', 'required');
+
+ if ($this->form_validation->run() == false) {
+ $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
+ return $this->outputJsonError($this->form_validation->error_array());
+ }
+
+ $stdsem = $this->input->post('studiensemester');
+
+ $this->load->model('system/Variable_model', 'VariableModel');
+
+ $result = $this->VariableModel->setVariable(getAuthUID(), 'semester_aktuell', $stdsem);
+
+ if (isError($result)) {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ return $this->outputJson($result);
+ }
+
+ $this->outputJsonSuccess(true);
+ }
+}
diff --git a/application/controllers/jobs/AntragJob.php b/application/controllers/jobs/AntragJob.php
new file mode 100644
index 000000000..46a31f3d6
--- /dev/null
+++ b/application/controllers/jobs/AntragJob.php
@@ -0,0 +1,707 @@
+load->config('studierendenantrag');
+
+ // Loads SanchoHelper
+ $this->load->helper('hlp_sancho_helper');
+
+ $this->load->library('AntragLib');
+
+ // Load Model
+ $this->load->model('education/Studierendenantrag_model', 'StudierendenantragModel');
+ $this->load->model('education/Studierendenantragstatus_model', 'StudierendenantragstatusModel');
+ $this->load->model('education/Pruefung_model', 'PruefungModel');
+ $this->load->model('person/Kontakt_model', 'KontaktModel');
+ $this->load->model('crm/Student_model', 'StudentModel');
+ $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+
+ $this->loadPhrases([
+ 'lehre'
+ ]);
+ }
+
+ /**
+ * Send infomail to Stgl
+ */
+ public function sendStglSammelmail()
+ {
+ $this->load->model('person/Person_model', 'PersonModel');
+
+ $this->logInfo('Start Job sendStglSammelmail');
+
+ $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
+
+ $this->StudierendenantragModel->addJoin('public.tbl_prestudent', 'prestudent_id');
+ $this->db->group_start();
+ $this->db->where('typ', Studierendenantrag_model::TYP_ABMELDUNG);
+ $this->db->where('campus.get_status_studierendenantrag(studierendenantrag_id)', Studierendenantragstatus_model::STATUS_CREATED);
+ $this->db->group_end();
+
+ $this->db->or_group_start();
+ $this->db->where('typ', Studierendenantrag_model::TYP_ABMELDUNG_STGL);
+ $this->db->where('campus.get_status_studierendenantrag(studierendenantrag_id)', Studierendenantragstatus_model::STATUS_CREATED);
+ $this->db->group_end();
+
+ $this->db->or_group_start();
+ $this->db->where('typ', Studierendenantrag_model::TYP_UNTERBRECHUNG);
+ $this->db->where('campus.get_status_studierendenantrag(studierendenantrag_id)', Studierendenantragstatus_model::STATUS_CREATED);
+ $this->db->group_end();
+
+ $this->db->or_group_start();
+ $this->db->where('typ', Studierendenantrag_model::TYP_WIEDERHOLUNG);
+ $this->db->where('campus.get_status_studierendenantrag(studierendenantrag_id)', Studierendenantragstatus_model::STATUS_LVSASSIGNED);
+ $this->db->group_end();
+
+ $result = $this->StudierendenantragModel->load();
+ if(isError($result))
+ return $this->logError(getError($result));
+
+ if(!hasData($result))
+ return $this->logInfo('End Job sendStglSammelmail: 0 Mails sent');
+
+ $antraege = getData($result);
+
+ $stgs = array();
+ $stgLeitungen = array();
+
+ foreach ($antraege as $antrag)
+ {
+ if (!isset($stgs[$antrag->studiengang_kz]))
+ {
+ $result = $this->StudiengangModel->getLeitung($antrag->studiengang_kz);
+ if (isError($result))
+ {
+ $this->logError(getError($result));
+ continue;
+ }
+ if (!hasData($result))
+ {
+ $this->logError('Keine Leitung für Studiengang ' . $antrag->studiengang_kz . ' gefunden!');
+ continue;
+ }
+
+ $leitung = current(getData($result));
+ if (!isset($stgLeitungen[$leitung->uid]))
+ {
+ $stgLeitungen[$leitung->uid] = [ 'Details' => $leitung, 'stgs' => [] ];
+ }
+ $stgLeitungen[$leitung->uid]['stgs'][] = $antrag->studiengang_kz;
+
+ $result = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id);
+ if (isError($result))
+ {
+ $this->logError(getError($result));
+ continue;
+ }
+ if (!hasData($result))
+ {
+ $this->logError('Keine Details für Studiengang ' . $antrag->studiengang_kz . ' gefunden!');
+ continue;
+ }
+ $details = current(getData($result));
+
+ $stgs[$antrag->studiengang_kz] = [
+ 'Abmeldung' => [],
+ 'Unterbrechung' => [],
+ 'Wiederholung' => [],
+ 'Details' => $details
+ ];
+ }
+ $stgs[$antrag->studiengang_kz][str_replace('Stgl', '', $antrag->typ)] = $antrag;
+ }
+
+ $this->load->model('system/Sprache_model', 'SpracheModel');
+ $result = $this->SpracheModel->loadWhere(['content' => true]);
+ if (isError($result)) {
+ $this->logError(getError($result));
+ $languages = [DEFAULT_LANGUAGE];
+ } elseif (!hasData($result)) {
+ $languages = [DEFAULT_LANGUAGE];
+ } else {
+ $languages = array_map(function ($row) {
+ return $row->sprache;
+ }, getData($result));
+ }
+
+ $count = 0;
+ foreach ($stgLeitungen as $leitung)
+ {
+ $data = [
+ 'name' => trim($leitung['Details']->vorname . ' ' . $leitung['Details']->nachname),
+ 'vorname' => $leitung['Details']->vorname,
+ 'nachname' => $leitung['Details']->nachname
+ ];
+
+ foreach ($languages as $lang) {
+ unset($this->p);
+ $this->loadPhrases(['studierendenantrag'], $lang);
+
+ $table = '';
+ foreach ($leitung['stgs'] as $studiengang_kz) {
+ $rows = '';
+ $stg = $stgs[$studiengang_kz];
+ foreach (['Abmeldung', 'Unterbrechung', 'Wiederholung'] as $typ) {
+ $c = count($stg[$typ]);
+ if ($c) {
+ $rows .= $this->p->t('studierendenantrag', 'mail_part_x_new_' . $typ, ['count' => $c]);
+ }
+ }
+ $table .= $this->p->t('studierendenantrag', 'mail_part_table', [
+ 'stg_bezeichnung' => $stg['Details']->bezeichnung,
+ 'stg_orgform_kurzbz' => $stg['Details']->orgform_kurzbz,
+ 'rows' => $rows
+ ]);
+ }
+ $data['table_' . $lang] = $table;
+ }
+
+ $data['table'] = $data['table_' . DEFAULT_LANGUAGE];
+ $data['leitungLink'] = APP_ROOT. 'index.ci.php/lehre/Studierendenantrag/leitung';
+
+ //Mail an Stgl und Assistenz
+ $to = $leitung['Details']->uid . '@' . DOMAIN;
+ $cc = $leitung['Details']->email;
+
+ // NOTE(chris): Sancho mail
+ if (sendSanchoMail(
+ "Sancho_Mail_Antrag_Stgl",
+ $data,
+ $to,
+ 'Anträge - Aktion(en) erforderlich',
+ DEFAULT_SANCHO_HEADER_IMG,
+ DEFAULT_SANCHO_FOOTER_IMG,
+ '',
+ $cc
+ ))
+ $count++;
+ }
+
+ $this->logInfo($count . " Emails erfolgreich versandt");
+
+ $this->logInfo('End Job sendStglSammelmail');
+ }
+
+ /**
+ * Send reminder to Assistant for Wiedereinstieg Unterbrecher
+ *
+ */
+ public function sendReminderWiedereinstieg()
+ {
+ $now = new DateTime();
+ $modifier = $this->config->item('unterbrechung_job_remind_wiedereinstieg_date_modifier');
+ if (!$modifier)
+ return $this->logError('Konnte Job nicht starten: Config "unterbrechung_job_remind_wiedereinstieg_date_modifiers" nicht gesetzt');
+
+ $end = new DateTime();
+ $end->modify($modifier);
+
+ $this->logInfo(sprintf(
+ 'Start Job sendReminderWiedereinstieg (Wiedereinstieg zwischen %s - %s)',
+ $now->format('Y-m-d'),
+ $end->format('Y-m-d')
+ ));
+
+ $result = $this->StudierendenantragModel->getAntraegeWhereWiedereinstiegBetween($now, $end);
+
+ if(isError($result))
+ {
+ $this->logError(getError($result));
+ $this->logInfo('Ende Job sendReminderWiedereinstieg');
+ return;
+ }
+
+ $antraege = getData($result) ?: [];
+ $count = 0;
+ foreach ($antraege as $antrag)
+ {
+ $res = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id);
+ $stg = '';
+ $orgform = '';
+ if (hasData($res)) {
+ $studiengang = current(getData($res));
+ $stg = $studiengang->bezeichnung;
+ $orgform = $studiengang->orgform_kurzbz;
+ }
+
+ $datum = new DateTime($antrag->datum_wiedereinstieg);
+ $data = array(
+ 'prestudent' => $antrag->prestudent_id,
+ 'name' => trim($antrag->vorname . ' '. $antrag->nachname),
+ 'datum_wiedereinstieg' => $datum->format('d.m.Y'),
+ 'vorname' => $antrag->vorname,
+ 'nachname' => $antrag->nachname,
+ 'Orgform' => $orgform,
+ 'stg' => $stg
+ );
+ $result = $this->StudentModel->loadWhere(['prestudent_id'=> $antrag->prestudent_id]);
+ if (hasData($result)) {
+ $student = current(getData($result));
+ $data['UID'] = $student->student_uid;
+ }
+
+ // NOTE(chris): Sancho mail
+ if(sendSanchoMail('Sancho_Mail_Antrag_U_Reminder', $data, $antrag->email, 'Reminder: Unterbrechung Wiedereinstieg'))
+ {
+ $count++;
+ $this->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag->studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_REMINDERSENT,
+ 'insertvon' => 'AntragJob'
+ ]);
+ }
+ }
+ $this->logInfo($count . ' Reminder gesendet - Ende Job sendReminderWiedereinstieg');
+ }
+
+ /**
+ * Set Wiederholer after deadline to Abbrecher
+ *
+ */
+ public function handleWiederholerDeadline()
+ {
+ $this->logInfo('Start Job handleWiederholerDeadline');
+
+ $this->load->library('PrestudentLib');
+
+ $insertvon = $this->config->item('antrag_job_systemuser');
+ if (!$insertvon) {
+ $this->logError('Config "antrag_job_systemuser" nicht gesetzt');
+ $this->logInfo('Ende Job handleWiederholerDeadline');
+ return;
+ }
+
+ $modifier_deadline = $this->config->item('wiederholung_job_deadline_date_modifier');
+ if (!$modifier_deadline) {
+ $this->logError('Config "wiederholung_job_deadline_date_modifier" nicht gesetzt');
+ $this->logInfo('Ende Job handleWiederholerDeadline');
+ return;
+ }
+
+ $digi_start= $this->config->item('digitalization_start');
+ if($digi_start)
+ $digi_start = new DateTime($digi_start);
+
+ $dateDeadline = new DateTime();
+ $dateDeadline->sub(DateInterval::createFromDateString($modifier_deadline));
+
+ $result = $this->PruefungModel->getAllPrestudentsWhereCommitteeExamFailed(
+ [
+ Studierendenantragstatus_model::STATUS_REQUESTSENT_1,
+ Studierendenantragstatus_model::STATUS_REQUESTSENT_2
+ ],
+ $dateDeadline,
+ $digi_start
+ );
+ if(isError($result))
+ {
+ $this->logError(getError($result));
+ }
+ else
+ {
+ $prestudents = getData($result) ?: [];
+ $count = 0;
+
+ $prestudents = $this->prestudentsGetUnique($prestudents);
+
+
+ foreach ($prestudents as $prestudent)
+ {
+ $result = $this->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $prestudent->studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED,
+ 'insertvon' => 'AntragJob'
+ ]);
+ if (isError($result)) {
+ $this->logError(getError($result));
+ } else {
+ $deregisterStatus = getData($result);
+
+ $result = $this->antraglib->pauseAntrag(
+ $prestudent->studierendenantrag_id,
+ Studierendenantragstatus_model::INSERTVON_DEREGISTERED
+ );
+ if (isError($result))
+ $this->logError(getError($result));
+
+ $result = $this->prestudentlib->setAbbrecher($prestudent->prestudent_id, '', $insertvon);
+ if (isError($result)) {
+ $this->StudierendenantragstatusModel->delete($deregisterStatus);
+ $this->logError(getError($result));
+ } else {
+ $count++;
+
+ $datum_kp = new DateTime($prestudent->datum);
+ $dataMail = array(
+ 'name'=> trim($prestudent->vorname . ' '. $prestudent->nachname),
+ 'vorname' => $prestudent->vorname,
+ 'nachname' => $prestudent->nachname,
+ 'pers_kz'=> $prestudent->matrikelnr,
+ 'stg' => $prestudent->bezeichnung,
+ 'lvbezeichnung' => $prestudent->lvbezeichnung,
+ 'datum_kp' => $datum_kp->format('d.m.Y'),
+ 'studiensemester'=> $prestudent->studiensemester_kurzbz,
+ 'Orgform'=> $prestudent->orgform,
+ 'prestudent_id' => $prestudent->prestudent_id,
+ 'fristablauf' => $dateDeadline->format('d.m.Y')
+ );
+
+ $email = $this->StudentModel->getEmailFH($this->StudentModel->getUID($prestudent->prestudent_id));
+ // Mail to Student
+ if (!sendSanchoMail('Sancho_Mail_Antrag_W_DL_Stud', $dataMail, $email, 'Wiederholung: Frist abgelaufen')) {
+ $this->logWarning("Failed to send Notification to " . $email);
+ }
+
+ $result = $this->StudiengangModel->load($prestudent->studiengang_kz);
+ if (!hasData($result)) {
+ $this->logWarning('No Studiengang found');
+ continue;
+ }
+ $studiengang = current(getData($result));
+ $email = $studiengang->email;
+ // Mail to Assistenz
+ if (!sendSanchoMail('Sancho_Mail_Antrag_W_DL_Assist', $dataMail, $email, 'Wiederholung: Frist abgelaufen')) {
+ $this->logWarning("Failed to send Notification to " . $email);
+ }
+ }
+ }
+ }
+ $this->logInfo($count . " Students set to Abbrecher");
+ }
+
+ $this->logInfo('Ende Job handleWiederholerDeadline');
+ }
+
+ /**
+ * Set Abmeldungen after deadline to Abbrecher
+ *
+ */
+ public function handleAbmeldungenStglDeadline()
+ {
+ $this->logInfo('Start Job handleAbmeldungenStglDeadline');
+
+ $insertvon = $this->config->item('antrag_job_systemuser');
+ if (!$insertvon) {
+ $this->logError('Config "antrag_job_systemuser" nicht gesetzt');
+ $this->logInfo('Ende Job handleAbmeldungenStglDeadline');
+ return;
+ }
+
+ $modifier_deadline = $this->config->item('abmeldung_job_deadline_date_modifier');
+ if (!$modifier_deadline) {
+ $this->logError('Config "abmeldung_job_deadline_date_modifier" nicht gesetzt');
+ $this->logInfo('Ende Job handleAbmeldungenStglDeadline');
+ return;
+ }
+
+ $dateDeadline = new DateTime();
+ $dateDeadline->sub(DateInterval::createFromDateString($modifier_deadline));
+
+ $this->StudierendenantragModel->addSelect('tbl_studierendenantrag.studierendenantrag_id');
+ $this->StudierendenantragModel->addSelect('prestudent_id');
+ $this->StudierendenantragModel->addSelect('studiensemester_kurzbz');
+ $this->StudierendenantragModel->addSelect('s.insertamum');
+ $this->StudierendenantragModel->addSelect('s.insertvon');
+ $this->StudierendenantragModel->addJoin('public.tbl_student pts', 'prestudent_id');
+ $this->StudierendenantragModel->addSelect('pts.student_uid');
+
+ $this->StudierendenantragModel->db->where_in(
+ 'public.get_rolle_prestudent(prestudent_id, studiensemester_kurzbz)',
+ $this->config->item('antrag_prestudentstatus_whitelist_abmeldung')
+ );
+
+ $result = $this->StudierendenantragModel->getWithLastStatusWhere([
+ 'typ' => Studierendenantrag_model::TYP_ABMELDUNG_STGL,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED,
+ 's.insertamum <=' => $dateDeadline->format('c')
+ ]);
+
+ if(isError($result))
+ {
+ $this->logError(getError($result));
+ }
+ else
+ {
+ $antraege = getData($result) ?: [];
+ $count = 0;
+
+ foreach ($antraege as $antrag)
+ {
+ $result = $this->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag->studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED,
+ 'insertvon' => 'AntragJob'
+ ]);
+ if (isError($result))
+ $this->logError(getError($result));
+ else {
+ $deregisterStatus = getData($result);
+
+ $result = $this->antraglib->pauseAntrag($antrag->studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_DEREGISTERED);
+ if (isError($result))
+ $this->logError(getError($result));
+
+ $this->load->model('crm/Statusgrund_model', 'StatusgrundModel');
+ $result = $this->StatusgrundModel->loadWhere(['statusgrund_kurzbz' => 'abbrecherStgl']);
+ if (isError($result)) {
+ $this->logError(getError($result));
+ continue;
+ } elseif (!hasData($result)) {
+ $this->logError($this->p->t('lehre', 'error_noStatusgrund', ['statusgrund_kurzbz' => 'abbrecherStgl']));
+ continue;
+ }
+
+ $statusgrund = current(getData($result));
+
+ $result = $this->prestudentlib->setAbbrecher(
+ $antrag->prestudent_id,
+ $antrag->studiensemester_kurzbz,
+ 'AntragJob',
+ $statusgrund->statusgrund_id,
+ $antrag->insertamum,
+ null,
+ $antrag->insertvon ?: $insertvon
+ );
+ if (isError($result)) {
+ $this->StudierendenantragstatusModel->delete($deregisterStatus);
+ $this->logError(getError($result));
+ } else {
+ $count++;
+ $result = $this->PrestudentModel->load($antrag->prestudent_id);
+ if(!hasData($result)) {
+ $this->logWarning('No Prestudent found');
+ continue;
+ }
+ $prestudent = current(getData($result));
+ $result = $this->StudiengangModel->load($prestudent->studiengang_kz);
+ if(!hasData($result)) {
+ $this->logWarning('No Studiengang found');
+ continue;
+ }
+ $studiengang = current(getData($result));
+ $result = $this->PersonModel->loadPrestudent($antrag->prestudent_id);
+ if(!hasData($result))
+ {
+ $this->logWarning('No Person found');
+ continue;
+ }
+ $person = current(getData($result));
+ $email = $studiengang->email;
+ $dataMail = array(
+ 'prestudent' => 'UID: ' . $antrag->student_uid . ', PreStudentId: ' . $antrag->prestudent_id,
+ 'studiensemester' => $antrag->studiensemester_kurzbz,
+ 'name' => trim($person->vorname . ' '. $person->nachname),
+ );
+
+ if(!sendSanchoMail('Sancho_Mail_Antrag_A_Assist', $dataMail, $email, 'Einspruchsfrist abgelaufen'))
+ {
+ $this->logWarning("Failed to send Notification to " . $email);
+ }
+ }
+ }
+ }
+ $this->logInfo($count . "/" . count($antraege) . " Students set to Abbrecher");
+ }
+ $this->logInfo('Ende Job handleAbmeldungenStglDeadline');
+ }
+
+ /**
+ * Send Request to Student do Decide between Wiederholung and Verzicht
+ *
+ */
+ public function sendAufforderungWiederholer()
+ {
+ $this->logInfo('Start Job sendAufforderungWiederholer');
+
+ $modifier_request_1 = $this->config->item('wiederholung_job_request_1_date_modifier');
+ $modifier_request_2 = $this->config->item('wiederholung_job_request_2_date_modifier');
+ $modifier_deadline = $this->config->item('wiederholung_job_deadline_date_modifier');
+
+ $digi_start = $this->config->item('digitalization_start');
+ if ($digi_start) {
+ try {
+ $digi_start = new DateTime($digi_start);
+ } catch(Exception $e) {
+ }
+ }
+
+ if ($modifier_deadline) {
+ $dateDeadline = new DateTime();
+ $dateDeadline->sub(DateInterval::createFromDateString($modifier_deadline));
+
+ if ($digi_start)
+ $dateDeadline = max($digi_start, $dateDeadline);
+ } else {
+ $dateDeadline = $digi_start ?: null;
+ }
+
+ //first request
+ if ($modifier_request_1) {
+ $dateStichtag = new DateTime();
+ $dateStichtag->sub(DateInterval::createFromDateString($modifier_request_1));
+ if (!$dateDeadline || $dateStichtag > $dateDeadline)
+ $this->sendReminder(
+ 'Request1',
+ null,
+ Studierendenantragstatus_model::STATUS_REQUESTSENT_1,
+ $dateDeadline,
+ $dateStichtag,
+ $modifier_deadline,
+ 'Aufforderung: Bekanntgabe Wiederholung'
+ );
+ } else
+ $this->logError('Config "wiederholung_job_request_1_date_modifier" nicht gesetzt');
+
+ //second request
+ if ($modifier_request_2) {
+ $dateStichtag = new DateTime();
+ $dateStichtag->sub(DateInterval::createFromDateString($modifier_request_2));
+ if (!$dateDeadline || $dateStichtag > $dateDeadline)
+ $this->sendReminder(
+ 'Request2',
+ Studierendenantragstatus_model::STATUS_REQUESTSENT_1,
+ Studierendenantragstatus_model::STATUS_REQUESTSENT_2,
+ $dateDeadline,
+ $dateStichtag,
+ $modifier_deadline,
+ 'Reminder Aufforderung: Bekanntgabe Wiederholung'
+ );
+ } else
+ $this->logError('Config "wiederholung_job_request_2_date_modifier" nicht gesetzt');
+
+ $this->logInfo('Ende Job sendAufforderungWiederholer');
+ }
+
+ protected function prestudentsGetUnique($prestudents)
+ {
+ $result = [];
+ foreach ($prestudents as $prestudent) {
+ if (!isset($result[$prestudent->prestudent_id]))
+ $result[$prestudent->prestudent_id] = $prestudent;
+ else {
+ if ($result[$prestudent->prestudent_id]->datum > $prestudent->datum)
+ $result[$prestudent->prestudent_id] = $prestudent;
+ }
+ }
+ return $result;
+ }
+
+ protected function sendReminder($name, $status_from, $status_to, $deadline, $date_stichtag, $modifier_deadline, $subject)
+ {
+ $this->logInfo('Start Job sendAufforderungWiederholer ' . $name);
+
+ $result = $this->PruefungModel->getAllPrestudentsWhereCommitteeExamFailed($status_from, $date_stichtag, $deadline);
+
+ if(isError($result))
+ {
+ $this->logError(getError($result));
+ }
+ else
+ {
+ $prestudents = getData($result) ?: [];
+ $count = 0;
+
+ $prestudents = $this->prestudentsGetUnique($prestudents);
+
+ foreach ($prestudents as $prestudent)
+ {
+ $stg_kz = $prestudent->studiengang_kz;
+ if (in_array($stg_kz, $this->config->item('stgkz_blacklist_wiederholung')))
+ continue;
+ $url = site_url('lehre/Studierendenantrag/wiederholung/' . $prestudent->prestudent_id);
+ $urlCIS = CIS_ROOT . 'index.ci.php/lehre/Studierendenantrag/wiederholung/' . $prestudent->prestudent_id;
+ $email = $this->StudentModel->getEmailFH($this->StudentModel->getUID($prestudent->prestudent_id));
+
+ $fristende = new DateTime($prestudent->datum);
+ $fristende->add(DateInterval::createFromDateString($modifier_deadline));
+
+ $datum_kp = new DateTime($prestudent->datum);
+
+ $result = $this->StudiensemesterModel->getNextFrom($prestudent->studiensemester_kurzbz);
+ $next_sem = "";
+ $sem_after_next_sem = "";
+ if (hasData($result)) {
+ $next_sem = current(getData($result))->studiensemester_kurzbz;
+ $result = $this->StudiensemesterModel->getNextFrom($next_sem);
+ if (hasData($result)) {
+ $sem_after_next_sem = current(getData($result))->studiensemester_kurzbz;
+ }
+ }
+
+ $dataMail = array(
+ 'name'=> trim($prestudent->vorname . ' '. $prestudent->nachname),
+ 'vorname' => $prestudent->vorname,
+ 'nachname' => $prestudent->nachname,
+ 'pers_kz'=> $prestudent->matrikelnr,
+ 'stg' => $prestudent->bezeichnung,
+ 'lvbezeichnung' => $prestudent->lvbezeichnung,
+ 'datum_kp' => $datum_kp->format('d.m.Y'),
+ 'studiensemester'=> $prestudent->studiensemester_kurzbz,
+ 'Orgform'=> $prestudent->orgform,
+ 'prestudent_id' => $prestudent->prestudent_id,
+ 'url' => $url,
+ 'urlCIS' => $urlCIS,
+ 'fristablauf' => $fristende->format('d.m.Y'),
+ 'pre_wiederholer_sem' => $next_sem,
+ 'wiederholer_sem' => $sem_after_next_sem,
+ 'sem' => $prestudent->ausbildungssemester
+ );
+
+ // NOTE(chris): Sancho mail
+ if(sendSanchoMail('Sancho_Mail_Antrag_W_' . $name, $dataMail, $email, $subject))
+ {
+ $antrag_id = null;
+ $result = $this->StudierendenantragModel->loadWhere([
+ 'prestudent_id' => $prestudent->prestudent_id,
+ 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG
+ ]);
+ if (isError($result))
+ $this->logError(getError($result));
+ elseif (hasData($result))
+ $antrag_id = current(getData($result) ?: []) -> studierendenantrag_id;
+ if ($antrag_id == null)
+ {
+ $result = $this->StudierendenantragModel->insert([
+ 'prestudent_id' => $prestudent->prestudent_id,
+ 'studiensemester_kurzbz'=> $prestudent->studiensemester_kurzbz,
+ 'datum' => date('c'),
+ 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ 'insertvon' => 'AntragJob'
+ ]);
+ if (isError($result))
+ $this->logError(getError($result));
+ else
+ $antrag_id = getData($result);
+ }
+ if ($antrag_id)
+ {
+ $result = $this->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => $status_to,
+ 'insertvon' => 'AntragJob'
+ ]);
+ if (isError($result))
+ $this->logError(getError($result));
+ }
+ $count++;
+ }
+ }
+ $this->logInfo($count . " Mails '" . $subject . "' sent");
+ }
+ $this->logInfo('Ende Job sendAufforderungWiederholer ' . $name);
+ }
+}
diff --git a/application/controllers/jobs/ESIJob.php b/application/controllers/jobs/ESIJob.php
new file mode 100644
index 000000000..c9a558a46
--- /dev/null
+++ b/application/controllers/jobs/ESIJob.php
@@ -0,0 +1,165 @@
+load->model('person/Person_model', 'PersonModel');
+ $this->load->model('person/Kennzeichen_model', 'KennzeichenModel');
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Initialises generateESI job, handles job queue, logs infos/errors
+ */
+ public function generateESI()
+ {
+ //$jobType = 'DVUHSendPruefungsaktivitaeten';
+ $this->logInfo(ESIScheduler::JOB_TYPE_GENERATE_ESI.' job start');
+
+ // Gets the latest jobs
+ $lastJobs = $this->getLastJobs(ESIScheduler::JOB_TYPE_GENERATE_ESI);
+
+ if (isError($lastJobs))
+ {
+ $this->logError(getCode($lastJobs).': '.getError($lastJobs), ESIScheduler::JOB_TYPE_GENERATE_ESI);
+ }
+ else
+ {
+ $this->updateJobs(
+ getData($lastJobs), // Jobs to be updated
+ array(JobsQueueLib::PROPERTY_START_TIME), // Job properties to be updated
+ array(date('Y-m-d H:i:s')) // Job properties new values
+ );
+
+ $person_arr = $this->_getInputObjArray(getData($lastJobs));
+
+ foreach ($person_arr as $persobj)
+ {
+ if (!isset($persobj->person_id))
+ $this->logError("Error when generating ESI: invalid parameters");
+ else
+ {
+ $person_id = $persobj->person_id;
+
+ // check if there already is an active ESI
+ $this->KennzeichenModel->addSelect('1');
+ $activeKennzeichenRes = $this->KennzeichenModel->loadWhere(
+ array('person_id' => $person_id, 'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ, 'aktiv' => true)
+ );
+
+ if (hasData($activeKennzeichenRes))
+ {
+ $this->logError("Active ESI for person Id $person_id already exists");
+ continue;
+ }
+
+ // get Matrikelnr for person for which ESI should be generated
+ $this->PersonModel->addSelect('matr_nr');
+ $personRes = $this->PersonModel->load($person_id);
+
+ if (!hasData($personRes))
+ {
+ $this->logError("Person with Id $person_id not found");
+ continue;
+ }
+
+ $matr_nr = getData($personRes)[0]->matr_nr;
+
+ if (isEmptyString($matr_nr))
+ {
+ $this->logError("Matrikelnummer for person with Id $person_id is empty");
+ continue;
+ }
+
+ $esi = self::ESI_PREFIX.$matr_nr;
+
+ // check if ESI was already used
+ $this->KennzeichenModel->addSelect('1');
+ $existingKennzeichenRes = $this->KennzeichenModel->loadWhere(
+ array('person_id' => $person_id, 'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ, 'inhalt' => $esi)
+ );
+
+ if (hasData($existingKennzeichenRes))
+ {
+ $this->logError("ESI $esi for person Id $person_id already exists");
+ continue;
+ }
+
+ // if everything ok, save the esi for the person
+ $saveEsiResult = $this->KennzeichenModel->insert(
+ array(
+ 'person_id' => $person_id,
+ 'kennzeichentyp_kurzbz' => ESIScheduler::KENNZEICHENTYP_KURZBZ,
+ 'inhalt' => $esi,
+ 'aktiv' => true,
+ 'insertvon' => self::INSERT_VON
+ )
+ );
+
+ if (isError($saveEsiResult))
+ {
+ $this->logError("Error when sending ESI, person Id $person_id ".getError($saveEsiResult));
+ }
+ }
+ }
+
+ // Update jobs properties values
+ $this->updateJobs(
+ getData($lastJobs), // Jobs to be updated
+ array(JobsQueueLib::PROPERTY_STATUS, JobsQueueLib::PROPERTY_END_TIME), // Job properties to be updated
+ array(JobsQueueLib::STATUS_DONE, date('Y-m-d H:i:s')) // Job properties new values
+ );
+
+ if (hasData($lastJobs)) $this->updateJobsQueue(ESIScheduler::JOB_TYPE_GENERATE_ESI, getData($lastJobs));
+ }
+
+ $this->logInfo(ESIScheduler::JOB_TYPE_GENERATE_ESI.' job stop');
+ }
+
+ // --------------------------------------------------------------------------------------------
+ // Private methods
+
+ /**
+ * Extracts input data from jobs.
+ * @param $jobs
+ * @return array with jobinput
+ */
+ private function _getInputObjArray($jobs)
+ {
+ $mergedUsersArray = array();
+
+ if (count($jobs) == 0) return $mergedUsersArray;
+
+ foreach ($jobs as $job)
+ {
+ $decodedInput = json_decode($job->input);
+ if ($decodedInput != null)
+ {
+ foreach ($decodedInput as $el)
+ {
+ $mergedUsersArray[] = $el;
+ }
+ }
+ }
+ return $mergedUsersArray;
+ }
+}
diff --git a/application/controllers/jobs/IssueResolver.php b/application/controllers/jobs/IssueResolver.php
index cf97b7f68..ca07439c3 100755
--- a/application/controllers/jobs/IssueResolver.php
+++ b/application/controllers/jobs/IssueResolver.php
@@ -9,8 +9,8 @@ class IssueResolver extends IssueResolver_Controller
{
parent::__construct();
- // set fehler codes which can be resolved by the job
- // structure: fehlercode => class (library) name for resolving
+ // set fehler codes which can be resolved by the job, with own resolver defined
+ // structure: fehlercode => class (library) name for resolving in "resolvers" folder
$this->_codeLibMappings = array(
'CORE_ZGV_0001' => 'CORE_ZGV_0001',
'CORE_ZGV_0002' => 'CORE_ZGV_0002',
@@ -30,7 +30,6 @@ class IssueResolver extends IssueResolver_Controller
'CORE_STG_0002' => 'CORE_STG_0002',
'CORE_STG_0003' => 'CORE_STG_0003',
'CORE_STG_0004' => 'CORE_STG_0004',
- 'CORE_STUDENTSTATUS_0001' => 'CORE_STUDENTSTATUS_0001',
'CORE_STUDENTSTATUS_0002' => 'CORE_STUDENTSTATUS_0002',
'CORE_STUDENTSTATUS_0003' => 'CORE_STUDENTSTATUS_0003',
'CORE_STUDENTSTATUS_0004' => 'CORE_STUDENTSTATUS_0004',
@@ -45,10 +44,17 @@ class IssueResolver extends IssueResolver_Controller
'CORE_STUDENTSTATUS_0013' => 'CORE_STUDENTSTATUS_0013',
'CORE_STUDENTSTATUS_0014' => 'CORE_STUDENTSTATUS_0014',
'CORE_STUDENTSTATUS_0015' => 'CORE_STUDENTSTATUS_0015',
+ 'CORE_STUDENTSTATUS_0016' => 'CORE_STUDENTSTATUS_0016',
'CORE_PERSON_0001' => 'CORE_PERSON_0001',
'CORE_PERSON_0002' => 'CORE_PERSON_0002',
'CORE_PERSON_0003' => 'CORE_PERSON_0003',
'CORE_PERSON_0004' => 'CORE_PERSON_0004'
);
+
+ // fehler which are resolved by the job the same way as they are produced
+ // structure: fehlercode => class (library) name for resolving in "plausichecks" folder
+ $this->_codeProducerLibMappings = array(
+ 'CORE_STUDENTSTATUS_0001' => 'AbbrecherAktiv',
+ );
}
}
diff --git a/application/controllers/jobs/OneTimeMessages.php b/application/controllers/jobs/OneTimeMessages.php
index 58bc1fb7c..525f63c3b 100644
--- a/application/controllers/jobs/OneTimeMessages.php
+++ b/application/controllers/jobs/OneTimeMessages.php
@@ -51,7 +51,7 @@ class OneTimeMessages extends JOB_Controller
FROM public.tbl_prestudent p
JOIN public.tbl_prestudentstatus ps USING (prestudent_id)
JOIN public.tbl_studiengang s USING (studiengang_kz)
- WHERE ps.status_kurzbz = \'Wartender\'
+ WHERE get_rolle_prestudent(ps.prestudent_id, NULL) = \'Wartender\'
AND ps.studiensemester_kurzbz = ?
AND ps.datum <= NOW() - \''.$days.' days\'::interval
AND s.typ = ?
diff --git a/application/controllers/jobs/ReihungstestJob.php b/application/controllers/jobs/ReihungstestJob.php
index 431ac5b04..b55287439 100644
--- a/application/controllers/jobs/ReihungstestJob.php
+++ b/application/controllers/jobs/ReihungstestJob.php
@@ -467,7 +467,7 @@ class ReihungstestJob extends JOB_Controller
$this->PrestudentstatusModel->addJoin('public.tbl_person', 'person_id');
$yesterdays_applicants_arr = $this->PrestudentstatusModel->loadWhere('
- status_kurzbz = \'Interessent\' AND
+ status_kurzbz IN (\'Interessent\', \'Bewerber\') AND
typ = \'b\' AND
bestaetigtam = current_date - 1
');
@@ -730,33 +730,27 @@ class ReihungstestJob extends JOB_Controller
tbl_reihungstest.reihungstest_id,
tbl_studienplan.studienplan_id,
tbl_reihungstest.studiensemester_kurzbz,
- tbl_studienordnung.studiengang_kz
+ tbl_studienordnung.studiengang_kz,
+ tbl_studienplan.orgform_kurzbz
FROM
public.tbl_reihungstest
- JOIN public.tbl_rt_studienplan ON(tbl_rt_studienplan.reihungstest_id=tbl_reihungstest.reihungstest_id)
- JOIN lehre.tbl_studienplan USING(studienplan_id)
- JOIN lehre.tbl_studienordnung USING(studienordnung_id)
+ JOIN public.tbl_rt_studienplan ON(tbl_rt_studienplan.reihungstest_id=tbl_reihungstest.reihungstest_id)
+ JOIN lehre.tbl_studienplan USING(studienplan_id)
+ JOIN lehre.tbl_studienordnung USING(studienordnung_id)
WHERE
- NOT EXISTS(
- SELECT 1 FROM lehre.tbl_studienplan_semester
- WHERE studienplan_id=tbl_rt_studienplan.studienplan_id
- AND tbl_studienplan_semester.studiensemester_kurzbz=tbl_reihungstest.studiensemester_kurzbz
+ EXISTS (
+ SELECT studienplan_id
+ FROM lehre.tbl_studienordnung sordnung
+ JOIN lehre.tbl_studienplan USING (studienordnung_id)
+ JOIN lehre.tbl_studienplan_semester USING (studienplan_id)
+ WHERE sordnung.studiengang_kz = tbl_studienordnung.studiengang_kz
+ AND tbl_studienplan_semester.studiensemester_kurzbz = tbl_reihungstest.studiensemester_kurzbz
+ AND tbl_studienplan.studienplan_id NOT IN
+ (
+ SELECT studienplan_id FROM tbl_rt_studienplan WHERE reihungstest_id = tbl_reihungstest.reihungstest_id
+ )
)
- AND tbl_reihungstest.datum >= now()
- AND NOT EXISTS(
- SELECT
- 1
- FROM
- public.tbl_rt_studienplan rtstp
- JOIN lehre.tbl_studienplan stp USING(studienplan_id)
- JOIN lehre.tbl_studienordnung sto USING(studienordnung_id)
- JOIN lehre.tbl_studienplan_semester stpsem USING(studienplan_id)
- WHERE
- sto.studiengang_kz=tbl_studienordnung.studiengang_kz
- AND rtstp.reihungstest_id=tbl_reihungstest.reihungstest_id
- AND stpsem.studiensemester_kurzbz=tbl_reihungstest.studiensemester_kurzbz
- )
- ";
+ AND tbl_reihungstest.datum >= now()";
$db = new DB_Model();
$result_rt = $db->execReadOnlyQuery($qry);
@@ -766,7 +760,9 @@ class ReihungstestJob extends JOB_Controller
// find an active studyplan for the same degree program with is valid in this semester
$result_stpl = $this->StudienplanModel->getStudienplaeneBySemester(
$row_rt->studiengang_kz,
- $row_rt->studiensemester_kurzbz
+ $row_rt->studiensemester_kurzbz,
+ null,
+ $row_rt->orgform_kurzbz
);
if (hasData($result_stpl)) {
@@ -1027,7 +1023,7 @@ class ReihungstestJob extends JOB_Controller
{
$studiengang = $this->StudiengangModel->load($stg);
$mailcontent = '';
-
+ $content = false;
foreach ($orgform AS $art=>$value)
{
// Orgform nur dazu schreiben, wenn es mehr als Eine gibt
@@ -1048,6 +1044,7 @@ class ReihungstestJob extends JOB_Controller
$mailcontent .= '
| '.$bewerber.' |
';
}
$mailcontent .= '
';
+ $content = true;
}
if (isset($value['AufnahmeHoeherePrio']) && !isEmptyArray($value['AufnahmeHoeherePrio']))
{
@@ -1062,6 +1059,7 @@ class ReihungstestJob extends JOB_Controller
$mailcontent .= '| '.$bewerber.' |
';
}
$mailcontent .= '';
+ $content = true;
}
if (isset($value['AbgewiesenHoeherePrio']) && !isEmptyArray($value['AbgewiesenHoeherePrio']))
{
@@ -1075,6 +1073,7 @@ class ReihungstestJob extends JOB_Controller
$mailcontent .= '| '.$bewerber.' |
';
}
$mailcontent .= '';
+ $content = true;
}
if ($bcc != '' && isset($value['AbgewiesenWeilBewerber']) && !isEmptyArray($value['AbgewiesenWeilBewerber']))
{
@@ -1089,13 +1088,14 @@ class ReihungstestJob extends JOB_Controller
$mailcontent .= '| '.$bewerber.' |
';
}
$mailcontent .= '';
+ $content = true;
}
}
$mailcontent_data_arr['table'] = $mailcontent;
// Send email in Sancho design
- if (!isEmptyString($mailcontent))
+ if (!isEmptyString($mailcontent) && $content === true)
{
sendSanchoMail(
'Sancho_ReihungstestteilnehmerJob',
diff --git a/application/controllers/jobs/schedulers/ESIScheduler.php b/application/controllers/jobs/schedulers/ESIScheduler.php
new file mode 100644
index 000000000..3ab858937
--- /dev/null
+++ b/application/controllers/jobs/schedulers/ESIScheduler.php
@@ -0,0 +1,108 @@
+load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Creates jobs queue entries for generateESI job.
+ * @param string $studiensemester_kurzbz semester for which ESIs should be generated
+ */
+ public function generateESI($studiensemester_kurzbz = null)
+ {
+ // if no semester given, get current studiensemester
+ if (!isset($studiensemester_kurzbz))
+ {
+ $semRes = $this->StudiensemesterModel->getAkt();
+
+ if (hasData($semRes))
+ {
+ $studiensemester_kurzbz = getData($semRes)[0]->studiensemester_kurzbz;
+ }
+ }
+
+ if (isset($studiensemester_kurzbz))
+ {
+ $this->logInfo('Start job queue scheduler '.self::JOB_TYPE_GENERATE_ESI);
+
+ $qry = "
+ SELECT
+ DISTINCT person_id
+ FROM
+ public.tbl_person pers
+ JOIN public.tbl_prestudent ps USING (person_id)
+ JOIN public.tbl_prestudentstatus pss USING (prestudent_id)
+ WHERE
+ pss.studiensemester_kurzbz = ?
+ AND pers.matr_nr IS NOT NULL
+ AND pss.status_kurzbz IN ?
+ AND NOT EXISTS ( -- has no ESI yet
+ SELECT 1
+ FROM
+ public.tbl_kennzeichen
+ WHERE
+ person_id = pers.person_id
+ AND kennzeichentyp_kurzbz = ?
+ AND aktiv
+ )
+ AND NOT EXISTS ( -- making sure it's not an incoming
+ SELECT 1
+ FROM
+ public.tbl_prestudentstatus
+ WHERE
+ prestudent_id = ps.prestudent_id
+ AND status_kurzbz = 'Incoming'
+ )";
+
+ $db = new DB_Model();
+ $jobInputResult = $db->execReadOnlyQuery($qry, array($studiensemester_kurzbz, $this->_active_status_kurzbz, self::KENNZEICHENTYP_KURZBZ));
+
+ // If an error occured then log it
+ if (isError($jobInputResult))
+ {
+ $this->logError(getError($jobInputResult));
+ }
+ elseif (hasData($jobInputResult)) // if persons found
+ {
+ // Add the new job to the jobs queue
+ $addNewJobResult = $this->addNewJobsToQueue(
+ self::JOB_TYPE_GENERATE_ESI, // job type
+ $this->generateJobs( // gnerate the structure of the new job
+ JobsQueueLib::STATUS_NEW,
+ json_encode(getData($jobInputResult))
+ )
+ );
+
+ // If error occurred return it
+ if (isError($addNewJobResult)) $this->logError(getError($addNewJobResult));
+ }
+ }
+ else
+ {
+ $this->logError('Error when getting Studiensemester');
+ }
+
+ $this->logInfo('End job queue scheduler '.self::JOB_TYPE_GENERATE_ESI);
+ }
+}
diff --git a/application/controllers/jobs/vertragsbestandteil_test/VertragsbestandteilTest.php b/application/controllers/jobs/vertragsbestandteil_test/VertragsbestandteilTest.php
new file mode 100644
index 000000000..d22ddb85f
--- /dev/null
+++ b/application/controllers/jobs/vertragsbestandteil_test/VertragsbestandteilTest.php
@@ -0,0 +1,114 @@
+load->library('vertragsbestandteil/VertragsbestandteilLib',
+ null, 'VertragsbestandteilLib');
+ $this->load->library('vertragsbestandteil/GehaltsbestandteilLib',
+ null, 'GehaltsbestandteilLib');
+ }
+
+ public function testFetch()
+ {
+ $dienstverhaeltnis_id = 1;
+ $stichtag = null;
+
+ foreach($this->VertragsbestandteilLib->fetchVertragsbestandteile(
+ $dienstverhaeltnis_id, $stichtag) as $vertragsbestandteil)
+ {
+ //print_r($vertragsbestandteil);
+ echo $vertragsbestandteil . "\n";
+ }
+ }
+
+ public function testUpdate()
+ {
+ $now = new DateTime();
+
+ $data = new stdClass();
+ $data->vertragsbestandteil_id = 32;
+ $data->von = '2022-12-05';
+
+ $data->wochenstunden = 45.0;
+ $data->vertragsbestandteiltyp_kurzbz = VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_STUNDEN;
+
+ $vb = VertragsbestandteilFactory::getVertragsbestandteil($data);
+
+ try
+ {
+ $this->VertragsbestandteilLib->storeVertragsbestandteil($vb);
+ echo "Update successful.\n";
+ }
+ catch( Exception $ex )
+ {
+ echo "Update failed.\n";
+ }
+ }
+
+
+ public function testInsert()
+ {
+ $now = new DateTime();
+
+ $data = new stdClass();
+ $data->dienstverhaeltnis_id = 1;
+ $data->von = '2022-12-01';
+ $data->insertamum = $now->format(DateTime::ATOM);
+ $data->insertvon = 'ma0080';
+ $data->vertragsbestandteiltyp_kurzbz = VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FUNKTION;
+
+ $data->benutzerfunktion_id = 112667;
+ $data->anmerkung = 'test funkton';
+ $data->kuendigungsrelevant = false;
+
+ $vb = VertragsbestandteilFactory::getVertragsbestandteil($data);
+
+ try
+ {
+ $this->VertragsbestandteilLib->storeVertragsbestandteil($vb);
+ echo "Insert successful.\n";
+ }
+ catch( Exception $ex )
+ {
+ echo "Insert failed.\n";
+ }
+ }
+
+ public function testGehaltsbestandteilInsert()
+ {
+ $data = new stdClass();
+ $data->gehaltsbestandteil_id = 2;
+ /*
+ $data->dienstverhaeltnis_id = 39;
+ $data->vertragsbestandteil_id = 123;
+ $data->gehaltstyp_kurzbz = 'zulage';
+ $data->von = '2023-04-01';
+ $data->bis = '2023-08-31';
+ $data->anmerkung = 'test anmerkung';
+ $data->grundbetrag = 100;
+ $data->betrag_valorisiert = 100;
+ $data->valorisierung = true;
+ */
+ $data->auszahlungen = 12;
+
+ $gb = new \vertragsbestandteil\Gehaltsbestandteil();
+ $gb->hydrateByStdClass($data);
+
+ print_r($gb->toStdClass());
+
+ $this->GehaltsbestandteilLib->storeGehaltsbestandteil($gb);
+ }
+}
diff --git a/application/controllers/lehre/Antrag/Attachment.php b/application/controllers/lehre/Antrag/Attachment.php
new file mode 100644
index 000000000..073a03df0
--- /dev/null
+++ b/application/controllers/lehre/Antrag/Attachment.php
@@ -0,0 +1,82 @@
+load->model('education/Studierendenantrag_model', 'StudierendenantragModel');
+
+ $this->load->library('DmsLib');
+ $this->load->library('AuthLib');
+ $this->load->library('PermissionLib');
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * @param integer $dms_id
+ *
+ * @return void
+ */
+ public function show($dms_id)
+ {
+ $result = $this->StudierendenantragModel->loadWhere(['dms_id' => $dms_id]);
+ if (!getData($result))
+ return show_404();
+
+ if (!$this->permissionlib->isBerechtigt('student/antragfreigabe'))
+ {
+ $isSamePerson = false;
+ $antraege = getData($result);
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+ foreach ($antraege as $antrag)
+ {
+ $prestudent = $this->PrestudentModel->load($antrag->prestudent_id);
+ if(hasData($prestudent))
+ {
+ if(current(getData($prestudent))->person_id == getAuthPersonId())
+ {
+ $isSamePerson = true;
+ break;
+ }
+ }
+ }
+
+ if ($isSamePerson == false)
+ {
+ $this->output->set_status_header(REST_Controller::HTTP_FORBIDDEN); // set the HTTP header as unauthorized
+
+ $this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output
+
+ // Prints the main error message
+ $this->eprintflib->printError('You are not allowed to access to this content');
+ // Prints the called controller name
+ $this->eprintflib->printInfo('Controller name: '.$this->router->class);
+ // Prints the called controller method name
+ $this->eprintflib->printInfo('Method name: '.$this->router->method);
+ // Prints the required permissions needed to access to this method
+ $this->eprintflib->printInfo('Required permissions: student/antragfreigabe');
+
+ return show_error('You are not entitled to read this document');
+ }
+ }
+
+ $result = $this->dmslib->download($dms_id);
+ if (isError($result))
+ return show_error(getError($result));
+
+ $this->outputFile(getData($result));
+ }
+}
diff --git a/application/controllers/lehre/Antrag/Wiederholung.php b/application/controllers/lehre/Antrag/Wiederholung.php
new file mode 100644
index 000000000..2aa57d733
--- /dev/null
+++ b/application/controllers/lehre/Antrag/Wiederholung.php
@@ -0,0 +1,48 @@
+ 'student/studierendenantrag:w'
+ ]);
+
+ $this->load->library('AntragLib');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'studierendenantrag'
+ ]);
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Public methods
+ public function assistenz($antrag_id)
+ {
+
+ $result = $this->antraglib->getDetailsForAntrag($antrag_id);
+
+ if (isError($result))
+ return show_error(getError($result));
+
+ if (!hasData($result))
+ return show_404();
+
+ $this->load->view('lehre/Antrag/Wiederholung/Student', [
+ 'antrag_id' => $antrag_id,
+ 'antrag' => getData($result)
+ ]);
+ }
+}
diff --git a/application/controllers/lehre/Studierendenantrag.php b/application/controllers/lehre/Studierendenantrag.php
new file mode 100644
index 000000000..107c9af96
--- /dev/null
+++ b/application/controllers/lehre/Studierendenantrag.php
@@ -0,0 +1,190 @@
+load->library('AuthLib');
+ $this->load->library('AntragLib');
+
+ // Load Models
+ $this->load->model('education/Studierendenantrag_model', 'StudierendenantragModel');
+ $this->load->model('person/Person_model', 'PersonModel');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'studierendenantrag'
+ ]);
+
+ if (strtolower($this->router->method) === 'leitung')
+ $this->_isAllowed([
+ 'leitung' => ['student/studierendenantrag:r', 'student/antragfreigabe:r']
+ ]);
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Public methods
+ public function index()
+ {
+ $dataAntrag = $this->StudierendenantragModel->loadForPerson(getAuthPersonId());
+ if (isError($dataAntrag))
+ return show_error(getError($dataAntrag));
+ $dataAntrag = (getData($dataAntrag) ? : []);
+ $prestudentenArr = array();
+
+ foreach ($dataAntrag as $antrag)
+ {
+ if (!isset($prestudentenArr[$antrag->prestudent_id]))
+ {
+ $prestudentenArr[$antrag->prestudent_id] = array(
+ 'allowedNewTypes' => array(),
+ 'antraege'=> array(),
+ 'bezeichnungStg' => $antrag->bezeichnung,
+ 'bezeichnungOrgform' => $antrag->orgform
+ );
+
+ $result = $this->antraglib->getPrestudentWiederholungsBerechtigt($antrag->prestudent_id);
+ if (getData($result) == 1)
+ $prestudentenArr[$antrag->prestudent_id]['allowedNewTypes'][] = 'Wiederholung';
+
+ $result = $this->antraglib->getPrestudentUnterbrechungsBerechtigt($antrag->prestudent_id);
+ if (getData($result) == 1)
+ $prestudentenArr[$antrag->prestudent_id]['allowedNewTypes'][] = 'Unterbrechung';
+
+ $result = $this->antraglib->getPrestudentAbmeldeBerechtigt($antrag->prestudent_id);
+ if (getData($result) == 1)
+ $prestudentenArr[$antrag->prestudent_id]['allowedNewTypes'][] = 'Abmeldung';
+ }
+ if ($antrag->studierendenantrag_id == null)
+ continue;
+ if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL && (!$antrag->isapproved))
+ continue;
+
+ $prestudentenArr[$antrag->prestudent_id]['antraege'][] = $antrag;
+ }
+
+ $this->load->view('lehre/Antrag/Student/List', [
+ 'antraege' => $prestudentenArr
+ ]);
+ }
+
+ public function leitung()
+ {
+ $stgL = $this->permissionlib->getSTG_isEntitledFor('student/antragfreigabe') ?: [];
+
+ $stgA = $this->permissionlib->getSTG_isEntitledFor('student/studierendenantrag') ?: [];
+
+ $this->load->view('lehre/Antrag/Leitung/List', [
+ 'stgA' => $stgA,
+ 'stgL' => $stgL
+ ]);
+ }
+
+ public function abmeldung($prestudent_id, $studierendenantrag_id = null)
+ {
+ $this->load->view('lehre/Antrag/Create', [
+ 'prestudent_id' => $prestudent_id,
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'antrag_type' => 'Abmeldung'
+ ]);
+ }
+
+ public function abmeldungstgl($prestudent_id, $studierendenantrag_id = null)
+ {
+
+ $this->load->view('lehre/Antrag/Create', [
+ 'prestudent_id' => $prestudent_id,
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'antrag_type' => 'AbmeldungStgl'
+ ]);
+ }
+
+ public function unterbrechung($prestudent_id, $studierendenantrag_id = null)
+ {
+ $this->load->view('lehre/Antrag/Create', [
+ 'prestudent_id' => $prestudent_id,
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'antrag_type' => 'Unterbrechung'
+ ]);
+ }
+
+ public function wiederholung($prestudent_id, $studierendenantrag_id = null)
+ {
+ $this->load->view('lehre/Antrag/Create', [
+ 'prestudent_id' => $prestudent_id,
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'antrag_type' => 'Wiederholung'
+ ]);
+ }
+
+ /**
+ * Checks if the caller is allowed to access to this content with the given permissions
+ * If it is not allowed will set the HTTP header with code 401
+ * Wrapper for permissionlib->isEntitled
+ */
+ private function _isAllowed($requiredPermissions)
+ {
+ // Loads permission lib
+ $this->load->library('PermissionLib');
+
+ // Checks if this user is entitled to access to this content
+ if (!$this->permissionlib->isEntitled($requiredPermissions, $this->router->method))
+ {
+ $this->output->set_status_header(REST_Controller::HTTP_UNAUTHORIZED); // set the HTTP header as unauthorized
+
+ $this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output
+
+ // Prints the main error message
+ $this->eprintflib->printError('You are not allowed to access to this content');
+ // Prints the called controller name
+ $this->eprintflib->printInfo('Controller name: '.$this->router->class);
+ // Prints the called controller method name
+ $this->eprintflib->printInfo('Method name: '.$this->router->method);
+ // Prints the required permissions needed to access to this method
+ $this->eprintflib->printInfo('Required permissions: '.$this->_rpsToString($requiredPermissions, $this->router->method));
+
+ exit; // immediately terminate the execution
+ }
+ }
+
+ /**
+ * Converts an array of permissions to a string that contains them as a comma separated list
+ * Ex: ", , "
+ */
+ private function _rpsToString($requiredPermissions, $method)
+ {
+ $strRequiredPermissions = ''; // string that contains all the required permissions needed to access to this method
+
+ if (isset($requiredPermissions[$method])) // if the called method is present in the permissions array
+ {
+ // If it is NOT then convert it into an array
+ $rpsMethod = $requiredPermissions[$method];
+ if (!is_array($rpsMethod))
+ {
+ $rpsMethod = array($rpsMethod);
+ }
+
+ // Copy all the permissions into $strRequiredPermissions separated by a comma
+ for ($i = 0; $i < count($rpsMethod); $i++)
+ {
+ $strRequiredPermissions .= $rpsMethod[$i].', ';
+ }
+
+ $strRequiredPermissions = rtrim($strRequiredPermissions, ', ');
+ }
+
+ return $strRequiredPermissions;
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/lehre/anrechnung/RequestAnrechnung.php b/application/controllers/lehre/anrechnung/RequestAnrechnung.php
index 1922bacda..ebc272e3e 100644
--- a/application/controllers/lehre/anrechnung/RequestAnrechnung.php
+++ b/application/controllers/lehre/anrechnung/RequestAnrechnung.php
@@ -111,8 +111,13 @@ class requestAnrechnung extends Auth_Controller
$lehrveranstaltung_id = $this->input->post('lv_id');
$studiensemester_kurzbz = $this->input->post('studiensemester');
$bestaetigung = $this->input->post('bestaetigung');
- $begruendung_ects = $this->input->post('begruendung_ects');
- $begruendung_lvinhalt = $this->input->post('begruendung_lvinhalt');
+ $begruendung_ects = $this->config->item('explain_equivalence') === TRUE
+ ? $this->input->post('begruendung_ects')
+ : NULL;
+ $begruendung_lvinhalt = $this->config->item('explain_equivalence') === TRUE
+ ? $this->input->post('begruendung_lvinhalt')
+ : NULL;
+
// Validate data
if (empty($_FILES['uploadfile']['name']))
@@ -124,8 +129,8 @@ class requestAnrechnung extends Auth_Controller
isEmptyString($anmerkung) ||
isEmptyString($lehrveranstaltung_id) ||
isEmptyString($studiensemester_kurzbz) ||
- isEmptyString($begruendung_ects) ||
- isEmptyString($begruendung_lvinhalt))
+ ($this->config->item('explain_equivalence') === TRUE && isEmptyString($begruendung_ects)) ||
+ ($this->config->item('explain_equivalence') === TRUE && isEmptyString($begruendung_lvinhalt)))
{
return $this->outputJsonError($this->p->t('ui', 'errorFelderFehlen'));
}
@@ -152,10 +157,10 @@ class requestAnrechnung extends Auth_Controller
return $this->outputJsonError($this->p->t('anrechnung', 'antragBereitsGestellt'));
}
- // Exit if application is not for actual studysemester
- if (!self::_applicationIsForActualSS($studiensemester_kurzbz))
+ // Exit if application is a past ( < actual ) studysemester
+ if (self::_applicationIsPastSS($studiensemester_kurzbz))
{
- return $this->outputJsonError($this->p->t('anrechnung', 'antragNurImAktSS'));
+ return $this->outputJsonError($this->p->t('anrechnung', 'antragNichtFuerVerganganeSS'));
}
// Upload document
@@ -168,7 +173,7 @@ class requestAnrechnung extends Auth_Controller
// Hold just inserted DMS ID
$lastInsert_dms_id = $result->retval['dms_id'];
-
+
// Save Anrechnung and Anrechnungstatus
$result = $this->AnrechnungModel->createAnrechnungsantrag(
$prestudent_id,
@@ -312,18 +317,21 @@ class requestAnrechnung extends Auth_Controller
}
/**
- * Check if applications' study semester is actual study semester.
+ * Check if applications' study semester is < actual study semester.
*
* @param $studiensemester_kurzbz
* @return bool
*/
- private function _applicationIsForActualSS($studiensemester_kurzbz)
+ private function _applicationIsPastSS($studiensemester_kurzbz)
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$result = $this->StudiensemesterModel->getNearest();
- $actual_ss = getData($result)[0]->studiensemester_kurzbz;
+ $actual_ss = getData($result)[0];
- return $studiensemester_kurzbz == $actual_ss;
+ $result = $this->StudiensemesterModel->load($studiensemester_kurzbz);
+ $anrechnung_ss = getData($result)[0];
+
+ return $anrechnung_ss->ende < $actual_ss->start;
}
private function _LVhasBlockingGrades($studiensemester_kurzbz, $lehrveranstaltung_id)
diff --git a/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php b/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php
index 6ac2da887..4abb1c400 100644
--- a/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php
+++ b/application/controllers/lehre/lehrauftrag/LehrauftragAkzeptieren.php
@@ -35,6 +35,7 @@ class LehrauftragAkzeptieren extends Auth_Controller
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('codex/Bisverwendung_model', 'BisverwendungModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
+ $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model', 'DienstverhaeltnisModel');
// Load libraries
$this->load->library('WidgetLib');
@@ -94,9 +95,9 @@ class LehrauftragAkzeptieren extends Auth_Controller
'lektor' => true,
'aktiv' => true
));
-
+
$is_external_lector = hasData($result) ? true : false;
-
+
$view_data = array(
'studiensemester_selected' => $studiensemester_kurzbz,
'is_external_lector' => $is_external_lector
@@ -207,15 +208,41 @@ class LehrauftragAkzeptieren extends Auth_Controller
*/
public function checkInkludierteLehre()
{
- $result = $this->BisverwendungModel->getLast($this->_uid, false);
-
- if (hasData($result))
+ if(defined('DIENSTVERHAELTNIS_SUPPORT') && DIENSTVERHAELTNIS_SUPPORT)
{
- $this->outputJsonSuccess(!is_null($result->retval[0]->inkludierte_lehre) && $result->retval[0]->inkludierte_lehre != 0);
+ // Bei neuer Vertragsstruktur wird nur anhand des echten DVs entschieden ob eine Anzeige
+ // des Stundensatzes erfolgt oder nicht.
+ $result = $this->DienstverhaeltnisModel->getDVByPersonUID($this->_uid, null, date('Y-m-d'));
+
+ if (hasData($result))
+ {
+ $data = getData($result);
+ foreach($data as $row)
+ {
+ if($row->vertragsart_kurzbz == 'echterdv')
+ $this->outputJsonSuccess(true);
+ else
+ $this->outputJsonSuccess(false);
+ }
+ }
+ else
+ {
+ $this->outputJsonError(getError($result));
+ }
}
else
{
- $this->outputJsonError(getError($result));
+ // DEPRECATED
+ $result = $this->BisverwendungModel->getLast($this->_uid, false);
+
+ if (hasData($result))
+ {
+ $this->outputJsonSuccess(!is_null($result->retval[0]->inkludierte_lehre) && $result->retval[0]->inkludierte_lehre != 0);
+ }
+ else
+ {
+ $this->outputJsonError(getError($result));
+ }
}
}
diff --git a/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php
new file mode 100644
index 000000000..b1ab2fe26
--- /dev/null
+++ b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php
@@ -0,0 +1,45 @@
+ 'lehre/lehrveranstaltung:rw',
+ )
+ );
+
+ // Load libraries
+ $this->load->library('AuthLib');
+
+
+ // Load language phrases
+ $this->loadPhrases(
+ array(
+ 'global',
+ 'lehre'
+ )
+ );
+
+ $this->_setAuthUID();
+ }
+
+ public function index()
+ {
+ $this->load->view('lehre/lvplanung/lvTemplateUebersicht.php');
+ }
+
+
+ /**
+ * Retrieve the UID of the logged user and checks if it is valid
+ */
+ private function _setAuthUID()
+ {
+ $this->_uid = getAuthUID();
+
+ if (!$this->_uid) show_error('User authentification failed');
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/public/js/Components.php b/application/controllers/public/js/Components.php
new file mode 100644
index 000000000..830e7ea65
--- /dev/null
+++ b/application/controllers/public/js/Components.php
@@ -0,0 +1,43 @@
+output->set_content_type('text/javascript');
+ $this->output->set_output($contents);
+ }
+}
diff --git a/application/controllers/system/MigrateContract.php b/application/controllers/system/MigrateContract.php
new file mode 100644
index 000000000..817eaa4f0
--- /dev/null
+++ b/application/controllers/system/MigrateContract.php
@@ -0,0 +1,759 @@
+load->model('codex/bisverwendung_model', 'BisVerwendungModel');
+ $this->load->model('person/benutzerfunktion_model', 'BenutzerfunktionModel');
+
+ $this->load->config('migratecontract');
+
+ $this->OE_DEFAULT = $this->config->item('migratecontract_oe_default');
+ $this->matching_ba1_vertragsart = $this->config->item('migratecontract_matching_ba1_vertragsart');
+ $this->configerrors = array();
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Public methods
+ public function checkConfig()
+ {
+ echo "OE_DEFAULT: " . $this->OE_DEFAULT . "\n";
+ echo "matching_ba1_vertragsart: " . print_r($this->matching_ba1_vertragsart, true);
+
+ $this->checkOE_DEFAULT();
+ $this->checkMatching_ba1_vertragsart();
+
+ if( count($this->configerrors) > 0 )
+ {
+ foreach($this->configerrors AS $configerror)
+ {
+ echo $configerror . "\n";
+ }
+ die("Fehler in der Konfiguration. Abbruch!\n");
+ }
+ else
+ {
+ echo "Konfiguration OK.\n";
+ }
+ }
+
+ protected function checkOE_DEFAULT()
+ {
+ $db = new DB_Model();
+ $oesql = 'SELECT * FROM public.tbl_organisationseinheit WHERE oe_kurzbz = ?';
+ $oeres = $db->execReadOnlyQuery($oesql, array($this->OE_DEFAULT));
+ if( !hasData($oeres) )
+ {
+ $this->configerrors[] = 'Default Organisationseinheit: "'
+ . $this->OE_DEFAULT . '" nicht gefunden.';
+ }
+ }
+
+ protected function checkMatching_ba1_vertragsart() {
+ $db = new DB_Model();
+ foreach( $this->matching_ba1_vertragsart AS $vertragsart_kurzbz )
+ {
+ $vasql = 'SELECT * FROM hr.tbl_vertragsart WHERE vertragsart_kurzbz = ?';
+ $vares = $db->execReadOnlyQuery($vasql, array($vertragsart_kurzbz));
+ if( !hasData($vares) )
+ {
+ $this->configerrors[] = 'Vertragsart "' . $vertragsart_kurzbz
+ . '" nicht gefunden.';
+ }
+ }
+ }
+
+ /**
+ * Everything has a beginning
+ */
+ public function index($user = null)
+ {
+ $this->checkConfig();
+
+ if (!is_null($user))
+ {
+ $contracts = $this->_transformUser($user);
+
+ /*
+ Format:
+ $contracts['dv'][]['vbs'][]
+ */
+ //$this->outputJson($contracts);
+ var_dump($contracts);
+ $this->_saveJSON($contracts);
+ }
+ else
+ {
+ $qry = "SELECT distinct mitarbeiter_uid FROM bis.tbl_bisverwendung";
+ $db = new DB_Model();
+
+ $resultUser = $db->execReadOnlyQuery($qry);
+ if (hasData($resultUser))
+ {
+ $users = getData($resultUser);
+ foreach($users as $user)
+ {
+ $contracts = $this->_transformUser($user->mitarbeiter_uid);
+ $this->_saveJSON($contracts);
+ }
+ }
+
+ }
+ }
+
+ private function _saveJSON($contracts)
+ {
+ $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel');
+ $this->load->model('vertragsbestandteil/Vertragsbestandteil_model','VertragsbestandteilModel');
+ $this->load->model('vertragsbestandteil/VertragsbestandteilStunden_model','VertragsbestandteilStundenModel');
+ $this->load->model('vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model','VertragsbestandteilZeitaufzeichnungModel');
+ $this->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model','VertragsbestandteilFreitextModel');
+ $this->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model','VertragsbestandteilFunktionModel');
+ $this->load->model('vertragsbestandteil/VertragsbestandteilKarenz_model','VertragsbestandteilKarenzModel');
+
+ $failed = false;
+ $this->db->trans_begin();
+
+ foreach($contracts['dv'] as $row_dv)
+ {
+ // Dienstvertrag erstellen
+ $resultDV = $this->DienstverhaeltnisModel->insert(
+ array(
+ 'mitarbeiter_uid' => $row_dv['mitarbeiter_uid'],
+ 'vertragsart_kurzbz' => $row_dv['vertragsart_kurzbz'],
+ 'oe_kurzbz' => $row_dv['oe_kurzbz'],
+ 'von' => $row_dv['von'],
+ 'bis' => $row_dv['bis'],
+ 'insertamum' => date('Y-m-d H:i:s'),
+ 'insertvon' => 'MigrateContract'
+ )
+ );
+
+ if (isSuccess($resultDV) && hasData($resultDV))
+ {
+ $dv_id = getData($resultDV);
+
+ // Vertragsbetandteile erstellen
+ foreach($row_dv['vbs'] as $row_vbs)
+ {
+ $resultVBS = $this->VertragsbestandteilModel->insert(
+ array(
+ 'dienstverhaeltnis_id' => $dv_id,
+ 'vertragsbestandteiltyp_kurzbz' => $row_vbs['vertragsbestandteiltyp_kurzbz'],
+ 'von' => $row_vbs['von'],
+ 'bis' => $row_vbs['bis'],
+ 'insertamum' => date('Y-m-d H:i:s'),
+ 'insertvon' => 'MigrateContract'
+ )
+ );
+
+ if (isSuccess($resultVBS) && hasData($resultVBS))
+ {
+ $vbs_id = getData($resultVBS);
+ echo 'VBS:'.$vbs_id;
+
+ switch($row_vbs['vertragsbestandteiltyp_kurzbz'])
+ {
+ case 'stunden':
+ $resultVBS = $this->_insertVBSStunden($vbs_id, $row_vbs);
+ break;
+ case 'zeitaufzeichnung':
+ $resultVBS = $this->_insertVBSZeitaufzeichnung($vbs_id, $row_vbs);
+ break;
+ case 'funktion':
+ $resultVBS = $this->_insertVBSFunktion($vbs_id, $row_vbs);
+ break;
+ case 'freitext':
+ $resultVBS = $this->_insertVBSFreitext($vbs_id, $row_vbs);
+ break;
+ case 'karenz':
+ $resultVBS = $this->_insertVBSKarenz($vbs_id, $row_vbs);
+ break;
+ }
+
+ if (isError($resultVBS))
+ {
+ echo "FAILED:".getError($resultVBS);
+ $failed = true;
+ }
+ }
+ else
+ {
+ $failed = true;
+ }
+ }
+ }
+ else
+ {
+ $failed = true;
+ }
+ }
+
+ if(!$failed)
+ {
+ $this->db->trans_commit();
+ }
+ else
+ {
+ echo "ROLLBACK";
+ $this->db->trans_rollback();
+ }
+ }
+
+ private function _insertVBSKarenz($vbs_id, $row_vbs)
+ {
+ return $this->VertragsbestandteilKarenzModel->insert(
+ array(
+ 'vertragsbestandteil_id' => $vbs_id,
+ 'karenztyp_kurzbz' => $row_vbs['karenztyp_kurzbz']
+ )
+ );
+ }
+
+ private function _insertVBSFreitext($vbs_id, $row_vbs)
+ {
+ return $this->VertragsbestandteilFreitextModel->insert(
+ array(
+ 'vertragsbestandteil_id' => $vbs_id,
+ 'freitexttyp_kurzbz' => $row_vbs['freitexttyp_kurzbz'],
+ 'titel' => $row_vbs['titel'],
+ 'anmerkung' => $row_vbs['anmerkung']
+ )
+ );
+ }
+
+ private function _insertVBSFunktion($vbs_id, $row_vbs)
+ {
+ return $this->VertragsbestandteilFunktionModel->insert(
+ array(
+ 'vertragsbestandteil_id' => $vbs_id,
+ 'benutzerfunktion_id' => $row_vbs['benutzerfunktion_id']
+ )
+ );
+ }
+
+ private function _insertVBSZeitaufzeichnung($vbs_id, $row_vbs)
+ {
+ return $this->VertragsbestandteilZeitaufzeichnungModel->insert(
+ array(
+ 'vertragsbestandteil_id' => $vbs_id,
+ 'zeitaufzeichnung' => $row_vbs['zeitaufzeichnung'],
+ 'azgrelevant' => $row_vbs['azgrelevant'],
+ 'homeoffice' => $row_vbs['homeoffice']
+ )
+ );
+ }
+
+ private function _insertVBSStunden($vbs_id, $row_vbs)
+ {
+ return $this->VertragsbestandteilStundenModel->insert(
+ array(
+ 'vertragsbestandteil_id' => $vbs_id,
+ 'wochenstunden' => $row_vbs['wochenstunden'],
+ 'teilzeittyp_kurzbz' => $row_vbs['teilzeittyp_kurzbz']
+ )
+ );
+ }
+
+ /**
+ * Ermittelt die neue Vertragsstruktur fuer einen User
+ */
+ private function _transformUser($user)
+ {
+ $contracts = array();
+ $this->BisVerwendungModel->addOrder('beginn');
+ $result_verwendung = $this->BisVerwendungModel->loadWhere(array("mitarbeiter_uid" => $user));
+
+ if (isError($result_verwendung))
+ die("Failed to load Verwendung");
+
+ if (hasData($result_verwendung))
+ {
+ $verwendung = getData($result_verwendung);
+
+ foreach ($verwendung as $row_verwendung)
+ {
+ $dv = $this->_getOrCreateDV($contracts, $row_verwendung);
+
+ // Ende des DV aktualisieren
+ if ($contracts['dv'][$dv]['bis'] < $row_verwendung->ende || $row_verwendung->ende == '')
+ $contracts['dv'][$dv]['bis'] = $row_verwendung->ende;
+
+ // Stundenbestandteil pruefen
+ $this->_addVertragsbestandteilStunden($contracts, $dv, $row_verwendung);
+
+ // Befristung
+ $this->_addVertragsbestandteilFreitextBefristung($contracts, $dv, $row_verwendung);
+
+ // All-In
+ $this->_addVertragsbestandteilFreitextAllIn($contracts, $dv, $row_verwendung);
+
+ // Zeitaufzeichnung
+ $this->_addVertragsbestandteilZeitaufzeichnung($contracts, $dv, $row_verwendung);
+
+ // Karenz
+ $this->_addVertragsbestandteilKarenz($contracts, $dv, $row_verwendung);
+
+ // Inkludierte Lehre
+ // Kuendigungsfrist
+ // Urlaubsanspruch
+ }
+
+ // Funktion
+ $this->_addVertragsbestandteilFunktion($contracts, $user);
+
+ }
+
+ return $contracts;
+ }
+
+ /**
+ * Fuegt Karenzierungseintraege zu bestehenden Dienstverhaeltnissen hinzu
+ */
+ private function _addVertragsbestandteilKarenz(&$contracts, $dv, $row_verwendung)
+ {
+ if ($row_verwendung->beschausmasscode == 5)
+ {
+ $dtstart = new DateTime($row_verwendung->beginn);
+ $dtende = new DateTime($row_verwendung->ende);
+ $interval = $dtende->diff($dtstart);
+ $dauer = $interval->format('%a');
+
+ // TODO: klären ob das so machbar ist
+ if ($dauer < 65)
+ $karenztyp = 'papamonat';
+ elseif ($dauer < 120)
+ $karenztyp = 'bildungskarenz';
+ else
+ $karenztyp = 'elternkarenz';
+
+ // VBS anlegen und Funktion zuweisen
+ $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'karenz';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['karenztyp_kurzbz'] = $karenztyp;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['geplanter_geburtstermin'] = null;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['tatsaechlicher_geburtstermin'] = null;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['hint'] = 'Dauer:'.$dauer;
+ }
+ }
+
+ /**
+ * Holt die Funktionen die Vertragsrelevant sind und verknüpft diese
+ */
+ private function _addVertragsbestandteilFunktion(&$contracts, $user)
+ {
+ // Alle Funktionen holen die Vertragsrelevant sind
+ $this->BenutzerfunktionModel->addOrder('datum_von');
+ $this->BenutzerfunktionModel->addJoin('public.tbl_funktion','funktion_kurzbz');
+ $resultFunktionen = $this->BenutzerfunktionModel->loadWhere(array('uid' => $user, 'vertragsrelevant' => true));
+
+ if (isSuccess($resultFunktionen) && hasData($resultFunktionen))
+ {
+ $funktionen = getData($resultFunktionen);
+
+ foreach ($funktionen as $row_funktion)
+ {
+ $funktion_added = 0;
+ $dv = '';
+
+ // Passendes DV suchen
+ foreach ($contracts['dv'] as $key_dv => $row_contract)
+ {
+ // Eine Funktion kann zu mehreren DV zugeordnet sein
+ // es werden daher alle durchsucht ob es reinfaellt und ggf mehrfach zugeordnet
+ if ((isset($row_funktion->datum_von) && $row_funktion->datum_von >= $row_contract['von'])
+ && ($row_contract['bis'] == '' || $row_contract['bis'] >= $row_funktion->datum_von)
+ && (
+ (
+ isset($row_funktion->datum_bis) && isset($row_contract['bis'])
+ && $row_funktion->datum_bis <= $row_contract['bis']
+ )
+ || $row_funktion->datum_bis == ''
+ || (isset($row_funktion->datum_bis) && !isset($row_contract['bis']))
+ )
+ )
+ {
+
+ $dv = $key_dv;
+
+ // Startdatum und Endedatum ermitteln wenn die Funktion ueber das DV hinausgeht
+ // Wenn die Dauer laenger ist, wird beim Beginn/Ende des DV abgegrenzt
+ $dtstart_fkt = new DateTime($row_funktion->datum_von);
+ $dtstart_dv = new DateTime($row_contract['von']);
+ if ($dtstart_fkt < $dtstart_dv)
+ $startdatum = $row_contract['von'];
+ else
+ $startdatum = $row_funktion->datum_von;
+
+ $dtende_fkt = new DateTime($row_funktion->datum_bis);
+ $dtende_dv = new DateTime($row_contract['bis']);
+ if ($dtende_fkt < $dtende_dv)
+ $endedatum = $row_funktion->datum_bis;
+ else
+ $endedatum = $row_contract['bis'];
+
+ // VBS anlegen und Funktion zuweisen
+ $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'funktion';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $startdatum;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $endedatum;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['benutzerfunktion_id'] = $row_funktion->benutzerfunktion_id;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['hint'] = $row_funktion->funktion_kurzbz.' '.$row_funktion->datum_von.' - '.$row_funktion->datum_bis;
+ $funktion_added++;
+ }
+ }
+ if ($funktion_added == 0)
+ {
+ echo "\nFunktion nicht zugeordnet: ".$row_funktion->funktion_kurzbz.' '.$row_funktion->datum_von.' - '.$row_funktion->datum_bis;
+ }
+ }
+ }
+ }
+
+ /**
+ * Prueft ob schon ein Vertragsbestandteil fuer Zeitaufzeichnung vorhanden ist das in den Zeitraum passt
+ * bzw direkt anschließt. Wenn es direkt anschließend ist und die Art gleich sind wird die Laufzeit verlaengert
+ * Ansonsten wird ein neuer VBS angelegt
+ */
+ private function _addVertragsbestandteilZeitaufzeichnung(&$contracts, $dv, $row_verwendung)
+ {
+ if( is_null($row_verwendung->zeitaufzeichnungspflichtig) || is_null($row_verwendung->azgrelevant) )
+ {
+ return;
+ }
+
+ if (isset($contracts['dv'][$dv]['vbs']))
+ {
+ foreach ($contracts['dv'][$dv]['vbs'] as $index_vbs=>$row_vbs)
+ {
+ if ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'zeitaufzeichnung')
+ {
+ if ($this->_isVBSAngrenzend($row_verwendung, $row_vbs)
+ && $row_vbs['zeitaufzeichnung'] == $row_verwendung->zeitaufzeichnungspflichtig
+ && $row_vbs['azgrelevant'] == $row_verwendung->azgrelevant
+ && $row_vbs['homeoffice'] == $row_verwendung->homeoffice
+ )
+ {
+ // Zeitaufzeichnungsarten bleiben gleich - Ende des VBS verlaengern
+ $contracts['dv'][$dv]['vbs'][$index_vbs]['bis'] = $row_verwendung->ende;
+ return true;
+ }
+ }
+ }
+ }
+
+ // kein passender VBS gefunden - neuen anlegen
+ $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'zeitaufzeichnung';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['zeitaufzeichnung'] = $row_verwendung->zeitaufzeichnungspflichtig;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['azgrelevant'] = $row_verwendung->azgrelevant;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['homeoffice'] = $row_verwendung->homeoffice;
+
+ return true;
+ }
+
+ /**
+ * Fueg einen Freitextbestandteil fuer All-In zum DV hinzu
+ */
+ private function _addVertragsbestandteilFreitextAllIn(&$contracts, $dv, $row_verwendung)
+ {
+ if ($row_verwendung->ba1code == 111) // All-In
+ {
+ $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'freitext';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['freitexttyp_kurzbz'] = 'allin';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['titel'] = 'allin';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['anmerkung'] = 'allin';
+ }
+ return true;
+ }
+
+ /**
+ * Fueg einen Freitextbestandteil fuer die Berfristung zum DV hinzu
+ */
+ private function _addVertragsbestandteilFreitextBefristung(&$contracts, $dv, $row_verwendung)
+ {
+ if ($row_verwendung->ba2code == 1) // Befristung
+ {
+ $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'freitext';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['freitexttyp_kurzbz'] = 'befristung';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['titel'] = 'befristung';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['anmerkung'] = 'befristung';
+ }
+ return true;
+ }
+
+ /**
+ * Prueft ob schon ein Vertragsbestandteil mit diesem Stundenausmass vorhanden ist das in den Zeitraum passt
+ * bzw direkt anschließt. Wenn es direkt anschließend ist und die Stunden gleich sind wird die Laufzeit verlaengert
+ * Ansonsten wird ein neuer VBS angelegt
+ */
+ private function _addVertragsbestandteilStunden(&$contracts, $dv, $row_verwendung)
+ {
+ // Nur anlegen wenn im aktuellen Eintrag auch Stunden eingetragen sind
+ if ($row_verwendung->vertragsstunden != '')
+ {
+ if (isset($contracts['dv'][$dv]['vbs']))
+ {
+ foreach ($contracts['dv'][$dv]['vbs'] as $index_vbs=>$row_vbs)
+ {
+ if ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'stunden' || ($row_vbs['vertragsbestandteiltyp_kurzbz'] == 'karenz' && $row_verwendung->vertragsstunden === '0.00'))
+ {
+ if ($this->_isVBSAngrenzend($row_verwendung, $row_vbs) && ((isset($row_vbs['wochenstunden']) && $row_vbs['wochenstunden'] == $row_verwendung->vertragsstunden) || $row_verwendung->vertragsstunden === '0.00'))
+ {
+ // stunden bleiben gleich - Ende des VBS verlaengern
+ $contracts['dv'][$dv]['vbs'][$index_vbs]['bis'] = $row_verwendung->ende;
+ return true;
+ }
+ }
+ }
+ }
+
+ // kein passender VBS gefunden - neuen anlegen
+ $newVBSIndex = $this->_getNewVBSIndex($contracts, $dv);
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['vertragsbestandteiltyp_kurzbz'] = 'stunden';
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['von'] = $row_verwendung->beginn;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['bis'] = $row_verwendung->ende;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['wochenstunden'] = $row_verwendung->vertragsstunden;
+ $contracts['dv'][$dv]['vbs'][$newVBSIndex]['teilzeittyp_kurzbz'] = null;
+ }
+ return true;
+ }
+
+ /**
+ * Prueft ob die Verwendung direkt an den Vertragsbestandteil angrenzt
+ * @return boolean true wenn ja, sonst false
+ */
+ private function _isVBSAngrenzend($verwendung, $vbs)
+ {
+ // Beginn Minus 1 Tag
+ $dtstart = new DateTime($verwendung->beginn);
+ $dtstartMinus1 = $dtstart->sub(new DateInterval('P1D'))->format('Y-m-d');
+
+ if ($vbs['bis'] == ''
+ || $vbs['bis'] == $dtstartMinus1)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Create a new DV or Returns the Index of an existing
+ */
+ private function _getOrCreateDV(&$contracts, $row_verwendung)
+ {
+ $unternehmen = $this->OE_DEFAULT;
+ $resultUnternehmen = $this->_getUnternehmen($row_verwendung);
+ if(hasData($resultUnternehmen))
+ {
+ $unternehmen = getData($resultUnternehmen)[0]->oe_kurzbz;
+ }
+ else
+ {
+ // Fallback Unternehmen wird verwendet falls keine Zuordnung ermittelt werden kann
+ }
+
+ if (isset($contracts['dv']) && is_array($contracts['dv']))
+ {
+ foreach($contracts['dv'] as $indexdv => $row_dv)
+ {
+ // Vertragsart ist die selbe und selbes Unternehmen
+ if ($row_dv['vertragsart_kurzbz'] == $this->matching_ba1_vertragsart[$row_verwendung->ba1code]
+ && $row_dv['oe_kurzbz'] == $unternehmen
+ )
+ {
+
+ $dtstart = new DateTime($row_verwendung->beginn);
+
+ // Zeitraum passt zur Verwendung
+ if ($row_dv['von'] <= $row_verwendung->beginn // Beginn Datum Pruefen
+ && ( // Ende innerhalb des DV
+ (isset($row_dv['bis']) && $row_verwendung->ende != '' && ($row_dv['bis'] == '' || $row_dv['bis'] >= $row_verwendung->ende)
+ )
+ || // direkt angrenzend an dieses DV
+ (isset($row_dv['bis'])
+ && ($row_dv['bis'] == ''
+ || $row_dv['bis'] == $dtstart->sub(new DateInterval('P1D'))->format('Y-m-d')
+ )
+ )
+ )
+ )
+ {
+ return $indexdv;
+ }
+ }
+ }
+ }
+
+ $newDvIndex = $this->_getNewDVIndex($contracts);
+ $contracts['dv'][$newDvIndex]['mitarbeiter_uid'] = $row_verwendung->mitarbeiter_uid;
+ $contracts['dv'][$newDvIndex]['von'] = $row_verwendung->beginn;
+ $contracts['dv'][$newDvIndex]['bis'] = $row_verwendung->ende;
+ $contracts['dv'][$newDvIndex]['oe_kurzbz'] = $unternehmen;
+ $contracts['dv'][$newDvIndex]['vertragsart_kurzbz'] = $this->matching_ba1_vertragsart[$row_verwendung->ba1code];
+
+ return $newDvIndex;
+ }
+
+ /**
+ * Ermittelt in welchem Unternehmen die Person zum betreffenden Zeitpunkt ist.
+ */
+ private function _getUnternehmen($row_verwendung)
+ {
+
+ $resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung'", $row_verwendung->beginn);
+
+ // Wenn zeitlich keine passende Unternehmenszuordnung vorhanden ist, dann suchen ob generell eine Zuordnung ermittelt werden kann
+ if(!hasData($resultUnternehmen))
+ {
+ $resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung'");
+
+ // Falls nicht wird nach erweiterten Funktionen gesucht um die Zuordnung zu ermitteln.
+ if(!hasData($resultUnternehmen))
+ {
+ $resultUnternehmen = $this->_findUnternehmen($row_verwendung->mitarbeiter_uid, "'kstzuordnung', 'oezuordnung','hilfskraft','Leitung','fbk','fbl'");
+ }
+ }
+
+ return $resultUnternehmen;
+ }
+
+ /**
+ * Detailsuche fuer die Ermittlung des Unternehmenszuordnung einer Person
+ */
+ private function _findUnternehmen($uid, $fkt=null, $datum=null)
+ {
+ $db = new DB_Model();
+
+ $qry = "
+ WITH RECURSIVE meine_oes(oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz) as
+ (
+ SELECT
+ oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz
+ FROM
+ public.tbl_organisationseinheit
+ WHERE
+ oe_kurzbz=(SELECT
+ oe_kurzbz
+ FROM
+ public.tbl_benutzerfunktion
+ WHERE
+ uid=".$db->escape($uid);
+
+ if(!is_null($datum))
+ $qry.=" AND ".$db->escape($datum)." BETWEEN datum_von AND COALESCE(datum_bis, '2999-12-31')";
+
+ if(!is_null($fkt))
+ $qry.=" AND funktion_kurzbz in ($fkt)";
+
+ $qry.="
+ ORDER BY funktion_kurzbz, datum_von LIMIT 1)
+ UNION ALL
+ SELECT
+ o.oe_kurzbz, o.oe_parent_kurzbz, o.organisationseinheittyp_kurzbz
+ FROM
+ public.tbl_organisationseinheit o, meine_oes
+ WHERE
+ o.oe_kurzbz=meine_oes.oe_parent_kurzbz
+ )
+ SELECT
+ oe_kurzbz
+ FROM
+ meine_oes
+ WHERE
+ oe_parent_kurzbz is null
+ LIMIT 1
+ ";
+
+ $resultUnternehmen = $db->execReadOnlyQuery($qry);
+ return $resultUnternehmen;
+ }
+
+ /**
+ * Ermittelt den nächsten (freien) Index für den Vertragsbetandteil
+ */
+ private function _getNewVBSIndex($contracts, $dv)
+ {
+ if (isset($contracts['dv'][$dv]['vbs']))
+ return max(array_keys($contracts['dv'][$dv]['vbs'])) + 1;
+ else
+ return 0;
+ }
+
+ /**
+ * Ermittelt den nächsten (freien) Index für das Dienstverhältnis
+ */
+ private function _getNewDVIndex($contracts)
+ {
+ if (isset($contracts['dv']) && is_array($contracts['dv']))
+ return max(array_keys($contracts['dv'])) + 1;
+ else
+ return 0;
+ }
+
+ /**
+ * Habilitation wird aus der Tabelle bis.tbl_bisverwendung in die Tabelle public.tbl_mitarbeiter uebernommen
+ * Sofern die Person einmal in den Verwendungen eine habiliation eingetragen hat wird diese in den MA-Datensatz übernommen
+ * Da es in der regel öfter vorkommt dass das hakerl vergessen wurde beim Vertragswechsel als dass die person die habiliation verliert.
+ */
+ public function migrateHabilitation()
+ {
+ $this->load->model('ressource/Mitarbeiter_model','MitarbeiterModel');
+ $db = new DB_Model();
+
+ $qry = "
+ SELECT
+ distinct mitarbeiter_uid
+ FROM
+ bis.tbl_bisverwendung
+ WHERE
+ habilitation=true";
+
+ $resultHabilitation = $db->execReadOnlyQuery($qry);
+
+ if (isSuccess($resultHabilitation) && hasData($resultHabilitation))
+ {
+ $habilitationen = getData($resultHabilitation);
+
+ foreach ($habilitationen as $row_habilitationen)
+ {
+ $this->MitarbeiterModel->update($row_habilitationen->mitarbeiter_uid, array('habilitation'=>true));
+ }
+ }
+ }
+}
diff --git a/application/controllers/system/MigrateHourlyRate.php b/application/controllers/system/MigrateHourlyRate.php
new file mode 100644
index 000000000..dbc8f1416
--- /dev/null
+++ b/application/controllers/system/MigrateHourlyRate.php
@@ -0,0 +1,268 @@
+_ci = & get_instance();
+
+ $this->load->model('codex/Bisverwendung_model', 'BisVerwendungModel');
+ $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
+ $this->load->model('ressource/Stundensatz_model', 'StundensatzModel');
+
+ $this->load->config('migratecontract');
+
+ $this->OE_DEFAULT = $this->config->item('migratecontract_oe_default');
+ $this->configerrors = array();
+ }
+
+ public function checkConfig()
+ {
+ echo "OE_DEFAULT: " . $this->OE_DEFAULT . "\n";
+
+ $this->checkOE_DEFAULT();
+
+ if( count($this->configerrors) > 0 )
+ {
+ foreach($this->configerrors AS $configerror)
+ {
+ echo $configerror . "\n";
+ }
+ die("Fehler in der Konfiguration. Abbruch!\n");
+ }
+ else
+ {
+ echo "Konfiguration OK.\n";
+ }
+ }
+
+ public function index($user = null)
+ {
+ $this->checkConfig();
+
+ echo "Lehre Stundensaetze werden migriert.\n";
+ $mitarbeiterResult = $this->_getMitarbeiterStunden($user);
+ if (isError($mitarbeiterResult)) return $mitarbeiterResult;
+ if (!hasData($mitarbeiterResult)) return error('Keine Mitarbeiterstunden gefunden');
+
+ $mitarbeiterArray = getData($mitarbeiterResult);
+
+ foreach ($mitarbeiterArray as $mitarbeiter)
+ {
+ $this->_getUnternehmen($mitarbeiter);
+ $insertResult = $this->_addStundensatz($mitarbeiter, self::STUNDENSTAZTYP_LEHRE, self::DEFAULT_DATE);
+ if (isError($insertResult)) return $insertResult;
+ }
+
+ if( $this->checkIfSAPSyncTableExists() )
+ {
+ echo "SAP Sync Tabelle gefunden. SAP Stundensaetze werden migriert.\n";
+ $sapResult = $this->_getSapStunden($user);
+ if (isError($sapResult)) return $sapResult;
+ if (!hasData($sapResult)) return error('Keinen kalkulatorischen Stundensaetze gefunden');
+
+ $mitarbeiterArray = getData($sapResult);
+
+ foreach ($mitarbeiterArray as $mitarbeiter)
+ {
+ $this->_getUnternehmen($mitarbeiter);
+ $insertResult = $this->_addStundensatz($mitarbeiter, self::STUNDENSTAZTYP_KALKULATORISCH, date_format(date_create($mitarbeiter->beginn), 'Y-m-d'));
+ if (isError($insertResult)) return $insertResult;
+ }
+ }
+ else
+ {
+ echo "SAP Sync Tabelle nicht gefunden. Ignoriere SAP Stundensaetze.\n";
+ }
+ }
+
+ protected function checkOE_DEFAULT()
+ {
+ $db = new DB_Model();
+ $oesql = 'SELECT * FROM public.tbl_organisationseinheit WHERE oe_kurzbz = ?';
+ $oeres = $db->execReadOnlyQuery($oesql, array($this->OE_DEFAULT));
+ if( !hasData($oeres) )
+ {
+ $this->configerrors[] = 'Default Organisationseinheit: "'
+ . $this->OE_DEFAULT . '" nicht gefunden.';
+ }
+ }
+
+ protected function checkIfSAPSyncTableExists()
+ {
+ $dbModel = new DB_Model();
+ $params = array(
+ DB_NAME,
+ 'sync',
+ 'tbl_sap_stundensatz'
+ );
+
+ $sql = "SELECT
+ 1 AS exists
+ FROM
+ information_schema.tables
+ WHERE
+ table_catalog = ? AND
+ table_schema = ? AND
+ table_name = ?";
+
+ $res = $dbModel->execReadOnlyQuery($sql, $params);
+
+ if( hasData($res) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ private function _getSapStunden($user = null)
+ {
+ $dbModel = new DB_Model();
+ $params = array();
+
+ $qry = "SELECT ss.mitarbeiter_uid as uid,
+ ss.sap_kalkulatorischer_stundensatz as stundensatz,
+ ss.insertamum as beginn
+ FROM sync.tbl_sap_stundensatz ss
+ WHERE ss.sap_kalkulatorischer_stundensatz IS NOT NULL";
+
+ if (!is_null($user))
+ {
+ $qry .= " AND ss.mitarbeiter_uid = ? ";
+ $params[] = $user;
+ }
+ $qry .= " ORDER BY ss.mitarbeiter_uid";
+
+ return $dbModel->execReadOnlyQuery($qry, $params);
+ }
+
+ private function _getMitarbeiterStunden($user = null)
+ {
+ $dbModel = new DB_Model();
+ $params = array();
+
+ $qry = "SELECT mitarbeiter.mitarbeiter_uid as uid,
+ stundensatz
+ FROM public.tbl_mitarbeiter mitarbeiter
+ WHERE mitarbeiter.stundensatz != 0.00
+ AND mitarbeiter.stundensatz IS NOT NULL";
+
+ if (!is_null($user))
+ {
+ $qry .= " AND mitarbeiter.mitarbeiter_uid = ?";
+ $params[] = $user;
+ }
+
+ $qry .= " ORDER BY mitarbeiter.mitarbeiter_uid";
+
+ return $dbModel->execReadOnlyQuery($qry, $params);
+ }
+
+ private function _addStundensatz($mitarbeiter, $stundensatztyp, $gueltig_von)
+ {
+ return $this->_ci->StundensatzModel->insert(
+ array(
+ 'uid' => $mitarbeiter->uid,
+ 'stundensatztyp' => $stundensatztyp,
+ 'stundensatz' => $mitarbeiter->stundensatz,
+ 'oe_kurzbz' => $mitarbeiter->unternehmen,
+ 'gueltig_von' => $gueltig_von,
+ 'insertamum' => date('Y-m-d H:i:s'),
+ 'insertvon' => 'MigrateHours'
+ )
+ );
+ }
+
+ private function _getUnternehmen(&$mitarbeiter)
+ {
+ $bvResult = $this->_ci->BisVerwendungModel->getLast($mitarbeiter->uid);
+
+ $beginn = null;
+ if (hasData($bvResult))
+ {
+ $beginn = getData($bvResult)[0]->beginn;
+ }
+
+ $unternehmenResult = $this->_findUnternehmen($mitarbeiter->uid, "'kstzuordnung', 'oezuordnung'", $beginn);
+
+ if(!hasData($unternehmenResult)) //&& hasData($bvResult)
+ {
+ $unternehmenResult = $this->_findUnternehmen($mitarbeiter->uid, "'kstzuordnung', 'oezuordnung'");
+ }
+
+ $unternehmen = $this->OE_DEFAULT;
+
+ if (hasData($unternehmenResult))
+ $unternehmen = getData($unternehmenResult)[0]->oe_kurzbz;
+
+ $mitarbeiter->unternehmen = $unternehmen;
+ }
+
+ /**
+ * Detailsuche fuer die Ermittlung des Unternehmenszuordnung einer Person
+ */
+ private function _findUnternehmen($uid, $fkt=null, $datum=null)
+ {
+ $dbModel = new DB_Model();
+
+ $qry = "
+ WITH RECURSIVE meine_oes(oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz) as
+ (
+ SELECT
+ oe_kurzbz, oe_parent_kurzbz, organisationseinheittyp_kurzbz
+ FROM
+ public.tbl_organisationseinheit
+ WHERE
+ oe_kurzbz=(SELECT
+ oe_kurzbz
+ FROM
+ public.tbl_benutzerfunktion
+ WHERE
+ uid=".$dbModel->escape($uid);
+
+ if(!is_null($datum))
+ $qry.=" AND ".$dbModel->escape($datum)." BETWEEN datum_von AND COALESCE(datum_bis, '2999-12-31')";
+
+ if(!is_null($fkt))
+ $qry.=" AND funktion_kurzbz in ($fkt)";
+
+ $qry.="
+ ORDER BY funktion_kurzbz, datum_von LIMIT 1)
+ UNION ALL
+ SELECT
+ o.oe_kurzbz, o.oe_parent_kurzbz, o.organisationseinheittyp_kurzbz
+ FROM
+ public.tbl_organisationseinheit o, meine_oes
+ WHERE
+ o.oe_kurzbz=meine_oes.oe_parent_kurzbz
+ )
+ SELECT
+ oe_kurzbz
+ FROM
+ meine_oes
+ WHERE
+ oe_parent_kurzbz is null
+ LIMIT 1
+ ";
+
+ return $dbModel->execReadOnlyQuery($qry);
+ }
+
+}
diff --git a/application/controllers/system/MigrateSalary.php b/application/controllers/system/MigrateSalary.php
new file mode 100644
index 000000000..4bd1d3e7d
--- /dev/null
+++ b/application/controllers/system/MigrateSalary.php
@@ -0,0 +1,495 @@
+ G
+ private $INDEX_LOHNART = 4;
+ private $INDEX_BEZEICHNUNG = 5;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->load->model('vertragsbestandteil/Gehaltsbestandteil_model', 'GehaltsbestandteilModel');
+ $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel');
+ $this->load->model('vertragsbestandteil/Vertragsbestandteil_model','VertragsbestandteilModel');
+ $this->load->model('vertragsbestandteil/VertragsbestandteilStunden_model','VertragsbestandteilStundenModel');
+ $this->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model','VertragsbestandteilFreitextModel');
+ $this->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model','VertragsbestandteilFunktionModel');
+
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Everything has a beginning
+ */
+ public function import($file)
+ {
+
+ // CSV Laden
+ $file = urldecode($file);
+ if($handle = fopen($file, "r"))
+ {
+ $csvrow = -1;
+ $lastuser = '';
+ $monate = array();
+ $gehaltsarr = array();
+ $gehaltsindex = 0;
+
+ while (($data = fgetcsv($handle, null, ';')) !== FALSE)
+ {
+ $csvrow++;
+ // Kopfzeile ueberspringen
+ if($csvrow == 0)
+ {
+ for($i = $this->GEHALT_BEGINN_SPALTE; $i < count($data); $i++)
+ {
+ $monate[] = $data[$i];
+ }
+ continue;
+ }
+
+ // User zur SVNR ermitteln
+ $svnr = str_replace(' ', '',$data[0]);
+ $resultuser = $this->_getUser($svnr);
+
+ if(!hasData($resultuser))
+ {
+ echo getError($resultuser);
+ break;
+ }
+
+ $user = getData($resultuser)[0]->mitarbeiter_uid;
+ echo "\nUser:".$user;
+
+ if($user != $lastuser && $lastuser != '')
+ {
+ $this->_saveGehalt($lastuser, $gehaltsarr);
+ $gehaltsarr = array();
+ $gehaltsindex = 0;
+ $lastuser = $user;
+ }
+ else
+ {
+ $lastuser = $user;
+ }
+
+ // Gehalt Clustern
+
+ $monat = 0;
+ for ($i = $this->GEHALT_BEGINN_SPALTE; $i < count($data); $i++)
+ {
+ if (count($gehaltsarr) == 0 && $data[$i] != '')
+ {
+ $gehaltsarr[$gehaltsindex]['betrag'] = $data[$i];
+ $gehaltsarr[$gehaltsindex]['lohnart'] = $data[$this->INDEX_LOHNART];
+ $gehaltsarr[$gehaltsindex]['bezeichnung'] = $data[$this->INDEX_BEZEICHNUNG];
+ $gehaltsarr[$gehaltsindex]['beginn'] = $monate[$monat];
+ }
+ else
+ {
+ if ($data[$i] != ''
+ && isset($gehaltsarr[$gehaltsindex]) && isset($gehaltsarr[$gehaltsindex]['betrag'])
+ && $gehaltsarr[$gehaltsindex]['betrag'] == $data[$i])
+ {
+ // Gehalt bleibt gleich
+ }
+ else
+ {
+ if ($data[$i] != '')
+ {
+ // Gehalt hat sich geändert
+ if ($monat != 0 && isset($gehaltsarr[$gehaltsindex]))
+ $gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1];
+
+ $gehaltsindex++;
+
+ $gehaltsarr[$gehaltsindex]['betrag'] = $data[$i];
+ $gehaltsarr[$gehaltsindex]['lohnart'] = $data[$this->INDEX_LOHNART];
+ $gehaltsarr[$gehaltsindex]['bezeichnung'] = $data[$this->INDEX_BEZEICHNUNG];
+ $gehaltsarr[$gehaltsindex]['beginn'] = $monate[$monat];
+ }
+ elseif(isset($gehaltsarr[$gehaltsindex]))
+ {
+ // Gehalt wurde beendet
+ if($monat!=0)
+ $gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1];
+ $gehaltsindex++;
+ }
+ }
+ }
+
+ $monat++;
+ }
+
+ // Zeile zu Ende - Ende Datum setzen wenn nicht für alle Monate ein Eintrag vorhanden ist
+ if($monat < count($monate) && isset($gehaltsarr[$gehaltsindex]))
+ $gehaltsarr[$gehaltsindex]['ende'] = $monate[$monat-1];
+
+ }
+ $this->_saveGehalt($lastuser, $gehaltsarr);
+ }
+ }
+
+ /**
+ * Ermittelt das passende Dienstverhaeltnis uns speichert den
+ * Gehaltsbestandteil
+ */
+ private function _saveGehalt($uid, $gehaltsarr)
+ {
+ $failed = false;
+ $this->db->trans_begin();
+
+ foreach($gehaltsarr as $row_gehalt)
+ {
+ //var_dump($row_gehalt);
+ $auszahlungen = 14;
+ $dvid = '';
+ $vbsid = '';
+ $typ = '';
+ $allin = false;
+
+ //DV und VBS Ermitteln
+ $dv = $this->DienstverhaeltnisModel->getDVByPersonUID($uid, $this->OE_DEFAULT, $row_gehalt['beginn']);
+
+ // Wenn keiner gefunden wird oder mit Monatsersteln nur ein externer gefunden wird, weitersuchen ob im Monat noch ein
+ // "richtiger" Vertrag startet
+ if (!hasData($dv) || getData($dv)[0]->vertragsart_kurzbz='externerLehrender')
+ {
+ $date = new DateTime($row_gehalt['beginn']);
+ $date->modify('last day of this month');
+ $last_day_this_month = $date->format('Y-m-d');
+
+ // Wenn mit Monatsersten kein DV gefunden wird, wird stattdessen mit Monatsletzten gesucht um DVs zu finden
+ // für Personen die erst später im Monat in ihr DV einsteigen
+ $dv = $this->DienstverhaeltnisModel->getDVByPersonUIDOverlapping($uid, $this->OE_DEFAULT, $row_gehalt['beginn'], $last_day_this_month);
+
+ if (!hasData($dv))
+ {
+ echo "\nKein passendes DV gefunden für User ".$uid." und Datum ".$row_gehalt['beginn']." -> ROLLBACK\n";
+ $failed = true;
+ break;
+ }
+ else
+ {
+ $resultdata = getData($dv);
+ foreach($resultdata as $dvdata)
+ {
+ // Externer DV wird in Monatsmitte zu echten DV - daher weitersuchen bei externenDVs da
+ // diese sowieso kein Gehalt zugeordnet haben
+ if($dvdata->vertragsart_kurzbz != 'externerLehrender')
+ {
+ $dvid = $dvdata->dienstverhaeltnis_id;
+ // Gehaltsstart wird auf den Start des DV korrigiert wenn nicht der Monatserste
+ // nur wenn das Beginndatum vor dem DV-Start liegt da sonst das Datum korrigiert wird
+ // wenn der Vertragsbestandteil wechselt
+ if($row_gehalt['beginn'] < $dvdata->von)
+ $row_gehalt['beginn'] = $dvdata->von;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ $resultdata = getData($dv);
+
+ if (count($resultdata) == 1)
+ $dvid = $resultdata[0]->dienstverhaeltnis_id;
+ }
+
+ if ($dvid == '')
+ {
+ echo "Kein oder mehrere DVs gefunden -> ROLLBACK";
+ $failed = true;
+ break;
+ }
+
+ $allin = $this->_isAllIn($dvid, $row_gehalt['beginn']);
+
+ $db = new DB_Model();
+
+ $resultVBS = $this->_getVBS($dvid, $row_gehalt['beginn']);
+
+ if (hasData($resultVBS))
+ {
+ $vbsid = getData($resultVBS)[0]->vertragsbestandteil_id;
+ $vbsbis = getData($resultVBS)[0]->bis;
+ }
+ else
+ {
+ echo "Vertragsbestandteil fuer $uid DV $dvid wurde nicht gefunden mit Beginn ".$row_gehalt['beginn']."-> ROLLBACK";
+ $failed = true;
+ break;
+ }
+
+ if ($row_gehalt['lohnart'] == 1000)
+ {
+ if($allin)
+ $typ = 'grundgehalt';
+ else
+ $typ = 'basisgehalt';
+ }
+ elseif ($row_gehalt['lohnart']==1041 // 14x
+ || $row_gehalt['lohnart']==1042 // 12x
+ || $row_gehalt['lohnart']==3410) // USTDPausch
+ {
+ $typ = 'zusatzvereinbarung';
+
+ // Freitextbestandteil anlegen fuer die Zulage
+ // Gaehalt wird der Zuglage zugeordnet
+
+ $data = array(
+ 'dienstverhaeltnis_id' => $dvid,
+ 'von' => $row_gehalt['beginn'],
+ 'vertragsbestandteiltyp_kurzbz' => 'freitext',
+ 'insertamum' => date('Y-m-d H:i:s'),
+ 'insertvon' => 'MigrateSalary'
+ );
+ if (isset($row_gehalt['ende']) && $row_gehalt['ende']!='')
+ $data['bis'] = $row_gehalt['ende'];
+
+ $resultVBS = $this->VertragsbestandteilModel->Insert($data);
+ if(!isSuccess($resultVBS))
+ {
+ echo "VBS kann nicht erstellt werden -> ROLLBACK";
+ $failed = true;
+ break;
+ }
+ $vbsid = getData($resultVBS);
+
+ $data = array(
+ 'vertragsbestandteil_id' => $vbsid,
+ 'freitexttyp_kurzbz' => 'zusatzvereinbarung',
+ 'titel' => $row_gehalt['bezeichnung'],
+ 'anmerkung' => $row_gehalt['bezeichnung'],
+ );
+ $resultVBSFreitext = $this->VertragsbestandteilFreitextModel->Insert($data);
+ if(!isSuccess($resultVBSFreitext))
+ {
+ echo "VBS Freitext Zusatz kann nicht erstellt werden -> ROLLBACK";
+ $failed = true;
+ break;
+ }
+ }
+ elseif ($row_gehalt['lohnart']==9999) // All-In Custom Lohnart nicht per Default vorhanden
+ {
+ $typ = 'zulage';
+
+ // Freitextbestandteil anlegen fuer die Zulage
+ // Gaehalt wird der Zuglage zugeordnet
+
+ $data = array(
+ 'dienstverhaeltnis_id' => $dvid,
+ 'von' => $row_gehalt['beginn'],
+ 'vertragsbestandteiltyp_kurzbz' => 'freitext',
+ 'insertamum' => date('Y-m-d H:i:s'),
+ 'insertvon' => 'MigrateSalary'
+ );
+ if (isset($row_gehalt['ende']) && $row_gehalt['ende']!='')
+ $data['bis'] = $row_gehalt['ende'];
+
+ $resultVBS = $this->VertragsbestandteilModel->Insert($data);
+ if(!isSuccess($resultVBS))
+ {
+ echo "VBS AllIn kann nicht erstellt werden -> ROLLBACK";
+ $failed = true;
+ break;
+ }
+ $vbsid = getData($resultVBS);
+
+ $data = array(
+ 'vertragsbestandteil_id' => $vbsid,
+ 'freitexttyp_kurzbz' => 'allin',
+ 'titel' => $row_gehalt['bezeichnung'],
+ 'anmerkung' => $row_gehalt['bezeichnung'],
+ );
+ $resultVBSFreitext = $this->VertragsbestandteilFreitextModel->Insert($data);
+ if(!isSuccess($resultVBSFreitext))
+ {
+ echo "VBS Freitext AllIn Zusatz kann nicht erstellt werden -> ROLLBACK";
+ $failed = true;
+ break;
+ }
+ }
+ elseif($row_gehalt['lohnart']==5500) // ATZ
+ {
+ $typ = 'lohnausgleichatz';
+ }
+ else
+ {
+ $typ = 'unbekannt - '.$row_gehalt['lohnart'];
+ echo "\nGehaltstyp unbekannt Lohnart: ".$row_gehalt['lohnart']." -> ROLLBACK";
+ $failed = true;
+ break;
+ }
+
+ // Zulage 12x und Zulage 14x aus der Bezeichnung ermitteln
+ if(strstr($row_gehalt['bezeichnung'], '12x'))
+ {
+ $auszahlungen = 12;
+ }
+
+ // Format ist 7.777,77 und wird umformattiert in 7777.77
+ $betrag = str_replace('.','', $row_gehalt['betrag']);
+ $betrag = str_replace(',','.',$betrag);
+
+ $data = array(
+ 'dienstverhaeltnis_id' => $dvid,
+ 'vertragsbestandteil_id' => $vbsid,
+ 'gehaltstyp_kurzbz' => $typ,
+ 'von' => $row_gehalt['beginn'],
+ 'grundbetrag' => $betrag,
+ 'betrag_valorisiert' => $betrag,
+ 'anmerkung' => $row_gehalt['bezeichnung'],
+ 'valorisierung' => true,
+ 'auszahlungen' => $auszahlungen,
+ 'insertamum' => date('Y-m-d H:i:s'),
+ 'insertvon' => 'MigrateSalary',
+ 'updateamum' => date('Y-m-d H:i:s'),
+ 'updatevon' => 'MigrateSalary'
+ );
+
+ if (isset($row_gehalt['ende']) && $row_gehalt['ende'] != '')
+ {
+ // Im Ende steht noch der Monatserste des letzten Monats
+ // Das muss geaendert werden auf den Monatsletzten oder das Ende des DVs
+ $date = new DateTime($row_gehalt['ende']);
+ $date->modify('last day of this month');
+ $last_day_this_month = $date->format('Y-m-d');
+
+ // Wenn das Dienstverhaeltnis in diesem Monat endet und nicht der Monatsletzte ist,
+ // dann muss hier das Ende Datum des DV stehen bzw das Ende
+ // oder das Ende des VBS falls die Person in der Monatsmitte Stunden wechselt
+ $data['bis'] = $last_day_this_month;
+
+ // Wenn der Vertragsbestandteil endet bevor das Gehalt endet, dann wir das Gehaltsende auf VBS Ende gesetzt
+ //echo "Ende des VBS: $vbsbis Ende des Gehalt: ".$data['bis'];
+ if ($vbsbis != '' && $vbsbis < $data['bis'])
+ {
+ $data['bis'] = $vbsbis;
+ //echo "Gehalt auf vbs ende gesetzt";
+ }
+ }
+
+ $ret = $this->GehaltsbestandteilModel->insert($data,
+ $this->GehaltsbestandteilModel->getEncryptedColumns()
+ );
+ }
+
+ if(!$failed)
+ {
+ $this->db->trans_commit();
+ }
+ else
+ {
+ echo "ROLLBACK";
+ $this->db->trans_rollback();
+ }
+ }
+
+ /**
+ * Prueft ob ein AllIn Vertrag vorhanden ist
+ */
+ private function _isAllIn($dvid, $datum)
+ {
+ $db = new DB_Model();
+
+ $qry = "
+ SELECT
+ *
+ FROM
+ hr.tbl_vertragsbestandteil
+ JOIN hr.tbl_vertragsbestandteil_freitext USING(vertragsbestandteil_id)
+ WHERE
+ dienstverhaeltnis_id=".$db->escape($dvid)."
+ AND vertragsbestandteiltyp_kurzbz='freitext'
+ AND ".$db->escape($datum)." BETWEEN von AND COALESCE(bis, '2999-12-31')
+ AND freitexttyp_kurzbz='allin'";
+
+ $resultAllIn = $db->execReadOnlyQuery($qry);
+
+ if (hasData($resultAllIn))
+ return true;
+ else
+ return false;
+ }
+
+ private function _getVBS($dvid, $datum)
+ {
+ $db = new DB_Model();
+
+ $qry = "
+ SELECT
+ *
+ FROM
+ hr.tbl_vertragsbestandteil
+ WHERE
+ dienstverhaeltnis_id=".$db->escape($dvid)."
+ AND vertragsbestandteiltyp_kurzbz='stunden'
+ AND ".$db->escape($datum)." BETWEEN von AND COALESCE(bis, '2999-12-31')";
+
+ $resultVBS = $db->execReadOnlyQuery($qry);
+
+ return $resultVBS;
+ }
+
+ /**
+ * Ermittelt den User zu einer SVNR
+ */
+ private function _getUser($svnr)
+ {
+ $db = new DB_Model();
+
+ $qry = "
+ SELECT
+ mitarbeiter_uid
+ FROM
+ public.tbl_person
+ JOIN public.tbl_benutzer using(person_id)
+ JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid)
+ WHERE
+ tbl_person.svnr = ". $db->escape($svnr)."
+ AND EXISTS(
+ SELECT
+ 1
+ FROM
+ hr.tbl_dienstverhaeltnis
+ WHERE
+ mitarbeiter_uid=tbl_mitarbeiter.mitarbeiter_uid
+ AND oe_kurzbz=". $db->escape($this->OE_DEFAULT)."
+ )
+ ORDER BY tbl_benutzer.aktiv DESC
+ LIMIT 1;
+ ";
+
+ $result = $db->execReadOnlyQuery($qry);
+
+ if (hasdata($result))
+ {
+ return $result;
+ }
+ else
+ return error('Kein Benutzer mit DV und SVNR:'.$svnr.' gefunden');
+ }
+}
diff --git a/application/controllers/system/Navigation.php b/application/controllers/system/Navigation.php
index c3764b612..71ab1c81b 100644
--- a/application/controllers/system/Navigation.php
+++ b/application/controllers/system/Navigation.php
@@ -22,6 +22,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
* This controller operates between (interface) the JS (GUI) and the NavigationLib (back-end)
* Provides data to the ajax get calls about the filter
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ * TODO(chris): deprecated
*/
class Navigation extends FHC_Controller
{
diff --git a/application/controllers/system/TestVBform.php b/application/controllers/system/TestVBform.php
new file mode 100644
index 000000000..9923bf05b
--- /dev/null
+++ b/application/controllers/system/TestVBform.php
@@ -0,0 +1,32 @@
+ 'system/developer:r'
+ )
+ );
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ /**
+ * Everything has a beginning
+ */
+ public function index()
+ {
+ $this->load->view('system/logs/testVBform.php');
+ }
+}
diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php
index cf0c6755a..f6e41d2e6 100644
--- a/application/controllers/system/infocenter/InfoCenter.php
+++ b/application/controllers/system/infocenter/InfoCenter.php
@@ -337,10 +337,13 @@ class InfoCenter extends Auth_Controller
$persondata = $this->_loadPersonData($person_id);
$checkPerson = $this->PersonModel->checkDuplicate($person_id);
-
if (isError($checkPerson)) show_error(getError($checkPerson));
- $duplicate = array('duplicated' => getData($checkPerson));
+ $checkUnruly = $this->PersonModel->checkUnruly($persondata['stammdaten']->vorname, $persondata['stammdaten']->nachname, $persondata['stammdaten']->gebdatum);
+ if (isError($checkUnruly)) show_error(getError($checkUnruly));
+
+ $duplicate = array('duplicate' => getData($checkPerson));
+ $unruly = array('unruly' => getData($checkUnruly));
$prestudentdata = $this->_loadPrestudentData($person_id);
@@ -351,7 +354,8 @@ class InfoCenter extends Auth_Controller
$persondata,
$prestudentdata,
$dokumentdata,
- $duplicate
+ $duplicate,
+ $unruly
);
$data[self::FHC_CONTROLLER_ID] = $this->getControllerId();
@@ -1285,67 +1289,28 @@ class InfoCenter extends Auth_Controller
$this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern'));
$kontakte = $this->input->post('kontakt');
- foreach ($kontakte as $kontakt)
- {
- $kontaktExists = $this->KontaktModel->loadWhere(array(
- 'kontakt_id' => $kontakt['id'],
- 'person_id' => $person_id,
- ));
+ if($kontakte) {
- if (hasData($kontaktExists))
- {
- $kontaktExists = getData($kontaktExists)[0];
+ foreach ($kontakte as $kontakt) {
+ $kontaktExists = $this->KontaktModel->loadWhere(array(
+ 'kontakt_id' => $kontakt['id'],
+ 'person_id' => $person_id,
+ ));
- if ($kontaktExists->kontakt === $kontakt['value'])
- continue;
+ if (hasData($kontaktExists)) {
+ $kontaktExists = getData($kontaktExists)[0];
- $update = $this->KontaktModel->update(
- array
- (
- 'kontakt_id' => $kontakt['id']
- ),
- array
- (
- 'kontakt' => isEmptyString($kontakt['value']) ? null : $kontakt['value'],
- 'updateamum' => date('Y-m-d H:i:s'),
- 'updatevon' => $this->_uid
- )
- );
+ if ($kontaktExists->kontakt === $kontakt['value'])
+ continue;
- if (isError($update))
- $this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern'));
- }
- }
-
- $adressen = $this->input->post('adresse');
-
- foreach ($adressen as $adresse)
- {
- $adresseExists = $this->AdresseModel->loadWhere(array(
- 'adresse_id' => $adresse['id'],
- 'person_id' => $person_id,
- ));
-
- if (hasData($adresseExists))
- {
- $adresse = $adresse['value'];
- $adresseExists = getData($adresseExists)[0];
- if ($adresseExists->strasse !== $adresse['strasse'] ||
- $adresseExists->plz !== $adresse['plz'] ||
- $adresseExists->ort !== $adresse['ort'] ||
- $adresseExists->nation !== $adresse['nation'])
- {
- $update = $this->AdresseModel->update(
+ $update = $this->KontaktModel->update(
array
(
- 'adresse_id' => $adresseExists->adresse_id
+ 'kontakt_id' => $kontakt['id']
),
array
(
- 'strasse' => isEmptyString($adresse['strasse']) ? null : $adresse['strasse'],
- 'plz' => isEmptyString($adresse['plz']) ? null : $adresse['plz'],
- 'ort' => isEmptyString($adresse['ort']) ? null : $adresse['ort'],
- 'nation' => isEmptyString($adresse['nation']) ? null : $adresse['nation'],
+ 'kontakt' => isEmptyString($kontakt['value']) ? null : $kontakt['value'],
'updateamum' => date('Y-m-d H:i:s'),
'updatevon' => $this->_uid
)
@@ -1354,7 +1319,48 @@ class InfoCenter extends Auth_Controller
if (isError($update))
$this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern'));
}
+ }
+ }
+
+ $adressen = $this->input->post('adresse');
+
+ if($adressen) {
+
+ foreach ($adressen as $adresse) {
+ $adresseExists = $this->AdresseModel->loadWhere(array(
+ 'adresse_id' => $adresse['id'],
+ 'person_id' => $person_id,
+ ));
+
+ if (hasData($adresseExists)) {
+ $adresse = $adresse['value'];
+ $adresseExists = getData($adresseExists)[0];
+ if ($adresseExists->strasse !== $adresse['strasse'] ||
+ $adresseExists->plz !== $adresse['plz'] ||
+ $adresseExists->ort !== $adresse['ort'] ||
+ $adresseExists->nation !== $adresse['nation']) {
+ $update = $this->AdresseModel->update(
+ array
+ (
+ 'adresse_id' => $adresseExists->adresse_id
+ ),
+ array
+ (
+ 'strasse' => isEmptyString($adresse['strasse']) ? null : $adresse['strasse'],
+ 'plz' => isEmptyString($adresse['plz']) ? null : $adresse['plz'],
+ 'ort' => isEmptyString($adresse['ort']) ? null : $adresse['ort'],
+ 'nation' => isEmptyString($adresse['nation']) ? null : $adresse['nation'],
+ 'updateamum' => date('Y-m-d H:i:s'),
+ 'updatevon' => $this->_uid
+ )
+ );
+
+ if (isError($update))
+ $this->terminateWithJsonError($this->p->t('ui', 'fehlerBeimSpeichern'));
+ }
+
+ }
}
}
@@ -2383,4 +2389,4 @@ class InfoCenter extends Auth_Controller
$this->outputJsonSuccess("Success");
}
-}
+}
\ No newline at end of file
diff --git a/application/controllers/system/messages/FASMessages.php b/application/controllers/system/messages/FASMessages.php
index 55d1da25f..e2169af9b 100644
--- a/application/controllers/system/messages/FASMessages.php
+++ b/application/controllers/system/messages/FASMessages.php
@@ -37,7 +37,7 @@ class FASMessages extends Auth_Controller
// Loads the view to write a new message with a template
$this->load->view(
- 'system/messages/htmlWriteTemplate',
+ 'system/messages/FAShtmlWriteTemplate',
$this->CLMessagesModel->prepareHtmlWriteTemplatePrestudents($prestudents)
);
}
@@ -53,7 +53,7 @@ class FASMessages extends Auth_Controller
// Loads the view to write a new message with a template
$this->load->view(
- 'system/messages/htmlWriteTemplate',
+ 'system/messages/FAShtmlWriteTemplate',
$this->CLMessagesModel->prepareHtmlWriteTemplatePrestudents($prestudents, $message_id, $recipient_id)
);
}
diff --git a/application/core/Auth_Controller.php b/application/core/Auth_Controller.php
index c407a106f..466627fe3 100644
--- a/application/core/Auth_Controller.php
+++ b/application/core/Auth_Controller.php
@@ -7,6 +7,10 @@ if (!defined('BASEPATH')) exit('No direct script access allowed');
*/
abstract class Auth_Controller extends FHC_Controller
{
+ // Special Permissions
+ const PERM_ANONYMOUS = 'anonymous'; // Everyone
+ const PERM_LOGGED = 'logged_in'; // Every registered user
+
/**
* Extends this controller if authentication is required
*/
@@ -14,17 +18,41 @@ abstract class Auth_Controller extends FHC_Controller
{
parent::__construct();
- // Loads authentication library and starts authentication
- $this->load->library('AuthLib');
+ if (!is_array($requiredPermissions) || isEmptyArray($requiredPermissions))
+ show_error('The given permissions is not a valid array or it is an empty one');
+
+ if (!isset($requiredPermissions[$this->router->method]))
+ show_error('The given permission array does not contain the given method or is not correctly set');
+
+ $anonAllowed = false;
+ if ($requiredPermissions[$this->router->method] == self::PERM_ANONYMOUS)
+ $anonAllowed = true;
+ elseif (is_array($requiredPermissions[$this->router->method])
+ && in_array(self::PERM_ANONYMOUS, $requiredPermissions[$this->router->method]))
+ $anonAllowed = true;
- // Checks if the caller is allowed to access to this content
- $this->_isAllowed($requiredPermissions);
+ if ($anonAllowed) {
+ // Loads authentication library without authentication
+ $this->load->library('AuthLib', [false]);
+
+ // Loads helper since it would only be called on authentication
+ $this->load->helper('hlp_authentication');
+ } else {
+ // Loads authentication library and starts authentication
+ $this->load->library('AuthLib');
+
+ // Checks if the caller is allowed to access to this content
+ $this->_isAllowed($requiredPermissions);
+ }
}
/**
* Checks if the caller is allowed to access to this content with the given permissions
* If it is not allowed will set the HTTP header with code 401
* Wrapper for permissionlib->isEntitled
+ *
+ * @param array $requiredPermissions
+ * @return void
*/
private function _isAllowed($requiredPermissions)
{
@@ -34,28 +62,145 @@ abstract class Auth_Controller extends FHC_Controller
// Checks if this user is entitled to access to this content
if (!$this->permissionlib->isEntitled($requiredPermissions, $this->router->method))
{
- $this->output->set_status_header(REST_Controller::HTTP_UNAUTHORIZED); // set the HTTP header as unauthorized
-
- $this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output
-
- // Prints the main error message
- $this->eprintflib->printError('You are not allowed to access to this content');
- // Prints the called controller name
- $this->eprintflib->printInfo('Controller name: '.$this->router->class);
- // Prints the called controller method name
- $this->eprintflib->printInfo('Method name: '.$this->router->method);
- // Prints the required permissions needed to access to this method
- $this->eprintflib->printInfo('Required permissions: '.$this->_rpsToString($requiredPermissions, $this->router->method));
-
+ $this->_outputAuthError($requiredPermissions);
exit; // immediately terminate the execution
}
}
+ /**
+ * Checks for Permissions depending if the given person is a
+ * Mitarbeiter and/or Student
+ * and exits/outputs an error if they are not met.
+ *
+ * @param integer $person_id
+ * @param array $permMa Perms if the person is a Mitarbeiter
+ * @param array $permStud Perms if the person is a Student
+ *
+ * @return void
+ */
+ protected function checkPermissionsForPerson($person_id, $permMa, $permStud)
+ {
+ $res = $this->hasPermissionsForPerson($person_id, $permMa, $permStud);
+
+ if ($res) {
+ $perm = array_keys(array_flip(array_merge($res|1 ? $permMa : [], $res|2 ? $permStud : [])));
+ $this->_outputAuthError([$this->router->method => $perm]);
+ }
+ }
+
+ /**
+ * Checks for Permissions depending on the Studiengang of a Prestudent
+ * and exits/outputs an error if they are not met.
+ *
+ * @param integer $prestudent_id
+ * @param array $permStud Perms if the person is a Student
+ *
+ * @return void
+ */
+ protected function checkPermissionsForPrestudent($prestudent_id, $permStud)
+ {
+ if (!$this->hasPermissionsForPrestudent($prestudent_id, $permStud)) {
+ $this->_outputAuthError([$this->router->method => $permStud]);
+ }
+ }
+
+ /**
+ * Checks for Permissions depending if the given person is a
+ * Mitarbeiter and/or Student
+ * and returns the result.
+ *
+ * @param integer $person_id
+ * @param array $permMa Perms if the person is a Mitarbeiter
+ * @param array $permStud Perms if the person is a Student
+ *
+ * @return integer 0 if permission is granted
+ */
+ protected function hasPermissionsForPerson($person_id, $permMa, $permStud)
+ {
+ $res = 3;
+ $this->load->model('person/Person_model', 'PersonModel');
+ $this->PersonModel->addJoin('public.tbl_benutzer', 'person_id');
+ $this->PersonModel->addJoin('public.tbl_mitarbeiter', 'uid = mitarbeiter_uid');
+ $result = $this->PersonModel->load($person_id);
+ if (hasData($result)) {
+ if ($this->permissionlib->isEntitled(['a' => $permMa], 'a'))
+ return 0;
+ $res = 1;
+ }
+ $this->PersonModel->addJoin('public.tbl_prestudent', 'person_id');
+ $result = $this->PersonModel->load($person_id);
+ if (hasData($result)) {
+ $permStudConverted = [];
+ foreach (getData($result) as $row) {
+ foreach ($permStud as $k => $v) {
+ if (!isset($permStudConverted[$k])) {
+ $permStudConverted[$k] = $this->permissionlib->convertAccessType($v);
+ }
+ if ($this->permissionlib->isBerechtigt($permStudConverted[$k][0], $permStudConverted[$k][1], $row->studiengang_kz))
+ return 0;
+ }
+ }
+ $res += 2;
+ }
+ return $res;
+ }
+
+ /**
+ * Checks for Permissions depending on the Studiengang of a Prestudent
+ * and returns the result.
+ *
+ * @param integer $prestudent_id
+ * @param array $permStud Perms if the person is a Student
+ *
+ * @return boolean
+ */
+ protected function hasPermissionsForPrestudent($prestudent_id, $permStud)
+ {
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+ $result = $this->PrestudentModel->load($prestudent_id);
+ if (!hasData($result))
+ show_404();
+ $stg = current(getData($result))->studiengang_kz;
+ foreach ($permStud as $k => $v) {
+ $perm = $this->permissionlib->convertAccessType($v);
+ if ($this->permissionlib->isBerechtigt($perm[0], $perm[1], $stg))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Outputs an error message and sets the HTTP Header.
+ * This function is protected so that it can be overwritten.
+ *
+ * @param array $requiredPermissions
+ * @return void
+ */
+ protected function _outputAuthError($requiredPermissions)
+ {
+ $this->output->set_status_header(REST_Controller::HTTP_UNAUTHORIZED); // set the HTTP header as unauthorized
+
+ $this->load->library('EPrintfLib'); // loads the EPrintfLib to format the output
+
+ // Prints the main error message
+ $this->eprintflib->printError('You are not allowed to access to this content');
+ // Prints the called controller name
+ $this->eprintflib->printInfo('Controller name: '.$this->router->class);
+ // Prints the called controller method name
+ $this->eprintflib->printInfo('Method name: '.$this->router->method);
+ // Prints the required permissions needed to access to this method
+ $this->eprintflib->printInfo('Required permissions: '.$this->_rpsToString($requiredPermissions, $this->router->method));
+ }
+
/**
* Converts an array of permissions to a string that contains them as a comma separated list
* Ex: ", , "
+ *
+ * @param array $requiredPermissions
+ * @param string $method
+ * @return void
*/
- private function _rpsToString($requiredPermissions, $method)
+ final protected function _rpsToString($requiredPermissions, $method)
{
$strRequiredPermissions = ''; // string that contains all the required permissions needed to access to this method
diff --git a/application/core/CI3_Events.php b/application/core/CI3_Events.php
new file mode 100644
index 000000000..33a96b89e
--- /dev/null
+++ b/application/core/CI3_Events.php
@@ -0,0 +1,51 @@
+.
+ */
+
+use \stdClass as stdClass;
+
if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
@@ -27,6 +46,15 @@ class DB_Model extends CI_Model
const PGSQL_INT8_TYPE = 'int8';
const PGSQL_FLOAT4_TYPE = 'float4';
const PGSQL_FLOAT8_TYPE = 'float8';
+ const PGSQL_BYTEA_TYPE = 'bytea';
+
+ // Name of the config entry containing an array of password that can be used to encrypt/decrypt
+ const CRYPT_CONF_PASSWORDS = 'encryption_passwords';
+ const CRYPT_CAST = 'cast';
+ const CRYPT_PASSWORD_NAME = 'passwordName';
+ const CRYPT_SELECT_TEMPLATE = 'PGP_SYM_DECRYPT(%s, \'%s\')::%s AS %s';
+ const CRYPT_WHERE_TEMPLATE = 'PGP_SYM_DECRYPT(%s, \'%s\')::%s';
+ const CRYPT_WRITE_TEMPLATE = 'PGP_SYM_ENCRYPT(\'%s\', \'%s\')';
protected $dbTable; // Name of the DB-Table for CI-Insert, -Update, ...
protected $pk; // Name of the PrimaryKey for DB-Update, Load, ...
@@ -36,7 +64,7 @@ class DB_Model extends CI_Model
private $executedQueryMetaData;
private $executedQueryListFields;
- private $debugMode;
+ private $debugMode; // Debug mode enable (true) or disabled (false)
/**
* Constructor
@@ -46,20 +74,23 @@ class DB_Model extends CI_Model
// Call parent constructor
parent::__construct();
- // Set properties
- $this->hasSequence = true;
-
- // Loads DB conns and confs
+ // Loads DB connections and configs
$this->load->database($dbtype);
+ // Loads the DB config to encrypt/decrypt data
+ $this->config->load('db_crypt');
+
+ // Set properties
+ $this->hasSequence = true;
+ $this->debugMode = isset($this->db->db_debug) && $this->db->db_debug === true;
+
+ // Loads UDF model
$this->load->model('system/UDF_model', 'UDFModel');
// Loads the UDF library
$this->load->library('UDFLib');
// Loads the logs library
$this->load->library('LogLib');
-
- $this->debugMode = isset($this->db->db_debug) && $this->db->db_debug === true;
}
// ------------------------------------------------------------------------------------------
@@ -85,13 +116,20 @@ class DB_Model extends CI_Model
* @param array $data DataArray for Insert
* @return array
*/
- public function insert($data)
+ public function insert($data, $encryptedColumns = null)
{
// Check class properties
if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL);
// If this table has UDF and the validation of them is ok
- if (isError($validate = $this->_prepareUDFsWrite($data, $this->dbTable))) return $validate;
+ $validate = $this->_prepareUDFsWrite($data, $this->dbTable);
+ if (isError($validate)) return $validate;
+
+ // Add the pgp_sym_eccrypt postgresql function to the set clause if needed
+ $this->_addEncrypt($encryptedColumns, $data);
+
+ // Add the pgp_sym_eccrypt postgresql function to the set clause if needed
+ if (!empty($encryptedColumns)) $this->_addEncrypt($encryptedColumns, $data);
// DB-INSERT
$insert = $this->db->insert($this->dbTable, $data);
@@ -135,14 +173,15 @@ class DB_Model extends CI_Model
* @param array $data DataArray for Insert
* @return array
*/
- public function update($id, $data)
+ public function update($id, $data, $encryptedColumns = null)
{
// Check class properties
if (is_null($this->pk)) return error('The given primary key is not valid', EXIT_MODEL);
if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL);
// If this table has UDF and the validation of them is ok
- if (isError($validate = $this->_prepareUDFsWrite($data, $this->dbTable, $id))) return $validate;
+ $validate = $this->_prepareUDFsWrite($data, $this->dbTable, $id);
+ if (isError($validate)) return $validate;
$tmpId = $id;
@@ -161,6 +200,9 @@ class DB_Model extends CI_Model
$this->db->where($tmpId);
+ // Add the pgp_sym_eccrypt postgresql function to the set clause if needed
+ $this->_addEncrypt($encryptedColumns, $data);
+
// DB-UPDATE
$update = $this->db->update($this->dbTable, $data);
@@ -224,7 +266,7 @@ class DB_Model extends CI_Model
* @param string $id ID (Primary Key) for SELECT ... WHERE
* @return array
*/
- public function load($id = null)
+ public function load($id = null, $encryptedColumns = null)
{
// Check class properties
if (is_null($this->pk)) return error('The given primary key is not valid', EXIT_MODEL);
@@ -245,7 +287,7 @@ class DB_Model extends CI_Model
$tmpId = array($this->pk => $id);
}
- return $this->loadWhere($tmpId);
+ return $this->loadWhere($tmpId, $encryptedColumns);
}
/**
@@ -253,11 +295,14 @@ class DB_Model extends CI_Model
*
* @return array
*/
- public function loadWhere($where = null)
+ public function loadWhere($where = null, $encryptedColumns = null)
{
// Check class properties
if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL);
+ // Add the pgp_sym_decrypt postgresql function to the select and where clause if needed
+ $this->_addDecryptLoad($encryptedColumns, $where);
+
// Execute query
$result = $this->db->get_where($this->dbTable, $where);
@@ -265,7 +310,7 @@ class DB_Model extends CI_Model
if ($result)
{
- return success($this->_toPhp($result));
+ return success($this->_toPhp($result, $encryptedColumns));
}
else
{
@@ -303,7 +348,8 @@ class DB_Model extends CI_Model
// NOTE: $this->db->list_fields($tables[$t]) doesn't work if there are two tables with
// the same name in two different schemas, use this workaround
$fields = array();
- if (isSuccess($lstColumns = $this->_list_columns($schemaAndTable->schema, $schemaAndTable->table)))
+ $lstColumns = $this->_list_columns($schemaAndTable->schema, $schemaAndTable->table);
+ if (isSuccess($lstColumns))
{
$fields = $lstColumns->retval;
}
@@ -381,7 +427,8 @@ class DB_Model extends CI_Model
$tmpFilteredArray = array_filter(get_object_vars($sideTableObj));
if (isset($tmpFilteredArray) && count($tmpFilteredArray) > 0)
{
- if (($k = $this->_findMainTable($mainTableObj, $returnArray)) === false)
+ $k = $this->_findMainTable($mainTableObj, $returnArray);
+ if ($k === false)
{
$mainTableObj->{$sideTableProperty} = array($sideTableObj);
$returnArray[$returnArrayCounter++] = $mainTableObj;
@@ -758,14 +805,13 @@ class DB_Model extends CI_Model
/**
* Like execQuery, but it allows only to perform queries to read data
*/
- public function execReadOnlyQuery($query, $parametersArray = null)
+ public function execReadOnlyQuery($query, $parametersArray = null, $encryptedColumns = null)
{
$result = error('You are allowed to run only query for reading data'); //
$cleanedQuery = trim(preg_replace('/\t|\n|\r|;/', '', $query)); //
//
- if (
- (stripos($cleanedQuery, 'INSERT') > 0 || stripos($cleanedQuery, 'INSERT') == false)
+ if ((stripos($cleanedQuery, 'INSERT') > 0 || stripos($cleanedQuery, 'INSERT') == false)
&& (stripos($cleanedQuery, 'UPDATE') > 0 || stripos($cleanedQuery, 'UPDATE') == false)
&& (stripos($cleanedQuery, 'CREATE') > 0 || stripos($cleanedQuery, 'CREATE') == false)
&& (stripos($cleanedQuery, 'DELETE') > 0 || stripos($cleanedQuery, 'DELETE') == false)
@@ -775,12 +821,29 @@ class DB_Model extends CI_Model
{
$queryToExec = str_replace(';', '', $query); //
- $result = $this->execQuery($queryToExec, $parametersArray);
+ $result = $this->execQuery($queryToExec, $parametersArray, $encryptedColumns);
}
return $result;
}
+ public function getDbTable()
+ {
+ return $this->dbTable;
+ }
+
+ public function getPk()
+ {
+ return $this->pk;
+ }
+
+ public function getPks()
+ {
+ if (is_array($this->pk))
+ return $this->pk;
+ return [$this->pk];
+ }
+
// ------------------------------------------------------------------------------------------
// Protected methods
@@ -790,13 +853,16 @@ class DB_Model extends CI_Model
* boolean if the query is of the write type (INSERT, UPDATE, DELETE...)
* array that represents DB data
*/
- protected function execQuery($query, $parametersArray = null)
+ protected function execQuery($query, $parametersArray = null, $encryptedColumns = null)
{
$result = null;
// If the query is empty don't lose time
if (!isEmptyString($query))
{
+ // Add the pgp_sym_decrypt postgresql function to the given query
+ $this->_addDecryptQuery($encryptedColumns, $query);
+
// If there are parameters to bind to the query
if (is_array($parametersArray) && count($parametersArray) > 0)
{
@@ -812,7 +878,7 @@ class DB_Model extends CI_Model
// If no errors occurred
if ($resultDB)
{
- $result = success($this->_toPhp($resultDB));
+ $result = success($this->_toPhp($resultDB, $encryptedColumns));
}
else
{
@@ -840,7 +906,8 @@ class DB_Model extends CI_Model
$result->schema = DB_Model::DEFAULT_SCHEMA;
// If a schema is specified
- if (($pos = strpos($schemaAndTable, '.')) !== false)
+ $pos = strpos($schemaAndTable, '.');
+ if ($pos !== false)
{
$result->schema = substr($schemaAndTable, 0, $pos);
$result->table = substr($schemaAndTable, $pos + 1);
@@ -851,6 +918,207 @@ class DB_Model extends CI_Model
// ------------------------------------------------------------------------------------------
// Private methods
+ //
+ //
+
+ /**
+ * To add the pgp_sym_encrypt function to the set clause where needed
+ */
+ private function _addEncrypt($encryptedColumns, &$data)
+ {
+ // If encryptedColumns is not defined then exit
+ if (isEmptyArray($encryptedColumns)) return;
+
+ $tmpData = array(); // Temporary array used to copy not encrypted columns
+
+ // For each column that is going to be inserted/updated
+ foreach ($data as $column => $value)
+ {
+ // If the current column is in the list of the columns to be encrypted
+ // and contains the password name element
+ if (array_key_exists($column, $encryptedColumns)
+ && array_key_exists(self::CRYPT_PASSWORD_NAME, $encryptedColumns[$column]))
+ {
+ // Password to encrypt data
+ $cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS);
+ $encryptionPassword = $cryptConfPasswords[$encryptedColumns[$column][self::CRYPT_PASSWORD_NAME]];
+
+ // Add the encrypted column to the set clause without escaping
+ $this->db->set(
+ $column,
+ sprintf(
+ self::CRYPT_WRITE_TEMPLATE,
+ $value,
+ $encryptionPassword
+ ),
+ false // no escaping
+ );
+ }
+ else // otherwise copy this element as it is
+ {
+ $tmpData[$column] = $value;
+ }
+ }
+
+ $data = $tmpData; // this array does not contain encrypted columns
+ }
+
+ /**
+ * To add the pgp_sym_decrypt function to the given query
+ */
+ private function _addDecryptQuery($encryptedColumns, &$query)
+ {
+ // If it is request to get encrypted columns
+ if (!isEmptyArray($encryptedColumns))
+ {
+ // For each requested encrypted column
+ foreach ($encryptedColumns as $encryptedColumn => $definition)
+ {
+ // If the requested encrypted column is well defined
+ if (!isEmptyArray($definition)
+ && array_key_exists(self::CRYPT_CAST, $definition)
+ && array_key_exists(self::CRYPT_PASSWORD_NAME, $definition))
+ {
+ // And if exists the wanted password to decrypt in the configs
+ if (array_key_exists($definition[self::CRYPT_PASSWORD_NAME], $this->config->item(self::CRYPT_CONF_PASSWORDS)))
+ {
+ // Password to decrypt data
+ $cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS);
+ $decryptionPassword = $cryptConfPasswords[$definition[self::CRYPT_PASSWORD_NAME]];
+
+ // Find and replace all the occurrences of the provided encrypted columns
+ // with the postgresql decryption function
+ $query = str_replace(
+ $encryptedColumn,
+ sprintf(
+ self::CRYPT_WHERE_TEMPLATE,
+ $encryptedColumn,
+ $decryptionPassword,
+ $definition[self::CRYPT_CAST]
+ ),
+ $query
+ );
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * To add the pgp_sym_decrypt function to the select and where clause where needed
+ */
+ private function _addDecryptLoad($encryptedColumns, &$where)
+ {
+ // If it is request to get encrypted columns
+ if (!isEmptyArray($encryptedColumns))
+ {
+ // For each requested encrypted column
+ foreach ($encryptedColumns as $encryptedColumn => $definition)
+ {
+ // If the requested encrypted column is well defined
+ if (!isEmptyArray($definition)
+ && array_key_exists(self::CRYPT_CAST, $definition)
+ && array_key_exists(self::CRYPT_PASSWORD_NAME, $definition))
+ {
+ // And if exists the wanted password to decrypt in the configs
+ if (array_key_exists($definition[self::CRYPT_PASSWORD_NAME], $this->config->item(self::CRYPT_CONF_PASSWORDS)))
+ {
+ // Password to decrypt data
+ $cryptConfPasswords = $this->config->item(self::CRYPT_CONF_PASSWORDS);
+ $decryptionPassword = $cryptConfPasswords[$definition[self::CRYPT_PASSWORD_NAME]];
+
+ // -----------------------------------------
+ // SELECT
+
+ // Add to the select clause the column to be decrypted
+ // NOTE: this is going to override any previously added column with the same name
+ $this->addSelect(
+ sprintf(
+ self::CRYPT_SELECT_TEMPLATE,
+ $encryptedColumn,
+ $decryptionPassword,
+ $definition[self::CRYPT_CAST],
+ $encryptedColumn
+ )
+ );
+
+ // -----------------------------------------
+ // WHERE
+
+ // If the where parameter is a valid array
+ if (!isEmptyArray($where))
+ {
+ $tmpWhere = array();
+
+ // For each condition of the where clause
+ foreach ($where as $column => $condition)
+ {
+ $operator = null; // operator not found in the column name
+
+ // Custom operators with 2 chars
+ if (strpos($column, '>=') != false
+ || strpos($column, '<=') != false
+ || strpos($column, '!=') != false
+ || strpos($column, '<>') != false
+ )
+ {
+ $operator = ' '.substr(trim($column), -2).' ';
+ }
+ // Custom operators with 1 chars
+ elseif (strpos($column, '>') != false
+ || strpos($column, '<') != false
+ || strpos($column, '=') != false
+ )
+ {
+ $operator = ' '.substr(trim($column), -1).' ';
+ }
+ else // default operator
+ {
+ $operator = ' = ';
+ }
+
+ // If the column from the where clause is the same from the encrypted columns definition
+ if (trim($column) == $encryptedColumn
+ || ($operator != null && substr(trim($column), 0, strlen(trim($column)) - 2) == $encryptedColumn)
+ )
+ {
+ // Then rename the column using the postgresql decryption function
+ $tmpWhere[sprintf(
+ self::CRYPT_WHERE_TEMPLATE,
+ $encryptedColumn,
+ $decryptionPassword,
+ $definition[self::CRYPT_CAST]
+ ).$operator] = $condition;
+ }
+ else // otherwise copy the column as it is
+ {
+ $tmpWhere[$column] = $condition;
+ }
+ }
+
+ $where = $tmpWhere; // replace with the new where
+ }
+ // Otherwise if the where parameter is a valid string
+ elseif (!isEmptyString($where))
+ {
+ // Find and replace all the occurrences of the provided encrypted columns
+ // with the postgresql decryption function
+ $where = str_replace(
+ $encryptedColumn,
+ sprintf(
+ self::CRYPT_WHERE_TEMPLATE,
+ $encryptedColumn,
+ $decryptionPassword,
+ $definition[self::CRYPT_CAST]
+ ),
+ $where
+ );
+ }
+ }
+ }
+ }
+ }
+ }
/**
* Invalid ID
@@ -877,11 +1145,11 @@ class DB_Model extends CI_Model
{
if ($id != null)
{
- $prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $this->dbTable, $this->_getUDFsNoPerms($id));
+ $prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $schemaAndTable, $this->_getUDFsNoPerms($id));
}
else
{
- $prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $this->dbTable);
+ $prepareUDFsWrite = $this->udflib->prepareUDFsWrite($data, $schemaAndTable);
}
}
@@ -895,7 +1163,7 @@ class DB_Model extends CI_Model
* - A FALSE value on failure
* - Otherwise an object filled with data on success
*/
- private function _toPhp($result)
+ private function _toPhp($result, $encryptedColumns = null)
{
$udfs = false; // if UDFs are inside the given result set
$toPhp = $result; // if there is nothing to convert then return the result from DB
@@ -911,7 +1179,9 @@ class DB_Model extends CI_Model
// Looking for booleans, arrays and UDFs
foreach ($this->executedQueryMetaData as $eqmd)
{
- // If array type, boolean type OR a UDF
+ // If array type, boolean type, numeric type
+ // Or bytea type
+ // Or UDF type
if (strpos($eqmd->type, DB_Model::PGSQL_ARRAY_TYPE) !== false
|| $eqmd->type == DB_Model::PGSQL_BOOLEAN_TYPE
|| $eqmd->type == DB_Model::PGSQL_INT2_TYPE
@@ -919,6 +1189,7 @@ class DB_Model extends CI_Model
|| $eqmd->type == DB_Model::PGSQL_INT8_TYPE
|| $eqmd->type == DB_Model::PGSQL_FLOAT4_TYPE
|| $eqmd->type == DB_Model::PGSQL_FLOAT8_TYPE
+ || $eqmd->type == DB_Model::PGSQL_BYTEA_TYPE
|| $this->udflib->isUDFColumn($eqmd->name, $eqmd->type))
{
// If UDFs are inside this result set
@@ -981,6 +1252,21 @@ class DB_Model extends CI_Model
{
$resultElement->{$toBeConverted->name} = $this->pgFloatPhp($resultElement->{$toBeConverted->name});
}
+ // Byte A type
+ elseif ($toBeConverted->type == DB_Model::PGSQL_BYTEA_TYPE)
+ {
+ // If encrypted columns are defined
+ // and if the byte a column is defined as encrypted column
+ if (!isEmptyArray($encryptedColumns)
+ && array_key_exists($toBeConverted->name, $encryptedColumns))
+ {
+ // keep the column
+ }
+ else // otherwise remove the column from the result
+ {
+ unset($resultElement->{$toBeConverted->name});
+ }
+ }
}
}
}
diff --git a/application/core/FHCAPI_Controller.php b/application/core/FHCAPI_Controller.php
new file mode 100644
index 000000000..36388e271
--- /dev/null
+++ b/application/core/FHCAPI_Controller.php
@@ -0,0 +1,236 @@
+returnObj['meta']) || !isset($this->returnObj['meta']['status'])) {
+ switch ($http_response_code) {
+ case 200:
+ $this->setStatus(self::STATUS_SUCCESS);
+ break;
+ case 400:
+ $this->setStatus(self::STATUS_FAIL);
+ break;
+ default:
+ $this->setStatus(self::STATUS_ERROR);
+ break;
+ }
+ }
+
+ return json_encode($this->returnObj);
+ });
+
+ // NOTE(chris): overwrite error_views_path before constructor
+ load_class('Config')->set_item('error_views_path', VIEWPATH.'errors'.DIRECTORY_SEPARATOR.'json'.DIRECTORY_SEPARATOR);
+
+ parent::__construct($requiredPermissions);
+
+ // For JSON Requests (as opposed to multipart/form-data) get the $_POST variable from the input stream instead
+ if ($this->input->get_request_header('Content-Type', true) == 'application/json')
+ $_POST = json_decode($this->security->xss_clean($this->input->raw_input_stream), true);
+ elseif (isset($_POST['_jsondata'])) {
+ $_POST = array_merge($_POST, json_decode($_POST['_jsondata'], true));
+ unset($_POST['_jsondata']);
+ }
+ }
+
+
+ // ---------------------------------------------------------------
+ // Handle Output object
+ // ---------------------------------------------------------------
+
+ /**
+ * @param string|array|object $data
+ * @param string $type (optional)
+ * @return void
+ */
+ public function addError($data, $type = null)
+ {
+ if (!isset($this->returnObj['errors']))
+ $this->returnObj['errors'] = [];
+
+ $error = [];
+
+ if (is_array($data)) {
+ if ($type == self::ERROR_TYPE_VALIDATION)
+ $error['messages'] = $data;
+ else
+ $error = $data;
+ } elseif (is_object($data)) {
+ $error = (array)$data;
+ } else {
+ $error['message'] = $data;
+ }
+
+ if ($type)
+ $error['type'] = $type;
+
+ if (!isset($error['type']))
+ $error['type'] = self::ERROR_TYPE_GENERAL;
+
+ $this->returnObj['errors'][] = $error;
+ }
+
+ /**
+ * @param mixed $data
+ * @return void
+ */
+ public function setData($data)
+ {
+ $this->returnObj['data'] = $data;
+ }
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ * @return void
+ */
+ public function addMeta($key, $value)
+ {
+ if (!isset($this->returnObj['meta']))
+ $this->returnObj['meta'] = [];
+ $this->returnObj['meta'][$key] = $value;
+ }
+
+ /**
+ * @param string $status
+ * @return void
+ */
+ public function setStatus($status)
+ {
+ $this->addMeta('status', $status);
+ }
+
+
+ // ---------------------------------------------------------------
+ // Handle Output object - Shortcut functions
+ // ---------------------------------------------------------------
+
+ /**
+ * @param mixed $data (optional)
+ * @return void
+ */
+ protected function terminateWithSuccess($data = null)
+ {
+ $this->setData($data);
+ $this->setStatus(self::STATUS_SUCCESS);
+ exit;
+ }
+
+ /**
+ * @param array $errors
+ * @return void
+ */
+ protected function terminateWithValidationErrors($errors)
+ {
+ $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST);
+ $this->addError($errors, self::ERROR_TYPE_VALIDATION);
+ $this->setStatus(self::STATUS_FAIL);
+ exit(EXIT_ERROR);
+ }
+
+ /**
+ * @param array $error
+ * @param string $type (optional)
+ * @param integer $status (optional)
+ * @return void
+ */
+ protected function terminateWithError($error, $type = null, $status = REST_Controller::HTTP_INTERNAL_SERVER_ERROR)
+ {
+ $this->output->set_status_header($status);
+ $this->addError($error, $type);
+ $this->setStatus(self::STATUS_ERROR);
+ exit;
+ }
+
+ /**
+ * @param stdclass $result
+ * @param string $errortype
+ * @return void
+ */
+ protected function getDataOrTerminateWithError($result, $errortype = self::ERROR_TYPE_GENERAL)
+ {
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), $errortype);
+ }
+ return $result->retval;
+ }
+
+
+ // ---------------------------------------------------------------
+ // Security
+ // ---------------------------------------------------------------
+
+ /**
+ * Outputs an error message and sets the HTTP Header.
+ * This overwrites the default behaviour to output a json object.
+ *
+ * @param array $requiredPermissions
+ * @return void
+ */
+ protected function _outputAuthError($requiredPermissions)
+ {
+ $this->output->set_status_header(isLogged() ? REST_Controller::HTTP_FORBIDDEN : REST_Controller::HTTP_UNAUTHORIZED);
+
+ $this->addError([
+ 'message' => 'You are not allowed to access to this content',
+ 'controller' => $this->router->class,
+ 'method' => $this->router->method,
+ 'required_permissions' => $this->_rpsToString($requiredPermissions, $this->router->method)
+ ], self::ERROR_TYPE_AUTH);
+ }
+}
diff --git a/application/core/IEncryption.php b/application/core/IEncryption.php
new file mode 100644
index 000000000..6b9132c23
--- /dev/null
+++ b/application/core/IEncryption.php
@@ -0,0 +1,24 @@
+.
+ */
+
+interface IEncryption
+{
+ public function getEncryptedColumns(): array;
+}
+
diff --git a/application/core/IssueResolver_Controller.php b/application/core/IssueResolver_Controller.php
index 758064ed8..ea278ddb0 100755
--- a/application/core/IssueResolver_Controller.php
+++ b/application/core/IssueResolver_Controller.php
@@ -5,21 +5,18 @@
*/
abstract class IssueResolver_Controller extends JOB_Controller
{
- const CI_PATH = 'application';
- const CI_LIBRARY_FOLDER = 'libraries';
- const EXTENSIONS_FOLDER = 'extensions';
- const ISSUE_RESOLVERS_FOLDER = 'issues/resolvers';
- const CHECK_ISSUE_RESOLVED_METHOD_NAME = 'checkIfIssueIsResolved';
+ // mappings in form fehlercode -> resolverlibrary name, fehler which have explicit resolver class defined
+ protected $_codeLibMappings = [];
- protected $_codeLibMappings;
+ // mappings in form fehlercode -> producer library name, fehler which are resolved the same way they are produced
+ protected $_codeProducerLibMappings = [];
public function __construct()
{
parent::__construct();
+ // pass extension name if calling from extension
$this->load->model('system/Issue_model', 'IssueModel');
-
- $this->load->library('IssuesLib');
}
/**
@@ -27,97 +24,29 @@ abstract class IssueResolver_Controller extends JOB_Controller
*/
public function run()
{
+ $this->load->library(
+ 'issues/PlausicheckResolverLib',
+ [
+ 'extensionName' => $this->_extensionName ?? null,
+ 'codeLibMappings' => $this->_codeLibMappings,
+ 'codeProducerLibMappings' => $this->_codeProducerLibMappings
+ ]
+ );
+
$this->logInfo("Issue resolve job started");
// load open issues with given errorcodes
- $openIssuesRes = $this->IssueModel->getOpenIssues(array_keys($this->_codeLibMappings));
+ $openIssuesRes = $this->IssueModel->getOpenIssues(
+ array_merge(array_keys($this->_codeLibMappings), array_keys($this->_codeProducerLibMappings))
+ );
- // log error if occured
- if (isError($openIssuesRes))
- {
- $this->logError(getError($openIssuesRes));
- }
- else
- {
- // log info if no data found
- if (!hasData($openIssuesRes))
- {
- $this->logInfo("No open issues found");
- }
- else
- {
- $openIssues = getData($openIssuesRes);
+ $openIssues = hasData($openIssuesRes) ? getData($openIssuesRes) : [];
- foreach ($openIssues as $issue)
- {
- // ignore if Fehlercode is not in libmappings (shouldn't be checked)
- if (!isset($this->_codeLibMappings[$issue->fehlercode])) continue;
+ $result = $this->plausicheckresolverlib->resolvePlausicheckIssues($openIssues);
- $libName = $this->_codeLibMappings[$issue->fehlercode];
-
- // add person id and oe kurzbz automatically as params, merge it with additional params
- // decode bewerbung_parameter into assoc array
- $params = array_merge(
- array('issue_id' => $issue->issue_id, 'issue_person_id' => $issue->person_id, 'issue_oe_kurzbz' => $issue->oe_kurzbz),
- isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array()
- );
-
- // if called from extension (extension name set), path includes extension names
- $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : '';
-
- // path for loading issue library
- $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/';
-
- // file path of library for check if file exists
- $issuesLibFilePath = DOC_ROOT . self::CI_PATH
- . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php';
-
- // check if library file exists
- if (!file_exists($issuesLibFilePath))
- {
- // log error and continue with next issue if not
- $this->logError("Issue library file " . $issuesLibFilePath . " does not exist");
- continue;
- }
-
- // load library connected to fehlercode
- $this->load->library($issuesLibPath . $libName);
-
- $lowercaseLibName = mb_strtolower($libName);
-
- // check if method is defined in library class
- if (!is_callable(array($this->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME)))
- {
- // log error and continue with next issue if not
- $this->logError("Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName");
- continue;
- }
-
- // call the function for checking for issue resolution
- $issueResolvedRes = $this->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params);
-
- if (isError($issueResolvedRes))
- {
- $this->logError(getError($issueResolvedRes));
- }
- else
- {
- $issueResolvedData = getData($issueResolvedRes);
-
- if ($issueResolvedData === true)
- {
- // set issue to resolved if needed
- $behobenRes = $this->issueslib->setBehoben($issue->issue_id, null);
-
- if (isError($behobenRes))
- $this->logError(getError($behobenRes));
- else
- $this->logInfo("Issue " . $issue->issue_id . " successfully resolved");
- }
- }
- }
- }
- }
+ // log if error, or log info if inserted new issue
+ foreach ($result->errors as $error) $this->logError($error);
+ foreach ($result->infos as $info) $this->logInfo($info);
$this->logInfo("Issue resolve job ended");
}
diff --git a/application/core/Notiz_Controller.php b/application/core/Notiz_Controller.php
new file mode 100644
index 000000000..05f70ee85
--- /dev/null
+++ b/application/core/Notiz_Controller.php
@@ -0,0 +1,461 @@
+ self::DEFAULT_PERMISSION_R,
+ 'getNotizen' => self::DEFAULT_PERMISSION_R,
+ 'loadNotiz' => self::DEFAULT_PERMISSION_R,
+ 'addNewNotiz' => self::DEFAULT_PERMISSION_RW,
+ 'updateNotiz' => self::DEFAULT_PERMISSION_RW,
+ 'deleteNotiz' => self::DEFAULT_PERMISSION_RW,
+ 'loadDokumente' => self::DEFAULT_PERMISSION_R,
+ 'getMitarbeiter' => self::DEFAULT_PERMISSION_R,
+ 'isBerechtigt' => self::DEFAULT_PERMISSION_R,
+ ];
+
+ if(!is_array($permissions))
+ {
+ $this->terminateWithError("Notiz_controller construct: permissions must be an array");
+ }
+
+ $merged_permissions = array_merge($default_permissions, $permissions);
+
+ parent::__construct($merged_permissions);
+
+ //Load Models
+ $this->load->model('person/Notiz_model', 'NotizModel');
+ $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui'
+ ]);
+ }
+
+ public function getUid()
+ {
+ $this->terminateWithSuccess(getAuthUID());
+ }
+
+
+ //Override function for extensions
+ protected function assignNotiz($notiz_id, $id, $type)
+ {
+ $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
+ $result = $this->NotizzuordnungModel->isValidType($type);
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $result = $this->NotizzuordnungModel->insert(array('notiz_id' => $notiz_id, $type => $id));
+ if (isError($result))
+ {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return success(getData($result));
+ }
+
+ //Override function for extensions
+ protected function deleteNotizzuordnung($notiz_id, $id, $type)
+ {
+ $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
+ $result = $this->NotizzuordnungModel->isValidType($type);
+ if (isError($result)) {
+ $this->terminateWithError('type not in table notizzuordnung enthalten..', self::ERROR_TYPE_GENERAL);
+ }
+
+ $result = $this->NotizzuordnungModel->delete(['notiz_id' => $notiz_id, $type => $id]);
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return success(getData($result));
+ }
+
+
+ //Override function for extensions
+ public function getNotizen($id, $type)
+ {
+ $result = $this->NotizzuordnungModel->isValidType($type);
+ if(isError($result))
+ $this->terminateWithError($result->retval, self::ERROR_TYPE_GENERAL);
+
+ $result = $this->NotizModel->getNotizWithDocEntries($id, $type);
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result) ?: []);
+ }
+
+
+ //Override function
+ protected function isBerechtigt($id, $typeId){
+ return $this->terminateWithError("in abstract function: define right in extension", self::ERROR_TYPE_GENERAL);
+ }
+
+ public function loadNotiz()
+ {
+ $_POST = json_decode(utf8_encode($this->input->raw_input_stream), true);
+
+ $notiz_id = $this->input->post('notiz_id');
+
+ //$this->load->model('person/Notiz_model', 'NotizModel');
+ $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'notiz_id', 'LEFT');
+ $this->NotizModel->addSelect('*');
+ $this->NotizModel->addSelect("TO_CHAR(CASE WHEN public.tbl_notiz.updateamum >= public.tbl_notiz.insertamum
+ THEN public.tbl_notiz.updateamum ELSE public.tbl_notiz.insertamum END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate");
+ $this->NotizModel->addLimit(1);
+
+ $result = $this->NotizModel->loadWhere(
+ array('notiz_id' => $notiz_id)
+ );
+ if (isError($result))
+ {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ elseif (!hasData($result))
+ {
+ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL);
+ }
+ else
+ {
+ $this->terminateWithSuccess(current(getData($result)));
+ }
+ }
+
+ public function addNewNotiz($id, $paramTyp = null)
+ {
+ $this->load->library('DmsLib');
+ $this->load->library('form_validation');
+
+ $uid = getAuthUID();
+
+ if (isset($_POST['data']))
+ {
+ $data = json_decode($_POST['data']);
+ unset($_POST['data']);
+ foreach ($data as $k => $v) {
+ $_POST[$k] = $v;
+ }
+ }
+
+ //Form Validation
+ $this->form_validation->set_rules('titel', 'Titel', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel'])
+ ]);
+
+ $this->form_validation->set_rules('text', 'Text', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Text'])
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $titel = $this->input->post('titel');
+ $text = $this->input->post('text');
+ $erledigt = $this->input->post('erledigt');
+ $verfasser_uid = isset($_POST['verfasser']) ? $_POST['verfasser'] : $uid;
+ $bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : null;
+ $type = $this->input->post('typeId');
+ $start = $this->input->post('start');
+ $ende = $this->input->post('ende');
+
+ // Start DB transaction
+ $this->db->trans_start();
+
+ //Save note
+ $result = $this->NotizModel->insert(array('titel' => $titel, 'text' => $text, 'erledigt' => $erledigt, 'verfasser_uid' => $verfasser_uid,
+ "insertvon" => $verfasser_uid, 'start' => $start, 'ende' => $ende, 'bearbeiter_uid' => $bearbeiter_uid));
+
+ if (isError($result))
+ {
+ $this->db->trans_rollback();
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ $notiz_id = $result->retval;
+
+ //save Notizzuordnung
+ $result = $this->assignNotiz($notiz_id, $id, $type);
+
+ if (isError($result))
+ {
+ $this->db->trans_rollback();
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ //save Documents
+ $dms_id_arr = [];
+ foreach ($_FILES as $k => $file)
+ {
+ $dms = array(
+ 'kategorie_kurzbz' => 'notiz',
+ 'version' => 0,
+ 'name' => $file["name"],
+ 'mimetype' => $file["type"],
+ 'insertamum' => date('c'),
+ 'insertvon' => $uid
+ );
+
+ //Todo(manu) check if filetypes weiter eingeschränkt werden sollen
+ //Todo(manu)check name files: nicht gleiches file 2mal hochladen
+ //Todo define in dms component: readFile, downloadFile
+ $result = $this->dmslib->upload($dms, $k, ['*']);
+ /* $result = $this->dmslib->upload($dms, $k, ['application/pdf','application/x.fhc-dms+json']);*/
+ if (isError($result))
+ {
+ $this->db->trans_rollback();
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $dms_id_arr[] = $result->retval['dms_id'];
+ }
+
+ //save entry in Notizdokument
+ if($dms_id_arr)
+ {
+ $this->load->model('person/Notizdokument_model', 'NotizdokumentModel');
+ foreach($dms_id_arr as $dms_id)
+ {
+ $result = $this->NotizdokumentModel->insert(array('notiz_id' => $notiz_id, 'dms_id' => $dms_id));
+ if (isError($result))
+ {
+ $this->db->trans_rollback();
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ }
+ }
+ $this->db->trans_commit();
+ return $this->terminateWithSuccess($result);
+ }
+
+ public function updateNotiz()
+ {
+ $this->load->library('form_validation');
+ $this->load->library('DmsLib');
+
+ if (isset($_POST['data']))
+ {
+ $data = json_decode($_POST['data']);
+ unset($_POST['data']);
+ foreach ($data as $k => $v) {
+ $_POST[$k] = $v;
+ }
+ }
+
+ $notiz_id = $this->input->post('notiz_id');
+
+ if(!$notiz_id)
+ {
+ $this->terminateWithError($this->p->t('ui','error_missingId',['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ //Form Validation
+ $this->form_validation->set_rules('titel', 'Titel', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel'])
+ ]);
+
+ $this->form_validation->set_rules('text', 'Text', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Text'])
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ //update Notiz
+ $uid = getAuthUID();
+ $titel = $this->input->post('titel');
+ $text = $this->input->post('text');
+ $verfasser_uid = isset($_POST['verfasser']) ? $_POST['verfasser'] : $uid;
+ $bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : $uid;
+ $erledigt = $this->input->post('erledigt');
+ $start = $this->input->post('start');
+ $ende = $this->input->post('ende');
+
+ $result = $this->NotizModel->update(
+ [
+ 'notiz_id' => $notiz_id
+ ],
+ [
+ 'titel' => $titel,
+ 'updatevon' => $uid,
+ 'updateamum' => date('c'),
+ 'text' => $text,
+ 'verfasser_uid' => $verfasser_uid,
+ 'bearbeiter_uid' => $bearbeiter_uid,
+ 'start' => $start,
+ 'ende' => $ende,
+ 'erledigt' => $erledigt
+ ]
+ );
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ //update(1) loading all dms-entries with this notiz_id
+ $this->load->model('person/Notizdokument_model', 'NotizdokumentModel');
+ $this->NotizdokumentModel->addJoin('campus.tbl_dms_version', 'dms_id');
+
+ $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id));
+ $result = $this->getDataOrTerminateWithError($result);
+ foreach ($result as $doc) {
+ $dms_id_arr[$doc->dms_id] = array(
+ 'name' => $doc->name,
+ 'dms_id' => $doc->dms_id
+ );
+ }
+
+ foreach ($_FILES as $k => $file)
+ {
+ //update(2) attach all new files (except type application/x.fhc-dms+json)
+ if($file["type"] == 'application/x.fhc-dms+json')
+ {
+ $jsonFile = json_decode(file_get_contents($file['tmp_name']));
+ unset($dms_id_arr[$jsonFile->dms_id]);
+ #$dms_uploaded[] = $jsonFile->dms_id;
+ }
+ else
+ {
+ $dms = array(
+ 'kategorie_kurzbz' => 'notiz',
+ 'version' => 0,
+ 'name' => $file["name"],
+ 'mimetype' => $file["type"],
+ 'insertamum' => date('c'),
+ 'insertvon' => $uid
+ );
+
+ //Todo(manu) check if filetypes weiter eingeschränkt werden sollen
+ //Todo(manu)check name files: nicht gleiches file 2mal hochladen
+ //Todo define in dms component: readFile, downloadFile
+ $result = $this->dmslib->upload($dms, $k, array('*'));
+
+ $result = $this->getDataOrTerminateWithError($result);
+ $dms_id = $result['dms_id'];
+
+ $result = $this->NotizdokumentModel->insert(array('notiz_id' => $notiz_id, 'dms_id' => $dms_id));
+
+ $this->getDataOrTerminateWithError($result);
+ }
+ }
+
+ //update(3) check if all files have been deleted
+ foreach ($dms_id_arr as $file)
+ {
+ $result = $this->dmslib->removeAll($file['dms_id']);
+
+ $this->getDataOrTerminateWithError($result);
+ }
+
+ return $this->terminateWithSuccess($result);
+ }
+
+ public function deleteNotiz()
+ {
+ $this->load->library('DmsLib');
+
+ $notiz_id = $this->input->post('notiz_id');
+ $typeId = $this->input->post('type_id');
+ $id = $this->input->post('id');
+
+ //TODO(manu): define Permissions for deletion document if filecomponent finished
+
+ //get dms_id from notizdokument
+ $this->load->model('person/Notizdokument_model', 'NotizdokumentModel');
+
+ $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id));
+
+ $result = $this->getDataOrTerminateWithError($result);
+
+ // Start DB transaction
+ $this->db->trans_start();
+
+ if ($result)
+ $this->load->library('DmsLib');
+
+ foreach ($result as $doc) {
+ $res = $this->dmslib->removeAll($doc->dms_id);
+ if (isError($result))
+ {
+ $this->db->trans_rollback();
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ }
+
+ //delete Notizzuordnung
+ $result = $this-> deleteNotizzuordnung($notiz_id, $id, $typeId);
+ if (isError($result))
+ {
+ $this->db->trans_rollback();
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ $this->load->model('person/Notiz_model', 'NotizModel');
+
+ //Delete Note
+ $result = $this->NotizModel->delete($notiz_id);
+
+ if (isError($result))
+ {
+ $this->db->trans_rollback();
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ if(!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ $this->db->trans_complete();
+ return $this->terminateWithSuccess(getData($result));
+ }
+
+ public function loadDokumente()
+ {
+ $notiz_id = $this->input->post('notiz_id');
+
+ $this->NotizModel->addSelect('campus.tbl_dms_version.*');
+
+ $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'ON (public.tbl_notiz_dokument.notiz_id = public.tbl_notiz.notiz_id)');
+ $this->NotizModel->addJoin('campus.tbl_dms_version', 'ON (public.tbl_notiz_dokument.dms_id = campus.tbl_dms_version.dms_id)');
+
+ $result = $this->NotizModel->loadWhere(
+ array('public.tbl_notiz.notiz_id' => $notiz_id)
+ );
+ if (isError($result)) {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+
+ if(!hasData($result))
+ {
+ return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess(getData($result));
+ }
+
+ public function getMitarbeiter($searchString)
+ {
+ $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
+ $result = $this->MitarbeiterModel->searchMitarbeiter($searchString);
+ if (isError($result)) {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ return $this->terminateWithSuccess($result);
+ }
+
+}
\ No newline at end of file
diff --git a/application/core/PlausiIssueProducer_Controller.php b/application/core/PlausiIssueProducer_Controller.php
index 0dce7a487..5216d284c 100644
--- a/application/core/PlausiIssueProducer_Controller.php
+++ b/application/core/PlausiIssueProducer_Controller.php
@@ -5,61 +5,23 @@
*/
abstract class PlausiIssueProducer_Controller extends JOB_Controller
{
- protected $_fehlerLibMappings;
+ protected $_fehlerLibMappings = [];
protected $_app;
- public function __construct($app = null)
- {
- parent::__construct();
-
- // pass extension name if calling from extension
- $extensionName = isset($this->_extensionName) ? $this->_extensionName : null;
-
- // load libraries
- $this->load->library('issues/PlausicheckProducerLib', array('extensionName' => $extensionName, 'app' => $this->_app));
- $this->load->library('IssuesLib');
- }
-
protected function producePlausicheckIssues($params)
{
+ $this->load->library(
+ 'issues/PlausicheckProducerLib',
+ ['extensionName' => $this->_extensionName ?? null, 'app' => $this->_app, 'fehlerLibMappings' => $this->_fehlerLibMappings]
+ );
+
$this->logInfo("Plausicheck issue producer job started");
- // get the data returned by Plausicheck
- foreach ($this->_fehlerLibMappings as $fehler_kurzbz => $libName)
- {
- // execute the check
- $this->logInfo("Checking " . $fehler_kurzbz . "...");
- $plausicheckRes = $this->plausicheckproducerlib->producePlausicheckIssue(
- $libName,
- $fehler_kurzbz,
- $params
- );
+ $result = $this->plausicheckproducerlib->producePlausicheckIssues($params);
- if (isError($plausicheckRes)) $this->logError(getError($plausicheckRes));
-
- if (hasData($plausicheckRes))
- {
- $plausicheckData = getData($plausicheckRes);
-
- foreach ($plausicheckData as $plausiData)
- {
- // get the data needed for issue production
- $person_id = isset($plausiData['person_id']) ? $plausiData['person_id'] : null;
- $oe_kurzbz = isset($plausiData['oe_kurzbz']) ? $plausiData['oe_kurzbz'] : null;
- $fehlertext_params = isset($plausiData['fehlertext_params']) ? $plausiData['fehlertext_params'] : null;
- $resolution_params = isset($plausiData['resolution_params']) ? $plausiData['resolution_params'] : null;
-
- // write the issue
- $addIssueRes = $this->issueslib->addFhcIssue($fehler_kurzbz, $person_id, $oe_kurzbz, $fehlertext_params, $resolution_params);
-
- // log if error, or log info if inserted new issue
- if (isError($addIssueRes))
- $this->logError(getError($addIssueRes));
- elseif (hasData($addIssueRes) && is_integer(getData($addIssueRes)))
- $this->logInfo("Plausicheck issue " . $fehler_kurzbz . " successfully produced, person_id: " . $person_id);
- }
- }
- }
+ // log if error, or log info if inserted new issue
+ foreach ($result->errors as $error) $this->logError($error);
+ foreach ($result->infos as $info) $this->logInfo($info);
$this->logInfo("Plausicheck issue producer job stopped");
}
diff --git a/application/helpers/hlp_common_helper.php b/application/helpers/hlp_common_helper.php
index 913d29b54..40aed007c 100644
--- a/application/helpers/hlp_common_helper.php
+++ b/application/helpers/hlp_common_helper.php
@@ -18,6 +18,8 @@
if (! defined('BASEPATH')) exit('No direct script access allowed');
+use \DateTime as DateTime;
+
// ------------------------------------------------------------------------
// Collection of utility functions for general purpose
// ------------------------------------------------------------------------
@@ -354,7 +356,8 @@ function sanitizeProblemChars($str)
'ss' => '/ß/'
);
- return preg_replace($acentos, array_keys($acentos), htmlentities($str, ENT_NOQUOTES | ENT_HTML5, $enc));
+ $tmp = preg_replace($acentos, array_keys($acentos), htmlentities($str, ENT_NOQUOTES | ENT_HTML5, $enc));
+ return html_entity_decode($tmp, ENT_NOQUOTES | ENT_HTML5, $enc);
}
/**
@@ -405,3 +408,93 @@ function findResource($path, $resource, $subdir = false, $extraDir = null)
return null;
}
+/**
+ * check if String can be converted to a date
+ */
+function isValidDate($dateString)
+{
+ try
+ {
+ return (new DateTime($dateString)) !== false;
+ }
+ catch(Exception $e)
+ {
+ return false;
+ }
+}
+
+
+// ------------------------------------------------------------------------
+// Collection of utility functions for form validation purposes
+// ------------------------------------------------------------------------
+
+/**
+ * check if string can be converted to a date
+ */
+function is_valid_date($dateString)
+{
+ try
+ {
+ return (new DateTime($dateString)) !== false;
+ }
+ catch(Exception $e)
+ {
+ return false;
+ }
+}
+
+/**
+ * check if given permissions are met
+ */
+function has_write_permissions($value, $permissions = '')
+{
+ if (!$permissions)
+ $permissions = $value;
+ $permissions = explode(',', $permissions);
+
+ $CI =& get_instance();
+ $CI->load->library('AuthLib');
+ $CI->load->library('PermissionLib');
+
+ return $CI->permissionlib->hasAtLeastOne(
+ $permissions,
+ 'sometable',
+ PermissionLib::WRITE_RIGHT
+ );
+}
+
+/**
+ * check if has permissions for a studiengang_kz
+ */
+function has_permissions_for_stg($studiengang_kz, $permissions = '')
+{
+ if (!$permissions)
+ return false;
+ $permissions = explode(',', $permissions);
+
+ $CI =& get_instance();
+ $CI->load->library('AuthLib');
+ $CI->load->library('PermissionLib');
+
+ foreach ($permissions as $perm) {
+ if (strpos($perm, PermissionLib::PERMISSION_SEPARATOR) === false) {
+ $CI->addError(
+ 'The given permission does not use the correct format',
+ FHCAPI_Controller::ERROR_TYPE_GENERAL
+ );
+ return false;
+ }
+
+ list($perm, $accesstype) = explode(PermissionLib::PERMISSION_SEPARATOR, $perm);
+ $at = '';
+ if (strpos($accesstype, PermissionLib::READ_RIGHT) !== false)
+ $at = PermissionLib::SELECT_RIGHT; // S
+ if (strpos($accesstype, PermissionLib::WRITE_RIGHT) !== false)
+ $at .= PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT; // UID
+
+ if ($CI->permissionlib->isBerechtigt($perm, $at, $studiengang_kz))
+ return true;
+ }
+
+ return false;
+}
diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php
index 05bba48c4..ea1795ad5 100644
--- a/application/helpers/hlp_header_helper.php
+++ b/application/helpers/hlp_header_helper.php
@@ -96,7 +96,8 @@ function generateJSDataStorageObject($indexPage, $calledPath, $calledMethod)
app_root: "'.APP_ROOT.'",
ci_router: "'.$indexPage.'",
called_path: "'.$calledPath.'",
- called_method: "'.$calledMethod.'"
+ called_method: "'.$calledMethod.'",
+ user_language: "'.$user_language.'"
};';
$toPrint .= "\n";
$toPrint .= '';
diff --git a/application/language/english/form_validation_lang.php b/application/language/english/form_validation_lang.php
new file mode 100644
index 000000000..b8918a721
--- /dev/null
+++ b/application/language/english/form_validation_lang.php
@@ -0,0 +1,43 @@
+_ci =& get_instance();
+
+ // Configs
+ $this->_ci->load->config('studierendenantrag');
+
+ // Models
+ $this->_ci->load->model('education/Studierendenantrag_model', 'StudierendenantragModel');
+ $this->_ci->load->model('education/Studierendenantragstatus_model', 'StudierendenantragstatusModel');
+ $this->_ci->load->model('education/Studierendenantraglehrveranstaltung_model', 'StudierendenantraglehrveranstaltungModel');
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel');
+ $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
+ $this->_ci->load->model('person/Person_model', 'PersonModel');
+ $this->_ci->load->model('education/Pruefung_model', 'PruefungModel');
+
+ // Helper
+ $this->_ci->load->helper('hlp_sancho_helper');
+
+ // Libraries
+ $this->_ci->load->library('PermissionLib');
+ $this->_ci->load->library('PrestudentLib');
+ }
+
+ /**
+ * @param integer $antrag_id
+ * @param string $insertvon
+ *
+ * @return stdClass
+ */
+ public function cancelAntrag($antrag_id, $insertvon)
+ {
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CANCELLED,
+ 'insertvon' => $insertvon
+ ]);
+
+ // NOTE(chris): remove "preabbrecher" statusgrund and paused stati for sibling Anträge for Stgl-Abmeldungen if set
+ $res = $this->_ci->StudierendenantragModel->load($antrag_id);
+ if (hasData($res) && current(getData($res))->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL) {
+ $this->unpauseAntrag($antrag_id, Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL);
+
+ $this->_ci->PrestudentstatusModel->addSelect('tbl_status_grund.statusgrund_kurzbz');
+ $res = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail(current(getData($res))->prestudent_id, '', 'Student');
+ if (hasData($res) && current(getData($res))->statusgrund_kurzbz == 'preabbrecher') {
+ $prestudentstatus = current(getData($res));
+ $this->_ci->PrestudentstatusModel->update([
+ 'prestudent_id' => $prestudentstatus->prestudent_id,
+ 'status_kurzbz'=>$prestudentstatus->status_kurzbz,
+ 'studiensemester_kurzbz'=>$prestudentstatus->studiensemester_kurzbz,
+ 'ausbildungssemester'=>$prestudentstatus->ausbildungssemester
+ ], [
+ 'statusgrund_id' => null
+ ]);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param integer $antrag_id
+ * @param string $insertvon
+ *
+ * @return stdClass
+ */
+ public function pauseAntrag($antrag_id, $insertvon)
+ {
+ switch ($insertvon) {
+ case Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL:
+ $result = $this->_ci->StudierendenantragstatusModel->stopAntraegeForAbmeldungStgl($antrag_id);
+ break;
+ case Studierendenantragstatus_model::INSERTVON_DEREGISTERED:
+ $result = $this->_ci->StudierendenantragstatusModel->stopAntraegeForAbbruchBy($antrag_id);
+ break;
+ default:
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE,
+ 'insertvon' => $insertvon
+ ]);
+ break;
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param integer $antrag_id
+ * @param string $insertvon
+ *
+ * @return stdClass
+ */
+ public function unpauseAntrag($antrag_id, $insertvon)
+ {
+ if ($insertvon == Studierendenantragstatus_model::INSERTVON_DEREGISTERED)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_right'));
+ if ($insertvon == Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL) {
+ return $this->_ci->StudierendenantragstatusModel->resumeAntraegeForAbmeldungStgl($antrag_id);
+ }
+ // NOTE(chris): get last status that is not pause
+ $this->_ci->StudierendenantragstatusModel->addOrder('insertamum');
+ $this->_ci->StudierendenantragstatusModel->addLimit(1);
+ $result = $this->_ci->StudierendenantragstatusModel->loadWhere([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz !=' => Studierendenantragstatus_model::STATUS_PAUSE
+ ]);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antragstatus', ['id' => $antrag_id]));
+ $status = current(getData($result));
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => $status->studierendenantrag_statustyp_kurzbz,
+ 'insertvon' => $insertvon
+ ]);
+ return $result;
+ }
+
+ /**
+ * NOTE(chris): permissions & verification must be handled outside
+ *
+ * @param integer $prestudent_id
+ * @param string $studiensemester_kurzbz
+ * @param string $insertvon
+ * @param string $grund
+ *
+ * @return stdClass
+ */
+ public function createAbmeldung($prestudent_id, $studiensemester_kurzbz, $insertvon, $grund)
+ {
+ $result = $this->_ci->PrestudentModel->load($prestudent_id);
+ if (isError($result))
+ return $result;
+ if(!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', "error_no_prestudent", ['prestudent_id' => $prestudent_id]));
+
+ $prestudent = getData($result)[0];
+ if($prestudent->person_id == getAuthPersonId())
+ $typ = Studierendenantrag_model::TYP_ABMELDUNG;
+ else
+ $typ = Studierendenantrag_model::TYP_ABMELDUNG_STGL;
+
+ $result = $this->_ci->StudierendenantragModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'studiensemester_kurzbz'=> $studiensemester_kurzbz,
+ 'datum' => date('c'),
+ 'typ' => $typ,
+ 'insertvon' => $insertvon,
+ 'grund' => $grund
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ $antrag_id = getData($result);
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED,
+ 'insertvon' => $insertvon
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ return success($antrag_id);
+ }
+
+ /**
+ * @param array $studierendenantrag_ids
+ * @param string $insertvon
+ *
+ * @return stdClass
+ */
+ public function approveAbmeldung($studierendenantrag_ids, $insertvon)
+ {
+ $this->_ci->load->model('crm/Student_model', 'StudentModel');
+
+ $errors = [];
+ foreach ($studierendenantrag_ids as $studierendenantrag_id) {
+ $result = $this->_ci->StudierendenantragModel->load($studierendenantrag_id);
+ if (isError($result))
+ {
+ $errors[] = getError($result);
+ continue;
+ }
+ if(!hasData($result))
+ {
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id]);
+ continue;
+ }
+ $antrag = getData($result)[0];
+
+ $insertam = date('c');
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED,
+ 'insertvon' => $insertvon,
+ 'insertamum' => $insertam
+ ]);
+ if (isError($result))
+ $errors[] = getError($result);
+ else {
+ $this->_ci->StudiengangModel->addJoin('public.tbl_prestudent ps', 'studiengang_kz');
+ $result = $this->_ci->StudiengangModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]);
+ $stg = '';
+ $orgform = '';
+ if (hasData($result)) {
+ $studiengang = current(getData($result));
+ $stg = $studiengang->bezeichnung;
+ }
+ if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG)
+ {
+ $resultPrestudentStatus = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail($antrag->prestudent_id);
+ if (isError($resultPrestudentStatus))
+ $errors[] = getError($resultPrestudentStatus);
+
+ else {
+ $prestudent_status = getData($resultPrestudentStatus)[0];
+ $orgform = $prestudent_status->orgform_kurzbz;
+
+ $vorlage ='Sancho_Mail_Antrag_A_Approve';
+ $subject = $this->_ci->p->t('studierendenantrag', 'mail_subject_A_Approve');
+
+ $result = $this->pauseAntrag($studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_DEREGISTERED);
+ if (isError($result))
+ $errors[] = getError($result);
+
+ $this->_ci->load->model('crm/Statusgrund_model', 'StatusgrundModel');
+ $result = $this->_ci->StatusgrundModel->loadWhere(['statusgrund_kurzbz' => 'abbrecherStud']);
+ if (isError($result)) {
+ $errors[] = getError($result);
+ continue;
+ } elseif (!hasData($result)) {
+ $errors[] = $this->_ci->p->t('lehre', 'error_noStatusgrund', ['statusgrund_kurzbz' => 'abbrecherStud']);
+ continue;
+ }
+ $statusgrund = current(getData($result));
+
+ $result = $this->_ci->prestudentlib->setAbbrecher(
+ $antrag->prestudent_id,
+ $antrag->studiensemester_kurzbz,
+ $insertvon,
+ $statusgrund->statusgrund_id,
+ $antrag->datum,
+ $insertam
+ );
+ if (isError($result)) {
+ $errors[] = getError($result);
+ continue;
+ }
+
+ $result = $this->_ci->PersonModel->loadPrestudent($antrag->prestudent_id);
+ $data = [
+ 'student' => $this->_ci->p->t('person', 'studentIn'),
+ 'sem' => $antrag->studiensemester_kurzbz,
+ 'linkPdf' => base_url('content/pdfExport.php?xml=Antrag' .
+ $antrag->typ .
+ '.xml.php&xsl=Antrag' .
+ $antrag->typ .
+ '&id=' .
+ $antrag->studierendenantrag_id .
+ '&output=pdf')
+ ];
+ if (hasData($result)) {
+ $person = current(getData($result));
+ $data['student'] = trim($person->vorname . ' ' . $person->nachname);
+ $data['vorname'] = $person->vorname;
+ $data['nachname'] = $person->nachname;
+ }
+ $result = $this->_ci->StudentModel->loadWhere(['prestudent_id'=> $antrag->prestudent_id]);
+ if (hasData($result)) {
+ $student = current(getData($result));
+ $data['UID'] = $student->student_uid;
+ }
+
+ $data['Orgform'] = $prestudent_status->orgform;
+ $data['stg'] = $stg;
+
+ // NOTE(chris): Sancho mail
+ sendSanchoMail($vorlage, $data, $prestudent_status->email, $subject);
+ }
+ } else { // ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL)
+ $result = $this->pauseAntrag($studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL);
+ if (isError($result))
+ $errors[] = getError($result);
+
+ $result = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail($antrag->prestudent_id, '', 'Student');
+ if (isError($result))
+ {
+ $errors[] = getError($result);
+ continue;
+ }
+ if(!hasData($result))
+ {
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', ['prestudent_id' => $antrag->prestudent_id]);
+ continue;
+ }
+ $prestudentstatus = getData($result)[0];
+ $orgform = $prestudentstatus->orgform_kurzbz;
+
+ $result = $this->_ci->PrestudentstatusModel->withGrund('preabbrecher')->update([
+ 'prestudent_id' => $prestudentstatus->prestudent_id,
+ 'status_kurzbz'=>$prestudentstatus->status_kurzbz,
+ 'studiensemester_kurzbz'=>$prestudentstatus->studiensemester_kurzbz,
+ 'ausbildungssemester'=>$prestudentstatus->ausbildungssemester
+ ], []);
+ if (isError($result))
+ {
+ $errors[] = getError($result);
+ continue;
+ }
+ }
+
+ $res = $this->_ci->PrestudentModel->load($antrag->prestudent_id);
+
+ if (hasData($res)) {
+ $prestudent = current(getData($res));
+ $res = $this->_ci->PersonModel->load($prestudent->person_id);
+ if (hasData($res)) {
+ $person = current(getData($res));
+ $name = trim($person->vorname . ' ' . $person->nachname);
+ $vorname = $person->vorname;
+ $nachname = $person->nachname;
+ } else {
+ $name = $this->_ci->p->t('person', 'studentIn');
+ $vorname = '';
+ $nachname = $name;
+ }
+ $res = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]);
+ if (hasData($res)) {
+ $email = $this->_ci->StudentModel->getEmailFH(current(getData($res))->student_uid);
+ $vorlage = $antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG ? 'Student' : 'Stgl';
+
+ // NOTE(chris): Sancho mail
+ sendSanchoMail(
+ 'Sancho_Mail_Antrag_A_' . $vorlage,
+ [
+ 'name' => $name,
+ 'grund' => $antrag->grund,
+ 'vorname' => $vorname,
+ 'nachname' => $nachname,
+ 'Orgform' => $orgform,
+ 'stg' => $stg
+ ],
+ $email,
+ $this->_ci->p->t('studierendenantrag', 'mail_subject_A_' . $vorlage)
+ );
+ }
+ }
+ }
+ }
+
+ if (count($errors))
+ return error(implode(',', $errors));
+
+ return success();
+ }
+
+ /**
+ * @param integer $studierendenantrag_id
+ * @param string $insertvon
+ *
+ * @return stdClass
+ */
+ public function denyObjectionAbmeldung($studierendenantrag_id, $insertvon, $grund = null)
+ {
+ $result = $this->_ci->StudierendenantragModel->load($studierendenantrag_id);
+ if (isError($result))
+ {
+ return $result;
+ }
+ if(!hasData($result))
+ {
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id]));
+ }
+ $antrag = getData($result)[0];
+
+ $result = $this->_ci->StudierendenantragstatusModel->loadWhere([
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED
+ ]);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_not_approved'));
+
+ $status = current(getData($result));
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_OBJECTION_DENIED,
+ 'grund' => $grund,
+ 'insertvon' => $insertvon
+ ]);
+ if (isError($result))
+ return $result;
+ else {
+ $result = $this->pauseAntrag($studierendenantrag_id, Studierendenantragstatus_model::INSERTVON_DEREGISTERED);
+ // NOTE(chris): here we should have error handling but at the
+ // moment there is no way to notify the user for "soft" errors
+
+ $this->_ci->load->model('crm/Statusgrund_model', 'StatusgrundModel');
+ $result = $this->_ci->StatusgrundModel->loadWhere(['statusgrund_kurzbz' => 'abbrecherStgl']);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('lehre', 'error_noStatusgrund', ['statusgrund_kurzbz' => 'abbrecherStgl']));
+
+ $statusgrund = current(getData($result));
+
+ $result = $this->_ci->prestudentlib->setAbbrecher(
+ $antrag->prestudent_id,
+ $antrag->studiensemester_kurzbz,
+ $insertvon,
+ $statusgrund->statusgrund_id,
+ $status->insertamum
+ );
+
+ if (isError($result))
+ return $result;
+
+ $res = $this->_ci->PrestudentModel->load($antrag->prestudent_id);
+
+ if (hasData($res)) {
+ $this->_ci->load->model('crm/Student_model', 'StudentModel');
+
+ $prestudent = current(getData($res));
+ $res = $this->_ci->PersonModel->load($prestudent->person_id);
+ if (hasData($res)) {
+ $person = current(getData($res));
+ $name = trim($person->vorname . ' ' . $person->nachname);
+ $vorname = $person->vorname;
+ $nachname = $person->nachname;
+ } else {
+ $name = $this->_ci->p->t('person', 'studentIn');
+ }
+
+ $res = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]);
+ if (hasData($res)) {
+ $email = $this->_ci->StudentModel->getEmailFH(current(getData($res))->student_uid);
+
+ $res = $this->_ci->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id);
+ $stg = '';
+ $orgform = '';
+ if (hasData($res)) {
+ $studiengang = current(getData($res));
+ $stg = $studiengang->bezeichnung;
+ $orgform = $studiengang->orgform_kurzbz;
+ }
+
+ sendSanchoMail(
+ 'Sancho_Mail_Antrag_A_ObjDenied',
+ [
+ 'name' => $name,
+ 'vorname' => $vorname,
+ 'nachname' => $nachname,
+ 'grund' => $grund,
+ 'Orgform' => $orgform,
+ 'stg' => $stg
+ ],
+ $email,
+ $this->_ci->p->t('studierendenantrag', 'mail_subject_A_ObjectionDenied')
+ );
+ }
+ }
+ }
+
+ return success();
+ }
+
+ /**
+ * NOTE(chris): permissions & verification must be handled outside
+ *
+ * @param integer $prestudent_id
+ * @param string $studiensemester_kurzbz
+ * @param string $insertvon
+ * @param string $grund
+ * @param string $datum_wiedereinstieg
+ *
+ * @return stdClass
+ */
+ public function createUnterbrechung($prestudent_id, $studiensemester_kurzbz, $insertvon, $grund, $datum_wiedereinstieg, $dms_id)
+ {
+ $datum_wiedereinstieg = new DateTime($datum_wiedereinstieg);
+ $datum_wiedereinstieg = $datum_wiedereinstieg->format("Y-m-d");
+ $result = $this->_ci->StudierendenantragModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'studiensemester_kurzbz'=> $studiensemester_kurzbz,
+ 'datum' => date('c'),
+ 'typ' => Studierendenantrag_model::TYP_UNTERBRECHUNG,
+ 'insertvon' => $insertvon,
+ 'grund' => $grund,
+ 'datum_wiedereinstieg' => $datum_wiedereinstieg,
+ 'dms_id' => $dms_id
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ $antrag_id = getData($result);
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED,
+ 'insertvon' => $insertvon
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ return success($antrag_id);
+ }
+
+
+ /**
+ * @param array $studierendenantrag_ids
+ * @param string $insertvon
+ *
+ * @return stdClass
+ */
+ public function approveUnterbrechung($studierendenantrag_ids, $insertvon)
+ {
+ $this->_ci->load->model('person/Kontakt_model', 'KontaktModel');
+ $this->_ci->load->model('crm/Student_model', 'StudentModel');
+
+ $errors = [];
+
+ foreach ($studierendenantrag_ids as $studierendenantrag_id)
+ {
+ $data = $this->getDataForUnterbrechung($studierendenantrag_id);
+
+ if (isError($data)) {
+ $error_msg = getError($data);
+ if (is_array($error_msg) && isset($error_msg['message']))
+ $error_msg = $error_msg['message'];
+
+ $errors['failed_' . $studierendenantrag_id] = 'Could not approve Unterbrechung for studierendenantrag_id: ' .
+ $studierendenantrag_id .
+ '
Details:
' .
+ $error_msg;
+ } else {
+ $data = getData($data);
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED,
+ 'insertvon' => $insertvon
+ ]);
+ if (isError($result))
+ {
+ $errors['failed_' . $studierendenantrag_id] = $this->_ci->p->t('studierendenantrag', 'error_U_Approve', [
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'message' => getError($result)['message']
+ ]);
+ }
+ else
+ {
+ $studierendenantrag_status_id = getData($result);
+ $resultAntrag = $this->_ci->StudierendenantragModel->load($studierendenantrag_id);
+ if (isError($resultAntrag))
+ return $resultAntrag;
+ $resultAntrag = getData($resultAntrag);
+ if (!$resultAntrag)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id]));
+ $resultAntrag = current($resultAntrag);
+
+ // Prestudentstatus und Unterbrechungsfolgeaktionen setzen
+ $result = $this->_ci->prestudentlib->setUnterbrecher(
+ $resultAntrag->prestudent_id,
+ $resultAntrag->studiensemester_kurzbz,
+ $studierendenantrag_id
+ );
+
+ if (isError($result)) {
+ $this->_ci->StudierendenantragstatusModel->delete($studierendenantrag_status_id);
+ return $result;
+ }
+
+
+ //Mail
+ $subject = $this->_ci->p->t('studierendenantrag', 'mail_subject_U_Approve');
+ $mail = [];
+
+ if (isset($data['errors']['person_id']))
+ {
+ //send assistenz mit id
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_and_name', ['message' => $data['errors']['person_id']]);
+ $mail['ass'] = $this->_ci->p->t('studierendenantrag', 'StudentIn', ['prestudent_id' => $data['antrag']->prestudent_id]);
+ }
+ elseif (isset($data['errors']['email']))
+ {
+ if (isset($data['errors']['person']))
+ {
+ //send assistenz mit id
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_and_name', [
+ 'message' => $data['errors']['email'] . '
' . $data['errors']['person']
+ ]);
+ $mail['ass'] = $this->_ci->p->t('studierendenantrag', 'StudentIn', ['prestudent_id' => $data['antrag']->prestudent_id]);
+ }
+ else
+ {
+ //send assistenz mit name
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail', ['message' => $data['errors']['email']]);
+ $mail['ass'] = trim($data['person']->vorname . ' ' . $data['person']->nachname);
+ }
+ }
+ else
+ {
+ if (isset($data['errors']['person']))
+ {
+ //send assistenz mit id & student mit "Student/in"
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_name', ['message' => $data['errors']['person']]);
+ $mail['ass'] = $this->_ci->p->t('studierendenantrag', 'StudentIn', ['prestudent_id' => $data['antrag']->prestudent_id]);
+ $mail['stu'] = $this->_ci->p->t('person', 'StudentIn');
+ }
+ else
+ {
+ //send normal
+ $mail['ass'] = $mail['stu'] = trim($data['person']->vorname . ' ' . $data['person']->nachname);
+ }
+ }
+
+ if (isset($mail['ass'])) {
+ // NOTE(chris): Sancho mail
+ $mailVorlage = 'Sancho_Mail_Antrag_U_Approve';
+
+ $result = $this->_ci->StudentModel->loadWhere(['prestudent_id'=> $data['antrag']->prestudent_id]);
+ if (hasData($result)) {
+ $student = current(getData($result));
+ $data['UID'] = $student->student_uid;
+ }
+
+ $result = $this->_ci->PersonModel->getFullName($insertvon);
+ if (isError($result))
+ return $result;
+ $approvedBy = $insertvon;
+ if (hasData($result))
+ {
+ $approvedBy = getData($result);
+ }
+
+ if (!sendSanchoMail(
+ $mailVorlage,
+ [
+ 'name' => $mail['ass'],
+ 'stg' => $data['studiengang']->bezeichnung,
+ 'Orgform' => $data['prestudent_status']->orgform_kurzbz,
+ 'vorname' => $data['person']->vorname,
+ 'nachname' => $data['person']->nachname,
+ 'UID' => $data['UID'],
+ 'sem' => $resultAntrag->studiensemester_kurzbz,
+ 'linkPdf' => base_url(
+ 'content/pdfExport.php?xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&id=' .
+ $studierendenantrag_id .
+ '&output=pdf'
+ ),
+ 'insertvon' => $approvedBy
+ ],
+ $data['prestudent_status']->email,
+ $subject
+ )) {
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_to', $data['prestudent_status']);
+ }
+ }
+ if (isset($mail['stu'])) {
+ // NOTE(chris): Sancho mail
+ $mailVorlage = 'Sancho_Mail_Antrag_U_Student';
+ if ($data['studienbeitrag'])
+ $mailVorlage .= '_SB';
+ if (!sendSanchoMail(
+ $mailVorlage,
+ [
+ 'name' => $mail['stu'],
+ 'stg' => $data['studiengang']->bezeichnung,
+ 'Orgform' => $data['prestudent_status']->orgform_kurzbz,
+ 'vorname' => $data['person']->vorname,
+ 'nachname' => $data['person']->nachname
+ ],
+ $data['email'],
+ $subject
+ )) {
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_to', $data);
+ }
+ }
+ }
+ }
+ }
+
+ if (count($errors))
+ return error($errors);
+
+ return success();
+ }
+
+ /**
+ * @param array $studierendenantrag_ids
+ * @param string $insertvon
+ * @param string $grund
+ *
+ * @return stdClass
+ */
+ public function rejectUnterbrechung($studierendenantrag_ids, $insertvon, $grund)
+ {
+ $this->_ci->load->model('person/Kontakt_model', 'KontaktModel');
+ $this->_ci->load->model('crm/Student_model', 'StudentModel');
+
+ $errors = [];
+
+ foreach ($studierendenantrag_ids as $studierendenantrag_id) {
+ $data = $this->getDataForUnterbrechung($studierendenantrag_id);
+
+ if (isError($data)) {
+ $error_msg = getError($data);
+ if (is_array($error_msg) && isset($error_msg['message']))
+ $error_msg = $error_msg['message'];
+
+ $errors['failed_' . $studierendenantrag_id] = $this->_ci->p->t('studierendenantrag', 'error_U_Reject', [
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'message' => $error_msg
+ ]);
+ } else {
+ $data = getData($data);
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_REJECTED,
+ 'insertvon' => $insertvon,
+ 'grund' => $grund
+ ]);
+ if (isError($result)) {
+ $errors['failed_' . $studierendenantrag_id] = $this->_ci->p->t('studierendenantrag', 'error_U_Reject', [
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'message' => getError($result)['message']
+ ]);
+ } else {
+ $name = '';
+
+ if (isset($data['errors']['person_id']) || isset($data['errors']['email'])) {
+ $error_msg = [];
+ if (isset($data['errors']['person_id']))
+ $error_msg[] = $data['errors']['person_id'];
+ if (isset($data['errors']['email']))
+ $error_msg[] = $data['errors']['email'];
+ $error_msg = $this->_ci->p->t('studierendenantrag', 'error_mail', ['message' => implode('
', $error_msg)]);
+ $errors[] = $error_msg;
+ } else {
+ if (isset($data['errors']['person'])) {
+ //send student mit "Student/in"
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_name', ['message' => $data['errors']['person']]);
+ $name = $this->_ci->p->t('person', 'studentIn');
+ $vorname = "";
+ $nachname = $name;
+ } else {
+ //send normal
+ $name = trim($data['person']->vorname . ' ' . $data['person']->nachname);
+ $vorname = $data['person']->vorname;
+ $nachname = $data['person']->nachname;
+ }
+ }
+ if ($name)
+ // NOTE(chris): Sancho mail
+ if (!sendSanchoMail(
+ 'Sancho_Mail_Antrag_U_Reject',
+ [
+ 'name' => $name,
+ 'vorname' => $vorname,
+ 'nachname' => $nachname,
+ 'grund' => $grund,
+ 'stg' => $data['studiengang']->bezeichnung,
+ 'Orgform' => $data['prestudent_status']->orgform_kurzbz,
+ 'prestudent_id' => $data['prestudent_status']->prestudent_id,
+ 'abmeldungLink' => site_url('lehre/Studierendenantrag/abmeldung/' . $data['prestudent_status']->prestudent_id),
+ 'abmeldungLinkCIS' => CIS_ROOT .
+ 'index.ci.php/lehre/Studierendenantrag/abmeldung/' .
+ $data['prestudent_status']->prestudent_id
+ ],
+ $data['email'],
+ $this->_ci->p->t('studierendenantrag', 'mail_subject_U_Reject')
+ ))
+ $errors[] = $this->_ci->p->t('studierendenantrag', 'error_mail_to', $data);
+ }
+ }
+ }
+
+ if (count($errors))
+ return error($errors);
+
+ return success();
+ }
+
+ /**
+ * @param integer $studierendenantrag_id
+ *
+ * @return array
+ */
+ private function getDataForUnterbrechung($studierendenantrag_id)
+ {
+ $result = [];
+ $errors = [];
+
+ $res = $this->_ci->StudierendenantragModel->load($studierendenantrag_id);
+ if (isError($res))
+ return $res;
+
+ $res = getData($res);
+ if (!$res)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id]));
+
+ $result['antrag'] = $antrag = current($res);
+ $this->_ci->StudiengangModel->addJoin('public.tbl_prestudent ps', 'studiengang_kz');
+ $res = $this->_ci->StudiengangModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]);
+ if (hasData($res)) {
+ $result['studiengang'] = current(getData($res));
+ }
+ else{
+ $result['studiengang'] = new stdClass();
+ $result['studiengang']->bezeichnung = "";
+ }
+
+ $res = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail($antrag->prestudent_id);
+ if (isError($res))
+ return $res;
+
+ $res = getData($res);
+ if (!$res)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', $antrag));
+
+ $result['prestudent_status'] = current($res);
+
+
+ $res = $this->_ci->PrestudentModel->load($antrag->prestudent_id);
+
+ if (isError($res)) {
+ $errors['person_id'] = getError($res);
+ } else {
+ $res = getData($res);
+ if (!$res) {
+ $errors['person_id'] = $this->_ci->p->t('studierendenantrag', 'error_no_prestudent', $antrag);
+ } else {
+ $person_id = current($res)->person_id;
+
+ $res = $this->_ci->PersonModel->load($person_id);
+ if (isError($res)) {
+ $errors['person'] = getError($res);
+ } else {
+ $res = getData($res);
+ if (!$res) {
+ $errors['person'] = $this->_ci->p->t('studierendenantrag', 'error_no_person', ['person_id' => $person_id]);
+ } else {
+ $result['person'] = current($res);
+ }
+ }
+
+ $res = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $antrag->prestudent_id]);
+ if (isError($res)) {
+ $errors['email'] = getError($res);
+ } else {
+ $res = getData($res);
+
+ if (!$res) {
+ $errors['email'] = $this->_ci->p->t('studierendenantrag', 'error_no_email', ['person_id' => $person_id]);
+ } else {
+ $result['email'] = $this->_ci->StudentModel->getEmailFH(current($res)->student_uid);
+ }
+ }
+ }
+ }
+
+ $result['studienbeitrag'] = false;
+ if (!isset($errors['person_id'])) {
+ $date_target = new DateTime(
+ $this->_ci->config->item('frist_rueckzahlung_studiengebuer_' . substr($result['antrag']->studiensemester_kurzbz, 0, 2)) .
+ substr($result['antrag']->studiensemester_kurzbz, 2)
+ );
+ $date_created = new DateTime($result['antrag']->datum);
+ if ($date_created < $date_target) {
+ $this->_ci->load->model('crm/Konto_model', 'KontoModel');
+ $result['studienbeitrag'] = $this->_ci->KontoModel->checkStudienbeitragFromPerson(
+ $person_id,
+ $result['antrag']->studiensemester_kurzbz
+ );
+ }
+ }
+
+ $result['errors'] = $errors;
+
+ return success($result);
+ }
+
+ /**
+ * @param integer $prestudent_id
+ * @param string $studiensemester_kurzbz
+ * @param string $insertvon
+ * @param boolean $repeat
+ *
+ * @return stdClass
+ */
+ public function createWiederholung($prestudent_id, $studiensemester_kurzbz, $insertvon, $repeat)
+ {
+ $result = $this->_ci->StudierendenantragModel->loadIdAndStatusWhere([
+ 'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
+ 'studiensemester_kurzbz'=> $studiensemester_kurzbz,
+ 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG
+ ]);
+
+ $antrag_id = null;
+ if (hasData($result)) {
+ $antrag = current(getData($result));
+ if ($antrag->status == Studierendenantragstatus_model::STATUS_REOPENED ||
+ $antrag->status == Studierendenantragstatus_model::STATUS_REQUESTSENT_1 ||
+ $antrag->status == Studierendenantragstatus_model::STATUS_REQUESTSENT_2)
+ {
+ $antrag_id = $antrag->studierendenantrag_id;
+ }
+ else
+ {
+ return error($this->_ci->p->t('global', 'antragBereitsGestellt'));
+ }
+ }
+
+ if ($antrag_id === null) {
+ $result = $this->_ci->StudierendenantragModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'studiensemester_kurzbz'=> $studiensemester_kurzbz,
+ 'datum' => date('c'),
+ 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ 'insertvon' => $insertvon
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ $antrag_id = getData($result);
+ }
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => $repeat
+ ? Studierendenantragstatus_model::STATUS_CREATED
+ : Studierendenantragstatus_model::STATUS_PASS,
+ 'insertvon' => $insertvon
+ ]);
+
+ if ($repeat) {
+ $res = $this->_ci->PrestudentstatusModel->getLastStatusWithStgEmail($prestudent_id);
+ if (isError($res))
+ return $res;
+ $res = getData($res);
+ if (!$res)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', ['prestudent_id' => $prestudent_id]));
+
+ $prestudent_status = current($res);
+ $email = $prestudent_status->email;
+ // NOTE(chris): Sancho mail
+ $lvzuweisungLink = site_url('lehre/Antrag/Wiederholung/assistenz/' . $antrag_id);
+ if (defined('VILESCI_ROOT')) {
+ $lvzuweisungLink = VILESCI_ROOT . 'index.ci.php/lehre/Antrag/Wiederholung/assistenz/' . $antrag_id;
+ }
+ sendSanchoMail(
+ 'Sancho_Mail_Antrag_W_New',
+ [
+ 'antrag_id' => $antrag_id,
+ 'stg' => $prestudent_status->stg_bezeichnung,
+ 'Orgform' => $prestudent_status->orgform,
+ 'lvzuweisungLink' => $lvzuweisungLink
+ ],
+ $email,
+ $this->_ci->p->t('studierendenantrag', 'mail_subject_W_New')
+ );
+ }
+
+ if (isError($result))
+ return $result;
+
+ return success($antrag_id);
+ }
+
+ /**
+ * @param integer $studierendenantrag_id
+ * @param string $insertvon
+ *
+ * @return stdClass
+ */
+ public function reopenWiederholung($studierendenantrag_id, $insertvon)
+ {
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_REOPENED,
+ 'insertvon' => $insertvon
+ ]);
+ return $result;
+ }
+
+ /**
+ * @param integer $studierendenantrag_id
+ * @param string $objectedvon
+ *
+ * @return stdClass
+ */
+ public function objectAbmeldung($studierendenantrag_id, $objectedvon)
+ {
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $studierendenantrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_OBJECTED,
+ 'insertvon' => $objectedvon
+ ]);
+ return $result;
+ }
+
+ public function getWiederholungsAntraege($status)
+ {
+ $studiengaenge = $this->_ci->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
+ $result = $this->_ci->StudierendenantragModel->loadForStudiengaenge(
+ $studiengaenge,
+ Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ $status
+ );
+ if (!getData($result))
+ return $result;
+ $result = getData($result);
+ $grouped = [];
+
+ foreach ($result as $item) {
+ if (!isset($grouped[$item->studiengang_kz])) {
+ $grouped[$item->studiengang_kz] = [
+ 'bezeichnung' => $item->bezeichnung,
+ 'bezeichnung_mehrsprachig' => $item->bezeichnung_mehrsprachig,
+ 'antraege' => []
+ ];
+ }
+ $grouped[$item->studiengang_kz]['antraege'][] = $item;
+ }
+
+ return success($grouped);
+ }
+
+ public function getLvsForAntrag($antrag_id)
+ {
+ $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
+ $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+ $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel');
+
+ $result = $this->_ci->StudierendenantragModel->load($antrag_id);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $antrag_id]));
+ $antrag = current($result);
+
+
+ $result = $this->_ci->StudierendenantragModel->getStgAndSem($antrag_id);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_stg_and_sem', ['id' => $antrag_id]));
+ $result = current($result);
+ $studiengang_kz = $result->studiengang_kz;
+ $orgform_kurzbz = $result->orgform_kurzbz;
+ $ausbildungssemester = $result->ausbildungssemester;
+ $sprache = $result->sprache;
+
+ // NOTE(chris): check permission
+ $allowedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('student/studierendenantrag') ?: [];
+ if (!in_array($studiengang_kz, $allowedStgs)) {
+ $allowedStgs = $this->_ci->permissionlib->getSTG_isEntitledFor('student/antragfreigabe') ?: [];
+ if (!in_array($studiengang_kz, $allowedStgs)) {
+ if(!$this->isOwnAntrag($antrag_id))
+ return error('Forbidden');
+ }
+ }
+
+
+ $result = $this->_ci->StudiensemesterModel->getNextFrom($antrag->studiensemester_kurzbz);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_sem_after', ['semester' => $antrag->studiensemester_kurzbz]));
+ $semA = current($result)->studiensemester_kurzbz;
+
+ $result = $this->_ci->StudiensemesterModel->getNextFrom($semA);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_sem_after', ['semester' => $semA]));
+ $semB = current($result)->studiensemester_kurzbz;
+
+ $result = $this->_ci->StudierendenantraglehrveranstaltungModel->loadWhere(['studierendenantrag_id' => $antrag_id]);
+ if (isError($result))
+ return $result;
+ $result = getData($result) ?: [];
+
+ $lvszugewiesen = array();
+ foreach ($result as $lv)
+ {
+ $lvszugewiesen[$lv->lehrveranstaltung_id] = $lv;
+ }
+
+ $result = $this->getLvsByStgStsemAndSem(
+ $studiengang_kz,
+ $orgform_kurzbz,
+ $semA,
+ $ausbildungssemester + 1,
+ $antrag->prestudent_id,
+ $sprache
+ );
+ if (isError($result))
+ return $result;
+ $lvsA = $result->retval; // NOTE(chris): don't use getData() because we want to differenciate [] and null
+ $repeat_last = false;
+ if ($lvsA) {
+ foreach($lvsA as $lv)
+ {
+ if (isset($lvszugewiesen[$lv->lehrveranstaltung_id]) &&
+ ($lvszugewiesen[$lv->lehrveranstaltung_id]->note == $this->_ci->config->item('wiederholung_note_nicht_zugelassen')))
+ {
+ $lv->antrag_zugelassen = true;
+ $lv->antrag_anmerkung = $lvszugewiesen[$lv->lehrveranstaltung_id]->anmerkung;
+ }
+ }
+ } elseif ($lvsA === null) {
+ // NOTE(chris): We are repeating the last semester
+ $repeat_last = true;
+
+ $result = $this->_ci->PrestudentstatusModel->getStatusByFilter($antrag->prestudent_id, 'Student', $ausbildungssemester - 1);
+ if (isError($result))
+ return $result;
+
+ $stdsems = getData($result) ?: [];
+ $stdsem = null;
+
+ $result = $this->_ci->StudiensemesterModel->load($antrag->studiensemester_kurzbz);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t(
+ 'studierendenantrag',
+ 'error_no_stdsem',
+ ['studiensemester_kurzbz' => $antrag->studiensemester_kurzbz]
+ ));
+ $asem = current(getData($result));
+
+ foreach ($stdsems as $sem) {
+ $result = $this->_ci->StudiensemesterModel->load($sem->studiensemester_kurzbz);
+ if (isError($result))
+ return $result;
+ if (hasData($result)) {
+ if (current(getData($result))->start < $asem->start) {
+ $stdsem = $sem->studiensemester_kurzbz;
+ break;
+ }
+ }
+ }
+
+ // NOTE(chris): if we don't find a status in the previous semester there is something wrong
+ if (!$stdsem)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_status_in_prev_sem'));
+
+ $result = $this->getLvsByStgStsemAndSem(
+ $studiengang_kz,
+ $orgform_kurzbz,
+ $semA,
+ $ausbildungssemester - 1,
+ $antrag->prestudent_id,
+ $sprache
+ );
+ if (isError($result))
+ return $result;
+
+ $lvsA = getData($result) ?: [];
+
+ $result = $this->getLvsByStgStsemAndSem(
+ $studiengang_kz,
+ $orgform_kurzbz,
+ $stdsem,
+ $ausbildungssemester - 1,
+ $antrag->prestudent_id,
+ $sprache
+ );
+ if (isError($result))
+ return $result;
+
+ $lvsAtest = getData($result) ?: [];
+
+ if (count(array_intersect(array_map(function ($a) {
+ return $a->lehrveranstaltung_id;
+ }, $lvsA), array_map(function ($a) {
+ return $a->lehrveranstaltung_id;
+ }, $lvsAtest)))) {
+ foreach ($lvsA as $lv) {
+ if (isset($lvszugewiesen[$lv->lehrveranstaltung_id]) && ($lvszugewiesen[$lv->lehrveranstaltung_id]->note == 0)) {
+ $lv->antrag_anmerkung = $lvszugewiesen[$lv->lehrveranstaltung_id]->anmerkung;
+ $lv->antrag_zugelassen = true;
+ }
+ }
+ } else {
+ $lvsA = null;
+ }
+ }
+
+ $result = $this->getLvsByStgStsemAndSem(
+ $studiengang_kz,
+ $orgform_kurzbz,
+ $semB,
+ $ausbildungssemester,
+ $antrag->prestudent_id,
+ $sprache
+ );
+ if (isError($result))
+ return $result;
+ $lvsB = getData($result) ?: [];
+ foreach($lvsB as $lv)
+ {
+ if(isset($lvszugewiesen[$lv->lehrveranstaltung_id]) && ($lvszugewiesen[$lv->lehrveranstaltung_id]->note == 0))
+ {
+ $lv->antrag_anmerkung = $lvszugewiesen[$lv->lehrveranstaltung_id]->anmerkung;
+ $lv->antrag_zugelassen = true;
+ }
+ // TODO(manu): eventuelle Änderungen taggen
+ }
+
+ $result = [
+ '1' . $semA => $lvsA,
+ '2' . $semB => $lvsB ?: []
+ ];
+ if ($repeat_last)
+ $result['repeat_last'] = true;
+
+ return success($result);
+ }
+
+ public function getLvsByStgStsemAndSem(
+ $studiengang_kz,
+ $orgform_kurzbz,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $prestudent_id,
+ $sprache
+ ) {
+ $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel');
+
+ $result = $this->_ci->StudienplanModel->getStudienplaeneBySemester(
+ $studiengang_kz,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $orgform_kurzbz
+ );
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result) {
+ $result = $this->_ci->StudiengangModel->load($studiengang_kz);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_stg', ['studiengang_kz' => $studiengang_kz]));
+ $stg = current(getData($result));
+
+ if ($ausbildungssemester > $stg->max_semester)
+ return success();
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_studienplan', [
+ 'studiengang_kz' => $studiengang_kz,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'semester' => $ausbildungssemester
+ ]));
+ }
+ if (count($result) > 1) {
+ $langmap = array_unique(array_map(function ($a) {
+ return $a->sprache;
+ }, $result));
+ if ($sprache
+ && count($langmap) == count($result)
+ && in_array($sprache, $langmap)
+ ) {
+ $result = array_filter($result, function ($a) use ($sprache) {
+ return $a->sprache == $sprache;
+ });
+ } else {
+ return error($this->_ci->p->t('studierendenantrag', 'error_multiple_studienplan', [
+ 'studiengang_kz' => $studiengang_kz,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'semester' => $ausbildungssemester
+ ]));
+ }
+ }
+ $studienplan = current($result);
+
+ return $this->_ci->StudienplanModel->getStudienplanLehrveranstaltungForPrestudent(
+ $studienplan->studienplan_id,
+ $ausbildungssemester,
+ $prestudent_id
+ );
+ }
+
+ /**
+ * Checks if a prestudent can submit an Antrag for Abmeldung
+ *
+ * @param integer $prestudent_id
+ *
+ * @return \stdClass on success retval 0 means not a student;
+ * retval 1 means Berechtigt;
+ * retval -1 means has already an Antrag pending;
+ * retval -2 means other Antrag pending;
+ * retval -3 means in blacklist stg
+ */
+ public function getPrestudentAbmeldeBerechtigt($prestudent_id)
+ {
+ $result = $this->_ci->PrestudentModel->load($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(0);
+ $result = current(getData($result));
+ $stg_kz = $result->studiengang_kz;
+ if (in_array($stg_kz, $this->_ci->config->item('stgkz_blacklist_abmeldung')))
+ return success(-3);
+
+ $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(0);
+ $result = current(getData($result));
+ $datumStatus = $result->datum;
+
+ if (!in_array($result->status_kurzbz, $this->_ci->config->item('antrag_prestudentstatus_whitelist_abmeldung'))) {
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
+ 'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
+ 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED
+ ], [
+ Studierendenantrag_model::TYP_ABMELDUNG,
+ Studierendenantrag_model::TYP_ABMELDUNG_STGL
+ ]);
+ if (isError($result))
+ return $result;
+ if (hasData($result))
+ return success(-1);
+
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
+ 'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
+ 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE
+ ], [
+ Studierendenantrag_model::TYP_ABMELDUNG,
+ Studierendenantrag_model::TYP_ABMELDUNG_STGL
+ ]);
+ if (isError($result))
+ return $result;
+ if (hasData($result))
+ return success(-1);
+
+ return success(0);
+ }
+
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(1);
+ $result= getData($result);
+ foreach ($result as $antrag)
+ {
+ if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG || $antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL)
+ {
+ if ($antrag->status == Studierendenantragstatus_model::STATUS_CREATED)
+ return success(-1);
+ elseif ($antrag->status == Studierendenantragstatus_model::STATUS_APPROVED && $antrag->datum > $datumStatus)
+ return success(-1);
+ }
+ if ($antrag->typ == Studierendenantrag_model::TYP_WIEDERHOLUNG)
+ {
+ if($antrag->status == Studierendenantragstatus_model::STATUS_PASS)
+ return success(-2);
+ }
+ }
+
+ return success(1);
+ }
+
+ /**
+ * Checks if a prestudent can submit an Antrag for Unterbrechung
+ *
+ * @param integer $prestudent_id
+ * @param string $studiensemester_kurzbz (optional)
+ *
+ * @return \stdClass on success retval 0 means not a student;
+ * retval 1 means Berechtigt;
+ * retval -1 means has already an Antrag pending;
+ * retval -2 means other Antrag pending;
+ * retval -3 means in blacklist stg
+ */
+ public function getPrestudentUnterbrechungsBerechtigt($prestudent_id, $studiensemester_kurzbz = null, $datum_wiedereinstieg = null)
+ {
+ $result = $this->_ci->PrestudentModel->load($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(0);
+ $result = current(getData($result));
+ $stg_kz = $result->studiengang_kz;
+ if (in_array($stg_kz, $this->_ci->config->item('stgkz_blacklist_unterbrechung')))
+ return success(-3);
+
+ $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(0);
+ $result = current(getData($result));
+ $prestudent_stdsem = $result->studiensemester_kurzbz;
+ $datumStatus = $result->datum;
+ if (!in_array($result->status_kurzbz, $this->_ci->config->item('antrag_prestudentstatus_whitelist'))
+ && $result->status_kurzbz != 'Unterbrecher') {
+ return success(0);
+ }
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(1);
+
+ $result = getData($result);
+ foreach ($result as $antrag)
+ {
+ if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG || $antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL)
+ {
+ if($antrag->status == Studierendenantragstatus_model::STATUS_CREATED)
+ return success(-2);
+ elseif($antrag->status == Studierendenantragstatus_model::STATUS_APPROVED && $antrag->datum > $datumStatus)
+ return success(-2);
+ }
+ if ($antrag->typ == Studierendenantrag_model::TYP_WIEDERHOLUNG)
+ {
+ if($antrag->status == Studierendenantragstatus_model::STATUS_PASS)
+ return success(-2);
+ }
+ }
+
+ if (!$studiensemester_kurzbz) {
+ $sems = $this->getSemesterForUnterbrechung($prestudent_id, $prestudent_stdsem);
+ if (!count(array_filter($sems, function ($item) {
+ return !$item['disabled'];
+ })))
+ return success(-1);
+ } else {
+ if ($this->_ci->StudierendenantragModel->hasRunningUnterbrechungBetween($prestudent_id, $studiensemester_kurzbz, $datum_wiedereinstieg))
+ return success(-1);
+ }
+
+ return success(1);
+ }
+
+ /**
+ * Checks if a prestudent can submit an Antrag for Wiederholung
+ *
+ * @param integer $prestudent_id
+ *
+ * @return \stdClass on success retval 0 means not a student;
+ * retval 1 means Berechtigt;
+ * retval -1 means has already an Antrag pending;
+ * retval -2 means other Antrag pending;
+ * retval -3 means in blacklist stg
+ */
+ public function getPrestudentWiederholungsBerechtigt($prestudent_id)
+ {
+ $result = $this->_ci->PrestudentModel->load($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(0);
+ $result = current(getData($result));
+ $stg_kz = $result->studiengang_kz;
+ if (in_array($stg_kz, $this->_ci->config->item('stgkz_blacklist_wiederholung')))
+ return success(-3);
+
+ $result = $this->getFailedExamForPrestudent($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(0);
+
+ $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(0);
+
+ $result = current(getData($result));
+ $datumStatus = $result->datum;
+ if (!in_array($result->status_kurzbz, $this->_ci->config->item('antrag_prestudentstatus_whitelist'))) {
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
+ 'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
+ 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED
+ ]);
+ if (isError($result))
+ return $result;
+ if (hasData($result))
+ return success(-1);
+
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
+ 'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
+ 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_DEREGISTERED
+ ]);
+ if (isError($result))
+ return $result;
+ if (hasData($result))
+ return success(-1);
+
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere([
+ 'tbl_studierendenantrag.prestudent_id' => $prestudent_id,
+ 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE
+ ]);
+ if (isError($result))
+ return $result;
+ if (hasData($result))
+ return success(-1);
+
+ return success(0);
+ }
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere(['tbl_studierendenantrag.prestudent_id' => $prestudent_id]);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(1);
+ $result= getData($result);
+ foreach ($result as $antrag)
+ {
+ if ($antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG || $antrag->typ == Studierendenantrag_model::TYP_ABMELDUNG_STGL)
+ {
+ if($antrag->status == Studierendenantragstatus_model::STATUS_CREATED)
+ return success(-2);
+ elseif($antrag->status == Studierendenantragstatus_model::STATUS_APPROVED && $antrag->datum > $datumStatus)
+ return success(-2);
+ }
+ if ($antrag->typ == Studierendenantrag_model::TYP_WIEDERHOLUNG)
+ {
+ return success(-1);
+ }
+ }
+
+ return success(1);
+ }
+
+ /**
+ * Gets details for a new Antrag
+ *
+ * @param integer $prestudent_id
+ *
+ * @return \stdClass
+ */
+ public function getDetailsForNewAntrag($prestudent_id)
+ {
+ $result = $this->_ci->PrestudentstatusModel->loadLastWithStgDetails($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', ['prestudent_id' => $prestudent_id]));
+ $result = current(getData($result));
+ return success($result);
+ }
+
+ /**
+ * Gets details for the latest Antrag of one or more types
+ *
+ * @param integer $prestudent_id
+ * @param array|string $typ
+ *
+ * @return \stdClass
+ */
+ public function getDetailsForLastAntrag($prestudent_id, $typ = null)
+ {
+ $where = [
+ 'tbl_studierendenantrag.prestudent_id' => $prestudent_id
+ ];
+ $types = null;
+ if ($typ) {
+ if (is_array($typ))
+ $types = $typ;
+ else
+ $where['typ'] = $typ;
+ }
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere($where, $types);
+ if (isError($result))
+ return $result;
+
+ $antraege = getData($result) ?: [];
+ $resultAntrag = null;
+ foreach ($antraege as $antrag) {
+ if ($antrag->status != Studierendenantragstatus_model::STATUS_CANCELLED) {
+ $resultAntrag = $antrag;
+ break;
+ }
+ }
+ if (!$resultAntrag)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found_prestudent', [
+ 'typ' => $typ ?: '',
+ 'prestudent_id' => $prestudent_id
+ ]));
+
+ return $this->addDetailsToAntrag($resultAntrag);
+ }
+
+ /**
+ * Gets details for a specific Antrag
+ *
+ * @param integer $studierendenantrag_id
+ *
+ * @return \stdClass
+ */
+ public function getDetailsForAntrag($studierendenantrag_id)
+ {
+ $where = [
+ 's.studierendenantrag_id' => $studierendenantrag_id
+ ];
+
+ $result = $this->_ci->StudierendenantragModel->loadWithStatusWhere($where);
+ if (isError($result))
+ return $result;
+
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', "error_no_antrag_found", ['id' => $studierendenantrag_id]));
+ $resultAntrag = current(getData($result));
+
+ return $this->addDetailsToAntrag($resultAntrag);
+ }
+
+ /**
+ * Helper function for getDetailsForAntrag and getDetailsForLastAntrag
+ *
+ * @param \stdClass $antrag
+ *
+ * @return \stdClass
+ */
+ protected function addDetailsToAntrag($antrag)
+ {
+ $result = $this->_ci->PrestudentstatusModel->loadLastWithStgDetails(
+ $antrag->prestudent_id,
+ $antrag->studiensemester_kurzbz,
+ $antrag->insertamum
+ );
+ if (isError($result))
+ return $result;
+ if (!hasData($result)) {
+ $result = $this->_ci->PrestudentstatusModel->loadLastWithStgDetails(
+ $antrag->prestudent_id,
+ null,
+ $antrag->insertamum
+ );
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudent_in_sem', $antrag));
+ $tmp = current(getData($result));
+ $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+ $res = $this->_ci->StudiensemesterModel->load($antrag->studiensemester_kurzbz);
+ if (hasData($res))
+ $tmp->studienjahr_kurzbz = current(getData($res))->studienjahr_kurzbz;
+ else
+ $tmp->studienjahr_kurzbz = '';
+ // NOTE(chris): the semester might not be correct on this fallback so we disable it
+ $tmp->semester = '';
+ }
+
+ $result = current(getData($result));
+
+ $result->status = $antrag->status;
+ $result->statustyp = $antrag->statustyp;
+ $result->status_insertvon = $antrag->status_insertvon;
+ $result->grund = $antrag->grund;
+ $result->studierendenantrag_id = $antrag->studierendenantrag_id;
+ $result->typ = $antrag->typ;
+ $result->datum = $antrag->datum;
+ $result->dms_id = $antrag->dms_id;
+ $result->datum_wiedereinstieg = $antrag->datum_wiedereinstieg;
+
+ return success($result);
+ }
+
+ /**
+ * Rearrange the free semester slots for a new Unterbrechung
+ *
+ * @param integer $prestudent_id
+ * @param string $studiensemester_kurzbz
+ *
+ * @return array
+ */
+ public function getSemesterForUnterbrechung($prestudent_id, $studiensemester_kurzbz)
+ {
+ $result = $this->_ci->StudierendenantragModel->getFreeSlotsForUnterbrechung($prestudent_id, $studiensemester_kurzbz);
+ if (isError($result))
+ return [];
+ $result = getData($result);
+ if (!$result)
+ return [];
+ return array_reduce($result, function ($carry, $item) {
+ if (!isset($carry[$item->von]))
+ $carry[$item->von] = [
+ 'studienjahr_kurzbz' => $item->studienjahr_kurzbz,
+ 'studiensemester_kurzbz' => $item->von,
+ 'wiedereinstieg' => [],
+ 'disabled' => true
+ ];
+
+ $carry[$item->von]['wiedereinstieg'][] = [
+ 'studiensemester_kurzbz' => $item->bis,
+ 'start' => $item->ende,
+ 'disabled' => (boolean)$item->studierendenantrag_id
+ ];
+
+ if ($carry[$item->von]['disabled'] && !$item->studierendenantrag_id) {
+ $carry[$item->von]['disabled'] = false;
+ }
+
+ return $carry;
+ }, []);
+ return $result;
+ }
+
+ public function getAktivePrestudentenInStgs($studiengaenge, $query)
+ {
+ $blacklist = $this->_ci->config->item('stgkz_blacklist_abmeldung');
+ $studiengaenge = array_diff($studiengaenge, $blacklist);
+ return $this->_ci->StudiengangModel->getAktivePrestudenten(
+ $studiengaenge,
+ [ Studierendenantrag_model::TYP_ABMELDUNG ],
+ $query
+ );
+ }
+
+ public function getFailedExamForPrestudent($prestudent_id, $max_date = null, $studiensemester_kurzbz = null)
+ {
+ return $this->_ci->PruefungModel->loadWhereCommitteeExamFailedForPrestudent($prestudent_id, $max_date, $studiensemester_kurzbz);
+ }
+
+ public function saveLvs($lvArray)
+ {
+ $result = $this->_ci->StudierendenantraglehrveranstaltungModel->deleteWhere([
+ 'studierendenantrag_id' => $lvArray[0]['studierendenantrag_id']
+ ]);
+ if (isError($result))
+ return $result;
+
+ $result = $this->_ci->StudierendenantraglehrveranstaltungModel->insertBatch($lvArray);
+ if (isError($result))
+ return $result;
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $lvArray[0]['studierendenantrag_id'],
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_LVSASSIGNED,
+ 'insertvon' => $lvArray[0]['insertvon']
+ ]);
+ if (isError($result))
+ return $result;
+
+ $antrag_status_id = getData($result);
+ $result = $this->_ci->StudierendenantragstatusModel->loadWithTyp($antrag_status_id);
+
+ return $result;
+ }
+
+ public function approveWiederholung($antrag_id, $insertvon)
+ {
+ $this->_ci->load->model('crm/Student_model', 'StudentModel');
+
+ $result = $this->_ci->StudierendenantragstatusModel->insert([
+ 'studierendenantrag_id' => $antrag_id,
+ 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED,
+ 'insertvon' => $insertvon
+ ]);
+
+ if (isError($result)) {
+ return $result;
+ }
+
+ $result = $this->_ci->StudierendenantragModel->getStgEmail($antrag_id);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_stg_email', ['id' => $antrag_id]));
+
+ $email = current($result)->email;
+
+ $result = $this->_ci->StudierendenantragModel->getStgAndSem($antrag_id);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_stg_antrag', ['id' => $antrag_id]));
+
+ $stg = current($result);
+ $semester = $stg->ausbildungssemester;
+
+ $result = $this->_ci->StudierendenantragModel->load($antrag_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $antrag_id]));
+ $result = current(getData($result));
+ $prestudent_id = $result->prestudent_id;
+
+ $result = $this->_ci->PersonModel->loadPrestudent($prestudent_id);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_person_prestudent', ['prestudent_id' => $prestudent_id]));
+ $person = current(getData($result));
+ $student = trim($person->vorname . ' ' . $person->nachname);
+
+ $result = $this->_ci->PersonModel->getFullName($insertvon);
+ if (isError($result))
+ return $result;
+ $mitarbeiter = $insertvon;
+ if (hasData($result)) {
+ $mitarbeiter = getData($result);
+ }
+
+ $result = $this->_ci->StudentModel->loadWhere(['prestudent_id'=> $prestudent_id]);
+ if (hasData($result)) {
+ $studentObj = current(getData($result));
+ $student_uid = $studentObj->student_uid;
+ }
+ else
+ $student_uid = '';
+
+ // NOTE(chris): Sancho mail
+ if (!sendSanchoMail(
+ 'Sancho_Mail_Antrag_W_Approve',
+ [
+ 'antrag_id' => $antrag_id,
+ 'stg' => $stg->bezeichnung,
+ 'sem' => $semester,
+ 'student' => $student,
+ 'mitarbeiter' => $mitarbeiter,
+ 'Orgform' => $stg->orgform_kurzbz,
+ 'UID' => $student_uid
+ ],
+ $email,
+ $this->_ci->p->t('studierendenantrag', 'mail_subject_W_Approve')
+ ))
+ return error($this->_ci->p->t('studierendenantrag', 'error_mail_to', ['email' => $email]));
+
+ if ($student_uid) {
+ $email = $this->_ci->StudentModel->getEmailFH($student_uid);
+ $vorlage = 'Sancho_Mail_Antrag_W_Student';
+
+ $sem_not_allowed = $sem_to_repeat = '';
+ $list_not_allowed = $list_to_repeat = $this->_ci->p->t('studierendenantrag', 'mail_part_error_no_lvs');
+
+ $result = $this->getLvsForAntrag($antrag_id);
+ if (hasData($result)) {
+ $lvs = getData($result);
+ if (isset($lvs['repeat_last'])) {
+ unset($lvs['repeat_last']);
+ $vorlage .= '_Lst';
+ }
+ foreach ($lvs as $sem => $lv_list) {
+ $lvs_filtered = array_filter($lv_list, function ($el) {
+ return property_exists($el, 'antrag_zugelassen') && $el->antrag_zugelassen;
+ });
+ if (substr($sem, 0, 1) == '1') {
+ $sem_not_allowed = substr($sem, 1);
+ $list_not_allowed = array_map(function ($el) {
+ return $el->bezeichnung . '(' . $el->lehrform_kurzbz . ')';
+ }, $lvs_filtered);
+ $list_not_allowed = '- ' . implode('
- ', $list_not_allowed) . '
';
+ } else {
+ $sem_to_repeat = substr($sem, 1);
+ $list_to_repeat = array_map(function ($el) {
+ return $el->bezeichnung . '(' . $el->lehrform_kurzbz . ')';
+ }, $lvs_filtered);
+ $list_to_repeat = '- ' . implode('
- ', $list_to_repeat) . '
';
+ }
+ }
+ }
+
+ // NOTE(chris): Sancho mail
+ sendSanchoMail(
+ $vorlage,
+ [
+ 'antrag_id' => $antrag_id,
+ 'stg' => $stg->bezeichnung,
+ 'sem' => $semester,
+ 'mitarbeiter' => $mitarbeiter,
+ 'student' => $student,
+ 'sem_not_allowed' => $sem_not_allowed,
+ 'list_not_allowed' => $list_not_allowed,
+ 'sem_to_repeat' => $sem_to_repeat,
+ 'list_to_repeat' => $list_to_repeat,
+ 'Orgform' => $stg->orgform_kurzbz
+ ],
+ $email,
+ $this->_ci->p->t('studierendenantrag', 'mail_subject_W_Student')
+ );
+ }
+
+
+ return success();
+ }
+
+ public function getAntragHistory($antrag_id)
+ {
+ $result = $this->_ci->StudierendenantragstatusModel->loadWithTypWhere([
+ 'studierendenantrag_id' => $antrag_id
+ ]);
+ return $result;
+ }
+
+
+ /**
+ * @param integer $studierendenantrag_id
+ *
+ * @return boolean
+ */
+ protected function isOwnAntrag($studierendenantrag_id)
+ {
+ if ($studierendenantrag_id == null)
+ return false;
+ $result = $this->_ci->StudierendenantragModel->loadForPerson(getAuthPersonId());
+ if (!hasData($result))
+ return false;
+ $antraege = array_map(function ($antrag) {
+ return $antrag->studierendenantrag_id;
+ }, getData($result));
+
+ return in_array($studierendenantrag_id, $antraege);
+ }
+
+ /**
+ * @param integer $studierendenantrag_id
+ * @param string $permission either 'student/antragfreigabe' or 'student/studierendenantrag'
+ *
+ * @return boolean
+ */
+ protected function hasAccessToAntrag($studierendenantrag_id, $permission)
+ {
+ $studiengaenge = $this->_ci->permissionlib->getSTG_isEntitledFor($permission);
+ if (!$studiengaenge)
+ return false;
+ $result = $this->_ci->StudierendenantragModel->isInStudiengang($studierendenantrag_id, $studiengaenge);
+ return (boolean)getData($result);
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToShowAntrag($antrag_id)
+ {
+ return
+ (
+ $this->isOwnAntrag($antrag_id) ||
+ $this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') ||
+ $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag')
+ );
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToSeeHistoryForAntrag($antrag_id)
+ {
+ return
+ (
+ $this->isOwnAntrag($antrag_id) ||
+ $this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') ||
+ $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag')
+ );
+ }
+
+ /**
+ * @param integer $prestudent_id
+ * @param boolean $checkAssistencePermission
+ *
+ * @return boolean
+ */
+ public function isEntitledToCreateAntragFor($prestudent_id, $checkAssistencePermission = false)
+ {
+ $result = $this->_ci->PrestudentModel->load($prestudent_id);
+ if (!hasData($result))
+ return false;
+
+ $result = getData($result)[0];
+ $person_id = $result->person_id;
+
+ if (getAuthPersonId() == $person_id)
+ return true;
+
+ if ($checkAssistencePermission)
+ {
+ $studiengaenge = $this->_ci->permissionlib->getSTG_isEntitledFor('student/studierendenantrag');
+ if (in_array($result->studiengang_kz, $studiengaenge ?: []))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToCancelAntrag($antrag_id)
+ {
+ $result = $this->_ci->StudierendenantragModel->load($antrag_id);
+ if (!hasData($result))
+ return false;
+ $antrag = current(getData($result));
+
+ if ($antrag->typ != Studierendenantrag_model::TYP_ABMELDUNG_STGL)
+ return $this->isOwnAntrag($antrag_id);
+
+ return $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag');
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToPauseAntrag($antrag_id)
+ {
+ return ($this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') || $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag'));
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToUnpauseAntrag($antrag_id)
+ {
+ return ($this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') || $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag'));
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToReopenAntrag($antrag_id)
+ {
+ return $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag');
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToObjectAntrag($antrag_id)
+ {
+ return ($this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe') || $this->hasAccessToAntrag($antrag_id, 'student/studierendenantrag'));
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToApproveAntrag($antrag_id)
+ {
+ return $this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe');
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isEntitledToRejectAntrag($antrag_id)
+ {
+ return $this->hasAccessToAntrag($antrag_id, 'student/antragfreigabe');
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function antragCanBeManualPaused($antrag_id)
+ {
+ $this->_ci->StudierendenantragModel->db->where_not_in('campus.get_status_studierendenantrag(studierendenantrag_id)', [
+ Studierendenantragstatus_model::STATUS_DEREGISTERED,
+ Studierendenantragstatus_model::STATUS_APPROVED,
+ Studierendenantragstatus_model::STATUS_PAUSE
+ ]);
+ $result = $this->_ci->StudierendenantragModel->loadWhere([
+ 'studierendenantrag_id' => $antrag_id,
+ 'typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG
+ ]);
+
+ return hasData($result);
+ }
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function antragCanBeManualUnpaused($antrag_id)
+ {
+ return $this->_ci->StudierendenantragModel->isManuallyPaused($antrag_id);
+ }
+
+ /**
+ * @param integer $antrag_id
+ * @param string|array $status
+ *
+ * @return boolean
+ */
+ public function hasStatus($antrag_id, $status)
+ {
+ $result = $this->_ci->StudierendenantragModel->getWithLastStatusWhere(['s.studierendenantrag_id' => $antrag_id]);
+ if (!hasData($result))
+ return false;
+ $lastStatus = getData($result)[0];
+
+ if (!is_array($status))
+ $status = [$status];
+
+ return in_array($lastStatus->studierendenantrag_statustyp_kurzbz, $status);
+ }
+
+ /**
+ * @param integer $antrag_id
+ * @param string|array $type
+ *
+ * @return boolean
+ */
+ public function hasType($antrag_id, $type)
+ {
+ $result = $this->_ci->StudierendenantragModel->load($antrag_id);
+ if (!hasData($result))
+ return false;
+ $antrag = getData($result)[0];
+
+ if (!is_array($type))
+ $type = [$type];
+
+ return in_array($antrag->typ, $type);
+ }
+
+
+ /**
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz)
+ {
+ $result = $this->_ci->StudierendenantraglehrveranstaltungModel->getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz);
+ return $result;
+ }
+}
\ No newline at end of file
diff --git a/application/libraries/DmsLib.php b/application/libraries/DmsLib.php
index fccfe503b..774ebdc79 100644
--- a/application/libraries/DmsLib.php
+++ b/application/libraries/DmsLib.php
@@ -595,6 +595,8 @@ class DmsLib
if (isError($insDmsResult)) return $insDmsResult;
$upload_data['dms_id'] = getData($insDmsResult);
+ if(isset($upload_data['file_type']) && !isset($dms['mimetype']))
+ $dms['mimetype'] = $upload_data['file_type'];
// Insert DMS version
$insVersionResult = $this->_ci->DmsVersionModel->insert(
diff --git a/application/libraries/FilterCmptLib.php b/application/libraries/FilterCmptLib.php
index 9d6dfa681..8b13ae3e5 100644
--- a/application/libraries/FilterCmptLib.php
+++ b/application/libraries/FilterCmptLib.php
@@ -1,4 +1,5 @@
_setSessionElement(FilterCmptLib::SESSION_SIDE_MENU,
- $this->_generateFilterMenu($this->_app, $this->_datasetName));
+ $this->_setSessionElement(
+ FilterCmptLib::SESSION_SIDE_MENU,
+ $this->_generateFilterMenu($this->_app, $this->_datasetName)
+ );
}
return $saveCustomFilter;
@@ -717,6 +723,7 @@ class FilterCmptLib
$this->_filterKurzbz = null;
$this->_query = null;
$this->_requiredPermissions = null;
+ $this->_encryptedColumns = null;
$this->_reloadDataset = true; // by default the dataset is NOT cached in session
$this->_sessionTimeout = FilterCmptLib::SESSION_DEFAULT_TIMEOUT;
@@ -727,6 +734,12 @@ class FilterCmptLib
$this->_requiredPermissions = $filterCmptArray[FilterCmptLib::REQUIRED_PERMISSIONS];
}
+ // Retrieved the encrypted columns parameter if present
+ if (isset($filterCmptArray[FilterCmptLib::ENCRYPTED_COLUMNS]))
+ {
+ $this->_encryptedColumns = $filterCmptArray[FilterCmptLib::ENCRYPTED_COLUMNS];
+ }
+
// Parameters needed to retrieve univocally a filter from DB
if (isset($filterCmptArray[FilterCmptLib::APP]))
{
@@ -1129,7 +1142,7 @@ class FilterCmptLib
$this->_ci->load->model('system/Filters_model', 'FiltersModel');
// Execute the given SQL statement suppressing error messages
- $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery);
+ $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $this->_encryptedColumns);
}
return $dataset;
diff --git a/application/libraries/FilterWidgetLib.php b/application/libraries/FilterWidgetLib.php
index 19cdec848..9968767d9 100644
--- a/application/libraries/FilterWidgetLib.php
+++ b/application/libraries/FilterWidgetLib.php
@@ -1,7 +1,26 @@
.
+ */
+
if (! defined('BASEPATH')) exit('No direct script access allowed');
+use \stdClass as stdClass;
+
/**
* FilterWidget logic
*/
@@ -16,6 +35,7 @@ class FilterWidgetLib
const SESSION_SELECTED_FIELDS = 'selectedFields';
const SESSION_COLUMNS_ALIASES = 'columnsAliases';
const SESSION_ADDITIONAL_COLUMNS = 'additionalColumns';
+ const SESSION_ENCRYPTED_COLUMNS = 'encryptedColumns';
const SESSION_CHECKBOXES = 'checkboxes';
const SESSION_FILTERS = 'filters';
const SESSION_METADATA = 'datasetMetadata';
@@ -56,6 +76,7 @@ class FilterWidgetLib
const ADDITIONAL_COLUMNS = 'additionalColumns';
const CHECKBOXES = 'checkboxes';
const COLUMNS_ALIASES = 'columnsAliases';
+ const ENCRYPTED_COLUMNS = 'encryptedColumns';
// ...to format/mark records of a dataset
const FORMAT_ROW = 'formatRow';
@@ -120,7 +141,7 @@ class FilterWidgetLib
/**
* Gets the CI instance and loads message helper
*/
- public function __construct($params = null)
+ public function __construct()
{
$this->_ci =& get_instance(); // get code igniter instance
}
@@ -367,7 +388,7 @@ class FilterWidgetLib
/**
* Retrieves the dataset from the DB
*/
- public function getDataset($datasetQuery)
+ public function getDataset($datasetQuery, $encryptedColumns)
{
$dataset = null;
@@ -376,7 +397,7 @@ class FilterWidgetLib
$this->_ci->load->model('system/Filters_model', 'FiltersModel');
// Execute the given SQL statement suppressing error messages
- $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery);
+ $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $encryptedColumns);
}
return $dataset;
@@ -390,7 +411,7 @@ class FilterWidgetLib
public function getFilterName($filterJson)
{
$filterName = $filterJson->name; // always present, used as default
- $trimedname = (isset($filterJson->namePhrase)?trim($filterJson->namePhrase):'');
+
// Filter name from phrases system
if (isset($filterJson->namePhrase) && !isEmptyString($filterJson->namePhrase))
{
@@ -451,7 +472,8 @@ class FilterWidgetLib
if (in_array($selectedField, $fields))
{
// If the selected field is present in the list of the selected fields by the current filter
- if (($pos = array_search($selectedField, $selectedFields)) !== false)
+ $pos = array_search($selectedField, $selectedFields);
+ if ($pos !== false)
{
// Then remove it and shift the rest of elements by one if needed
array_splice($selectedFields, $pos, 1);
@@ -750,7 +772,6 @@ class FilterWidgetLib
$this->_ci->load->library('NavigationLib', array(self::NAVIGATION_PAGE => $navigationPage));
$filterMenu = null;
- $currentMenu = $this->_ci->navigationlib->getSessionMenu(); // The navigation menu currently stored in session
$session = $this->getSession(); // The filter currently stored in session (the one that is currently used)
if ($session != null)
diff --git a/application/libraries/IssuesLib.php b/application/libraries/IssuesLib.php
index 9b3a9de6e..f38303b3c 100644
--- a/application/libraries/IssuesLib.php
+++ b/application/libraries/IssuesLib.php
@@ -246,7 +246,27 @@ class IssuesLib
$fehlertext = vsprintf($fehlertextVorlage, $fehlertext_params);
}
- $openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount($fehlercode, $person_id, $oe_kurzbz, $fehlercode_extern);
+ if (isset($resolution_params))
+ {
+ if (is_array($resolution_params))
+ {
+ foreach ($resolution_params as $resolution_key => $resolution_param)
+ {
+ if (!is_string($resolution_key))
+ return error("Invalid parameter for resolution, must be an associative array");
+ }
+ }
+ else
+ return error("Invalid parameters for resolution");
+ }
+
+ $openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount(
+ $fehlercode,
+ $person_id,
+ $oe_kurzbz,
+ $fehlercode_extern,
+ $resolution_params
+ );
if (hasData($openIssuesCountRes))
{
@@ -256,20 +276,6 @@ class IssuesLib
if ($openIssueCount == 0)
{
- if (isset($resolution_params))
- {
- if (is_array($resolution_params))
- {
- foreach ($resolution_params as $resolution_key => $resolution_param)
- {
- if (!is_string($resolution_key))
- return error("Invalid parameter for resolution, must be an associative array");
- }
- }
- else
- return error("Invalid parameters for resolution");
- }
-
// insert new issue
return $this->_ci->IssueModel->insert(
array(
diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php
index 09f89abee..857defbf7 100644
--- a/application/libraries/PermissionLib.php
+++ b/application/libraries/PermissionLib.php
@@ -21,6 +21,8 @@ require_once(FHCPATH.'include/functions.inc.php');
require_once(FHCPATH.'include/wawi_kostenstelle.class.php');
require_once(FHCPATH.'include/benutzerberechtigung.class.php');
+use \benutzerberechtigung as benutzerberechtigung;
+
class PermissionLib
{
// Available rights in the DB
@@ -65,8 +67,10 @@ class PermissionLib
if (!is_cli())
{
// API Caller rights initialization
+ $authObj = $this->_ci->authlib->getAuthObj();
self::$bb = new benutzerberechtigung();
- self::$bb->getBerechtigungen(($this->_ci->authlib->getAuthObj())->{AuthLib::AO_USERNAME});
+ if ($authObj)
+ self::$bb->getBerechtigungen($authObj->{AuthLib::AO_USERNAME});
}
}
@@ -143,19 +147,7 @@ class PermissionLib
if (strpos($permissions[$pCounter], PermissionLib::PERMISSION_SEPARATOR) !== false)
{
// Retrieves permission and required access type from the $requiredPermissions array
- list($permission, $requiredAccessType) = explode(PermissionLib::PERMISSION_SEPARATOR, $permissions[$pCounter]);
-
- $accessType = '';
-
- // Set the access type
- if (strpos($requiredAccessType, PermissionLib::READ_RIGHT) !== false)
- {
- $accessType = PermissionLib::SELECT_RIGHT; // S
- }
- if (strpos($requiredAccessType, PermissionLib::WRITE_RIGHT) !== false)
- {
- $accessType .= PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT; // UID
- }
+ list($permission, $accessType) = $this->convertAccessType($permissions[$pCounter]);
if (!isEmptyString($accessType)) // if compliant
{
@@ -166,6 +158,16 @@ class PermissionLib
if ($checkPermissions === true) break;
}
}
+ elseif ($permissions[$pCounter] == Auth_Controller::PERM_ANONYMOUS)
+ {
+ $checkPermissions = true;
+ break;
+ }
+ elseif ($permissions[$pCounter] == Auth_Controller::PERM_LOGGED)
+ {
+ $checkPermissions = isLogged();
+ break;
+ }
else
{
show_error('The given permission does not use the correct format');
@@ -195,6 +197,24 @@ class PermissionLib
return $checkPermissions;
}
+ /**
+ * Retrieves permission and required access type from the newly formatted permission string
+ *
+ * @param string $permission
+ *
+ * @return array
+ */
+ public function convertAccessType($permission)
+ {
+ list($permission, $reqAccessType) = explode(PermissionLib::PERMISSION_SEPARATOR, $permission);
+ $accessType = '';
+ if (strpos($reqAccessType, PermissionLib::READ_RIGHT) !== false)
+ $accessType = PermissionLib::SELECT_RIGHT;
+ if (strpos($reqAccessType, PermissionLib::WRITE_RIGHT) !== false)
+ $accessType = PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT;
+ return [$permission, $accessType];
+ }
+
/**
* Checks if at least one of the permissions given as parameter (requiredPermissions) belongs to the authenticated user
* It checks the given permissions against a given method (controller method name) and a given permission type (R and/or W)
diff --git a/application/libraries/PrestudentLib.php b/application/libraries/PrestudentLib.php
new file mode 100644
index 000000000..ef5e2e3a9
--- /dev/null
+++ b/application/libraries/PrestudentLib.php
@@ -0,0 +1,934 @@
+_ci =& get_instance();
+
+ // // Configs
+ // $this->_ci->load->config('studierendenantrag');
+
+ // // Models
+ $this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel');
+ $this->_ci->load->model('crm/Student_model', 'StudentModel');
+ $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
+ $this->_ci->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel');
+ $this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
+ $this->_ci->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel');
+ $this->_ci->load->model('person/Benutzer_model', 'BenutzerModel');
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ }
+
+ public function setAbbrecher(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $insertvon = null,
+ $statusgrund_id = null,
+ $datum = null,
+ $bestaetigtam = null,
+ $bestaetigtvon = null
+ ) {
+ if (!$insertvon)
+ $insertvon = getAuthUID();
+ if (!$bestaetigtvon)
+ $bestaetigtvon = $insertvon;
+
+ $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id, $studiensemester_kurzbz);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudent_in_sem', [
+ 'prestudent_id' => $prestudent_id,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ ]));
+
+ $prestudent_status = current($result);
+
+ $result = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
+
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id]));
+
+ $student = current($result);
+
+ if(!$datum)
+ $datum = date('c');
+
+ if(!$bestaetigtam)
+ $bestaetigtam = date('c');
+
+ // Status und Statusgrund updaten
+ $result = $this->_ci->PrestudentstatusModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_ABBRECHER,
+ 'studiensemester_kurzbz' => $prestudent_status->studiensemester_kurzbz,
+ 'ausbildungssemester' => $prestudent_status->ausbildungssemester,
+ 'datum' => $datum,
+ 'insertvon' => $insertvon,
+ 'insertamum' => date('c'),
+ 'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz,
+ 'studienplan_id'=> $prestudent_status->studienplan_id,
+ 'bestaetigtvon' => $bestaetigtvon,
+ 'bestaetigtam' => $bestaetigtam,
+ 'statusgrund_id' => $statusgrund_id
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ //Verband anlegen
+ $result = $this->_ci->LehrverbandModel->load([
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => 'A',
+ 'gruppe' => ''
+ ]);
+
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ {
+ $result = $this->_ci->LehrverbandModel->load([
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => '',
+ 'gruppe' => ''
+ ]);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+
+ if(!$result)
+ {
+ $this->_ci->LehrverbandModel->insert([
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => '',
+ 'gruppe' => '',
+ 'bezeichnung' => 'Ab-Unterbrecher',
+ 'aktiv' => true,
+ ]);
+ }
+
+ $this->_ci->LehrverbandModel->insert([
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => 'A',
+ 'gruppe' => '',
+ 'bezeichnung' => 'Abbrecher',
+ 'aktiv' => true
+ ]);
+ }
+
+ // noch nicht eingetragene Zeugnisnoten auf 9 setzen
+ $result = $this->_ci->ZeugnisnoteModel->getZeugnisnoten($student->student_uid, $prestudent_status->studiensemester_kurzbz);
+ if (isError($result))
+ return $result;
+ $result = getData($result) ?: [];
+
+ foreach ($result as $lv)
+ {
+ if (!$lv->note)
+ {
+ $result = $this->_ci->ZeugnisnoteModel->insert([
+ 'note' => 9,
+ 'studiensemester_kurzbz' => $lv->studiensemester_kurzbz,
+ 'student_uid' => $lv->uid,
+ 'lehrveranstaltung_id' => $lv->lehrveranstaltung_id
+ ]);
+ if (isError($result)) {
+ $result = $this->_ci->ZeugnisnoteModel->update([
+ 'studiensemester_kurzbz' => $lv->studiensemester_kurzbz,
+ 'student_uid' => $lv->uid,
+ 'lehrveranstaltung_id' => $lv->lehrveranstaltung_id
+ ], [
+ 'note' => 9
+ ]);
+
+ if (isError($result))
+ return $result;
+ }
+ }
+ }
+
+
+ // Update Aktionen
+
+ // StudentModel updaten
+ $this->_ci->StudentModel->update([
+ 'student_uid' => $student->student_uid
+ ], [
+ 'verband' => 'A',
+ 'gruppe' => '',
+ 'semester' => 0,
+ 'updatevon' => $insertvon,
+ 'updateamum' => date('c')
+ ]);
+
+ //Studentlehrverband setzen
+ $this->_ci->StudentlehrverbandModel->update([
+ 'studiensemester_kurzbz' => $prestudent_status->studiensemester_kurzbz,
+ 'student_uid' => $student->student_uid
+ ], [
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => 'A',
+ 'gruppe' => '',
+ 'updateamum' => date('c'),
+ 'updatevon' => $insertvon
+ ]);
+
+ // Benutzer inaktiv setzen
+ $this->_ci->BenutzerModel->update([
+ 'uid' => $student->student_uid
+ ], [
+ 'aktiv' => false,
+ 'updateaktivvon' => $insertvon,
+ 'updateaktivam' => date('c'),
+ 'updatevon' => $insertvon,
+ 'updateamum' => date('c')
+ ]);
+
+ return success();
+ }
+
+ public function setUnterbrecher(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $studierendenantrag_id = null,
+ $insertvon = null,
+ $ausbildungssemester = null,
+ $statusgrund_id = null
+ ) {
+ $ausbildungssemester_plus = 0;
+
+ if (!$insertvon)
+ $insertvon = getAuthUID();
+
+
+ $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id, $studiensemester_kurzbz);
+
+ if (isError($result))
+ return $result;
+
+ $result = getData($result);
+
+ if (!$result) { // NOTE(chris): no status in target stdsem
+ //NOTE(manu): only valid if nextSemester focus max
+
+ $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+
+ // check if ausbildungssemester is last
+ $this->_ci->StudiengangModel->addJoin('public.tbl_prestudent p', 'studiengang_kz');
+ $res = $this->_ci->StudiengangModel->loadWhere(['p.prestudent_id' => $prestudent_id]);
+ if(isError($res))
+ return $res;
+ if(!hasData($res))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_stg_for_prestudent', [
+ 'prestudent_id' => $prestudent_id
+ ]));
+
+ $studiengang = current(getData($res));
+ $prestudent_status = current($result);
+ if ($prestudent_status->status_kurzbz != Prestudentstatus_model::STATUS_UNTERBRECHER && $prestudent_status->ausbildungssemester + 1 < $studiengang->max_semester)
+ $ausbildungssemester_plus = 1;
+
+ if(!$result)
+ {
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudent_in_sem', [
+ 'prestudent_id' => $prestudent_id,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ ]));
+ }
+ } elseif (current($result)->status_kurzbz == Prestudentstatus_model::STATUS_UNTERBRECHER) {
+ if ($studierendenantrag_id)
+ {
+ $resultAntrag = $this->_ci->StudierendenantragModel->load($studierendenantrag_id);
+ if (isError($resultAntrag))
+ return $resultAntrag;
+ $resultAntrag = getData($resultAntrag);
+ if (!$resultAntrag)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id]));
+
+ $antrag = current($resultAntrag);
+ $anmerkung = current($result)->anmerkung . ' Wiedereinstieg ' . $antrag->datum_wiedereinstieg;
+
+ $result = $this->_ci->PrestudentstatusModel->update([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_UNTERBRECHER,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'ausbildungssemester' => current($result)->ausbildungssemester
+ ], [
+ 'updatevon' => $insertvon,
+ 'updateamum' => date('c'),
+ 'anmerkung'=> $anmerkung
+ ]);
+
+ if (isError($result))
+ return $result;
+ }
+
+ return success();
+ }
+
+ $prestudent_status = current($result);
+
+
+ $result = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
+
+ if (isError($result))
+ return $result;
+
+ $result = getData($result);
+
+ if (!$result)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id]));
+
+ $student = current($result);
+
+
+ if ($studierendenantrag_id)
+ {
+ $resultAntrag = $this->_ci->StudierendenantragModel->load($studierendenantrag_id);
+ if (isError($resultAntrag))
+ return $resultAntrag;
+ $resultAntrag = getData($resultAntrag);
+ if (!$resultAntrag)
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_antrag_found', ['id' => $studierendenantrag_id]));
+
+ $antrag = current($resultAntrag);
+ $anmerkung = 'Wiedereinstieg ' . $antrag->datum_wiedereinstieg;
+ }
+ else
+ $anmerkung = '';
+
+ if ($ausbildungssemester)
+ $semester = $ausbildungssemester;
+ else
+ $semester = $prestudent_status->ausbildungssemester + $ausbildungssemester_plus;
+
+ // Status updaten
+ $result = $this->_ci->PrestudentstatusModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_UNTERBRECHER,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'ausbildungssemester' => $semester,
+ 'datum' => date('c'),
+ 'insertvon' => $insertvon,
+ 'insertamum' => date('c'),
+ 'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz,
+ 'studienplan_id'=> $prestudent_status->studienplan_id,
+ 'bestaetigtvon' => $insertvon,
+ 'bestaetigtam' => date('c'),
+ 'anmerkung'=> $anmerkung,
+ 'statusgrund_id' => $statusgrund_id
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ //Verband anlegen
+ $result = $this->_ci->LehrverbandModel->load([
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => 'B',
+ 'gruppe' => ''
+ ]);
+
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+ if (!$result)
+ {
+ $result = $this->_ci->LehrverbandModel->load([
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => '',
+ 'gruppe' => ''
+ ]);
+ if (isError($result))
+ return $result;
+ $result = getData($result);
+
+ if(!$result)
+ {
+ $this->_ci->LehrverbandModel->insert([
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => '',
+ 'gruppe' => '',
+ 'bezeichnung' => 'Ab-Unterbrecher',
+ 'aktiv' => true,
+ ]);
+ }
+
+ $this->_ci->LehrverbandModel->insert([
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => 'B',
+ 'gruppe' => '',
+ 'bezeichnung' => 'Unterbrecher',
+ 'aktiv' => true
+ ]);
+ }
+
+ // noch nicht eingetragene Zeugnisnoten auf 9 setzen
+ $result = $this->_ci->ZeugnisnoteModel->getZeugnisnoten($student->student_uid, $studiensemester_kurzbz);
+ if (isError($result))
+ return $result;
+ $result = getData($result) ?: [];
+
+ foreach ($result as $lv)
+ {
+ if (!$lv->note)
+ {
+ $result = $this->_ci->ZeugnisnoteModel->insert([
+ 'note' => 9,
+ 'studiensemester_kurzbz' => $lv->studiensemester_kurzbz,
+ 'student_uid' => $lv->uid,
+ 'lehrveranstaltung_id' => $lv->lehrveranstaltung_id
+ ]);
+ if (isError($result)) {
+ $result = $this->_ci->ZeugnisnoteModel->update([
+ 'studiensemester_kurzbz' => $lv->studiensemester_kurzbz,
+ 'student_uid' => $lv->uid,
+ 'lehrveranstaltung_id' => $lv->lehrveranstaltung_id
+ ], [
+ 'note' => 9
+ ]);
+
+ if (isError($result))
+ return $result;
+ }
+ }
+ }
+
+ // Update Aktionen
+
+ // StudentModel updaten
+ $this->_ci->StudentModel->update([
+ 'student_uid' => $student->student_uid
+ ], [
+ 'verband' => 'B',
+ 'gruppe' => '',
+ 'semester' => 0,
+ 'updatevon' => $insertvon,
+ 'updateamum' => date('c')
+ ]);
+
+ //Studentlehrverband setzen
+ $result = $this->_ci->StudentlehrverbandModel->loadWhere([
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'student_uid' => $student->student_uid
+ ]);
+ if (hasData($result)) {
+ $this->_ci->StudentlehrverbandModel->update([
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'student_uid' => $student->student_uid
+ ], [
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => 'B',
+ 'gruppe' => '',
+ 'updateamum' => date('c'),
+ 'updatevon' => $insertvon
+ ]);
+ } else {
+ $this->_ci->StudentlehrverbandModel->insert([
+ 'student_uid' => $student->student_uid,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'studiengang_kz' => $student->studiengang_kz,
+ 'semester' => 0,
+ 'verband' => 'B',
+ 'gruppe' => '',
+ 'insertamum' => date('c'),
+ 'insertvon' => $insertvon
+ ]);
+ }
+
+ return success();
+ }
+
+ public function setStudent($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id)
+ {
+ $authUID = getAuthUID();
+ $now = date('c');
+
+
+ $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id);
+
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', [
+ 'prestudent_id' => $prestudent_id
+ ]));
+
+ $prestudent_status = current(getData($result));
+
+
+ $result = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
+
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id]));
+
+ $student = current(getData($result));
+
+
+ $this->_ci->load->library('VariableLib', ['uid' => $authUID]);
+ $semester_aktuell = $this->_ci->variablelib->getVar('semester_aktuell');
+
+
+ // Update Aktionen
+
+ // Status updaten
+ $result = $this->_ci->PrestudentstatusModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_STUDENT,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'statusgrund_id' => $statusgrund_id,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'datum' => $now,
+ 'insertvon' => $authUID,
+ 'insertamum' => $now,
+ 'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz,
+ 'studienplan_id'=> $prestudent_status->studienplan_id,
+ 'bestaetigtvon' => $authUID,
+ 'bestaetigtam' => $now
+ ]);
+
+ if (isError($result))
+ return $result;
+
+
+ // Student updaten
+ $result = $this->_ci->StudentModel->update([
+ 'student_uid' => $student->student_uid
+ ], [
+ 'semester' => $ausbildungssemester,
+ 'verband' => '',
+ 'gruppe' => '',
+ 'updatevon' => $authUID,
+ 'updateamum' => $now
+ ]);
+
+ if (isError($result))
+ return $result;
+
+
+ // Studentlehrverband updaten
+ $result = $this->_ci->StudentlehrverbandModel->update([
+ 'student_uid' => $student->student_uid,
+ 'studiensemester_kurzbz' => $semester_aktuell
+ ], [
+ 'semester' => $ausbildungssemester,
+ 'verband' => '',
+ 'gruppe' => '',
+ 'updatevon' => $authUID,
+ 'updateamum' => $now
+ ]);
+
+ if (isError($result))
+ return $result;
+
+
+ // Benutzer updaten
+ $result = $this->_ci->BenutzerModel->load([$student->student_uid]);
+
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('person', 'error_noBenutzer'));
+
+ $benutzer = current(getData($result));
+ $updateData = [
+ 'aktiv' => true,
+ 'updateamum' => $now,
+ 'updatevon' => $authUID
+ ];
+ if (!$benutzer->aktiv) {
+ $updateData['updateaktivam'] = $now;
+ $updateData['updateaktivvon'] = $authUID;
+ }
+
+
+ $this->_ci->BenutzerModel->update([$student->student_uid], $updateData);
+
+ return success();
+ }
+
+ public function setFirstStudent(
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $orgform_kurzbz,
+ $studienplan_id,
+ $statusgrund_id
+ ) {
+ $this->_ci->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
+ $this->_ci->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz');
+ $result = $this->_ci->PrestudentModel->load($prestudent_id);
+
+ if (isError($result))
+ return $result;
+
+ if (!hasData($result))
+ return error('No prestudent');
+
+ $student_data = current(getData($result));
+
+
+ $authUID = getAuthUID();
+ $now = date('c');
+ $today = date('Y-m-d');
+
+ $jahr = mb_substr($studiensemester_kurzbz, 4, 2);
+
+
+ // Genererate Personenkennzeichen
+ $personenkennzeichen = $this->_ci->StudentModel->generateMatrikelnummer2(
+ $student_data->studiengang_kz,
+ $studiensemester_kurzbz,
+ $student_data->typ
+ );
+ if (isError($personenkennzeichen))
+ return $personenkennzeichen;
+ $personenkennzeichen = getData($personenkennzeichen);
+
+
+ // Generate UID
+ $uid = $this->_ci->StudentModel->generateUID(
+ $student_data->kurzbz,
+ $jahr,
+ $student_data->typ,
+ $personenkennzeichen,
+ $student_data->vorname,
+ $student_data->nachname
+ );
+ if (isError($uid))
+ return $uid;
+ $uid = getData($uid);
+
+
+ // Generate Matrikelnummer
+ $matrikelnummer = $this->_ci->BenutzerModel->generateMatrikelnummer(
+ $student_data->oe_kurzbz
+ );
+ if (isError($matrikelnummer))
+ return $matrikelnummer;
+ $matrikelnummer = getData($matrikelnummer);
+
+
+ // Generate Alias
+ $alias = '';
+ if (!defined('GENERATE_ALIAS_STUDENT')
+ || GENERATE_ALIAS_STUDENT === true
+ ) {
+ $result = $this->_ci->BenutzerModel->generateAliasFromName($student_data->vorname, $student_data->nachname);
+ if (isError($result))
+ return $result;
+ $alias = getData($result);
+ }
+
+ // Generate Activation Key
+ $activationkey = $this->_ci->BenutzerModel->generateActivationkey();
+
+
+ // Overwrite stuff
+ if (defined('SET_UID_AS_MATRIKELNUMMER')
+ && SET_UID_AS_MATRIKELNUMMER)
+ $matrikelnummer = $uid;
+ if (defined('SET_UID_AS_PERSONENKENNZEICHEN')
+ && SET_UID_AS_PERSONENKENNZEICHEN)
+ $personenkennzeichen = $uid;
+
+
+ // Update Person
+ $this->_ci->load->model('person/Person_model', 'PersonModel');
+ $result = $this->_ci->PersonModel->update([
+ 'person_id' => $student_data->person_id,
+ 'matr_nr' => null
+ ], [
+ 'matr_nr' => $matrikelnummer
+ ]);
+
+ if (isError($result))
+ return $result;
+
+
+ // Add Benutzer
+ $result = $this->_ci->BenutzerModel->insert([
+ 'uid' => $uid,
+ 'person_id' => $student_data->person_id,
+ 'aktiv' => true,
+ 'aktivierungscode' => $activationkey,
+ 'alias' => $alias,
+ 'insertvon' => $authUID,
+ 'insertamum' => $now,
+ ]);
+
+ if (isError($result))
+ return $result;
+
+
+ // Add Student
+ $result = $this->_ci->StudentModel->insert([
+ 'student_uid' => $uid,
+ 'matrikelnr' => $personenkennzeichen,
+ 'prestudent_id' => $prestudent_id,
+ 'studiengang_kz' => $student_data->studiengang_kz,
+ 'semester' => $ausbildungssemester,
+ 'verband' => ' ',
+ 'gruppe' => ' ',
+ 'insertvon' => $authUID,
+ 'insertamum' => $now
+ ]);
+
+ if (isError($result))
+ return $result;
+
+
+ // Add Lehrverband if it does not exist
+ $result = $this->_ci->LehrverbandModel->load([' ', ' ', $ausbildungssemester, $student_data->studiengang_kz]);
+
+ if (isError($result))
+ return $result;
+
+ if (!hasData($result)) {
+ $result = $this->_ci->LehrverbandModel->insert([
+ 'studiengang_kz' => $student_data->studiengang_kz,
+ 'semester' => $ausbildungssemester,
+ 'verband' => ' ',
+ 'gruppe' => ' ',
+ 'aktiv' => true
+ ]);
+
+ if (isError($result))
+ return $result;
+ }
+
+
+ // Add Rolle
+ $result = $this->_ci->PrestudentstatusModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_STUDENT,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'orgform_kurzbz'=> $orgform_kurzbz,
+ 'studienplan_id'=> $studienplan_id,
+ 'datum' => $today,
+ 'insertamum' => $now,
+ 'insertvon' => $authUID,
+ 'bestaetigtam' => $today,
+ 'bestaetigtvon' => $authUID,
+ 'statusgrund_id' => $statusgrund_id
+ ]);
+
+ if (isError($result))
+ return $result;
+
+
+ // Add Studentlehrverband
+ $result = $this->_ci->StudentlehrverbandModel->insert([
+ 'student_uid' => $uid,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'studiengang_kz' => $student_data->studiengang_kz,
+ 'semester' => $ausbildungssemester,
+ 'verband' => ' ',
+ 'gruppe' => ' ',
+ 'insertamum' => $now,
+ 'insertvon' => $authUID
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ return success();
+ }
+
+ public function setDiplomand($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id)
+ {
+ return $this->setBasic(
+ getAuthUID(),
+ date('c'),
+ Prestudentstatus_model::STATUS_DIPLOMAND,
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ }
+
+ public function setAbsolvent($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id)
+ {
+ $authUID = getAuthUID();
+ $now = date('c');
+
+
+ $result = $this->setBasic(
+ $authUID,
+ $now,
+ Prestudentstatus_model::STATUS_ABSOLVENT,
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+
+ if (isError($result))
+ return $result;
+
+
+ // Load Student
+ $result = $this->_ci->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]);
+
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_student_for_prestudent', ['prestudent_id' => $prestudent_id]));
+
+ $student = current(getData($result));
+
+
+ // Benutzer inaktiv setzen
+ $this->_ci->BenutzerModel->update([
+ 'uid' => $student->student_uid
+ ], [
+ 'aktiv' => false,
+ 'updateaktivvon' => $authUID,
+ 'updateaktivam' => $now,
+ 'updatevon' => $authUID,
+ 'updateamum' => $now
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ return success();
+ }
+
+ public function setBewerber($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id)
+ {
+ $result = $this->setBasic(
+ getAuthUID(),
+ date('c'),
+ Prestudentstatus_model::STATUS_BEWERBER,
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+
+ if (isError($result))
+ return $result;
+
+ if (SEND_BEWERBER_INFOMAIL) {
+ // TODO(chris): IMPLEMENT!
+ }
+
+ return success();
+ }
+
+ public function setAufgenommener($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id)
+ {
+ return $this->setBasic(
+ getAuthUID(),
+ date('c'),
+ Prestudentstatus_model::STATUS_AUFGENOMMENER,
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ }
+
+ public function setAbgewiesener($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id)
+ {
+ return $this->setBasic(
+ getAuthUID(),
+ date('c'),
+ Prestudentstatus_model::STATUS_ABGEWIESENER,
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ }
+
+ public function setWartender($prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id)
+ {
+ return $this->setBasic(
+ getAuthUID(),
+ date('c'),
+ Prestudentstatus_model::STATUS_WARTENDER,
+ $prestudent_id,
+ $studiensemester_kurzbz,
+ $ausbildungssemester,
+ $statusgrund_id
+ );
+ }
+
+ protected function setBasic($authUID, $now, $status_kurzbz, $prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id = null)
+ {
+ $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id);
+
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_prestudentstatus', [
+ 'prestudent_id' => $prestudent_id
+ ]));
+
+ $prestudent_status = current(getData($result));
+
+
+ // Update Aktionen
+
+ // Status updaten
+ $result = $this->_ci->PrestudentstatusModel->insert([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => $status_kurzbz,
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'datum' => $now,
+ 'insertvon' => $authUID,
+ 'insertamum' => $now,
+ 'orgform_kurzbz'=> $prestudent_status->orgform_kurzbz,
+ 'studienplan_id'=> $prestudent_status->studienplan_id,
+ 'bestaetigtvon' => $authUID,
+ 'bestaetigtam' => $now,
+ 'statusgrund_id' => $statusgrund_id
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ return success();
+ }
+}
diff --git a/application/libraries/PrestudentstatusCheckLib.php b/application/libraries/PrestudentstatusCheckLib.php
new file mode 100644
index 000000000..5e3d8a307
--- /dev/null
+++ b/application/libraries/PrestudentstatusCheckLib.php
@@ -0,0 +1,922 @@
+_ci =& get_instance();
+
+ $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+ $this->_ci->load->model('person/Person_model', 'PersonModel');
+ $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
+ $this->_ci->load->model('crm/Prestudent_model', 'PrestudentModel');
+ $this->_ci->load->model('crm/Student_model', 'StudentModel');
+ $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel');
+ $this->_ci->load->model('codex/Bismeldestichtag_model', 'BismeldestichtagModel');
+ }
+
+ /**
+ * Checks if a status add is valid.
+ * @return object error if invalid
+ */
+ public function checkStatusAdd(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_status_studiensemester_kurzbz,
+ $new_status_datum,
+ $new_status_ausbildungssemester,
+ $new_studienplan_id
+ ) {
+ $studentName = '';
+
+ $nameRes = $this->_ci->PersonModel->loadPrestudent($prestudent_id);
+
+ if (hasData($nameRes))
+ {
+ $nameData = getData($nameRes)[0];
+ $studentName = $nameData->vorname.' '.$nameData->nachname;
+ }
+
+ // Datum des neuen Status darf nicht in Vergangenheit liegen, sonst Probleme wenn neues Datum < Bismeldedatum
+ if (new DateTime($new_status_datum) < new DateTime('today'))
+ return error($studentName . $this->_ci->p->t('lehre', 'error_entryInPast'));
+
+ return $this->_checkIfValidStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_status_studiensemester_kurzbz,
+ $new_status_datum,
+ $new_status_ausbildungssemester,
+ $new_studienplan_id
+ );
+ }
+
+ /**
+ * Checks if a status update is valid.
+ * @return error if invalid
+ */
+ public function checkStatusUpdate(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_status_studiensemester_kurzbz,
+ $new_status_datum,
+ $new_status_ausbildungssemester,
+ $new_studienplan_id,
+ $old_status_studiensemester,
+ $old_status_ausbildungssemester
+ ) {
+
+ return $this->_checkIfValidStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_status_studiensemester_kurzbz,
+ $new_status_datum,
+ $new_status_ausbildungssemester,
+ $new_studienplan_id,
+ $old_status_studiensemester,
+ $old_status_ausbildungssemester
+ );
+ }
+
+ /**
+ * Checks if a student already exists.
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function checkIfExistingStudent($prestudent_id)
+ {
+ $result = $this->_ci->StudentModel->loadWhere([
+ 'prestudent_id' => $prestudent_id
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ return success(hasData($result));
+ }
+
+ /**
+ * Check if Reihungstest was admitted
+ *
+ * @param stdClass $prestudent
+ *
+ * @return stdClass
+ */
+ public function checkIfAngetreten($prestudent)
+ {
+ return success($prestudent->reihungstestangetreten);
+ }
+
+ /**
+ * Check if ZGV-Code is registered
+ *
+ * @param stdClass $prestudent
+ *
+ * @return stdClass
+ */
+ public function checkIfZGVEingetragen($prestudent_person)
+ {
+ return success((boolean)$prestudent_person->zgv_code);
+ }
+
+ /**
+ * Check if Master ZGV-Code is registered
+ *
+ * @param stdClass $prestudent
+ *
+ * @return booleans $zgv_code, error if not registered
+ */
+ public function checkIfZGVEingetragenMaster($prestudent)
+ {
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $result = $this->_ci->StudiengangModel->load($prestudent->studiengang_kz);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return error($this->_ci->p->t('studierendenantrag', 'error_no_stg', ['studiengang_kz' => $prestudent->studiengang_kz]));
+
+ if (current($result->retval)->typ != 'm')
+ return success(true); // NOTE(chris): we only test master stgs, all other stgs should default to true
+
+ return success((boolean)$prestudent->zgvmas_code);
+ }
+
+ /**
+ * Checks if a bewerber status already exists.
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function checkIfExistingBewerberstatus($prestudent_id)
+ {
+ $result = $this->_ci->PrestudentstatusModel->loadWhere([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_BEWERBER
+ ]);
+ if (isError($result))
+ return $result;
+
+ return success(hasData($result));
+ }
+
+
+ /**
+ * Checks if status aufgenommen already exists.
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function checkIfExistingAufgenommenerstatus($prestudent_id)
+ {
+ $result = $this->_ci->PrestudentstatusModel->loadWhere([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_AUFGENOMMENER
+ ]);
+ if (isError($result))
+ return $result;
+
+ return success(hasData($result));
+ }
+
+ /**
+ * Checks if the last Bewerber status and the last Aufgenommener status
+ * have the same studiensemester and ausbildungssemester.
+ *
+ * Attention:
+ * If one of those two status is missing the function returns true!
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function checkIfLastBewerberAndAufgenommenerShareSemesters($prestudent_id)
+ {
+ $this->_ci->PrestudentstatusModel->addOrder('datum', 'DESC');
+ $this->_ci->PrestudentstatusModel->addOrder('insertamum', 'DESC');
+ $this->_ci->PrestudentstatusModel->addLimit(1);
+ $result = $this->_ci->PrestudentstatusModel->loadWhere([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_BEWERBER
+ ]);
+
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(true);
+
+ $bewerber = current(getData($result));
+
+ $this->_ci->PrestudentstatusModel->addOrder('datum', 'DESC');
+ $this->_ci->PrestudentstatusModel->addOrder('insertamum', 'DESC');
+ $this->_ci->PrestudentstatusModel->addLimit(1);
+ $result = $this->_ci->PrestudentstatusModel->loadWhere([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => Prestudentstatus_model::STATUS_AUFGENOMMENER
+ ]);
+
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(true);
+
+ $aufgenommener = current(getData($result));
+
+ return success(
+ $bewerber->studiensemester_kurzbz == $aufgenommener->studiensemester_kurzbz
+ && $bewerber->ausbildungssemester == $aufgenommener->ausbildungssemester
+ );
+ }
+
+ /**
+ * Check if Bismeldestichtag erreicht
+ *
+ * @param DateTime $statusDatum
+ * @param string $studiensemester_kurzbz
+ *
+ * @return stdClass
+ */
+ public function checkIfMeldestichtagErreicht($statusDatum, $studiensemester_kurzbz = null)
+ {
+ $result = $this->_ci->BismeldestichtagModel->checkIfMeldestichtagErreicht($statusDatum, $studiensemester_kurzbz);
+
+ if (isError($result))
+ return $result;
+
+ return success(getData($result) == "1");
+ }
+
+ /**
+ * Runs all checks on Status History and saves it in cache.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param DateTime $new_date
+ * @param string $new_studiensemester_kurzbz
+ * @param integer $new_ausbildungssemester
+ * @param string $old_studiensemester_kurzbz
+ * @param integer $old_ausbildungssemester
+ *
+ * @return stdClass
+ */
+ protected function prepareStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ) {
+ // Generate key for caching
+ $primary = implode('|', [
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date->format('Y-m-d'),
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ]);
+
+ if (isset($this->_cache_history[$primary]))
+ return $this->_cache_history[$primary];
+
+ $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
+
+ // Get the history
+ $result = $this->_ci->PrestudentstatusModel->getHistoryWithNewOrEditedState(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ );
+
+ if (isError($result))
+ return $result;
+
+ if (!hasData($result))
+ return error('This is impossible');
+
+ $history = getData($result);
+ $historyCount = count($history);
+
+ // Run checks
+ $checks = [
+ 'timesequence' => true,
+ 'laststatus' => true,
+ 'unterbrechersemester' => true,
+ 'abbrechersemester' => true,
+ 'diplomant' => true,
+ 'student' => true
+ ];
+
+ for ($n = 0, $c = 1; $c < $historyCount; $n++, $c++) {
+ if (!$checks['timesequence']
+ && !$checks['laststatus']
+ && !$checks['unterbrechersemester']
+ && !$checks['abbrechersemester']
+ && !$checks['diplomant']
+ && !$checks['student']
+ )
+ break; // early out
+
+ $next = $history[$n];
+ $current = $history[$c];
+
+ // Zeitabfolge ungültig?
+ if ($checks['timesequence']
+ && $next->start < $current->start
+ )
+ $checks['timesequence'] = false;
+
+ // Abbrecher- oder Absolventenstatus muss Endstatus sein
+ if ($checks['laststatus']
+ && in_array($current->status_kurzbz, [self::ABSOLVENT_STATUS, self::ABBRECHER_STATUS])
+ )
+ $checks['laststatus'] = false;
+
+ // wenn Unterbrecher auf Unterbrecher folgt, muss Ausbildungssemester gleich sein
+ if ($checks['unterbrechersemester']
+ && $current->status_kurzbz == self::UNTERBRECHER_STATUS
+ && $next->status_kurzbz == self::UNTERBRECHER_STATUS
+ && $current->ausbildungssemester != $next->ausbildungssemester
+ )
+ $checks['unterbrechersemester'] = false;
+
+ // wenn Abbrecher auf Unterbrecher folgt, muss Ausbildungssemester gleich sein
+ if ($checks['abbrechersemester']
+ && $current->status_kurzbz == self::UNTERBRECHER_STATUS
+ && $next->status_kurzbz == self::ABBRECHER_STATUS
+ && $current->ausbildungssemester != $next->ausbildungssemester
+ )
+ $checks['abbrechersemester'] = false;
+
+ if (($checks['diplomant']
+ || $checks['student'])
+ && $next->status_kurzbz == self::STUDENT_STATUS
+ ) {
+ $restl_stati = array_unique(array_column(array_slice($history, $c), 'status_kurzbz'));
+
+ // keine Studenten nach Diplomand Status
+ if ($checks['diplomant']
+ && in_array(self::DIPLOMAND_STATUS, $restl_stati)
+ )
+ $checks['diplomant'] = false;
+
+ // vor Studentenstatus müssen bestimmte Status vorhanden sein
+ if ($checks['student']
+ && array_values(array_intersect($restl_stati, $this->_statusAbfolgeVorStudent)) != array_values($this->_statusAbfolgeVorStudent)
+ )
+ $checks['student'] = false;
+ }
+ }
+
+ $this->_cache_history[$primary] = success($checks);
+
+ return success($checks);
+ }
+
+ /**
+ * Checks if the time sequence of the status history is valid.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param DateTime $new_date
+ * @param string $new_studiensemester_kurzbz
+ * @param integer $new_ausbildungssemester
+ * @param string $old_studiensemester_kurzbz
+ * @param integer $old_ausbildungssemester
+ *
+ * @return stdClass
+ */
+ public function checkStatusHistoryTimesequence(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ) {
+ $result = $this->prepareStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ );
+
+ if (isError($result))
+ return $result;
+
+ return success(getData($result)['timesequence']);
+ }
+
+ /**
+ * Checks if the last status of the status history is not Abbrecher or
+ * Absolvent.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param DateTime $new_date
+ * @param string $new_studiensemester_kurzbz
+ * @param integer $new_ausbildungssemester
+ * @param string $old_studiensemester_kurzbz
+ * @param integer $old_ausbildungssemester
+ *
+ * @return stdClass
+ */
+ public function checkStatusHistoryLaststatus(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ) {
+ $result = $this->prepareStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ );
+
+ if (isError($result))
+ return $result;
+
+ return success(getData($result)['laststatus']);
+ }
+
+ /**
+ * Checks if two consecutively Unterbrecher have the same
+ * ausbildungssemester in the status history.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param DateTime $new_date
+ * @param string $new_studiensemester_kurzbz
+ * @param integer $new_ausbildungssemester
+ * @param string $old_studiensemester_kurzbz
+ * @param integer $old_ausbildungssemester
+ *
+ * @return stdClass
+ */
+ public function checkStatusHistoryUnterbrechersemester(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ) {
+ $result = $this->prepareStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ );
+
+ if (isError($result))
+ return $result;
+
+ return success(getData($result)['unterbrechersemester']);
+ }
+
+ /**
+ * Checks if an Unterbrecher followed by an Abbrecher have the same
+ * ausbildungssemester in the status history.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param DateTime $new_date
+ * @param string $new_studiensemester_kurzbz
+ * @param integer $new_ausbildungssemester
+ * @param string $old_studiensemester_kurzbz
+ * @param integer $old_ausbildungssemester
+ *
+ * @return stdClass
+ */
+ public function checkStatusHistoryAbbrechersemester(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ) {
+ $result = $this->prepareStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ );
+
+ if (isError($result))
+ return $result;
+
+ return success(getData($result)['abbrechersemester']);
+ }
+
+ /**
+ * Checks if no Diplomant is followed by a Student in the status history.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param DateTime $new_date
+ * @param string $new_studiensemester_kurzbz
+ * @param integer $new_ausbildungssemester
+ * @param string $old_studiensemester_kurzbz
+ * @param integer $old_ausbildungssemester
+ *
+ * @return stdClass
+ */
+ public function checkStatusHistoryDiplomant(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ) {
+ $result = $this->prepareStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ );
+
+ if (isError($result))
+ return $result;
+
+ return success(getData($result)['diplomant']);
+ }
+
+ /**
+ * Checks if a Student precedes given stati in the status history.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param DateTime $new_date
+ * @param string $new_studiensemester_kurzbz
+ * @param integer $new_ausbildungssemester
+ * @param string $old_studiensemester_kurzbz
+ * @param integer $old_ausbildungssemester
+ *
+ * @return stdClass
+ */
+ public function checkStatusHistoryStudent(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ) {
+ // TODO(chris): TEST
+ $result = $this->prepareStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ );
+
+ if (isError($result))
+ return $result;
+
+ return success(getData($result)['student']);
+ }
+
+ /**
+ * Checks if Personenkennzeichen is set correctly.
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function checkPersonenkennzeichen($prestudent_id)
+ {
+ // TODO(chris): TEST
+ $this->_ci->PrestudentstatusModel->addSelect('tbl_prestudentstatus.prestudent_id');
+ $this->_ci->PrestudentstatusModel->addSelect('tbl_student.matrikelnr');
+
+ $this->_ci->PrestudentstatusModel->addJoin('public.tbl_student', 'prestudent_id');
+
+ $this->_ci->PrestudentstatusModel->addOrder('tbl_prestudentstatus.datum', 'DESC');
+ $this->_ci->PrestudentstatusModel->addOrder('tbl_prestudentstatus.insertamum', 'DESC');
+ $this->_ci->PrestudentstatusModel->addOrder('tbl_prestudentstatus.ext_id', 'DESC');
+
+ $this->_ci->PrestudentstatusModel->addLimit(1);
+
+ $result = $this->_ci->PrestudentstatusModel->loadWhere([
+ 'tbl_prestudentstatus.prestudent_id' => $prestudent_id,
+ 'tbl_prestudentstatus.status_kurzbz' => self::STATUS_STUDENT
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ if (!hasData($result))
+ return success(true); // Not a student yet so no wrong personenkennzeichen
+
+ $data = current(getData($result));
+
+ $jahr = $this->_ci->StudiensemesterModel->getStudienjahrNumberFromStudiensemester($data->studiensemester_kurzbz);
+
+
+ return success($jahr == mb_substr($data->matrikelnr, 0, 2));
+ }
+
+ /**
+ * Checks if Orgform of Student status and Bewerber status match.
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function checkStudentOrgform($prestudent_id)
+ {
+ // TODO(chris): TEST
+ $result = $this->_ci->PrestudentstatusModel->getBewerberWhereOrgformNotStudent($prestudent_id);
+
+ if (isError($result))
+ return $result;
+
+ return success(!hasData($result));
+ }
+
+ /**
+ * Check if History of StatusData is valid
+ * @param integer $prestudent_id
+ * @return error if not valid, array StatusArr if valid
+ */
+ private function _checkIfValidStatusHistory(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_status_studiensemester_kurzbz,
+ $new_status_datum,
+ $new_status_ausbildungssemester,
+ $new_studienplan_id,
+ $old_status_studiensemester = null,
+ $old_status_ausbildungssemester = null
+ ) {
+ //get start studiensemester
+ $semResult = $this->_ci->StudiensemesterModel->load([
+ 'studiensemester_kurzbz' => $new_status_studiensemester_kurzbz
+ ]);
+
+ if (isError($semResult))
+ {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ return $this->outputJson(getError($semResult));
+ }
+
+ if (!hasData($semResult)) {
+ return error($this->_ci->p->t('lehre', 'error_noStudiensemester') . $new_status_studiensemester_kurzbz);
+ }
+
+ $studiensemester = getData($semResult)[0];
+ $new_status_semesterstart = $studiensemester->start;
+
+ // get studienplan orgform
+ $new_studienplan_orgform_kurzbz = '';
+ $this->_ci->StudienplanModel->addSelect('orgform_kurzbz');
+ $stplResult = $this->_ci->StudienplanModel->load([
+ 'studienplan_id' => $new_studienplan_id
+ ]);
+
+ if (isError($stplResult))
+ {
+ $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
+ return $this->outputJson(getError($stplResult));
+ }
+
+ if (hasData($stplResult)) $new_studienplan_orgform_kurzbz = getData($stplResult)[0]->orgform_kurzbz;
+
+
+ //get all prestudentstati
+ $resultPs = $this->_ci->PrestudentstatusModel->getAllPrestudentstatiWithStudiensemester($prestudent_id);
+
+ if (isError($resultPs)) return $resultPs;
+
+ $resultArr = hasData($resultPs) ? getData($resultPs) : [];
+ $statusArr = [];
+
+ $newStatusInserted = false;
+ $new_status_datum_form = new DateTime($new_status_datum);
+ $new_status_semesterstart_form = new DateTime($new_status_semesterstart);
+
+ if (!isEmptyArray($resultArr))
+ {
+ // neuen Status zum Hinzufügen
+ $first_status = $resultArr[0];
+ $neuer_status = new stdClass();
+ $neuer_status->status_kurzbz = $status_kurzbz;
+ $neuer_status->studiensemester_kurzbz = $new_status_studiensemester_kurzbz;
+ $neuer_status->datum = $new_status_datum;
+ $neuer_status->ausbildungssemester = $new_status_ausbildungssemester;
+ $neuer_status->studienplan_orgform_kurzbz = $new_studienplan_orgform_kurzbz;
+ $neuer_status->matrikelnr = $first_status->matrikelnr;
+ $neuer_status->vorname = $first_status->vorname;
+ $neuer_status->nachname = $first_status->nachname;
+
+ // Status, welcher gerade geändert wird, holen
+ $status_to_change = array_filter(
+ $resultArr,
+ function ($status) use ($status_kurzbz, $old_status_studiensemester, $old_status_ausbildungssemester) {
+ return
+ $status->status_kurzbz == $status_kurzbz
+ && $status->studiensemester_kurzbz == $old_status_studiensemester
+ && $status->ausbildungssemester == $old_status_ausbildungssemester;
+ }
+ );
+
+ if (!isEmptyArray($status_to_change))
+ {
+ $status_to_change_index = key($status_to_change);
+
+ // wenn sich Studiensemester und Ausbildungssemester nicht geändert haben...
+ if ($new_status_studiensemester_kurzbz == $old_status_studiensemester
+ && $new_status_ausbildungssemester == $old_status_ausbildungssemester)
+ {
+ // ...neuen status an selber stelle einfügen wie zu ändernder Status
+ $resultArr[$status_to_change_index] = (object)array_merge((array)$resultArr[$status_to_change_index], (array)$neuer_status);
+ $newStatusInserted = true;
+ }
+ else
+ {
+ // bei Status mit neuem Semester: alten Status entfernen
+ unset($resultArr[$status_to_change_index]);
+ }
+ }
+ }
+
+ foreach ($resultArr as $row)
+ {
+ $studiensemester_start = new DateTime($row->studiensemester_start);
+ $status_datum = new DateTime($row->datum);
+
+ if ($new_status_datum_form >= $status_datum && $new_status_semesterstart_form >= $studiensemester_start)
+ {
+ if (!$newStatusInserted)
+ {
+ // neuer Status erstmals größer als Datum eines bestehenden Status -> neuen Status EINMALIG einfügen für spätere Statusprüfung
+ $statusArr[] = $neuer_status;
+ $newStatusInserted = true;
+ }
+ $statusArr[] = $row;
+ }
+ elseif ($new_status_datum_form <= $status_datum && $new_status_semesterstart_form <= $studiensemester_start)
+ {
+ $statusArr[] = $row;
+ }
+ else
+ {
+ // Zeitabfolge ungültig, Fehler
+ return error($this->_ci->p->t('lehre', 'error_statuseintrag_zeitabfolge'));
+ }
+ }
+
+ // erster Studentstatus
+ $ersterStudent = null;
+
+ // Über alle gespeicherten Status gehen und Statusabfolge prüfen
+ for ($i = 0; $i < count($statusArr); $i++)
+ {
+ $curr_status = $statusArr[$i];
+ $curr_status_kurzbz = $curr_status->status_kurzbz;
+ $curr_status_ausbildungssemester = $curr_status->ausbildungssemester;
+ $next_idx = $i - 1; //absteigend sortiert, nächster Status ist vorheriger Eintrag
+ $next_status = isset($statusArr[$next_idx]) ? $statusArr[$next_idx] : null;
+
+ $studentName = $curr_status->vorname . ' ' . $curr_status->nachname;
+
+ if ($curr_status_kurzbz == self::STUDENT_STATUS) $ersterStudent = $curr_status;
+
+ // Abbrecher- oder Absolventenstatus muss Endstatus sein
+ if (isset($next_status) && in_array($curr_status_kurzbz, $this->_endStatusArr))
+ {
+ return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_endstatus'));
+ }
+
+ // wenn Unterbrecher auf Unterbrecher folgt, muss Ausbildungssemester gleich sein
+ if
+ ($curr_status_kurzbz == self::UNTERBRECHER_STATUS && isset($next_status) && $next_status->status_kurzbz == self::UNTERBRECHER_STATUS
+ && $curr_status_ausbildungssemester != $next_status->ausbildungssemester)
+ {
+ return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_consecutiveUnterbrecher'));
+ }
+
+ // wenn Abbrecher auf Unterbrecher folgt, muss Ausbildungssemester gleich sein
+ if (isset($next_status)
+ && $curr_status_kurzbz == self::UNTERBRECHER_STATUS
+ && $next_status->status_kurzbz == self::ABBRECHER_STATUS && $curr_status_ausbildungssemester != $next_status->ausbildungssemester)
+ {
+ return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_consecutiveUnterbrecherAbbrecher'));
+ }
+
+ if (isset($next_status) && $next_status->status_kurzbz == self::STUDENT_STATUS)
+ {
+ $restliche_status_obj = array_slice($statusArr, $i);
+ $restliche_status = array_unique(array_column($restliche_status_obj, 'status_kurzbz'));
+ $status_intersected = array_intersect($restliche_status, $this->_statusAbfolgeVorStudent);
+
+ // Vor Studentstatus darf kein Diplomand Status vorhanden sein
+ if (in_array(self::DIPLOMAND_STATUS, $restliche_status))
+ {
+ return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_consecutiveDiplomandStudent'));
+ }
+
+ // Vor Studentstatus müssen bestimmte Status vorhanden sein
+ if (array_values($status_intersected) != array_values(array_reverse($this->_statusAbfolgeVorStudent)))
+ {
+ return error(
+ $studentName . ' '
+ . $this->_ci->p->t('lehre', 'error_wrongStatusOrderBeforeStudent', array(implode(', ', $this->_statusAbfolgeVorStudent)))
+ );
+ }
+ }
+ }
+
+ if (isset($ersterStudent))
+ {
+ $studentName = $ersterStudent->vorname . ' ' . $ersterStudent->nachname;
+
+ // wenn erster Studentstatus, checken ob Personenkennzeichen passt
+ $studienjahrNumber = $this->_ci->StudiensemesterModel->getStudienjahrNumberFromStudiensemester($ersterStudent->studiensemester_kurzbz);
+
+ if ($studienjahrNumber != mb_substr($ersterStudent->matrikelnr, 0, 2))
+ {
+ return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_personenkennzeichenPasstNichtZuStudiensemester'));
+ }
+
+ // wenn erster Studentstatus, checken ob Orgform des Bewerbers mit Studenten übereinstimmt
+ if (!isEmptyArray(
+ array_filter(
+ $restliche_status_obj,
+ function ($s) use ($ersterStudent) {
+ return
+ $s->status_kurzbz == self::BEWERBER_STATUS
+ && (
+ $s->studienplan_orgform_kurzbz != $ersterStudent->studienplan_orgform_kurzbz
+ );
+ }
+ )
+ )
+ )
+ {
+ return error($studentName . ' ' . $this->_ci->p->t('lehre', 'error_bewerberOrgformUngleichStudentOrgform'));
+ }
+ }
+
+ return $resultPs;
+ }
+}
diff --git a/application/libraries/SearchBarLib.php b/application/libraries/SearchBarLib.php
index 3a9d06d13..b725f6e90 100644
--- a/application/libraries/SearchBarLib.php
+++ b/application/libraries/SearchBarLib.php
@@ -30,9 +30,10 @@ class SearchBarLib
const ERROR_WRONG_SEARCHSTR = 'ERR002';
const ERROR_NO_TYPES = 'ERR003';
const ERROR_WRONG_TYPES = 'ERR004';
+ const ERROR_NOT_AUTH = 'ERR005';
// List of allowed types of search
- const ALLOWED_TYPES = ['mitarbeiter', 'organisationunit', 'raum', 'person', 'student', 'prestudent', 'document', 'cms'];
+ const ALLOWED_TYPES = ['mitarbeiter', 'mitarbeiter_ohne_zuordnung', 'organisationunit', 'raum', 'person', 'student', 'prestudent', 'document', 'cms'];
const PHOTO_IMG_URL = '/cis/public/bild.php?src=person&person_id=';
@@ -108,6 +109,92 @@ class SearchBarLib
return $result;
}
+ private function _mitarbeiter_ohne_zuordnung($searchstr, $type)
+ {
+ $dbModel = new DB_Model();
+
+ $sql = '
+ SELECT
+ \''.$type.'\' AS type,
+ b.uid AS uid,
+ p.person_id AS person_id,
+ p.vorname || \' \' || p.nachname AS name,
+ ARRAY_AGG(DISTINCT(org.bezeichnung)) AS organisationunit_name,
+ COALESCE(b.alias, b.uid) || \''.'@'.DOMAIN.'\' AS email,
+ TRIM(COALESCE(k.kontakt, \'\') || \' \' || COALESCE(m.telefonklappe, \'\')) AS phone,
+ \''.base_url(self::PHOTO_IMG_URL).'\' || p.person_id AS photo_url,
+ ARRAY_AGG(DISTINCT(stdkst.bezeichnung)) AS standardkostenstelle
+ FROM public.tbl_mitarbeiter m
+ JOIN public.tbl_benutzer b ON(b.uid = m.mitarbeiter_uid)
+ LEFT JOIN (
+ SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid
+ FROM public.tbl_benutzerfunktion bf
+ JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
+ JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
+ WHERE bf.funktion_kurzbz = \'kstzuordnung\'
+ AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
+ AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
+ GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid
+ ) stdkst ON stdkst.uid = b.uid
+ JOIN public.tbl_person p USING(person_id)
+ LEFT JOIN (
+ SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid
+ FROM public.tbl_benutzerfunktion bf
+ JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
+ JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
+ WHERE bf.funktion_kurzbz = \'oezuordnung\'
+ AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
+ AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
+ GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid
+ ) org ON org.uid = b.uid
+ LEFT JOIN (
+ SELECT kontakt, standort_id
+ FROM public.tbl_kontakt
+ WHERE kontakttyp = \'telefon\'
+ ) k ON(k.standort_id = m.standort_id)
+ WHERE
+ (stdkst.bezeichnung IS NULL
+ OR org.bezeichnung IS NULL)
+ AND (
+ ' .
+ $this->buildSearchClause(
+ $dbModel,
+ array('b.uid', 'p.vorname', 'p.nachname'),
+ $searchstr
+ ) .
+ '
+ )
+ GROUP BY type, b.uid, p.person_id, name, email, m.telefonklappe, phone
+ ';
+
+ $employees = $dbModel->execReadOnlyQuery($sql);
+
+ // If something has been found then return it
+ if (hasData($employees)) return getData($employees);
+
+ // Otherwise return an empty array
+ return array();
+ }
+
+ protected function buildSearchClause(DB_Model $dbModel, array $columns, $searchstr)
+ {
+ $document = implode(' || \' \' || ', $columns);
+ $query = '\'' . implode(':* & ', explode(' ', trim($searchstr))) . ':*\'';
+ $reversequery = '\'*:' . implode(' & *:', explode(' ', trim($searchstr))) . '\'';
+ $nospacequery = '\'' . implode('', explode(' ', trim($searchstr))) . ':*\'';
+
+ $searchclause = <<= NOW())
- GROUP BY o.bezeichnung, bf.uid
+ GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid
) stdkst ON stdkst.uid = b.uid
JOIN public.tbl_person p USING(person_id)
JOIN (
- SELECT o.bezeichnung, bf.uid
+ SELECT \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS bezeichnung, bf.uid
FROM public.tbl_benutzerfunktion bf
JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
+ JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
WHERE bf.funktion_kurzbz = \'oezuordnung\'
AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
- GROUP BY o.bezeichnung, bf.uid
+ GROUP BY o.bezeichnung, ot.bezeichnung, bf.uid
) org ON org.uid = b.uid
LEFT JOIN (
SELECT kontakt, standort_id
FROM public.tbl_kontakt
WHERE kontakttyp = \'telefon\'
) k ON(k.standort_id = m.standort_id)
- WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
- OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
- OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
- OR org.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
- OR stdkst.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
+ WHERE ' .
+ $this->buildSearchClause(
+ $dbModel,
+ array('b.uid', 'p.vorname', 'p.nachname', 'org.bezeichnung', 'stdkst.bezeichnung'),
+ $searchstr
+ ) .
+ '
GROUP BY type, b.uid, p.person_id, name, email, m.telefonklappe, phone
');
@@ -178,15 +269,17 @@ class SearchBarLib
SELECT
\''.$type.'\' AS type,
o.oe_kurzbz AS oe_kurzbz,
- o.bezeichnung AS name,
+ \'[\' || ot.bezeichnung || \'] \' || o.bezeichnung AS name,
oParent.oe_kurzbz AS parentoe_kurzbz,
- oParent.bezeichnung AS parentoe_name,
+ (CASE WHEN oParent.bezeichnung IS NOT NULL THEN \'[\' || otParent.bezeichnung || \'] \' || oParent.bezeichnung END) AS parentoe_name,
ARRAY_AGG(DISTINCT(bfLeader.uid)) AS leader_uid,
ARRAY_AGG(DISTINCT(bfLeader.vorname || \' \' || bfLeader.nachname)) AS leader_name,
COUNT(bfCount.benutzerfunktion_id) AS number_of_people,
(CASE WHEN o.mailverteiler = TRUE THEN o.oe_kurzbz || \''.'@'.DOMAIN.'\' END) AS mailgroup
FROM public.tbl_organisationseinheit o
+ JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
LEFT JOIN public.tbl_organisationseinheit oParent ON(oParent.oe_kurzbz = o.oe_parent_kurzbz)
+ LEFT JOIN public.tbl_organisationseinheittyp otParent ON(oParent.organisationseinheittyp_kurzbz = otParent.organisationseinheittyp_kurzbz)
LEFT JOIN (
SELECT benutzerfunktion_id, oe_kurzbz
FROM public.tbl_benutzerfunktion
@@ -204,9 +297,14 @@ class SearchBarLib
AND (datum_bis IS NULL OR datum_bis >= NOW())
AND b.aktiv = TRUE
) bfLeader ON(bfLeader.oe_kurzbz = o.oe_kurzbz)
- WHERE o.oe_kurzbz ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
- OR o.bezeichnung ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
- GROUP BY type, o.oe_kurzbz, o.bezeichnung, oParent.oe_kurzbz, oParent.bezeichnung
+ WHERE ' .
+ $this->buildSearchClause(
+ $dbModel,
+ array('o.oe_kurzbz', 'o.bezeichnung', 'ot.bezeichnung'),
+ $searchstr
+ ) .
+ '
+ GROUP BY type, o.oe_kurzbz, o.bezeichnung, ot.bezeichnung, oParent.oe_kurzbz, oParent.bezeichnung, otParent.bezeichnung
');
// If something has been found
@@ -260,6 +358,35 @@ class SearchBarLib
*/
private function _student($searchstr, $type)
{
+ $dbModel = new DB_Model();
+
+ $students = $dbModel->execReadOnlyQuery('
+ SELECT
+ \''.$type.'\' AS type,
+ s.student_uid AS uid,
+ s.matrikelnr,
+ p.person_id AS person_id,
+ p.vorname || \' \' || p.nachname AS name,
+ k.kontakt as email ,
+ p.foto
+ FROM public.tbl_student s
+ JOIN public.tbl_benutzer b ON(b.uid = s.student_uid)
+ JOIN public.tbl_person p USING(person_id)
+ LEFT JOIN (
+ SELECT kontakt, person_id
+ FROM public.tbl_kontakt
+ WHERE kontakttyp = \'email\'
+ ) as k USING(person_id)
+ WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
+ OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
+ OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
+ GROUP BY type, s.student_uid, s.matrikelnr, p.person_id, name, email, p.foto
+ ');
+
+ // If something has been found then return it
+ if (hasData($students)) return getData($students);
+
+ // Otherwise return an empty array
return array();
}
@@ -268,6 +395,41 @@ class SearchBarLib
*/
private function _prestudent($searchstr, $type)
{
+ $dbModel = new DB_Model();
+
+ $prestudent = $dbModel->execReadOnlyQuery('
+ SELECT
+ \''.$type.'\' AS type,
+ ps.prestudent_id,
+ ps.studiengang_kz,
+ p.person_id AS person_id,
+ b.uid,
+ p.vorname || \' \' || p.nachname AS name,
+ (
+ SELECT kontakt
+ FROM public.tbl_kontakt
+ WHERE kontakttyp = \'email\'
+ AND person_id = p.person_id
+ LIMIT 1
+ ) as email,
+ p.foto,
+ sg.bezeichnung
+ FROM public.tbl_prestudent ps
+ LEFT JOIN public.tbl_student s USING (prestudent_id)
+ LEFT JOIN public.tbl_benutzer b ON (b.uid = s.student_uid)
+ JOIN public.tbl_person p ON (p.person_id = ps.person_id)
+ LEFT JOIN public.tbl_studiengang sg ON (sg.studiengang_kz = ps.studiengang_kz)
+ WHERE b.uid ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
+ OR p.vorname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
+ OR p.nachname ILIKE \'%'.$dbModel->escapeLike($searchstr).'%\'
+ or cast(ps.prestudent_id as text) ILIKE \'%'.$dbModel->escapeLIKE($searchstr).'%\'
+ GROUP BY type, b.uid, ps.prestudent_id, ps.studiengang_kz, sg.bezeichnung, s.student_uid, s.matrikelnr, p.person_id, name, email, p.foto
+ ');
+
+ // If something has been found then return it
+ if (hasData($prestudent)) return getData($prestudent);
+
+ // Otherwise return an empty array
return array();
}
diff --git a/application/libraries/TableWidgetLib.php b/application/libraries/TableWidgetLib.php
index dc746b6d5..3af99cca7 100644
--- a/application/libraries/TableWidgetLib.php
+++ b/application/libraries/TableWidgetLib.php
@@ -1,5 +1,22 @@
.
+ */
+
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
@@ -16,6 +33,7 @@ class TableWidgetLib
const SESSION_FIELDS = 'fields';
const SESSION_COLUMNS_ALIASES = 'columnsAliases';
const SESSION_ADDITIONAL_COLUMNS = 'additionalColumns';
+ const SESSION_ENCRYPTED_COLUMNS = 'encryptedColumns';
const SESSION_CHECKBOXES = 'checkboxes';
const SESSION_METADATA = 'datasetMetadata';
const SESSION_ROW_NUMBER = 'rowNumber';
@@ -49,6 +67,7 @@ class TableWidgetLib
const ADDITIONAL_COLUMNS = 'additionalColumns';
const CHECKBOXES = 'checkboxes';
const COLUMNS_ALIASES = 'columnsAliases';
+ const ENCRYPTED_COLUMNS = 'encryptedColumns';
// ...to format/mark records of a dataset
const FORMAT_ROW = 'formatRow';
@@ -74,7 +93,7 @@ class TableWidgetLib
/**
* Gets the CI instance and loads message helper
*/
- public function __construct($params = null)
+ public function __construct()
{
$this->_ci =& get_instance(); // get code igniter instance
}
@@ -177,7 +196,7 @@ class TableWidgetLib
/**
* Retrieves the dataset from the DB
*/
- public function getDataset($datasetQuery)
+ public function getDataset($datasetQuery, $encryptedColumns)
{
$dataset = null;
@@ -186,7 +205,7 @@ class TableWidgetLib
$this->_ci->load->model('system/Filters_model', 'FiltersModel');
// Execute the given SQL statement suppressing error messages
- $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery);
+ $dataset = @$this->_ci->FiltersModel->execReadOnlyQuery($datasetQuery, null, $encryptedColumns);
}
return $dataset;
diff --git a/application/libraries/UDFLib.php b/application/libraries/UDFLib.php
index c5f0d3e98..7437c58ff 100644
--- a/application/libraries/UDFLib.php
+++ b/application/libraries/UDFLib.php
@@ -65,6 +65,8 @@ class UDFLib
private $_udfUniqueId; // Property that contains the UDF widget unique id
+ private $_definition_cache = [];
+
/**
* Gets CI instance
*/
@@ -157,7 +159,7 @@ class UDFLib
$found = false; // used to check if the field is found or not in the json schema
$this->_sortJsonSchemas($jsonSchemasArray); // Sort the list of UDF by sort property
-
+
// Loops through json schemas
foreach ($jsonSchemasArray as $jsonSchema)
{
@@ -292,7 +294,7 @@ class UDFLib
// Checks if the requiredPermissions is available and it is a valid array or a valid string
if (isset($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})
&& (!isEmptyArray($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})
- || !isEmptyString($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})))
+ || !isEmptyString($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})))
{
// Then check if the user has the permissions to read such UDF
if (!$this->_readAllowed($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}))
@@ -353,7 +355,7 @@ class UDFLib
// Checks if the requiredPermissions is available and it is a valid array or a valid string
if (isset($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})
&& (!isEmptyArray($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})
- || !isEmptyString($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})))
+ || !isEmptyString($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER})))
{
// Then check if the user has the permissions to write such UDF
if (!$this->_writeAllowed($decodedUDFDefinition->{self::REQUIRED_PERMISSIONS_PARAMETER}))
@@ -613,6 +615,162 @@ class UDFLib
);
}
+ /**
+ * Gets the UDF definitions for a model
+ *
+ * @param DB_Model $targetModel
+ *
+ * @return stdClass
+ */
+ public function getDefinitionForModel($targetModel)
+ {
+ $dbTable = $targetModel->getDbTable();
+ if (!isset($this->_definition_cache[$dbTable])) {
+ $this->_ci->load->model('system/UDF_model', 'UDFModel');
+ list($schema, $table) = explode('.', $dbTable);
+ $result = $this->_ci->UDFModel->loadWhere([
+ 'schema' => $schema,
+ 'table' => $table
+ ]);
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ $this->_definition_cache[$dbTable] = [];
+ else
+ $this->_definition_cache[$dbTable] = json_decode(current($result->retval)->jsons, true);
+ }
+ return success($this->_definition_cache[$dbTable]);
+ }
+
+ /**
+ * Gets the UDFs for db entry with translated params and resolved listValues for dropdowns
+ *
+ * @param DB_Model $targetModel
+ * @param mixed $id
+ *
+ * @return stdClass
+ */
+ public function getFieldArray($targetModel, $id)
+ {
+ // Load Libraries
+ $this->_ci->load->library('PhrasesLib');
+ $this->_ci->load->library('PermissionLib');
+
+ $result = $this->getDefinitionForModel($targetModel);
+ if (isError($result))
+ return $result;
+ $definitions = $result->retval;
+
+ usort($definitions, function ($a, $b) {
+ return $a[self::SORT] - $b[self::SORT];
+ });
+
+ $values = $targetModel->getUDFs($id);
+
+ $fields = [];
+ foreach ($definitions as $field) {
+ // check read permissions
+ if (!$this->_ci->permissionlib->hasAtLeastOne(
+ $field[self::REQUIRED_PERMISSIONS_PARAMETER],
+ self::PERMISSION_TABLE_METHOD,
+ self::PERMISSION_TYPE_READ
+ ))
+ continue;
+
+ // set value
+ if (isset($values[$field[self::NAME]])) {
+ $field['value'] = $values[$field[self::NAME]];
+ } elseif (isset($field['defaultValue'])) {
+ $field['value'] = $field['defaultValue'];
+ } elseif (isset($field[self::TYPE]) && $field[self::TYPE] == 'checkbox') {
+ $field['value'] = false;
+ } else {
+ $field['value'] = '';
+ }
+
+ // translate params
+ foreach ([self::LABEL, self::TITLE, self::PLACEHOLDER] as $key) {
+ if (isset($field[$key])) {
+ $res = $this->_ci->phraseslib->getPhrases(self::PHRASES_APP_NAME, getUserLanguage(), $field[$key], null, null, 'no');
+ if (hasData($res))
+ $field[$key] = current(getData($res))->text;
+ }
+ }
+
+ // check write permissions
+ $field['disabled'] = !$this->_ci->permissionlib->hasAtLeastOne(
+ $field[self::REQUIRED_PERMISSIONS_PARAMETER],
+ self::PERMISSION_TABLE_METHOD,
+ self::PERMISSION_TYPE_WRITE
+ );
+
+ // set listValues for dropdowns
+ if (isset($field[self::LIST_VALUES])) {
+ if (isset($field[self::LIST_VALUES]['enum'])) {
+ $field['options'] = $field[self::LIST_VALUES]['enum'];
+ } elseif (isset($field[self::LIST_VALUES]['sql'])) {
+ $res = $this->_ci->UDFModel->execReadOnlyQuery($field[self::LIST_VALUES]['sql']);
+ $field['options'] = hasData($res) ? getData($res) : [];
+ }
+ }
+
+ // add to array
+ $fields[] = $field;
+ }
+ return success($fields);
+ }
+
+ /**
+ * Gets a validation config array for CI form_validation
+ *
+ * @param DB_Model $targetModel
+ * @param array (optional) $filter
+ *
+ * @return stdClass
+ */
+ public function getCiValidations($targetModel, $filter = null)
+ {
+ $result = $this->getDefinitionForModel($targetModel);
+ if (isError($result))
+ return $result;
+ $definitions = getData($result);
+
+ $result = [];
+ foreach ($definitions as $def) {
+ if ($filter && !isset($filter[$def['name']]))
+ continue;
+ $validations = [];
+ if (isset($def['requiredPermissions']))
+ $validations[] = 'has_write_permissions[' . implode(',', $def['requiredPermissions']) . ']';
+ if (isset($def['required']))
+ $validations[] = 'required';
+ if (isset($def['validation'])) {
+ if (isset($def['validation']['max-value']))
+ $validations[] = 'less_than_equal_to[' . $def['validation']['max-value'] . ']';
+ if (isset($def['validation']['min-value']))
+ $validations[] = 'greater_than_equal_to[' . $def['validation']['min-value'] . ']';
+ if (isset($def['validation']['max-length']))
+ $validations[] = 'max_length[' . $def['validation']['max-length'] . ']';
+ if (isset($def['validation']['min-length']))
+ $validations[] = 'min_length[' . $def['validation']['min-length'] . ']';
+ if (isset($def['validation']['regex']) && is_array($def['validation']['regex'])) {
+ foreach ($def['validation']['regex'] as $regex) {
+ if ($regex['language'] == 'php') {
+ $validations[] = 'regex_match[' . $regex['expression'] . ']';
+ }
+ }
+ }
+ }
+ if ($validations)
+ $result[] = [
+ 'field' => $def['name'],
+ 'label' => $def['title'],
+ 'rules' => $validations
+ ];
+ }
+ return success($result);
+ }
+
// -------------------------------------------------------------------------------------------------
// Private methods
//
@@ -841,7 +999,7 @@ class UDFLib
$htmlParameters[HTMLWidget::HTML_ID] = $jsonSchema->{self::NAME};
$htmlParameters[HTMLWidget::HTML_NAME] = $jsonSchema->{self::NAME};
}
-
+
/**
* Sort the list of UDF by sort property
*/
@@ -864,7 +1022,7 @@ class UDFLib
return ($a->{self::SORT} < $b->{self::SORT}) ? -1 : 1;
});
}
-
+
/**
* Loads the UDF description by the given schema and table
*/
diff --git a/application/libraries/issues/PlausicheckDefinitionLib.php b/application/libraries/issues/PlausicheckDefinitionLib.php
index cef28a736..d8c26d43a 100644
--- a/application/libraries/issues/PlausicheckDefinitionLib.php
+++ b/application/libraries/issues/PlausicheckDefinitionLib.php
@@ -15,7 +15,6 @@ class PlausicheckDefinitionLib
'AktSemesterNull' => 'AktSemesterNull',
'AktiverStudentOhneStatus' => 'AktiverStudentOhneStatus',
'AusbildungssemPrestudentUngleichAusbildungssemStatus' => 'AusbildungssemPrestudentUngleichAusbildungssemStatus',
- 'BewerberNichtZumRtAngetreten' => 'BewerberNichtZumRtAngetreten',
'DatumAbschlusspruefungFehlt' => 'DatumAbschlusspruefungFehlt',
'DatumSponsionFehlt' => 'DatumSponsionFehlt',
'DatumStudiensemesterFalscheReihenfolge' => 'DatumStudiensemesterFalscheReihenfolge',
@@ -33,8 +32,10 @@ class PlausicheckDefinitionLib
'PrestudentMischformOhneOrgform' => 'PrestudentMischformOhneOrgform',
'StgPrestudentUngleichStgStudienplan' => 'StgPrestudentUngleichStgStudienplan',
'StgPrestudentUngleichStgStudent' => 'StgPrestudentUngleichStgStudent',
- 'StudentstatusNachAbbrecher' => 'StudentstatusNachAbbrecher'
+ 'StudentstatusNachAbbrecher' => 'StudentstatusNachAbbrecher',
+ 'DualesStudiumOhneMarkierung' => 'DualesStudiumOhneMarkierung'
//'StudienplanUngueltig' => 'StudienplanUngueltig'
+ //'BewerberNichtZumRtAngetreten' => 'BewerberNichtZumRtAngetreten'
);
/**
diff --git a/application/libraries/issues/PlausicheckProducerLib.php b/application/libraries/issues/PlausicheckProducerLib.php
index c32f1f863..cea9967fb 100644
--- a/application/libraries/issues/PlausicheckProducerLib.php
+++ b/application/libraries/issues/PlausicheckProducerLib.php
@@ -12,19 +12,25 @@ class PlausicheckProducerLib
private $_ci; // ci instance
private $_extensionName; // name of extension
- private $_app; // name of application
- private $_konfiguration = array(); // konfigratio parameters
+ private $_konfiguration = []; // configuration parameters
+ private $_fehlerLibMappings = []; // mappings of fehler and libraries for producing them
+ private $_isForResolutionCheck = false; // mappings of fehler and libraries for producing them
public function __construct($params = null)
{
// set extension name if called from extension
if (isset($params['extensionName'])) $this->_extensionName = $params['extensionName'];
+ if (isset($params['fehlerLibMappings'])) $this->_fehlerLibMappings = $params['fehlerLibMappings'];
+ if (isset($params['isForResolutionCheck'])) $this->_isForResolutionCheck = $params['isForResolutionCheck'];
// set application
$app = isset($params['app']) ? $params['app'] : null;
$this->_ci =& get_instance(); // get ci instance
+ // load libraries
+ $this->_ci->load->library('IssuesLib');
+
// load models
$this->_ci->load->model('system/Fehlerkonfiguration_model', 'FehlerkonfigurationModel');
@@ -42,6 +48,52 @@ class PlausicheckProducerLib
}
}
+ /**
+ * Produces multiple plausicheck issues at once and saved them to db.
+ * @param array $params passed to each plausicheck
+ * @return result object with occured error and info
+ */
+ public function producePlausicheckIssues($params)
+ {
+ $result = new StdClass();
+ $result->errors = [];
+ $result->infos = [];
+
+ foreach ($this->_fehlerLibMappings as $fehler_kurzbz => $libName)
+ {
+ $plausicheckRes = $this->producePlausicheckIssue(
+ $libName,
+ $fehler_kurzbz,
+ $params
+ );
+
+ if (hasData($plausicheckRes))
+ {
+ $plausicheckData = getData($plausicheckRes);
+
+ foreach ($plausicheckData as $plausiData)
+ {
+ // get the data needed for issue production
+ $person_id = isset($plausiData['person_id']) ? $plausiData['person_id'] : null;
+ $oe_kurzbz = isset($plausiData['oe_kurzbz']) ? $plausiData['oe_kurzbz'] : null;
+ $fehlertext_params = isset($plausiData['fehlertext_params']) ? $plausiData['fehlertext_params'] : null;
+ $resolution_params = isset($plausiData['resolution_params']) ? $plausiData['resolution_params'] : null;
+
+ // write the issue
+ $addIssueRes = $this->_ci->issueslib->addFhcIssue($fehler_kurzbz, $person_id, $oe_kurzbz, $fehlertext_params, $resolution_params);
+
+ // log if error, or log info if inserted new issue
+ if (isError($addIssueRes))
+ $result->errors[] = getError($addIssueRes);
+ elseif (hasData($addIssueRes) && is_integer(getData($addIssueRes)))
+ $result->infos[] = "Plausicheck issue " . $fehler_kurzbz . " successfully produced, person_id: " . $person_id;
+ }
+ }
+ }
+
+ return $result;
+ }
+
/**
* Executes plausicheck using a given library, returns the result.
* @param $libName string name of library producing the issue
@@ -67,7 +119,10 @@ class PlausicheckProducerLib
$config = isset($this->_konfiguration[$fehler_kurzbz]) ? $this->_konfiguration[$fehler_kurzbz] : null;
// load library connected to fehlercode
- $this->_ci->load->library($issuesLibPath . $libName, $config);
+ $this->_ci->load->library(
+ $issuesLibPath . $libName,
+ ['configurationParams' => $config, 'isForResolutionCheck' => $this->_isForResolutionCheck]
+ );
$lowercaseLibName = mb_strtolower($libName);
diff --git a/application/libraries/issues/PlausicheckResolverLib.php b/application/libraries/issues/PlausicheckResolverLib.php
new file mode 100644
index 000000000..26da985f6
--- /dev/null
+++ b/application/libraries/issues/PlausicheckResolverLib.php
@@ -0,0 +1,136 @@
+_extensionName = $params['extensionName'];
+ if (isset($params['codeLibMappings'])) $this->_codeLibMappings = $params['codeLibMappings'];
+ if (isset($params['codeProducerLibMappings'])) $this->_codeProducerLibMappings = $params['codeProducerLibMappings'];
+
+ $this->_ci =& get_instance(); // get ci instance
+
+ $this->_ci->load->library('IssuesLib');
+ $this->_ci->load->library('issues/PlausicheckProducerLib', ['extensionName' => $this->_extensionName, 'isForResolutionCheck' => true]);
+ }
+
+ /**
+ * Reseolves multiple plausicheck issues at once.
+ * @param array $codeLibMappings contains fehler type to check and library responsible for check (fehlercode => libName)
+ * @param array $openIssues passed issues to resolve
+ * @return result object with occured error and info
+ */
+ public function resolvePlausicheckIssues($openIssues)
+ {
+ $result = new StdClass();
+ $result->errors = [];
+ $result->infos = [];
+
+ foreach ($openIssues as $issue)
+ {
+ // add person id and oe kurzbz automatically as params, merge it with additional params
+ // decode bewerbung_parameter into assoc array
+ $params = array_merge(
+ array('issue_id' => $issue->issue_id, 'issue_person_id' => $issue->person_id, 'issue_oe_kurzbz' => $issue->oe_kurzbz),
+ isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array()
+ );
+
+ $issueResolved = false;
+
+ // ignore if Fehlercode is not in libmappings (shouldn't be checked)
+ if (isset($this->_codeLibMappings[$issue->fehlercode]))
+ {
+ $libName = $this->_codeLibMappings[$issue->fehlercode];
+
+ // if called from extension (extension name set), path includes extension names
+ $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : '';
+
+ // path for loading issue library
+ $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/';
+
+ // file path of library for check if file exists
+ $issuesLibFilePath = DOC_ROOT . self::CI_PATH
+ . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php';
+
+ // check if library file exists
+ if (!file_exists($issuesLibFilePath))
+ {
+ // log error and continue with next issue if not
+ $result->errors[] = "Issue library file " . $issuesLibFilePath . " does not exist";
+ continue;
+ }
+
+ // load library connected to fehlercode
+ $this->_ci->load->library($issuesLibPath . $libName);
+
+ $lowercaseLibName = mb_strtolower($libName);
+
+ // check if method is defined in library class
+ if (!is_callable(array($this->_ci->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME)))
+ {
+ // log error and continue with next issue if not
+ $result->errors[] = "Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName";
+ continue;
+ }
+
+ // call the function for checking for issue resolution
+ $issueResolvedRes = $this->_ci->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params);
+
+ if (isError($issueResolvedRes))
+ {
+ $result->errors[] = getError($issueResolvedRes);
+ }
+ else
+ {
+ $issueResolved = getData($issueResolvedRes) === true;
+ }
+ }
+ elseif (isset($this->_codeProducerLibMappings[$issue->fehlercode]))
+ {
+ $libName = $this->_codeProducerLibMappings[$issue->fehlercode];
+
+ $issueResolvedRes = $this->_ci->plausicheckproducerlib->producePlausicheckIssue(
+ $libName,
+ $issue->fehler_kurzbz,
+ $params
+ );
+
+ if (isError($issueResolvedRes))
+ {
+ $result->errors[] = getError($issueResolvedRes);
+ }
+ else
+ {
+ $issueResolved = !hasData($issueResolvedRes);
+ }
+ }
+
+ // set issue to resolved if needed
+ if ($issueResolved)
+ {
+ $behobenRes = $this->_ci->issueslib->setBehoben($issue->issue_id, null);
+
+ if (isError($behobenRes))
+ $result->errors[] = getError($behobenRes);
+ else
+ $result->infos[] = "Issue " . $issue->issue_id . " successfully resolved";
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/application/libraries/issues/plausichecks/AbbrecherAktiv.php b/application/libraries/issues/plausichecks/AbbrecherAktiv.php
index 9eae389b5..464b77a30 100644
--- a/application/libraries/issues/plausichecks/AbbrecherAktiv.php
+++ b/application/libraries/issues/plausichecks/AbbrecherAktiv.php
@@ -9,83 +9,21 @@ require_once('PlausiChecker.php');
*/
class AbbrecherAktiv extends PlausiChecker
{
- public function executePlausiCheck($params)
- {
- $results = array();
+ protected $_base_sql = "
+ SELECT
+ pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz
+ FROM
+ public.tbl_prestudentstatus pre_status
+ JOIN public.tbl_prestudent pre USING(prestudent_id)
+ JOIN public.tbl_student student USING(prestudent_id)
+ JOIN public.tbl_benutzer benutzer on(benutzer.uid=student.student_uid)
+ JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz
+ WHERE
+ pre_status.status_kurzbz ='Abbrecher'
+ AND benutzer.aktiv=true";
- // get parameters from config
- $exkludierte_studiengang_kz = isset($this->_config['exkludierteStudiengaenge']) ? $this->_config['exkludierteStudiengaenge'] : null;
-
- // pass parameters needed for plausicheck
- $studiengang_kz = isset($params['studiengang_kz']) ? $params['studiengang_kz'] : null;
-
- // get all students failing the plausicheck
- $prestudentRes = $this->getAbbrecherAktiv($studiengang_kz, null, $exkludierte_studiengang_kz);
-
- if (isError($prestudentRes)) return $prestudentRes;
-
- if (hasData($prestudentRes))
- {
- $prestudents = getData($prestudentRes);
-
- // populate results with data necessary for writing issues
- foreach ($prestudents as $prestudent)
- {
- $results[] = array(
- 'person_id' => $prestudent->person_id,
- 'oe_kurzbz' => $prestudent->prestudent_stg_oe_kurzbz,
- 'fehlertext_params' => array('prestudent_id' => $prestudent->prestudent_id),
- 'resolution_params' => array('prestudent_id' => $prestudent->prestudent_id)
- );
- }
- }
-
- // return the results
- return success($results);
- }
-
- /**
- * Abbrecher cannot be active.
- * @param studiengang_kz int if check is to be executed for certain Studiengang
- * @param prestudent_id int if check is to be executed only for one prestudent
- * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check
- * @return success with prestudents or error
- */
- public function getAbbrecherAktiv($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null)
- {
- $params = array();
-
- $qry = "
- SELECT
- pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz
- FROM
- public.tbl_prestudentstatus pre_status
- JOIN public.tbl_prestudent pre USING(prestudent_id)
- JOIN public.tbl_student student USING(prestudent_id)
- JOIN public.tbl_benutzer benutzer on(benutzer.uid=student.student_uid)
- JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz
- WHERE
- pre_status.status_kurzbz ='Abbrecher'
- AND benutzer.aktiv=true";
-
- if (isset($studiengang_kz))
- {
- $qry .= " AND stg.studiengang_kz = ?";
- $params[] = $studiengang_kz;
- }
-
- if (isset($prestudent_id))
- {
- $qry .= " AND pre.prestudent_id = ?";
- $params[] = $prestudent_id;
- }
-
- if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz))
- {
- $qry .= " AND stg.studiengang_kz NOT IN ?";
- $params[] = $exkludierte_studiengang_kz;
- }
-
- return $this->_db->execReadOnlyQuery($qry, $params);
- }
+ protected $_config_params = ['exkludierteStudiengaenge' => " AND stg.studiengang_kz NOT IN ?"];
+ protected $_params_for_checking = ['studiengang_kz' => " AND stg.studiengang_kz = ?", 'prestudent_id' => " AND pre.prestudent_id = ?"];
+ protected $_fehlertext_params = ['prestudent_id'];
+ protected $_resolution_params = ['prestudent_id'];
}
diff --git a/application/libraries/issues/plausichecks/DualesStudiumOhneMarkierung.php b/application/libraries/issues/plausichecks/DualesStudiumOhneMarkierung.php
new file mode 100644
index 000000000..3951f6d76
--- /dev/null
+++ b/application/libraries/issues/plausichecks/DualesStudiumOhneMarkierung.php
@@ -0,0 +1,143 @@
+_config['exkludierteStudiengaenge']) ? $this->_config['exkludierteStudiengaenge'] : null;
+
+ // pass parameters needed for plausicheck
+ $studiensemester_kurzbz = isset($params['studiensemester_kurzbz']) ? $params['studiensemester_kurzbz'] : null;
+ $studiengang_kz = isset($params['studiengang_kz']) ? $params['studiengang_kz'] : null;
+
+ // get all students failing the plausicheck
+ $prestudentRes = $this->getDualesStudiumOhneMarkierung(
+ $studiensemester_kurzbz,
+ $studiengang_kz,
+ null,
+ $exkludierte_studiengang_kz
+ );
+
+ if (isError($prestudentRes)) return $prestudentRes;
+
+ if (hasData($prestudentRes))
+ {
+ $prestudents = getData($prestudentRes);
+
+ // populate results with data necessary for writing issues
+ foreach ($prestudents as $prestudent)
+ {
+ $results[] = array(
+ 'person_id' => $prestudent->person_id,
+ 'oe_kurzbz' => $prestudent->prestudent_stg_oe_kurzbz,
+ 'fehlertext_params' => array(
+ 'prestudent_id' => $prestudent->prestudent_id,
+ 'studienplan' => $prestudent->studienplan
+ ),
+ 'resolution_params' => array(
+ 'prestudent_id' => $prestudent->prestudent_id,
+ 'studiensemester_kurzbz' => $prestudent->studiensemester_kurzbz
+ )
+ );
+ }
+ }
+
+ // return the results
+ return success($results);
+ }
+
+ /**
+ * All prestudents in dual Studiengang should have set the dual flag to true.
+ * @param studiensemester_kurzbz string check is to be executed for certain Studiensemester
+ * @param studiengang_kz int if check is to be executed for certain Studiengang
+ * @param prestudent_id int if check is to be executed only for one prestudent
+ * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check
+ * @return success with prestudents or error
+ */
+ public function getDualesStudiumOhneMarkierung(
+ $studiensemester_kurzbz,
+ $studiengang_kz = null,
+ $prestudent_id = null,
+ $exkludierte_studiengang_kz = null
+ ) {
+ $params = array($studiensemester_kurzbz);
+
+ $qry = "
+ SELECT
+ DISTINCT pre.person_id, pre.prestudent_id,
+ stpl.bezeichnung AS studienplan,
+ status.studiensemester_kurzbz,
+ status.ausbildungssemester,
+ stg.oe_kurzbz AS prestudent_stg_oe_kurzbz
+ FROM
+ public.tbl_prestudent pre
+ JOIN public.tbl_prestudentstatus status USING(prestudent_id)
+ JOIN public.tbl_person USING(person_id)
+ JOIN lehre.tbl_studienplan stpl USING(studienplan_id)
+ JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz
+ JOIN public.tbl_studiensemester sem USING(studiensemester_kurzbz)
+ WHERE
+ (stpl.orgform_kurzbz = 'DUA' OR status.orgform_kurzbz = 'DUA')
+ AND pre.dual = FALSE
+ AND status.studiensemester_kurzbz=?
+ AND pre.bismelden
+ AND stg.melderelevant
+ AND NOT EXISTS (
+ SELECT 1
+ FROM
+ public.tbl_prestudentstatus
+ JOIN lehre.tbl_studienplan USING(studienplan_id)
+ JOIN public.tbl_studiensemester USING(studiensemester_kurzbz)
+ WHERE
+ prestudent_id = pre.prestudent_id
+ AND
+ (
+ -- if there is a newer non-dual status, dual has not to be set
+ (
+ (
+ tbl_studienplan.orgform_kurzbz <> stpl.orgform_kurzbz
+ OR status.orgform_kurzbz <> tbl_prestudentstatus.orgform_kurzbz
+ )
+ AND
+ (
+ tbl_studiensemester.ende::date > sem.ende::date
+ OR (tbl_studiensemester.ende::date = sem.ende::date AND tbl_prestudentstatus.datum::date > status.datum::date)
+ )
+ )
+ OR
+ -- exclude Abgewiesene - they are not reported
+ tbl_prestudentstatus.status_kurzbz = 'Abgewiesener'
+ )
+ )";
+
+ if (isset($studiengang_kz))
+ {
+ $qry .= " AND stg.studiengang_kz = ?";
+ $params[] = $studiengang_kz;
+ }
+
+ if (isset($prestudent_id))
+ {
+ $qry .= " AND pre.prestudent_id = ?";
+ $params[] = $prestudent_id;
+ }
+
+ if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz))
+ {
+ $qry .= " AND stg.studiengang_kz NOT IN ?";
+ $params[] = $exkludierte_studiengang_kz;
+ }
+
+ return $this->_db->execReadOnlyQuery($qry, $params);
+ }
+}
diff --git a/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php b/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php
index dead2b1e7..59965e238 100644
--- a/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php
+++ b/application/libraries/issues/plausichecks/InaktiverStudentAktiverStatus.php
@@ -67,6 +67,7 @@ class InaktiverStudentAktiverStatus extends PlausiChecker
$prestudent_id = null,
$exkludierte_studiengang_kz = null
) {
+ $this->_ci->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
$aktStudiensemesterRes = $this->_ci->StudiensemesterModel->getAkt();
if (isError($aktStudiensemesterRes)) return $aktStudiensemesterRes;
diff --git a/application/libraries/issues/plausichecks/PlausiChecker.php b/application/libraries/issues/plausichecks/PlausiChecker.php
index 086a44cc4..7e5fe7db0 100644
--- a/application/libraries/issues/plausichecks/PlausiChecker.php
+++ b/application/libraries/issues/plausichecks/PlausiChecker.php
@@ -6,15 +6,25 @@
abstract class PlausiChecker
{
protected $_ci; // code igniter instance
- protected $_config; // configuration parameters for this plausicheck
+ protected $_config; // all applicable configuration parameters for this plausicheck
protected $_db; // database for queries
- public function __construct($configurationParams = null)
+ protected $_isForResolutionCheck; // if true, additional parameters only needed for resolution are checked
+
+ protected $_config_params = []; // name of all config params which should be applied for this plausicheck, with sql [name] => [sql]
+ protected $_params_for_checking = []; // name of all passed params for checking, with sql [name] => [sql]
+
+ protected $_fehlertext_params = []; // parameter names for fehlertext params used for this plausicheck
+ protected $_resolution_params = []; // parameter names for resolution params used for this plausicheck
+
+ public function __construct($params = null)
{
$this->_ci =& get_instance(); // get code igniter instance
// set configuration
- $this->_config = $configurationParams;
+ $this->_config = $params['configurationParams'] ?? [];
+
+ $this->_isForResolutionCheck = $params['isForResolutionCheck'] ?? false;
// get database for queries
$this->_db = new DB_Model();
@@ -25,5 +35,83 @@ abstract class PlausiChecker
* @param $paramsForChecking array parameters needed for executing the check
* @return array with objects which failed the plausi check
*/
- abstract public function executePlausiCheck($paramsForChecking);
+ public function executePlausiCheck($paramsForChecking)
+ {
+ $results = [];
+ $params = [];
+ $qry = $this->_base_sql;
+
+ if ($this->_isForResolutionCheck == true)
+ {
+ foreach ($this->_resolution_params as $resParam)
+ {
+ if (!isset($paramsForChecking[$resParam]))
+ return error("$resParam missing".(isset($paramsForChecking['issue_id']) ? ", issue ID: ".$paramsForChecking['issue_id'] : ""));
+ }
+ }
+
+ // add config params to query
+ if (isset($this->_config_params) && !isEmptyArray($this->_config_params))
+ {
+ foreach ($this->_config_params as $param_name => $param_sql)
+ {
+ if (isset($this->_config[$param_name]))
+ {
+ $qry .= $param_sql;
+ $params[] = $this->_config[$param_name];
+ }
+ }
+ }
+
+ // add check params to query
+ if (isset($this->_params_for_checking) && !isEmptyArray($this->_params_for_checking))
+ {
+ foreach ($this->_params_for_checking as $param_name => $param_sql)
+ {
+ if (isset($paramsForChecking[$param_name]))
+ {
+ $qry .= $param_sql;
+ $params[] = $paramsForChecking[$param_name];
+ }
+ }
+ }
+
+ $result = $this->_db->execReadOnlyQuery($qry, $params);
+
+ if (isError($result)) return $result;
+
+ if (hasData($result))
+ {
+ $data = getData($result);
+
+ // populate results with data necessary for writing issues
+ foreach ($data as $d)
+ {
+ $fehlertext_params = [];
+ $resolution_params = [];
+
+ // add params for error texts
+ foreach ($this->_fehlertext_params as $param)
+ {
+ if (isset($d->{$param})) $fehlertext_params[$param] = $d->{$param};
+ }
+
+ // add params for resolution of issue
+ foreach ($this->_resolution_params as $param)
+ {
+ if (isset($d->{$param})) $resolution_params[$param] = $d->{$param};
+ }
+
+ $results[] = array(
+ 'person_id' => $d->person_id,
+ 'oe_kurzbz' => $d->prestudent_stg_oe_kurzbz,
+ 'fehlertext_params' => $fehlertext_params,
+ 'resolution_params' => $resolution_params
+ );
+ }
+ }
+
+ // return the results
+ return success($results);
+ }
}
diff --git a/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0016.php b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0016.php
new file mode 100644
index 000000000..0bba1ddff
--- /dev/null
+++ b/application/libraries/issues/resolvers/CORE_STUDENTSTATUS_0016.php
@@ -0,0 +1,36 @@
+_ci =& get_instance(); // get code igniter instance
+
+ $this->_ci->load->library('issues/plausichecks/DualesStudiumOhneMarkierung');
+
+ // check if issue persists
+ $checkRes = $this->_ci->dualesstudiumohnemarkierung->getDualesStudiumOhneMarkierung(
+ $params['studiensemester_kurzbz'],
+ null,
+ $params['prestudent_id']
+ );
+
+ if (isError($checkRes)) return $checkRes;
+
+ if (hasData($checkRes))
+ return success(false); // not resolved if issue is still present
+ else
+ return success(true); // resolved otherwise
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/AbstractBestandteil.php b/application/libraries/vertragsbestandteil/AbstractBestandteil.php
new file mode 100644
index 000000000..ccd05f5e2
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/AbstractBestandteil.php
@@ -0,0 +1,69 @@
+isvalid = false;
+ $this->validationerrors = array();
+
+ $this->modifiedcolumns = array();
+ $this->fromdb = false;
+ }
+
+ public function isDirty() {
+ return count($this->modifiedcolumns) > 0;
+ }
+
+ protected function markDirty($columnname, $old_value, $new_value) {
+ if( $this->fromdb ) {
+ // data comes from db dont check for changes
+ if( isset($this->modifiedcolumns[$columnname]) ) {
+ unset($this->modifiedcolumns[$columnname]);
+ }
+ return;
+ }
+
+ if( is_bool($new_value) && ($old_value !== $new_value) ) {
+ $this->modifiedcolumns[$columnname] = $columnname;
+ } else if($old_value != $new_value) {
+ $this->modifiedcolumns[$columnname] = $columnname;
+ }
+ }
+
+ public function isValid()
+ {
+ return $this->isvalid;
+ }
+
+ public function getValidationErrors()
+ {
+ return $this->validationerrors;
+ }
+
+
+ public function addValidationError($errormsg)
+ {
+ if( !in_array($errormsg, $this->validationerrors, true) )
+ {
+ $this->validationerrors[] = $errormsg;
+ }
+ $this->isvalid = false;
+ }
+
+ abstract public function hydrateByStdClass($data, $fromdb=false);
+}
diff --git a/application/libraries/vertragsbestandteil/Dienstverhaeltnis.php b/application/libraries/vertragsbestandteil/Dienstverhaeltnis.php
new file mode 100644
index 000000000..07c417077
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/Dienstverhaeltnis.php
@@ -0,0 +1,296 @@
+checkoverlap = true;
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ $this->fromdb = $fromdb;
+ isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id);
+ isset($data->mitarbeiter_uid) && $this->setMitarbeiter_uid($data->mitarbeiter_uid);
+ isset($data->vertragsart_kurzbz) && $this->setVertragsart_kurzbz($data->vertragsart_kurzbz);
+ isset($data->checkoverlap) && $this->setCheckoverlap($data->checkoverlap);
+ isset($data->oe_kurzbz) && $this->setOe_kurzbz($data->oe_kurzbz);
+ isset($data->von) && $this->setVon($data->von);
+ isset($data->bis) && $this->setBis($data->bis);
+ isset($data->insertamum) && $this->setInsertamum($data->insertamum);
+ isset($data->insertvon) && $this->setInsertvon($data->insertvon);
+ isset($data->updateamum) && $this->setUpdateamum($data->updateamum);
+ isset($data->updatevon) && $this->setUpdatevon($data->updatevon);
+ isset($data->dvendegrund_kurzbz) && $this->setDvendegrund_kurzbz($data->dvendegrund_kurzbz);
+ isset($data->dvendegrund_anmerkung) && $this->setDvendegrund_anmerkung($data->dvendegrund_anmerkung);
+ $this->fromdb = false;
+ }
+
+ public function toStdClass(): \stdClass
+ {
+ $tmp = array(
+ 'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(),
+ 'mitarbeiter_uid' => $this->getMitarbeiter_uid(),
+ 'vertragsart_kurzbz' => $this->getVertragsart_kurzbz(),
+ 'oe_kurzbz' => $this->getOe_kurzbz(),
+ 'von' => $this->getVon(),
+ 'bis' => $this->getBis(),
+ 'insertamum' => $this->getInsertamum(),
+ 'insertvon' => $this->getInsertvon(),
+ 'updateamum' => $this->getUpdateamum(),
+ 'updatevon' => $this->getUpdatevon(),
+ 'dvendegrund_kurzbz' => $this->getDvendegrund_kurzbz(),
+ 'dvendegrund_anmerkung' => $this->getDvendegrund_anmerkung()
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+
+ public function __toString()
+ {
+ $txt = <<getDienstverhaeltnis_id()}
+ mitarbeiter_uid: {$this->getMitarbeiter_uid()}
+ vertragsart_kurzbz: {$this->getVertragsart_kurzbz()}
+ oe_kurzbz: {$this->getOe_kurzbz()}
+ von: {$this->getVon()}
+ bis: {$this->getBis()}
+
+EOTXT;
+ return $txt;
+ }
+
+ public function getDienstverhaeltnis_id()
+ {
+ return $this->dienstverhaeltnis_id;
+ }
+
+ public function getMitarbeiter_uid()
+ {
+ return $this->mitarbeiter_uid;
+ }
+
+ public function getVertragsart_kurzbz()
+ {
+ return $this->vertragsart_kurzbz;
+ }
+
+ public function getOe_kurzbz()
+ {
+ return $this->oe_kurzbz;
+ }
+
+ public function getVon()
+ {
+ return $this->von;
+ }
+
+ public function getBis()
+ {
+ return $this->bis;
+ }
+
+ public function getInsertamum()
+ {
+ return $this->insertamum;
+ }
+
+ public function getInsertvon()
+ {
+ return $this->insertvon;
+ }
+
+ public function getUpdateamum()
+ {
+ return $this->updateamum;
+ }
+
+ public function getUpdatevon()
+ {
+ return $this->updatevon;
+ }
+
+ public function getDvendegrund_kurzbz()
+ {
+ return $this->dvendegrund_kurzbz;
+ }
+
+ public function getDvendegrund_anmerkung()
+ {
+ return $this->dvendegrund_anmerkung;
+ }
+
+ public function setDienstverhaeltnis_id($dienstverhaeltnis_id)
+ {
+ $this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id);
+ $this->dienstverhaeltnis_id = $dienstverhaeltnis_id;
+ return $this;
+ }
+
+ public function setMitarbeiter_uid($mitarbeiter_uid)
+ {
+ $this->markDirty('mitarbeiter_uid', $this->mitarbeiter_uid, $mitarbeiter_uid);
+ $this->mitarbeiter_uid = $mitarbeiter_uid;
+ return $this;
+ }
+
+ public function setVertragsart_kurzbz($vertragsart_kurzbz)
+ {
+ $this->markDirty('vertragsart_kurzbz', $this->vertragsart_kurzbz, $vertragsart_kurzbz);
+ $this->vertragsart_kurzbz = $vertragsart_kurzbz;
+ return $this;
+ }
+
+ public function setCheckoverlap(bool $checkoverlap)
+ {
+ $this->checkoverlap = $checkoverlap;
+ }
+
+ public function setOe_kurzbz($oe_kurzbz)
+ {
+ $this->markDirty('oe_kurzbz', $this->oe_kurzbz, $oe_kurzbz);
+ $this->oe_kurzbz = $oe_kurzbz;
+ return $this;
+ }
+
+ public function setVon($von)
+ {
+ $this->markDirty('von', $this->von, $von);
+ $this->von = $von;
+ return $this;
+ }
+
+ public function setBis($bis)
+ {
+ $this->markDirty('bis', $this->bis, $bis);
+ $this->bis = $bis;
+ return $this;
+ }
+
+ public function setInsertamum($insertamum)
+ {
+ $this->markDirty('insertamum', $this->insertamum, $insertamum);
+ $this->insertamum = $insertamum;
+ return $this;
+ }
+
+ public function setInsertvon($insertvon)
+ {
+ $this->markDirty('insertvon', $this->insertvon, $insertvon);
+ $this->insertvon = $insertvon;
+ return $this;
+ }
+
+ public function setUpdateamum($updateamum)
+ {
+ $this->markDirty('updateamum', $this->updateamum, $updateamum);
+ $this->updateamum = $updateamum;
+ return $this;
+ }
+
+ public function setUpdatevon($updatevon)
+ {
+ $this->markDirty('updatevon', $this->updatevon, $updatevon);
+ $this->updatevon = $updatevon;
+ return $this;
+ }
+
+ public function setDvendegrund_kurzbz($dvendegrund_kurzbz)
+ {
+ $this->markDirty('dvendegrund_kurzbz', $this->dvendegrund_kurzbz, $dvendegrund_kurzbz);
+ $this->dvendegrund_kurzbz = $dvendegrund_kurzbz;
+ return $this;
+ }
+
+ public function setDvendegrund_anmerkung($dvendegrund_anmerkung)
+ {
+ $this->markDirty('dvendegrund_anmerkung', $this->dvendegrund_anmerkung, $dvendegrund_anmerkung);
+ $this->dvendegrund_anmerkung = $dvendegrund_anmerkung;
+ return $this;
+ }
+
+ public function validate() {
+ //do Validation here
+ $ci = get_instance();
+ $ci->load->library('vertragsbestandteil/VertragsbestandteilLib',
+ null, 'VertragsbestandteilLib');
+
+ if( empty($this->mitarbeiter_uid) ) {
+ $this->validationerrors[] = 'Mitarbeiter_UID fehlt.';
+ }
+
+ if( empty($this->oe_kurzbz) ) {
+ $this->validationerrors[] = 'Unternehmen fehlt.';
+ }
+
+ if( empty($this->vertragsart_kurzbz) ) {
+ $this->validationerrors[] = 'Vertragsart fehlt.';
+ }
+
+ $von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von);
+ $bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis);
+
+ if( false === $von ) {
+ $this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.';
+ }
+
+ if( $this->bis !== null && $bis === false ) {
+ $this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.';
+ }
+
+ if( $this-> bis !== null && $von && $bis && $von > $bis ) {
+ $this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.';
+ }
+
+ if( $this->checkoverlap && !(in_array($this->vertragsart_kurzbz, array('werkvertrag', 'studentischehilfskr')) )
+ && $ci->VertragsbestandteilLib->isOverlappingExistingDV($this) )
+ {
+ $this->validationerrors[] = 'Es existiert bereits ein überlappendes Dienstverhältnis';
+ }
+
+ // return status after Validation
+ if( count($this->validationerrors) > 0 ) {
+ $this->isvalid = false;
+ } else {
+ $this->isvalid = true;
+ }
+
+ return $this->isvalid;
+ }
+}
\ No newline at end of file
diff --git a/application/libraries/vertragsbestandteil/Gehaltsbestandteil.php b/application/libraries/vertragsbestandteil/Gehaltsbestandteil.php
new file mode 100644
index 000000000..95bbdd908
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/Gehaltsbestandteil.php
@@ -0,0 +1,368 @@
+fromdb = $fromdb;
+ isset($data->gehaltsbestandteil_id) && $this->setGehaltsbestandteil_id($data->gehaltsbestandteil_id);
+ isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id);
+ isset($data->vertragsbestandteil_id) && $this->setVertragsbestandteil_id($data->vertragsbestandteil_id);
+ isset($data->gehaltstyp_kurzbz) && $this->setGehaltstyp_kurzbz($data->gehaltstyp_kurzbz);
+ isset($data->von) && $this->setVon($data->von);
+ isset($data->bis) && $this->setBis($data->bis);
+ isset($data->anmerkung) && $this->setAnmerkung($data->anmerkung);
+ isset($data->grundbetrag) && $this->setGrundbetrag($data->grundbetrag);
+ isset($data->betrag_valorisiert) && $this->setBetrag_valorisiert($data->betrag_valorisiert);
+ isset($data->valorisierungssperre) && $this->setValorisierungssperre($data->valorisierungssperre);
+ isset($data->valorisierung) && $this->setValorisierung($data->valorisierung);
+ isset($data->auszahlungen) && $this->setAuszahlungen($data->auszahlungen);
+
+ isset($data->insertamum) && $this->setInsertamum($data->insertamum);
+ isset($data->insertvon) && $this->setInsertvon($data->insertvon);
+ isset($data->updateamum) && $this->setUpdateamum($data->updateamum);
+ isset($data->updatevon) && $this->setUpdatevon($data->updatevon);
+ $this->fromdb = false;
+ }
+
+ public function getGehaltsbestandteil_id()
+ {
+ return $this->gehaltsbestandteil_id;
+ }
+
+ public function getDienstverhaeltnis_id()
+ {
+ return $this->dienstverhaeltnis_id;
+ }
+
+ public function getVertragsbestandteil_id()
+ {
+ return $this->vertragsbestandteil_id;
+ }
+
+ public function getGehaltstyp_kurzbz()
+ {
+ return $this->gehaltstyp_kurzbz;
+ }
+
+ public function getVon()
+ {
+ return $this->von;
+ }
+
+ public function getBis()
+ {
+ return $this->bis;
+ }
+
+ public function getVonDateTime()
+ {
+ return $this->toDateTime($this->von);
+ }
+
+ public function getBisDateTime()
+ {
+ return $this->toDateTime($this->bis);
+ }
+
+ protected function toDateTime($d) {
+ if ($d == null) return null;
+ return new DateTimeImmutable($d);
+ }
+
+ public function getAnmerkung()
+ {
+ return $this->anmerkung;
+ }
+
+ public function getGrundbetrag()
+ {
+ return $this->grundbetrag;
+ }
+
+ public function getBetrag_valorisiert()
+ {
+ return $this->betrag_valorisiert;
+ }
+
+ public function getValorisierungssperre()
+ {
+ return $this->valorisierungssperre;
+ }
+
+ public function getValorisierung()
+ {
+ return $this->valorisierung;
+ }
+
+ public function getAuszahlungen()
+ {
+ return $this->auszahlungen;
+ }
+
+ public function getInsertamum()
+ {
+ return $this->insertamum;
+ }
+
+ public function getInsertvon()
+ {
+ return $this->insertvon;
+ }
+
+ public function getUpdateamum()
+ {
+ return $this->updateamum;
+ }
+
+ public function getUpdatevon()
+ {
+ return $this->updatevon;
+ }
+
+ public function setGehaltsbestandteil_id($gehaltsbestandteil_id)
+ {
+ $this->markDirty('gehaltsbestandteil_id', $this->gehaltsbestandteil_id, $gehaltsbestandteil_id);
+ $this->gehaltsbestandteil_id = $gehaltsbestandteil_id;
+ return $this;
+ }
+
+ public function setDienstverhaeltnis_id($dienstverhaeltnis_id)
+ {
+ $this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id);
+ $this->dienstverhaeltnis_id = $dienstverhaeltnis_id;
+ return $this;
+ }
+
+ public function setVertragsbestandteil_id($vertragsbestandteil_id)
+ {
+ $this->markDirty('vertragsbestandteil_id', $this->vertragsbestandteil_id, $vertragsbestandteil_id);
+ $this->vertragsbestandteil_id = $vertragsbestandteil_id;
+ return $this;
+ }
+
+ public function setGehaltstyp_kurzbz($gehaltstyp_kurzbz)
+ {
+ $this->markDirty('gehaltstyp_kurzbz', $this->gehaltstyp_kurzbz, $gehaltstyp_kurzbz);
+ $this->gehaltstyp_kurzbz = $gehaltstyp_kurzbz;
+ return $this;
+ }
+
+ public function setVon($von)
+ {
+ $this->markDirty('von', $this->von, $von);
+ $this->von = $von;
+ return $this;
+ }
+
+ public function setBis($bis)
+ {
+ $this->markDirty('bis', $this->bis, $bis);
+ $this->bis = $bis;
+ return $this;
+ }
+
+ public function setAnmerkung($anmerkung)
+ {
+ $this->markDirty('anmerkung', $this->anmerkung, $anmerkung);
+ $this->anmerkung = $anmerkung;
+ return $this;
+ }
+
+ public function setGrundbetrag($grundbetrag)
+ {
+ if(is_float($grundbetrag))
+ {
+ $grundbetrag = number_format($grundbetrag, 2, '.', '');
+ }
+ $this->markDirty('grundbetrag', $this->grundbetrag, $grundbetrag);
+ $this->grundbetrag = $grundbetrag;
+ return $this;
+ }
+
+ public function setBetrag_valorisiert($betrag_valorisiert)
+ {
+ if(is_float($betrag_valorisiert))
+ {
+ $betrag_valorisiert = number_format($betrag_valorisiert, 2, '.', '');
+ }
+ $this->markDirty('betrag_valorisiert', $this->betrag_valorisiert, $betrag_valorisiert);
+ $this->betrag_valorisiert = $betrag_valorisiert;
+ return $this;
+ }
+
+ public function setValorisierungssperre($valorisierungssperre)
+ {
+ $this->markDirty('valorisierungssperre', $this->valorisierungssperre, $valorisierungssperre);
+ $this->valorisierungssperre = $valorisierungssperre;
+ return $this;
+ }
+
+ public function setValorisierung($valorisierung)
+ {
+ $this->markDirty('valorisierung', $this->valorisierung, $valorisierung);
+ $this->valorisierung = $valorisierung;
+ return $this;
+ }
+
+ public function setAuszahlungen($auszahlungen)
+ {
+ $this->markDirty('auszahlungen', $this->auszahlungen, $auszahlungen);
+ $this->auszahlungen = $auszahlungen;
+ return $this;
+ }
+
+ public function setInsertamum($insertamum)
+ {
+ $this->markDirty('insertamum', $this->insertamum, $insertamum);
+ $this->insertamum = $insertamum;
+ return $this;
+ }
+
+ public function setInsertvon($insertvon)
+ {
+ $this->markDirty('insertvon', $this->insertvon, $insertvon);
+ $this->insertvon = $insertvon;
+ return $this;
+ }
+
+ public function setUpdateamum($updateamum)
+ {
+ $this->markDirty('updateamum', $this->updateamum, $updateamum);
+ $this->updateamum = $updateamum;
+ return $this;
+ }
+
+ public function setUpdatevon($updatevon)
+ {
+ $this->markDirty('updatevon', $this->updatevon, $updatevon);
+ $this->updatevon = $updatevon;
+ return $this;
+ }
+
+ public function jsonSerialize()
+ {
+ $vars = get_object_vars($this);
+ unset($vars['CI']);
+ return $vars;
+ }
+
+ public function toStdClass(): \stdClass
+ {
+ $tmp = array(
+ 'gehaltsbestandteil_id' => $this->getGehaltsbestandteil_id(),
+ 'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(),
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'gehaltstyp_kurzbz' => $this->getGehaltstyp_kurzbz(),
+ 'von' => $this->getVon(),
+ 'bis' => $this->getBis(),
+ 'anmerkung' => $this->getAnmerkung(),
+ 'grundbetrag' => $this->getGrundbetrag(),
+ 'betrag_valorisiert' => $this->getBetrag_valorisiert(),
+ 'valorisierungssperre' => $this->getValorisierungssperre(),
+ 'valorisierung' => $this->getValorisierung(),
+ 'auszahlungen' => $this->getAuszahlungen(),
+ 'insertamum' => $this->getInsertamum(),
+ 'insertvon' => $this->getInsertvon(),
+ 'updateamum' => $this->getUpdateamum(),
+ 'updatevon' => $this->getUpdatevon()
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function __toString()
+ {
+ $txt = <<getGehaltsbestandteil_id()}
+ dienstverhaeltnis_id: {$this->getDienstverhaeltnis_id()}
+ vertragsbestandteil_id: {$this->getVertragsbestandteil_id()}
+ gehaltstyp_kurzbz: {$this->getGehaltstyp_kurzbz()}
+ von: {$this->getVon()}
+ bis: {$this->getBis()}
+ anmerkung: {$this->getAnmerkung()}
+ grundbetrag: {$this->getGrundbetrag()}
+ betrag_valorisiert: {$this->getBetrag_valorisiert()}
+ valorisierungssperre: {$this->getValorisierungssperre()}
+ valorisierung: {$this->getValorisierung()}
+ auszahlungen: {$this->getAuszahlungen()}
+ insertamum: {$this->getInsertamum()}
+ insertvon: {$this->getInsertvon()}
+ updateamum: {$this->getUpdateamum()}
+ updatevon: {$this->getUpdatevon()}
+
+EOTXT;
+ return $txt;
+ }
+
+ public function validate() {
+ //do Validation here
+ if( empty($this->gehaltstyp_kurzbz) )
+ {
+ $this->validationerrors[] = "Ein Gehaltstyp muss ausgewählt sein.";
+ }
+
+ if( empty($this->grundbetrag) )
+ {
+ $this->validationerrors[] = "Betrag fehlt.";
+ }
+
+ $von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von);
+ $bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis);
+
+ if( false === $von ) {
+ $this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.';
+ }
+
+ if( $this->bis !== null && $bis === false ) {
+ $this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.';
+ }
+
+ if( $this-> bis !== null && $von && $bis && $von > $bis ) {
+ $this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.';
+ }
+
+ // return status after Validation
+ if( count($this->validationerrors) > 0 ) {
+ $this->isvalid = false;
+ } else {
+ $this->isvalid = true;
+ }
+
+ return $this->isvalid;
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/GehaltsbestandteilLib.php b/application/libraries/vertragsbestandteil/GehaltsbestandteilLib.php
new file mode 100644
index 000000000..b75bdd722
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/GehaltsbestandteilLib.php
@@ -0,0 +1,149 @@
+loggedInUser = getAuthUID();
+ $this->CI = get_instance();
+ $this->CI->load->model('vertragsbestandteil/Gehaltsbestandteil_model',
+ 'GehaltsbestandteilModel');
+ $this->CI->load->library('extensions/FHC-Core-Personalverwaltung/abrechnung/GehaltsLib');
+ $this->GehaltsbestandteilModel = $this->CI->GehaltsbestandteilModel;
+ }
+
+ public function fetchGehaltsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false)
+ {
+ return $this->GehaltsbestandteilModel->getGehaltsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture);
+ }
+
+ public function fetchGehaltsbestandteil($gehaltsbestandteil_id)
+ {
+ return $this->GehaltsbestandteilModel->getGehaltsbestandteil($gehaltsbestandteil_id);
+ }
+
+ public function storeGehaltsbestandteile($gehaltsbestandteile)
+ {
+ foreach( $gehaltsbestandteile as $gehaltsbestandteil )
+ {
+ $this->storeGehaltsbestandteil($gehaltsbestandteil);
+ }
+ }
+
+ public function storeGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
+ {
+ try
+ {
+ $this->setUIDtoPGSQL();
+ if( intval($gehaltsbestandteil->getGehaltsbestandteil_id()) > 0 )
+ {
+ $this->updateGehaltsbestandteil($gehaltsbestandteil);
+ }
+ else
+ {
+ $this->insertGehaltsbestandteil($gehaltsbestandteil);
+ }
+ }
+ catch (Exception $ex)
+ {
+ log_message('debug', "Storing Gehaltsbestandteil failed. " . $ex->getMessage());
+ throw new Exception('Storing Gehaltsbestandteil failed.');
+ }
+ }
+
+ protected function insertGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
+ {
+ $gehaltsbestandteil->setInsertvon($this->loggedInUser)
+ ->setInsertamum(strftime('%Y-%m-%d %H:%M:%S'));
+ $ret = $this->GehaltsbestandteilModel->insert($gehaltsbestandteil->toStdClass(),
+ $this->GehaltsbestandteilModel->getEncryptedColumns());
+ if( hasData($ret) )
+ {
+ $gehaltsbestandteil->setGehaltsbestandteil_id(getData($ret));
+ }
+ else
+ {
+ throw new Exception('error inserting gehaltsbestandteil');
+ }
+ }
+
+ protected function updateGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
+ {
+ if(!$gehaltsbestandteil->isDirty()) {
+ return;
+ }
+
+ $gehaltsbestandteil->setUpdatevon($this->loggedInUser)
+ ->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S'));
+ $ret = $this->GehaltsbestandteilModel->update($gehaltsbestandteil->getGehaltsbestandteil_id(),
+ $gehaltsbestandteil->toStdClass(),
+ $this->GehaltsbestandteilModel->getEncryptedColumns());
+
+ if(isError($ret) )
+ {
+ throw new Exception('error updating gehaltsbestandteil');
+ }
+ }
+
+ public function deleteGehaltsbestandteile($gehaltsbestandteile)
+ {
+ foreach( $gehaltsbestandteile as $gehaltsbestandteil )
+ {
+ $this->deleteGehaltsbestandteil($gehaltsbestandteil);
+ }
+ }
+
+ public function deleteGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
+ {
+ $this->setUIDtoPGSQL();
+
+ // delete Gehaltsabrechnung
+ $ret = $this->CI->gehaltslib->deleteAbrechnung($gehaltsbestandteil);
+
+ //
+ $ret = $this->GehaltsbestandteilModel->delete($gehaltsbestandteil->getGehaltsbestandteil_id());
+
+ if (isError($ret))
+ {
+ throw new Exception('error deleting gehaltsbestandteil');
+ }
+ }
+
+ public function endGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil, $enddate)
+ {
+ $this->setUIDtoPGSQL();
+ if( $gehaltsbestandteil->getBis() !== null && $gehaltsbestandteil->getBis() < $enddate )
+ {
+ return;
+ }
+
+ $gehaltsbestandteil->setBis($enddate);
+ $this->updateGehaltsbestandteil($gehaltsbestandteil);
+ }
+
+ protected function setUIDtoPGSQL() {
+ $ret = $this->GehaltsbestandteilModel
+ ->execReadOnlyQuery('SET LOCAL pv21.uid TO \''
+ . $this->loggedInUser . '\'');
+ if(isError($ret))
+ {
+ throw new Exception('error setting uid to pgsql');
+ }
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/IValidation.php b/application/libraries/vertragsbestandteil/IValidation.php
new file mode 100644
index 000000000..c55e33bcd
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/IValidation.php
@@ -0,0 +1,18 @@
+CI = get_instance();
+ $this->CI->load->model('vertragsbestandteil/Vertragsbestandteil_model',
+ 'VertragsbestandteilModel');
+ $this->VertragsbestandteilModel = $this->CI->VertragsbestandteilModel;
+ $this->CI->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model',
+ 'VertragsbestandteilFreitextModel');
+ $this->VertragsbestandteilFreitextModel = $this->CI->VertragsbestandteilFreitextModel;
+ $this->CI->load->model('vertragsbestandteil/Vertragsbestandteiltyp_model',
+ 'VertragsbestandteilTypModel');
+ $this->VertragsbestandteilTypModel = $this->CI->VertragsbestandteilTypModel;
+ $this->CI->load->model('vertragsbestandteil/VertragsbestandteilFreitexttyp_model',
+ 'VertragsbestandteilFreitexttypModel');
+ $this->VertragsbestandteilFreitexttypModel = $this->CI->VertragsbestandteilFreitexttypModel;
+ }
+
+ public function overlapsVB(Vertragsbestandteil $vb)
+ {
+ $result = $this->VertragsbestandteilTypModel->load($vb->getVertragsbestandteiltyp_kurzbz());
+ if( null === ($vertragsbestandteiltyp = getData($result)) )
+ {
+ throw new Exception('vertragsbestandteiltyp: '
+ . $vb->getVertragsbestandteiltyp_kurzbz() . ' not found.');
+ }
+
+ if( true === $vertragsbestandteiltyp[0]->ueberlappend )
+ {
+ // vertragsbestandteiltyp can overlap
+ return false;
+ }
+
+ if( $this->VertragsbestandteilModel->countOverlappingVBsOfSameType($vb) === 0 )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ public function overlapsFreitext(VertragsbestandteilFreitext $vbft)
+ {
+ $result = $this->VertragsbestandteilFreitexttypModel->load($vbft->getFreitexttypKurzbz());
+ if( null === ($vertragsbestandteilfreitexttyp = getData($result)) )
+ {
+ throw new Exception('vertragsbestandteilfreitexttyp: '
+ . $vbft->getFreitexttypKurzbz() . ' not found.');
+ }
+
+ if( true === $vertragsbestandteilfreitexttyp[0]->ueberlappend )
+ {
+ // freitexttyp can overlap
+ return false;
+ }
+
+ if( $this->VertragsbestandteilFreitextModel->countOverlappingVBFreitextsOfSameType($vbft) === 0 )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ private function __clone() {}
+}
diff --git a/application/libraries/vertragsbestandteil/Vertragsbestandteil.php b/application/libraries/vertragsbestandteil/Vertragsbestandteil.php
new file mode 100644
index 000000000..bf5ec6211
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/Vertragsbestandteil.php
@@ -0,0 +1,265 @@
+gehaltsbestandteile = array();
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ $this->fromdb = $fromdb;
+ isset($data->vertragsbestandteil_id) && $this->setVertragsbestandteil_id($data->vertragsbestandteil_id);
+ isset($data->dienstverhaeltnis_id) && $this->setDienstverhaeltnis_id($data->dienstverhaeltnis_id);
+ isset($data->von) && $this->setVon($data->von);
+ isset($data->bis) && $this->setBis($data->bis);
+ isset($data->vertragsbestandteiltyp_kurzbz) && $this->setVertragsbestandteiltyp_kurzbz($data->vertragsbestandteiltyp_kurzbz);
+ isset($data->insertamum) && $this->setInsertamum($data->insertamum);
+ isset($data->insertvon) && $this->setInsertvon($data->insertvon);
+ isset($data->updateamum) && $this->setUpdateamum($data->updateamum);
+ isset($data->updatevon) && $this->setUpdatevon($data->updatevon);
+ $this->fromdb = false;
+ }
+
+ public function addGehaltsbestandteil(Gehaltsbestandteil $gehaltsbestandteil)
+ {
+ $gehaltsbestandteil->setDienstverhaeltnis_id($this->getDienstverhaeltnis_id());
+ $gehaltsbestandteil->setVertragsbestandteil_id($this->getVertragsbestandteil_id());
+ $this->gehaltsbestandteile[] = $gehaltsbestandteil;
+ return $this;
+ }
+
+ public function getGehaltsbestandteile()
+ {
+ return $this->gehaltsbestandteile;
+ }
+
+ public function getVertragsbestandteil_id()
+ {
+ return $this->vertragsbestandteil_id;
+ }
+
+ public function getDienstverhaeltnis_id()
+ {
+ return $this->dienstverhaeltnis_id;
+ }
+
+ public function getVon()
+ {
+ return $this->von;
+ }
+
+ public function getBis()
+ {
+ return $this->bis;
+ }
+
+ public function getVertragsbestandteiltyp_kurzbz()
+ {
+ return $this->vertragsbestandteiltyp_kurzbz;
+ }
+
+ public function getInsertamum()
+ {
+ return $this->insertamum;
+ }
+
+ public function getInsertvon()
+ {
+ return $this->insertvon;
+ }
+
+ public function getUpdateamum()
+ {
+ return $this->updateamum;
+ }
+
+ public function getUpdatevon()
+ {
+ return $this->updatevon;
+ }
+
+ public function setGehaltsbestandteile($gehaltsbestandteile)
+ {
+ $this->gehaltsbestandteile = $gehaltsbestandteile;
+ return $this;
+ }
+
+ public function setVertragsbestandteil_id($vertragsbestandteil_id)
+ {
+ $this->markDirty('vertragsbestandteil_id', $this->vertragsbestandteil_id, $vertragsbestandteil_id);
+ $this->vertragsbestandteil_id = $vertragsbestandteil_id;
+ foreach ($this->gehaltsbestandteile as $gehaltsbestandteil)
+ {
+ $gehaltsbestandteil->setVertragsbestandteil_id($vertragsbestandteil_id);
+ }
+ return $this;
+ }
+
+ public function setDienstverhaeltnis_id($dienstverhaeltnis_id)
+ {
+ $this->markDirty('dienstverhaeltnis_id', $this->dienstverhaeltnis_id, $dienstverhaeltnis_id);
+ $this->dienstverhaeltnis_id = $dienstverhaeltnis_id;
+ foreach ($this->gehaltsbestandteile as $gehaltsbestandteil)
+ {
+ $gehaltsbestandteil->setDienstverhaeltnis_id($dienstverhaeltnis_id);
+ }
+ return $this;
+ }
+
+ public function setVon($von)
+ {
+ $this->markDirty('von', $this->von, $von);
+ $this->von = $von;
+ return $this;
+ }
+
+ public function setBis($bis)
+ {
+ $this->markDirty('bis', $this->bis, $bis);
+ $this->bis = $bis;
+ return $this;
+ }
+
+ public function setVertragsbestandteiltyp_kurzbz($vertragsbestandteiltyp_kurzbz)
+ {
+ $this->markDirty('vertragsbestandteiltyp_kurzbz', $this->vertragsbestandteiltyp_kurzbz, $vertragsbestandteiltyp_kurzbz);
+ $this->vertragsbestandteiltyp_kurzbz = $vertragsbestandteiltyp_kurzbz;
+ return $this;
+ }
+
+ public function setInsertamum($insertamum)
+ {
+ $this->markDirty('insertamum', $this->insertamum, $insertamum);
+ $this->insertamum = $insertamum;
+ return $this;
+ }
+
+ public function setInsertvon($insertvon)
+ {
+ $this->markDirty('insertvon', $this->insertvon, $insertvon);
+ $this->insertvon = $insertvon;
+ return $this;
+ }
+
+ public function setUpdateamum($updateamum)
+ {
+ $this->markDirty('updateamum', $this->updateamum, $updateamum);
+ $this->updateamum = $updateamum;
+ return $this;
+ }
+
+ public function setUpdatevon($updatevon)
+ {
+ $this->markDirty('updatevon', $this->updatevon, $updatevon);
+ $this->updatevon = $updatevon;
+ return $this;
+ }
+
+ public function baseToStdClass() {
+ $tmp = array(
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'dienstverhaeltnis_id' => $this->getDienstverhaeltnis_id(),
+ 'von' => $this->getVon(),
+ 'bis' => $this->getBis(),
+ 'vertragsbestandteiltyp_kurzbz' => $this->getVertragsbestandteiltyp_kurzbz(),
+ 'insertamum' => $this->getInsertamum(),
+ 'insertvon' => $this->getInsertvon(),
+ 'updateamum' => $this->getUpdateamum(),
+ 'updatevon' => $this->getUpdatevon(),
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function jsonSerialize()
+ {
+ $vars = get_object_vars($this);
+ unset($vars['CI']);
+
+ // TODO cleanup workaroung for vb freitext where db column is anmerkung and formfield is freitext
+ if( isset($vars['anmerkung']) ) {
+ $vars['freitext'] = $vars['anmerkung'];
+ }
+
+ return $vars;
+ }
+
+ public function __toString()
+ {
+ return <<getVertragsbestandteil_id()}
+ dienstverhaeltnis_id: {$this->getDienstverhaeltnis_id()}
+ von: {$this->getVon()}
+ bis: {$this->getBis()}
+ vertragsbestandteiltyp_kurzbz: {$this->getVertragsbestandteiltyp_kurzbz()}
+ insertamum: {$this->getInsertamum()}
+ insertvon: {$this->getInsertvon()}
+ updateamum: {$this->getUpdateamum()}
+ updatevon: {$this->getUpdatevon()}
+
+EOTXT;
+
+ }
+
+ public function beforePersist() {
+ // can be overridden in childs
+ }
+
+ public function afterDelete() {
+ // can be overridden in childs
+ }
+
+ public function validate() {
+ $von = \DateTimeImmutable::createFromFormat('Y-m-d', $this->von);
+ $bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis);
+
+ if( false === $von ) {
+ $this->validationerrors[] = 'Beginn muss ein gültiges Datum sein.';
+ }
+
+ if( $this->bis !== null && $bis === false ) {
+ $this->validationerrors[] = 'Ende muss ein gültiges Datum oder leer sein.';
+ }
+
+ if( $this-> bis !== null && $von && $bis && $von > $bis ) {
+ $this->validationerrors[] = 'Das Beginndatum muss vor dem Endedatum liegen.';
+ }
+
+ if( count($this->validationerrors) > 0 ) {
+ $this->isvalid = false;
+ } else {
+ $this->isvalid = true;
+ }
+
+ return $this->isvalid;
+ }
+
+ public abstract function toStdClass();
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilFactory.php b/application/libraries/vertragsbestandteil/VertragsbestandteilFactory.php
new file mode 100644
index 000000000..6e7b0af06
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilFactory.php
@@ -0,0 +1,137 @@
+vertragsbestandteiltyp_kurzbz)
+ ? $data->vertragsbestandteiltyp_kurzbz : false;
+ if( false === $vertragsbestandteiltyp_kurzbz )
+ {
+ throw new Exception('Missing Parameter vertragsbestandteiltyp_kurzbz');
+ }
+
+ $vertragsbestandteil = null;
+ switch ($vertragsbestandteiltyp_kurzbz)
+ {
+ case self::VERTRAGSBESTANDTEIL_FREITEXT:
+ $vertragsbestandteil = new VertragsbestandteilFreitext();
+ $vertragsbestandteil->hydrateByStdClass($data, $fromdb);
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_FUNKTION:
+ $vertragsbestandteil = new VertragsbestandteilFunktion();
+ $vertragsbestandteil->hydrateByStdClass($data, $fromdb);
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_KARENZ:
+ $vertragsbestandteil = new VertragsbestandteilKarenz();
+ $vertragsbestandteil->hydrateByStdClass($data, $fromdb);
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST:
+ $vertragsbestandteil = new VertragsbestandteilKuendigungsfrist();
+ $vertragsbestandteil->hydrateByStdClass($data, $fromdb);
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_STUNDEN:
+ $vertragsbestandteil = new VertragsbestandteilStunden();
+ $vertragsbestandteil->hydrateByStdClass($data, $fromdb);
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH:
+ $vertragsbestandteil = new VertragsbestandteilUrlaubsanspruch();
+ $vertragsbestandteil->hydrateByStdClass($data, $fromdb);
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG:
+ $vertragsbestandteil = new VertragsbestandteilZeitaufzeichnung();
+ $vertragsbestandteil->hydrateByStdClass($data, $fromdb);
+ break;
+
+ default:
+ throw new Exception('Unknown vertragsbestandteiltyp_kurzbz '
+ . $vertragsbestandteiltyp_kurzbz);
+ }
+
+ return $vertragsbestandteil;
+ }
+
+ public static function getVertragsbestandteilDBModel($vertragsbestandteil_kurzbz): \DB_model
+ {
+ $CI = get_instance();
+
+ $vertragsbestandteildbmodel = null;
+ switch ($vertragsbestandteil_kurzbz)
+ {
+ case self::VERTRAGSBESTANDTEIL_FREITEXT:
+ $CI->load->model('vertragsbestandteil/VertragsbestandteilFreitext_model',
+ 'VertragsbestandteilFreitext_model');
+ $vertragsbestandteildbmodel = $CI->VertragsbestandteilFreitext_model;
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_FUNKTION:
+ $CI->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model',
+ 'VertragsbestandteilFunktion_model');
+ $vertragsbestandteildbmodel = $CI->VertragsbestandteilFunktion_model;
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_KARENZ:
+ $CI->load->model('vertragsbestandteil/VertragsbestandteilKarenz_model',
+ 'VertragsbestandteilKarenz_model');
+ $vertragsbestandteildbmodel = $CI->VertragsbestandteilKarenz_model;
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST:
+ $CI->load->model('vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model',
+ 'VertragsbestandteilKuendigungsfrist_model');
+ $vertragsbestandteildbmodel = $CI->VertragsbestandteilKuendigungsfrist_model;
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_STUNDEN:
+ $CI->load->model('vertragsbestandteil/VertragsbestandteilStunden_model',
+ 'VertragsbestandteilStunden_model');
+ $vertragsbestandteildbmodel = $CI->VertragsbestandteilStunden_model;
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH:
+ $CI->load->model('vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model',
+ 'VertragsbestandteilUrlaubsanspruch_model');
+ $vertragsbestandteildbmodel = $CI->VertragsbestandteilUrlaubsanspruch_model;
+ break;
+
+ case self::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG:
+ $CI->load->model('vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model',
+ 'VertragsbestandteilZeitaufzeichnung_model');
+ $vertragsbestandteildbmodel = $CI->VertragsbestandteilZeitaufzeichnung_model;
+ break;
+
+ default:
+ throw new Exception('Unknown vertragsbestandteil_kurzbz '
+ . $vertragsbestandteil_kurzbz);
+ }
+
+ return $vertragsbestandteildbmodel;
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilFreitext.php b/application/libraries/vertragsbestandteil/VertragsbestandteilFreitext.php
new file mode 100644
index 000000000..07e8a3c58
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilFreitext.php
@@ -0,0 +1,134 @@
+setVertragsbestandteiltyp_kurzbz(
+ VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FREITEXT);
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ parent::hydrateByStdClass($data, $fromdb);
+ $this->fromdb = $fromdb;
+ isset($data->freitexttyp) && $this->setFreitexttypKurzbz($data->freitexttyp);
+ isset($data->freitexttyp_kurzbz) && $this->setFreitexttypKurzbz($data->freitexttyp_kurzbz);
+ isset($data->titel) && $this->setTitel($data->titel);
+ isset($data->freitext) && $this->setAnmerkung($data->freitext);
+ isset($data->anmerkung) && $this->setAnmerkung($data->anmerkung);
+ $this->fromdb = false;
+ }
+
+ public function toStdClass(): \stdClass
+ {
+ $tmp = array(
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'freitexttyp_kurzbz' => $this->getFreitexttypKurzbz(),
+ 'titel' => $this->getTitel(),
+ 'anmerkung' => $this->getAnmerkung()
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function __toString()
+ {
+ $txt = <<getAnmerkung()}
+ titel: {$this->getTitel()}
+ freitexttyp_kurzbz: {$this->getFreitexttypKurzbz()}
+
+EOTXT;
+ return parent::__toString() . $txt;
+ }
+
+ /**
+ * Get the value of anmerkung
+ */
+ public function getAnmerkung()
+ {
+ return $this->anmerkung;
+ }
+
+ /**
+ * Set the value of anmerkung
+ */
+ public function setAnmerkung($anmerkung): self
+ {
+ $this->markDirty('anmerkung', $this->anmerkung, $anmerkung);
+ $this->anmerkung = $anmerkung;
+
+ return $this;
+ }
+
+ /**
+ * Get the value of titel
+ */
+ public function getTitel()
+ {
+ return $this->titel;
+ }
+
+ /**
+ * Set the value of titel
+ */
+ public function setTitel($titel): self
+ {
+ $this->markDirty('titel', $this->titel, $titel);
+ $this->titel = $titel;
+
+ return $this;
+ }
+
+ /**
+ * Get the value of freitexttyp_kurzbz
+ */
+ public function getFreitexttypKurzbz()
+ {
+ return $this->freitexttyp_kurzbz;
+ }
+
+ /**
+ * Set the value of freitexttyp_kurzbz
+ */
+ public function setFreitexttypKurzbz($freitexttyp_kurzbz): self
+ {
+ $this->markDirty('freitexttyp_kurzbz', $this->freitexttyp_kurzbz, $freitexttyp_kurzbz);
+ $this->freitexttyp_kurzbz = $freitexttyp_kurzbz;
+
+ return $this;
+ }
+
+ public function validate()
+ {
+ if( empty($this->freitexttyp_kurzbz) ) {
+ $this->validationerrors[] = 'Bitte einen gültigen Freitexttyp auswählen.';
+ }
+
+ if( empty($this->titel) ) {
+ $this->validationerrors[] = 'Bitte einen Titel angeben.';
+ }
+
+ if( empty($this->anmerkung) ) {
+ $this->validationerrors[] = 'Bitte eine Beschreibung eingeben.';
+ }
+
+ return parent::validate();
+ }
+
+
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilFunktion.php b/application/libraries/vertragsbestandteil/VertragsbestandteilFunktion.php
new file mode 100644
index 000000000..ee5cd713f
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilFunktion.php
@@ -0,0 +1,369 @@
+benutzerfunktiondata = null;
+
+ $this->setVertragsbestandteiltyp_kurzbz(
+ VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_FUNKTION);
+
+ $this->CI = get_instance();
+ $this->CI->load->model('person/Benutzerfunktion_model',
+ 'BenutzerfunktionModel');
+ $this->CI->load->model('vertragsbestandteil/VertragsbestandteilFunktion_model',
+ 'VertragsbestandteilFunktionModel');
+ $this->CI->load->library('vertragsbestandteil/VertragsbestandteilLib',
+ null, 'VertragsbestandteilLib');
+ }
+
+ public function isDirty()
+ {
+ $isdirty = parent::isDirty();
+ if( !$isdirty ) {
+ $bf = $this->loadBenutzerfunktion($this->getBenutzerfunktion_id());
+ if( !$this->areVbAndBfInSync($bf) )
+ {
+ $isdirty = true;
+ }
+ }
+ return $isdirty;
+ }
+
+ public function beforePersist()
+ {
+ if( isset($this->benutzerfunktion_id) && intval($this->benutzerfunktion_id) > 0 )
+ {
+ $this->beforePersitExisting();
+ }
+ else
+ {
+ $this->beforePersitNew();
+ }
+ }
+
+ protected function loadBenutzerfunktion($bfid)
+ {
+ $bfres = $this->CI->BenutzerfunktionModel->load($bfid);
+ if(!hasData($bfres))
+ {
+ throw new Exception('failed to load existing Benutzerfunktion');
+ }
+ return (getData($bfres))[0];
+ }
+
+ protected function loadPersitedVB($vbid)
+ {
+ $vb = $this->CI->VertragsbestandteilLib->fetchVertragsbestandteil($vbid);
+ if( $vb === null )
+ {
+ throw new Exception('failed to load persited Vertragsbestandteil');
+ }
+ return $vb;
+ }
+
+ protected function areVbAndBfInSync($bf)
+ {
+ $vbvon = $this->getVon();
+ $vbbis = $this->getBis();
+ if( intval($this->getVertragsbestandteil_id()) > 0 )
+ {
+ $vb = $this->loadPersitedVB($this->getVertragsbestandteil_id());
+ $vbvon = $vb->getVon();
+ $vbbis = $vb->getBis();
+ }
+
+ if( ($bf->datum_von === $vbvon) && ($bf->datum_bis === $vbbis) )
+ {
+ return true;
+ }
+ return false;
+ }
+
+ protected function isBefore($a, $b)
+ {
+ if($a === null) {
+ return false;
+ }
+ elseif($b === null) {
+ return true;
+ }
+ else {
+ return $a < $b;
+ }
+ }
+
+ protected function isAfter($a, $b)
+ {
+ if($b === null) {
+ return false;
+ }
+ elseif($a === null) {
+ return true;
+ }
+ else {
+ return $a > $b;
+ }
+ }
+
+ protected function beforePersitExisting()
+ {
+ $bf = $this->loadBenutzerfunktion($this->getBenutzerfunktion_id());
+ if( $this->areVbAndBfInSync($bf) )
+ {
+ // vb or stored vb von bis is in sync so update benutzerfunktion
+ $this->updateBenutzerfunktion($bf, $this->getVon(), $this->getBis());
+ }
+ else
+ {
+ $daybeforevon = \DateTime::createFromFormat('Y-m-d', $this->getVon(),
+ new \DateTimeZone('Europe/Vienna'));
+ $daybeforevon->sub(new \DateInterval('P1D'));
+
+ if( $this->isBefore($bf->datum_von, $this->getVon()) &&
+ $this->isBefore($bf->datum_von, $this->getBis()) )
+ {
+ $data = (object) array(
+ 'mitarbeiter_uid' => $bf->uid,
+ 'funktion' => $bf->funktion_kurzbz,
+ 'orget' => $bf->oe_kurzbz
+ );
+ $this->createBenutzerfunktionData($data);
+ $bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert());
+ $this->setBenutzerfunktion_id($bfid);
+ }
+ elseif( $this->isBefore($bf->datum_von, $this->getVon()) &&
+ $this->isAfter($this->getBis(), $bf->datum_von) )
+ {
+ $this->updateBenutzerfunktion($bf, $bf->datum_von, $daybeforevon->format('Y-m-d'));
+ $data = (object) array(
+ 'mitarbeiter_uid' => $bf->uid,
+ 'funktion' => $bf->funktion_kurzbz,
+ 'orget' => $bf->oe_kurzbz
+ );
+ $this->createBenutzerfunktionData($data);
+ $bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert());
+ $this->setBenutzerfunktion_id($bfid);
+ }
+ else
+ {
+ $this->updateBenutzerfunktion($bf, $this->getVon(), $this->getBis());
+ }
+ }
+ }
+
+ protected function updateBenutzerfunktion($bf, $von, $bis)
+ {
+ $data = array();
+
+ if($von !== $bf->datum_von)
+ {
+ $data['datum_von'] = $von;
+ }
+ if($bis !== $bf->datum_bis)
+ {
+ $data['datum_bis'] = $bis;
+ }
+
+ if( count($data) === 0 )
+ {
+ return;
+ }
+
+ $data['updateamum'] = strftime('%Y-%m-%d %H:%M:%S');
+ $data['updatevon'] = getAuthUID();
+
+ $ret = $this->CI->BenutzerfunktionModel->update($bf->benutzerfunktion_id, $data);
+
+ if(isError($ret) )
+ {
+ throw new Exception('failed to update Benutzerfunktion');
+ }
+ }
+
+ protected function insertBenutzerfunktion($benutzerfunktiondata)
+ {
+ $ret = $this->CI->BenutzerfunktionModel->insert($benutzerfunktiondata);
+
+ if(isError($ret) )
+ {
+ throw new Exception('failed to create Benutzerfunktion');
+ }
+
+ return getData($ret);
+ }
+
+ protected function deleteBenutzerfunktion($benutzerfunktion_id)
+ {
+ $ret = $this->CI->BenutzerfunktionModel->delete($benutzerfunktion_id);
+
+ if(isError($ret) )
+ {
+ throw new Exception('failed to delete Benutzerfunktion');
+ }
+ }
+
+ protected function beforePersitNew() {
+ if( $this->benutzerfunktiondata === null)
+ {
+ return;
+ }
+
+ $bfid = $this->insertBenutzerfunktion($this->getBenutzerfunktionData4Insert());
+
+ $this->setBenutzerfunktion_id($bfid);
+ }
+
+ public function afterDelete()
+ {
+ if( !(intval($this->getBenutzerfunktion_id()) > 0) )
+ {
+ return;
+ }
+
+ $this->deleteBenutzerfunktion($this->getBenutzerfunktion_id());
+ }
+
+ public function toStdClass()
+ {
+ $tmp = array(
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'benutzerfunktion_id' => $this->getBenutzerfunktion_id()
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function __toString()
+ {
+ $txt = <<getBenutzerfunktion_id()}
+
+EOTXT;
+ return parent::__toString() . $txt;
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ parent::hydrateByStdClass($data, $fromdb);
+ $this->fromdb = $fromdb;
+ isset($data->benutzerfunktionid) && $this->setBenutzerfunktion_id($data->benutzerfunktionid);
+ isset($data->benutzerfunktion_id) && $this->setBenutzerfunktion_id($data->benutzerfunktion_id);
+ isset($data->funktion) && isset($data->orget)
+ && isset($data->mitarbeiter_uid) && $this->createBenutzerfunktionData($data);
+ isset($data->funktion_bezeichnung) && isset($data->oe_bezeichnung)
+ && $this->createBenutzerfunktionData4Display($data);
+ $this->fromdb = false;
+
+ }
+
+ public function getBenutzerfunktion_id()
+ {
+ return $this->benutzerfunktion_id;
+ }
+
+ public function setBenutzerfunktion_id($benutzerfunktion_id)
+ {
+ $this->markDirty('benutzerfunktion_id', $this->benutzerfunktion_id, $benutzerfunktion_id);
+ $this->benutzerfunktion_id = $benutzerfunktion_id;
+ return $this;
+ }
+
+ protected function getBenutzerfunktionData4Insert()
+ {
+ if( null === $this->benutzerfunktiondata ) {
+ return null;
+ }
+
+ $benutzerfunktiondata = (object) array(
+ 'funktion_kurzbz' => $this->benutzerfunktiondata->funktion_kurzbz,
+ 'oe_kurzbz' => $this->benutzerfunktiondata->oe_kurzbz,
+ 'uid' => $this->benutzerfunktiondata->uid,
+ 'datum_von' => $this->getVon(),
+ 'datum_bis' => $this->getBis(),
+ 'insertamum' => strftime('%Y-%m-%d %H:%M:%S'),
+ 'insertvon' => getAuthUID()
+ );
+
+ return $benutzerfunktiondata;
+ }
+
+ protected function createBenutzerfunktionData($data)
+ {
+ if( empty($data->funktion) || empty($data->orget) )
+ {
+ return;
+ }
+
+ $this->benutzerfunktiondata = (object) array(
+ 'funktion_kurzbz' => $data->funktion,
+ 'oe_kurzbz' => $data->orget,
+ 'uid' => $data->mitarbeiter_uid
+ );
+ }
+
+ protected function createBenutzerfunktionData4Display($data)
+ {
+ if( empty($data->funktion_bezeichnung) || empty($data->oe_bezeichnung) )
+ {
+ return;
+ }
+
+ $this->benutzerfunktiondata = (object) array(
+ 'funktion_kurzbz' => $data->funktion_kurzbz,
+ 'funktion_bezeichnung' => $data->funktion_bezeichnung,
+ 'oe_kurzbz' => $data->oe_kurzbz,
+ 'oe_bezeichnung' => $data->oe_bezeichnung,
+ 'oe_kurzbz_sap' => $data->oe_kurzbz_sap,
+ 'oe_typ_kurzbz' => $data->oe_typ_kurzbz,
+ 'oe_typ_bezeichnung' => $data->oe_typ_bezeichnung,
+ 'uid' => $data->mitarbeiter_uid
+ );
+ }
+
+ public function validate()
+ {
+ if( (intval($this->benutzerfunktion_id) < 1)
+ && ($this->benutzerfunktiondata === NULL) ) {
+ $this->validationerrors[] = 'Eine bestehende Funktion oder eine '
+ . 'Funktion und eine Organisationseinheit müssen ausgewählt sein.';
+ }
+
+ // TODO check if Benutzerfunktion is assigned to another vb
+ if( intval($this->benutzerfunktion_id) > 0 )
+ {
+ if ( $this->CI->VertragsbestandteilFunktionModel
+ ->isBenutzerfunktionAlreadyAttachedToAnotherVB(
+ $this->benutzerfunktion_id,
+ $this->getVertragsbestandteil_id()) )
+ {
+ $this->validationerrors[] = 'Die Benutzerfunktion ist bereits '
+ . 'mit einem anderen Vertragsbestandteil verknüpft und kann '
+ . 'nicht mehrfach verknüft werden.';
+ }
+ }
+
+ return parent::validate();
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilKarenz.php b/application/libraries/vertragsbestandteil/VertragsbestandteilKarenz.php
new file mode 100644
index 000000000..7b49bfe4c
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilKarenz.php
@@ -0,0 +1,141 @@
+setVertragsbestandteiltyp_kurzbz(
+ VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_KARENZ);
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ parent::hydrateByStdClass($data, $fromdb);
+ $this->fromdb = $fromdb;
+ isset($data->karenztyp_kurzbz) && $this->setKarenztypKurzbz($data->karenztyp_kurzbz);
+ isset($data->geplanter_geburtstermin) && $this->setGeplanterGeburtstermin($data->geplanter_geburtstermin);
+ isset($data->tatsaechlicher_geburtstermin) && $this->setTatsaechlicherGeburtstermin($data->tatsaechlicher_geburtstermin);
+ $this->fromdb = false;
+ }
+
+ /**
+ * Get the value of karenztyp_kurzbz
+ */
+ public function getKarenztypKurzbz()
+ {
+ return $this->karenztyp_kurzbz;
+ }
+
+ /**
+ * Set the value of karenztyp_kurzbz
+ */
+ public function setKarenztypKurzbz($karenztyp_kurzbz): self
+ {
+ $this->markDirty('karenztyp_kurzbz', $this->karenztyp_kurzbz, $karenztyp_kurzbz);
+ $this->karenztyp_kurzbz = $karenztyp_kurzbz;
+
+ return $this;
+ }
+
+ /**
+ * Get the value of tatsaechlicher_geburtstermin
+ */
+ public function getTatsaechlicherGeburtstermin()
+ {
+ return $this->tatsaechlicher_geburtstermin;
+ }
+
+ /**
+ * Set the value of tatsaechlicher_geburtstermin
+ */
+ public function setTatsaechlicherGeburtstermin($tatsaechlicher_geburtstermin): self
+ {
+ $this->markDirty('tatsaechlicher_geburtstermin', $this->tatsaechlicher_geburtstermin, $tatsaechlicher_geburtstermin);
+ $this->tatsaechlicher_geburtstermin = $tatsaechlicher_geburtstermin;
+
+ return $this;
+ }
+
+ /**
+ * Get the value of geplanter_geburtstermin
+ */
+ public function getGeplanterGeburtstermin()
+ {
+ return $this->geplanter_geburtstermin;
+ }
+
+ /**
+ * Set the value of geplanter_geburtstermin
+ */
+ public function setGeplanterGeburtstermin($geplanter_geburtstermin): self
+ {
+ $this->markDirty('geplanter_geburtstermin', $this->geplanter_geburtstermin, $geplanter_geburtstermin);
+ $this->geplanter_geburtstermin = $geplanter_geburtstermin;
+
+ return $this;
+ }
+
+ public function toStdClass(): \stdClass
+ {
+ $tmp = array(
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'karenztyp_kurzbz' => $this->getKarenztypKurzbz(),
+ 'tatsaechlicher_geburtstermin' => $this->getTatsaechlicherGeburtstermin(),
+ 'geplanter_geburtstermin' => $this->getGeplanterGeburtstermin()
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function __toString()
+ {
+ $txt = <<getKarenztypKurzbz()}
+ tatsaechlicher_geburtstermin: {$this->getTatsaechlicherGeburtstermin()}
+ geplanter_geburtstermin: {$this->getGeplanterGeburtstermin()}
+
+EOTXT;
+ return parent::__toString() . $txt;
+ }
+
+ public function validate()
+ {
+ if( empty($this->karenztyp_kurzbz) ) {
+ $this->validationerrors[] = 'Ein Karenztyp muss ausgewählt sein.';
+ }
+
+ if( $this->karenztyp_kurzbz === 'elternkarenz' ) {
+ $geplant = \DateTimeImmutable::createFromFormat('Y-m-d', $this->geplanter_geburtstermin);
+ $tatsaechlich = \DateTimeImmutable::createFromFormat('Y-m-d', $this->tatsaechlicher_geburtstermin);
+
+ if( false === $geplant ) {
+ $this->validationerrors[] = 'Bei Elternkarenz muss der geplanter Geburtstermin ein gültiges Datum sein.';
+ }
+
+ if( !empty($this->tatsaechlicher_geburtstermin) && $tatsaechlich === false ) {
+ $this->validationerrors[] = 'Bei Elternkarenz muss der tatsaechliche Geburtstermin leer oder ein gültiges Datum sein.';
+ }
+ }
+
+ $bis = \DateTimeImmutable::createFromFormat('Y-m-d', $this->bis);
+
+ if( false === $bis ) {
+ $this->validationerrors[] = 'Bei einer Karenz muss ein gültiges Ende-Datum angegeben werden.';
+ }
+
+ return parent::validate();
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilKuendigungsfrist.php b/application/libraries/vertragsbestandteil/VertragsbestandteilKuendigungsfrist.php
new file mode 100644
index 000000000..81ea0dcec
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilKuendigungsfrist.php
@@ -0,0 +1,117 @@
+setVertragsbestandteiltyp_kurzbz(
+ VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_KUENDIGUNGSFRIST);
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ parent::hydrateByStdClass($data, $fromdb);
+ $this->fromdb = $fromdb;
+ isset($data->arbeitgeber_frist) && $this->setArbeitgeberFrist($data->arbeitgeber_frist);
+ isset($data->arbeitnehmer_frist) && $this->setArbeitnehmerFrist($data->arbeitnehmer_frist);
+ $this->fromdb = false;
+ }
+
+ /**
+ * Get the value of arbeitgeber_frist
+ */
+ public function getArbeitgeberFrist()
+ {
+ return $this->arbeitgeber_frist;
+ }
+
+ /**
+ * Set the value of arbeitgeber_frist
+ */
+ public function setArbeitgeberFrist($arbeitgeber_frist): self
+ {
+ $this->markDirty('arbeitgeber_frist', $this->arbeitgeber_frist, $arbeitgeber_frist);
+ $this->arbeitgeber_frist = $arbeitgeber_frist;
+
+ return $this;
+ }
+
+ /**
+ * Get the value of arbeitnehmer_frist
+ */
+ public function getArbeitnehmerFrist()
+ {
+ return $this->arbeitnehmer_frist;
+ }
+
+ /**
+ * Set the value of arbeitnehmer_frist
+ */
+ public function setArbeitnehmerFrist($arbeitnehmer_frist): self
+ {
+ $this->markDirty('arbeitnehmer_frist', $this->arbeitnehmer_frist, $arbeitnehmer_frist);
+ $this->arbeitnehmer_frist = $arbeitnehmer_frist;
+
+ return $this;
+ }
+
+ public function toStdClass(): \stdClass
+ {
+ $tmp = array(
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'arbeitgeber_frist' => $this->getArbeitgeberFrist(),
+ 'arbeitnehmer_frist' => $this->getArbeitnehmerFrist()
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function __toString()
+ {
+ $txt = <<getArbeitgeberFrist()}
+ arbeitnehmer_frist: {$this->getArbeitnehmerFrist()}
+
+EOTXT;
+ return parent::__toString() . $txt;
+ }
+
+ public function validate()
+ {
+ if( !(filter_var($this->arbeitgeber_frist, FILTER_VALIDATE_INT,
+ array(
+ 'options' => array(
+ 'min_range' => 0,
+ 'max_range' => 52
+ )
+ )
+ )) ) {
+ $this->validationerrors[] = 'Arbeitgeberfrist muss eine Wochenanzahl im Bereich 1 bis 52 sein.';
+ }
+
+ if( !(filter_var($this->arbeitnehmer_frist, FILTER_VALIDATE_INT,
+ array(
+ 'options' => array(
+ 'min_range' => 1,
+ 'max_range' => 52
+ )
+ )
+ )) ) {
+ $this->validationerrors[] = 'Arbeitnehmerfrist muss eine Wochenanzahl im Bereich 1 bis 52 sein.';
+ }
+
+ return parent::validate();
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilLib.php b/application/libraries/vertragsbestandteil/VertragsbestandteilLib.php
new file mode 100644
index 000000000..b58c514e1
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilLib.php
@@ -0,0 +1,512 @@
+loggedInUser = getAuthUID();
+ $this->CI = get_instance();
+ $this->CI->load->model('vertragsbestandteil/Dienstverhaeltnis_model',
+ 'DienstverhaeltnisModel');
+ $this->DienstverhaeltnisModel = $this->CI->DienstverhaeltnisModel;
+ $this->CI->load->model('vertragsbestandteil/Vertragsbestandteil_model',
+ 'VertragsbestandteilModel');
+ $this->VertragsbestandteilModel = $this->CI->VertragsbestandteilModel;
+ $this->CI->load->model('person/benutzer_model',
+ 'BenutzerModel');
+ $this->BenutzerModel = $this->CI->BenutzerModel;
+ $this->CI->load->library('vertragsbestandteil/GehaltsbestandteilLib',
+ null, 'GehaltsbestandteilLib');
+ $this->GehaltsbestandteilLib = $this->CI->GehaltsbestandteilLib;
+ }
+
+ public function handleGUIData($guidata, $employeeUID, $userUID)
+ {
+ $guiHandler = new GUIHandler($employeeUID, $userUID);
+ $ret = false;
+ try {
+ $ret = $guiHandler->handle($guidata, $employeeUID, $userUID);
+ } catch (Exception $ex)
+ {
+ log_message('debug', "Error handling json data from GUI. " . $ex->getMessage());
+ }
+
+ return $ret;
+ }
+
+ public function fetchDienstverhaeltnisse($unternehmen, $stichtag=null, $mitarbeiteruid=null) {
+ $dvs = $this->DienstverhaeltnisModel->fetchDienstverhaeltnisse($unternehmen, $stichtag, $mitarbeiteruid);
+ return $dvs;
+ }
+
+ public function fetchDienstverhaeltnis($dienstverhaeltnis_id)
+ {
+ $result = $this->DienstverhaeltnisModel->load($dienstverhaeltnis_id);
+ $dv = null;
+ if(null !== ($row = getData($result)))
+ {
+ $dv = new Dienstverhaeltnis();
+ $dv->hydrateByStdClass($row[0], true);
+ }
+ return $dv;
+ }
+
+ public function fetchVertragsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false)
+ {
+ $vbs = $this->VertragsbestandteilModel->getVertragsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture);
+ $gbs = $this->GehaltsbestandteilLib->fetchGehaltsbestandteile($dienstverhaeltnis_id, $stichtag, $includefuture);
+
+ $gbsByVBid = array();
+ foreach( $gbs as $gb )
+ {
+ if( intval($gb->getVertragsbestandteil_id()) > 0 )
+ {
+ if( !isset($gbsByVBid[$gb->getVertragsbestandteil_id()])
+ || !is_array($gbsByVBid[$gb->getVertragsbestandteil_id()]) ) {
+ $gbsByVBid[$gb->getVertragsbestandteil_id()] = array();
+ }
+ $gbsByVBid[$gb->getVertragsbestandteil_id()][] = $gb;
+ }
+ }
+
+ foreach ($vbs as $vb)
+ {
+ if( isset($gbsByVBid[$vb->getVertragsbestandteil_id()]) )
+ {
+ $vb->setGehaltsbestandteile($gbsByVBid[$vb->getVertragsbestandteil_id()]);
+ }
+ }
+
+ return $vbs;
+ }
+
+ public function fetchVertragsbestandteil($vertragsbestandteil_id)
+ {
+ return $this->VertragsbestandteilModel->getVertragsbestandteil($vertragsbestandteil_id);
+ }
+
+ public function storeDienstverhaeltnis(Dienstverhaeltnis $dv)
+ {
+ if( intval($dv->getDienstverhaeltnis_id()) > 0 )
+ {
+ $this->updateDienstverhaeltnis($dv);
+ }
+ else
+ {
+ $this->insertDienstverhaeltnis($dv);
+ }
+ }
+
+ public function storeVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil)
+ {
+ $this->CI->db->trans_begin();
+ try
+ {
+ $this->setUIDtoPGSQL();
+ if( intval($vertragsbestandteil->getVertragsbestandteil_id()) > 0 )
+ {
+ $this->updateVertragsbestandteil($vertragsbestandteil);
+ }
+ else
+ {
+ $this->insertVertragsbestandteil($vertragsbestandteil);
+ }
+ if( $this->CI->db->trans_status() === false )
+ {
+ log_message('debug', "Transaction failed");
+ throw new Exception("Transaction failed");
+ }
+ $this->CI->db->trans_commit();
+ }
+ catch (Exception $ex)
+ {
+ log_message('debug', "Transaction rolled back. " . $ex->getMessage());
+ $this->CI->db->trans_rollback();
+ throw new Exception('Storing Vertragsbestandteil failed.');
+ }
+ }
+
+ public function deleteDienstverhaeltnis(Dienstverhaeltnis $dv)
+ {
+ $this->CI->db->trans_begin();
+ try
+ {
+ $this->setUIDtoPGSQL();
+ if( intval($dv->getDienstverhaeltnis_id()) > 0 )
+ {
+ $vbs = $this->fetchVertragsbestandteile($dv->getDienstverhaeltnis_id());
+ foreach ($vbs as $vb)
+ {
+ $this->deleteVertragsbestandteil($vb);
+ }
+
+ $ret = $this->DienstverhaeltnisModel->delete($dv->getDienstverhaeltnis_id());
+ if(isError($ret) )
+ {
+ log_message('debug', "Delete DV failed");
+ throw new Exception('error deleting dienstverhaeltnis '
+ . $dv->getDienstverhaeltnis_id());
+ }
+
+ if( $this->CI->db->trans_status() === false )
+ {
+ log_message('debug', "Transaction failed");
+ throw new Exception("Transaction failed");
+ }
+ $this->CI->db->trans_commit();
+ }
+ }
+ catch (Exception $ex)
+ {
+ log_message('debug', "Transaction rolled back. " . $ex->getMessage());
+ $this->CI->db->trans_rollback();
+ return $ex->getMessage();
+ }
+
+ return true;
+
+ }
+
+ public function deleteVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil)
+ {
+ $this->CI->db->trans_begin();
+ try
+ {
+ $this->setUIDtoPGSQL();
+ if( intval($vertragsbestandteil->getVertragsbestandteil_id()) > 0 )
+ {
+ $this->deleteVertragsbestandteilHelper($vertragsbestandteil);
+ }
+ if( $this->CI->db->trans_status() === false )
+ {
+ log_message('debug', "Transaction failed");
+ throw new Exception("Transaction failed");
+ }
+ $this->CI->db->trans_commit();
+ }
+ catch (Exception $ex)
+ {
+ log_message('debug', "Transaction rolled back. " . $ex->getMessage());
+ $this->CI->db->trans_rollback();
+ throw new Exception('Delete Vertragsbestandteil failed.');
+ }
+ }
+
+ protected function insertDienstverhaeltnis(Dienstverhaeltnis $dv)
+ {
+ $dv->setInsertvon($this->loggedInUser)
+ ->setInsertamum(strftime('%Y-%m-%d %H:%M:%S'));
+ $ret = $this->DienstverhaeltnisModel->insert($dv->toStdClass());
+ if( hasData($ret) )
+ {
+ $dv->setDienstverhaeltnis_id(getData($ret));
+ }
+ else
+ {
+ throw new Exception('error inserting dienstverhaeltnis');
+ }
+ }
+
+ protected function insertVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil)
+ {
+ $vertragsbestandteil->setInsertvon($this->loggedInUser)
+ ->setInsertamum(strftime('%Y-%m-%d %H:%M:%S'));
+ $vertragsbestandteil->beforePersist();
+ $ret = $this->VertragsbestandteilModel->insert($vertragsbestandteil->baseToStdClass());
+ if( hasData($ret) )
+ {
+ $vertragsbestandteil->setVertragsbestandteil_id(getData($ret));
+ }
+ else
+ {
+ throw new Exception('error inserting vertragsbestandteil');
+ }
+
+ $specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel(
+ $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
+ $retspecial = $specialisedModel->insert($vertragsbestandteil->toStdClass());
+
+ if(isError($retspecial) )
+ {
+ throw new Exception('error updating vertragsbestandteil '
+ . $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
+ }
+
+ try
+ {
+ $gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile();
+ $this->GehaltsbestandteilLib->storeGehaltsbestandteile($gehaltsbestandteile);
+ }
+ catch(Exception $ex)
+ {
+ throw new Exception('VertragsbestandteilLib insertVertragsbestandteil '
+ . 'failed to store Gehaltsbestandteile. ' . $ex->getMessage());
+ }
+ }
+
+ protected function updateDienstverhaeltnis(Dienstverhaeltnis $dv)
+ {
+ if(!$dv->isDirty()) {
+ return;
+ }
+
+ $dv->setUpdatevon($this->loggedInUser)
+ ->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S'));
+ $ret = $this->DienstverhaeltnisModel->update($dv->getDienstverhaeltnis_id(),
+ $dv->toStdClass());
+ if(isError($ret) )
+ {
+ throw new Exception('error updating dienstverhaeltnis');
+ }
+ }
+
+ private function deleteVertragsbestandteilHelper(Vertragsbestandteil $vertragsbestandteil)
+ {
+
+ $specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel(
+ $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
+ $retspecial = $specialisedModel->delete($vertragsbestandteil->getVertragsbestandteil_id());
+
+ if(isError($retspecial) )
+ {
+ throw new Exception('error deleting vertragsbestandteil '
+ . $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
+ }
+
+ try
+ {
+ $gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile();
+ $this->GehaltsbestandteilLib->deleteGehaltsbestandteile($gehaltsbestandteile);
+ }
+ catch(Exception $ex)
+ {
+ throw new Exception('VertragsbestandteilLib deleteVertragsbestandteil '
+ . 'failed to delete Gehaltsbestandteile. ' . $ex->getMessage());
+ }
+
+
+ $ret = $this->VertragsbestandteilModel->delete($vertragsbestandteil->getVertragsbestandteil_id());
+
+ if(isError($ret) )
+ {
+ throw new Exception('error deleting vertragsbestandteil');
+ }
+
+ $vertragsbestandteil->afterDelete();
+ }
+
+ protected function updateVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil)
+ {
+ if($vertragsbestandteil->isDirty()) {
+ $vertragsbestandteil->setUpdatevon($this->loggedInUser)
+ ->setUpdateamum(strftime('%Y-%m-%d %H:%M:%S'));
+ $vertragsbestandteil->beforePersist();
+ $basedata = $vertragsbestandteil->baseToStdClass();
+ if( count((array) $basedata) > 0 )
+ {
+ $ret = $this->VertragsbestandteilModel->update(
+ $vertragsbestandteil->getVertragsbestandteil_id(),
+ $basedata);
+
+ if(isError($ret) )
+ {
+ throw new Exception('error updating vertragsbestandteil');
+ }
+ }
+
+ $specialisedData = $vertragsbestandteil->toStdClass();
+ if( count((array) $specialisedData) > 0 )
+ {
+ $specialisedModel = VertragsbestandteilFactory::getVertragsbestandteilDBModel(
+ $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
+ $retspecial = $specialisedModel->update(
+ $vertragsbestandteil->getVertragsbestandteil_id(),
+ $specialisedData);
+
+ if(isError($retspecial) )
+ {
+ throw new Exception('error updating vertragsbestandteil '
+ . $vertragsbestandteil->getVertragsbestandteiltyp_kurzbz());
+ }
+ }
+ }
+
+ try
+ {
+ $gehaltsbestandteile = $vertragsbestandteil->getGehaltsbestandteile();
+ $this->GehaltsbestandteilLib->storeGehaltsbestandteile($gehaltsbestandteile);
+ }
+ catch(Exception $ex)
+ {
+ throw new Exception('VertragsbestandteilLib updateVertragsbestandteil '
+ . 'failed to store Gehaltsbestandteile. ' . $ex->getMessage());
+ }
+ }
+
+ public function isOverlappingExistingDV(Dienstverhaeltnis $dv)
+ {
+ return $this->DienstverhaeltnisModel->isOverlappingExistingDV(
+ $dv->getMitarbeiter_uid(),
+ $dv->getOe_kurzbz(),
+ $dv->getVon(),
+ $dv->getBis(),
+ $dv->getDienstverhaeltnis_id()
+ );
+ }
+
+ protected function hasOtherActiveDV(Dienstverhaeltnis $dv, $duedate)
+ {
+ $hasotheractivedv = false;
+ $result = $this->DienstverhaeltnisModel->getDVByPersonUID($dv->getMitarbeiter_uid(), null, $duedate);
+ $dvs = getData($result);
+ foreach ($dvs as $tmpdv)
+ {
+ if(intval($tmpdv->dienstverhaeltnis_id) !== intval($dv->getDienstverhaeltnis_id()))
+ {
+ $hasotheractivedv = true;
+ break;
+ }
+ }
+ return $hasotheractivedv;
+ }
+
+ /**
+ * like endDienstverhaeltnis, but also sets aktiv flag to false
+ */
+ public function deactivateDienstverhaeltnis(Dienstverhaeltnis $dv, $enddate, $deactivate)
+ {
+ $result = $this->endDienstverhaeltnis($dv, $enddate);
+ if ( $result === true)
+ {
+ if (!$deactivate) return $result;
+
+ if(!$this->hasOtherActiveDV($dv, $enddate))
+ {
+ $result = $this->BenutzerModel->update(
+ array('uid' => $dv->getMitarbeiter_uid()),
+ array(
+ 'aktiv' => false,
+ 'updateaktivam' => date('Y-m-d'),
+ 'updateaktivvon' => $this->loggedInUser
+ )
+ );
+ }
+ }
+
+ return $result;
+ }
+
+ public function endDienstverhaeltnis(Dienstverhaeltnis $dv, $enddate, $dvendegrund_kurzbz=null, $dvendegrund_anmerkung=null)
+ {
+ if( $dv->getBis() !== null && $dv->getBis() < $enddate )
+ {
+ return 'Dienstverhältnis ist bereits beendet.';
+ }
+
+ $this->CI->db->trans_begin();
+ try
+ {
+ $this->setUIDtoPGSQL();
+ if( intval($dv->getDienstverhaeltnis_id()) > 0 )
+ {
+ $gbs = $this->GehaltsbestandteilLib->fetchGehaltsbestandteile($dv->getDienstverhaeltnis_id());
+ foreach ($gbs as $gb)
+ {
+ $this->GehaltsbestandteilLib->endGehaltsbestandteil($gb, $enddate);
+ }
+
+ $vbs = $this->fetchVertragsbestandteile($dv->getDienstverhaeltnis_id());
+ foreach ($vbs as $vb)
+ {
+ $this->endVertragsbestandteil($vb, $enddate);
+ }
+
+ if( $dvendegrund_kurzbz !== null )
+ {
+ $dv->setDvendegrund_kurzbz($dvendegrund_kurzbz);
+ }
+ if( $dvendegrund_anmerkung !== null )
+ {
+ $dv->setDvendegrund_anmerkung($dvendegrund_anmerkung);
+ }
+ $dv->setBis($enddate);
+ $this->updateDienstverhaeltnis($dv);
+
+ if( $this->CI->db->trans_status() === false )
+ {
+ log_message('debug', "Transaction failed");
+ throw new Exception("Transaction failed");
+ }
+ $this->CI->db->trans_commit();
+ }
+ }
+ catch (Exception $ex)
+ {
+ log_message('debug', "end DV failed " . $dv->getDienstverhaeltnis_id());
+ log_message('debug', "Transaction rolled back. " . $ex->getMessage());
+ $this->CI->db->trans_rollback();
+ return $ex->getMessage();
+ }
+ return true;
+ }
+
+ public function endVertragsbestandteil(Vertragsbestandteil $vertragsbestandteil, $enddate)
+ {
+ if( $vertragsbestandteil->getBis() !== null && $vertragsbestandteil->getBis() < $enddate )
+ {
+ return;
+ }
+
+ $vertragsbestandteil->setBis($enddate);
+ $this->updateVertragsbestandteil($vertragsbestandteil);
+ }
+
+ protected function setUIDtoPGSQL() {
+ $ret = $this->VertragsbestandteilModel
+ ->execReadOnlyQuery('SET LOCAL pv21.uid TO \''
+ . $this->loggedInUser . '\'');
+ if(isError($ret))
+ {
+ throw new Exception('error setting uid to pgsql');
+ }
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilStunden.php b/application/libraries/vertragsbestandteil/VertragsbestandteilStunden.php
new file mode 100644
index 000000000..f2d8c8081
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilStunden.php
@@ -0,0 +1,110 @@
+setVertragsbestandteiltyp_kurzbz(
+ VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_STUNDEN);
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ parent::hydrateByStdClass($data, $fromdb);
+ $this->fromdb = $fromdb;
+ isset($data->wochenstunden) && $this->setWochenstunden($data->wochenstunden);
+ isset($data->teilzeittyp_kurzbz) && $this->setTeilzeittyp_kurzbz($data->teilzeittyp_kurzbz);
+ $this->fromdb = false;
+ }
+
+ public function getWochenstunden()
+ {
+ return $this->wochenstunden;
+ }
+
+ public function getTeilzeittyp_kurzbz()
+ {
+ return $this->teilzeittyp_kurzbz;
+ }
+
+ public function setWochenstunden($wochenstunden)
+ {
+ $this->markDirty('wochenstunden', $this->wochenstunden, $wochenstunden);
+ $this->wochenstunden = $wochenstunden;
+ return $this;
+ }
+
+ public function setTeilzeittyp_kurzbz($teilzeittyp_kurzbz)
+ {
+ $teilzeittyp_kurzbz = ($teilzeittyp_kurzbz !== '')
+ ? $teilzeittyp_kurzbz : null;
+ $this->markDirty('teilzeittyp_kurzbz', $this->teilzeittyp_kurzbz, $teilzeittyp_kurzbz);
+ $this->teilzeittyp_kurzbz = $teilzeittyp_kurzbz;
+ return $this;
+ }
+
+ public function toStdClass(): \stdClass
+ {
+ $tmp = array(
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'wochenstunden' => $this->getWochenstunden(),
+ 'teilzeittyp_kurzbz' => $this->getTeilzeittyp_kurzbz()
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function __toString()
+ {
+ $txt = <<getWochenstunden()}
+ teilzeittyp_kurzbz: {$this->getTeilzeittyp_kurzbz()}
+
+EOTXT;
+ return parent::__toString() . $txt;
+ }
+
+ public function validate()
+ {
+ if( false === filter_var($this->wochenstunden, FILTER_VALIDATE_FLOAT,
+ array(
+ 'options' => array(
+ 'min_range' => 0,
+ 'max_range' => 100
+ )
+ )
+ ) ) {
+ $this->validationerrors[] = 'Stunden muss eine Kommazahl im Bereich 0 bis 100 sein.';
+ }
+ else
+ {
+ if( floatval($this->wochenstunden) < floatval('0.01') &&
+ $this->teilzeittyp_kurzbz !== 'altersteilzeit' )
+ {
+ $this->validationerrors[] = '0 Wochenstunden ist nur in Kombination mit Altersteilzeit zulässig.';
+ }
+ }
+
+ return parent::validate();
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch.php b/application/libraries/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch.php
new file mode 100644
index 000000000..fe683211d
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch.php
@@ -0,0 +1,83 @@
+setVertragsbestandteiltyp_kurzbz(
+ VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH);
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ parent::hydrateByStdClass($data, $fromdb);
+ $this->fromdb = $fromdb;
+ isset($data->tage) && $this->setTage($data->tage);
+ $this->fromdb = false;
+ }
+
+ /**
+ * Get the value of tage
+ */
+ public function getTage()
+ {
+ return $this->tage;
+ }
+
+ /**
+ * Set the value of tage
+ */
+ public function setTage($tage): self
+ {
+ $this->markDirty('tage', $this->tage, $tage);
+ $this->tage = $tage;
+
+ return $this;
+ }
+
+ public function toStdClass(): \stdClass
+ {
+ $tmp = array(
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'tage' => $this->getTage(),
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function __toString()
+ {
+ $txt = <<getTage()}
+
+EOTXT;
+ return parent::__toString() . $txt;
+ }
+
+ public function validate()
+ {
+ if( !(filter_var($this->tage, FILTER_VALIDATE_INT,
+ array(
+ 'options' => array(
+ 'min_range' => 1,
+ 'max_range' => 50
+ )
+ )
+ )) ) {
+ $this->validationerrors[] = 'Urlaubsanspruch muss eine Tagesanzahl im Bereich 1 bis 50 sein.';
+ }
+
+ return parent::validate();
+ }
+}
diff --git a/application/libraries/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung.php b/application/libraries/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung.php
new file mode 100644
index 000000000..5bbdaa36f
--- /dev/null
+++ b/application/libraries/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung.php
@@ -0,0 +1,118 @@
+setVertragsbestandteiltyp_kurzbz(
+ VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG);
+ }
+
+ public function hydrateByStdClass($data, $fromdb=false)
+ {
+ parent::hydrateByStdClass($data, $fromdb);
+ $this->fromdb = $fromdb;
+ isset($data->zeitaufzeichnung) && $this->setZeitaufzeichnung($data->zeitaufzeichnung);
+ isset($data->azgrelevant) && $this->setAzgrelevant($data->azgrelevant);
+ isset($data->homeoffice) && $this->setHomeoffice($data->homeoffice);
+ $this->fromdb = false;
+ }
+
+ /**
+ * Get the value of zeitaufzeichnung
+ */
+ public function getZeitaufzeichnung()
+ {
+ return $this->zeitaufzeichnung;
+ }
+
+ /**
+ * Set the value of zeitaufzeichnung
+ */
+ public function setZeitaufzeichnung($zeitaufzeichnung): self
+ {
+ $this->markDirty('zeitaufzeichnung', $this->zeitaufzeichnung, $zeitaufzeichnung);
+ $this->zeitaufzeichnung = $zeitaufzeichnung;
+
+ return $this;
+ }
+
+ /**
+ * Get the value of azgrelevant
+ */
+ public function getAzgrelevant()
+ {
+ return $this->azgrelevant;
+ }
+
+ /**
+ * Set the value of azgrelevant
+ */
+ public function setAzgrelevant($azgrelevant): self
+ {
+ $this->markDirty('azgrelevant', $this->azgrelevant, $azgrelevant);
+ $this->azgrelevant = $azgrelevant;
+
+ return $this;
+ }
+
+ /**
+ * Get the value of homeoffice
+ */
+ public function getHomeoffice()
+ {
+ return $this->homeoffice;
+ }
+
+ /**
+ * Set the value of homeoffice
+ */
+ public function setHomeoffice($homeoffice): self
+ {
+ $this->markDirty('homeoffice', $this->homeoffice, $homeoffice);
+ $this->homeoffice = $homeoffice;
+
+ return $this;
+ }
+
+ public function toStdClass(): \stdClass
+ {
+ $tmp = array(
+ 'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
+ 'zeitaufzeichnung' => $this->getZeitaufzeichnung(),
+ 'azgrelevant' => $this->getAzgrelevant(),
+ 'homeoffice' => $this->getHomeoffice()
+ );
+
+ $tmp = array_filter($tmp, function($k) {
+ return in_array($k, $this->modifiedcolumns);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return (object) $tmp;
+ }
+
+ public function __toString()
+ {
+ $txt = <<getZeitaufzeichnung()}
+ azgrelevant: {$this->getAzgrelevant()}
+ homeoffice: {$this->getHomeoffice()}
+
+EOTXT;
+ return parent::__toString() . $txt;
+ }
+
+ public function validate()
+ {
+ return parent::validate();
+ }
+}
diff --git a/application/models/codex/Bismeldestichtag_model.php b/application/models/codex/Bismeldestichtag_model.php
new file mode 100644
index 000000000..f9b412e7a
--- /dev/null
+++ b/application/models/codex/Bismeldestichtag_model.php
@@ -0,0 +1,133 @@
+dbTable = 'bis.tbl_bismeldestichtag';
+ $this->pk = 'meldestichtag_id';
+ }
+
+ public function getLastReachedMeldestichtag($studiensemester_kurzbz = null)
+ {
+ $this->addSelect('meldestichtag_id');
+ $this->addSelect('meldestichtag');
+ $this->addSelect('studiensemester_kurzbz');
+ $this->addSelect('insertamum');
+ $this->addSelect('insertvon');
+ $this->addSelect('updateamum');
+ $this->addSelect('updatevon');
+
+ if ($studiensemester_kurzbz) {
+ $this->db->where('studiensemester_kurzbz', $studiensemester_kurzbz);
+ }
+
+ $this->addOrder('meldestichtag', 'DESC');
+ $this->addLimit(1);
+
+ return $this->loadWhere([
+ 'meldestichtag < NOW()' => null
+ ]);
+ }
+
+ /**
+ * Liefert nächstliegenden Bismeldestichtag.
+ * @return object success or error
+ */
+ public function getNextMeldestichtag()
+ {
+ $this->addSelect('meldestichtag');
+ $this->addSelect('studiensemester_kurzbz');
+
+ $this->addOrder('meldestichtag', 'ASC');
+ $this->addLimit(1);
+
+ return $this->loadWhere([
+ 'meldestichtag >= NOW()' => null
+ ]);
+ }
+
+ /**
+ * Prüft, ob Meldestichtag für ein bestimmtes Statusdatum und Studiensemester erreicht ist.
+ *
+ * @param $status_datum
+ * @return boolean true wenn erreicht, oder false
+ */
+ public function checkIfMeldestichtagErreicht($status_datum, $studiensemester_kurzbz = null)
+ {
+ $erreicht = false;
+
+ if (isset($studiensemester_kurzbz))
+ {
+ // Studiensemesterende holen
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+ $result = $this->StudiensemesterModel->loadWhere(
+ array(
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ )
+ );
+ if(isError($result))
+ {
+ return $result;
+ }
+ $result = current(getData($result));
+
+ $studiensemester_ende = new DateTime($result->ende);
+ }
+
+ // letztes erreichtes Bismeldedatum holen
+ $result = $this->getLastReachedMeldestichtag();
+ if (isError($result))
+ {
+ return $result;
+ }
+ if (!hasData($result)) {
+ return success("0",'No Statusdata vorhanden');
+ }
+ $stichtag = current(getData($result));
+ $stichtag = new DateTime($stichtag->meldestichtag);
+
+ $statusDatum = new DateTime($status_datum);
+
+ // Prüfen, ob Studentstatusdatum oder Studiensemester vor dem Stichtagsdatum liegen
+ if (isset($statusDatum))
+ {
+ if (isset($stichtag))
+ $erreicht = $statusDatum < $stichtag;
+ }
+
+ if (isset($studiensemester_ende))
+ {
+ $erreicht = $erreicht || $studiensemester_ende < $stichtag;
+ }
+
+ if ($erreicht)
+ return success("1", "Studentstatus mit Datum oder Semesterende vor erreichtem Meldestichtag können nicht hinzugefügt werden");
+
+ return success("0", "Meldestatus nicht erreicht");
+ }
+
+ /**
+ * Gets last Bismeldestichtag for a Studiensemester.
+ * @param $studiensemester_kurzbz
+ * @return object success or error
+ */
+ public function getByStudiensemester($studiensemester_kurzbz)
+ {
+ $query = '
+ SELECT
+ meldestichtag
+ FROM
+ bis.tbl_bismeldestichtag
+ JOIN public.tbl_studiensemester USING (studiensemester_kurzbz)
+ WHERE
+ studiensemester_kurzbz = ?
+ ORDER BY meldestichtag DESC
+ LIMIT 1';
+
+ return $this->execQuery($query, array($studiensemester_kurzbz));
+ }
+}
diff --git a/application/models/codex/Gemeinde_model.php b/application/models/codex/Gemeinde_model.php
index c782346a0..670da739d 100644
--- a/application/models/codex/Gemeinde_model.php
+++ b/application/models/codex/Gemeinde_model.php
@@ -19,4 +19,13 @@ class Gemeinde_model extends DB_Model
return $this->loadWhere(array("plz" => $plz));
}
+
+ public function checkLocation($plz, $gemeinde, $ort)
+ {
+ $this->db->where('ortschaftsname', $ort);
+ $this->db->where('name', $gemeinde);
+ $this->db->where('plz', $plz);
+
+ return (boolean)$this->db->count_all_results($this->dbTable);
+ }
}
\ No newline at end of file
diff --git a/application/models/crm/Konto_model.php b/application/models/crm/Konto_model.php
index 4b2a259c9..d130d5db8 100644
--- a/application/models/crm/Konto_model.php
+++ b/application/models/crm/Konto_model.php
@@ -1,4 +1,7 @@
pk = 'buchungsnr';
}
+ /**
+ * Insert Data into DB-Table
+ *
+ * @param array $data DataArray for Insert
+ * @return stdClass
+ */
+ public function insert($data, $encryptedColumns = null)
+ {
+ if (isset($data['buchungsnr_verweis']) && $data['buchungsnr_verweis'])
+ return parent::insert($data, $encryptedColumns);
+
+ $this->db->trans_begin();
+
+ $result = parent::insert($data, $encryptedColumns);
+ if (isError($result)) {
+ $this->db->trans_rollback();
+ return $result;
+ }
+
+ $buchungsnr = $result->retval;
+ // If studiengang_kz is not present in $data it will fail above since it is a not null field
+ $studiengang_kz = $data['studiengang_kz'];
+
+
+ $zahlungsreferenz = false;
+ Events::trigger('generate_zahlungsreferenz', $buchungsnr, $data, function ($value) use ($zahlungsreferenz) {
+ $zahlungsreferenz = $value;
+ });
+
+ if ($zahlungsreferenz === false) {
+ $result = $this->execQuery('SELECT UPPER(oe_kurzbz) || ? as zahlungsreferenz
+ FROM public.tbl_studiengang
+ WHERE studiengang_kz=?', [$buchungsnr, $studiengang_kz]);
+ if (isError($result)) {
+ $this->db->trans_rollback();
+ return $result;
+ }
+ $zahlungsreferenz = current(getData($result))->zahlungsreferenz;
+ } elseif (isError($zahlungsreferenz)) {
+ $this->db->trans_rollback();
+ return $zahlungsreferenz;
+ }
+
+
+ $result = $this->update($buchungsnr, [
+ 'zahlungsreferenz' => $zahlungsreferenz
+ ]);
+
+ if (isError($result)) {
+ $this->db->trans_rollback();
+ return $result;
+ }
+
+ $this->db->trans_commit();
+
+ return success($buchungsnr);
+ }
+
+ /**
+ * Delete data from DB-Table
+ *
+ * @param string $id Primary Key for DELETE
+ *
+ * @return stdClass
+ */
+ public function delete($id)
+ {
+ $this->db->where('buchungsnr_verweis', $id);
+ if ($this->db->count_all_results($this->dbTable))
+ return error('Bitte zuerst die zugeordneten Buchungen loeschen', 42);
+ return parent::delete($id);
+ }
+
+ /**
+ * Adds additional fields to the Query
+ *
+ * @return Konto_model
+ */
+ public function withAdditionalInfo()
+ {
+ $this->addSelect($this->dbTable . '.*');
+ $this->addSelect('UPPER(typ::varchar(1) || kurzbz) AS kuerzel');
+ $this->addSelect('person.anrede');
+ $this->addSelect('person.titelpost');
+ $this->addSelect('person.titelpre');
+ $this->addSelect('person.vorname');
+ $this->addSelect('person.vornamen');
+ $this->addSelect('person.nachname');
+
+ $this->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
+ $this->addJoin('public.tbl_person person', 'person_id', 'LEFT');
+
+ Events::trigger('konto_query');
+
+ return $this;
+ }
+
+ /**
+ * Get all accounting entries for a person optionally filtered by Studiengang
+ *
+ * @param integer|array $person_id
+ * @param string (optional) $studiengang_kz
+ *
+ * @return stdClass
+ */
+ public function getAlleBuchungen($person_id, $studiengang_kz = '')
+ {
+ $this->withAdditionalInfo();
+
+ $this->addOrder('buchungsdatum');
+
+ if (is_array($person_id))
+ $this->db->where_in('person_id', $person_id);
+ else
+ $this->db->where('person_id', $person_id);
+
+ if ($studiengang_kz)
+ return $this->loadWhere([
+ 'studiengang_kz' => $studiengang_kz
+ ]);
+ return $this->load();
+ }
+
+ /**
+ * Get all open accounting entries for a person optionally filtered by Studiengang
+ *
+ * @param integer|array $person_id
+ * @param string (optional) $studiengang_kz
+ *
+ * @return stdClass
+ */
+ public function getOffeneBuchungen($person_id, $studiengang_kz = '')
+ {
+ $this->addSelect('buchungsnr');
+ $this->db->where('(betrag + (
+ SELECT CASE WHEN sum(betrag) is null THEN 0 ELSE sum(betrag) END
+ FROM ' . $this->dbTable . '
+ WHERE buchungsnr_verweis=konto_a.buchungsnr
+ )) !=', 0, false);
+ if (is_array($person_id))
+ $this->db->where_in('person_id', $person_id);
+ else
+ $this->db->where('person_id', $person_id);
+ $sql = $this->db->get_compiled_select($this->dbTable . ' konto_a');
+
+ $this->db->group_start();
+ $this->db->where_in('buchungsnr', $sql, false);
+ $this->db->or_where_in('buchungsnr_verweis', $sql, false);
+ $this->db->group_end();
+
+ return $this->getAlleBuchungen($person_id, $studiengang_kz);
+ }
+
+ /**
+ * Check double Buchungen
+ *
+ * @param array $person_ids
+ * @param string $studiensemester_kurzbz
+ * @param array $buchungstyp_kurzbzs
+ *
+ * @return stdClass
+ */
+ public function checkDoubleBuchung($person_ids, $studiensemester_kurzbz, $buchungstyp_kurzbzs)
+ {
+ $this->addSelect('vorname');
+ $this->addSelect('nachname');
+
+ $this->addJoin('public.tbl_person', 'person_id');
+
+ $this->db->where_in('person_id', $person_ids);
+ $this->db->where_in('buchungstyp_kurzbz', $buchungstyp_kurzbzs);
+
+ $this->addGroupBy('vorname, nachname');
+ $this->addOrder('nachname');
+ $this->addOrder('vorname');
+
+ return $this->loadWhere([
+ 'studiensemester_kurzbz' => $studiensemester_kurzbz
+ ]);
+ }
+
+ /**
+ * Berechnet den offenen Betrag einer Buchung
+ *
+ * @param integer $buchungsnr
+ *
+ * @return stdClass
+ */
+ public function getDifferenz($buchungsnr)
+ {
+ $this->addSelect('buchungsnr_verweis');
+ $this->db->where('buchungsnr', $buchungsnr);
+ $sql = $this->db->get_compiled_select($this->dbTable);
+
+ $this->addSelect('buchungsnr_verweis');
+ $this->db->where('buchungsnr', $buchungsnr);
+ $this->db->or_where('buchungsnr_verweis', '(' . $sql . ')', false);
+ $sql = $this->db->get_compiled_select($this->dbTable);
+
+ $this->addSelect('sum(betrag) differenz');
+ $this->db->where('buchungsnr', $buchungsnr);
+ $this->db->or_where('buchungsnr_verweis', $buchungsnr);
+ $this->db->or_where('buchungsnr', '(' . $sql . ')', false);
+
+ $result = $this->load();
+ if (isError($result))
+ return $result;
+ if (!hasData($result))
+ return success(null);
+ return success(current(getData($result))->differenz * -1);
+ }
+
/**
* Sets a Payment as paid
*/
@@ -100,8 +315,8 @@ class Konto_model extends DB_Model
public function checkStudienbeitrag($uid, $stsem, $buchungstypen)
{
- $query = 'SELECT tbl_konto.buchungsnr,
- tbl_konto.buchungsdatum
+ $query = 'SELECT tbl_konto.buchungsnr,
+ tbl_konto.buchungsdatum
FROM public.tbl_konto,
public.tbl_benutzer,
public.tbl_student
@@ -117,10 +332,47 @@ class Konto_model extends DB_Model
FROM public.tbl_konto skonto
WHERE skonto.buchungsnr = tbl_konto.buchungsnr_verweis
OR skonto.buchungsnr_verweis = tbl_konto.buchungsnr_verweis
- )
+ )
ORDER BY buchungsnr DESC LIMIT 1
';
return $this->execQuery($query);
}
+
+ /**
+ * check if student has paid studienbeitrag for certain semester
+ *
+ * @param $person_id person_id
+ * @param $stsem stsem
+ *
+ * @return boolean
+ */
+ public function checkStudienbeitragFromPerson($person_id, $stsem)
+ {
+ $this->addOrder('buchungsnr');
+ $this->addLimit(1);
+ $result = $this->loadWhere([
+ 'person_id'=>$person_id,
+ 'studiensemester_kurzbz' => $stsem,
+ 'buchungstyp_kurzbz' => 'Studiengebuehr'
+ ]);
+
+ if (!getData($result))
+ return false;
+
+ $data = getData($result)[0];
+
+ $this->resetQuery();
+
+ $this->addSelect('sum(betrag) as differenz');
+ $this->db->or_where('buchungsnr', $data->buchungsnr);
+ $this->db->or_where('buchungsnr_verweis', $data->buchungsnr);
+
+ $result = $this->load();
+ if (!getData($result))
+ return false;
+
+ $data = getData($result)[0];
+ return $data->differenz >= 0;
+ }
}
diff --git a/application/models/crm/Prestudent_model.php b/application/models/crm/Prestudent_model.php
index 7b24b8769..242c26518 100644
--- a/application/models/crm/Prestudent_model.php
+++ b/application/models/crm/Prestudent_model.php
@@ -14,6 +14,39 @@ class Prestudent_model extends DB_Model
$this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel');
}
+ /**
+ * Update Data in DB-Table
+ *
+ * @param string $id PK for DB-Table
+ * @param array $data DataArray for Insert
+ * @return array
+ */
+ public function update($id, $data, $encryptedColumns = null)
+ {
+ if (isset($data['zgvmas_code'])
+ || isset($data['zgvmanation'])
+ || isset($data['zgv_code'])
+ || isset($data['zgvnation'])
+ ) {
+ /**
+ * Falls ZGV vorhanden, setze Ausstellungsstaat (für BIS-Meldung)
+ * auf Nation der höchsten angegebenen ZGV
+ */
+ $case = '(CASE
+ WHEN zgvmas_code IS NOT NULL AND zgvmanation IS NOT NULL THEN zgvmanation
+ WHEN zgv_code IS NOT NULL AND zgvnation IS NOT NULL THEN zgvnation
+ ELSE NULL END)';
+
+ foreach (['zgvmas_code', 'zgvmanation', 'zgv_code', 'zgvnation'] as $key)
+ if (isset($data[$key]))
+ $case = str_replace($key, $this->escape($data[$key]), $case);
+
+ $this->db->set('ausstellungsstaat', $case, false);
+ }
+
+ return parent::update($id, $data, $encryptedColumns);
+ }
+
/**
* getLastStatuses
*/
@@ -700,4 +733,33 @@ class Prestudent_model extends DB_Model
return $this->execQuery($query, array($prestudent_id));
}
+ /**
+ * Gets history of all prestudents, person_id given
+ * @param int $person_id
+ * @return object
+ */
+ public function getHistoryPrestudents($person_id)
+ {
+
+ $query = "
+ SELECT ps.studiensemester_kurzbz, p.priorisierung, p.studiengang_kz, sg.kurzbzlang, ps.orgform_kurzbz,
+ ps.status_kurzbz, s.student_uid, sp.bezeichnung, ps.ausbildungssemester,
+ CONCAT(ps.status_kurzbz, ' (', ps.ausbildungssemester, '. Semester)') as status, p.prestudent_id
+ FROM public.tbl_prestudent p
+ JOIN (
+ SELECT DISTINCT ON(prestudent_id) *
+ FROM public.tbl_prestudentstatus
+ WHERE prestudent_id IN (SELECT prestudent_id FROM public.tbl_prestudent WHERE person_id = ?)
+ ORDER BY prestudent_id, datum desc, insertamum desc
+ ) ps USING(prestudent_id)
+ JOIN public.tbl_status USING(status_kurzbz)
+ LEFT JOIN public.tbl_status_grund g USING (statusgrund_id)
+ JOIN public.tbl_studiengang sg USING(studiengang_kz)
+ LEFT JOIN lehre.tbl_studienplan sp USING (studienplan_id)
+ LEFT JOIN public.tbl_student s USING (prestudent_id)
+ ORDER BY p.priorisierung
+ ";
+
+ return $this->execQuery($query, array($person_id));
+ }
}
diff --git a/application/models/crm/Prestudentstatus_model.php b/application/models/crm/Prestudentstatus_model.php
index f39a41fda..5f0b5876c 100644
--- a/application/models/crm/Prestudentstatus_model.php
+++ b/application/models/crm/Prestudentstatus_model.php
@@ -2,6 +2,19 @@
class Prestudentstatus_model extends DB_Model
{
+
+ const STATUS_ABBRECHER = 'Abbrecher';
+ const STATUS_UNTERBRECHER = 'Unterbrecher';
+ const STATUS_STUDENT = 'Student';
+ const STATUS_DIPLOMAND = 'Diplomand';
+ const STATUS_ABSOLVENT = 'Absolvent';
+ const STATUS_BEWERBER = 'Bewerber';
+ const STATUS_AUFGENOMMENER = 'Aufgenommener';
+ const STATUS_WARTENDER = 'Wartender';
+ const STATUS_ABGEWIESENER = 'Abgewiesener';
+ const STATUS_INTERESSENT = 'Interessent';
+ const STATUS_INCOMING = 'Incoming';
+
/**
* Constructor
*/
@@ -226,4 +239,353 @@ class Prestudentstatus_model extends DB_Model
return $this->execQuery($query, $parametersArray);
}
-}
+
+ /**
+ * get Email of relevant Studiengang of prestudent
+ */
+ public function getLastStatusWithStgEmail($prestudent_id, $studiensemester_kurzbz = '', $status_kurzbz = '')
+ {
+ $this->addSelect('tbl_prestudentstatus.*,
+ tbl_studienplan.bezeichnung AS studienplan_bezeichnung,
+ tbl_orgform.orgform_kurzbz AS orgform,
+ tbl_studienplan.sprache,
+ tbl_orgform.bezeichnung_mehrsprachig AS bezeichnung_orgform,
+ tbl_status.bezeichnung_mehrsprachig,
+ tbl_status_grund.bezeichnung_mehrsprachig AS bezeichnung_statusgrund,
+ tbl_studiengang.bezeichnung AS stg_bezeichnung,
+ tbl_studiengang.email');
+ $this->addJoin('lehre.tbl_studienplan', 'studienplan_id', 'LEFT');
+ $this->addJoin('lehre.tbl_studienordnung', 'studienordnung_id', 'LEFT');
+ $this->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT');
+ $this->addJoin('public.tbl_status', 'tbl_status.status_kurzbz = tbl_prestudentstatus.status_kurzbz');
+ $this->addJoin('public.tbl_status_grund', 'statusgrund_id', 'LEFT');
+ $this->addJoin('bis.tbl_orgform', 'COALESCE(tbl_studienplan.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz, tbl_studiengang.orgform_kurzbz) = tbl_orgform.orgform_kurzbz', 'LEFT');
+ $this->db->where('tbl_status.status_kurzbz = tbl_prestudentstatus.status_kurzbz');
+
+ $where = array('prestudent_id' => $prestudent_id);
+ if ($studiensemester_kurzbz)
+ $where['studiensemester_kurzbz'] = $studiensemester_kurzbz;
+ if ($status_kurzbz)
+ $where['tbl_prestudentstatus.status_kurzbz'] = $status_kurzbz;
+
+ $this->addOrder('datum', 'DESC');
+ $this->addOrder('insertamum', 'DESC');
+ $this->addOrder('ext_id', 'DESC');
+ $this->addLimit(1);
+
+ return $this->loadWhere($where);
+ }
+
+ public function loadLastWithStgDetails($prestudent_id, $studiensemester_kurzbz = null, $max_date = null)
+ {
+ $this->load->config('studierendenantrag');
+
+ $lang = getUserLanguage();
+
+ $this->addSelect($this->dbTable . '.prestudent_id');
+ $this->addSelect($this->dbTable . '.ausbildungssemester AS semester');
+ $this->addSelect($this->dbTable . '.studiensemester_kurzbz');
+ $this->addSelect('s.matrikelnr');
+ $this->addSelect('ss.studienjahr_kurzbz');
+ $this->addSelect('pers.vorname');
+ $this->addSelect('pers.nachname');
+ $this->addSelect('pers.unruly');
+ $this->addSelect('TRIM(CONCAT(pers.vorname, \' \', pers.nachname)) AS name');
+ $this->addSelect('pers.person_id');
+ $this->addSelect('g.studiengang_kz');
+ $this->addSelect('g.bezeichnung');
+ $this->addSelect('o.orgform_kurzbz');
+ $this->addSelect(
+ 'o.bezeichnung_mehrsprachig[(SELECT index FROM public.tbl_sprache WHERE sprache=\'' . $lang . '\')] AS orgform_bezeichnung',
+ false
+ );
+
+ $this->addJoin('public.tbl_student s', 'prestudent_id');
+ $this->addJoin('public.tbl_prestudent p', 'prestudent_id');
+ $this->addJoin('public.tbl_studiensemester ss', 'studiensemester_kurzbz');
+ $this->addJoin('public.tbl_person pers', 'person_id');
+ $this->addJoin('public.tbl_studiengang g', 'p.studiengang_kz=g.studiengang_kz');
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+ $this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz');
+
+ $this->addOrder($this->dbTable . '.datum', 'DESC');
+ $this->addOrder($this->dbTable . '.insertamum', 'DESC');
+ $this->addOrder($this->dbTable . '.ext_id', 'DESC');
+
+ $this->addLimit(1);
+
+ if ($max_date)
+ $this->db->where($this->dbTable . '.insertamum <', $max_date);
+
+ $whereArr = [
+ $this->dbTable . '.prestudent_id' => $prestudent_id,
+ 'g.aktiv' => true
+ ];
+
+ if ($studiensemester_kurzbz !== null)
+ {
+ $whereArr[$this->dbTable. '.studiensemester_kurzbz'] = $studiensemester_kurzbz;
+ }
+
+ return $this->loadWhere($whereArr);
+ }
+
+ /**
+ * call like this:
+ * $this->PrestudentstatusModel->withGrund('grund_kurzbz')->update($id, $otherData);
+ * or:
+ * $this->PrestudentstatusModel->withGrund('grund_kurzbz')->insert($otherData);
+ * @param string $statusgrund_kurzbz
+ * @return object $this
+ */
+ public function withGrund($statusgrund_kurzbz)
+ {
+ if ($statusgrund_kurzbz)
+ $this->db->set(
+ 'statusgrund_id',
+ '(SELECT statusgrund_id FROM public.tbl_status_grund WHERE statusgrund_kurzbz=' . $this->db->escape($statusgrund_kurzbz) . ')',
+ false
+ );
+
+ return $this;
+ }
+
+ /**
+ * Check if there is only one prestudentstatus left
+ *
+ * @param integer $prestudent_id
+ * @param string $studiensemester_kurzbz
+ *
+ * @return stdClass
+ */
+ public function checkIfLastStatusEntry($prestudent_id, $studiensemester_kurzbz = null)
+ {
+ $this->addSelect('COUNT(*) AS anzahl', false);
+
+ if ($studiensemester_kurzbz)
+ $this->db->where('studiensemester_kurzbz', $studiensemester_kurzbz);
+
+ $result = $this->loadWhere([
+ 'prestudent_id' => $prestudent_id
+ ]);
+
+ if (isError($result))
+ return $result;
+
+ $resultObject = current($result->retval);
+
+ $anzahl = (int)$resultObject->anzahl;
+
+ if ($anzahl <= 1)
+ return success(true, $this->p->t('lehre', 'error_lastRole'));
+
+ return success(false, $this->p->t('lehre', 'anzahl_existingRoles', ['anzahl' => $anzahl]));
+ }
+
+ public function getAllPrestudentstatiWithStudiensemester($prestudent_id)
+ {
+ $qry = "
+ SELECT
+ tbl_prestudentstatus.status_kurzbz,
+ tbl_prestudentstatus.studiensemester_kurzbz,
+ tbl_prestudentstatus.ausbildungssemester,
+ tbl_prestudentstatus.datum,
+ s.start AS studiensemester_start,
+ pl.orgform_kurzbz AS studienplan_orgform_kurzbz,
+ stud.matrikelnr,
+ pers.vorname,
+ pers.nachname
+ FROM
+ public.tbl_prestudentstatus
+ JOIN public.tbl_studiensemester s USING (studiensemester_kurzbz)
+ JOIN public.tbl_prestudent USING (prestudent_id)
+ JOIN public.tbl_person pers USING (person_id)
+ LEFT JOIN public.tbl_student stud USING (prestudent_id)
+ LEFT JOIN lehre.tbl_studienplan pl USING (studienplan_id)
+ WHERE
+ prestudent_id = ?
+ ORDER BY
+ public.tbl_prestudentstatus.datum DESC,
+ public.tbl_prestudentstatus.insertamum DESC,
+ public.tbl_prestudentstatus.ext_id DESC
+ ";
+
+ return $this->execQuery($qry, array($prestudent_id));
+ }
+
+ /**
+ * Gets status history of a prestudent
+ * This function uses the language of the logged in user to
+ * translate the given statusgrund
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function getHistoryPrestudent($prestudent_id)
+ {
+ $lang= getUserLanguage();
+ $this->addSelect('tbl_prestudentstatus.prestudent_id');
+ $this->addSelect('tbl_prestudentstatus.status_kurzbz');
+ $this->addSelect('tbl_prestudentstatus.studiensemester_kurzbz');
+ $this->addSelect('tbl_prestudentstatus.ausbildungssemester');
+ $this->addSelect('tbl_prestudentstatus.datum');
+ $this->addSelect("TO_CHAR(tbl_prestudentstatus.datum::timestamp, 'DD.MM.YYYY') AS format_datum");
+ $this->addSelect('tbl_prestudentstatus.insertamum');
+ $this->addSelect('tbl_prestudentstatus.insertvon');
+ $this->addSelect('tbl_prestudentstatus.updateamum');
+ $this->addSelect('tbl_prestudentstatus.updatevon');
+ $this->addSelect('tbl_prestudentstatus.orgform_kurzbz');
+ $this->addSelect('tbl_prestudentstatus.bestaetigtam');
+ $this->addSelect("TO_CHAR(tbl_prestudentstatus.bestaetigtam::timestamp, 'DD.MM.YYYY') AS format_bestaetigtam");
+ $this->addSelect('tbl_prestudentstatus.bestaetigtvon');
+ $this->addSelect('tbl_prestudentstatus.bewerbung_abgeschicktamum');
+ $this->addSelect("TO_CHAR(tbl_prestudentstatus.bewerbung_abgeschicktamum::timestamp, 'DD.MM.YYYY') AS format_bewerbung_abgeschicktamum");
+ $this->addSelect('tbl_prestudentstatus.anmerkung');
+ $this->addSelect('plan.studienplan_id');
+ $this->addSelect('plan.bezeichnung');
+
+ $this->addSelect('grund.beschreibung[(
+ SELECT index
+ FROM public.tbl_sprache
+ WHERE sprache=' . $this->escape($lang) . '
+ )] AS statusgrund_bezeichnung', false);
+ $this->addSelect("CASE
+ WHEN s.student_uid IS NOT NULL
+ AND tbl_prestudentstatus.status_kurzbz IN (" . implode(",", $this->escape([
+ 'Student',
+ 'Diplomand',
+ 'Abbrecher',
+ 'Absolvent',
+ 'Ausserodentlicher',
+ 'Incoming',
+ 'Outgoing',
+ 'Unterbrecher'
+ ])) . ")
+ THEN lv.semester || lv.verband || lv.gruppe
+ ELSE '-'
+ END AS lehrverband", false);
+
+
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+ $this->addJoin('public.tbl_status_grund grund', 'statusgrund_id', 'LEFT');
+ $this->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT');
+ $this->addJoin(
+ 'public.tbl_studentlehrverband lv',
+ 's.student_uid IS NOT NULL AND s.student_uid=lv.student_uid AND tbl_prestudentstatus.studiensemester_kurzbz=lv.studiensemester_kurzbz',
+ 'LEFT'
+ );
+
+ $this->addOrder('tbl_prestudentstatus.datum', 'DESC');
+ $this->addOrder('tbl_prestudentstatus.insertamum', 'DESC');
+ $this->addOrder('tbl_prestudentstatus.ext_id', 'DESC');
+
+ return $this->loadWhere([
+ 'tbl_prestudentstatus.prestudent_id' => $prestudent_id
+ ]);
+ }
+
+ /**
+ * Gets status history of a prestudent for checking purposes.
+ * This function adds the new state or replaces the edited.
+ *
+ * @param integer $prestudent_id
+ * @param string $status_kurzbz
+ * @param DateTime $new_date
+ * @param string $new_studiensemester_kurzbz
+ * @param integer $new_ausbildungssemester
+ * @param string $old_studiensemester_kurzbz
+ * @param integer $old_ausbildungssemester
+ *
+ * @return stdClass
+ */
+ public function getHistoryWithNewOrEditedState(
+ $prestudent_id,
+ $status_kurzbz,
+ $new_date,
+ $new_studiensemester_kurzbz,
+ $new_ausbildungssemester,
+ $old_studiensemester_kurzbz,
+ $old_ausbildungssemester
+ ) {
+ $new_date = $new_date->format('Y-m-d');
+
+ $this->addSelect('status_kurzbz');
+ $this->addSelect('studiensemester_kurzbz');
+ $this->addSelect('ausbildungssemester');
+ $this->addSelect('datum');
+ $this->addSelect('insertamum');
+ $this->addSelect('ext_id');
+
+ if ($old_studiensemester_kurzbz || $old_ausbildungssemester) {
+ $this->db->not_group_start();
+ $this->db->where('status_kurzbz', $status_kurzbz);
+ $this->db->where('studiensemester_kurzbz', $old_studiensemester_kurzbz);
+ $this->db->where('ausbildungssemester', $old_ausbildungssemester);
+ $this->db->group_end();
+ }
+
+ $this->db->where('prestudent_id', $prestudent_id);
+
+ $tmpTable = $this->db->get_compiled_select($this->dbTable);
+
+ $tmpTable .= "UNION
+ SELECT " .
+ $this->escape($status_kurzbz) . " AS status_kurzbz, " .
+ $this->escape($new_studiensemester_kurzbz) . " AS studiensemester_kurzbz, " .
+ $this->escape($new_ausbildungssemester) . " AS ausbildungssemester, " .
+ $this->escape($new_date) . "::date AS datum," .
+ $this->escape(date('c')) . "::date AS insertamum," .
+ "NULL AS ext_id";
+
+ $this->addJoin('public.tbl_studiensemester sem', 'studiensemester_kurzbz');
+
+ $this->addOrder('s.datum', 'DESC');
+ $this->addOrder('s.insertamum', 'DESC');
+ $this->addOrder('s.ext_id', 'DESC');
+
+ $dbTable = $this->dbTable;
+ $this->dbTable = "(" . $tmpTable . ") s";
+
+ $result = $this->load();
+
+ $this->dbTable = $dbTable;
+
+ return $result;
+ }
+
+ /**
+ * For checks if Orgform of Student status and Bewerber status match.
+ * Returns any Bewerber status that does not match the first Student
+ * status' Orgform.
+ *
+ * @param integer $prestudent_id
+ *
+ * @return stdClass
+ */
+ public function getBewerberWhereOrgformNotStudent($prestudent_id)
+ {
+ $this->addSelect('plan.orgform_kurzbz');
+
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+
+ $this->addOrder('tbl_prestudentstatus.datum', 'DESC');
+ $this->addOrder('tbl_prestudentstatus.insertamum', 'DESC');
+ $this->addOrder('tbl_prestudentstatus.ext_id', 'DESC');
+
+ $this->addLimit(1);
+
+ $this->db->where('prestudent_id', $prestudent_id);
+ $this->db->where('status_kurzbz', self::STATUS_STUDENT);
+
+ $sql = $this->db->get_compiled_select($this->dbTable);
+
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+
+ $this->db->where('plan.orgform_kurzbz !=', '(' . $sql . ')', false);
+ return $this->loadWhere([
+ 'prestudent_id' => $prestudent_id,
+ 'status_kurzbz' => self::STATUS_BEWERBER
+ ]);
+ }
+}
\ No newline at end of file
diff --git a/application/models/crm/Reihungstest_model.php b/application/models/crm/Reihungstest_model.php
index ec1982ea6..86ebfd0af 100644
--- a/application/models/crm/Reihungstest_model.php
+++ b/application/models/crm/Reihungstest_model.php
@@ -322,7 +322,7 @@ class Reihungstest_model extends DB_Model
JOIN lehre.tbl_studienplan ON (tbl_prestudentstatus.studienplan_id = tbl_studienplan.studienplan_id)
LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code)
WHERE rt_id = ?
- AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\'
+ AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\')
AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz
AND bewerbung_abgeschicktamum IS NOT NULL
AND bestaetigtam IS NOT NULL
@@ -411,7 +411,7 @@ class Reihungstest_model extends DB_Model
JOIN lehre.tbl_studienplan ON (tbl_prestudentstatus.studienplan_id = tbl_studienplan.studienplan_id)
LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code)
WHERE rt.studiengang_kz = ?
- AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\'
+ AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\')
AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz
AND bewerbung_abgeschicktamum IS NOT NULL
AND bestaetigtam IS NOT NULL
@@ -462,7 +462,7 @@ class Reihungstest_model extends DB_Model
LEFT JOIN bis.tbl_zgv ON (ps.zgv_code = tbl_zgv.zgv_code)
LEFT JOIN PUBLIC.tbl_ort ON (tbl_rt_person.ort_kurzbz = tbl_ort.ort_kurzbz)
WHERE rt_id = ?
- AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) = \'Interessent\'
+ AND get_rolle_prestudent(prestudent_id, rt.studiensemester_kurzbz) IN (\'Interessent\', \'Bewerber\')
AND tbl_prestudentstatus.studiensemester_kurzbz = rt.studiensemester_kurzbz
AND bewerbung_abgeschicktamum IS NOT NULL
AND bestaetigtam IS NOT NULL
diff --git a/application/models/crm/Rueckstellung_model.php b/application/models/crm/Rueckstellung_model.php
index d2c39ffde..c84c625eb 100644
--- a/application/models/crm/Rueckstellung_model.php
+++ b/application/models/crm/Rueckstellung_model.php
@@ -20,7 +20,7 @@ class Rueckstellung_model extends DB_Model
$this->addLimit(1);
$this->addJoin('tbl_rueckstellung_status', 'status_kurzbz');
$this->addSelect('*,
- array_to_json(bezeichnung_mehrsprachig::varchar[])->>'.$language_index . 'as bezeichnung');
+ array_to_json(bezeichnung_mehrsprachig::varchar[])->>'.$language_index . ' as bezeichnung');
$this->addOrder('datum_bis', 'DESC');
$where['person_id'] = $person_id;
diff --git a/application/models/crm/Status_model.php b/application/models/crm/Status_model.php
index 7b1b38ecb..1ee2a5199 100644
--- a/application/models/crm/Status_model.php
+++ b/application/models/crm/Status_model.php
@@ -11,4 +11,21 @@ class Status_model extends DB_Model
$this->dbTable = 'public.tbl_status';
$this->pk = 'status_kurzbz';
}
+
+ public function getAllStatiWithStatusgruende()
+ {
+ $lang = '[(SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()) . ' LIMIT 1)]';
+
+ $this->addSelect('sg.status_kurzbz');
+
+ $this->addSelect('statusgrund_id');
+ $this->addSelect('sg.bezeichnung_mehrsprachig' . $lang . ' AS bezeichnung');
+ $this->addSelect('sg.beschreibung' . $lang . ' AS beschreibung');
+
+ $this->addJoin('public.tbl_status_grund sg', 'ON (sg.status_kurzbz = public.tbl_status.status_kurzbz)', 'LEFT');
+
+ return $this->loadWhere([
+ 'aktiv'=> true,
+ ]);
+ }
}
diff --git a/application/models/crm/Statusgrund_model.php b/application/models/crm/Statusgrund_model.php
index d488e12d1..8fc2a3a62 100644
--- a/application/models/crm/Statusgrund_model.php
+++ b/application/models/crm/Statusgrund_model.php
@@ -27,4 +27,19 @@ class Statusgrund_model extends DB_Model
return success($status->retval);
}
+
+ public function getAktiveGruende()
+ {
+ $lang = '[(SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage()) . ' LIMIT 1)]';
+
+ $this->addSelect('tbl_status_grund.*');
+ $this->addSelect('bezeichnung_mehrsprachig' . $lang . ' AS bezeichnung');
+ $this->addSelect('beschreibung' . $lang . ' AS beschreibung');
+
+ $this->addOrder('bezeichnung_mehrsprachig' . $lang);
+
+ return $this->loadWhere([
+ 'aktiv' => true
+ ]);
+ }
}
diff --git a/application/models/crm/Student_model.php b/application/models/crm/Student_model.php
index 4404beb54..bd7ab41b6 100644
--- a/application/models/crm/Student_model.php
+++ b/application/models/crm/Student_model.php
@@ -1,4 +1,8 @@
= 90010 && $studiengang_kz <= 90019)
+ {
+ $matrikelnummer = sprintf("%02d", $jahr).$art.substr($studiengang_kz, 0, 4);
+ }
+ else
+ {
+ $matrikelnummer = sprintf("%02d", $jahr).$art.sprintf("%04d", $studiengang_kz);
+ }
+
+ $qry = "SELECT matrikelnr FROM public.tbl_student WHERE matrikelnr LIKE ? ORDER BY matrikelnr DESC LIMIT 1";
+ $matrikelnrres = $this->execQuery($qry, array($matrikelnummer.'%'));
+
+ $max = 0;
+ if ($matrikelnrres && hasData($matrikelnrres)) {
+ $max = mb_substr($matrikelnrres->retval[0]->matrikelnr, 7);
+ if (!is_numeric($max)) {
+ $max = (int)$max;
+ }
+ }
+
+ $max += 1;
+ return success($matrikelnummer.sprintf("%03d", $max));
+ }
+
+ /**
+ * Generiert die UID
+ * FORMAT: el07b001
+ * $stgkzl: el = studiengangskuerzel
+ * $jahr: 07 = Jahr
+ * $stgtyp: b/m/d/x = Bachelor/Master/Diplom/Incoming
+ * $matrikelnummer
+ * 001 = Laufende Nummer Wenn StSem==SS dann wird zur Nummer 500 dazugezaehlt
+ * Bei Incoming im Masterstudiengang wird auch 500 dazugezaehlt
+ *
+ * @param string $stgkzl
+ * @param string $jahr
+ * @param string $stgtyp
+ * @param string $matrikelnummer
+ * @param string $vorname
+ * @param string $nachname
+ *
+ * @return stdClass
+ */
+ public function generateUID($stgkzl, $jahr, $stgtyp, $matrikelnummer, $vorname, $nachname)
+ {
+ $uid = false;
+
+ Events::trigger(
+ 'generate_student_uid',
+ function ($value) use ($uid) {
+ $uid = $value;
+ },
+ $stgkzl,
+ $jahr,
+ $stgtyp,
+ $matrikelnummer,
+ $vorname,
+ $nachname
+ );
+
+ if ($uid !== false)
+ return success($uid);
+
+ $art = mb_substr($matrikelnummer, 2, 1);
+ $nr = mb_substr($matrikelnummer, mb_strlen(trim($matrikelnummer))-3);
+ if($art=='2') //Sommersemester
+ $nr = $nr+500;
+ elseif($art=='0' && $stgtyp=='m') //Incoming im Masterstudiengang
+ $nr = $nr+500;
+ elseif($art=='4' && $stgtyp=='l') // Lehrgangsteilnehmer im Sommersemester
+ $nr = $nr+500;
+
+
+ return success(mb_strtolower($stgkzl.$jahr.($art!='0'?$stgtyp:'x').$nr));
+ }
+
+
/**
* Get students UID by PrestudentID.
* @param $prestudent_id
@@ -78,8 +242,19 @@ class Student_model extends DB_Model
OR lower(person.nachname) like ".$this->db->escape('%'.$filter.'%')."
OR lower(person.vorname) like ".$this->db->escape('%'.$filter.'%')."
OR lower(person.nachname || ' ' || person.vorname) like ".$this->db->escape('%'.$filter.'%')."
- OR lower(person.vorname || ' ' || person.nachname) like ".$this->db->escape('%'.$filter.'%'));
+ OR lower(person.vorname || ' ' || person.nachname) like ".$this->db->escape('%'.$filter.'%')
+ );
return $result;
}
+
+ /**
+ * Get the FH-Email for a student (not the private kontakt email)
+ * @param $student_uid
+ * @return string
+ */
+ public function getEmailFH($student_uid)
+ {
+ return $student_uid . '@' . DOMAIN;
+ }
}
diff --git a/application/models/education/Gsstudientyp_model.php b/application/models/education/Gsstudientyp_model.php
new file mode 100644
index 000000000..ca9106d99
--- /dev/null
+++ b/application/models/education/Gsstudientyp_model.php
@@ -0,0 +1,14 @@
+dbTable = 'bis.tbl_gsstudientyp';
+ $this->pk = 'gsstudientyp_kurzbz';
+ }
+}
\ No newline at end of file
diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php
index 1f1b90131..de8ebc5c9 100644
--- a/application/models/education/Lehrveranstaltung_model.php
+++ b/application/models/education/Lehrveranstaltung_model.php
@@ -15,6 +15,297 @@ class Lehrveranstaltung_model extends DB_Model
$this->load->model('organisation/studiensemester_model', 'StudiensemesterModel');
}
+ /**
+ * Get Lehrveranstaltungen by eventQuery string. Use with autocomplete event queries.
+ * @param $eventQuery String
+ * @param string $studiensemester_kurzbz Filter by Studiensemester
+ * @param array $oes Filter by Organisationseinheiten
+ * @return array
+ */
+ public function getAutocompleteSuggestions($eventQuery, $studiensemester_kurzbz = null, $oes = null)
+ {
+ $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes);
+ $params = [];
+
+ /* filter by input string */
+ if (is_string($eventQuery)) {
+ $subQry.= ' AND lv.bezeichnung ILIKE ?';
+ $params[] = '%' . $eventQuery . '%';
+ }
+
+ $qry = 'SELECT DISTINCT ON (lehrveranstaltung_id) * FROM ('. $subQry. ') AS tmp';
+
+ return $this->execQuery($qry, $params);
+ }
+
+ /**
+ * Get Lehrveranstaltungen with its Stg, OE and OE-type.
+ * Filter by Studiensemester and Organisationseinheiten if necessary.
+ * @param $eventQuery String
+ * @param string $studiensemester_kurzbz Filter by Studiensemester
+ * @param array $oes Filter by Organisationseinheiten
+ * @param array $lv_ids Filter by Lehrveranstaltung-Ids
+ * @return array
+ */
+ public function getLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lv_ids = null)
+ {
+ $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes);
+ $qry = 'SELECT * FROM ('. $subQry. ') AS tmp';
+
+ if (isset($lv_ids) && is_array($lv_ids))
+ {
+ /* filter by lv_ids */
+ $implodedLvIds = "'". implode("', '", $lv_ids). "'";
+ $qry.= ' WHERE lehrveranstaltung_id IN ('. $implodedLvIds. ')';
+ }
+
+ $qry.= ' ORDER BY stg_typ_kurzbz, orgform_kurzbz DESC';
+
+ return $this->execQuery($qry);
+ }
+
+ /**
+ * Get basic query to retrieve Lehrveranstaltungen according to the Orgforms and Ausbildungssemesters actual Studienplan.
+ *
+ * @return string
+ */
+ private function _getQryLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lehrtyp_kurzbz = 'lv')
+ {
+ $qry = '
+ SELECT
+ lv.oe_kurzbz AS lv_oe_kurzbz,
+ CASE
+ WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung)
+ WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung)
+ ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
+ END AS lv_oe_bezeichnung,
+ stplsem.studiensemester_kurzbz,
+ studienordnung_id,
+ sto.studiengang_kz,
+ stpl.studienplan_id,
+ stplsem.semester,
+ stpl.orgform_kurzbz,
+ upper(stg.typ || stg.kurzbz) AS stg_typ_kurzbz,
+ stg.bezeichnung AS stg_bezeichnung,
+ stgtyp.bezeichnung AS stg_typ_bezeichnung,
+ lv.lehrveranstaltung_id,
+ lv.semester,
+ lv.bezeichnung AS lv_bezeichnung,
+ (
+ -- comma seperated string of all lehreinheitgruppen
+ SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung
+ FROM(
+ -- distinct bezeichnung, as may come multiple times from different lehreinheiten
+ SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM
+ (
+ -- distinct lehreinheitgruppe, as may come multiple times from different lehrform
+ SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz,
+ -- get Spezialgruppe or Lehrverbandgruppe
+ COALESCE(
+ legr.gruppe_kurzbz,
+ CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe )
+ ) as bezeichnung
+ FROM lehre.tbl_lehreinheitgruppe legr
+ JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
+ JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id)
+ JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz
+ WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id
+ AND le.studiensemester_kurzbz = stplsem.studiensemester_kurzbz
+ ) AS lehreinheitgruppen
+ GROUP BY studiengang_kz, bezeichnung
+ ORDER BY studiengang_kz DESC
+ ) AS uniqueLehreinheitgruppen_bezeichnung
+ ) AS lehreinheitgruppen_bezeichnung
+ FROM
+ lehre.tbl_studienplan stpl
+ JOIN lehre.tbl_studienordnung sto USING (studienordnung_id)
+ JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id)
+ JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester)
+ JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
+ JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
+ JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
+ JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
+ /* filter by lehrtyp_kurzbz, default is lvs only */
+ WHERE
+ lehrtyp_kurzbz = '. $this->db->escape($lehrtyp_kurzbz);
+
+ if (isset($studiensemester_kurzbz) && is_string($studiensemester_kurzbz))
+ {
+ /* filter by studiensemester */
+ $qry.= ' AND stplsem.studiensemester_kurzbz = '. $this->db->escape($studiensemester_kurzbz);
+
+ }
+
+ if (isset($oes) && is_array($oes))
+ {
+ /* filter by organisationseinheit */
+ $implodedOes = "'". implode("', '", $oes). "'";
+ $qry.= ' AND lv.oe_kurzbz IN ('. $implodedOes. ')';
+ }
+
+ return $qry;
+ }
+
+ /**
+ * Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes, that are assigned to
+ * a template. This data structure can be used for nested tabulator data tree.
+ *
+ * @param null|string $studiensemester_kurzbz
+ * @param null|array $oes
+ * @return array|stdClass|null
+ */
+ public function getTemplateLvTree($studiensemester_kurzbz = null, $oes = null){
+ $params = [];
+ $qry = '
+ WITH
+ -- All Lvs that are assigned to a template in given Studiensemester for given Oes
+ -- joining via actual Studienplan
+ standardisierteLvs AS (
+ SELECT
+ lv.*,
+ stpl.studienplan_id::text as studienplan_id,
+ stpl.bezeichnung AS studienplan_bezeichnung,
+ stplsem.studiensemester_kurzbz
+ FROM
+ lehre.tbl_studienplan stpl
+ JOIN lehre.tbl_studienordnung sto USING (studienordnung_id)
+ JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id)
+ JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester)
+ JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
+ JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
+ JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
+ JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
+ WHERE
+ -- filter type lv
+ lehrtyp_kurzbz = \'lv\'
+ -- filter lvs assigned to template (= standardisierte lv)
+ AND lehrveranstaltung_template_id IS NOT NULL';
+
+ if (is_string($studiensemester_kurzbz))
+ {
+ /* filter by studiensemester */
+ $params[]= $studiensemester_kurzbz;
+ $qry.= ' AND stplsem.studiensemester_kurzbz = ? ';
+
+ }
+
+ if (is_array($oes))
+ {
+ /* filter by organisationseinheit */
+ $params[]= $oes;
+ $qry.= ' AND lv.oe_kurzbz IN ? ';
+ }
+ $qry.= '
+ ),
+ -- All templates
+ templateLvs AS (
+ SELECT
+ lv.*,
+ NULL AS studienplan_id,
+ (
+ SELECT string_agg(stpl_bezeichnung, \', \')
+ FROM
+ (
+ SELECT stlv.studienplan_bezeichnung AS stpl_bezeichnung
+ FROM standardisierteLvs stlv
+ WHERE stlv.lehrveranstaltung_template_id = lv.lehrveranstaltung_id
+ ) AS studienplaene
+ ) AS studienplan_bezeichnung,
+ NULL AS studiensemester_kurzbz
+ FROM
+ lehre.tbl_lehrveranstaltung lv
+ WHERE
+ -- filter type template
+ lehrtyp_kurzbz = \'tpl\'
+ -- filter semester that were retrieved by standardisierte lvs semester for selected studiensemester
+ AND EXISTS (
+ SELECT 1
+ FROM standardisierteLvs std
+ WHERE std.lehrveranstaltung_template_id = lv.lehrveranstaltung_id
+ )';
+
+ if (is_array($oes))
+ {
+ /* filter by organisationseinheit */
+ $params[]= $oes;
+ $qry.= ' AND lv.oe_kurzbz IN ? ';
+ }
+ $qry.= '
+ )
+ ';
+
+ $qry.= '
+ SELECT
+ lv.lehrveranstaltung_id,
+ lv.kurzbz,
+ lv.lehrtyp_kurzbz,
+ lv.bezeichnung AS lv_bezeichnung,
+ lv.bezeichnung_english,
+ lv.studiengang_kz,
+ lv.semester,
+ lv.oe_kurzbz,
+ lv.ects,
+ lv.lehrform_kurzbz,
+ lv.orgform_kurzbz,
+ lv.sprache,
+ lv.aktiv,
+ lv.lehrveranstaltung_template_id,
+ lv.studienplan_id,
+ lv.studienplan_bezeichnung,
+ lv.studiensemester_kurzbz,
+ upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz",
+ stg.bezeichnung AS "stg_bezeichnung",
+ stgtyp.bezeichnung AS "stg_typ_bezeichnung",
+ CASE
+ WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung)
+ WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung)
+ ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
+ END AS "lv_oe_bezeichnung",
+ (
+ -- comma seperated string of all lehreinheitgruppen
+ SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung
+ FROM(
+ -- distinct bezeichnung, as may come multiple times from different lehreinheiten
+ SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM
+ (
+ -- distinct lehreinheitgruppe, as may come multiple times from different lehrform
+ SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz,
+ -- get Spezialgruppe or Lehrverbandgruppe
+ COALESCE(
+ legr.gruppe_kurzbz,
+ CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe )
+ ) as bezeichnung
+ FROM lehre.tbl_lehreinheitgruppe legr
+ JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
+ JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id)
+ JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz
+ WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id
+ AND le.studiensemester_kurzbz = lv.studiensemester_kurzbz
+ ) AS lehreinheitgruppen
+ GROUP BY studiengang_kz, bezeichnung
+ ORDER BY studiengang_kz DESC
+ ) AS uniqueLehreinheitgruppen_bezeichnung
+ ) AS lehreinheitgruppen_bezeichnung
+ FROM (
+ SELECT
+ *
+ FROM
+ standardisierteLvs
+ UNION
+ SELECT
+ *
+ FROM templateLvs
+ ) AS lv
+ JOIN public.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz
+ JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ
+ JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = lv.oe_kurzbz
+ ORDER BY
+ oe.bezeichnung, lv.semester, lv.bezeichnung
+ ';
+
+ return $this->execQuery($qry, $params);
+ }
+
/**
* Gets unique Groupstrings for Lehrveranstaltungen, e.g. WS2018_BIF_1_PRJM_VZ_LV12345
* @param string $studiensemester_kurzbz
@@ -493,4 +784,11 @@ class Lehrveranstaltung_model extends DB_Model
return $this->execQuery($qry, array($student_uid));
}
+
+ public function getStg($lehrveranstaltung_id)
+ {
+ $this->addSelect('stg.*');
+ $this->addJoin('public.tbl_studiengang stg', 'studiengang_kz');
+ return $this->load($lehrveranstaltung_id);
+ }
}
diff --git a/application/models/education/Lvgesamtnote_model.php b/application/models/education/Lvgesamtnote_model.php
index f0c1883de..975833287 100644
--- a/application/models/education/Lvgesamtnote_model.php
+++ b/application/models/education/Lvgesamtnote_model.php
@@ -10,5 +10,6 @@ class Lvgesamtnote_model extends DB_Model
parent::__construct();
$this->dbTable = 'campus.tbl_lvgesamtnote';
$this->pk = array('student_uid', 'studiensemester_kurzbz', 'lehrveranstaltung_id');
+ $this->hasSequence = false;
}
}
diff --git a/application/models/education/Paabgabe_model.php b/application/models/education/Paabgabe_model.php
index b876030a6..5fb58cc81 100644
--- a/application/models/education/Paabgabe_model.php
+++ b/application/models/education/Paabgabe_model.php
@@ -25,7 +25,7 @@ class Paabgabe_model extends DB_Model
WHERE projektarbeit_id = ?
AND paabgabetyp_kurzbz = 'end'
AND paabg.abgabedatum IS NOT NULL
- ORDER BY paabg.abgabedatum, paabg.datum DESC
+ ORDER BY paabg.abgabedatum DESC, paabg.datum DESC
LIMIT 1";
return $this->execQuery($qry, array($projektarbeit_id));
diff --git a/application/models/education/Pruefung_model.php b/application/models/education/Pruefung_model.php
index e3776c4ad..409c0b733 100644
--- a/application/models/education/Pruefung_model.php
+++ b/application/models/education/Pruefung_model.php
@@ -29,11 +29,252 @@ class Pruefung_model extends DB_Model
JOIN lehre.tbl_pruefung prfg USING (student_uid)
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
- JOIN public.tbl_studiengang stg ON prst.studiengang_kz = stg.studiengang_kz
+ JOIN public.tbl_studiengang stg ON prst.studiengang_kz = stg.studiengang_kz
WHERE pers.person_id = ?
AND le.studiensemester_kurzbz = ?
ORDER BY prfg.datum, pruefung_id';
return $this->execQuery($qry, array($person_id, $studiensemester_kurzbz));
}
+
+
+ /**
+ * NOTE(chris): not used
+ * @return string
+ */
+ protected function loadWhereThreeExamsFailed()
+ {
+ $this->load->config('studierendenantrag');
+
+ $this->dbTable = 'lehre.tbl_pruefung p';
+
+ $sprache_index = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
+
+ $this->addSelect('max(p.datum) as datum');
+ $this->addSelect('pers.vorname');
+ $this->addSelect('pers.nachname');
+ $this->addSelect('pers.person_id');
+ $this->addSelect('s.matrikelnr');
+ $this->addSelect('g.bezeichnung');
+ $this->addSelect('g.studiengang_kz');
+ $this->addSelect('o.bezeichnung_mehrsprachig[(' . $sprache_index . ')] AS orgform', false);
+ $this->addSelect('ps.prestudent_id');
+ $this->addSelect('lv.bezeichnung as lvbezeichnung');
+ $this->addSelect('le.studiensemester_kurzbz');
+ $this->addSelect('a.typ');
+ $this->addSelect('campus.get_status_studierendenantrag(a.studierendenantrag_id) status');
+ $this->addSelect('count(1) as count');
+
+ $this->addGroupBy([
+ 'pers.vorname',
+ 'pers.nachname',
+ 'pers.person_id',
+ 's.matrikelnr',
+ 'g.bezeichnung',
+ 'g.studiengang_kz',
+ 'o.bezeichnung_mehrsprachig',
+ 'ps.prestudent_id',
+ 'lv.bezeichnung',
+ 'le.studiensemester_kurzbz',
+ 'a.typ',
+ 'a.studierendenantrag_id'
+ ]);
+ $this->addJoin('lehre.tbl_note n', 'note');
+ $this->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id');
+ $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
+ $this->addJoin('public.tbl_student s', 'student_uid');
+ $this->addJoin('public.tbl_prestudent ps', 'prestudent_id');
+ $this->addJoin('public.tbl_person pers', 'person_id');
+ $this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid');
+ $this->addJoin('public.tbl_studiengang g', 'ps.studiengang_kz=g.studiengang_kz');
+ $this->addJoin(
+ 'public.tbl_prestudentstatus pss',
+ 'pss.prestudent_id=ps.prestudent_id
+ AND pss.studiensemester_kurzbz=le.studiensemester_kurzbz
+ AND pss.status_kurzbz=get_rolle_prestudent(ps.prestudent_id, le.studiensemester_kurzbz)',
+ 'LEFT'
+ );
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+ $this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, pss.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz');
+ $this->db->join('campus.tbl_studierendenantrag a', 'ps.prestudent_id=a.prestudent_id and a.typ = ?', 'LEFT', false);
+
+ $this->db->where("n.positiv", false);
+ /* $this->db->where_in("p.pruefungstyp_kurzbz1", ['kommPruef','zusKommPruef']);*/
+ $this->db->where_in("get_rolle_prestudent(ps.prestudent_id, null)", $this->config->item('antrag_prestudentstatus_whitelist'));
+
+ $this->db->where("g.aktiv", true);
+
+ $this->db->where('lv.studiengang_kz not in(
+ SELECT ps.studiengang_kz
+ FROM
+ public.tbl_prestudent ps1
+ JOIN public.tbl_prestudentstatus pss USING (prestudent_id)
+ WHERE pss.statusgrund_id in ?
+ AND ps.prestudent_id = ps1.prestudent_id)', null, false);
+
+ // NOTE(chris): is Wiederholer without set statusgrund (legacy?)
+ $this->db->where(
+ '(SELECT COUNT(*)
+ FROM (SELECT DISTINCT studiensemester_kurzbz
+ FROM tbl_prestudentstatus _s
+ WHERE ausbildungssemester=get_absem_prestudent(ps.prestudent_id, le.studiensemester_kurzbz)
+ AND prestudent_id=ps.prestudent_id) a) = 1',
+ null,
+ false
+ );
+
+ return $this->db->get_compiled_select($this->dbTable);
+ }
+
+ /**
+ * @return stdClass
+ */
+ public function loadWhereCommitteeExamsFailed()
+ {
+ $this->load->config('studierendenantrag');
+
+ $this->dbTable = 'lehre.tbl_pruefung p';
+
+ $this->addSelect('p.datum');
+
+ $this->addJoin('lehre.tbl_note n', 'note');
+
+ $this->db->where("n.positiv", false);
+ $note_blacklist = $this->config->item('note_blacklist_wiederholung');
+ if ($note_blacklist)
+ $this->db->where_not_in("n.note", $note_blacklist);
+ $this->db->where_in("p.pruefungstyp_kurzbz", ['kommPruef','zusKommPruef']);
+
+ $this->addOrder('p.datum', 'DESC');
+
+ return $this->load();
+ }
+
+
+ /**
+ * @return void
+ */
+ protected function withDetailsForStudierendenAntrag()
+ {
+ $this->load->config('studierendenantrag');
+
+ $sprache_index = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
+
+ $this->addSelect('pers.vorname');
+ $this->addSelect('pers.nachname');
+ $this->addSelect('pers.person_id');
+ $this->addSelect('s.matrikelnr');
+ $this->addSelect('g.bezeichnung');
+ $this->addSelect('g.studiengang_kz');
+ $this->addSelect('o.bezeichnung_mehrsprachig[(' . $sprache_index . ')] AS orgform', false);
+ $this->addSelect('ps.prestudent_id');
+ $this->addSelect('lv.bezeichnung as lvbezeichnung');
+ $this->addSelect('le.studiensemester_kurzbz');
+ $this->addSelect('a.studierendenantrag_id');
+ $this->addSelect('a.typ');
+ $this->addSelect('campus.get_status_studierendenantrag(a.studierendenantrag_id) status');
+ $this->addSelect('pss.ausbildungssemester');
+
+ $this->addJoin('(SELECT MAX(datum) AS datum, lehreinheit_id AS le_id, student_uid AS stud_uid FROM lehre.tbl_pruefung p WHERE pruefungstyp_kurzbz IN (\'kommPruef\', \'zusKommPruef\') GROUP BY lehreinheit_id, student_uid) lpd',
+ 'p.datum = lpd.datum AND p.lehreinheit_id = lpd.le_id AND p.student_uid = lpd.stud_uid');
+ $this->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id');
+ $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
+ $this->addJoin('public.tbl_student s', 'student_uid');
+ $this->addJoin('public.tbl_prestudent ps', 'prestudent_id');
+ $this->addJoin('public.tbl_person pers', 'person_id');
+ $this->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid');
+ $this->addJoin('public.tbl_studiengang g', 'ps.studiengang_kz=g.studiengang_kz');
+ $this->addJoin(
+ 'public.tbl_prestudentstatus pss',
+ 'pss.prestudent_id=ps.prestudent_id
+ AND pss.studiensemester_kurzbz=le.studiensemester_kurzbz
+ AND pss.status_kurzbz=get_rolle_prestudent(ps.prestudent_id, le.studiensemester_kurzbz)',
+ 'LEFT'
+ );
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+ $this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, pss.orgform_kurzbz, g.orgform_kurzbz)=o.orgform_kurzbz');
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag a',
+ 'ps.prestudent_id=a.prestudent_id and a.typ=' . $this->escape(Studierendenantrag_model::TYP_WIEDERHOLUNG),
+ 'LEFT'
+ );
+
+ $this->db->where("g.aktiv", true);
+
+ $statusgruende = $this->config->item('status_gruende_wiederholer');
+ if (is_array($statusgruende) && !isEmptyArray($statusgruende)) {
+ foreach ($statusgruende as $k => $v) {
+ $statusgruende[$k] = $this->db->escape($v);
+ }
+ $this->db->where('lv.studiengang_kz NOT IN(
+ SELECT ps1.studiengang_kz
+ FROM
+ public.tbl_prestudent ps1
+ JOIN public.tbl_prestudentstatus pss USING (prestudent_id)
+ WHERE pss.statusgrund_id in (' . implode(',', $statusgruende) . ')
+ AND ps.prestudent_id = ps1.prestudent_id)', null, false);
+ }
+ }
+
+ /**
+ * @param integer $prestudent_id student_uid
+ *
+ * @return stdClass
+ */
+ public function loadWhereCommitteeExamFailedForPrestudent($prestudent_id, $max_date = null, $studiensemester_kurzbz = null)
+ {
+ $this->withDetailsForStudierendenAntrag();
+
+ $this->db->where('ps.prestudent_id', $prestudent_id);
+
+ if ($max_date !== null) {
+ $this->db->where('p.datum <=', $max_date);
+ }
+ if ($studiensemester_kurzbz !== null) {
+ $this->db->where('le.studiensemester_kurzbz', $studiensemester_kurzbz);
+ }
+
+ return $this->loadWhereCommitteeExamsFailed();
+ }
+
+ /**
+ * @param string $status
+ * @param \DateTime $maxDate
+ * @param \DateTime $minDate
+ *
+ * @return stdClass
+ */
+ public function getAllPrestudentsWhereCommitteeExamFailed($status, $maxDate, $minDate)
+ {
+ $this->withDetailsForStudierendenAntrag();
+
+ if ($maxDate)
+ $this->db->where("p.datum <= ", $maxDate->format('Y-m-d'));
+ if ($minDate)
+ $this->db->where("p.datum > ", $minDate->format('Y-m-d'));
+
+ $this->db->where("b.aktiv", true);
+
+ $this->db->where_in("get_rolle_prestudent(ps.prestudent_id, null)", $this->config->item('antrag_prestudentstatus_whitelist'));
+
+ if (is_array($status)) {
+ if (in_array(null, $status)) {
+ $status = array_filter($status);
+ if (count($status)) {
+ $this->db->group_start();
+ $this->db->where_in('campus.get_status_studierendenantrag(a.studierendenantrag_id)', $status);
+ $this->db->or_where('campus.get_status_studierendenantrag(a.studierendenantrag_id)', null);
+ $this->db->group_end();
+ } else {
+ $this->db->where('campus.get_status_studierendenantrag(a.studierendenantrag_id)', null);
+ }
+ } else {
+ $this->db->where_in('campus.get_status_studierendenantrag(a.studierendenantrag_id)', $status);
+ }
+ } else {
+ $this->db->where('campus.get_status_studierendenantrag(a.studierendenantrag_id)', $status);
+ }
+
+ return $this->loadWhereCommitteeExamsFailed();
+ }
}
diff --git a/application/models/education/Studentlehrverband_model.php b/application/models/education/Studentlehrverband_model.php
index 765429396..2ef14e58e 100644
--- a/application/models/education/Studentlehrverband_model.php
+++ b/application/models/education/Studentlehrverband_model.php
@@ -11,5 +11,7 @@ class Studentlehrverband_model extends DB_Model
$this->dbTable = 'public.tbl_studentlehrverband';
$this->pk = array('studiensemester_kurzbz', 'student_uid');
$this->hasSequence = false;
+
+ $this->load->model('crm/prestudentstatus_model', 'PrestudentstatusModel');
}
}
diff --git a/application/models/education/Studierendenantrag_model.php b/application/models/education/Studierendenantrag_model.php
new file mode 100644
index 000000000..677d01f04
--- /dev/null
+++ b/application/models/education/Studierendenantrag_model.php
@@ -0,0 +1,493 @@
+dbTable = 'campus.tbl_studierendenantrag';
+ $this->pk = 'studierendenantrag_id';
+
+ $this->load->config('studierendenantrag');
+
+ $this->load->model('education/Studierendenantragstatus_model', 'StudierendenantragstatusModel');
+ }
+
+ public function loadCreatedForStudiengaenge($studiengaenge, $typ)
+ {
+ return $this->loadForStudiengaenge($studiengaenge, $typ, $this->StudierendenantragstatusModel::STATUS_CREATED);
+ }
+
+ public function loadForStudiengaenge($studiengaenge, $typ = null, $status = null, $sql = null)
+ {
+ if ($sql == null)
+ $sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
+
+ $this->addSelect('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung AS bezeichnung');
+ $this->addSelect('bezeichnung_mehrsprachig[(' . $sql . ')] AS orgform', false);
+ $this->addSelect('s.studierendenantrag_id');
+ $this->addSelect('matrikelnr');
+ $this->addSelect('studienjahr_kurzbz');
+ $this->addSelect('vorname');
+ $this->addSelect('nachname');
+ $this->addSelect('unruly');
+ $this->addSelect('p.prestudent_id');
+ $this->addSelect('p.studiengang_kz');
+ $this->addSelect('semester');
+ $this->addSelect($this->dbTable . '.grund');
+ $this->addSelect($this->dbTable . '.datum');
+ $this->addSelect('datum_wiedereinstieg');
+ $this->addSelect($this->dbTable . '.typ');
+ $this->addSelect('st.studierendenantrag_statustyp_kurzbz as status');
+ $this->addSelect('s.insertvon as status_insertvon');
+ $this->addSelect('s.insertamum as status_insertamum');
+ $this->addSelect('dms_id');
+ $this->addSelect('st.bezeichnung[(' . $sql . ')] as statustyp');
+
+ $this->addJoin('public.tbl_prestudent p', 'prestudent_id');
+ $this->addJoin('public.tbl_student', 'prestudent_id');
+ $this->addJoin('public.tbl_person', 'person_id');
+ $this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz');
+ $this->addJoin('public.tbl_studiensemester ss', 'studiensemester_kurzbz');
+ $this->addJoin(
+ 'public.tbl_prestudentstatus ps',
+ 'ps.prestudent_id=p.prestudent_id
+ AND ps.studiensemester_kurzbz=ss.studiensemester_kurzbz
+ AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, ss.studiensemester_kurzbz)',
+ 'LEFT'
+ );
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+ $this->addJoin('bis.tbl_orgform of', 'of.orgform_kurzbz=COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, stg.orgform_kurzbz)');
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_status as s',
+ 'campus.get_status_id_studierendenantrag('. $this->dbTable .'.studierendenantrag_id) = studierendenantrag_status_id'
+ );
+ $this->addJoin('campus.tbl_studierendenantrag_statustyp as st', 'studierendenantrag_statustyp_kurzbz');
+
+ $this->db->where_in('p.studiengang_kz', $studiengaenge);
+
+ $where = [];
+ if ($status !== null)
+ $where['st.studierendenantrag_statustyp_kurzbz'] = $status;
+ if ($typ !== null)
+ $where[$this->dbTable . '.typ'] = $typ;
+
+ return $this->loadWhere($where);
+ }
+
+ public function loadActiveForStudiengaenge($studiengaenge)
+ {
+ // NOTE(chris): get language before changing things in the global
+ // db object because getUserLanguage() might use it and it should
+ // not have been tampered with
+ $sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
+
+ $this->db->group_start();
+ $this->db->where_not_in('s.studierendenantrag_statustyp_kurzbz', [
+ Studierendenantragstatus_model::STATUS_CANCELLED,
+ Studierendenantragstatus_model::STATUS_APPROVED,
+ Studierendenantragstatus_model::STATUS_REJECTED,
+ Studierendenantragstatus_model::STATUS_OBJECTION_DENIED,
+ Studierendenantragstatus_model::STATUS_DEREGISTERED,
+ Studierendenantragstatus_model::STATUS_PAUSE,
+ Studierendenantragstatus_model::STATUS_REMINDERSENT
+ ]);
+ $this->db->or_group_start();
+ $this->db->where('s.studierendenantrag_statustyp_kurzbz', Studierendenantragstatus_model::STATUS_APPROVED);
+ $this->db->where('tbl_studierendenantrag.typ', Studierendenantrag_model::TYP_ABMELDUNG_STGL);
+ $this->db->group_end();
+ $this->db->group_end();
+
+ return $this->loadForStudiengaenge($studiengaenge, null, null, $sql);
+ }
+
+ public function loadStgsWithAntraege($studiengaenge)
+ {
+ $this->addDistinct();
+ $this->addSelect('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung AS bezeichnung');
+ $this->addSelect('p.studiengang_kz');
+
+ $this->addJoin('public.tbl_prestudent p', 'prestudent_id');
+ $this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz');
+
+ $this->addOrder('UPPER(stg.typ) || UPPER(stg.kurzbz) || \' \' || stg.bezeichnung');
+
+ $this->db->where_in('p.studiengang_kz', $studiengaenge);
+
+ return $this->load();
+ }
+
+ public function isInStudiengang($studierendenantrag_id, $studiengaenge)
+ {
+ $this->addJoin('public.tbl_prestudent', 'prestudent_id');
+
+ $this->db->where_in('studiengang_kz', $studiengaenge);
+
+ return $this->load($studierendenantrag_id);
+ }
+
+ public function loadIdAndStatusWhere($where)
+ {
+ $this->addSelect('studierendenantrag_id');
+ $this->addSelect('campus.get_status_studierendenantrag(studierendenantrag_id) status');
+ return $this->loadWhere($where);
+ }
+
+ public function loadWithStatusWhere($where, $types = null)
+ {
+ $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage());
+
+ $this->addSelect('*');
+ $this->addSelect($this->dbTable . '.grund AS grund');
+ $this->addSelect('s.studierendenantrag_statustyp_kurzbz status');
+ $this->addSelect('s.insertvon status_insertvon');
+ $this->addSelect('t.bezeichnung[(' . $lang . ')] statustyp');
+ $this->addSelect('p.unruly AS unruly');
+ $this->addSelect($this->dbTable . '.insertamum AS insertamum');
+
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_status s',
+ 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id'
+ );
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_statustyp t',
+ 's.studierendenantrag_statustyp_kurzbz=t.studierendenantrag_statustyp_kurzbz'
+ );
+ $this->addJoin(
+ 'public.tbl_student st',
+ 'st.prestudent_id=tbl_studierendenantrag.prestudent_id'
+ );
+ $this->addJoin(
+ 'public.tbl_benutzer b',
+ 'st.student_uid=b.uid'
+ );
+ $this->addJoin(
+ 'public.tbl_person p',
+ 'b.person_id=p.person_id'
+ );
+
+ if ($types && is_array($types)) {
+ $this->db->where_in('typ', $types);
+ }
+
+ $this->addOrder('datum', 'DESC');
+
+ return $this->loadWhere($where);
+ }
+
+ /**
+ * Get the studiengang and ausbildungssemester the student was in
+ * for the studiensemester the antrag was committed for
+ *
+ * @param integer $antrag_id
+ *
+ * @return stdClass
+ */
+ public function getStgAndSem($antrag_id)
+ {
+ $this->addSelect('p.studiengang_kz');
+ $this->addSelect('stg.bezeichnung');
+ $this->addSelect('s.ausbildungssemester');
+ $this->addSelect('plan.sprache');
+ $this->addSelect('COALESCE(plan.orgform_kurzbz, s.orgform_kurzbz, stg.orgform_kurzbz) AS orgform_kurzbz');
+
+ $this->addJoin(
+ 'public.tbl_prestudentstatus s',
+ $this->dbTable . '.prestudent_id=s.prestudent_id
+ AND ' .
+ $this->dbTable . '.studiensemester_kurzbz=s.studiensemester_kurzbz
+ AND ' .
+ $this->dbTable . '.insertamum > s.insertamum'
+ );
+ $this->addJoin('public.tbl_prestudent p', $this->dbTable . '.prestudent_id=p.prestudent_id');
+ $this->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+
+ $this->addOrder('s.datum', 'DESC');
+ $this->addOrder('s.insertamum', 'DESC');
+ $this->addOrder('s.ext_id', 'DESC');
+
+ $this->addLimit(1);
+
+ return $this->loadWhere([
+ $this->pk => $antrag_id
+ ]);
+ }
+
+ /**
+ * Get the studiengang the student is in
+ *
+ * @param integer $antrag_id
+ *
+ * @return stdClass
+ */
+ public function getStg($antrag_id)
+ {
+ $this->addSelect('p.studiengang_kz');
+ $this->addJoin('public.tbl_prestudent p', 'prestudent_id');
+
+ $this->addLimit(1);
+
+ return $this->load(
+ $antrag_id
+ );
+ }
+
+ public function getStgEmail($antrag_id)
+ {
+ $this->addJoin('public.tbl_prestudent p', 'prestudent_id');
+ $this->addJoin('public.tbl_studiengang sg', 'studiengang_kz');
+ $this->addSelect('sg.email');
+
+ return $this->load($antrag_id);
+ }
+
+ public function loadForPerson($person_id)
+ {
+ $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage());
+ $this->addSelect('stg.bezeichnung');
+ $this->addSelect('bezeichnung_mehrsprachig[(' . $lang . ')] as orgform');
+ $this->addSelect('p.studiengang_kz');
+ $this->addSelect('st.studierendenantrag_statustyp_kurzbz as status');
+ $this->addSelect('st.bezeichnung[(' . $lang . ')] as status_bezeichnung');
+ $this->addSelect('p.prestudent_id');
+ $this->addSelect($this->dbTable . '.studierendenantrag_id');
+ $this->addSelect($this->dbTable . '.studiensemester_kurzbz');
+ $this->addSelect($this->dbTable . '.datum');
+ $this->addSelect($this->dbTable . '.typ');
+ $this->addSelect($this->dbTable . '.insertamum');
+ $this->addSelect($this->dbTable . '.insertvon');
+ $this->addSelect($this->dbTable . '.datum_wiedereinstieg');
+ $this->addSelect($this->dbTable . '.grund');
+ $this->addSelect($this->dbTable . '.dms_id');
+ $this->addSelect('s.insertvon AS status_insertvon');
+ $this->addSelect(
+ "(SELECT count(1) FROM campus.tbl_studierendenantrag_status WHERE studierendenantrag_id = " .
+ $this->dbTable .
+ ".studierendenantrag_id AND studierendenantrag_statustyp_kurzbz = 'Genehmigt') AS isapproved",
+ false
+ );
+
+ $this->addJoin('public.tbl_prestudent p', 'prestudent_id', 'RIGHT');
+ $this->addJoin('public.tbl_studiengang stg', 'p.studiengang_kz=stg.studiengang_kz');
+ $this->addJoin(
+ 'public.tbl_prestudentstatus ps',
+ 'ps.prestudent_id=p.prestudent_id AND ps.studiensemester_kurzbz=' .
+ $this->dbTable .
+ '.studiensemester_kurzbz AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, ' .
+ $this->dbTable .
+ '.studiensemester_kurzbz)',
+ 'LEFT'
+ );
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
+ $this->addJoin('bis.tbl_orgform of', 'of.orgform_kurzbz=COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, stg.orgform_kurzbz)');
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_status s',
+ 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id',
+ 'LEFT'
+ );
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_statustyp st',
+ 's.studierendenantrag_statustyp_kurzbz=st.studierendenantrag_statustyp_kurzbz',
+ 'LEFT'
+ );
+
+ $this->db->where("(
+ SELECT status_kurzbz
+ FROM public.tbl_prestudentstatus
+ WHERE prestudent_id=p.prestudent_id
+ AND status_kurzbz='Student'
+ LIMIT 1
+ ) IS NOT NULL", null, false);
+
+
+ return $this->loadWhere([
+ 'p.person_id' => $person_id
+ ]);
+ }
+
+ public function getAntraegeWhereWiedereinstiegBetween($start, $end)
+ {
+ $this->addSelect('sg.email');
+ $this->addSelect('vorname');
+ $this->addSelect('nachname');
+ $this->addSelect($this->dbTable.'.*');
+
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_status s',
+ 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id'
+ );
+ $this->addJoin('public.tbl_prestudent p', 'prestudent_id');
+ $this->addJoin('public.tbl_person', 'person_id');
+ $this->addJoin('public.tbl_studiengang sg', 'studiengang_kz');
+
+ $this->db->where('datum_wiedereinstieg >=', $start->format('Y-m-d'));
+ $this->db->where('datum_wiedereinstieg <=', $end->format('Y-m-d'));
+
+ return $this->loadWhere([
+ 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED,
+ $this->dbTable.'.typ' => self::TYP_UNTERBRECHUNG,
+ ]);
+ }
+
+ public function getWithLastStatusWhere($where)
+ {
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_status s',
+ 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id'
+ );
+
+ return $this->loadWhere($where);
+ }
+
+ /**
+ * Checks if the Prestudent has an active Unterbrechung between
+ * the start of the given semester and the given enddate.
+ * If the enddate is omitted the end of the given semester is used.
+ *
+ * @param integer $prestudent_id
+ * @param string $studiensemester_kurzbz
+ * @param string $enddate (optional)
+ *
+ * @return boolean
+ */
+ public function hasRunningUnterbrechungBetween($prestudent_id, $studiensemester, $enddate = null)
+ {
+ $start = '(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=' . $this->db->escape($studiensemester) . ')';
+ $end = $enddate
+ ? $this->db->escape($enddate)
+ : '(SELECT ende FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=' . $this->db->escape($studiensemester) . ')';
+
+ $this->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
+ $this->db->where([
+ 'prestudent_id' => $prestudent_id,
+ 'typ' => Studierendenantrag_model::TYP_UNTERBRECHUNG,
+ 'campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN (\'' . Studierendenantragstatus_model::STATUS_CANCELLED . '\', \'' . Studierendenantragstatus_model::STATUS_REJECTED . '\')' => null,
+ 'start < ' . $end => null,
+ 'datum_wiedereinstieg > ' . $start => null,
+ ]);
+ return (boolean)$this->db->count_all_results($this->dbTable);
+ }
+
+ /**
+ * Gets free semester slots for a new Unterbrechung.
+ *
+ * @param integer $prestudent_id
+ * @param string $studiensemester_kurzbz (optional)
+ *
+ * @return stdClass
+ */
+ public function getFreeSlotsForUnterbrechung($prestudent_id, $studiensemester = null)
+ {
+ $max_starters = 2;
+ $max_length = max(
+ 2,
+ (integer)$this->config->item('unterbrecher_semester_max_length')
+ );
+
+
+ $subquery = '';
+ if ($studiensemester)
+ $subquery = 'SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=?';
+ else
+ $subquery = 'SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=public.get_stdsem_prestudent (?, null)';
+
+ $sql = "WITH numbered_sems AS (
+ SELECT
+ a.studienjahr_kurzbz AS studienjahr_kurzbz,
+ a.studiensemester_kurzbz AS von,
+ b.studiensemester_kurzbz AS bis,
+ a.start AS start,
+ b.start AS ende,
+ ROW_NUMBER() OVER (
+ PARTITION BY a.studiensemester_kurzbz
+ ORDER BY b.start
+ ) AS row_number
+ FROM public.tbl_studiensemester a
+ LEFT JOIN public.tbl_studiensemester b ON (b.start > a.ende)
+ ),
+ last_sems AS (
+ SELECT *
+ FROM numbered_sems
+ WHERE numbered_sems.row_number <= ?
+ )
+ SELECT s.von, s.bis, s.start, s.ende, studierendenantrag_id, studienjahr_kurzbz
+ FROM last_sems s
+ LEFT JOIN (
+ SELECT studierendenantrag_id, start, datum_wiedereinstieg AS ende
+ FROM campus.tbl_studierendenantrag
+ LEFT JOIN public.tbl_studiensemester USING(studiensemester_kurzbz)
+ WHERE typ=?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
+ AND prestudent_id=?
+ ) a ON (s.start < a.ende AND s.ende > a.start)
+ WHERE s.start >= (" . $subquery . ")
+ ORDER BY s.start, s.ende
+ LIMIT ?;";
+
+ return $this->execQuery($sql, [
+ $max_length,
+ self::TYP_UNTERBRECHUNG,
+ array(
+ Studierendenantragstatus_model::STATUS_CANCELLED,
+ Studierendenantragstatus_model::STATUS_REJECTED
+ ),
+ $prestudent_id,
+ $studiensemester ?: $prestudent_id,
+ $max_length * $max_starters
+ ]);
+ }
+
+ /**
+ * Returns if an Antrag is manually paused
+ *
+ * @param integer $antrag_id
+ *
+ * @return boolean
+ */
+ public function isManuallyPaused($antrag_id)
+ {
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_status s',
+ 'campus.get_status_id_studierendenantrag(' . $this->dbTable . '.studierendenantrag_id)=s.studierendenantrag_status_id'
+ );
+
+ $this->db->where([
+ 's.studierendenantrag_id' => $antrag_id,
+ 's.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_PAUSE
+ ]);
+
+ $this->db->group_start();
+ $this->db->where_not_in('s.insertvon', [
+ Studierendenantragstatus_model::INSERTVON_DEREGISTERED,
+ Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL
+ ]);
+ $this->db->or_group_start();
+ $this->db->where('s.insertvon', Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL);
+ $this->db->where('1 !=', '(
+ SELECT COUNT(*)%2
+ FROM campus.tbl_studierendenantrag_status i
+ WHERE i.studierendenantrag_id = s.studierendenantrag_id
+ AND i.insertamum > (
+ SELECT ii.insertamum
+ FROM campus.tbl_studierendenantrag_status ii
+ WHERE ii.studierendenantrag_id = s.studierendenantrag_id
+ AND ii.insertvon <> ' . $this->escape(Studierendenantragstatus_model::INSERTVON_ABMELDUNGSTGL) . '
+ ORDER BY ii.insertamum DESC
+ LIMIT 1
+ )
+ )', false);
+ $this->db->group_end();
+ $this->db->group_end();
+
+ return hasData($this->load());
+ }
+}
diff --git a/application/models/education/Studierendenantraglehrveranstaltung_model.php b/application/models/education/Studierendenantraglehrveranstaltung_model.php
new file mode 100644
index 000000000..4318c773e
--- /dev/null
+++ b/application/models/education/Studierendenantraglehrveranstaltung_model.php
@@ -0,0 +1,104 @@
+dbTable = 'campus.tbl_studierendenantrag_lehrveranstaltung';
+ $this->pk = 'studierendenantrag_lehrveranstaltung_id';
+ }
+
+ public function insertBatch($data)
+ {
+ // Check class properties
+ if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL);
+
+ // DB-INSERT
+ $insert = $this->db->insert_batch($this->dbTable, $data);
+
+ if ($insert)
+ {
+ return success();
+ }
+ else
+ {
+ return error($this->db->error(), EXIT_DATABASE);
+ }
+ }
+
+ public function deleteWhere($where)
+ {
+ if (is_null($this->dbTable)) return error('The given database table name is not valid', EXIT_MODEL);
+
+ $delete = $this->db->delete($this->dbTable, $where);
+
+ if ($delete)
+ {
+ return success();
+ }
+ else
+ {
+ return error($this->db->error(), EXIT_DATABASE);
+ }
+ }
+
+ public function getLvsForPrestudent($prestudent_id, $studiensemester_kurzbz)
+ {
+ $this->addSelect($this->dbTable . '.*');
+ $this->addSelect('a.prestudent_id');
+ $this->addSelect('lv.bezeichnung as lv_bezeichnung');
+ $this->addSelect('stat.insertamum as freigabedatum');
+ $this->addSelect('n.bezeichnung as note_bezeichnung');
+ $this->addSelect('stg.bezeichnung as stg_bezeichnung');
+
+ $this->addJoin('campus.tbl_studierendenantrag a', 'studierendenantrag_id');
+ $this->addJoin('lehre.tbl_note n', 'note');
+ $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
+ $this->addJoin('public.tbl_prestudent ps', 'prestudent_id');
+ $this->addJoin('public.tbl_studiengang stg', 'ps.studiengang_kz = stg.studiengang_kz');
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag_status stat',
+ 'stat.studierendenantrag_status_id = campus.get_status_id_studierendenantrag(a.studierendenantrag_id)'
+ );
+ $this->addJoin('public.tbl_student s', 'prestudent_id');
+
+ // NOTE(chris): last offizell note
+ $this->addJoin('(
+ SELECT z.*
+ FROM lehre.tbl_zeugnisnote z
+ LEFT JOIN public.tbl_studiensemester zs
+ USING(studiensemester_kurzbz)
+ JOIN (
+ SELECT zi.lehrveranstaltung_id, zi.student_uid, MAX(zis.start) AS start
+ FROM lehre.tbl_zeugnisnote zi
+ LEFT JOIN lehre.tbl_note zin
+ USING(note)
+ LEFT JOIN public.tbl_studiensemester zis
+ USING(studiensemester_kurzbz)
+ WHERE zin.aktiv AND zin.offiziell
+ GROUP BY zi.lehrveranstaltung_id, zi.student_uid
+ ) zx
+ ON (
+ z.lehrveranstaltung_id=zx.lehrveranstaltung_id
+ AND z.student_uid=zx.student_uid
+ AND zs.start = zx.start
+ )) z', 'z.lehrveranstaltung_id=lv.lehrveranstaltung_id AND z.student_uid=s.student_uid', 'LEFT');
+ $this->addJoin('lehre.tbl_note zn', 'z.note = zn.note', 'LEFT');
+
+ $this->load->config('studierendenantrag');
+ $note_intern_angerechntet = $this->config->item('wiederholung_note_angerechnet');
+
+ return $this->loadWhere([
+ 'ps.prestudent_id' => $prestudent_id,
+ 'a.typ' => Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ 'stat.studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_APPROVED,
+ 'n.note <> ' => 0,
+ $this->dbTable . '.studiensemester_kurzbz' => $studiensemester_kurzbz,
+ '(n.note<>' . $this->db->escape($note_intern_angerechntet) . ' OR (z.note IS NOT NULL AND zn.positiv))' => null
+ ]);
+ }
+}
diff --git a/application/models/education/Studierendenantragstatus_model.php b/application/models/education/Studierendenantragstatus_model.php
new file mode 100644
index 000000000..cf9cce1be
--- /dev/null
+++ b/application/models/education/Studierendenantragstatus_model.php
@@ -0,0 +1,209 @@
+dbTable = 'campus.tbl_studierendenantrag_status';
+ $this->pk = 'studierendenantrag_status_id';
+ }
+
+ public function loadWithTyp($studierendenantrag_status_id)
+ {
+ $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage());
+
+ $this->addSelect($this->dbTable . '.*');
+ $this->addSelect('bezeichnung[(' . $lang . ')] AS typ');
+
+ $this->addJoin('campus.tbl_studierendenantrag_statustyp', 'studierendenantrag_statustyp_kurzbz');
+
+ return $this->load($studierendenantrag_status_id);
+ }
+
+ public function loadWithTypWhere($where)
+ {
+ $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage());
+
+ $this->addSelect($this->dbTable . '.*');
+ $this->addSelect('bezeichnung[(' . $lang . ')] AS typ');
+
+ $this->addJoin('campus.tbl_studierendenantrag_statustyp', 'studierendenantrag_statustyp_kurzbz');
+
+ return $this->loadWhere($where);
+ }
+
+ public function stopAntraegeForAbmeldungStgl($antrag_id)
+ {
+ $sql = 'INSERT INTO campus.tbl_studierendenantrag_status
+ (studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum)
+ SELECT studierendenantrag_id, ?, ?, (
+ SELECT insertamum
+ FROM campus.tbl_studierendenantrag_status
+ WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?)
+ )
+ FROM campus.tbl_studierendenantrag
+ WHERE prestudent_id = (
+ SELECT prestudent_id
+ FROM campus.tbl_studierendenantrag
+ WHERE studierendenantrag_id = ?
+ )
+ AND studierendenantrag_id <> ?
+ AND (
+ (
+ typ = ?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ?
+ ) OR (
+ typ = ?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ?
+ ) OR (
+ typ = ?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) IN ?
+ )
+ )';
+
+ return $this->execQuery($sql, [
+ self::STATUS_PAUSE,
+ self::INSERTVON_ABMELDUNGSTGL,
+ $antrag_id,
+ $antrag_id,
+ $antrag_id,
+ Studierendenantrag_model::TYP_ABMELDUNG,
+ [
+ Studierendenantragstatus_model::STATUS_CREATED
+ ],
+ Studierendenantrag_model::TYP_UNTERBRECHUNG,
+ [
+ Studierendenantragstatus_model::STATUS_CREATED
+ ],
+ Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ [
+ Studierendenantragstatus_model::STATUS_REQUESTSENT_1,
+ Studierendenantragstatus_model::STATUS_REQUESTSENT_2,
+ Studierendenantragstatus_model::STATUS_CREATED,
+ Studierendenantragstatus_model::STATUS_LVSASSIGNED,
+ Studierendenantragstatus_model::STATUS_PAUSE
+ ],
+ ]);
+ }
+
+ public function resumeAntraegeForAbmeldungStgl($antrag_id)
+ {
+ $sql = 'INSERT INTO campus.tbl_studierendenantrag_status
+ (studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum)
+ SELECT studierendenantrag_id, (
+ SELECT studierendenantrag_statustyp_kurzbz
+ FROM campus.tbl_studierendenantrag_status s
+ WHERE s.studierendenantrag_id=a.studierendenantrag_id
+ AND campus.get_status_id_studierendenantrag(a.studierendenantrag_id) <> studierendenantrag_status_id
+ ORDER BY insertamum DESC
+ LIMIT 1
+ ), ?, (
+ SELECT insertamum
+ FROM campus.tbl_studierendenantrag_status
+ WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?)
+ )
+ FROM campus.tbl_studierendenantrag a
+ WHERE prestudent_id = (
+ SELECT prestudent_id
+ FROM campus.tbl_studierendenantrag
+ WHERE studierendenantrag_id = ?
+ )
+ AND typ <> ?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) = ?
+ ';
+
+ return $this->execQuery($sql, [
+ self::INSERTVON_ABMELDUNGSTGL,
+ $antrag_id,
+ $antrag_id,
+ Studierendenantrag_model::TYP_ABMELDUNG_STGL,
+ Studierendenantragstatus_model::STATUS_PAUSE
+ ]);
+ }
+
+ public function stopAntraegeForAbbruchBy($antrag_id)
+ {
+ $sql = 'INSERT INTO campus.tbl_studierendenantrag_status
+ (studierendenantrag_id, studierendenantrag_statustyp_kurzbz, insertvon, insertamum)
+ SELECT studierendenantrag_id, ?, ?, (
+ SELECT insertamum
+ FROM campus.tbl_studierendenantrag_status
+ WHERE studierendenantrag_status_id = campus.get_status_id_studierendenantrag(?)
+ )
+ FROM campus.tbl_studierendenantrag
+ WHERE prestudent_id = (
+ SELECT prestudent_id
+ FROM campus.tbl_studierendenantrag
+ WHERE studierendenantrag_id = ?
+ )
+ AND studierendenantrag_id <> ?
+ AND (
+ (
+ typ = ?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
+ ) OR (
+ typ = ?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
+ ) OR (
+ typ = ?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
+ ) OR (
+ typ = ?
+ AND campus.get_status_studierendenantrag(studierendenantrag_id) NOT IN ?
+ )
+ )';
+
+ return $this->execQuery($sql, [
+ self::STATUS_PAUSE,
+ self::INSERTVON_DEREGISTERED,
+ $antrag_id,
+ $antrag_id,
+ $antrag_id,
+ Studierendenantrag_model::TYP_ABMELDUNG,
+ [
+ Studierendenantragstatus_model::STATUS_APPROVED,
+ Studierendenantragstatus_model::STATUS_CANCELLED
+ ],
+ Studierendenantrag_model::TYP_UNTERBRECHUNG,
+ [
+ Studierendenantragstatus_model::STATUS_APPROVED,
+ Studierendenantragstatus_model::STATUS_CANCELLED,
+ Studierendenantragstatus_model::STATUS_REMINDERSENT,
+ Studierendenantragstatus_model::STATUS_REJECTED
+ ],
+ Studierendenantrag_model::TYP_ABMELDUNG_STGL,
+ [
+ Studierendenantragstatus_model::STATUS_CANCELLED,
+ Studierendenantragstatus_model::STATUS_DEREGISTERED,
+ Studierendenantragstatus_model::STATUS_OBJECTION_DENIED
+ ],
+ Studierendenantrag_model::TYP_WIEDERHOLUNG,
+ [
+ Studierendenantragstatus_model::STATUS_DEREGISTERED,
+ Studierendenantragstatus_model::STATUS_APPROVED
+ ],
+ ]);
+ }
+}
diff --git a/application/models/education/Zeugnisnote_model.php b/application/models/education/Zeugnisnote_model.php
index a4185a7f4..b4d909e37 100644
--- a/application/models/education/Zeugnisnote_model.php
+++ b/application/models/education/Zeugnisnote_model.php
@@ -102,7 +102,7 @@ class Zeugnisnote_model extends DB_Model
JOIN lehre.tbl_zeugnisnote zgnisnote USING (student_uid)
JOIN lehre.tbl_note note ON zgnisnote.note = note.note
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
- JOIN public.tbl_studiengang stg ON prst.studiengang_kz = stg.studiengang_kz
+ JOIN public.tbl_studiengang stg ON prst.studiengang_kz = stg.studiengang_kz
WHERE pers.person_id = ?
AND zgnisnote.studiensemester_kurzbz = ?";
@@ -140,4 +140,83 @@ class Zeugnisnote_model extends DB_Model
return $this->execQuery($qry, $params);
}
+
+ /**
+ * Gets courses (Zeugnisnoten) for a student.
+ * @param string $student_uid,
+ * @param string $studiensemester_kurzbz
+ *
+ * @return object
+ */
+ public function getZeugnisnoten($student_uid, $studiensemester_kurzbz)
+ {
+ $params = array();
+ $where='';
+
+ if ($student_uid != null)
+ {
+ $where .= " AND uid=?";
+ $params[] = $student_uid;
+ }
+ if ($studiensemester_kurzbz !=null)
+ {
+ $where.=" AND vw_student_lehrveranstaltung.studiensemester_kurzbz= ?";
+ $params[] = $studiensemester_kurzbz;
+ }
+
+ $where2='';
+
+ if ($student_uid != null)
+ {
+ $where2 .= " AND student_uid=?";
+ $params[] = $student_uid;
+ }
+ if ($studiensemester_kurzbz !=null)
+ {
+ $where2 .= " AND studiensemester_kurzbz= ?";
+ $params[] = $studiensemester_kurzbz;
+ }
+
+ $qry = "SELECT vw_student_lehrveranstaltung.lehrveranstaltung_id, uid,
+ vw_student_lehrveranstaltung.studiensemester_kurzbz, note, punkte, uebernahmedatum, benotungsdatum,
+ vw_student_lehrveranstaltung.ects, vw_student_lehrveranstaltung.semesterstunden,
+ tbl_zeugnisnote.updateamum, tbl_zeugnisnote.updatevon, tbl_zeugnisnote.insertamum,
+ tbl_zeugnisnote.insertvon, tbl_zeugnisnote.ext_id,
+ vw_student_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung,
+ vw_student_lehrveranstaltung.bezeichnung_english as lehrveranstaltung_bezeichnung_english,
+ tbl_note.bezeichnung as note_bezeichnung,
+ tbl_note.positiv as note_positiv,
+ tbl_zeugnisnote.bemerkung as bemerkung,
+ vw_student_lehrveranstaltung.sort,
+ vw_student_lehrveranstaltung.zeugnis,
+ vw_student_lehrveranstaltung.studiengang_kz,
+ vw_student_lehrveranstaltung.lv_lehrform_kurzbz,
+ tbl_lehrveranstaltung.sws
+ FROM
+ (
+ campus.vw_student_lehrveranstaltung LEFT JOIN lehre.tbl_zeugnisnote
+ ON(uid=student_uid
+ AND vw_student_lehrveranstaltung.studiensemester_kurzbz=tbl_zeugnisnote.studiensemester_kurzbz
+ AND vw_student_lehrveranstaltung.lehrveranstaltung_id=tbl_zeugnisnote.lehrveranstaltung_id
+ )
+ ) LEFT JOIN lehre.tbl_note USING(note)
+ JOIN lehre.tbl_lehrveranstaltung ON(vw_student_lehrveranstaltung.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id)
+ WHERE true $where
+
+ UNION
+ SELECT lehre.tbl_lehrveranstaltung.lehrveranstaltung_id,student_uid AS uid,studiensemester_kurzbz, note, punkte,
+ uebernahmedatum, benotungsdatum,lehre.tbl_lehrveranstaltung.ects,lehre.tbl_lehrveranstaltung.semesterstunden, tbl_zeugnisnote.updateamum, tbl_zeugnisnote.updatevon, tbl_zeugnisnote.insertamum,
+ tbl_zeugnisnote.insertvon, tbl_zeugnisnote.ext_id, lehre.tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung, lehre.tbl_lehrveranstaltung.bezeichnung_english as lehrveranstaltung_bezeichnung_english,
+ tbl_note.bezeichnung as note_bezeichnung, tbl_note.positiv as note_positiv, tbl_zeugnisnote.bemerkung as bemerkung, tbl_lehrveranstaltung.sort, tbl_lehrveranstaltung.zeugnis, tbl_lehrveranstaltung.studiengang_kz,
+ tbl_lehrveranstaltung.lehrform_kurzbz as lv_lehrform_kurzbz, tbl_lehrveranstaltung.sws
+ FROM
+ lehre.tbl_zeugnisnote
+ JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id)
+ JOIN lehre.tbl_note USING(note)
+ WHERE true $where2
+
+ ORDER BY sort";
+
+ return $this->execQuery($qry, $params);
+ }
}
diff --git a/application/models/organisation/Geschaeftsjahr_model.php b/application/models/organisation/Geschaeftsjahr_model.php
index 4f0d03b73..fdd774a8c 100644
--- a/application/models/organisation/Geschaeftsjahr_model.php
+++ b/application/models/organisation/Geschaeftsjahr_model.php
@@ -32,11 +32,20 @@ class Geschaeftsjahr_model extends DB_Model
* Gets next Geschaeftsjahr, as determined by its start date
* @return array|null
*/
- public function getNextGeschaeftsjahr()
+ public function getNextGeschaeftsjahr($offsetDays=null)
{
$query = 'SELECT *
- FROM public.tbl_geschaeftsjahr
- WHERE start > now()
+ FROM public.tbl_geschaeftsjahr WHERE ';
+
+ if(!is_null($offsetDays))
+ {
+ $query .= "start > now() - '".$offsetDays." days'::interval";
+ }
+ else
+ {
+ $query .= 'start > now()';
+ }
+ $query .= '
ORDER BY start
LIMIT 1';
diff --git a/application/models/organisation/Lehrverband_model.php b/application/models/organisation/Lehrverband_model.php
index 953e4b7b2..0e760a116 100644
--- a/application/models/organisation/Lehrverband_model.php
+++ b/application/models/organisation/Lehrverband_model.php
@@ -11,4 +11,34 @@ class Lehrverband_model extends DB_Model
$this->dbTable = 'public.tbl_lehrverband';
$this->pk = array('gruppe', 'verband', 'semester', 'studiengang_kz');
}
+
+ /**
+ * Gets the maximum possible semester for one or more Studiengaenge.
+ * If there are more than one Studiengang each maximum is calculated and
+ * the smallest result is returned.
+ *
+ * @param array $studiengang_kzs
+ *
+ * @return stdClass
+ */
+ public function getMaxSemester($studiengang_kzs)
+ {
+ $sqls = [];
+ foreach ($studiengang_kzs as $studiengang_kz) {
+ $this->addSelect('MAX(semester) AS maxsem');
+ $this->db->where('studiengang_kz', $studiengang_kz);
+ $sqls[] = $this->db->get_compiled_select($this->dbTable);
+ }
+
+ $this->addSelect('MIN(a.maxsem) AS maxsem');
+
+ $dbTable = $this->dbTable;
+ $this->dbTable = '(' . implode(' UNION ', $sqls) . ') AS a';
+
+ $result = $this->load();
+
+ $this->dbTable = $dbTable;
+
+ return $result;
+ }
}
diff --git a/application/models/organisation/Organisationseinheit_model.php b/application/models/organisation/Organisationseinheit_model.php
index bec4aee47..4a64ee055 100644
--- a/application/models/organisation/Organisationseinheit_model.php
+++ b/application/models/organisation/Organisationseinheit_model.php
@@ -188,4 +188,20 @@ class Organisationseinheit_model extends DB_Model
}
return $this->loadWhere($condition);
}
+
+ /**
+ * Get OEs by eventQuery string. Use with autocomplete event queries.
+ * @param $eventQuery String
+ * @return array
+ */
+ public function getAutocompleteSuggestions($eventQuery)
+ {
+ $this->addSelect('oe_kurzbz');
+ $this->addSelect('organisationseinheittyp_kurzbz, oe_kurzbz, bezeichnung, aktiv, lehre');
+ $this->addOrder('organisationseinheittyp_kurzbz, bezeichnung');
+
+ return $this->loadWhere("
+ oe_kurzbz ILIKE '%". $this->escapeLike($eventQuery). "%'
+ ");
+ }
}
diff --git a/application/models/organisation/Standort_model.php b/application/models/organisation/Standort_model.php
index 382236e2f..aeeab4497 100644
--- a/application/models/organisation/Standort_model.php
+++ b/application/models/organisation/Standort_model.php
@@ -11,4 +11,29 @@ class Standort_model extends DB_Model
$this->dbTable = 'public.tbl_standort';
$this->pk = 'standort_id';
}
+
+ public function searchStandorte($filter)
+ {
+ $filter = strtoLower($filter);
+ $qry = "
+ SELECT
+ s.kurzbz, s.standort_id
+ FROM
+ public.tbl_standort s
+ WHERE
+ lower (s.kurzbz) LIKE '%". $this->db->escape_like_str($filter)."%'
+ OR
+ lower (s.bezeichnung) LIKE '%". $this->db->escape_like_str($filter)."%'";
+
+
+ return $this->execQuery($qry);
+ }
+
+ public function getStandorteByFirma($firma_id)
+ {
+ $this->addSelect("DISTINCT ON (standort_id) bezeichnung, standort_id");
+
+ return $this->loadWhere(array("firma_id" => $firma_id));
+ }
}
+
diff --git a/application/models/organisation/Studiengang_model.php b/application/models/organisation/Studiengang_model.php
index f4f8b3c9e..4bbb63805 100644
--- a/application/models/organisation/Studiengang_model.php
+++ b/application/models/organisation/Studiengang_model.php
@@ -511,10 +511,10 @@ class Studiengang_model extends DB_Model
public function getStudiengangTyp($studiengang_kz, $typ = null)
{
$query = "SELECT DISTINCT(sgt.*)
- FROM tbl_studiengangstyp sgt JOIN tbl_studiengang sg on sgt.typ = sg.typ
+ FROM tbl_studiengangstyp sgt JOIN tbl_studiengang sg on sgt.typ = sg.typ
WHERE studiengang_kz IN ?";
- $params[] = $studiengang_kz;
+ $params = [$studiengang_kz];
if (!is_null($typ))
{
@@ -524,4 +524,80 @@ class Studiengang_model extends DB_Model
return $this->execQuery($query, $params);
}
+
+ /**
+ * @param array $studiengang_kzs
+ * @param array $not_antrag_typ (optional) If the prestudent has an antrag with one of the specified types it will be excluded from the result
+ * @param array $prestudent_stati (optional)
+ *
+ * @return stdClass
+ */
+ public function getAktivePrestudenten($studiengang_kzs, $not_antrag_typ = null, $query = null)
+ {
+ $this->load->config('studierendenantrag');
+
+ $sql = "SELECT index FROM public.tbl_sprache WHERE sprache='" . getUserLanguage() . "' LIMIT 1";
+
+ $this->addSelect($this->dbTable . '.studiengang_kz');
+ $this->addSelect($this->dbTable . '.bezeichnung');
+ $this->addSelect('o.orgform_kurzbz');
+ $this->addSelect('o.bezeichnung_mehrsprachig[(' . $sql . ')] AS orgform', false);
+ $this->addSelect('ps.ausbildungssemester AS semester');
+ $this->addSelect('ps.studiensemester_kurzbz');
+ $this->addSelect('p.prestudent_id');
+ $this->addSelect('pers.vorname');
+ $this->addSelect('pers.nachname');
+ $this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', " . $this->dbTable . ".bezeichnung, ')') AS name");
+
+ $this->addJoin('public.tbl_prestudent p', 'studiengang_kz');
+ $this->addJoin(
+ 'public.tbl_prestudentstatus ps',
+ 'ps.prestudent_id=p.prestudent_id
+ AND ps.studiensemester_kurzbz=get_stdsem_prestudent(p.prestudent_id, NULL)
+ AND ps.ausbildungssemester=get_absem_prestudent(p.prestudent_id, NULL)
+ AND ps.status_kurzbz=get_rolle_prestudent(p.prestudent_id, NULL)'
+ );
+ $this->addJoin('lehre.tbl_studienplan plan', 'studienplan_id');
+ $this->addJoin('bis.tbl_orgform o', 'COALESCE(plan.orgform_kurzbz, ps.orgform_kurzbz, ' . $this->dbTable . '.orgform_kurzbz)=o.orgform_kurzbz');
+ $this->addJoin('public.tbl_person pers', 'person_id');
+ $this->addJoin('public.tbl_student stud', 'p.prestudent_id=stud.prestudent_id', 'LEFT');
+
+ $this->db->where_in($this->dbTable . '.studiengang_kz', $studiengang_kzs);
+ $this->db->where_in('ps.status_kurzbz', $this->config->item('antrag_prestudentstatus_whitelist_abmeldung'));
+ $this->db->where($this->dbTable . ".aktiv", true);
+
+ if ($not_antrag_typ !== null && is_array($not_antrag_typ)) {
+ foreach($not_antrag_typ as $k => $v)
+ $not_antrag_typ[$k] = $this->db->escape($v);
+ $this->addJoin(
+ 'campus.tbl_studierendenantrag a',
+ 'a.prestudent_id=p.prestudent_id and a.typ in ('.
+ implode(',', $not_antrag_typ).
+ ") AND campus.get_status_studierendenantrag (a.studierendenantrag_id)<>'" .
+ Studierendenantragstatus_model::STATUS_CANCELLED . "'",
+ 'LEFT'
+ );
+ $this->db->where('a.typ IS NULL');
+ }
+
+ if ($query) {
+ $query = explode(' ', $query);
+ $this->db->group_start();
+ foreach ($query as $q) {
+ $this->db->group_start();
+ $this->db->where('pers.vorname ILIKE', "%" . $q . "%");
+ $this->db->or_where('pers.nachname ILIKE', "%" . $q . "%");
+ $this->db->or_where('stud.student_uid ILIKE', "%" . $q . "%");
+ $this->db->or_where($this->dbTable . '.bezeichnung ILIKE', "%" . $q . "%");
+ if (is_numeric($q))
+ $this->db->or_where('p.prestudent_id', $q);
+ $this->db->group_end();
+ }
+ $this->db->group_end();
+ }
+
+ $this->addOrder('name');
+
+ return $this->load();
+ }
}
diff --git a/application/models/organisation/Studienjahr_model.php b/application/models/organisation/Studienjahr_model.php
index 3bbe3a07f..a6e1bc575 100644
--- a/application/models/organisation/Studienjahr_model.php
+++ b/application/models/organisation/Studienjahr_model.php
@@ -29,4 +29,54 @@ class Studienjahr_model extends DB_Model
return $this->execQuery($query);
}
+
+ /**
+ * Get the current Studienjahr. During the summer term, continue using the previous Studienjahr.
+ *
+ * @param int $days
+ * @return array|stdClass|null
+ */
+ public function getLastOrAktStudienjahr($days = 60)
+ {
+ if (!is_numeric($days))
+ {
+ $days = 60;
+ }
+
+ $query = '
+ SELECT *
+ FROM public.tbl_studienjahr
+ JOIN public.tbl_studiensemester USING (studienjahr_kurzbz)
+ WHERE start < NOW() - \'' . $days . ' DAYS\'::INTERVAL
+ ORDER by start DESC
+ LIMIT 1
+ ';
+
+ return $this->execQuery($query);
+ }
+
+ /**
+ * Get the current Studienjahr. During the summer term, get the upcoming next Studienjahr.
+ *
+ * @param int $days
+ * @return array|stdClass|null
+ */
+ public function getAktOrNextStudienjahr($days = 62)
+ {
+ if (!is_numeric($days))
+ {
+ $days = 62;
+ }
+
+ $query = '
+ SELECT *
+ FROM public.tbl_studienjahr
+ JOIN public.tbl_studiensemester using(studienjahr_kurzbz)
+ WHERE start < NOW() + \'' . $days . ' DAYS\'::INTERVAL
+ ORDER by start DESC
+ LIMIT 1
+ ';
+
+ return $this->execQuery($query);
+ }
}
diff --git a/application/models/organisation/Studienplan_model.php b/application/models/organisation/Studienplan_model.php
index 0cc23b85d..e35ba52fb 100644
--- a/application/models/organisation/Studienplan_model.php
+++ b/application/models/organisation/Studienplan_model.php
@@ -45,7 +45,7 @@ class Studienplan_model extends DB_Model
$whereArray["tbl_studienplan.sprache"] = $sprache;
}
- return $this->StudienplanModel->loadWhere($whereArray);
+ return $this->loadWhere($whereArray);
}
public function getStudienplanLehrveranstaltung($studienplan_id, $semester)
@@ -53,9 +53,85 @@ class Studienplan_model extends DB_Model
$this->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'studienplan_id');
$this->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id');
$this->addOrder('tbl_lehrveranstaltung.sort');
+
return $this->loadWhere(array(
'studienplan_id' => $studienplan_id,
'tbl_studienplan_lehrveranstaltung.semester' => $semester
));
}
+
+ public function getStudienplanLehrveranstaltungForPrestudent($studienplan_id, $semester, $prestudent_id)
+ {
+ $lang = 'SELECT index FROM public.tbl_sprache WHERE sprache=' . $this->escape(getUserLanguage());
+ $sql = 'SELECT student_uid FROM public.tbl_student WHERE prestudent_id=' . $this->escape($prestudent_id);
+
+ $this->addSelect($this->dbTable . '.*');
+ $this->addSelect('lv.*');
+ $this->addSelect('COALESCE(n.bezeichnung_mehrsprachig[(' . $lang . ')], NULL) AS note');
+ $this->addSelect('n.positiv');
+ $this->addSelect('lehre.tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id');
+ $this->addSelect('lehre.tbl_studienplan_lehrveranstaltung.sort plan_sort');
+ $this->addSelect('lehre.tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent');
+
+ $this->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'studienplan_id');
+ $this->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
+ // NOTE(chris): last offizell note
+ $this->addJoin('(
+ SELECT z.*
+ FROM lehre.tbl_zeugnisnote z
+ LEFT JOIN public.tbl_studiensemester zs
+ USING(studiensemester_kurzbz)
+ JOIN (
+ SELECT zi.lehrveranstaltung_id, zi.student_uid, MAX(zis.start) AS start
+ FROM lehre.tbl_zeugnisnote zi
+ LEFT JOIN lehre.tbl_note zin
+ USING(note)
+ LEFT JOIN public.tbl_studiensemester zis
+ USING(studiensemester_kurzbz)
+ WHERE zin.aktiv AND zin.offiziell
+ GROUP BY zi.lehrveranstaltung_id, zi.student_uid
+ ) zx
+ ON (
+ z.lehrveranstaltung_id=zx.lehrveranstaltung_id
+ AND z.student_uid=zx.student_uid
+ AND zs.start = zx.start
+ )) zn', 'zn.lehrveranstaltung_id=lv.lehrveranstaltung_id AND zn.student_uid=( ' . $sql . ')', 'LEFT');
+ $this->addJoin('lehre.tbl_note n', 'n.note=zn.note', 'LEFT');
+
+ $this->addOrder('lehre.tbl_studienplan_lehrveranstaltung.sort');
+ $this->addOrder('lv.sort');
+
+ return $this->loadWhere(array(
+ 'studienplan_id' => $studienplan_id,
+ 'tbl_studienplan_lehrveranstaltung.semester' => $semester
+ ));
+ }
+
+ public function getAllOesForLv($lehrveranstaltung_id)
+ {
+ $this->addDistinct('oe_kurzbz');
+
+ $this->addJoin('lehre.tbl_studienplan_lehrveranstaltung lv', 'studienplan_id');
+ $this->addJoin('lehre.tbl_studienordnung', 'studienordnung_id');
+ $this->addJoin('public.tbl_studiengang', 'studiengang_kz');
+
+ return $this->loadWhere([
+ 'lv.lehrveranstaltung_id' => $lehrveranstaltung_id
+ ]);
+ }
+
+ public function getStudienplaeneByPrestudents($prestudent_id)
+ {
+ $this->addDistinct();
+ $this->addSelect($this->dbTable . '.*');
+ $this->addSelect('sem.start AS start_stsem');
+ $this->addJoin('lehre.tbl_studienordnung o', 'studienordnung_id');
+ $this->addJoin('public.tbl_prestudent p', 'studiengang_kz');
+ $this->addJoin('public.tbl_studiensemester sem', 'sem.studiensemester_kurzbz = o.gueltigvon', 'LEFT');
+ $this->addOrder('sem.start');
+
+ return $this->loadWhere([
+ 'prestudent_id' => $prestudent_id
+ ]);
+ }
}
diff --git a/application/models/organisation/Studiensemester_model.php b/application/models/organisation/Studiensemester_model.php
index 45a4eac7c..c59c9d343 100644
--- a/application/models/organisation/Studiensemester_model.php
+++ b/application/models/organisation/Studiensemester_model.php
@@ -13,35 +13,35 @@ class Studiensemester_model extends DB_Model
$this->hasSequence = false;
}
- /**
- * Get actual Studiensemester.
- *
- * @return array
- */
- public function getAkt()
- {
- return $this->loadWhere(array(
- 'start <= ' => 'NOW()',
- 'ende >= ' => 'NOW()'
- )
- );
- }
+ /**
+ * Get actual Studiensemester.
+ *
+ * @return array
+ */
+ public function getAkt()
+ {
+ return $this->loadWhere(array(
+ 'start <= ' => 'NOW()',
+ 'ende >= ' => 'NOW()'
+ )
+ );
+ }
// Get next study semester
public function getNext()
- {
- $query = '
- SELECT *
- FROM
- public.tbl_studiensemester
- WHERE
- start > now()
- ORDER BY start
- LIMIT 1;
- ';
+ {
+ $query = '
+ SELECT *
+ FROM
+ public.tbl_studiensemester
+ WHERE
+ start > now()
+ ORDER BY start
+ LIMIT 1;
+ ';
- return $this->execQuery($query);
- }
+ return $this->execQuery($query);
+ }
/**
* getLastOrAktSemester
@@ -182,10 +182,10 @@ class Studiensemester_model extends DB_Model
return success(array());
$query = "
- SELECT *
- FROM public.tbl_studiensemester
- WHERE ( ?::date < ende AND ?::date > start )
- ORDER BY start DESC";
+ SELECT *
+ FROM public.tbl_studiensemester
+ WHERE ( ?::date < ende AND ?::date > start )
+ ORDER BY start DESC";
return $this->execQuery($query, array($from, $to));
}
@@ -200,7 +200,7 @@ class Studiensemester_model extends DB_Model
{
$query = "SELECT studiensemester_kurzbz, start, ende FROM public.vw_studiensemester
WHERE studiensemester_kurzbz <> ?
- ORDER BY delta, start LIMIT 1";
+ ORDER BY delta, start LIMIT 1";
return $this->execQuery($query, array($studiensemester_kurzbz));
}
@@ -211,7 +211,46 @@ class Studiensemester_model extends DB_Model
FROM public.tbl_studiensemester
WHERE start >= NOW() OR (start <= NOW() AND ende >= NOW())
ORDER BY start';
-
+
return $this->execQuery($query);
}
+
+ /**
+ * Liefert ausgehend von heutigen Datum $plus studiensemester in die Zukunft und $minus Studiensemester in die Vergangenheit
+ *
+ * @param integer $plus Optional. Wieviele Studiensemester in die Zukunft sollen ausgegeben werden. Wenn NULL werden alle zukuenftigen geliefert.
+ * @param integer $minus Optional. Wieviele Studiensemester in die Vergangenheit sollen ausgegeben werden. Wenn NULL werden alle vergangenen geliefert.
+ *
+ * @return stdClass
+ */
+ public function addPlusMinus($plus = null, $minus = null)
+ {
+ $this->addSelect($this->pk);
+ $this->addOrder('ende');
+ if ($plus)
+ $this->addLimit($plus);
+ $this->db->where('start >= NOW()', null, false);
+ $plus = $this->db->get_compiled_select($this->dbTable);
+
+ $this->addSelect($this->pk);
+ $this->addOrder('start', 'DESC');
+ if ($minus)
+ $this->addLimit($minus);
+ $this->db->where('start <= NOW()', null, false);
+ $minus = $this->db->get_compiled_select($this->dbTable);
+
+ $this->db->where_in($this->pk, '(' . $plus . ') UNION (' . $minus . ')', false);
+ }
+
+ /**
+ * Holt letzen zwei Ziffern des Studienjahres von Studiensemester, z.B. 24 für WS2024 und SS2025
+ * @param studiensemester_kurzbz
+ * @return string Studienjahr Nummer
+ */
+ public function getStudienjahrNumberFromStudiensemester($studiensemester_kurzbz)
+ {
+ $studienjahrNumber = mb_substr($studiensemester_kurzbz, 4, 2);
+ if (is_numeric($studienjahrNumber) && mb_substr($studiensemester_kurzbz, 0, 2) == 'SS') (int)$studienjahrNumber -= 1;
+ return $studienjahrNumber;
+ }
}
diff --git a/application/models/person/Adresse_model.php b/application/models/person/Adresse_model.php
index fb5112a8d..4dd03ea6b 100644
--- a/application/models/person/Adresse_model.php
+++ b/application/models/person/Adresse_model.php
@@ -24,4 +24,4 @@ class Adresse_model extends DB_Model
$this->addSelect($select);
return $this->loadWhere(array('person_id' => $person_id, 'zustelladresse'=> true));
}
-}
+}
\ No newline at end of file
diff --git a/application/models/person/Benutzer_model.php b/application/models/person/Benutzer_model.php
index eff1329a6..65121dbb5 100644
--- a/application/models/person/Benutzer_model.php
+++ b/application/models/person/Benutzer_model.php
@@ -1,4 +1,7 @@
addLimit(1);
$this->addSelect('vorname, nachname');
$this->addJoin('public.tbl_person', 'person_id');
$nameresult = $this->loadWhere(array('uid' => $uid));
- if (hasData($nameresult))
- {
- $aliasdata = getData($nameresult);
- $alias = $this->_sanitizeAliasName($aliasdata[0]->vorname).'.'.$this->_sanitizeAliasName($aliasdata[0]->nachname);
- $aliasexists = $this->aliasExists($alias);
+ if (isError($nameresult))
+ return $nameresult;
- if (hasData($aliasexists) && !getData($aliasexists)[0])
- $aliasres = $alias;
- }
- return success($aliasres);
+ if (!hasData($nameresult))
+ return success('');
+
+ $aliasdata = current(getData($nameresult));
+
+ return $this->generateAliasFromName($aliasdata->vorname, $aliasdata->nachname);
+ }
+
+ /**
+ * Generates alias for a vor- and nachname.
+ *
+ * @param string $vorname
+ * @param string $nachname
+ *
+ * @return stdClass
+ */
+ public function generateAliasFromName($vorname, $nachname)
+ {
+ $alias = $this->_sanitizeAliasName($vorname . '.' . $nachname);
+
+ $result = $this->aliasExists($alias);
+
+ if (isError($result))
+ return $result;
+
+ if (current(getData($result)))
+ return success('');
+
+ return success($alias);
+ }
+
+ /**
+ * Generates a matrikelnummer
+ *
+ * @param string $oe_kurzbz
+ *
+ * @return stdClass
+ */
+ public function generateMatrikelnummer($oe_kurzbz)
+ {
+ $matrikelnummer = false;
+
+ Events::trigger(
+ 'generate_matrikelnummer',
+ function ($value) use ($matrikelnummer) {
+ $matrikelnummer = $value;
+ },
+ $oe_kurzbz
+ );
+
+ if ($matrikelnummer !== false)
+ return success($matrikelnummer);
+
+ return success(null);
+ }
+
+ /**
+ * Generates an activation key
+ *
+ * @return string
+ */
+ public function generateActivationkey()
+ {
+ $this->load->library('CryptLib');
+
+ $key = '';
+ for ($i=0; $i<32; $i++)
+ $key .= ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'][mt_rand(0, 15)];
+
+ $value = uniqid(mt_rand(), true);
+ $length = strlen($value);
+ $value = str_pad($value, $length + 32 - ($length % 32), chr(0));
+
+ return md5($this->cryptlib->RIJNDAEL_256_ECB($value, $key, true));
}
// --------------------------------------------------------------------------------------------
@@ -100,9 +169,10 @@ class Benutzer_model extends DB_Model
* @param string $str
* @return string
*/
+
private function _sanitizeAliasName($str)
{
$str = sanitizeProblemChars($str);
- return mb_strtolower(str_replace(' ','_', $str));
+ return mb_strtolower(str_replace(' ', '_', $str));
}
}
diff --git a/application/models/person/Benutzerfunktion_model.php b/application/models/person/Benutzerfunktion_model.php
index 27f9b6184..e44281a92 100644
--- a/application/models/person/Benutzerfunktion_model.php
+++ b/application/models/person/Benutzerfunktion_model.php
@@ -180,4 +180,60 @@ class Benutzerfunktion_model extends DB_Model
return $this->execQuery($query, $parameters_array);
}
+
+
+ public function insertBenutzerfunktion($Json)
+ {
+ unset($Json['benutzerfunktion_id']);
+ unset($Json['updateamum']);
+ $Json['insertvon'] = getAuthUID();
+ $Json['insertamum'] = $this->escape('NOW()');
+
+ if ($Json['datum_bis']=='')
+ {
+ unset($Json['datum_bis']);
+ }
+
+ $result = $this->insert($Json);
+
+ if (isError($result))
+ {
+ return error($result->msg, EXIT_ERROR);
+ }
+
+ $record = $this->load($result->retval);
+
+ return $record;
+ }
+
+ function updateBenutzerfunktion($funktionJson)
+ {
+ $funktionJson['updatevon'] = getAuthUID();
+ $funktionJson['updateamum'] = $this->escape('NOW()');
+
+ $result = $this->update($funktionJson['benutzerfunktion_id'], $funktionJson);
+
+ if (isError($result))
+ {
+ return error($result->msg, EXIT_ERROR);
+ }
+
+ $result = $this->load($funktionJson['benutzerfunktion_id']);
+
+ return $result;
+ }
+
+ function deleteBenutzerfunktion($funktionJson)
+ {
+ $result = $this->delete($funktionJson);
+
+ if (isError($result))
+ {
+ return error($result->msg, EXIT_ERROR);
+ }
+
+ return success($funktionJson);
+ }
+
+
}
diff --git a/application/models/person/Kennzeichen_model.php b/application/models/person/Kennzeichen_model.php
new file mode 100644
index 000000000..fe8a9ac62
--- /dev/null
+++ b/application/models/person/Kennzeichen_model.php
@@ -0,0 +1,15 @@
+dbTable = 'public.tbl_kennzeichen';
+ $this->pk = 'kennzeichen_id';
+ }
+
+}
diff --git a/application/models/person/Notiz_model.php b/application/models/person/Notiz_model.php
index bfd8aa258..349eaac60 100644
--- a/application/models/person/Notiz_model.php
+++ b/application/models/person/Notiz_model.php
@@ -139,12 +139,51 @@ class Notiz_model extends DB_Model
*/
public function getNotiz($person_id)
{
- // Join with the table public.tbl_notizzuordnung using notiz_id
+ $this->addSelect('public.tbl_notiz.*');
$this->addJoin('public.tbl_notizzuordnung', 'notiz_id');
return $this->loadWhere(array('person_id' => $person_id));
}
+ /**
+ * gets all Notizen with Documententries for a certain type and type_id
+ * @param String type of id eg. person_id, prestudent_id, mitarbeiter_uid, projekt_kurzbz, projektphase_id, projekttask_id,
+ * bestellung_id, lehreinheit_id, anrechnung_id, uid)
+ * @param $id the corresponding id, part of public.tbl_notizzuordnung
+ */
+ public function getNotizWithDocEntries($id, $type)
+ {
+ $qry = "
+ SELECT
+ n.*, count(dms_id) as countDoc, z.notizzuordnung_id,
+ TO_CHAR (CASE
+ WHEN n.updateamum >= n.insertamum THEN n.updateamum
+ ELSE n.insertamum
+ END::timestamp, 'DD.MM.YYYY HH24:MI:SS') AS lastUpdate,
+ regexp_replace(n.text, '<[^>]*>', '', 'g') as text_stripped,
+ TO_CHAR(n.start::timestamp, 'DD.MM.YYYY') AS start_format,
+ TO_CHAR(n.ende::timestamp, 'DD.MM.YYYY') AS ende_format,
+ z.notiz_id, z.person_id as id, ? as type_id
+
+ FROM
+ public.tbl_notiz n
+ JOIN
+ public.tbl_notizzuordnung z USING (notiz_id)
+ LEFT JOIN
+ public.tbl_notiz_dokument dok USING (notiz_id)
+ LEFT JOIN
+ campus.tbl_dms_version USING (dms_id)
+ WHERE
+ z.$type = ?
+ GROUP BY
+ notiz_id, z.notizzuordnung_id
+ ";
+
+ return $this->execQuery($qry, array($type, $id));
+
+ }
+
+
/**
* gets all Notizen for a person with a specific title
* @param $person_id
@@ -231,6 +270,4 @@ class Notiz_model extends DB_Model
return $this->loadWhere(array('anrechnung_id' => $anrechnung_id));
}
- // ------------------------------------------------------------------------------------------------------
-
}
diff --git a/application/models/person/Notizdokument_model.php b/application/models/person/Notizdokument_model.php
new file mode 100644
index 000000000..6b141307f
--- /dev/null
+++ b/application/models/person/Notizdokument_model.php
@@ -0,0 +1,14 @@
+dbTable = 'public.tbl_notiz_dokument';
+ $this->pk= array('notiz_id' , 'dms_id');
+ }
+}
\ No newline at end of file
diff --git a/application/models/person/Notizzuordnung_model.php b/application/models/person/Notizzuordnung_model.php
index 187a8399b..b94ff3fb6 100644
--- a/application/models/person/Notizzuordnung_model.php
+++ b/application/models/person/Notizzuordnung_model.php
@@ -11,4 +11,38 @@ class Notizzuordnung_model extends DB_Model
$this->dbTable = 'public.tbl_notizzuordnung';
$this->pk = 'notizzuordnung_id';
}
+
+ public function isValidType($type)
+ {
+ $validTypes = [];
+
+ $qry = "
+ SELECT column_name
+ FROM information_schema.columns
+ WHERE table_schema = 'public'
+ AND table_name = 'tbl_notizzuordnung'
+ AND column_name not in ('notizzuordnung_id', 'notiz_id')
+ ";
+
+ $type_arr = $this->execQuery($qry);
+ $type_arr = $type_arr->retval;
+
+ foreach ($type_arr as $t)
+ {
+ $validTypes[] = $t->column_name;
+ }
+
+ //TODO(manu) param id
+ if (in_array($type, $validTypes) )
+ //if (in_array($type, $validTypes) ||($type == 'software_id')) //Just for testing
+ {
+ return success("Type " . $type . " is valid");
+ // $result = success('Type of Id is valid');
+ }
+ else
+ {
+ return error("Type " . $type . " is NOT valid");
+ }
+ //return $result;
+ }
}
diff --git a/application/models/person/Person_model.php b/application/models/person/Person_model.php
index ed21082e2..dc925a171 100644
--- a/application/models/person/Person_model.php
+++ b/application/models/person/Person_model.php
@@ -1,5 +1,22 @@
.
+ */
+
class Person_model extends DB_Model
{
/**
@@ -8,6 +25,7 @@ class Person_model extends DB_Model
public function __construct()
{
parent::__construct();
+
$this->dbTable = 'public.tbl_person';
$this->pk = 'person_id';
@@ -70,7 +88,7 @@ class Person_model extends DB_Model
if (isset($person['svnr']) && $person['svnr'] != '')
{
$this->PersonModel->addOrder('svnr', 'DESC');
- $result = $this->PersonModel->loadWhere(array(
+ $result = $this->PersonModel->loadWhere(array(
'person_id != ' => $person['person_id'],
'SUBSTRING(svnr FROM 1 FOR 10) = ' => $person['svnr'])
);
@@ -138,7 +156,8 @@ class Person_model extends DB_Model
'lower(nachname) like '.$this->db->escape('%'.$filter.'%')."
OR lower(vorname) like ".$this->db->escape('%'.$filter.'%')."
OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.$filter.'%')."
- OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%'));
+ OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%')
+ );
return $result;
}
@@ -152,8 +171,12 @@ class Person_model extends DB_Model
*/
public function getPersonStammdaten($person_id, $zustellung_only = false)
{
- $this->addSelect('public.tbl_person.*, tbl_person.staatsbuergerschaft AS staatsbuergerschaft_code, tbl_person.geburtsnation AS geburtsnation_code,
- s.kurztext as staatsbuergerschaft, g.kurztext as geburtsnation');
+ $this->addSelect('public.tbl_person.*,
+ tbl_person.staatsbuergerschaft AS staatsbuergerschaft_code,
+ tbl_person.geburtsnation AS geburtsnation_code,
+ s.kurztext as staatsbuergerschaft,
+ g.kurztext as geburtsnation'
+ );
$this->addJoin('bis.tbl_nation s', 'public.tbl_person.staatsbuergerschaft = s.nation_code', 'LEFT');
$this->addJoin('bis.tbl_nation g', 'public.tbl_person.geburtsnation = g.nation_code', 'LEFT');
@@ -258,7 +281,8 @@ class Person_model extends DB_Model
*/
public function getFullName($uid)
{
- if (!$result = getData($this->getByUid($uid))[0])
+ $result = getData($this->getByUid($uid))[0];
+ if (!$result)
{
show_error('Failed loading person');
}
@@ -270,15 +294,15 @@ class Person_model extends DB_Model
{
$qry = "SELECT person_id
FROM public.tbl_prestudent p
- JOIN
+ JOIN
(
SELECT DISTINCT ON(prestudent_id) *
FROM public.tbl_prestudentstatus
- WHERE prestudent_id IN
+ WHERE prestudent_id IN
(
- SELECT prestudent_id
- FROM public.tbl_prestudent
- WHERE person_id IN
+ SELECT prestudent_id
+ FROM public.tbl_prestudent
+ WHERE person_id IN
(
SELECT p2.person_id
FROM public.tbl_person p
@@ -292,8 +316,8 @@ class Person_model extends DB_Model
ORDER BY prestudent_id, datum DESC, insertamum DESC
) ps USING(prestudent_id)
JOIN public.tbl_status USING(status_kurzbz)
- WHERE status_kurzbz = 'Interessent'
- AND studiengang_kz IN
+ WHERE status_kurzbz = 'Interessent'
+ AND studiengang_kz IN
(
SELECT studiengang_kz
FROM public.tbl_prestudent p
@@ -337,4 +361,51 @@ class Person_model extends DB_Model
return $this->execQuery($qry, array($person_id, $person_id, $person_id));
}
-}
+
+ public function loadPrestudent($prestudent_id)
+ {
+ $this->addSelect($this->dbTable . '.*');
+
+ $this->addJoin('public.tbl_prestudent p', 'person_id');
+
+ $this->addLimit(1);
+
+ return $this->loadWhere([
+ 'prestudent_id' => $prestudent_id
+ ]);
+ }
+
+ public function checkUnruly($vorname, $nachname, $gebdatum)
+ {
+ $qry = "SELECT person_id, vorname, nachname, gebdatum, unruly
+ FROM tbl_person
+ WHERE tbl_person.vorname = ?
+ AND tbl_person.nachname = ?
+ AND tbl_person.gebdatum = ?
+ AND tbl_person.unruly = TRUE;";
+
+ return $this->execQuery($qry, [$vorname, $nachname, $gebdatum]);
+ }
+
+ public function checkUnrulyWhere($where, $paramsArray)
+ {
+ $qry = 'SELECT *
+ FROM tbl_person p
+ WHERE '.$where.';';
+
+ return $this->execQuery($qry, $paramsArray);
+ }
+
+ public function updateUnruly($person_id, $unruly)
+ {
+ $result = $this->update($person_id, array(
+ 'unruly' => $unruly
+ ));
+
+ if (isError($result)) {
+ return error($result->msg, EXIT_ERROR);
+ } else if (isSuccess($result) && hasData($result)) {
+ return success($result);
+ }
+ }
+}
\ No newline at end of file
diff --git a/application/models/ressource/Betriebsmittel_model.php b/application/models/ressource/Betriebsmittel_model.php
index 849a9199f..290c3491d 100644
--- a/application/models/ressource/Betriebsmittel_model.php
+++ b/application/models/ressource/Betriebsmittel_model.php
@@ -11,4 +11,24 @@ class Betriebsmittel_model extends DB_Model
$this->dbTable = 'wawi.tbl_betriebsmittel';
$this->pk = 'betriebsmittel_id';
}
+
+ /**
+ * load Liste Inventarnummern
+ */
+ public function loadInventarliste($filter)
+ {
+ $filter = urldecode(strtoLower($filter));
+
+ $qry = "
+ SELECT
+ bm.inventarnummer, bm.betriebsmitteltyp, bm.betriebsmittel_id, CONCAT(bm.inventarnummer, ' ', bm.beschreibung) as dropdowntext
+ FROM
+ wawi.tbl_betriebsmittel bm
+ WHERE
+ upper(bm.inventarnummer) LIKE '%" .$this->db->escape_like_str($filter)."%'
+ OR
+ lower(bm.inventarnummer) LIKE '%" .$this->db->escape_like_str($filter)."%'";
+
+ return $this->execQuery($qry);
+ }
}
diff --git a/application/models/ressource/Betriebsmittelperson_model.php b/application/models/ressource/Betriebsmittelperson_model.php
index 04878a9ad..39f08b5cd 100644
--- a/application/models/ressource/Betriebsmittelperson_model.php
+++ b/application/models/ressource/Betriebsmittelperson_model.php
@@ -96,4 +96,49 @@ class Betriebsmittelperson_model extends DB_Model
return $this->loadWhere($condition);
}
+
+ public function getBetriebsmittelData($id, $type_id)
+ {
+ switch ($type_id) {
+ case 'person_id':
+ $cond = 'bmp.person_id';
+ break;
+ case 'uid':
+ $cond = 'bmp.uid';
+ break;
+ case 'betriebsmittelperson_id':
+ $cond = 'bmp.betriebsmittelperson_id';
+ break;
+ default:
+ return error("ID nicht gültig");
+ }
+
+ $query = "
+ SELECT
+ bm.nummer, bmp.person_id, bm.betriebsmitteltyp, bmp.anmerkung as anmerkung, bmp.retouram, TO_CHAR(bmp.retouram::timestamp, 'DD.MM.YYYY') AS format_retour, bmp.ausgegebenam, TO_CHAR(bmp.ausgegebenam::timestamp, 'DD.MM.YYYY') AS format_ausgabe, bm.beschreibung, bmp.uid, bmp.kaution, bm.betriebsmittel_id, bmp.betriebsmittelperson_id, bm.inventarnummer, bm.nummer2
+ FROM
+ wawi.tbl_betriebsmittelperson bmp
+ JOIN
+ wawi.tbl_betriebsmittel bm ON (bmp.betriebsmittel_id = bm.betriebsmittel_id)
+ WHERE
+ " . $cond . " = ? ";
+
+ return $this->execQuery($query, array($id));
+ }
+
+ /**
+ * Perform a loadWhere on the vw_betriebsmittelperson DB View
+ *
+ * @param array $where
+ *
+ * @return stdClass
+ */
+ public function loadViewWhere($where)
+ {
+ $table = $this->dbTable;
+ $this->dbTable = 'public.vw_betriebsmittelperson';
+ $result = $this->loadWhere($where);
+ $this->dbTable = $table;
+ return $result;
+ }
}
diff --git a/application/models/ressource/Firma_model.php b/application/models/ressource/Firma_model.php
index 1b8dfb51d..431f0815f 100644
--- a/application/models/ressource/Firma_model.php
+++ b/application/models/ressource/Firma_model.php
@@ -11,4 +11,18 @@ class Firma_model extends DB_Model
$this->dbTable = 'public.tbl_firma';
$this->pk = 'firma_id';
}
+
+ public function searchFirmen($filter)
+ {
+ $filter = strtoLower($filter);
+ $qry = "
+ SELECT
+ f.name, f.firma_id
+ FROM
+ public.tbl_firma f
+ WHERE
+ lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'";
+
+ return $this->execQuery($qry);
+ }
}
diff --git a/application/models/ressource/Mitarbeiter_model.php b/application/models/ressource/Mitarbeiter_model.php
index 90c30927f..c38fcf054 100644
--- a/application/models/ressource/Mitarbeiter_model.php
+++ b/application/models/ressource/Mitarbeiter_model.php
@@ -144,10 +144,15 @@ class Mitarbeiter_model extends DB_Model
* Checks if alias exists
* @param $kurzbz
*/
- public function kurzbzExists($kurzbz)
+ public function kurzbzExists($kurzbz, $uid=null)
{
$this->addSelect('1');
- $result = $this->loadWhere(array('kurzbz' => $kurzbz));
+ $where = array('kurzbz' => $kurzbz);
+ if ($uid != null)
+ {
+ $where['mitarbeiter_uid<>'] = $uid;
+ }
+ $result = $this->loadWhere($where);
if (isSuccess($result))
{
@@ -171,7 +176,6 @@ class Mitarbeiter_model extends DB_Model
*/
public function generateKurzbz($uid)
{
- $kurzbz = '';
$this->addLimit(1);
$this->addSelect('vorname, nachname');
$this->addJoin('public.tbl_benutzer', 'tbl_mitarbeiter.mitarbeiter_uid = tbl_benutzer.uid');
@@ -181,25 +185,57 @@ class Mitarbeiter_model extends DB_Model
if (hasData($nameresult))
{
$kurzbzdata = getData($nameresult);
- $nachname_clean = sanitizeProblemChars($kurzbzdata[0]->nachname);
- $vorname_clean = sanitizeProblemChars($kurzbzdata[0]->vorname);
+ $genKurzbz = $this->generateKurzbzHelper($kurzbzdata[0]->vorname, $kurzbzdata[0]->nachname);
- for ($nn = 6, $vn = 2; $nn != 0; $nn--, $vn++)
- {
- $kurzbz = mb_substr($nachname_clean, 0, $nn);
- $kurzbz .= mb_substr($vorname_clean, 0, $vn);
+ return $genKurzbz;
+ }
+ return error('No Kurzbezeichnung could be generated');
+ }
- $kurzbzexists = $this->kurzbzExists($kurzbz);
+ public function generateKurzbzHelper($vorname, $nachname)
+ {
+ $nachname_clean = sanitizeProblemChars($nachname);
+ $vorname_clean = sanitizeProblemChars($vorname);
+ $kurzbz = '';
- if (hasData($kurzbzexists) && !getData($kurzbzexists)[0])
- break;
- }
+ for ($nn = 6, $vn = 2; $nn != 0; $nn--, $vn++)
+ {
+ $kurzbz = mb_substr($nachname_clean, 0, $nn);
+ $kurzbz .= mb_substr($vorname_clean, 0, $vn);
$kurzbzexists = $this->kurzbzExists($kurzbz);
- if (hasData($kurzbzexists) && getData($kurzbzexists)[0])
- return error('No Kurzbezeichnung could be generated');
+ if (hasData($kurzbzexists) && !getData($kurzbzexists)[0])
+ break;
}
+
+ $kurzbzexists = $this->kurzbzExists($kurzbz);
+
+ if (hasData($kurzbzexists) && getData($kurzbzexists)[0])
+ return error('No Kurzbezeichnung could be generated');
+
return success($kurzbz);
}
+
+ public function searchMitarbeiter($filter)
+ {
+ $filter = strtoLower($filter);
+ $qry = "
+ SELECT
+ ma.mitarbeiter_uid, CONCAT(p.nachname, ' ', p.vorname, ' (', ma.mitarbeiter_uid , ')') as mitarbeiter
+ FROM
+ public.tbl_mitarbeiter ma
+ JOIN
+ public.tbl_benutzer b on (ma.mitarbeiter_uid = b.uid)
+ JOIN
+ public.tbl_person p on (p.person_id = b.person_id)
+ WHERE
+ lower (p.nachname) LIKE '%". $this->db->escape_like_str($filter)."%'
+ OR
+ lower (p.vorname) LIKE '%". $this->db->escape_like_str($filter)."%'
+ OR
+ (ma.mitarbeiter_uid) LIKE '%". $this->db->escape_like_str($filter)."%'";
+
+ return $this->execQuery($qry);
+ }
}
diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php
new file mode 100644
index 000000000..c397d8573
--- /dev/null
+++ b/application/models/ressource/Stundensatz_model.php
@@ -0,0 +1,17 @@
+dbTable = 'hr.tbl_stundensatz';
+ $this->pk = 'stundensatz_id';
+ $this->hasSequence = true;
+ }
+
+}
\ No newline at end of file
diff --git a/application/models/ressource/Stundensatztyp_model.php b/application/models/ressource/Stundensatztyp_model.php
new file mode 100644
index 000000000..8dfd54c7d
--- /dev/null
+++ b/application/models/ressource/Stundensatztyp_model.php
@@ -0,0 +1,16 @@
+dbTable = 'hr.tbl_stundensatztyp';
+ $this->pk = 'stundensatztyp';
+ }
+
+}
\ No newline at end of file
diff --git a/application/models/ressource/Zeitaufzeichnung_model.php b/application/models/ressource/Zeitaufzeichnung_model.php
index b44861d13..8639a716a 100644
--- a/application/models/ressource/Zeitaufzeichnung_model.php
+++ b/application/models/ressource/Zeitaufzeichnung_model.php
@@ -21,4 +21,26 @@ class Zeitaufzeichnung_model extends DB_Model
return $this->execQuery($qry);
}
+
+ public function getFullInterval($uid, $fromDate, $toDate)
+ {
+ $qry = <<execQuery($qry, array($uid, $fromDate, $toDate, $uid, $fromDate, $toDate, $fromDate, $toDate));
+ }
}
diff --git a/application/models/system/Issue_model.php b/application/models/system/Issue_model.php
index ab1f9ba6e..331b0f050 100644
--- a/application/models/system/Issue_model.php
+++ b/application/models/system/Issue_model.php
@@ -22,13 +22,23 @@ class Issue_model extends DB_Model
*/
public function getOpenIssues($fehlercodes, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null)
{
- $params = array($fehlercodes);
+ $params = array();
// issue exists for a fehlercode (or fehlercode_extern), person_id, oe_kurzbz, if not verarbeitet yet
- $qry = 'SELECT issue_id, fehlercode, inhalt, fehlercode_extern, inhalt_extern, person_id, oe_kurzbz,
- behebung_parameter, datum, verarbeitetvon, verarbeitetamum
- FROM system.tbl_issue
- WHERE fehlercode IN ?
- AND verarbeitetamum IS NULL';
+ $qry = 'SELECT
+ iss.issue_id, iss.fehlercode, fe.fehler_kurzbz, iss.inhalt, iss.fehlercode_extern,
+ iss.inhalt_extern, iss.person_id, iss.oe_kurzbz, iss.behebung_parameter,
+ iss.datum, iss.verarbeitetvon, iss.verarbeitetamum
+ FROM
+ system.tbl_issue iss
+ JOIN system.tbl_fehler fe USING (fehlercode)
+ WHERE
+ verarbeitetamum IS NULL';
+
+ if (!isEmptyArray($fehlercodes))
+ {
+ $qry .= ' AND fehlercode IN ?';
+ $params[] = $fehlercodes;
+ }
if (!isEmptyString($fehlercode_extern))
{
@@ -59,7 +69,7 @@ class Issue_model extends DB_Model
* @param string $fehlercode_extern if provided, only issues with this external fehlercode are counted (for identifying issues from external systems).
* @return Object success with number of issues or error
*/
- public function getOpenIssueCount($fehlercode, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null)
+ public function getOpenIssueCount($fehlercode, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null, $behebung_parameter = null)
{
$params = array($fehlercode);
// issue exists for a fehlercode (or fehlercode_extern), person_id, oe_kurzbz, if not verarbeitet yet
@@ -85,6 +95,19 @@ class Issue_model extends DB_Model
$params[] = $oe_kurzbz;
}
+ if (isset($behebung_parameter) && !isEmptyArray($behebung_parameter))
+ {
+ // convert array to JSON string for postgres
+ $behebung_parameter_string = json_encode($behebung_parameter);
+
+ if ($behebung_parameter_string)
+ {
+ // check if jsonb value is equal to the passed parameters array (if value contains array and array contains value)
+ $qry .= ' AND behebung_parameter @> ? AND behebung_parameter <@ ?';
+ $params = array_merge($params, array($behebung_parameter_string, $behebung_parameter_string));
+ }
+ }
+
return $this->execQuery($qry, $params);
}
}
diff --git a/application/models/system/PersonLog_model.php b/application/models/system/PersonLog_model.php
index 7a66958b8..88b50487a 100644
--- a/application/models/system/PersonLog_model.php
+++ b/application/models/system/PersonLog_model.php
@@ -1,5 +1,22 @@
.
+ */
+
class PersonLog_model extends DB_Model
{
/**
@@ -17,7 +34,7 @@ class PersonLog_model extends DB_Model
* @param array $data Data of Log Entry to save.
* @return success object if true
*/
- public function insert($data)
+ public function insert($data, $encryptedColumns = null)
{
$result = $this->db->insert($this->dbTable, $data);
if ($result)
diff --git a/application/models/system/Recipient_model.php b/application/models/system/Recipient_model.php
index d74d03243..1c7811f93 100644
--- a/application/models/system/Recipient_model.php
+++ b/application/models/system/Recipient_model.php
@@ -327,7 +327,7 @@ class Recipient_model extends DB_Model
pr.nachname,
ms.person_id,
mrou.token
- ORDER BY sent DESC';
+ ORDER BY sent DESC LIMIT 1500';
return $this->execQuery($sql, array($person_id, $functions, $person_id));
}
diff --git a/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php b/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php
new file mode 100644
index 000000000..6827beaa4
--- /dev/null
+++ b/application/models/vertragsbestandteil/Dienstverhaeltnis_model.php
@@ -0,0 +1,249 @@
+dbTable = 'hr.tbl_dienstverhaeltnis';
+ $this->pk = 'dienstverhaeltnis_id';
+ }
+
+ /**
+ * @return list of DV
+ */
+ public function getDVByPersonUID($uid, $oe_kurzbz=null, $datum=null)
+ {
+ $result = null;
+
+ $qry = "
+ SELECT
+ dv.dienstverhaeltnis_id,
+ tbl_benutzer.uid,
+ tbl_mitarbeiter.personalnummer,
+ tbl_mitarbeiter.kurzbz,
+ tbl_mitarbeiter.lektor,
+ tbl_mitarbeiter.fixangestellt,
+ tbl_person.person_id,
+ tbl_benutzer.alias,
+ org.oe_kurzbz,
+ org.bezeichnung oe_bezeichnung,
+ dv.von,
+ dv.bis,
+ dv.dvendegrund_kurzbz,
+ dv.dvendegrund_anmerkung,
+ dv.vertragsart_kurzbz,
+ dv.updateamum,
+ dv.updatevon,
+ dv.dvendegrund_kurzbz,
+ dv.dvendegrund_anmerkung
+ FROM tbl_mitarbeiter
+ JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text
+ JOIN tbl_person USING (person_id)
+ JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text)
+ JOIN public.tbl_organisationseinheit org USING(oe_kurzbz)
+ WHERE tbl_benutzer.uid=?";
+ $data = array($uid);
+
+ if(!is_null($oe_kurzbz))
+ {
+ $qry.=" AND oe_kurzbz=?";
+ $data[] = $oe_kurzbz;
+ }
+
+ if (!is_null($datum))
+ {
+ $qry.=" AND ? BETWEEN dv.von AND COALESCE(dv.bis, '2999-12-31')";
+ $data[] = $datum;
+ }
+
+ $qry .="
+ ORDER BY dv.von desc
+ ";
+
+ return $this->execQuery($qry, $data);
+
+ }
+
+ public function getDVByID($dvid) {
+ $this->addSelect('hr.tbl_dienstverhaeltnis.*, public.tbl_organisationseinheit.bezeichnung as unternehmen');
+ $this->addJoin('public.tbl_organisationseinheit', 'hr.tbl_dienstverhaeltnis.oe_kurzbz = public.tbl_organisationseinheit.oe_kurzbz');
+ $result = $this->load($dvid);
+
+ if (hasData($result)) {
+ return $result;
+ }
+ return error('could not fetch DV by ID');
+ }
+
+
+ public function getCurrentDVByPersonUID($uid, $dateAsUnixTS)
+ {
+
+ $date = DateTime::createFromFormat( 'U', $dateAsUnixTS );
+ $datestring = $date->format("Y-m-d");
+
+ $qry = "
+ SELECT
+ dv.dienstverhaeltnis_id,
+ tbl_benutzer.uid,
+ tbl_mitarbeiter.personalnummer,
+ tbl_mitarbeiter.kurzbz,
+ tbl_mitarbeiter.lektor,
+ tbl_mitarbeiter.fixangestellt,
+ tbl_person.person_id,
+ tbl_benutzer.alias,
+ dv.von,
+ dv.bis,
+ dv.vertragsart_kurzbz,
+ dv.updateamum,
+ dv.updatevon
+ FROM tbl_mitarbeiter
+ JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text
+ JOIN tbl_person USING (person_id)
+ JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text)
+ WHERE tbl_benutzer.uid=? and (dv.von<=? and (dv.bis is null OR dv.bis>=?))
+ ORDER BY dv.von desc
+ ";
+
+ return $this->execQuery($qry, array($uid, $datestring, $datestring));
+ }
+
+ public function isOverlappingExistingDV($mitarbeiter_uid, $oe_kurzbz, $von, $bis, $dvid=null)
+ {
+ $params = array($mitarbeiter_uid, $oe_kurzbz, $von, $bis, $von, $bis);
+ $dvidclause = '';
+ if (intval($dvid) > 0)
+ {
+ $params = array_merge($params, array($dvid, $dvid));
+ $dvidclause = <<= COALESCE(vb.von, '1970-01-01'::date)
+ AND
+ COALESCE(dv.bis::date, '2170-12-31'::date) <= COALESCE(vb.bis, '2170-12-31')
+ ) = 0
+ AND dv.dienstverhaeltnis_id != ?
+EODVIDC;
+
+ }
+
+ $query = <<= dv.von
+ AND (
+ SELECT
+ COUNT(*) AS karenzen
+ FROM
+ hr.tbl_vertragsbestandteil vb
+ WHERE
+ vb.dienstverhaeltnis_id = dv.dienstverhaeltnis_id
+ AND
+ vb.vertragsbestandteiltyp_kurzbz = 'karenz'
+ AND
+ ?::date >= COALESCE(vb.von, '1970-01-01'::date)
+ AND
+ COALESCE(?::date, '2170-12-31'::date) <= COALESCE(vb.bis, '2170-12-31')
+ ) = 0
+ {$dvidclause}
+EOSQL;
+
+ $ret = $this->execReadOnlyQuery($query, $params);
+
+ if( ($dvcount = getData($ret)) && ($dvcount[0]->dvcount > 0) ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public function getDVByPersonUIDOverlapping($uid, $oe_kurzbz=null, $beginn=null, $ende=null)
+ {
+ $result = null;
+
+ $qry = "
+ SELECT
+ dv.dienstverhaeltnis_id,
+ tbl_benutzer.uid,
+ tbl_mitarbeiter.personalnummer,
+ tbl_mitarbeiter.kurzbz,
+ tbl_mitarbeiter.lektor,
+ tbl_mitarbeiter.fixangestellt,
+ tbl_person.person_id,
+ tbl_benutzer.alias,
+ org.oe_kurzbz,
+ org.bezeichnung oe_bezeichnung,
+ dv.von,
+ dv.bis,
+ dv.vertragsart_kurzbz,
+ dv.updateamum,
+ dv.updatevon
+ FROM tbl_mitarbeiter
+ JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid::text = tbl_benutzer.uid::text
+ JOIN tbl_person USING (person_id)
+ JOIN hr.tbl_dienstverhaeltnis dv ON(tbl_benutzer.uid::text = dv.mitarbeiter_uid::text)
+ JOIN public.tbl_organisationseinheit org USING(oe_kurzbz)
+ WHERE tbl_benutzer.uid=?";
+ $data = array($uid);
+
+ if(!is_null($oe_kurzbz))
+ {
+ $qry.=" AND oe_kurzbz=?";
+ $data[] = $oe_kurzbz;
+ }
+
+ if (!is_null($beginn) && !is_null($ende))
+ {
+ $qry.=" AND (?,?) OVERLAPS (dv.von, COALESCE(dv.bis, '2999-12-31'))";
+ $data[] = $beginn;
+ $data[] = $ende;
+ }
+
+ $qry .="
+ ORDER BY dv.von desc
+ ";
+
+ return $this->execQuery($qry, $data);
+
+ }
+
+ public function fetchDienstverhaeltnisse($unternehmen, $stichtag=null, $mitarbeiteruid=null) {
+ $where = "oe_kurzbz = " . $this->escape($unternehmen);
+ if( !is_null($stichtag) )
+ {
+ $where .= " AND " . $this->escape($stichtag) . " BETWEEN COALESCE(von, '1970-01-01') AND COALESCE(bis, '2070-12-31')";
+ }
+ if( !is_null($mitarbeiteruid) )
+ {
+ $where .= " AND mitarbeiter_uid = " . $this->escape($mitarbeiteruid);
+ }
+ $res = $this->loadWhere($where);
+ $dvs = array();
+ if(hasData($res) )
+ {
+ $dvs = getData($res);
+ }
+ return $dvs;
+ }
+}
diff --git a/application/models/vertragsbestandteil/GehaltsTyp_model.php b/application/models/vertragsbestandteil/GehaltsTyp_model.php
new file mode 100644
index 000000000..c933a3b38
--- /dev/null
+++ b/application/models/vertragsbestandteil/GehaltsTyp_model.php
@@ -0,0 +1,28 @@
+dbTable = 'hr.tbl_gehaltstyp';
+ $this->pk = 'gehaltstyp_kurzbz';
+ }
+
+ /**
+ * Gets Gehaltstyp for a Gehaltsbestandteil.
+ * @param int gehaltsbestandteil_id
+ * @return object the typ
+ */
+ public function getGehaltstypByGehaltsbestandteil($gehaltsbestandteil_id)
+ {
+ $gehaltsTyp = null;
+ $this->addJoin('hr.tbl_gehaltsbestandteil', 'gehaltstyp_kurzbz');
+ $result = $this->loadWhere(['gehaltsbestandteil_id' => $gehaltsbestandteil_id]);
+
+ if (hasData($result)) $gehaltsTyp = getData($result)[0];
+
+ return $gehaltsTyp;
+ }
+}
diff --git a/application/models/vertragsbestandteil/Gehaltsbestandteil_model.php b/application/models/vertragsbestandteil/Gehaltsbestandteil_model.php
new file mode 100644
index 000000000..e9006dfc0
--- /dev/null
+++ b/application/models/vertragsbestandteil/Gehaltsbestandteil_model.php
@@ -0,0 +1,147 @@
+dbTable = 'hr.tbl_gehaltsbestandteil';
+ $this->pk = 'gehaltsbestandteil_id';
+ }
+
+ public function getEncryptedColumns(): array
+ {
+ return array(
+ 'grundbetrag' => array(
+ DB_Model::CRYPT_CAST => 'numeric',
+ DB_Model::CRYPT_PASSWORD_NAME => 'ENCRYPTIONKEYGEHALT'
+ ),
+ 'betrag_valorisiert' => array(
+ DB_Model::CRYPT_CAST => 'numeric',
+ DB_Model::CRYPT_PASSWORD_NAME => 'ENCRYPTIONKEYGEHALT'
+ )
+ );
+ }
+
+ public function getCurrentGBTByDV($dienstverhaeltnis_id, $dateAsUnixTS)
+ {
+ $date = DateTime::createFromFormat( 'U', $dateAsUnixTS );
+ $datestring = $date->format("Y-m-d");
+
+ $qry = "
+ SELECT
+ gehaltsbestandteil_id,
+ gbt.von,
+ gbt.bis,
+ gbt.anmerkung,
+ gbt.dienstverhaeltnis_id,
+ gehaltstyp_kurzbz,
+ valorisierungssperre,
+ gbt.valorisierung,
+ grundbetrag as grund_betrag_decrypted,
+ betrag_valorisiert as betrag_val_decrypted,
+ gt.bezeichnung as gehaltstyp_bezeichnung,
+ vb.vertragsbestandteiltyp_kurzbz,
+ bf.funktion_kurzbz,
+ bf.oe_kurzbz,
+ fkt.beschreibung as fkt_beschreibung,
+ fb.bezeichnung as fb_bezeichnung,
+ org.bezeichnung as org_bezeichnung,
+ freitext.freitexttyp_kurzbz,
+ freitext.titel as freitext_titel
+ FROM hr.tbl_gehaltsbestandteil gbt LEFT JOIN hr.tbl_gehaltstyp gt using(gehaltstyp_kurzbz)
+ LEFT JOIN hr.tbl_vertragsbestandteil vb using(vertragsbestandteil_id)
+ LEFT JOIN hr.tbl_vertragsbestandteil_funktion vbf using(vertragsbestandteil_id)
+ LEFT JOIN public.tbl_benutzerfunktion bf using(benutzerfunktion_id)
+ LEFT JOIN public.tbl_funktion fkt using(funktion_kurzbz)
+ LEFT JOIN public.tbl_fachbereich fb using(fachbereich_kurzbz)
+ LEFT JOIN public.tbl_organisationseinheit org on (bf.oe_kurzbz=org.oe_kurzbz)
+ LEFT JOIN hr.tbl_vertragsbestandteil_freitext freitext on(vb.vertragsbestandteil_id=freitext.vertragsbestandteil_id)
+ WHERE gbt.dienstverhaeltnis_id=? AND
+ (gbt.von<=? and (gbt.bis is null OR gbt.bis>=?))
+ ORDER BY gt.sort
+ ";
+
+ return $this->execQuery($qry,
+ array($dienstverhaeltnis_id, $datestring, $datestring),
+ $this->getEncryptedColumns());
+ }
+
+ public function getGBTChartDataByDV_old($dienstverhaeltnis_id)
+ {
+
+ $qry = "
+ WITH gbt as
+ (select von,bis,grundbetrag as grund_betrag_decrypted from hr.tbl_gehaltsbestandteil where dienstverhaeltnis_id=?)
+ select von,bis, (select sum(gbt.grund_betrag_decrypted) as sum_betrag
+ from gbt where gbt.von<=gbtmeta.von and (gbt.bis is null or gbt.bis>=gbtmeta.von)
+ ) as summe from gbt as gbtmeta order by von,bis
+ ";
+
+ return $this->execQuery($qry,
+ array($dienstverhaeltnis_id),
+ $this->getEncryptedColumns());
+ }
+
+
+ public function getGehaltsbestandteile($dienstverhaeltnis_id, $stichtag=null, $includefuture=false)
+ {
+ $stichtagclause = '';
+ if( !is_null($stichtag) )
+ {
+ $date = strftime('%Y-%m-%d', strtotime($stichtag));
+ $stichtagclause = 'AND (' . $this->escape($date)
+ . ' BETWEEN COALESCE(von, \'1970-01-01\'::date)'
+ . ' AND COALESCE(bis, \'2170-01-01\'::date)';
+ if( $includefuture )
+ {
+ $stichtagclause .= ' OR COALESCE(von, \'1970-01-01\'::date) > '
+ . $this->escape($date);
+ }
+ $stichtagclause .= ')';
+ }
+
+ $this->addSelect('*');
+ $where = <<escape($dienstverhaeltnis_id)}
+ {$stichtagclause}
+EOSQL;
+
+ $query = $this->loadWhere(
+ $where,
+ $this->getEncryptedColumns()
+ );
+
+ $gehaltsbestandteile = array();
+ if( null !== ($rows = getData($query)) )
+ {
+ foreach( $rows as $row ) {
+ $tmpgb = new Gehaltsbestandteil();
+ $tmpgb->hydrateByStdClass($row, true);
+ $gehaltsbestandteile[] = $tmpgb;
+ }
+ }
+
+ return $gehaltsbestandteile;
+ }
+
+
+ public function getGehaltsbestandteil($id)
+ {
+ $this->addSelect('*');
+ $query = $this->load($id, $this->getEncryptedColumns());
+ $gehaltsbestandteil = null;
+
+ if( null !== ($row = getData($query)) )
+ {
+ $gehaltsbestandteil = new Gehaltsbestandteil();
+ $gehaltsbestandteil->hydrateByStdClass($row[0], true);
+ }
+
+ return $gehaltsbestandteil;
+ }
+}
diff --git a/application/models/vertragsbestandteil/IEncryption.php b/application/models/vertragsbestandteil/IEncryption.php
new file mode 100644
index 000000000..ebfb437ea
--- /dev/null
+++ b/application/models/vertragsbestandteil/IEncryption.php
@@ -0,0 +1,7 @@
+dbTable = 'hr.tbl_vertragsbestandteil_freitext';
+ $this->pk = 'vertragsbestandteil_id';
+ }
+
+ public function countOverlappingVBFreitextsOfSameType(vertragsbestandteil\VertragsbestandteilFreitext $vbft)
+ {
+ $notselfclause = (intval($vbft->getVertragsbestandteil_id()) > 0)
+ ? 'AND v.vertragsbestandteil_id <> ' . $this->escape($vbft->getVertragsbestandteil_id())
+ : '';
+ $sql = <<= COALESCE(v.von, '1970-01-01'::date)
+ AND
+ ?::date <= COALESCE(v.bis, '2170-12-31')
+ {$notselfclause}
+EOSQL;
+ $ret = $this->execReadOnlyQuery($sql, array(
+ $vbft->getDienstverhaeltnis_id(),
+ $vbft->getVertragsbestandteiltyp_kurzbz(),
+ $vbft->getFreitexttypKurzbz(),
+ $vbft->getBis(),
+ $vbft->getVon()
+ ));
+
+ if( null === ($vbcount = getData($ret)) ) {
+ throw new Exception('failed to fetch overlappingvbs count');
+ }
+
+ return $vbcount[0]->overlappingvbs;
+ }
+}
diff --git a/application/models/vertragsbestandteil/VertragsbestandteilFreitexttyp_model.php b/application/models/vertragsbestandteil/VertragsbestandteilFreitexttyp_model.php
new file mode 100644
index 000000000..09d2380b6
--- /dev/null
+++ b/application/models/vertragsbestandteil/VertragsbestandteilFreitexttyp_model.php
@@ -0,0 +1,12 @@
+dbTable = 'hr.tbl_vertragsbestandteil_freitexttyp';
+ $this->pk = 'freitexttyp_kurzbz';
+ }
+}
diff --git a/application/models/vertragsbestandteil/VertragsbestandteilFunktion_model.php b/application/models/vertragsbestandteil/VertragsbestandteilFunktion_model.php
new file mode 100644
index 000000000..7263ac893
--- /dev/null
+++ b/application/models/vertragsbestandteil/VertragsbestandteilFunktion_model.php
@@ -0,0 +1,35 @@
+dbTable = 'hr.tbl_vertragsbestandteil_funktion';
+ $this->pk = 'vertragsbestandteil_id';
+ }
+
+ public function isBenutzerfunktionAlreadyAttachedToAnotherVB($benutzerfunktion_id, $vertragsbestandteil_id)
+ {
+ $where = array('benutzerfunktion_id' => $benutzerfunktion_id);
+ if( intval($vertragsbestandteil_id) > 0 )
+ {
+ $where['vertragsbestandteil_id != '] = $vertragsbestandteil_id;
+ }
+ $this->addSelect('count(*) AS vbscount');
+ $res = $this->loadWhere($where);
+ if(isError($res))
+ {
+ throw new Exception('failed to check if benutzerfunktionid is already attached to another vertragsbestanteil');
+ }
+ $count = (getData($res))[0]->vbscount;
+ return $count > 0;
+ }
+}
diff --git a/application/models/vertragsbestandteil/VertragsbestandteilKarenz_model.php b/application/models/vertragsbestandteil/VertragsbestandteilKarenz_model.php
new file mode 100644
index 000000000..525291439
--- /dev/null
+++ b/application/models/vertragsbestandteil/VertragsbestandteilKarenz_model.php
@@ -0,0 +1,14 @@
+dbTable = 'hr.tbl_vertragsbestandteil_karenz';
+ $this->pk = 'vertragsbestandteil_id';
+ }
+}
diff --git a/application/models/vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model.php b/application/models/vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model.php
new file mode 100644
index 000000000..ccb02dd88
--- /dev/null
+++ b/application/models/vertragsbestandteil/VertragsbestandteilKuendigungsfrist_model.php
@@ -0,0 +1,14 @@
+dbTable = 'hr.tbl_vertragsbestandteil_kuendigungsfrist';
+ $this->pk = 'vertragsbestandteil_id';
+ }
+}
diff --git a/application/models/vertragsbestandteil/VertragsbestandteilStunden_model.php b/application/models/vertragsbestandteil/VertragsbestandteilStunden_model.php
new file mode 100644
index 000000000..569c9a601
--- /dev/null
+++ b/application/models/vertragsbestandteil/VertragsbestandteilStunden_model.php
@@ -0,0 +1,18 @@
+dbTable = 'hr.tbl_vertragsbestandteil_stunden';
+ $this->pk = 'vertragsbestandteil_id';
+ }
+}
diff --git a/application/models/vertragsbestandteil/VertragsbestandteilTyp_model.php b/application/models/vertragsbestandteil/VertragsbestandteilTyp_model.php
new file mode 100644
index 000000000..f64cb70f4
--- /dev/null
+++ b/application/models/vertragsbestandteil/VertragsbestandteilTyp_model.php
@@ -0,0 +1,12 @@
+dbTable = 'hr.tbl_vertragsbestandteiltyp';
+ $this->pk = 'vertragsbestandteiltyp_kurzbz';
+ }
+}
diff --git a/application/models/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model.php b/application/models/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model.php
new file mode 100644
index 000000000..561ed2932
--- /dev/null
+++ b/application/models/vertragsbestandteil/VertragsbestandteilUrlaubsanspruch_model.php
@@ -0,0 +1,11 @@
+dbTable = 'hr.tbl_vertragsbestandteil_urlaubsanspruch';
+ $this->pk = 'vertragsbestandteil_id';
+ }
+}
diff --git a/application/models/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model.php b/application/models/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model.php
new file mode 100644
index 000000000..8e2d45e1a
--- /dev/null
+++ b/application/models/vertragsbestandteil/VertragsbestandteilZeitaufzeichnung_model.php
@@ -0,0 +1,12 @@
+dbTable = 'hr.tbl_vertragsbestandteil_zeitaufzeichnung';
+ $this->pk = 'vertragsbestandteil_id';
+ }
+}
diff --git a/application/models/vertragsbestandteil/Vertragsbestandteil_model.php b/application/models/vertragsbestandteil/Vertragsbestandteil_model.php
new file mode 100644
index 000000000..6d8c18859
--- /dev/null
+++ b/application/models/vertragsbestandteil/Vertragsbestandteil_model.php
@@ -0,0 +1,181 @@
+dbTable = 'hr.tbl_vertragsbestandteil';
+ $this->pk = 'vertragsbestandteil_id';
+ }
+
+ protected function getVertragsbestandteilSQL()
+ {
+ $sql = <<escape($date)
+ . ' BETWEEN COALESCE(v.von, \'1970-01-01\'::date)'
+ . ' AND COALESCE(v.bis, \'2170-01-01\'::date)';
+ if( $includefuture )
+ {
+ $stichtagclause .= ' OR COALESCE(v.von, \'1970-01-01\'::date) > '
+ . $this->escape($date);
+ }
+ $stichtagclause .= ')';
+ }
+
+ $sql = <<getVertragsbestandteilSQL()}
+ WHERE
+ v.dienstverhaeltnis_id = {$this->escape($dienstverhaeltnis_id)}
+ {$stichtagclause}
+ ;
+EOSQL;
+
+ // echo $sql . "\n\n";
+ $query = $this->execReadOnlyQuery($sql); // TODO add decryption
+ $data = getData($query);
+
+ if ($data == null)
+ {
+ return array();
+ }
+
+ $vertragsbestandteile = array();
+ foreach( $data as $row ) {
+ try
+ {
+ $vertragsbestandteile[] = VertragsbestandteilFactory::getVertragsbestandteil($row, true);
+ }
+ catch (Exception $ex)
+ {
+ echo $ex->getMessage() . "\n";
+ }
+ }
+
+ $dummy = json_encode($vertragsbestandteile);
+ return $vertragsbestandteile;
+ }
+
+
+ public function getVertragsbestandteil($id)
+ {
+
+ $sql = <<getVertragsbestandteilSQL()}
+ WHERE
+ v.vertragsbestandteil_id = {$this->escape($id)}
+ ;
+EOSQL;
+
+ $query = $this->execReadOnlyQuery($sql);
+
+ $vertragsbestandteil = null;
+
+ if( hasData($query) )
+ {
+ $data = getData($query)[0];
+ try
+ {
+ $vertragsbestandteil = VertragsbestandteilFactory::getVertragsbestandteil($data, true); // TODO add decryption
+ }
+ catch (Exception $ex)
+ {
+ echo $ex->getMessage() . "\n";
+ }
+ }
+
+ return $vertragsbestandteil;
+
+ }
+
+ public function countOverlappingVBsOfSameType(vertragsbestandteil\Vertragsbestandteil $vb)
+ {
+ $notselfclause = (intval($vb->getVertragsbestandteil_id()) > 0)
+ ? 'AND v.vertragsbestandteil_id <> ' . $this->escape($vb->getVertragsbestandteil_id())
+ : '';
+ $sql = <<= COALESCE(v.von, '1970-01-01'::date)
+ AND
+ ?::date <= COALESCE(v.bis, '2170-12-31')
+ {$notselfclause}
+EOSQL;
+ $ret = $this->execReadOnlyQuery($sql, array(
+ $vb->getDienstverhaeltnis_id(),
+ $vb->getVertragsbestandteiltyp_kurzbz(),
+ $vb->getBis(),
+ $vb->getVon()
+ ));
+
+ if( null === ($vbcount = getData($ret)) ) {
+ throw new Exception('failed to fetch overlappingvbs count');
+ }
+
+ return $vbcount[0]->overlappingvbs;
+ }
+}
diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php
new file mode 100644
index 000000000..2d0d22346
--- /dev/null
+++ b/application/views/Studentenverwaltung.php
@@ -0,0 +1,55 @@
+ 'Studentenverwaltung',
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'fontawesome6' => true,
+ 'vue3' => true,
+ 'primevue3' => true,
+ #'filtercomponent' => true,
+ 'tabulator5' => true,
+ 'tinymce5' => true,
+ 'phrases' => array(
+ 'global',
+ 'ui',
+ 'notiz',
+ ),
+ 'customCSSs' => [
+ 'public/css/components/vue-datepicker.css',
+ 'public/css/components/primevue.css',
+ 'public/css/Studentenverwaltung.css'
+ ],
+ 'customJSs' => [
+ #'vendor/npm-asset/primevue/tree/tree.min.js',
+ #'vendor/npm-asset/primevue/toast/toast.min.js'
+ ],
+ 'customJSModules' => [
+ 'public/js/apps/Studentenverwaltung.js'
+ ]
+ );
+
+ $this->load->view('templates/FHC-Header', $includesArray);
+?>
+
+ !defined('GENERATE_ALIAS_STUDENT') ? true : GENERATE_ALIAS_STUDENT,
+ 'showZgvDoktor' => !defined('ZGV_DOKTOR_ANZEIGEN') ? false : ZGV_DOKTOR_ANZEIGEN,
+ 'showZgvErfuellt' => !defined('ZGV_ERFUELLT_ANZEIGEN') ? false : ZGV_ERFUELLT_ANZEIGEN
+];
+?>
+
+
+
+
+
+
+load->view('templates/FHC-Footer', $includesArray); ?>
+
diff --git a/application/views/codex/bismeldestichtag.php b/application/views/codex/bismeldestichtag.php
new file mode 100644
index 000000000..37af16cc6
--- /dev/null
+++ b/application/views/codex/bismeldestichtag.php
@@ -0,0 +1,75 @@
+ 'Bismeldestichtage',
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'fontawesome6' => true,
+ 'vue3' => true,
+ 'filtercomponent' => true,
+ 'navigationcomponent' => true,
+ 'tabulator5' => true,
+ 'customCSSs' => array('vendor/vuejs/vuedatepicker_css/main.css'),
+ 'customJSs' => array('vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js'),
+ 'customJSModules' => array('public/js/apps/Bismeldestichtag/Bismeldestichtag.js')
+ );
+
+ $this->load->view('templates/FHC-Header', $includesArray);
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+load->view('templates/FHC-Footer', $includesArray); ?>
diff --git a/application/views/codex/uhstat1.php b/application/views/codex/uhstat1.php
index a09f9c70a..a255781f1 100644
--- a/application/views/codex/uhstat1.php
+++ b/application/views/codex/uhstat1.php
@@ -47,6 +47,9 @@ $saved = isset($saved) && $saved === true;
p->t('uhstat', 'uhstat1AnmeldungEinleitungstext') ?>
+
+ p->t('uhstat', 'uhstat1EinleitungSvnrtext') ?>
+
@@ -71,16 +74,23 @@ $saved = isset($saved) && $saved === true;
@@ -91,16 +101,23 @@ $saved = isset($saved) && $saved === true;
p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
-
+
+
+
+
+
+
@@ -111,16 +128,23 @@ $saved = isset($saved) && $saved === true;
p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
-
+
+
+
+
+
+
@@ -158,16 +182,23 @@ $saved = isset($saved) && $saved === true;
@@ -178,16 +209,23 @@ $saved = isset($saved) && $saved === true;
p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
-
+
+
+
+
+
+
@@ -198,16 +236,23 @@ $saved = isset($saved) && $saved === true;
p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
-
+
+
+
+
+
+
@@ -268,7 +313,7 @@ $saved = isset($saved) && $saved === true;
-
-
+
+
load->view('templates/FHC-Footer'); ?>
diff --git a/application/views/errors/json/html/error_404.php b/application/views/errors/json/html/error_404.php
new file mode 100644
index 000000000..0caade2b1
--- /dev/null
+++ b/application/views/errors/json/html/error_404.php
@@ -0,0 +1,65 @@
+
+
+
+
+404 Page Not Found
+
+
+
+
+
+
+
+
+
diff --git a/application/views/errors/json/html/error_db.php b/application/views/errors/json/html/error_db.php
new file mode 100644
index 000000000..dce6a7572
--- /dev/null
+++ b/application/views/errors/json/html/error_db.php
@@ -0,0 +1,49 @@
+', $msg);
+
+$msgs = [];
+
+$error = [
+ 'heading' => $heading
+];
+
+/** NOTE(chris): extract Error Number and SQL
+ * @see: DB_driver.php:692
+ */
+if (substr(current($msg), 0, 14) == 'Error Number: ') {
+ $code = substr(array_shift($msg), 14);
+ if ($code)
+ $error['code'] = (int)$code;
+ $msgs[] = array_shift($msg);
+ $error['sql'] = array_shift($msg);
+}
+
+/** NOTE(chris): extract Line Number and Filename
+ * @see: DB_driver.php:1782
+ * @see: DB_driver.php:1783
+ */
+if (count($msg) >= 2) {
+ if (substr(end($msg), 0, 13) == 'Line Number: ' && substr(prev($msg), 0, 10) == 'Filename: ') {
+ $error['line'] = (int)substr(array_pop($msg), 13);
+ $error['filename'] = substr(array_pop($msg), 10);
+ }
+}
+
+foreach ($msg as $m)
+ $msgs[] = $m;
+
+
+if (count($msgs) == 1)
+ $error['message'] = current($msgs);
+else
+ $error['messages'] = $msgs;
+
+$g_result->addError($error, FHCAPI_Controller::ERROR_TYPE_DB);
+$g_result->setStatus(FHCAPI_Controller::STATUS_ERROR);
diff --git a/application/views/errors/json/html/error_exception.php b/application/views/errors/json/html/error_exception.php
new file mode 100644
index 000000000..7984bd13e
--- /dev/null
+++ b/application/views/errors/json/html/error_exception.php
@@ -0,0 +1,27 @@
+ $message,
+ 'class' => get_class($exception),
+ 'filename' => $exception->getFile(),
+ 'line' => $exception->getLine()
+];
+
+if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === true) {
+ $error['backtrace'] = [];
+ foreach (debug_backtrace() as $err) {
+ if (isset($err['file']) && strpos($err['file'], realpath(BASEPATH)) !== 0) {
+ $error['backtrace'][] = [
+ 'file' => $err['file'],
+ 'line' => $err['line'],
+ 'function' => $err['function']
+ ];
+ }
+ }
+}
+
+$g_result->addError($error, FHCAPI_Controller::ERROR_TYPE_EXCEPTION);
+$g_result->setStatus(FHCAPI_Controller::STATUS_ERROR);
diff --git a/application/views/errors/json/html/error_general.php b/application/views/errors/json/html/error_general.php
new file mode 100644
index 000000000..e69494463
--- /dev/null
+++ b/application/views/errors/json/html/error_general.php
@@ -0,0 +1,20 @@
+
', $msg);
+
+$error = [
+ 'heading' => $heading
+];
+if (count($msg) == 1)
+ $error['message'] = current($msg);
+else
+ $error['messages'] = $msg;
+
+$g_result->addError($error, FHCAPI_Controller::ERROR_TYPE_GENERAL);
+$g_result->setStatus(FHCAPI_Controller::STATUS_ERROR);
diff --git a/application/views/errors/json/html/error_php.php b/application/views/errors/json/html/error_php.php
new file mode 100644
index 000000000..91f2abf3c
--- /dev/null
+++ b/application/views/errors/json/html/error_php.php
@@ -0,0 +1,31 @@
+ $message,
+ 'severity' => $severity,
+ 'filename' => $filepath,
+ 'line' => $line
+];
+
+if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === true) {
+ $error['backtrace'] = [];
+ foreach (debug_backtrace() as $err) {
+ if (isset($err['file']) && strpos($err['file'], realpath(BASEPATH)) !== 0) {
+ $error['backtrace'][] = [
+ 'file' => $err['file'],
+ 'line' => $err['line'],
+ 'function' => $err['function']
+ ];
+ }
+ }
+}
+
+// TODO(chris): change type with severity
+$g_result->addError($error, 'php');
+
+if (((E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity) {
+ $g_result->setStatus('error');
+}
diff --git a/application/views/lehre/Antrag/Create.php b/application/views/lehre/Antrag/Create.php
new file mode 100644
index 000000000..7e8bda874
--- /dev/null
+++ b/application/views/lehre/Antrag/Create.php
@@ -0,0 +1,55 @@
+ 'Antrag auf Änderung des Studierendenstatus',
+ 'cis' => true,
+ 'vue3' => true,
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'fontawesome6' => true,
+ 'phrases' => array(
+ ),
+ 'customJSModules' => array('public/js/apps/lehre/Antrag.js'),
+ 'customCSSs' => array(
+ 'public/css/Fhc.css',
+ 'public/css/components/primevue.css',
+ 'vendor/vuejs/vuedatepicker_css/main.css'
+ ),
+ 'customJSs' => array(
+ )
+);
+
+$this->load->view(
+ 'templates/FHC-Header',
+ $sitesettings
+);
+?>
+
+
+
+load->view(
+ 'templates/FHC-Footer',
+ $sitesettings
+);
\ No newline at end of file
diff --git a/application/views/lehre/Antrag/Leitung/List.php b/application/views/lehre/Antrag/Leitung/List.php
new file mode 100644
index 000000000..1225b16b6
--- /dev/null
+++ b/application/views/lehre/Antrag/Leitung/List.php
@@ -0,0 +1,60 @@
+ 'Anträge auf Änderung des Studierendenstatus',
+ 'cis' => true,
+ 'vue3' => true,
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'tabulator5' => true,
+ 'fontawesome6' => true,
+ 'primevue3' => true,
+ 'phrases' => array(
+ 'global',
+ 'ui',
+ 'studierendenantrag',
+ 'lehre',
+ 'person',
+ ),
+ 'customJSModules' => array('public/js/apps/lehre/Antrag/Leitung.js'),
+ 'customCSSs' => array(
+ 'public/css/Fhc.css',
+ 'public/css/components/primevue.css',
+ ),
+ 'customJSs' => array(
+ )
+);
+
+$this->load->view(
+ 'templates/FHC-Header',
+ $sitesettings
+);
+?>
+
+
+
+load->view(
+ 'templates/FHC-Footer',
+ $sitesettings
+);
diff --git a/application/views/lehre/Antrag/Student/List.php b/application/views/lehre/Antrag/Student/List.php
new file mode 100644
index 000000000..4a4b4f064
--- /dev/null
+++ b/application/views/lehre/Antrag/Student/List.php
@@ -0,0 +1,227 @@
+ 'Antrag auf Änderung des Studierendenstatus',
+ 'cis' => true,
+ 'vue3' => true,
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'fontawesome6' => true,
+ 'phrases' => array(
+ ),
+ 'customJSModules' => array('public/js/apps/lehre/Antrag/Student.js'),
+ 'customCSSs' => array(
+ 'public/css/Fhc.css',
+ 'public/css/components/primevue.css',
+ ),
+ 'customJSs' => array(
+ )
+);
+
+$this->load->view(
+ 'templates/FHC-Header',
+ $sitesettings
+);
+?>
+
+
+
+
+
+
+
+
+ $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/FHC-Footer',
+ $sitesettings
+);
diff --git a/application/views/lehre/Antrag/Wiederholung/Student.php b/application/views/lehre/Antrag/Wiederholung/Student.php
new file mode 100644
index 000000000..2171d6928
--- /dev/null
+++ b/application/views/lehre/Antrag/Wiederholung/Student.php
@@ -0,0 +1,43 @@
+ 'Antrag Wiederholung vom Studium',
+ 'cis' => true,
+ 'vue3' => true,
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'fontawesome6' => true,
+ 'tabulator5' => true,
+ 'phrases' => array(
+ 'ui',
+ 'lehre',
+ 'global'
+ ),
+ 'customJSModules' => array('public/js/apps/lehre/Antrag/Lvzuweisung.js'),
+ 'customCSSs' => array(
+ 'public/css/Fhc.css',
+ 'public/css/components/primevue.css',
+ ),
+ 'customJSs' => array(
+ )
+);
+
+$this->load->view(
+ 'templates/FHC-Header',
+ $sitesettings
+);
+?>
+
+
+
+
+ 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/approveAnrechnungDetail.php b/application/views/lehre/anrechnung/approveAnrechnungDetail.php
index 0970b6edd..c96631781 100644
--- a/application/views/lehre/anrechnung/approveAnrechnungDetail.php
+++ b/application/views/lehre/anrechnung/approveAnrechnungDetail.php
@@ -1,4 +1,5 @@
load->config('anrechnung');
$this->load->view(
'templates/FHC-Header',
array(
@@ -172,14 +173,16 @@ $this->load->view(
p->t('global', 'begruendung'); ?> |
begruendung ?> |
-
- | p->t('anrechnung', 'begruendungEctsLabel'); ?> |
- begruendung_ects ?> |
-
-
- | p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> |
- begruendung_lvinhalt ?> |
-
+ config->item('explain_equivalence')): ?>
+
+ | p->t('anrechnung', 'begruendungEctsLabel'); ?> |
+ begruendung_ects ?> |
+
+
+ | p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> |
+ begruendung_lvinhalt ?> |
+
+
diff --git a/application/views/lehre/anrechnung/requestAnrechnung.php b/application/views/lehre/anrechnung/requestAnrechnung.php
index 18fd66a67..bb3c48235 100644
--- a/application/views/lehre/anrechnung/requestAnrechnung.php
+++ b/application/views/lehre/anrechnung/requestAnrechnung.php
@@ -4,6 +4,7 @@ const CHAR_LENGTH150 = 150;
const CHAR_LENGTH500 = 500;
const CHAR_LENGTH1000 = 1000;
+$this->load->config('anrechnung');
$this->load->view(
'templates/FHC-Header',
array(
@@ -200,27 +201,29 @@ $this->load->view(
-
-
-
-
-
- p->t('anrechnung', 'begruendungEcts'); ?>
-
-
-
-
-
-
-
p->t('ui', 'maxZeichen'); ?> :
+
+ config->item('explain_equivalence')): ?>
+
+
+
+
+
+ p->t('anrechnung', 'begruendungEcts'); ?>
+
+
+
+
+
+
+ p->t('ui', 'maxZeichen'); ?> :
+
-
-
-
+
+
@@ -240,6 +243,8 @@ $this->load->view(
+
+
diff --git a/application/views/lehre/anrechnung/reviewAnrechnungDetail.php b/application/views/lehre/anrechnung/reviewAnrechnungDetail.php
index 08d23d8c4..98fee67a3 100644
--- a/application/views/lehre/anrechnung/reviewAnrechnungDetail.php
+++ b/application/views/lehre/anrechnung/reviewAnrechnungDetail.php
@@ -1,4 +1,5 @@
load->config('anrechnung');
$this->load->view(
'templates/FHC-Header',
array(
@@ -143,14 +144,16 @@ $this->load->view(
target="_blank">dokumentname) ?>
-
- | p->t('anrechnung', 'begruendungEctsLabel'); ?> |
- begruendung_ects ?> |
-
-
- | p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> |
- begruendung_lvinhalt ?> |
-
+ config->item('explain_equivalence')): ?>
+
+ | p->t('anrechnung', 'begruendungEctsLabel'); ?> |
+ begruendung_ects ?> |
+
+
+ | p->t('anrechnung', 'begruendungLvinhaltLabel'); ?> |
+ begruendung_lvinhalt ?> |
+
+
diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftrag.php b/application/views/lehre/lehrauftrag/acceptLehrauftrag.php
index d018beda8..6c65559d9 100644
--- a/application/views/lehre/lehrauftrag/acceptLehrauftrag.php
+++ b/application/views/lehre/lehrauftrag/acceptLehrauftrag.php
@@ -142,14 +142,17 @@ $this->load->view(
-
+
- p->t('dms' , 'informationsblattExterneLehrende'); ?>
+ p->t('ui' , 'hinweistextLehrauftrag'); ?>
+
+ p->t('dms' , 'informationsblattExterneLehrende'); ?>
+
-
+
diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php
index 92c896ce7..fcd9b953c 100644
--- a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php
+++ b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php
@@ -142,7 +142,7 @@ FROM
WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung)
ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
END AS "lv_oe_kurzbz",
- TRUNC(lema.semesterstunden, 1) AS "stunden",
+ TRUNC(lema.semesterstunden, 2) AS "stunden",
TRUNC((lema.semesterstunden * lema.stundensatz), 2) AS "betrag",
vertrag_id,
vertragsstunden AS "vertrag_stunden",
@@ -232,7 +232,7 @@ FROM
SELECT
pa.lehreinheit_id,
lv.lehrveranstaltung_id,
- pa.projektarbeit_id AS "projektarbeit_id",
+ pa.projektarbeit_id::text AS "projektarbeit_id",
le.studiensemester_kurzbz,
stg.studiengang_kz,
upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz",
@@ -375,9 +375,9 @@ $filterWidgetArray = array(
orgform_kurzbz: {visible: false, headerFilter:"input"},
person_id: {visible: false, headerFilter:"input"},
lv_oe_kurzbz: {visible: false, headerFilter:"input"},
- stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1},
+ stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:2},
headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator,
- bottomCalc:"sum", bottomCalcParams:{precision:1}
+ bottomCalc:"sum", bottomCalcParams:{precision:2}
},
betrag: {align:"right", formatter: form_formatNulltoStringNumber,
headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator,
diff --git a/application/views/lehre/lehrauftrag/approveLehrauftragData.php b/application/views/lehre/lehrauftrag/approveLehrauftragData.php
index 0414ddbf6..4f0c61193 100644
--- a/application/views/lehre/lehrauftrag/approveLehrauftragData.php
+++ b/application/views/lehre/lehrauftrag/approveLehrauftragData.php
@@ -149,7 +149,7 @@ FROM
ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
END AS "lv_oe_kurzbz",
(person.nachname || \' \' || person.vorname) AS "lektor",
- TRUNC(lema.semesterstunden, 1) AS "stunden",
+ TRUNC(lema.semesterstunden, 2) AS "stunden",
lema.stundensatz,
TRUNC((lema.semesterstunden * lema.stundensatz), 2) AS "betrag",
vertrag_id,
@@ -400,9 +400,9 @@ $filterWidgetArray = array(
person_id: {visible: false, headerFilter:"input"},
lv_oe_kurzbz: {visible: false, headerFilter:"input"},
lektor: {headerFilter:"input", widthGrow: 2},
- stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1},
+ stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:2},
headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator,
- bottomCalc:"sum", bottomCalcParams:{precision:1}},
+ bottomCalc:"sum", bottomCalcParams:{precision:2}},
stundensatz: {visible: true, align:"right", formatter: form_formatNulltoStringNumber,
headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator},
betrag: {align:"right", formatter: form_formatNulltoStringNumber,
diff --git a/application/views/lehre/lehrauftrag/orderLehrauftragData.php b/application/views/lehre/lehrauftrag/orderLehrauftragData.php
index 5a2ad98bd..85b663d4a 100644
--- a/application/views/lehre/lehrauftrag/orderLehrauftragData.php
+++ b/application/views/lehre/lehrauftrag/orderLehrauftragData.php
@@ -159,7 +159,7 @@ FROM
(
SELECT
/* lehrauftraege also planned with dummies, therefore personalnummer is needed */
- ma.personalnummer,
+ ma.personalnummer::text,
lema.lehreinheit_id,
lv.lehrveranstaltung_id,
lv.bezeichnung AS "lv_bezeichnung",
@@ -179,7 +179,7 @@ FROM
ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung)
END AS "lv_oe_kurzbz",
(person.nachname || \' \' || person.vorname) AS "lektor",
- TRUNC(lema.semesterstunden, 1) AS "stunden",
+ TRUNC(lema.semesterstunden, 2) AS "stunden",
lema.stundensatz,
TRUNC((lema.semesterstunden * lema.stundensatz), 2) AS "betrag",
vertrag_id,
@@ -219,7 +219,7 @@ FROM
(SELECT
uid
FROM
- public.tbl_benutzer JOIN public.tbl_mitarbeiter ma
+ public.tbl_benutzer JOIN public.tbl_mitarbeiter ma
ON tbl_benutzer.uid = ma.mitarbeiter_uid
WHERE
person_id = tmp_projektbetreuung.person_id
@@ -272,7 +272,7 @@ FROM
pa.lehreinheit_id,
lv.lehrveranstaltung_id,
lv.bezeichnung AS "lv_bezeichnung",
- pa.projektarbeit_id AS "projektarbeit_id",
+ pa.projektarbeit_id::text AS "projektarbeit_id",
le.studiensemester_kurzbz,
stg.studiengang_kz,
upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz",
@@ -414,7 +414,7 @@ $filterWidgetArray = array(
row_index: {visible: false},
personalnummer: {visible: false, headerFilter:"input"},
auftrag: {
- headerFilter:"input", widthGrow: 2,
+ headerFilter:"input", widthGrow: 2,
bottomCalc:"count", bottomCalcFormatter:function(cell){return "'. ucfirst($this->p->t('global', 'anzahl')). ': " + cell.getValue();}
},
stg_typ_kurzbz: {headerFilter:"input"},
@@ -432,9 +432,9 @@ $filterWidgetArray = array(
person_id: {visible: false, headerFilter:"input"},
lv_oe_kurzbz: {headerFilter:"input"},
lektor: {headerFilter:"input", widthGrow: 2},
- stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1},
+ stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:2},
headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator,
- bottomCalc:"sum", bottomCalcParams:{precision:1}},
+ bottomCalc:"sum", bottomCalcParams:{precision:2}},
stundensatz: {visible: true, align:"right", formatter: form_formatNulltoStringNumber,
headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator},
betrag: {align:"right", formatter: form_formatNulltoStringNumber,
diff --git a/application/views/lehre/lvplanung/lvTemplateUebersicht.php b/application/views/lehre/lvplanung/lvTemplateUebersicht.php
new file mode 100644
index 000000000..5c873486c
--- /dev/null
+++ b/application/views/lehre/lvplanung/lvTemplateUebersicht.php
@@ -0,0 +1,29 @@
+ 'LV Template Übersicht',
+ 'vue3' => true,
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'tabulator5' => true,
+ 'fontawesome6' => true,
+ 'primevue3' => true,
+ 'navigationcomponent' => true,
+ 'filtercomponent' => true,
+ 'customJSModules' => array('public/js/apps/lehre/lvplanung/LvTemplates.js'),
+ 'customCSSs' => array(
+ 'public/css/Fhc.css',
+ 'public/css/lvTemplateUebersicht.css'
+ )
+);
+
+$this->load->view('templates/FHC-Header', $includesArray);
+?>
+
+
+
+
+
+
+
+
+load->view('templates/FHC-Footer', $includesArray); ?>
diff --git a/application/views/person/bpk/bpkDetails.php b/application/views/person/bpk/bpkDetails.php
index 198065c24..bd6191c6a 100644
--- a/application/views/person/bpk/bpkDetails.php
+++ b/application/views/person/bpk/bpkDetails.php
@@ -9,7 +9,6 @@
'jqueryui1' => true,
'ajaxlib' => true,
'tablesorter2' => true,
- 'tinymce4' => true,
'sbadmintemplate3' => true,
'addons' => true,
'navigationwidget' => true,
@@ -126,10 +125,18 @@
-
diff --git a/application/views/system/infocenter/infocenterAbgewiesenData.php b/application/views/system/infocenter/infocenterAbgewiesenData.php
index 2307ea87e..da816b2c7 100644
--- a/application/views/system/infocenter/infocenterAbgewiesenData.php
+++ b/application/views/system/infocenter/infocenterAbgewiesenData.php
@@ -31,21 +31,35 @@ $query = '
ORDER BY l.log_id DESC
LIMIT 1
)
- AND '. $LOGDATA_VON .' = (
+ AND ('. $LOGDATA_VON .' = (
SELECT l.insertvon
FROM system.tbl_log l
WHERE l.person_id = p.person_id
ORDER BY l.log_id DESC
LIMIT 1
)
+ OR
+ (
+ (
+ SELECT l.insertvon
+ FROM system.tbl_log l
+ WHERE l.person_id = p.person_id
+ ORDER BY l.log_id DESC
+ LIMIT 1
+ ) IS NULL
+ )
+ )
AND l.zeitpunkt >= pss.insertamum
ORDER BY l.log_id DESC
LIMIT 1
) AS "Nachricht",
(
- SELECT SUM(konto.betrag)
+ SELECT
+ CASE
+ WHEN COUNT(CASE WHEN konto.betrag != 0 THEN 1 END) = 0 THEN null
+ ELSE SUM(konto.betrag)
+ END AS "Kaution"
FROM public.tbl_konto konto
- LEFT JOIN tbl_konto skonto ON (skonto.buchungsnr_verweis = konto.buchungsnr)
WHERE konto.person_id = p.person_id
AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .'
AND konto.buchungstyp_kurzbz = '. $STUDIENGEBUEHR_ANZAHLUNG .'
diff --git a/application/views/system/infocenter/infocenterData.php b/application/views/system/infocenter/infocenterData.php
index bb5b84479..61dc5a575 100644
--- a/application/views/system/infocenter/infocenterData.php
+++ b/application/views/system/infocenter/infocenterData.php
@@ -292,9 +292,12 @@
rueck.datum_bis AS "HoldDate",
rueck.bezeichnung AS "Rueckstellgrund",
(
- SELECT SUM(konto.betrag)
+ SELECT
+ CASE
+ WHEN COUNT(CASE WHEN konto.betrag != 0 THEN 1 END) = 0 THEN null
+ ELSE SUM(konto.betrag)
+ END AS "Kaution"
FROM public.tbl_konto konto
- LEFT JOIN tbl_konto skonto ON (skonto.buchungsnr_verweis = konto.buchungsnr)
WHERE konto.person_id = p.person_id
AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .'
AND konto.buchungstyp_kurzbz = '. $STUDIENGEBUEHR_ANZAHLUNG .'
diff --git a/application/views/system/infocenter/infocenterDetails.php b/application/views/system/infocenter/infocenterDetails.php
index c61bb3cd2..51b913b6c 100644
--- a/application/views/system/infocenter/infocenterDetails.php
+++ b/application/views/system/infocenter/infocenterDetails.php
@@ -8,7 +8,7 @@
'dialoglib' => true,
'ajaxlib' => true,
'tablesorter2' => true,
- 'tinymce4' => true,
+ 'tinymce5' => true,
'sbadmintemplate3' => true,
'addons' => true,
'navigationwidget' => true,
@@ -27,7 +27,8 @@
'public/js/infocenter/rueckstellung.js',
'public/js/infocenter/zgvUeberpruefung.js',
'public/js/infocenter/docUeberpruefung.js',
- 'public/js/infocenter/stammdaten.js'
+ 'public/js/infocenter/stammdaten.js',
+ 'public/js/infocenter/personcheck.js'
),
'phrases' => array(
'infocenter',
@@ -38,6 +39,14 @@
$this->load->view('templates/FHC-Header', $includesArray);
?>
+
+
+
widgetlib->widget('NavigationWidget'); ?>
@@ -74,22 +83,8 @@
-
-
-
-
- person_id . '
';
- }
- ?>
-
-
-
-
+
+ load->view('system/infocenter/personCheck.php', array('unruly' => $unruly, 'duplicate' => $duplicate)); ?>
@@ -201,5 +196,4 @@
-load->view('templates/FHC-Footer', $includesArray); ?>
-
+load->view('templates/FHC-Footer', $includesArray); ?>
\ No newline at end of file
diff --git a/application/views/system/infocenter/infocenterFreigegebenData.php b/application/views/system/infocenter/infocenterFreigegebenData.php
index 32315c145..8003b42e0 100644
--- a/application/views/system/infocenter/infocenterFreigegebenData.php
+++ b/application/views/system/infocenter/infocenterFreigegebenData.php
@@ -267,9 +267,12 @@ $query = '
LIMIT 1
) AS "AktenId",
(
- SELECT SUM(konto.betrag)
+ SELECT
+ CASE
+ WHEN COUNT(CASE WHEN konto.betrag != 0 THEN 1 END) = 0 THEN null
+ ELSE SUM(konto.betrag)
+ END AS "Kaution"
FROM public.tbl_konto konto
- LEFT JOIN tbl_konto skonto ON (skonto.buchungsnr_verweis = konto.buchungsnr)
WHERE konto.person_id = p.person_id
AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .'
AND konto.buchungstyp_kurzbz = '. $STUDIENGEBUEHR_ANZAHLUNG .'
diff --git a/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php b/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php
index e6b6d2495..7f9ee1288 100644
--- a/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php
+++ b/application/views/system/infocenter/infocenterReihungstestAbsolviertData.php
@@ -198,7 +198,11 @@ $query = '
LIMIT 1
) AS "InfoCenterMitarbeiter",
(
- SELECT SUM(konto.betrag)
+ SELECT
+ CASE
+ WHEN COUNT(CASE WHEN konto.betrag != 0 THEN 1 END) = 0 THEN null
+ ELSE SUM(konto.betrag)
+ END AS "Kaution"
FROM public.tbl_konto konto
WHERE konto.person_id = p.person_id
AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .'
diff --git a/application/views/system/infocenter/infocenterZgvDetails.php b/application/views/system/infocenter/infocenterZgvDetails.php
index 7636647ab..aefd95da0 100644
--- a/application/views/system/infocenter/infocenterZgvDetails.php
+++ b/application/views/system/infocenter/infocenterZgvDetails.php
@@ -10,7 +10,7 @@
'dialoglib' => true,
'ajaxlib' => true,
'tablesorter2' => true,
- 'tinymce4' => true,
+ 'tinymce5' => true,
'sbadmintemplate3' => true,
'addons' => true,
'navigationwidget' => true,
@@ -131,7 +131,11 @@
p->t('infocenter', 'zgvNichtErfuellt') ?>
-