From af30a3408cd3d6dfc462554ffdb6c3a48c90fa35 Mon Sep 17 00:00:00 2001 From: ma0068 Date: Tue, 15 Apr 2025 14:22:39 +0200 Subject: [PATCH] add switch stundenplan, excel export, phrases --- .../api/frontend/v1/stv/LvTermine.php | 408 ++++++++++++++++++ .../api/frontend/v1/stv/Lvtermine.php | 67 --- .../models/ressource/Stundenplan_model.php | 124 +++++- public/css/Studentenverwaltung.css | 4 + public/js/api/stv/courselist.js | 13 +- .../ListLehrveranstaltungstermine.js | 175 +++++++- system/phrasesupdate.php | 180 ++++++++ 7 files changed, 876 insertions(+), 95 deletions(-) create mode 100644 application/controllers/api/frontend/v1/stv/LvTermine.php delete mode 100644 application/controllers/api/frontend/v1/stv/Lvtermine.php diff --git a/application/controllers/api/frontend/v1/stv/LvTermine.php b/application/controllers/api/frontend/v1/stv/LvTermine.php new file mode 100644 index 000000000..c29f56964 --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/LvTermine.php @@ -0,0 +1,408 @@ + ['admin:r', 'assistenz:r'], + 'getStudiensemester' => ['admin:r', 'assistenz:r'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + $this->load->library('form_validation'); + + // Load language phrases + $this->loadPhrases([ + 'ui', + ]); + + // Load models + $this->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + //query verwenden wie im Cis endpoint + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); + $this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + } + + //TODO Build own lib or combine with Controller Stundenplan.php + //here use of logic of Stundenplan.php, extended with parameters uid, grouping, and used dbTable + public function getStundenplan($uid, $start_date = null, $end_date = null, $groupConsecutiveHours = false, $dbStundenplanTable = "stundenplan") + { + $student_uid = $uid; + $semester_range = $this->studienSemesterErmitteln($start_date, $end_date); + + $this->sortStudienSemester($semester_range); + $this->applyLoadUeberSemesterHaelfte($semester_range); + + $benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($semester_range, $student_uid); + $student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($semester_range, $student_uid); + + if(!$groupConsecutiveHours) + $stundenplan_query = $this->StundenplanModel->getStundenplanQuery( + $start_date, + $end_date, + $semester_range, + $benutzer_gruppen, + $student_lehrverband + ); + else + $stundenplan_query = $this->StundenplanModel->getStundenplanQuery( + $start_date, + $end_date, + $semester_range, + $benutzer_gruppen, + $student_lehrverband, + true, + $dbStundenplanTable + ); + + if(!$stundenplan_query) + { + $this->terminateWithSuccess([]); + } + + if($groupConsecutiveHours) + { + $stundenplan_data = $this->StundenplanModel->stundenplanGruppierungConsecutive($stundenplan_query); + } + else + { + $stundenplan_data = $this->StundenplanModel->stundenplanGruppierung($stundenplan_query); + } + + $stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? []; + $this->terminateWithSuccess($stundenplan_data); + + $this->expand_object_information($stundenplan_data); + + $this->returnObj['$stundenplan_query'] = $stundenplan_query; + $this->returnObj['$student_lehrverband'] = $student_lehrverband; + $this->returnObj['$benutzer_gruppen'] = $benutzer_gruppen; + $this->terminateWithSuccess($stundenplan_data); + } + + public function getStudiensemester() + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addOrder('studienjahr_kurzbz', 'DESC'); + $result = $this->StudiensemesterModel->load(); + $data = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($data); + } + + //copied from Stundenplan.php + private function studienSemesterErmitteln($start_date, $end_date) + { + // gets all studiensemester from the student from start_date to end_date + $semester_range = $this->StudiensemesterModel->getByDateRange($start_date, $end_date); + $semester_range = array_map( + function ($sem) { + return $sem->studiensemester_kurzbz; + }, + $this->getDataOrTerminateWithError($semester_range) + ); + + // if no studiensemester is found for the given timespan, get the nearest studiensemester + if(count($semester_range) == 0) + { + $aktuelle_studiensemester = $this->StudiensemesterModel->getNearest(); + $aktuelle_studiensemester = $this->getDataOrTerminateWithError($aktuelle_studiensemester); + if (count($aktuelle_studiensemester) == 0) { + $this->terminateWithError("No aktuelles semester"); + } + $aktuelle_studiensemester = current($aktuelle_studiensemester)->studiensemester_kurzbz; + // push aktuelles semester in active semester array + array_push($semester_range, $aktuelle_studiensemester); + } + return $semester_range; + } + + //copied from Stundenplan.php + private function sortStudienSemester(&$semester_range) + { + usort( + $semester_range, + function ($first, $second) { + $sem_first = null; + $year_first = null; + $match_first = null; + + $sem_second = null; + $year_second = null; + $match_second = null; + + preg_match('/([WS]+)([0-9]+)/', $first, $match_first); + preg_match('/([WS]+)([0-9]+)/', $second, $match_second); + + $sem_first = $match_first[1]; + $year_first = intval($match_first[2]); + + $sem_second = $match_second[1]; + $year_second = intval($match_second[2]); + + if($year_first < $year_second) + { + return -1; + } + elseif($year_first > $year_second) + { + return 1; + } + elseif($year_first == $year_second && $sem_first > $sem_second) + { + return 1; + } + elseif($year_first == $year_second && $sem_first < $sem_second) + { + return -1; + } + return 0; + } + ); + } + + //copied from Stundenplan.php + private function applyLoadUeberSemesterHaelfte(&$semester_range) + { + /* + @var($semester_collection) + convert the array of studiensemester into an associative array with the studiensemester as the key + and the values of each key are the studiensemester needed for the query associated to that studiensemester + example: + + #INPUT: + ['WS2023','SS2024','WS2024'] + #OUTPUT: + [ + 'WS2023' => ['SS2023','WS2023'] + 'SS2024' => ['WS2023','SS2024'] + 'WS2024' => ['SS2024','WS2024'] + ] + */ + $semester_collection = []; + foreach($semester_range as $studiensemester) + { + $previous_studiensemester = $this->StudiensemesterModel->getPreviousFrom($studiensemester); + $previous_studiensemester = $this->getDataOrTerminateWithError($previous_studiensemester); + if (count($previous_studiensemester) == 0) { + $this->terminateWithError("No previous semester"); + } + $previous_studiensemester = current($previous_studiensemester)->studiensemester_kurzbz; + $semester_collection[$studiensemester] = [$previous_studiensemester, $studiensemester]; + } + + /* + @var($studienSemesterDateRanges) + fetches for each studiensemester the start and end date, (SS) summer studiensemester are extended by 1 month to cover the summerbreak + based on the LVPLAN_LOAD_UEBER_SEMESTERHAELFTE constant it will load both the semester and the previous semester with the full date range + or the semester with the full date range and the previous semester with the half date range: + + #INPUT: + [ + 'WS2023' => ['SS2023','WS2023'] + 'SS2024' => ['WS2023','SS2024'] + 'WS2024' => ['SS2024','WS2024'] + ] + #OUTPUT: depends whether LVPLAN_LOAD_UEBER_SEMESTERHAELFTE is true or false + ~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == true + [ + "SS2024": [ + "WS2023": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ], + "SS2024": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ] + ] + ] + ~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == false + [ + "SS2024": [ + "WS2023": [ + "start"=> "2024-02-03", + "ende"=> "2024-05-17" + ], + "SS2024": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ] + ] + ] + */ + $studienSemesterDateRanges=[]; + foreach($semester_collection as $semester_original => $semester_adjoint) + { + $semester_start_ende = $this->StudiensemesterModel->getStartEndeFromStudiensemester($semester_original); + $semester_start_ende = current($this->getDataOrTerminateWithError($semester_start_ende)); + + // initialize empty arrays to add key value pairs + $studienSemesterDateRanges[$semester_original] = []; + + // check if the studiensemester is a summer semester and add 1 month to bridge the school summer break + $match = null; + preg_match("/^(SS)([0-9]+)/", $semester_original, $match); + if(count($match) >0) + { + $one_month = new DateInterval('P1M'); + $one_day = DateInterval::createFromDateString('1 days'); + $summer_studiensemester_end_date = DateTime::createFromFormat('Y-m-d', $semester_start_ende->ende); + $summer_studiensemester_end_date->add($one_month); + $summer_studiensemester_end_date->sub($one_day); + $semester_start_ende->ende = date_format($summer_studiensemester_end_date, 'Y-m-d'); + } + if (defined('LVPLAN_LOAD_UEBER_SEMESTERHAELFTE') && LVPLAN_LOAD_UEBER_SEMESTERHAELFTE === true) + { + foreach($semester_adjoint as $adjoint) + { + $studienSemesterDateRanges[$semester_original][$adjoint]=$semester_start_ende; + } + } + else + { + //TODO: half of a DateInterval might not be correctly calculated + // calculate the half of the studiensemester + $studiensemester_start_date = DateTime::createFromFormat('Y-m-d', $semester_start_ende->start); + $studiensemester_end_date = DateTime::createFromFormat('Y-m-d', $semester_start_ende->ende); + $studiensemester_time_difference = $studiensemester_start_date->diff($studiensemester_end_date); + $half_dateNumber = ceil($studiensemester_time_difference->d/2)+ceil(($studiensemester_time_difference->m*30)/2); + $half_dateInterval = new DateInterval('P'.strval($half_dateNumber) .'D'); + $studiensemester_half = date_format($studiensemester_start_date->add($half_dateInterval), 'Y-m-d'); + + $first_half = new stdClass(); + $first_half->start = $semester_start_ende->start; + $first_half->ende = $studiensemester_half; + + $studienSemesterDateRanges[$semester_original][$semester_adjoint[0]] = $first_half; + $studienSemesterDateRanges[$semester_original][$semester_adjoint[1]] = $semester_start_ende; + } + $semester_range = $studienSemesterDateRanges; + } + } + + //copied from Stundenplan.php, extended with $student_uid + private function fetchBenutzerGruppenFromStudiensemester($semester_range, $student_uid) + { + //$student_uid = getAuthUID(); + $benutzer_gruppen = []; + // for each studiensemester fetch the benutzer gruppen and add them to an associate $bentuzer_gruppen array + /* + [ + ['WS2023'] => [['gruppe1_SS2023','gruppe2_SS2023'],['gruppe1_WS2023','gruppe2_WS2023']], + ['SS2024'] => [['gruppe1_WS2023','gruppe2_WS2023'],['gruppe1_SS2024','gruppe2_SS2024']], + ['WS2024'] => [['gruppe1_SS2024','gruppe2_SS2024'],['gruppe1_WS2024','gruppe2_WS2024']], + ] + */ + foreach($semester_range as $semester_key => $semester_array) + { + $benutzer_gruppen[$semester_key] = []; + // each semester could have ajoint semesters that need to be checked + foreach($semester_array as $semester => $semester_date_range) + { + // for each active semester query the benutzer_gruppen associated to the semester + $benutzer_query = $this->BenutzergruppeModel->execReadOnlyQuery(" + SELECT * FROM tbl_benutzergruppe where uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]); + $benutzer_query_result = $this->getDataOrTerminateWithError($benutzer_query); + array_push( + $benutzer_gruppen[$semester_key], + array_map( + function ($item) { + return "'".$item->gruppe_kurzbz. "'"; + }, + $benutzer_query_result + ) + ); + } + } + + // merge the gruppen of each studiensemester together for the original studiensemester + /* + [ + ['WS2023'] => ['gruppe1_SS2023','gruppe2_SS2023','gruppe1_WS2023','gruppe2_WS2023'], + ['SS2024'] => ['gruppe1_WS2023','gruppe2_WS2023','gruppe1_SS2024','gruppe2_SS2024'], + ['WS2024'] => ['gruppe1_SS2024','gruppe2_SS2024','gruppe1_WS2024','gruppe2_WS2024'], + ] + */ + $benutzer_gruppen = array_map( + function ($gruppe) { + $merged_gruppe = []; + foreach($gruppe as $gruppen_array) + { + $merged_gruppe = array_merge($merged_gruppe, $gruppen_array); + } + return $merged_gruppe; + }, + $benutzer_gruppen + ); + + return $benutzer_gruppen; + } + + //copied from Stundenplan.php, extended with $student_uid + private function fetchStudentlehrverbandFromStudiensemester($semester_range, $student_uid) + { + //$student_uid = getAuthUID(); + $student_lehrverband = []; + // for each studiensemester fetch the studentlehrverbaende and add them to an associate $student_lehrverband array + /* + [ + ['WS2023'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ] ], + ['SS2024'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ] ], + ['WS2024'] => [ [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ] ], + ] + */ + foreach($semester_range as $semester_key => $semester_array) + { + $student_lehrverband[$semester_key] = []; + foreach($semester_array as $semester => $semester_date_range) + { + // for each active semester query the student_lehrverband associated to the semester + $lehrverband_query = $this->BenutzergruppeModel->execReadOnlyQuery(" + SELECT * FROM tbl_studentlehrverband where student_uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]); + $lehrverband_query_result = $this->getDataOrTerminateWithError($lehrverband_query); + array_push($student_lehrverband[$semester_key], array_map( + function ($item) { + $result = new stdClass(); + $result->studiengang_kz = $item->studiengang_kz; + $result->semester = $item->semester; + $result->verband = $item->verband; + $result->gruppe = $item->gruppe; + return $result; + }, + $lehrverband_query_result)); + } + } + + // merge the studentlehrverband of each studiensemester together for the original studiensemester + /* + [ + ['WS2023'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ], + ['SS2024'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ], + ['WS2024'] => [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ], + ] + */ + $student_lehrverband = array_map( + function ($studentlehrverband) { + $merged_studentlehrverband = []; + foreach($studentlehrverband as $studentlehrverband_array) + { + $merged_studentlehrverband = array_merge($merged_studentlehrverband, $studentlehrverband_array); + } + return $merged_studentlehrverband; + }, + $student_lehrverband + ); + + return $student_lehrverband; + } +} diff --git a/application/controllers/api/frontend/v1/stv/Lvtermine.php b/application/controllers/api/frontend/v1/stv/Lvtermine.php deleted file mode 100644 index 17a529f85..000000000 --- a/application/controllers/api/frontend/v1/stv/Lvtermine.php +++ /dev/null @@ -1,67 +0,0 @@ - ['admin:r', 'assistenz:r'], - 'getLvsStudent' => ['admin:r', 'assistenz:r'], - ]); - - // Load Libraries - $this->load->library('VariableLib', ['uid' => getAuthUID()]); - $this->load->library('form_validation'); - - // Load language phrases - $this->loadPhrases([ - 'ui', - ]); - - // Load models - $this->load->model('ressource/Stundenplan_model', 'StundenplanModel'); - } - - public function getStundenplan($uid) - { - //get stundenplan for uid - $result = $this->StundenplanModel->loadForUid($uid); - - $data = $this->getDataOrTerminateWithError($result); - - $this->terminateWithSuccess($data); - - } - - public function getLvsStudent($uid) - { - $authUID = getAuthUID(); - //$this->terminateWithError('uid' . $uid, self::ERROR_TYPE_GENERAL); - //$this->terminateWithError('uid' . $authUID, self::ERROR_TYPE_GENERAL); - - $this->load->model('system/Variable_model', 'VariableModel'); - $result = $this->VariableModel->getVariables($authUID); - $data = $this->getDataOrTerminateWithError($result); - - //$this->terminateWithSuccess(current($data)); // WS2025 - - $this->load->model('ressource/Stunde_model', 'StundeModel'); - $this->StundeModel->addOrder('stunde', 'ASC'); - $result = $this->StundeModel->load(); - $dataStunden = $this->getDataOrTerminateWithError($result); - $this->terminateWithSuccess($dataStunden); - // $this->terminateWithSuccess(current($data)); - - //TODO(manu) check existing apis for liste stundenplan und lvs - // version for student - // version for lehrfaecherverteilung - - - - - } -} \ No newline at end of file diff --git a/application/models/ressource/Stundenplan_model.php b/application/models/ressource/Stundenplan_model.php index 40498a766..ac20c96c3 100644 --- a/application/models/ressource/Stundenplan_model.php +++ b/application/models/ressource/Stundenplan_model.php @@ -50,7 +50,6 @@ class Stundenplan_model extends DB_Model */ public function groupedCalendarEvents($ort_kurzbz,$start_date,$end_date){ - $gruppierteEvents= $this->execReadOnlyQuery(" SELECT @@ -186,6 +185,99 @@ class Stundenplan_model extends DB_Model return $query_result; } + /** + * groups rows of a subquery that fetches data from the lehre.vw_stundenplan table or lehre.vw_stundenplandev + * @param string $stundenplanViewQuery the subquery used to group the result regarding consecutive hours (Tab LV Termine) + * + * @return stdClass + */ + public function stundenplanGruppierungConsecutive($stundenplanViewQuery) + { + $query_result = $this->execReadOnlyQuery(" + SELECT + distinct lehrveranstaltung_id, + datum, + MIN(beginn) as beginn, + MAX(ende) as ende, + type, + topic, + gruppe, + ort_kurzbz, + lehreinheit_id, + lehrfach_bez, + lektor, + lektorname, + gruppen_kuerzel, + farbe + FROM + ( + SELECT + 'lehreinheit' as type, beginn, ende, datum, + CONCAT(lehrfach,'-',lehrform) as topic, + array_agg(DISTINCT lektor) as lektor, + array_agg(DISTINCT lektorname) as lektorname, + array_agg(DISTINCT (gruppe,verband,semester,studiengang_kz,gruppen_kuerzel)) as gruppe, + array_agg(DISTINCT (gruppen_kuerzel)) as gruppen_kuerzel, + string_agg(DISTINCT ort_kurzbz, '/') as ort_kurzbz, + array_agg(DISTINCT lehreinheit_id) as lehreinheit_id, + titel, lehrfach, lehrform, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id + + FROM + ( + SELECT unr,datum,beginn, ende, + CASE + WHEN sp.mitarbeiter_kurzbz IS NOT NULL THEN sp.mitarbeiter_kurzbz + ELSE lektor + END as lektor, + CASE + WHEN gruppe_kurzbz IS NOT NULL THEN gruppe_kurzbz + ELSE (SELECT UPPER(typ || kurzbz) + FROM public.tbl_studiengang + WHERE studiengang_kz=sp.studiengang_kz) || COALESCE(sp.semester,'0') || COALESCE(sp.verband,'') || COALESCE(sp.gruppe,'') + END as gruppen_kuerzel, + (SELECT bezeichnung + FROM public.tbl_organisationseinheit + WHERE oe_kurzbz IN( + SELECT oe_kurzbz + FROM lehre.tbl_lehrveranstaltung + WHERE lehrveranstaltung_id = sp.lehrveranstaltung_id + )) as organisationseinheit, + ort_kurzbz, studiengang_kz, titel,lehreinheit_id,lehrfach_id,sp.anmerkung,fix,lehrveranstaltung_id, + stg_kurzbzlang,stg_bezeichnung,stg_typ,fachbereich_kurzbz,lehrfach,lehrfach_bez,farbe,lehrform, + anmerkung_lehreinheit,gruppe, verband, semester,stg_kurzbz, + CONCAT(p.nachname, ' ', p.vorname) as lektorname + + FROM (".$stundenplanViewQuery.") sp + JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = sp.stunde + LEFT JOIN public.tbl_benutzer bn ON bn.uid = sp.uid + LEFT JOIN public.tbl_person p ON p.person_id = bn.person_id + ) as subquery + + GROUP BY unr, datum, beginn, ende, ort_kurzbz, titel, lehrform, lehrfach, lehrfach_bez, organisationseinheit, + farbe, lehrveranstaltung_id + + ORDER BY datum, beginn) t + + GROUP BY + lehrveranstaltung_id, + type, + datum, + topic, + lektor, + lehrfach_bez, + gruppe, + ort_kurzbz, + lehreinheit_id, + lektorname, + gruppen_kuerzel, + farbe + ORDER BY + datum, beginn + " + ); + return $query_result; + } + /** * queries Stundenplan but for a whole lva, irrespective of who is requesting it * @@ -300,10 +392,13 @@ class Stundenplan_model extends DB_Model /** * NO STANDALONE FUNCTION - Generates a SQL query string to fetch 'stundenplan' events for a specific student within the current semester. * + * @param isLvList if condition needed for Tab LV Termine is given + * @param db_stpl_table enables switch to db 'stundenplandev' + * * @return mixed */ - public function getStundenplanQuery($start_date, $end_date,$semester,$gruppen,$studentlehrverbaende){ - + public function getStundenplanQuery($start_date, $end_date, $semester, $gruppen, $studentlehrverbaende, $isLvList=false, $db_stpl_table='stundenplan'){ + // helper function to check if either $gruppen or $studentlehrverbaende are empty for each semester $emptyCheck = function($toBeCheckedArray) use ($semester){ $result = true; @@ -325,7 +420,7 @@ class Stundenplan_model extends DB_Model $query = "select sp.* - from lehre.vw_stundenplan sp + from lehre.vw_".$db_stpl_table." sp WHERE sp.datum >= ".$this->escape($start_date)." AND sp.datum <= ".$this->escape($end_date); @@ -335,10 +430,10 @@ class Stundenplan_model extends DB_Model { $query .= " AND ( "; } - + foreach($semester as $sem => $semester_date_range) { - + foreach($semester_date_range as $sem_date => $sem_date_range) { // if there are not groups for the semester skip the iteration step @@ -358,7 +453,13 @@ class Stundenplan_model extends DB_Model { $query = substr($query, 0, -2); } - + + //Condition for showLVList FHC4 + if(!$isLvList) + $stringGroupLv = "AND gruppe_kurzbz is null"; + else + $stringGroupLv =""; + foreach($semester as $sem=>$semester_date_range) { foreach($semester_date_range as $sem_date => $sem_date_range) @@ -373,10 +474,10 @@ class Stundenplan_model extends DB_Model // Eintraege fuer den ganzen Verband $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND (sp.gruppe is null OR sp.gruppe='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")"; // Eintraege fuer das ganze Semester - $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).") AND gruppe_kurzbz is null)"; - + $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start) + ." AND ".$this->escape($sem_date_range->ende).")". $stringGroupLv. ")"; + $query .="OR"; - } } } @@ -421,7 +522,7 @@ class Stundenplan_model extends DB_Model */ public function loadForUid($uid) { - $this->addSelect(['5sp.*','le.studiensemester_kurzbz']); + $this->addSelect(['sp.*','le.studiensemester_kurzbz']); $this->db->join('public.tbl_benutzergruppe bg', 'sp.gruppe_kurzbz=bg.gruppe_kurzbz AND bg.uid=?', 'LEFT', false); $this->addJoin('public.tbl_studiensemester ss1', 'bg.studiensemester_kurzbz=ss1.studiensemester_kurzbz AND ss1.start<=sp.datum AND ss1.ende>=sp.datum', 'LEFT'); $this->db->join('public.tbl_studentlehrverband slv', "sp.studiengang_kz=slv.studiengang_kz AND slv.student_uid=? AND (slv.semester=sp.semester OR sp.semester IS NULL) AND (slv.verband=sp.verband OR sp.verband IS NULL OR sp.verband='' OR sp.verband='0') AND (slv.gruppe=sp.gruppe OR sp.gruppe IS NULL OR sp.gruppe='' OR sp.gruppe='0') AND sp.gruppe_kurzbz IS NULL", 'LEFT', false); @@ -434,5 +535,4 @@ class Stundenplan_model extends DB_Model return $this->execQuery($query, [$uid, $uid]); } - } diff --git a/public/css/Studentenverwaltung.css b/public/css/Studentenverwaltung.css index 1ccac1273..67cff2982 100644 --- a/public/css/Studentenverwaltung.css +++ b/public/css/Studentenverwaltung.css @@ -77,6 +77,10 @@ html { overflow: visible !important; } +.highlight-row { + background-color: #e5aeae !important; +} + @media (min-width: 768px) { #sidebarMenu { visibility: visible!important; diff --git a/public/js/api/stv/courselist.js b/public/js/api/stv/courselist.js index b6035c098..6bd999e5f 100644 --- a/public/js/api/stv/courselist.js +++ b/public/js/api/stv/courselist.js @@ -1,6 +1,15 @@ export default { getCourselist(url, config, params) { - console.log("her"); - return this.$fhcApi.get('api/frontend/v1/stv/Lvtermine/getLvsStudent/' + params.id); + //corresponding logic controller Stundenplan.php + return this.$fhcApi.get('api/frontend/v1/stv/LvTermine/getStundenplan/' + + params.student_uid + '/' + + params.start_date + '/' + + params.end_date + '/' + + params.group_consecutiveHours + '/' + + params.dbStundenplanTable + ); + }, + getStudiensemester(){ + return this.$fhcApi.get('api/frontend/v1/stv/LvTermine/getStudiensemester/'); }, } \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js b/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js index 8a6c0d2b0..bc4e02b51 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js @@ -1,39 +1,173 @@ import {CoreFilterCmpt} from "../../../../filter/Filter.js"; +import FormInput from "../../../../Form/Input.js"; +import FormForm from '../../../../Form/Form.js'; export default { name: "TblCourseList", components: { - CoreFilterCmpt + CoreFilterCmpt, + FormInput, + FormForm + }, + computed: { + downloadLink: function(){ + if(!this.dataSem.start || !this.dataSem.ende || !this.student.uid) return; + let start = new Date(this.dataSem.start); + start = Math.floor(start.getTime()/1000); + let ende = new Date(this.dataSem.ende); + ende = Math.floor(ende.getTime() / 1000); + + let link = + FHC_JS_DATA_STORAGE_OBJECT.app_root + "cis/private/lvplan/stpl_kalender.php?type=student&pers_uid=" + this.student.uid + "&begin=" + start + "&ende= " +ende + "&format=excel"; + return link; + }, + dbStundenplanTable: function (){ + return this.showStundenplanDev ? 'stundenplandev' : 'stundenplan'; + } + }, + inject: { + currentSemester: { + from: 'currentSemester', + }, }, props: { student: Object }, data(){ return { - tabulatorOptions: { + tabulatorOptions: null, + tabulatorEvents: [], + listStudiensemester: [], + dataSem: {}, + showStundenplanDev: false + }; + }, + methods: { + initTabulatorOptions(){ + this.tabulatorOptions = { ajaxURL: 'dummy', ajaxRequestFunc: this.$fhcApi.factory.stv.courselist.getCourselist, ajaxParams: () => { return { - id: this.student.uid + student_uid: this.student.uid, + start_date: this.dataSem.start, + end_date: this.dataSem.ende, + group_consecutiveHours: true, + dbStundenplanTable: this.dbStundenplanTable }; }, - ajaxResponse: (url, params, response) => response.data, + ajaxResponse: (url, params, response) => { + return response.data; + }, columns: [ - {title: "Prestudent_id", field: "prestudent_id"}, - ] - }, - tabulatorEvents: [], - } + {title: "lv_id", field: "lehrveranstaltung_id", visible: false}, + {title: "lehreinheit_id", field: "lehreinheit_id", 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: "beginn", field: "beginn"}, + {title: "ende", field: "ende"}, + {title: "farbe", field: "farbe", visible: false}, + {title: "Gruppen", field: "gruppen_kuerzel"}, + {title: "ort", field: "ort_kurzbz"}, + {title: "lektorIn", field: "lektorname"}, + {title: "Lehrfach", field: "lehrfach_bez"} + ], + rowFormatter: function(row){ + var data = row.getData(); + //highlight background of row if color red in table + if(data.farbe == "A4A7FC"){ + let el = row.getElement(); + row.getElement().classList.add("highlight-row"); + row.getElement().classList.remove("tabulator-row-odd"); + row.getElement().classList.remove("tabulator-row-even"); + } + } + }; + this.tabulatorEvents = [ + { + event: 'tableBuilt', + handler: async() => { + await this.$p.loadCategory(['global', 'ui', 'lehre']); + + let cm = this.$refs.table.tabulator.columnManager; + + cm.getColumnByField('lehrveranstaltung_id').component.updateDefinition({ + title: this.$p.t('lehre', 'lehrveranstaltung_id') + }); + cm.getColumnByField('lehreinheit_id').component.updateDefinition({ + title: this.$p.t('global', 'lehreinheit_id') + }); + cm.getColumnByField('datum').component.updateDefinition({ + title: this.$p.t('global', 'datum') + }); + cm.getColumnByField('beginn').component.updateDefinition({ + title: this.$p.t('ui', 'dateFrom') + }); + cm.getColumnByField('ende').component.updateDefinition({ + title: this.$p.t('ui', 'dateTo') + }); + cm.getColumnByField('gruppen_kuerzel').component.updateDefinition({ + title: this.$p.t('global', 'gruppen') + }); + cm.getColumnByField('ort_kurzbz').component.updateDefinition({ + title: this.$p.t('global', 'ortLocation') + }); + cm.getColumnByField('lektorname').component.updateDefinition({ + title: this.$p.t('lehre', 'lektor') + }); + cm.getColumnByField('lehrfach_bez').component.updateDefinition({ + title: this.$p.t('global', 'lehrfach') + }); + } + } + ]; + }, + getDatesOfSemester(studiensemester_kurzbz) { + this.dataSem = this.listStudiensemester.find(item => item.studiensemester_kurzbz === studiensemester_kurzbz); + }, + exportToExcel(){ + window.open(this.downloadLink, '_blank'); + }, + reload() { + this.$refs.table.reloadTable(); + }, + switchStundenplan(){ + this.showStundenplanDev = !this.showStundenplanDev; + this.reload(); + } + }, + watch: { + currentSemester(newVal, oldVal) { + this.getDatesOfSemester(newVal); + }, + }, + created(){ + this.$fhcApi.factory.stv.courselist.getStudiensemester() + .then(result => { + this.listStudiensemester = result.data; + this.getDatesOfSemester(this.currentSemester); + this.initTabulatorOptions(); + + }) + .catch(this.$fhcAlert.handleSystemError); }, - methods: {}, template: `
-

Termine

- {{student}} - +

{{$p.t('global', 'termine')}}

+ +
` -} \ No newline at end of file +} diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 7d6d7361d..5749562ac 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -41416,6 +41416,186 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'core', + 'category' => 'ui', + 'phrase' => 'export', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Exportieren', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Export', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'stundenplanDev', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Stundenplan DEV', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Timetable DEV', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'lehreinheit_id', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehreinheit ID', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Teaching Unit ID', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'ui', + 'phrase' => 'dateFrom', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'von', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'from', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'ui', + 'phrase' => 'dateTo', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'bis', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'to', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'gruppen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Gruppen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'groups', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'ortLocation', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ort', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'location', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'lehrfach', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehrfach', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'subject', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'termine', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Termine', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Dates', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), // FHC 4 Lehrveranstaltungstermine ENDE --------------------------------------------------------------------------- );