diff --git a/application/config/stv.php b/application/config/stv.php index 039dd8891..34a30a96e 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -61,7 +61,11 @@ $config['tabs'] = 'notes' => [ //if true, the count of Messages will be shown in the header of the Tab Messages 'showCountNotes' => true - ] + ], + 'combinePeople' => [ + //multitab should only be shown with this length of selection + 'validCountMulti' => 2, + ], ]; // List of fields to show when ZGV_DOKTOR_ANZEIGEN is defined @@ -84,9 +88,14 @@ if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) { ); } -$config['tabs']['projektarbeit']['defaultProjektbetreuerStunden'] = '4.0'; -$config['tabs']['projektarbeit']['defaultProjektbetreuerStundenDiplom'] = '5.0'; -$config['tabs']['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz'] = true; +$config['tabs']['projektarbeit']['defaultProjektbetreuerStunden'] = + defined('FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_BACHELOR') + ? FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_BACHELOR + : '0.0'; +$config['tabs']['projektarbeit']['defaultProjektbetreuerStundenDiplom'] = + defined('FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_MASTER') + ? FAS_STUDIERENDE_PROJEKTARBEIT_DEFAULT_BETREUER_STUNDEN_MASTER + : '0.0'; $config['tabs']['projektarbeit']['defaultProjektbetreuerStundensatz'] = '80.0'; $config['student_tab_order'] = [ @@ -115,8 +124,10 @@ $config['student_tab_order'] = [ $config['students_tab_order'] = [ 'banking', 'status', + 'messages', 'groups', 'finalexam', + 'combinePeople', 'archive', ]; diff --git a/application/controllers/Cis/Pub.php b/application/controllers/Cis/Pub.php index bebc844ab..de456145b 100644 --- a/application/controllers/Cis/Pub.php +++ b/application/controllers/Cis/Pub.php @@ -14,7 +14,7 @@ class Pub extends Auth_Controller { parent::__construct( array( - 'bild' => ['basis/cis:r'] + 'bild' => ['basis/cis:r', 'assistenz:r'] ) ); } diff --git a/application/controllers/NeueNachricht.php b/application/controllers/NeueNachricht.php index 9b61b78ef..b0ff5c554 100644 --- a/application/controllers/NeueNachricht.php +++ b/application/controllers/NeueNachricht.php @@ -20,11 +20,18 @@ class NeueNachricht extends Auth_Controller */ public function _remap() { + $typeid = $this->input->post('typeid'); + $ids = ($this->input->post('ids') && strpos($this->input->post('ids'), ',')) + ? explode(',', $this->input->post('ids')) + : $this->input->post('ids'); + //now working $this->load->view('Nachrichten', [ 'permissions' => [ 'assistenz_schreibrechte' => $this->permissionlib->isBerechtigt('assistenz','suid'), - ] + ], + 'ids' => $ids, + 'typeid' => $typeid ]); } } diff --git a/application/controllers/Studentenverwaltung.php b/application/controllers/Studentenverwaltung.php index 2ce19c58a..36c91d5f6 100644 --- a/application/controllers/Studentenverwaltung.php +++ b/application/controllers/Studentenverwaltung.php @@ -32,6 +32,10 @@ class Studentenverwaltung extends Auth_Controller 'student/keine_studstatuspruefung' => $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'), 'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht'), 'system/change_outputformat' => $this->permissionlib->getOE_isEntitledFor('system/change_outputformat'), + 'student/editBakkZgv' => $this->permissionlib->getSTG_isEntitledFor('student/editBakkZgv') ?: array(), + 'student/editMakkZgv' => $this->permissionlib->getSTG_isEntitledFor('student/editMakkZgv') ?: array(), + 'student/editDokZgv' => $this->permissionlib->getSTG_isEntitledFor('student/editDokZgv') ?: array(), + 'student/editBismelden' => $this->permissionlib->isBerechtigt('student/editBismelden') ], 'variables' => [ 'semester_aktuell' => $this->variablelib->getVar('semester_aktuell') diff --git a/application/controllers/api/frontend/v1/Documents.php b/application/controllers/api/frontend/v1/Documents.php index 2d2c410cf..7b2fc4a15 100644 --- a/application/controllers/api/frontend/v1/Documents.php +++ b/application/controllers/api/frontend/v1/Documents.php @@ -442,6 +442,10 @@ class Documents extends FHCAPI_Controller 'betreuerart_kurzbz', 'studiensemester_kurzbz' ] as $key) { + if (in_array($xsl, array('Ausbildungsver', 'AusbVerEng')) && $key === 'uid') + { + continue; + } $value = $this->input->post_get($key); if ($value !== null) $params .= '&' . $key . '=' . urlencode($value); diff --git a/application/controllers/api/frontend/v1/messages/Messages.php b/application/controllers/api/frontend/v1/messages/Messages.php index 355fe79a4..3035e532d 100644 --- a/application/controllers/api/frontend/v1/messages/Messages.php +++ b/application/controllers/api/frontend/v1/messages/Messages.php @@ -1,6 +1,5 @@ ['admin:r', 'assistenz:r'], 'getMsgVarsLoggedInUser' => ['admin:r', 'assistenz:r'], 'getNameOfDefaultRecipient' => ['admin:r', 'assistenz:r'], + 'getNameOfDefaultRecipients' => ['admin:r', 'assistenz:r'], 'sendMessage' => ['admin:r', 'assistenz:r'], 'deleteMessage' => ['admin:r', 'assistenz:r'], 'getDataVorlage' => ['admin:r', 'assistenz:r'], @@ -21,6 +21,7 @@ class Messages extends FHCAPI_Controller 'getReplyData' => ['admin:r', 'assistenz:r'], 'getPersonId' => ['admin:r', 'assistenz:r'], 'getUid' => ['admin:r', 'assistenz:r'], + 'getUids' => ['admin:r', 'assistenz:r'], ]); //Load Models @@ -37,7 +38,7 @@ class Messages extends FHCAPI_Controller // Load language phrases $this->loadPhrases([ - 'ui' + 'ui', 'messages' ]); } @@ -101,22 +102,49 @@ class Messages extends FHCAPI_Controller $this->terminateWithSuccess($vorlage); } - public function getMessageVarsPerson($id, $typeId) + public function getMessageVarsPerson($typeId) { - $person_id = ($typeId == 'mitarbeiter_uid') ? $this->_getPersonId($id, $typeId) : $id; - $result = $this->MessageModel->getMsgVarsDataByPersonId($person_id); - $data = $this->getDataOrTerminateWithError($result); + $ids = $this->input->post('ids'); + $messageVarsPerson = []; - $this->terminateWithSuccess($data); + foreach ($ids as $id) + { + $person_id = ($typeId == 'mitarbeiter_uid') ? $this->_getPersonId($id, $typeId) : $id; + $result = $this->MessageModel->getMsgVarsDataByPersonId($person_id); + $data = $this->getDataOrTerminateWithError($result); + $messageVarsPerson[] = current($data); + } + + $this->terminateWithSuccess($messageVarsPerson); } - public function getMsgVarsPrestudent($id, $typeId) + public function getMsgVarsPrestudent($typeId) { - $prestudent_id = ($typeId == 'uid') ? $this->_getPrestudentIdFromUid($id) : $id; - $result = $this->MessageModel->getMsgVarsDataByPrestudentId($prestudent_id); - $data = $this->getDataOrTerminateWithError($result); + $ids = $this->input->post('ids'); + if(!is_array($ids)) { + $ids = array($ids); + } + $messageVarsPrestudent = []; - $this->terminateWithSuccess($data); + if($typeId == 'uid') + { + $prestudent_ids = []; + foreach ($ids as $id) + { + $prestudent_ids[] = $this->_getPrestudentIdFromUid($id); + } + } + else + $prestudent_ids = $ids; + + foreach ($prestudent_ids as $prestudent_id) + { + $result = $this->MessageModel->getMsgVarsDataByPrestudentId($prestudent_id); + $data = $this->getDataOrTerminateWithError($result); + $messageVarsPrestudent[] = current($data); + } + + $this->terminateWithSuccess($messageVarsPrestudent); } public function getMsgVarsLoggedInUser() @@ -127,27 +155,45 @@ class Messages extends FHCAPI_Controller $this->terminateWithSuccess($data); } - public function getNameOfDefaultRecipient($id, $type_id) + public function getNameOfDefaultRecipients($type_id) { - $id = ($type_id != 'person_id') ? $this->_getPersonId($id, $type_id) : $id; + $ids = $this->input->post('ids'); + if(!is_array($ids)) { + $ids = array($ids); + } + $recipients = []; + + if (empty($ids)) { + + throw new InvalidArgumentException($this->p->t('ui', 'errorMissingOrInvalidParameters', ['parameter'=> 'Id(s)']), self::ERROR_TYPE_GENERAL); + } $this->load->model('person/Person_model', 'PersonModel'); + if($type_id != 'person_id'){ + foreach ($ids as $id) + { + $person_id = $this->_getPersonId($id, $type_id); + $result = $this->PersonModel->load($person_id); + $data = $this->getDataOrTerminateWithError($result); + $name = current($data); + $recipients[$id] = $name->vorname . " " . $name->nachname; + } + } + else { + foreach ($ids as $id) { + $result = $this->PersonModel->load($id); + $data = $this->getDataOrTerminateWithError($result); + $name = current($data); + $recipients[$id] = $name->vorname . " " . $name->nachname; + } + } - $result = $this->PersonModel->load($id); - $data = $this->getDataOrTerminateWithError($result); - $name = current($data); - - $this->terminateWithSuccess($name->vorname . " " . $name->nachname ); + $this->terminateWithSuccess($recipients); } - public function sendMessage($recipient_id) + public function sendMessage($typeId) { - //has to be uid - // $this->terminateWithError("uid", $recipient_id, self::ERROR_TYPE_GENERAL); - - //default setting - $receiversPersonId = $this->_getPersonId($recipient_id, 'uid'); - + $resultReturn = []; $uid = getAuthUID(); $this->load->model('person/Benutzer_model', 'BenutzerModel'); $result = $this->BenutzerModel->loadWhere( @@ -185,47 +231,61 @@ class Messages extends FHCAPI_Controller $body = $this->input->post('body'); $relationmessage_id = $this->input->post('relationmessage_id'); - $typeId = $this->input->post('type_id'); - $id = $this->input->post('id'); - - if($typeId == 'uid') + if (isset($_POST['ids'])) { - $prestudent_id = $this-> _getPrestudentIdFromUid($id); - - //parseMessagetext for variables Prestudent - $result = $this->MessagesModel->parseMessageTextPrestudent($prestudent_id, $body); - $bodyParsed = $this->getDataOrTerminateWithError($result); - } - if($typeId == 'mitarbeiter_uid') - { - $person_id = $this->_getPersonId($id, $typeId); - - $result = $this->MessagesModel->parseMessageTextPerson($person_id, $body); - $bodyParsed = $this->getDataOrTerminateWithError($result); - $this->terminateWithError($bodyParsed, self::ERROR_TYPE_GENERAL); - - } - elseif($typeId == 'person_id') - { - $result = $this->MessagesModel->parseMessageTextPerson($id, $body); - $bodyParsed = $this->getDataOrTerminateWithError($result); - } - elseif($typeId == 'prestudent_id') - { - $result = $this->MessagesModel->parseMessageTextPrestudent($id, $body); - $bodyParsed = $this->getDataOrTerminateWithError($result); - } - else - { - $this->terminateWithError("type_id " . $typeId . " not valid", self::ERROR_TYPE_GENERAL); + $ids = json_decode($_POST['ids']); + unset($_POST['ids']); + foreach ($data as $k => $v) { + $_POST[$k] = $v; + } } - $result = $this->messagelib->sendMessageUser($receiversPersonId, $subject, $bodyParsed, $benutzer->person_id, null, $relationmessage_id); + if (!is_array($ids)) { + $ids = [$ids]; + } - $this->terminateWithSuccess($result); + foreach ($ids as $id) + { + $receiversPersonId = $typeId == "person_id" ? $id : $this->_getPersonId($id, $typeId); + + if($typeId == 'uid') + { + $prestudent_id = $this-> _getPrestudentIdFromUid($id); + + $result = $this->MessagesModel->parseMessageTextPrestudent($prestudent_id, $body); + $bodyParsed = $this->getDataOrTerminateWithError($result); + } + if($typeId == 'mitarbeiter_uid') + { + $person_id = $this->_getPersonId($id, $typeId); + + $result = $this->MessagesModel->parseMessageTextPerson($person_id, $body); + $bodyParsed = $this->getDataOrTerminateWithError($result); + } + elseif($typeId == 'person_id') + { + $result = $this->MessagesModel->parseMessageTextPerson($id, $body); + $bodyParsed = $this->getDataOrTerminateWithError($result); + } + elseif($typeId == 'prestudent_id') + { + $result = $this->MessagesModel->parseMessageTextPrestudent($id, $body); + $bodyParsed = $this->getDataOrTerminateWithError($result); + } + else + { + $this->terminateWithError($this->p->t('messages', 'error_missingLogic', ['type'=> $typeId]), self::ERROR_TYPE_GENERAL); + } + + $result =$this->messagelib->sendMessageUser($receiversPersonId, $subject, $bodyParsed, $benutzer->person_id, null, $relationmessage_id); + $data = $this->getDataOrTerminateWithError($result); + $resultReturn[] = current($data); + + } + $this->terminateWithSuccess($resultReturn); } - public function getPreviewText($id, $type_id) + public function getPreviewText($type_id) { if (isset($_POST['data'])) { @@ -233,39 +293,60 @@ class Messages extends FHCAPI_Controller unset($_POST['data']); } else - $this->terminateWithError("Textbody missing ", self::ERROR_TYPE_GENERAL); + $this->terminateWithError($this->p->t('messages', 'errorMissingOrInvalidParameters', ['parameter'=> "Textbody"]), self::ERROR_TYPE_GENERAL); - switch($type_id) + if (isset($_POST['ids'])) { - case 'uid': - $prestudent_id = $this->_getPrestudentIdFromUid($id); - $result = $this->MessagesModel->parseMessageTextPrestudent($prestudent_id, $data); - break; - case 'prestudent_id': - $result = $this->MessagesModel->parseMessageTextPrestudent($id, $data); - break; - case 'person_id': - $result = $this->MessagesModel->parseMessageTextPerson($id, $data); - break; - case 'mitarbeiter_uid': - { - $person_id = $this->_getPersonId($id, $type_id); - $result = $this->MessagesModel->parseMessageTextPerson($person_id, $data); - } - break; - default: - $this->terminateWithError("MESSAGES::getPreviewText logic for type_id " . $type_id . " not defined yet", self::ERROR_TYPE_GENERAL); - break; + $ids = json_decode($_POST['ids']); + if(!is_array($ids)) + { + $ids = array($ids); + } + unset($_POST['ids']); } + else + $this->terminateWithError($this->p->t('ui', 'errorMissingOrInvalidParameters', ['parameter'=> 'Id(s)']), self::ERROR_TYPE_GENERAL); - $bodyParsed = $this->getDataOrTerminateWithError($result); + $bodyParsed = []; + + foreach ($ids as $id) + { + switch($type_id) + { + case 'uid': + $prestudent_id = $this->_getPrestudentIdFromUid($id); + $result = $this->MessagesModel->parseMessageTextPrestudent($prestudent_id, $data); + $bodyParsed[$id] = $this->getDataOrTerminateWithError($result); + break; + case 'prestudent_id': + $result = $this->MessagesModel->parseMessageTextPrestudent($id, $data); + $bodyParsed[$id] = $this->getDataOrTerminateWithError($result); + break; + case 'person_id': + $result = $this->MessagesModel->parseMessageTextPerson($id, $data); + $bodyParsed[$id] = $this->getDataOrTerminateWithError($result); + break; + case 'mitarbeiter_uid': + { + $person_id = $this->_getPersonId($id, $type_id); + $result = $this->MessagesModel->parseMessageTextPerson($person_id, $data); + $bodyParsed[$id] = $this->getDataOrTerminateWithError($result); + } + break; + default: + $this->terminateWithError($this->p->t('messages', 'error_missingLogic', ['type'=> $type_id]), self::ERROR_TYPE_GENERAL); + break; + } + } $this->terminateWithSuccess($bodyParsed); } public function getReplyData($messageId) { - //TODO(Manu) validation of messageId: if number + if (!is_numeric($messageId)) { + $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value'=> 'Message ID']), self::ERROR_TYPE_GENERAL); + } $this->MessageModel->addSelect('public.tbl_msg_message.*'); $this->MessageModel->addSelect('r.*'); @@ -288,7 +369,6 @@ class Messages extends FHCAPI_Controller $replyBody = $this->_getReplyBody($body, $dataMessage[0]->nachname, $dataMessage[0]->vorname, $dataMessage[0]->insertamum); $dataMessage[0]->replyBody = $replyBody; - $dataMessage[0]->rest = "Help Manu"; $dataMessage[0]->replySubject = $prefix . $subject; $this->terminateWithSuccess($dataMessage); @@ -336,6 +416,11 @@ class Messages extends FHCAPI_Controller ['prestudent_id' => $id] ); } + else + { + $this->terminateWithError($this->p->t('messages', 'error_missingLogic', ['type'=> $typeId]), self::ERROR_TYPE_GENERAL); + } + $data = $this->getDataOrTerminateWithError($result); $person = current($data); @@ -343,8 +428,11 @@ class Messages extends FHCAPI_Controller $this->terminateWithSuccess($person->person_id); } - public function getUid($id, $typeId) + public function getUids($typeId) { + $ids = $this->input->post('ids'); + $benutzerIds = []; + if (!$typeId) { $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Type ID']), self::ERROR_TYPE_GENERAL); @@ -352,39 +440,50 @@ class Messages extends FHCAPI_Controller elseif ($typeId == 'person_id') { $this->load->model('person/Benutzer_model', 'BenutzerModel'); - $result = $this->BenutzerModel->loadWhere( - ['person_id' => $id] - ); + foreach ($ids as $id) + { + $result = $this->BenutzerModel->loadWhere( + ['person_id' => $id] + ); + $data = $this->getDataOrTerminateWithError($result); + $benutzer = current($data); + + $benutzerIds[$id] = $benutzer->uid; + } } elseif($typeId == 'prestudent_id') { $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - $result = $this->PrestudentModel->loadWhere( - ['prestudent_id' => $id] - ); + foreach ($ids as $id) + { + $result = $this->PrestudentModel->loadWhere( + ['prestudent_id' => $id] + ); - $data = $this->getDataOrTerminateWithError($result); - $person = current($data); - $person_id = $person->person_id; + $data = $this->getDataOrTerminateWithError($result); + $person = current($data); + $person_id = $person->person_id; - $this->load->model('person/Benutzer_model', 'BenutzerModel'); - $result = $this->BenutzerModel->loadWhere( - ['person_id' => $person_id] - ); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $result = $this->BenutzerModel->loadWhere( + ['person_id' => $person_id] + ); + $data = $this->getDataOrTerminateWithError($result); + $benutzer = current($data); + + $benutzerIds[$id] = $benutzer->uid; + } } elseif($typeId == 'uid' || $typeId == 'mitarbeiter_uid') { - $this->terminateWithSuccess($id); + $this->terminateWithSuccess($ids); } else { - $this->terminateWithError("MESSAGES::getUID logic for type_id " . $typeId . " not defined yet", self::ERROR_TYPE_GENERAL); + $this->terminateWithError($this->p->t('messages', 'error_missingLogic', ['type'=> $typeId]), self::ERROR_TYPE_GENERAL); } - $data = $this->getDataOrTerminateWithError($result); - $benutzer = current($data); - - $this->terminateWithSuccess($benutzer->uid); + $this->terminateWithSuccess($benutzerIds); } private function _getPersonId($id, $typeId) @@ -403,11 +502,16 @@ class Messages extends FHCAPI_Controller ['prestudent_id' => $id] ); } + else + { + $this->terminateWithError($this->p->t('messages', 'error_missingLogic', ['type'=> $typeId]), self::ERROR_TYPE_GENERAL); + } + $data = $this->getDataOrTerminateWithError($result); if (count($data) < 1) { - $this->terminateWithError('Error: Messages API no person_id found.'); + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL); } $person = current($data); @@ -416,7 +520,6 @@ class Messages extends FHCAPI_Controller private function _getPrestudentIdFromUid($uid) { - // $this->terminateWithError($uid, self::ERROR_TYPE_GENERAL); $this->load->model('crm/Student_model', 'StudentModel'); $result = $this->StudentModel->loadWhere( ['student_uid' => $uid] @@ -425,7 +528,7 @@ class Messages extends FHCAPI_Controller $data = $this->getDataOrTerminateWithError($result); if (count($data) < 1) { - $this->terminateWithError('Error: Messages API no prestudent_id found.'); + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL); } $student = current($data); diff --git a/application/controllers/api/frontend/v1/organisation/Studienplan.php b/application/controllers/api/frontend/v1/organisation/Studienplan.php new file mode 100644 index 000000000..c5a69fdee --- /dev/null +++ b/application/controllers/api/frontend/v1/organisation/Studienplan.php @@ -0,0 +1,69 @@ + self::PERM_LOGGED + ]); + } + + public function getBySemester() + { + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $studiengang_kz = $this->input->get('studiengang_kz'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + $ausbildungssemester = $this->input->get('ausbildungssemester') ?: null; + $orgform_kurzbz = $this->input->get('orgform_kurzbz') ?: null; + + if (!$studiengang_kz || !is_numeric($studiengang_kz)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Studiengangskennzahl']), self::ERROR_TYPE_GENERAL); + + if (!$studiensemester_kurzbz) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Studiensemester']), self::ERROR_TYPE_GENERAL); + + if (isset($ausbildungssemester) && !is_numeric($ausbildungssemester)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Ausbildungssemester']), self::ERROR_TYPE_GENERAL); + + + //~ $this->load->library('form_validation'); + + //~ $this->form_validation->set_rules('studiengang_kz', 'StudiengangKz', 'required|numeric'); + //~ $this->form_validation->set_rules('studiensemester_kurzbz', 'StudiensemesterKurbz', 'required'); + //~ $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'numeric'); + + //~ if (!$this->form_validation->run()) + //~ { + //~ $this->addMeta('fail2', 'fail2'); + //~ return $this->terminateWithValidationErrors($this->form_validation->error_array()); + //~ } + + + $this->addMeta('stg_kz', $studiengang_kz); + $this->addMeta('sem', $studiensemester_kurzbz); + $this->addMeta('sem2', $ausbildungssemester); + $this->addMeta('org', $orgform_kurzbz); + + $result = $this->StudienplanModel->getStudienplaeneBySemester($studiengang_kz, $studiensemester_kurzbz, $ausbildungssemester, $orgform_kurzbz); + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + + $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } +} diff --git a/application/controllers/api/frontend/v1/stv/Aufnahmetermine.php b/application/controllers/api/frontend/v1/stv/Aufnahmetermine.php index 86b739c90..26033908d 100644 --- a/application/controllers/api/frontend/v1/stv/Aufnahmetermine.php +++ b/application/controllers/api/frontend/v1/stv/Aufnahmetermine.php @@ -298,7 +298,7 @@ class Aufnahmetermine extends FHCAPI_Controller $reihungstestangetreten = (isset($formData['reihungstestangetreten']) && !empty($formData['reihungstestangetreten'])) ? $formData['reihungstestangetreten'] - : null; + : false; $aufnahmegruppe_kurzbz = (isset($formData['aufnahmegruppe_kurzbz']) && !empty($formData['aufnahmegruppe_kurzbz'])) ? $formData['aufnahmegruppe_kurzbz'] diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 97d626246..17b360f8c 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -33,6 +33,8 @@ class Config extends FHCAPI_Controller { // TODO(chris): permissions parent::__construct([ + 'get' => ['admin:r', 'assistenz:r'], + 'set' => ['admin:r', 'assistenz:r'], 'filter' => ['admin:r', 'assistenz:r'], 'student' => ['admin:r', 'assistenz:r'], 'students' => ['admin:r', 'assistenz:r'] @@ -55,6 +57,95 @@ class Config extends FHCAPI_Controller } /** + * get App config + */ + public function get() + { + $this->load->model('system/Variable_model', 'VariableModel'); + $this->load->config('stv'); + + $config = []; + + #number_displayed_past_studiensemester + $result = $this->VariableModel->getVariables(getAuthUID(), ['number_displayed_past_studiensemester']); + $data = $this->getDataOrTerminateWithError($result); + + $number_displayed_past_studiensemester_default = $this->config->item('number_displayed_past_studiensemester_default'); + + $config['number_displayed_past_studiensemester'] = [ + "type" => "number", + "label" => $this->p->t('stv', 'settings_no_displayed_past_sem'), + "value" => $data['number_displayed_past_studiensemester'] + ?? $number_displayed_past_studiensemester_default + ]; + + #font_size + $result = $this->VariableModel->getVariables(getAuthUID(), ['stv_font_size']); + $data = $this->getDataOrTerminateWithError($result); + $config['font_size'] = [ + "type" => "select", + "label" => $this->p->t('stv', 'settings_fontsize'), + "value" => $data['stv_font_size'] ?? "fs_normal", + "options" => [ + "fs_xx-small" => $this->p->t('stv', 'settings_fontsize_xx-small'), + "fs_x-small" => $this->p->t('stv', 'settings_fontsize_x-small'), + "fs_small" => $this->p->t('stv', 'settings_fontsize_small'), + "fs_normal" => $this->p->t('stv', 'settings_fontsize_normal'), + "fs_big" => $this->p->t('stv', 'settings_fontsize_big'), + "fs_huge" => $this->p->t('stv', 'settings_fontsize_huge') + ] + ]; + + #others + Events::trigger('stv_config_get', function & () use (&$config) { + return $config; + }); + + $this->terminateWithSuccess($config); + } + + /** + * set App config + */ + public function set() + { + $this->load->model('system/Variable_model', 'VariableModel'); + $this->load->library('form_validation'); + + $this->form_validation->set_rules( + 'number_displayed_past_studiensemester', + $this->p->t('stv', 'settings_no_displayed_past_sem'), + 'required|integer' + ); + $this->form_validation->set_rules( + 'font_size', + $this->p->t('stv', 'settings_fontsize'), + 'required|in_list[fs_xx-small,fs_x-small,fs_small,fs_normal,fs_big,fs_huge]' + ); + + Events::trigger('stv_config_validation', $this->form_validation); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $this->VariableModel->setVariable( + getAuthUID(), + 'number_displayed_past_studiensemester', + $this->input->post('number_displayed_past_studiensemester') + ); + $this->VariableModel->setVariable( + getAuthUID(), + 'stv_font_size', + $this->input->post('font_size') + ); + + Events::trigger('stv_config_set', $this->input); + + $this->terminateWithSuccess(); + } + + /* * Get the config for the student filters * * @return void @@ -240,7 +331,10 @@ class Config extends FHCAPI_Controller ]; $result['status'] = [ 'title' => 'Status', - 'component' => absoluteJsImportUrl('public/js/components/Stv/Studentenverwaltung/Details/MultiStatus.js') + 'component' => absoluteJsImportUrl('public/js/components/Stv/Studentenverwaltung/Details/MultiStatus.js'), + 'config' => [ + 'showStatusVorruecken' => defined('STATUS_VORRUECKEN_ANZEIGEN') ? STATUS_VORRUECKEN_ANZEIGEN : true, + ] ]; $result['documents'] = [ 'title' => $this->p->t('stv', 'tab_documents'), @@ -271,7 +365,6 @@ class Config extends FHCAPI_Controller $result['messages'] = [ 'title' => $this->p->t('stv', 'tab_messages'), 'component' => absoluteJsImportUrl('public/js/components/Stv/Studentenverwaltung/Details/Messages.js'), - 'showOnlyWithUid' => true ]; $result['grades'] = [ @@ -407,11 +500,25 @@ class Config extends FHCAPI_Controller ] ]; + if($this->permissionlib->isBerechtigt('basis/person')) + { + $result['combinePeople'] = [ + 'title' => $this->p->t('stv', 'tab_combine_people'), + 'component' => './Stv/Studentenverwaltung/Details/CombinePeople.js', + 'config' => $config['combinePeople'] + ]; + } + $result['kontaktieren'] = [ 'title' => $this->p->t('stv', 'tab_kontaktieren'), 'component' => absoluteJsImportUrl('public/js/components/Stv/Studentenverwaltung/Details/Kontaktieren.js'), ]; + $result['messages'] = [ + 'title' => $this->p->t('stv', 'tab_messages'), + 'component' => absoluteJsImportUrl('public/js/components/Stv/Studentenverwaltung/Details/Messages.js'), + ]; + Events::trigger('stv_conf_students', function & () use (&$result) { return $result; }); diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php index 4f33405ae..9f54d0aa4 100644 --- a/application/controllers/api/frontend/v1/stv/Dokumente.php +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -590,14 +590,14 @@ class Dokumente extends FHCAPI_Controller $documents = [ buildDropdownEntryPrintArray("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uid, 10, null), - buildDropdownEntryPrintArray("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uid, 20, null), - buildDropdownEntryPrintArray("ausbildungsvertrag_en", "Ausbildungsvertrag Zweisprachig", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uid, 21, null), + buildDropdownEntryPrintArray("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf&prestudent_id=$prestudent_id", null,20, null), + buildDropdownEntryPrintArray("ausbildungsvertrag_en", "Ausbildungsvertrag Zweisprachig", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&prestudent_id=$prestudent_id", null,21, null), buildDropdownEntryPrintArray("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uid, 25, null), buildDropdownEntryPrintArray("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uid, 26, null), - buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uid, 50, null), - buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uid, 51, null), + buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uid, 50, null), + buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uid, 51, null), buildDropdownEntryPrintArray("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uid", $uid,200, "zutrittskarte.php"), buildDropdownEntryPrintArray("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uid, 60, null), buildDropdownEntryPrintArray("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uid, 61, null), @@ -686,8 +686,8 @@ class Dokumente extends FHCAPI_Controller buildDropdownEntryPrintArray("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uidString, 10, null), buildDropdownEntryPrintArray("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uidString, 20, null), buildDropdownEntryPrintArray("ausbildungsvertrag_en", "Ausbildungsvertrag Englisch", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uidString, 21, null), - buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uidString, 50, null), - buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uidString, 51, null), + buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uidString, 50, null), + buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uidString, 51, null), buildDropdownEntryPrintArray("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uidString", $uidString,200, "zutrittskarte.php"), buildDropdownEntryPrintArray("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uidString, 60, null), buildDropdownEntryPrintArray("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uidString, 61, null), diff --git a/application/controllers/api/frontend/v1/stv/GemeinsameStudien.php b/application/controllers/api/frontend/v1/stv/GemeinsameStudien.php index 97dad48fd..8f3d6419a 100644 --- a/application/controllers/api/frontend/v1/stv/GemeinsameStudien.php +++ b/application/controllers/api/frontend/v1/stv/GemeinsameStudien.php @@ -83,7 +83,7 @@ class GemeinsameStudien extends FHCAPI_Controller { $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); - $this->StudiensemesterModel->addOrder('studienjahr_kurzbz', 'DESC'); + $this->StudiensemesterModel->addOrder('start', 'DESC'); $result = $this->StudiensemesterModel->load(); $data = $this->getDataOrTerminateWithError($result); $this->terminateWithSuccess($data); diff --git a/application/controllers/api/frontend/v1/stv/Grades.php b/application/controllers/api/frontend/v1/stv/Grades.php index dd8f53a27..128316d2b 100644 --- a/application/controllers/api/frontend/v1/stv/Grades.php +++ b/application/controllers/api/frontend/v1/stv/Grades.php @@ -60,7 +60,8 @@ class Grades extends FHCAPI_Controller { $this->load->model('codex/Note_model', 'NoteModel'); - $this->NoteModel->addOrder('note'); + $this->NoteModel->addOrder('notenwert', 'ASC'); + $this->NoteModel->addOrder('bezeichnung', 'ASC'); $result = $this->NoteModel->load(); diff --git a/application/controllers/api/frontend/v1/stv/Gruppen.php b/application/controllers/api/frontend/v1/stv/Gruppen.php index c45165b41..b10cfb328 100644 --- a/application/controllers/api/frontend/v1/stv/Gruppen.php +++ b/application/controllers/api/frontend/v1/stv/Gruppen.php @@ -147,7 +147,8 @@ class Gruppen extends FHCAPI_Controller 'lehre' => true, 'sichtbar' => true, 'aktiv' => true, - 'direktinskription' => false + 'direktinskription' => false, + 'generiert' => false ]); $data = $this->getDataOrTerminateWithError($result); diff --git a/application/controllers/api/frontend/v1/stv/Konto.php b/application/controllers/api/frontend/v1/stv/Konto.php index 384452f3e..ecd58671a 100644 --- a/application/controllers/api/frontend/v1/stv/Konto.php +++ b/application/controllers/api/frontend/v1/stv/Konto.php @@ -239,7 +239,7 @@ class Konto extends FHCAPI_Controller $data[$field] = $this->input->post($field); if (defined('FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE') && isset(unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']])) { - $data['kostenstelle'] = unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']]; + $data['studiengang_kz'] = unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']]; } $result = []; diff --git a/application/controllers/api/frontend/v1/stv/Prestudent.php b/application/controllers/api/frontend/v1/stv/Prestudent.php index 7dc607d1a..d8c8d1ff2 100644 --- a/application/controllers/api/frontend/v1/stv/Prestudent.php +++ b/application/controllers/api/frontend/v1/stv/Prestudent.php @@ -43,7 +43,7 @@ class Prestudent extends FHCAPI_Controller // Load language phrases $this->loadPhrases([ - 'ui', 'studierendenantrag', 'lehre' + 'ui', 'studierendenantrag', 'lehre', 'global' ]); } @@ -98,11 +98,9 @@ class Prestudent extends FHCAPI_Controller 'person_id', 'berufstaetigkeit_code', 'ausbildungcode', - 'zgv_code', 'zgvort', 'zgvdatum', 'zgvnation', - 'zgvmas_code', 'zgvmaort', 'zgvmadatum', 'zgvmanation', @@ -110,7 +108,6 @@ class Prestudent extends FHCAPI_Controller 'bismelden', 'anmerkung', 'dual', - 'zgvdoktor_code', 'zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', @@ -125,6 +122,57 @@ class Prestudent extends FHCAPI_Controller 'standort_code' ]; + // add zgv code fields only if user has permission + $this->load->library('PermissionLib'); + $prestudentres = $this->PrestudentModel->load($prestudent_id); + if(!hasData($prestudentres)) + { + $this->terminateWithError($this->p->t('ui', 'error_fieldNotFound', ['field' => 'Prestudent ' . $prestudent_id])); + } + $prestudent = (getData($prestudentres))[0]; + $bakkZgvStg = $this->permissionlib->getSTG_isEntitledFor('student/editBakkZgv') ?: array(); + $makkZgvStg = $this->permissionlib->getSTG_isEntitledFor('student/editMakkZgv') ?: array(); + $dokZgvStg = $this->permissionlib->getSTG_isEntitledFor('student/editDokZgv') ?: array(); + + if(in_array($prestudent->studiengang_kz, $bakkZgvStg)) + { + $array_allowed_props_prestudent[] = 'zgv_code'; + } + else if(!is_null($this->input->post('zgv_code'))) + { + $this->terminateWithError( + $this->p->t('global', 'zgv') + . ' - ' . + $this->p->t('ui', 'error_keineBerechtigungStg') + ); + } + + if(in_array($prestudent->studiengang_kz, $makkZgvStg)) + { + $array_allowed_props_prestudent[] = 'zgvmas_code'; + } + else if(!is_null($this->input->post('zgvmas_code'))) + { + $this->terminateWithError( + $this->p->t('lehre', 'zgvMaster') + . ' - ' . + $this->p->t('ui', 'error_keineBerechtigungStg') + ); + } + + if(in_array($prestudent->studiengang_kz, $dokZgvStg)) + { + $array_allowed_props_prestudent[] = 'zgvdoktor_code'; + } + else if(!is_null($this->input->post('zgvdoktor_code'))) + { + $this->terminateWithError( + $this->p->t('lehre', 'zgvDoktor') + . ' - ' . + $this->p->t('ui', 'error_keineBerechtigungStg') + ); + } + // add UDFs $result = $this->udflib->getDefinitionForModel($this->PrestudentModel); diff --git a/application/controllers/api/frontend/v1/stv/Projektarbeit.php b/application/controllers/api/frontend/v1/stv/Projektarbeit.php index 75478332f..8740ef3d6 100644 --- a/application/controllers/api/frontend/v1/stv/Projektarbeit.php +++ b/application/controllers/api/frontend/v1/stv/Projektarbeit.php @@ -17,7 +17,8 @@ class Projektarbeit extends FHCAPI_Controller 'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'], 'getFirmen' => ['admin:r', 'assistenz:r'], 'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'], - 'getNoten' => ['admin:r', 'assistenz:r'] + 'getNoten' => ['admin:r', 'assistenz:r'], + 'getStudiensemester' => ['admin:r', 'assistenz:r'] ]); // Load Libraries @@ -40,11 +41,15 @@ class Projektarbeit extends FHCAPI_Controller $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); $this->load->model('education/Note_model', 'NoteModel'); $this->load->model('education/Projektbetreuer_model', 'BetreuerModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); // load libraries $this->load->library('PermissionLib'); } + /** + * Get projekt works for a uid. + */ public function getProjektarbeit() { $student_uid = $this->input->get('uid'); @@ -53,10 +58,7 @@ class Projektarbeit extends FHCAPI_Controller $result = $this->ProjektarbeitModel->getProjektarbeit($student_uid); - if (isError($result)) - { - $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - } + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); if (!hasData($result)) $this->terminateWithSuccess([]); @@ -79,6 +81,9 @@ class Projektarbeit extends FHCAPI_Controller $this->terminateWithSuccess($projektarbeiten); } + /** + * Load a single Projektarbeit by id. + */ public function loadProjektarbeit() { $projektarbeit_id = $this->input->get('projektarbeit_id'); @@ -101,6 +106,9 @@ class Projektarbeit extends FHCAPI_Controller $this->terminateWithSuccess(current($data)); } + /** + * Inwert a Projektarbeit. + */ public function insertProjektarbeit() { $student_uid = $this->input->post('uid'); @@ -128,6 +136,9 @@ class Projektarbeit extends FHCAPI_Controller $this->terminateWithSuccess($data); } + /** + * Update a Projektarbeit by ID. + */ public function updateProjektarbeit() { $projektarbeit_id = $this->input->post('projektarbeit_id'); @@ -157,6 +168,9 @@ class Projektarbeit extends FHCAPI_Controller $this->terminateWithSuccess($data); } + /** + * Delete Projektarbeit by ID after validation. + */ public function deleteProjektarbeit() { $projektarbeit_id = $this->input->post('projektarbeit_id'); @@ -185,6 +199,9 @@ class Projektarbeit extends FHCAPI_Controller return $this->terminateWithSuccess(current(getData($result)) ? : null); } + /** + * Get all active projekt work types. + */ public function getTypenProjektarbeit() { $result = $this->ProjekttypModel->loadWhere(['aktiv' => true]); @@ -194,6 +211,9 @@ class Projektarbeit extends FHCAPI_Controller return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Gets companies by search string. + */ public function getFirmen() { $searchString = $this->input->get('searchString'); @@ -208,6 +228,9 @@ class Projektarbeit extends FHCAPI_Controller return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Get Lehrveranstaltungen by params, incling lehreinheiten for a specific Studiensemester.. + */ public function getLehrveranstaltungen() { $student_uid = $this->input->get('student_uid'); @@ -218,6 +241,7 @@ class Projektarbeit extends FHCAPI_Controller if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); if (!isset($studiensemester_kurzbz)) $this->terminateWithError('Studiensemster missing', self::ERROR_TYPE_GENERAL); + // get Lvs $lvsResult = $this->LehrveranstaltungModel->getLvsForProjektarbeit($student_uid, $studiengang_kz, $additional_lehrveranstaltung_id); if (isError($lvsResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL); @@ -226,6 +250,7 @@ class Projektarbeit extends FHCAPI_Controller foreach ($lvs as $lv) { + // add Lehreinheiten for each Lv for the semester $lehreinheiten = $this->LehreinheitModel->getLesForLv( $lv->lehrveranstaltung_id, $studiensemester_kurzbz ); @@ -250,8 +275,14 @@ class Projektarbeit extends FHCAPI_Controller return $this->terminateWithSuccess($lvs); } + /** + * Get all noten. + */ public function getNoten() { + $this->NoteModel->addOrder('notenwert', 'ASC'); + $this->NoteModel->addOrder('bezeichnung', 'ASC'); + $result = $this->NoteModel->load(); if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); @@ -260,18 +291,27 @@ class Projektarbeit extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Get all Studiensemester, sorted. + */ + public function getStudiensemester() + { + $this->StudiensemesterModel->addOrder('start', 'DESC'); + $result = $this->StudiensemesterModel->load(); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + /** + * Validate Projektarbeit data. + * @param formData + * @return bool true if data valid */ private function _validate($formData) { $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']) ]); @@ -297,9 +337,9 @@ class Projektarbeit extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Extract Projektarbeit data from passed form data. + * @param formData + * @return array */ private function _getProjektarbeitArr($formData) { @@ -321,9 +361,9 @@ class Projektarbeit extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Check if deletion of a Projektarbeit is possible. + * @param $projektarbeit_id + * @return object success if deletion possible, error otherwise. */ private function _validateDelete($projektarbeit_id) { @@ -344,6 +384,11 @@ class Projektarbeit extends FHCAPI_Controller return success(); } + /** + * Checks permissions for a student. + * @param $student_uid + * @return bool true if authorized + */ private function _hasBerechtigungForStudent($student_uid) { if (!$student_uid) diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php index 98567ecde..904fa6167 100644 --- a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -3,7 +3,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); use \DateTime as DateTime; -use CI3_Events as Events; +use \CI3_Events as Events; class Projektbetreuer extends FHCAPI_Controller { @@ -43,6 +43,9 @@ class Projektbetreuer extends FHCAPI_Controller $this->load->library('PermissionLib'); } + /** + * Gets Projektbetreuer data for a Projektarbeit. + */ public function getProjektbetreuer() { $projektarbeit_id = $this->input->get('projektarbeit_id'); @@ -50,21 +53,30 @@ class Projektbetreuer extends FHCAPI_Controller if (!isset($projektarbeit_id)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); - $this->ProjektbetreuerModel->addSelect( - 'projektarbeit_id, person_id, nachname, vorname, note, punkte, round(stunden, 1) AS stunden, - stundensatz, betreuerart_kurzbz, vertrag_id, titelpre, titelpost' - ); - $this->ProjektbetreuerModel->addSelect("CASE - WHEN EXISTS - (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=pers.person_id) - THEN 'Mitarbeiter' - WHEN EXISTS - (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=pers.person_id) - THEN 'Student' - ELSE 'Person' - END AS status"); - $this->ProjektbetreuerModel->addJoin('public.tbl_person pers', 'person_id'); - $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + $qry = " + SELECT * FROM ( + SELECT + projektarbeit_id, person_id, nachname, vorname, note, punkte, round(stunden, 1) AS stunden, + stundensatz, betreuerart_kurzbz, vertrag_id, titelpre, titelpost, + CASE + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=pers.person_id) + THEN 'Mitarbeiter' + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=pers.person_id) + THEN 'Student' + ELSE 'Person' + END AS status + FROM + lehre.tbl_projektbetreuer + JOIN public.tbl_person pers USING (person_id) + WHERE + projektarbeit_id = ? + ) betreuer + ORDER BY + CASE WHEN status = 'Mitarbeiter' THEN 0 WHEN status = 'Person' THEN 1 ELSE 2 END"; + + $result = $this->ProjektbetreuerModel->execReadOnlyQuery($qry, [$projektarbeit_id]); if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); @@ -86,6 +98,7 @@ class Projektbetreuer extends FHCAPI_Controller //~ } //~ } + // add thesis download link (from external extension) foreach ($projektbetreuer as $pb) { $downloadLink = null; @@ -104,6 +117,9 @@ class Projektbetreuer extends FHCAPI_Controller $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); } + /** + * Saves (adds or updates) a single Projektbetreuer for a Projektarbeit. + */ public function saveProjektbetreuer() { $projektarbeit_id = $this->input->post('projektarbeit_id'); @@ -118,14 +134,36 @@ class Projektbetreuer extends FHCAPI_Controller if ($this->_validate($projektbetreuer) == false) $this->terminateWithValidationErrors($this->form_validation->error_array()); + // check if assessor has already been assigned + if (isset($projektbetreuer['person_id'])) + { + $this->ProjektbetreuerModel->addSelect('1'); + $betreuerRes = $this->ProjektbetreuerModel->loadWhere( + [ + 'person_id' => $projektbetreuer['person_id'], + 'projektarbeit_id' => $projektbetreuer['projektarbeit_id'], + 'betreuerart_kurzbz' => $projektbetreuer['betreuerart_kurzbz'] + ] + ); + + if (hasData($betreuerRes) + && (!isset($projektbetreuer['person_id_old']) || $projektbetreuer['person_id'] != $projektbetreuer['person_id_old'])) { + return $this->terminateWithError($this->p->t('projektarbeit', 'betreuerZugewiesen'), self::ERROR_TYPE_GENERAL); + } + } + $result = null; + $stunden = isset($projektbetreuer['stunden']) && !isEmptyString($projektbetreuer['stunden']) ? $projektbetreuer['stunden'] : null; + $stundensatz = + isset($projektbetreuer['stundensatz']) && !isEmptyString($projektbetreuer['stundensatz']) ? $projektbetreuer['stundensatz'] : null; + $betreuer = [ 'projektarbeit_id' => $projektarbeit_id, 'person_id' => $projektbetreuer['person_id'], 'note' => $projektbetreuer['note'], - 'stunden' => $projektbetreuer['stunden'], - 'stundensatz' => $projektbetreuer['stundensatz'], + 'stunden' => $stunden, + 'stundensatz' => $stundensatz, 'betreuerart_kurzbz' => $projektbetreuer['betreuerart_kurzbz'] ]; @@ -152,6 +190,9 @@ class Projektbetreuer extends FHCAPI_Controller $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Delete a Projektbetreuer assignment to a Projektarbeit. + */ public function deleteProjektbetreuer() { $projektarbeit_id = $this->input->post('projektarbeit_id'); @@ -159,21 +200,44 @@ class Projektbetreuer extends FHCAPI_Controller $betreuerart_kurzbz = $this->input->post('betreuerart_kurzbz'); if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) - return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> $this->p->t('projektarbeit', 'projektarbeit').' ID'], self::ERROR_TYPE_GENERAL)); + { + return $this->terminateWithError( + $this->p->t('ui', 'error_missingId', ['id'=> $this->p->t('projektarbeit', 'projektarbeit').' ID'], self::ERROR_TYPE_GENERAL) + ); + } if (!isset($person_id) || !is_numeric($person_id)) return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID'], self::ERROR_TYPE_GENERAL)); if (!isset($betreuerart_kurzbz)) - return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> $this->p->t('projektarbeit', 'betreuerart')], self::ERROR_TYPE_GENERAL)); + { + return $this->terminateWithError( + $this->p->t('ui', 'error_missingId', ['id'=> $this->p->t('projektarbeit', 'betreuerart')], self::ERROR_TYPE_GENERAL) + ); + } + // check permission if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); - $validate = $this->_validateDelete($projektarbeit_id, $person_id); + $validate = $this->_validateDelete($projektarbeit_id, $person_id, $betreuerart_kurzbz); if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); + // check if there is a Projektarbeitsbeurteilung - if yes, it is handled (possibly deleted) by external extension. + $beurteilungDeleteSuccess = true; + + Events::trigger( + 'projektarbeitsbeurteilung_delete', + $projektarbeit_id, + function ($value) use (&$beurteilungDeleteSuccess) { + $beurteilungDeleteSuccess = $value; + } + ); + + // if there is still a Beurteilung, Projektarbeit cannot be deleted - return with error + if (!$beurteilungDeleteSuccess) return $this->terminateWithError($this->p->t('projektarbeit', 'error_paarbeitHatBeurteilung')); + $result = $this->ProjektbetreuerModel->delete( ['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id, 'betreuerart_kurzbz' => $betreuerart_kurzbz] ); @@ -185,9 +249,12 @@ class Projektbetreuer extends FHCAPI_Controller $this->outputJson($result); } - return $this->terminateWithSuccess(current(getData($result)) ? : null); + return $this->terminateWithSuccess(getData($result)); } + /** + * Get all active Betreuerarten. + */ public function getBetreuerarten() { $result = $this->BetreuerartModel->loadWhere(['aktiv' => true]); @@ -197,6 +264,9 @@ class Projektbetreuer extends FHCAPI_Controller return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Get all Noten. + */ public function getNoten() { $result = $this->NoteModel->load(); @@ -206,6 +276,9 @@ class Projektbetreuer extends FHCAPI_Controller return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + /** + * Get default Stundensätze for an employee in a semester. + */ public function getDefaultStundensaetze() { $person_id = $this->input->get('person_id'); @@ -216,6 +289,9 @@ class Projektbetreuer extends FHCAPI_Controller return $this->terminateWithSuccess($result); } + /** + * Get all Projektbetreuer by search string. + */ public function getProjektbetreuerBySearchQuery() { $searchString = $this->input->get('searchString'); @@ -227,9 +303,23 @@ class Projektbetreuer extends FHCAPI_Controller if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - return $this->terminateWithSuccess(hasData($result) ? $this->_addFullNameToBetreuer(getData($result)) : []); + if (!hasData($result)) $this->terminateWithSuccess([]); + + $persons = $this->_addFullNameToBetreuer(getData($result)); + + // sort persons by type (employees first) + usort($persons, function ($a, $b) { + $statusRanks = ['Mitarbeiter' => 0, 'Person' => 1, 'Student' => 2]; + return (isset($statusRanks[$a->status]) ? $statusRanks[$a->status] : count($statusRanks) + 1) + - (isset($statusRanks[$b->status]) ? $statusRanks[$b->status] : count($statusRanks) + 1); + }); + + return $this->terminateWithSuccess($persons); } + /** + * Get person info by Id. + */ public function getPerson() { $person_id = $this->input->get('person_id'); @@ -255,9 +345,7 @@ class Projektbetreuer extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Validate list of Projektbetreuer. */ public function validateProjektbetreuer() { @@ -277,9 +365,9 @@ class Projektbetreuer extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Validation funciton for checking Projektbetreuer input. + * @param $formData Betreuer data + * @return bool true when data is valid */ private function _validate($formData) { @@ -306,26 +394,32 @@ class Projektbetreuer extends FHCAPI_Controller } /** - * - * @param - * @return object success or error + * Check possibility of deletion of a Projektbetreuer. + * @param projektarbeit_id + * @param person_id + * @param betreuerart_kurzbz + * @return object success when delete possible, error otherwise */ - private function _validateDelete($projektarbeit_id, $person_id) + private function _validateDelete($projektarbeit_id, $person_id, $betreuerart_kurzbz) { + // check if contract exists $this->ProjektbetreuerModel->addSelect('vertrag_id'); - $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id]); + $result = $this->ProjektbetreuerModel->loadWhere( + ['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id, 'betreuerart_kurzbz' => $betreuerart_kurzbz] + ); if (isError($result)) return $result; + // if contract exists, no deletion is possible if (hasData($result) && getData($result)[0]->vertrag_id != null) return error($this->p->t('projektarbeit', 'error_betreuerHatVertrag')); return success(); } /** - * - * @param - * @return object success or error + * Add full name to array with Betreuer. + * @param $betreuerArr + * @return array including Betreuer with their full names */ private function _addFullNameToBetreuer($betreuerArr) { diff --git a/application/controllers/api/frontend/v1/stv/Pruefung.php b/application/controllers/api/frontend/v1/stv/Pruefung.php index e205c85b8..4521c2033 100644 --- a/application/controllers/api/frontend/v1/stv/Pruefung.php +++ b/application/controllers/api/frontend/v1/stv/Pruefung.php @@ -18,6 +18,8 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); +use \DateTime as DateTime; + /** * This controller operates between (interface) the JS (GUI) and the back-end * Provides data to the ajax get calls about addresses @@ -111,7 +113,7 @@ class Pruefung extends FHCAPI_Controller // Load language phrases $this->loadPhrases([ - 'global', 'ui','lehre' + 'global', 'ui', 'lehre', 'exam' ]); } @@ -172,174 +174,11 @@ class Pruefung extends FHCAPI_Controller * * @param lehrveranstaltung_id, student_uid, lehreinheit_id * - * @return values on success - * retval 0: pruefung inserted - * reval 1: pruefung and zeugnisnote inserted - * retval 2: pruefung inserted, no insert Zeugnisnote - * (change after date of examination) - * retval 3: pruefung of type Termin2 inserted - * and pruefung of type Termin1 as well - * retval 5: prueufungen Termin 2 and 1 inserted - * and no insert Zeugnisnote (change after date of examination) + * @return void */ public function insertPruefung() { - $authUID = getAuthUID(); - - $this->load->library('form_validation'); - - $this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehrveranstaltung')]), - ]); - $this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]), - ]); - $this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]), - ]); - $this->form_validation->set_rules( - 'datum', - $this->p->t('global', 'datum'), - ['is_valid_date'] - ); - - if ($this->form_validation->run() == false) - { - $this->terminateWithValidationErrors($this->form_validation->error_array()); - } - - //calculate studiensemester_kurzbz this from lehreinheit (case newPruefung) - $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); - if (!$studiensemester_kurzbz) - { - $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); - - $result = $this->LehreinheitModel->load($this->input->post('lehreinheit_id')); - - $lehreinheit = $this->getDataOrTerminateWithError($result); - $studiensemester_kurzbz = current($lehreinheit)->studiensemester_kurzbz; - - if (isError($result)) - { - $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - } - } - - $result = $this->PruefungModel->insert([ - 'lehreinheit_id' => $this->input->post('lehreinheit_id'), - 'student_uid' => $this->input->post('student_uid'), - 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), - 'datum' => $this->input->post('datum'), - 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), - 'note' => $this->input->post('note'), - 'anmerkung' => $this->input->post('anmerkung'), - 'insertamum' => date('c'), - 'insertvon' => $authUID, - ]); - - $this->getDataOrTerminateWithError($result); - - //check if existing zeugnisnote - $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); - - $result = $this->ZeugnisnoteModel->loadWhere(array( - 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), - 'student_uid' => $this->input->post('student_uid'), - 'studiensemester_kurzbz' => $studiensemester_kurzbz)); - - if (isError($result)) - { - $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - } - - if (!hasData($result)) - { - //insert zeugnisnote, if not existing - $result = $this->ZeugnisnoteModel->insert(array( - 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), - 'student_uid' => $this->input->post('student_uid'), - 'studiensemester_kurzbz' => $studiensemester_kurzbz, - 'note' => $this->input->post('note'), - 'uebernahmedatum' => date('c'), - 'benotungsdatum' => $this->input->post('datum'), - 'insertamum' => date('c'), - 'insertvon' => $authUID - )); - - if (isError($result)) - { - $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - } - $this->terminateWithSuccess(1); - } - - $return_code = 0; - - //handling Termin1 if not existing - if($this->input->post('pruefungstyp_kurzbz') == "Termin2") - { - $resultP = $this->PruefungModel->loadWhere(array( - 'lehreinheit_id' => $this->input->post('lehreinheit_id'), - 'student_uid' => $this->input->post('student_uid'), - 'pruefungstyp_kurzbz' => 'Termin1')); - - if (isError($resultP)) - { - $this->terminateWithError(getError($resultP), self::ERROR_TYPE_GENERAL); - } - if(!hasData($resultP)) - { - //check if existing Zeugnisnote - $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); - $this->ZeugnisnoteModel->addJoin('lehre.tbl_lehreinheit', 'lehrveranstaltung_id'); - - $resultP = $this->ZeugnisnoteModel->loadWhere(array( - 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), - 'student_uid' => $this->input->input->post('student_uid'), - 'lehre.tbl_zeugnisnote.studiensemester_kurzbz' => $studiensemester_kurzbz)); - if (isError($resultP)) - { - $this->terminateWithError(getError($resultP), self::ERROR_TYPE_GENERAL); - } - if (!hasData($resultP)) - { - $this->terminateWithError("Zeugnisnote existiert nicht", self::ERROR_TYPE_GENERAL); - } - $dataNote = current(getData($resultP)); - - $resultN = $this->PruefungModel->insert([ - 'lehreinheit_id' => $this->input->post('lehreinheit_id'), - 'student_uid' => $this->input->post('student_uid'), - 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), - 'datum' => $dataNote->benotungsdatum, - 'pruefungstyp_kurzbz' => 'Termin1', - 'note' => $dataNote->note, - 'punkte' => $dataNote->punkte, - 'anmerkung' => 'automatisiert aus Zeugnisnote erstellt', - 'insertamum' => date('c'), - 'insertvon' => $authUID, - ]); - - if (isError($resultN)) { - $this->terminateWithError(getError($resultN), self::ERROR_TYPE_GENERAL); - } - $return_code = 3; - } - } - - $note = current(getData($result)); - $uebernahmedatum = new DateTime($note->uebernahmedatum); - $benotungsdatum = new DateTime($note->benotungsdatum); - - $checkDate = $uebernahmedatum === '' || $benotungsdatum > $uebernahmedatum - ? $benotungsdatum - : $uebernahmedatum; - - if ($checkDate >= $this->input->post('datum') && $note !== $note->note) - { - $this->terminateWithSuccess($return_code + 2); - } - $this->terminateWithSuccess($return_code + 2); + $this->insertOrUpdatePruefung(); } /** @@ -348,8 +187,6 @@ class Pruefung extends FHCAPI_Controller * @param pruefung_id * * @return success or error - * - * no impact on lehre.tbl_zeugnisnote */ public function updatePruefung($pruefung_id) { @@ -359,48 +196,7 @@ class Pruefung extends FHCAPI_Controller if (!$oldpruefung) show_404(); // Pruefung that should be updated does not exist - $authUID = getAuthUID(); - - $this->load->library('form_validation'); - - $this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehrveranstaltung')]), - ]); - $this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]), - ]); - $this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]), - ]); - $this->form_validation->set_rules( - 'datum', - $this->p->t('global', 'datum'), - ['is_valid_date'] - ); - - if ($this->form_validation->run() == false) - { - $this->terminateWithValidationErrors($this->form_validation->error_array()); - } - - $result = $this->PruefungModel->update( - [ - 'pruefung_id' => $pruefung_id - ], - [ 'lehreinheit_id' => $this->input->post('lehreinheit_id'), - 'student_uid' => $this->input->post('student_uid'), - 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), - 'note' => $this->input->post('note'), - 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), - 'datum' => $this->input->post('datum'), - 'anmerkung' => $this->input->post('anmerkung'), - 'updatevon' => $authUID, - 'updateamum' => date('c'), - ] - ); - $this->getDataOrTerminateWithError($result); - - return $this->outputJsonSuccess(true); + $this->insertOrUpdatePruefung($pruefung_id); } /** @@ -574,4 +370,198 @@ class Pruefung extends FHCAPI_Controller return $this->terminateWithSuccess($data); } + + protected function insertOrUpdatePruefung($pruefung_id=null) + { + $authUID = getAuthUID(); + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]), + ]); + $this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]), + ]); + $this->form_validation->set_rules( + 'datum', + $this->p->t('global', 'datum'), + ['is_valid_date'] + ); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $this->PruefungModel->db->trans_start(); + + if ($this->input->post('pruefungstyp_kurzbz') == "Termin2") + { + //Wenn ein 2. Termin angelegt wird, und kein 1. Termin vorhanden ist, + //dann wird auch ein 1. Termin angelegt mit der derzeitigen Zeugnisnote + $resultP = $this->PruefungModel->loadWhere(array( + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'pruefungstyp_kurzbz' => 'Termin1')); + + $termin1 = $this->getDataOrTerminateWithError($resultP); + if (!$termin1) + { + //check if existing Zeugnisnote + $this->ZeugnisnoteModel->addJoin('lehre.tbl_lehreinheit', 'lehrveranstaltung_id'); + + $this->ZeugnisnoteModel->db->where( + 'lehre.tbl_zeugnisnote.studiensemester_kurzbz', + 'lehre.tbl_lehreinheit.studiensemester_kurzbz', + false + ); + $resultP = $this->ZeugnisnoteModel->loadWhere(array( + 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), + 'student_uid' => $this->input->post('student_uid') + )); + + $zeugnisnoten = $this->getDataOrTerminateWithError($resultP); + if ($zeugnisnoten) + { + $zeugnisnote = current($zeugnisnoten); + + $resultN = $this->PruefungModel->insert([ + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'datum' => $zeugnisnote->benotungsdatum, + 'pruefungstyp_kurzbz' => 'Termin1', + 'note' => $zeugnisnote->note, + 'punkte' => $zeugnisnote->punkte, + 'anmerkung' => 'automatisiert aus Zeugnisnote erstellt', + 'insertamum' => date('c'), + 'insertvon' => $authUID, + ]); + + $this->getDataOrTerminateWithError($resultN); + } + //Wenn keine Zeugnisnote vorhanden ist, dann wird kein + //1.Termin angelegt + } + } + + if(intval($pruefung_id) > 0) + { + $result = $this->PruefungModel->update( + [ + 'pruefung_id' => $pruefung_id + ], + [ 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'note' => $this->input->post('note'), + 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), + 'datum' => $this->input->post('datum'), + 'anmerkung' => $this->input->post('anmerkung'), + 'updatevon' => $authUID, + 'updateamum' => date('c'), + ] + ); + } + else + { + $result = $this->PruefungModel->insert([ + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'datum' => $this->input->post('datum'), + 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), + 'note' => $this->input->post('note'), + 'anmerkung' => $this->input->post('anmerkung'), + 'insertamum' => date('c'), + 'insertvon' => $authUID, + 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null + ]); + } + + $this->getDataOrTerminateWithError($result); + + //get studiensemester_kurzbz and lehreveranstaltung_id from lehreinheit + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + $result = $this->LehreinheitModel->load($this->input->post('lehreinheit_id')); + + $lehreinheiten = $this->getDataOrTerminateWithError($result); + + if (!$lehreinheiten) { + $this->terminateWithValidationErrors([ + 'lehreinheit_id' => $this->p->t('ui', 'error_fieldNotFound', [ + 'field' => $this->p->t('lehre', 'lehreinheit') + ]) + ]); + } + $lehreinheit = current($lehreinheiten); + $studiensemester_kurzbz = $lehreinheit->studiensemester_kurzbz; + $lehrveranstaltung_id = $lehreinheit->lehrveranstaltung_id; + + //check if existing zeugnisnote + $result = $this->ZeugnisnoteModel->loadWhere(array( + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'student_uid' => $this->input->post('student_uid'), + 'studiensemester_kurzbz' => $studiensemester_kurzbz + )); + + $zeugnisnoten = $this->getDataOrTerminateWithError($result); + + if (!$zeugnisnoten) + { + //insert zeugnisnote, if not existing + $result = $this->ZeugnisnoteModel->insert(array( + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'student_uid' => $this->input->post('student_uid'), + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'note' => $this->input->post('note'), + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $this->input->post('datum'), + 'insertamum' => date('c'), + 'insertvon' => $authUID, + 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null + )); + + $this->getDataOrTerminateWithError($result); + + $this->PruefungModel->db->trans_complete(); + $this->terminateWithSuccess(); + } + + $note = current($zeugnisnoten); + $uebernahmedatum = new DateTime($note->uebernahmedatum); + $benotungsdatum = new DateTime($note->benotungsdatum); + $pruefungsdatum = new DateTime($this->input->post('datum')); + + $checkDate = $note->uebernahmedatum === '' || $benotungsdatum > $uebernahmedatum + ? $benotungsdatum + : $uebernahmedatum; + + if ($checkDate > $pruefungsdatum && $this->input->post('note') !== $note->note) + { + $this->PruefungModel->db->trans_complete(); + $this->terminateWithSuccess($this->p->t('exam', 'hinweis_changeAfterExamDate')); + } + + //update zeugnisnote, if existing and valid datum + $result = $this->ZeugnisnoteModel->update([ + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'student_uid' => $this->input->post('student_uid'), + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ], [ + 'note' => $this->input->post('note'), + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $this->input->post('datum'), + 'updateamum' => date('c'), + 'updatevon' => $authUID, + 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null + ]); + + $this->PruefungModel->db->trans_complete(); + $this->terminateWithSuccess(); + } } diff --git a/application/controllers/api/frontend/v1/stv/Status.php b/application/controllers/api/frontend/v1/stv/Status.php index e490772db..09a9f18b1 100644 --- a/application/controllers/api/frontend/v1/stv/Status.php +++ b/application/controllers/api/frontend/v1/stv/Status.php @@ -1078,6 +1078,24 @@ class Status extends FHCAPI_Controller $this->terminateWithSuccess(true); } + protected function checkForCriticalChangesBis($oldstatus) + { + $changedFields = array(); + $allowedFields = array('anmerkung', 'statusgrund_id'); + $oldstatus_array = get_object_vars($oldstatus); + foreach($oldstatus_array as $key => $oldValue) + { + $newValue = $this->input->post($key); + if( $newValue !== $oldValue ) + { + $changedFields[] = $key; + } + } + $criticalFieldsChanged = array_diff($changedFields, $allowedFields); + $hasCriticalChangesBis = count($criticalFieldsChanged) > 0 ? true : false; + return $hasCriticalChangesBis; + } + /** * Updates a status entry * @@ -1102,6 +1120,7 @@ class Status extends FHCAPI_Controller $oldstatus = current($oldstatus); + $hasCriticalChangesBis = $this->checkForCriticalChangesBis($oldstatus); $isBerechtigtNoStudstatusCheck = $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'); $isBerechtigtBasisPrestudentstatus = $this->permissionlib->isBerechtigt('basis/prestudentstatus'); @@ -1112,7 +1131,6 @@ class Status extends FHCAPI_Controller $ausbildungssemester = $this->input->post('ausbildungssemester') ?: $oldstatus->ausbildungssemester; $datum = $this->input->post('datum') ?: $oldstatus->datum; - //Form Validation $this->load->library('form_validation'); @@ -1135,9 +1153,15 @@ class Status extends FHCAPI_Controller $this->p->t('global', 'datum'), [ 'is_valid_date', - ['meldestichtag_not_exceeded', function ($value) use ($isBerechtigtNoStudstatusCheck) { + ['meldestichtag_not_exceeded', function ($value) use ($isBerechtigtNoStudstatusCheck, $hasCriticalChangesBis){ if ($isBerechtigtNoStudstatusCheck) - return true; // Skip if access right says so + { + return true; // Skip if access right says so*/ + } + if (!$hasCriticalChangesBis) { + return true; // Skip if no critical changes were made + } + if (!$value) return true; // Error will be handled by the required statement above @@ -1341,6 +1365,7 @@ class Status extends FHCAPI_Controller 'updateamum' => date('c'), 'updatevon' => $authUID ]; + $nullableFields = ['statusgrund_id', 'anmerkung', 'rt_stufe']; foreach ([ 'orgform_kurzbz', 'anmerkung', @@ -1349,8 +1374,17 @@ class Status extends FHCAPI_Controller 'rt_stufe', 'statusgrund_id' ] as $key) - if ($this->input->post($key)) + { + if (in_array($key, $nullableFields)) + { + $updateData[$key] = ($this->input->post($key) === '') ? null : $this->input->post($key); + } + else if ($this->input->post($key)) + { $updateData[$key] = $this->input->post($key); + } + } + if ($this->input->post('bestaetigtam')) { $updateData['bestaetigtam'] = $this->input->post('bestaetigtam'); diff --git a/application/controllers/api/frontend/v1/stv/Student.php b/application/controllers/api/frontend/v1/stv/Student.php index f0172da8a..943577bb3 100644 --- a/application/controllers/api/frontend/v1/stv/Student.php +++ b/application/controllers/api/frontend/v1/stv/Student.php @@ -37,7 +37,7 @@ class Student extends FHCAPI_Controller 'get' => ['admin:r', 'assistenz:r'], 'save' => ['admin:rw', 'assistenz:rw'], 'saveStudent' => ['admin:rw', 'assistenz:rw'], - 'check' => ['admin:rw', 'assistenz:rw'], + 'getPerson' => ['admin:rw', 'assistenz:rw'], 'add' => ['admin:rw', 'assistenz:rw'] // TODO(chris): extra permissions ]); @@ -159,9 +159,9 @@ class Student extends FHCAPI_Controller 'LEFT');*/ $result = $this->PrestudentModel->loadWhere(['tbl_prestudent.prestudent_id' => $prestudent_id]); - + $student = $this->getDataOrTerminateWithError($result); - + if (!$student) return show_404(); @@ -221,7 +221,7 @@ class Student extends FHCAPI_Controller ]); $this->load->library('UDFLib'); - + $result = $this->udflib->getCiValidations($this->PersonModel, $this->input->post()); $udf_field_validations = $this->getDataOrTerminateWithError($result); @@ -232,7 +232,7 @@ class Student extends FHCAPI_Controller $this->terminateWithValidationErrors($this->form_validation->error_array()); $result = $this->StudentModel->loadWhere(['prestudent_id' => $prestudent_id]); - + $student = $this->getDataOrTerminateWithError($result); $uid = $student ? current($student)->student_uid : null; @@ -245,7 +245,6 @@ class Student extends FHCAPI_Controller $person_id = $person ? current($person)->person_id : null; - $array_allowed_props_lehrverband = ['verband', 'semester', 'gruppe']; $update_lehrverband = array(); foreach ($array_allowed_props_lehrverband as $prop) { @@ -305,7 +304,7 @@ class Student extends FHCAPI_Controller } $array_allowed_props_student = ['matrikelnr']; - if($this->isLaufendesSemester($studiensemester_kurzbz)) + if($this->isLaufendesSemester($studiensemester_kurzbz)) { $array_allowed_props_student = ['matrikelnr', 'verband', 'semester', 'gruppe']; } @@ -322,6 +321,10 @@ class Student extends FHCAPI_Controller foreach ($array_allowed_props_benutzer as $prop) { $val = $this->input->post($prop); if ($val !== null) { + if($prop === 'alias' && $val === '') + { + $val = null; + } $update_benutzer[$prop] = $val; } } @@ -462,7 +465,7 @@ class Student extends FHCAPI_Controller return $this->save($student->prestudent_id, $studiensemester_kurzbz); } - public function check() + public function getPerson() { $this->load->library('form_validation'); @@ -480,21 +483,55 @@ class Student extends FHCAPI_Controller $this->load->model('person/Person_model', 'PersonModel'); + $this->PersonModel->addSelect( + 'person_id, vorname, nachname, vornamen, wahlname, gebdatum, staatsbuergerschaft, geburtsnation, sprache, anrede, + titelpost, titelpre, gebort, gebzeit, homepage, geschlecht, matr_nr, + aktiv, unruly, tbl_geschlecht.bezeichnung_mehrsprachig AS geschlecht_bezeichnung' + ); + $this->PersonModel->addJoin('public.tbl_geschlecht', 'geschlecht'); + if ($gebdatum) $this->PersonModel->db->where('gebdatum', (new DateTime($gebdatum))->format('Y-m-d')); if ($vorname && $nachname) { $this->PersonModel->db->or_group_start(); - $this->PersonModel->db->where('LOWER(nachname)', 'LOWER(' . $this->PersonModel->db->escape($nachname) . ')', false); - $this->PersonModel->db->where('LOWER(vorname)', 'LOWER(' . $this->PersonModel->db->escape($vorname) . ')', false); + $this->PersonModel->db->where('LOWER(nachname)', 'LOWER(' . $this->PersonModel->db->escape(trim($nachname)) . ')', false); + $this->PersonModel->db->where('LOWER(vorname)', 'LOWER(' . $this->PersonModel->db->escape(trim($vorname)) . ')', false); $this->PersonModel->db->group_end(); } elseif ($nachname) { - $this->PersonModel->db->or_where('LOWER(nachname)', 'LOWER(' . $this->PersonModel->escape($nachname) . ')', false); + $this->PersonModel->db->or_where('LOWER(nachname)', 'LOWER(' . $this->PersonModel->escape(trim($nachname)) . ')', false); } $result = $this->PersonModel->load(); $data = $this->getDataOrTerminateWithError($result); + $this->load->model('person/Adresse_model', 'AdresseModel'); + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + + foreach ($data as $person) + { + // get adresses + $langIdx = $this->_getLanguageIndex() - 1; + $person->geschlecht_bezeichnung = isset($person->geschlecht_bezeichnung[$langIdx]) ? $person->geschlecht_bezeichnung[$langIdx] : ''; + + // get Adresse + $this->AdresseModel->addOrder('heimatadresse', 'DESC'); + $this->AdresseModel->addOrder('zustelladresse', 'DESC'); + $this->AdresseModel->addOrder('adresse_id', 'DESC'); + $result = $this->AdresseModel->loadWhere(['person_id' => $person->person_id]); + + $adressen = $this->getDataOrTerminateWithError($result); + + $person->adressen = $adressen; + + // get status + $result = $this->PrestudentstatusModel->getLastStatusPerson($person->person_id); + + $status = $this->getDataOrTerminateWithError($result); + + $person->status = $status; + } + $this->terminateWithSuccess($data); } @@ -508,71 +545,52 @@ class Student extends FHCAPI_Controller $_POST['ausbildungssemester'] = 0; } - $this->load->library('form_validation'); + $this->_validate(); - $this->form_validation->set_rules('nachname', 'Nachname', 'callback_requiredIfNotPersonId', [ - '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_fieldRequired', ['field' => $this->p->t('person', 'geschlecht')]) - ]); - $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_fieldRequired', ['field' => $this->p->t('person', 'plz')]) - ]); - $this->form_validation->set_rules('address[gemeinde]', 'Gemeinde', 'callback_requiredIfAddressFunc', [ - '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_fieldRequired', ['field' => $this->p->t('person', 'ort')]) - ]); - $this->form_validation->set_rules('address[address]', 'Adresse', 'callback_requiredIfAddressFunc', [ - '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', '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? - - if (!$this->form_validation->run()) - $this->terminateWithValidationErrors($this->form_validation->error_array()); - - // TODO(chris): This should be in a library + $this->load->model('crm/Student_model', 'StudentModel'); $this->load->model('crm/Prestudent_model', 'PrestudentModel'); $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->load->model('organisation/Lehrverband_model', 'LehrverbandModel'); + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); - $this->db->trans_start(); + $this->load->library('PrestudentLib'); - $result = $this->addInteressent(); + $errors = []; + $person_id = null; - $this->db->trans_complete(); + $this->db->trans_begin(); - if ($this->db->trans_status() === FALSE) - $this->terminateWithError('TODO(chris): TEXT', self::ERROR_TYPE_GENERAL); + $result = $this->_addPerson(); + if (isError($result)) $errors[] = getError($result); - $data = $this->getDataOrTerminateWithError($result); + if (hasData($result)) + { + $person_id = getData($result); + $result = $this->_addAdresse($person_id); + if (isError($result)) $errors[] = getError($result); + $result = $this->_addKontakt($person_id); + if (isError($result)) $errors[] = getError($result); + if (!$this->input->post('personOnly')) $result = $this->_addFirstPrestudentstatus($person_id); + if (isError($result)) $errors[] = getError($result); + } - $this->terminateWithSuccess($data); + if ($this->db->trans_status() === FALSE || !isEmptyArray($errors)) + { + $this->db->trans_rollback(); + $this->terminateWithError(isEmptyArray($errors) ? $this->p->t('stv', 'error_add_student') : $errors); + } + $this->db->trans_commit(); + + $this->terminateWithSuccess($person_id); } - protected function addInteressent() + private function _addPerson() { // Person anlegen wenn nötig $person_id = $this->input->post('person_id'); if (!$person_id) { $this->load->model('person/Person_model', 'PersonModel'); - + $data = [ 'nachname' => $this->input->post('nachname'), 'insertamum' => date('c'), @@ -595,19 +613,25 @@ class Student extends FHCAPI_Controller if ($this->input->post('geschlecht')) $data['geschlecht'] = $this->input->post('geschlecht'); if ($this->input->post('gebdatum')) - $data['gebdatum'] = (new DateTime($this->input->post('datum_obj')))->format('Y-m-d'); + $data['gebdatum'] = (new DateTime($this->input->post('gebdatum')))->format('Y-m-d'); if ($this->input->post('geburtsnation')) $data['geburtsnation'] = $this->input->post('geburtsnation'); if ($this->input->post('staatsbuergerschaft')) $data['staatsbuergerschaft'] = $this->input->post('staatsbuergerschaft'); - $result = $this->PersonModel->insert($data); - $person_id = $this->getDataOrTerminateWithError($result); + return $this->PersonModel->insert($data); } - // Addresse anlegen - $anlegen = $this->input->post('address[func]'); - if ($anlegen) { + return success($person_id); + } + + private function _addAdresse($person_id) + { + // Addresse anlegen? + $anlegen = $this->input->post('address[checked]'); + if ($anlegen === true) + { + // Adresse laden $this->load->model('person/Adresse_model', 'AdresseModel'); $data = [ @@ -619,52 +643,45 @@ class Student extends FHCAPI_Controller 'typ' => 'h', '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([ 'person_id' => $person_id ]); - $address = $this->getDataOrTerminateWithError($result); - if ($address) { - $address = current($address); - $data['updateamum'] = date('c'); - $data['updatevon'] = getAuthUID(); + if (isError($result)) return $result; + + // wenn neue Adresse, heimatadresse setzen + if (!hasData($result)) $data['heimatadresse'] = true; - $result = $this->AdresseModel->update($address->adresse_id, $data); - $this->getDataOrTerminateWithError($result); - } else { - //Wenn keine Adrese vorhanden ist dann eine neue Anlegen - $anlegen = 1; - $data['heimatadresse'] = true; - } - } - if ($anlegen > 0) { $data['person_id'] = $person_id; $data['insertamum'] = date('c'); $data['insertvon'] = getAuthUID(); - if (!isset($data['heimatadresse'])) - $data['heimatadresse'] = !$this->input->post('person_id'); - - $result = $this->AdresseModel->insert($data); - $this->getDataOrTerminateWithError($result); - } + + return $this->AdresseModel->insert($data); } - + + return success(null); + } + + private function _addKontakt($person_id) + { // Kontaktdaten $kontaktdaten = []; - foreach (['email', 'telefon', 'mobil'] as $k) { + + foreach (['email', 'telefon', 'mobil'] as $k) + { $v = $this->input->post($k); if ($v) $kontaktdaten[$k] = $v; } - if (count($kontaktdaten)) { + + if (count($kontaktdaten)) + { $this->load->model('person/Kontakt_model', 'KontaktModel'); - foreach ($kontaktdaten as $typ => $kontakt) { + foreach ($kontaktdaten as $typ => $kontakt) + { $data = [ 'person_id' => $person_id, 'kontakttyp' => $typ, @@ -674,87 +691,70 @@ class Student extends FHCAPI_Controller 'insertvon' => getAuthUID() ]; $result = $this->KontaktModel->insert($data); - $this->getDataOrTerminateWithError($result); + if (isError($result)) return $result; } } + return success(null); + } - $personOnly = $anlegen = $this->input->post('personOnly'); + private function _addFirstPrestudentstatus($person_id) + { + // Prestudent anlegen - if (!$personOnly) + // Anmerkung with Ausbildungsart + $studiengang_kz = $this->input->post('studiengang_kz'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $ausbildungsart = $this->input->post('ausbildungsart'); + $anmerkung = $this->input->post('anmerkungen'); + $foerderrelevant = null; + if ($ausbildungsart) + $anmerkung .= ' Ausbildungsart:' . $ausbildungsart; + + // Incomings und ausserordentliche sind bei Meldung nicht förderrelevant + $incoming = $this->input->post('incoming'); + if ($incoming || substr($studiengang_kz, 0, 1) == '9') + $foerderrelevant = false; + + // Prestudent speichern + $result = $this->prestudentlib->setPrestudent( + $person_id, + $studiengang_kz, + $this->input->post('letzteausbildung'), + $anmerkung, + $foerderrelevant + ); + if (isError($result)) return $result; + if (!hasData($result)) return error('Error when adding prestudent'); + + $prestudent_id = getData($result); + + // wenn Incoming, Incoming Daten hinzufügen + if ($incoming) { - // 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 - } + $statusResult = $this->prestudentlib->setFirstIncoming( + $prestudent_id, + $studiengang_kz, + $studiensemester_kurzbz, + $this->input->post('orgform_kurzbz'), + $this->input->post('studienplan_id') + ); } - // TODO(chris): DEBUG - /*$result = $this->PrestudentModel->loadWhere([ - 'pestudent_id' => 1 - ]); - if (isError($result)) { - return $result; - }*/ + else + { + // Prestudent Rolle Anlegen + $statusResult = $this->prestudentlib->setFirstStatus( + $prestudent_id, + $this->PrestudentstatusModel::STATUS_INTERESSENT, + $studiensemester_kurzbz, + $this->input->post('ausbildungssemester'), + $this->input->post('orgform_kurzbz'), + $this->input->post('studienplan_id') + ); + } + if (!hasData($statusResult)) return error('error when adding status'); + if (isError($statusResult)) return $statusResult; - return success($person_id); + return success($prestudent_id); } public function requiredIfNotPersonId($value) @@ -766,20 +766,84 @@ class Student extends FHCAPI_Controller public function requiredIfAddressFunc($value) { - if (!$_POST['address']['func'] || $_POST['address']['func'] == 0) + if (!isset($_POST['address']['checked']) || !$_POST['address']['checked']) return true; return !!$value; } public function requiredIfStudentFunc($value) { - if ($_POST['personOnly']) + if (isset($_POST['personOnly']) && $_POST['personOnly']) return true; return !!$value; } - public function isValidDate($value) + public function requiredIfStudentAndNotIncomingFunc($value) { - return isValidDate($value); + if ((isset($_POST['incoming']) && $_POST['incoming']) || $this->requiredIfStudentFunc($value)) + return true; + return !!$value; + } + + /** + * Validates input data. Terminates with validation errors, if invalid. + */ + private function _validate() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('nachname', 'Nachname', 'callback_requiredIfNotPersonId', [ + '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_fieldRequired', ['field' => $this->p->t('person', 'geschlecht')]) + ]); + $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[checked]', 'Address', 'required'); + $this->form_validation->set_rules('address[plz]', 'PLZ', 'callback_requiredIfAddressFunc', [ + '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_fieldRequired', ['field' => $this->p->t('person', 'gemeinde')]) + ]); + $this->form_validation->set_rules('address[ort]', 'Ort', 'callback_requiredIfAddressFunc', [ + '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_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', '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_requiredIfStudentAndNotIncomingFunc|integer|less_than[9]|greater_than[-1]', + [ + 'requiredIfStudentAndNotIncomingFunc' => + $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? + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + private function _getLanguageIndex() + { + $this->load->model('system/Sprache_model', 'SpracheModel'); + $this->SpracheModel->addSelect('index'); + $result = $this->SpracheModel->loadWhere(array('sprache' => getUserLanguage())); + $this->addMeta('lang', getUserLanguage()); + + return hasData($result) ? getData($result)[0]->index : 1; } } diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index e16f641b0..c7e34c669 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -765,6 +765,86 @@ class Students extends FHCAPI_Controller $this->terminateWithSuccess($data); } + /** + * @param string $studiensemester_kurzbz + * + * @return void + */ + public function search($studiensemester_kurzbz) + { + $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz + )); + + $this->load->library('SearchLib', [ 'config' => 'searchstv' ]); + $this->load->library('form_validation'); + + $this->form_validation->set_rules('searchstr', 'searchstr', 'required'); + $this->form_validation->set_rules('types[]', 'types', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $result = $this->searchlib->search($this->input->post('searchstr'), $this->input->post('types')); + + $data = $this->getDataOrTerminateWithError($result); + + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + $this->prepareQuery($studiensemester_kurzbz); + + $this->PrestudentModel->addSelect("COALESCE(v.semester::text, CASE WHEN public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') THEN public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)::text ELSE ''::text END) AS semester", false); + $this->PrestudentModel->addSelect('v.verband'); + $this->PrestudentModel->addSelect('v.gruppe'); + + //add status per semester + $this->PrestudentModel->addSelect( + "( + SELECT status_kurzbz + FROM public.tbl_prestudentstatus pss + WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id + AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ORDER BY GREATEST(pss.datum, '0001-01-01') DESC + LIMIT 1 + ) AS statusofsemester" + ); + + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + $prestudent_ids = []; + $student_uids = []; + $this->addMeta('data', $data); + foreach ($data as $row) { + $dataset = json_decode($row->data); + if ($row->type == 'prestudent') { + $prestudent_ids[] = $dataset->prestudent_id; + } elseif ($row->type == 'student') { + $student_uids[] = $dataset->uid; + } + } + + if ($prestudent_ids && $student_uids) { + $this->PrestudentModel->db->where_in('tbl_prestudent.prestudent_id', $prestudent_ids); + $this->PrestudentModel->db->or_where_in('s.student_uid', $student_uids); + } elseif ($prestudent_ids) { + $this->PrestudentModel->db->where_in('tbl_prestudent.prestudent_id', $prestudent_ids); + } elseif ($student_uids) { + $this->PrestudentModel->db->where_in('s.student_uid', $student_uids); + } else { + $this->terminateWithSuccess([]); + } + + $result = $this->PrestudentModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + /** * @param string|null $studiensemester_kurzbz * @param string $type diff --git a/application/controllers/api/frontend/v1/stv/Verband.php b/application/controllers/api/frontend/v1/stv/Verband.php index 9fcd97c91..32ef30a45 100644 --- a/application/controllers/api/frontend/v1/stv/Verband.php +++ b/application/controllers/api/frontend/v1/stv/Verband.php @@ -165,7 +165,17 @@ class Verband extends FHCAPI_Controller $this->StudiengangModel->addDistinct(); $this->StudiengangModel->addSelect("CONCAT(" . $this->StudiengangModel->escape($link) . ", semester) AS link", false); - $this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester ORDER BY verband, gruppe LIMIT 1)) AS name", false); + $this->StudiengangModel->addSelect("CONCAT( + UPPER(CONCAT(typ, kurzbz)), + '-', + semester, + ( + SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END + FROM public.tbl_lehrverband + WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester + ORDER BY verband, gruppe LIMIT 1 + ) + ) AS name", false); $this->StudiengangModel->addSelect('semester'); $this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . '::integer AS stg_kz', false); @@ -173,6 +183,7 @@ class Verband extends FHCAPI_Controller $this->StudiengangModel->addOrder('semester'); if ($org_form !== null) { + $this->StudiengangModel->addSelect("v.orgform_kurzbz"); $this->StudiengangModel->db->group_start(); $this->StudiengangModel->db->where('v.semester', 0); $this->StudiengangModel->db->or_where('v.orgform_kurzbz', $org_form); @@ -188,6 +199,7 @@ class Verband extends FHCAPI_Controller array_unshift($list, [ 'name' => 'PreStudent', 'link' => $link . 'prestudent', + 'no_sem_reload' => true, 'stg_kz' => (int)$studiengang_kz, 'children' => $this->getStdSem($link . 'prestudent/', $studiengang_kz) ]); @@ -203,6 +215,7 @@ class Verband extends FHCAPI_Controller $this->StudienordnungModel->addDistinct(); $this->StudienordnungModel->addSelect("CONCAT(studiengang_kz, '/', p.orgform_kurzbz) AS link"); $this->StudienordnungModel->addSelect("p.orgform_kurzbz AS name"); + $this->StudienordnungModel->addSelect("studiengang_kz AS stg_kz"); $this->StudienordnungModel->addJoin('lehre.tbl_studienplan p', 'studienordnung_id'); @@ -216,7 +229,6 @@ class Verband extends FHCAPI_Controller $list = array_merge($list, $result); } } - } $this->terminateWithSuccess($list); } diff --git a/application/controllers/api/v1/person/Person.php b/application/controllers/api/v1/person/Person.php index 6a373137f..935fbae62 100644 --- a/application/controllers/api/v1/person/Person.php +++ b/application/controllers/api/v1/person/Person.php @@ -233,10 +233,10 @@ class Person extends API_Controller //Quersumme bilden for ($i = 0; $i < 10; $i++) { - $erg += $gewichtung[$i] * $tmpSvnr{$i}; + $erg += $gewichtung[$i] * $tmpSvnr[$i]; } - if ($tmpSvnr{3} != ($erg % 11)) //Vergleichen der Pruefziffer mit Quersumme Modulo 11 + if ($tmpSvnr[3] != ($erg % 11)) //Vergleichen der Pruefziffer mit Quersumme Modulo 11 { return error('SVNR ist ungueltig'); } @@ -244,7 +244,7 @@ class Person extends API_Controller if (mb_strlen($person['svnr']) == 12) { $last = substr($person['svnr'], 10, 12); - if ($last{0} != 'v' || !is_numeric($last{1})) + if ($last[0] != 'v' || !is_numeric($last[1])) { return error('SVNR ist ungueltig'); } diff --git a/application/controllers/jobs/AntragJob.php b/application/controllers/jobs/AntragJob.php index debcfe391..8dc4870ea 100644 --- a/application/controllers/jobs/AntragJob.php +++ b/application/controllers/jobs/AntragJob.php @@ -200,13 +200,14 @@ class AntragJob extends JOB_Controller } /** - * Send reminder to Assistant for Wiedereinstieg Unterbrecher + * Send reminder to Assistant and to Student for Wiedereinstieg Unterbrecher * */ public function sendReminderWiedereinstieg() { $now = new DateTime(); $modifier = $this->config->item('unterbrechung_job_remind_wiedereinstieg_date_modifier'); + if (!$modifier) return $this->logError('Konnte Job nicht starten: Config "unterbrechung_job_remind_wiedereinstieg_date_modifiers" nicht gesetzt'); @@ -230,6 +231,7 @@ class AntragJob extends JOB_Controller $antraege = getData($result) ?: []; $count = 0; + $countReminderStudent = 0; foreach ($antraege as $antrag) { $res = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id); @@ -257,10 +259,92 @@ class AntragJob extends JOB_Controller $data['UID'] = $student->student_uid; } - // NOTE(chris): Sancho mail - if(sendSanchoMail('Sancho_Mail_Antrag_U_Reminder', $data, $antrag->email, 'Reminder: Unterbrechung Wiedereinstieg')) + //Data für Email Student + $result = $this->PrestudentModel->load($antrag->prestudent_id); + $dataPrestudent = current(getData($result)); + $person_id = $dataPrestudent->person_id; + + $this->KontaktModel->addSelect('kontakt'); + + $result = $this->KontaktModel->loadWhere([ + 'person_id'=> $person_id, + 'zustellung' => true, + 'kontakttyp' => 'email' + ]); + + $email_student_privat = null; + $dataKontakt = getData($result); + if ($dataKontakt) { + $stud_private_zustell_emails = array_map(function($kontakt) { + return $kontakt->kontakt; + }, $dataKontakt); + $email_student_privat = implode(', ', $stud_private_zustell_emails); + } + + $email_student_FH = $this->StudentModel->getEmailFH($this->StudentModel->getUID($antrag->prestudent_id)); + + //studiensemester + $result = $this->StudiensemesterModel->getByDate($datum->format('Y-m-d')); + if (hasData($result)) { + $dataSem = current(getData($result)); + } + + $studiensemester = $dataSem->studiensemester_kurzbz; + $studsemShort = substr($studiensemester, 0, 2); + + if($studsemShort == "SS") + { + $data['studSemShort_Eng'] = "summer semester"; + $data['meldenBis'] = "15.1."; + $data['meldenBis_Eng'] = "January 15"; + } + elseif ($studsemShort == "WS") { + $data['studSemShort_Eng'] = "winter semester"; + $data['meldenBis'] = "1.8."; + $data['meldenBis_Eng'] = "August 1"; + } + else + { + $studsemShort = "SS/WS"; + $data['studSemShort_Eng'] = "summer/winter semester"; + $data['meldenBis'] = "15.1. (bei Einstieg ins SS) / 1.8. (bei Einstieg ins WS)"; + $data['meldenBis_Eng'] = "January 15 (for sommer semester enrollment) / August 1 (for winter semester enrollment)"; + } + + $data['studSemShort'] = $studsemShort; + + // NOTE(chris): Sancho mail Assistant + $sancho_assistant_sent = sendSanchoMail('Sancho_Mail_Antrag_U_Reminder', $data, $antrag->email, 'Reminder: Unterbrechung Wiedereinstieg'); + if($sancho_assistant_sent) { $count++; + } + else + { + $this->logError('Error: failed to send Assistant Reminder studierendenantrag_id: ' . $antrag->studierendenantrag_id); + } + //Mail to Student + $sancho_student_sent = sendSanchoMail( + 'Sancho_Mail_Antrag_U_Remind_Stud', + $data, + $email_student_FH, + 'Reminder: Unterbrechung Wiedereinstieg', + '', + '', + '', + $email_student_privat); + + if($sancho_student_sent) + { + $countReminderStudent++; + } + else + { + $this->logError('Error: failed to send Student Reminder studierendenantrag_id: ' . $antrag->studierendenantrag_id); + } + + if($sancho_assistant_sent && $sancho_student_sent) + { $this->StudierendenantragstatusModel->insert([ 'studierendenantrag_id' => $antrag->studierendenantrag_id, 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_REMINDERSENT, @@ -268,7 +352,7 @@ class AntragJob extends JOB_Controller ]); } } - $this->logInfo($count . ' Reminder gesendet - Ende Job sendReminderWiedereinstieg'); + $this->logInfo($count . ' Reminder an Assistenz und ' . $countReminderStudent . ' Reminder an Student gesendet - Ende Job sendReminderWiedereinstieg'); } /** diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index 1a4f566e6..eaa207ff1 100644 --- a/application/controllers/system/infocenter/InfoCenter.php +++ b/application/controllers/system/infocenter/InfoCenter.php @@ -22,6 +22,7 @@ class InfoCenter extends Auth_Controller const REIHUNGSTESTABSOLVIERT_PAGE = 'reihungstestAbsolviert'; const ABGEWIESEN_PAGE = 'abgewiesen'; const AUFGENOMMEN_PAGE = 'aufgenommen'; + const ONBOARDING_PAGE = 'onboarding'; const SHOW_DETAILS_PAGE = 'showDetails'; const SHOW_ZGV_DETAILS_PAGE = 'showZGVDetails'; const ZGV_UBERPRUEFUNG_PAGE = 'ZGVUeberpruefung'; @@ -116,6 +117,7 @@ class InfoCenter extends Auth_Controller 'index' => 'infocenter:r', 'freigegeben' => 'infocenter:r', 'abgewiesen' => 'infocenter:r', + 'onboarding' => 'infocenter:r', 'aufgenommen' => 'infocenter:r', 'reihungstestAbsolviert' => 'infocenter:r', 'showDetails' => 'infocenter:r', @@ -230,6 +232,13 @@ class InfoCenter extends Auth_Controller $this->load->view('system/infocenter/infocenterAbgewiesen.php'); } + + public function onboarding() + { + $this->_setNavigationMenu(self::ONBOARDING_PAGE); // define the navigation menu for this page + + $this->load->view('system/infocenter/onboarding.php'); + } /** * Aufgenommene page of the InfoCenter tool @@ -1553,6 +1562,7 @@ class InfoCenter extends Auth_Controller $reihungstestAbsolviertLink = site_url(self::INFOCENTER_URI.'/'.self::REIHUNGSTESTABSOLVIERT_PAGE); $abgewiesenLink = site_url(self::INFOCENTER_URI.'/'.self::ABGEWIESEN_PAGE); $aufgenommenLink = site_url(self::INFOCENTER_URI.'/'.self::AUFGENOMMEN_PAGE); + $onboardingLink = site_url(self::INFOCENTER_URI.'/'.self::ONBOARDING_PAGE); $currentFilterId = $this->input->get(self::FILTER_ID); if (isset($currentFilterId)) @@ -1561,6 +1571,7 @@ class InfoCenter extends Auth_Controller $reihungstestAbsolviertLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; $abgewiesenLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; $aufgenommenLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; + $onboardingLink .= '?'.self::PREV_FILTER_ID.'='.$currentFilterId; } $this->navigationlib->setSessionMenu( @@ -1624,6 +1635,18 @@ class InfoCenter extends Auth_Controller '', // target 40 // sort ), + 'ohnePrestudent' => $this->navigationlib->oneLevel( + 'Electronic Onboarding', // description + $onboardingLink, // link + null, // children + 'users', // icon + null, // subscriptDescription + false, // expand + null, // subscriptLinkClass + null, // subscriptLinkValue + '', // target + 50 // sort + ), ) ); } @@ -1650,6 +1673,8 @@ class InfoCenter extends Auth_Controller $link = site_url(self::ZGV_UEBERPRUEFUNG_URI); if ($origin_page === self::ABGEWIESEN_PAGE) $link = site_url(self::INFOCENTER_URI.'/'.self::ABGEWIESEN_PAGE); + if ($origin_page === self::ONBOARDING_PAGE) + $link = site_url(self::INFOCENTER_URI.'/'.self::ONBOARDING_PAGE); if ($origin_page === self::AUFGENOMMEN_PAGE) $link = site_url(self::INFOCENTER_URI.'/'.self::AUFGENOMMEN_PAGE); @@ -1691,6 +1716,7 @@ class InfoCenter extends Auth_Controller $freigegebenLink = site_url(self::INFOCENTER_URI.'/'.self::FREIGEGEBEN_PAGE); $absolviertLink = site_url(self::INFOCENTER_URI.'/'.self::REIHUNGSTESTABSOLVIERT_PAGE); $abgewiesenLink = site_url(self::INFOCENTER_URI.'/'.self::ABGEWIESEN_PAGE); + $onboardingLink = site_url(self::INFOCENTER_URI.'/'.self::ONBOARDING_PAGE); $prevFilterId = $this->input->get(self::PREV_FILTER_ID); if (isset($prevFilterId)) { @@ -1767,6 +1793,24 @@ class InfoCenter extends Auth_Controller ) ); } + if($page == self::ONBOARDING_PAGE) + { + $this->navigationlib->setSessionElementMenu( + 'onboarding', + $this->navigationlib->oneLevel( + 'Electronic Onboarding', // description + $onboardingLink, // link + null, // children + 'users', // icon + null, // subscriptDescription + false, // expand + null, // subscriptLinkClass + null, // subscriptLinkValue + '', // target + 50 // sort + ) + ); + } } /** diff --git a/application/libraries/PrestudentLib.php b/application/libraries/PrestudentLib.php index 2d795369f..a57533da0 100644 --- a/application/libraries/PrestudentLib.php +++ b/application/libraries/PrestudentLib.php @@ -35,6 +35,90 @@ class PrestudentLib $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel'); } + /** + * Sets initial prestudent entry, no status yet. + * @return object success or error + */ + public function setPrestudent( + $person_id, + $studiengang_kz, + $ausbildungscode, + $anmerkung, + $foerderrelevant + ) + { + // Prestudent anlegen + $data = [ + 'aufmerksamdurch_kurzbz' => 'k.A.', + 'person_id' => $person_id, + 'studiengang_kz' => $studiengang_kz, + 'ausbildungcode' => $ausbildungscode, + 'anmerkung' => $anmerkung, + 'reihungstestangetreten' => false, + 'bismelden' => true, + 'foerderrelevant' => $foerderrelevant, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]; + + // Wenn die Person schon im System erfasst ist, dann die ZGV des Datensatzes uebernehmen + $this->_ci->PrestudentModel->addSelect('public.tbl_prestudent.*, public.tbl_person.vorname, public.tbl_person.nachname'); + $this->_ci->PrestudentModel->addJoin('public.tbl_person', 'person_id'); + $this->_ci->PrestudentModel->addOrder('zgvmas_code'); + $this->_ci->PrestudentModel->addOrder('zgv_code', 'DESC'); + $this->_ci->PrestudentModel->addLimit(1); + $result = $this->_ci->PrestudentModel->loadWhere([ + 'person_id' => $person_id, + 'zgv_code IS NOT NULL' => null + ]); + + if (isError($result)) return $result; + + if (hasData($result)) { + $prestudent = getData($result)[0]; + 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 + return $this->_ci->PrestudentModel->insert($data); + } + + /** + * Sets first status of a prestudent.! + * @return object success or error + */ + public function setFirstStatus( + $prestudent_id, + $status_kurzbz, + $studiensemester_kurzbz, + $ausbildungssemester = null, + $orgform_kurzbz = null, + $studienplan_id = null + ) + { + // Prestudent Rolle Anlegen + $data = [ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $status_kurzbz, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'ausbildungssemester' => $ausbildungssemester ?: 0, + 'orgform_kurzbz' => $orgform_kurzbz ?: null, + 'studienplan_id' => $studienplan_id ?: null, + 'datum' => date('Y-m-d'), + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]; + + return $this->_ci->PrestudentstatusModel->insert($data); + } + public function setAbbrecher( $prestudent_id, $studiensemester_kurzbz, @@ -603,9 +687,6 @@ class PrestudentLib $now = date('c'); $today = date('Y-m-d'); - $jahr = mb_substr($studiensemester_kurzbz, 4, 2); - - // Genererate Personenkennzeichen $personenkennzeichen = $this->_ci->StudentModel->generateMatrikelnummer2( $student_data->studiengang_kz, @@ -615,8 +696,9 @@ class PrestudentLib if (isError($personenkennzeichen)) return $personenkennzeichen; $personenkennzeichen = getData($personenkennzeichen); - - + + $jahr = mb_substr($personenkennzeichen, 0, 2); + // Generate UID $uid = $this->_ci->StudentModel->generateUID( $student_data->kurzbz, @@ -889,6 +971,155 @@ class PrestudentLib ); } + /** + * Creates an incoming, saves necessary data for an incoming. + * @param $prestudent_id existing prestudent, for which incoming entry is created + * @param $studiengang_kz Studiengang assigned to incoming + * @param $studiensemester_kurzbz start semester for incoming + * @return object success if incoming successfully saved, or error + */ + public function setFirstIncoming($prestudent_id, $studiengang_kz, $studiensemester_kurzbz, $orgform_kurzbz, $studienplan_id) + { + // Verband and Ausbildungssemester for incoming + $authUID = getAuthUID(); + $incomingVerband = 'I'; + $incomingAusbildungssemester = '0'; + + // get prestudent + $this->_ci->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); + $this->_ci->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz'); + $result = $this->_ci->PrestudentModel->load($prestudent_id); + + if (isError($result)) return $result; + if (!hasData($result)) return error('No prestudent'); + + $student_data = getData($result)[0]; + + $result = $this->setFirstStatus( + $prestudent_id, + $this->_ci->PrestudentstatusModel::STATUS_INCOMING, + $studiensemester_kurzbz, + $incomingAusbildungssemester, + $orgform_kurzbz, + $studienplan_id + ); + if (isError($result)) return $result; + if (!hasData($result)) return error('Error when adding prestudentstatus'); + + // generate Personenkennzeichen + $result = $this->_ci->StudentModel->generateMatrikelnummer2($studiengang_kz, $studiensemester_kurzbz); + if (isError($result)) return $result; + if (!hasData($result)) return error('No personenkennzeichen could be generated'); + + $personenkennzeichen = getData($result); + + $jahr = mb_substr($personenkennzeichen, 0, 2); + $stg = mb_substr($personenkennzeichen, 3, 4); + + $nachname_clean = mb_strtolower(sanitizeProblemChars($student_data->nachname)); + $vorname_clean = mb_strtolower(sanitizeProblemChars($student_data->vorname)); + $nachname_clean = str_replace(' ','_', $nachname_clean); + $vorname_clean = str_replace(' ','_', $vorname_clean); + + // get Studiengang data + $result = $this->_ci->StudiengangModel->load(ltrim($stg, '0')); + if (isError($result)) return $result; + if (!hasData($result)) return error('No Studiengang'); + + $stgObj = getData($result)[0]; + + // gernerate uid + $result = $this->_ci->StudentModel->generateUID($stgObj->kurzbz, $jahr, $stgObj->typ, $personenkennzeichen, $vorname_clean, $nachname_clean); + if (isError($result)) return $result; + if (!hasData($result)) return error("UID could not be generated"); + $uid = getData($result); + + //Benutzerdatensatz anlegen + $benutzer = [ + 'uid' => $uid, + 'person_id' => $student_data->person_id, + 'aktiv' => true, + 'aktivierungscode' => $this->_ci->BenutzerModel->generateActivationkey() + ]; + + // Generate Alias + $alias = ''; + if (!defined('GENERATE_ALIAS_STUDENT') || GENERATE_ALIAS_STUDENT === true) + { + $result = $this->_ci->BenutzerModel->generateAliasFromName($student_data->vorname, $student_data->nachname); + if (isError($result)) + return $result; + $alias = getData($result); + } + + $benutzer['alias'] = $alias; + $benutzer['insertamum'] = date('Y-m-d H:i:s'); + $benutzer['insertvon'] = $authUID; + + $result = $this->_ci->BenutzerModel->insert($benutzer); + + if (isError($result)) return $result; + + // Studentendatensatz anlegen + $student = [ + 'student_uid' => $uid, + 'matrikelnr' => $personenkennzeichen, + 'prestudent_id' => $prestudent_id, + 'studiengang_kz' => $studiengang_kz, + 'semester' => $incomingAusbildungssemester, + 'verband' => $incomingVerband, + 'gruppe' => ' ' + ]; + + $result = $this->_ci->LehrverbandModel->loadWhere([ + 'studiengang_kz' => $student['studiengang_kz'], + 'semester' => $student['semester'], + 'verband' => $student['verband'], + 'gruppe' => $student['gruppe'] + ]); + + if (isError($result)) return $result; + + if (!hasData($result)) + { + // Add Lehrverband if it does not exist + $result = $this->_ci->LehrverbandModel->insert([ + 'studiengang_kz' => $student_data->studiengang_kz, + 'semester' => $student['semester'], + 'verband' => $student['verband'], + 'gruppe' => $student['gruppe'], + 'bezeichnung' => 'Incoming', + 'aktiv' => true + ]); + + if (isError($result)) return $result; + } + + // add student + $student['insertamum'] = date('Y-m-d H:i:s'); + $student['insertvon'] = $authUID; + + $result = $this->_ci->StudentModel->insert($student); + if (isError($result)) return $result; + + // Add Studentlehrverband + $result = $this->_ci->StudentlehrverbandModel->insert([ + 'student_uid' => $uid, + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'studiengang_kz' => $student_data->studiengang_kz, + 'semester' => $incomingAusbildungssemester, + 'verband' => $incomingVerband, + 'gruppe' => ' ', + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => $authUID + ]); + + if (isError($result)) + return $result; + + return success($prestudent_id); + } + protected function setBasic($authUID, $now, $status_kurzbz, $prestudent_id, $studiensemester_kurzbz, $ausbildungssemester, $statusgrund_id = null) { $result = $this->_ci->PrestudentstatusModel->getLastStatus($prestudent_id); diff --git a/application/models/crm/Prestudentstatus_model.php b/application/models/crm/Prestudentstatus_model.php index de91319b9..c0ed8595e 100644 --- a/application/models/crm/Prestudentstatus_model.php +++ b/application/models/crm/Prestudentstatus_model.php @@ -290,7 +290,11 @@ class Prestudentstatus_model extends DB_Model */ public function getLastStatusPerson($person_id, $studiensemester_kurzbz = null) { - $query = 'SELECT * + $query = 'SELECT p.*, ps.*, s.*, + stg.kurzbz AS studiengang_kurzbz, stg.kurzbzlang AS studiengang_kurzbzlang, + UPPER(typ::varchar(1) || kurzbz) AS studiengang_kuerzel, + stg.typ AS studiengang_typ, stg.bezeichnung AS studiengang_bezeichnung, stg.english AS studiengang_bezeichnung_english, + stg.orgform_kurzbz AS studiengang_orgform FROM public.tbl_prestudent p JOIN ( SELECT DISTINCT ON(prestudent_id) * @@ -298,7 +302,8 @@ class Prestudentstatus_model extends DB_Model WHERE prestudent_id IN (SELECT prestudent_id FROM public.tbl_prestudent WHERE person_id = ?) ORDER BY prestudent_id, datum desc, insertamum desc ) ps USING(prestudent_id) - JOIN public.tbl_status USING(status_kurzbz)'; + JOIN public.tbl_status s USING(status_kurzbz) + JOIN public.tbl_studiengang stg USING (studiengang_kz)'; $parametersArray = array($person_id); diff --git a/application/models/crm/Student_model.php b/application/models/crm/Student_model.php index 539c3cf56..ca9cfe4c3 100644 --- a/application/models/crm/Student_model.php +++ b/application/models/crm/Student_model.php @@ -27,7 +27,7 @@ class Student_model extends DB_Model $this->addSelect('1'); $result = $this->loadWhere(array('student_uid' => $uid)); - + if(hasData($result)) { @@ -169,7 +169,7 @@ class Student_model extends DB_Model $max = 0; if ($matrikelnrres && hasData($matrikelnrres)) { - $max = mb_substr($matrikelnrres->retval[0]->matrikelnr, 7); + $max = mb_substr(trim(getData($matrikelnrres)[0]->matrikelnr), -3); if (!is_numeric($max)) { $max = (int)$max; } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 7347cf2ca..ccac33bc7 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -316,8 +316,8 @@ class Lehrveranstaltung_model extends DB_Model (SELECT status_kurzbz FROM public.tbl_prestudentstatus WHERE prestudent_id=tbl_student.prestudent_id ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1) as status, tbl_bisio.bisio_id, tbl_bisio.von, tbl_bisio.bis, tbl_student.studiengang_kz AS stg_kz_student, tbl_zeugnisnote.note, tbl_mitarbeiter.mitarbeiter_uid, tbl_person.matr_nr, tbl_benutzer.uid, - UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung - + UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung, + tbl_student.prestudent_id FROM campus.vw_student_lehrveranstaltung JOIN public.tbl_benutzer USING(uid) @@ -386,6 +386,37 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($query, array($lehrveranstaltung_id, $studiensemester_kurzbz)); } + + /** + * Get LV-Leitung of given Lehrveranstaltung ID and Studiensemester. + * + * @param $lehrveranstaltung_id + * @param $studiensemester + * @return array|stdClass|null + */ + public function getLvLeitung($lehrveranstaltung_id, $studiensemester) + { + $params = [$lehrveranstaltung_id, $studiensemester]; + + $qry = " + SELECT + vorname, nachname, mitarbeiter_uid, lehrfunktion_kurzbz + FROM + lehre.tbl_lehreinheit + JOIN lehre.tbl_lehreinheitmitarbeiter lema USING (lehreinheit_id) + JOIN public.tbl_benutzer b ON b.uid = lema.mitarbeiter_uid + JOIN public.tbl_person p using (person_id) + WHERE + tbl_lehreinheit.lehrveranstaltung_id= ? + AND tbl_lehreinheit.studiensemester_kurzbz = ? + AND lehrfunktion_kurzbz = 'LV-Leitung' + ORDER BY + lema.insertamum DESC + LIMIT 1 + "; + + return $this->execQuery($qry, $params); + } /** * Gets all Leiter of Lehrveranstaltungsorganisationseinheit * @param $lehrveranstaltung_id diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 1ca2a18a8..193446402 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -24,17 +24,28 @@ class Projektarbeit_model extends DB_Model public function getProjektarbeit($student_uid, $studiengang_kz = null, $studiensemester_kurzbz = null, $projekttyp = null, $final = null) { $qry = "SELECT - tbl_projektarbeit.*, tbl_projekttyp.bezeichnung, + pa.*, tbl_projekttyp.bezeichnung, tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.lehrveranstaltung_id, - tbl_firma.name AS firma_name + tbl_firma.name AS firma_name, + ( + SELECT + STRING_AGG(trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')), ', ') + FROM + lehre.tbl_projektbetreuer + JOIN public.tbl_person USING (person_id) + WHERE + projektarbeit_id = pa.projektarbeit_id + AND student_uid = pa.student_uid + GROUP BY projektarbeit_id + ) AS projektbetreuer FROM - lehre.tbl_projektarbeit + lehre.tbl_projektarbeit pa JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) JOIN lehre.tbl_lehreinheit USING (lehreinheit_id) JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) LEFT JOIN public.tbl_firma USING (firma_id) WHERE - tbl_projektarbeit.student_uid = ?"; + pa.student_uid = ?"; $params = array($student_uid); @@ -53,16 +64,16 @@ class Projektarbeit_model extends DB_Model if (isset($projekttyp)) { if (is_array($projekttyp)) - $qry .= ' AND tbl_projektarbeit.projekttyp_kurzbz IN ?'; + $qry .= ' AND pa.projekttyp_kurzbz IN ?'; else - $qry .= ' AND tbl_projektarbeit.projekttyp_kurzbz=?'; + $qry .= ' AND pa.projekttyp_kurzbz=?'; $params[] = $projekttyp; } if (isset($final)) { - $qry .= ' AND tbl_projektarbeit.final=?'; + $qry .= ' AND pa.final=?'; $params[] = $final; } diff --git a/application/models/organisation/Studiengang_model.php b/application/models/organisation/Studiengang_model.php index 02f972690..2b235aeb8 100644 --- a/application/models/organisation/Studiengang_model.php +++ b/application/models/organisation/Studiengang_model.php @@ -801,4 +801,73 @@ class Studiengang_model extends DB_Model return $this->execReadOnlyQuery($qry, array($studiengang_kz, $orgform_kurzbz, $studiensemester_kurzbz)); } + + /** + * Get active Studiengänge with Kuerzel by given Studiengang-Kennzahlen. + * Helpful to easily get Studiengänge the user is entitled for. + * + * @param $studiengang_kz_arr + * @param $studiensemester_kurzbz + * @return array|stdClass|null Returns one row per Studiengang. Not considering the Orgforms. + */ + public function getByStgs($studiengang_kz_arr, $studiensemester_kurzbz) + { + if (is_numeric($studiengang_kz_arr)) + { + $studiengang_kz_arr = [$studiengang_kz_arr]; + } + + $qry = ' + SELECT + DISTINCT stg.*, UPPER(typ::varchar(1) || kurzbz) AS kuerzel + FROM + public.tbl_studiengang stg + JOIN lehre.tbl_studienordnung sto USING(studiengang_kz) + JOIN lehre.tbl_studienplan stpl USING(studienordnung_id) + JOIN lehre.tbl_studienplan_semester stplsem USING(studienplan_id) + WHERE + stg.studiengang_kz IN ? + AND stplsem.studiensemester_kurzbz = ? + ORDER BY + stg.kurzbzlang + '; + + return $this->execQuery($qry, [$studiengang_kz_arr, $studiensemester_kurzbz]); + } + + /** + * Get OrgForms of given Studiengang and Studiensemester. + * + * @param $studiengang_kz + * @param $studiensemester_kurzbz + * @return array|stdClass|null + */ + public function getOrgformsByStg($studiengang_kz, $studiensemester_kurzbz) + { + $qry = ' + SELECT + stpl.orgform_kurzbz + FROM + public.tbl_studiengang stg + JOIN lehre.tbl_studienordnung sto USING(studiengang_kz) + JOIN lehre.tbl_studienplan stpl USING(studienordnung_id) + JOIN lehre.tbl_studienplan_semester stplsem USING(studienplan_id) + WHERE + stg.studiengang_kz = ? + AND stg.aktiv = TRUE + AND stplsem.studiensemester_kurzbz = ? + GROUP BY + stpl.orgform_kurzbz + ORDER BY + CASE stpl.orgform_kurzbz + WHEN \'VZ\' THEN 1 + WHEN \'BB\' THEN 2 + WHEN \'DUA\' THEN 3 + ELSE 4 + END, + stpl.orgform_kurzbz; + '; + + return $this->execQuery($qry, [$studiengang_kz, $studiensemester_kurzbz]); + } } diff --git a/application/models/person/Profil_update_model.php b/application/models/person/Profil_update_model.php index 31005c4b7..039810537 100644 --- a/application/models/person/Profil_update_model.php +++ b/application/models/person/Profil_update_model.php @@ -135,7 +135,8 @@ class Profil_update_model extends DB_Model attachment_id, UPPER(public.tbl_studiengang.typ || public.tbl_studiengang.kurzbz) AS studiengang, COALESCE(of.orgform_kurzbz, public.tbl_studiengang.orgform_kurzbz) AS orgform, - NULL as oezuordnung + NULL as oezuordnung, + tbl_student.semester FROM public.tbl_profil_update JOIN public.tbl_profil_update_status ON public.tbl_profil_update_status.status_kurzbz = public.tbl_profil_update.status JOIN public.tbl_student ON public.tbl_student.student_uid=public.tbl_profil_update.uid diff --git a/application/models/ressource/Stundenplan_model.php b/application/models/ressource/Stundenplan_model.php index 389be582d..067e2b790 100644 --- a/application/models/ressource/Stundenplan_model.php +++ b/application/models/ressource/Stundenplan_model.php @@ -535,4 +535,53 @@ class Stundenplan_model extends DB_Model return $this->execQuery($query, [$uid, $uid]); } + + /** + * Get Stundenplantermine for given Lehreinheit. + * + * @param $lehreinheit_id + * @return array|stdClass|null + */ + public function getTermineByLe($lehreinheit_id) + { + $qry = ' + SELECT DISTINCT + datum + FROM + lehre.vw_stundenplan + WHERE + lehreinheit_id = ? + ORDER BY + datum ASC + '; + + return $this->execQuery($qry, [$lehreinheit_id]); + } + + /** + * Get Stundenplantermine for given Lehrveranstaltung of given Studiensemester. + * + * @param $lehrveranstaltung_id + * @param $studiensemester_kurzbz + * @return array|stdClass|null + */ + public function getTermineByLv($lehrveranstaltung_id, $studiensemester_kurzbz) + { + $qry = ' + SELECT DISTINCT + datum + FROM + lehre.vw_stundenplan + WHERE + lehreinheit_id IN ( + SELECT lehreinheit_id + FROM lehre.tbl_lehreinheit + WHERE lehrveranstaltung_id = ? + AND studiensemester_kurzbz = ? + ) + ORDER BY datum ASC + '; + + return $this->execQuery($qry, [$lehrveranstaltung_id, $studiensemester_kurzbz]); + } } diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php index c8ee367d8..2a7418924 100644 --- a/application/models/ressource/Stundensatz_model.php +++ b/application/models/ressource/Stundensatz_model.php @@ -47,7 +47,6 @@ class Stundensatz_model extends DB_Model { $this->load->config('stv'); - $useFixangestelltStundensatz = $this->config->item('tabs')['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz']; $defaultStundensatz = $this->config->item('tabs')['projektarbeit']['defaultProjektbetreuerStundensatz']; $stundensatz = ''; @@ -63,7 +62,7 @@ class Stundensatz_model extends DB_Model { $studiensemester = getData($result)[0]; - if (isset($useFixangestelltStundensatz) && !$useFixangestelltStundensatz) + if (defined('FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ') && !FAS_LV_LEKTORINNENZUTEILUNG_FIXANGESTELLT_STUNDENSATZ) { // load Mitarbeiter $params = [$person_id]; @@ -83,19 +82,30 @@ class Stundensatz_model extends DB_Model if (hasData($result)) { - foreach (getData($result) as $ma) - { - if (!$ma->fixangestellt) - { - $stundensatzRes = $this->getStundensatzByDatum( - $ma->mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre' - ); + $ma = getData($result)[0]; - if (hasData($stundensatzRes)) - $stundensatz = getData($stundensatzRes)[0]->stundensatz; - else - $stundensatz = '0.00'; - } + $this->load->model('vertragsbestandteil/Dienstverhaeltnis_model','DienstverhaeltnisModel'); + $echterdv_result = $this->DienstverhaeltnisModel->existsDienstverhaeltnis( + $ma->mitarbeiter_uid, + $studiensemester->start, + $studiensemester->ende, + 'echterdv' + ); + + if (hasData($echterdv_result)) + { + $stundensatz = null; + } + else + { + $stundensatzRes = $this->getStundensatzByDatum( + $ma->mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre' + ); + + if (hasData($stundensatzRes)) + $stundensatz = getData($stundensatzRes)[0]->stundensatz; + else + $stundensatz = '0.00'; } } else diff --git a/application/views/Nachrichten.php b/application/views/Nachrichten.php index cf34bfd53..0d0e8e707 100644 --- a/application/views/Nachrichten.php +++ b/application/views/Nachrichten.php @@ -40,6 +40,10 @@ $configArray = [ cis-root="" :permissions="" :config="" + + :id ="" + type-id ="" + > diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php index 3c4938c0d..4f2311334 100644 --- a/application/views/Studentenverwaltung.php +++ b/application/views/Studentenverwaltung.php @@ -24,7 +24,8 @@ //'public/css/Lvverwaltung.css' //css tags? ], 'customJSs' => [ - 'vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js' + 'vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js', + 'vendor/moment/luxonjs/luxon.min.js' #'vendor/npm-asset/primevue/tree/tree.min.js', #'vendor/npm-asset/primevue/toast/toast.min.js' ], @@ -55,6 +56,8 @@ $configArray = [ active-addons="" stv-root="" cis-root="" + avatar-url="" + logout-url="" :permissions="" :config="" > diff --git a/application/views/system/infocenter/onboarding.php b/application/views/system/infocenter/onboarding.php new file mode 100644 index 000000000..1f5bae847 --- /dev/null +++ b/application/views/system/infocenter/onboarding.php @@ -0,0 +1,47 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Info Center', + 'jquery3' => true, + 'jqueryui1' => true, + 'jquerycheckboxes1' => true, + 'bootstrap3' => true, + 'fontawesome4' => true, + 'sbadmintemplate3' => true, + 'tablesorter2' => true, + 'ajaxlib' => true, + 'filterwidget' => true, + 'navigationwidget' => true, + 'dialoglib' => true, + 'phrases' => array( + 'person' => array('vorname', 'nachname'), + 'ui' => array('bitteEintragWaehlen') + ), + 'customCSSs' => array('public/css/sbadmin2/tablesort_bootstrap.css', 'public/css/infocenter/infocenterPersonDataset.css'), + 'customJSs' => array('public/js/bootstrapper.js', 'public/js/infocenter/rueckstellung.js', 'public/js/infocenter/infocenterPersonDataset.js') + ) + ); +?> + +
+ + widgetlib->widget('NavigationWidget'); ?> + +
+
+
+
+ +
+
+
+ load->view('system/infocenter/onboardingData.php'); ?> +
+
+
+
+ +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/system/infocenter/onboardingData.php b/application/views/system/infocenter/onboardingData.php new file mode 100644 index 000000000..5ee66fdde --- /dev/null +++ b/application/views/system/infocenter/onboardingData.php @@ -0,0 +1,116 @@ +>0 as bezeichnung + FROM public.tbl_rueckstellung + JOIN public.tbl_rueckstellung_status USING(status_kurzbz) + JOIN public.tbl_person sp ON tbl_rueckstellung.person_id = sp.person_id + WHERE tbl_rueckstellung.rueckstellung_id = + ( + SELECT srueck.rueckstellung_id + FROM public.tbl_rueckstellung srueck + WHERE srueck.person_id = tbl_rueckstellung.person_id + AND datum_bis >= NOW() + ORDER BY srueck.datum_bis DESC LIMIT 1 + ) + ) rueck ON rueck.person_id = p.person_id + WHERE p.person_id NOT IN (SELECT person_id FROM public.tbl_prestudent)'; + + $filterWidgetArray = array( + 'query' => $query, + 'app' => InfoCenter::APP, + 'datasetName' => 'onboarding', + 'filter_id' => $this->input->get('filter_id'), + 'requiredPermissions' => 'infocenter', + 'datasetRepresentation' => 'tablesorter', + 'checkboxes' => 'PersonId', + 'additionalColumns' => array('Details'), + 'columnsAliases' => array( + 'PersonId', + ucfirst($this->p->t('person', 'vorname')) , + ucfirst($this->p->t('person', 'nachname')), + ucfirst($this->p->t('global', 'sperrdatum')), + ucfirst($this->p->t('global', 'gesperrtVon')), + ucfirst($this->p->t('infocenter', 'rueckstelldatum')), + ucfirst($this->p->t('infocenter', 'rueckstellgrund')), + ), + + 'formatRow' => function($datasetRaw) { + /* NOTE: Dont use $this here for PHP Version compatibility */ + $datasetRaw->{'Details'} = sprintf( + 'Details', + site_url('system/infocenter/InfoCenter/showDetails'), + $datasetRaw->{'PersonId'}, + 'onboarding', + (isset($_GET['fhc_controller_id']) ? $_GET['fhc_controller_id'] : ''), + (isset($_GET['filter_id']) ? $_GET['filter_id'] : '') + ); + + if ($datasetRaw->{'LockDate'} == null) + { + $datasetRaw->{'LockDate'} = '-'; + } + + if ($datasetRaw->{'LockUser'} == null) + { + $datasetRaw->{'LockUser'} = '-'; + } + + if ($datasetRaw->{'HoldDate'} == null) + { + $datasetRaw->{'HoldDate'} = '-'; + } + else + { + $datasetRaw->{'HoldDate'} = date_format(date_create($datasetRaw->{'HoldDate'}), 'Y-m-d H:i'); + } + + if ($datasetRaw->{'Rueckstellgrund'} === null) + { + $datasetRaw->{'Rueckstellgrund'} = '-'; + } + + return $datasetRaw; + }, + + 'markRow' => function($datasetRaw) { + + if ($datasetRaw->LockDate != null) + { + return FilterWidget::DEFAULT_MARK_ROW_CLASS; + } + } + + + + ); + + echo $this->widgetlib->widget('FilterWidget', $filterWidgetArray); +?> diff --git a/cis/testtool/externeueberwachung.js b/cis/testtool/externeueberwachung.js new file mode 100644 index 000000000..71951779f --- /dev/null +++ b/cis/testtool/externeueberwachung.js @@ -0,0 +1,15 @@ +(function () { + function sendMessage() { + let frame = window.frames['content']; + if (frame) + frame.postMessage({ type: "proctoringReady" }); + } + + window.addEventListener("message", function (e) + { + if (e.data.indexOf("proctoringReady_") === 0) + { + sendMessage(); + } + }); +})(); diff --git a/cis/testtool/frage.css b/cis/testtool/frage.css new file mode 100644 index 000000000..04024ae53 --- /dev/null +++ b/cis/testtool/frage.css @@ -0,0 +1,30 @@ +.proctoring-blocker +{ + position: fixed; + inset: 0; + z-index: 99999; + backdrop-filter: blur(6px); + pointer-events: all; + user-select: none; +} + +.proctoring-blocker.hidden +{ + display: none !important; +} + +.proctoring-text +{ + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: #fff; + font-size: 16px; + font-family: sans-serif; +} + +.proctoring-blur-fallback +{ + filter: blur(6px); +} diff --git a/cis/testtool/frage.php b/cis/testtool/frage.php index c38229cdf..bf2ee24c5 100644 --- a/cis/testtool/frage.php +++ b/cis/testtool/frage.php @@ -45,7 +45,7 @@ if (!$db = new basis_db()) $PHP_SELF=$_SERVER["PHP_SELF"]; // Start session -session_start(); +require_once './session_init.php'; // If language is changed by language select menu, reset language variables if (isset($_GET['sprache_user']) && !empty($_GET['sprache_user'])) @@ -182,6 +182,12 @@ echo ' if(!isset($_SESSION['pruefling_id'])) die($p->t('testtool/bitteZuerstAnmelden')); +if (!empty($_SESSION['externe_ueberwachung']) && isset($_SESSION['externe_ueberwachung_verified'])): ?> + + + +load($_SESSION['pruefling_id']); diff --git a/cis/testtool/frage_externe_ueberwachung.js b/cis/testtool/frage_externe_ueberwachung.js new file mode 100644 index 000000000..31a7b414f --- /dev/null +++ b/cis/testtool/frage_externe_ueberwachung.js @@ -0,0 +1,53 @@ +(function () { + let ok = false; + let blocker; + + function showBlocker() { + blocker = document.getElementById("proctoringBlocker"); + + if (!blocker) + { + blocker = document.createElement("div"); + blocker.id = "proctoringBlocker"; + blocker.className = "proctoring-blocker"; + blocker.innerHTML = '
Loading...
'; + document.body.appendChild(blocker); + } + document.documentElement.classList.add("proctoring-blur-fallback"); + } + + function block() { + showBlocker(); + blocker.classList.remove("hidden"); + } + + function unblock() { + document.documentElement.classList.remove("proctoring-blur-fallback"); + if (!blocker) return; + blocker.classList.add("hidden"); + } + + const blockTimer = setTimeout(function () { + if (!ok) + block(); + }, 1500); + + window.addEventListener("message", function (e) { + const data = e.data || {}; + + if (data.type === "proctoringReady") + { + ok = true; + clearTimeout(blockTimer); + unblock(); + } + }); + + setTimeout(function () { + if (!ok) { + top.location.href = "resetconnection.php"; + } + }, 3000); +})(); + + diff --git a/cis/testtool/index.php b/cis/testtool/index.php index d235e6ce9..6f2cfac26 100644 --- a/cis/testtool/index.php +++ b/cis/testtool/index.php @@ -1,16 +1,79 @@ TestTool - FH Technikum Wien + + + + @@ -26,3 +89,4 @@ if(isset($_GET['prestudent']) && is_numeric($_GET['prestudent'])) + diff --git a/cis/testtool/login.php b/cis/testtool/login.php index 5a2ae0dea..d028a41ff 100644 --- a/cis/testtool/login.php +++ b/cis/testtool/login.php @@ -40,8 +40,7 @@ if (!$db = new basis_db()) die('Fehler beim Oeffnen der Datenbankverbindung'); // Start session -session_start(); - +require_once './session_init.php'; // Logout (triggered by logout button in menu.php) if (isset($_GET['logout']) && $_GET['logout'] == true) { @@ -173,6 +172,12 @@ if (isset($_REQUEST['prestudent'])) else $reload_menu = true; } + + if ($rt->externe_ueberwachung && defined('TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED') && TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED) + { + $_SESSION['externe_ueberwachung'] = true; + $_SESSION['externe_ueberwachung_verified'] = false; + } } $pruefling = new pruefling(); @@ -339,6 +344,8 @@ if ((isset($_SESSION['prestudent_id']) && !isset($_SESSION['pruefling_id']) && !isset($_SESSION['confirmation_needed']) && !isset($_SESSION['confirmed_code'])) || (isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true && isset($_SESSION['confirmed_code']) && $_SESSION['confirmed_code'] === true && + isset($_SESSION['externe_ueberwachung']) && $_SESSION['externe_ueberwachung'] === true && + isset($_SESSION['externe_ueberwachung_verified']) && $_SESSION['externe_ueberwachung_verified'] === true && isset($_SESSION['prestudent_id']) && !isset($_SESSION['pruefling_id']))) { $pruefling = new pruefling(); @@ -447,14 +454,6 @@ if (isset($_POST['save']) && isset($_SESSION['prestudent_id'])) { e.preventDefault(); }); - // If Browser is any other than Mozilla Firefox and the test includes any MathML, - // show message to use Mozilla Firefox - var ua = navigator.userAgent; - if ((ua.indexOf("Firefox") > -1) == false) - { - $("#alertmsgdiv").html("
BITTE VERWENDEN SIE DEN MOZILLA FIREFOX BROWSER!
(Manche Prüfungsfragen werden sonst nicht korrekt dargestellt.

PLEASE USE MOZILLA FIREFOX BROWSER!
(Otherwise some exam items will not be displayed correctly
"); - //alert('BITTE VERWENDEN SIE DEN MOZILLA FIREFOX BROWSER!\n(Manche Prüfungsfragen werden sonst nicht korrekt dargestellt.\n\nPLEASE USE MOZILLA FIREFOX BROWSER!\n(Ohterwise some exam items will not be displayed correctly.)'); - } }); top.location.href = 'resetconnection.php';"; + exit; +} +else if (isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true && isset($_SESSION['confirmed_code']) && $_SESSION['confirmed_code'] === false) { echo ' @@ -726,7 +731,7 @@ else // LOGIN Site (vor Login) echo ''; echo '
@@ -736,6 +741,12 @@ else // LOGIN Site (vor Login) '.$p->t('testtool/confirmationText').'

+ + '.$p->t('testtool/dsgvoConfirmText').' +

+ + '.$p->t('testtool/procotoringConfirmText').' +

diff --git a/cis/testtool/menu.php b/cis/testtool/menu.php index 7c8b12b9d..11e032f0b 100644 --- a/cis/testtool/menu.php +++ b/cis/testtool/menu.php @@ -34,7 +34,7 @@ if (!$db = new basis_db()) die('Fehler beim Oeffnen der Datenbankverbindung'); // Start session -session_start(); +require_once './session_init.php'; // If language is changed by language select menu, reset language and session variables if(isset($_GET['sprache_user']) && !empty($_GET['sprache_user'])) @@ -61,8 +61,12 @@ $p = new phrasen($sprache_user); db_add_param($_SESSION['studiengang_kz'])." LIMIT 1"; @@ -73,7 +77,7 @@ if (isset($_SESSION['pruefling_id'])) // Link zur Startseite echo ' - '.$p->t('testtool/startseite').' + '.$p->t('testtool/startseite').' '; // Link zur Einleitung @@ -83,7 +87,7 @@ if (isset($_SESSION['pruefling_id'])) { echo ' - '.$p->t('testtool/einleitung').' + '.$p->t('testtool/einleitung').' '; } @@ -379,10 +383,13 @@ if (isset($_SESSION['pruefling_id'])) } } + echo ' + - '.$gebietbezeichnung.' + '.$gebietbezeichnung.' + '; @@ -401,7 +408,7 @@ if (isset($_SESSION['pruefling_id'])) // Link zum Logout echo ' - Logout + Logout '; echo ''; @@ -425,28 +432,6 @@ else e.preventDefault(); }); }); - // Get users Browser - var ua = navigator.userAgent; - - // If Browser is any other than Mozilla Firefox and the test includes any MathML, - // show message to use Mozilla Firefox - if ((ua.indexOf("Firefox") > -1) == false) - { - let hasMathML = ""; - let userLang = ""; - if (hasMathML == true) - { - if (userLang == 'German') - { - alert('BITTE VERWENDEN SIE DEN MOZILLA FIREFOX BROWSER!\n(Manche Prüfungsfragen werden sonst nicht korrekt dargestellt.)'); - } - else if(userLang == 'English') - { - alert('PLEASE USE MOZILLA FIREFOX BROWSER!\n(Ohterwise some exam items will not be displayed correctly.)'); - } - } - } - // Error massage if check_gebiet function returns false $(function() { var invalid_gebiete = ""; @@ -461,5 +446,22 @@ else ''); } }); + + function loadContent(url) + { + if (parent && typeof parent.loadInContent === 'function') + { + parent.loadInContent(url); + return false; + } + + let frame = parent?.frames?.["content"]; + if (frame) + { + frame.location.href = url; + return false; + } + } + diff --git a/cis/testtool/resetconnection.php b/cis/testtool/resetconnection.php new file mode 100644 index 000000000..ab2806a1f --- /dev/null +++ b/cis/testtool/resetconnection.php @@ -0,0 +1,18 @@ +start($_SESSION['prestudent_id'], $_SESSION['reihungstestID'], $_SESSION['sprache']); + $urlSafe = htmlspecialchars($url, ENT_QUOTES); + header("Location: $urlSafe"); + $_SESSION['externe_ueberwachung_verified'] = true; +} \ No newline at end of file diff --git a/cis/testtool/session_init.php b/cis/testtool/session_init.php new file mode 100644 index 000000000..fd7f0b5f3 --- /dev/null +++ b/cis/testtool/session_init.php @@ -0,0 +1,11 @@ +=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.8 <=9" + }, + "suggest": { + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.0.0" + }, + "time": "2022-01-24T15:18:34+00:00" + }, { "name": "fortawesome/font-awesome4", "version": "4.7.0", diff --git a/config/cis.config-default.inc.php b/config/cis.config-default.inc.php index 9985a90d4..1b38a2be6 100644 --- a/config/cis.config-default.inc.php +++ b/config/cis.config-default.inc.php @@ -301,4 +301,16 @@ define ('DEFAULT_ECHTER_DIENSTVERTRAG',[103,111]); // Weiterleiten zu CIS neu (wenn Rechte vorhanden) define('CIS_REDIRECT_TO_CIS4', false); + +//Externe Ueberwachung +define('EXTERNE_UEBERWACHUNG_PROTOCOL_URL', 'https://example.com'); +define('EXTERNE_UEBERWACHUNG_SECRET_KEY', null); +define('EXTERNE_UEBERWACHUNG_INTEGRATION_NAME', 'example'); +define('EXTERNE_UEBERWACHUNG_SESSION_URL', 'https://example.com'); +define('EXTERNE_UEBERWACHUNG_TRIAL_TEST', false); +define('EXTERNE_UEBERWACHUNG_EXAM_PARAMS', []); +define('EXTERNE_UEBERWACHUNG_EXAM_RULES', []); +define('EXTERNE_UEBERWACHUNG_EXAM_SCORE', []); + + ?> diff --git a/config/global.config-default.inc.php b/config/global.config-default.inc.php index f24a302cc..c43cb38d1 100644 --- a/config/global.config-default.inc.php +++ b/config/global.config-default.inc.php @@ -28,11 +28,15 @@ define('CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN',false); define('CIS_LEHRVERANSTALTUNG_GESAMTNOTE_ANZEIGEN', true); define('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN', true); define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN', true); +define('CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN', true); // Wenn gesetzt, werden die Digitale Anwesenheit-Icons nur fuer diese Studiengaenge angezeigt, sonst für alle // define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN_STG', serialize(array('257'))); // define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN_LVA', serialize(array('39455','39481','39480','41906','41905','41904','39459','39512','39454','39482','42230','42231','39458','41921','41922','39457','42896'))); +// Wenn gesetzt, werden die LV-Evaluierung-Icons nur für diese Studiengaenge angezeigt, sonst alle +define('CIS_EVALUIERUNG_ANZEIGEN_STG', serialize((array('335', '585', '914', '298')))); // BIW, MAI, BUB, MIO + // Im CIS Menue Links bei Modulen anzeigen wenn Lehrauftrag define('CIS_LEHRVERANSTALTUNG_MODULE_LINK',true); @@ -360,4 +364,11 @@ define('SANCHO_MAIL_HEADER_IMG', 'sancho_header_DEFAULT.jpg'); // footer image for eigene Mails define('SANCHO_MAIL_FOOTER_IMG', 'sancho_footer_DEFAULT.jpg'); + +// Gibt an, ob in der StudVW der Status vorgerueckt werden kann +define('STATUS_VORRUECKEN_ANZEIGEN', true); + +//externe Ueberwachung im Testtool erlauben +define('TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED', false); + ?> diff --git a/content/statistik/notenspiegel.php b/content/statistik/notenspiegel.php index 1a7651296..0901b834f 100644 --- a/content/statistik/notenspiegel.php +++ b/content/statistik/notenspiegel.php @@ -62,6 +62,11 @@ if(!$rechte->isBerechtigt('student/noten',$studiengang_kz, 's')) $semester = isset($_GET['semester'])?$_GET['semester']:''; $typ = isset($_GET['typ'])?$_GET['typ']:''; +if(isset($_GET['studiensemester']) && preg_match('/[WS]S[0-9]{4}/', $_GET['studiensemester'])) +{ + $semester_aktuell = $_GET['studiensemester']; +} + if($semester=='') die('Bitte ein Semester auswaehlen'); diff --git a/content/statistik/notenspiegel_erweitert.php b/content/statistik/notenspiegel_erweitert.php index 2849a1895..67097ed22 100644 --- a/content/statistik/notenspiegel_erweitert.php +++ b/content/statistik/notenspiegel_erweitert.php @@ -64,6 +64,11 @@ if (!$rechte->isBerechtigt('student/noten', $studiengang_kz, 's')) $semester = isset($_GET['semester']) ? $_GET['semester'] : ''; $typ = isset($_GET['typ']) ? $_GET['typ'] : ''; +if(isset($_GET['studiensemester']) && preg_match('/[WS]S[0-9]{4}/', $_GET['studiensemester'])) +{ + $semester_aktuell = $_GET['studiensemester']; +} + if ($semester == '') die('Bitte ein Semester auswaehlen'); diff --git a/include/File/CSV.php b/include/File/CSV.php index c4c4d44ad..ea67181f1 100644 --- a/include/File/CSV.php +++ b/include/File/CSV.php @@ -178,7 +178,7 @@ class File_CSV return $field; } - if ($quote && $field{0} == $quote && $field{strlen($field)-1} == $quote) { + if ($quote && $field[0] == $quote && $field[strlen($field) - 1] == $quote) { return substr($field, 1, -1); } return $field; @@ -230,7 +230,7 @@ class File_CSV } elseif ($c == "\n" || $c == "\r") { $sub = ($prev == "\r") ? 2 : 1; if ((strlen($buff) >= $sub) && - ($buff{strlen($buff) - $sub} == $quote)) + ($buff[strlen($buff) - $sub] == $quote)) { $in_quote = false; } @@ -312,9 +312,9 @@ class File_CSV $last =& $fields[count($fields) - 1]; // Fallback to read the line with readQuoted when guess // that the simple explode won't work right - if (($last{strlen($last) - 1} == "\n" - && $last{0} == $conf['quote'] - && $last{strlen(rtrim($last)) - 1} != $conf['quote']) + if (($last[strlen($last) - 1] == "\n" + && $last[0] == $conf['quote'] + && $last[strlen(rtrim($last)) - 1] != $conf['quote']) || (count($fields) != $conf['fields']) // XXX perhaps there is a separator inside a quoted field @@ -511,4 +511,4 @@ class File_CSV return true; } } -?> \ No newline at end of file +?> diff --git a/include/File/Util.php b/include/File/Util.php index 941c61441..5474bc2a7 100644 --- a/include/File/Util.php +++ b/include/File/Util.php @@ -96,7 +96,7 @@ class File_Util { if (File_Util::isAbsolute($path)) { if (FILE_WIN32) { - return substr($path, $path{3} == '\\' ? 4 : 3); + return substr($path, $path[3] == '\\' ? 4 : 3); } return ltrim($path, '/'); } @@ -182,7 +182,7 @@ class File_Util if (FILE_WIN32) { return preg_match('/^[a-zA-Z]:(\\\|\/)/', $path); } - return ($path{0} == '/') || ($path{0} == '~'); + return ($path[0] == '/') || ($path[0] == '~'); } /** @@ -244,11 +244,11 @@ class File_Util } else { $cwd = getcwd(); $drive = substr($cwd, 0, 2); - if ($path{0} !== $separator{0}) { + if ($path[0] !== $separator[0]) { $path = substr($cwd, 3) . $separator . $path; } } - } elseif ($path{0} !== $separator) { + } elseif ($path[0] !== $separator) { $path = getcwd() . $separator . $path; } @@ -323,7 +323,7 @@ class File_Util $entries = array(); for ($dir = dir($path); false !== $entry = $dir->read(); ) { - if ($list & FILE_LIST_DOTS || $entry{0} !== '.') { + if ($list & FILE_LIST_DOTS || $entry[0] !== '.') { $isRef = ($entry === '.' || $entry === '..'); $isDir = $isRef || is_dir($path .'/'. $entry); if ( ((!$isDir && $list & FILE_LIST_FILES) || diff --git a/include/externe_ueberwachung.class.php b/include/externe_ueberwachung.class.php new file mode 100644 index 000000000..ecdaac2fc --- /dev/null +++ b/include/externe_ueberwachung.class.php @@ -0,0 +1,216 @@ +getSessionByPrestudent($prestudent_id); + return $this->getSessionStatus($session_id); + } + public function start($prestudent_id, $reihungstest_id, $sprache) + { + $session_id = $this->getSessionByPrestudent($prestudent_id); + + if (!$session_id) + { + $session_id = $this->createSession($prestudent_id); + } + else + { + $status = $this->getSessionStatus($session_id); + + if (in_array($status, array('late_to_start', 'finished'))) + { + $session_id = $this->createSession($prestudent_id); + } + } + + $payload = $this->getPayload($session_id, $prestudent_id, $reihungstest_id, $sprache); + return $this->getStartUrl($payload); + } + + + private function createSession($prestudent_id) + { + if (is_null($prestudent_id)) + { + $this->errormsg = 'Falsche Parameterübergabe'; + return false; + } + + $uuid = $this->genereateUUID(); + + $qry = "INSERT INTO testtool.tbl_externe_ueberwachung (prestudent_id, session_id) + VALUES (". + $this->db_add_param($prestudent_id).",". + $this->db_add_param($uuid).")"; + + if($this->db_query($qry)) + { + return $uuid; + } + else + { + $this->errormsg = 'Fehler beim Speichern der Antwort'; + return false; + } + } + public function getSessionByPrestudent($prestudent_id) + { + if (is_null($prestudent_id)) + { + $this->errormsg = 'Falsche Parameterübergabe'; + return false; + } + + $qry = "SELECT session_id + FROM testtool.tbl_externe_ueberwachung + WHERE prestudent_id = ".$this->db_add_param($prestudent_id, FHC_INTEGER) . " + ORDER BY insertamum DESC + LIMIT 1"; + + if($result = $this->db_query($qry)) + { + if ($row = $this->db_fetch_object($result)) + { + return $row->session_id; + } + else + { + $this->errormsg = 'Daten konnten nicht geladen werden'; + return false; + } + } + else + { + $this->errormsg = 'Fehler bei einer Abfrage'; + return false; + } + } + + public function getSessionStatus($session_id) + { + $payload = $this->getSessionPayload($session_id); + $jwt = $this->createToken($payload); + + $url = $this->getSessionUrl($session_id); + + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Authorization: JWT {$jwt}", + "Content-Type: application/json", + ]); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + curl_close($ch); + + $data = json_decode($response, true); + return isset($data['status']) ? $data['status'] : false; + } + + private function getSessionPayload($session_id) + { + return [ + "session_id" => $session_id, + "iat" => time(), + "exp" => time() + 120, + ]; + } + + private function getPayload($session_id, $prestudent_id, $reihungstest_id, $sprache) + { + $prestudent = new prestudent($prestudent_id); + $person = new Person($prestudent->person_id); + + $reihungstest = new Reihungstest($reihungstest_id); + + $datetime = new DateTime(); + $today = $datetime->format('Y-m-d'); + + $payload = [ + "userId" => $prestudent_id, + "lastName" => $person->nachname, + "firstName" => $person->vorname, + "language" => $sprache === 'German' ? 'de' : 'en', + "accountName" => "technikum_wien", + "accountId" => "technikum_wien", + "examId" => $reihungstest_id . '_' . $today, + "examName" => !is_null(trim($reihungstest->anmerkung)) ? ($reihungstest->anmerkung . '_' . $today) : ($reihungstest_id . '_' . $today), + "duration" => 1440, + "schedule" => false, + "trial" => EXTERNE_UEBERWACHUNG_TRIAL_TEST, + "proctoring" => "offline", + "startDate" => $reihungstest->datum . 'T00:00:00Z', + "endDate" => $reihungstest->datum . 'T23:59:59Z', + "sessionId" => $session_id, + "sessionUrl" => EXTERNE_UEBERWACHUNG_SESSION_URL + ]; + + if (defined('EXTERNE_UEBERWACHUNG_EXAM_PARAMS')) + { + $payload = array_merge($payload, EXTERNE_UEBERWACHUNG_EXAM_PARAMS); + } + + if (defined('EXTERNE_UEBERWACHUNG_EXAM_RULES')) + { + $payload['rules'] = EXTERNE_UEBERWACHUNG_EXAM_RULES; + } + + if (defined('EXTERNE_UEBERWACHUNG_EXAM_SCORE')) + { + $payload['scoreConfig'] = EXTERNE_UEBERWACHUNG_EXAM_SCORE; + } + + return $payload; + } + + private function getSessionUrl($session_id) + { + return EXTERNE_UEBERWACHUNG_PROTOCOL_URL . "/api/v2/integration/simple/". EXTERNE_UEBERWACHUNG_INTEGRATION_NAME . "/sessions/". urlencode($session_id) ."/status/"; + } + + private function getStartUrl($payload) + { + $token = $this->createToken($payload); + $query = http_build_query(['token' => $token]); + + return EXTERNE_UEBERWACHUNG_PROTOCOL_URL . '/integration/simple/'. EXTERNE_UEBERWACHUNG_INTEGRATION_NAME .'/start?' . $query; + } + + private function createToken($payload) + { + return JWT::encode($payload, EXTERNE_UEBERWACHUNG_SECRET_KEY, 'HS256'); + } + + private function genereateUUID() + { + $data = openssl_random_pseudo_bytes(16); + + $data[6] = chr(ord($data[6]) & 0x0f | 0x40); + $data[8] = chr(ord($data[8]) & 0x3f | 0x80); + + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } +} + +?> + + + diff --git a/include/filter.class.php b/include/filter.class.php index c3d1d6ac1..7100e6562 100644 --- a/include/filter.class.php +++ b/include/filter.class.php @@ -240,7 +240,7 @@ class filter extends basis_db { //$value->value = preg_replace('/(.*?)selected=.selected./', '$1', $value->value); //$value->value = preg_replace('/(.*?)\s*[selected=?selected?]/', '$1', $value->value); - //$value->value = preg_replace('/(.*?)\s*selected="selected"\s*/', '${1}', $value->value); + //$value->value = preg_replace('/(.*?)\s*selected="selected"\s*/', '$[1]', $value->value); //$value->value = preg_replace('/^\s*selected=.*?selected.*?\s*/', ' ', $value->value); //$value->value = str_replace('selected=', '', $value->value); diff --git a/include/lehrveranstaltung.class.php b/include/lehrveranstaltung.class.php index 26f846f8e..cc89556c7 100644 --- a/include/lehrveranstaltung.class.php +++ b/include/lehrveranstaltung.class.php @@ -70,6 +70,7 @@ class lehrveranstaltung extends basis_db public $farbe; public $lehrauftrag=true; public $lehrveranstaltung_template_id; // integer + public $evaluierung=true; // boolean public $studienplan_lehrveranstaltung_id; @@ -170,6 +171,7 @@ class lehrveranstaltung extends basis_db $this->benotung = $this->db_parse_bool($row->benotung); $this->lvinfo = $this->db_parse_bool($row->lvinfo); $this->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $this->evaluierung = $this->db_parse_bool($row->evaluierung); // FIXME: LV-Bezeichnung richtig mehrsprachig machen // Zwischenzeitlich 'Italian' zum bezeichnung_arr dazugegeben @@ -244,6 +246,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -394,6 +397,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['Italian'] = $row->bezeichnung; @@ -524,6 +528,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -607,6 +612,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -779,7 +785,7 @@ class lehrveranstaltung extends basis_db insertvon, planfaktor, planlektoren, planpersonalkosten, plankostenprolektor, updateamum, updatevon, sort, zeugnis, projektarbeit, sprache, koordinator, bezeichnung_english, orgform_kurzbz, incoming, lehrtyp_kurzbz, oe_kurzbz, raumtyp_kurzbz, anzahlsemester, semesterwochen, lvnr, semester_alternativ, farbe, lehrveranstaltung_template_id,sws,lvs,alvs,lvps,las,benotung,lvinfo, - lehrauftrag, lehrmodus_kurzbz) VALUES ('. + lehrauftrag, lehrmodus_kurzbz, evaluierung) VALUES ('. $this->db_add_param($this->studiengang_kz). ', '. $this->db_add_param($this->bezeichnung). ', '. $this->db_add_param($this->kurzbz). ', '. @@ -824,7 +830,8 @@ class lehrveranstaltung extends basis_db $this->db_add_param($this->benotung, FHC_BOOLEAN).','. $this->db_add_param($this->lvinfo, FHC_BOOLEAN).','. $this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).','. - $this->db_add_param($this->lehrmodus_kurzbz) + $this->db_add_param($this->lehrmodus_kurzbz).','. + $this->db_add_param($this->evaluierung, FHC_BOOLEAN) .');'; } else @@ -880,7 +887,8 @@ class lehrveranstaltung extends basis_db 'las = '.$this->db_add_param($this->las).', '. 'benotung = '.$this->db_add_param($this->benotung, FHC_BOOLEAN).', '. 'lvinfo = '.$this->db_add_param($this->lvinfo, FHC_BOOLEAN).', '. - 'lehrauftrag = '.$this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).' '. + 'lehrauftrag = '.$this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).', '. + 'evaluierung = '.$this->db_add_param($this->evaluierung, FHC_BOOLEAN).' '. 'WHERE lehrveranstaltung_id = ' . $this->db_add_param($this->lehrveranstaltung_id, FHC_INTEGER, false) . ';'; } @@ -991,6 +999,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1086,6 +1095,7 @@ class lehrveranstaltung extends basis_db $l->benotung = $this->db_parse_bool($row->benotung); $l->lvinfo = $this->db_parse_bool($row->lvinfo); $l->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $l->evaluierung = $this->db_parse_bool($row->evaluierung); $l->bezeichnung_arr['German'] = $row->bezeichnung; $l->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1170,6 +1180,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1271,6 +1282,7 @@ class lehrveranstaltung extends basis_db $obj->benotung = $this->db_parse_bool($row->benotung); $obj->lvinfo = $this->db_parse_bool($row->lvinfo); $obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $obj->evaluierung = $this->db_parse_bool($row->evaluierung); $obj->bezeichnung_arr['German'] = $row->bezeichnung; $obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1396,6 +1408,7 @@ class lehrveranstaltung extends basis_db $obj->lvinfo =$this->db_parse_bool( $lv->lvinfo); $obj->zeugnis = $this->db_parse_bool($lv->zeugnis); $obj->lehrauftrag = $this->db_parse_bool($lv->lehrauftrag); + $obj->evaluierung = $this->db_parse_bool($lv->evaluierung); $values[] = $obj; @@ -1422,6 +1435,7 @@ class lehrveranstaltung extends basis_db $obj->lvinfo =$this->db_parse_bool( $this->lvinfo); $obj->zeugnis = $this->db_parse_bool($this->zeugnis); $obj->lehrauftrag = $this->db_parse_bool($this->lehrauftrag); + $obj->evaluierung = $this->db_parse_bool($this->evaluierung); $values[] = $obj; } @@ -1476,6 +1490,7 @@ class lehrveranstaltung extends basis_db $obj->export = $lv->export; $obj->genehmigung = $lv->genehmigung; $obj->lehrauftrag = $lv->lehrauftrag; + $obj->evaluierung = $lv->evaluierung; $obj->lehre = $lv->lehre; $obj->children = array(); if(count($lv->childs) > 0) @@ -1507,6 +1522,7 @@ class lehrveranstaltung extends basis_db $obj->zeugnis = $this->db_parse_bool($this->zeugnis); $obj->curriculum = $this->db_parse_bool($this->curriculum); $obj->lehrauftrag = $this->lehrauftrag; + $obj->evaluierung = $this->db_parse_bool($this->evaluierung); $values[] = $obj; } @@ -1613,6 +1629,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1700,6 +1717,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1873,6 +1891,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -2003,6 +2022,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->studiengang_kurzbzlang = $row->studiengang_kurzbzlang; @@ -2131,6 +2151,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -2402,6 +2423,7 @@ class lehrveranstaltung extends basis_db $obj->benotung = $this->db_parse_bool($row->benotung); $obj->lvinfo = $this->db_parse_bool($row->lvinfo); $obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $obj->evaluierung = $this->db_parse_bool($row->evaluierung); $obj->bezeichnung_arr['German'] = $row->bezeichnung; $obj->bezeichnung_arr['English'] = $row->bezeichnung_english; diff --git a/include/reihungstest.class.php b/include/reihungstest.class.php index df4134ebf..94d064c25 100644 --- a/include/reihungstest.class.php +++ b/include/reihungstest.class.php @@ -63,6 +63,7 @@ class reihungstest extends basis_db public $zugangs_ueberpruefung = false; //boolean public $zugangscode; //smallint + public $externe_ueberwachung = false; //boolean /** @@ -119,6 +120,7 @@ class reihungstest extends basis_db $this->aufnahmegruppe_kurzbz = $row->aufnahmegruppe_kurzbz; $this->zugangs_ueberpruefung = $this->db_parse_bool($row->zugangs_ueberpruefung); $this->zugangscode = $row->zugangscode; + $this->externe_ueberwachung = $this->db_parse_bool($row->externe_ueberwachung); return true; } @@ -234,7 +236,7 @@ class reihungstest extends basis_db $qry = 'BEGIN; INSERT INTO public.tbl_reihungstest (studiengang_kz, ort_kurzbz, anmerkung, datum, uhrzeit, insertamum, insertvon, updateamum, updatevon, max_teilnehmer, oeffentlich, freigeschaltet, - studiensemester_kurzbz, stufe, anmeldefrist, aufnahmegruppe_kurzbz, zugangs_ueberpruefung, zugangscode) VALUES('. + studiensemester_kurzbz, stufe, anmeldefrist, aufnahmegruppe_kurzbz, zugangs_ueberpruefung, zugangscode, externe_ueberwachung) VALUES('. $this->db_add_param($this->studiengang_kz, FHC_INTEGER).', '. $this->db_add_param($this->ort_kurzbz).', '. $this->db_add_param($this->anmerkung).', '. @@ -250,7 +252,8 @@ class reihungstest extends basis_db $this->db_add_param($this->anmeldefrist).','. $this->db_add_param($this->aufnahmegruppe_kurzbz). ',' . $this->db_add_param($this->zugangs_ueberpruefung, FHC_BOOLEAN).','. - $this->db_add_param($this->zugangscode) . ');'; + $this->db_add_param($this->zugangscode) . ','. + $this->db_add_param($this->externe_ueberwachung, FHC_BOOLEAN) . ');'; } else { @@ -270,7 +273,8 @@ class reihungstest extends basis_db 'anmeldefrist='.$this->db_add_param($this->anmeldefrist).', '. 'aufnahmegruppe_kurzbz='.$this->db_add_param($this->aufnahmegruppe_kurzbz).', '. 'zugangs_ueberpruefung='.$this->db_add_param($this->zugangs_ueberpruefung, FHC_BOOLEAN).', '. - 'zugangscode='.$this->db_add_param($this->zugangscode).' '. + 'zugangscode='.$this->db_add_param($this->zugangscode).', '. + 'externe_ueberwachung='.$this->db_add_param($this->externe_ueberwachung, FHC_BOOLEAN).' '. 'WHERE reihungstest_id='.$this->db_add_param($this->reihungstest_id, FHC_INTEGER, false).';'; } diff --git a/include/securimage/WavFile.php b/include/securimage/WavFile.php index 6d84fc725..d56dbd942 100644 --- a/include/securimage/WavFile.php +++ b/include/securimage/WavFile.php @@ -1532,7 +1532,7 @@ class WavFile } else { // replace for ($i = 0; $i < $sampleBytes; ++$i) { - $this->_samples{$offset + $i} = $sampleBinary{$i}; + $this->_samples[$offset + $i] = $sampleBinary[$i]; } } diff --git a/include/securimage/securimage.php b/include/securimage/securimage.php index 51d876672..820e8b92f 100644 --- a/include/securimage/securimage.php +++ b/include/securimage/securimage.php @@ -1435,7 +1435,7 @@ class Securimage $length = strlen($code['display']); for($i = 0; $i < $length; ++$i) { - $letter = $code['display']{$i}; + $letter = $code['display'][$i]; $letters[] = $letter; } } diff --git a/include/tw/cis_menu_lv.inc.php b/include/tw/cis_menu_lv.inc.php index 29ba54724..03ce016ca 100644 --- a/include/tw/cis_menu_lv.inc.php +++ b/include/tw/cis_menu_lv.inc.php @@ -500,6 +500,27 @@ if((!defined('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN') || CIS_LEHRVERANSTALTU ); } +// LV-Evaluierung NEU +if(defined('CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN') + && CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN + && $angemeldet + && (!defined('CIS_EVALUIERUNG_ANZEIGEN_STG') || in_array($lv->studiengang_kz, unserialize(CIS_EVALUIERUNG_ANZEIGEN_STG))) + && ($rechte->isBerechtigt('extension/lvevaluierung_init'))) +{ + $text='(Pilotphase)'; + + $link= APP_ROOT. 'index.ci.php/extensions/FHC-Core-Evaluierung/Initiierung?lehrveranstaltung_id='. urlencode($lv->lehrveranstaltung_id).'&studiensemester_kurzbz='.urlencode($angezeigtes_stsem); + + $menu[]=array + ( + 'id'=>'extension_lvevaluierung_menu_initiierung', + 'position'=>'140', + 'name'=>$p->t('lvevaluierung/lvevaluierung'). ' - '. strtoupper($p->t('global/neu')), + 'icon'=>'../../../skin/images/button_lvevaluierung.png', + 'link'=> $link, + 'text'=>$text + ); +} //************* Menuepunkte anzeigen **************** diff --git a/locale/de-AT/testtool.php b/locale/de-AT/testtool.php index 6977704cc..b2a1dc38a 100644 --- a/locale/de-AT/testtool.php +++ b/locale/de-AT/testtool.php @@ -53,6 +53,8 @@ $this->phrasen['testtool/fuerFolgendeStgAngemeldet']='Für folgende Studiengäng $this->phrasen['testtool/invalideGebiete']='Ein oder mehrere Fragengebiet/e inkorrekt!
Bitte melden Sie dies der Betreuungsperson.'; $this->phrasen['testtool/confirmationText']='Ich bestätige, den Online-Reihungstest persönlich, selbständig, ohne Hilfe einer zusätzlichen Person und ohne Hilfsmittel zu absolvieren.
I confirm that I will complete the online placement test personally, independently, without the help of an additional person and without any aids.
'; +$this->phrasen['testtool/dsgvoConfirmText']='Ich habe die Datenschutzerklärung gelesen.'; +$this->phrasen['testtool/procotoringConfirmText']='Ich stimme der digitalen Beaufsichtigung beim Online-Reihungstest (Proctoring) zu.'; $this->phrasen['testtool/loginNoetig']='Bitte beachten Sie, dass der Reihungstest erst unmittelbar vor Ihrem Reihungstesttermin von uns aktiviert wird.
Please note that the test will be activated by us immediately before your placement test date.'; $this->phrasen['testtool/start']='Reihungstest jetzt starten'; diff --git a/public/css/Cis4/Cis.css b/public/css/Cis4/Cis.css index ff1b181dd..2bb467048 100644 --- a/public/css/Cis4/Cis.css +++ b/public/css/Cis4/Cis.css @@ -407,6 +407,7 @@ html { background-color: var(--fhc-background); border-color: var(--fhc-border); padding: var(--fhc-cis-main-py) var(--fhc-cis-main-px); + min-width: 0; /* fix flex-grow with tabulator exceeding width */ } #cis-main .fa-arrow-up-right-from-square { @@ -854,4 +855,4 @@ html { #cis-main .modal-footer { background-color: var(--fhc-secondary); -} \ No newline at end of file +} diff --git a/public/css/Studentenverwaltung.css b/public/css/Studentenverwaltung.css index 56e99b937..eb6becc15 100644 --- a/public/css/Studentenverwaltung.css +++ b/public/css/Studentenverwaltung.css @@ -11,6 +11,24 @@ html { font-size: .875em; } +html.fs_xx-small { + font-size: .5em; +} +html.fs_x-small { + font-size: .625em; +} +html.fs_small { + font-size: .75em; +} +html.fs_normal { + font-size: .875em; +} +html.fs_big { + font-size: 1em; +} +html.fs_huge { + font-size: 1.125em; +} #appMenu { width: 300px; @@ -43,6 +61,12 @@ html { flex: 1 1 auto; } +#nav-user-btn img { + object-fit: contain; + height: 2.5rem; + width: 2.5rem; +} + .tabulator-row.disabled.tabulator-row-odd .tabulator-cell { color: var(--gray-400); } @@ -160,4 +184,4 @@ html { .tiny-90 div.tox.tox-tinymce { height: 90% !important; -} \ No newline at end of file +} diff --git a/public/css/components/AppMenu.css b/public/css/components/AppMenu.css index b980c1efc..e142858f8 100644 --- a/public/css/components/AppMenu.css +++ b/public/css/components/AppMenu.css @@ -16,11 +16,15 @@ padding: .5rem 1rem; text-decoration: none; } +.fhc-app-menu li a.disabled { + --bs-link-opacity: .5; +} .fhc-app-menu li a.active, .fhc-app-menu li a:hover { --bs-link-color-rgb: var(--bs-link-hover-color-rgb); background: var(--surface-hover); } +.fhc-app-menu li a.disabled, .fhc-app-menu li a.active { pointer-events: none; } diff --git a/public/js/api/factory/messages/messages.js b/public/js/api/factory/messages/messages.js index c6d4b67b6..b7b21dd8a 100644 --- a/public/js/api/factory/messages/messages.js +++ b/public/js/api/factory/messages/messages.js @@ -38,16 +38,18 @@ export default { url: 'api/frontend/v1/messages/messages/getMsgVarsLoggedInUser/' }; }, - getMessageVarsPerson(userParams){ + getMessageVarsPerson(ids, type_id){ return { method: 'post', - url: 'api/frontend/v1/messages/messages/getMessageVarsPerson/' + userParams.id + '/' + userParams.type_id + url: 'api/frontend/v1/messages/messages/getMessageVarsPerson/' + type_id, + params: {ids} }; }, - getMsgVarsPrestudent(userParams){ + getMsgVarsPrestudent(ids, type_id){ return { method: 'post', - url: 'api/frontend/v1/messages/messages/getMsgVarsPrestudent/' + userParams.id + '/' + userParams.type_id + url: 'api/frontend/v1/messages/messages/getMsgVarsPrestudent/' + type_id, + params: {ids} }; }, getPersonId(params){ @@ -56,28 +58,23 @@ export default { url: 'api/frontend/v1/messages/messages/getPersonId/' + params.id + '/' + params.type_id }; }, - getUid(userParams){ - return { - method: 'get', - url: 'api/frontend/v1/messages/messages/getUid/' + userParams.id + '/' + userParams.type_id - }; - }, getDataVorlage(vorlage_kurzbz){ return { method: 'get', url: 'api/frontend/v1/messages/messages/getDataVorlage/' + vorlage_kurzbz }; }, - getNameOfDefaultRecipient(params){ - return { - method: 'get', - url: 'api/frontend/v1/messages/messages/getNameOfDefaultRecipient/' + params.id + '/' + params.type_id - }; - }, - getPreviewText(userParams, params){ + getNameOfDefaultRecipients(ids, type_id){ return { method: 'post', - url: 'api/frontend/v1/messages/messages/getPreviewText/' + userParams.id + '/' + userParams.type_id, + url: 'api/frontend/v1/messages/messages/getNameOfDefaultRecipients/' + type_id, + params: {ids} + }; + }, + getPreviewText(type_id, params){ + return { + method: 'post', + url: 'api/frontend/v1/messages/messages/getPreviewText/' + type_id, params }; }, @@ -87,17 +84,10 @@ export default { url: 'api/frontend/v1/messages/messages/getReplyData/' + messageId }; }, - sendMessageFromModalContext(id, params) { + sendMessage(type_id, params) { return { method: 'post', - url: 'api/frontend/v1/messages/messages/sendMessage/' + id, - params - }; - }, - sendMessage(id, params) { - return { - method: 'post', - url: 'api/frontend/v1/messages/messages/sendMessage/' + id, + url: 'api/frontend/v1/messages/messages/sendMessage/' + type_id, params }; }, diff --git a/public/js/api/factory/studienplan.js b/public/js/api/factory/studienplan.js new file mode 100644 index 000000000..550a5211c --- /dev/null +++ b/public/js/api/factory/studienplan.js @@ -0,0 +1,11 @@ +export default { + + getStudienplaeneBySemester(studiengang_kz, studiensemester_kurzbz, ausbildungssemester, orgform_kurzbz) + { + return { + method: 'get', + url: 'api/frontend/v1/organisation/studienplan/getBySemester', + params: { studiengang_kz, studiensemester_kurzbz, ausbildungssemester, orgform_kurzbz }, + }; + } +} \ No newline at end of file diff --git a/public/js/api/factory/studiensemester.js b/public/js/api/factory/studiensemester.js new file mode 100644 index 000000000..367ec9558 --- /dev/null +++ b/public/js/api/factory/studiensemester.js @@ -0,0 +1,11 @@ +export default { + + getAll(order = null, start = null) + { + return { + method: 'get', + url: 'api/frontend/v1/organisation/studiensemester/getAll', + params: { order, start } + }; + } +} \ No newline at end of file diff --git a/public/js/api/factory/stv/config.js b/public/js/api/factory/stv/config.js new file mode 100644 index 000000000..c54b2f8b2 --- /dev/null +++ b/public/js/api/factory/stv/config.js @@ -0,0 +1,32 @@ +/** + * 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 { + get() { + return { + method: 'get', + url: 'api/frontend/v1/stv/config/get' + }; + }, + set(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/config/set', + params + }; + } +}; \ No newline at end of file diff --git a/public/js/api/factory/stv/mobility.js b/public/js/api/factory/stv/mobility.js index fc4fd17b4..fcff30954 100644 --- a/public/js/api/factory/stv/mobility.js +++ b/public/js/api/factory/stv/mobility.js @@ -101,7 +101,7 @@ export default { deleteMobilityPurpose(params) { return { method: 'post', - url: 'api/frontend/v1/stv/mobility/deleteMobilityPurpose/', + url: 'api/frontend/v1/stv/mobility/deleteMobilityPurpose/' + params.bisio_id, params }; }, diff --git a/public/js/api/factory/stv/projektarbeit.js b/public/js/api/factory/stv/projektarbeit.js index 4412f1842..e9b3e7efc 100644 --- a/public/js/api/factory/stv/projektarbeit.js +++ b/public/js/api/factory/stv/projektarbeit.js @@ -49,6 +49,12 @@ export default { url: 'api/frontend/v1/stv/projektarbeit/getNoten' }; }, + getStudiensemester() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getStudiensemester' + }; + }, loadProjektarbeit(projektarbeit_id) { return { method: 'get', diff --git a/public/js/api/factory/stv/students.js b/public/js/api/factory/stv/students.js index 07d4453d8..c17e32ff9 100644 --- a/public/js/api/factory/stv/students.js +++ b/public/js/api/factory/stv/students.js @@ -46,16 +46,24 @@ export default { url: url }; }, + search(params, studiensemester_kurzbz) { + return { + method: 'post', + url: 'api/frontend/v1/stv/students/search/' + + encodeURIComponent(studiensemester_kurzbz), + params + }; + }, verband(relative_path) { return { method: 'get', url: 'api/frontend/v1/stv/students/' + relative_path }; }, - check(params) { + getPerson(params) { return { method: 'post', - url: 'api/frontend/v1/stv/student/check', + url: 'api/frontend/v1/stv/student/getPerson', params }; }, diff --git a/public/js/apps/Nachrichten.js b/public/js/apps/Nachrichten.js index 84b9ddee5..ab9baf084 100644 --- a/public/js/apps/Nachrichten.js +++ b/public/js/apps/Nachrichten.js @@ -1,14 +1,15 @@ import NewMessage from "../components/Messages/Details/NewMessage/NewDiv.js"; -import Phrasen from "../plugin/Phrasen.js"; +import Phrasen from "../plugins/Phrasen.js"; const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router; const router = VueRouter.createRouter({ history: VueRouter.createWebHistory(), routes: [ - { path: `/${ciPath}/NeueNachricht/:id/:typeId`, component: NewMessage }, - { path: `/${ciPath}/NeueNachricht/:id/:typeId/:messageId`, component: NewMessage }, + { path: `/${ciPath}/NeueNachricht`, component: NewMessage, props: true }, + { path: `/${ciPath}/NeueNachricht/:id/:typeId`, component: NewMessage, props: true }, + { path: `/${ciPath}/NeueNachricht/:id/:typeId/:messageId`, component: NewMessage, props: true }, ] }); diff --git a/public/js/apps/Studentenverwaltung.js b/public/js/apps/Studentenverwaltung.js index 5eda16dd6..e6f77d5f5 100644 --- a/public/js/apps/Studentenverwaltung.js +++ b/public/js/apps/Studentenverwaltung.js @@ -148,6 +148,44 @@ const router = VueRouter.createRouter({ next(); } }, + { + name: 'search', + path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/search/:searchstr`, + component: FhcStudentenverwaltung, + props(route) { + return { + url_studiensemester_kurzbz: route.params.studiensemester_kurzbz, + url_mode: 'search', + url_prestudent_id: route.params.searchstr + }; + }, + beforeEnter(to, from, next) { + const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz); + if (!isSemester) { + return next({name: 'index'}); + } + next(); + } + }, + { + name: 'search_w_types', + path: `/${ciPath}/studentenverwaltung/:studiensemester_kurzbz/search/:types/:searchstr`, + component: FhcStudentenverwaltung, + props(route) { + return { + url_studiensemester_kurzbz: route.params.studiensemester_kurzbz, + url_mode: 'search', + url_prestudent_id: route.params.type + '/' + route.params.searchstr + }; + }, + beforeEnter(to, from, next) { + const isSemester = /^[WS]S\d{4}$/.test(to.params.studiensemester_kurzbz); + if (!isSemester) { + return next({name: 'index'}); + } + next(); + } + }, { path: '/:pathMatch(.*)*', redirect: { diff --git a/public/js/components/AppConfig.js b/public/js/components/AppConfig.js new file mode 100644 index 000000000..b6b6aaeac --- /dev/null +++ b/public/js/components/AppConfig.js @@ -0,0 +1,135 @@ +/** + * 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 . + */ + +import BsModal from "./Bootstrap/Modal.js"; +import FhcForm from "./Form/Form.js"; +import FormInput from "./Form/Input.js"; + + +export default { + name: 'AppConfig', + components: { + BsModal, + FhcForm, + FormInput + }, + emits: [ + 'update:modelValue' + ], + props: { + modelValue: { + type: Object, + required: true + }, + endpoints: { + type: Object, + required: true + } + }, + data() { + return { + setup: {}, + tempValues: {} + }; + }, + watch: { + '$p.user_language.value'(n, o) { + if (n !== o && o !== undefined && Object.keys(this.setup).length) { + this.$api + .call(this.endpoints.get()) + .then(res => { + this.setup = {}; + Object.keys(res.data).forEach(key => { + const binding = { ...res.data[key] }; + delete binding.value; + delete binding.options; + const options = res.data[key].options; + this.setup[key] = { + binding, + options + }; + }); + }) + .catch(this.$fhcAlert.handleSystemErrors); + } + } + + }, + methods: { + update() { + this.$refs.form + .call(this.endpoints.set(this.tempValues)) + .then(() => { + this.$emit('update:modelValue', { ...this.tempValues }); + this.$refs.modal.hide(); + this.$fhcAlert.alertSuccess(this.$p.t('ui/settings_saved')); + }) + .catch(this.$fhcAlert.handleSystemErrors); + } + }, + created() { + this.$api + .call(this.endpoints.get()) + .then(res => { + Object.keys(res.data).forEach(key => { + const binding = { ...res.data[key] }; + delete binding.value; + delete binding.options; + const options = res.data[key].options; + this.tempValues[key] = res.data[key].value; + this.setup[key] = { + binding, + options + }; + }); + this.$emit('update:modelValue', { ...this.tempValues }); + }) + .catch(this.$fhcAlert.handleSystemErrors); + }, + template: /* html */` + + + + + + + ` +}; diff --git a/public/js/components/AppMenu.js b/public/js/components/AppMenu.js index 33d35f8df..9e85debcd 100644 --- a/public/js/components/AppMenu.js +++ b/public/js/components/AppMenu.js @@ -64,5 +64,6 @@ export default { {{ menu.description }} + ` }; diff --git a/public/js/components/Calendar/Base/Grid.js b/public/js/components/Calendar/Base/Grid.js index c232dd955..3418a9151 100644 --- a/public/js/components/Calendar/Base/Grid.js +++ b/public/js/components/Calendar/Base/Grid.js @@ -316,7 +316,7 @@ export default { template: /* html */`
-
- - - - -
diff --git a/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js index 745f53002..9798ba7a4 100644 --- a/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js +++ b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js @@ -46,7 +46,6 @@ export default { loading: false, filter: "Pending", profil_update_id: Number(this.id), - }; }, computed: { @@ -60,6 +59,10 @@ export default { }, profilUpdateOptions: function () { return { + persistence: { + columns: ["width", "visible", "frozen"], + }, + persistenceID: 'cis-profilupdate-2025121702', ajaxURL: 'dummy', ajaxRequestFunc: (url, config, params) => { return this.$api.call(ApiProfilUpdate.getProfilUpdateWithPermission(params.filter)); @@ -205,7 +208,7 @@ export default { //responsive:0, }, { - title: this.$p.t("lehre", "studiengang") + ' (' + this.$p.t("profil", "studentIn") + ')', + title: this.$p.t("profil", "stg_short") + ' (' + this.$p.t("profil", "studentIn") + ')', field: "studiengang", minWidth: 50, resizable: true, @@ -213,8 +216,14 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { - title: this.$p.t("lehre", "organisationsform") + ' (' + this.$p.t("profil", "studentIn") + ')', + { + title: this.$p.t("profil", "sem_short") + ' (' + this.$p.t("profil", "studentIn") + ')', + field: "semester", + headerFilter: "list", + headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"} + }, + { + title: this.$p.t("profil", "orgform_short") + ' (' + this.$p.t("profil", "studentIn") + ')', field: "orgform", minWidth: 50, resizable: true, @@ -222,8 +231,8 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { - title: this.$p.t("lehre", "organisationseinheit") + ' (' + this.$p.t("profil", "mitarbeiterIn") + ')', + { + title: this.$p.t("profil", "orgeinheit_short") + ' (' + this.$p.t("profil", "mitarbeiterIn") + ')', field: "oezuordnung", minWidth: 200, resizable: true, @@ -231,7 +240,7 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { + { title: this.$p.t("profilUpdate", "Topic"), field: "topic", resizable: true, @@ -240,7 +249,7 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { + { title: this.$p.t("profilUpdate", "insertamum"), field: "insertamum_iso", resizable: true, @@ -251,7 +260,7 @@ export default { formatterParams: this.datetimeFormatterParams(), //responsive:0, }, - { + { title: this.$p.t("profilUpdate", "Status"), field: "status_translated", hozAlign: "center", @@ -273,7 +282,6 @@ export default { } return `
${cell.getValue()}
`; }, - resizable: true, minWidth: 200, //responsive:0, @@ -309,7 +317,6 @@ export default { ], }; } - }, methods: { denyProfilUpdate: function (data) { @@ -351,7 +358,6 @@ export default { this.showModal = false; this.modalData = null; }, - showAcceptDenyModal(value) { this.modalData = value; if (!this.modalData) { @@ -364,7 +370,6 @@ export default { this.$refs.AcceptDenyModal.show(); }); }, - updateData: function (event) { this.$refs.UpdatesTable.tabulator.setData(); //? store the selected view in the session storage of the browser @@ -415,22 +420,30 @@ export default { }, template: /*html*/ `
- - -
-
{{$p.t('ui','anzeigen')}}
- - - -
- - - + +

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

+ -
`, + + + + +
`, }; diff --git a/public/js/components/Form/Input.js b/public/js/components/Form/Input.js index 81b47d504..3c3fa45d5 100644 --- a/public/js/components/Form/Input.js +++ b/public/js/components/Form/Input.js @@ -280,6 +280,7 @@ export default { + diff --git a/public/js/components/LVVerwaltung/LVVerwaltung.js b/public/js/components/LVVerwaltung/LVVerwaltung.js index f9b153ead..42c50bdfa 100644 --- a/public/js/components/LVVerwaltung/LVVerwaltung.js +++ b/public/js/components/LVVerwaltung/LVVerwaltung.js @@ -124,6 +124,10 @@ export default { ? `${this.stg}/${this.semester}` : this.stg; } + else + { + this.selectedStudiengang = ''; + } this.filter = filter; }, handleRowClicked(data) @@ -163,6 +167,7 @@ export default { const routeName = this.filter.emp ? 'byEmp' : 'byStg'; const params = { stg }; + params.semester = ''; if (semester !== null) params.semester = semester; if (studiensemester_kurzbz) diff --git a/public/js/components/Messages/Details/NewMessage/Modal.js b/public/js/components/Messages/Details/NewMessage/Modal.js index ce9235617..47187de89 100644 --- a/public/js/components/Messages/Details/NewMessage/Modal.js +++ b/public/js/components/Messages/Details/NewMessage/Modal.js @@ -4,6 +4,8 @@ import FormInput from '../../../Form/Input.js'; import ListBox from "../../../../../../index.ci.php/public/js/components/primevue/listbox/listbox.esm.min.js"; import DropdownComponent from "../../../VorlagenDropdown/VorlagenDropdown.js"; +import ApiMessages from '../../../../api/factory/messages/messages.js'; + export default { name: "ModalNewMessages", components: { @@ -14,13 +16,9 @@ export default { ListBox }, props: { - endpoint: { - type: Object, - required: true - }, typeId: String, id: { - type: [Number, String], + type: Array, required: true }, messageId: { @@ -43,6 +41,8 @@ export default { vorlagen: [], recipientsArray: [], defaultRecipient: null, + defaultRecipients: [], + defaultRecipientString: null, editor: null, fieldsUser: [], fieldsPerson: [], @@ -56,7 +56,6 @@ export default { previewText: null, previewBody: "", replyData: null, - uid: null, } }, methods: { @@ -111,34 +110,28 @@ export default { }, sendMessage() { const data = new FormData(); - const params = { - id: this.id, - type_id: this.typeId - }; - const merged = { - ...this.formData, - ...params - }; - data.append('data', JSON.stringify(merged)); + data.append('data', JSON.stringify(this.formData)); + data.append('ids', JSON.stringify(this.id)); return this.$refs.formMessage - .call(this.endpoint.sendMessageFromModalContext(this.uid, data)) + .call(ApiMessages.sendMessage(this.typeId, data)) .then(response => { this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSent')); this.hideModal('modalNewMessage'); this.resetForm(); }).catch(this.$fhcAlert.handleSystemError) .finally(() => { - //this.resetForm(); - //closeModal - //closewindwo + + //just emit if no multitasking + if(this.id.length == 1){ this.$emit('reloadTable'); + } } ); }, getDataVorlage(vorlage_kurzbz){ return this.$api - .call(this.endpoint.getDataVorlage(vorlage_kurzbz)) + .call(ApiMessages.getDataVorlage(vorlage_kurzbz)) .then(response => { this.formData.body = response.data.text; this.formData.subject = response.data.subject; @@ -146,17 +139,17 @@ export default { }, getPreviewText(){ const data = new FormData(); - data.append('data', JSON.stringify(this.formData.body)); + data.append('ids', JSON.stringify(this.id)); + return this.$api - .call(this.endpoint.getPreviewText({ - id: this.id, - type_id: this.typeId}, data)) + .call(ApiMessages.getPreviewText( + this.typeId, data)) .then(response => { - this.previewText = response.data; + const previews = response.data; + this.previewText = previews[this.defaultRecipient]; }).catch(this.$fhcAlert.handleSystemError) .finally(() => { - //this.resetForm(); //closeModal //closewindwo }); @@ -171,7 +164,7 @@ export default { this.editor.save(); } else { - console.error("Editor instance is not available."); + console.error(this.$p.t('messages', 'errorEditorNotAvailable')); } }, resetForm(){ @@ -180,6 +173,7 @@ export default { body: null, subject: null, }; + this.$emit('resetMessageId'); if (this.editor) { @@ -201,18 +195,6 @@ export default { this.previewBody = this.previewText; }); }, - getUid(id, typeId){ - const params = { - id: id, - type_id: typeId - }; - this.$api - .call(this.endpoint.getUid(params)) - .then(result => { - this.uid = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - }, show(){ this.$refs.modalNewMessage.show(); }, @@ -245,7 +227,7 @@ export default { if (!newMessageId) return; try { - const result = await this.$api.call(this.endpoint.getReplyData(newMessageId)); + const result = await this.$api.call(ApiMessages.getReplyData(newMessageId)); this.replyData = result.data; if (this.replyData.length > 0) { @@ -260,15 +242,9 @@ export default { } }, created(){ - this.getUid(this.id, this.typeId); - if(this.typeId == 'person_id' || this.typeId == 'mitarbeiter_uid'){ - const params = { - id: this.id, - type_id: this.typeId - }; this.$api - .call(this.endpoint.getMessageVarsPerson(params)) + .call(ApiMessages.getMessageVarsPerson(this.id, this.typeId)) .then(result => { this.fieldsPerson = result.data; const person = this.fieldsPerson[0]; @@ -281,12 +257,8 @@ export default { } if(this.typeId == 'prestudent_id' || this.typeId == 'uid'){ - const params = { - id: this.id, - type_id: this.typeId - }; this.$api - .call(this.endpoint.getMsgVarsPrestudent(params)) + .call(ApiMessages.getMsgVarsPrestudent(this.id, this.typeId)) .then(result => { this.fieldsPrestudent = result.data; const prestudent = this.fieldsPrestudent[0]; @@ -299,7 +271,7 @@ export default { } this.$api - .call(this.endpoint.getMsgVarsLoggedInUser()) + .call(ApiMessages.getMsgVarsLoggedInUser()) .then(result => { this.fieldsUser = result.data; const user = this.fieldsUser; @@ -311,21 +283,18 @@ export default { .catch(this.$fhcAlert.handleSystemError); this.$api - .call(this.endpoint.getNameOfDefaultRecipient({ - id: this.id, - type_id: this.typeId})) + .call(ApiMessages.getNameOfDefaultRecipients(this.id, this.typeId)) .then(result => { - this.defaultRecipient = result.data; - this.recipientsArray.push({ - 'uid': this.uid, - 'details': this.defaultRecipient}); + this.defaultRecipients = result.data; + this.defaultRecipientString = Object.values(this.defaultRecipients).join("; "); + }) .catch(this.$fhcAlert.handleSystemError); //case of reply if(this.messageId) { this.$api - .call(this.endpoint.getReplyData(this.messageId)) + .call(ApiMessages.getReplyData(this.messageId)) .then(result => { this.replyData = result.data; this.formData.subject = this.replyData[0].replySubject; @@ -381,7 +350,7 @@ export default { type="text" name="recipient" :label="$p.t('messages/recipient')" - v-model="defaultRecipient" + v-model="defaultRecipientString" disabled > @@ -502,17 +471,17 @@ export default { >

- +
diff --git a/public/js/components/Messages/Details/NewMessage/NewDiv.js b/public/js/components/Messages/Details/NewMessage/NewDiv.js index 24674fd3f..b0c52f0f7 100644 --- a/public/js/components/Messages/Details/NewMessage/NewDiv.js +++ b/public/js/components/Messages/Details/NewMessage/NewDiv.js @@ -2,6 +2,7 @@ import FormForm from '../../../Form/Form.js'; import FormInput from '../../../Form/Input.js'; import ListBox from "../../../../../../index.ci.php/public/js/components/primevue/listbox/listbox.esm.min.js"; import DropdownComponent from '../../../VorlagenDropdown/VorlagenDropdown.js'; +import ApiMessages from "../../../../api/factory/messages/messages.js"; //props not working with route export default { name: "ComponentNewMessages", @@ -12,33 +13,17 @@ export default { DropdownComponent, }, props: { - endpoint: { - type: Object, - required: true - }, openMode: String, - tempTypeId: String, - tempId: { - type: [Number, String], + typeId: String, + id: { + type: Array, required: false }, - tempMessageId: { + messageId: { type: Number, required: false, } }, - computed: { - //params with routes for new tab and new window AND props for inSamePage - id(){ - return this.$props.tempId || this.$route.params.id; - }, - typeId(){ - return this.$props.tempTypeId || this.$route.params.typeId; - }, - messageId(){ - return this.$props.tempMessageId ||this.$route.params.messageId; - } - }, data(){ return { formData: { @@ -53,6 +38,8 @@ export default { vorlagen: [], recipientsArray: [], defaultRecipient: null, + defaultRecipients: [], + defaultRecipientString: null, editor: null, isVisible: false, fieldsUser: [], @@ -67,8 +54,7 @@ export default { previewText: null, previewBody: "", replyData: null, - uid: null, - messageSent: false + messageSent: false, } }, methods: { @@ -106,19 +92,11 @@ export default { }, sendMessage() { const data = new FormData(); + data.append('data', JSON.stringify(this.formData)); + data.append('ids', JSON.stringify(this.id)); - const params = { - id: this.id, - type_id: this.typeId - }; - - const merged = { - ...this.formData, - ...params - }; - data.append('data', JSON.stringify(merged)); return this.$api - .call(this.endpoint.sendMessage(this.uid, data)) + .call(ApiMessages.sendMessage(this.typeId, data)) .then(response => { this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSent')); this.hideTemplate(); @@ -126,11 +104,7 @@ export default { this.messageSent = true; }).catch(this.$fhcAlert.handleSystemError) .finally(() => { - //TODO(Manu) hier route definieren für openmode in Tab, Page? - // ist kein child sondern mit route aufgerufen - //würde allerdings neues fenster aktualisiert öffnen, altes bleibt ohne reload gleich - //Reload vorheriges tab??? - if(this.openMode == "inSamePage"){ + if(this.openMode == "inSamePage" && this.id.length == 1 ){ this.$emit('reloadTable'); } } @@ -138,25 +112,29 @@ export default { }, getDataVorlage(vorlage_kurzbz){ return this.$api - .call(this.endpoint.getDataVorlage(vorlage_kurzbz)) + .call(ApiMessages.getDataVorlage(vorlage_kurzbz)) .then(response => { this.formData.body = response.data.text; this.formData.subject = response.data.subject; }).catch(this.$fhcAlert.handleSystemError); }, - getPreviewText(id, typeId){ + getPreviewText(){ + console.log("subj" + this.formData.subject); const data = new FormData(); data.append('data', JSON.stringify(this.formData.body)); + data.append('ids', JSON.stringify(this.id)); + + console.log("subj" + this.formData.subject); + return this.$api - .call(this.endpoint.getPreviewText({ - id: this.id, - type_id: this.typeId}, data)) + .call(ApiMessages.getPreviewText( + this.typeId, data)) .then(response => { - this.previewText = response.data; + const previews = response.data; + this.previewText = previews[this.defaultRecipient]; }).catch(this.$fhcAlert.handleSystemError) .finally(() => { - //this.resetForm(); }); }, insertVariable(selectedItem){ @@ -169,7 +147,7 @@ export default { this.editor.save(); } else { - console.error("Editor instance is not available."); + console.error(this.$p.t('messages', 'errorEditorNotAvailable')); } }, resetForm(){ @@ -177,11 +155,13 @@ export default { vorlage_kurzbz: null, body: null, subject: null, + recipient: null, + selectedValue: null }; if (this.editor) { this.editor.setContent(""); } - this.$refs.dropdownComp.setValue(null); + // this.$refs.dropdownComp.setValue(null); this.previewBody = null; @@ -199,23 +179,25 @@ export default { this.isVisible = false; }, showTemplate(){ - if (this.openMode == "inSamePage") + if (this.openMode == "inSamePage") { this.isVisible = true; + //to enable send newMessage after sentMessage + this.messageSent = false; + } }, - showPreview(id, typeId){ - this.getPreviewText(id, typeId).then(() => { + showPreview(){ + this.getPreviewText().then(() => { this.previewBody = this.previewText; }); }, - getUid(id, typeId){ - const params = { - id: id, - type_id: typeId - }; + loadReplyData(messageId){ this.$api - .call(this.endpoint.getUid(params)) + .call(ApiMessages.getReplyData(messageId)) .then(result => { - this.uid = result.data; + this.replyData = result.data; + this.formData.subject = this.replyData[0].replySubject; + this.formData.body = this.replyData[0].replyBody; + this.formData.relationmessage_id = messageId; }) .catch(this.$fhcAlert.handleSystemError); } @@ -242,38 +224,43 @@ export default { }, }, created(){ - this.getUid(this.id, this.typeId); + const missingparamsmsgs = []; + if(!this.typeId) + { + missingparamsmsgs.push(this.$p.t('messages', 'errorMissingOrInvalidParameterRecipientTypeId')); + } - if (['person_id', 'mitarbeiter_uid'].includes(this.typeId)){ - const params = { - id: this.id, - type_id: this.typeId - }; + if(!this.id || this.id.length < 1) + { + missingparamsmsgs.push(this.$p.t('messages', 'errorMissingOrInvalidParameterRecipientIds')); + } - this.$api - .call(this.endpoint.getMessageVarsPerson(params)) - .then(result => { - this.fieldsPerson = result.data; - const person = this.fieldsPerson[0]; - this.itemsPerson = Object.entries(person).map(([key, value]) => ({ - label: key.toLowerCase(), - value: '{' + key.toLowerCase() + '}' - })); - }) - .catch(this.$fhcAlert.handleSystemError); - } + if(missingparamsmsgs.length > 0) + { + this.$fhcAlert.alertMultiple(missingparamsmsgs, 'warn', 'Warning', true); + return; + } - if (['prestudent_id', 'uid'].includes(this.typeId)){ - const params = { - id: this.id, - type_id: this.typeId - }; + if(this.typeId == 'person_id' || this.typeId == 'mitarbeiter_uid'){ this.$api - .call(this.endpoint.getMsgVarsPrestudent(params)) + .call(ApiMessages.getMessageVarsPerson(this.id, this.typeId)) + .then(result => { + this.fieldsPerson = result.data; + const person = this.fieldsPerson[0]; + this.itemsPerson = Object.entries(person).map(([key, value]) => ({ + label: key.toLowerCase(), + value: '{' + key.toLowerCase() + '}' + })); + }) + .catch(this.$fhcAlert.handleSystemError); + } + + if(this.typeId == 'prestudent_id' || this.typeId == 'uid'){ + this.$api + .call(ApiMessages.getMsgVarsPrestudent(this.id, this.typeId)) .then(result => { this.fieldsPrestudent = result.data; const prestudent = this.fieldsPrestudent[0]; - this.itemsPrestudent = Object.entries(prestudent).map(([key, value]) => ({ label: key.toLowerCase(), value: '{' + key.toLowerCase() + '}' @@ -283,7 +270,7 @@ export default { } this.$api - .call(this.endpoint.getMsgVarsLoggedInUser()) + .call(ApiMessages.getMsgVarsLoggedInUser()) .then(result => { this.fieldsUser = result.data; const user = this.fieldsUser; @@ -295,28 +282,26 @@ export default { .catch(this.$fhcAlert.handleSystemError); this.$api - .call(this.endpoint.getNameOfDefaultRecipient({ - id: this.id, - type_id: this.typeId})) + .call(ApiMessages.getNameOfDefaultRecipients(this.id, this.typeId)) .then(result => { - this.defaultRecipient = result.data; - this.recipientsArray.push({ - 'uid': this.uid, - 'details': this.defaultRecipient}); + this.defaultRecipients = result.data; + this.defaultRecipientString = Object.values(this.defaultRecipients).join("; "); + }) .catch(this.$fhcAlert.handleSystemError); //case of reply if(this.messageId != null) { - this.$api - .call(this.endpoint.getReplyData(this.messageId)) + this.loadReplyData(this.messageId); +/* this.$api + .call(ApiMessages.getReplyData(this.messageId)) .then(result => { this.replyData = result.data; this.formData.subject = this.replyData[0].replySubject; this.formData.body = this.replyData[0].replyBody; this.formData.relationmessage_id = this.messageId; }) - .catch(this.$fhcAlert.handleSystemError); + .catch(this.$fhcAlert.handleSystemError);*/ } }, @@ -330,7 +315,7 @@ export default {
-
+

{{ $p.t('messages', 'neueNachricht') }}

@@ -343,7 +328,7 @@ export default { type="text" name="recipient" :label="$p.t('messages/recipient')" - v-model="defaultRecipient" + v-model="defaultRecipientString" disabled > @@ -472,18 +457,18 @@ export default { v-model="defaultRecipient" > -

- +
diff --git a/public/js/components/Messages/Details/TableMessages.js b/public/js/components/Messages/Details/TableMessages.js index 2a12128eb..a55ddec63 100644 --- a/public/js/components/Messages/Details/TableMessages.js +++ b/public/js/components/Messages/Details/TableMessages.js @@ -1,6 +1,8 @@ import {CoreFilterCmpt} from "../../filter/Filter.js"; import FormForm from '../../Form/Form.js'; +import ApiMessages from "../../../api/factory/messages/messages.js" + export default { name: "TableMessages", components: { @@ -13,13 +15,9 @@ export default { }, }, props: { - endpoint: { - type: Object, - required: true - }, typeId: String, id: { - type: [Number, String], + type: Array, required: true }, messageLayout: String, @@ -38,12 +36,13 @@ export default { }, ajaxResponse: (url, params, response) => this.buildTreemap(response), columns: [ - {title: "subject", field: "subject"}, - {title: "body", field: "body", formatter: "html", visible: false}, - {title: "message_id", field: "message_id", visible: false}, + {title: "subject", field: "subject", headerFilter: true}, + {title: "body", field: "body", formatter: "html", visible: false, headerFilter: true}, + {title: "message_id", field: "message_id", visible: false, headerFilter: true}, { title: "Datum", field: "insertamum", + headerFilter: true, formatter: function (cell) { const dateStr = cell.getValue(); const date = new Date(dateStr); // Convert to Date object @@ -55,16 +54,28 @@ export default { minute: "2-digit", hour12: false }); + }, + headerFilterFunc(headerValue, rowValue) { + const matches = headerValue.match(/^(([0-9]{2})\.)?([0-9]{2})\.([0-9]{4})?$/); + let comparestr = headerValue; + if(matches !== null) { + const year = (matches[4] !== undefined) ? matches[4] : ''; + const month = matches[3]; + const day = (matches[2] !== undefined) ? matches[2] : ''; + comparestr = year + '-' + month + '-' + day; + } + return rowValue.match(comparestr); } }, - {title: "sender", field: "sender"}, - {title: "recipient", field: "recipient"}, - {title: "senderId", field: "sender_id"}, - {title: "recipientId", field: "recipient_id"}, - {title: "Relationmessage ID", field: "relationmessage_id"}, + {title: "sender", field: "sender", headerFilter: true}, + {title: "recipient", field: "recipient", headerFilter: true}, + {title: "senderId", field: "sender_id", headerFilter: true}, + {title: "recipientId", field: "recipient_id", headerFilter: true}, + {title: "Relationmessage ID", field: "relationmessage_id", headerFilter: true}, { title: "Status", field: "status", + headerFilter: true, formatterParams: [ "unread", "read", @@ -73,11 +84,12 @@ export default { ], formatter: (cell, formatterParams) => { return formatterParams[cell.getValue()]; - } + }, }, { title: "letzte Änderung", field: "statusdatum", + headerFilter: true, formatter: function (cell) { const dateStr = cell.getValue(); const date = new Date(dateStr); // Convert to Date object @@ -89,6 +101,17 @@ export default { minute: "2-digit", hour12: false }); + }, + headerFilterFunc(headerValue, rowValue) { + const matches = headerValue.match(/^(([0-9]{2})\.)?([0-9]{2})\.([0-9]{4})?$/); + let comparestr = headerValue; + if(matches !== null) { + const year = (matches[4] !== undefined) ? matches[4] : ''; + const month = matches[3]; + const day = (matches[2] !== undefined) ? matches[2] : ''; + comparestr = year + '-' + month + '-' + day; + } + return rowValue.match(comparestr); } }, { @@ -132,9 +155,10 @@ export default { frozen: true } ], - layout: 'fitDataFill', + layout: 'fitDataStretchFrozen', layoutColumnsOnNewData: false, height: '400', + selectable: 1, selectableRangeMode: 'click', index: 'message_id', pagination: true, @@ -147,7 +171,7 @@ export default { dataTreeCollapseElement:"", dataTreeChildIndent: 15, dataTreeStartExpanded: false, - persistenceID: 'core-message', + persistenceID: 'core-message-2025112401', locale: 'de', "langs": { "de":{ //German language definition @@ -255,7 +279,7 @@ export default { }, deleteMessage(message_id){ return this.$api - .call(this.endpoint.deleteMessage(message_id)) + .call(ApiMessages.deleteMessage(message_id)) .then(response => { this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); }).catch(this.$fhcAlert.handleSystemError) @@ -321,7 +345,7 @@ export default { }, loadAjaxCall(url, config, params){ return this.$api.call( - this.endpoint.getMessages(params) + ApiMessages.getMessages(params) ); } }, @@ -346,13 +370,13 @@ export default { });*/ }, created(){ - if(this.typeId != 'person_id') { + if(this.typeId != 'person_id' && Array.isArray(this.id) && this.id.length === 1) { const params = { id: this.id, type_id: this.typeId }; this.$api - .call(this.endpoint.getPersonId(params)) + .call(ApiMessages.getPersonId(params)) .then(result => { this.personId = result.data; }) diff --git a/public/js/components/Messages/Messages.js b/public/js/components/Messages/Messages.js index 176c05b6b..1f9afcb9e 100644 --- a/public/js/components/Messages/Messages.js +++ b/public/js/components/Messages/Messages.js @@ -14,10 +14,6 @@ export default { } }, props: { - endpoint: { - type: Object, - required: true - }, typeId: { type: String, required: true, @@ -31,7 +27,7 @@ export default { } }, id: { - type: [Number, String], + type: Array, required: true }, showTable: Boolean, @@ -65,6 +61,9 @@ export default { } }, methods: { + getControllerUrl() { + return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/NeueNachricht'; + }, reloadTable(){ this.$refs.templateTableMessage.reload(); }, @@ -77,44 +76,65 @@ export default { this.openInNewTab(id, typeId, messageId); } else if (this.openMode == "modal"){ + if(!messageId) + this.$refs.modalMsg.resetForm(); this.$refs.modalMsg.show(); } else if (this.openMode == "inSamePage"){ + console.log("in same Page"); this.isVisibleDiv = true; + if(messageId) + this.$refs.templateNewDivMessage.loadReplyData(messageId); + else + this.$refs.templateNewDivMessage.resetForm(); + + this.$refs.templateNewDivMessage.showTemplate(); } else console.log("no valid openMode"); }, - openInNewTab(id, typeId, messageId= null){ + openInNewTab(id, typeId, messageId=null){ + if(id.length > 1) + { + this.$refs['newMsgForm'].submit(); + return; + } - let path = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router; + let path = this.getControllerUrl(); if (messageId){ - path += "/NeueNachricht/" + id + "/" + typeId + "/" + messageId; + path += "/" + encodeURIComponent(id) + "/" + encodeURIComponent(typeId) + "/" + encodeURIComponent(messageId); } else { - path += "/NeueNachricht/" + id + "/" + typeId; + path += "/" + encodeURIComponent(id) + "/" + encodeURIComponent(typeId); } const newTab = window.open(path, "_blank"); }, openInNewWindow(id, typeId, messageId){ - let path = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router; - - if (messageId){ - path += "/NeueNachricht/" + id + "/" + typeId + "/" + messageId; - } - - else { - path += "/NeueNachricht/" + id + "/" + typeId; - } - const width = Math.round(window.innerWidth * 0.75); const height = Math.round(window.innerHeight * 0.75); const left = Math.round((window.innerWidth - width) / 2); const top = Math.round((window.innerHeight - height) / 2); + if(id.length > 1) + { + const newWindow = window.open('', "NewMsgWindow", `width=${width},height=${height},left=${left},top=${top}`); + this.$refs['newMsgForm'].submit(); + return; + } + + let path = this.getControllerUrl(); + + if (messageId){ + path += "/" + encodeURIComponent(id) + "/" + encodeURIComponent(typeId) + "/" + encodeURIComponent(messageId); + } + + else { + path += "/" + encodeURIComponent(id) + "/" + encodeURIComponent(typeId); + } + const newWindow = window.open(path, "_blank", `width=${width},height=${height},left=${left},top=${top}`); }, resetMessageId(){ @@ -124,13 +144,21 @@ export default { }, template: `
+ +
+ + +
-
+
- - -
+ +
{{$p.t('studierendenantrag', 'dropdown_plageat')}} + + + + + +
+
+
+
+ +
+ + + + +
+ ` + }; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Messages.js b/public/js/components/Stv/Studentenverwaltung/Details/Messages.js index 59650eaab..8bbb596d6 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Messages.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Messages.js @@ -1,5 +1,5 @@ import CoreMessages from "../../../Messages/Messages.js"; -import ApiMessages from "../../../../api/factory/messages/messages.js"; +//import ApiMessages from "../../../../api/factory/messages/messages.js"; export default { name: "TabMessages", @@ -11,29 +11,50 @@ export default { }, data(){ return { - endpoint: ApiMessages + //endpoint: ApiMessages }; }, + computed: { + prestudent_ids() { + if (this.modelValue.prestudent_id) + { + return [this.modelValue.prestudent_id]; + } + return this.modelValue.map(e => e.prestudent_id); + }, + person_ids() { + if (this.modelValue.person_id) + { + return [this.modelValue.person_id]; + } + return this.modelValue.map(e => e.person_id); + }, + }, template: `
- - - + +
` }; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Mobility/List/Purpose.js b/public/js/components/Stv/Studentenverwaltung/Details/Mobility/List/Purpose.js index 296d29e8d..fa93fc256 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Mobility/List/Purpose.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Mobility/List/Purpose.js @@ -71,10 +71,10 @@ export default { frozen: true }, ], - layout: 'fitColumns', + layout: 'fitDataStretchFrozen', layoutColumnsOnNewData: false, height: 200, - persistenceID: 'core-mobility-purpose' + persistenceID: 'core-mobility-purpose-2025112401' }, tabulatorEvents: [ { @@ -169,6 +169,11 @@ export default { { this.localData.push(newEntry); + // reload tabulator mit tabulator method + if (this.$refs.table?.tabulator) { + this.$refs.table.tabulator.replaceData(this.localData); + } + this.$emit('setMobilityPurposeToNewMobility', { zweck_code: this.formData.zweck_code, }); @@ -198,7 +203,6 @@ export default {
- - +
` } \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js index d3ca1a25e..4d0996b6b 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js @@ -217,9 +217,10 @@ export default { }, columns, height: '100%', + layout: 'fitDataStretchFrozen', selectable: 1, selectableRangeMode: 'click', - persistenceID: 'stv-details-noten-zeugnis-2025111801', + persistenceID: 'stv-details-noten-zeugnis-2025112401', persistence:{ columns: ["width", "visible", "frozen"] } diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Notizen.js b/public/js/components/Stv/Studentenverwaltung/Details/Notizen.js index 7cba49005..77eb8adba 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Notizen.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Notizen.js @@ -30,6 +30,7 @@ export default { show-tiny-mce :visibleColumns="['titel','text','verfasser','bearbeiter','dokumente']" @reload="$emit('update:suffix')" + tabulator-persistence-id="stv-notiz-2026011301" > diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Prestudent.js b/public/js/components/Stv/Studentenverwaltung/Details/Prestudent.js index dc645dadc..47724e4d7 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Prestudent.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Prestudent.js @@ -30,6 +30,22 @@ export default { from: 'hasAdminPermission', default: false }, + hasZGVBakkPermission: { + from: 'hasZGVBakkPermission', + default: [] + }, + hasZGVMasterPermission: { + from: 'hasZGVMasterPermission', + default: [] + }, + hasZGVDoctorPermission: { + from: 'hasZGVDoctorPermission', + default: [] + }, + hasBismeldenPermission: { + from: 'hasBismeldenPermission', + default: false + }, currentSemester: { from: 'currentSemester', required: true @@ -73,6 +89,15 @@ export default { computed: { deltaLength() { return Object.keys(this.deltaArray).length; + }, + disableZgvBakk: function() { + return !this.hasZGVBakkPermission.includes(this.modelValue.studiengang_kz.toString()); + }, + disableZgvMaster: function() { + return !this.hasZGVMasterPermission.includes(this.modelValue.studiengang_kz.toString()); + }, + disableZgvDoctor: function() { + return !this.hasZGVDoctorPermission.includes(this.modelValue.studiengang_kz.toString()); } }, watch: { @@ -106,7 +131,7 @@ export default { }, methods: { - loadPrestudent() { + async loadPrestudent() { return this.$api .call(ApiStvPrestudent.get(this.modelValue.prestudent_id, this.currentSemester)) .then(result => result.data) @@ -154,8 +179,8 @@ export default { ) }, }, - created() { - this.loadPrestudent(); + async created() { + await this.loadPrestudent(); this.$api .call(ApiStvPrestudent.getBezeichnungZGV()) .then(result => result.data) @@ -273,6 +298,7 @@ export default { dropdown name="zgv_code" @complete="filterZgvs" + :disabled="disableZgvBakk" >