From 1e68eb0b9005a0ec00d03ac96f159a5b9485ff4b Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Thu, 21 Aug 2025 13:35:38 +0200 Subject: [PATCH] =?UTF-8?q?berechtigungspr=C3=BCfung=20'lehre/benotungstoo?= =?UTF-8?q?l:rw'=20in=20Noten=20Controller;=20API=20Method=20documentation?= =?UTF-8?q?;=20removed=20addMeta=20statements;=20removed=20Tabulator=20Eve?= =?UTF-8?q?nt=20logging;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/api/frontend/v1/Noten.php | 125 ++++++---- .../Cis/Benotungstool/Benotungstool.js | 7 +- system/checksystem.php | 1 + system/phrasesupdate.php | 222 +++++++++++++++++- 4 files changed, 312 insertions(+), 43 deletions(-) diff --git a/application/controllers/api/frontend/v1/Noten.php b/application/controllers/api/frontend/v1/Noten.php index 261bf612b..488288875 100644 --- a/application/controllers/api/frontend/v1/Noten.php +++ b/application/controllers/api/frontend/v1/Noten.php @@ -29,15 +29,15 @@ class Noten extends FHCAPI_Controller public function __construct() { parent::__construct([ - 'getStudentenNoten' => self::PERM_LOGGED, // todo: berechtigung - 'getNoten' => self::PERM_LOGGED, - 'saveStudentenNoten' => self::PERM_LOGGED, // todo: berechtigungen! - 'getNotenvorschlagStudent' => self::PERM_LOGGED, - 'saveNotenvorschlag' => self::PERM_LOGGED, - 'saveStudentPruefung' => self::PERM_LOGGED, - 'createPruefungen' => self::PERM_LOGGED, - 'saveNotenvorschlagBulk' => self::PERM_LOGGED, - 'savePruefungenBulk' => self::PERM_LOGGED + 'getStudentenNoten' => array('lehre/benotungstool:rw'), + 'getNoten' => array('lehre/benotungstool:rw'), + 'saveStudentenNoten' => array('lehre/benotungstool:rw'), + 'getNotenvorschlagStudent' => array('lehre/benotungstool:rw'), + 'saveNotenvorschlag' => array('lehre/benotungstool:rw'), + 'saveStudentPruefung' => array('lehre/benotungstool:rw'), + 'createPruefungen' => array('lehre/benotungstool:rw'), + 'saveNotenvorschlagBulk' => array('lehre/benotungstool:rw'), + 'savePruefungenBulk' => array('lehre/benotungstool:rw') ]); $this->load->library('AuthLib', null, 'AuthLib'); @@ -63,7 +63,16 @@ class Noten extends FHCAPI_Controller $this->load->helper('hlp_sancho_helper'); } - + + + /** + * GET METHOD + * expects 'lv_id', 'sem_kurzbz' + * returns List of all Students of given lehrveranstaltung and semester and fetches their grades. + * Loads LvGesamtnote aswell as Teilnoten from externalSources via getExternalGrades Event. + * Calculates the Notenvorschlag for every student based on averaging their Teilnoten. + * Finally also fetches all Prüfungen for every student which are linked to lva and semester. + */ public function getStudentenNoten() { $lv_id = $this->input->get("lv_id",TRUE); $sem_kurzbz = $this->input->get("sem_kurzbz",TRUE); @@ -71,13 +80,10 @@ class Noten extends FHCAPI_Controller if (!isset($lv_id) || isEmptyString($lv_id) || !isset($sem_kurzbz) || isEmptyString($sem_kurzbz)) $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - // todo: check various other berechtigungen if its mitarbeiter/lektor/zugeteilterLektor? + // get studenten for lva & sem with zeugnisnote if available $studenten = $this->LehrveranstaltungModel->getStudentsByLv($sem_kurzbz, $lv_id); $studentenData = $this->getDataOrTerminateWithError($studenten); -// $studentenData = getData($studenten); - $this->addMeta('$studentenData', $studentenData); $func = function ($value) { return $value->uid; @@ -85,15 +91,11 @@ class Noten extends FHCAPI_Controller $grades = array(); $student_uids = array_map($func, $studentenData); - - $res = $this->StudentModel->load(['be21b081']); - $this->addMeta('be21b081', $res); foreach($student_uids as $uid) { $grades[$uid]['grades'] = []; $res = $this->StudentModel->load([$uid]); - $this->addMeta($uid, $res); if(!isError($res) && hasData($res)) $student = getData($res)[0]; $prestudent_id = $student->prestudent_id; @@ -112,7 +114,7 @@ class Noten extends FHCAPI_Controller $grades[$uid]['mobility'] = $eintrag; $result = $this->LvgesamtnoteModel->getLvGesamtNoten($lv_id, $uid, $sem_kurzbz); - $this->addMeta('getLvGesamtNoten', $result); + if(!isError($result) && hasData($result)) { $lvgesamtnote = getData($result)[0]; $grades[$uid]['note_lv'] = $lvgesamtnote->note; @@ -139,9 +141,8 @@ class Noten extends FHCAPI_Controller 'stsem' => $sem_kurzbz ] ); - $this->addMeta('$grades', $grades); - // calculate notenvorschläge from teilnoten, TODO: seperate function + own endpoint + // calculate notenvorschläge from teilnoten foreach($studentenData as $student) { $g = $grades[$student->uid]['grades']; $note_lv = $grades[$student->uid]['note_lv']; @@ -208,11 +209,14 @@ class Noten extends FHCAPI_Controller // get all prüfungen with noten held in that semester in that lva $pruefungen = $this->LePruefungModel->getPruefungenByLvStudiensemester($lv_id, $sem_kurzbz); $pruefungenData = getData($pruefungen); -// $pruefungenData = $this->getDataOrTerminateWithError($pruefungen); - $this->addMeta('$pruefungenData', $pruefungenData); + $this->terminateWithSuccess(array($studentenData, $pruefungenData, DOMAIN, $grades)); } + /** + * GET METHOD + * returns List of all available & active NotenOptions + */ public function getNoten() { $this->load->model('education/Note_model', 'NoteModel'); @@ -220,7 +224,17 @@ class Noten extends FHCAPI_Controller $noten = $this->getDataOrTerminateWithError($result); $this->terminateWithSuccess($noten); } - + + /** + * POST METHOD + * expects 'lv_id', 'sem_kurzbz', 'password', 'noten' + * Notenfreigabe method which checks the users password as a security measure. + * Tries to load Lehrveranstaltung, Studiengang and Person via Model in order to validate the coherency of input parameters + * lv_id & sem_kurzbz in relation to the noten array delivered. + * Updates the LvGesamtnote note, aswell as freigabedatum, which is key in the logic of the freigegeben/offen/changed notenStatus + * Along this process builds a html table to be placed in a confirmation email (uid only and full variant depending on config) + * which is being sent to the Lektor, aswell as the assigned Assistenz. + */ public function saveStudentenNoten() { $result = $this->getPostJSON(); @@ -238,8 +252,6 @@ class Noten extends FHCAPI_Controller $ret = []; - // TODO: also do something similar when updating/creating a pruefung! - $res = $this->LehrveranstaltungModel->load($lv_id); if(isError($res) || !hasData($res)) { $this->terminateWithError($this->p->t('benotungstool', 'noValidLvFoundForId', [$lv_id])); @@ -295,7 +307,7 @@ class Noten extends FHCAPI_Controller if (!isError($resultLVGes) && hasData($resultLVGes)) { $lvgesamtnote = getData($resultLVGes)[0]; - $this->addMeta($note->uid, $lvgesamtnote); + if ($lvgesamtnote->benotungsdatum > $lvgesamtnote->freigabedatum) { @@ -346,6 +358,7 @@ class Noten extends FHCAPI_Controller $this->terminateWithSuccess($ret); } + private function sendEmail($lektorFullName, $lvaFullName, $notenCount, $emailAdressen, $studlist, $betreff) { $emailAdressen[] = getAuthUID() . "@" . DOMAIN; // also send mail to lektors own adress @@ -373,12 +386,26 @@ class Noten extends FHCAPI_Controller } + /** + * GET METHOD + * should return Notenvorschlag for single Students, not yet implemented since it is not needed anywhere right now, + * but could be useful later on. + */ public function getNotenvorschlagStudent() { // TODO: Notenvorschlag laden allgemeiner Endpunkt, der im Backend mit Logik (z.B. Moodle) angepasst werden kann. $this->terminateWithSuccess(); } - + + /** + * POST METHOD + * expects 'datum', 'lva_id', 'student_uid', 'note' + * Inserts or updates a pruefung for lva & student_uid at given datum (YYYY-MM-DD). When creating a new + * Pruefung, sets the provided (Prüfungs-) Note. + * Updates the LvGesamtnote of student. + * Can return 1 or 2 Prüfungen, since the original grade before the first prüfung is being saved as "Termin1" when + * a "Termin2" is being created. + */ public function saveStudentPruefung() { // einzelne pruefung speichern $result = $this->getPostJSON(); @@ -489,9 +516,7 @@ class Noten extends FHCAPI_Controller } } - - $this->addMeta('$pruefungenChanged', $pruefungenChanged); - $this->addMeta('$lvgesamtnote', $lvgesamtnote); + $savedPruefung = $pruefungenChanged['savedPruefung'] ?? null; $extraPruefung = $pruefungenChanged['extraPruefung'] ?? null; @@ -500,7 +525,10 @@ class Noten extends FHCAPI_Controller $this->terminateWithSuccess(array($savedPruefungData, $lvgesamtnote, $extraPruefungData)); } - + + /** + * private helper method to update/insert pruefungstermine + */ private function savePruefungstermin($typ, $student_uid, $lva_id, $stsem, $lehreinheit_id, $note, $punkte, $datum) { $jetzt = date("Y-m-d H:i:s"); @@ -525,8 +553,6 @@ class Noten extends FHCAPI_Controller $resultLV = $this->LvgesamtnoteModel->getLvGesamtNoten($lva_id, $student_uid, $stsem); - $this->addMeta('$resultLV', $resultLV); - // update Termin1 note if (hasData($resultLV)) { @@ -541,8 +567,6 @@ class Noten extends FHCAPI_Controller $pr_punkte = null; $benotungsdatum = $jetzt; } - - $this->addMeta('$pr_punkte', $pr_punkte); $id = $this->LePruefungModel->insert( array( @@ -562,7 +586,6 @@ class Noten extends FHCAPI_Controller ) ); if($id) { - $this->addMeta('idTermin1', $id); $res = $this->LePruefungModel->load($id->retval); if(hasData($res)) $pruefungenChanged['extraPruefung'] = getData($res); } @@ -675,6 +698,12 @@ class Noten extends FHCAPI_Controller return $pruefungenChanged; } + /** + * POST METHOD + * expects 'sem_kurzbz', 'lv_id', 'student_uid', 'note' + * Method that sets lv_note of student in lva and semester from provided Points/Grade Selection. + * Updates the note & benotungsdatum, which is key in the noten state offen/freigegeben/changed + */ public function saveNotenvorschlag() { $result = $this->getPostJSON(); @@ -689,7 +718,7 @@ class Noten extends FHCAPI_Controller $note = $result->note; $result = $this->LvgesamtnoteModel->getLvGesamtNoten($lv_id, $student_uid, $sem_kurzbz); - $this->addMeta('getLvGesamtNoten', $result); + if(!isError($result) && hasData($result)) { $lvgesamtnote = getData($result)[0]; @@ -736,6 +765,11 @@ class Noten extends FHCAPI_Controller $this->terminateWithSuccess(array($lvgesamtnote)); } + /** + * POST METHOD + * expects 'sem_kurzbz', 'lv_id', 'noten' + * Bulk variant of saveNotenvorschlag, used when importing grades from csv. + */ public function saveNotenvorschlagBulk() { $result = $this->getPostJSON(); @@ -754,7 +788,7 @@ class Noten extends FHCAPI_Controller { $result = $this->LvgesamtnoteModel->getLvGesamtNoten($lv_id, $note->uid, $sem_kurzbz); - $this->addMeta('getLvGesamtNoten', $result); + if(!isError($result) && hasData($result)) { $lvgesamtnote = getData($result)[0]; @@ -803,7 +837,13 @@ class Noten extends FHCAPI_Controller $this->terminateWithSuccess($retLvNoten); } - + + /** + * POST METHOD + * expects 'uids', 'datum' + * Bulk variant of saveStudentPruefung, used when creating a new Prüfung for several students. Always sets note to + * "noch nicht eingetragen" for the created Prüfung. + */ public function createPruefungen() { $result = $this->getPostJSON(); @@ -832,6 +872,11 @@ class Noten extends FHCAPI_Controller $this->terminateWithSuccess($ret); } + /** + * POST METHOD + * expects 'lv_id', 'sem_kurzbz', 'pruefungen' + * Bulk variant of saveStudentPruefung, used when importing pruefungsdata from csv with available noten. + */ public function savePruefungenBulk() { $result = $this->getPostJSON(); diff --git a/public/js/components/Cis/Benotungstool/Benotungstool.js b/public/js/components/Cis/Benotungstool/Benotungstool.js index a873e2613..e20f8166e 100644 --- a/public/js/components/Cis/Benotungstool/Benotungstool.js +++ b/public/js/components/Cis/Benotungstool/Benotungstool.js @@ -439,7 +439,6 @@ export const Benotungstool = { return true; // student can be selected to add pruefung }, rowFormatter: this.fixTabulatorSelectionFormatter, - debugEventsExternal:true, columns: [ { formatter: function (cell, formatterParams, onRendered) { @@ -1063,7 +1062,9 @@ export const Benotungstool = { this.$api.call(ApiNoten.getStudentenNoten(lv_id, sem_kurzbz)) .then(res => { if(res?.data) this.setupData(res.data) - }) + }).finally(()=> { + this.loading = false + }) }, handleUuidDefined(uuid) { this.tabulatorUuid = uuid @@ -1106,6 +1107,8 @@ export const Benotungstool = { this.notenOptionsLehre = res.data.filter(n => n.lehre === true) this.notenTableOptions = this.getNotenTableOptions() this.tabulatorCanBeBuilt = true // because promises would be more work and not much better here + }).catch(e => { + this.loading = false }) }, diff --git a/system/checksystem.php b/system/checksystem.php index 4af8bc56d..1f7968282 100644 --- a/system/checksystem.php +++ b/system/checksystem.php @@ -150,6 +150,7 @@ $berechtigungen = array( array('lehre','Berechtigung fuer CIS-Seite'), array('lehre/abgabetool','Projektabgabetool, Studentenansicht'), array('lehre/abgabetool:download','Download von Projektarbeitsabgaben'), + array('lehre/benotungstool','Cis4 Gesamtnoteneingabe'), array('lehre/freifach','Freifachverwaltung'), array('lehre/lehrfach','Lehrfachverwaltung'), array('lehre/lehrfach:begrenzt','Lehrfachverwaltung - nur aktiv aenderbar, nur aktive LF werden angezeigt'), diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index f78b8622c..0263cf992 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -47678,7 +47678,7 @@ and represent the current state of research on the topic. The prescribed citatio ), array( 'sprache' => 'English', - 'text' => 'negative', + 'text' => 'Negative', 'description' => '', 'insertvon' => 'system' ) @@ -48284,6 +48284,226 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'notenImportSuccessAlert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Noten erfolgreich importiert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Grades successfully imported', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'pruefungImportSuccessAlert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfungen erfolgreich importiert und gespeichert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Exams successfully imported and saved', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'changePruefungButtonText', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ändern', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Change', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'addPruefungButtonText', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Hinzufügen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Create', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'pruefungSaveForUid', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfung für Student {0} gespeichert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Exam for student {0} has been saved', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'pruefungAngelegtAn', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfung an {0} angelegt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Exam on {0} has been created', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'noValidLvFoundForId', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Keine gültige Lehrveranstaltung gefunden für ID: {0}', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'No valid course found for ID: {0}', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'noValidStudiengangFoundForId', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Kein gültiger Studiengang gefunden für ID: {0}', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'No valid study program found for ID: {0}', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'noValidPersonFoundForId', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Keine gültige Person gefunden für ID: {0}', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'No Valid Person found for ID: {0}', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'wrongPruefungType', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Prüfung für Student {0} konnte nicht bearbeitet werden, {1} ist keine gültiger Prüfungstyp.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Exam for Student {0} was not saved, {1} is not a valid exam type.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'benotungstool', + 'phrase' => 'notenfreigabe', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Notenfreigabe', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Grades Approval', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), // CIS4 GESAMTNOTENEINGABE ENDE ------------------------------------------------------------------------------------