diff --git a/application/config/navigation.php b/application/config/navigation.php index 3680930d0..d57cd697a 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -55,6 +55,12 @@ $config['navigation_header'] = array( 'description' => 'CIS', 'sort' => 10 ), + 'lehrveranstaltungen' => array( + 'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'), + 'icon' => '', + 'description' => 'Lehrveranstaltungen', + 'sort' => 15 + ), 'reihungstest' => array( 'link' => site_url('organisation/Reihungstest'), 'description' => 'Reihungstests', @@ -287,6 +293,15 @@ $config['navigation_menu']['lehre/lehrauftrag/LehrauftragErteilen/*'] = array( ) ); +$config['navigation_menu']['lehre/lvplanung/LvTemplateUebersicht/index'] = array( + 'lvTemplateUebersicht' => array( + 'link' => site_url('lehre/lvplanung/LvTemplateUebersicht'), + 'description' => 'LV Template Übersicht', + 'icon' => '', + 'sort' => 1 + ) +); + $config['navigation_menu']['system/issues/Issues/*'] = array( 'fehlerzustaendigkeiten' => array( 'link' => site_url('system/issues/IssuesZustaendigkeiten'), diff --git a/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php new file mode 100644 index 000000000..636c8e3f3 --- /dev/null +++ b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php @@ -0,0 +1,65 @@ + array( + 'lehre/lehrveranstaltung:rw' + ) + )); + + // Load model LehrveranstaltungModel + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + } + + /** + * Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes of given Berechtigung, + * that are assigned to a template. This data structure can be used for nested tabulators' data tree. + * + * @param null|string $studiensemester_kurzbz + * @param null|string $berechtigung + * @return array|stdClass|null + */ + public function getTemplateLvTree() + { + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + $berechtigung = $this->input->get('berechtigung'); + + if ($berechtigung) + { + $oe_permissions = $this->permissionlib->getOE_isEntitledFor($berechtigung); + if(!$oe_permissions) $oe_permissions = []; + + $result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz, $oe_permissions); + } + else + { + $result = $this->LehrveranstaltungModel->getTemplateLvTree($studiensemester_kurzbz); + } + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess((getData($result) ?: [])); + } +} diff --git a/application/controllers/api/frontend/v1/organisation/Studiensemester.php b/application/controllers/api/frontend/v1/organisation/Studiensemester.php new file mode 100644 index 000000000..72a449aaa --- /dev/null +++ b/application/controllers/api/frontend/v1/organisation/Studiensemester.php @@ -0,0 +1,118 @@ + self::PERM_LOGGED, + 'getAktNext' => self::PERM_LOGGED + ) + ); + // Load model StudiensemesterModel + $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); + } + + /** + * Get all Studiensemester. + * + * @param null|string $order Sorting order for the Studiensemester, 'asc' or 'desc'. Defaults to 'asc'. + * @param null|string $start Start date of the displayed Studiensemester in the format 'YYYY-MM-DD'. + * If provided, only Studiensemester starting from this date onwards will be returned. + * eg. '2020-09-01' will start with WS2020. + */ + public function getAll() + { + $order = $this->input->get('order'); + $start = $this->input->get('start'); + + if (strcasecmp($order, 'DESC') == 0) + { + $this->StudiensemesterModel->addOrder('ende', 'DESC'); + } + else + { + $this->StudiensemesterModel->addOrder('ende', 'ASC'); + } + + if ($start) + { + $result = $this->StudiensemesterModel->loadWhere([ + 'start >= ' => $start + ]); + } + else + { + $result = $this->StudiensemesterModel->load(); + } + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess((getData($result) ?: [])); + } + + /** + * @return void + */ + public function getAktNext() + { + $semester = $this->input->get('semester'); + + $result = null; + + if (!is_numeric($semester)) + { + $result = $this->StudiensemesterModel->loadWhere(array('start <=' => 'NOW()', 'ende >=' => 'NOW()')); + } + + if (!hasData($result)) + { + $this->StudiensemesterModel->addOrder('ende'); + $this->StudiensemesterModel->addLimit(1); + + $whereArray = array('ende >=' => 'NOW()'); + + if (is_numeric($semester)) + { + if ($semester % 2 == 0) + { + $ss = 'SS'; + } + else + { + $ss = 'WS'; + } + + $whereArray['SUBSTRING(studiensemester_kurzbz FROM 1 FOR 2) ='] = $ss; + } + + $result = $this->StudiensemesterModel->loadWhere($whereArray); + } + + if (isError($result)) { + $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + } + + $this->terminateWithSuccess((getData($result) ?: '')); + } +} diff --git a/application/controllers/codex/UHSTAT1.php b/application/controllers/codex/UHSTAT1.php index 38b0f3b6d..ff59ef41a 100644 --- a/application/controllers/codex/UHSTAT1.php +++ b/application/controllers/codex/UHSTAT1.php @@ -5,8 +5,12 @@ if (! defined("BASEPATH")) exit("No direct script access allowed"); class UHSTAT1 extends FHC_Controller { const BERECHTIGUNG_UHSTAT_VERWALTEN = 'student/uhstat1daten_verwalten'; + const LOGIN_SESSION_INDEX = 'bewerbung/user'; const PERSON_ID_SESSION_INDEX = 'bewerbung/personId'; const CODEX_OESTERREICH = 'A'; + const CODEX_UNKNOWN_YEAR = 9999; + const CODEX_UNKNOWN_NATION = 'XXX'; + const CODEX_UNKNOWN_BILDUNGMAX = 999; const LOWER_BOUNDARY_YEARS = 160; const UPPER_BOUNDARY_YEARS = 20; @@ -210,7 +214,9 @@ class UHSTAT1 extends FHC_Controller else return true; - if (!isset($bildungsstaat)) return true; + // if no Bildungsstaat or Bildungmax unknown - valid + if (!isset($bildungsstaat) || $bildungmax == self::CODEX_UNKNOWN_BILDUNGMAX) return true; + // find out if abschluss is in Austria $this->AbschlussModel->addSelect("in_oesterreich"); @@ -219,8 +225,11 @@ class UHSTAT1 extends FHC_Controller if (hasData($abschlussRes)) { $in_oesterreich = getData($abschlussRes)[0]->in_oesterreich; - // invalid if abschluss in Austria, but not Bildungsstaat, or abschluss not in Austria, but Bildungsstaat in Austria - return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH) || (!$in_oesterreich && $bildungsstaat != self::CODEX_OESTERREICH); + + // valid if Bildungsstaat and Abschluss in Austria, or Bildungsstaat and Abschluss not in Austria + // (or Abschluss not in Austria and Bildungsstaat unknown) + return ($in_oesterreich && $bildungsstaat == self::CODEX_OESTERREICH) + || (!$in_oesterreich && ($bildungsstaat != self::CODEX_OESTERREICH || $bildungsstaat == self::CODEX_UNKNOWN_NATION)); } return false; @@ -367,7 +376,7 @@ class UHSTAT1 extends FHC_Controller $formMetaData['jahre'] = array_combine($yearRange, $yearRange); // add "unknown" option - $formMetaData['jahre'][9999] = 'unbekannt'; + $formMetaData['jahre'][self::CODEX_UNKNOWN_YEAR] = 'unbekannt'; return success($formMetaData); } @@ -415,7 +424,10 @@ class UHSTAT1 extends FHC_Controller private function _getValidPersonId($berechtigungsArt) { // if coming from bewerbungstool - person id is in session (person must be logged in bewerbungstool) - if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX]) && is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX])) + if (isset($_SESSION[self::PERSON_ID_SESSION_INDEX]) + && is_numeric($_SESSION[self::PERSON_ID_SESSION_INDEX]) + && isset($_SESSION[self::LOGIN_SESSION_INDEX]) + ) return $_SESSION[self::PERSON_ID_SESSION_INDEX]; // if person id passed directly... diff --git a/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php new file mode 100644 index 000000000..b1ab2fe26 --- /dev/null +++ b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php @@ -0,0 +1,45 @@ + 'lehre/lehrveranstaltung:rw', + ) + ); + + // Load libraries + $this->load->library('AuthLib'); + + + // Load language phrases + $this->loadPhrases( + array( + 'global', + 'lehre' + ) + ); + + $this->_setAuthUID(); + } + + public function index() + { + $this->load->view('lehre/lvplanung/lvTemplateUebersicht.php'); + } + + + /** + * Retrieve the UID of the logged user and checks if it is valid + */ + private function _setAuthUID() + { + $this->_uid = getAuthUID(); + + if (!$this->_uid) show_error('User authentification failed'); + } +} \ No newline at end of file diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index cefd147b9..de8ebc5c9 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -15,6 +15,297 @@ class Lehrveranstaltung_model extends DB_Model $this->load->model('organisation/studiensemester_model', 'StudiensemesterModel'); } + /** + * Get Lehrveranstaltungen by eventQuery string. Use with autocomplete event queries. + * @param $eventQuery String + * @param string $studiensemester_kurzbz Filter by Studiensemester + * @param array $oes Filter by Organisationseinheiten + * @return array + */ + public function getAutocompleteSuggestions($eventQuery, $studiensemester_kurzbz = null, $oes = null) + { + $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes); + $params = []; + + /* filter by input string */ + if (is_string($eventQuery)) { + $subQry.= ' AND lv.bezeichnung ILIKE ?'; + $params[] = '%' . $eventQuery . '%'; + } + + $qry = 'SELECT DISTINCT ON (lehrveranstaltung_id) * FROM ('. $subQry. ') AS tmp'; + + return $this->execQuery($qry, $params); + } + + /** + * Get Lehrveranstaltungen with its Stg, OE and OE-type. + * Filter by Studiensemester and Organisationseinheiten if necessary. + * @param $eventQuery String + * @param string $studiensemester_kurzbz Filter by Studiensemester + * @param array $oes Filter by Organisationseinheiten + * @param array $lv_ids Filter by Lehrveranstaltung-Ids + * @return array + */ + public function getLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lv_ids = null) + { + $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes); + $qry = 'SELECT * FROM ('. $subQry. ') AS tmp'; + + if (isset($lv_ids) && is_array($lv_ids)) + { + /* filter by lv_ids */ + $implodedLvIds = "'". implode("', '", $lv_ids). "'"; + $qry.= ' WHERE lehrveranstaltung_id IN ('. $implodedLvIds. ')'; + } + + $qry.= ' ORDER BY stg_typ_kurzbz, orgform_kurzbz DESC'; + + return $this->execQuery($qry); + } + + /** + * Get basic query to retrieve Lehrveranstaltungen according to the Orgforms and Ausbildungssemesters actual Studienplan. + * + * @return string + */ + private function _getQryLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lehrtyp_kurzbz = 'lv') + { + $qry = ' + SELECT + lv.oe_kurzbz AS lv_oe_kurzbz, + CASE + WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung) + WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung) + ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung) + END AS lv_oe_bezeichnung, + stplsem.studiensemester_kurzbz, + studienordnung_id, + sto.studiengang_kz, + stpl.studienplan_id, + stplsem.semester, + stpl.orgform_kurzbz, + upper(stg.typ || stg.kurzbz) AS stg_typ_kurzbz, + stg.bezeichnung AS stg_bezeichnung, + stgtyp.bezeichnung AS stg_typ_bezeichnung, + lv.lehrveranstaltung_id, + lv.semester, + lv.bezeichnung AS lv_bezeichnung, + ( + -- comma seperated string of all lehreinheitgruppen + SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung + FROM( + -- distinct bezeichnung, as may come multiple times from different lehreinheiten + SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM + ( + -- distinct lehreinheitgruppe, as may come multiple times from different lehrform + SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz, + -- get Spezialgruppe or Lehrverbandgruppe + COALESCE( + legr.gruppe_kurzbz, + CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe ) + ) as bezeichnung + FROM lehre.tbl_lehreinheitgruppe legr + JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id) + JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz + WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id + AND le.studiensemester_kurzbz = stplsem.studiensemester_kurzbz + ) AS lehreinheitgruppen + GROUP BY studiengang_kz, bezeichnung + ORDER BY studiengang_kz DESC + ) AS uniqueLehreinheitgruppen_bezeichnung + ) AS lehreinheitgruppen_bezeichnung + FROM + lehre.tbl_studienplan stpl + JOIN lehre.tbl_studienordnung sto USING (studienordnung_id) + JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id) + JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester) + JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz) + JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz + JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ + /* filter by lehrtyp_kurzbz, default is lvs only */ + WHERE + lehrtyp_kurzbz = '. $this->db->escape($lehrtyp_kurzbz); + + if (isset($studiensemester_kurzbz) && is_string($studiensemester_kurzbz)) + { + /* filter by studiensemester */ + $qry.= ' AND stplsem.studiensemester_kurzbz = '. $this->db->escape($studiensemester_kurzbz); + + } + + if (isset($oes) && is_array($oes)) + { + /* filter by organisationseinheit */ + $implodedOes = "'". implode("', '", $oes). "'"; + $qry.= ' AND lv.oe_kurzbz IN ('. $implodedOes. ')'; + } + + return $qry; + } + + /** + * Get all Templates and union with all Lehrveranstaltungen of given Studiensemester and Oes, that are assigned to + * a template. This data structure can be used for nested tabulator data tree. + * + * @param null|string $studiensemester_kurzbz + * @param null|array $oes + * @return array|stdClass|null + */ + public function getTemplateLvTree($studiensemester_kurzbz = null, $oes = null){ + $params = []; + $qry = ' + WITH + -- All Lvs that are assigned to a template in given Studiensemester for given Oes + -- joining via actual Studienplan + standardisierteLvs AS ( + SELECT + lv.*, + stpl.studienplan_id::text as studienplan_id, + stpl.bezeichnung AS studienplan_bezeichnung, + stplsem.studiensemester_kurzbz + FROM + lehre.tbl_studienplan stpl + JOIN lehre.tbl_studienordnung sto USING (studienordnung_id) + JOIN lehre.tbl_studienplan_semester stplsem USING (studienplan_id) + JOIN lehre.tbl_studienplan_lehrveranstaltung stpllv ON (stpllv.studienplan_id = stpl.studienplan_id AND stpllv.semester = stplsem.semester) + JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz) + JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz + JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ + WHERE + -- filter type lv + lehrtyp_kurzbz = \'lv\' + -- filter lvs assigned to template (= standardisierte lv) + AND lehrveranstaltung_template_id IS NOT NULL'; + + if (is_string($studiensemester_kurzbz)) + { + /* filter by studiensemester */ + $params[]= $studiensemester_kurzbz; + $qry.= ' AND stplsem.studiensemester_kurzbz = ? '; + + } + + if (is_array($oes)) + { + /* filter by organisationseinheit */ + $params[]= $oes; + $qry.= ' AND lv.oe_kurzbz IN ? '; + } + $qry.= ' + ), + -- All templates + templateLvs AS ( + SELECT + lv.*, + NULL AS studienplan_id, + ( + SELECT string_agg(stpl_bezeichnung, \', \') + FROM + ( + SELECT stlv.studienplan_bezeichnung AS stpl_bezeichnung + FROM standardisierteLvs stlv + WHERE stlv.lehrveranstaltung_template_id = lv.lehrveranstaltung_id + ) AS studienplaene + ) AS studienplan_bezeichnung, + NULL AS studiensemester_kurzbz + FROM + lehre.tbl_lehrveranstaltung lv + WHERE + -- filter type template + lehrtyp_kurzbz = \'tpl\' + -- filter semester that were retrieved by standardisierte lvs semester for selected studiensemester + AND EXISTS ( + SELECT 1 + FROM standardisierteLvs std + WHERE std.lehrveranstaltung_template_id = lv.lehrveranstaltung_id + )'; + + if (is_array($oes)) + { + /* filter by organisationseinheit */ + $params[]= $oes; + $qry.= ' AND lv.oe_kurzbz IN ? '; + } + $qry.= ' + ) + '; + + $qry.= ' + SELECT + lv.lehrveranstaltung_id, + lv.kurzbz, + lv.lehrtyp_kurzbz, + lv.bezeichnung AS lv_bezeichnung, + lv.bezeichnung_english, + lv.studiengang_kz, + lv.semester, + lv.oe_kurzbz, + lv.ects, + lv.lehrform_kurzbz, + lv.orgform_kurzbz, + lv.sprache, + lv.aktiv, + lv.lehrveranstaltung_template_id, + lv.studienplan_id, + lv.studienplan_bezeichnung, + lv.studiensemester_kurzbz, + upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz", + stg.bezeichnung AS "stg_bezeichnung", + stgtyp.bezeichnung AS "stg_typ_bezeichnung", + CASE + WHEN oe.organisationseinheittyp_kurzbz = \'Kompetenzfeld\' THEN (\'KF \' || oe.bezeichnung) + WHEN oe.organisationseinheittyp_kurzbz = \'Department\' THEN (\'DEP \' || oe.bezeichnung) + ELSE (oe.organisationseinheittyp_kurzbz || \' \' || oe.bezeichnung) + END AS "lv_oe_bezeichnung", + ( + -- comma seperated string of all lehreinheitgruppen + SELECT string_agg(bezeichnung, \', \') AS lehreinheitgruppe_bezeichnung + FROM( + -- distinct bezeichnung, as may come multiple times from different lehreinheiten + SELECT DISTINCT ON (studiengang_kz, bezeichnung) studiengang_kz, bezeichnung FROM + ( + -- distinct lehreinheitgruppe, as may come multiple times from different lehrform + SELECT DISTINCT ON (legr.lehreinheitgruppe_id) legr.studiengang_kz, + -- get Spezialgruppe or Lehrverbandgruppe + COALESCE( + legr.gruppe_kurzbz, + CONCAT( UPPER(stg1.typ), UPPER(stg1.kurzbz), \'-\', legr.semester, legr.verband, legr.gruppe ) + ) as bezeichnung + FROM lehre.tbl_lehreinheitgruppe legr + JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung lv1 USING (lehrveranstaltung_id) + JOIN public.tbl_studiengang stg1 ON stg1.studiengang_kz = legr.studiengang_kz + WHERE lv1.lehrveranstaltung_id = lv.lehrveranstaltung_id + AND le.studiensemester_kurzbz = lv.studiensemester_kurzbz + ) AS lehreinheitgruppen + GROUP BY studiengang_kz, bezeichnung + ORDER BY studiengang_kz DESC + ) AS uniqueLehreinheitgruppen_bezeichnung + ) AS lehreinheitgruppen_bezeichnung + FROM ( + SELECT + * + FROM + standardisierteLvs + UNION + SELECT + * + FROM templateLvs + ) AS lv + JOIN public.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz + JOIN public.tbl_studiengangstyp stgtyp ON stgtyp.typ = stg.typ + JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = lv.oe_kurzbz + ORDER BY + oe.bezeichnung, lv.semester, lv.bezeichnung + '; + + return $this->execQuery($qry, $params); + } + /** * Gets unique Groupstrings for Lehrveranstaltungen, e.g. WS2018_BIF_1_PRJM_VZ_LV12345 * @param string $studiensemester_kurzbz diff --git a/application/models/education/Lvgesamtnote_model.php b/application/models/education/Lvgesamtnote_model.php index f0c1883de..975833287 100644 --- a/application/models/education/Lvgesamtnote_model.php +++ b/application/models/education/Lvgesamtnote_model.php @@ -10,5 +10,6 @@ class Lvgesamtnote_model extends DB_Model parent::__construct(); $this->dbTable = 'campus.tbl_lvgesamtnote'; $this->pk = array('student_uid', 'studiensemester_kurzbz', 'lehrveranstaltung_id'); + $this->hasSequence = false; } } diff --git a/application/models/education/Studierendenantrag_model.php b/application/models/education/Studierendenantrag_model.php index e138d1a1c..7595d8036 100644 --- a/application/models/education/Studierendenantrag_model.php +++ b/application/models/education/Studierendenantrag_model.php @@ -96,7 +96,8 @@ class Studierendenantrag_model extends DB_Model Studierendenantragstatus_model::STATUS_REJECTED, Studierendenantragstatus_model::STATUS_OBJECTION_DENIED, Studierendenantragstatus_model::STATUS_DEREGISTERED, - Studierendenantragstatus_model::STATUS_PAUSE + Studierendenantragstatus_model::STATUS_PAUSE, + Studierendenantragstatus_model::STATUS_REMINDERSENT ]); $this->db->or_group_start(); $this->db->where('s.studierendenantrag_statustyp_kurzbz', Studierendenantragstatus_model::STATUS_APPROVED); diff --git a/application/models/organisation/Geschaeftsjahr_model.php b/application/models/organisation/Geschaeftsjahr_model.php index 4f0d03b73..fdd774a8c 100644 --- a/application/models/organisation/Geschaeftsjahr_model.php +++ b/application/models/organisation/Geschaeftsjahr_model.php @@ -32,11 +32,20 @@ class Geschaeftsjahr_model extends DB_Model * Gets next Geschaeftsjahr, as determined by its start date * @return array|null */ - public function getNextGeschaeftsjahr() + public function getNextGeschaeftsjahr($offsetDays=null) { $query = 'SELECT * - FROM public.tbl_geschaeftsjahr - WHERE start > now() + FROM public.tbl_geschaeftsjahr WHERE '; + + if(!is_null($offsetDays)) + { + $query .= "start > now() - '".$offsetDays." days'::interval"; + } + else + { + $query .= 'start > now()'; + } + $query .= ' ORDER BY start LIMIT 1'; diff --git a/application/models/organisation/Studienjahr_model.php b/application/models/organisation/Studienjahr_model.php index 3bbe3a07f..a6e1bc575 100644 --- a/application/models/organisation/Studienjahr_model.php +++ b/application/models/organisation/Studienjahr_model.php @@ -29,4 +29,54 @@ class Studienjahr_model extends DB_Model return $this->execQuery($query); } + + /** + * Get the current Studienjahr. During the summer term, continue using the previous Studienjahr. + * + * @param int $days + * @return array|stdClass|null + */ + public function getLastOrAktStudienjahr($days = 60) + { + if (!is_numeric($days)) + { + $days = 60; + } + + $query = ' + SELECT * + FROM public.tbl_studienjahr + JOIN public.tbl_studiensemester USING (studienjahr_kurzbz) + WHERE start < NOW() - \'' . $days . ' DAYS\'::INTERVAL + ORDER by start DESC + LIMIT 1 + '; + + return $this->execQuery($query); + } + + /** + * Get the current Studienjahr. During the summer term, get the upcoming next Studienjahr. + * + * @param int $days + * @return array|stdClass|null + */ + public function getAktOrNextStudienjahr($days = 62) + { + if (!is_numeric($days)) + { + $days = 62; + } + + $query = ' + SELECT * + FROM public.tbl_studienjahr + JOIN public.tbl_studiensemester using(studienjahr_kurzbz) + WHERE start < NOW() + \'' . $days . ' DAYS\'::INTERVAL + ORDER by start DESC + LIMIT 1 + '; + + return $this->execQuery($query); + } } diff --git a/application/models/system/Recipient_model.php b/application/models/system/Recipient_model.php index d74d03243..1c7811f93 100644 --- a/application/models/system/Recipient_model.php +++ b/application/models/system/Recipient_model.php @@ -327,7 +327,7 @@ class Recipient_model extends DB_Model pr.nachname, ms.person_id, mrou.token - ORDER BY sent DESC'; + ORDER BY sent DESC LIMIT 1500'; return $this->execQuery($sql, array($person_id, $functions, $person_id)); } diff --git a/application/views/lehre/lvplanung/lvTemplateUebersicht.php b/application/views/lehre/lvplanung/lvTemplateUebersicht.php new file mode 100644 index 000000000..5c873486c --- /dev/null +++ b/application/views/lehre/lvplanung/lvTemplateUebersicht.php @@ -0,0 +1,29 @@ + 'LV Template Übersicht', + 'vue3' => true, + 'axios027' => true, + 'bootstrap5' => true, + 'tabulator5' => true, + 'fontawesome6' => true, + 'primevue3' => true, + 'navigationcomponent' => true, + 'filtercomponent' => true, + 'customJSModules' => array('public/js/apps/lehre/lvplanung/LvTemplates.js'), + 'customCSSs' => array( + 'public/css/Fhc.css', + 'public/css/lvTemplateUebersicht.css' + ) +); + +$this->load->view('templates/FHC-Header', $includesArray); +?> + +
+ + + + +
+ +load->view('templates/FHC-Footer', $includesArray); ?> diff --git a/include/tw/vilesci_menu_main.inc.php b/include/tw/vilesci_menu_main.inc.php index 2aa2e67d3..2a1ca74ae 100644 --- a/include/tw/vilesci_menu_main.inc.php +++ b/include/tw/vilesci_menu_main.inc.php @@ -70,6 +70,7 @@ $menu=array 'link'=>'left.php?categorie=Lehre', 'target'=>'nav', 'Gruppenverwaltung'=>array('name'=>'Gruppen', 'permissions'=>array('admin','lv-plan','support','lehre/gruppe'), 'link'=>'stammdaten/lvbgruppenverwaltung.php', 'target'=>'main'), 'Lehrveranstaltung'=>array('name'=>'Lehrveranstaltung', 'link'=>'lehre/lehrveranstaltung_frameset.html', 'target'=>'main'), + 'lvTemplateUebersicht'=>array('name'=>'LV-Template Übersicht', 'link'=>'../index.ci.php/lehre/lvplanung/LvTemplateUebersicht', 'target'=>'_blank'), 'Studienordnung'=>array('name'=>'Studienordnung', 'link'=>'lehre/studienordnung.php', 'target'=>'_blank','permissions'=>array('lehre/studienordnung')), 'StudienplanGueltigkeit'=>array('name'=>'Studienplan Gültigkeit', 'link'=>'lehre/studienplan_gueltigkeit.php', 'target'=>'main','permissions'=>array('lehre/studienordnung')), 'StudienplanVorruecken'=>array('name'=>'Studienplan vorrücken', 'link'=>'lehre/studienplan_vorrueckung.php', 'target'=>'main','permissions'=>array('lehre/studienplan')), diff --git a/public/css/lvTemplateUebersicht.css b/public/css/lvTemplateUebersicht.css new file mode 100644 index 000000000..af279b8cb --- /dev/null +++ b/public/css/lvTemplateUebersicht.css @@ -0,0 +1,3 @@ +html { + font-size: .75em; +} \ No newline at end of file diff --git a/public/js/apps/lehre/lvplanung/LvTemplates.js b/public/js/apps/lehre/lvplanung/LvTemplates.js new file mode 100644 index 000000000..b6ad3ae81 --- /dev/null +++ b/public/js/apps/lehre/lvplanung/LvTemplates.js @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2023 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import LvTemplateUebersicht from '../../../lehre/lvplanung/LvTemplateUebersicht.js'; +import {CoreNavigationCmpt} from '../../../components/navigation/Navigation.js'; +import FhcAlert from '../../../plugin/FhcAlert.js'; +import FhcApi from "../../../plugin/FhcApi.js"; +import Phrasen from "../../../plugin/Phrasen.js"; + + +const lvTemplatesApp = Vue.createApp({ + components: { + CoreNavigationCmpt, + LvTemplateUebersicht + } +}); + +lvTemplatesApp + .use(primevue.config.default,{zIndex: {overlay: 9999}}) + .use(FhcAlert) + .use(FhcApi) + .use(Phrasen) + .mount('#main') \ No newline at end of file diff --git a/public/js/lehre/lvplanung/LvTemplateUebersicht.js b/public/js/lehre/lvplanung/LvTemplateUebersicht.js new file mode 100644 index 000000000..be0da75b8 --- /dev/null +++ b/public/js/lehre/lvplanung/LvTemplateUebersicht.js @@ -0,0 +1,289 @@ +import {CoreFilterCmpt} from '../../components/filter/Filter.js'; +import CoreFormInput from "../../components/Form/Input.js"; + +// Fields used to restructure table data for dataTree +const idField = 'lehrveranstaltung_id'; +const parentIdField = 'lehrveranstaltung_template_id'; +const STUDIENSEMESTER_DROPDOWN_STARTDATE = '2011-01-01'; + +export default { + components: { + CoreFilterCmpt, + CoreFormInput + }, + data: function() { + return { + table: null, + studiensemester: [], + selectedStudiensemester: '', + cbDataTreeStartExpanded: false // checkbox expand dataTree or not + } + }, + computed: { + tabulatorOptions() { + const fhcValuesLookup = function(cell) { + var values = {}; + const field = cell.getField(); + const data = cell.getTable().getData(); + const collectvalues = function(rows, field) { + var values = {}; + var childvalues = {}; + for(const row of rows) { + const rowvalue = (row[field] !== null) ? row[field] : ''; + values[rowvalue] = rowvalue; + if(row['_children'] && row['_children'].length > 0) { + childvalues = collectvalues(row['_children'], field); + values = {...values, ...childvalues} + } + } + return values; + } + values = collectvalues(data, field); + const vals = Object.keys(values).sort(); + if(vals.indexOf('') === -1) { + vals.unshift(''); + } + return vals; + }; + const fhctreefilter = function(headerValue, rowValue, rowData, filterParams){ + if (rowData['_children'] && rowData['_children'].length > 0) { + for (var i in rowData['_children']) { + return rowValue == headerValue || + fhctreefilter( + headerValue, + rowData['_children'][i][filterParams.field], + rowData['_children'][i], + filterParams + ); + } + } + + return rowValue == headerValue; + }; + const self = this; + return { + // NOTE: data is set on table built to await preselected actual Studiensemester + ajaxResponse(url, params, response) { + return self.prepDataTreeData(response.data) // Prepare data for dataTree view + }, + layout: 'fitColumns', + autoResize: false, // prevent auto resizing of table + resizableColumnFit: true, //maintain the fit of columns when resizing + index: 'lehrveranstaltung_id', + selectable: true, + selectableRangeMode: 'click', + dataTree: true, + dataTreeStartExpanded: self.cbDataTreeStartExpanded, + dataTreeChildIndent: 15, //indent child rows by 15 px + persistence:{ + filter: false, //persist filter sorting + }, + columns: [ + {title: 'LV-ID', field: 'lehrveranstaltung_id', headerFilter: true, visible: false}, + {title: 'LV Kurzbz', field: 'kurzbz', headerFilter: true, visible:false, width: 70}, + {title: 'STG Kurzbz', field: 'stg_typ_kurzbz', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'stg_typ_kurzbz'}, visible:true, width: 80}, + {title: 'OrgEinheit', field: 'lv_oe_bezeichnung', headerFilter: true, visible: false, width: 250}, + {title: 'Lehrtyp Kurzbz', field: 'lehrtyp_kurzbz', headerFilter: true, visible:false, width: 70}, + {title: 'Studiengangtyp', field: 'stg_typ_bezeichnung', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'stg_typ_bezeichnung'}, width: 150}, + {title: 'OrgForm', field: 'orgform_kurzbz', headerFilter: "list", headerFilterParams: {valuesLookup: fhcValuesLookup}, headerFilterFunc: fhctreefilter, headerFilterFuncParams: {field: 'orgform_kurzbz'}, width: 70}, + {title: 'Semester', field: 'semester', headerFilter: true, width: 50}, + {title: 'Lehrveranstaltung', field: 'lv_bezeichnung', headerFilter: true, minWidth: 250}, + {title: 'Lehrveranstaltung ENG', field: 'bezeichnung_english', headerFilter: true, minWidth: 250}, + {title: 'ECTS', field: 'ects', headerFilter: true, width: 50, hozAlign: 'right'}, + {title: 'Lehrform', field: 'lehrform_kurzbz', headerFilter: true, width: 50}, + {title: 'Sprache', field: 'sprache', headerFilter: true, width: 100}, + {title: 'Aktiv', field: 'aktiv', width: 50, + formatter:"tickCross", + headerFilter:"tickCross", + headerFilterParams:{"tristate": true}, + hozAlign:"center", + formatterParams: { + tickElement: '', + crossElement: '' + } + }, + {title: 'Studienplan', field: 'studienplan_bezeichnung', headerFilter: true, visible:true, width: 220}, + {title: 'OE Kurzbz', field: 'lv_oe_kurzbz', headerFilter: true, visible:false, minWidth: 80}, + { + title: this.$p.t('global/aktionen'), + field: 'actions', + width: 140, + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary'; + button.innerHTML = ' ' + this.$p.t('global/verwalten'); + button.addEventListener('click', (event) => this.openAdminLvTemplate(event, cell.getRow())); + container.append(button); + + return container; + }, + frozen: true + } + ] + } + }, + urlToAdminAllTemplates() { + return FHC_JS_DATA_STORAGE_OBJECT.app_root + + 'vilesci/lehre/lehrveranstaltung.php?stg_kz=99999&semester=-1&orgform=-1'; + } + }, + methods: { + async loadAndSetStudiensemester(){ + const result = await this.$fhcApi + .get('api/frontend/v1/organisation/Studiensemester/getAll', {start: STUDIENSEMESTER_DROPDOWN_STARTDATE}) + .then(result => this.studiensemester = result.data ) + .then(() => this.$fhcApi.get('api/frontend/v1/organisation/Studiensemester/getAktNext') ) // Get actual Studiensemester + .then(result => this.selectedStudiensemester = result.data[0].studiensemester_kurzbz ) // Preselect Studiensemester + .catch(error => this.$fhcAlert.handleSystemError(error) ); + }, + async onTableBuilt(){ + + this.table = this.$refs.lvTemplateUebersichtTable.tabulator; + + // Await Studiensemester + await this.loadAndSetStudiensemester(); + + // Set table data + this.table.setData( + this.$fhcApi.getUri() + + '/api/frontend/v1/education/Lehrveranstaltung/getTemplateLvTree' + + '?studiensemester_kurzbz=' + this.selectedStudiensemester + ); + + // Await phrases categories + await this.$p.loadCategory(['lehre']); + + // Replace column titles with phrasen + this.table.updateColumnDefinition('lv_bezeichnung', {title: this.$p.t('lehre', 'lehrveranstaltung')}); + + }, + onChangeStudiensemester(){ + // Reset table data + this.table.setData( + this.$fhcApi.getUri() + + '/api/frontend/v1/education/Lehrveranstaltung/getTemplateLvTree' + + '?studiensemester_kurzbz=' + this.selectedStudiensemester + ); + }, + openAdminLvTemplate(event, row){ + const url = FHC_JS_DATA_STORAGE_OBJECT.app_root + + 'vilesci/lehre/lehrveranstaltung.php?stg_kz=&semester=-1&orgform=-1&lehrveranstaltung_id=' + + row.getData().lehrveranstaltung_id; + + window.open(url, '_blank').focus(); + }, + prepDataTreeData(data){ + let toDelete = []; + + // loop through all data + for (let childIdx = 0; childIdx < data.length; childIdx++) + { + let child = data[childIdx]; + + // if it has parent id, it is a child + if (child[parentIdField]) + { + // append the child on the right place. If parent found, mark original sw child on 0 level for deleting + if (this._appendChild(data, child)) toDelete.push(childIdx); + } + } + + // delete the marked children from 0 level + for (let counter = 0; counter < toDelete.length; counter++) + { + // decrease index by counter as index of data array changes after every deletion + data.splice(toDelete[counter] - counter, 1); + } + + return data; + }, + _appendChild(data, child) { + // get parent id + let parentId = child[parentIdField]; + + // loop thorugh all data + for (let parentIdx = 0; parentIdx < data.length; parentIdx++) + { + let parent = data[parentIdx]; + + // if it's the parent + if (parent[idField] == parentId) + { + // create children array if not done yet + if (!parent._children) parent._children = []; + + // if child is not included in children array, append the child + if (!parent._children.includes(child)) parent._children.push(child); + + // parent found + return true; + } + // search children for parents + else if (parent._children) this._appendChild(parent._children, child); + } + + // parent not found + return false; + }, + reloadTabulator() { + if (this.table !== null && this.table !== undefined) + { + for (let option in this.tabulatorOptions) + { + if (this.table.options.hasOwnProperty(option)) + this.table.options[option] = this.tabulatorOptions[option]; + } + this.$refs.lvTemplateUebersichtTable.reloadTable(); + } + }, + }, + template: ` +
+
+
{{ $p.t('lehre/lvTemplatesUebersicht') }}
+
+ + + +
+
+
+
+ + + +
+
+ +
+` +}; diff --git a/system/dbupdate_3.4/41150_oe-pfad_db_view.php b/system/dbupdate_3.4/41150_oe-pfad_db_view.php index c108fcd77..65686dbcb 100644 --- a/system/dbupdate_3.4/41150_oe-pfad_db_view.php +++ b/system/dbupdate_3.4/41150_oe-pfad_db_view.php @@ -1,15 +1,11 @@ db_query("SELECT * FROM information_schema.views WHERE table_catalog = '" . DB_NAME . "' AND table_schema = 'public' AND table_name = 'vw_oe_path'")) -{ - if($db->db_num_rows($result) == 0) - { - $qry = " +$qry = " CREATE OR REPLACE VIEW public.vw_oe_path AS - WITH RECURSIVE vw_oe_path(oe_kurzbz, bezeichnung, oe_parent_kurzbz, organisationseinheittyp_kurzbz, oetyp_bezeichnung, depth, path) AS ( + WITH RECURSIVE vw_oe_path(oe_kurzbz, bezeichnung, oe_parent_kurzbz, organisationseinheittyp_kurzbz, oetyp_bezeichnung, depth, path, path_kurzbz) AS ( SELECT - oe.oe_kurzbz, oe.bezeichnung, oe.oe_parent_kurzbz, oe.organisationseinheittyp_kurzbz, oetyp.bezeichnung AS oetyp_bezeichnung, 0, '/' || oetyp.bezeichnung || ' ' || oe.bezeichnung AS path + oe.oe_kurzbz, oe.bezeichnung, oe.oe_parent_kurzbz, oe.organisationseinheittyp_kurzbz, oetyp.bezeichnung AS oetyp_bezeichnung, 0, '/' || oetyp.bezeichnung || ' ' || oe.bezeichnung AS path, '/' || oe.oe_kurzbz AS path_kurzbz FROM public.tbl_organisationseinheit oe JOIN @@ -18,7 +14,7 @@ if ($result = $db->db_query("SELECT * FROM information_schema.views WHERE table_ oe.oe_parent_kurzbz IS NULL UNION ALL SELECT - oe.oe_kurzbz, oe.bezeichnung, oe.oe_parent_kurzbz, oe.organisationseinheittyp_kurzbz, oetyp.bezeichnung AS oetyp_bezeichnung, depth + 1, oet.path || '/' || oetyp.bezeichnung || ' ' || oe.bezeichnung + oe.oe_kurzbz, oe.bezeichnung, oe.oe_parent_kurzbz, oe.organisationseinheittyp_kurzbz, oetyp.bezeichnung AS oetyp_bezeichnung, depth + 1, oet.path || '/' || oetyp.bezeichnung || ' ' || oe.bezeichnung, oet.path_kurzbz || '/' || oe.oe_kurzbz AS path_kurzbz FROM public.tbl_organisationseinheit oe, vw_oe_path oet JOIN @@ -29,11 +25,27 @@ if ($result = $db->db_query("SELECT * FROM information_schema.views WHERE table_ SELECT * FROM vw_oe_path ORDER BY path, depth; GRANT SELECT ON public.vw_oe_path TO vilesci; - "; - +"; + + +if ($result = $db->db_query("SELECT * FROM information_schema.views WHERE table_catalog = '" . DB_NAME . "' AND table_schema = 'public' AND table_name = 'vw_oe_path'")) +{ + if($db->db_num_rows($result) == 0) + { if (!$db->db_query($qry)) echo 'public.vw_oe_path: ' . $db->db_last_error() . '
'; else echo 'public.vw_oe_path: erstellt
'; } } + +if ($result = $db->db_query("SELECT * FROM information_schema.columns WHERE table_catalog = '" . DB_NAME . "' AND table_schema = 'public' AND table_name = 'vw_oe_path' AND column_name = 'path_kurzbz'")) +{ + if($db->db_num_rows($result) == 0) + { + if (!$db->db_query($qry)) + echo 'public.vw_oe_path: ' . $db->db_last_error() . '
'; + else + echo 'public.vw_oe_path: neu erstellt mit zusätzlicher spalte path_kurzbz
'; + } +} diff --git a/system/filtersupdate.php b/system/filtersupdate.php index e885b4e14..51dd86314 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1298,6 +1298,7 @@ $filters = array( {"name": "os"}, {"name": "lizenzserver_kurzbz"}, {"name": "lizenzserver_port"}, + {"name": "anzahl_lizenzen"}, {"name": "softwarestatus_kurzbz"} ], "filters": [] diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 7019892e0..7ef0269c9 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -9987,13 +9987,13 @@ Any unusual occurrences 'phrases' => array( array( 'sprache' => 'German', - 'text' => 'Der Plagiatscheck wurde durchgeführt und bestätigt, dass der zentrale Inhalt der Arbeit im erforderlichen Ausmaß eigenständig verfasst wurde (vgl. Satzungsteil Studienrechtliche Bestimmungen / Prüfungsordnung, § 18 Abs. 2 und 3).', + 'text' => 'Der Plagiatscheck wurde durchgeführt und bestätigt, dass der zentrale Inhalt der Arbeit im erforderlichen Ausmaß eigenständig verfasst wurde (vgl. Satzungsteil Studienrechtliche Bestimmungen / Prüfungsordnung, § 20 Abs. 2 und 3).', 'description' => '', 'insertvon' => 'system' ), array( 'sprache' => 'English', - 'text' => 'The plagiarism check has been carried out and confirms that the central content of the thesis has been written independently to the required extent (cf. part of the Statutes on Studies Act Provisions / Examination Regulations, § 18 Para. 2 and 3).', + 'text' => 'The plagiarism check has been carried out and confirms that the central content of the thesis has been written independently to the required extent (cf. part of the Statutes on Studies Act Provisions / Examination Regulations, § 20 Para. 2 and 3).', 'description' => '', 'insertvon' => 'system' ) @@ -18148,6 +18148,26 @@ array( ) ) ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'alledurchgefuehrten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Alle durchgeführten anzeigen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Show all performed', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'international', 'category' => 'international', @@ -18663,6 +18683,366 @@ array( ) ) ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusGeplant', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'geplant', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'planned', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusGeplantDesc', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Studierende hat die Maßnahme geplant.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The student has planned the measure.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusAkzeptiert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'akzeptiert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'accepted', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusAkzeptiertDesc', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die geplante Maßnahme wurde akzeptiert.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The planned measure has been accepted.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusDurchgefuehrt', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'durchgeführt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'performed', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusDurchgefuehrtDesc', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Eine Bestätigung wurde hochgeladen.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'A confirmation has been uploaded.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusBestaetigt', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'bestätigt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'confirmed', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusBestaetigtDesc', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die hochgeladene Bestätigung wurde akzeptiert.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The uploaded confirmation has been accepted.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusAbgelehnt', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'abgelehnt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'declined', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'statusAbgelehntDesc', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die Maßnahme wurde abgelehnt.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The measure was rejected.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'ampelRed', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Es wurden keine Maßnahmen geplant oder alle wurden abgelehnt.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'No measures have been planned, or all have been rejected.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'ampelYellow', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Mindestens eine Maßnahme wurde akzeptiert.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'At least one measure has been accepted.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'ampelOrange', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Es gibt mindestens eine geplante oder durchgeführte Maßnahme.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'There is at least one planned or performed measure.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'ampelGreenyellow', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Nur bestätigte Maßnahmen vorhanden, aber weniger als 5 ECTs.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Only confirmed measures, but fewer than 5 ECTs.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'ampelGreen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Es wurden 5 ECTs erreicht.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => '5 ECTs points have been achieved.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'mailMeldungzuviele', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die Anzahl der Empfänger überschreitet 50. Bitte verwenden Sie einen Filter (z.B. Semester), um die Empfängeranzahl zu reduzieren.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The number of recipients exceeds 50. Please use a filter (e.g., semester) to reduce the number of recipients.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'mailMeldung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Keine Studierenden ohne geplante Maßnahmen gefunden.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'No students without planned measures were found.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'mailButton', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'E-Mail nur an Studierende, die keine Maßnahmen geplant haben.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Send email only to students who have no planned measures.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'international', 'category' => 'international', @@ -18703,6 +19083,26 @@ array( ) ) ), + array( + 'app' => 'international', + 'category' => 'international', + 'phrase' => 'mailversenden', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Mail versenden', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Send mail', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'international', 'category' => 'international', @@ -28798,6 +29198,446 @@ array( ) ), // Betriebsmittel end + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'softwareanforderung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Softwareanforderung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Software Request', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'softwareanforderungSubtitle', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Softwareanforderung und Lizenzmanagement für die Lehre', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Software Request and License management for Education', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'swAnforderungenUndLizenen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Softwareanforderungen & Lizenzen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Software Requirements & Licenses', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'anforderungNachSw', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Anforderung nach Software', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Request by Software', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'anforderungNachLv', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Anforderung nach LV', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Request by Course', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'swNichtGefundenHierBestellen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Software nicht gefunden?
Hier bei IT-Services bestellen", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Software not found?
Order here from IT Services", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'bereitsAngefordert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Bereits angefordert", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Requested already", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'mindEineZuorndungExistiertBereits', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Mindestens eine Zuordnung existiert bereits.", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "At least one assignment already exists.", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'swFuerLvAnfordern', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Software für LV anfordern", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Request software for courses", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'swWurdeBereitsAngefordert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Software wurde bereits angefordert", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Software has already been requested", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'swAnforderungUeberAuswahlVonSw', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Softwareanforderung über die Auswahl von Software", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Software Requirements based on the Selection of Software", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'swAnforderungUeberAuswahlVonLvs', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Softwareanforderung über die Auswahl von Lehrveranstaltungen", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Software Requirements based on the Selection of Courses", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'lizenzAnzahlNeu', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Lizenz-Anzahl NEU", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "License Number NEW", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'lizenzanzahlAendern', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Lizenzanzahl ändern", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Change Number of Licenses", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'eingabeFehlt', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Eingabe fehlt", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Input missing", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'unveraendert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Unverändert", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Unchanged", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'anforderungenVorruecken', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Anforderungen vorrücken", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Take over Requirements", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'vorrueckenInStudiensemester', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Vorrücken in Studiensemester", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Take over to semester", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'softwarebereitstellung', + 'category' => 'global', + 'phrase' => 'anteiligInProzent', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Anteilig in %", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Percentage share", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'verwalten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Verwalten", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Administrate", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'lvTemplatesVerwalten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "LV Templates verwalten", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Administrate Course Templates", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'lehre', + 'phrase' => 'lvTemplatesUebersicht', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "LV Templates Übersicht", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Course Templates Overview", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), //**************************** CORE/konto array( 'app' => 'core', diff --git a/vilesci/lehre/lehreinheiten_vorrueckung.php b/vilesci/lehre/lehreinheiten_vorrueckung.php index 5afe1f3df..49fa02b48 100644 --- a/vilesci/lehre/lehreinheiten_vorrueckung.php +++ b/vilesci/lehre/lehreinheiten_vorrueckung.php @@ -106,7 +106,7 @@ echo ' -

Lehreinheiten Vorrückung

+

LV-Teile Vorrückung

'; echo '
'; echo 'Studiengang:
'; + die (); + } + elseif ($anzahl_von > 0 && $anzahl_nach >= $anzahl_von && !isset($_GET['continue'])) + { + echo '

Es sind schon '.$anzahl_nach.' LV-Teile fuer das '.$stsem_nach.' in '.$stg_arr[$studiengang_kz].' '.$semester.' vorhanden. Trotzdem fortsetzen?

'; @@ -553,15 +561,15 @@ if ($studiengang_kz != '' && $stsem_von != '' && $stsem_nach != '') } else { - $text .= 'Fehler beim Laden der Lehreinheiten '.$db->db_last_error(); + $text .= 'Fehler beim Laden der LV-Teile '.$db->db_last_error(); $error_lehreinheit++; } echo "

"; - echo "Vorgerueckte Lehreinheiten: $anzahl_lehreinheiten
"; + echo "Vorgerueckte LV-Teile: $anzahl_lehreinheiten
"; echo "Vorgerueckte LEMitarbeiter: $anzahl_lehreinheitmitarbeiter
"; echo "Vorgerueckte LEGruppen: $anzahl_lehreinheitgruppe
"; - echo "Fehler bei Lehreinheiten: $error_lehreinheit
"; + echo "Fehler bei LV-Teil: $error_lehreinheit
"; echo "Fehler bei LEMitarbeiter: $error_lehreinheitmitarbeiter
"; echo "Fehler bei LEGruppen: $error_lehreinheitmitarbeiter
";