diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 463c7bcfb..4c4dcb425 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -1353,7 +1353,9 @@ class Lehrveranstaltung_model extends DB_Model tbl_lehrveranstaltung.semester as lv_semester, tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung, (SELECT kurzbz FROM public.tbl_mitarbeiter - WHERE mitarbeiter_uid=tbl_lehreinheitmitarbeiter.mitarbeiter_uid) as lektor + WHERE mitarbeiter_uid=tbl_lehreinheitmitarbeiter.mitarbeiter_uid) as lektor, + lehre.tbl_lehrveranstaltung.orgform_kurzbz as orgform + FROM lehre.tbl_lehreinheit JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id) JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) diff --git a/content/statistik/notenspiegel_erweitert.php b/content/statistik/notenspiegel_erweitert.php index 67097ed22..264324154 100644 --- a/content/statistik/notenspiegel_erweitert.php +++ b/content/statistik/notenspiegel_erweitert.php @@ -95,37 +95,37 @@ foreach ($result_student as $row) if ($uids == '') die('Es befinden sich keine Studierende in diesem Semester'); -$qry = "SELECT - lehrveranstaltung_id, bezeichnung, studiengang_kz, semester, ects - FROM - lehre.tbl_lehrveranstaltung - WHERE - lehrveranstaltung_id IN - ( - SELECT - distinct lehrveranstaltung_id - FROM - campus.vw_student_lehrveranstaltung, public.tbl_studentlehrverband - WHERE - tbl_studentlehrverband.studiengang_kz=".$db->db_add_param($studiengang_kz, FHC_INTEGER)." AND - tbl_studentlehrverband.semester=".$db->db_add_param($semester, FHC_INTEGER)." AND - vw_student_lehrveranstaltung.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)." AND - uid=student_uid AND - vw_student_lehrveranstaltung.studiensemester_kurzbz=tbl_studentlehrverband.studiensemester_kurzbz +$qry = "SELECT + lehrveranstaltung_id, bezeichnung, studiengang_kz, semester, ects + FROM + lehre.tbl_lehrveranstaltung + WHERE + lehrveranstaltung_id IN ( + SELECT + DISTINCT lehrveranstaltung_id + FROM + campus.vw_student_lehrveranstaltung + JOIN public.tbl_studentlehrverband ON(student_uid = uid) + WHERE + tbl_studentlehrverband.studiengang_kz = ".$db->db_add_param($studiengang_kz, FHC_INTEGER)." + AND tbl_studentlehrverband.semester = ".$db->db_add_param($semester, FHC_INTEGER)." + AND vw_student_lehrveranstaltung.studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell)." + AND vw_student_lehrveranstaltung.studiensemester_kurzbz = tbl_studentlehrverband.studiensemester_kurzbz ) - AND studiengang_kz<>0 + AND studiengang_kz != 0 AND zeugnis - UNION - SELECT - lehrveranstaltung_id, bezeichnung, studiengang_kz, semester, ects - FROM - lehre.tbl_lehrveranstaltung JOIN lehre.tbl_zeugnisnote USING(lehrveranstaltung_id) - WHERE - tbl_lehrveranstaltung.studiengang_kz=".$db->db_add_param($studiengang_kz, FHC_INTEGER)." AND - tbl_zeugnisnote.student_uid in($uids) AND - tbl_zeugnisnote.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)." AND - zeugnis - ORDER BY bezeichnung"; + UNION + SELECT + lehrveranstaltung_id, bezeichnung, studiengang_kz, semester, ects + FROM + lehre.tbl_lehrveranstaltung + JOIN lehre.tbl_zeugnisnote USING(lehrveranstaltung_id) + WHERE + tbl_lehrveranstaltung.studiengang_kz = ".$db->db_add_param($studiengang_kz, FHC_INTEGER)." + AND tbl_zeugnisnote.student_uid IN ($uids) + AND tbl_zeugnisnote.studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell)." + AND zeugnis + ORDER BY bezeichnung"; if (!$result_lva = $db->db_query($qry)) die('Fehler beim Ermitteln der Lehrveranstaltungen'); @@ -338,6 +338,10 @@ if ($typ == 'xls') } $anzahl_lvspalten = $spalte - 2; + $worksheet->write($zeile, ++$spalte, 'ECTS Summe zugeteilt', $format_bold); + $maxlength[$spalte] = 20; + $worksheet->write($zeile, ++$spalte, 'ECTS Summe gewichtet', $format_bold); + $maxlength[$spalte] = 20; $worksheet->write($zeile, ++$spalte, 'Notendurchschnitt', $format_bold); $maxlength[$spalte] = 15; $worksheet->write($zeile, ++$spalte, "Gewichteter\nNotendurchschnitt", $format_bold_wrap); @@ -372,9 +376,12 @@ if ($typ == 'xls') $worksheet->write($zeile, ++$spalte, $row_student->gruppe, $format_bold_left); $worksheet->write($zeile, ++$spalte, $row_student->matrikelnr, $format_bold); - //Alle Zeugnisnoten des Studierenden holen + // Alle Zeugnisnoten des Studierenden holen $noten = array(); - $qry = "SELECT * FROM lehre.tbl_zeugnisnote WHERE student_uid=".$db->db_add_param($row_student->uid)." AND studiensemester_kurzbz=".$db->db_add_param($semester_aktuell); + $qry = "SELECT lehrveranstaltung_id, note + FROM lehre.tbl_zeugnisnote + WHERE student_uid = ".$db->db_add_param($row_student->uid)." + AND studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell); if ($result = $db->db_query($qry)) while ($row = $db->db_fetch_object($result)) $noten[$row->lehrveranstaltung_id] = $row->note; @@ -382,15 +389,16 @@ if ($typ == 'xls') //Zu jeder Lehrveranstaltungsnote Prüfungstyp (Anzahl der Antritte) holen $pruefungstypen = array(); $qry = "SELECT tbl_lehrveranstaltung.lehrveranstaltung_id, pruefungstyp_kurzbz, sort, datum - FROM - lehre.tbl_pruefung - JOIN - lehre.tbl_lehreinheit using(lehreinheit_id) - JOIN - lehre.tbl_lehrveranstaltung using(lehrveranstaltung_id) - WHERE - student_uid=".$db->db_add_param($row_student->uid)." AND studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)." - ORDER BY lehrveranstaltung_id, sort, datum"; + FROM + lehre.tbl_pruefung + JOIN + lehre.tbl_lehreinheit USING(lehreinheit_id) + JOIN + lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + WHERE + student_uid = ".$db->db_add_param($row_student->uid)." + AND studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell)." + ORDER BY lehrveranstaltung_id, sort, datum"; if ($result = $db->db_query($qry)) { while ($row = $db->db_fetch_object($result)) @@ -399,15 +407,14 @@ if ($typ == 'xls') } } - //Alle LVs holen zu denen der Studierende zugeteilt ist + // Alle LVs holen zu denen der Studierende zugeteilt ist $zugeteilte_lvs = array(); - $qry = "SELECT distinct lehrveranstaltung_id - FROM - campus.vw_student_lehrveranstaltung - WHERE - uid=".$db->db_add_param($row_student->uid)." AND - studiensemester_kurzbz=".$db->db_add_param($semester_aktuell); - + $qry = "SELECT DISTINCT lehrveranstaltung_id + FROM + campus.vw_student_lehrveranstaltung + WHERE + uid = ".$db->db_add_param($row_student->uid)." + AND studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell); if ($result = $db->db_query($qry)) while ($row = $db->db_fetch_object($result)) $zugeteilte_lvs[] = $row->lehrveranstaltung_id; @@ -416,17 +423,20 @@ if ($typ == 'xls') $summe = 0; $rowcount = 0; $summeects = 0; + $total_ects = 0; $gewichtetenote = 0; while ($rowcount < $db->db_num_rows($result_lva)) { $row_lva = $db->db_fetch_object($result_lva, $rowcount); $rowcount++; + //wenn es eine Note gibt if (isset($noten[$row_lva->lehrveranstaltung_id])) { $note = $noten[$row_lva->lehrveranstaltung_id]; $format = 0; + $total_ects += $row_lva->ects; //wenn für die LV der Studierende eine Nachprüfung hat (z.B. 2 Termin, kommissionelle...) if (isset($pruefungstypen[$row_lva->lehrveranstaltung_id])) @@ -472,6 +482,7 @@ if ($typ == 'xls') //Keine Note fuer diese LV vorhanden if (in_array($row_lva->lehrveranstaltung_id, $zugeteilte_lvs)) { + $total_ects += $row_lva->ects; $worksheet->write($zeile, ++$spalte, '', $format_colored_nichteingetragen); } else @@ -489,6 +500,8 @@ if ($typ == 'xls') if ($summeects != 0) $gewichtetenote /= $summeects; + $worksheet->write($zeile, ++$spalte, sprintf("%.2f", $total_ects), $format_number); + $worksheet->write($zeile, ++$spalte, sprintf("%.2f", $summeects), $format_number); $worksheet->write($zeile, ++$spalte, sprintf("%.2f", $schnitt), $format_number); $worksheet->write($zeile, ++$spalte, sprintf("%.2f", $gewichtetenote), $format_number); if ($gewichtetenote != 0) @@ -529,6 +542,8 @@ if ($typ == 'xls') $schnitt = $summe_schnitt / $anzahl_schnitt; else $schnitt = 0; + $worksheet->write($zeile, ++$spalte, '-', $format_bold_center); + $worksheet->write($zeile, ++$spalte, '-', $format_bold_center); $worksheet->write($zeile, ++$spalte, sprintf("%.2f", $schnitt), $format_number); if ($anzahlgewichtet != 0) $summegewichtet = $summegewichtet / $anzahlgewichtet; diff --git a/public/js/apps/Cis/Cis.js b/public/js/apps/Cis/Cis.js index 2896775b4..7702ffd55 100644 --- a/public/js/apps/Cis/Cis.js +++ b/public/js/apps/Cis/Cis.js @@ -101,7 +101,7 @@ const router = VueRouter.createRouter({ props: true }, { - path: `/Cis/Benotungstool/:lv_id/:sem_kurzbz`, + path: `/Cis/Benotungstool/:lv_id?/:sem_kurzbz?`, name: 'Benotungstool', component: Benotungstool, props: true diff --git a/public/js/components/Cis/Benotungstool/Benotungstool.js b/public/js/components/Cis/Benotungstool/Benotungstool.js index 8abaef7ad..0440ffba0 100644 --- a/public/js/components/Cis/Benotungstool/Benotungstool.js +++ b/public/js/components/Cis/Benotungstool/Benotungstool.js @@ -1,6 +1,7 @@ import {CoreFilterCmpt} from "../../filter/Filter.js"; import ApiLehre from "../../../api/factory/lehre.js"; import ApiNoten from "../../../api/factory/noten.js"; +import ApiAuthinfo from "../../../api/factory/authinfo.js"; import ApiStudiensemester from "../../../api/factory/studiensemester.js"; import BsModal from '../../Bootstrap/Modal.js'; import BsOffcanvas from '../../Bootstrap/Offcanvas.js'; @@ -9,7 +10,7 @@ import LehreinheitenModule from '../../DropdownModes/LehreinheitenModule.js'; import MobilityLegende from '../../Mobility/Legende.js'; import FhcOverlay from "../../Overlay/FhcOverlay.js"; import {debounce} from "../../../helpers/debounce.js"; -import {centeredFormatter} from "../../../tabulator/formatter/centered.js"; +import {centeredTextFormatter} from "../../../tabulator/formatter/centered.js"; export const Benotungstool = { name: "Benotungstool", @@ -30,25 +31,20 @@ export const Benotungstool = { props: { lv_id: { default: null, - required: true + required: false }, sem_kurzbz: { default: null, - required: true - }, - viewData: { - type: Object, - required: true, - default: () => ({uid: ''}), - validator(value) { - return value && value.uid - } + required: false } }, data() { return { + uid: null, headerFiltersRestored: false, filtersRestored: false, + filteredRows: null, + filteredcount: 0, colLayoutRestored: false, sortRestored: false, stateRestored: false, @@ -137,10 +133,32 @@ export const Benotungstool = { this.undoSelection(cell) } } + }, + { + event: 'dataFiltered', + handler: (filters, rows) => { + this.filteredRows = rows; + this.filteredcount = rows.length; + + if (!this.selectedUids.length) return; + + const visibleData = new Set(rows.map(r => r.getData())); + const filteredOut = this.selectedUids.filter(su => !visibleData.has(su)); + if (!filteredOut.length) return; + + const filteredOutSet = new Set(filteredOut); + this.$refs.notenTable.tabulator.getSelectedRows() + .filter(r => filteredOutSet.has(r.getData())) + .forEach(r => r.deselect()); + } } ]}; }, methods: { + async fetchAuthUID() { + const authIdResponse = await this.$api.call(ApiAuthinfo.getAuthUID()); + this.uid = authIdResponse.data.uid; + }, loadState() { return JSON.parse(localStorage.getItem(this.persistenceID) || "null"); }, @@ -724,12 +742,13 @@ export const Benotungstool = { virtualDom: true, virtualDomBuffer: 5000, index: 'uid', - layout: 'fitDataStretch', + layout: 'fitData', placeholder: this.$capitalize(this.$p.t('global/noDataAvailable')), selectable: true, selectableRangeMode: "click", // shift+click selectablePersistence: false, // reset selection on table reload selectableCheck: this.selectableCheck, + rowHeight: 30, rowFormatter: this.fixTabulatorSelectionFormatter, columns: this.getColumnsDefinition(), persistence: false, @@ -797,18 +816,18 @@ export const Benotungstool = { field: 'selectCol', title: '' }) - columns.push({title: 'UID', field: 'uid', tooltip: false, widthGrow: 1, topCalc: this.sumCalcFunc, formatter: centeredFormatter, cssClass: 'sticky-col'}) - columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4mail'))), field: 'email', formatter: this.mailFormatter, tooltip: false, visible: false, widthGrow: 1, variableHeight: true}) - columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4antrittCountv2'))), field: 'hoechsterAntritt', formatter: centeredFormatter, tooltip: false, widthGrow: 1}) - columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4vorname'))), field: 'vorname', formatter: centeredFormatter, headerFilter: true, tooltip: false, widthGrow: 1}) - columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4nachname'))), field: 'nachname', formatter: centeredFormatter, headerFilter: true, widthGrow: 1}) - columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4anwesenheitsquote'))), field: 'anwquote', widthGrow: 1, formatter: this.percentFormatter}) - columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4mobility'))), field: 'mobility_zusatz', formatter: centeredFormatter, headerFilter: true, widthGrow: 1, visible: false}) + columns.push({title: 'UID', field: 'uid', tooltip: false, topCalc: this.sumCalcFunc, formatter: centeredTextFormatter, cssClass: 'sticky-col'}) + columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4mail'))), field: 'email', formatter: this.mailFormatter, tooltip: false, visible: false, variableHeight: true}) + columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4antrittCountv2'))), field: 'hoechsterAntritt', formatter: centeredTextFormatter, tooltip: false}) + columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4vorname'))), field: 'vorname', formatter: centeredTextFormatter, headerFilter: true, tooltip: false}) + columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4nachname'))), field: 'nachname', formatter: centeredTextFormatter, headerFilter: true}) + columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4anwesenheitsquote'))), field: 'anwquote', formatter: this.percentFormatter}) + columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4mobility'))), field: 'mobility_zusatz', formatter: centeredTextFormatter, headerFilter: true, visible: false}) if(this.config?.CIS_GESAMTNOTE_PRUEFUNG_MOODLE_LE_NOTE) { - columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4teilnoten'))), field: 'teilnote', widthGrow: 1, formatter: this.teilnotenFormatter, variableHeight: true}) + columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4teilnoten'))), field: 'teilnote', formatter: this.teilnotenFormatter, variableHeight: true}) } if(this.config?.CIS_GESAMTNOTE_PUNKTE) { - columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4punkte'))), field: 'punkte', widthGrow: 1, + columns.push({title: Vue.computed(() => this.$capitalize(this.$p.t('benotungstool/c4punkte'))), field: 'punkte', editor: this.liveNumberEditor, editable: (cell) => { const rowData = cell.getRow().getData(); @@ -856,8 +875,7 @@ export const Benotungstool = { 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 '