diff --git a/application/config/stv.php b/application/config/stv.php index 0e18be220..8942c35e6 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -88,9 +88,14 @@ if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) { ); } -$config['tabs']['projektarbeit']['defaultProjektbetreuerStunden'] = '4.0'; -$config['tabs']['projektarbeit']['defaultProjektbetreuerStundenDiplom'] = '5.0'; -$config['tabs']['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz'] = true; +$config['tabs']['projektarbeit']['defaultProjektbetreuerStunden'] = + defined('FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_BACHELOR') + ? FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_BACHELOR + : '0.0'; +$config['tabs']['projektarbeit']['defaultProjektbetreuerStundenDiplom'] = + defined('FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_MASTER') + ? FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_MASTER + : '0.0'; $config['tabs']['projektarbeit']['defaultProjektbetreuerStundensatz'] = '80.0'; $config['student_tab_order'] = [ diff --git a/application/controllers/api/frontend/v1/Documents.php b/application/controllers/api/frontend/v1/Documents.php index 2d2c410cf..7b2fc4a15 100644 --- a/application/controllers/api/frontend/v1/Documents.php +++ b/application/controllers/api/frontend/v1/Documents.php @@ -442,6 +442,10 @@ class Documents extends FHCAPI_Controller 'betreuerart_kurzbz', 'studiensemester_kurzbz' ] as $key) { + if (in_array($xsl, array('Ausbildungsver', 'AusbVerEng')) && $key === 'uid') + { + continue; + } $value = $this->input->post_get($key); if ($value !== null) $params .= '&' . $key . '=' . urlencode($value); diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php index 4f33405ae..8a69d28ab 100644 --- a/application/controllers/api/frontend/v1/stv/Dokumente.php +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -590,8 +590,8 @@ class Dokumente extends FHCAPI_Controller $documents = [ buildDropdownEntryPrintArray("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uid, 10, null), - buildDropdownEntryPrintArray("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uid, 20, null), - buildDropdownEntryPrintArray("ausbildungsvertrag_en", "Ausbildungsvertrag Zweisprachig", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uid, 21, null), + buildDropdownEntryPrintArray("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf&prestudent_id=$prestudent_id", null,20, null), + buildDropdownEntryPrintArray("ausbildungsvertrag_en", "Ausbildungsvertrag Zweisprachig", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&prestudent_id=$prestudent_id", null,21, null), buildDropdownEntryPrintArray("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uid, 25, null), buildDropdownEntryPrintArray("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uid, 26, null), diff --git a/application/controllers/api/frontend/v1/stv/Grades.php b/application/controllers/api/frontend/v1/stv/Grades.php index dd8f53a27..128316d2b 100644 --- a/application/controllers/api/frontend/v1/stv/Grades.php +++ b/application/controllers/api/frontend/v1/stv/Grades.php @@ -60,7 +60,8 @@ class Grades extends FHCAPI_Controller { $this->load->model('codex/Note_model', 'NoteModel'); - $this->NoteModel->addOrder('note'); + $this->NoteModel->addOrder('notenwert', 'ASC'); + $this->NoteModel->addOrder('bezeichnung', 'ASC'); $result = $this->NoteModel->load(); diff --git a/application/controllers/api/frontend/v1/stv/Projektarbeit.php b/application/controllers/api/frontend/v1/stv/Projektarbeit.php index 9cc604184..8740ef3d6 100644 --- a/application/controllers/api/frontend/v1/stv/Projektarbeit.php +++ b/application/controllers/api/frontend/v1/stv/Projektarbeit.php @@ -17,7 +17,8 @@ class Projektarbeit extends FHCAPI_Controller 'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'], 'getFirmen' => ['admin:r', 'assistenz:r'], 'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'], - 'getNoten' => ['admin:r', 'assistenz:r'] + 'getNoten' => ['admin:r', 'assistenz:r'], + 'getStudiensemester' => ['admin:r', 'assistenz:r'] ]); // Load Libraries @@ -40,11 +41,15 @@ class Projektarbeit extends FHCAPI_Controller $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); $this->load->model('education/Note_model', 'NoteModel'); $this->load->model('education/Projektbetreuer_model', 'BetreuerModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); // load libraries $this->load->library('PermissionLib'); } + /** + * Get projekt works for a uid. + */ public function getProjektarbeit() { $student_uid = $this->input->get('uid'); @@ -53,10 +58,7 @@ class Projektarbeit extends FHCAPI_Controller $result = $this->ProjektarbeitModel->getProjektarbeit($student_uid); - if (isError($result)) - { - $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - } + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); if (!hasData($result)) $this->terminateWithSuccess([]); @@ -79,6 +81,9 @@ class Projektarbeit extends FHCAPI_Controller $this->terminateWithSuccess($projektarbeiten); } + /** + * Load a single Projektarbeit by id. + */ public function loadProjektarbeit() { $projektarbeit_id = $this->input->get('projektarbeit_id'); @@ -101,6 +106,9 @@ class Projektarbeit extends FHCAPI_Controller $this->terminateWithSuccess(current($data)); } + /** + * Inwert a Projektarbeit. + */ public function insertProjektarbeit() { $student_uid = $this->input->post('uid'); @@ -128,6 +136,9 @@ class Projektarbeit extends FHCAPI_Controller $this->terminateWithSuccess($data); } + /** + * Update a Projektarbeit by ID. + */ public function updateProjektarbeit() { $projektarbeit_id = $this->input->post('projektarbeit_id'); @@ -157,6 +168,9 @@ class Projektarbeit extends FHCAPI_Controller $this->terminateWithSuccess($data); } + /** + * Delete Projektarbeit by ID after validation. + */ public function deleteProjektarbeit() { $projektarbeit_id = $this->input->post('projektarbeit_id'); @@ -185,6 +199,9 @@ class Projektarbeit extends FHCAPI_Controller return $this->terminateWithSuccess(current(getData($result)) ? : null); } + /** + * Get all active projekt work types. + */ public function getTypenProjektarbeit() { $result = $this->ProjekttypModel->loadWhere(['aktiv' => true]); @@ -194,6 +211,9 @@ class Projektarbeit extends FHCAPI_Controller return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Gets companies by search string. + */ public function getFirmen() { $searchString = $this->input->get('searchString'); @@ -208,6 +228,9 @@ class Projektarbeit extends FHCAPI_Controller return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Get Lehrveranstaltungen by params, incling lehreinheiten for a specific Studiensemester.. + */ public function getLehrveranstaltungen() { $student_uid = $this->input->get('student_uid'); @@ -218,6 +241,7 @@ class Projektarbeit extends FHCAPI_Controller if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); if (!isset($studiensemester_kurzbz)) $this->terminateWithError('Studiensemster missing', self::ERROR_TYPE_GENERAL); + // get Lvs $lvsResult = $this->LehrveranstaltungModel->getLvsForProjektarbeit($student_uid, $studiengang_kz, $additional_lehrveranstaltung_id); if (isError($lvsResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL); @@ -226,6 +250,7 @@ class Projektarbeit extends FHCAPI_Controller foreach ($lvs as $lv) { + // add Lehreinheiten for each Lv for the semester $lehreinheiten = $this->LehreinheitModel->getLesForLv( $lv->lehrveranstaltung_id, $studiensemester_kurzbz ); @@ -250,8 +275,14 @@ class Projektarbeit extends FHCAPI_Controller return $this->terminateWithSuccess($lvs); } + /** + * Get all noten. + */ public function getNoten() { + $this->NoteModel->addOrder('notenwert', 'ASC'); + $this->NoteModel->addOrder('bezeichnung', 'ASC'); + $result = $this->NoteModel->load(); if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); @@ -260,9 +291,22 @@ class Projektarbeit extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Get all Studiensemester, sorted. + */ + public function getStudiensemester() + { + $this->StudiensemesterModel->addOrder('start', 'DESC'); + $result = $this->StudiensemesterModel->load(); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + /** + * Validate Projektarbeit data. + * @param formData + * @return bool true if data valid */ private function _validate($formData) { @@ -293,9 +337,9 @@ class Projektarbeit extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Extract Projektarbeit data from passed form data. + * @param formData + * @return array */ private function _getProjektarbeitArr($formData) { @@ -317,9 +361,9 @@ class Projektarbeit extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Check if deletion of a Projektarbeit is possible. + * @param $projektarbeit_id + * @return object success if deletion possible, error otherwise. */ private function _validateDelete($projektarbeit_id) { @@ -340,6 +384,11 @@ class Projektarbeit extends FHCAPI_Controller return success(); } + /** + * Checks permissions for a student. + * @param $student_uid + * @return bool true if authorized + */ private function _hasBerechtigungForStudent($student_uid) { if (!$student_uid) diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php index 98567ecde..904fa6167 100644 --- a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -3,7 +3,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); use \DateTime as DateTime; -use CI3_Events as Events; +use \CI3_Events as Events; class Projektbetreuer extends FHCAPI_Controller { @@ -43,6 +43,9 @@ class Projektbetreuer extends FHCAPI_Controller $this->load->library('PermissionLib'); } + /** + * Gets Projektbetreuer data for a Projektarbeit. + */ public function getProjektbetreuer() { $projektarbeit_id = $this->input->get('projektarbeit_id'); @@ -50,21 +53,30 @@ class Projektbetreuer extends FHCAPI_Controller if (!isset($projektarbeit_id)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); - $this->ProjektbetreuerModel->addSelect( - 'projektarbeit_id, person_id, nachname, vorname, note, punkte, round(stunden, 1) AS stunden, - stundensatz, betreuerart_kurzbz, vertrag_id, titelpre, titelpost' - ); - $this->ProjektbetreuerModel->addSelect("CASE - WHEN EXISTS - (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=pers.person_id) - THEN 'Mitarbeiter' - WHEN EXISTS - (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=pers.person_id) - THEN 'Student' - ELSE 'Person' - END AS status"); - $this->ProjektbetreuerModel->addJoin('public.tbl_person pers', 'person_id'); - $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + $qry = " + SELECT * FROM ( + SELECT + projektarbeit_id, person_id, nachname, vorname, note, punkte, round(stunden, 1) AS stunden, + stundensatz, betreuerart_kurzbz, vertrag_id, titelpre, titelpost, + CASE + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=pers.person_id) + THEN 'Mitarbeiter' + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=pers.person_id) + THEN 'Student' + ELSE 'Person' + END AS status + FROM + lehre.tbl_projektbetreuer + JOIN public.tbl_person pers USING (person_id) + WHERE + projektarbeit_id = ? + ) betreuer + ORDER BY + CASE WHEN status = 'Mitarbeiter' THEN 0 WHEN status = 'Person' THEN 1 ELSE 2 END"; + + $result = $this->ProjektbetreuerModel->execReadOnlyQuery($qry, [$projektarbeit_id]); if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); @@ -86,6 +98,7 @@ class Projektbetreuer extends FHCAPI_Controller //~ } //~ } + // add thesis download link (from external extension) foreach ($projektbetreuer as $pb) { $downloadLink = null; @@ -104,6 +117,9 @@ class Projektbetreuer extends FHCAPI_Controller $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); } + /** + * Saves (adds or updates) a single Projektbetreuer for a Projektarbeit. + */ public function saveProjektbetreuer() { $projektarbeit_id = $this->input->post('projektarbeit_id'); @@ -118,14 +134,36 @@ class Projektbetreuer extends FHCAPI_Controller if ($this->_validate($projektbetreuer) == false) $this->terminateWithValidationErrors($this->form_validation->error_array()); + // check if assessor has already been assigned + if (isset($projektbetreuer['person_id'])) + { + $this->ProjektbetreuerModel->addSelect('1'); + $betreuerRes = $this->ProjektbetreuerModel->loadWhere( + [ + 'person_id' => $projektbetreuer['person_id'], + 'projektarbeit_id' => $projektbetreuer['projektarbeit_id'], + 'betreuerart_kurzbz' => $projektbetreuer['betreuerart_kurzbz'] + ] + ); + + if (hasData($betreuerRes) + && (!isset($projektbetreuer['person_id_old']) || $projektbetreuer['person_id'] != $projektbetreuer['person_id_old'])) { + return $this->terminateWithError($this->p->t('projektarbeit', 'betreuerZugewiesen'), self::ERROR_TYPE_GENERAL); + } + } + $result = null; + $stunden = isset($projektbetreuer['stunden']) && !isEmptyString($projektbetreuer['stunden']) ? $projektbetreuer['stunden'] : null; + $stundensatz = + isset($projektbetreuer['stundensatz']) && !isEmptyString($projektbetreuer['stundensatz']) ? $projektbetreuer['stundensatz'] : null; + $betreuer = [ 'projektarbeit_id' => $projektarbeit_id, 'person_id' => $projektbetreuer['person_id'], 'note' => $projektbetreuer['note'], - 'stunden' => $projektbetreuer['stunden'], - 'stundensatz' => $projektbetreuer['stundensatz'], + 'stunden' => $stunden, + 'stundensatz' => $stundensatz, 'betreuerart_kurzbz' => $projektbetreuer['betreuerart_kurzbz'] ]; @@ -152,6 +190,9 @@ class Projektbetreuer extends FHCAPI_Controller $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Delete a Projektbetreuer assignment to a Projektarbeit. + */ public function deleteProjektbetreuer() { $projektarbeit_id = $this->input->post('projektarbeit_id'); @@ -159,21 +200,44 @@ class Projektbetreuer extends FHCAPI_Controller $betreuerart_kurzbz = $this->input->post('betreuerart_kurzbz'); if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) - return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> $this->p->t('projektarbeit', 'projektarbeit').' ID'], self::ERROR_TYPE_GENERAL)); + { + return $this->terminateWithError( + $this->p->t('ui', 'error_missingId', ['id'=> $this->p->t('projektarbeit', 'projektarbeit').' ID'], self::ERROR_TYPE_GENERAL) + ); + } if (!isset($person_id) || !is_numeric($person_id)) return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID'], self::ERROR_TYPE_GENERAL)); if (!isset($betreuerart_kurzbz)) - return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> $this->p->t('projektarbeit', 'betreuerart')], self::ERROR_TYPE_GENERAL)); + { + return $this->terminateWithError( + $this->p->t('ui', 'error_missingId', ['id'=> $this->p->t('projektarbeit', 'betreuerart')], self::ERROR_TYPE_GENERAL) + ); + } + // check permission if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); - $validate = $this->_validateDelete($projektarbeit_id, $person_id); + $validate = $this->_validateDelete($projektarbeit_id, $person_id, $betreuerart_kurzbz); if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); + // check if there is a Projektarbeitsbeurteilung - if yes, it is handled (possibly deleted) by external extension. + $beurteilungDeleteSuccess = true; + + Events::trigger( + 'projektarbeitsbeurteilung_delete', + $projektarbeit_id, + function ($value) use (&$beurteilungDeleteSuccess) { + $beurteilungDeleteSuccess = $value; + } + ); + + // if there is still a Beurteilung, Projektarbeit cannot be deleted - return with error + if (!$beurteilungDeleteSuccess) return $this->terminateWithError($this->p->t('projektarbeit', 'error_paarbeitHatBeurteilung')); + $result = $this->ProjektbetreuerModel->delete( ['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id, 'betreuerart_kurzbz' => $betreuerart_kurzbz] ); @@ -185,9 +249,12 @@ class Projektbetreuer extends FHCAPI_Controller $this->outputJson($result); } - return $this->terminateWithSuccess(current(getData($result)) ? : null); + return $this->terminateWithSuccess(getData($result)); } + /** + * Get all active Betreuerarten. + */ public function getBetreuerarten() { $result = $this->BetreuerartModel->loadWhere(['aktiv' => true]); @@ -197,6 +264,9 @@ class Projektbetreuer extends FHCAPI_Controller return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Get all Noten. + */ public function getNoten() { $result = $this->NoteModel->load(); @@ -206,6 +276,9 @@ class Projektbetreuer extends FHCAPI_Controller return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Get default Stundensätze for an employee in a semester. + */ public function getDefaultStundensaetze() { $person_id = $this->input->get('person_id'); @@ -216,6 +289,9 @@ class Projektbetreuer extends FHCAPI_Controller return $this->terminateWithSuccess($result); } + /** + * Get all Projektbetreuer by search string. + */ public function getProjektbetreuerBySearchQuery() { $searchString = $this->input->get('searchString'); @@ -227,9 +303,23 @@ class Projektbetreuer extends FHCAPI_Controller if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - return $this->terminateWithSuccess(hasData($result) ? $this->_addFullNameToBetreuer(getData($result)) : []); + if (!hasData($result)) $this->terminateWithSuccess([]); + + $persons = $this->_addFullNameToBetreuer(getData($result)); + + // sort persons by type (employees first) + usort($persons, function ($a, $b) { + $statusRanks = ['Mitarbeiter' => 0, 'Person' => 1, 'Student' => 2]; + return (isset($statusRanks[$a->status]) ? $statusRanks[$a->status] : count($statusRanks) + 1) + - (isset($statusRanks[$b->status]) ? $statusRanks[$b->status] : count($statusRanks) + 1); + }); + + return $this->terminateWithSuccess($persons); } + /** + * Get person info by Id. + */ public function getPerson() { $person_id = $this->input->get('person_id'); @@ -255,9 +345,7 @@ class Projektbetreuer extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Validate list of Projektbetreuer. */ public function validateProjektbetreuer() { @@ -277,9 +365,9 @@ class Projektbetreuer extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Validation funciton for checking Projektbetreuer input. + * @param $formData Betreuer data + * @return bool true when data is valid */ private function _validate($formData) { @@ -306,26 +394,32 @@ class Projektbetreuer extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Check possibility of deletion of a Projektbetreuer. + * @param projektarbeit_id + * @param person_id + * @param betreuerart_kurzbz + * @return object success when delete possible, error otherwise */ - private function _validateDelete($projektarbeit_id, $person_id) + private function _validateDelete($projektarbeit_id, $person_id, $betreuerart_kurzbz) { + // check if contract exists $this->ProjektbetreuerModel->addSelect('vertrag_id'); - $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id]); + $result = $this->ProjektbetreuerModel->loadWhere( + ['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id, 'betreuerart_kurzbz' => $betreuerart_kurzbz] + ); if (isError($result)) return $result; + // if contract exists, no deletion is possible if (hasData($result) && getData($result)[0]->vertrag_id != null) return error($this->p->t('projektarbeit', 'error_betreuerHatVertrag')); return success(); } /** - * - * @param - * @return object success or error + * Add full name to array with Betreuer. + * @param $betreuerArr + * @return array including Betreuer with their full names */ private function _addFullNameToBetreuer($betreuerArr) { diff --git a/application/controllers/api/frontend/v1/stv/Status.php b/application/controllers/api/frontend/v1/stv/Status.php index 36d445fc6..09a9f18b1 100644 --- a/application/controllers/api/frontend/v1/stv/Status.php +++ b/application/controllers/api/frontend/v1/stv/Status.php @@ -1078,6 +1078,24 @@ class Status extends FHCAPI_Controller $this->terminateWithSuccess(true); } + protected function checkForCriticalChangesBis($oldstatus) + { + $changedFields = array(); + $allowedFields = array('anmerkung', 'statusgrund_id'); + $oldstatus_array = get_object_vars($oldstatus); + foreach($oldstatus_array as $key => $oldValue) + { + $newValue = $this->input->post($key); + if( $newValue !== $oldValue ) + { + $changedFields[] = $key; + } + } + $criticalFieldsChanged = array_diff($changedFields, $allowedFields); + $hasCriticalChangesBis = count($criticalFieldsChanged) > 0 ? true : false; + return $hasCriticalChangesBis; + } + /** * Updates a status entry * @@ -1102,6 +1120,7 @@ class Status extends FHCAPI_Controller $oldstatus = current($oldstatus); + $hasCriticalChangesBis = $this->checkForCriticalChangesBis($oldstatus); $isBerechtigtNoStudstatusCheck = $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'); $isBerechtigtBasisPrestudentstatus = $this->permissionlib->isBerechtigt('basis/prestudentstatus'); @@ -1112,7 +1131,6 @@ class Status extends FHCAPI_Controller $ausbildungssemester = $this->input->post('ausbildungssemester') ?: $oldstatus->ausbildungssemester; $datum = $this->input->post('datum') ?: $oldstatus->datum; - //Form Validation $this->load->library('form_validation'); @@ -1135,9 +1153,15 @@ class Status extends FHCAPI_Controller $this->p->t('global', 'datum'), [ 'is_valid_date', - ['meldestichtag_not_exceeded', function ($value) use ($isBerechtigtNoStudstatusCheck) { + ['meldestichtag_not_exceeded', function ($value) use ($isBerechtigtNoStudstatusCheck, $hasCriticalChangesBis){ if ($isBerechtigtNoStudstatusCheck) - return true; // Skip if access right says so + { + return true; // Skip if access right says so*/ + } + if (!$hasCriticalChangesBis) { + return true; // Skip if no critical changes were made + } + if (!$value) return true; // Error will be handled by the required statement above diff --git a/application/controllers/api/frontend/v1/stv/Verband.php b/application/controllers/api/frontend/v1/stv/Verband.php index eb25a548b..32ef30a45 100644 --- a/application/controllers/api/frontend/v1/stv/Verband.php +++ b/application/controllers/api/frontend/v1/stv/Verband.php @@ -215,6 +215,7 @@ class Verband extends FHCAPI_Controller $this->StudienordnungModel->addDistinct(); $this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link"); $this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name"); + $this->StudienordnungModel->addSelect("studiengang_kz AS stg_kz"); $this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id'); diff --git a/application/controllers/jobs/AntragJob.php b/application/controllers/jobs/AntragJob.php index debcfe391..8dc4870ea 100644 --- a/application/controllers/jobs/AntragJob.php +++ b/application/controllers/jobs/AntragJob.php @@ -200,13 +200,14 @@ class AntragJob extends JOB_Controller } /** - * Send reminder to Assistant for Wiedereinstieg Unterbrecher + * Send reminder to Assistant and to Student 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'); @@ -230,6 +231,7 @@ class AntragJob extends JOB_Controller $antraege = getData($result) ?: []; $count = 0; + $countReminderStudent = 0; foreach ($antraege as $antrag) { $res = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id); @@ -257,10 +259,92 @@ class AntragJob extends JOB_Controller $data['UID'] = $student->student_uid; } - // NOTE(chris): Sancho mail - if(sendSanchoMail('Sancho_Mail_Antrag_U_Reminder', $data, $antrag->email, 'Reminder: Unterbrechung Wiedereinstieg')) + //Data für Email Student + $result = $this->PrestudentModel->load($antrag->prestudent_id); + $dataPrestudent = current(getData($result)); + $person_id = $dataPrestudent->person_id; + + $this->KontaktModel->addSelect('kontakt'); + + $result = $this->KontaktModel->loadWhere([ + 'person_id'=> $person_id, + 'zustellung' => true, + 'kontakttyp' => 'email' + ]); + + $email_student_privat = null; + $dataKontakt = getData($result); + if ($dataKontakt) { + $stud_private_zustell_emails = array_map(function($kontakt) { + return $kontakt->kontakt; + }, $dataKontakt); + $email_student_privat = implode(', ', $stud_private_zustell_emails); + } + + $email_student_FH = $this->StudentModel->getEmailFH($this->StudentModel->getUID($antrag->prestudent_id)); + + //studiensemester + $result = $this->StudiensemesterModel->getByDate($datum->format('Y-m-d')); + if (hasData($result)) { + $dataSem = current(getData($result)); + } + + $studiensemester = $dataSem->studiensemester_kurzbz; + $studsemShort = substr($studiensemester, 0, 2); + + if($studsemShort == "SS") + { + $data['studSemShort_Eng'] = "summer semester"; + $data['meldenBis'] = "15.1."; + $data['meldenBis_Eng'] = "January 15"; + } + elseif ($studsemShort == "WS") { + $data['studSemShort_Eng'] = "winter semester"; + $data['meldenBis'] = "1.8."; + $data['meldenBis_Eng'] = "August 1"; + } + else + { + $studsemShort = "SS/WS"; + $data['studSemShort_Eng'] = "summer/winter semester"; + $data['meldenBis'] = "15.1. (bei Einstieg ins SS) / 1.8. (bei Einstieg ins WS)"; + $data['meldenBis_Eng'] = "January 15 (for sommer semester enrollment) / August 1 (for winter semester enrollment)"; + } + + $data['studSemShort'] = $studsemShort; + + // NOTE(chris): Sancho mail Assistant + $sancho_assistant_sent = sendSanchoMail('Sancho_Mail_Antrag_U_Reminder', $data, $antrag->email, 'Reminder: Unterbrechung Wiedereinstieg'); + if($sancho_assistant_sent) { $count++; + } + else + { + $this->logError('Error: failed to send Assistant Reminder studierendenantrag_id: ' . $antrag->studierendenantrag_id); + } + //Mail to Student + $sancho_student_sent = sendSanchoMail( + 'Sancho_Mail_Antrag_U_Remind_Stud', + $data, + $email_student_FH, + 'Reminder: Unterbrechung Wiedereinstieg', + '', + '', + '', + $email_student_privat); + + if($sancho_student_sent) + { + $countReminderStudent++; + } + else + { + $this->logError('Error: failed to send Student Reminder studierendenantrag_id: ' . $antrag->studierendenantrag_id); + } + + if($sancho_assistant_sent && $sancho_student_sent) + { $this->StudierendenantragstatusModel->insert([ 'studierendenantrag_id' => $antrag->studierendenantrag_id, 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_REMINDERSENT, @@ -268,7 +352,7 @@ class AntragJob extends JOB_Controller ]); } } - $this->logInfo($count . ' Reminder gesendet - Ende Job sendReminderWiedereinstieg'); + $this->logInfo($count . ' Reminder an Assistenz und ' . $countReminderStudent . ' Reminder an Student gesendet - Ende Job sendReminderWiedereinstieg'); } /** diff --git a/application/libraries/PrestudentLib.php b/application/libraries/PrestudentLib.php index 28879fb47..a57533da0 100644 --- a/application/libraries/PrestudentLib.php +++ b/application/libraries/PrestudentLib.php @@ -68,7 +68,8 @@ class PrestudentLib $this->_ci->PrestudentModel->addOrder('zgv_code', 'DESC'); $this->_ci->PrestudentModel->addLimit(1); $result = $this->_ci->PrestudentModel->loadWhere([ - 'person_id' => $person_id + 'person_id' => $person_id, + 'zgv_code IS NOT NULL' => null ]); if (isError($result)) return $result; @@ -686,9 +687,6 @@ class PrestudentLib $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, @@ -698,8 +696,9 @@ class PrestudentLib if (isError($personenkennzeichen)) return $personenkennzeichen; $personenkennzeichen = getData($personenkennzeichen); - - + + $jahr = mb_substr($personenkennzeichen, 0, 2); + // Generate UID $uid = $this->_ci->StudentModel->generateUID( $student_data->kurzbz, diff --git a/application/models/crm/Student_model.php b/application/models/crm/Student_model.php index 6f2404cbd..ca9cfe4c3 100644 --- a/application/models/crm/Student_model.php +++ b/application/models/crm/Student_model.php @@ -169,7 +169,7 @@ class Student_model extends DB_Model $max = 0; if ($matrikelnrres && hasData($matrikelnrres)) { - $max = mb_substr(getData($matrikelnrres)[0]->matrikelnr, 7); + $max = mb_substr(trim(getData($matrikelnrres)[0]->matrikelnr), -3); if (!is_numeric($max)) { $max = (int)$max; } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 1ca2a18a8..414d1d1be 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -24,17 +24,28 @@ class Projektarbeit_model extends DB_Model public function getProjektarbeit($student_uid, $studiengang_kz = null, $studiensemester_kurzbz = null, $projekttyp = null, $final = null) { $qry = "SELECT - tbl_projektarbeit.*, tbl_projekttyp.bezeichnung, + pa.*, tbl_projekttyp.bezeichnung, tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.lehrveranstaltung_id, - tbl_firma.name AS firma_name + tbl_firma.name AS firma_name, + ( + SELECT + STRING_AGG(trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')), ', ') + FROM + lehre.tbl_projektbetreuer + JOIN public.tbl_person USING (person_id) + WHERE + projektarbeit_id = pa.projektarbeit_id + AND student_uid = pa.student_uid + GROUP BY projektarbeit_id + ) AS projektbetreuer FROM - lehre.tbl_projektarbeit + lehre.tbl_projektarbeit pa JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) JOIN lehre.tbl_lehreinheit USING (lehreinheit_id) JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) LEFT JOIN public.tbl_firma USING (firma_id) WHERE - tbl_projektarbeit.student_uid = ?"; + pa.student_uid = ?"; $params = array($student_uid); diff --git a/application/models/person/Profil_update_model.php b/application/models/person/Profil_update_model.php index 31005c4b7..039810537 100644 --- a/application/models/person/Profil_update_model.php +++ b/application/models/person/Profil_update_model.php @@ -135,7 +135,8 @@ class Profil_update_model extends DB_Model attachment_id, UPPER(public.tbl_studiengang.typ || public.tbl_studiengang.kurzbz) AS studiengang, COALESCE(of.orgform_kurzbz, public.tbl_studiengang.orgform_kurzbz) AS orgform, - NULL as oezuordnung + NULL as oezuordnung, + tbl_student.semester FROM public.tbl_profil_update JOIN public.tbl_profil_update_status ON public.tbl_profil_update_status.status_kurzbz = public.tbl_profil_update.status JOIN public.tbl_student ON public.tbl_student.student_uid=public.tbl_profil_update.uid diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php index c8ee367d8..2a7418924 100644 --- a/application/models/ressource/Stundensatz_model.php +++ b/application/models/ressource/Stundensatz_model.php @@ -47,7 +47,6 @@ class Stundensatz_model extends DB_Model { $this->load->config('stv'); - $useFixangestelltStundensatz = $this->config->item('tabs')['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz']; $defaultStundensatz = $this->config->item('tabs')['projektarbeit']['defaultProjektbetreuerStundensatz']; $stundensatz = ''; @@ -63,7 +62,7 @@ class Stundensatz_model extends DB_Model { $studiensemester = getData($result)[0]; - if (isset($useFixangestelltStundensatz) && !$useFixangestelltStundensatz) + if (defined('FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ') && !FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ) { // load Mitarbeiter $params = [$person_id]; @@ -83,19 +82,30 @@ class Stundensatz_model extends DB_Model if (hasData($result)) { - foreach (getData($result) as $ma) - { - if (!$ma->fixangestellt) - { - $stundensatzRes = $this->getStundensatzByDatum( - $ma->mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre' - ); + $ma = getData($result)[0]; - if (hasData($stundensatzRes)) - $stundensatz = getData($stundensatzRes)[0]->stundensatz; - else - $stundensatz = '0.00'; - } + $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel'); + $echterdv_result = $this->DienstverhaeltnisModel->existsDienstverhaeltnis( + $ma->mitarbeiter_uid, + $studiensemester->start, + $studiensemester->ende, + 'echterdv' + ); + + if (hasData($echterdv_result)) + { + $stundensatz = null; + } + else + { + $stundensatzRes = $this->getStundensatzByDatum( + $ma->mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre' + ); + + if (hasData($stundensatzRes)) + $stundensatz = getData($stundensatzRes)[0]->stundensatz; + else + $stundensatz = '0.00'; } } else diff --git a/cis/testtool/login.php b/cis/testtool/login.php index 5a2ae0dea..5306dadab 100644 --- a/cis/testtool/login.php +++ b/cis/testtool/login.php @@ -447,14 +447,6 @@ if (isset($_POST['save']) && isset($_SESSION['prestudent_id'])) { e.preventDefault(); }); - // If Browser is any other than Mozilla Firefox and the test includes any MathML, - // show message to use Mozilla Firefox - var ua = navigator.userAgent; - if ((ua.indexOf("Firefox") > -1) == false) - { - $("#alertmsgdiv").html("
BITTE VERWENDEN SIE DEN MOZILLA FIREFOX BROWSER!
(Manche Prüfungsfragen werden sonst nicht korrekt dargestellt.

PLEASE USE MOZILLA FIREFOX BROWSER!
(Otherwise some exam items will not be displayed correctly
"); - //alert('BITTE VERWENDEN SIE DEN MOZILLA FIREFOX BROWSER!\n(Manche Prüfungsfragen werden sonst nicht korrekt dargestellt.\n\nPLEASE USE MOZILLA FIREFOX BROWSER!\n(Ohterwise some exam items will not be displayed correctly.)'); - } }); -1) == false) - { - let hasMathML = ""; - let userLang = ""; - if (hasMathML == true) - { - if (userLang == 'German') - { - alert('BITTE VERWENDEN SIE DEN MOZILLA FIREFOX BROWSER!\n(Manche Prüfungsfragen werden sonst nicht korrekt dargestellt.)'); - } - else if(userLang == 'English') - { - alert('PLEASE USE MOZILLA FIREFOX BROWSER!\n(Ohterwise some exam items will not be displayed correctly.)'); - } - } - } - // Error massage if check_gebiet function returns false $(function() { var invalid_gebiete = ""; diff --git a/public/js/api/factory/stv/mobility.js b/public/js/api/factory/stv/mobility.js index fc4fd17b4..fcff30954 100644 --- a/public/js/api/factory/stv/mobility.js +++ b/public/js/api/factory/stv/mobility.js @@ -101,7 +101,7 @@ export default { deleteMobilityPurpose(params) { return { method: 'post', - url: 'api/frontend/v1/stv/mobility/deleteMobilityPurpose/', + url: 'api/frontend/v1/stv/mobility/deleteMobilityPurpose/' + params.bisio_id, params }; }, diff --git a/public/js/api/factory/stv/projektarbeit.js b/public/js/api/factory/stv/projektarbeit.js index 4412f1842..e9b3e7efc 100644 --- a/public/js/api/factory/stv/projektarbeit.js +++ b/public/js/api/factory/stv/projektarbeit.js @@ -49,6 +49,12 @@ export default { url: 'api/frontend/v1/stv/projektarbeit/getNoten' }; }, + getStudiensemester() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getStudiensemester' + }; + }, loadProjektarbeit(projektarbeit_id) { return { method: 'get', diff --git a/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js index 745f53002..9798ba7a4 100644 --- a/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js +++ b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js @@ -46,7 +46,6 @@ export default { loading: false, filter: "Pending", profil_update_id: Number(this.id), - }; }, computed: { @@ -60,6 +59,10 @@ export default { }, profilUpdateOptions: function () { return { + persistence: { + columns: ["width", "visible", "frozen"], + }, + persistenceID: 'cis-profilupdate-2025121702', ajaxURL: 'dummy', ajaxRequestFunc: (url, config, params) => { return this.$api.call(ApiProfilUpdate.getProfilUpdateWithPermission(params.filter)); @@ -205,7 +208,7 @@ export default { //responsive:0, }, { - title: this.$p.t("lehre", "studiengang") + ' (' + this.$p.t("profil", "studentIn") + ')', + title: this.$p.t("profil", "stg_short") + ' (' + this.$p.t("profil", "studentIn") + ')', field: "studiengang", minWidth: 50, resizable: true, @@ -213,8 +216,14 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { - title: this.$p.t("lehre", "organisationsform") + ' (' + this.$p.t("profil", "studentIn") + ')', + { + title: this.$p.t("profil", "sem_short") + ' (' + this.$p.t("profil", "studentIn") + ')', + field: "semester", + headerFilter: "list", + headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"} + }, + { + title: this.$p.t("profil", "orgform_short") + ' (' + this.$p.t("profil", "studentIn") + ')', field: "orgform", minWidth: 50, resizable: true, @@ -222,8 +231,8 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { - title: this.$p.t("lehre", "organisationseinheit") + ' (' + this.$p.t("profil", "mitarbeiterIn") + ')', + { + title: this.$p.t("profil", "orgeinheit_short") + ' (' + this.$p.t("profil", "mitarbeiterIn") + ')', field: "oezuordnung", minWidth: 200, resizable: true, @@ -231,7 +240,7 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { + { title: this.$p.t("profilUpdate", "Topic"), field: "topic", resizable: true, @@ -240,7 +249,7 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { + { title: this.$p.t("profilUpdate", "insertamum"), field: "insertamum_iso", resizable: true, @@ -251,7 +260,7 @@ export default { formatterParams: this.datetimeFormatterParams(), //responsive:0, }, - { + { title: this.$p.t("profilUpdate", "Status"), field: "status_translated", hozAlign: "center", @@ -273,7 +282,6 @@ export default { } return `
${cell.getValue()}
`; }, - resizable: true, minWidth: 200, //responsive:0, @@ -309,7 +317,6 @@ export default { ], }; } - }, methods: { denyProfilUpdate: function (data) { @@ -351,7 +358,6 @@ export default { this.showModal = false; this.modalData = null; }, - showAcceptDenyModal(value) { this.modalData = value; if (!this.modalData) { @@ -364,7 +370,6 @@ export default { this.$refs.AcceptDenyModal.show(); }); }, - updateData: function (event) { this.$refs.UpdatesTable.tabulator.setData(); //? store the selected view in the session storage of the browser @@ -415,22 +420,30 @@ export default { }, template: /*html*/ `
- - -
-
{{$p.t('ui','anzeigen')}}
- - - -
- - - + +

{{$p.t('profilUpdate', 'profilUpdateRequests')}}

+ -
`, + + + + + `, }; diff --git a/public/js/components/Studierendenantrag/Form/AbmeldungStgl.js b/public/js/components/Studierendenantrag/Form/AbmeldungStgl.js index 81106e64c..332c2a16a 100644 --- a/public/js/components/Studierendenantrag/Form/AbmeldungStgl.js +++ b/public/js/components/Studierendenantrag/Form/AbmeldungStgl.js @@ -192,7 +192,15 @@ export default { + + + + +