diff --git a/application/controllers/Cis/Benotungstool.php b/application/controllers/Cis/Benotungstool.php index 30d4ed0c1..81379b587 100644 --- a/application/controllers/Cis/Benotungstool.php +++ b/application/controllers/Cis/Benotungstool.php @@ -15,6 +15,8 @@ class Benotungstool extends Auth_Controller parent::__construct([ 'index' => self::PERM_LOGGED ]); + + $this->_ci =& get_instance(); } // ----------------------------------------------------------------------------------------------------------------- @@ -26,8 +28,12 @@ class Benotungstool extends Auth_Controller public function index() { + + // TODO: check if related CIS config is also loaded when being routed in Cis4 by vuerouter + // TODO: check if new benotungstool should be configurable the exact same way? $viewData = array( 'uid'=>getAuthUID(), + 'CIS_GESAMTNOTE_UEBERSCHREIBEN' => CIS_GESAMTNOTE_UEBERSCHREIBEN ); $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Benotungstool']); diff --git a/application/controllers/api/frontend/v1/Lehre.php b/application/controllers/api/frontend/v1/Lehre.php index 237f97090..5c821296f 100644 --- a/application/controllers/api/frontend/v1/Lehre.php +++ b/application/controllers/api/frontend/v1/Lehre.php @@ -32,7 +32,8 @@ class Lehre extends FHCAPI_Controller 'LV' => self::PERM_LOGGED, 'Pruefungen' => self::PERM_LOGGED, 'getLvViewData' => self::PERM_LOGGED, - 'getZugewieseneLv' => self::PERM_LOGGED + 'getZugewieseneLv' => self::PERM_LOGGED, + 'getLeForLv' => self::PERM_LOGGED ]); // Loads phrases system @@ -129,6 +130,17 @@ class Lehre extends FHCAPI_Controller $this->terminateWithSuccess($data); } + + public function getLeForLv() { + $lv_id = $this->input->get("lv_id",TRUE); + $sem_kurzbz = $this->input->get("sem_kurzbz",TRUE); + + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + +// $this->terminateWithSuccess($this->LehreinheitModel->getLesForLv($lv_id, $sem_kurzbz)); + $this->terminateWithSuccess($this->LehreinheitModel->getAllLehreinheitenForLvaAndMaUid($lv_id, getAuthUID(), $sem_kurzbz)); + } + diff --git a/application/controllers/api/frontend/v1/Noten.php b/application/controllers/api/frontend/v1/Noten.php index 9a5030d82..86c56d5ad 100644 --- a/application/controllers/api/frontend/v1/Noten.php +++ b/application/controllers/api/frontend/v1/Noten.php @@ -31,7 +31,10 @@ class Noten extends FHCAPI_Controller parent::__construct([ 'getStudentenNoten' => self::PERM_LOGGED, // todo: berechtigung 'getNoten' => self::PERM_LOGGED, - 'saveStudentenNoten' => self::PERM_LOGGED // todo: berechtigungen! + 'saveStudentenNoten' => self::PERM_LOGGED, // todo: berechtigungen! + 'getNotenvorschlagStudent' => self::PERM_LOGGED, + 'saveNotenvorschlag' => self::PERM_LOGGED, + 'saveStudentPruefung' => self::PERM_LOGGED ]); $this->load->library('AuthLib', null, 'AuthLib'); @@ -40,9 +43,16 @@ class Noten extends FHCAPI_Controller $this->loadPhrases([ 'global' ]); - + require_once(FHCPATH . 'include/mobilitaet.class.php'); + require_once(FHCPATH . 'include/student.class.php'); + require_once(FHCPATH . 'include/lvgesamtnote.class.php'); + require_once(FHCPATH . 'include/lehrveranstaltung.class.php'); + require_once(FHCPATH . 'include/lehreinheit.class.php'); + require_once(FHCPATH . 'include/studiengang.class.php'); + require_once(FHCPATH . 'include/pruefung.class.php'); + } - + public function getStudentenNoten() { $lv_id = $this->input->get("lv_id",TRUE); $sem_kurzbz = $this->input->get("sem_kurzbz",TRUE); @@ -58,18 +68,44 @@ class Noten extends FHCAPI_Controller // get studenten for lva & sem with zeugnisnote if available $studenten = $this->LehrveranstaltungModel->getStudentsByLv($sem_kurzbz, $lv_id); - $studentenData = $this->getDataOrTerminateWithError($studenten); +// $studentenData = $this->getDataOrTerminateWithError($studenten); + $studentenData = getData($studenten); + $this->addMeta('$studentenData', $studentenData); $func = function ($value) { return $value->uid; }; - + $grades = array(); $student_uids = array_map($func, $studentenData); foreach($student_uids as $uid) { $grades[$uid]['grades'] = []; + + $student = new student(); + $student->load($uid); + $student->result[]= $student; + $prestudent_id = $student->prestudent_id; + + $mobility = new mobilitaet(); + $mobility->loadPrestudent($prestudent_id); + $output = $mobility->result; + $eintrag = ''; + foreach ($output as $k) + { + if(($k->mobilitaetstyp_kurzbz == 'GS') && ($k->studiensemester_kurzbz == $sem_kurzbz)) + $eintrag = ' (d.d.)'; + } + $grades[$uid]['mobility'] = $eintrag; + + if ($lvgesamtnote = new lvgesamtnote($lv_id, $uid, $sem_kurzbz)) + { + $grades[$uid]['note_lv'] = $lvgesamtnote->note; + $grades[$uid]['freigabedatum'] = $lvgesamtnote->freigabedatum; + $grades[$uid]['benotungsdatum'] = $lvgesamtnote->benotungsdatum; + $grades[$uid]['punkte_lv'] = $lvgesamtnote->punkte; + } } - + // send $grades reference to moodle addon Events::trigger( 'moodleGrades', @@ -82,18 +118,81 @@ class Noten extends FHCAPI_Controller 'stsem' => $sem_kurzbz ] ); + $this->addMeta('$grades', $grades); + + // calculate notenvorschläge from teilnoten, TODO: seperate function + own endpoint + foreach($studentenData as $student) { + $g = $grades[$student->uid]['grades']; + $note_lv = $grades[$student->uid]['note_lv']; + + // overwrite any calculation with lv note once available + if(!is_null($note_lv)) { + $student->note_vorschlag = $note_lv; + } else if(count($g) > 0) { + + $notensumme = 0; + $notensumme_gewichtet = 0; + $gewichtsumme = 0; + $punktesumme = 0; + $punktesumme_gewichtet = 0; + $anzahlnoten = 0; + foreach($g as $teilnote) { + if (is_numeric($teilnote['grade']) || (is_null($teilnote['grade']) && is_numeric($teilnote['points']))) + { + $notensumme += $teilnote['grade']; + $punktesumme += $teilnote['points']; + $notensumme_gewichtet += $teilnote['grade'] * $teilnote['weight']; + $punktesumme_gewichtet += $teilnote['points'] * $teilnote['weight']; + $gewichtsumme += $teilnote['weight']; + $anzahlnoten += 1; + } + } + + // calculate grades points from notenschlüssel + if (CIS_GESAMTNOTE_PUNKTE) + { + if (defined('CIS_GESAMTNOTE_GEWICHTUNG') && CIS_GESAMTNOTE_GEWICHTUNG) + { + // Lehreinheitsgewichtung + $punkte_vorschlag = round($punktesumme_gewichtet / $gewichtsumme, 2); + $notenschluessel = new notenschluessel(); + $note_vorschlag = $notenschluessel->getNote($punkte_vorschlag, $lv_id, $sem_kurzbz); + } + else + { + $punkte_vorschlag = round($punktesumme / $anzahlnoten, 2); + $notenschluessel = new notenschluessel(); + $note_vorschlag = $notenschluessel->getNote($punkte_vorschlag, $lv_id, $sem_kurzbz); + } + } + else + { + if (defined('CIS_GESAMTNOTE_GEWICHTUNG') && CIS_GESAMTNOTE_GEWICHTUNG) + { + $note_vorschlag = round($notensumme_gewichtet / $gewichtsumme); + } + else + { + $note_vorschlag = round($notensumme / $anzahlnoten); + } + } + + $student->note_vorschlag = $note_vorschlag; + } + } // get all prüfungen with noten held in that semester in that lva $pruefungen = $this->PruefungModel->getPruefungenByLvStudiensemester($lv_id, $sem_kurzbz); - $pruefungenData = $this->getDataOrTerminateWithError($pruefungen); - + $pruefungenData = getData($pruefungen); +// $pruefungenData = $this->getDataOrTerminateWithError($pruefungen); + $this->addMeta('$pruefungenData', $pruefungenData); $this->terminateWithSuccess(array($studentenData, $pruefungenData, DOMAIN, $grades)); } public function getNoten() { $this->load->model('education/Note_model', 'NoteModel'); - $result = $this->NoteModel->getAll(); + $result = $this->NoteModel->getAllActive(); $noten = $this->getDataOrTerminateWithError($result); $this->terminateWithSuccess($noten); } @@ -101,13 +200,345 @@ class Noten extends FHCAPI_Controller public function saveStudentenNoten() { $result = $this->getPostJSON(); - if(!property_exists($result, 'password')) { + if(!property_exists($result, 'sem_kurzbz') || !property_exists($result, 'lv_id') || + !property_exists($result, 'password') || !property_exists($result, 'noten')) { + $this->terminateWithError($this->p->t('global', 'missingParameters'), 'general'); + } + + if(!$this->AuthLib->checkUserAuthByUsernamePassword(getAuthUID(), $result->password)->retval) { + $this->terminateWithError($this->p->t('global', 'wrongPassword'), 'general'); + } + + $lv_id = $result->lv_id; + $sem_kurzbz = $result->sem_kurzbz; + + $ret = []; + + // TODO: also do something similar when updating/creating a pruefung! + + foreach($result->noten as $note) { + $lvgesamtnote = new lvgesamtnote(); + if ($lvgesamtnote->load($lv_id, $note->uid, $sem_kurzbz)) + { + if ($lvgesamtnote->benotungsdatum > $lvgesamtnote->freigabedatum) + { + $lvgesamtnote->freigabedatum = date("Y-m-d H:i:s"); + $lvgesamtnote->freigabevon_uid = getAuthUID(); + if($lvgesamtnote->save()) { + $ret[] = array('uid' => $note->uid, 'freigabedatum' => $lvgesamtnote->freigabedatum, 'benotungsdatum' => $lvgesamtnote->benotungsdatum); + } + + if (defined('CIS_GESAMTNOTE_FREIGABEMAIL_NOTE') && CIS_GESAMTNOTE_FREIGABEMAIL_NOTE) + { + // TODO: infomail an studiengangsassistenz + // Enthalten sind MatrikelNr., Vorname, Nachname und Note der neuen oder geänderten Einträge. + } + + } + } + + } + + + $this->terminateWithSuccess($ret); + } + + public function getNotenvorschlagStudent() { + // TODO: Notenvorschlag laden allgemeiner Endpunkt, der im Backend mit Logik (z.B. Moodle) angepasst werden kann. + + $this->terminateWithSuccess(); + } + + public function saveStudentPruefung() { // einzelne pruefung speichern + $result = $this->getPostJSON(); + + if(!property_exists($result, 'datum') || !property_exists($result, 'lva_id') || + !property_exists($result, 'student_uid') || !property_exists($result, 'note')) { $this->terminateWithError($this->p->t('global', 'missingParameters'), 'general'); } - // TODO: send & save noten + $student_uid = $result->student_uid; + $note = $result->note; + $punkte = $result->punkte; + $datum = $result->datum; + $lva_id = $result->lva_id; + $lehreinheit_id = $result->lehreinheit_id; - $this.$this->terminateWithSuccess($this->AuthLib->checkUserAuthByUsernamePassword(getAuthUID(), $result->password)); +// $lehreinheit_id_pr = $result->lehreinheit_id_pr; // todo: very rare, refactor? + $stsem = $result->sem_kurzbz; + $typ = $result->typ; + + $jetzt = date("Y-m-d H:i:s"); + + // nachpruefungeintragen.php script calls query on campus.student_lehrveranstaltung to find a + // lehreinheit_id for lva_id -> lehreinheit should be determined prior to that in new benotungstool + // by retrieving it from students row in campus.vw_student_lehrveranstaltung earlier on + +// $lehreinheit_id = getLehreinheit($db, $lvid, $student_uid, $stsem); + $lehreinheit_id = $result->lehreinheit_id; + + $punkte = str_replace(',', '.', $punkte); + + if($punkte!='') + { + // Bei Punkteeingabe wird die Note nochmals geprueft und ggf korrigiert + $notenschluessel = new notenschluessel(); + $note_pruef = $notenschluessel->getNote($punkte, $lva_id, $stsem); + if($note_pruef!=$note) + { + $note = $note_pruef; + $note_dirty=true; + } + } + + if($note=='') + $note = 9; + + $old_note = $note; + + //Laden der Lehrveranstaltung + $lv_obj = new lehrveranstaltung(); + if(!$lv_obj->load($lva_id)) + die($lv_obj->errormsg); + + //Studiengang laden + $stg_obj = new studiengang($lv_obj->studiengang_kz); + +// $response = savePruefung($lvid, $student_uid, $stsem, $lehreinheit_id, $datum, $typ, $note, $punkte); + $savedPruefung = null; + $extraPruefung = null; + if($typ == "Termin2") { + + $pr = new Pruefung(); + + // Wenn eine Pruefung angelegt wird, wird zuerst eine Pruefung mit 1. Termin angelegt + // und dort die Zeugnisnote gespeichert + if($pr->getPruefungen($student_uid, "Termin1", $lva_id, $stsem)) + { + if ($pr->result) + { + // TODO: is this filler if branch really necessary? + $termin1 = 1; + } + else + { + $lvnote = new lvgesamtnote(); + // update Termin1 note + if ($lvnote->load($lva_id, $student_uid, $stsem)) + { + $pr_note = $lvnote->note; + $pr_punkte = $lvnote->punkte; + $benotungsdatum = $lvnote->benotungsdatum; + } + else // set Termin1 note to "noch nicht eingetragen" + { + $pr_note = 9; + $pr_punkte = ''; + $benotungsdatum = $jetzt; + } + + $pr_1 = new Pruefung(); + $pr_1->lehreinheit_id = $lehreinheit_id; + $pr_1->student_uid = $student_uid; + $pr_1->mitarbeiter_uid = getAuthUID(); + $pr_1->note = $pr_note; + $pr_1->punkte = $pr_punkte; + $pr_1->pruefungstyp_kurzbz = "Termin1"; + $pr_1->datum = $benotungsdatum; + $pr_1->anmerkung = ""; + $pr_1->insertamum = $jetzt; + $pr_1->insertvon = getAuthUID(); + $pr_1->updateamum = null; + $pr_1->updatevon = null; + $pr_1->ext_id = null; + $pr_1->new = true; + $pr_1->save(); + $extraPruefung = $pr_1; //"neu T1"; + } + + $prTermin2 = new Pruefung(); + $pr_2 = new Pruefung(); + + // Die Pruefung wird als Termin2 eingetragen + if ($prTermin2->getPruefungen($student_uid, 'Termin2', $lva_id, $stsem)) + { + if ($prTermin2->result) + { + $pr_2->load($prTermin2->result[0]->pruefung_id); + $pr_2->new = null; + $pr_2->updateamum = $jetzt; + $pr_2->updatevon = getAuthUID(); + $old_note = $pr_2->note; + $pr_2->note = $note; + $pr_2->punkte = $punkte; + $pr_2->datum = $datum; + $pr_2->anmerkung = ""; + $savedPruefung = $pr_2;//"update T2"; + } + else + { + $pr_2->lehreinheit_id = $lehreinheit_id; + $pr_2->student_uid = $student_uid; + $pr_2->mitarbeiter_uid = getAuthUID(); + $pr_2->note = $note; + $pr_2->punkte = $punkte; + $pr_2->pruefungstyp_kurzbz = $typ; + $pr_2->datum = $datum; + $pr_2->anmerkung = ""; + $pr_2->insertamum = $jetzt; + $pr_2->insertvon = getAuthUID(); + $pr_2->updateamum = null; + $pr_2->updatevon = null; + $pr_2->ext_id = null; + $pr_2->new = true; + $old_note = -1; + $savedPruefung = $pr_2;//"new T2"; + } + $pr_2->save(); + } + } + + } else if($typ == "Termin3") { + + $prTermin3 = new Pruefung(); + $pr_3 = new Pruefung(); + + if ($prTermin3->getPruefungen($student_uid, 'Termin3', $lva_id, $stsem)) + { + if ($prTermin3->result) + { + $pr_3->load($prTermin3->result[0]->pruefung_id); + $pr_3->new = null; + $pr_3->updateamum = $jetzt; + $pr_3->updatevon = getAuthUID(); + $old_note = $pr_3->note; + $pr_3->note = $note; + $pr_3->punkte = $punkte; + $pr_3->datum = $datum; + $pr_3->anmerkung = ""; + $savedPruefung = $pr_3; //"update T3"; + } + else + { + $pr_3->lehreinheit_id = $lehreinheit_id; + $pr_3->student_uid = $student_uid; + $pr_3->mitarbeiter_uid = getAuthUID(); + $pr_3->note = $note; + $pr_3->punkte = $punkte; + $pr_3->pruefungstyp_kurzbz = $typ; + $pr_3->datum = $datum; + $pr_3->anmerkung = ""; + $pr_3->insertamum = $jetzt; + $pr_3->insertvon = getAuthUID(); + $pr_3->updateamum = null; + $pr_3->updatevon = null; + $pr_3->ext_id = null; + $pr_3->new = true; + $old_note = -1; + $savedPruefung = $pr_3; //"new T3"; + } + $pr_3->save(); + } + } else { + $this->terminateWithError("typ is not termin2 or termin3", 'general'); + } + + + + //Gesamtnote updaten + $lvgesamtnote = new lvgesamtnote(); + if (!$lvgesamtnote->load($lva_id, $student_uid, $stsem)) + { + $lvgesamtnote->student_uid = $student_uid; + $lvgesamtnote->lehrveranstaltung_id = $lva_id; + $lvgesamtnote->studiensemester_kurzbz = $stsem; + $lvgesamtnote->note = $note; + $lvgesamtnote->punkte = $punkte; + $lvgesamtnote->mitarbeiter_uid = getAuthUID(); + $lvgesamtnote->benotungsdatum = $jetzt; + $lvgesamtnote->freigabedatum = null; + $lvgesamtnote->freigabevon_uid = null; + $lvgesamtnote->bemerkung = null; + $lvgesamtnote->updateamum = null; + $lvgesamtnote->updatevon = null; + $lvgesamtnote->insertamum = $jetzt; + $lvgesamtnote->insertvon = getAuthUID(); + $new = true; +// $response = "neu"; + } + else + { + $lvgesamtnote->note = $note; + $lvgesamtnote->punkte = $punkte; + $lvgesamtnote->benotungsdatum = $jetzt; + $lvgesamtnote->updateamum = $jetzt; + $lvgesamtnote->updatevon = getAuthUID(); + $new = false; +// if ($lvgesamtnote->freigabedatum) +// $response = "update_f"; +// else +// $response = "update"; + } + + $saved = $lvgesamtnote->save($new); + + $this->terminateWithSuccess(array($savedPruefung, $lvgesamtnote, $saved, $extraPruefung)); + } + + public function saveNotenvorschlag() { + $result = $this->getPostJSON(); + + if(!property_exists($result, 'lv_id') || !property_exists($result, 'sem_kurzbz') || + !property_exists($result, 'student_uid') || !property_exists($result, 'note')) { + $this->terminateWithError($this->p->t('global', 'missingParameters'), 'general'); + } + + $lv_id = $result->lv_id; + $student_uid = $result->student_uid; + $sem_kurzbz = $result->sem_kurzbz; + $note = $result->note; + + $lvgesamtnote = new lvgesamtnote(); + if (!$lvgesamtnote->load($lv_id, $student_uid, $sem_kurzbz)) + { + $lvgesamtnote->student_uid = $student_uid; + $lvgesamtnote->lehrveranstaltung_id = $lv_id; + $lvgesamtnote->studiensemester_kurzbz = $sem_kurzbz; + $lvgesamtnote->note = trim($note); + $lvgesamtnote->mitarbeiter_uid = getAuthUID(); + $lvgesamtnote->benotungsdatum = date("Y-m-d H:i:s"); + $lvgesamtnote->freigabedatum = null; + $lvgesamtnote->freigabevon_uid = null; + $lvgesamtnote->bemerkung = null; + $lvgesamtnote->updateamum = null; + $lvgesamtnote->updatevon = null; + $lvgesamtnote->insertamum = date("Y-m-d H:i:s"); + $lvgesamtnote->insertvon = getAuthUID(); + $lvgesamtnote->punkte =// TODO: deprecated? + $new = true; + $response = "neu"; + } + else + { + $lvgesamtnote->note = trim($note); + $lvgesamtnote->punkte = null; // TODO: deprecated? + $lvgesamtnote->benotungsdatum = date("Y-m-d H:i:s"); + $lvgesamtnote->updateamum = date("Y-m-d H:i:s"); + $lvgesamtnote->updatevon = getAuthUID(); + $new = false; + if ($lvgesamtnote->freigabedatum) + $response = "update_f"; + else + $response = "update"; + } + if (!$lvgesamtnote->save($new)) + $ret = $lvgesamtnote->errormsg; + else + $ret = $response; + + $lvgesamtnote->load($lv_id, $student_uid, $sem_kurzbz); + + $this->terminateWithSuccess(array($ret, $lvgesamtnote)); } } diff --git a/application/models/education/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php index d4bc7a22f..15024c023 100644 --- a/application/models/education/Lehreinheit_model.php +++ b/application/models/education/Lehreinheit_model.php @@ -303,4 +303,26 @@ EOSQL; return $this->execQuery($query, $params); } + + public function getAllLehreinheitenForLvaAndMaUid($lva_id, $ma_uid, $sem_kurzbz) + { + $query = "SELECT DISTINCT tbl_lehreinheitmitarbeiter.lehreinheit_id, tbl_lehreinheit.lehrveranstaltung_id, tbl_lehreinheit.lehrform_kurzbz, + tbl_lehreinheitmitarbeiter.mitarbeiter_uid, + tbl_lehreinheitgruppe.semester, + tbl_lehreinheitgruppe.verband, + tbl_lehreinheitgruppe.gruppe, + tbl_lehreinheitgruppe.gruppe_kurzbz, + tbl_lehrveranstaltung.kurzbz, + tbl_studiengang.kurzbzlang, + (SELECT COUNT(DISTINCT datum) FROM campus.vw_stundenplan WHERE lehreinheit_id = lehre.tbl_lehreinheit.lehreinheit_id) as termincount, + (SELECT COUNT(*) FROM campus.vw_student_lehrveranstaltung WHERE lehreinheit_id = lehre.tbl_lehreinheit.lehreinheit_id) as studentcount + FROM lehre.tbl_lehreinheit JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id) + JOIN lehre.tbl_lehreinheitgruppe USING(lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + JOIN public.tbl_studiengang ON (tbl_lehreinheitgruppe.studiengang_kz = tbl_studiengang.studiengang_kz) + WHERE lehrveranstaltung_id = ? AND studiensemester_kurzbz = ? AND mitarbeiter_uid = ? + ORDER BY tbl_lehreinheitgruppe.gruppe_kurzbz"; + + return $this->execQuery($query, [$lva_id, $sem_kurzbz, $ma_uid]); + } } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 883c6d9ca..6fa38b36c 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -316,7 +316,8 @@ class Lehrveranstaltung_model extends DB_Model (SELECT status_kurzbz FROM public.tbl_prestudentstatus WHERE prestudent_id=tbl_student.prestudent_id ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1) as status, tbl_bisio.bisio_id, tbl_bisio.von, tbl_bisio.bis, tbl_student.studiengang_kz AS stg_kz_student, tbl_zeugnisnote.note, tbl_mitarbeiter.mitarbeiter_uid, tbl_person.matr_nr, tbl_benutzer.uid, - UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung + UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung, + campus.vw_student_lehrveranstaltung.lehreinheit_id FROM campus.vw_student_lehrveranstaltung @@ -343,7 +344,7 @@ class Lehrveranstaltung_model extends DB_Model $query .= " ORDER BY nachname, vorname, person_id, tbl_bisio.bis DESC"; - + return $this->execQuery($query, array($studiensemester_kurzbz, $lehrveranstaltung_id)); } diff --git a/application/models/education/Note_model.php b/application/models/education/Note_model.php index fe601b1f9..f5ffa2cd3 100644 --- a/application/models/education/Note_model.php +++ b/application/models/education/Note_model.php @@ -12,9 +12,10 @@ class Note_model extends DB_Model $this->pk = 'note'; } - public function getAll() { + public function getAllActive() { $qry ="SELECT * - FROM lehre.tbl_note"; + FROM lehre.tbl_note + WHERE aktiv = true"; return $this->execReadOnlyQuery($qry); } diff --git a/application/views/CisRouterView/CisRouterView.php b/application/views/CisRouterView/CisRouterView.php index 9d24d9a68..b433ab9bd 100644 --- a/application/views/CisRouterView/CisRouterView.php +++ b/application/views/CisRouterView/CisRouterView.php @@ -9,6 +9,7 @@ $includesArray = array( 'vue3' => true, 'primevue3' => true, 'customCSSs' => array( + 'vendor/vuejs/vuedatepicker_css/main.css', 'public/css/components/verticalsplit.css', 'public/css/components/searchbar/searchbar.css', 'public/css/Fhc.css', diff --git a/public/js/api/factory/lehre.js b/public/js/api/factory/lehre.js index f9306839e..05edd02ca 100644 --- a/public/js/api/factory/lehre.js +++ b/public/js/api/factory/lehre.js @@ -36,24 +36,18 @@ export default { url: `/api/frontend/v1/Lehre/Pruefungen/${lehrveranstaltung_id}` }; }, - getStudentenNoten(lv_id, sem_kurzbz) { - return { - method: 'get', - url: '/api/frontend/v1/Noten/getStudentenNoten', - params: { lv_id, sem_kurzbz } - }; - }, - getNoten(){ - return { - method: 'get', - url: '/api/frontend/v1/Noten/getNoten' - }; - }, getZugewieseneLv(uid, sem_kurzbz){ return { method: 'get', url: '/api/frontend/v1/Lehre/getZugewieseneLv', params: { uid, sem_kurzbz} }; + }, + getLeForLv(lv_id, sem_kurzbz) { + return { + method: 'get', + url: '/api/frontend/v1/Lehre/getLeForLv', + params: { lv_id, sem_kurzbz } + }; } }; \ No newline at end of file diff --git a/public/js/api/factory/noten.js b/public/js/api/factory/noten.js index e0343cb4b..d26a1a884 100644 --- a/public/js/api/factory/noten.js +++ b/public/js/api/factory/noten.js @@ -29,11 +29,25 @@ export default { url: '/api/frontend/v1/Noten/getNoten' }; }, - saveStudentenNoten(password) { + saveStudentenNoten(password, noten, lv_id, sem_kurzbz) { return { method: 'post', url: '/api/frontend/v1/Noten/saveStudentenNoten', - params: { password } + params: { password, noten, lv_id, sem_kurzbz } + }; + }, + saveNotenvorschlag(lv_id, sem_kurzbz, student_uid, note) { + return { + method: 'post', + url: '/api/frontend/v1/Noten/saveNotenvorschlag', + params: { lv_id, sem_kurzbz, student_uid, note } + }; + }, + saveStudentPruefung(student_uid, note, punkte, datum, lva_id, lehreinheit_id, sem_kurzbz, typ){ + return { + method: 'post', + url: '/api/frontend/v1/Noten/saveStudentPruefung', + params: { student_uid, note, punkte, datum, lva_id, lehreinheit_id, sem_kurzbz, typ } }; } }; \ No newline at end of file diff --git a/public/js/components/Cis/Benotungstool/Benotungstool.js b/public/js/components/Cis/Benotungstool/Benotungstool.js index 2f3dfe3be..2075082cb 100644 --- a/public/js/components/Cis/Benotungstool/Benotungstool.js +++ b/public/js/components/Cis/Benotungstool/Benotungstool.js @@ -3,6 +3,7 @@ import ApiLehre from "../../../api/factory/lehre.js"; import ApiNoten from "../../../api/factory/noten.js"; import ApiStudiensemester from "../../../api/factory/studiensemester.js"; import BsModal from '../../Bootstrap/Modal.js'; +import VueDatePicker from '../../vueDatepicker.js.php'; export const Benotungstool = { name: "Benotungstool", @@ -10,7 +11,8 @@ export const Benotungstool = { BsModal, CoreFilterCmpt, Dropdown: primevue.dropdown, - Password: primevue.password + Password: primevue.password, + Datepicker: VueDatePicker }, props: { lv_id: { @@ -32,9 +34,18 @@ export const Benotungstool = { }, data() { return { + selectedLehreinheit: null, + lehreinheiten: null, + tabulatorCanBeBuilt: false, + selectedPruefungNote: null, + selectedPruefungDate: new Date(), // v-model for pruefung edit datepicker + pruefungStudent: null, + pruefung: null, password: '', + changedNotenCounter: 0, tabulatorUuid: Vue.ref(0), domain: '', + teilnoten: null, lv: null, studenten: null, pruefungen: null, @@ -44,78 +55,311 @@ export const Benotungstool = { selectedLehrveranstaltung: null, tableBuiltResolve: null, notenOptions: null, + notenOptionsLehre: null, + notenOptionsPromise: null, tableBuiltPromise: null, - notenTableOptions: { - height: 700, - index: 'student_uid', - layout: 'fitDataStretch', - placeholder: this.$p.t('global/noDataAvailable'), - columns: [ - {title: Vue.computed(() => this.$p.t('benotungstool/c4mail')), field: 'email', formatter: this.mailFormatter, tooltip: false, widthGrow: 1}, - {title: 'UID', field: 'uid', tooltip: false, widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('benotungstool/c4vorname')), field: 'vorname', tooltip: false, widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('benotungstool/c4nachname')), field: 'nachname', widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('benotungstool/c4teilnoten')), field: 'teilnote', widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('benotungstool/c4note')), field: 'note_vorschlag', - editor: 'list', - editorParams: { - values: Vue.computed(()=>this.notenOptions.map(opt => { - return { - label: opt.bezeichnung, - value: opt.note - } - })) - }, - formatter: (cell) => { - const value = cell.getValue() - const match = this.notenOptions.find(opt => opt.note === value) - return match ? match.bezeichnung : value - }, - widthGrow: 1}, - {title: '', width: 50, hozAlign: 'center', formatter: this.arrowFormatter, cellClick: this.saveNote}, - {title: Vue.computed(() => this.$p.t('benotungstool/c4lvnote')), field: 'lv_note', - formatter: this.notenFormatter, - widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('benotungstool/c4freigabe')), field: 'freigegeben', widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('benotungstool/c4zeugnisnote')), field: 'note', formatter: this.notenFormatter, widthGrow: 1} - // {title: Vue.computed(() => this.$p.t('benotungstool/c4termin1')), field: 'termin1', widthGrow: 1}, - // {title: Vue.computed(() => this.$p.t('benotungstool/c4termin2')), field: 'termin2', widthGrow: 1}, - // {title: Vue.computed(() => this.$p.t('benotungstool/c4termin3')), field: 'termin3', widthGrow: 1} - ], - persistence: false, - }, + notenTableOptions: null, // built later when noten are available notenTableEventHandlers: [{ event: "tableBuilt", handler: async () => { this.tableBuiltResolve() } }, - { - event: "cellClick", - handler: async (e, cell) => { - - + { + event: "cellClick", + handler: async (e, cell) => { + + } + }, + { + event: "cellEdited", + handler: async (cell) => { + const field = cell.getField() + + if(field === 'note_vorschlag') { + const rowData = cell.getRow().getData(); + const newValue = cell.getValue(); + const original = rowData._originalNoteVorschlag; + // If nothing was selected, restore + if (newValue == null || newValue === "" || newValue === original) { + // revert value + cell.setValue(original, true); + } + + delete rowData._originalNoteVorschlag; // Clean up + + const row = cell.getRow() + row.reformat() // trigger reformat of arrow } } + } ]}; }, methods: { + getNotenTableOptions() { + return { + height: 700, + index: 'uid', + layout: 'fitDataStretch', + placeholder: this.$p.t('global/noDataAvailable'), + columns: [ + {title: Vue.computed(() => this.$p.t('benotungstool/c4mail')), field: 'email', formatter: this.mailFormatter, tooltip: false, widthGrow: 1}, + {title: 'UID', field: 'uid', tooltip: false, widthGrow: 1}, + {title: Vue.computed(() => this.$p.t('benotungstool/c4vorname')), field: 'vorname', tooltip: false, widthGrow: 1}, + {title: Vue.computed(() => this.$p.t('benotungstool/c4nachname')), field: 'nachname', widthGrow: 1}, + {title: Vue.computed(() => this.$p.t('benotungstool/c4teilnoten')), field: 'teilnote', widthGrow: 1, formatter: this.teilnotenFormatter}, + {title: Vue.computed(() => this.$p.t('benotungstool/c4note')), field: 'note_vorschlag', + editor: 'list', + editorParams: (cell) => { + // write original cell value into row to it can be retrieved if edit is cancelled without selection + const rowData = cell.getRow().getData(); + rowData._originalNoteVorschlag = cell.getValue(); + + return { + values: this.notenOptionsLehre.map(opt => ({ + label: opt.bezeichnung, + value: opt.note + })) + }; + }, + editable: (cell) => { + const rowData = cell.getRow().getData(); + const noteOption = this.notenOptions.find(opt => opt.note == rowData.note) + if(!noteOption) return true + + // also if student has any pruefungsnote disable noten selection + if(this.pruefungen.find(p => p.student_uid == rowData.uid)) return false + + return noteOption.lkt_ueberschreibbar + }, + formatter: (cell) => { + const rowData = cell.getRow().getData(); + const value = cell.getValue() + const match = this.notenOptions?.find(opt => opt.note == value) + const val = match ? match.bezeichnung : value + const p = this.pruefungen.find(p => p.student_uid == rowData.uid) + let style = '' + + if(val === undefined) return '' + if(p || !match?.lkt_ueberschreibbar) style = 'color: gray;font-style: italic; background-color: #f0f0f0;pointer-events: none;opacity: 0.6;user-select: none;cursor: not-allowed;' + return '