From 405062f5493fcdaaf3ed0e9b501a08e5aa93f081 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 7 May 2025 18:36:51 +0200 Subject: [PATCH 001/101] 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 002/101] 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 009/101] 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 010/101] 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 011/101] 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 012/101] =?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 017/101] 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 018/101] 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 019/101] 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 75adcefd5168f2b3da82d7fa19aaeb7eb6343821 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Mon, 21 Jul 2025 17:52:21 +0200 Subject: [PATCH 020/101] 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 021/101] 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 022/101] 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 023/101] 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 024/101] 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 025/101] 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 026/101] 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 027/101] 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 028/101] 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 029/101] 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 030/101] 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 031/101] 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 032/101] 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 033/101] 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 034/101] 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 { -