From bc484453041935f163a2b029a556aa7bffd98693 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Mon, 10 Feb 2025 13:05:44 +0100 Subject: [PATCH 001/258] - infocenter filter fuer electronic onboarding hinzugefuegt --- .../system/infocenter/InfoCenter.php | 44 +++++++ .../views/system/infocenter/onboarding.php | 47 +++++++ .../system/infocenter/onboardingData.php | 116 ++++++++++++++++++ system/filtersupdate.php | 23 ++++ 4 files changed, 230 insertions(+) create mode 100644 application/views/system/infocenter/onboarding.php create mode 100644 application/views/system/infocenter/onboardingData.php diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index f6e41d2e6..9024088f8 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 @@ -1552,6 +1561,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)) @@ -1560,6 +1570,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( @@ -1623,6 +1634,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 + ), ) ); } @@ -1649,6 +1672,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); @@ -1690,6 +1715,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)) { @@ -1766,6 +1792,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/views/system/infocenter/onboarding.php b/application/views/system/infocenter/onboarding.php new file mode 100644 index 000000000..a600364d9 --- /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/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/system/filtersupdate.php b/system/filtersupdate.php index 51dd86314..cfcceb0f6 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -529,6 +529,29 @@ $filters = array( ', 'oe_kurzbz' => null, ), + array( + 'app' => 'infocenter', + 'dataset_name' => 'onboarding', + 'filter_kurzbz' => 'InfoCenterOnboarding', + 'description' => '{Alle}', + 'sort' => 1, + 'default_filter' => true, + 'filter' => ' + { + "name": "Electronic Onboarding - Alle", + "columns": [ + {"name": "PersonId"}, + {"name": "Vorname"}, + {"name": "Nachname"}, + {"name": "LockUser"}, + {"name": "HoldDate"}, + {"name": "Rueckstellgrund"} + ], + "filters": [] + } + ', + 'oe_kurzbz' => null, + ), array( 'app' => 'infocenter', 'dataset_name' => 'aufgenommen', From 405062f5493fcdaaf3ed0e9b501a08e5aa93f081 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 7 May 2025 18:36:51 +0200 Subject: [PATCH 002/258] added Projektarbeit tab to Studierendenverwaltung, adding, editing, deleting of Projektarbeiten now possible --- .../api/frontend/v1/stv/Config.php | 5 + .../api/frontend/v1/stv/Projektarbeit.php | 334 +++++++ .../education/Lehrveranstaltung_model.php | 57 ++ .../models/education/Projektarbeit_model.php | 34 +- application/models/ressource/Firma_model.php | 21 +- public/js/api/factory/stv/projektarbeit.js | 80 ++ .../Details/Projektarbeit.js | 24 + .../Details/Projektarbeit/Betreuung.js | 847 ++++++++++++++++++ .../Details/Projektarbeit/Details.js | 461 ++++++++++ .../Details/Projektarbeit/Projektarbeit.js | 377 ++++++++ 10 files changed, 2230 insertions(+), 10 deletions(-) create mode 100644 application/controllers/api/frontend/v1/stv/Projektarbeit.php create mode 100644 public/js/api/factory/stv/projektarbeit.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 455b1e8fc..dd2eaed02 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -123,6 +123,11 @@ class Config extends FHCAPI_Controller 'config' => $config['finalexam'] ]; + $result['projektarbeit'] = [ + 'title' => $this->p->t('stv', 'tab_projektarbeit'), + 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js' + ]; + $result['mobility'] = [ 'title' => $this->p->t('stv', 'tab_mobility'), 'component' => './Stv/Studentenverwaltung/Details/Mobility.js' diff --git a/application/controllers/api/frontend/v1/stv/Projektarbeit.php b/application/controllers/api/frontend/v1/stv/Projektarbeit.php new file mode 100644 index 000000000..3be2b26a3 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Projektarbeit.php @@ -0,0 +1,334 @@ + ['admin:r', 'assistenz:r'], + 'loadProjektarbeit' => ['admin:r', 'assistenz:r'], + 'insertProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'updateProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'deleteProjektarbeit' => ['admin:rw', 'assistenz:rw'], + 'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'], + 'getFirmen' => ['admin:r', 'assistenz:r'], + 'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'], + 'getNoten' => ['admin:rw', 'assistenz:rw'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->load->model('education/Projekttyp_model', 'ProjekttypModel'); + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $this->load->model('ressource/Firma_model', 'FirmaModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('education/Note_model', 'NoteModel'); + $this->load->model('education/Projektbetreuer_model', 'BetreuerModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getProjektarbeit() + { + $student_uid = $this->input->get('uid'); + + if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektarbeitModel->getProjektarbeit($student_uid); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $projektarbeiten = getData($result); + + foreach ($projektarbeiten as $projektarbeit) + { + $projektarbeit_id = $projektarbeit->projektarbeit_id; + $abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id); + + if (isError($abgabeRes)) $this->terminateWithError(getError($abgabeRes), self::ERROR_TYPE_GENERAL); + + if (hasData($abgabeRes)) + { + $paabgabe = getData($abgabeRes)[0]; + $projektarbeit->abgabedatum = $paabgabe->abgabedatum; + } + } + + $this->terminateWithSuccess($projektarbeiten); + } + + public function loadProjektarbeit() + { + $projektarbeit_id = $this->input->get('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) return $this->terminateWithError('Projektarbeit Id missing', self::ERROR_TYPE_GENERAL); + + $this->ProjektarbeitModel->addSelect( + 'lehre.tbl_projektarbeit.projektarbeit_id, titel, titel_english, themenbereich, projekttyp_kurzbz, firma_id, + lehrveranstaltung_id, lehreinheit_id, beginn, note, final, freigegeben, tbl_projektarbeit.anmerkung, fa.name AS firma_name' + ); + $this->ProjektarbeitModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); + $this->ProjektarbeitModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); + $this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id'); + $result = $this->ProjektarbeitModel->loadWhere( + array('projektarbeit_id' => $projektarbeit_id) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess(current($data)); + } + + public function insertProjektarbeit() + { + $student_uid = $this->input->post('uid'); + + if (!$student_uid) return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + + if (!$this->_hasBerechtigungForStudent($student_uid)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $formData = $this->input->post('formData'); + + $this->addMeta('form', $formData); + + if ($this->_validate($formData) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->ProjektarbeitModel->insert( + array_merge($formData, ['insertamum' => date('c'), 'insertvon' => getAuthUID(), 'student_uid' => $student_uid]) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function updateProjektarbeit() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!$projektarbeit_id || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $formData = $this->input->post('formData'); + + if ($this->_validate($formData) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $result = $this->ProjektarbeitModel->update( + $projektarbeit_id, + array_merge($formData, ['updateamum' => date('c'), 'updatevon' => getAuthUID()]) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteProjektarbeit() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID'], self::ERROR_TYPE_GENERAL)); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $validate = $this->_validateDelete($projektarbeit_id); + + if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektarbeitModel->delete( + array('projektarbeit_id' => $projektarbeit_id) + ); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) + { + $this->outputJson($result); + } + + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function getTypenProjektarbeit() + { + $result = $this->ProjekttypModel->loadWhere(['aktiv' => true]); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getFirmen() + { + $searchString = $this->input->get('searchString'); + + if (!isset($searchString)) $this->terminateWithError($this->p->t('projektarbeit', 'error_searchStringMissing', self::ERROR_TYPE_GENERAL)); + + $result = $this->FirmaModel->searchFirmen($searchString, $aktiv = true); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getLehrveranstaltungen() + { + $student_uid = $this->input->get('student_uid'); + $studiengang_kz = $this->input->get('studiengang_kz'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + $additional_lehrveranstaltung_id = $this->input->get('additional_lehrveranstaltung_id'); + + if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL); + if (!isset($studiensemester_kurzbz)) $this->terminateWithError('Studiensemster missing', self::ERROR_TYPE_GENERAL); + + $lvsResult = $this->LehrveranstaltungModel->getLvsForProjektarbeit($student_uid, $studiengang_kz, $additional_lehrveranstaltung_id); + + if (isError($lvsResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL); + + $lvs = hasData($lvsResult) ? getData($lvsResult) : []; + + foreach ($lvs as $lv) + { + $lehreinheiten = $this->LehreinheitModel->getLesForLv( + $lv->lehrveranstaltung_id, $studiensemester_kurzbz + ); + + foreach ($lehreinheiten as $lehreinheit) + { + if (!isEmptyArray($lehreinheit->lektoren)) + { + $this->MitarbeiterModel->addSelect('kurzbz'); + $this->MitarbeiterModel->db->where_in('tbl_mitarbeiter.mitarbeiter_uid', $lehreinheit->lektoren); + $maResult = $this->MitarbeiterModel->load(); + + if (isError($maResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL); + + $lehreinheit->lektoren = array_column(getData($maResult), 'kurzbz'); + } + } + + $lv->lehreinheiten = $lehreinheiten; + } + + return $this->terminateWithSuccess($lvs); + } + + public function getNoten() + { + $result = $this->NoteModel->load(); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + /** + * + * @param + * @return object success or error + */ + private function _validate($formData) + { + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('titel', 'Titel', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel']) + ]); + + $this->form_validation->set_rules('projekttyp_kurzbz', 'Projekttyp', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Projekttyp']) + ]); + + $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|numeric', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), + //'matches' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) + ]); + + $this->form_validation->set_rules('beginn', 'Beginn', 'is_valid_date', [ + 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Beginn']) + ]); + + return $this->form_validation->run(); + } + + /** + * + * @param + * @return object success or error + */ + private function _validateDelete($projektarbeit_id) + { + $this->BetreuerModel->addSelect('1'); + $result = $this->BetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + + if (isError($result)) return $result; + + if (hasData($result)) return error($this->p->t('projektarbeit', 'error_betreuerNichtGeloescht')); + + $this->PaabgabeModel->addSelect('1'); + $result = $this->PaabgabeModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + + if (isError($result)) return $result; + + if (hasData($result)) return error($this->p->t('projektarbeit', 'error_paabgabeNichtGeloescht')); + + return success(); + } + + private function _hasBerechtigungForStudent($student_uid) + { + if (!$student_uid) + return false; + + $this->load->model('crm/Student_model', 'StudentModel'); + + $this->StudentModel->addSelect('studiengang_kz'); + $result = $this->StudentModel->load([$student_uid]); + if (isError($result) || !hasData($result)) + return false; + + $studiengang_kz = getData($result)[0]->studiengang_kz; + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz)) + return true; + + return false; + } +} diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 056fb45d7..446e6e9cf 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -988,4 +988,61 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($qry, $params); } + + /** + * Gets Lehrveranstaltungen for a student, as needed for a Projektarbeit. + * @param student_uid + * @param studiengang_kz optional, all Lvs of this Studiengang will be included + * @param additional_lehrveranstaltung_id optional, this lv will be added to result + * @return object success or error + */ + public function getLvsForProjektarbeit($student_uid, $studiengang_kz = null, $additional_lehrveranstaltung_id = null) + { + $params = array($student_uid, $student_uid); + + $qry = " + SELECT * + FROM + lehre.tbl_lehrveranstaltung + WHERE + ( + lehrveranstaltung_id IN ( + + SELECT + lehrveranstaltung_id + FROM + campus.vw_student_lehrveranstaltung + WHERE + uid=? + + UNION + + SELECT + lehrveranstaltung_id + FROM + lehre.tbl_zeugnisnote + WHERE + student_uid=? + )"; + + if (isset($studiengang_kz)) + { + $params[] = $studiengang_kz; + $qry .= " OR (studiengang_kz = ? AND semester IS NOT NULL)"; + } + + if (isset($additional_lehrveranstaltung_id)) + { + $params[] = $additional_lehrveranstaltung_id; + $qry .= " OR lehrveranstaltung_id = ?"; + } + + $qry .= " + ) + AND projektarbeit = TRUE + ORDER BY + semester, bezeichnung"; + + return $this->execQuery($qry, $params); + } } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 109e23373..2be79f8e9 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -24,15 +24,17 @@ class Projektarbeit_model extends DB_Model public function getProjektarbeit($student_uid, $studiengang_kz = null, $studiensemester_kurzbz = null, $projekttyp = null, $final = null) { $qry = "SELECT - tbl_projektarbeit.* , tbl_projekttyp.bezeichnung + tbl_projektarbeit.*, tbl_projekttyp.bezeichnung, + tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.lehrveranstaltung_id, + tbl_firma.name AS firma_name FROM lehre.tbl_projektarbeit JOIN - lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung - + lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, public.tbl_firma WHERE tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND + tbl_projektarbeit.firma_id = tbl_firma.firma_id AND tbl_projektarbeit.student_uid = ?"; $params = array($student_uid); @@ -69,4 +71,30 @@ class Projektarbeit_model extends DB_Model return $this->execQuery($qry, $params); } + + /** + * + * @param + * @return object success or error + */ + public function hasBerechtigungForProjektarbeit($projektarbeit_id) + { + if (!$projektarbeit_id || !is_numeric($projektarbeit_id)) + return false; + + $this->ProjektarbeitModel->addSelect('studiengang_kz'); + $this->ProjektarbeitModel->addJoin('public.tbl_student', 'student_uid'); + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + if (isError($result) || !hasData($result)) + return false; + + $studiengang_kz = getData($result)[0]->studiengang_kz; + + if ($this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz)) + return true; + if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz)) + return true; + + return false; + } } diff --git a/application/models/ressource/Firma_model.php b/application/models/ressource/Firma_model.php index 431f0815f..5ae53eeaf 100644 --- a/application/models/ressource/Firma_model.php +++ b/application/models/ressource/Firma_model.php @@ -12,17 +12,24 @@ class Firma_model extends DB_Model $this->pk = 'firma_id'; } - public function searchFirmen($filter) + public function searchFirmen($filter, $aktiv = null) { + $params = []; $filter = strtoLower($filter); $qry = " - SELECT + SELECT f.name, f.firma_id - FROM - public.tbl_firma f - WHERE - lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'"; + FROM + public.tbl_firma f + WHERE + lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'"; - return $this->execQuery($qry); + if (isset($aktiv) && is_bool($aktiv)) + { + $params[] = $aktiv; + $qry .= " AND aktiv = ?"; + } + + return $this->execQuery($qry, $params); } } diff --git a/public/js/api/factory/stv/projektarbeit.js b/public/js/api/factory/stv/projektarbeit.js new file mode 100644 index 000000000..243383de0 --- /dev/null +++ b/public/js/api/factory/stv/projektarbeit.js @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2025 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export default { + getProjektarbeit(uid) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getProjektarbeit', + params: { uid } + }; + }, + getTypenProjektarbeit() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getTypenProjektarbeit' + }; + }, + getFirmen(searchString) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getFirmen', + params: {searchString} + }; + }, + getLehrveranstaltungen(student_uid, studiengang_kz, studiensemester_kurzbz, additional_lehrveranstaltung_id) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getLehrveranstaltungen', + params: { student_uid, studiengang_kz, studiensemester_kurzbz, additional_lehrveranstaltung_id } + }; + }, + getNoten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/getNoten' + }; + }, + loadProjektarbeit(projektarbeit_id) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektarbeit/loadProjektarbeit', + params: { projektarbeit_id } + }; + }, + addNewProjektarbeit(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/insertProjektarbeit', + params + }; + }, + updateProjektarbeit(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/updateProjektarbeit', + params + }; + }, + deleteProjektarbeit(projektarbeit_id) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektarbeit/deleteProjektarbeit', + params: { projektarbeit_id } + }; + } +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js new file mode 100644 index 000000000..3615e8f5d --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit.js @@ -0,0 +1,24 @@ +import Projektarbeit from './Projektarbeit/Projektarbeit.js'; + +export default { + name: "TabProjektarbeit", + components: { + Projektarbeit + }, + provide() { + return { + config: this.config + }; + }, + props: { + modelValue: Object, + config: Object + }, + data(){ + return {} + }, + template: ` +
+ +
` +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js new file mode 100644 index 000000000..5d223d694 --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js @@ -0,0 +1,847 @@ +import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import FormForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; + +import ApiStvAbschlusspruefung from '../../../../../api/factory/stv/abschlusspruefung.js'; + +export default { + components: { + CoreFilterCmpt, + BsModal, + FormForm, + FormInput, + PvAutoComplete, + AbschlusspruefungDropdown, + PruefungList + }, + inject: { + cisRoot: { + from: 'cisRoot' + }, + config: { + from: 'config', + required: true + }, + $reloadList: { + from: '$reloadList', + required: true + }, + isBerechtigtDocAndOdt: { + from: 'hasPermissionOutputformat', + default: false + } + }, + computed: { + studentUids() { + if (this.student.uid) + { + return [this.student.uid]; + } + return this.student.map(e => e.uid); + }, + studentKzs(){ + if (this.student.uid) + { + return [this.student.studiengang_kz]; + } + return this.student.map(e => e.studiengang_kz); + }, + stg_kz(){ + return this.studentKzs[0]; + }, + }, + props: { + student: Object + }, + data() { + return { + tabulatorOptions: { + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call(ApiStvAbschlusspruefung.getAbschlusspruefung(this.student.uid)), + ajaxResponse: (url, params, response) => response.data, + columns: [ + {title: "vorsitz", field: "vorsitz_nachname"}, + {title: "abschlussbeurteilung", field: "beurteilung_bezeichnung"}, + {title: "prueferIn1", field: "p1_nachname", visible: false}, + {title: "prueferIn2", field: "p2_nachname", visible: false}, + {title: "prueferIn3", field: "p3_nachname", visible: false}, + { + title: "datum", + field: "datum", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + {title: "uhrzeit", field: "uhrzeit"}, + { + title: "freigabe", + field: "freigabedatum", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + {title: "pruefungsantritt", field: "antritt_bezeichnung"}, + { + title: "sponsion", + field: "sponsion", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + {title: "anmerkung", field: "anmerkung"}, + {title: "abschlusspruefung_id", field: "abschlusspruefung_id", visible: false}, + {title: "typ", field: "pruefungstyp_kurzbz", visible: false}, + + { + title: 'Aktionen', field: 'actions', + minWidth: 150, // Ensures Action-buttons will be always fully displayed + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'bearbeiten'); + button.addEventListener('click', (event) => + this.actionEditAbschlusspruefung(cell.getData().abschlusspruefung_id) + ); + container.append(button); + + button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', () => + this.actionDeleteAbschlusspruefung(cell.getData().abschlusspruefung_id) + ); + container.append(button); + + container.append(cell.getData().actionDiv); + + return container; + }, + frozen: true + }, + ], + layout: 'fitDataFill', + layoutColumnsOnNewData: false, + height: 'auto', + minHeight: '200', + selectable: true, + index: 'abschlusspruefung_id', + persistenceID: 'stv-details-finalexam' + }, + tabulatorEvents: [ + { + event: 'dataLoaded', + handler: data => this.tabulatorData = data.map(item => { + item.actionDiv = document.createElement('div'); + return item; + }), + }, + { + event: 'tableBuilt', + handler: async() => { + await this.$p.loadCategory(['global', 'person', 'stv', 'abschlusspruefung', 'ui']); + + + let cm = this.$refs.table.tabulator.columnManager; + + cm.getColumnByField('vorsitz_nachname').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'vorsitz_header') + }); + cm.getColumnByField('beurteilung_bezeichnung').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'abschlussbeurteilung') + }); + cm.getColumnByField('p1_nachname').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'pruefer1') + }); + cm.getColumnByField('p2_nachname').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'pruefer2') + }); + cm.getColumnByField('p3_nachname').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'pruefer3') + }); + cm.getColumnByField('datum').component.updateDefinition({ + title: this.$p.t('global', 'datum') + }); + cm.getColumnByField('uhrzeit').component.updateDefinition({ + title: this.$p.t('global', 'uhrzeit') + }); + cm.getColumnByField('freigabedatum').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'freigabe') + }); + cm.getColumnByField('antritt_bezeichnung').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'pruefungsantritt') + }); + cm.getColumnByField('sponsion').component.updateDefinition({ + title: this.$p.t('abschlusspruefung', 'sponsion') + }); + cm.getColumnByField('anmerkung').component.updateDefinition({ + title: this.$p.t('global', 'anmerkung') + }); + cm.getColumnByField('pruefungstyp_kurzbz').component.updateDefinition({ + title: this.$p.t('global', 'typ') + }); + cm.getColumnByField('abschlusspruefung_id').component.updateDefinition({ + title: this.$p.t('ui', 'abschlusspruefung_id') + }); + /* + cm.getColumnByField('actions').component.updateDefinition({ + title: this.$p.t('global', 'aktionen') + }); + */ + } + } + ], + tabulatorData: [], + lastSelected: null, + formData: { + typStg: null, + pruefungstyp_kurzbz: null, + akadgrad_id: null, + vorsitz: null, + pruefungsantritt_kurzbz: null, + abschlussbeurteilung_kurzbz: null, + datum: null, + sponsion: null, + pruefer1: null, + pruefer2: null, + pruefer3: null, + anmerkung: null, + protokoll: null, + note: null, + link: null + }, + statusNew: true, + arrTypen: [], + arrAntritte: [], + arrBeurteilungen: [], + arrAkadGrad: [], + arrNoten: [], + filteredMitarbeiter: [], + filteredPruefer: [], + abortController: { + mitarbeiter: null, + pruefer: null + }, + stgInfo: { typ: '', oe_kurzbz: '' } + } + }, + watch: { + student(){ + if (this.$refs.table) { + this.$refs.table.reloadTable(); + } + this.getStudiengangByKz(); + } + }, + methods: { + getStudiengangByKz(){ + this.stgInfo = { typ: '', oe_kurzbz: '' }; + this.$api + .call(ApiStudiengang.getStudiengangByKz(this.stg_kz)) + .then(result => this.stgInfo = result.data) + .catch(this.$fhcAlert.handleSystemError); + }, + actionNewAbschlusspruefung() { + this.resetForm(); + this.statusNew = true; + this.$refs.finalexamModal.show(); + this.setDefaultFormData(); + }, + actionEditAbschlusspruefung(abschlusspruefung_id) { + this.resetForm(); + this.statusNew = false; + this.$refs.finalexamModal.show(); + this.loadAbschlusspruefung(abschlusspruefung_id); + }, + actionDeleteAbschlusspruefung(abschlusspruefung_id) { + this.$fhcAlert + .confirmDelete() + .then(result => result + ? abschlusspruefung_id + : Promise.reject({handled: true})) + .then(this.deleteAbschlusspruefung) + .catch(this.$fhcAlert.handleSystemError); + }, + addNewAbschlusspruefung() { + const dataToSend = { + uid: this.student.uid, + formData: this.formData + }; + + return this.$refs.formFinalExam + .call(ApiStvAbschlusspruefung.addNewAbschlusspruefung(dataToSend)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + this.hideModal('finalexamModal'); + this.resetForm(); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(() => { + this.reload(); + }); + }, + hideModal(modalRef){ + this.$refs[modalRef].hide(); + }, + reload() { + this.$refs.table.reloadTable(); + }, + loadAbschlusspruefung(abschlusspruefung_id) { + return this.$api + .call(ApiStvAbschlusspruefung.loadAbschlusspruefung(abschlusspruefung_id)) + .then(result => { + this.formData = result.data; + //TODO(Manu) check if cisRoot is okay + this.formData.link = this.cisRoot + 'index.ci.php/lehre/Pruefungsprotokoll/showProtokoll?abschlusspruefung_id=' + this.formData.abschlusspruefung_id + '&fhc_controller_id=67481e5ed5490'; + return result; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + updateAbschlusspruefung(abschlusspruefung_id) { + const dataToSend = { + id: abschlusspruefung_id, + formData: this.formData + }; + return this.$refs.formFinalExam + .call(ApiStvAbschlusspruefung.updateAbschlusspruefung(dataToSend)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + this.hideModal('finalexamModal'); + this.resetForm(); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(() => { + this.reload(); + }); + }, + deleteAbschlusspruefung(abschlusspruefung_id) { + return this.$api + .call(ApiStvAbschlusspruefung.deleteAbschlusspruefung(abschlusspruefung_id)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }) + .catch(this.$fhcAlert.handleSystemError) + .finally(() => { + this.reload(); + }); + }, + resetForm() { + this.formData.pruefungstyp_kurzbz = null; + this.formData.akadgrad_id = null; + this.formData.vorsitz = null; + this.formData.pruefungsantritt_kurzbz = null; + this.formData.abschlussbeurteilung_kurzbz = null; + this.formData.datum = null; //oder new Date(); + this.formData.sponsion = null; + this.formData.pruefer1 = null; + this.formData.pruefer2 = null; + this.formData.pruefer3 = null; + this.formData.anmerkung = null; + this.formData.protokoll = null; + this.formData.note = null; + this.formData.p1 = null; + this.formData.p2 = null; + this.formData.p3 = null; + this.formData.pv = null; + }, + search(event) { + if (this.abortController.mitarbeiter) { + this.abortController.mitarbeiter.abort(); + } + this.abortController.mitarbeiter = new AbortController(); + + return this.$api + .call(ApiStvAbschlusspruefung.getMitarbeiter(event.query)) + .then(result => { + this.filteredMitarbeiter = result.data.retval; + }); + }, + searchNotAkad(event) { + if (this.abortController.pruefer) { + this.abortController.pruefer.abort(); + } + this.abortController.pruefer = new AbortController(); + + return this.$api + .call(ApiStvAbschlusspruefung.getPruefer(event.query)) + .then(result => { + this.filteredPruefer = result.data.retval; + }); + }, + setDefaultFormData() { + + this.resetForm(); + + if (this.stgInfo.typ === 'b') { + this.formData.pruefungstyp_kurzbz = 'Bachelor'; + this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster'); + } + if (this.stgInfo.typ === 'd' || this.stgInfo === 'm') { + this.formData.pruefungstyp_kurzbz = 'Diplom'; + this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster'); + } + if (this.stgInfo.typ === 'lg') { + this.formData.pruefungstyp_kurzbz = 'lgabschluss'; + } + + if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) { + this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id; + } + }, + printDocument(link) { + window.open(link, '_blank'); + }, + }, + created() { + this.$api + .call(ApiStvAbschlusspruefung.getTypenAbschlusspruefung()) + .then(result => { + this.arrTypen = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvAbschlusspruefung.getTypenAntritte()) + .then(result => { + this.arrAntritte = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvAbschlusspruefung.getBeurteilungen()) + .then(result => { + this.arrBeurteilungen = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvAbschlusspruefung.getNoten()) + .then(result => { + this.arrNoten = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvAbschlusspruefung.getAkadGrade(this.student.studiengang_kz)) + .then(result => { + this.arrAkadGrad = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + if (!this.student.length) { + this.$api + .call(ApiStudiengang.getStudiengangByKz(this.student.studiengang_kz)) + .then(result => { + this.stgInfo = result.data; + this.setDefaultFormData(); + }) + .catch(this.$fhcAlert.handleSystemError); + } else + this.getStudiengangByKz(); + }, + template: ` +
+

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

+ +
+ +
+ + + + + + + + + + + + + {{this.$p.t('global','details')}} +

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

+
+ + + + + + + +
+ +
+ + + + +
+ +
+ + + + + +
+ +
+ + + + + + + +
+ +
+ + + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+
+

{{$p.t('abschlusspruefung', 'zurBeurteilung')}}

+
+ +
+ +
+ + + +
+ + + + +
+` +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js new file mode 100644 index 000000000..a6256ceb1 --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -0,0 +1,461 @@ +import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import FormForm from '../../../../Form/Form.js'; +import FormInput from '../../../../Form/Input.js'; +import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; + +import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js'; + +export default { + components: { + CoreFilterCmpt, + FormForm, + FormInput, + PvAutoComplete + }, + emits: ['details-saved'], + inject: { + defaultSemester: { + from: 'defaultSemester' + } + //~ cisRoot: { + //~ from: 'cisRoot' + //~ }, + //~ config: { + //~ from: 'config', + //~ required: true + //~ } + }, + computed: { + arrLes() { + let lehreinheiten = []; + if (this.formData.lehrveranstaltung_id) { + let lv = this.arrLvs.find(lv => {return lv.lehrveranstaltung_id == this.formData.lehrveranstaltung_id}); + if (lv) lehreinheiten = lv.lehreinheiten + } + + for (let le of lehreinheiten) + { + let bezeichnung = le.lehrfach_kurzbz + '-' + le.lehrform_kurzbz + ' ' + le.lehrfach_bezeichnung + ' '; + + for (let grp of le.lehreinheitgruppen) + { + bezeichnung += grp.gruppe_kurzbz ? grp.gruppe_kurzbz : '' + grp.semester ?? '' + grp.verband ?? '' + grp.gruppe ?? ''; + } + + bezeichnung += ' (' + le.lektoren.join(' ') + ') ID: ' + le.lehreinheit_id; + + le.bezeichnung = bezeichnung; + } + + return lehreinheiten; + }, + //~ preparedFormData() { + //~ console.log("FOR DATA CALLEd"); + //~ if (this.formData.projektarbeit_id == null) delete(this.formData.projektarbeit_id); + //~ if (this.formData.firma) this.formData.firma_id = this.formData.firma.firma_id; + //~ delete(this.formData.firma); + //~ delete(this.formData.firma_name); + //~ delete(this.formData.lehrveranstaltung_id); + //~ // convert null value fields from string to null + //~ return this.formData; + //~ } + }, + props: { + statusNew: Boolean, + student: Object, + projektarbeit: Object, + stg_kz: Number + }, + data() { + return { + formData: { + projektarbeit_id: null, + titel: null, + titel_english: null, + themenbereich: null, + projekttyp_kurzbz: null, + firma: null, + lehrveranstaltung_id: null, + lehreinheit_id: null, + beginn: null, + ende: null, + freigegeben: true, + gesperrtbis: null, + note: null, + final: true, + anmerkung: null + }, + arrTypen: [], + arrFirmen: [], + arrLvs: [], + arrNoten: [], + filteredFirmen: [], + abortController: { + firma: null + } + } + }, + methods: { + resetForm() { + this.formData.projektarbeit_id = null; + this.formData.titel = null; + this.formData.titel_english = null; + this.formData.themenbereich = null; + this.formData.projekttyp_kurzbz = null; + this.formData.firma = null; + this.formData.lehrveranstaltung_id = null; + this.formData.lehreinheit_id = null; + this.formData.beginn = null; + this.formData.ende = null; + this.formData.freigegeben = true; + this.formData.gesperrtbis = null; + this.formData.note = null; + this.formData.final = true; + this.formData.anmerkung = null; + }, + getFormData(statusNew, studiensemester_kurzbz, additional_lehrveranstaltung_id/*, successCallback*/) { + + //~ let callArray = [ + //~ this.$api.call(ApiStvProjektarbeit.getTypenProjektarbeit()), + //~ this.$api.call(ApiStvProjektarbeit.getLehrveranstaltungen( + //~ this.student.uid, + //~ projektarbeit_id ? null : this.student.studiengang_kz, + //~ studiensemester_kurzbz ?? this.defaultSemester, + //~ additional_lehrveranstaltung_id ?? null + //~ )), + //~ this.$api.call(ApiStvProjektarbeit.getNoten()) + //~ ]; + + //~ if (projektarbeit_id) callArray.push(this.$api.call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id))); + + //~ // Run when All promises are settled + //~ Promise.allSettled(callArray).then((results) => { + //~ let hasError = false; + //~ let allFormData = []; + //~ results.forEach((promise_result) => { + + //~ if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success") { + //~ allFormData.push(promise_result.value.data); + //~ } else { + //~ hasError = true; + //~ //this.$fhcAlert.handleSystemError(promise_result); + //~ } + //~ //let data = promise_result.value.data; + //~ console.log(promise_result.status); + //~ }); + + //~ if (!hasError) { + //~ this.setFormData(allFormData[0], allFormData[1], allFormData[2], allFormData[3], allFormData[4] ?? null); + //~ if (successCallback) successCallback(); + //~ } + //~ }); + + this.$api + .call(ApiStvProjektarbeit.getTypenProjektarbeit()) + .then(result => { + this.arrTypen = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvProjektarbeit.getLehrveranstaltungen( + this.student.uid, + statusNew ? this.student.studiengang_kz : null, + studiensemester_kurzbz ?? this.defaultSemester, + additional_lehrveranstaltung_id + )) + .then(result => { + this.arrLvs = result.data + } + ) + .catch(this.$fhcAlert.handleSystemError); + + this.$api + .call(ApiStvProjektarbeit.getNoten()) + .then(result => { + this.arrNoten = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + setFormData(arrTypen, arrLvs, arrNoten, projektarbeitData) { + this.arrTypen = arrTypen; + this.arrLvs = arrLvs; + this.arrNoten = arrNoten; + if (projektarbeitData) { + projektarbeitData.firma = {firma_id: projektarbeitData.firma_id, name: projektarbeitData.firma_name}; + this.formData = projektarbeitData; + } + }, + loadProjektarbeit(projektarbeit_id) { + + return this.$api + .call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id)) + .then(result => { + this.formData = result.data; + return result; + }) + .catch(this.$fhcAlert.handleSystemError) + }, + addNewProjektarbeit() { + + let dataToSend = { + uid: this.student.uid, + formData: this.getPreparedFormData() + }; + + return this.$refs.formDetails + .call(ApiStvProjektarbeit.addNewProjektarbeit(dataToSend)); + }, + updateProjektarbeit() { + + let dataToSend = { + projektarbeit_id: this.formData.projektarbeit_id, + formData: this.getPreparedFormData() + }; + return this.$refs.formDetails + .call(ApiStvProjektarbeit.updateProjektarbeit(dataToSend)); + }, + searchFirma(event) { + if (this.abortController.firma) { + this.abortController.firma.abort(); + } + this.abortController.firma = new AbortController(); + + return this.$api + .call(ApiStvProjektarbeit.getFirmen(event.query)) + .then(result => { + this.filteredFirmen = result.data; + }); + }, + lvChanged(event) { + this.formData.lehreinheit_id = null; + }, + getPreparedFormData() { + let preparedFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy + + // delete "helper" fields + if (preparedFormData.projektarbeit_id == null) delete(preparedFormData.projektarbeit_id); + if (preparedFormData.firma) preparedFormData.firma_id = preparedFormData.firma.firma_id; + delete(preparedFormData.firma); + delete(preparedFormData.firma_name); + delete(preparedFormData.lehrveranstaltung_id); + + return preparedFormData; + } + //~ setDefaultFormData() { + //~ this.resetForm(); + //~ }, + }, + template: ` + + + {{this.$p.t('global','details')}} +

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

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

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

+ + + + + + + + + + + + + +
+` +} + From 382006aa8bfdec7696256d2b2236eb448003daf7 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Fri, 16 May 2025 13:37:21 +0200 Subject: [PATCH 003/258] Projektarbeit Studierendenverwaltung: now possible to save and edit Projektbetreuer --- application/config/stv.php | 7 +- .../api/frontend/v1/stv/Config.php | 5 +- .../api/frontend/v1/stv/Projektarbeit.php | 11 +- .../api/frontend/v1/stv/Projektbetreuer.php | 333 +++++++ .../models/education/Projektarbeit_model.php | 9 +- .../education/Projektbetreuer_model.php | 1 + application/models/person/Person_model.php | 19 +- .../models/ressource/Stundensatz_model.php | 95 +- public/js/api/factory/stv/projektbetreuer.js | 73 ++ .../Details/Projektarbeit/Betreuung.js | 847 ------------------ .../Details/Projektarbeit/Details.js | 27 +- .../Details/Projektarbeit/Projektarbeit.js | 86 +- .../Details/Projektarbeit/Projektbetreuer.js | 421 +++++++++ system/phrasesupdate.php | 2 +- 14 files changed, 1002 insertions(+), 934 deletions(-) create mode 100644 application/controllers/api/frontend/v1/stv/Projektbetreuer.php create mode 100644 public/js/api/factory/stv/projektbetreuer.js delete mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js diff --git a/application/config/stv.php b/application/config/stv.php index 31ce3f521..f5c1599ab 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -54,7 +54,7 @@ $config['tabs'] = ], ] ]; - + // List of fields to show when ZGV_DOKTOR_ANZEIGEN is defined $fieldsZgvDoktor = ['zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', 'zgvdoktor_erfuellt', 'zgvdoktor_code']; @@ -74,3 +74,8 @@ if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) { $fieldsZgvDoktor ); } + +$config['tabs']['projektarbeit']['defaultProjektbetreuerStunden'] = '4.0'; +$config['tabs']['projektarbeit']['defaultProjektbetreuerStundenDiplom'] = '5.0'; +$config['tabs']['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz'] = true; +$config['tabs']['projektarbeit']['defaultProjektbetreuerStundensatz'] = '80.0'; diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index dd2eaed02..afdf8efb8 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -125,7 +125,8 @@ class Config extends FHCAPI_Controller $result['projektarbeit'] = [ 'title' => $this->p->t('stv', 'tab_projektarbeit'), - 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js' + 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js', + 'config' => $config['projektarbeit'] ]; $result['mobility'] = [ @@ -323,7 +324,7 @@ class Config extends FHCAPI_Controller $title_eng = $this->p->t("global", "englisch"); $title_ff = $this->p->t("stv", "document_certificate"); $title_lv = $this->p->t("stv", "document_coursecertificate"); - + $link_ff = "documents/export/" . "zertifikat.rdf.php/" . "Zertifikat" . diff --git a/application/controllers/api/frontend/v1/stv/Projektarbeit.php b/application/controllers/api/frontend/v1/stv/Projektarbeit.php index 3be2b26a3..70775fdbc 100644 --- a/application/controllers/api/frontend/v1/stv/Projektarbeit.php +++ b/application/controllers/api/frontend/v1/stv/Projektarbeit.php @@ -17,7 +17,7 @@ class Projektarbeit extends FHCAPI_Controller 'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'], 'getFirmen' => ['admin:r', 'assistenz:r'], 'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'], - 'getNoten' => ['admin:rw', 'assistenz:rw'] + 'getNoten' => ['admin:r', 'assistenz:r'] ]); // Load Libraries @@ -91,7 +91,7 @@ class Projektarbeit extends FHCAPI_Controller ); $this->ProjektarbeitModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id'); $this->ProjektarbeitModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id'); - $this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id'); + $this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id', 'LEFT'); $result = $this->ProjektarbeitModel->loadWhere( array('projektarbeit_id' => $projektarbeit_id) ); @@ -170,7 +170,7 @@ class Projektarbeit extends FHCAPI_Controller if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); $result = $this->ProjektarbeitModel->delete( - array('projektarbeit_id' => $projektarbeit_id) + ['projektarbeit_id' => $projektarbeit_id] ); if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); @@ -273,10 +273,9 @@ class Projektarbeit extends FHCAPI_Controller 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Projekttyp']) ]); - $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|numeric', [ + $this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|is_natural', [ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), - //'matches' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']), - 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) + 'is_natural' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit']) ]); $this->form_validation->set_rules('beginn', 'Beginn', 'is_valid_date', [ diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php new file mode 100644 index 000000000..ac6663132 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -0,0 +1,333 @@ + ['admin:r', 'assistenz:r'], + 'saveProjektbetreuer' => ['admin:rw', 'assistenz:rw'], + 'deleteProjektbetreuer' => ['admin:rw', 'assistenz:rw'], + 'getBetreuerarten' => ['admin:r', 'assistenz:r'], + 'getNoten' => ['admin:r', 'assistenz:r'], + 'getDefaultStundensaetze' => ['admin:r', 'assistenz:r'], + 'getProjektbetreuerBySearchQuery' => ['admin:r', 'assistenz:r'], + 'validateProjektbetreuer' => ['admin:r', 'assistenz:r'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); + $this->load->model('education/Betreuerart_model', 'BetreuerartModel'); + $this->load->model('ressource/Stundensatz_model', 'StundensatzModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->load->model('education/Note_model', 'NoteModel'); + $this->load->model('person/Person_model', 'PersonModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getProjektbetreuer() + { + $projektarbeit_id = $this->input->get('projektarbeit_id'); + + if (!isset($projektarbeit_id)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); + + $this->ProjektbetreuerModel->addSelect( + 'projektarbeit_id, person_id, nachname, vorname, note, punkte, stunden, stundensatz, betreuerart_kurzbz, vertrag_id, titelpre, titelpost' + ); + $this->ProjektbetreuerModel-> addSelect("CASE + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=pers.person_id) + THEN 'Mitarbeiter' + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=pers.person_id) + THEN 'Student' + ELSE 'Person' + END AS status"); + $this->ProjektbetreuerModel->addJoin('public.tbl_person pers', 'person_id'); + $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]); + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $projektbetreuer = getData($result); + + //~ foreach ($projektbetreuer as $projektarbeit) + //~ { + //~ $projektarbeit_id = $projektarbeit->projektarbeit_id; + //~ $abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id); + + //~ if (isError($abgabeRes)) $this->terminateWithError(getError($abgabeRes), self::ERROR_TYPE_GENERAL); + + //~ if (hasData($abgabeRes)) + //~ { + //~ $paabgabe = getData($abgabeRes)[0]; + //~ $projektarbeit->abgabedatum = $paabgabe->abgabedatum; + //~ } + //~ } + + $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); + } + + public function saveProjektbetreuer() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $projektbetreuer = $this->input->post('projektbetreuerListe'); + + //$this->addMeta('form', $projektbetreuer); + + if (!is_array($projektbetreuer)) + { + return $this->terminateWithError( + $this->p->t('projektarbeit', 'error_invalidProjektbetreuer'), self::ERROR_TYPE_GENERAL + ); + } + + foreach ($projektbetreuer as $pb) + { + if ($this->_validate($pb) == false) + { + $this->addMeta('test', 'foisch'); + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + } + + $result = null; + + foreach ($projektbetreuer as $pb) + { + //~ $this->addMeta('form', $pb); + //~ error_log(print_r($pb, true)); + //die(); + + //~ $this->ProjektbetreuerModel->addSelect('1'); + //~ $checkResult = $this->ProjektbetreuerModel->loadWhere( + //~ ['person_id' => $pb['person_id'], 'projektarbeit_id' => $projektarbeit_id, 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz']] + //~ ); + + //~ if (isError($checkResult)) $this->terminateWithError(getError($checkResult), self::ERROR_TYPE_GENERAL); + + $betreuer = [ + 'projektarbeit_id' => $projektarbeit_id, + 'person_id' => $pb['person_id'], + 'note' => $pb['note'], + 'stunden' => $pb['stunden'], + 'stundensatz' => $pb['stundensatz'], + 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz'] + ]; + + if (isset($pb['person_id_old']) && isset($pb['betreuerart_kurzbz_old'])) + { + $result = $this->ProjektbetreuerModel->update( + [ + 'projektarbeit_id' => $projektarbeit_id, + 'person_id' => $pb['person_id_old'], + 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz_old'] + ], + array_merge($betreuer, ['updateamum' => date('c'), 'updatevon' => getAuthUID()]) + ); + } + else + { + $result = $this->ProjektbetreuerModel->insert( + array_merge($betreuer, ['insertamum' => date('c'), 'insertvon' => getAuthUID()]) + ); + } + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function deleteProjektbetreuer() + { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + $person_id = $this->input->post('person_id'); + $betreuerart_kurzbz = $this->input->post('betreuerart_kurzbz'); + + if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektbetreuer 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'=> 'Betreuerart'], self::ERROR_TYPE_GENERAL)); + + if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); + + $validate = $this->_validateDelete($projektarbeit_id, $person_id); + + if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL); + + $result = $this->ProjektbetreuerModel->delete( + ['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id, 'betreuerart_kurzbz' => $betreuerart_kurzbz] + ); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) + { + $this->outputJson($result); + } + + return $this->terminateWithSuccess(current(getData($result)) ? : null); + } + + public function getBetreuerarten() + { + $result = $this->BetreuerartModel->loadWhere(['aktiv' => true]); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getNoten() + { + $result = $this->NoteModel->load(); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? getData($result) : []); + } + + public function getDefaultStundensaetze() + { + $person_id = $this->input->get('person_id'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + + $result = $this->StundensatzModel->getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz); + + $this->addMeta('res', $result); + + //if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess($result); + } + + public function getProjektbetreuerBySearchQuery() + { + $searchString = $this->input->get('searchString'); + + if (!isset($searchString)) $this->terminateWithError($this->p->t('projektarbeit', 'error_searchStringMissing', self::ERROR_TYPE_GENERAL)); + + $result = $this->PersonModel->searchPerson($searchString); + + $this->addMeta('met', $result); + + if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + return $this->terminateWithSuccess(hasData($result) ? $this->_addFullNameToBetreuer(getData($result)) : []); + } + + /** + * + * @param + * @return object success or error + */ + public function validateProjektbetreuer() + { + $projektbetreuerArr = $this->input->post('projektbetreuer'); + + if (!is_array($projektbetreuerArr)) $projektbetreuerArr = [$projektbetreuerArr]; + + foreach ($projektbetreuerArr as $pb) + { + if ($this->_validate($pb) == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + } + + $this->terminateWithSuccess([]); + } + + /** + * + * @param + * @return object success or error + */ + private function _validate($formData) + { + $this->form_validation->set_data($formData); + + $this->form_validation->set_rules('betreuerart_kurzbz', 'Betreuerart', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Betreuerart']) + ]); + + $this->form_validation->set_rules('person_id', 'Person', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Person ID']) + ]); + + $this->form_validation->set_rules('stunden', 'Stunden', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Stunden']) + ]); + + $this->form_validation->set_rules('stundensatz', 'Stundensatz', 'numeric', [ + 'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Stundensatz']) + ]); + + + return $this->form_validation->run(); + } + + /** + * + * @param + * @return object success or error + */ + private function _validateDelete($projektarbeit_id, $person_id) + { + $this->ProjektbetreuerModel->addSelect('vertrag_id'); + $result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id]); + + if (isError($result)) return $result; + + if (hasData($result) && getData($result)[0]->vertrag_id != null) return error($this->p->t('projektarbeit', 'error_betreuerHatVertrag')); + + return success(); + } + + /** + * + * @param + * @return object success or error + */ + private function _addFullNameToBetreuer($betreuerArr) + { + foreach ($betreuerArr as $betreuer) + { + $betreuer->name = ($betreuer->titelpre ? $betreuer->titelpre . ' ' : '') . + $betreuer->nachname . ' ' . $betreuer->vorname . ($betreuer->titelpost ? ' ' . $betreuer->titelpre : ''). + ' (' . $betreuer->status . ')'; + } + + return $betreuerArr; + } +} diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 2be79f8e9..357886de1 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -29,12 +29,11 @@ class Projektarbeit_model extends DB_Model tbl_firma.name AS firma_name FROM lehre.tbl_projektarbeit - JOIN - lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, public.tbl_firma + JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) + JOIN lehre.tbl_lehreinheit USING (lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) + LEFT JOIN public.tbl_firma USING (firma_id) WHERE - tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND - tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND - tbl_projektarbeit.firma_id = tbl_firma.firma_id AND tbl_projektarbeit.student_uid = ?"; $params = array($student_uid); diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index 95950bf95..02368ae21 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -10,6 +10,7 @@ class Projektbetreuer_model extends DB_Model parent::__construct(); $this->dbTable = 'lehre.tbl_projektbetreuer'; $this->pk = array('betreuerart_kurzbz', 'projektarbeit_id', 'person_id'); + $this->hasSequence = false; } /** diff --git a/application/models/person/Person_model.php b/application/models/person/Person_model.php index 997048972..d955f6401 100644 --- a/application/models/person/Person_model.php +++ b/application/models/person/Person_model.php @@ -151,12 +151,21 @@ class Person_model extends DB_Model */ public function searchPerson($filter) { - $this->addSelect('vorname, nachname, gebdatum, person_id'); + $this->addSelect('vorname, nachname, gebdatum, person_id, titelpre, titelpost'); + $this->addSelect("CASE + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=tbl_person.person_id) + THEN 'Mitarbeiter' + WHEN EXISTS + (SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=tbl_person.person_id) + THEN 'Student' + ELSE 'Person' + END AS status"); $result = $this->loadWhere( - 'lower(nachname) like '.$this->db->escape('%'.$filter.'%')." + 'lower(nachname) like '.$this->db->escape('%'.mb_strtolower($filter).'%')." OR lower(vorname) like ".$this->db->escape('%'.$filter.'%')." - OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.$filter.'%')." - OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%') + OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.mb_strtolower($filter).'%')." + OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.mb_strtolower($filter).'%') ); return $result; @@ -423,4 +432,4 @@ class Person_model extends DB_Model return success($result); } } -} \ No newline at end of file +} diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php index 10f5a6aa1..9d41dfbd9 100644 --- a/application/models/ressource/Stundensatz_model.php +++ b/application/models/ressource/Stundensatz_model.php @@ -2,7 +2,7 @@ class Stundensatz_model extends DB_Model { - + /** * Constructor */ @@ -42,4 +42,95 @@ class Stundensatz_model extends DB_Model return $this->execQuery($qry, $params); } -} \ No newline at end of file + + public function getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz) + { + $this->load->config('stv'); + + $useFixangestelltStundensatz = $this->config->item('tabs')['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz']; + $defaultStundensatz = $this->config->item('tabs')['projektarbeit']['defaultProjektbetreuerStundensatz']; + + $stundensatz = ''; + + if(isset($person_id) && isset($studiensemester_kurzbz)) + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addSelect('start, ende'); + $result = $this->StudiensemesterModel->load($studiensemester_kurzbz); + + if (hasData($result)) + { + $studiensemester = getData($result)[0]; + + if (isset($useFixangestelltStundensatz) && !$useFixangestelltStundensatz) + { + // load Mitarbeiter + $params = [$person_id]; + $qry = " + SELECT + mitarbeiter_uid, fixangestellt + FROM + public.tbl_mitarbeiter + JOIN public.tbl_benutzer ON(tbl_benutzer.uid=tbl_mitarbeiter.mitarbeiter_uid) + WHERE + person_id=? + ORDER BY + tbl_mitarbeiter.insertamum DESC NULLS LAST + LIMIT 1"; + + $result = $this->execQuery($qry, $params); + + if (hasData($result)) + { + foreach (getData($result) as $ma) + { + if (!$ma->fixangestellt) + { + $stundensatzRes = $this->getStundensatzByDatum( + $ma->mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre' + ); + + if (hasData($stundensatzRes)) + $stundensatz = getData($stundensatzRes)[0]->stundensatz; + else + $stundensatz = '0.00'; + } + } + } + else + { + $stundensatz = '0.00'; + } + + } + else + { + $params = [$person_id, $studiensemester->ende, $studiensemester->start]; + $qry = "SELECT ss.stundensatz + FROM hr.tbl_stundensatz ss + JOIN public.tbl_mitarbeiter ON ss.uid = tbl_mitarbeiter.mitarbeiter_uid + JOIN public.tbl_benutzer ON(tbl_benutzer.uid=tbl_mitarbeiter.mitarbeiter_uid) + WHERE person_id=? + AND stundensatztyp = 'lehre' + AND gueltig_von <= ? + AND (gueltig_bis >= ? OR gueltig_bis IS NULL) + ORDER BY gueltig_bis DESC NULLS FIRST, gueltig_von DESC NULLS LAST LIMIT 1"; + + $result = $this->execQuery($qry, $params); + + if (hasData($result)) + { + $stundensatz = getData($result)[0]->stundensatz; + } + else + { + $stundensatz = $defaultStundensatz; + } + } + } + } + + return $stundensatz; + } +} diff --git a/public/js/api/factory/stv/projektbetreuer.js b/public/js/api/factory/stv/projektbetreuer.js new file mode 100644 index 000000000..fc710fe81 --- /dev/null +++ b/public/js/api/factory/stv/projektbetreuer.js @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2025 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export default { + getProjektbetreuer(projektarbeit_id ) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getProjektbetreuer', + params: { projektarbeit_id } + }; + }, + getBetreuerarten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getBetreuerarten' + }; + }, + getDefaultStundensaetze(person_id, studiensemester_kurzbz) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getDefaultStundensaetze', + params: { person_id, studiensemester_kurzbz } + }; + }, + getNoten() { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getNoten' + }; + }, + saveProjektbetreuer(projektarbeit_id, projektbetreuerListe) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/saveProjektbetreuer', + params: { projektarbeit_id, projektbetreuerListe } + }; + }, + deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/deleteProjektbetreuer', + params: { projektarbeit_id, person_id, betreuerart_kurzbz } + }; + }, + getProjektbetreuerBySearchQuery(searchString) { + return { + method: 'get', + url: 'api/frontend/v1/stv/projektbetreuer/getProjektbetreuerBySearchQuery', + params: { searchString } + }; + }, + validateProjektbetreuer(projektbetreuer) { + return { + method: 'post', + url: 'api/frontend/v1/stv/projektbetreuer/validateProjektbetreuer', + params: { projektbetreuer } + }; + } +}; diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js deleted file mode 100644 index 5d223d694..000000000 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Betreuung.js +++ /dev/null @@ -1,847 +0,0 @@ -import {CoreFilterCmpt} from "../../../../filter/Filter.js"; -import FormForm from '../../../../Form/Form.js'; -import FormInput from '../../../../Form/Input.js'; -import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; - -import ApiStvAbschlusspruefung from '../../../../../api/factory/stv/abschlusspruefung.js'; - -export default { - components: { - CoreFilterCmpt, - BsModal, - FormForm, - FormInput, - PvAutoComplete, - AbschlusspruefungDropdown, - PruefungList - }, - inject: { - cisRoot: { - from: 'cisRoot' - }, - config: { - from: 'config', - required: true - }, - $reloadList: { - from: '$reloadList', - required: true - }, - isBerechtigtDocAndOdt: { - from: 'hasPermissionOutputformat', - default: false - } - }, - computed: { - studentUids() { - if (this.student.uid) - { - return [this.student.uid]; - } - return this.student.map(e => e.uid); - }, - studentKzs(){ - if (this.student.uid) - { - return [this.student.studiengang_kz]; - } - return this.student.map(e => e.studiengang_kz); - }, - stg_kz(){ - return this.studentKzs[0]; - }, - }, - props: { - student: Object - }, - data() { - return { - tabulatorOptions: { - ajaxURL: 'dummy', - ajaxRequestFunc: () => this.$api.call(ApiStvAbschlusspruefung.getAbschlusspruefung(this.student.uid)), - ajaxResponse: (url, params, response) => response.data, - columns: [ - {title: "vorsitz", field: "vorsitz_nachname"}, - {title: "abschlussbeurteilung", field: "beurteilung_bezeichnung"}, - {title: "prueferIn1", field: "p1_nachname", visible: false}, - {title: "prueferIn2", field: "p2_nachname", visible: false}, - {title: "prueferIn3", field: "p3_nachname", visible: false}, - { - title: "datum", - field: "datum", - formatter: function (cell) { - const dateStr = cell.getValue(); - if (!dateStr) return ""; - - const date = new Date(dateStr); - return date.toLocaleString("de-DE", { - day: "2-digit", - month: "2-digit", - year: "numeric", - hour12: false - }); - } - }, - {title: "uhrzeit", field: "uhrzeit"}, - { - title: "freigabe", - field: "freigabedatum", - formatter: function (cell) { - const dateStr = cell.getValue(); - if (!dateStr) return ""; - - const date = new Date(dateStr); - return date.toLocaleString("de-DE", { - day: "2-digit", - month: "2-digit", - year: "numeric", - hour12: false - }); - } - }, - {title: "pruefungsantritt", field: "antritt_bezeichnung"}, - { - title: "sponsion", - field: "sponsion", - formatter: function (cell) { - const dateStr = cell.getValue(); - if (!dateStr) return ""; - - const date = new Date(dateStr); - return date.toLocaleString("de-DE", { - day: "2-digit", - month: "2-digit", - year: "numeric", - hour12: false - }); - } - }, - {title: "anmerkung", field: "anmerkung"}, - {title: "abschlusspruefung_id", field: "abschlusspruefung_id", visible: false}, - {title: "typ", field: "pruefungstyp_kurzbz", visible: false}, - - { - title: 'Aktionen', field: 'actions', - minWidth: 150, // Ensures Action-buttons will be always fully displayed - formatter: (cell, formatterParams, onRendered) => { - let container = document.createElement('div'); - container.className = "d-flex gap-2"; - - let button = document.createElement('button'); - button.className = 'btn btn-outline-secondary btn-action'; - button.innerHTML = ''; - button.title = this.$p.t('ui', 'bearbeiten'); - button.addEventListener('click', (event) => - this.actionEditAbschlusspruefung(cell.getData().abschlusspruefung_id) - ); - container.append(button); - - button = document.createElement('button'); - button.className = 'btn btn-outline-secondary btn-action'; - button.innerHTML = ''; - button.title = this.$p.t('ui', 'loeschen'); - button.addEventListener('click', () => - this.actionDeleteAbschlusspruefung(cell.getData().abschlusspruefung_id) - ); - container.append(button); - - container.append(cell.getData().actionDiv); - - return container; - }, - frozen: true - }, - ], - layout: 'fitDataFill', - layoutColumnsOnNewData: false, - height: 'auto', - minHeight: '200', - selectable: true, - index: 'abschlusspruefung_id', - persistenceID: 'stv-details-finalexam' - }, - tabulatorEvents: [ - { - event: 'dataLoaded', - handler: data => this.tabulatorData = data.map(item => { - item.actionDiv = document.createElement('div'); - return item; - }), - }, - { - event: 'tableBuilt', - handler: async() => { - await this.$p.loadCategory(['global', 'person', 'stv', 'abschlusspruefung', 'ui']); - - - let cm = this.$refs.table.tabulator.columnManager; - - cm.getColumnByField('vorsitz_nachname').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'vorsitz_header') - }); - cm.getColumnByField('beurteilung_bezeichnung').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'abschlussbeurteilung') - }); - cm.getColumnByField('p1_nachname').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'pruefer1') - }); - cm.getColumnByField('p2_nachname').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'pruefer2') - }); - cm.getColumnByField('p3_nachname').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'pruefer3') - }); - cm.getColumnByField('datum').component.updateDefinition({ - title: this.$p.t('global', 'datum') - }); - cm.getColumnByField('uhrzeit').component.updateDefinition({ - title: this.$p.t('global', 'uhrzeit') - }); - cm.getColumnByField('freigabedatum').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'freigabe') - }); - cm.getColumnByField('antritt_bezeichnung').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'pruefungsantritt') - }); - cm.getColumnByField('sponsion').component.updateDefinition({ - title: this.$p.t('abschlusspruefung', 'sponsion') - }); - cm.getColumnByField('anmerkung').component.updateDefinition({ - title: this.$p.t('global', 'anmerkung') - }); - cm.getColumnByField('pruefungstyp_kurzbz').component.updateDefinition({ - title: this.$p.t('global', 'typ') - }); - cm.getColumnByField('abschlusspruefung_id').component.updateDefinition({ - title: this.$p.t('ui', 'abschlusspruefung_id') - }); - /* - cm.getColumnByField('actions').component.updateDefinition({ - title: this.$p.t('global', 'aktionen') - }); - */ - } - } - ], - tabulatorData: [], - lastSelected: null, - formData: { - typStg: null, - pruefungstyp_kurzbz: null, - akadgrad_id: null, - vorsitz: null, - pruefungsantritt_kurzbz: null, - abschlussbeurteilung_kurzbz: null, - datum: null, - sponsion: null, - pruefer1: null, - pruefer2: null, - pruefer3: null, - anmerkung: null, - protokoll: null, - note: null, - link: null - }, - statusNew: true, - arrTypen: [], - arrAntritte: [], - arrBeurteilungen: [], - arrAkadGrad: [], - arrNoten: [], - filteredMitarbeiter: [], - filteredPruefer: [], - abortController: { - mitarbeiter: null, - pruefer: null - }, - stgInfo: { typ: '', oe_kurzbz: '' } - } - }, - watch: { - student(){ - if (this.$refs.table) { - this.$refs.table.reloadTable(); - } - this.getStudiengangByKz(); - } - }, - methods: { - getStudiengangByKz(){ - this.stgInfo = { typ: '', oe_kurzbz: '' }; - this.$api - .call(ApiStudiengang.getStudiengangByKz(this.stg_kz)) - .then(result => this.stgInfo = result.data) - .catch(this.$fhcAlert.handleSystemError); - }, - actionNewAbschlusspruefung() { - this.resetForm(); - this.statusNew = true; - this.$refs.finalexamModal.show(); - this.setDefaultFormData(); - }, - actionEditAbschlusspruefung(abschlusspruefung_id) { - this.resetForm(); - this.statusNew = false; - this.$refs.finalexamModal.show(); - this.loadAbschlusspruefung(abschlusspruefung_id); - }, - actionDeleteAbschlusspruefung(abschlusspruefung_id) { - this.$fhcAlert - .confirmDelete() - .then(result => result - ? abschlusspruefung_id - : Promise.reject({handled: true})) - .then(this.deleteAbschlusspruefung) - .catch(this.$fhcAlert.handleSystemError); - }, - addNewAbschlusspruefung() { - const dataToSend = { - uid: this.student.uid, - formData: this.formData - }; - - return this.$refs.formFinalExam - .call(ApiStvAbschlusspruefung.addNewAbschlusspruefung(dataToSend)) - .then(response => { - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); - this.hideModal('finalexamModal'); - this.resetForm(); - }) - .catch(this.$fhcAlert.handleSystemError) - .finally(() => { - this.reload(); - }); - }, - hideModal(modalRef){ - this.$refs[modalRef].hide(); - }, - reload() { - this.$refs.table.reloadTable(); - }, - loadAbschlusspruefung(abschlusspruefung_id) { - return this.$api - .call(ApiStvAbschlusspruefung.loadAbschlusspruefung(abschlusspruefung_id)) - .then(result => { - this.formData = result.data; - //TODO(Manu) check if cisRoot is okay - this.formData.link = this.cisRoot + 'index.ci.php/lehre/Pruefungsprotokoll/showProtokoll?abschlusspruefung_id=' + this.formData.abschlusspruefung_id + '&fhc_controller_id=67481e5ed5490'; - return result; - }) - .catch(this.$fhcAlert.handleSystemError); - }, - updateAbschlusspruefung(abschlusspruefung_id) { - const dataToSend = { - id: abschlusspruefung_id, - formData: this.formData - }; - return this.$refs.formFinalExam - .call(ApiStvAbschlusspruefung.updateAbschlusspruefung(dataToSend)) - .then(response => { - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); - this.hideModal('finalexamModal'); - this.resetForm(); - }) - .catch(this.$fhcAlert.handleSystemError) - .finally(() => { - this.reload(); - }); - }, - deleteAbschlusspruefung(abschlusspruefung_id) { - return this.$api - .call(ApiStvAbschlusspruefung.deleteAbschlusspruefung(abschlusspruefung_id)) - .then(response => { - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); - }) - .catch(this.$fhcAlert.handleSystemError) - .finally(() => { - this.reload(); - }); - }, - resetForm() { - this.formData.pruefungstyp_kurzbz = null; - this.formData.akadgrad_id = null; - this.formData.vorsitz = null; - this.formData.pruefungsantritt_kurzbz = null; - this.formData.abschlussbeurteilung_kurzbz = null; - this.formData.datum = null; //oder new Date(); - this.formData.sponsion = null; - this.formData.pruefer1 = null; - this.formData.pruefer2 = null; - this.formData.pruefer3 = null; - this.formData.anmerkung = null; - this.formData.protokoll = null; - this.formData.note = null; - this.formData.p1 = null; - this.formData.p2 = null; - this.formData.p3 = null; - this.formData.pv = null; - }, - search(event) { - if (this.abortController.mitarbeiter) { - this.abortController.mitarbeiter.abort(); - } - this.abortController.mitarbeiter = new AbortController(); - - return this.$api - .call(ApiStvAbschlusspruefung.getMitarbeiter(event.query)) - .then(result => { - this.filteredMitarbeiter = result.data.retval; - }); - }, - searchNotAkad(event) { - if (this.abortController.pruefer) { - this.abortController.pruefer.abort(); - } - this.abortController.pruefer = new AbortController(); - - return this.$api - .call(ApiStvAbschlusspruefung.getPruefer(event.query)) - .then(result => { - this.filteredPruefer = result.data.retval; - }); - }, - setDefaultFormData() { - - this.resetForm(); - - if (this.stgInfo.typ === 'b') { - this.formData.pruefungstyp_kurzbz = 'Bachelor'; - this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster'); - } - if (this.stgInfo.typ === 'd' || this.stgInfo === 'm') { - this.formData.pruefungstyp_kurzbz = 'Diplom'; - this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster'); - } - if (this.stgInfo.typ === 'lg') { - this.formData.pruefungstyp_kurzbz = 'lgabschluss'; - } - - if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) { - this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id; - } - }, - printDocument(link) { - window.open(link, '_blank'); - }, - }, - created() { - this.$api - .call(ApiStvAbschlusspruefung.getTypenAbschlusspruefung()) - .then(result => { - this.arrTypen = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - - this.$api - .call(ApiStvAbschlusspruefung.getTypenAntritte()) - .then(result => { - this.arrAntritte = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - - this.$api - .call(ApiStvAbschlusspruefung.getBeurteilungen()) - .then(result => { - this.arrBeurteilungen = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - - this.$api - .call(ApiStvAbschlusspruefung.getNoten()) - .then(result => { - this.arrNoten = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - - this.$api - .call(ApiStvAbschlusspruefung.getAkadGrade(this.student.studiengang_kz)) - .then(result => { - this.arrAkadGrad = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - if (!this.student.length) { - this.$api - .call(ApiStudiengang.getStudiengangByKz(this.student.studiengang_kz)) - .then(result => { - this.stgInfo = result.data; - this.setDefaultFormData(); - }) - .catch(this.$fhcAlert.handleSystemError); - } else - this.getStudiengangByKz(); - }, - template: ` -
-

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

- -
- -
- - - - - - - - - - - - - {{this.$p.t('global','details')}} -

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

-
- - - - - - - -
- -
- - - - -
- -
- - - - - -
- -
- - - - - - - -
- -
- - - - - -
- -
- - - - -
- -
- - - - -
- -
-
-

{{$p.t('abschlusspruefung', 'zurBeurteilung')}}

-
- -
- -
- - - -
- - - - -
-` -} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js index a6256ceb1..7f98948d4 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -1,4 +1,3 @@ -import {CoreFilterCmpt} from "../../../../filter/Filter.js"; import FormForm from '../../../../Form/Form.js'; import FormInput from '../../../../Form/Input.js'; import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; @@ -7,7 +6,6 @@ import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js export default { components: { - CoreFilterCmpt, FormForm, FormInput, PvAutoComplete @@ -48,23 +46,12 @@ export default { } return lehreinheiten; - }, - //~ preparedFormData() { - //~ console.log("FOR DATA CALLEd"); - //~ if (this.formData.projektarbeit_id == null) delete(this.formData.projektarbeit_id); - //~ if (this.formData.firma) this.formData.firma_id = this.formData.firma.firma_id; - //~ delete(this.formData.firma); - //~ delete(this.formData.firma_name); - //~ delete(this.formData.lehrveranstaltung_id); - //~ // convert null value fields from string to null - //~ return this.formData; - //~ } + } }, props: { statusNew: Boolean, student: Object, - projektarbeit: Object, - stg_kz: Number + projektarbeit: Object }, data() { return { @@ -177,21 +164,13 @@ export default { }) .catch(this.$fhcAlert.handleSystemError); }, - setFormData(arrTypen, arrLvs, arrNoten, projektarbeitData) { - this.arrTypen = arrTypen; - this.arrLvs = arrLvs; - this.arrNoten = arrNoten; - if (projektarbeitData) { - projektarbeitData.firma = {firma_id: projektarbeitData.firma_id, name: projektarbeitData.firma_name}; - this.formData = projektarbeitData; - } - }, loadProjektarbeit(projektarbeit_id) { return this.$api .call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id)) .then(result => { this.formData = result.data; + if (this.formData.firma_id) this.formData.firma = {firma_id: this.formData.firma_id, name: this.formData.firma_name}; return result; }) .catch(this.$fhcAlert.handleSystemError) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js index 034b3fd6c..15c9aeeee 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -7,6 +7,7 @@ import PvAutoComplete from "../../../../../../../index.ci.php/public/js/componen import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js'; import ProjektarbeitDetails from "./Details.js"; +import Projektbetreuer from "./Projektbetreuer.js"; export default { components: { @@ -15,7 +16,8 @@ export default { FormForm, FormInput, PvAutoComplete, - ProjektarbeitDetails + ProjektarbeitDetails, + Projektbetreuer }, inject: { cisRoot: { @@ -174,7 +176,9 @@ export default { button.title = this.$p.t('ui', 'bearbeiten'); button.addEventListener('click', (event) => { let data = cell.getData(); - this.actionEditProjektarbeit(data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id); + this.actionEditProjektarbeit( + data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id, data.projekttyp_kurzbz + ); }); container.append(button); @@ -195,7 +199,6 @@ export default { }, ], layout: 'fitDataFill', - layoutColumnsOnNewData: false, height: 'auto', minHeight: '200', selectable: 1, @@ -240,25 +243,20 @@ export default { lehrveranstaltung_id: null } }, - //~ watch: { - //~ student(){ - //~ if (this.$refs.table) { - //~ this.$refs.table.reloadTable(); - //~ } - //~ this.getStudiengangByKz(); - //~ } - //~ }, methods: { actionNewProjektarbeit() { this.statusNew = true; this.$refs.projektarbeitDetails.resetForm(); this.$refs.projektarbeitDetails.getFormData(); + this.$refs.projektbetreuer.getData(); this.$refs.projektarbeitModal.show(); }, - actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id) { + actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id, projekttyp_kurzbz) { this.statusNew = false; this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id); + // TODO: maybe preload projektarbeit? not just on edit? this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id); + this.$refs.projektbetreuer.getData(projektarbeit_id, studiensemester_kurzbz, projekttyp_kurzbz); this.$refs.projektarbeitModal.show(); }, actionDeleteProjektarbeit(projektarbeit_id) { @@ -271,41 +269,41 @@ export default { .catch(this.$fhcAlert.handleSystemError); }, addNewProjektarbeit() { - Promise.allSettled([ - this.$refs.projektarbeitDetails.addNewProjektarbeit() - ]).then((results) => { - let hasError = false; - results.forEach((promise_result) => { + this.$refs.projektbetreuer.validateProjektbetreuer() + .then(() => { + return this.$refs.projektarbeitDetails.addNewProjektarbeit(); + }) + .then((result) => { + const projektarbeit_id = result.data; + console.log(projektarbeit_id); - if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) { - - hasError = true; + if (!isNaN(projektarbeit_id)) { + return this.$refs.projektbetreuer.saveProjektbetreuer(projektarbeit_id); } - }); - - if (!hasError) { + }) + .then((result) => { + console.log(result); this.projektarbeitSaved(); - } - }); + }) + .catch(this.$fhcAlert.handleSystemError); }, updateProjektarbeit() { - Promise.allSettled( - [ - this.$refs.projektarbeitDetails.updateProjektarbeit() - ]).then((results) => { - let hasError = false; - results.forEach((promise_result) => { + this.$refs.projektbetreuer.validateProjektbetreuer() + .then(() => { + return this.$refs.projektarbeitDetails.updateProjektarbeit(); + }) + .then((result) => { + const projektarbeit_id = result.data; + console.log(projektarbeit_id); - if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) { - - hasError = true; + if (!isNaN(projektarbeit_id)) { + return this.$refs.projektbetreuer.saveProjektbetreuer(projektarbeit_id); } - }); - - if (!hasError) { + }) + .then((result) => { this.projektarbeitSaved(); - } - }); + }) + .catch(this.$fhcAlert.handleSystemError); }, deleteProjektarbeit(projektarbeit_id) { return this.$api @@ -325,7 +323,6 @@ export default { this.$refs.projektarbeitDetails.resetForm(); }, rowSelectionChanged(data) { - console.log("selection changed"); this.lastSelected = data.length > 0 ? data[0] : null; }, hideModal(modalRef){ @@ -362,7 +359,14 @@ export default {

{{$p.t('projektarbeit', 'projektarbeitBearbeiten')}}

- +
+
+ +
+
+ +
+
` -}; \ No newline at end of file +}; diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index a4381b00d..433a52d3e 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -41789,7 +41789,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Title', + 'text' => 'title', 'description' => '', 'insertvon' => 'system' ) @@ -41809,7 +41809,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Title English', + 'text' => 'title English', 'description' => '', 'insertvon' => 'system' ) @@ -41829,7 +41829,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Topic area', + 'text' => 'topic area', 'description' => '', 'insertvon' => 'system' ) @@ -41849,7 +41849,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Type', + 'text' => 'type', 'description' => '', 'insertvon' => 'system' ) @@ -41869,7 +41869,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Company', + 'text' => 'company', 'description' => '', 'insertvon' => 'system' ) @@ -41889,7 +41889,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Course', + 'text' => 'course', 'description' => '', 'insertvon' => 'system' ) @@ -41909,7 +41909,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Teaching unit', + 'text' => 'teaching unit', 'description' => '', 'insertvon' => 'system' ) @@ -41920,6 +41920,26 @@ and represent the current state of research on the topic. The prescribed citatio 'category' => 'projektarbeit', 'phrase' => 'betreuer', 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Betreuer', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'assessor', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuerGross', + 'insertvon' => 'system', 'phrases' => array( array( 'sprache' => 'German', @@ -41935,6 +41955,26 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'betreuerart', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Betreuerart', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'assessor type', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'projektarbeit', @@ -41949,7 +41989,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Grade', + 'text' => 'grade', 'description' => '', 'insertvon' => 'system' ) @@ -41969,7 +42009,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Hours', + 'text' => 'hours', 'description' => '', 'insertvon' => 'system' ) @@ -41989,7 +42029,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Hourly rate', + 'text' => 'hourly rate', 'description' => '', 'insertvon' => 'system' ) @@ -42029,7 +42069,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Start', + 'text' => 'start', 'description' => '', 'insertvon' => 'system' ) @@ -42049,7 +42089,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'End', + 'text' => 'end', 'description' => '', 'insertvon' => 'system' ) @@ -42089,7 +42129,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Locked until', + 'text' => 'locked until', 'description' => '', 'insertvon' => 'system' ) @@ -42109,7 +42149,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Annotation', + 'text' => 'annotation', 'description' => '', 'insertvon' => 'system' ) @@ -42129,7 +42169,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Company Id', + 'text' => 'company Id', 'description' => '', 'insertvon' => 'system' ) @@ -42215,6 +42255,326 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'neuePersonAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Neue Person anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create new person', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'titelPre', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Titel (Pre)', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title (Pre)', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'titelPost', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Titel (Post)', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'title (Post)', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'weitereVornamen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Weitere Vornamen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'other first names', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'bestehendeAdresseUeberschreiben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Bestehende Adresse überschreiben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Replace existing address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'adresseHinzufuegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Adresse hinzufügen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Add new address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'adresseNichtAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Adresse nicht anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Do not create address', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'land', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Land', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'nation', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'mobil', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Mobil', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'mobile phone', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'letzeAusbildung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Letzte Ausbildung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'most recent education', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'ausbildungsart', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ausbildungsart', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'education type', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'anmerkungen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Anmerkungen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'notes', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'personAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Person anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create person', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'interessentAnlegen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'InteressentIn anlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create candidate', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'person', + 'phrase' => 'personExistiertPruefung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfung ob Person bereits existiert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Check if a person already exists', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'ui', + 'phrase' => 'zurueck', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Zurück', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Back', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From 750b956dd22ce736fe8341312ec141dad0265cad Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 2 Jun 2025 15:28:10 +0200 Subject: [PATCH 010/258] Studentenverwaltung Projektarbeit: added button for editing contact data --- .../Details/Projektarbeit/Projektbetreuer.js | 31 +++++++++++++++++-- system/phrasesupdate.php | 20 ++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index 079b8b796..4f3095cab 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -1,18 +1,22 @@ import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import BsModal from "../../../../Bootstrap/Modal.js"; import FormForm from '../../../../Form/Form.js'; import FormInput from '../../../../Form/Input.js'; import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; import NewPerson from "../../List/New.js"; +import Contact from "../Kontakt/Contact.js"; import ApiStvProjektbetreuer from '../../../../../api/factory/stv/projektbetreuer.js'; export default { components: { CoreFilterCmpt, + BsModal, FormForm, FormInput, PvAutoComplete, - NewPerson + NewPerson, + Contact }, inject: { }, @@ -340,6 +344,10 @@ export default { this.$refs.newPersonModal.reset(); this.$refs.newPersonModal.open(); }, + actionKontaktdatenBearbeiten() { + if (!this.autocompleteSelectedBetreuer) return; + this.$refs.kontaktdatenModal.show(); + }, personSaved(result) { this.$api .call(ApiStvProjektbetreuer.getPerson(result.person_id)) @@ -384,9 +392,12 @@ export default {
-
+
+
+ +
@@ -455,6 +466,22 @@ export default { + + + + + + +
+
+ + +
+
+ +
` } diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 433a52d3e..d467252d7 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -42575,6 +42575,26 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'kontaktdatenBearbeiten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Kontaktdaten bearbeiten', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Edit contact data', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ) ); From fe81e7fb7c5bb528f911d315bd64c28c894fb0e6 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 3 Jun 2025 21:18:03 +0200 Subject: [PATCH 011/258] Studierendenverwaltung Projektarbeit: added button for Projektarbeit download --- .../api/frontend/v1/stv/Projektbetreuer.php | 26 +- .../Details/Projektarbeit/Projektbetreuer.js | 251 ++++++++++-------- system/phrasesupdate.php | 20 ++ 3 files changed, 171 insertions(+), 126 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php index 34f626eca..7a1b803b9 100644 --- a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -3,6 +3,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); use \DateTime as DateTime; +use CI3_Events as Events; class Projektbetreuer extends FHCAPI_Controller { @@ -85,6 +86,21 @@ class Projektbetreuer extends FHCAPI_Controller //~ } //~ } + foreach ($projektbetreuer as $pb) + { + $downloadLink = null; + Events::trigger( + 'projektbeurteilung_download_link', + $pb->projektarbeit_id, + $pb->betreuerart_kurzbz, + $pb->person_id, + function ($value) use (&$downloadLink) { + $downloadLink = $value; + } + ); + $pb->projektarbeitDownload = $downloadLink; + } + $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); } @@ -105,11 +121,7 @@ class Projektbetreuer extends FHCAPI_Controller foreach ($projektbetreuer as $pb) { - if ($this->_validate($pb) == false) - { - $this->addMeta('test', 'foisch'); - $this->terminateWithValidationErrors($this->form_validation->error_array()); - } + if ($this->_validate($pb) == false) $this->terminateWithValidationErrors($this->form_validation->error_array()); } $result = null; @@ -210,10 +222,6 @@ class Projektbetreuer extends FHCAPI_Controller $result = $this->StundensatzModel->getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz); - $this->addMeta('res', $result); - - //if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); - return $this->terminateWithSuccess($result); } diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index 4f3095cab..bf459ebc5 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -113,6 +113,7 @@ export default { arrNoten: [], filteredBetreuer: [], autocompleteSelectedBetreuer: null, + projektarbeitDownload: null, abortController: { betreuer: null } @@ -146,6 +147,7 @@ export default { if (idx >= 0) { betreuer = projektbetreuerListe[idx]; this.formData = betreuer; + if (betreuer.projektarbeitDownload) this.projektarbeitDownload = betreuer.projektarbeitDownload this.autocompleteSelectedBetreuer = { person_id: this.formData.person_id, name: this.formData.name, @@ -268,6 +270,7 @@ export default { }, resetForm() { this.formData = this.getDefaultFormData(); + this.projektarbeitDownload = null; this.autocompleteSelectedBetreuer = null; this.initialFormData = null; if (this.projekttyp_kurzbz) this.setDefaultStunden(this.projekttyp_kurzbz); @@ -358,130 +361,144 @@ export default { } }, template: ` -
+
- {{this.$p.t('projektarbeit','betreuerGross')}} - +
- - + {{this.$p.t('projektarbeit','betreuerGross')}} + - -
- - -
+ + -
-
- -
-
- -
-
- -
- -
+ + +
+ + + + + + + + + +
+
+ + +
+
+ +
` } diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index d467252d7..d10f915cc 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -42594,6 +42594,26 @@ and represent the current state of research on the topic. The prescribed citatio 'insertvon' => 'system' ) ) + ), + array( + 'app' => 'core', + 'category' => 'projektarbeit', + 'phrase' => 'projektbeurteilungErstellen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Projektbeurteilung erstellen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create project assessment document', + 'description' => '', + 'insertvon' => 'system' + ) + ) ) ); From e26bce2cf7d21d78e59c09ba16c46097c6d4ef0b Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 10 Jun 2025 14:14:32 +0200 Subject: [PATCH 012/258] removed merge text from code --- application/models/ressource/Stundensatz_model.php | 1 - 1 file changed, 1 deletion(-) diff --git a/application/models/ressource/Stundensatz_model.php b/application/models/ressource/Stundensatz_model.php index 553bdd20b..c8ee367d8 100644 --- a/application/models/ressource/Stundensatz_model.php +++ b/application/models/ressource/Stundensatz_model.php @@ -150,4 +150,3 @@ class Stundensatz_model extends DB_Model return $default_stundensatz; } } -==== BASE ==== From d15d27b3e14dbbf179fa85e4167b71c09c49c5f0 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Fri, 13 Jun 2025 16:19:53 +0200 Subject: [PATCH 013/258] =?UTF-8?q?Studierendenverwaltung=20Projektarbeit:?= =?UTF-8?q?=20added=20Vertr=C3=A4ge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/frontend/v1/stv/Config.php | 6 +- .../api/frontend/v1/stv/Projektbetreuer.php | 2 +- .../api/frontend/v1/stv/Vertrag.php | 104 +++++++++++ .../models/accounting/Vertrag_model.php | 20 +++ public/js/api/factory/stv/vertrag.js | 20 +++ .../Details/Projektarbeit/Details.js | 6 +- .../Details/Projektarbeit/Projektarbeit.js | 24 --- .../Details/Projektarbeit/Projektbetreuer.js | 103 +++++++---- .../Details/Projektarbeit/Vertrag.js | 168 ++++++++++++++++++ system/phrasesupdate.php | 68 ++++++- 10 files changed, 457 insertions(+), 64 deletions(-) create mode 100644 application/controllers/api/frontend/v1/stv/Vertrag.php create mode 100644 public/js/api/factory/stv/vertrag.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 98a06ffb5..83173375e 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -127,7 +127,11 @@ class Config extends FHCAPI_Controller $result['projektarbeit'] = [ 'title' => $this->p->t('stv', 'tab_projektarbeit'), 'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js', - 'config' => $config['projektarbeit'] + 'config' => array_merge( + $config['projektarbeit'], + ['showVertragsdetails' => + defined('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN') && FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN] + ) ]; $result['mobility'] = [ diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php index 7a1b803b9..af0a11d0f 100644 --- a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -98,7 +98,7 @@ class Projektbetreuer extends FHCAPI_Controller $downloadLink = $value; } ); - $pb->projektarbeitDownload = $downloadLink; + $pb->beurteilungDownloadLink = $downloadLink; } $this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer)); diff --git a/application/controllers/api/frontend/v1/stv/Vertrag.php b/application/controllers/api/frontend/v1/stv/Vertrag.php new file mode 100644 index 000000000..f94fe795e --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Vertrag.php @@ -0,0 +1,104 @@ + ['admin:r', 'assistenz:r'], + 'cancelVertrag' => ['admin:r', 'assistenz:r'] + ]); + + // Load Libraries + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + 'person', + 'projektarbeit' + ]); + + // Load models + $this->load->model('accounting/Vertrag_model', 'VertragModel'); + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + + // load libraries + $this->load->library('PermissionLib'); + } + + public function getVertrag() + { + $vertrag_id = $this->input->get('vertrag_id'); + + if (!isset($vertrag_id) || !is_numeric($vertrag_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Vertrag ID']), self::ERROR_TYPE_GENERAL); + + $result = $this->VertragModel->getVertragById($vertrag_id); + + if (isError($result)) + { + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + } + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $vertrag = getData($result)[0]; + + $this->terminateWithSuccess($vertrag); + } + + public function cancelVertrag() + { + $vertrag_id = $this->input->post('vertrag_id'); + $person_id = $this->input->post('person_id'); + + if (!isset($vertrag_id) || !is_numeric($vertrag_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Vertrag ID']), self::ERROR_TYPE_GENERAL); + if (!isset($person_id) || !is_numeric($person_id)) + $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL); + + // * first find lehrveranstaltung_id of the contracts lehrveranstaltung + $this->VertragModel->addSelect('lehrveranstaltung_id'); + $this->VertragModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id', 'LEFT'); + $result = $this->VertragModel->loadWhere(['vertrag_id' => $vertrag_id]); + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + if (!hasData($result)) $this->terminateWithSuccess([]); + + $lehrveranstaltung_id = getData($result)[0]->lehrveranstaltung_id; + + $allOe = $this->LehrveranstaltungModel->getAllOe($lehrveranstaltung_id); + + if (isError($allOe)) $this->terminateWithError(getError($allOe), self::ERROR_TYPE_GENERAL); + + $allOe = hasData($allOe) ? getData($allOe) : []; + + $this->addMeta('oe', $allOe); + + // * then check if the user has permissions to cancel the corresponding lv-organisational units + if (!$this->permissionlib->isBerechtigtMultipleOe('admin', $allOe, 'suid') && + !$this->permissionlib->isBerechtigtMultipleOe('lehre/lehrauftrag_bestellen', $allOe, 'suid')) + { + return $this->_outputAuthError([$this->router->method => ['admin:rw', 'lehrauftrag_bestellen:rw']]); + } + + $uidResult = $this->BenutzerModel->getFromPersonId($person_id); + + if (isError($uidResult)) $this->terminateWithError(getError($uidResult), self::ERROR_TYPE_GENERAL); + + if (!hasData($uidResult)) $this->terminateWithError("no user found", self::ERROR_TYPE_GENERAL); + + $mitarbeiter_uid = getData($uidResult)[0]->uid; + + $result = $this->VertragModel->cancelVertrag($vertrag_id, $mitarbeiter_uid); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } +} diff --git a/application/models/accounting/Vertrag_model.php b/application/models/accounting/Vertrag_model.php index c17c676c7..4c036369b 100644 --- a/application/models/accounting/Vertrag_model.php +++ b/application/models/accounting/Vertrag_model.php @@ -402,6 +402,26 @@ class Vertrag_model extends DB_Model return $this->loadWhere(array('mitarbeiter_uid' => $mitarbeiter_uid, 'lehreinheit_id' => $lehreinheit_id)); } + public function getVertragById($vertrag_id) + { + $this->addSelect( + 'tbl_vertrag.vertrag_id, vertragstyp_kurzbz, vertragsstunden, vertragsstunden_studiensemester_kurzbz, status.vertragsstatus_kurzbz, + status.bezeichnung AS vertragsstatus, tbl_vertrag.betrag, lema.semesterstunden, lema.stundensatz' + ); + $this->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_vertrag.vertrag_id = lema.vertrag_id', 'LEFT'); + $this->addJoin(' + ( + SELECT DISTINCT ON(vst.vertrag_id) vst.vertrag_id, + bezeichnung, + tbl_vertragsstatus.vertragsstatus_kurzbz + FROM lehre.tbl_vertrag_vertragsstatus vst + JOIN lehre.tbl_vertragsstatus USING(vertragsstatus_kurzbz) + ORDER BY vst.vertrag_id, datum DESC + ) as status', 'status.vertrag_id = lehre.tbl_vertrag.vertrag_id', 'LEFT'); + + return $this->loadWhere(['tbl_vertrag.vertrag_id' => $vertrag_id]); + } + public function cancelVertrag($vertrag_id, $mitarbeiter_uid) { $vertrag = $this->load($vertrag_id); diff --git a/public/js/api/factory/stv/vertrag.js b/public/js/api/factory/stv/vertrag.js new file mode 100644 index 000000000..9070936da --- /dev/null +++ b/public/js/api/factory/stv/vertrag.js @@ -0,0 +1,20 @@ +export default { + + getVertrag(vertrag_id) + { + return { + method: 'get', + url: 'api/frontend/v1/stv/vertrag/getVertrag', + params: { vertrag_id }, + }; + }, + + cancelVertrag(data) + { + return { + method: 'post', + url: '/api/frontend/v1/stv/vertrag/cancelVertrag/', + params: data + }; + } +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js index 4f833621d..c2269c1b3 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -15,15 +15,13 @@ export default { defaultSemester: { from: 'defaultSemester' } - //~ cisRoot: { - //~ from: 'cisRoot' - //~ }, //~ config: { //~ from: 'config', //~ required: true //~ } }, computed: { + // prepared Lehreinheiten (with compound Bezeichnung) arrLes() { let lehreinheiten = []; if (this.formData.lehrveranstaltung_id) { @@ -133,7 +131,6 @@ export default { //~ //this.$fhcAlert.handleSystemError(promise_result); //~ } //~ //let data = promise_result.value.data; - //~ console.log(promise_result.status); //~ }); //~ if (!hasError) { @@ -214,6 +211,7 @@ export default { lvChanged(event) { this.formData.lehreinheit_id = null; }, + // enrich and modify data before sending getPreparedFormData() { let preparedFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js index 8314db8b3..3f9958a26 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -30,29 +30,6 @@ export default { from: '$reloadList', required: true } - //~ isBerechtigtDocAndOdt: { - //~ from: 'hasPermissionOutputformat', - //~ default: false - //~ } - }, - computed: { - //~ studentUids() { - //~ if (this.student.uid) - //~ { - //~ return [this.student.uid]; - //~ } - //~ return this.student.map(e => e.uid); - //~ }, - //~ studentKzs(){ - //~ if (this.student.uid) - //~ { - //~ return [this.student.studiengang_kz]; - //~ } - //~ return this.student.map(e => e.studiengang_kz); - //~ }, - //~ stg_kz(){ - //~ return this.studentKzs.length > 0 ? this.studentKzs.length[0] : null; - //~ } }, props: { student: Object @@ -271,7 +248,6 @@ export default { actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id, projekttyp_kurzbz) { this.statusNew = false; this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id); - // TODO: maybe preload projektarbeit? not just on edit? this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id); this.$refs.projektbetreuer.getData(projektarbeit_id, studiensemester_kurzbz, projekttyp_kurzbz); this.$refs.projektarbeitModal.show(); diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index bf459ebc5..8368534c7 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -5,6 +5,7 @@ import FormInput from '../../../../Form/Input.js'; import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; import NewPerson from "../../List/New.js"; import Contact from "../Kontakt/Contact.js"; +import Vertrag from "./Vertrag.js"; import ApiStvProjektbetreuer from '../../../../../api/factory/stv/projektbetreuer.js'; @@ -16,9 +17,13 @@ export default { FormInput, PvAutoComplete, NewPerson, - Contact + Contact, + Vertrag }, - inject: { + provide() { + return { + configShowVertragsdetails: this.config.showVertragsdetails + } }, computed: { betreuerFormOpened() { @@ -107,13 +112,13 @@ export default { initialFormData: null, defaultFormDataValues: {stunden: null, stundensatz: null}, projektarbeit_id: null, - statusNew: true, editedBetreuerIdx: -1, arrBetreuerart: [], arrNoten: [], filteredBetreuer: [], autocompleteSelectedBetreuer: null, - projektarbeitDownload: null, + beurteilungDownloadLink: null, + vertragFieldsDisabled: false, abortController: { betreuer: null } @@ -122,19 +127,19 @@ export default { methods: { actionNewProjektbetreuer() { this.resetForm(); - this.statusNew = true; this.newMode = !this.newMode; this.editMode = false; this.captureFormData(); }, actionEditProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { - - this.statusNew = false; this.editMode = true; + this.newMode = false; this.$api .call(ApiStvProjektbetreuer.getDefaultStundensaetze(person_id, this.studiensemester_kurzbz)) .then(result => { this.resetForm(); + + // get betreuer from tabulator list let projektbetreuerListe = this.$refs.projektbetreuerTable.tabulator.getData(); const idx = projektbetreuerListe.findIndex( betr => @@ -144,18 +149,29 @@ export default { ); let betreuer = []; - if (idx >= 0) { + if (idx >= 0) { // if betreuer found betreuer = projektbetreuerListe[idx]; + + // set currently edited betreuera this.formData = betreuer; - if (betreuer.projektarbeitDownload) this.projektarbeitDownload = betreuer.projektarbeitDownload + + // set download link + if (betreuer.beurteilungDownloadLink) this.beurteilungDownloadLink = betreuer.beurteilungDownloadLink + + // set betreuer for autocomplete field this.autocompleteSelectedBetreuer = { person_id: this.formData.person_id, name: this.formData.name, vorname: this.formData.vorname, - nachname: this.formData.nachname + nachname: this.formData.nachname, + vertrag_id: this.formData.vertrag_id }; } + + // set default stundensatz (if no other is set yet) if (this.formData.stundensatz == null) this.formData.stundensatz = result.data; + + // capture initial form data for detecting changes this.captureFormData(); }) .catch(this.$fhcAlert.handleSystemError); @@ -167,10 +183,12 @@ export default { ? {projektarbeit_id, person_id, betreuerart_kurzbz} : Promise.reject({handled: true})) .then(result => { - return this.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) + return this.$api + .call(ApiStvProjektbetreuer.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz)) }) .then(result => { this.$refs.projektbetreuerTable.tabulator.deleteRow(betreuer_id); + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); }) .catch(this.$fhcAlert.handleSystemError); }, @@ -178,9 +196,12 @@ export default { this.studiensemester_kurzbz = studiensemester_kurzbz; + // default Stundensätze from config this.defaultFormDataValues.stunden = this.getDefaultStunden(projekttyp_kurzbz); this.defaultFormDataValues.stundensatz = this.config.defaultProjektbetreuerStundensatz; + this.resetModes(); + // get other initial data this.$api .call(ApiStvProjektbetreuer.getBetreuerarten()) .then(result => { @@ -209,6 +230,7 @@ export default { this.resetForm(); } }, + // confirming Betreuer means adding/updating him in list (but not yet saving in db) confirmProjektbetreuer() { if (!this.betreuerFormOpened) return; @@ -217,11 +239,9 @@ export default { this.$refs.projektbetreuerTable.tabulator.addData(this.addAutoCompleteBetreuerToFormData(this.formData)); } else { this.$refs.projektbetreuerTable.tabulator.updateData([this.formData]); - this.statusNew = true; } - this.newMode = false; - this.editMode = false; + this.resetModes(); }, confirmProjektbetreuerAfterValidation() { //if (!this.formDataModified()) return; @@ -239,14 +259,6 @@ export default { ApiStvProjektbetreuer.saveProjektbetreuer(projektarbeit_id, this.$refs.projektbetreuerTable.tabulator.getData()) ); }, - deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { - return this.$api - .call(ApiStvProjektbetreuer.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz)) - .then(response => { - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); - }) - .catch(this.$fhcAlert.handleSystemError) - }, searchBetreuer(event) { if (this.abortController.betreuer) { this.abortController.betreuer.abort(); @@ -259,6 +271,7 @@ export default { this.filteredBetreuer = result.data; }); }, + // validate betreuer for data validateProjektbetreuer() { let alleBetreuer = this.$refs.projektbetreuerTable.tabulator.getData(); @@ -270,10 +283,15 @@ export default { }, resetForm() { this.formData = this.getDefaultFormData(); - this.projektarbeitDownload = null; + this.beurteilungDownloadLink = null; this.autocompleteSelectedBetreuer = null; this.initialFormData = null; if (this.projekttyp_kurzbz) this.setDefaultStunden(this.projekttyp_kurzbz); + this.disableVertragFields(false); + }, + resetModes() { + this.newMode = false; + this.editMode = false; }, getDefaultFormData() { let formData = {betreuerart_kurzbz : null, note: null}; @@ -287,6 +305,7 @@ export default { captureFormData() { this.initialFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy }, + // add own betreuer ids to betreuer liste addIds(betreuerListe) { for (const idx in betreuerListe) { @@ -298,6 +317,7 @@ export default { } return betreuerListe; }, + // add the betreuer selected in automomplete to betreuer liste addAutoCompleteBetreuerToFormData() { let preparedFormData = this.formData; @@ -311,6 +331,7 @@ export default { return preparedFormData; }, + // get default values for stunden getDefaultStunden(projekttyp_kurzbz) { let stunden = '0.0'; if (projekttyp_kurzbz == 'Bachelor') stunden = this.config.defaultProjektbetreuerStunden; @@ -319,8 +340,10 @@ export default { }, setDefaultStunden(projekttyp_kurzbz) { this.projekttyp_kurzbz = projekttyp_kurzbz; + // if form data has not already been modified by user, set the default stunden if (!this.formDataModified()) this.formData.stunden = this.getDefaultStunden(projekttyp_kurzbz); }, + // get a new betreuer id (max + 1) getNewBetreuerId() { let max = 0; @@ -330,6 +353,7 @@ export default { return max + 1; }, + // check if form data has been modified since initial data has been captured formDataModified() { if (this.autocompleteSelectedBetreuer != null) return true; @@ -351,22 +375,27 @@ export default { if (!this.autocompleteSelectedBetreuer) return; this.$refs.kontaktdatenModal.show(); }, + // stuff to do after new person has been saved personSaved(result) { this.$api .call(ApiStvProjektbetreuer.getPerson(result.person_id)) .then(response => { + // set the new person in autocomplete field this.autocompleteSelectedBetreuer = response.data; }) .catch(this.$fhcAlert.handleSystemError) + }, + // disable fields which are dependent on Vertrag status + disableVertragFields(disabled) { + this.vertragFieldsDisabled = disabled; } }, template: `
-
+
{{this.$p.t('projektarbeit','betreuerGross')}} -
@@ -448,6 +478,7 @@ export default { type="text" name="stunden" :label="$p.t('projektarbeit', 'stunden')" + :disabled="vertragFieldsDisabled" v-model="formData.stunden" > @@ -459,6 +490,7 @@ export default { type="text" name="stundensatz" :label="$p.t('projektarbeit', 'stundensatz')" + :disabled="vertragFieldsDisabled" v-model="formData.stundensatz" > @@ -469,11 +501,23 @@ export default { - +
+ + {{ autocompleteSelectedBetreuer?.person_id && (!beurteilungDownloadLink || beurteilungDownloadLink == '') ? $p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') : ''}} +
- @@ -485,8 +529,7 @@ export default { + v-if="autocompleteSelectedBetreuer && autocompleteSelectedBetreuer.person_id">
-
+
-
+
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index fd796e3e1..9b02f9b01 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -84,13 +84,16 @@ export default { frozen: true }, ], - layout: 'fitDataFill', + //layout: 'fitDataFill', layoutColumnsOnNewData: false, height: 'auto', minHeight: '100', selectable: true, selectable: 1, index: 'betreuer_id', + persistence:{ + columns: true, //persist column layout + }, persistenceID: 'stv-details-projektbetreuer' }, tabulatorEvents: [ @@ -99,6 +102,13 @@ export default { handler: async() => { await this.$p.loadCategory(['global', 'person', 'stv', 'projektarbeit', 'ui']); } + }, + { + event: 'rowSelected', + handler: row => { + let data = row.getData(); + this.actionEditProjektbetreuer(data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz); + } } ], formData: { @@ -156,7 +166,7 @@ export default { this.formData = betreuer; // set download link - if (betreuer.beurteilungDownloadLink) this.beurteilungDownloadLink = betreuer.beurteilungDownloadLink + if (betreuer.beurteilungDownloadLink !== null) this.beurteilungDownloadLink = betreuer.beurteilungDownloadLink; // set betreuer for autocomplete field this.autocompleteSelectedBetreuer = { @@ -279,15 +289,16 @@ export default { alleBetreuer.push(this.addAutoCompleteBetreuerToFormData(this.formData)); } - return this.$api.call(ApiStvProjektbetreuer.validateProjektbetreuer(alleBetreuer)); + return this.$refs.formProjektbetreuer.call(ApiStvProjektbetreuer.validateProjektbetreuer(alleBetreuer)); }, resetForm() { this.formData = this.getDefaultFormData(); - this.beurteilungDownloadLink = null; + if (this.beurteilungDownloadLink !== null) this.beurteilungDownloadLink = ''; this.autocompleteSelectedBetreuer = null; this.initialFormData = null; if (this.projekttyp_kurzbz) this.setDefaultStunden(this.projekttyp_kurzbz); this.disableVertragFields(false); + this.$refs.formProjektbetreuer.clearValidation(); }, resetModes() { this.newMode = false; @@ -417,7 +428,7 @@ export default { type="autocomplete" optionLabel="name" v-model="autocompleteSelectedBetreuer" - name="betreuer" + name="person_id" :suggestions="filteredBetreuer" @complete="searchBetreuer" :min-length="3" @@ -501,13 +512,13 @@ export default { -
+
- {{ autocompleteSelectedBetreuer?.person_id && (!beurteilungDownloadLink || beurteilungDownloadLink == '') ? $p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') : ''}} + {{ autocompleteSelectedBetreuer?.person_id && beurteilungDownloadLink === '' ? $p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') : ''}}
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js index 1f494d1ec..074d22bde 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js @@ -125,36 +125,22 @@ export default{
{{ betreuerProjektarbeit?.betreuerart_kurzbz && betreuerProjektarbeit?.vertrag_id == null ? ' – '+$p.t('lehre', 'nochKeinVertrag') : '' }}
-
- -
- {{$p.t('lehre', 'vertragurfassung')}}
- - +
+ {{ $p.t('lehre', 'vertragsstatus') }}: {{ vertragsstatus }} +
- - +
+ {{$p.t('lehre', 'vertragurfassung')}} +
+
+
+
+ {{ $p.t('lehre', 'semesterstunden') }}: {{ data.vertragsstunden }} +
+ {{ $p.t('lehre', 'studiensemester') }}: {{ data.vertragsstunden_studiensemester_kurzbz }} +
@@ -164,7 +150,7 @@ export default{ :disabled="vertragsstatus == vertragsstatus_storniert" @click="cancelVertrag" > - {{ $p.t('lehre', 'stornieren') }} + {{ $p.t('lehre', 'vertragStornieren') }}
diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index db16dc247..24b37f594 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -43778,7 +43778,7 @@ and represent the current state of research on the topic. The prescribed citatio array( 'app' => 'core', 'category' => 'lehre', - 'phrase' => 'stornieren', + 'phrase' => 'vertragStornieren', 'insertvon' => 'system', 'phrases' => array( array( @@ -43789,7 +43789,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'Cancel', + 'text' => 'Cancel contract', 'description' => '', 'insertvon' => 'system' ) From 4eaf71e5c634cfe7a96bdce0b3d5d7a3b423eee6 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 14 Jul 2025 17:01:16 +0200 Subject: [PATCH 025/258] cancel Vertrag: correct error handling --- .../Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js index 074d22bde..c5de5a1fb 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Vertrag.js @@ -96,7 +96,7 @@ export default{ ? {vertrag_id: this.vertrag_id, person_id: this.person_id} : Promise.reject({handled: true})) .then(result => { - this.$api.call(ApiVertrag.cancelVertrag({vertrag_id: this.vertrag_id, person_id: this.person_id})) + return this.$api.call(ApiVertrag.cancelVertrag({vertrag_id: this.vertrag_id, person_id: this.person_id})) }) .then(result => { this.resetForm(); From 1f258c84d4d01aa4db7df27480d8cea3042b7772 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 15 Jul 2025 18:56:49 +0200 Subject: [PATCH 026/258] Studierendenverwaltung Projektarbeit: moved Beurteilung download to table actions, separate tabs for details and Betreuer --- .../Details/Projektarbeit/Projektarbeit.js | 34 +++++-- .../Details/Projektarbeit/Projektbetreuer.js | 88 +++++++++++++------ 2 files changed, 87 insertions(+), 35 deletions(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js index dd7c4913c..76953867f 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -348,19 +348,39 @@ export default { - + -
-
- - + + +
+
+
+
+ + +
+
-
- + +
+
+
+ +
+
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index 9b02f9b01..183c81bc0 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -51,7 +51,8 @@ export default { {title: "Vertrag ID", field: "vertrag_id", visible: false}, {title: "Projektarbeit ID", field: "projektarbeit_id", visible: false}, { - title: 'Aktionen', field: 'actions', + title: 'Aktionen', + field: 'actions', minWidth: 150, // Ensures Action-buttons will be always fully displayed formatter: (cell, formatterParams, onRendered) => { let container = document.createElement('div'); @@ -62,6 +63,8 @@ export default { button.innerHTML = ''; button.title = this.$p.t('ui', 'bearbeiten'); button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); let data = cell.getData(); this.actionEditProjektbetreuer(data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz); }); @@ -71,13 +74,41 @@ export default { button.className = 'btn btn-outline-secondary btn-action'; button.innerHTML = ''; button.title = this.$p.t('ui', 'loeschen'); - button.addEventListener('click', () => { + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); const data = cell.getData(); this.actionDeleteProjektbetreuer(data.betreuer_id, data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz) }); container.append(button); - //container.append(cell.getData().actionDiv); + let data = cell.getData(); + if (data.beurteilungDownloadLink !== null) { + if (data.beurteilungDownloadLink == '') { + button = document.createElement('span'); + button.title = this.$p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') + button.innerHTML = ''; + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + }); + } + else { + button = document.createElement('a'); + button.setAttribute('href', data.beurteilungDownloadLink); + button.setAttribute('role', 'button'); + button.innerHTML = ''; + button.title = this.$p.t('projektarbeit', 'projektbeurteilungErstellen'); + button.className = 'btn btn-outline-secondary btn-action'; + button.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + window.location.href = data.beurteilungDownloadLink; + }); + } + container.append(button); + } return container; }, @@ -404,7 +435,7 @@ export default { template: `
-
+
{{this.$p.t('projektarbeit','betreuerGross')}} @@ -484,27 +515,28 @@ export default {
- - -
- -
- - +
+ + +
+
+ + +
@@ -512,17 +544,17 @@ export default { -
+
-
+
Date: Tue, 15 Jul 2025 23:08:12 +0200 Subject: [PATCH 027/258] Studierendenverwaltung archiv: removed tabulator columns from computed --- .../Stv/Studentenverwaltung/Details/Archiv.js | 91 ------------------- 1 file changed, 91 deletions(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js index 41bd222b8..d02b64c18 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js @@ -67,97 +67,6 @@ export default { }; }, computed: { - tabulatorColumns() { - const columns = [ - {title: "Akte Id", field: "akte_id", visible: false}, - {title: this.$p.t('stv', 'archiv_title'), field: "titel"}, - {title: this.$p.t('stv', 'archiv_description'), field: "bezeichnung"}, - {title: this.$p.t('stv', 'archiv_creation_date'), field: "erstelltam"}, - { - title: this.$p.t('stv', 'archiv_signiert'), - field: "signiert", - formatter:"tickCross", - hozAlign:"center", - formatterParams: { - tickElement: '', - crossElement: '' - } - }, - { - title: "Selfservice", - field: "stud_selfservice", - formatter:"tickCross", - hozAlign:"center", - formatterParams: { - tickElement: '', - crossElement: '' - }, - }, - {title: this.$p.t('stv', 'archiv_accepted_on_at'), field: "akzeptiertamum"}, - { - title: this.$p.t('stv', 'archiv_gedruckt'), - field: "gedruckt", - visible: false, - formatter:"tickCross", - hozAlign:"center", - formatterParams: { - tickElement: '', - crossElement: '' - } - }, - { - title: 'Aktionen', field: 'actions', - formatter: (cell, formatterParams, onRendered) => { - let container = document.createElement('div'); - container.className = "d-flex gap-2"; - - let downloadButton = document.createElement('button'); - downloadButton.className = 'btn btn-outline-secondary'; - downloadButton.innerHTML = ''; - downloadButton.title = this.$p.t('ui', 'downloadDok'); - downloadButton.addEventListener('click', evt => { - evt.stopPropagation(); - this.actionDownload(cell.getData().akte_id); - }); - container.append(downloadButton); - - if (this.config.showEdit) - { - let editButton = document.createElement('button'); - editButton.className = 'btn btn-outline-secondary'; - editButton.innerHTML = ''; - editButton.addEventListener('click', () => - this.$refs.edit.open(cell.getData()) - ); - container.append(editButton); - } - - let deleteButton = document.createElement('button'); - deleteButton.className = 'btn btn-outline-secondary'; - deleteButton.innerHTML = ''; - deleteButton.addEventListener('click', evt => { - evt.stopPropagation(); - this.$fhcAlert - .confirmDelete() - .then(result => result ? {akte_id: cell.getData().akte_id, studiengang_kz: this.modelValue.studiengang_kz} : Promise.reject({handled:true})) - .then(this.$fhcApi.factory.stv.archiv.delete) - .then(() => { - //cell.getRow().delete(); - this.reload(); - }) - .catch(this.$fhcAlert.handleSystemError); - }); - container.append(deleteButton); - - return container; - }, - minWidth: 150, // Ensures Action-buttons will be always fully displayed - maxWidth: 150, - frozen: true - } - ]; - return columns; - }, tabulatorOptions() { const options = { ajaxURL: 'dummy', From 94e25da6c89afb2a173bde19df662dd96cf6d07e Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 16 Jul 2025 16:13:27 +0200 Subject: [PATCH 028/258] Added phrases for lvevaluierung --- system/phrasesupdate.php | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 8ac45c0fa..417eb9110 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -42322,6 +42322,86 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'spracheAuswaehlen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sprache auswählen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Select language', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'fhtwLogo', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'FH Technikum Wien Logo', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'UAS Technikum Wien Logo', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungscodeEingeben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Evaluierungscode eingeben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Enter Evaluation code', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'fragebogen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Fragebogen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Questionnaire', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From 75adcefd5168f2b3da82d7fa19aaeb7eb6343821 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 21 Jul 2025 17:52:21 +0200 Subject: [PATCH 029/258] Studentenverwaltung Projektarbeit: made text input possible for all date input --- .../Studentenverwaltung/Details/Projektarbeit/Details.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js index e51828f98..2fdc9d996 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -350,7 +350,10 @@ export default { v-model="formData.beginn" auto-apply :enable-time-picker="false" + text-input + locale="de" format="dd.MM.yyyy" + model-type="yyyy-MM-dd" name="beginn" > @@ -361,7 +364,10 @@ export default { v-model="formData.ende" auto-apply :enable-time-picker="false" + text-input + locale="de" format="dd.MM.yyyy" + model-type="yyyy-MM-dd" name="ende" > @@ -375,7 +381,10 @@ export default { v-model="formData.gesperrtbis" auto-apply :enable-time-picker="false" + text-input + locale="de" format="dd.MM.yyyy" + model-type="yyyy-MM-dd" name="gesperrtbis" > From ca3f8bc554a71c5ebd66f61ec1750b6a821b0b15 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Tue, 19 Aug 2025 11:24:51 +0200 Subject: [PATCH 030/258] move statusofsemester select into shared function --- .../api/frontend/v1/stv/Students.php | 72 ++++--------------- 1 file changed, 12 insertions(+), 60 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 26b5000bb..4bd449715 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -334,18 +334,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect("'' AS gruppe"); $this->addSelectPrioRel(); - //add status per semester - $this->PrestudentModel->addSelect( - "( - SELECT status_kurzbz - FROM public.tbl_prestudentstatus pss - WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id - AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " - ORDER BY GREATEST(pss.datum, '0001-01-01') DESC - LIMIT 1 - ) AS statusofsemester" - ); - $this->addFilter($studiensemester_kurzbz); $result = $this->PrestudentModel->loadWhere($where); @@ -462,18 +450,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect('v.gruppe'); $this->PrestudentModel->addSelect("'' AS priorisierung_relativ"); - //add status per semester - $this->PrestudentModel->addSelect( - "( - SELECT status_kurzbz - FROM public.tbl_prestudentstatus pss - WHERE pss.prestudent_id = public.tbl_prestudent.prestudent_id - AND pss.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " - ORDER BY GREATEST(pss.datum, '0001-01-01') DESC - LIMIT 1 - ) AS statusofsemester" - ); - $where = []; @@ -562,18 +538,6 @@ class Students extends FHCAPI_Controller $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); @@ -631,18 +595,6 @@ class Students extends FHCAPI_Controller $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(); @@ -696,18 +648,6 @@ class Students extends FHCAPI_Controller $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); @@ -772,6 +712,18 @@ class Students extends FHCAPI_Controller // verband // 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->PrestudentModel->addSelect('UPPER(stg.typ || stg.kurzbz) AS studiengang'); $this->PrestudentModel->addSelect('tbl_prestudent.studiengang_kz'); $this->PrestudentModel->addSelect('stg.bezeichnung AS stg_bezeichnung'); From 6ee3f1d241a2f9f4360dfcfe8cb4ed892e0069d2 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Wed, 20 Aug 2025 11:32:31 +0200 Subject: [PATCH 031/258] show Bezeichnung in Subject Vorlage, add adaption for Tinymce for openMode inSamePage --- .../api/frontend/v1/messages/Messages.php | 18 ++++------ public/js/api/factory/messages/messages.js | 4 +-- public/js/api/messages/person.js | 4 +-- .../Messages/Details/NewMessage/Modal.js | 19 ++++------- .../Messages/Details/NewMessage/NewDiv.js | 34 ++++++------------- 5 files changed, 28 insertions(+), 51 deletions(-) diff --git a/application/controllers/api/frontend/v1/messages/Messages.php b/application/controllers/api/frontend/v1/messages/Messages.php index fa6748f6a..6ca1c74c0 100644 --- a/application/controllers/api/frontend/v1/messages/Messages.php +++ b/application/controllers/api/frontend/v1/messages/Messages.php @@ -16,7 +16,7 @@ class Messages extends FHCAPI_Controller 'getNameOfDefaultRecipient' => ['admin:r', 'assistenz:r'], 'sendMessage' => ['admin:r', 'assistenz:r'], 'deleteMessage' => ['admin:r', 'assistenz:r'], - 'getVorlagentext' => ['admin:r', 'assistenz:r'], + 'getDataVorlage' => ['admin:r', 'assistenz:r'], 'getPreviewText' => ['admin:r', 'assistenz:r'], 'getReplyData' => ['admin:r', 'assistenz:r'], 'getPersonId' => ['admin:r', 'assistenz:r'], @@ -89,10 +89,8 @@ class Messages extends FHCAPI_Controller $this->terminateWithSuccess($data); } - public function getVorlagentext($vorlage_kurzbz) + public function getDataVorlage($vorlage_kurzbz) { - //$this->terminateWithError("vor " . $vorlage_kurzbz, self::ERROR_TYPE_GENERAL); - //$studiengang_kz = 227; //TODO(Manu) dynamisieren NULL $studiengang_kz = 0; $this->load->model('system/Vorlagestudiengang_model', 'VorlagestudiengangModel'); $this->VorlagestudiengangModel->addOrder('version', 'DESC'); @@ -104,12 +102,8 @@ class Messages extends FHCAPI_Controller ]); $data = $this->getDataOrTerminateWithError($result); - - //not correct with Vorlage $vorlage = current($data); - - //$this->terminateWithSuccess($data); - $this->terminateWithSuccess($vorlage->text); + $this->terminateWithSuccess($vorlage); } public function getMessageVarsPerson($id, $typeId) @@ -154,7 +148,7 @@ class Messages extends FHCAPI_Controller public function sendMessage($recipient_id) { //has to be uid - // $this->terminateWithError("uid", $recipient_id, self::ERROR_TYPE_GENERAL); + // $this->terminateWithError("uid", $recipient_id, self::ERROR_TYPE_GENERAL); //default setting $receiversPersonId = $this->_getPersonId($recipient_id, 'uid'); @@ -223,7 +217,7 @@ class Messages extends FHCAPI_Controller } elseif($typeId == 'prestudent_id') { - // $this->terminateWithError("prestudent_id ", self::ERROR_TYPE_GENERAL); + // $this->terminateWithError("prestudent_id ", self::ERROR_TYPE_GENERAL); $result = $this->MessagesModel->parseMessageTextPrestudent($id, $body); $bodyParsed = $this->getDataOrTerminateWithError($result); @@ -429,7 +423,7 @@ class Messages extends FHCAPI_Controller private function _getPrestudentIdFromUid($uid) { - // $this->terminateWithError($uid, self::ERROR_TYPE_GENERAL); + // $this->terminateWithError($uid, self::ERROR_TYPE_GENERAL); $this->load->model('crm/Student_model', 'StudentModel'); $result = $this->StudentModel->loadWhere( ['student_uid' => $uid] diff --git a/public/js/api/factory/messages/messages.js b/public/js/api/factory/messages/messages.js index cec34ad8b..c6d4b67b6 100644 --- a/public/js/api/factory/messages/messages.js +++ b/public/js/api/factory/messages/messages.js @@ -62,10 +62,10 @@ export default { url: 'api/frontend/v1/messages/messages/getUid/' + userParams.id + '/' + userParams.type_id }; }, - getVorlagentext(vorlage_kurzbz){ + getDataVorlage(vorlage_kurzbz){ return { method: 'get', - url: 'api/frontend/v1/messages/messages/getVorlagentext/' + vorlage_kurzbz + url: 'api/frontend/v1/messages/messages/getDataVorlage/' + vorlage_kurzbz }; }, getNameOfDefaultRecipient(params){ diff --git a/public/js/api/messages/person.js b/public/js/api/messages/person.js index e2d2fd0c4..19b3603e2 100644 --- a/public/js/api/messages/person.js +++ b/public/js/api/messages/person.js @@ -20,8 +20,8 @@ export default { getUid(params){ return this.$fhcApi.get('api/frontend/v1/messages/messages/getUid/'+ params.id + '/' + params.type_id); }, - getVorlagentext(vorlage_kurzbz){ - return this.$fhcApi.get('api/frontend/v1/messages/messages/getVorlagentext/' + vorlage_kurzbz); + getDataVorlage(vorlage_kurzbz){ + return this.$fhcApi.get('api/frontend/v1/messages/messages/getDataVorlage/' + vorlage_kurzbz); }, getNameOfDefaultRecipient(params){ return this.$fhcApi.get('api/frontend/v1/messages/messages/getNameOfDefaultRecipient/' + params.id + '/' + params.type_id); diff --git a/public/js/components/Messages/Details/NewMessage/Modal.js b/public/js/components/Messages/Details/NewMessage/Modal.js index b0d8cca7d..ce9235617 100644 --- a/public/js/components/Messages/Details/NewMessage/Modal.js +++ b/public/js/components/Messages/Details/NewMessage/Modal.js @@ -136,17 +136,13 @@ export default { } ); }, - getVorlagentext(vorlage_kurzbz){ + getDataVorlage(vorlage_kurzbz){ return this.$api - .call(this.endpoint.getVorlagentext(vorlage_kurzbz)) + .call(this.endpoint.getDataVorlage(vorlage_kurzbz)) .then(response => { - this.formData.body = response.data; - }).catch(this.$fhcAlert.handleSystemError) - .finally(() => { - //this.resetForm(); - //closeModal - //closewindwo - }); + this.formData.body = response.data.text; + this.formData.subject = response.data.subject; + }).catch(this.$fhcAlert.handleSystemError); }, getPreviewText(){ const data = new FormData(); @@ -197,8 +193,7 @@ export default { }, handleSelectedVorlage(vorlage_kurzbz) { if (typeof vorlage_kurzbz === "string") { - this.getVorlagentext(vorlage_kurzbz); - this.formData.subject = vorlage_kurzbz; + this.getDataVorlage(vorlage_kurzbz); } }, showPreview(){ @@ -240,7 +235,7 @@ export default { handler(newVal){ if (newVal && newVal != null) { this.formData.subject = newVal; - return this.getVorlagentext(newVal); + return this.getDataVorlage(newVal); } } }, diff --git a/public/js/components/Messages/Details/NewMessage/NewDiv.js b/public/js/components/Messages/Details/NewMessage/NewDiv.js index 7622f0928..24674fd3f 100644 --- a/public/js/components/Messages/Details/NewMessage/NewDiv.js +++ b/public/js/components/Messages/Details/NewMessage/NewDiv.js @@ -136,15 +136,13 @@ export default { } ); }, - getVorlagentext(vorlage_kurzbz){ + getDataVorlage(vorlage_kurzbz){ return this.$api - .call(this.endpoint.getVorlagentext(vorlage_kurzbz)) + .call(this.endpoint.getDataVorlage(vorlage_kurzbz)) .then(response => { - this.formData.body = response.data; - }).catch(this.$fhcAlert.handleSystemError) - .finally(() => { - //this.resetForm(); - }); + this.formData.body = response.data.text; + this.formData.subject = response.data.subject; + }).catch(this.$fhcAlert.handleSystemError); }, getPreviewText(id, typeId){ const data = new FormData(); @@ -164,20 +162,11 @@ export default { insertVariable(selectedItem){ if (this.editor) { this.editor.insertContent(selectedItem.value + " "); - //TODO(Manu) check: Laden von Variblen geht nicht wenn kein Zeichen danach kommt - // nicht mal mit Punkt adden gehts ohne eintrag nach vars - //this.editor.focus(); - // this.editor.setDirty(true); - this.editor.setDirty(true);//seting dirty true if changes appear - // console.log(tinyMCE.activeEditor.isDirty());//dirty output = true - - - //this.editor.undoManager.add(); - - //this.editor.insertContent(selectedItem.value + "\u00A0"); - //this.editor.insertContent(`${selectedItem.value} `); - //this.editor.selection.setCursorLocation(this.editor.getBody(), 1); + this.editor.fire('input'); + this.editor.fire('change'); + this.editor.setDirty(true); + this.editor.save(); } else { console.error("Editor instance is not available."); @@ -202,8 +191,7 @@ export default { }, handleSelectedVorlage(vorlage_kurzbz) { if (typeof vorlage_kurzbz === "string") { - this.getVorlagentext(vorlage_kurzbz); - this.formData.subject = vorlage_kurzbz; + this.getDataVorlage(vorlage_kurzbz); } }, hideTemplate(){ @@ -248,7 +236,7 @@ export default { if (newVal && newVal != null) { this.formData.subject = newVal; - return this.getVorlagentext(newVal); + return this.getDataVorlage(newVal); } } }, From b73eac62b5dd36899ccd96a93f5db6dd59337e5d Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 11:54:01 +0200 Subject: [PATCH 032/258] add studiensemester param to incoming/outgoing/gs backend --- application/config/routes.php | 6 +++--- .../api/frontend/v1/stv/Students.php | 21 ++++++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/application/config/routes.php b/application/config/routes.php index da3a45f03..189400a72 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -70,9 +70,9 @@ $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv // (studiensemester_kurzbz)/inout[/(incoming|outgoing|gemeinsamestudien)] $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout'] = 'api/frontend/v1/stv/Students/index'; -$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/incoming'] = 'api/frontend/v1/stv/Students/getIncoming'; -$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/outgoing'] = 'api/frontend/v1/stv/Students/getOutgoing'; -$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/gemeinsamestudien'] = 'api/frontend/v1/stv/Students/getGemeinsamestudien'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/incoming'] = 'api/frontend/v1/stv/Students/getIncoming/$1'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/outgoing'] = 'api/frontend/v1/stv/Students/getOutgoing/$1'; +$route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/inout/gemeinsamestudien'] = 'api/frontend/v1/stv/Students/getGemeinsamestudien/$1'; // (studiengang_kz)/prestudent[/(studiensemester_kurzbz)[/(filter)[/(otherfilter)]]] $route['api/frontend/v1/stv/[sS]tudents/(:num)/prestudent'] = 'api/frontend/v1/stv/Students/getPrestudents/$1'; diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 4bd449715..88a87804e 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -101,31 +101,46 @@ class Students extends FHCAPI_Controller } /** + * @param string $studiensemester_kurzbz + * * @return void */ - public function getIncoming() + public function getIncoming($studiensemester_kurzbz) { $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', [ + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); // TODO(chris): IMPLEMENT! $this->terminateWithSuccess([]); } /** + * @param string $studiensemester_kurzbz + * * @return void */ - public function getOutgoing() + public function getOutgoing($studiensemester_kurzbz) { $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', [ + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); // TODO(chris): IMPLEMENT! $this->terminateWithSuccess([]); } /** + * @param string $studiensemester_kurzbz + * * @return void */ - public function getGemeinsamestudien() + public function getGemeinsamestudien($studiensemester_kurzbz) { $this->addMeta('ci_method', __FUNCTION__); + $this->addMeta('ci_params', [ + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); // TODO(chris): IMPLEMENT! $this->terminateWithSuccess([]); } From 31a5caa5580b2002c337265fdd64447a3bcc9361 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 11:56:29 +0200 Subject: [PATCH 033/258] better (safer) output for semester verband gruppe prio --- .../api/frontend/v1/stv/Students.php | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 88a87804e..71b7be872 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -342,9 +342,11 @@ class Students extends FHCAPI_Controller $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect(" - CASE WHEN ps.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') - THEN ps.ausbildungssemester::text - ELSE ''::text END AS semester", false); + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN ps.ausbildungssemester::text + ELSE ''::text + END AS semester", false); $this->PrestudentModel->addSelect("'' AS verband"); $this->PrestudentModel->addSelect("'' AS gruppe"); $this->addSelectPrioRel(); @@ -549,9 +551,16 @@ class Students extends FHCAPI_Controller );*/ $this->prepareQuery($studiensemester_kurzbz); - $this->PrestudentModel->addSelect("COALESCE(v.semester::text, CASE WHEN public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') THEN public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)::text ELSE ''::text END) AS semester", false); - $this->PrestudentModel->addSelect('v.verband'); - $this->PrestudentModel->addSelect('v.gruppe'); + $this->PrestudentModel->addSelect("COALESCE( + v.semester::text, + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN pls.ausbildungssemester::text + ELSE ''::text + END + ) AS semester", false); + $this->PrestudentModel->addSelect("COALESCE(v.verband::text, ''::text)"); + $this->PrestudentModel->addSelect("COALESCE(v.gruppe::text, ''::text)"); $this->addSelectPrioRel(); @@ -796,12 +805,12 @@ class Students extends FHCAPI_Controller SELECT count(*) FROM ( SELECT *, public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) AS laststatus - FROM PUBLIC.tbl_prestudent pss - JOIN PUBLIC.tbl_prestudentstatus USING (prestudent_id) + FROM public.tbl_prestudent pss + JOIN public.tbl_prestudentstatus USING (prestudent_id) WHERE person_id = p.person_id AND studiensemester_kurzbz = ( SELECT studiensemester_kurzbz - FROM PUBLIC.tbl_prestudentstatus + FROM public.tbl_prestudentstatus WHERE prestudent_id = tbl_prestudent.prestudent_id AND status_kurzbz = 'Interessent' LIMIT 1 @@ -810,7 +819,7 @@ class Students extends FHCAPI_Controller ) prest WHERE laststatus NOT IN ('Abbrecher', 'Abgewiesener', 'Absolvent') AND priorisierung <= tbl_prestudent.priorisierung - ) || ' (' || tbl_prestudent.priorisierung || ')' AS priorisierung_relativ", false); + ) || ' (' || COALESCE(tbl_prestudent.priorisierung::text, ' '::text) || ')' AS priorisierung_relativ", false); } /** From 923427b41f20bfde6304dba69102b7a993c08f89 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 11:57:31 +0200 Subject: [PATCH 034/258] Implement: stv/students/getIncoming --- .../api/frontend/v1/stv/Students.php | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 71b7be872..b4116ed0d 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -111,8 +111,43 @@ class Students extends FHCAPI_Controller $this->addMeta('ci_params', [ 'studiensemester_kurzbz' => $studiensemester_kurzbz ]); - // TODO(chris): IMPLEMENT! - $this->terminateWithSuccess([]); + + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + + $this->prepareQuery($studiensemester_kurzbz); + + $this->PrestudentModel->addSelect("COALESCE( + v.semester::text, + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN pls.ausbildungssemester::text + ELSE ''::text + END + ) AS semester", false); + $this->PrestudentModel->addSelect("COALESCE(v.verband::text, ''::text)"); + $this->PrestudentModel->addSelect("COALESCE(v.gruppe::text, ''::text)"); + + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + + $selectIncoming = "SELECT 1 + FROM public.tbl_prestudentstatus test + WHERE test.prestudent_id=tbl_prestudent.prestudent_id + AND test.status_kurzbz='Incoming' + AND test.studiensemester_kurzbz=v.studiensemester_kurzbz"; + + $this->PrestudentModel->db->where("EXISTS (" . $selectIncoming . ")", null, false); + + $result = $this->PrestudentModel->load(); + + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); } /** From 5ba0007641ec0bd23f95a7944da07ba304a5b39c Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 14:34:19 +0200 Subject: [PATCH 035/258] fix: correct relative priority calculation --- application/controllers/api/frontend/v1/stv/Students.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index b4116ed0d..fe2167189 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -839,7 +839,7 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect("( SELECT count(*) FROM ( - SELECT *, public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) AS laststatus + SELECT *, public.get_rolle_prestudent(pss.prestudent_id, NULL) AS laststatus FROM public.tbl_prestudent pss JOIN public.tbl_prestudentstatus USING (prestudent_id) WHERE person_id = p.person_id From c9104749c54969682790843bd8ab3111827bd8c4 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 16:52:16 +0200 Subject: [PATCH 036/258] Faster Query for stv/students/getIncoming --- .../api/frontend/v1/stv/Students.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index fe2167189..8dcdbcc5e 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -116,6 +116,17 @@ class Students extends FHCAPI_Controller $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->PrestudentModel->addJoin( + "( + SELECT prestudent_id + FROM public.tbl_prestudentstatus + WHERE status_kurzbz = 'Incoming' + AND studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ) test", + "prestudent_id" + ); + + $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect("COALESCE( @@ -134,14 +145,6 @@ class Students extends FHCAPI_Controller $this->addFilter($studiensemester_kurzbz); - $selectIncoming = "SELECT 1 - FROM public.tbl_prestudentstatus test - WHERE test.prestudent_id=tbl_prestudent.prestudent_id - AND test.status_kurzbz='Incoming' - AND test.studiensemester_kurzbz=v.studiensemester_kurzbz"; - - $this->PrestudentModel->db->where("EXISTS (" . $selectIncoming . ")", null, false); - $result = $this->PrestudentModel->load(); From 7de81fab7de9cb8472b670b25fe3b5e302d10968 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 20 Aug 2025 17:00:14 +0200 Subject: [PATCH 037/258] Implement: stv/students/getOutgoing --- .../api/frontend/v1/stv/Students.php | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 8dcdbcc5e..0e4a311c9 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -164,8 +164,60 @@ class Students extends FHCAPI_Controller $this->addMeta('ci_params', [ 'studiensemester_kurzbz' => $studiensemester_kurzbz ]); - // TODO(chris): IMPLEMENT! - $this->terminateWithSuccess([]); + + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + + $this->PrestudentModel->addJoin( + "( + SELECT prestudent_id + FROM bis.tbl_bisio bis + JOIN public.tbl_student USING (student_uid) + JOIN public.tbl_studiensemester stdsem ON ( + (bis.von >= stdsem.start AND bis.von <= stdsem.ende) + OR + (bis.bis >= stdsem.start AND bis.bis <= stdsem.ende) + OR + (bis.von <= stdsem.start AND bis.bis >= stdsem.ende) + ) + WHERE NOT EXISTS ( + SELECT 1 + FROM public.tbl_prestudentstatus + WHERE status_kurzbz = 'Incoming' + AND prestudent_id = tbl_student.prestudent_id + ) AND stdsem.studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + GROUP BY prestudent_id + ) test", + "prestudent_id" + ); + + + $this->prepareQuery($studiensemester_kurzbz); + + + $this->PrestudentModel->addSelect("COALESCE( + v.semester::text, + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN pls.ausbildungssemester::text + ELSE ''::text + END + ) AS semester", false); + $this->PrestudentModel->addSelect("COALESCE(v.verband::text, ''::text)"); + $this->PrestudentModel->addSelect("COALESCE(v.gruppe::text, ''::text)"); + + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + + $result = $this->PrestudentModel->load(); + + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); } /** From 608e2b5171aa236497369813226080d7b65ddf66 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 21 Aug 2025 09:18:52 +0200 Subject: [PATCH 038/258] Implement: stv/students/getGemeinsamestudien --- .../api/frontend/v1/stv/Students.php | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 0e4a311c9..691e56b74 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -231,8 +231,46 @@ class Students extends FHCAPI_Controller $this->addMeta('ci_params', [ 'studiensemester_kurzbz' => $studiensemester_kurzbz ]); - // TODO(chris): IMPLEMENT! - $this->terminateWithSuccess([]); + + + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + + + $this->PrestudentModel->addJoin( + "( + SELECT prestudent_id + FROM bis.tbl_mobilitaet + WHERE studiensemester_kurzbz = " . $this->PrestudentModel->escape($studiensemester_kurzbz) . " + ) bis", + "prestudent_id" + ); + + + $this->prepareQuery($studiensemester_kurzbz); + + + $this->PrestudentModel->addSelect("COALESCE( + v.semester::text, + CASE + WHEN pls.status_kurzbz IN ('Aufgenommener', 'Bewerber', 'Wartender', 'interessent') + THEN pls.ausbildungssemester::text + ELSE ''::text + END + ) AS semester", false); + $this->PrestudentModel->addSelect("COALESCE(v.verband::text, ''::text)"); + $this->PrestudentModel->addSelect("COALESCE(v.gruppe::text, ''::text)"); + + $this->addSelectPrioRel(); + + $this->addFilter($studiensemester_kurzbz); + + + $result = $this->PrestudentModel->load(); + + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); } public function getPrestudents($studiengang_kz, From 9b8ac595c6783060354e6ae0e8bbd1e9719e54a4 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 21 Aug 2025 12:59:24 +0200 Subject: [PATCH 039/258] Code Quality --- application/config/routes.php | 4 +- .../api/frontend/v1/stv/Students.php | 162 ++++++------------ 2 files changed, 56 insertions(+), 110 deletions(-) diff --git a/application/config/routes.php b/application/config/routes.php index 189400a72..58677e8ee 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -1,6 +1,6 @@ my_controller/my_method */ $route['default_controller'] = defined('CIS4') && CIS4 ? 'Cis4' : 'Vilesci'; -$route['translate_uri_dashes'] = FALSE; +$route['translate_uri_dashes'] = false; // Class name conflicts $route['api/v1/organisation/[S|s]tudiengang/(:any)'] = 'api/v1/organisation/studiengang2/$1'; diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 691e56b74..04dc7a33a 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -51,7 +51,6 @@ class Students extends FHCAPI_Controller 'lehre' ) ); - } /** @@ -75,7 +74,7 @@ class Students extends FHCAPI_Controller * /(studiengang_kz)/(orgform)/prestudent/(studiensemester_kurzbz)/(filter) => getPrestudentsOrgform * /(studiengang_kz)/(orgform)/prestudent/(studiensemester_kurzbz)/(filter)/(otherfilter) => getPrestudentsOrgform * - * /(studiensemester_kurzbz)/(studiengang_kz)/(semester)/grp/(gruppe) => getStudentsSpezialguppe + * /(studiensemester_kurzbz)/(studiengang_kz)/(semester)/grp/(gruppe) => getStudentsSpezialgruppe * * /(studiensemester_kurzbz)/(studiengang_kz) => getStudents * /(studiensemester_kurzbz)/(studiengang_kz)/(semester) => getStudents @@ -273,10 +272,11 @@ class Students extends FHCAPI_Controller $this->terminateWithSuccess($data); } - public function getPrestudents($studiengang_kz, - $studiensemester_kurzbz = null, $filter = null - ) - { + public function getPrestudents( + $studiengang_kz, + $studiensemester_kurzbz = null, + $filter = null + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiengang_kz' => $studiengang_kz, @@ -287,10 +287,12 @@ class Students extends FHCAPI_Controller $this->fetchPrestudents($studiengang_kz, $studiensemester_kurzbz, $filter); } - public function getPrestudentsOrgform($studiengang_kz, $orgform_kurzbz, - $studiensemester_kurzbz = null, $filter = null - ) - { + public function getPrestudentsOrgform( + $studiengang_kz, + $orgform_kurzbz, + $studiensemester_kurzbz = null, + $filter = null + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiengang_kz' => $studiengang_kz, @@ -370,7 +372,7 @@ class Students extends FHCAPI_Controller $stg = $this->getDataOrTerminateWithError($result); if (!$stg) - $this->terminateWithValidationErrors(['' => 'Studiengang does not exist']); // TODO(chris): phrase + $this->terminateWithSuccess([]); $stg = current($stg); $where['ps.status_kurzbz'] = 'Interessent'; @@ -439,7 +441,10 @@ class Students extends FHCAPI_Controller break; default: if (!$studiensemester_kurzbz) { - // TODO(chris): this does not work with $orgform_kurzbz != null + /** NOTE(chris): + * show all prestudents in this stg who don't have a status + * $orgform_kurzbz does not change the results since orgform is stored in the status table + */ $where['ps.status_kurzbz'] = null; } else { $this->PrestudentModel->db->where_in('ps.status_kurzbz', [ @@ -453,20 +458,6 @@ class Students extends FHCAPI_Controller break; } - /* - $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' - pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.prestudent_id=tbl_prestudent.prestudent_id - AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); - $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus ps', ' - ps.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') - AND ps.prestudent_id=tbl_prestudent.prestudent_id - AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') - AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT');*/ $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect(" @@ -488,10 +479,13 @@ class Students extends FHCAPI_Controller $this->terminateWithSuccess($data); } - public function getStudents($studiensemester_kurzbz, - $studiengang_kz, $semester = null, $verband = null, $gruppe = null - ) - { + public function getStudents( + $studiensemester_kurzbz, + $studiengang_kz, + $semester = null, + $verband = null, + $gruppe = null + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiensemester_kurzbz' => $studiensemester_kurzbz, @@ -504,10 +498,14 @@ class Students extends FHCAPI_Controller $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, null); } - public function getStudentsOrgform($studiensemester_kurzbz, - $studiengang_kz, $orgform_kurzbz, $semester = null, $verband = null, $gruppe = null - ) - { + public function getStudentsOrgform( + $studiensemester_kurzbz, + $studiengang_kz, + $orgform_kurzbz, + $semester = null, + $verband = null, + $gruppe = null + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiensemester_kurzbz' => $studiensemester_kurzbz, @@ -521,10 +519,12 @@ class Students extends FHCAPI_Controller $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, $verband, $gruppe, null, $orgform_kurzbz); } - public function getStudentsSpezialgruppe($studiensemester_kurzbz, - $studiengang_kz, $semester, $gruppe_kurzbz, - $orgform_kurzbz = null) - { + public function getStudentsSpezialgruppe( + $studiensemester_kurzbz, + $studiengang_kz, + $semester, + $gruppe_kurzbz + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiensemester_kurzbz' => $studiensemester_kurzbz, @@ -536,10 +536,13 @@ class Students extends FHCAPI_Controller $this->fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester, null, null, $gruppe_kurzbz, null); } - public function getStudentsOrgformSpezialgruppe($studiensemester_kurzbz, - $orgform_kurzbz, $studiengang_kz, $semester, $gruppe_kurzbz - ) - { + public function getStudentsOrgformSpezialgruppe( + $studiensemester_kurzbz, + $orgform_kurzbz, + $studiengang_kz, + $semester, + $gruppe_kurzbz + ) { $this->addMeta('ci_method', __FUNCTION__); $this->addMeta('ci_params', array( 'studiensemester_kurzbz' => $studiensemester_kurzbz, @@ -563,8 +566,15 @@ class Students extends FHCAPI_Controller * * @return void */ - protected function fetchStudents($studiensemester_kurzbz, $studiengang_kz, $semester = null, $verband = null, $gruppe = null, $gruppe_kurzbz = null, $orgform_kurzbz = null) - { + protected function fetchStudents( + $studiensemester_kurzbz, + $studiengang_kz, + $semester = null, + $verband = null, + $gruppe = null, + $gruppe_kurzbz = null, + $orgform_kurzbz = null + ) { $this->load->model('crm/Prestudent_model', 'PrestudentModel'); $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); @@ -573,21 +583,6 @@ class Students extends FHCAPI_Controller $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); } - /* - $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' - pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.prestudent_id=tbl_prestudent.prestudent_id - AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); - $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); - $this->PrestudentModel->addJoin( - 'public.tbl_studentlehrverband v', - 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz) - );*/ $this->prepareQuery($studiensemester_kurzbz, ''); $this->PrestudentModel->addSelect('v.semester'); @@ -627,7 +622,6 @@ class Students extends FHCAPI_Controller false ); } - } $this->addFilter($studiensemester_kurzbz); @@ -661,22 +655,6 @@ class Students extends FHCAPI_Controller $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - /* - $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' - pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.prestudent_id=tbl_prestudent.prestudent_id - AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); - $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid', 'LEFT'); - $this->PrestudentModel->addJoin( - 'public.tbl_studentlehrverband v', - 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), - 'LEFT' - );*/ $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect("COALESCE( @@ -725,22 +703,6 @@ class Students extends FHCAPI_Controller $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - /* - $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); - $this->PrestudentModel->addJoin('public.tbl_prestudentstatus pls', ' - pls.status_kurzbz=public.get_rolle_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.prestudent_id=tbl_prestudent.prestudent_id - AND pls.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, NULL) - AND pls.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, NULL)', 'LEFT'); - $this->PrestudentModel->addJoin('lehre.tbl_studienplan sp', 'studienplan_id', 'LEFT'); - $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); - $this->PrestudentModel->addJoin( - 'public.tbl_studentlehrverband v', - 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), - 'LEFT' - );*/ $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect('v.semester'); @@ -785,15 +747,6 @@ class Students extends FHCAPI_Controller $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - /* - $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); - $this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id'); - $this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid'); - $this->PrestudentModel->addJoin( - 'public.tbl_studentlehrverband v', - 'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz), - 'LEFT' - );*/ $this->prepareQuery($studiensemester_kurzbz); $this->PrestudentModel->addSelect('v.semester'); @@ -911,13 +864,6 @@ class Students extends FHCAPI_Controller $this->PrestudentModel->addSelect('mentor'); $this->PrestudentModel->addSelect('b.aktiv AS bnaktiv'); - /*$this->PrestudentModel->addSelect('tbl_prestudent.reihungstest_id'); - $this->PrestudentModel->addSelect('tbl_prestudent.anmeldungreihungstest'); - $this->PrestudentModel->addSelect('tbl_prestudent.gsstudientyp_kurzbz'); - $this->PrestudentModel->addSelect('tbl_prestudent.priorisierung'); - $this->PrestudentModel->addSelect('p.zugangscode'); - $this->PrestudentModel->addSelect('p.bpk');*/ - $this->PrestudentModel->db->where_in('tbl_prestudent.studiengang_kz', $this->allowedStgs); $this->PrestudentModel->addOrder('nachname'); From 3a5c4444cbce8262db135dbc6316d96b488f7e84 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Wed, 27 Aug 2025 14:11:03 +0200 Subject: [PATCH 040/258] Tab Archive: Documentdropdown for Printing - define structure for single print array - fill array with documents according to Fas Dropdown Drucken - event for adding documents from extension/addons --- .../api/frontend/v1/stv/Archiv.php | 2 +- .../api/frontend/v1/stv/Dokumente.php | 506 ++++++++++++++++++ public/js/api/factory/stv/archiv.js | 2 +- public/js/api/factory/stv/documents.js | 14 + .../Abschlusspruefung/Abschlusspruefung.js | 1 - .../Stv/Studentenverwaltung/Details/Archiv.js | 99 +++- .../Details/Archiv/DocumentDropdown.js | 116 ++++ system/phrasesupdate.php | 22 + 8 files changed, 754 insertions(+), 8 deletions(-) create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Archiv/DocumentDropdown.js diff --git a/application/controllers/api/frontend/v1/stv/Archiv.php b/application/controllers/api/frontend/v1/stv/Archiv.php index cc636951d..09cefc045 100644 --- a/application/controllers/api/frontend/v1/stv/Archiv.php +++ b/application/controllers/api/frontend/v1/stv/Archiv.php @@ -39,7 +39,7 @@ class Archiv extends FHCAPI_Controller 'archive' => ['admin:w', 'assistenz:w'], 'download' => ['admin:w', 'assistenz:w'], 'update' => ['admin:w'], - 'delete' => ['admin:w', 'assistenz:w'] + 'delete' => ['admin:w', 'assistenz:w'], ]); // Load models diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php index 18c976eb6..520f5d824 100644 --- a/application/controllers/api/frontend/v1/stv/Dokumente.php +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -2,6 +2,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); +use \CI3_Events as Events; use \DateTime as DateTime; class Dokumente extends FHCAPI_Controller @@ -19,6 +20,8 @@ class Dokumente extends FHCAPI_Controller 'getDoktypen' => ['admin:r', 'assistenz:r'], 'uploadDokument' => ['admin:rw', 'assistenz:rw'], 'download' => ['admin:rw', 'assistenz:rw'], + 'getDocumentDropDown' => ['admin:rw', 'assistenz:rw'], + 'getDocumentDropDownMulti' => ['admin:rw', 'assistenz:rw'], ]); // Load Libraries @@ -566,4 +569,507 @@ class Dokumente extends FHCAPI_Controller return false; } } + + public function getDocumentDropDown($prestudent_id, $studiensemester_kurzbz, $studiengang_kz) + { + //TODO(Manu) Berechtigungen hasPermissionOutputformat + //TODO(Manu) remove: just for test ouput + $hasPermissionOutputformat = false; + + //TODO(Manu) Validierungen + if (!$prestudent_id) { + $this->terminateWithError('Prestudent id is required.'); + } + if (!$studiensemester_kurzbz) + $this->terminateWithError("kein Studiensemester"); + if (!$studiengang_kz) + $this->terminateWithError("kein Studiengang_kz"); + + $uid = $this->_loadUIDFromPrestudent($prestudent_id); + $semArray = $this->_getEntriesStudiensemester(); + $stgTyp = $this->_getStudiengangstyp($studiengang_kz); + + //TODO(Manu) check if if Array[0] bis Array[4] befüllt + //TODO(Manu) handling stgTyp ungleich b,m,d + + // $semString = implode(";", $semArray); + // $this->terminateWithError("Semester " . $semString . " " . $semArray[0] . " " . $semArray[1]); + + $documents = [ + $this->buildDropdownEntry("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uid, 10, null), + $this->buildDropdownEntry("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uid, 20, null), + $this->buildDropdownEntry("ausbildungsvertrag_en", "Ausbildungsvertrag Englisch", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uid, 21, null), + $this->buildDropdownEntry("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uid, 40, null), + $this->buildDropdownEntry("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uid, 41, null), + $this->buildDropdownEntry("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uid", $uid,100, "zutrittskarte.php"), + $this->buildDropdownEntry("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uid, 60, null), + $this->buildDropdownEntry("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uid, 61, null), + + // Studienerfolg Menüs automatisch + $this->buildStudienerfolgSubmenu("de", $uid, $semArray, $studiensemester_kurzbz), + $this->buildStudienerfolgSubmenu("en", $uid, $semArray, $studiensemester_kurzbz), + $this->buildStudienerfolgSubmenu("de", $uid, $semArray, $studiensemester_kurzbz, true), + $this->buildStudienerfolgSubmenu("en", $uid, $semArray, $studiensemester_kurzbz, true), + + [ + "id" => "submenu_studstatus", + "type" => "submenu", + "name" => "Verwaltung des StudierendenStatus", + "order" => 110, + "data" => [ + $this->buildDropdownEntry("Abmeldung", "Abmeldung", "xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldungl&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + $this->buildDropdownEntry("Abmeldung durch Stgl", "AntragAbmeldungStgl", "xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + $this->buildDropdownEntry("Unterbrechung", "Unterbrechung", "xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + $this->buildDropdownEntry("Wiederholung", "Abmeldung durch Ablauf der Wiederholungsfrist", "xml=AntragWiederholung.xml.php&xsl=AntragWiederholung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + ] + ], + + $this->loadDropDownEntriesFinalExam($hasPermissionOutputformat, $stgTyp, $uid), + + $this->buildDropdownEntry("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uid, 80, null), + $this->buildDropdownEntry("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uid, 81, null) + ]; + + Events::trigger('DocumentGenerationDropDown', + // passing $menu per reference + function & () use (&$documents) { + return $documents; + }, + $prestudent_id, + $studiensemester_kurzbz, + $studiengang_kz + ); + + usort($documents, function ($a, $b) { + $orderA = isset($a['order']) ? (int)$a['order'] : PHP_INT_MAX; + $orderB = isset($b['order']) ? (int)$b['order'] : PHP_INT_MAX; + return $orderA <=> $orderB; + }); + + + $this->terminateWithSuccess($documents); + return $documents || null; + } + + public function getDocumentDropDownMulti() + { + $studentUids = $this->input->get('studentUids'); + $prestudentIds = []; + + if (is_array($studentUids) && !empty($studentUids)) { + foreach ($studentUids as $uid) { + $prestudent_id = $this-> _loadPrestudentFromUid($uid); + $prestudentIds[] = $prestudent_id; + } + } else { + echo "No prestudent IDs received."; + } + + $uidString = implode(";", $studentUids); + $prestudentIdsString = implode(";", $prestudentIds); + + + $documents = [ + [ + "id" => "accountinfo1", + "type" => "documenturl", + "name" => "Accountinfoblatt", + "url" => "pdfExport.php?xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ], + [ + "id" => "ausbildungsvertrag1_de", + "type" => "documenturl", + "name" => "Ausbildungsvertrag Deutsch", + "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ], + [ + "id" => "ausbildungsvertrag1_en", + "type" => "documenturl", + "name" => "Ausbildungsvertrag Englisch", + "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ], + [ + "id" => "submenu_studienerfolg_1", + "type" => "submenu", + "name" => "Studienerfolg", + "data" => [ + [ + "id" => "submenu_studienerfolg_sem1", + "type" => "submenu", + "name" => "Studienerfolg WS2025", + "data" => [ + [ + "id" => "studienerfolg_sem_alle_1", + "type" => "submenu", + "name" => "Studienerfolg WS2025 Alle", + "data" => [ + [ + "id" => "studienerfolg_sem_alle_1_FA", + "type" => "documenturl", + "name" => "Studienerfolg Alle FINANZAMT", + "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ], + [ + "id" => "studienerfolg_sem_alle_1_nichtFA", + "type" => "documenturl", + "name" => "Studienerfolg Alle NICHT FINANZAMT", + "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ] + ] + + ] + ] + ] + ] + ], + [ + "id" => "submenu_studstatus", + "type" => "submenu", + "name" => "Verwaltung des StudierendenStatus", + "data" => [ + [ + "id" => "Abmeldung", + "type" => "documenturl", + "name" => "Abmeldung", + "url" => "pdfExport.php?xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldung&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ], + [ + "id" => "Abmeldung durch Stg", + "type" => "documenturl", + "name" => "AntragAbmeldungStgl", + "url" => "pdfExport.php?xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ] + ] + ], + [ + "id" => "zutrittskarte", + "type" => "documenturl", + "name" => "Zutrittskarte", + "url" => "zutrittskarte.php?xsl=ZutrittskarteStud&output=pdf&data=" . $uidString, + "scope" => "prestudent" + ], + [ + "id" => "zutrittskarte", + "type" => "parameterurl", + "name" => "Zutrittskarte", + "baseurl" => "zutrittskarte.php", + "parameterurl" =>"xsl=ZutrittskarteStud&output=pdf&data=" . $uidString, + "scope" => "prestudent" + ], + [ + "id" => "studienbestaetigung", + "type" => "documenturl", + "name" => "Studienbestätigung", + "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ], + [ + "id" => "studienerfolg", + "type" => "documenturl", + "name" => "Studienbestätigung", + "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, + "scope" => "prestudent" + ], + + ]; + +/* Events::trigger('DocumentGenerationDropDownMulti', + // passing $menu per reference + function & () use (&$documents) { + return $documents; + }, + $prestudent_id, + $studiensemester_kurzbz, + $studiengang_kz + );*/ + + usort($documents, function ($a, $b) { + $orderA = isset($a['order']) ? (int)$a['order'] : PHP_INT_MAX; + $orderB = isset($b['order']) ? (int)$b['order'] : PHP_INT_MAX; + return $orderA <=> $orderB; + }); + + // FireEvent(DocumentGenerationDropDownMulti(&$documents); + + $this->terminateWithSuccess($documents); + + return $documents || null; + } + + private function _loadUIDFromPrestudent($prestudent_id) + { + if(!$prestudent_id){ + return $this->terminateWithError("no prestudent ID received."); + } + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->loadWhere( + ['prestudent_id' => $prestudent_id] + ); + + $data = $this->getDataOrTerminateWithError($result); + $student = current($data); + + return $student->student_uid; + } + + private function _loadPrestudentFromUid($studentUid) + { + + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->loadWhere( + ['student_uid' => $studentUid] + ); + + $data = $this->getDataOrTerminateWithError($result); + $student = current($data); + + + return $student->prestudent_id; + } + + /** + * is building an array with studiensemesterkurzb + * actual studiensemester plus the 5 studiensemester in the past + + * @return Array Studiensemester_kurzbz + */ + private function _getEntriesStudiensemester(){ + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addPlusMinus(1, 5); + $this->StudiensemesterModel->addOrder('ende', 'DESC'); + $result = $this->StudiensemesterModel->load(); + $data = $this->getDataOrTerminateWithError($result); + + foreach($data as $sem) + { + $semArray[] = $sem->studiensemester_kurzbz; + } + + array_shift($semArray); + + return $semArray; + } + /** + * is returning the typ of Studiengang (Bakk oder Master) + + * @return character eg. 'b' or 'm' + */ + private function _getStudiengangstyp($studiengang_kz) + { + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $result = $this->StudiengangModel->loadWhere( + array('studiengang_kz' => $studiengang_kz) + ); + $data = $this->getDataOrTerminateWithError($result); + + $typStudiengang = current($data)->typ; + + return $typStudiengang; + } + + //TODO(Manu) make helperfunction + /** + * is building an array for Dropdown Entry in Print Dropdown + * @param $id id for the Document to add to the Document Array + * @param $name name of the dropdownEntry + * @param $parameterUrl url of parameters xml, xsl,format as needed + * WITHOUT BASEURL eg. "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf" + * @param $uid default parameter, if null only parameterurl will be added + * additional needed parameter: put in the parameterUrl + * @param $alternativeBaseUrl: if baseUrl not pdfExport.php, put here alternative without ? char, eg. "zutrittskarte.php" + + * @return Array + */ + private function buildDropdownEntry($id, $name, $parameterurl, $uid=null, $order=null, $alternativeBaseUrl=null) + { + //DEFAULT BASEURL + $baseurl = "pdfExport.php?"; + + $uidString = $uid ? "&uid=" . $uid : ""; + + if($alternativeBaseUrl) + { + return [ + "id" => $id, + "type" => "documenturl", + "name" => $name, + "url" => $alternativeBaseUrl . "?" . $parameterurl . $uidString, + "order" => $order + ]; + } + else + return [ + "id" => $id, + "type" => "documenturl", + "name" => $name, + "url" => $baseurl . $parameterurl . "&uid=" . $uid, + "order" => $order + ]; + + } + + /** + * helper function to create ArrayStructure + * actual studiensemester plus the 5 studiensemester in the past + + * @return Array Studiensemester_kurzbz + */ + private function buildStudienerfolgSubmenu($lang, $uid, $semArray, $studiensemester_kurzbz, $fa = false) + { + $entries = []; + + $xsl = $lang === "de" ? "Studienerfolg" : "StudienerfolgEng"; + $idPrefix = "submenu_studienerfolg_" . $lang . ($fa ? "_fa" : ""); + + $entries[] = $this->buildDropdownEntry( + $idPrefix . "_aktuell", + "ausgewähltes Semester", + "xml=studienerfolg.rdf.php&xsl=$xsl&ss=$studiensemester_kurzbz" . ($fa ? "&typ=finanzamt" : ""), + $uid + ); + + //all semester + $entries[] = $this->buildDropdownEntry( + $idPrefix . "_all", + "alle Semester", + "xml=studienerfolg.rdf.php&xsl=$xsl&ss=$studiensemester_kurzbz&all=true" . ($fa ? "&typ=finanzamt" : ""), + $uid + ); + + //sem from array + foreach ($semArray as $i => $sem) { + $entries[] = $this->buildDropdownEntry( + $idPrefix . ($i === 0 ? "_akt" : "_minus" . $i), + $sem, + "xml=studienerfolg.rdf.php&xsl=$xsl&ss=$sem" . ($fa ? "&typ=finanzamt" : ""), + $uid + ); + + } + $order = 0; + if ($lang === "de" && !$fa) $order = 75; // Studienerfolg + if ($lang === "en" && !$fa) $order = 76; // Studienerfolg Englisch + if ($lang === "de" && $fa) $order = 77; // Studienerfolg Finanzamt + if ($lang === "en" && $fa) $order = 78; // Studienerfolg Finanzamt Englisch + + return [ + "id" => $idPrefix, + "type" => "submenu", + "name" => "Studienerfolg " . ($fa ? " Finanzamt" : "") . ($lang === "de" ? "" : "Englisch") , + "order" => $order, + "data" => $entries, + ]; + } + + private function loadDropDownEntriesFinalExam($hasPermissionOutputformat, $stgTyp, $uid) + { + if ($stgTyp == 'b') + $postfix = 'Bakk'; + else if ($stgTyp == 'm' || $stgTyp == 'd') + $postfix = 'Master'; + else + //TODO(Manu) sollte nicht null sein!! -> dropdown wird im Falle von Lehrgängen nicht erstellt + return null; + + + $arrayFinalExam = [ + 'pruefungsprotokoll' => [ + 'de' => [ + 'Bakk' => 'PrProtBA', + 'Master' => 'PrProtMA', + ], + 'en' => [ + 'Bakk' => 'PrProtBAEng', + 'Master' => 'PrProtMAEng', + ], + ], + 'pruefungszeugnis' => [ + 'de' => [ + 'Bakk' => 'Bakkzeugnis', + 'Master' => 'Diplomzeugnis', + ], + 'en' => [ + 'Bakk' => 'BakkzeugnisEng', + 'Master' => 'DiplomzeugnisEng', + ], + ], + 'urkunde' => [ + 'de' => [ + 'Bakk' => 'Bakkurkunde', + 'Master' => 'Diplomurkunde', + ], + 'en' => [ + 'Bakk' => 'BakkurkundeEng', + 'Master' => 'DiplomurkundeEng', + ], + ], + ]; + + $langLabels = [ + "de" => "Deutsch", + "en" => "Englisch" + ]; + + $docLabels = [ + "pruefungsprotokoll" => "Prüfungsprotokoll", + "pruefungszeugnis" => "Zeugnis", + "urkunde" => "Urkunde" + ]; + + $submenuData = []; + if ($hasPermissionOutputformat) { + foreach ($arrayFinalExam as $docType => $langs) { + foreach ($langs as $lang => $types) { + $xsl = $types[$postfix]; + $idPrefix = $docType . "_" . $lang; + + $baseName = $docLabels[$docType] . " " . $langLabels[$lang]; + $baseUrl = "xml=abschlusspruefung.rdf.php&xsl={$xsl}"; + + //3 outputformates + foreach (["pdf", "odt", "docx"] as $format) { + $submenuData[] = $this->buildDropdownEntry( + $idPrefix . "_" . $format, + $baseName . " (" . strtoupper($format) . ")", + $baseUrl . "&output=" . $format, + $uid + ); + } + } + } + } + else + { + foreach ($arrayFinalExam as $docType => $langs) { + foreach ($langs as $lang => $types) { + $xsl = $types[$postfix]; // Auswahl Bakk/Master für jeweilige Sprache + $id = $docType . "_" . $lang; + + $name = $docLabels[$docType] . " " . $langLabels[$lang]; + + $url = "xml=abschlusspruefung.rdf.php&xsl=" . $xsl . "&output=pdf"; + + $submenuData[] = $this->buildDropdownEntry($id, $name, $url, $uid); + } + } + } + return [ + "id" => "submenu_finalexam", + "type" => "submenu", + "name" => "Abschlussprüfung", + "data" => $submenuData, + "order" => null, + "order" => 80, + ]; + } + } diff --git a/public/js/api/factory/stv/archiv.js b/public/js/api/factory/stv/archiv.js index ca8f25116..cf380b25d 100644 --- a/public/js/api/factory/stv/archiv.js +++ b/public/js/api/factory/stv/archiv.js @@ -39,5 +39,5 @@ export default { url: 'api/frontend/v1/stv/archiv/delete', params: {akte_id, studiengang_kz} }; - } + }, }; diff --git a/public/js/api/factory/stv/documents.js b/public/js/api/factory/stv/documents.js index 1898023cd..37ec8298b 100644 --- a/public/js/api/factory/stv/documents.js +++ b/public/js/api/factory/stv/documents.js @@ -73,4 +73,18 @@ export default { params }; }, + getDocumentDropdown(params){ + console.log(params); + return { + method: 'get', + url: 'api/frontend/v1/stv/dokumente/getDocumentDropDown/' + params.prestudent_id + '/' + params.studiensemester_kurzbz + '/' + params.studiengang_kz, + }; + }, + getDocumentDropdownMulti(studentUids){ + return { + method: 'get', + url: 'api/frontend/v1/stv/dokumente/getDocumentDropDownMulti/', + params: {studentUids} + }; + } } \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Abschlusspruefung/Abschlusspruefung.js b/public/js/components/Stv/Studentenverwaltung/Details/Abschlusspruefung/Abschlusspruefung.js index e5c4cade1..5bcb75176 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Abschlusspruefung/Abschlusspruefung.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Abschlusspruefung/Abschlusspruefung.js @@ -7,7 +7,6 @@ import AbschlusspruefungDropdown from "./AbschlusspruefungDropdown.js"; import ApiStudiengang from '../../../../../api/factory/studiengang.js'; import ApiStvAbschlusspruefung from '../../../../../api/factory/stv/abschlusspruefung.js'; -import ApiStvAddress from "../../../../../api/factory/stv/kontakt/address.js"; export default { components: { diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js index 7a156965f..f439d0135 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js @@ -3,18 +3,29 @@ import FormInput from "../../../Form/Input.js"; import AkteEdit from "./Archiv/Edit.js"; import ApiStvArchiv from '../../../../api/factory/stv/archiv.js'; +import ApiStvDocuments from '../../../../api/factory/stv/documents.js'; +import DocumentDropdown from "../Details/Archiv/DocumentDropdown"; + export default { name: 'Archiv', components: { CoreFilterCmpt, FormInput, - AkteEdit + AkteEdit, + DocumentDropdown }, inject: { currentSemester: { from: 'currentSemester' - } + }, + /* isBerechtigtDocAndOdt: { + from: 'hasPermissionOutputformat', + default: false + },*/ + cisRoot: { + from: 'cisRoot' + }, }, props: { modelValue: Object, @@ -64,7 +75,8 @@ export default { 'abschlussdokument_lehrgaenge.xml.php': [ 'AbschlussdokumentLehrgaenge' ] - } + }, + documentDropdownObject: {} }; }, computed: { @@ -184,7 +196,42 @@ export default { ]; return events; + }, + studentUids() { + if (this.modelValue.uid) + { + return [this.modelValue.uid]; + } + return this.modelValue.map(e => e.uid); + }, + studentKzs(){ + if (this.modelValue.uid) + { + return [this.modelValue.studiengang_kz]; + } + return this.modelValue.map(e => e.studiengang_kz); + }, + stg_kz(){ + return this.studentKzs[0]; + }, + showAllFormats() { + if( this.isBerechtigtDocAndOdt === false + || !Array.isArray(this.isBerechtigtDocAndOdt) ) + { + return false; + } + let retval = this.isBerechtigtDocAndOdt.includes(this.stgInfo.oe_kurzbz); + return retval; + }, + showDropDownMulti(){ + + if (this.modelValue.length) { + console.log("started comp property showDropdown Multi " + this.modelValue.length); + return true; + } + return false; } + }, watch: { modelValue() { @@ -252,14 +299,44 @@ export default { } }, created() { + this.$api + .call(ApiStvArchiv.getArchivVorlagen()) + .then(result => { + this.vorlagenArchiv = result.data; + this.selectedVorlage = result.data.filter(o => o.vorlage_kurzbz == 'Zeugnis')[0]; + }) + .catch(this.$fhcAlert.handleSystemError); + + if (this.modelValue.length) { + console.log("multi" + this.modelValue.length); + console.log(this.studentUids); this.$api - .call(ApiStvArchiv.getArchivVorlagen()) - .then(result => {this.vorlagenArchiv = result.data; this.selectedVorlage = result.data.filter(o => o.vorlage_kurzbz == 'Zeugnis')[0];}) + .call(ApiStvDocuments.getDocumentDropdownMulti(this.studentUids)) + .then(result => { + console.log(result); + this.documentDropdownObject = result; + }) .catch(this.$fhcAlert.handleSystemError); + } else { + console.log("single"); + const params = { + prestudent_id: this.modelValue.prestudent_id, + studiensemester_kurzbz: this.currentSemester, + studiengang_kz: this.modelValue.studiengang_kz + }; + this.$api + .call(ApiStvDocuments.getDocumentDropdown(params)) + .then(result => { + console.log(result); + this.documentDropdownObject = result; + }) + .catch(this.$fhcAlert.handleSystemError); + } }, template: `
+ diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Archiv/DocumentDropdown.js b/public/js/components/Stv/Studentenverwaltung/Details/Archiv/DocumentDropdown.js new file mode 100644 index 000000000..215a1f1ca --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Archiv/DocumentDropdown.js @@ -0,0 +1,116 @@ +export default { + name: "DocumentDropdown", + props: { + documents: { + type: [Object, Array], + required: true, + }, + studentUids: { + type: [Array, String], + required: true, + default: () => [] + }, + showDropDownMulti: { + type: Boolean, + required: true + }, + cisRoot: { + type: String, + required: true + }, + stgKz: { + type: Number, + required: true + }, + showAllFormats: { + type: Boolean, + required: true + } + }, + data() { + return {}; + }, + methods: { + printDokument(url, scope){ + //TODO Manu(check if logic not in content (Zutrittkarte also in content folder)) + let linkToPdf = this.cisRoot + 'content/' + url; + console.log("in print " + linkToPdf + " scope" + scope); + window.open(linkToPdf, '_blank'); + } + }, + template: ` +
+
+ + + + + +
+
` +}; + + diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 23eb39a21..fa03c4ba5 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -47543,6 +47543,28 @@ and represent the current state of research on the topic. The prescribed citatio ) ), //**************************** CORE/search end + // ### DOKUMENTE ERSTELLEN PHRASEN START ### + array( + 'app' => 'core', + 'category' => 'dokumente', + 'phrase' => 'dokument_erstellen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Dokument erstellen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create Document', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + // ### DOKUMENTE ERSTELLEN PHRASEN END ### ); From 7b187ebadd42c3ad3f39821031a15df93deb046f Mon Sep 17 00:00:00 2001 From: ma0068 Date: Thu, 28 Aug 2025 11:05:04 +0200 Subject: [PATCH 041/258] add Dropdown for Multiaction Print add Event for adding Documents to PrintArray add Berechtigung hasPermissionOutputformat to enable Print for odt and doc Formats (documents abschlusspruefung) add Validations --- .../api/frontend/v1/stv/Dokumente.php | 184 ++++++------------ public/js/api/factory/stv/documents.js | 5 +- .../Stv/Studentenverwaltung/Details/Archiv.js | 12 +- .../Details/Archiv/DocumentDropdown.js | 95 ++++----- 4 files changed, 103 insertions(+), 193 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php index 520f5d824..17be3b9df 100644 --- a/application/controllers/api/frontend/v1/stv/Dokumente.php +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -572,29 +572,21 @@ class Dokumente extends FHCAPI_Controller public function getDocumentDropDown($prestudent_id, $studiensemester_kurzbz, $studiengang_kz) { - //TODO(Manu) Berechtigungen hasPermissionOutputformat - //TODO(Manu) remove: just for test ouput - $hasPermissionOutputformat = false; + //permission to create also odt, and doc outputs of certain documents(menu abschlusspruefung) + $hasPermissionOutputformat = $this->permissionlib->isBerechtigt('system/change_outputformat', 's'); - //TODO(Manu) Validierungen - if (!$prestudent_id) { - $this->terminateWithError('Prestudent id is required.'); - } + if (!$prestudent_id) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Prestudent_id']), self::ERROR_TYPE_GENERAL); if (!$studiensemester_kurzbz) - $this->terminateWithError("kein Studiensemester"); - if (!$studiengang_kz) - $this->terminateWithError("kein Studiengang_kz"); + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiensemester']), self::ERROR_TYPE_GENERAL); + if(!$studiengang_kz) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiengang_kz']), self::ERROR_TYPE_GENERAL); + $uid = $this->_loadUIDFromPrestudent($prestudent_id); $semArray = $this->_getEntriesStudiensemester(); $stgTyp = $this->_getStudiengangstyp($studiengang_kz); - //TODO(Manu) check if if Array[0] bis Array[4] befüllt - //TODO(Manu) handling stgTyp ungleich b,m,d - - // $semString = implode(";", $semArray); - // $this->terminateWithError("Semester " . $semString . " " . $semArray[0] . " " . $semArray[1]); - $documents = [ $this->buildDropdownEntry("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uid, 10, null), $this->buildDropdownEntry("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uid, 20, null), @@ -605,7 +597,6 @@ class Dokumente extends FHCAPI_Controller $this->buildDropdownEntry("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uid, 60, null), $this->buildDropdownEntry("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uid, 61, null), - // Studienerfolg Menüs automatisch $this->buildStudienerfolgSubmenu("de", $uid, $semArray, $studiensemester_kurzbz), $this->buildStudienerfolgSubmenu("en", $uid, $semArray, $studiensemester_kurzbz), $this->buildStudienerfolgSubmenu("de", $uid, $semArray, $studiensemester_kurzbz, true), @@ -617,7 +608,7 @@ class Dokumente extends FHCAPI_Controller "name" => "Verwaltung des StudierendenStatus", "order" => 110, "data" => [ - $this->buildDropdownEntry("Abmeldung", "Abmeldung", "xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldungl&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + $this->buildDropdownEntry("Abmeldung", "Abmeldung", "xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), $this->buildDropdownEntry("Abmeldung durch Stgl", "AntragAbmeldungStgl", "xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), $this->buildDropdownEntry("Unterbrechung", "Unterbrechung", "xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), $this->buildDropdownEntry("Wiederholung", "Abmeldung durch Ablauf der Wiederholungsfrist", "xml=AntragWiederholung.xml.php&xsl=AntragWiederholung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), @@ -651,8 +642,11 @@ class Dokumente extends FHCAPI_Controller return $documents || null; } - public function getDocumentDropDownMulti() + public function getDocumentDropDownMulti($studiensemester_kurzbz,$studiengang_kz) { + //permission to create also odt, and doc outputs of certain documents (menu abschlusspruefung) + $hasPermissionOutputformat = $this->permissionlib->isBerechtigt('system/change_outputformat', 's'); + $studentUids = $this->input->get('studentUids'); $prestudentIds = []; @@ -661,134 +655,71 @@ class Dokumente extends FHCAPI_Controller $prestudent_id = $this-> _loadPrestudentFromUid($uid); $prestudentIds[] = $prestudent_id; } - } else { - echo "No prestudent IDs received."; } + else + { + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Array StudentUIDs']), self::ERROR_TYPE_GENERAL); + } + + if (!$studiensemester_kurzbz) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiensemester']), self::ERROR_TYPE_GENERAL); + if(!$studiengang_kz) + $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiengang_kz']), self::ERROR_TYPE_GENERAL); + $uidString = implode(";", $studentUids); $prestudentIdsString = implode(";", $prestudentIds); + $semArray = $this->_getEntriesStudiensemester(); + $stgTyp = $this->_getStudiengangstyp($studiengang_kz); $documents = [ - [ - "id" => "accountinfo1", - "type" => "documenturl", - "name" => "Accountinfoblatt", - "url" => "pdfExport.php?xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ], - [ - "id" => "ausbildungsvertrag1_de", - "type" => "documenturl", - "name" => "Ausbildungsvertrag Deutsch", - "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ], - [ - "id" => "ausbildungsvertrag1_en", - "type" => "documenturl", - "name" => "Ausbildungsvertrag Englisch", - "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ], - [ - "id" => "submenu_studienerfolg_1", - "type" => "submenu", - "name" => "Studienerfolg", - "data" => [ - [ - "id" => "submenu_studienerfolg_sem1", - "type" => "submenu", - "name" => "Studienerfolg WS2025", - "data" => [ - [ - "id" => "studienerfolg_sem_alle_1", - "type" => "submenu", - "name" => "Studienerfolg WS2025 Alle", - "data" => [ - [ - "id" => "studienerfolg_sem_alle_1_FA", - "type" => "documenturl", - "name" => "Studienerfolg Alle FINANZAMT", - "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ], - [ - "id" => "studienerfolg_sem_alle_1_nichtFA", - "type" => "documenturl", - "name" => "Studienerfolg Alle NICHT FINANZAMT", - "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ] - ] + $this->buildDropdownEntry("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uidString, 10, null), + $this->buildDropdownEntry("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uidString, 20, null), + $this->buildDropdownEntry("ausbildungsvertrag_en", "Ausbildungsvertrag Englisch", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uidString, 21, null), + $this->buildDropdownEntry("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uidString, 40, null), + $this->buildDropdownEntry("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uidString, 41, null), + $this->buildDropdownEntry("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uidString", $uidString,100, "zutrittskarte.php"), + $this->buildDropdownEntry("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uidString, 60, null), + $this->buildDropdownEntry("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uidString, 61, null), + + // Studienerfolg Menüs automatisch + $this->buildStudienerfolgSubmenu("de", $uidString, $semArray, $studiensemester_kurzbz), + $this->buildStudienerfolgSubmenu("en", $uidString, $semArray, $studiensemester_kurzbz), + $this->buildStudienerfolgSubmenu("de", $uidString, $semArray, $studiensemester_kurzbz, true), + $this->buildStudienerfolgSubmenu("en", $uidString, $semArray, $studiensemester_kurzbz, true), - ] - ] - ] - ] - ], [ - "id" => "submenu_studstatus", + "id" => "submenu_studstatus", "type" => "submenu", "name" => "Verwaltung des StudierendenStatus", + "order" => 110, "data" => [ - [ - "id" => "Abmeldung", - "type" => "documenturl", - "name" => "Abmeldung", - "url" => "pdfExport.php?xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldung&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ], - [ - "id" => "Abmeldung durch Stg", - "type" => "documenturl", - "name" => "AntragAbmeldungStgl", - "url" => "pdfExport.php?xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ] + $this->buildDropdownEntry("Abmeldung", "Abmeldung", "xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), + $this->buildDropdownEntry("Abmeldung durch Stgl", "AntragAbmeldungStgl", "xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), + $this->buildDropdownEntry("Unterbrechung", "Unterbrechung", "xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), + $this->buildDropdownEntry("Wiederholung", "Abmeldung durch Ablauf der Wiederholungsfrist", "xml=AntragWiederholung.xml.php&xsl=AntragWiederholung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), ] ], - [ - "id" => "zutrittskarte", - "type" => "documenturl", - "name" => "Zutrittskarte", - "url" => "zutrittskarte.php?xsl=ZutrittskarteStud&output=pdf&data=" . $uidString, - "scope" => "prestudent" - ], - [ - "id" => "zutrittskarte", - "type" => "parameterurl", - "name" => "Zutrittskarte", - "baseurl" => "zutrittskarte.php", - "parameterurl" =>"xsl=ZutrittskarteStud&output=pdf&data=" . $uidString, - "scope" => "prestudent" - ], - [ - "id" => "studienbestaetigung", - "type" => "documenturl", - "name" => "Studienbestätigung", - "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ], - [ - "id" => "studienerfolg", - "type" => "documenturl", - "name" => "Studienbestätigung", - "url" => "pdfExport.php?xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf&uid=" . $uidString, - "scope" => "prestudent" - ], + $this->loadDropDownEntriesFinalExam($hasPermissionOutputformat, $stgTyp, $uidString), + + //TODO(Manu) also in Fas multi not working +/* $this->buildDropdownEntry("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uidString, 80, null), + */ + + $this->buildDropdownEntry("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uidString, 81, null) ]; -/* Events::trigger('DocumentGenerationDropDownMulti', + Events::trigger('DocumentGenerationDropDownMulti', // passing $menu per reference function & () use (&$documents) { return $documents; }, - $prestudent_id, + $studentUids, $studiensemester_kurzbz, $studiengang_kz - );*/ + ); usort($documents, function ($a, $b) { $orderA = isset($a['order']) ? (int)$a['order'] : PHP_INT_MAX; @@ -796,7 +727,6 @@ class Dokumente extends FHCAPI_Controller return $orderA <=> $orderB; }); - // FireEvent(DocumentGenerationDropDownMulti(&$documents); $this->terminateWithSuccess($documents); @@ -977,9 +907,7 @@ class Dokumente extends FHCAPI_Controller else if ($stgTyp == 'm' || $stgTyp == 'd') $postfix = 'Master'; else - //TODO(Manu) sollte nicht null sein!! -> dropdown wird im Falle von Lehrgängen nicht erstellt - return null; - + return []; $arrayFinalExam = [ 'pruefungsprotokoll' => [ diff --git a/public/js/api/factory/stv/documents.js b/public/js/api/factory/stv/documents.js index 37ec8298b..633afcba1 100644 --- a/public/js/api/factory/stv/documents.js +++ b/public/js/api/factory/stv/documents.js @@ -74,16 +74,15 @@ export default { }; }, getDocumentDropdown(params){ - console.log(params); return { method: 'get', url: 'api/frontend/v1/stv/dokumente/getDocumentDropDown/' + params.prestudent_id + '/' + params.studiensemester_kurzbz + '/' + params.studiengang_kz, }; }, - getDocumentDropdownMulti(studentUids){ + getDocumentDropdownMulti(studentUids, params){ return { method: 'get', - url: 'api/frontend/v1/stv/dokumente/getDocumentDropDownMulti/', + url: 'api/frontend/v1/stv/dokumente/getDocumentDropDownMulti/' + params.studiensemester_kurzbz + '/' + params.studiengang_kz, params: {studentUids} }; } diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js index f439d0135..dabb000d1 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js @@ -224,14 +224,11 @@ export default { return retval; }, showDropDownMulti(){ - if (this.modelValue.length) { - console.log("started comp property showDropdown Multi " + this.modelValue.length); return true; } return false; } - }, watch: { modelValue() { @@ -308,17 +305,18 @@ export default { .catch(this.$fhcAlert.handleSystemError); if (this.modelValue.length) { - console.log("multi" + this.modelValue.length); - console.log(this.studentUids); + const params = { + studiensemester_kurzbz: this.currentSemester, + studiengang_kz: this.stg_kz + }; this.$api - .call(ApiStvDocuments.getDocumentDropdownMulti(this.studentUids)) + .call(ApiStvDocuments.getDocumentDropdownMulti(this.studentUids, params)) .then(result => { console.log(result); this.documentDropdownObject = result; }) .catch(this.$fhcAlert.handleSystemError); } else { - console.log("single"); const params = { prestudent_id: this.modelValue.prestudent_id, studiensemester_kurzbz: this.currentSemester, diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Archiv/DocumentDropdown.js b/public/js/components/Stv/Studentenverwaltung/Details/Archiv/DocumentDropdown.js index 215a1f1ca..001a45ed8 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Archiv/DocumentDropdown.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Archiv/DocumentDropdown.js @@ -34,7 +34,6 @@ export default { printDokument(url, scope){ //TODO Manu(check if logic not in content (Zutrittkarte also in content folder)) let linkToPdf = this.cisRoot + 'content/' + url; - console.log("in print " + linkToPdf + " scope" + scope); window.open(linkToPdf, '_blank'); } }, @@ -42,71 +41,57 @@ export default {
- -
From 3cdb391a6da2336722d391ea09fa07e441af20e7 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Thu, 28 Aug 2025 14:29:26 +0200 Subject: [PATCH 042/258] use helper file instead of private function for building dropdown entry --- .../api/frontend/v1/stv/Dokumente.php | 108 ++++++------------ application/helpers/hlp_common_helper.php | 42 +++++++ .../Stv/Studentenverwaltung/Details/Archiv.js | 2 - 3 files changed, 76 insertions(+), 76 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php index 17be3b9df..e6f6f4351 100644 --- a/application/controllers/api/frontend/v1/stv/Dokumente.php +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -572,6 +572,7 @@ class Dokumente extends FHCAPI_Controller public function getDocumentDropDown($prestudent_id, $studiensemester_kurzbz, $studiengang_kz) { + $this->load->helper('hlp_common'); //permission to create also odt, and doc outputs of certain documents(menu abschlusspruefung) $hasPermissionOutputformat = $this->permissionlib->isBerechtigt('system/change_outputformat', 's'); @@ -588,14 +589,14 @@ class Dokumente extends FHCAPI_Controller $stgTyp = $this->_getStudiengangstyp($studiengang_kz); $documents = [ - $this->buildDropdownEntry("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uid, 10, null), - $this->buildDropdownEntry("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uid, 20, null), - $this->buildDropdownEntry("ausbildungsvertrag_en", "Ausbildungsvertrag Englisch", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uid, 21, null), - $this->buildDropdownEntry("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uid, 40, null), - $this->buildDropdownEntry("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uid, 41, null), - $this->buildDropdownEntry("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uid", $uid,100, "zutrittskarte.php"), - $this->buildDropdownEntry("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uid, 60, null), - $this->buildDropdownEntry("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uid, 61, null), + 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 Englisch", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uid, 21, null), + buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uid, 40, null), + buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uid, 41, null), + buildDropdownEntryPrintArray("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uid", $uid,100, "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), $this->buildStudienerfolgSubmenu("de", $uid, $semArray, $studiensemester_kurzbz), $this->buildStudienerfolgSubmenu("en", $uid, $semArray, $studiensemester_kurzbz), @@ -608,17 +609,17 @@ class Dokumente extends FHCAPI_Controller "name" => "Verwaltung des StudierendenStatus", "order" => 110, "data" => [ - $this->buildDropdownEntry("Abmeldung", "Abmeldung", "xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), - $this->buildDropdownEntry("Abmeldung durch Stgl", "AntragAbmeldungStgl", "xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), - $this->buildDropdownEntry("Unterbrechung", "Unterbrechung", "xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), - $this->buildDropdownEntry("Wiederholung", "Abmeldung durch Ablauf der Wiederholungsfrist", "xml=AntragWiederholung.xml.php&xsl=AntragWiederholung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + buildDropdownEntryPrintArray("Abmeldung", "Abmeldung", "xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + buildDropdownEntryPrintArray("Abmeldung durch Stgl", "AntragAbmeldungStgl", "xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + buildDropdownEntryPrintArray("Unterbrechung", "Unterbrechung", "xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), + buildDropdownEntryPrintArray("Wiederholung", "Abmeldung durch Ablauf der Wiederholungsfrist", "xml=AntragWiederholung.xml.php&xsl=AntragWiederholung&prestudent_id=$prestudent_id&output=pdf", $uid, null, null), ] ], $this->loadDropDownEntriesFinalExam($hasPermissionOutputformat, $stgTyp, $uid), - $this->buildDropdownEntry("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uid, 80, null), - $this->buildDropdownEntry("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uid, 81, null) + buildDropdownEntryPrintArray("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uid, 80, null), + buildDropdownEntryPrintArray("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uid, 81, null) ]; Events::trigger('DocumentGenerationDropDown', @@ -674,14 +675,14 @@ class Dokumente extends FHCAPI_Controller $stgTyp = $this->_getStudiengangstyp($studiengang_kz); $documents = [ - $this->buildDropdownEntry("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uidString, 10, null), - $this->buildDropdownEntry("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uidString, 20, null), - $this->buildDropdownEntry("ausbildungsvertrag_en", "Ausbildungsvertrag Englisch", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uidString, 21, null), - $this->buildDropdownEntry("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uidString, 40, null), - $this->buildDropdownEntry("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uidString, 41, null), - $this->buildDropdownEntry("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uidString", $uidString,100, "zutrittskarte.php"), - $this->buildDropdownEntry("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uidString, 60, null), - $this->buildDropdownEntry("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uidString, 61, null), + 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, 40, null), + buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uidString, 41, null), + buildDropdownEntryPrintArray("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uidString", $uidString,100, "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), // Studienerfolg Menüs automatisch $this->buildStudienerfolgSubmenu("de", $uidString, $semArray, $studiensemester_kurzbz), @@ -695,20 +696,20 @@ class Dokumente extends FHCAPI_Controller "name" => "Verwaltung des StudierendenStatus", "order" => 110, "data" => [ - $this->buildDropdownEntry("Abmeldung", "Abmeldung", "xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), - $this->buildDropdownEntry("Abmeldung durch Stgl", "AntragAbmeldungStgl", "xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), - $this->buildDropdownEntry("Unterbrechung", "Unterbrechung", "xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), - $this->buildDropdownEntry("Wiederholung", "Abmeldung durch Ablauf der Wiederholungsfrist", "xml=AntragWiederholung.xml.php&xsl=AntragWiederholung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), + buildDropdownEntryPrintArray("Abmeldung", "Abmeldung", "xml=AntragAbmeldung.xml.php&xsl=AntragAbmeldung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), + buildDropdownEntryPrintArray("Abmeldung durch Stgl", "AntragAbmeldungStgl", "xml=AntragAbmeldungStgl.xml.php&xsl=AntragAbmeldungStgl&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), + buildDropdownEntryPrintArray("Unterbrechung", "Unterbrechung", "xml=AntragUnterbrechung.xml.php&xsl=AntragUnterbrechung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), + buildDropdownEntryPrintArray("Wiederholung", "Abmeldung durch Ablauf der Wiederholungsfrist", "xml=AntragWiederholung.xml.php&xsl=AntragWiederholung&prestudent_id=$prestudentIdsString&output=pdf", $uidString, null, null), ] ], $this->loadDropDownEntriesFinalExam($hasPermissionOutputformat, $stgTyp, $uidString), //TODO(Manu) also in Fas multi not working -/* $this->buildDropdownEntry("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uidString, 80, null), +/* buildDropdownEntryPrintArray("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uidString, 80, null), */ - $this->buildDropdownEntry("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uidString, 81, null) + buildDropdownEntryPrintArray("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uidString, 81, null) ]; Events::trigger('DocumentGenerationDropDownMulti', @@ -806,47 +807,6 @@ class Dokumente extends FHCAPI_Controller return $typStudiengang; } - //TODO(Manu) make helperfunction - /** - * is building an array for Dropdown Entry in Print Dropdown - * @param $id id for the Document to add to the Document Array - * @param $name name of the dropdownEntry - * @param $parameterUrl url of parameters xml, xsl,format as needed - * WITHOUT BASEURL eg. "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf" - * @param $uid default parameter, if null only parameterurl will be added - * additional needed parameter: put in the parameterUrl - * @param $alternativeBaseUrl: if baseUrl not pdfExport.php, put here alternative without ? char, eg. "zutrittskarte.php" - - * @return Array - */ - private function buildDropdownEntry($id, $name, $parameterurl, $uid=null, $order=null, $alternativeBaseUrl=null) - { - //DEFAULT BASEURL - $baseurl = "pdfExport.php?"; - - $uidString = $uid ? "&uid=" . $uid : ""; - - if($alternativeBaseUrl) - { - return [ - "id" => $id, - "type" => "documenturl", - "name" => $name, - "url" => $alternativeBaseUrl . "?" . $parameterurl . $uidString, - "order" => $order - ]; - } - else - return [ - "id" => $id, - "type" => "documenturl", - "name" => $name, - "url" => $baseurl . $parameterurl . "&uid=" . $uid, - "order" => $order - ]; - - } - /** * helper function to create ArrayStructure * actual studiensemester plus the 5 studiensemester in the past @@ -860,7 +820,7 @@ class Dokumente extends FHCAPI_Controller $xsl = $lang === "de" ? "Studienerfolg" : "StudienerfolgEng"; $idPrefix = "submenu_studienerfolg_" . $lang . ($fa ? "_fa" : ""); - $entries[] = $this->buildDropdownEntry( + $entries[] = buildDropdownEntryPrintArray( $idPrefix . "_aktuell", "ausgewähltes Semester", "xml=studienerfolg.rdf.php&xsl=$xsl&ss=$studiensemester_kurzbz" . ($fa ? "&typ=finanzamt" : ""), @@ -868,7 +828,7 @@ class Dokumente extends FHCAPI_Controller ); //all semester - $entries[] = $this->buildDropdownEntry( + $entries[] = buildDropdownEntryPrintArray( $idPrefix . "_all", "alle Semester", "xml=studienerfolg.rdf.php&xsl=$xsl&ss=$studiensemester_kurzbz&all=true" . ($fa ? "&typ=finanzamt" : ""), @@ -877,7 +837,7 @@ class Dokumente extends FHCAPI_Controller //sem from array foreach ($semArray as $i => $sem) { - $entries[] = $this->buildDropdownEntry( + $entries[] = buildDropdownEntryPrintArray( $idPrefix . ($i === 0 ? "_akt" : "_minus" . $i), $sem, "xml=studienerfolg.rdf.php&xsl=$xsl&ss=$sem" . ($fa ? "&typ=finanzamt" : ""), @@ -965,7 +925,7 @@ class Dokumente extends FHCAPI_Controller //3 outputformates foreach (["pdf", "odt", "docx"] as $format) { - $submenuData[] = $this->buildDropdownEntry( + $submenuData[] = buildDropdownEntryPrintArray( $idPrefix . "_" . $format, $baseName . " (" . strtoupper($format) . ")", $baseUrl . "&output=" . $format, @@ -986,7 +946,7 @@ class Dokumente extends FHCAPI_Controller $url = "xml=abschlusspruefung.rdf.php&xsl=" . $xsl . "&output=pdf"; - $submenuData[] = $this->buildDropdownEntry($id, $name, $url, $uid); + $submenuData[] = buildDropdownEntryPrintArray($id, $name, $url, $uid); } } } diff --git a/application/helpers/hlp_common_helper.php b/application/helpers/hlp_common_helper.php index 00c0a1b93..ad030c075 100644 --- a/application/helpers/hlp_common_helper.php +++ b/application/helpers/hlp_common_helper.php @@ -515,3 +515,45 @@ function has_permissions_for_stg($studiengang_kz, $permissions = '') return false; } + +/** + * is building an array for Dropdown Entry in Print Dropdown + * @param $id id for the Document to add to the Document Array + * @param $name title of the dropdownEntry + * @param $parameterUrl url of parameters xml, xsl, format etc as needed + * WITHOUT BASEURL eg. "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf" + * @param $uid default parameter, if null only parameterurl will be added + * additional needed parameter: put in the parameterUrl + * @param $alternativeBaseUrl: if baseUrl not pdfExport.php, put here alternative without ? char, eg. "zutrittskarte.php" + * + * @return Array + */ +function buildDropdownEntryPrintArray($id, $name, $parameterurl, $uid=null, $order=null, $alternativeBaseUrl=null) +{ + //DEFAULT BASEURL + $baseurl = "pdfExport.php?"; + + $uidString = $uid ? "&uid=" . $uid : ""; + + + + if($alternativeBaseUrl) + { + return [ + "id" => $id, + "type" => "documenturl", + "name" => $name, + "url" => $alternativeBaseUrl . "?" . $parameterurl . $uidString, + "order" => $order + ]; + } + else + return [ + "id" => $id, + "type" => "documenturl", + "name" => $name, + "url" => $baseurl . $parameterurl . "&uid=" . $uid, + "order" => $order + ]; + +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js index dabb000d1..a3ac6593b 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js @@ -312,7 +312,6 @@ export default { this.$api .call(ApiStvDocuments.getDocumentDropdownMulti(this.studentUids, params)) .then(result => { - console.log(result); this.documentDropdownObject = result; }) .catch(this.$fhcAlert.handleSystemError); @@ -325,7 +324,6 @@ export default { this.$api .call(ApiStvDocuments.getDocumentDropdown(params)) .then(result => { - console.log(result); this.documentDropdownObject = result; }) .catch(this.$fhcAlert.handleSystemError); From fc845ebf4e75c1ec26b32186eef8b8f02ab6ea37 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 2 Sep 2025 15:04:45 +0200 Subject: [PATCH 043/258] Studierendenverwaltung Projektarbeit: separate saving of Projektarbeit and Betreuer, added action for editing Betreuer --- .../api/frontend/v1/stv/Projektarbeit.php | 6 +- .../api/frontend/v1/stv/Projektbetreuer.php | 65 +++--- .../education/Lehrveranstaltung_model.php | 57 ++++++ public/js/api/factory/stv/projektarbeit.js | 2 +- public/js/api/factory/stv/projektbetreuer.js | 4 +- .../Details/Projektarbeit/Details.js | 5 +- .../Details/Projektarbeit/Projektarbeit.js | 188 +++++++++--------- .../Details/Projektarbeit/Projektbetreuer.js | 82 +++----- system/phrasesupdate.php | 60 ++++-- 9 files changed, 248 insertions(+), 221 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Projektarbeit.php b/application/controllers/api/frontend/v1/stv/Projektarbeit.php index e7d1af1f9..75478332f 100644 --- a/application/controllers/api/frontend/v1/stv/Projektarbeit.php +++ b/application/controllers/api/frontend/v1/stv/Projektarbeit.php @@ -310,13 +310,13 @@ class Projektarbeit extends FHCAPI_Controller 'projekttyp_kurzbz' => $formData['projekttyp_kurzbz'], 'firma_id' => $formData['firma_id'] ?? null, 'lehreinheit_id' => $formData['lehreinheit_id'], - 'beginn' => $formData['beginn'] ?? null, - 'ende' => $formData['ende'] ?? null, + 'beginn' => isset($formData['beginn']) && !isEmptyString($formData['beginn']) ? $formData['beginn'] : null, + 'ende' => isset($formData['ende']) && !isEmptyString($formData['ende']) ? $formData['ende'] : null, 'note' => $formData['note'] ?? null, 'final' => $formData['final'] ?? null, 'freigegeben' => $formData['freigegeben'] ?? null, 'anmerkung' => $formData['anmerkung'] ?? null, - 'gesperrtbis' => $formData['gesperrtbis'] ?? null + 'gesperrtbis' => isset($formData['gesperrtbis']) && !isEmptyString($formData['gesperrtbis']) ? $formData['gesperrtbis'] : null ]; } diff --git a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php index 625a30c40..98567ecde 100644 --- a/application/controllers/api/frontend/v1/stv/Projektbetreuer.php +++ b/application/controllers/api/frontend/v1/stv/Projektbetreuer.php @@ -114,49 +114,40 @@ class Projektbetreuer extends FHCAPI_Controller if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id)) return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]); - $projektbetreuer = $this->input->post('projektbetreuerListe'); + $projektbetreuer = $this->input->post('projektbetreuer'); - if (!is_array($projektbetreuer)) - return $this->terminateWithError($this->p->t('projektarbeit', 'error_invalidProjektbetreuer'), self::ERROR_TYPE_GENERAL); - - foreach ($projektbetreuer as $pb) - { - if ($this->_validate($pb) == false) $this->terminateWithValidationErrors($this->form_validation->error_array()); - } + if ($this->_validate($projektbetreuer) == false) $this->terminateWithValidationErrors($this->form_validation->error_array()); $result = null; - foreach ($projektbetreuer as $pb) + $betreuer = [ + 'projektarbeit_id' => $projektarbeit_id, + 'person_id' => $projektbetreuer['person_id'], + 'note' => $projektbetreuer['note'], + 'stunden' => $projektbetreuer['stunden'], + 'stundensatz' => $projektbetreuer['stundensatz'], + 'betreuerart_kurzbz' => $projektbetreuer['betreuerart_kurzbz'] + ]; + + if (isset($projektbetreuer['person_id_old']) && isset($projektbetreuer['betreuerart_kurzbz_old'])) { - $betreuer = [ - 'projektarbeit_id' => $projektarbeit_id, - 'person_id' => $pb['person_id'], - 'note' => $pb['note'], - 'stunden' => $pb['stunden'], - 'stundensatz' => $pb['stundensatz'], - 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz'] - ]; - - if (isset($pb['person_id_old']) && isset($pb['betreuerart_kurzbz_old'])) - { - $result = $this->ProjektbetreuerModel->update( - [ - 'projektarbeit_id' => $projektarbeit_id, - 'person_id' => $pb['person_id_old'], - 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz_old'] - ], - array_merge($betreuer, ['updateamum' => date('c'), 'updatevon' => getAuthUID()]) - ); - } - else - { - $result = $this->ProjektbetreuerModel->insert( - array_merge($betreuer, ['insertamum' => date('c'), 'insertvon' => getAuthUID()]) - ); - } - - if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $result = $this->ProjektbetreuerModel->update( + [ + 'projektarbeit_id' => $projektarbeit_id, + 'person_id' => $projektbetreuer['person_id_old'], + 'betreuerart_kurzbz' => $projektbetreuer['betreuerart_kurzbz_old'] + ], + array_merge($betreuer, ['updateamum' => date('c'), 'updatevon' => getAuthUID()]) + ); } + else + { + $result = $this->ProjektbetreuerModel->insert( + array_merge($betreuer, ['insertamum' => date('c'), 'insertvon' => getAuthUID()]) + ); + } + + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 1b3b9e9d7..7347cf2ca 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -1255,4 +1255,61 @@ class Lehrveranstaltung_model extends DB_Model return $this->execReadOnlyQuery($qry, $params); } + + /** + * Gets Lehrveranstaltungen for a student, as needed for a Projektarbeit. + * @param student_uid + * @param studiengang_kz optional, all Lvs of this Studiengang will be included + * @param additional_lehrveranstaltung_id optional, this lv will be added to result + * @return object success or error + */ + public function getLvsForProjektarbeit($student_uid, $studiengang_kz = null, $additional_lehrveranstaltung_id = null) + { + $params = array($student_uid, $student_uid); + + $qry = " + SELECT * + FROM + lehre.tbl_lehrveranstaltung + WHERE + ( + lehrveranstaltung_id IN ( + + SELECT + lehrveranstaltung_id + FROM + campus.vw_student_lehrveranstaltung + WHERE + uid=? + + UNION + + SELECT + lehrveranstaltung_id + FROM + lehre.tbl_zeugnisnote + WHERE + student_uid=? + )"; + + if (isset($studiengang_kz)) + { + $params[] = $studiengang_kz; + $qry .= " OR (studiengang_kz = ? AND semester IS NOT NULL)"; + } + + if (isset($additional_lehrveranstaltung_id)) + { + $params[] = $additional_lehrveranstaltung_id; + $qry .= " OR lehrveranstaltung_id = ?"; + } + + $qry .= " + ) + AND projektarbeit = TRUE + ORDER BY + semester, bezeichnung"; + + return $this->execQuery($qry, $params); + } } diff --git a/public/js/api/factory/stv/projektarbeit.js b/public/js/api/factory/stv/projektarbeit.js index 243383de0..4412f1842 100644 --- a/public/js/api/factory/stv/projektarbeit.js +++ b/public/js/api/factory/stv/projektarbeit.js @@ -77,4 +77,4 @@ export default { params: { projektarbeit_id } }; } -}; \ No newline at end of file +}; diff --git a/public/js/api/factory/stv/projektbetreuer.js b/public/js/api/factory/stv/projektbetreuer.js index 211eaaca8..4ea7bc782 100644 --- a/public/js/api/factory/stv/projektbetreuer.js +++ b/public/js/api/factory/stv/projektbetreuer.js @@ -42,11 +42,11 @@ export default { url: 'api/frontend/v1/stv/projektbetreuer/getNoten' }; }, - saveProjektbetreuer(projektarbeit_id, projektbetreuerListe) { + saveProjektbetreuer(projektarbeit_id, projektbetreuer) { return { method: 'post', url: 'api/frontend/v1/stv/projektbetreuer/saveProjektbetreuer', - params: { projektarbeit_id, projektbetreuerListe } + params: { projektarbeit_id, projektbetreuer } }; }, deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) { diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js index 2fdc9d996..b7aea7169 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Details.js @@ -15,10 +15,6 @@ export default { defaultSemester: { from: 'defaultSemester' } - //~ config: { - //~ from: 'config', - //~ required: true - //~ } }, computed: { // prepared Lehreinheiten (with compound Bezeichnung) @@ -169,6 +165,7 @@ export default { }, loadProjektarbeit(projektarbeit_id) { + this.resetForm(); return this.$api .call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id)) .then(result => { diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js index 76953867f..952c47860 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektarbeit.js @@ -36,7 +36,63 @@ export default { }, data() { return { - tabulatorOptions: { + tabulatorEvents: [ + { + event: 'dataLoaded', + handler: data => this.tabulatorData = data.map(item => { + item.actionDiv = document.createElement('div'); + return item; + }), + }, + { + event: 'tableBuilt', + handler: async() => { + await this.$p.loadCategory(['global', 'person', 'stv', 'ui', 'projektarbeit']); + + let cm = this.$refs.table.tabulator.columnManager; + + cm.getColumnByField('projekttyp_kurzbz').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'typ') + }); + cm.getColumnByField('titel').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'titel') + }); + cm.getColumnByField('beginn').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'beginn') + }); + cm.getColumnByField('ende').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'ende') + }); + cm.getColumnByField('freigegeben').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'freigegeben') + }); + cm.getColumnByField('gesperrtbis').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'gesperrtBis') + }); + cm.getColumnByField('themenbereich').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'themenbereich') + }); + cm.getColumnByField('anmerkung').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'anmerkung') + }); + cm.getColumnByField('firma_id').component.updateDefinition({ + title: this.$p.t('projektarbeit', 'firmaId') + }); + } + }, + ], + tabulatorData: [], + //lastSelected: null, + editedProjektarbeit: null, + statusNew: true, + studiensemester_kurzbz: null, + lehrveranstaltung_id: null, + activeTab: 'details' + } + }, + computed: { + tabulatorOptions() { + const options = { ajaxURL: 'dummy', ajaxRequestFunc: () => this.$api.call(ApiStvProjektarbeit.getProjektarbeit(this.student.uid)), ajaxResponse: (url, params, response) => response.data, @@ -153,9 +209,19 @@ export default { button.title = this.$p.t('ui', 'bearbeiten'); button.addEventListener('click', (event) => { let data = cell.getData(); - this.actionEditProjektarbeit( - data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id, data.projekttyp_kurzbz - ); + this.editedProjektarbeit = data; + this.actionEditProjektarbeit(); + }); + container.append(button); + + button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('projektarbeit', 'betreuerBearbeiten'); + button.addEventListener('click', (event) => { + let data = cell.getData(); + this.editedProjektarbeit = data; + this.actionEditBetreuer(); }); container.append(button); @@ -184,76 +250,27 @@ export default { columns: true, //persist column layout }, persistenceID: 'stv-details-projektarbeit' - }, - tabulatorEvents: [ - { - event: 'rowSelectionChanged', - handler: this.rowSelectionChanged - }, - { - event: 'dataLoaded', - handler: data => this.tabulatorData = data.map(item => { - item.actionDiv = document.createElement('div'); - return item; - }), - }, - { - event: 'tableBuilt', - handler: async() => { - await this.$p.loadCategory(['global', 'person', 'stv', 'ui', 'projektarbeit']); - - let cm = this.$refs.table.tabulator.columnManager; - - cm.getColumnByField('projekttyp_kurzbz').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'typ') - }); - cm.getColumnByField('titel').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'titel') - }); - cm.getColumnByField('beginn').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'beginn') - }); - cm.getColumnByField('ende').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'ende') - }); - cm.getColumnByField('freigegeben').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'freigegeben') - }); - cm.getColumnByField('gesperrtbis').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'gesperrtBis') - }); - cm.getColumnByField('themenbereich').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'themenbereich') - }); - cm.getColumnByField('anmerkung').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'anmerkung') - }); - cm.getColumnByField('firma_id').component.updateDefinition({ - title: this.$p.t('projektarbeit', 'firmaId') - }); - } - }, - ], - tabulatorData: [], - lastSelected: null, - statusNew: true, - studiensemester_kurzbz: null, - lehrveranstaltung_id: null + } + return options; } }, methods: { actionNewProjektarbeit() { this.statusNew = true; - this.$refs.projektarbeitDetails.resetForm(); this.$refs.projektarbeitDetails.getFormData(this.statusNew); - this.$refs.projektbetreuer.getData(); this.$refs.projektarbeitModal.show(); }, - actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id, projekttyp_kurzbz) { + actionEditProjektarbeit() { this.statusNew = false; - this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id); - this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id); - this.$refs.projektbetreuer.getData(projektarbeit_id, studiensemester_kurzbz, projekttyp_kurzbz); + this.toggleMenu('details'); + this.$refs.projektarbeitDetails.getFormData(this.statusNew, this.editedProjektarbeit.studiensemester_kurzbz, this.editedProjektarbeit.lehrveranstaltung_id); + this.$refs.projektarbeitDetails.loadProjektarbeit(this.editedProjektarbeit.projektarbeit_id); + this.$refs.projektarbeitModal.show(); + }, + actionEditBetreuer() { + this.statusNew = false; + this.toggleMenu('betreuer'); + this.$refs.projektbetreuer.getData(this.editedProjektarbeit.projektarbeit_id, this.editedProjektarbeit.studiensemester_kurzbz, this.editedProjektarbeit.projekttyp_kurzbz); this.$refs.projektarbeitModal.show(); }, actionDeleteProjektarbeit(projektarbeit_id) { @@ -266,34 +283,14 @@ export default { .catch(this.$fhcAlert.handleSystemError); }, addNewProjektarbeit() { - this.$refs.projektbetreuer.validateProjektbetreuer() - .then(() => { - return this.$refs.projektarbeitDetails.addNewProjektarbeit(); - }) - .then((result) => { - const projektarbeit_id = result.data; - - if (!isNaN(projektarbeit_id)) { - return this.$refs.projektbetreuer.saveProjektbetreuer(projektarbeit_id); - } - }) + this.$refs.projektarbeitDetails.addNewProjektarbeit() .then((result) => { this.projektarbeitSaved(); }) .catch(this.$fhcAlert.handleSystemError); }, updateProjektarbeit() { - this.$refs.projektbetreuer.validateProjektbetreuer() - .then(() => { - return this.$refs.projektarbeitDetails.updateProjektarbeit(); - }) - .then((result) => { - const projektarbeit_id = result.data; - - if (!isNaN(projektarbeit_id)) { - return this.$refs.projektbetreuer.saveProjektbetreuer(projektarbeit_id); - } - }) + this.$refs.projektarbeitDetails.updateProjektarbeit() .then((result) => { this.projektarbeitSaved(); }) @@ -314,10 +311,6 @@ export default { this.reload(); this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); this.hideModal('projektarbeitModal'); - this.$refs.projektarbeitDetails.resetForm(); - }, - rowSelectionChanged(data) { - this.lastSelected = data.length > 0 ? data[0] : null; }, setDefaultStunden(projekttyp_kurzbz) { this.$refs.projektbetreuer.setDefaultStunden(projekttyp_kurzbz); @@ -327,6 +320,9 @@ export default { }, reload() { this.$refs.table.reloadTable(); + }, + toggleMenu(tabId) { + this.activeTab = tabId; } }, template: ` @@ -357,16 +353,16 @@ export default {
-
+
@@ -375,7 +371,7 @@ export default {
-
+
@@ -387,7 +383,7 @@ export default { diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index 183c81bc0..1eb19e3fd 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -132,6 +132,10 @@ export default { event: 'tableBuilt', handler: async() => { await this.$p.loadCategory(['global', 'person', 'stv', 'projektarbeit', 'ui']); + + // Force layout recalculation for handling overflow text + this.$refs.projektbetreuerTable.tabulator.redraw(true); + } }, { @@ -193,7 +197,7 @@ export default { if (idx >= 0) { // if betreuer found betreuer = projektbetreuerListe[idx]; - // set currently edited betreuera + // set currently edited betreuer this.formData = betreuer; // set download link @@ -259,46 +263,31 @@ export default { if (projektarbeit_id) { this.projektarbeit_id = projektarbeit_id; - this.$api - .call(ApiStvProjektbetreuer.getProjektbetreuer(projektarbeit_id)) - .then(result => { - this.$refs.projektbetreuerTable.tabulator.setData(this.addIds(result.data)); - this.resetForm(); - }) - .catch(this.$fhcAlert.handleSystemError); + this.getProjektbetreuer(); } else { this.$refs.projektbetreuerTable.tabulator.setData([]); this.resetForm(); } }, - // confirming Betreuer means adding/updating him in list (but not yet saving in db) - confirmProjektbetreuer() { - if (!this.betreuerFormOpened) return; - - if (typeof this.formData.betreuer_id == 'undefined') { - this.formData.betreuer_id = this.getNewBetreuerId(); - this.$refs.projektbetreuerTable.tabulator.addData(this.addAutoCompleteBetreuerToFormData(this.formData)); - } else { - this.$refs.projektbetreuerTable.tabulator.updateData([this.formData]); - } - - this.resetModes(); - }, - confirmProjektbetreuerAfterValidation() { - //if (!this.formDataModified()) return; - - this.validateProjektbetreuer() + getProjektbetreuer() { + this.$api + .call(ApiStvProjektbetreuer.getProjektbetreuer(this.projektarbeit_id)) .then(result => { - this.confirmProjektbetreuer(); + this.$refs.projektbetreuerTable.tabulator.replaceData(this.addIds(result.data)); this.resetForm(); }) .catch(this.$fhcAlert.handleSystemError); }, - saveProjektbetreuer(projektarbeit_id) { - this.confirmProjektbetreuer(); - return this.$refs.formProjektbetreuer.call( - ApiStvProjektbetreuer.saveProjektbetreuer(projektarbeit_id, this.$refs.projektbetreuerTable.tabulator.getData()) - ); + saveProjektbetreuer() { + this.$refs.formProjektbetreuer.call( + ApiStvProjektbetreuer.saveProjektbetreuer(this.projektarbeit_id, this.getFormDataWithBetreuer()) + ) + .then(result => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + this.getProjektbetreuer(); + this.resetModes(); + }) + .catch(this.$fhcAlert.handleSystemError); }, searchBetreuer(event) { if (this.abortController.betreuer) { @@ -312,16 +301,6 @@ export default { this.filteredBetreuer = result.data; }); }, - // validate betreuer for data - validateProjektbetreuer() { - let alleBetreuer = this.$refs.projektbetreuerTable.tabulator.getData(); - - if (this.betreuerFormOpened) { - alleBetreuer.push(this.addAutoCompleteBetreuerToFormData(this.formData)); - } - - return this.$refs.formProjektbetreuer.call(ApiStvProjektbetreuer.validateProjektbetreuer(alleBetreuer)); - }, resetForm() { this.formData = this.getDefaultFormData(); if (this.beurteilungDownloadLink !== null) this.beurteilungDownloadLink = ''; @@ -360,7 +339,7 @@ export default { return betreuerListe; }, // add the betreuer selected in automomplete to betreuer liste - addAutoCompleteBetreuerToFormData() { + getFormDataWithBetreuer() { let preparedFormData = this.formData; preparedFormData.projektarbeit_id = this.projektarbeit_id; @@ -385,16 +364,6 @@ export default { // if form data has not already been modified by user, set the default stunden if (!this.formDataModified()) this.formData.stunden = this.getDefaultStunden(projekttyp_kurzbz); }, - // get a new betreuer id (max + 1) - getNewBetreuerId() { - let max = 0; - - for (const betreuer of this.$refs.projektbetreuerTable.tabulator.getData()) { - if (betreuer.betreuer_id > max) max = betreuer.betreuer_id; - } - - return max + 1; - }, // check if form data has been modified since initial data has been captured formDataModified() { if (this.autocompleteSelectedBetreuer != null) return true; @@ -406,9 +375,6 @@ export default { return false; }, - reload() { - this.$refs.projektbetreuerTable.reloadTable(); - }, actionNewPerson() { this.$refs.newPersonModal.reset(); this.$refs.newPersonModal.open(); @@ -422,7 +388,7 @@ export default { this.$api .call(ApiStvProjektbetreuer.getPerson(result.person_id)) .then(response => { - // set the new person in autocomplete field + // set the new person in Betreuer autocomplete field this.autocompleteSelectedBetreuer = response.data; }) .catch(this.$fhcAlert.handleSystemError) @@ -541,8 +507,8 @@ export default { - - +
+ + + + + + + + + - - + + + + + + +
{{ $p.t('person', 'personExistiertPruefung') }}
{{ $p.t('person', 'nachname') }}{{ $p.t('person', 'vorname') }}{{ $p.t('person', 'weitereVornamen') }}{{ $p.t('person', 'geburtsdatum') }}{{ $p.t('person', 'geschlecht') }}{{ $p.t('person', 'adresse') }}Status
{{suggestion.vorname + ' ' + suggestion.nachname}}{{ suggestion.nachname }}{{ suggestion.vorname }}{{ suggestion.vornamen }}{{ dateFormatter(suggestion.gebdatum) }}{{ suggestion.geschlecht_bezeichnung }} +
+ {{ (adresse.plz ?? '') + (adresse.plz && adresse.ort ? ' ' : '') + (adresse.ort ?? '') + (adresse.ort && adresse.strasse ? ', ' : '') + (adresse.strasse ?? '') }} +
+
+
+ {{ status.status_kurzbz + " " + status.studiengang_kuerzel }} +
+
@@ -422,19 +457,18 @@ export default {
- - -
- -
+
+
Adresse
@@ -519,6 +553,7 @@ export default {
+
@@ -679,7 +714,7 @@ export default {
-
+
From 07bcbee11bc5fdca821e5c4ffdcaafeea4aae6ac Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 13 Oct 2025 10:52:52 +0200 Subject: [PATCH 092/258] add Interessent: insertamum and insertvon when adding prestuden --- application/libraries/PrestudentLib.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/application/libraries/PrestudentLib.php b/application/libraries/PrestudentLib.php index 983f41b87..28879fb47 100644 --- a/application/libraries/PrestudentLib.php +++ b/application/libraries/PrestudentLib.php @@ -56,7 +56,9 @@ class PrestudentLib 'anmerkung' => $anmerkung, 'reihungstestangetreten' => false, 'bismelden' => true, - 'foerderrelevant' => $foerderrelevant + 'foerderrelevant' => $foerderrelevant, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() ]; // Wenn die Person schon im System erfasst ist, dann die ZGV des Datensatzes uebernehmen From 2aee86baba09b66e92ad99c2881b7685dd234a5a Mon Sep 17 00:00:00 2001 From: Cristina Date: Tue, 14 Oct 2025 09:55:55 +0200 Subject: [PATCH 093/258] Changed phrase lvevaluierung/logoutText --- system/phrasesupdate.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 469815a46..ede5cc2e3 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -49663,8 +49663,9 @@ and represent the current state of research on the topic. The prescribed citatio array( 'sprache' => 'German', 'text' => ' -

Ihr Feedback dient den Lehrenden zur Selbstevaluierung und Ihre Jahrgangsvertretungen werden von der Studiengangsleitung zum Jour-Fixe eingeladen, um die Ergebnisse zu besprechen.

-

Ihr Feedback dient der kontinuierlichen Weiterentwicklung der Lehrveranstaltung. Mehr Details dazu finden Sie hier: +

Danke, dass Sie sich Zeit für das Feedback genommen haben! Ihre ehrliche und konstruktive Rückmeldung ist essenziell, damit Ihre Lehrenden und Ihre Studiengangsleitung die Lehrveranstaltung immer weiter verbessern und anpassen können!

+

Und was passiert jetzt mit Ihrem Feedback? Die Studiengangsleitung wird die Ergebnisse & Maßnahmen zusammen mit Ihrer Jahrgangsvertretung besprechen. So tragen Sie aktiv dazu bei, die Lehrveranstaltung für zukünftige Semester noch spannender & lehrreicher zu machen!

+

Gemeinsam für mehr Qualität in der Lehre!

', 'description' => '', 'insertvon' => 'system' @@ -49672,8 +49673,9 @@ and represent the current state of research on the topic. The prescribed citatio array( 'sprache' => 'English', 'text' => ' -

Your feedback is used by the lecturers for self-evaluation and your year representatives are invited to the Jour-Fixe by the head of degree program to discuss the results.

-

Your feedback is used for the continuous further development of the course. You can find more details here: +

Thank you for taking the time to provide feedback! Your honest and constructive input is essential for your lecturers and degree program director to continuously improve and adapt the course.

+

What happens with your feedback? The degree program director will discuss the results and potential measures together with your academic year representatives. You have thus actively contributed to making the course even more engaging and educational for future semesters!

+

Working together for higher quality in teaching!

', 'description' => '', 'insertvon' => 'system' From 1fbca8bdab52adf77632ab029679d51c04da7eb9 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Fri, 17 Oct 2025 10:14:47 +0200 Subject: [PATCH 094/258] Bugfix: Add overflow for horizontal scrolling --- public/js/components/Calendar/Base/Grid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 */`
Date: Fri, 17 Oct 2025 12:33:22 +0200 Subject: [PATCH 095/258] added download to StudentList --- .../components/Stv/Studentenverwaltung/List.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/js/components/Stv/Studentenverwaltung/List.js b/public/js/components/Stv/Studentenverwaltung/List.js index 67cada523..a5331a7c4 100644 --- a/public/js/components/Stv/Studentenverwaltung/List.js +++ b/public/js/components/Stv/Studentenverwaltung/List.js @@ -307,6 +307,23 @@ export default { + ' | ' + this.$p.t('global/gesamt') + ': ' + (this.count || 0) + ''; + }, + downloadConfig() { + return { + csv: { + formatter: 'csv', + file: this.fileString, + options: { + delimiter: ';', + bom: true, + } + } + }; + }, + fileString() { + let today = new Date().toLocaleDateString('en-GB') + .replace(/\//g, '_'); + return "StudentList_" + today + ".csv"; } }, // TODO(chris): focusin, focusout, keydown and tabindex should be in the filter component @@ -322,6 +339,7 @@ export default { table-only :side-menu="false" reload + :download="downloadConfig" ` + /* TODO(chris): Ausgeblendet für Testing new-btn-show */` From 6e9969d9e43c828f907e3f54a6c8c76d5717c60e Mon Sep 17 00:00:00 2001 From: ma0068 Date: Mon, 20 Oct 2025 16:08:12 +0200 Subject: [PATCH 096/258] use shorter table names for columns stg and orgform , add column ausbildungssemester --- .../models/person/Profil_update_model.php | 3 +- .../Cis/ProfilUpdate/ProfilUpdateView.js | 13 ++++-- system/phrasesupdate.php | 40 +++++++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) 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/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js index 745f53002..24a5d8bc3 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: { @@ -205,7 +204,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, @@ -214,7 +213,7 @@ export default { //responsive:0, }, { - title: this.$p.t("lehre", "organisationsform") + ' (' + this.$p.t("profil", "studentIn") + ')', + title: this.$p.t("profil", "orgform_short") + ' (' + this.$p.t("profil", "studentIn") + ')', field: "orgform", minWidth: 50, resizable: true, @@ -278,6 +277,12 @@ export default { minWidth: 200, //responsive:0, }, + { + title: this.$p.t("lehre", "ausbildungssemester"), + field: "semester", + headerFilter: "list", + headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"} + }, { title: this.$p.t("profilUpdate", "actions"), headerSort: false, @@ -415,7 +420,7 @@ export default { }, template: /*html*/ `
- +
{{$p.t('ui','anzeigen')}}
diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 5d3833dc9..aace77876 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -28596,6 +28596,46 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'profil', + 'phrase' => 'stg_short', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'StG', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'degree Progr', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'profil', + 'phrase' => 'orgform_short', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'OrgForm', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'org Form', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), //Profil Phrasen ende // LvPlan Phrasen start array( From 1423579a49ad245aa9fed4bac817f500027b6741 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Tue, 21 Oct 2025 14:42:02 +0200 Subject: [PATCH 097/258] refactor Profile Update for filter, backendfilter not active --- .../components/filters/ProfileUpdate.php | 51 ++++++++++ .../Cis/ProfilUpdate/ProfilUpdateView.js | 96 +++++++++++++++++-- system/filtersupdate.php | 57 +++++++++++ 3 files changed, 196 insertions(+), 8 deletions(-) create mode 100644 application/components/filters/ProfileUpdate.php diff --git a/application/components/filters/ProfileUpdate.php b/application/components/filters/ProfileUpdate.php new file mode 100644 index 000000000..1a53e5145 --- /dev/null +++ b/application/components/filters/ProfileUpdate.php @@ -0,0 +1,51 @@ + 'core', + 'datasetName' => 'profileupdate', + 'query' => ' + SELECT + profil_update_id, + tbl_profil_update.uid, + (tbl_person.vorname || \' \' || tbl_person.nachname) AS name , + topic, + requested_change, + tbl_profil_update.updateamum, + tbl_profil_update.updatevon, + tbl_profil_update.insertamum, + tbl_profil_update.insertvon, + status, + public.tbl_profil_update_status.bezeichnung_mehrsprachig[(" . $lang . ")] as status_translated, + status_timestamp, + status_message, + attachment_id, + 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, + 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 + JOIN public.tbl_benutzer ON public.tbl_benutzer.uid = public.tbl_student.student_uid + JOIN public.tbl_person ON public.tbl_benutzer.person_id=public.tbl_person.person_id + JOIN public.tbl_studiengang ON public.tbl_studiengang.studiengang_kz=public.tbl_student.studiengang_kz + LEFT JOIN ( + select + pss.prestudent_id, COALESCE(sp.orgform_kurzbz, pss.orgform_kurzbz) as orgform_kurzbz + from ( + select + prestudent_id, max(insertamum) as insertamum + from + public.tbl_prestudentstatus + where + datum <= NOW() + group by + prestudent_id + ) mpss + join + public.tbl_prestudentstatus pss on pss.prestudent_id = mpss.prestudent_id and pss.insertamum = mpss.insertamum + left join + lehre.tbl_studienplan sp on pss.studienplan_id = sp.studienplan_id + ) of ON of.prestudent_id = public.tbl_student.prestudent_id + ', + 'requiredPermissions' => 'student/stammdaten' +); \ No newline at end of file diff --git a/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js index 24a5d8bc3..bec825495 100644 --- a/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js +++ b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js @@ -417,25 +417,105 @@ export default { if (sessionStorage.getItem("filter")) { this.filter = sessionStorage.getItem("filter"); } - }, - template: /*html*/ ` -
- -
+ /* +
{{$p.t('ui','anzeigen')}}
- + - +
+ + + :title="$p.t('profilUpdate','profilUpdateRequests')" + +

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

+ + +
+
+ +
+
+ + + //Version mit filter rechts in eigener zeile + + + +
+ +
+ +
+ + //backendfilter not working: no parameters provided + + + + */ + + + + + }, + template: /*html*/ ` +
+ + + +

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

+ - +
+ +
+ +
+
+ + + +
`, }; diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 9e3c62a33..2942bcb4e 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1558,6 +1558,63 @@ $filters = array( }', 'oe_kurzbz' => null, ), + array( + 'app' => 'core', + 'dataset_name' => 'profileupdate', + 'filter_kurzbz' => 'ProfilupdatePending', + 'description' => '{Ausstehende Anfragen}', + 'sort' => 1, + 'default_filter' => true, + 'filter' => ' + { + "name": "Ausstehende Anfragen", + "columns": [ + {"name": "uid"}, + {"name": "name"}, + {"name": "studiengang"}, + {"name": "orgform"}, + {"name": "oezuordnung"}, + {"name": "status_translated"}, + {"name": "topic"}, + {"name": "insertamum_iso"}, + {"name": "semester"} + ], + "filters": [ + { + "name": "status_translated", + "option": "", + "operation": "equal", + "condition": "true" + } + ] + }', + 'oe_kurzbz' => null, + ), + array( + 'app' => 'core', + 'dataset_name' => 'profileupdate', + 'filter_kurzbz' => 'ProfilupdateAlle', + 'description' => '{Alle Anfragen}', + 'sort' => 1, + 'default_filter' => false, + 'filter' => ' + { + "name": "Alle Anfragen", + "columns": [ + {"name": "uid"}, + {"name": "name"}, + {"name": "studiengang"}, + {"name": "orgform"}, + {"name": "oezuordnung"}, + {"name": "status_translated"}, + {"name": "topic"}, + {"name": "insertamum_iso"}, + {"name": "semester"} + ], + "filters": [] + }', + 'oe_kurzbz' => null, + ), ); From 6337869098d71547f4fc85535ec6bf232b81d94e Mon Sep 17 00:00:00 2001 From: ma0068 Date: Wed, 22 Oct 2025 10:23:24 +0200 Subject: [PATCH 098/258] new Multitab CombinePeople, start Function --- application/config/stv.php | 1 + .../api/frontend/v1/stv/Config.php | 4 ++ .../Details/CombinePeople.js | 57 +++++++++++++++++++ system/phrasesupdate.php | 22 ++++++- 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/CombinePeople.js diff --git a/application/config/stv.php b/application/config/stv.php index 42afc318c..d6d06f44e 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -111,5 +111,6 @@ $config['students_tab_order'] = [ 'status', 'groups', 'finalexam', + 'combinePeople', 'archive', ]; diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index d52016943..20e43d23a 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -228,6 +228,10 @@ class Config extends FHCAPI_Controller 'showEdit' => $this->permissionlib->isBerechtigt('admin') ] ]; + $result['combinePeople'] = [ + 'title' => $this->p->t('stv', 'tab_combine_people'), + 'component' => './Stv/Studentenverwaltung/Details/CombinePeople.js', + ]; Events::trigger('stv_conf_students', function & () use (&$result) { return $result; diff --git a/public/js/components/Stv/Studentenverwaltung/Details/CombinePeople.js b/public/js/components/Stv/Studentenverwaltung/Details/CombinePeople.js new file mode 100644 index 000000000..4374687fe --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/CombinePeople.js @@ -0,0 +1,57 @@ +export default { + name: "TabCombinePeople", + inject: { + cisRoot: { + from: 'cisRoot' + }, + }, + props: { + modelValue: Object, + }, + computed: { + personIds(){ + if (this.modelValue.person_id) { + return [this.modelValue.person_id]; + } + return this.modelValue.map(e => e.person_id); + } + }, + methods: { + combinePeople(){ + + let person1_id = this.personIds[0]; + let person2_id = this.personIds[1]; + + if(person1_id == person2_id) { + return this.$fhcAlert.alertError("gleiche Person, keine Zusammenlegeung möglich"); + } + + let linkCombinePeople = this.cisRoot + 'vilesci/stammdaten/personen_wartung.php?person_id_1=' + person1_id + '&person_id_2='+ person2_id; + + console.log(linkCombinePeople); + window.open(linkCombinePeople, '_blank'); + + + } + }, + data(){ + return {} + }, + template: /*html*/ ` +
+

Personen zusammenlegen

+ + {{personIds}} + +
+ +

+ +

+

+ ungültige Anzahl: {{this.modelValue.length}} +

+
+
+ ` + }; \ No newline at end of file diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 5d3833dc9..d931f85c2 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -49982,7 +49982,27 @@ I have been informed that I am under no obligation to consent to the transmissio 'insertvon' => 'system' ) ) - ) + ), + array( + 'app' => 'core', + 'category' => 'stv', + 'phrase' => 'tab_combine_people', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Personen zusammenlegen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Combine People', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From 9a8fbabbe46f0519cecae6d6798bd8f7ee12d234 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Wed, 22 Oct 2025 14:25:43 +0200 Subject: [PATCH 099/258] move dropdown profileUpdateStates to FilterComponent, delete not needed code --- .../components/filters/ProfileUpdate.php | 51 ------ .../Cis/ProfilUpdate/ProfilUpdateView.js | 146 +++++------------- system/filtersupdate.php | 58 ------- system/phrasesupdate.php | 39 +++++ 4 files changed, 74 insertions(+), 220 deletions(-) delete mode 100644 application/components/filters/ProfileUpdate.php diff --git a/application/components/filters/ProfileUpdate.php b/application/components/filters/ProfileUpdate.php deleted file mode 100644 index 1a53e5145..000000000 --- a/application/components/filters/ProfileUpdate.php +++ /dev/null @@ -1,51 +0,0 @@ - 'core', - 'datasetName' => 'profileupdate', - 'query' => ' - SELECT - profil_update_id, - tbl_profil_update.uid, - (tbl_person.vorname || \' \' || tbl_person.nachname) AS name , - topic, - requested_change, - tbl_profil_update.updateamum, - tbl_profil_update.updatevon, - tbl_profil_update.insertamum, - tbl_profil_update.insertvon, - status, - public.tbl_profil_update_status.bezeichnung_mehrsprachig[(" . $lang . ")] as status_translated, - status_timestamp, - status_message, - attachment_id, - 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, - 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 - JOIN public.tbl_benutzer ON public.tbl_benutzer.uid = public.tbl_student.student_uid - JOIN public.tbl_person ON public.tbl_benutzer.person_id=public.tbl_person.person_id - JOIN public.tbl_studiengang ON public.tbl_studiengang.studiengang_kz=public.tbl_student.studiengang_kz - LEFT JOIN ( - select - pss.prestudent_id, COALESCE(sp.orgform_kurzbz, pss.orgform_kurzbz) as orgform_kurzbz - from ( - select - prestudent_id, max(insertamum) as insertamum - from - public.tbl_prestudentstatus - where - datum <= NOW() - group by - prestudent_id - ) mpss - join - public.tbl_prestudentstatus pss on pss.prestudent_id = mpss.prestudent_id and pss.insertamum = mpss.insertamum - left join - lehre.tbl_studienplan sp on pss.studienplan_id = sp.studienplan_id - ) of ON of.prestudent_id = public.tbl_student.prestudent_id - ', - 'requiredPermissions' => 'student/stammdaten' -); \ No newline at end of file diff --git a/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js index bec825495..222290e98 100644 --- a/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js +++ b/public/js/components/Cis/ProfilUpdate/ProfilUpdateView.js @@ -212,7 +212,13 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { + { + 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, @@ -221,8 +227,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, @@ -230,7 +236,7 @@ export default { headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}, //responsive:0, }, - { + { title: this.$p.t("profilUpdate", "Topic"), field: "topic", resizable: true, @@ -239,7 +245,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, @@ -250,7 +256,7 @@ export default { formatterParams: this.datetimeFormatterParams(), //responsive:0, }, - { + { title: this.$p.t("profilUpdate", "Status"), field: "status_translated", hozAlign: "center", @@ -272,17 +278,10 @@ export default { } return `
${cell.getValue()}
`; }, - resizable: true, minWidth: 200, //responsive:0, }, - { - title: this.$p.t("lehre", "ausbildungssemester"), - field: "semester", - headerFilter: "list", - headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"} - }, { title: this.$p.t("profilUpdate", "actions"), headerSort: false, @@ -314,7 +313,6 @@ export default { ], }; } - }, methods: { denyProfilUpdate: function (data) { @@ -356,7 +354,6 @@ export default { this.showModal = false; this.modalData = null; }, - showAcceptDenyModal(value) { this.modalData = value; if (!this.modalData) { @@ -369,7 +366,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 @@ -417,105 +413,33 @@ export default { if (sessionStorage.getItem("filter")) { this.filter = sessionStorage.getItem("filter"); } - - /* -
-
{{$p.t('ui','anzeigen')}}
- - - -
- - - :title="$p.t('profilUpdate','profilUpdateRequests')" - -

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

- - -
-
- -
-
- - - //Version mit filter rechts in eigener zeile - - - -
- -
- -
- - //backendfilter not working: no parameters provided - - - - */ - - - - }, template: /*html*/ `
+ +

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

+ - - -

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

- - - -
- -
- + + + - - - - -
`, +
`, }; diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 2942bcb4e..a4deca527 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1558,64 +1558,6 @@ $filters = array( }', 'oe_kurzbz' => null, ), - array( - 'app' => 'core', - 'dataset_name' => 'profileupdate', - 'filter_kurzbz' => 'ProfilupdatePending', - 'description' => '{Ausstehende Anfragen}', - 'sort' => 1, - 'default_filter' => true, - 'filter' => ' - { - "name": "Ausstehende Anfragen", - "columns": [ - {"name": "uid"}, - {"name": "name"}, - {"name": "studiengang"}, - {"name": "orgform"}, - {"name": "oezuordnung"}, - {"name": "status_translated"}, - {"name": "topic"}, - {"name": "insertamum_iso"}, - {"name": "semester"} - ], - "filters": [ - { - "name": "status_translated", - "option": "", - "operation": "equal", - "condition": "true" - } - ] - }', - 'oe_kurzbz' => null, - ), - array( - 'app' => 'core', - 'dataset_name' => 'profileupdate', - 'filter_kurzbz' => 'ProfilupdateAlle', - 'description' => '{Alle Anfragen}', - 'sort' => 1, - 'default_filter' => false, - 'filter' => ' - { - "name": "Alle Anfragen", - "columns": [ - {"name": "uid"}, - {"name": "name"}, - {"name": "studiengang"}, - {"name": "orgform"}, - {"name": "oezuordnung"}, - {"name": "status_translated"}, - {"name": "topic"}, - {"name": "insertamum_iso"}, - {"name": "semester"} - ], - "filters": [] - }', - 'oe_kurzbz' => null, - ), - ); // Loop through the filters array diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index aace77876..ad8d52f0a 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -28636,6 +28636,45 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'profil', + 'phrase' => 'orgeinheit_short', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'OrgEH', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'org Unit', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( + 'app' => 'core', + 'category' => 'profil', + 'phrase' => 'sem_short', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sem', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'sem', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), //Profil Phrasen ende // LvPlan Phrasen start array( From 1623c8e51c43199a38d413c9d3f76eadc0e21755 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 22 Oct 2025 16:57:19 +0200 Subject: [PATCH 100/258] Ausbildungsvertrag: akadgrad is coming from Studienordnung --- rdf/ausbildungsvertrag.xml.php | 42 ++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/rdf/ausbildungsvertrag.xml.php b/rdf/ausbildungsvertrag.xml.php index 56dfd95a4..3be40e0e2 100644 --- a/rdf/ausbildungsvertrag.xml.php +++ b/rdf/ausbildungsvertrag.xml.php @@ -332,6 +332,13 @@ foreach($prestudent_arr as $prest_id) { $studiengangbezeichnung = $studienordnung->__get('studiengangbezeichnung'); $studiengangbezeichnung_englisch = $studienordnung->__get('studiengangbezeichnung_englisch'); + $akadgrad = new akadgrad(); + if ($akadgrad->load($studienordnung->__get('akadgrad_id'))) + { + // TODO - geschlechterneutral? m/w/d + $akadgrad_titel = $akadgrad->titel; + $akadgrad_kurzbz = $akadgrad->akadgrad_kurzbz; + } } } $studiengang_bezeichnung = empty($studiengangbezeichnung) ? $studiengang->bezeichnung : $studiengangbezeichnung; @@ -428,25 +435,30 @@ foreach($prestudent_arr as $prest_id) //Wenn Quereinsteiger stimmt studiengang_maxsemester nicht mit der tatsaechlichen Ausbildungsdauer ueberein $student_maxsemester = ($studiengang->max_semester-$ausbildungssemester)+1; + + // TODO: where to get semester duration for master Legrgaenge? + //if ($lehrgangstyp->lgartcode == 1) $student_maxsemester += 2; echo "\t\t".$student_maxsemester."\n"; echo "\t\t".($student_maxsemester/2)."\n"; - - //Bis die Akadgrad-Tabelle an die Studienordnung angepasst ist, wird der Akadgrad hier ermittelt - - $akadgrad_titel = ''; - $akadgrad_kurzbz = ''; - - $qry = "SELECT * FROM lehre.tbl_akadgrad - WHERE studiengang_kz=".$db->db_add_param($studiengang->studiengang_kz, FHC_INTEGER)." - AND (geschlecht=".$db->db_add_param($person->geschlecht, FHC_STRING)." OR geschlecht IS NULL) - LIMIT 1"; - - if($db->db_query($qry)) + if (!isset($akadgrad_titel) || $akadgrad_titel == '') { - if($row = $db->db_fetch_object()) + //Bis die Akadgrad-Tabelle an die Studienordnung angepasst ist, wird der Akadgrad hier ermittelt + + $akadgrad_titel = ''; + $akadgrad_kurzbz = ''; + + $qry = "SELECT * FROM lehre.tbl_akadgrad + WHERE studiengang_kz=".$db->db_add_param($studiengang->studiengang_kz, FHC_INTEGER)." + AND (geschlecht=".$db->db_add_param($person->geschlecht, FHC_STRING)." OR geschlecht IS NULL) + LIMIT 1"; + + if($db->db_query($qry)) { - $akadgrad_titel = $row->titel; - $akadgrad_kurzbz = $row->akadgrad_kurzbz; + if($row = $db->db_fetch_object()) + { + $akadgrad_titel = $row->titel; + $akadgrad_kurzbz = $row->akadgrad_kurzbz; + } } } From 8ddc2f02fece2440279012082196bb513ccfaaa7 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 23 Oct 2025 11:47:33 +0200 Subject: [PATCH 101/258] SVG Icons --- public/css/SvgIcons.css | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 public/css/SvgIcons.css diff --git a/public/css/SvgIcons.css b/public/css/SvgIcons.css new file mode 100644 index 000000000..f25d842a4 --- /dev/null +++ b/public/css/SvgIcons.css @@ -0,0 +1,28 @@ +/* Themable Variables */ +:root { + --svg-icon-apps: var(--fhc-icon-apps, url('data:image/svg+xml,\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + ')); +} +.svg-icon { + display: inline-block; + width: 1rem; + line-height: 1; + background-color: currentColor; +} +.svg-icon:before { + content: "\00a0"; +} +.svg-icon.svg-icon-apps { + -webkit-mask-image: var(--svg-icon-apps); + mask-image: var(--svg-icon-apps); +} From 752ef8a57bbac02d0056aecac24e36868ff24f56 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 23 Oct 2025 11:48:03 +0200 Subject: [PATCH 102/258] AppMenu Component --- public/css/components/AppMenu.css | 26 ++++++++++++ public/js/components/AppMenu.js | 68 +++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 public/css/components/AppMenu.css create mode 100644 public/js/components/AppMenu.js diff --git a/public/css/components/AppMenu.css b/public/css/components/AppMenu.css new file mode 100644 index 000000000..b980c1efc --- /dev/null +++ b/public/css/components/AppMenu.css @@ -0,0 +1,26 @@ +.fhc-app-menu { + display: flex; + flex-direction: column; + padding-left: 0; + margin: calc(var(--bs-offcanvas-padding-y) * -1) calc(var(--bs-offcanvas-padding-x) * -1); +} +.fhc-app-menu li { + display: block; + border: var(--bs-border-width) solid var(--bs-border-color); +} +.fhc-app-menu li + li { + border-top-width: 0; +} +.fhc-app-menu li a { + display: block; + padding: .5rem 1rem; + text-decoration: none; +} +.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.active { + pointer-events: none; +} diff --git a/public/js/components/AppMenu.js b/public/js/components/AppMenu.js new file mode 100644 index 000000000..33d35f8df --- /dev/null +++ b/public/js/components/AppMenu.js @@ -0,0 +1,68 @@ +/** + * 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 ApiNavigation from '../api/factory/navigation.js'; + +export default { + name: 'AppMenu', + props: { + appIdentifier: { + type: String, + required: true + }, + navigationPage: { + type: String, + default: 'apps' + } + }, + data() { + return { + items: [] + }; + }, + watch: { + navigationPage() { + this.getItems(); + } + }, + methods: { + getItems() { + this.$api + .call(ApiNavigation.getMenu(this.navigationPage)) + .then(result => { + this.items = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + } + }, + created() { + this.getItems(); + }, + template: /* html */` + ` +}; From 11daf968501665c2078243826eb4e12e8f1c08e3 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 23 Oct 2025 11:48:55 +0200 Subject: [PATCH 103/258] add navigation entries for StV & LvV --- application/config/navigation.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/application/config/navigation.php b/application/config/navigation.php index 11fd1a3a6..2ce6a0062 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -336,3 +336,19 @@ $config['navigation_menu']['system/issues/Issues/*'] = array( 'requiredPermissions' => array('admin:rw') ), ); + +// TODO(chris): phrases? +$config['navigation_menu']['apps'] = [ + 'stv' => [ + 'link' => site_url('studentenverwaltung'), + 'description' => 'Studierenden Verwaltung', + #'icon' => 'users', + 'requiredPermissions' => array('admin:r', 'assistenz:r') + ], + 'lvv' => [ + 'link' => site_url('lVVerwaltung'), + 'description' => 'LV Verwaltung', + #'icon' => 'person-chalkboard', + 'requiredPermissions' => array('admin:r', 'assistenz:r') + ] +]; From 5baf8b645fe5ac46c9b3a1d20036bd7592730591 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 23 Oct 2025 11:49:07 +0200 Subject: [PATCH 104/258] use AppMenu in StV --- public/css/Studentenverwaltung.css | 10 +++-- .../js/components/Stv/Studentenverwaltung.js | 40 +++++++++++++++++-- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/public/css/Studentenverwaltung.css b/public/css/Studentenverwaltung.css index bb2588926..56e99b937 100644 --- a/public/css/Studentenverwaltung.css +++ b/public/css/Studentenverwaltung.css @@ -1,15 +1,21 @@ @import './Fhc.css'; +@import './SvgIcons.css'; @import './components/searchbar/searchbar.css'; @import './components/verticalsplit.css'; @import './components/FilterComponent.css'; @import './components/Tabs.css'; @import './components/Notiz.css'; @import './components/Messages.css'; +@import './components/AppMenu.css'; html { font-size: .875em; } +#appMenu { + width: 300px; +} + .navbar-dark .navbar-brand:focus { box-shadow: 0 0 0 .25rem rgba(13,110,253,.25); z-index: 3; @@ -37,10 +43,6 @@ html { flex: 1 1 auto; } -#sidebarMenu { - width: 0%; -} - .tabulator-row.disabled.tabulator-row-odd .tabulator-cell { color: var(--gray-400); } diff --git a/public/js/components/Stv/Studentenverwaltung.js b/public/js/components/Stv/Studentenverwaltung.js index d0543ad59..63511924f 100644 --- a/public/js/components/Stv/Studentenverwaltung.js +++ b/public/js/components/Stv/Studentenverwaltung.js @@ -17,6 +17,7 @@ import CoreSearchbar from "../searchbar/searchbar.js"; import VerticalSplit from "../verticalsplit/verticalsplit.js"; +import AppMenu from "../AppMenu.js"; import StvVerband from "./Studentenverwaltung/Verband.js"; import StvList from "./Studentenverwaltung/List.js"; import StvDetails from "./Studentenverwaltung/Details.js"; @@ -32,6 +33,7 @@ export default { components: { CoreSearchbar, VerticalSplit, + AppMenu, StvVerband, StvList, StvDetails, @@ -345,11 +347,34 @@ export default { //FHC_JS_DATA_STORAGE_OBJECT.systemerror_mailto = 'ma0068@technikum-wien.at';this.$fhcAlert.handleSystemError(1); this.handlePersonUrl(); }, - template: ` + template: /* html */`