From 6b4f5778c2dafd335aa992c70083459050114c54 Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Mon, 24 Nov 2025 16:26:11 +0100 Subject: [PATCH] refactor stv Pruefung Tab and API endpoint to use same logic for insert and update, use luxon lib to initialize datepicker with iso date and send iso date format to api endpoint --- .../api/frontend/v1/stv/Pruefung.php | 409 +++++++++--------- application/views/Studentenverwaltung.php | 3 +- .../Details/Noten/Zeugnis.js | 3 +- .../Details/Pruefung/Pruefunglist.js | 38 +- 4 files changed, 208 insertions(+), 245 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Pruefung.php b/application/controllers/api/frontend/v1/stv/Pruefung.php index a539a4d79..4521c2033 100644 --- a/application/controllers/api/frontend/v1/stv/Pruefung.php +++ b/application/controllers/api/frontend/v1/stv/Pruefung.php @@ -178,175 +178,7 @@ class Pruefung extends FHCAPI_Controller */ public function insertPruefung() { - $authUID = getAuthUID(); - - $this->load->library('form_validation'); - - $this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]), - ]); - $this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]), - ]); - $this->form_validation->set_rules( - 'datum', - $this->p->t('global', 'datum'), - ['is_valid_date'] - ); - - if ($this->form_validation->run() == false) - { - $this->terminateWithValidationErrors($this->form_validation->error_array()); - } - - $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); - - $this->PruefungModel->db->trans_start(); - - if ($this->input->post('pruefungstyp_kurzbz') == "Termin2") - { - //Wenn ein 2. Termin angelegt wird, und kein 1. Termin vorhanden ist, - //dann wird auch ein 1. Termin angelegt mit der derzeitigen Zeugnisnote - $resultP = $this->PruefungModel->loadWhere(array( - 'lehreinheit_id' => $this->input->post('lehreinheit_id'), - 'student_uid' => $this->input->post('student_uid'), - 'pruefungstyp_kurzbz' => 'Termin1')); - - $termin1 = $this->getDataOrTerminateWithError($resultP); - if (!$termin1) - { - //check if existing Zeugnisnote - $this->ZeugnisnoteModel->addJoin('lehre.tbl_lehreinheit', 'lehrveranstaltung_id'); - - $this->ZeugnisnoteModel->db->where( - 'lehre.tbl_zeugnisnote.studiensemester_kurzbz', - 'lehre.tbl_lehreinheit.studiensemester_kurzbz', - false - ); - $resultP = $this->ZeugnisnoteModel->loadWhere(array( - 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), - 'student_uid' => $this->input->post('student_uid') - )); - - $zeugnisnoten = $this->getDataOrTerminateWithError($resultP); - if ($zeugnisnoten) - { - $zeugnisnote = current($zeugnisnoten); - - $resultN = $this->PruefungModel->insert([ - 'lehreinheit_id' => $this->input->post('lehreinheit_id'), - 'student_uid' => $this->input->post('student_uid'), - 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), - 'datum' => $zeugnisnote->benotungsdatum, - 'pruefungstyp_kurzbz' => 'Termin1', - 'note' => $zeugnisnote->note, - 'punkte' => $zeugnisnote->punkte, - 'anmerkung' => 'automatisiert aus Zeugnisnote erstellt', - 'insertamum' => date('c'), - 'insertvon' => $authUID, - ]); - - $this->getDataOrTerminateWithError($resultN); - } - //Wenn keine Zeugnisnote vorhanden ist, dann wird kein - //1.Termin angelegt - } - } - - $result = $this->PruefungModel->insert([ - 'lehreinheit_id' => $this->input->post('lehreinheit_id'), - 'student_uid' => $this->input->post('student_uid'), - 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), - 'datum' => $this->input->post('datum'), - 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), - 'note' => $this->input->post('note'), - 'anmerkung' => $this->input->post('anmerkung'), - 'insertamum' => date('c'), - 'insertvon' => $authUID, - 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null - ]); - - $this->getDataOrTerminateWithError($result); - - //get studiensemester_kurzbz and lehreveranstaltung_id from lehreinheit - $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); - - $result = $this->LehreinheitModel->load($this->input->post('lehreinheit_id')); - - $lehreinheiten = $this->getDataOrTerminateWithError($result); - - if (!$lehreinheiten) { - $this->terminateWithValidationErrors([ - 'lehreinheit_id' => $this->p->t('ui', 'error_fieldNotFound', [ - 'field' => $this->p->t('lehre', 'lehreinheit') - ]) - ]); - } - $lehreinheit = current($lehreinheiten); - $studiensemester_kurzbz = $lehreinheit->studiensemester_kurzbz; - $lehrveranstaltung_id = $lehreinheit->lehrveranstaltung_id; - - //check if existing zeugnisnote - $result = $this->ZeugnisnoteModel->loadWhere(array( - 'lehrveranstaltung_id' => $lehrveranstaltung_id, - 'student_uid' => $this->input->post('student_uid'), - 'studiensemester_kurzbz' => $studiensemester_kurzbz - )); - - $zeugnisnoten = $this->getDataOrTerminateWithError($result); - - if (!$zeugnisnoten) - { - //insert zeugnisnote, if not existing - $result = $this->ZeugnisnoteModel->insert(array( - 'lehrveranstaltung_id' => $lehrveranstaltung_id, - 'student_uid' => $this->input->post('student_uid'), - 'studiensemester_kurzbz' => $studiensemester_kurzbz, - 'note' => $this->input->post('note'), - 'uebernahmedatum' => date('c'), - 'benotungsdatum' => $this->input->post('datum'), - 'insertamum' => date('c'), - 'insertvon' => $authUID, - 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null - )); - - $this->getDataOrTerminateWithError($result); - - $this->PruefungModel->db->trans_complete(); - $this->terminateWithSuccess(); - } - - $note = current($zeugnisnoten); - $uebernahmedatum = new DateTime($note->uebernahmedatum); - $benotungsdatum = new DateTime($note->benotungsdatum); - $pruefungsdatum = new DateTime($this->input->post('datum')); - - $checkDate = $uebernahmedatum === '' || $benotungsdatum > $uebernahmedatum - ? $benotungsdatum - : $uebernahmedatum; - - if ($checkDate >= $pruefungsdatum && $this->input->post('note') !== $note->note) - { - $this->PruefungModel->db->trans_complete(); - $this->terminateWithSuccess($this->p->t('exam', 'hinweis_changeAfterExamDate')); - } - - //update zeugnisnote, if existing and valid datum - $result = $this->ZeugnisnoteModel->update([ - 'lehrveranstaltung_id' => $lehrveranstaltung_id, - 'student_uid' => $this->input->post('student_uid'), - 'studiensemester_kurzbz' => $studiensemester_kurzbz - ], [ - 'note' => $this->input->post('note'), - 'uebernahmedatum' => date('c'), - 'benotungsdatum' => $this->input->post('datum'), - 'updateamum' => date('c'), - 'updatevon' => $authUID, - 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null - ]); - - $this->PruefungModel->db->trans_complete(); - $this->terminateWithSuccess(); + $this->insertOrUpdatePruefung(); } /** @@ -355,8 +187,6 @@ class Pruefung extends FHCAPI_Controller * @param pruefung_id * * @return success or error - * - * no impact on lehre.tbl_zeugnisnote */ public function updatePruefung($pruefung_id) { @@ -366,48 +196,7 @@ class Pruefung extends FHCAPI_Controller if (!$oldpruefung) show_404(); // Pruefung that should be updated does not exist - $authUID = getAuthUID(); - - $this->load->library('form_validation'); - - $this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehrveranstaltung')]), - ]); - $this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]), - ]); - $this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [ - 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]), - ]); - $this->form_validation->set_rules( - 'datum', - $this->p->t('global', 'datum'), - ['is_valid_date'] - ); - - if ($this->form_validation->run() == false) - { - $this->terminateWithValidationErrors($this->form_validation->error_array()); - } - - $result = $this->PruefungModel->update( - [ - 'pruefung_id' => $pruefung_id - ], - [ 'lehreinheit_id' => $this->input->post('lehreinheit_id'), - 'student_uid' => $this->input->post('student_uid'), - 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), - 'note' => $this->input->post('note'), - 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), - 'datum' => $this->input->post('datum'), - 'anmerkung' => $this->input->post('anmerkung'), - 'updatevon' => $authUID, - 'updateamum' => date('c'), - ] - ); - $this->getDataOrTerminateWithError($result); - - return $this->outputJsonSuccess(true); + $this->insertOrUpdatePruefung($pruefung_id); } /** @@ -581,4 +370,198 @@ class Pruefung extends FHCAPI_Controller return $this->terminateWithSuccess($data); } + + protected function insertOrUpdatePruefung($pruefung_id=null) + { + $authUID = getAuthUID(); + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('lehreinheit_id', $this->p->t('lehre', 'lehreinheit'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'lehreinheit')]), + ]); + $this->form_validation->set_rules('pruefungstyp_kurzbz', $this->p->t('lehre', 'pruefung'), 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('global', 'typ')]), + ]); + $this->form_validation->set_rules( + 'datum', + $this->p->t('global', 'datum'), + ['is_valid_date'] + ); + + if ($this->form_validation->run() == false) + { + $this->terminateWithValidationErrors($this->form_validation->error_array()); + } + + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + + $this->PruefungModel->db->trans_start(); + + if ($this->input->post('pruefungstyp_kurzbz') == "Termin2") + { + //Wenn ein 2. Termin angelegt wird, und kein 1. Termin vorhanden ist, + //dann wird auch ein 1. Termin angelegt mit der derzeitigen Zeugnisnote + $resultP = $this->PruefungModel->loadWhere(array( + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'pruefungstyp_kurzbz' => 'Termin1')); + + $termin1 = $this->getDataOrTerminateWithError($resultP); + if (!$termin1) + { + //check if existing Zeugnisnote + $this->ZeugnisnoteModel->addJoin('lehre.tbl_lehreinheit', 'lehrveranstaltung_id'); + + $this->ZeugnisnoteModel->db->where( + 'lehre.tbl_zeugnisnote.studiensemester_kurzbz', + 'lehre.tbl_lehreinheit.studiensemester_kurzbz', + false + ); + $resultP = $this->ZeugnisnoteModel->loadWhere(array( + 'lehrveranstaltung_id' => $this->input->post('lehrveranstaltung_id'), + 'student_uid' => $this->input->post('student_uid') + )); + + $zeugnisnoten = $this->getDataOrTerminateWithError($resultP); + if ($zeugnisnoten) + { + $zeugnisnote = current($zeugnisnoten); + + $resultN = $this->PruefungModel->insert([ + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'datum' => $zeugnisnote->benotungsdatum, + 'pruefungstyp_kurzbz' => 'Termin1', + 'note' => $zeugnisnote->note, + 'punkte' => $zeugnisnote->punkte, + 'anmerkung' => 'automatisiert aus Zeugnisnote erstellt', + 'insertamum' => date('c'), + 'insertvon' => $authUID, + ]); + + $this->getDataOrTerminateWithError($resultN); + } + //Wenn keine Zeugnisnote vorhanden ist, dann wird kein + //1.Termin angelegt + } + } + + if(intval($pruefung_id) > 0) + { + $result = $this->PruefungModel->update( + [ + 'pruefung_id' => $pruefung_id + ], + [ 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'note' => $this->input->post('note'), + 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), + 'datum' => $this->input->post('datum'), + 'anmerkung' => $this->input->post('anmerkung'), + 'updatevon' => $authUID, + 'updateamum' => date('c'), + ] + ); + } + else + { + $result = $this->PruefungModel->insert([ + 'lehreinheit_id' => $this->input->post('lehreinheit_id'), + 'student_uid' => $this->input->post('student_uid'), + 'mitarbeiter_uid' => $this->input->post('mitarbeiter_uid'), + 'datum' => $this->input->post('datum'), + 'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'), + 'note' => $this->input->post('note'), + 'anmerkung' => $this->input->post('anmerkung'), + 'insertamum' => date('c'), + 'insertvon' => $authUID, + 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null + ]); + } + + $this->getDataOrTerminateWithError($result); + + //get studiensemester_kurzbz and lehreveranstaltung_id from lehreinheit + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + $result = $this->LehreinheitModel->load($this->input->post('lehreinheit_id')); + + $lehreinheiten = $this->getDataOrTerminateWithError($result); + + if (!$lehreinheiten) { + $this->terminateWithValidationErrors([ + 'lehreinheit_id' => $this->p->t('ui', 'error_fieldNotFound', [ + 'field' => $this->p->t('lehre', 'lehreinheit') + ]) + ]); + } + $lehreinheit = current($lehreinheiten); + $studiensemester_kurzbz = $lehreinheit->studiensemester_kurzbz; + $lehrveranstaltung_id = $lehreinheit->lehrveranstaltung_id; + + //check if existing zeugnisnote + $result = $this->ZeugnisnoteModel->loadWhere(array( + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'student_uid' => $this->input->post('student_uid'), + 'studiensemester_kurzbz' => $studiensemester_kurzbz + )); + + $zeugnisnoten = $this->getDataOrTerminateWithError($result); + + if (!$zeugnisnoten) + { + //insert zeugnisnote, if not existing + $result = $this->ZeugnisnoteModel->insert(array( + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'student_uid' => $this->input->post('student_uid'), + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'note' => $this->input->post('note'), + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $this->input->post('datum'), + 'insertamum' => date('c'), + 'insertvon' => $authUID, + 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null + )); + + $this->getDataOrTerminateWithError($result); + + $this->PruefungModel->db->trans_complete(); + $this->terminateWithSuccess(); + } + + $note = current($zeugnisnoten); + $uebernahmedatum = new DateTime($note->uebernahmedatum); + $benotungsdatum = new DateTime($note->benotungsdatum); + $pruefungsdatum = new DateTime($this->input->post('datum')); + + $checkDate = $note->uebernahmedatum === '' || $benotungsdatum > $uebernahmedatum + ? $benotungsdatum + : $uebernahmedatum; + + if ($checkDate > $pruefungsdatum && $this->input->post('note') !== $note->note) + { + $this->PruefungModel->db->trans_complete(); + $this->terminateWithSuccess($this->p->t('exam', 'hinweis_changeAfterExamDate')); + } + + //update zeugnisnote, if existing and valid datum + $result = $this->ZeugnisnoteModel->update([ + 'lehrveranstaltung_id' => $lehrveranstaltung_id, + 'student_uid' => $this->input->post('student_uid'), + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ], [ + 'note' => $this->input->post('note'), + 'uebernahmedatum' => date('c'), + 'benotungsdatum' => $this->input->post('datum'), + 'updateamum' => date('c'), + 'updatevon' => $authUID, + 'punkte' => $this->input->post('punkte') ? str_replace(',', '.', $this->input->post('punkte')) : null + ]); + + $this->PruefungModel->db->trans_complete(); + $this->terminateWithSuccess(); + } } diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php index 01e611657..385935d27 100644 --- a/application/views/Studentenverwaltung.php +++ b/application/views/Studentenverwaltung.php @@ -22,7 +22,8 @@ 'public/css/components/function.css' ], 'customJSs' => [ - 'vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js' + 'vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js', + 'vendor/moment/luxonjs/luxon.min.js' #'vendor/npm-asset/primevue/tree/tree.min.js', #'vendor/npm-asset/primevue/toast/toast.min.js' ], diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js index d3ca1a25e..4d0996b6b 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js @@ -217,9 +217,10 @@ export default { }, columns, height: '100%', + layout: 'fitDataStretchFrozen', selectable: 1, selectableRangeMode: 'click', - persistenceID: 'stv-details-noten-zeugnis-2025111801', + persistenceID: 'stv-details-noten-zeugnis-2025112401', persistence:{ columns: ["width", "visible", "frozen"] } diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Pruefung/Pruefunglist.js b/public/js/components/Stv/Studentenverwaltung/Details/Pruefung/Pruefunglist.js index c0c3fd448..62cd47547 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Pruefung/Pruefunglist.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Pruefung/Pruefunglist.js @@ -46,8 +46,6 @@ export default{ {title: "Punkte", field: "punkte", visible: false}, { title: 'Aktionen', field: 'actions', - minWidth: 150, - maxWidth: 150, formatter: (cell, formatterParams, onRendered) => { let container = document.createElement('div'); container.className = "d-flex gap-2"; @@ -93,7 +91,7 @@ export default{ layoutColumnsOnNewData: false, height: 'auto', index: 'pruefung_id', - persistenceID: 'stv-details-pruefung-list' + persistenceID: 'stv-details-pruefung-list-2025112402' }, tabulatorEvents: [ { @@ -148,7 +146,6 @@ export default{ listMas: [], listMarks: [], zeugnisData: [], - checkData:[], filter: false, statusNew: true, isStartDropDown: false, @@ -181,7 +178,7 @@ export default{ this.pruefungData.student_uid = this.uid; this.pruefungData.note = 9; - this.pruefungData.datum = new Date(); + this.pruefungData.datum = luxon.DateTime.now().setZone(FHC_JS_DATA_STORAGE_OBJECT.timezone).toISODate(); this.pruefungData.pruefungstyp_kurzbz = null; if(lv_id){ this.pruefungData.lehrveranstaltung_id = lv_id; @@ -193,7 +190,7 @@ export default{ this.isStartDropDown = false; this.loadPruefung(pruefung_id).then(() => { this.pruefungData.note = 9; - this.pruefungData.datum = new Date(); + this.pruefungData.datum = luxon.DateTime.now().setZone(FHC_JS_DATA_STORAGE_OBJECT.timezone).toISODate(); this.pruefungData.pruefungstyp_kurzbz = null; this.pruefungData.anmerkung = null; this.prepareDropdowns(); @@ -242,12 +239,13 @@ export default{ }); }, updatePruefung(pruefung_id){ - this.checkChangeAfterExamDate(); return this.$refs.examData .call(ApiStvExam.updatePruefung(pruefung_id, this.pruefungData)) .then(response => { - this.checkData = response.data; - this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); + if (response.data) + this.$fhcAlert.alertDefault('info', 'Info', response.data, true); + else + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave')); this.hideModal('pruefungModal'); this.resetModal(); }).catch(this.$fhcAlert.handleSystemError) @@ -265,27 +263,6 @@ export default{ else this.showHint = false; }, - checkChangeAfterExamDate() { - const data = { - student_uid: this.pruefungData.student_uid, - studiensemester_kurzbz: this.pruefungData.studiensemester_kurzbz, - lehrveranstaltung_id: this.pruefungData.lehrveranstaltung_id - }; - return this.$api - .call(ApiStvExam.checkZeugnisnoteLv(data)) - .then(result => { - this.zeugnisData = result.data; - let checkDate = this.zeugnisData[0].uebernahmedatum === '' || - this.zeugnisData[0].benotungsdatum > this.zeugnisData[0].uebernahmedatum - ? this.zeugnisData[0].benotungsdatum - : this.zeugnisData[0].uebernahmedatum; - if (checkDate >= this.pruefungData.datum - && this.pruefungData.note !== this.zeugnisData[0].note) { - this.$fhcAlert.alertInfo(this.$p.t('exam', 'hinweis_changeAfterExamDate')); - } - }) - .catch(this.$fhcAlert.handleSystemError); - }, deletePruefung(pruefung_id) { return this.$api .call(ApiStvExam.deletePruefung(pruefung_id)) @@ -533,6 +510,7 @@ export default{ container-class="mb-3" type="DatePicker" v-model="pruefungData.datum" + model-type="yyyy-MM-dd" name="datum" :label="$p.t('global/datum')" auto-apply