diff --git a/application/config/stv.php b/application/config/stv.php index 42afc318c..e03c00084 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -63,7 +63,7 @@ $config['tabs'] = 'showCountNotes' => true ] ]; - + // List of fields to show when ZGV_DOKTOR_ANZEIGEN is defined $fieldsZgvDoktor = ['zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', 'zgvdoktor_erfuellt', 'zgvdoktor_code']; @@ -84,6 +84,11 @@ 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']['defaultProjektbetreuerStundensatz'] = '80.0'; + $config['student_tab_order'] = [ 'details', 'notes', @@ -97,6 +102,7 @@ $config['student_tab_order'] = [ 'grades', 'exam', 'exemptions', + 'projektarbeit', 'finalexam', 'mobility', 'jointstudies', diff --git a/application/controllers/api/frontend/v1/stv/Archiv.php b/application/controllers/api/frontend/v1/stv/Archiv.php index cc636951d..55f4270d6 100644 --- a/application/controllers/api/frontend/v1/stv/Archiv.php +++ b/application/controllers/api/frontend/v1/stv/Archiv.php @@ -107,13 +107,9 @@ class Archiv extends FHCAPI_Controller $result = $this->AkteModel->load($akte_id); - if (!hasData($result)) $this->terminateWithError('Akte not found'); - $data = $this->getDataOrTerminateWithError($result); - $data = getData($result)[0]; - //$this->addMeta("daa", $data->inhalt); $fileObj = new stdClass(); if (isset($data->inhalt) && $data->inhalt != '') @@ -133,12 +129,7 @@ class Archiv extends FHCAPI_Controller //header("Content-type: $data->mimetype"); header('Content-Disposition: attachment; filename="'.$data->titel.'"'); readfile($filename); - //echo base64_decode($data->inhalt); die(); - //~ $fileObj->file = $data->inhalt; - //~ $fileObj->name = $data->titel; - //~ $fileObj->mimetype = $data->mimetype; - //~ $fileObj->disposition = 'attachment'; } else { @@ -146,12 +137,6 @@ class Archiv extends FHCAPI_Controller $result = $this->aktelib->get($akte_id); } - - /* $fileObj->filename - * $fileObj->file - * $fileObj->name - * $fileObj->mimetype - * $fileObj->disposition*/ } /** diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index d52016943..9a2e49fe4 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -45,7 +45,8 @@ class Config extends FHCAPI_Controller 'lehre', 'stv', 'konto', - 'abschlusspruefung' + 'abschlusspruefung', + 'projektarbeit' ]); // Load Config @@ -147,6 +148,16 @@ class Config extends FHCAPI_Controller 'config' => $config['finalexam'] ]; + $result['projektarbeit'] = [ + 'title' => $this->p->t('stv', 'tab_projektarbeit'), + 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js', + 'config' => array_merge( + $config['projektarbeit'], + ['showVertragsdetails' => + defined('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN') && FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN] + ) + ]; + $result['mobility'] = [ 'title' => $this->p->t('stv', 'tab_mobility'), 'component' => './Stv/Studentenverwaltung/Details/Mobility.js' diff --git a/application/controllers/api/frontend/v1/stv/Kontakt.php b/application/controllers/api/frontend/v1/stv/Kontakt.php index 3a8268775..d246a04d9 100644 --- a/application/controllers/api/frontend/v1/stv/Kontakt.php +++ b/application/controllers/api/frontend/v1/stv/Kontakt.php @@ -52,6 +52,7 @@ class Kontakt extends FHCAPI_Controller // Extra Permissionchecks $permsMa = []; $permsStud = []; + $permsDefault = null; switch ($this->router->method) { case 'getBankverbindung': case 'loadBankverbindung': @@ -68,7 +69,7 @@ class Kontakt extends FHCAPI_Controller case 'getKontakte': case 'loadAddress': case 'loadContact': - $permsMa = $permsStud = ['admin:r', 'assistenz:r']; + $permsMa = $permsStud = $permsDefault = ['admin:r', 'assistenz:r']; break; case 'addNewAddress': case 'addNewContact': @@ -76,7 +77,7 @@ class Kontakt extends FHCAPI_Controller case 'updateContact': case 'deleteAddress': case 'deleteContact': - $permsMa = $permsStud = ['admin:rw', 'assistenz:rw']; + $permsMa = $permsStud = $permsDefault = ['admin:rw', 'assistenz:rw']; break; } if ($this->router->method == 'getAdressen' @@ -91,7 +92,7 @@ class Kontakt extends FHCAPI_Controller if (is_null($person_id) || !ctype_digit((string)$person_id)) $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); - $this->checkPermissionsForPerson($person_id, $permsMa, $permsStud); + $this->checkPermissionsForPerson($person_id, $permsMa, $permsStud, $permsDefault); } elseif ($this->router->method == 'loadAddress' || $this->router->method == 'loadContact' || $this->router->method == 'loadBankverbindung' @@ -135,7 +136,7 @@ class Kontakt extends FHCAPI_Controller $person_id = current($data)->person_id; - $this->checkPermissionsForPerson($person_id, $permsMa, $permsStud); + $this->checkPermissionsForPerson($person_id, $permsMa, $permsStud, $permsDefault); } } public function getAdressen($person_id) diff --git a/application/controllers/api/frontend/v1/stv/Projektarbeit.php b/application/controllers/api/frontend/v1/stv/Projektarbeit.php new file mode 100644 index 000000000..75478332f --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Projektarbeit.php @@ -0,0 +1,368 @@ + ['admin:r', 'assistenz:r'], + 'loadProjektarbeit' => ['admin:r', 'assistenz:r'], + 'insertProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'updateProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'deleteProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'], + 'getFirmen' => ['admin:r', 'assistenz:r'], + 'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'], + 'getNoten' => ['admin:r', 'assistenz:r'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->load->model('education/Projekttyp_model', 'ProjekttypModel'); + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $this->load->model('ressource/Firma_model', 'FirmaModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('education/Note_model', 'NoteModel'); + $this->load->model('education/Projektbetreuer_model', 'BetreuerModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getProjektarbeit() + { + $student_uid = $this->input->get('uid'); + + if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektarbeitModel->getProjektarbeit($student_uid); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $projektarbeiten = getData($result); + + foreach ($projektarbeiten as $projektarbeit) + { + $projektarbeit_id = $projektarbeit->projektarbeit_id; + $abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id); + + if (isError($abgabeRes)) $this->terminateWithError(getError($abgabeRes), self::ERROR_TYPE_GENERAL); + + if (hasData($abgabeRes)) + { + $paabgabe = getData($abgabeRes)[0]; + $projektarbeit->abgabedatum = $paabgabe->abgabedatum; + } + } + + $this->terminateWithSuccess($projektarbeiten); + } + + public function loadProjektarbeit() + { + $projektarbeit_id = $this->input->get('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) return $this->terminateWithError('Projektarbeit Id missing', self::ERROR_TYPE_GENERAL); + + $this->ProjektarbeitModel->addSelect( + 'lehre.tbl_projektarbeit.projektarbeit_id, titel, titel_english, themenbereich, projekttyp_kurzbz, lehrveranstaltung_id, lehreinheit_id, + firma_id, beginn, ende, gesperrtbis, note, final, freigegeben, tbl_projektarbeit.anmerkung, fa.name AS firma_name' + ); + $this->ProjektarbeitModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->ProjektarbeitModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id', 'LEFT'); + $result = $this->ProjektarbeitModel->loadWhere( + array('projektarbeit_id' => $projektarbeit_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function insertProjektarbeit() + { + $student_uid = $this->input->post('uid'); + + if (!$student_uid) return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + + if (!$this->_hasBerechtigungForStudent($student_uid)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $formData = $this->input->post('formData'); + + if ($this->_validate($formData) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $projektarbeit = $this->_getProjektarbeitArr($formData); + + $result = $this->ProjektarbeitModel->insert( + array_merge($projektarbeit, ['insertamum' => date('c'), 'insertvon' => getAuthUID(), 'student_uid' => $student_uid]) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function updateProjektarbeit() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!$projektarbeit_id || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $formData = $this->input->post('formData'); + + if ($this->_validate($formData) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $projektarbeit = $this->_getProjektarbeitArr($formData); + + $result = $this->ProjektarbeitModel->update( + $projektarbeit_id, + array_merge($projektarbeit, ['updateamum' => date('c'), 'updatevon' => getAuthUID()]) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteProjektarbeit() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID'], self::ERROR_TYPE_GENERAL)); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $validate = $this->_validateDelete($projektarbeit_id); + + if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektarbeitModel->delete( + ['projektarbeit_id' => $projektarbeit_id] + ); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) + { + $this->outputJson($result); + } + + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function getTypenProjektarbeit() + { + $result = $this->ProjekttypModel->loadWhere(['aktiv' => true]); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getFirmen() + { + $searchString = $this->input->get('searchString'); + + if (!isset($searchString)) + $this->terminateWithError($this->p->t('ui', 'error_fieldRequired', ['field' => 'Search term']), self::ERROR_TYPE_GENERAL); + + $result = $this->FirmaModel->searchFirmen($searchString, $aktiv = true); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getLehrveranstaltungen() + { + $student_uid = $this->input->get('student_uid'); + $studiengang_kz = $this->input->get('studiengang_kz'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + $additional_lehrveranstaltung_id = $this->input->get('additional_lehrveranstaltung_id'); + + 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); + + $lvsResult = $this->LehrveranstaltungModel->getLvsForProjektarbeit($student_uid, $studiengang_kz, $additional_lehrveranstaltung_id); + + if (isError($lvsResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL); + + $lvs = hasData($lvsResult) ? getData($lvsResult) : []; + + foreach ($lvs as $lv) + { + $lehreinheiten = $this->LehreinheitModel->getLesForLv( + $lv->lehrveranstaltung_id, $studiensemester_kurzbz + ); + + foreach ($lehreinheiten as $lehreinheit) + { + if (!isEmptyArray($lehreinheit->lektoren)) + { + $this->MitarbeiterModel->addSelect('kurzbz'); + $this->MitarbeiterModel->db->where_in('tbl_mitarbeiter.mitarbeiter_uid', $lehreinheit->lektoren); + $maResult = $this->MitarbeiterModel->load(); + + if (isError($maResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL); + + $lehreinheit->lektoren = array_column(getData($maResult), 'kurzbz'); + } + } + + $lv->lehreinheiten = $lehreinheiten; + } + + return $this->terminateWithSuccess($lvs); + } + + public function getNoten() + { + $result = $this->NoteModel->load(); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + /** + * + * @param + * @return object success or error + */ + private function _validate($formData) + { + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('titel', 'Titel', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel']) + ]); + + $this->form_validation->set_rules('projekttyp_kurzbz', 'Projekttyp', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Projekttyp']) + ]); + + $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|is_natural', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), + 'is_natural' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) + ]); + + $this->form_validation->set_rules('beginn', 'Beginn', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Beginn']) + ]); + + $this->form_validation->set_rules('ende', 'Ende', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Ende']) + ]); + + $this->form_validation->set_rules('gesperrtbis', 'Ende', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Gesperrt bis']) + ]); + + return $this->form_validation->run(); + } + + /** + * + * @param + * @return object success or error + */ + private function _getProjektarbeitArr($formData) + { + return [ + 'titel' => $formData['titel'], + 'titel_english' => $formData['titel_english'] ?? null, + 'themenbereich' => $formData['themenbereich'] ?? null, + 'projekttyp_kurzbz' => $formData['projekttyp_kurzbz'], + 'firma_id' => $formData['firma_id'] ?? null, + 'lehreinheit_id' => $formData['lehreinheit_id'], + 'beginn' => isset($formData['beginn']) && !isEmptyString($formData['beginn']) ? $formData['beginn'] : null, + 'ende' => isset($formData['ende']) && !isEmptyString($formData['ende']) ? $formData['ende'] : null, + 'note' => $formData['note'] ?? null, + 'final' => $formData['final'] ?? null, + 'freigegeben' => $formData['freigegeben'] ?? null, + 'anmerkung' => $formData['anmerkung'] ?? null, + 'gesperrtbis' => isset($formData['gesperrtbis']) && !isEmptyString($formData['gesperrtbis']) ? $formData['gesperrtbis'] : null + ]; + } + + /** + * + * @param + * @return object success or error + */ + private function _validateDelete($projektarbeit_id) + { + $this->BetreuerModel->addSelect('1'); + $result = $this->BetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + + if (isError($result)) return $result; + + if (hasData($result)) return error($this->p->t('projektarbeit', 'error_betreuerNichtGeloescht')); + + $this->PaabgabeModel->addSelect('1'); + $result = $this->PaabgabeModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + + if (isError($result)) return $result; + + if (hasData($result)) return error($this->p->t('projektarbeit', 'error_paabgabeNichtGeloescht')); + + return success(); + } + + private function _hasBerechtigungForStudent($student_uid) + { + if (!$student_uid) + return false; + + $this->load->model('crm/Student_model', 'StudentModel'); + + $this->StudentModel->addSelect('studiengang_kz'); + $result = $this->StudentModel->load([$student_uid]); + if (isError($result) || !hasData($result)) + return false; + + $studiengang_kz = getData($result)[0]->studiengang_kz; + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz)) + return true; + + return false; + } +} diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php new file mode 100644 index 000000000..98567ecde --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -0,0 +1,341 @@ + ['admin:r', 'assistenz:r'], + 'saveProjektbetreuer' => ['admin:rw', 'assistenz:rw'], + 'deleteProjektbetreuer' => ['admin:rw', 'assistenz:rw'], + 'getBetreuerarten' => ['admin:r', 'assistenz:r'], + 'getNoten' => ['admin:r', 'assistenz:r'], + 'getDefaultStundensaetze' => ['admin:r', 'assistenz:r'], + 'getProjektbetreuerBySearchQuery' => ['admin:r', 'assistenz:r'], + 'getPerson' => ['admin:r', 'assistenz:r'], + 'validateProjektbetreuer' => ['admin:r', 'assistenz:r'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); + $this->load->model('education/Betreuerart_model', 'BetreuerartModel'); + $this->load->model('ressource/Stundensatz_model', 'StundensatzModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->load->model('education/Note_model', 'NoteModel'); + $this->load->model('person/Person_model', 'PersonModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getProjektbetreuer() + { + $projektarbeit_id = $this->input->get('projektarbeit_id'); + + 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]); + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $projektbetreuer = getData($result); + + //~ foreach ($projektbetreuer as $projektarbeit) + //~ { + //~ $projektarbeit_id = $projektarbeit->projektarbeit_id; + //~ $abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id); + + //~ if (isError($abgabeRes)) $this->terminateWithError(getError($abgabeRes), self::ERROR_TYPE_GENERAL); + + //~ if (hasData($abgabeRes)) + //~ { + //~ $paabgabe = getData($abgabeRes)[0]; + //~ $projektarbeit->abgabedatum = $paabgabe->abgabedatum; + //~ } + //~ } + + foreach ($projektbetreuer as $pb) + { + $downloadLink = null; + Events::trigger( + 'projektbeurteilung_download_link', + $pb->projektarbeit_id, + $pb->betreuerart_kurzbz, + $pb->person_id, + function ($value) use (&$downloadLink) { + $downloadLink = $value; + } + ); + $pb->beurteilungDownloadLink = $downloadLink; + } + + $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); + } + + public function saveProjektbetreuer() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $projektbetreuer = $this->input->post('projektbetreuer'); + + if ($this->_validate($projektbetreuer) == false) $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = null; + + $betreuer = [ + 'projektarbeit_id' => $projektarbeit_id, + 'person_id' => $projektbetreuer['person_id'], + 'note' => $projektbetreuer['note'], + 'stunden' => $projektbetreuer['stunden'], + 'stundensatz' => $projektbetreuer['stundensatz'], + 'betreuerart_kurzbz' => $projektbetreuer['betreuerart_kurzbz'] + ]; + + if (isset($projektbetreuer['person_id_old']) && isset($projektbetreuer['betreuerart_kurzbz_old'])) + { + $result = $this->ProjektbetreuerModel->update( + [ + 'projektarbeit_id' => $projektarbeit_id, + 'person_id' => $projektbetreuer['person_id_old'], + 'betreuerart_kurzbz' => $projektbetreuer['betreuerart_kurzbz_old'] + ], + array_merge($betreuer, ['updateamum' => date('c'), 'updatevon' => getAuthUID()]) + ); + } + else + { + $result = $this->ProjektbetreuerModel->insert( + array_merge($betreuer, ['insertamum' => date('c'), 'insertvon' => getAuthUID()]) + ); + } + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function deleteProjektbetreuer() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + $person_id = $this->input->post('person_id'); + $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)); + + 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)); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $validate = $this->_validateDelete($projektarbeit_id, $person_id); + + if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektbetreuerModel->delete( + ['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id, 'betreuerart_kurzbz' => $betreuerart_kurzbz] + ); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) + { + $this->outputJson($result); + } + + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function getBetreuerarten() + { + $result = $this->BetreuerartModel->loadWhere(['aktiv' => true]); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getNoten() + { + $result = $this->NoteModel->load(); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getDefaultStundensaetze() + { + $person_id = $this->input->get('person_id'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + + $result = $this->StundensatzModel->getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz); + + return $this->terminateWithSuccess($result); + } + + public function getProjektbetreuerBySearchQuery() + { + $searchString = $this->input->get('searchString'); + + if (!isset($searchString)) + $this->terminateWithError($this->p->t('ui', 'error_fieldRequired', ['field' => 'Search term']), self::ERROR_TYPE_GENERAL); + + $result = $this->PersonModel->searchPerson($searchString); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? $this->_addFullNameToBetreuer(getData($result)) : []); + } + + public function getPerson() + { + $person_id = $this->input->get('person_id'); + + if (!isset($person_id)) + $this->terminateWithError($this->p->t('ui', 'error_fieldRequired', ['field' => 'Person']), self::ERROR_TYPE_GENERAL); + + $this->PersonModel->addSelect("CASE + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=tbl_person.person_id) + THEN 'Mitarbeiter' + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=tbl_person.person_id) + THEN 'Student' + ELSE 'Person' + END AS status"); + $result = $this->PersonModel->addSelect('titelpre, titelpost, vorname, nachname, person_id'); + $result = $this->PersonModel->load($person_id); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? $this->_addFullNameToBetreuer(getData($result))[0] : []); + } + + /** + * + * @param + * @return object success or error + */ + public function validateProjektbetreuer() + { + $projektbetreuerArr = $this->input->post('projektbetreuer'); + + if (!is_array($projektbetreuerArr)) $projektbetreuerArr = [$projektbetreuerArr]; + + foreach ($projektbetreuerArr as $pb) + { + if ($this->_validate($pb) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + } + + $this->terminateWithSuccess([]); + } + + /** + * + * @param + * @return object success or error + */ + private function _validate($formData) + { + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('betreuerart_kurzbz', 'Betreuerart', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('projektarbeit', 'betreuerart')]) + ]); + + $this->form_validation->set_rules('person_id', 'Person', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('projektarbeit', 'betreuer')]) + ]); + + $this->form_validation->set_rules('stunden', 'Stunden', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => $this->p->t('projektarbeit', 'stunden')]) + ]); + + $this->form_validation->set_rules('stundensatz', 'Stundensatz', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => $this->p->t('projektarbeit', 'stundensatz')]) + ]); + + + return $this->form_validation->run(); + } + + /** + * + * @param + * @return object success or error + */ + private function _validateDelete($projektarbeit_id, $person_id) + { + $this->ProjektbetreuerModel->addSelect('vertrag_id'); + $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id]); + + if (isError($result)) return $result; + + 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 + */ + private function _addFullNameToBetreuer($betreuerArr) + { + foreach ($betreuerArr as $betreuer) + { + $betreuer->name = ($betreuer->titelpre ? $betreuer->titelpre . ' ' : '') . + $betreuer->nachname . ' ' . $betreuer->vorname . ($betreuer->titelpost ? ' ' . $betreuer->titelpre : ''). + ' (' . $betreuer->status . ')'; + } + + return $betreuerArr; + } +} diff --git a/application/controllers/api/frontend/v1/stv/Student.php b/application/controllers/api/frontend/v1/stv/Student.php index f2845572f..52fb94ce1 100644 --- a/application/controllers/api/frontend/v1/stv/Student.php +++ b/application/controllers/api/frontend/v1/stv/Student.php @@ -55,7 +55,7 @@ class Student extends FHCAPI_Controller // Load language phrases $this->loadPhrases([ - 'ui', 'lehre' + 'ui', 'lehre', 'person' ]); } @@ -465,7 +465,6 @@ class Student extends FHCAPI_Controller 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; @@ -474,31 +473,37 @@ class Student extends FHCAPI_Controller $this->load->library('form_validation'); $this->form_validation->set_rules('nachname', 'Nachname', 'callback_requiredIfNotPersonId', [ - 'requiredIfNotPersonId' => $this->p->t('ui', 'error_required') + 'requiredIfNotPersonId' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('person', 'nachname')]) ]); $this->form_validation->set_rules('geschlecht', 'Geschlecht', 'callback_requiredIfNotPersonId', [ - 'requiredIfNotPersonId' => $this->p->t('ui', 'error_required') + 'requiredIfNotPersonId' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('person', 'geschlecht')]) ]); - $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'callback_isValidDate', [ + $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', ['isValidDate', function($value) { return isValidDate($value); }], [ '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') + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('person', 'plz')]) ]); $this->form_validation->set_rules('address[gemeinde]', 'Gemeinde', 'callback_requiredIfAddressFunc', [ - 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('person', 'gemeinde')]) ]); $this->form_validation->set_rules('address[ort]', 'Ort', 'callback_requiredIfAddressFunc', [ - 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('person', 'ort')]) ]); $this->form_validation->set_rules('address[address]', 'Adresse', 'callback_requiredIfAddressFunc', [ - 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('person', 'adresse')]) ]); $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]'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'callback_requiredIfStudentFunc', [ + 'requiredIfStudentFunc' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'studiengang')]) + ]); + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'callback_requiredIfStudentFunc', [ + 'requiredIfStudentFunc' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'studiensemester')]) + ]); + $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'callback_requiredIfStudentFunc|integer|less_than[9]|greater_than[-1]', [ + 'requiredIfStudentFunc' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'ausbildungssemester')]) + ]); // TODO(chris): validate studienplan with studiengang, semester and orgform? // TODO(chris): validate person_id, studiengang_kz, studiensemester_kurzbz, orgform_kurzbz, nation, gemeinde, ort, geschlecht? @@ -518,7 +523,9 @@ class Student extends FHCAPI_Controller if ($this->db->trans_status() === FALSE) $this->terminateWithError('TODO(chris): TEXT', self::ERROR_TYPE_GENERAL); - $this->terminateWithSuccess($result); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); } protected function addInteressent() @@ -575,6 +582,8 @@ class Student extends FHCAPI_Controller 'zustelladresse' => true, ]; if ($anlegen < 0) { // Überschreiben + $this->AdresseModel->addSelect('adresse_id'); + $this->AdresseModel->addJoin('public.tbl_adressentyp', 'typ = adressentyp_kurzbz'); $this->AdresseModel->addOrder('zustelladresse', 'DESC'); $this->AdresseModel->addOrder('sort'); $result = $this->AdresseModel->loadWhere([ @@ -631,70 +640,74 @@ class Student extends FHCAPI_Controller } } - // 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; + $personOnly = $anlegen = $this->input->post('personOnly'); - $data['zgvmas_code'] = $prestudent->zgvmas_code; - $data['zgvmaort'] = $prestudent->zgvmaort; - $data['zgvmadatum'] = $prestudent->zgvmadatum; + if (!$personOnly) + { + // 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 } } - // 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 @@ -703,7 +716,7 @@ class Student extends FHCAPI_Controller return $result; }*/ - return success(true); + return success($person_id); } public function requiredIfNotPersonId($value) @@ -715,7 +728,14 @@ class Student extends FHCAPI_Controller public function requiredIfAddressFunc($value) { - if (!$_POST['address']['func']) + if (!$_POST['address']['func'] || $_POST['address']['func'] == 0) + return true; + return !!$value; + } + + public function requiredIfStudentFunc($value) + { + if ($_POST['personOnly']) return true; return !!$value; } diff --git a/application/controllers/api/frontend/v1/stv/Vertrag.php b/application/controllers/api/frontend/v1/stv/Vertrag.php new file mode 100644 index 000000000..f94fe795e --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Vertrag.php @@ -0,0 +1,104 @@ + ['admin:r', 'assistenz:r'], + 'cancelVertrag' => ['admin:r', 'assistenz:r'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('accounting/Vertrag_model', 'VertragModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getVertrag() + { + $vertrag_id = $this->input->get('vertrag_id'); + + if (!isset($vertrag_id) || !is_numeric($vertrag_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Vertrag ID']), self::ERROR_TYPE_GENERAL); + + $result = $this->VertragModel->getVertragById($vertrag_id); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $vertrag = getData($result)[0]; + + $this->terminateWithSuccess($vertrag); + } + + public function cancelVertrag() + { + $vertrag_id = $this->input->post('vertrag_id'); + $person_id = $this->input->post('person_id'); + + if (!isset($vertrag_id) || !is_numeric($vertrag_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Vertrag ID']), self::ERROR_TYPE_GENERAL); + if (!isset($person_id) || !is_numeric($person_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL); + + // * first find lehrveranstaltung_id of the contracts lehrveranstaltung + $this->VertragModel->addSelect('lehrveranstaltung_id'); + $this->VertragModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id', 'LEFT'); + $result = $this->VertragModel->loadWhere(['vertrag_id' => $vertrag_id]); + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $lehrveranstaltung_id = getData($result)[0]->lehrveranstaltung_id; + + $allOe = $this->LehrveranstaltungModel->getAllOe($lehrveranstaltung_id); + + if (isError($allOe)) $this->terminateWithError(getError($allOe), self::ERROR_TYPE_GENERAL); + + $allOe = hasData($allOe) ? getData($allOe) : []; + + $this->addMeta('oe', $allOe); + + // * then check if the user has permissions to cancel the corresponding lv-organisational units + if (!$this->permissionlib->isBerechtigtMultipleOe('admin', $allOe, 'suid') && + !$this->permissionlib->isBerechtigtMultipleOe('lehre/lehrauftrag_bestellen', $allOe, 'suid')) + { + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'lehrauftrag_bestellen:rw']]); + } + + $uidResult = $this->BenutzerModel->getFromPersonId($person_id); + + if (isError($uidResult)) $this->terminateWithError(getError($uidResult), self::ERROR_TYPE_GENERAL); + + if (!hasData($uidResult)) $this->terminateWithError("no user found", self::ERROR_TYPE_GENERAL); + + $mitarbeiter_uid = getData($uidResult)[0]->uid; + + $result = $this->VertragModel->cancelVertrag($vertrag_id, $mitarbeiter_uid); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} diff --git a/application/core/Auth_Controller.php b/application/core/Auth_Controller.php index 466627fe3..d6c89be57 100644 --- a/application/core/Auth_Controller.php +++ b/application/core/Auth_Controller.php @@ -70,20 +70,22 @@ abstract class Auth_Controller extends FHC_Controller /** * Checks for Permissions depending if the given person is a * Mitarbeiter and/or Student + * If neither Student nor Mitarbeiter, default permissions are checked * 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 + * @param array $permDefault Perms if the person is neither a Student nor a Mitarbeiter * * @return void */ - protected function checkPermissionsForPerson($person_id, $permMa, $permStud) + protected function checkPermissionsForPerson($person_id, $permMa, $permStud, $permDefault = null) { - $res = $this->hasPermissionsForPerson($person_id, $permMa, $permStud); - + $res = $this->hasPermissionsForPerson($person_id, $permMa, $permStud, $permDefault); + if ($res) { - $perm = array_keys(array_flip(array_merge($res|1 ? $permMa : [], $res|2 ? $permStud : []))); + $perm = array_keys(array_flip(array_merge($res&1 ? $permMa : [], $res&2 ? $permStud : [], $res&4 ? $permDefault : []))); $this->_outputAuthError([$this->router->method => $perm]); } } @@ -108,16 +110,19 @@ abstract class Auth_Controller extends FHC_Controller * Checks for Permissions depending if the given person is a * Mitarbeiter and/or Student * and returns the result. - * + * If neither Student nor Mitarbeiter, default permissions are checked + * * @param integer $person_id * @param array $permMa Perms if the person is a Mitarbeiter * @param array $permStud Perms if the person is a Student - * + * @param array $permDefault Perms if the person is neither a Student nor a Mitarbeiter * @return integer 0 if permission is granted */ - protected function hasPermissionsForPerson($person_id, $permMa, $permStud) + protected function hasPermissionsForPerson($person_id, $permMa, $permStud, $permDefault) { - $res = 3; + $res = 8; + $isMitarbeiter = false; + $isStudent = false; $this->load->model('person/Person_model', 'PersonModel'); $this->PersonModel->addJoin('public.tbl_benutzer', 'person_id'); $this->PersonModel->addJoin('public.tbl_mitarbeiter', 'uid = mitarbeiter_uid'); @@ -125,7 +130,8 @@ abstract class Auth_Controller extends FHC_Controller if (hasData($result)) { if ($this->permissionlib->isEntitled(['a' => $permMa], 'a')) return 0; - $res = 1; + $isMitarbeiter = true; + $res += 1; } $this->PersonModel->addJoin('public.tbl_prestudent', 'person_id'); $result = $this->PersonModel->load($person_id); @@ -140,8 +146,15 @@ abstract class Auth_Controller extends FHC_Controller return 0; } } + $isStudent = true; $res += 2; } + if (isset($permDefault) && !$isMitarbeiter && !$isStudent) + { + if ($this->permissionlib->isEntitled(['a' => $permDefault], 'a')) + return 0; + $res += 4; + } return $res; } diff --git a/application/models/accounting/Vertrag_model.php b/application/models/accounting/Vertrag_model.php index c17c676c7..4c036369b 100644 --- a/application/models/accounting/Vertrag_model.php +++ b/application/models/accounting/Vertrag_model.php @@ -402,6 +402,26 @@ class Vertrag_model extends DB_Model return $this->loadWhere(array('mitarbeiter_uid' => $mitarbeiter_uid, 'lehreinheit_id' => $lehreinheit_id)); } + public function getVertragById($vertrag_id) + { + $this->addSelect( + 'tbl_vertrag.vertrag_id, vertragstyp_kurzbz, vertragsstunden, vertragsstunden_studiensemester_kurzbz, status.vertragsstatus_kurzbz, + status.bezeichnung AS vertragsstatus, tbl_vertrag.betrag, lema.semesterstunden, lema.stundensatz' + ); + $this->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_vertrag.vertrag_id = lema.vertrag_id', 'LEFT'); + $this->addJoin(' + ( + SELECT DISTINCT ON(vst.vertrag_id) vst.vertrag_id, + bezeichnung, + tbl_vertragsstatus.vertragsstatus_kurzbz + FROM lehre.tbl_vertrag_vertragsstatus vst + JOIN lehre.tbl_vertragsstatus USING(vertragsstatus_kurzbz) + ORDER BY vst.vertrag_id, datum DESC + ) as status', 'status.vertrag_id = lehre.tbl_vertrag.vertrag_id', 'LEFT'); + + return $this->loadWhere(['tbl_vertrag.vertrag_id' => $vertrag_id]); + } + public function cancelVertrag($vertrag_id, $mitarbeiter_uid) { $vertrag = $this->load($vertrag_id); diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 1b3b9e9d7..7347cf2ca 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -1255,4 +1255,61 @@ class Lehrveranstaltung_model extends DB_Model return $this->execReadOnlyQuery($qry, $params); } + + /** + * Gets Lehrveranstaltungen for a student, as needed for a Projektarbeit. + * @param student_uid + * @param studiengang_kz optional, all Lvs of this Studiengang will be included + * @param additional_lehrveranstaltung_id optional, this lv will be added to result + * @return object success or error + */ + public function getLvsForProjektarbeit($student_uid, $studiengang_kz = null, $additional_lehrveranstaltung_id = null) + { + $params = array($student_uid, $student_uid); + + $qry = " + SELECT * + FROM + lehre.tbl_lehrveranstaltung + WHERE + ( + lehrveranstaltung_id IN ( + + SELECT + lehrveranstaltung_id + FROM + campus.vw_student_lehrveranstaltung + WHERE + uid=? + + UNION + + SELECT + lehrveranstaltung_id + FROM + lehre.tbl_zeugnisnote + WHERE + student_uid=? + )"; + + if (isset($studiengang_kz)) + { + $params[] = $studiengang_kz; + $qry .= " OR (studiengang_kz = ? AND semester IS NOT NULL)"; + } + + if (isset($additional_lehrveranstaltung_id)) + { + $params[] = $additional_lehrveranstaltung_id; + $qry .= " OR lehrveranstaltung_id = ?"; + } + + $qry .= " + ) + AND projektarbeit = TRUE + ORDER BY + semester, bezeichnung"; + + return $this->execQuery($qry, $params); + } } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 4083dbf6e..1ca2a18a8 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -24,15 +24,16 @@ 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 + tbl_projektarbeit.*, tbl_projekttyp.bezeichnung, + tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.lehrveranstaltung_id, + tbl_firma.name AS firma_name FROM lehre.tbl_projektarbeit - JOIN - lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung - + 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.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND - tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND tbl_projektarbeit.student_uid = ?"; $params = array($student_uid); @@ -261,4 +262,30 @@ class Projektarbeit_model extends DB_Model return $this->execReadOnlyQuery($qry, array($projektarbeit_id)); } + + /** + * + * @param + * @return object success or error + */ + public function hasBerechtigungForProjektarbeit($projektarbeit_id) + { + if (!$projektarbeit_id || !is_numeric($projektarbeit_id)) + return false; + + $this->ProjektarbeitModel->addSelect('studiengang_kz'); + $this->ProjektarbeitModel->addJoin('public.tbl_student', 'student_uid'); + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + if (isError($result) || !hasData($result)) + return false; + + $studiengang_kz = getData($result)[0]->studiengang_kz; + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz)) + return true; + + return false; + } } diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index 95950bf95..02368ae21 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -10,6 +10,7 @@ class Projektbetreuer_model extends DB_Model parent::__construct(); $this->dbTable = 'lehre.tbl_projektbetreuer'; $this->pk = array('betreuerart_kurzbz', 'projektarbeit_id', 'person_id'); + $this->hasSequence = false; } /** diff --git a/application/models/organisation/Studienplan_model.php b/application/models/organisation/Studienplan_model.php index 481a0564c..4a5f87832 100644 --- a/application/models/organisation/Studienplan_model.php +++ b/application/models/organisation/Studienplan_model.php @@ -157,7 +157,6 @@ class Studienplan_model extends DB_Model return $this->execReadOnlyQuery($qry, array($lv_id)); } - public function getStudienplaeneForPerson($person_id) { $this->addDistinct(); diff --git a/application/models/person/Notiz_model.php b/application/models/person/Notiz_model.php index bc4494f57..64fce8944 100644 --- a/application/models/person/Notiz_model.php +++ b/application/models/person/Notiz_model.php @@ -207,7 +207,6 @@ class Notiz_model extends DB_Model "; return $this->execQuery($qry, array($type, $id)); - } diff --git a/application/models/person/Person_model.php b/application/models/person/Person_model.php index 3947378cf..233cfc751 100644 --- a/application/models/person/Person_model.php +++ b/application/models/person/Person_model.php @@ -151,12 +151,21 @@ class Person_model extends DB_Model */ public function searchPerson($filter) { - $this->addSelect('vorname, nachname, gebdatum, person_id'); + $this->addSelect('vorname, nachname, gebdatum, person_id, titelpre, titelpost'); + $this->addSelect("CASE + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=tbl_person.person_id) + THEN 'Mitarbeiter' + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=tbl_person.person_id) + THEN 'Student' + ELSE 'Person' + END AS status"); $result = $this->loadWhere( - 'lower(nachname) like '.$this->db->escape('%'.$filter.'%')." + 'lower(nachname) like '.$this->db->escape('%'.mb_strtolower($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(nachname || ' ' || vorname) like ".$this->db->escape('%'.mb_strtolower($filter).'%')." + OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.mb_strtolower($filter).'%') ); return $result; @@ -411,4 +420,4 @@ class Person_model extends DB_Model return success($result); } } -} \ No newline at end of file +} diff --git a/application/models/ressource/Firma_model.php b/application/models/ressource/Firma_model.php index 431f0815f..5ae53eeaf 100644 --- a/application/models/ressource/Firma_model.php +++ b/application/models/ressource/Firma_model.php @@ -12,17 +12,24 @@ class Firma_model extends DB_Model $this->pk = 'firma_id'; } - public function searchFirmen($filter) + public function searchFirmen($filter, $aktiv = null) { + $params = []; $filter = strtoLower($filter); $qry = " - SELECT + SELECT f.name, f.firma_id - FROM - public.tbl_firma f - WHERE - lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'"; + FROM + public.tbl_firma f + WHERE + lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'"; - return $this->execQuery($qry); + if (isset($aktiv) && is_bool($aktiv)) + { + $params[] = $aktiv; + $qry .= " AND aktiv = ?"; + } + + return $this->execQuery($qry, $params); } } diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php index f34ad07ed..c8ee367d8 100644 --- a/application/models/ressource/Stundensatz_model.php +++ b/application/models/ressource/Stundensatz_model.php @@ -2,7 +2,7 @@ class Stundensatz_model extends DB_Model { - + /** * Constructor */ @@ -43,6 +43,97 @@ class Stundensatz_model extends DB_Model return $this->execQuery($qry, $params); } + public function getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz) + { + $this->load->config('stv'); + + $useFixangestelltStundensatz = $this->config->item('tabs')['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz']; + $defaultStundensatz = $this->config->item('tabs')['projektarbeit']['defaultProjektbetreuerStundensatz']; + + $stundensatz = ''; + + if(isset($person_id) && isset($studiensemester_kurzbz)) + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addSelect('start, ende'); + $result = $this->StudiensemesterModel->load($studiensemester_kurzbz); + + if (hasData($result)) + { + $studiensemester = getData($result)[0]; + + if (isset($useFixangestelltStundensatz) && !$useFixangestelltStundensatz) + { + // load Mitarbeiter + $params = [$person_id]; + $qry = " + SELECT + mitarbeiter_uid, fixangestellt + FROM + public.tbl_mitarbeiter + JOIN public.tbl_benutzer ON(tbl_benutzer.uid=tbl_mitarbeiter.mitarbeiter_uid) + WHERE + person_id=? + ORDER BY + tbl_mitarbeiter.insertamum DESC NULLS LAST + LIMIT 1"; + + $result = $this->execQuery($qry, $params); + + if (hasData($result)) + { + foreach (getData($result) as $ma) + { + if (!$ma->fixangestellt) + { + $stundensatzRes = $this->getStundensatzByDatum( + $ma->mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre' + ); + + if (hasData($stundensatzRes)) + $stundensatz = getData($stundensatzRes)[0]->stundensatz; + else + $stundensatz = '0.00'; + } + } + } + else + { + $stundensatz = '0.00'; + } + + } + else + { + $params = [$person_id, $studiensemester->ende, $studiensemester->start]; + $qry = "SELECT ss.stundensatz + FROM hr.tbl_stundensatz ss + JOIN public.tbl_mitarbeiter ON ss.uid = tbl_mitarbeiter.mitarbeiter_uid + JOIN public.tbl_benutzer ON(tbl_benutzer.uid=tbl_mitarbeiter.mitarbeiter_uid) + WHERE person_id=? + AND stundensatztyp = 'lehre' + AND gueltig_von <= ? + AND (gueltig_bis >= ? OR gueltig_bis IS NULL) + ORDER BY gueltig_bis DESC NULLS FIRST, gueltig_von DESC NULLS LAST LIMIT 1"; + + $result = $this->execQuery($qry, $params); + + if (hasData($result)) + { + $stundensatz = getData($result)[0]->stundensatz; + } + else + { + $stundensatz = $defaultStundensatz; + } + } + } + } + + return $stundensatz; + } + public function getDefaultStundensatz($mitarbeiter_uid, $beginn, $ende = null, $typ = null) { $stundensatz_result = $this->getStundensatzByDatum($mitarbeiter_uid, $beginn, $ende, $typ); @@ -58,4 +149,4 @@ class Stundensatz_model extends DB_Model } return $default_stundensatz; } -} \ No newline at end of file +} diff --git a/public/js/api/factory/stv/projektarbeit.js b/public/js/api/factory/stv/projektarbeit.js new file mode 100644 index 000000000..4412f1842 --- /dev/null +++ b/public/js/api/factory/stv/projektarbeit.js @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2025 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export default { + getProjektarbeit(uid) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getProjektarbeit', + params: { uid } + }; + }, + getTypenProjektarbeit() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getTypenProjektarbeit' + }; + }, + getFirmen(searchString) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getFirmen', + params: {searchString} + }; + }, + getLehrveranstaltungen(student_uid, studiengang_kz, studiensemester_kurzbz, additional_lehrveranstaltung_id) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getLehrveranstaltungen', + params: { student_uid, studiengang_kz, studiensemester_kurzbz, additional_lehrveranstaltung_id } + }; + }, + getNoten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getNoten' + }; + }, + loadProjektarbeit(projektarbeit_id) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/loadProjektarbeit', + params: { projektarbeit_id } + }; + }, + addNewProjektarbeit(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/insertProjektarbeit', + params + }; + }, + updateProjektarbeit(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/updateProjektarbeit', + params + }; + }, + deleteProjektarbeit(projektarbeit_id) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/deleteProjektarbeit', + params: { projektarbeit_id } + }; + } +}; diff --git a/public/js/api/factory/stv/projektbetreuer.js b/public/js/api/factory/stv/projektbetreuer.js new file mode 100644 index 000000000..4ea7bc782 --- /dev/null +++ b/public/js/api/factory/stv/projektbetreuer.js @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2025 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export default { + getProjektbetreuer(projektarbeit_id ) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getProjektbetreuer', + params: { projektarbeit_id } + }; + }, + getBetreuerarten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getBetreuerarten' + }; + }, + getDefaultStundensaetze(person_id, studiensemester_kurzbz) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getDefaultStundensaetze', + params: { person_id, studiensemester_kurzbz } + }; + }, + getNoten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getNoten' + }; + }, + saveProjektbetreuer(projektarbeit_id, projektbetreuer) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/saveProjektbetreuer', + params: { projektarbeit_id, projektbetreuer } + }; + }, + deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/deleteProjektbetreuer', + params: { projektarbeit_id, person_id, betreuerart_kurzbz } + }; + }, + getProjektbetreuerBySearchQuery(searchString) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getProjektbetreuerBySearchQuery', + params: { searchString } + }; + }, + getPerson(person_id) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getPerson', + params: { person_id } + }; + }, + validateProjektbetreuer(projektbetreuer) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/validateProjektbetreuer', + params: { projektbetreuer } + }; + } +}; diff --git a/public/js/api/factory/stv/students.js b/public/js/api/factory/stv/students.js index 18f3b1743..07d4453d8 100644 --- a/public/js/api/factory/stv/students.js +++ b/public/js/api/factory/stv/students.js @@ -58,5 +58,12 @@ export default { url: 'api/frontend/v1/stv/student/check', params }; + }, + add(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/student/add', + params + }; } -}; \ No newline at end of file +}; diff --git a/public/js/api/factory/stv/vertrag.js b/public/js/api/factory/stv/vertrag.js new file mode 100644 index 000000000..9070936da --- /dev/null +++ b/public/js/api/factory/stv/vertrag.js @@ -0,0 +1,20 @@ +export default { + + getVertrag(vertrag_id) + { + return { + method: 'get', + url: 'api/frontend/v1/stv/vertrag/getVertrag', + params: { vertrag_id }, + }; + }, + + cancelVertrag(data) + { + return { + method: 'post', + url: '/api/frontend/v1/stv/vertrag/cancelVertrag/', + params: data + }; + } +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js new file mode 100644 index 000000000..3615e8f5d --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js @@ -0,0 +1,24 @@ +import Projektarbeit from './Projektarbeit/Projektarbeit.js'; + +export default { + name: "TabProjektarbeit", + components: { + Projektarbeit + }, + provide() { + return { + config: this.config + }; + }, + props: { + modelValue: Object, + config: Object + }, + data(){ + return {} + }, + template: ` +
+ +
` +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js new file mode 100644 index 000000000..a51342c7c --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -0,0 +1,411 @@ +import FormForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; + +import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js'; + +export default { + components: { + FormForm, + FormInput, + PvAutoComplete + }, + emits: ['projekttypChanged'], + inject: { + defaultSemester: { + from: 'defaultSemester' + } + }, + computed: { + // prepared Lehreinheiten (with compound Bezeichnung) + arrLes() { + let lehreinheiten = []; + if (this.formData.lehrveranstaltung_id) { + let lv = this.arrLvs.find(lv => {return lv.lehrveranstaltung_id == this.formData.lehrveranstaltung_id}); + if (lv) lehreinheiten = lv.lehreinheiten + } + + for (let le of lehreinheiten) + { + let bezeichnung = le.lehrfach_kurzbz + '-' + le.lehrform_kurzbz + ' ' + le.lehrfach_bezeichnung + ' '; + + for (let grp of le.lehreinheitgruppen) + { + bezeichnung += grp.gruppe_kurzbz ? grp.gruppe_kurzbz : '' + grp.semester ?? '' + grp.verband ?? '' + grp.gruppe ?? ''; + } + + bezeichnung += ' (' + le.lektoren.join(' ') + ') ID: ' + le.lehreinheit_id; + + le.bezeichnung = bezeichnung; + } + + return lehreinheiten; + } + }, + props: { + statusNew: Boolean, + student: Object, + projektarbeit: Object + }, + data() { + return { + formData: { + projektarbeit_id: null, + titel: null, + titel_english: null, + themenbereich: null, + projekttyp_kurzbz: null, + firma: null, + lehrveranstaltung_id: null, + lehreinheit_id: null, + beginn: null, + ende: null, + freigegeben: true, + gesperrtbis: null, + note: null, + final: true, + anmerkung: null + }, + arrTypen: [], + arrFirmen: [], + arrLvs: [], + arrNoten: [], + filteredFirmen: [], + abortController: { + firma: null + } + } + }, + watch: { + 'formData.projekttyp_kurzbz'(newValue, oldValue) { + this.$emit('projekttypChanged', newValue); + } + }, + methods: { + resetForm() { + this.formData.projektarbeit_id = null; + this.formData.titel = null; + this.formData.titel_english = null; + this.formData.themenbereich = null; + this.formData.projekttyp_kurzbz = null; + this.formData.firma = null; + this.formData.lehrveranstaltung_id = null; + this.formData.lehreinheit_id = null; + this.formData.beginn = null; + this.formData.ende = null; + this.formData.freigegeben = true; + this.formData.gesperrtbis = null; + this.formData.note = null; + this.formData.final = true; + this.formData.anmerkung = null; + this.$refs.formDetails.clearValidation(); + }, + getFormData(statusNew, studiensemester_kurzbz, additional_lehrveranstaltung_id) { + + this.$api + .call(ApiStvProjektarbeit.getTypenProjektarbeit()) + .then(result => { + this.arrTypen = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvProjektarbeit.getLehrveranstaltungen( + this.student.uid, + statusNew ? this.student.studiengang_kz : null, + studiensemester_kurzbz ?? this.defaultSemester, + additional_lehrveranstaltung_id + )) + .then(result => { + this.arrLvs = result.data + } + ) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvProjektarbeit.getNoten()) + .then(result => { + this.arrNoten = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + if (statusNew) this.resetForm(); + }, + loadProjektarbeit(projektarbeit_id) { + + if (this?.formData?.projektarbeit_id == projektarbeit_id) return; + this.resetForm(); + return this.$api + .call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id)) + .then(result => { + this.formData = result.data; + if (this.formData.firma_id) this.formData.firma = {firma_id: this.formData.firma_id, name: this.formData.firma_name}; + return result; + }) + .catch(this.$fhcAlert.handleSystemError) + }, + addNewProjektarbeit() { + + let dataToSend = { + uid: this.student.uid, + formData: this.getPreparedFormData() + }; + + return this.$refs.formDetails + .call(ApiStvProjektarbeit.addNewProjektarbeit(dataToSend)); + }, + updateProjektarbeit() { + + let dataToSend = { + projektarbeit_id: this.formData.projektarbeit_id, + formData: this.getPreparedFormData() + }; + return this.$refs.formDetails + .call(ApiStvProjektarbeit.updateProjektarbeit(dataToSend)); + }, + searchFirma(event) { + if (this.abortController.firma) { + this.abortController.firma.abort(); + } + this.abortController.firma = new AbortController(); + + return this.$api + .call(ApiStvProjektarbeit.getFirmen(event.query)) + .then(result => { + this.filteredFirmen = result.data; + }); + }, + lvChanged(event) { + this.formData.lehreinheit_id = null; + }, + // enrich and modify data before sending + getPreparedFormData() { + let preparedFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy + + // set firma Id + if (preparedFormData.firma) + preparedFormData.firma_id = preparedFormData.firma.firma_id; + else + preparedFormData.firma_id = null; + + // delete "helper" fields + if (preparedFormData.projektarbeit_id == null) delete(preparedFormData.projektarbeit_id); + delete(preparedFormData.firma); + delete(preparedFormData.firma_name); + delete(preparedFormData.lehrveranstaltung_id); + + return preparedFormData; + } + }, + template: ` + + + Details +

[{{$p.t('ui', 'neu')}}]

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + +
+ + +
+ + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + +
+ + +
+
+ +
+ + + + +
+ + +
+
+ +
+ + +
+ +
` +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js new file mode 100644 index 000000000..d4f941e4b --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -0,0 +1,407 @@ +import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import BsModal from "../../../../Bootstrap/Modal.js"; +import FormForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; + +import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js'; +import ProjektarbeitDetails from "./Details.js"; +import Projektbetreuer from "./Projektbetreuer.js"; + +export default { + components: { + CoreFilterCmpt, + BsModal, + FormForm, + FormInput, + PvAutoComplete, + ProjektarbeitDetails, + Projektbetreuer + }, + inject: { + cisRoot: { + from: 'cisRoot' + }, + config: { + from: 'config', + required: true + }, + $reloadList: { + from: '$reloadList', + required: true + } + }, + props: { + student: Object + }, + data() { + return { + tabulatorEvents: [ + { + event: 'dataLoaded', + handler: data => this.tabulatorData = data.map(item => { + item.actionDiv = document.createElement('div'); + return item; + }), + }, + { + event: 'tableBuilt', + handler: async() => { + await this.$p.loadCategory(['global', 'person', 'stv', 'ui', 'projektarbeit']); + + let cm = this.$refs.table.tabulator.columnManager; + + cm.getColumnByField('projekttyp_kurzbz').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'typ') + }); + cm.getColumnByField('titel').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'titel') + }); + cm.getColumnByField('beginn').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'beginn') + }); + cm.getColumnByField('ende').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'ende') + }); + cm.getColumnByField('freigegeben').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'freigegeben') + }); + cm.getColumnByField('gesperrtbis').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'gesperrtBis') + }); + cm.getColumnByField('themenbereich').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'themenbereich') + }); + cm.getColumnByField('anmerkung').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'anmerkung') + }); + cm.getColumnByField('firma_id').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'firmaId') + }); + } + }, + ], + tabulatorData: [], + editedProjektarbeit: null, + statusNew: true, + studiensemester_kurzbz: null, + lehrveranstaltung_id: null, + activeTab: 'details' + } + }, + computed: { + tabulatorOptions() { + const options = { + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call(ApiStvProjektarbeit.getProjektarbeit(this.student.uid)), + ajaxResponse: (url, params, response) => response.data, + columns: [ + {title: "Projektarbeit ID", field: "projektarbeit_id", visible: false}, + {title: "Typ", field: "bezeichnung"}, + {title: "Typ Kurzbz", field: "projekttyp_kurzbz", visible: false}, + {title: "Studiensemester", field: "studiensemester_kurzbz"}, + {title: "Titel", field: "titel"}, + { + title: "Abgabe Enduplad", + field: "abgabedatum", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + { + title: "Beginn", + field: "beginn", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + }, + visible: false + }, + { + title: "Ende", + field: "ende", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + }, + visible: false + }, + { + title:"Freigegeben", + field:"freigegeben", + formatter:"tickCross", + hozAlign:"center", + formatterParams: { + tickElement: '', + crossElement: '' + }, + visible: false + }, + { + title: "Gesperrt bis", + field: "gesperrtbis", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + }, + visible: false + }, + {title: "Themenbereich", field: "themenbereich", visible: false}, + {title: "Anmerkung", field: "anmerkung", visible: false}, + {title: "Lehreinheit ID", field: "lehreinheit_id", visible: false}, + {title: "Student UID", field: "student_uid", visible: false}, + { + title:"Final", + field:"final", + formatter:"tickCross", + hozAlign:"center", + formatterParams: { + tickElement: '', + crossElement: '' + }, + visible: false + }, + {title: "Firma ID", field: "firma_id", visible: false}, + { + title: 'Aktionen', field: 'actions', + minWidth: 150, // Ensures Action-buttons will be always fully displayed + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'bearbeiten'); + button.addEventListener('click', (event) => { + let data = cell.getData(); + this.editedProjektarbeit = data; + this.actionEditProjektarbeit(); + }); + container.append(button); + + button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('projektarbeit', 'betreuerBearbeiten'); + button.addEventListener('click', (event) => { + let data = cell.getData(); + this.editedProjektarbeit = data; + this.actionEditBetreuer(); + }); + container.append(button); + + button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', () => + this.actionDeleteProjektarbeit(cell.getData().projektarbeit_id) + ); + container.append(button); + + container.append(cell.getData().actionDiv); + + return container; + }, + frozen: true + }, + ], + //layout: 'fitDataFill', + height: 'auto', + minHeight: '200', + selectable: 1, + index: 'projektarbeit_id', + persistence:{ + columns: true, //persist column layout + }, + persistenceID: 'stv-details-projektarbeit' + } + return options; + } + }, + methods: { + actionNewProjektarbeit() { + this.statusNew = true; + this.editedProjektarbeit = null; + this.toggleMenu('details'); + this.$refs.projektarbeitDetails.getFormData(this.statusNew); + this.$refs.projektarbeitModal.show(); + }, + actionEditProjektarbeit() { + this.statusNew = false; + this.toggleMenu('details'); + this.$refs.projektarbeitModal.show(); + }, + actionEditBetreuer() { + this.statusNew = false; + this.toggleMenu('betreuer'); + this.$refs.projektarbeitModal.show(); + }, + actionDeleteProjektarbeit(projektarbeit_id) { + this.$fhcAlert + .confirmDelete() + .then(result => result + ? projektarbeit_id + : Promise.reject({handled: true})) + .then(this.deleteProjektarbeit) + .catch(this.$fhcAlert.handleSystemError); + }, + addNewProjektarbeit() { + this.$refs.projektarbeitDetails.addNewProjektarbeit() + .then((result) => { + this.projektarbeitSaved(); + }) + .catch(this.$fhcAlert.handleSystemError); + }, + updateProjektarbeit() { + this.$refs.projektarbeitDetails.updateProjektarbeit() + .then((result) => { + this.projektarbeitSaved(); + }) + .catch(this.$fhcAlert.handleSystemError); + }, + deleteProjektarbeit(projektarbeit_id) { + return this.$api + .call(ApiStvProjektarbeit.deleteProjektarbeit(projektarbeit_id)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(() => { + this.reload(); + }); + }, + projektarbeitSaved() { + this.reload(); + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + this.hideModal('projektarbeitModal'); + }, + setDefaultStunden(projekttyp_kurzbz) { + this.$refs.projektbetreuer.setDefaultStunden(projekttyp_kurzbz); + }, + hideModal(modalRef){ + this.$refs[modalRef].hide(); + }, + reload() { + this.$refs.table.reloadTable(); + }, + toggleMenu(tabId) { + this.activeTab = tabId; + if (this.statusNew == false) { + switch(tabId) { + case 'details': + this.$refs.projektarbeitDetails.getFormData( + this.statusNew, this.editedProjektarbeit?.studiensemester_kurzbz, this.editedProjektarbeit?.lehrveranstaltung_id + ); + this.$refs.projektarbeitDetails.loadProjektarbeit(this.editedProjektarbeit?.projektarbeit_id); + break; + case 'betreuer': + this.$refs.projektbetreuer.getFormData( + this.editedProjektarbeit ? this.editedProjektarbeit.projekttyp_kurzbz : null + ); + this.$refs.projektbetreuer.getProjektbetreuer(this.editedProjektarbeit?.projektarbeit_id, this.editedProjektarbeit?.studiensemester_kurzbz); + break; + } + } + } + }, + template: ` +
+

{{this.$p.t('stv','tab_projektarbeit')}}

+ + + + + + + + + + +
+
+
+
+ + +
+
+
+ +
+
+
+ +
+
+
+
+ + + +
+
+` +} + diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js new file mode 100644 index 000000000..adcf2f2a8 --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -0,0 +1,561 @@ +import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import BsModal from "../../../../Bootstrap/Modal.js"; +import FormForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; +import NewPerson from "../../List/New.js"; +import Contact from "../Kontakt/Contact.js"; +import Vertrag from "./Vertrag.js"; + +import ApiStvProjektbetreuer from '../../../../../api/factory/stv/projektbetreuer.js'; + +export default { + components: { + CoreFilterCmpt, + BsModal, + FormForm, + FormInput, + PvAutoComplete, + NewPerson, + Contact, + Vertrag + }, + provide() { + return { + configShowVertragsdetails: this.config.showVertragsdetails + } + }, + computed: { + betreuerFormOpened() { + return this.newMode || this.editMode; + } + }, + props: { + config: { + type: Object, + default: {} + } + }, + data() { + return { + tabulatorOptions: { + columns: [ + {title: "Nachname", field: "nachname"}, + {title: "Vorname", field: "vorname"}, + {title: "Note", field: "note"}, + {title: "Punkte", field: "punkte"}, + {title: "Stunden", field: "stunden"}, + {title: "Stundensatz", field: "stundensatz", visible: false}, + {title: "Art", field: "betreuerart_kurzbz", visible: false}, + {title: "Person ID", field: "person_id", visible: false}, + {title: "Vertrag ID", field: "vertrag_id", visible: false}, + {title: "Projektarbeit ID", field: "projektarbeit_id", visible: false}, + { + title: 'Aktionen', + field: 'actions', + minWidth: 150, // Ensures Action-buttons will be always fully displayed + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'bearbeiten'); + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + let data = cell.getData(); + this.actionEditProjektbetreuer(data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz); + }); + container.append(button); + + button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + const data = cell.getData(); + this.actionDeleteProjektbetreuer(data.betreuer_id, data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz) + }); + container.append(button); + + let data = cell.getData(); + if (data.beurteilungDownloadLink !== null) { + if (data.beurteilungDownloadLink == '') { + button = document.createElement('span'); + button.title = this.$p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') + button.innerHTML = ''; + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + }); + } + else { + button = document.createElement('a'); + button.setAttribute('href', data.beurteilungDownloadLink); + button.setAttribute('role', 'button'); + button.innerHTML = ''; + button.title = this.$p.t('projektarbeit', 'projektbeurteilungErstellen'); + button.className = 'btn btn-outline-secondary btn-action'; + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + window.location.href = data.beurteilungDownloadLink; + }); + } + container.append(button); + } + + return container; + }, + frozen: true + }, + ], + //layout: 'fitDataFill', + layoutColumnsOnNewData: false, + height: 'auto', + minHeight: '100', + selectable: true, + selectable: 1, + index: 'betreuer_id', + persistence:{ + columns: true, //persist column layout + }, + persistenceID: 'stv-details-projektbetreuer' + }, + tabulatorEvents: [ + { + event: 'tableBuilt', + handler: async() => { + await this.$p.loadCategory(['global', 'person', 'stv', 'projektarbeit', 'ui']); + + // Force layout recalculation for handling overflow text + this.$refs.projektbetreuerTable.tabulator.redraw(true); + + } + }, + { + event: 'rowSelected', + handler: row => { + let data = row.getData(); + this.actionEditProjektbetreuer(data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz); + } + } + ], + formData: { + betreuerart_kurzbz: null, + note: null, + stunden: null, + stundensatz: null + }, + newMode: false, + editMode: false, + initialFormData: null, + defaultFormDataValues: {stunden: null, stundensatz: null}, + projektarbeit_id: null, + editedBetreuerIdx: -1, + arrBetreuerart: [], + arrNoten: [], + filteredBetreuer: [], + autocompleteSelectedBetreuer: null, + beurteilungDownloadLink: null, + vertragFieldsDisabled: false, + abortController: { + betreuer: null + } + } + }, + methods: { + actionNewProjektbetreuer() { + this.resetForm(); + this.newMode = !this.newMode; + this.editMode = false; + this.captureFormData(); + }, + actionEditProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { + this.editMode = true; + this.newMode = false; + this.$api + .call(ApiStvProjektbetreuer.getDefaultStundensaetze(person_id, this.studiensemester_kurzbz)) + .then(result => { + this.resetForm(); + + // get betreuer from tabulator list + let projektbetreuerListe = this.$refs.projektbetreuerTable.tabulator.getData(); + const idx = projektbetreuerListe.findIndex( + betr => + betr.person_id === person_id && + betr.projektarbeit_id === projektarbeit_id && + betr.betreuerart_kurzbz === betreuerart_kurzbz + ); + + if (idx >= 0) { // if betreuer found + + // set currently edited betreuer (deep copy) + this.formData = JSON.parse(JSON.stringify(projektbetreuerListe[idx])); + + // set download link + if (this.formData.beurteilungDownloadLink !== null) this.beurteilungDownloadLink = this.formData.beurteilungDownloadLink; + + // set betreuer for autocomplete field + this.autocompleteSelectedBetreuer = { + person_id: this.formData.person_id, + name: this.formData.name, + vorname: this.formData.vorname, + nachname: this.formData.nachname, + vertrag_id: this.formData.vertrag_id + }; + } + + // set default stundensatz (if no other is set yet) + if (this.formData.stundensatz == null) this.formData.stundensatz = result.data; + + // capture initial form data for detecting changes + this.captureFormData(); + }) + .catch(this.$fhcAlert.handleSystemError); + }, + actionDeleteProjektbetreuer(betreuer_id, projektarbeit_id, person_id, betreuerart_kurzbz) { + this.$fhcAlert + .confirmDelete() + .then(result => result + ? {projektarbeit_id, person_id, betreuerart_kurzbz} + : Promise.reject({handled: true})) + .then(result => { + return this.$api + .call(ApiStvProjektbetreuer.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz)) + }) + .then(result => { + this.$refs.projektbetreuerTable.tabulator.deleteRow(betreuer_id); + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError); + }, + getFormData(projekttyp_kurzbz) { + // default Stundensätze from config + this.defaultFormDataValues.stunden = this.getDefaultStunden(projekttyp_kurzbz); + this.defaultFormDataValues.stundensatz = this.config.defaultProjektbetreuerStundensatz; + + // get other initial data + this.$api + .call(ApiStvProjektbetreuer.getBetreuerarten()) + .then(result => { + this.arrBetreuerart = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvProjektbetreuer.getNoten()) + .then(result => { + this.arrNoten = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + getProjektbetreuer(projektarbeit_id, studiensemester_kurzbz) { + if (projektarbeit_id) { + // if projektarbeit changed, reset the form to hold new data + if (this.projektarbeit_id != projektarbeit_id) { + this.resetForm(); + this.resetModes(); + } + this.projektarbeit_id = projektarbeit_id; + this.studiensemester_kurzbz = studiensemester_kurzbz; + this.$api + .call(ApiStvProjektbetreuer.getProjektbetreuer(this.projektarbeit_id)) + .then(result => { + this.$refs.projektbetreuerTable.tabulator.replaceData(this.addIds(result.data)); + }) + .catch(this.$fhcAlert.handleSystemError); + } else { + this.emptyBetreuer(); + } + }, + saveProjektbetreuer() { + this.$refs.formProjektbetreuer.call( + ApiStvProjektbetreuer.saveProjektbetreuer(this.projektarbeit_id, this.getFormDataWithBetreuer()) + ) + .then(result => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + this.getProjektbetreuer(this.projektarbeit_id, this.studiensemester_kurzbz); + this.resetModes(); + }) + .catch(this.$fhcAlert.handleSystemError); + }, + searchBetreuer(event) { + if (this.abortController.betreuer) { + this.abortController.betreuer.abort(); + } + this.abortController.betreuer = new AbortController(); + + return this.$api + .call(ApiStvProjektbetreuer.getProjektbetreuerBySearchQuery(event.query)) + .then(result => { + this.filteredBetreuer = result.data; + }); + }, + emptyBetreuer() { + this.$refs.projektbetreuerTable.tabulator.clearData(); + }, + resetForm() { + this.formData = this.getDefaultFormData(); + if (this.beurteilungDownloadLink !== null) this.beurteilungDownloadLink = ''; + this.autocompleteSelectedBetreuer = null; + this.initialFormData = null; + if (this.projekttyp_kurzbz) this.setDefaultStunden(this.projekttyp_kurzbz); + this.disableVertragFields(false); + this.$refs.formProjektbetreuer.clearValidation(); + }, + resetModes() { + this.newMode = false; + this.editMode = false; + }, + getDefaultFormData() { + let formData = {betreuerart_kurzbz : null, note: null}; + + for (const name in this.defaultFormDataValues) { + formData[name] = this.defaultFormDataValues[name]; + } + + return formData; + }, + captureFormData() { + this.initialFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy + }, + // add own betreuer ids to betreuer liste + addIds(betreuerListe) { + + for (const idx in betreuerListe) { + let betreuer = betreuerListe[idx]; + + betreuer.person_id_old = betreuer.person_id; + betreuer.betreuerart_kurzbz_old = betreuer.betreuerart_kurzbz; + betreuer.betreuer_id = parseInt(idx); + } + return betreuerListe; + }, + // add the betreuer selected in automomplete to betreuer liste + getFormDataWithBetreuer() { + let preparedFormData = this.formData; + + preparedFormData.projektarbeit_id = this.projektarbeit_id; + if (this.autocompleteSelectedBetreuer) { + preparedFormData.person_id = this.autocompleteSelectedBetreuer.person_id; + preparedFormData.name = this.autocompleteSelectedBetreuer.name; + preparedFormData.vorname = this.autocompleteSelectedBetreuer.vorname; + preparedFormData.nachname = this.autocompleteSelectedBetreuer.nachname; + } + + return preparedFormData; + }, + // get default values for stunden + getDefaultStunden(projekttyp_kurzbz) { + let stunden = '0.0'; + if (projekttyp_kurzbz == 'Bachelor') stunden = this.config.defaultProjektbetreuerStunden; + if (projekttyp_kurzbz == 'Diplom') stunden = this.config.defaultProjektbetreuerStundenDiplom; + return stunden; + }, + setDefaultStunden(projekttyp_kurzbz) { + this.projekttyp_kurzbz = projekttyp_kurzbz; + // if form data has not already been modified by user, set the default stunden + if (!this.formDataModified()) { + let defaultStunden = this.getDefaultStunden(projekttyp_kurzbz); + // adapt initial form data so it does not count as modified + if (this.initialFormData) this.initialFormData.stunden = defaultStunden; + // set default Stunden + this.formData.stunden = defaultStunden; + } + }, + // check if form data has been modified since initial data has been captured + formDataModified() { + if (this.autocompleteSelectedBetreuer != null) return true; + + for (const prop in this.initialFormData) { + if (typeof this.formData[prop] == 'undefined') return true; + if (this.formData[prop] != this.initialFormData[prop]) return true; + } + + return false; + }, + actionNewPerson() { + this.$refs.newPersonModal.reset(); + this.$refs.newPersonModal.open(); + }, + actionKontaktdatenBearbeiten() { + if (!this.autocompleteSelectedBetreuer) return; + this.$refs.kontaktdatenModal.show(); + }, + // stuff to do after new person has been saved + personSaved(result) { + this.$api + .call(ApiStvProjektbetreuer.getPerson(result)) + .then(response => { + // set the new person in Betreuer autocomplete field + this.autocompleteSelectedBetreuer = response.data; + }) + .catch(this.$fhcAlert.handleSystemError) + }, + // disable fields which are dependent on Vertrag status + disableVertragFields(statusAkzeptiert) { + this.vertragFieldsDisabled = statusAkzeptiert; + } + }, + template: ` +
+ +
+ + {{this.$p.t('projektarbeit','betreuerGross')}} + + + + + +
+ + +
+ +
+
+ +
+
+ +
+
+ +
+ + + +
+ +
+ + + + +
+ +
+
+ + +
+
+ + +
+
+ +
+ + + +
+ +
+ + +
+ +
+ + + + + + + + + +
+
+ + +
+
+ +
+` +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js new file mode 100644 index 000000000..c5de5a1fb --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js @@ -0,0 +1,160 @@ +import CoreForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import ApiVertrag from '../../../../../api/factory/stv/vertrag.js'; + +export default{ + name: "ProjektarbeitVertrag", + components: { + CoreForm, + FormInput + }, + emits: [ + 'canceledVertrag', + 'vertragsstatusChanged' + ], + props: { + vertrag_id: Number, + person_id: Number, + betreuerProjektarbeit: Object + }, + + inject: { + showVertragsdetails: { + from: 'configShowVertragsdetails', + default: false + } + }, + + data() { + return{ + data: { + vertragsstatus: null, + vertragsstunden: null, + vertragsstunden_studiensemester_kurzbz: null + }, + // status names for stages of Vertrag ("constants") + vertragsstatus_akzeptiert: 'Akzeptiert', + vertragsstatus_geaendert:'Geändert', + vertragsstatus_storniert: 'Storno' + } + }, + watch: { + vertrag_id: + { + //deep: true, + handler(newVal, oldVal) { + this.resetForm(); + if (newVal !== null && newVal !== undefined) this.getVertrag(); + } + }, + }, + computed: { + vertragsstatus() { + // not show Vertragsstatus if no data + if (!this.data?.vertragsstatus || !this.betreuerProjektarbeit?.betreuerart_kurzbz) return; + + const betragVertrag = Number(this.data.betrag) || 0; + const stundenVertrag = Number(this.data.vertragsstunden) || 0; + + const semStunden = Number(this.betreuerProjektarbeit.stunden) || 0; + const stundensatz = Number(this.betreuerProjektarbeit.stundensatz) || 0; + + const kostenAktuell = semStunden * stundensatz; + + // Vertragsstunden amount should be same as Semesterstunden amount, otherwise there has been a change + let vertragsstatus = (stundenVertrag !== semStunden || betragVertrag !== kostenAktuell) + ? this.vertragsstatus_geaendert + : (this.data.vertragsstatus || ''); + + // vertragsstatus changed to "akzeptiert" + this.$emit('vertragsstatusChanged', vertragsstatus == this.vertragsstatus_akzeptiert); + + return vertragsstatus; + }, + }, + methods: { + getVertrag() { + if (this.showVertragsdetails === false) + return; + + if (!this.vertrag_id) + return; + + this.$api.call(ApiVertrag.getVertrag(this.vertrag_id)) + .then(result => { + if (result.data.vertragsstatus != this.vertragsstatus_storniert) { + this.data = result.data; + } + }) + .catch(this.$fhcAlert.handleSystemError); + }, + + cancelVertrag() { + this.$fhcAlert + .confirmDelete() + .then(result => result + ? {vertrag_id: this.vertrag_id, person_id: this.person_id} + : Promise.reject({handled: true})) + .then(result => { + return this.$api.call(ApiVertrag.cancelVertrag({vertrag_id: this.vertrag_id, person_id: this.person_id})) + }) + .then(result => { + this.resetForm(); + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + this.$emit('canceledVertrag'); + // vertragsstatus not "akzeptiert" anymore + this.$emit('vertragsstatusChanged', false); + }) + .catch(this.$fhcAlert.handleSystemError); + }, + resetForm() { + this.data = { + vertrag_id: null, + vertragsstatus: null, + vertragsstunden: null, + vertragsstunden_studiensemester_kurzbz: null + } + } + }, + template: ` + +
+ + {{$p.t('lehre', 'vertragsdetails')}} + +
+ {{ betreuerProjektarbeit?.betreuerart_kurzbz && betreuerProjektarbeit?.vertrag_id == null ? ' – '+$p.t('lehre', 'nochKeinVertrag') : '' }} +
+
+
+ {{ $p.t('lehre', 'vertragsstatus') }}: {{ vertragsstatus }} +
+
+
+
+ {{$p.t('lehre', 'vertragurfassung')}} +
+
+
+
+ {{ $p.t('lehre', 'semesterstunden') }}: {{ data.vertragsstunden }} +
+ {{ $p.t('lehre', 'studiensemester') }}: {{ data.vertragsstunden_studiensemester_kurzbz }} +
+
+
+
+ +
+
+
+
+ ` +}; diff --git a/public/js/components/Stv/Studentenverwaltung/List/New.js b/public/js/components/Stv/Studentenverwaltung/List/New.js index 8de217e00..75896d408 100644 --- a/public/js/components/Stv/Studentenverwaltung/List/New.js +++ b/public/js/components/Stv/Studentenverwaltung/List/New.js @@ -10,7 +10,7 @@ import ApiStvStudents from '../../../../api/factory/stv/students.js'; var _uuid = 0; const FORMDATA_DEFAULT = { address: { - func: 0, + func: 1, nation: 'A' }, geburtsnation: 'A', @@ -33,7 +33,9 @@ export default { inject: [ 'lists' ], + emits: ['saved'], props: { + personOnly: Boolean, studiengangKz: Number, studiensemesterKurzbz: String }, @@ -108,7 +110,7 @@ export default { return; this.abortController.suggestions = new AbortController(); - + this.$api .call(ApiStvStudents.check({ vorname: this.formData.vorname, @@ -119,6 +121,11 @@ export default { }) .then(result => this.suggestions = result.data) .catch(error => { + + if (error.code == 'ERR_BAD_REQUEST') { + return this.suggestions = []; + } + // NOTE(chris): repeat request if (error.code != "ERR_CANCELED") window.setTimeout(this.loadSuggestions, 100); @@ -191,14 +198,22 @@ export default { if (data.studiensemester_kurzbz === undefined) data.studiensemester_kurzbz = this.studiensemesterKurzbz; - // TODO(chris): move to fhcapi.factory - this.$refs.form - .post('api/frontend/v1/stv/student/add', data) - .then(result => { - this.$fhcAlert.alertSuccess('Gespeichert'); - this.$refs.modal.hide(); - }) - .catch(this.$fhcAlert.handleSystemError); + data.personOnly = this.personOnly; + + this.$refs.form.call( + ApiStvStudents.add(data) + ) + .then(result => { + this.$emit('saved', result.data); + this.$fhcAlert.alertSuccess('Gespeichert'); + this.$refs.modal.hide(); + }) + .catch(this.$fhcAlert.handleSystemError); + }, + setPerson(suggestion) + { + this.person = suggestion; + this.formData.address.func = -1; } }, created() { @@ -215,7 +230,7 @@ export default { ` -}; \ No newline at end of file +}; diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 5d3833dc9..858d7abe4 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -49982,7 +49982,989 @@ I have been informed that I am under no obligation to consent to the transmissio 'insertvon' => 'system' ) ) + ), + // FHC-4 Projektarbeiten & Vertraege START + array( + 'app' => 'core', + 'category' => 'stv', + 'phrase' => 'tab_projektarbeit', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Projektarbeit', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Project work', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'projektarbeitAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Projektarbeit anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create project work', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'projektarbeitBearbeiten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Projektarbeit bearbeiten', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Edit project work', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'titel', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Titel', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'titelEnglisch', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Titel Englisch', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title English', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'themenbereich', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Themenbereich', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'topic area', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'typ', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Typ', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'type', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'firma', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Firma', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'company', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'lehrveranstaltung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehrveranstaltung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'course', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'lvTeil', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'LV-Teil', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'teaching unit', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuer', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'BetreuerIn', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'assessor', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuerGross', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'BetreuerIn', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Assessor', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuerart', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Betreuerart', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'assessor type', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'note', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Note', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'grade', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'stunden', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Stunden', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'hours', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'stundensatz', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Stundensatz', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'hourly rate', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'beginn', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Beginn', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'start', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'ende', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ende', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'end', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'freigegeben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'freigegeben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'approved', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'gesperrtBis', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Gesperrt bis', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'locked until', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'anmerkung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Anmerkung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'annotation', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'firmaId', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Firma ID', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'company Id', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'error_betreuerNichtGeloescht', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Löschen nicht möglich, dieser Projektarbeit sind bereits BetreuerInnen zugewiesen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Deleting not possible, assessors were already assigned to this projekt work', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'error_paabgabeNichtGeloescht', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Löschen nicht möglich, für diese Projektarbeit gibt es bereits Projektarbeitsabgaben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Deleting not possible, there are projekt submissions for this project work', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'error_invalidProjektbetreuer', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'ProjektbetreuerIn ungültig', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Invalid project assessors', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'error_betreuerHatVertrag', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Löschen nicht möglich, ProjektbetreuerIn hat bereits einen Vertrag', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Deleting not possible, project assessor has a contract already', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'neuePersonAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Neue Person anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create new person', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'titelPre', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Titel (Pre)', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title (Pre)', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'titelPost', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Titel (Post)', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title (Post)', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'weitereVornamen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Weitere Vornamen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'other first names', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'bestehendeAdresseUeberschreiben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Bestehende Adresse überschreiben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Replace existing address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'adresseHinzufuegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Adresse hinzufügen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Add new address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'adresseNichtAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Adresse nicht anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Do not create address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'land', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Land', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'nation', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'mobil', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Mobil', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'mobile phone', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'letzeAusbildung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Letzte Ausbildung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'most recent education', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'ausbildungsart', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ausbildungsart', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'education type', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'anmerkungen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Anmerkungen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'notes', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'personAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Person anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create person', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'interessentAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'InteressentIn anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create candidate', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'personExistiertPruefung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfung ob Person bereits existiert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Check if a person already exists', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'ui', + 'phrase' => 'zurueck', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Zurück', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Back', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'kontaktdatenBearbeiten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Kontaktdaten bearbeiten', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Edit contact data', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'projektbeurteilungErstellen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Projektbeurteilung erstellen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create project assessment document', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'projektarbeitNochNichtBeurteilt', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Projektarbeit ist noch nicht beurteilt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Projekt work was not assessed yet', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'vertragStornieren', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Stornieren', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Cancel contract', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'nochKeinVertrag', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Noch kein Vertrag', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'No contract yet', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuerBearbeiten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'BetreuerIn bearbeiten', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Edit assessor', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuerSpeichern', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'BetreuerIn speichern', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Save assessor', + 'description' => '', + 'insertvon' => 'system' + ) + ) ) + // FHC-4 Projektarbeiten & Vertraege ENDE );