From 1416e91af747569e533dedb4a925ad23b27d7a69 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Tue, 11 Jul 2023 15:58:48 +0200 Subject: [PATCH 01/54] Issues: Behebung parameter are included in identification of an issue --- application/libraries/IssuesLib.php | 36 +++++++++++++---------- application/models/system/Issue_model.php | 15 +++++++++- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/application/libraries/IssuesLib.php b/application/libraries/IssuesLib.php index 9b3a9de6e..f38303b3c 100644 --- a/application/libraries/IssuesLib.php +++ b/application/libraries/IssuesLib.php @@ -246,7 +246,27 @@ class IssuesLib $fehlertext = vsprintf($fehlertextVorlage, $fehlertext_params); } - $openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount($fehlercode, $person_id, $oe_kurzbz, $fehlercode_extern); + if (isset($resolution_params)) + { + if (is_array($resolution_params)) + { + foreach ($resolution_params as $resolution_key => $resolution_param) + { + if (!is_string($resolution_key)) + return error("Invalid parameter for resolution, must be an associative array"); + } + } + else + return error("Invalid parameters for resolution"); + } + + $openIssuesCountRes = $this->_ci->IssueModel->getOpenIssueCount( + $fehlercode, + $person_id, + $oe_kurzbz, + $fehlercode_extern, + $resolution_params + ); if (hasData($openIssuesCountRes)) { @@ -256,20 +276,6 @@ class IssuesLib if ($openIssueCount == 0) { - if (isset($resolution_params)) - { - if (is_array($resolution_params)) - { - foreach ($resolution_params as $resolution_key => $resolution_param) - { - if (!is_string($resolution_key)) - return error("Invalid parameter for resolution, must be an associative array"); - } - } - else - return error("Invalid parameters for resolution"); - } - // insert new issue return $this->_ci->IssueModel->insert( array( diff --git a/application/models/system/Issue_model.php b/application/models/system/Issue_model.php index ab1f9ba6e..3d39e9879 100644 --- a/application/models/system/Issue_model.php +++ b/application/models/system/Issue_model.php @@ -59,7 +59,7 @@ class Issue_model extends DB_Model * @param string $fehlercode_extern if provided, only issues with this external fehlercode are counted (for identifying issues from external systems). * @return Object success with number of issues or error */ - public function getOpenIssueCount($fehlercode, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null) + public function getOpenIssueCount($fehlercode, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null, $behebung_parameter = null) { $params = array($fehlercode); // issue exists for a fehlercode (or fehlercode_extern), person_id, oe_kurzbz, if not verarbeitet yet @@ -85,6 +85,19 @@ class Issue_model extends DB_Model $params[] = $oe_kurzbz; } + if (isset($behebung_parameter) && !isEmptyArray($behebung_parameter)) + { + // convert array to JSON string for postgres + $behebung_parameter_string = json_encode($behebung_parameter); + + if ($behebung_parameter_string) + { + // check if jsonb value is equal to the passed parameters array (if value contains array and array contains value) + $qry .= ' AND behebung_parameter @> ? AND behebung_parameter <@ ?'; + $params = array_merge($params, array($behebung_parameter_string, $behebung_parameter_string)); + } + } + return $this->execQuery($qry, $params); } } From b1e85fe92b8bb185ce9d0786facd947c0640e669 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Wed, 24 Apr 2024 14:18:55 +0200 Subject: [PATCH 02/54] - international skills auf vuejs - note uebernehmen hinzugefuegt --- application/models/education/Lvgesamtnote_model.php | 1 + 1 file changed, 1 insertion(+) 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; } } From a0284c313afc149e8b29f3d21fb532c45404e3ff Mon Sep 17 00:00:00 2001 From: ma0048 Date: Mon, 13 May 2024 09:16:29 +0200 Subject: [PATCH 03/54] - funktion fuer das alle markierten akzeptieren getrennt - fehlende phrasen hinzugefuegt --- system/phrasesupdate.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 12e251133..1c41f67d8 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -17727,6 +17727,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', From d2611ac0a54634d09673bc9670843a4142f89ca9 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Fri, 21 Jun 2024 14:34:31 +0200 Subject: [PATCH 04/54] put issue logik in own library (so GUIs should not have to reimplement it) --- application/core/IssueResolver_Controller.php | 100 ++------------- .../core/PlausiIssueProducer_Controller.php | 40 +----- .../issues/PlausicheckProducerLib.php | 50 ++++++++ .../issues/PlausicheckResolverLib.php | 117 ++++++++++++++++++ 4 files changed, 180 insertions(+), 127 deletions(-) create mode 100644 application/libraries/issues/PlausicheckResolverLib.php diff --git a/application/core/IssueResolver_Controller.php b/application/core/IssueResolver_Controller.php index 758064ed8..a9091045f 100755 --- a/application/core/IssueResolver_Controller.php +++ b/application/core/IssueResolver_Controller.php @@ -5,21 +5,18 @@ */ abstract class IssueResolver_Controller extends JOB_Controller { - const CI_PATH = 'application'; - const CI_LIBRARY_FOLDER = 'libraries'; - const EXTENSIONS_FOLDER = 'extensions'; - const ISSUE_RESOLVERS_FOLDER = 'issues/resolvers'; - const CHECK_ISSUE_RESOLVED_METHOD_NAME = 'checkIfIssueIsResolved'; - protected $_codeLibMappings; public function __construct() { parent::__construct(); + // pass extension name if calling from extension + $extensionName = isset($this->_extensionName) ? $this->_extensionName : null; + $this->load->model('system/Issue_model', 'IssueModel'); - $this->load->library('IssuesLib'); + $this->load->library('issues/PlausicheckResolverLib', ['extensionName' => $extensionName]); } /** @@ -32,92 +29,13 @@ abstract class IssueResolver_Controller extends JOB_Controller // load open issues with given errorcodes $openIssuesRes = $this->IssueModel->getOpenIssues(array_keys($this->_codeLibMappings)); - // log error if occured - if (isError($openIssuesRes)) - { - $this->logError(getError($openIssuesRes)); - } - else - { - // log info if no data found - if (!hasData($openIssuesRes)) - { - $this->logInfo("No open issues found"); - } - else - { - $openIssues = getData($openIssuesRes); + $openIssues = hasData($openIssuesRes) ? getData($openIssuesRes) : []; - foreach ($openIssues as $issue) - { - // ignore if Fehlercode is not in libmappings (shouldn't be checked) - if (!isset($this->_codeLibMappings[$issue->fehlercode])) continue; + $result = $this->plausicheckresolverlib->resolvePlausicheckIssues($this->_codeLibMappings, $openIssues); - $libName = $this->_codeLibMappings[$issue->fehlercode]; - - // add person id and oe kurzbz automatically as params, merge it with additional params - // decode bewerbung_parameter into assoc array - $params = array_merge( - array('issue_id' => $issue->issue_id, 'issue_person_id' => $issue->person_id, 'issue_oe_kurzbz' => $issue->oe_kurzbz), - isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array() - ); - - // if called from extension (extension name set), path includes extension names - $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : ''; - - // path for loading issue library - $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/'; - - // file path of library for check if file exists - $issuesLibFilePath = DOC_ROOT . self::CI_PATH - . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php'; - - // check if library file exists - if (!file_exists($issuesLibFilePath)) - { - // log error and continue with next issue if not - $this->logError("Issue library file " . $issuesLibFilePath . " does not exist"); - continue; - } - - // load library connected to fehlercode - $this->load->library($issuesLibPath . $libName); - - $lowercaseLibName = mb_strtolower($libName); - - // check if method is defined in library class - if (!is_callable(array($this->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME))) - { - // log error and continue with next issue if not - $this->logError("Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName"); - continue; - } - - // call the function for checking for issue resolution - $issueResolvedRes = $this->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); - - if (isError($issueResolvedRes)) - { - $this->logError(getError($issueResolvedRes)); - } - else - { - $issueResolvedData = getData($issueResolvedRes); - - if ($issueResolvedData === true) - { - // set issue to resolved if needed - $behobenRes = $this->issueslib->setBehoben($issue->issue_id, null); - - if (isError($behobenRes)) - $this->logError(getError($behobenRes)); - else - $this->logInfo("Issue " . $issue->issue_id . " successfully resolved"); - } - } - } - } - } + // log if error, or log info if inserted new issue + foreach ($result->errors as $error) $this->logError($error); + foreach ($result->infos as $info) $this->logInfo($info); $this->logInfo("Issue resolve job ended"); } diff --git a/application/core/PlausiIssueProducer_Controller.php b/application/core/PlausiIssueProducer_Controller.php index 0dce7a487..d8eea61e9 100644 --- a/application/core/PlausiIssueProducer_Controller.php +++ b/application/core/PlausiIssueProducer_Controller.php @@ -17,49 +17,17 @@ abstract class PlausiIssueProducer_Controller extends JOB_Controller // load libraries $this->load->library('issues/PlausicheckProducerLib', array('extensionName' => $extensionName, 'app' => $this->_app)); - $this->load->library('IssuesLib'); } protected function producePlausicheckIssues($params) { $this->logInfo("Plausicheck issue producer job started"); - // get the data returned by Plausicheck - foreach ($this->_fehlerLibMappings as $fehler_kurzbz => $libName) - { - // execute the check - $this->logInfo("Checking " . $fehler_kurzbz . "..."); - $plausicheckRes = $this->plausicheckproducerlib->producePlausicheckIssue( - $libName, - $fehler_kurzbz, - $params - ); + $result = $this->plausicheckproducerlib->producePlausicheckIssues($this->_fehlerLibMappings, $params); - if (isError($plausicheckRes)) $this->logError(getError($plausicheckRes)); - - if (hasData($plausicheckRes)) - { - $plausicheckData = getData($plausicheckRes); - - foreach ($plausicheckData as $plausiData) - { - // get the data needed for issue production - $person_id = isset($plausiData['person_id']) ? $plausiData['person_id'] : null; - $oe_kurzbz = isset($plausiData['oe_kurzbz']) ? $plausiData['oe_kurzbz'] : null; - $fehlertext_params = isset($plausiData['fehlertext_params']) ? $plausiData['fehlertext_params'] : null; - $resolution_params = isset($plausiData['resolution_params']) ? $plausiData['resolution_params'] : null; - - // write the issue - $addIssueRes = $this->issueslib->addFhcIssue($fehler_kurzbz, $person_id, $oe_kurzbz, $fehlertext_params, $resolution_params); - - // log if error, or log info if inserted new issue - if (isError($addIssueRes)) - $this->logError(getError($addIssueRes)); - elseif (hasData($addIssueRes) && is_integer(getData($addIssueRes))) - $this->logInfo("Plausicheck issue " . $fehler_kurzbz . " successfully produced, person_id: " . $person_id); - } - } - } + // log if error, or log info if inserted new issue + foreach ($result->errors as $error) $this->logError($error); + foreach ($result->infos as $info) $this->logInfo($info); $this->logInfo("Plausicheck issue producer job stopped"); } diff --git a/application/libraries/issues/PlausicheckProducerLib.php b/application/libraries/issues/PlausicheckProducerLib.php index 3a51e2b1e..e7a772e59 100644 --- a/application/libraries/issues/PlausicheckProducerLib.php +++ b/application/libraries/issues/PlausicheckProducerLib.php @@ -24,6 +24,9 @@ class PlausicheckProducerLib $this->_ci =& get_instance(); // get ci instance + // load libraries + $this->_ci->load->library('IssuesLib'); + // load models $this->_ci->load->model('system/Fehlerkonfiguration_model', 'FehlerkonfigurationModel'); @@ -41,6 +44,53 @@ class PlausicheckProducerLib } } + /** + * Produces multiple plausicheck issues at once. + * @param array $fehlerLibMappings contains fehler type to check and library responsible for check (fehler_kurzbz => libName) + * @param array $params passed to each plausicheck + * @return result object with occured error and info + */ + public function producePlausicheckIssues($fehlerLibMappings, $params) + { + $result = new StdClass(); + $result->errors = []; + $result->infos = []; + + foreach ($fehlerLibMappings as $fehler_kurzbz => $libName) + { + $plausicheckRes = $this->producePlausicheckIssue( + $libName, + $fehler_kurzbz, + $params + ); + + if (hasData($plausicheckRes)) + { + $plausicheckData = getData($plausicheckRes); + + foreach ($plausicheckData as $plausiData) + { + // get the data needed for issue production + $person_id = isset($plausiData['person_id']) ? $plausiData['person_id'] : null; + $oe_kurzbz = isset($plausiData['oe_kurzbz']) ? $plausiData['oe_kurzbz'] : null; + $fehlertext_params = isset($plausiData['fehlertext_params']) ? $plausiData['fehlertext_params'] : null; + $resolution_params = isset($plausiData['resolution_params']) ? $plausiData['resolution_params'] : null; + + // write the issue + $addIssueRes = $this->_ci->issueslib->addFhcIssue($fehler_kurzbz, $person_id, $oe_kurzbz, $fehlertext_params, $resolution_params); + + // log if error, or log info if inserted new issue + if (isError($addIssueRes)) + $result->errors[] = getError($addIssueRes); + elseif (hasData($addIssueRes) && is_integer(getData($addIssueRes))) + $result->infos[] = "Plausicheck issue " . $fehler_kurzbz . " successfully produced, person_id: " . $person_id; + } + } + } + + return $result; + } + /** * Executes plausicheck using a given library, returns the result. * @param $libName string name of library producing the issue diff --git a/application/libraries/issues/PlausicheckResolverLib.php b/application/libraries/issues/PlausicheckResolverLib.php new file mode 100644 index 000000000..ec586230a --- /dev/null +++ b/application/libraries/issues/PlausicheckResolverLib.php @@ -0,0 +1,117 @@ +_extensionName = $params['extensionName']; + + $this->_ci =& get_instance(); // get ci instance + + $this->_ci->load->library('IssuesLib'); + } + + /** + * Reseolves multiple plausicheck issues at once. + * @param array $codeLibMappings contains fehler type to check and library responsible for check (fehlercode => libName) + * @param array $openIssues passed issues to resolve + * @return result object with occured error and info + */ + public function resolvePlausicheckIssues($codeLibMappings, $openIssues) + { + $result = new StdClass(); + $result->errors = []; + $result->infos = []; + + //var_dump($openIssues); + //var_dump($codeLibMappings); + + foreach ($openIssues as $issue) + { + // ignore if Fehlercode is not in libmappings (shouldn't be checked) + if (!isset($codeLibMappings[$issue->fehlercode])) continue; + + $libName = $codeLibMappings[$issue->fehlercode]; + + // add person id and oe kurzbz automatically as params, merge it with additional params + // decode bewerbung_parameter into assoc array + $params = array_merge( + array('issue_id' => $issue->issue_id, 'issue_person_id' => $issue->person_id, 'issue_oe_kurzbz' => $issue->oe_kurzbz), + isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array() + ); + + // if called from extension (extension name set), path includes extension names + $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : ''; + + // path for loading issue library + $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/'; + + // file path of library for check if file exists + $issuesLibFilePath = DOC_ROOT . self::CI_PATH + . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php'; + + // check if library file exists + if (!file_exists($issuesLibFilePath)) + { + // log error and continue with next issue if not + $result->errors[] = "Issue library file " . $issuesLibFilePath . " does not exist"; + continue; + } + + // load library connected to fehlercode + $this->_ci->load->library($issuesLibPath . $libName); + + $lowercaseLibName = mb_strtolower($libName); + + // check if method is defined in library class + if (!is_callable(array($this->_ci->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME))) + { + // log error and continue with next issue if not + $result->errors[] = "Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName"; + continue; + } + + // call the function for checking for issue resolution + $issueResolvedRes = $this->_ci->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); + + var_dump($params); + var_dump($issueResolvedRes); + + if (isError($issueResolvedRes)) + { + $result->errors[] = getError($issueResolvedRes); + } + else + { + $issueResolvedData = getData($issueResolvedRes); + + if ($issueResolvedData === true) + { + // set issue to resolved if needed + $behobenRes = $this->_ci->issueslib->setBehoben($issue->issue_id, null); + + var_dump($behobenRes); + + if (isError($behobenRes)) + $result->errors[] = getError($behobenRes); + else + $result->infos[] = "Issue " . $issue->issue_id . " successfully resolved"; + } + } + } + + return $result; + } +} From 453f93aba602e4320d393eeb4e575b83b0795297 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Fri, 21 Jun 2024 14:58:26 +0200 Subject: [PATCH 05/54] outsourcing Issue logic: removed var dumps --- application/libraries/issues/PlausicheckResolverLib.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/application/libraries/issues/PlausicheckResolverLib.php b/application/libraries/issues/PlausicheckResolverLib.php index ec586230a..cd88cf5be 100644 --- a/application/libraries/issues/PlausicheckResolverLib.php +++ b/application/libraries/issues/PlausicheckResolverLib.php @@ -35,9 +35,6 @@ class PlausicheckResolverLib $result->errors = []; $result->infos = []; - //var_dump($openIssues); - //var_dump($codeLibMappings); - foreach ($openIssues as $issue) { // ignore if Fehlercode is not in libmappings (shouldn't be checked) @@ -86,9 +83,6 @@ class PlausicheckResolverLib // call the function for checking for issue resolution $issueResolvedRes = $this->_ci->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); - var_dump($params); - var_dump($issueResolvedRes); - if (isError($issueResolvedRes)) { $result->errors[] = getError($issueResolvedRes); @@ -102,8 +96,6 @@ class PlausicheckResolverLib // set issue to resolved if needed $behobenRes = $this->_ci->issueslib->setBehoben($issue->issue_id, null); - var_dump($behobenRes); - if (isError($behobenRes)) $result->errors[] = getError($behobenRes); else From 3a16c4ebf329759096cf3eec0f81aa186317cfd1 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 26 Jun 2024 10:45:56 +0200 Subject: [PATCH 06/54] Added method getAutocompleteSuggestions to Lehrveranstaltung_model.php Get Lehrveranstaltungen by eventQuery string. Use with autocomplete event queries. --- .../education/Lehrveranstaltung_model.php | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 1f1b90131..c7f32fef6 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -15,6 +15,71 @@ 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) + { + $params = []; + + $eventQuery = '%' . $eventQuery . '%'; + + $qry = ' + SELECT DISTINCT ON (lv_oe_kurzbz, stg_bezeichnung, lehrveranstaltung_id) + le.studiensemester_kurzbz, + 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", + stg.studiengang_kz, + upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz", + stg.bezeichnung AS "stg_bezeichnung", + lv.semester, + lv.lehrveranstaltung_id, + lv.bezeichnung AS "lv_bezeichnung" + FROM + lehre.tbl_lehrveranstaltung lv + JOIN lehre.tbl_lehreinheit le USING (lehrveranstaltung_id) + JOIN PUBLIC.tbl_organisationseinheit oe USING (oe_kurzbz) + JOIN PUBLIC.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz + WHERE + /* filter negative studiengaenge */ + stg.studiengang_kz > 0 '; + + if (isset($studiensemester_kurzbz) && is_string($studiensemester_kurzbz)) + { + /* filter studiensemester */ + $qry.= ' AND le.studiensemester_kurzbz = ? '; + $params[]= $studiensemester_kurzbz; + } + + if (isset($oes) && is_array($oes)) + { + /* filter organisationseinheit */ + $qry.= ' AND lv.oe_kurzbz IN ? '; + $params[]= $oes; + } + + $qry.= ' + /* filter active lehrveranstaltungen */ + AND lv.aktiv = TRUE + /* filter active organisationseinheiten */ + AND oe.aktiv = TRUE + /* filter by search entry */ + AND lv.bezeichnung ILIKE ? + '; + + $params[]= $eventQuery; + + return $this->execQuery($qry, $params); + } + /** * Gets unique Groupstrings for Lehrveranstaltungen, e.g. WS2018_BIF_1_PRJM_VZ_LV12345 * @param string $studiensemester_kurzbz From 580f063efea0d35da04db86a1e8b78dc567a893b Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 26 Jun 2024 10:48:59 +0200 Subject: [PATCH 07/54] Updated phrases: Added phrases for Softwareanforderung in category Softwarebereitstellung --- system/phrasesupdate.php | 200 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 20f155afe..1aa798586 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -26139,6 +26139,206 @@ array( ) ) ), + 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' + ) + ) + ), ); From 32e1e487a98cdc4de00ec07045c59be304299d87 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 26 Jun 2024 22:46:36 +0200 Subject: [PATCH 08/54] issues: enabled resolving without explicitely creating a resolver (by using producer method), old resolvers are still working. Created example for "self-resolving" issue: AbbrecherAktiv --- .../controllers/jobs/IssueResolver.php | 9 +- application/core/IssueResolver_Controller.php | 25 +++- .../core/PlausiIssueProducer_Controller.php | 20 +-- .../issues/PlausicheckProducerLib.php | 18 ++- .../issues/PlausicheckResolverLib.php | 127 +++++++++++------- .../issues/plausichecks/AbbrecherAktiv.php | 94 +++---------- .../issues/plausichecks/PlausiChecker.php | 96 ++++++++++++- application/models/system/Issue_model.php | 22 ++- 8 files changed, 245 insertions(+), 166 deletions(-) diff --git a/application/controllers/jobs/IssueResolver.php b/application/controllers/jobs/IssueResolver.php index be66a6b23..f0f13694e 100755 --- a/application/controllers/jobs/IssueResolver.php +++ b/application/controllers/jobs/IssueResolver.php @@ -9,7 +9,7 @@ class IssueResolver extends IssueResolver_Controller { parent::__construct(); - // set fehler codes which can be resolved by the job + // set fehler codes which can be resolved by the job, with own resolver defined // structure: fehlercode => class (library) name for resolving $this->_codeLibMappings = array( 'CORE_ZGV_0001' => 'CORE_ZGV_0001', @@ -30,7 +30,6 @@ class IssueResolver extends IssueResolver_Controller 'CORE_STG_0002' => 'CORE_STG_0002', 'CORE_STG_0003' => 'CORE_STG_0003', 'CORE_STG_0004' => 'CORE_STG_0004', - 'CORE_STUDENTSTATUS_0001' => 'CORE_STUDENTSTATUS_0001', 'CORE_STUDENTSTATUS_0002' => 'CORE_STUDENTSTATUS_0002', 'CORE_STUDENTSTATUS_0003' => 'CORE_STUDENTSTATUS_0003', 'CORE_STUDENTSTATUS_0004' => 'CORE_STUDENTSTATUS_0004', @@ -51,5 +50,11 @@ class IssueResolver extends IssueResolver_Controller 'CORE_PERSON_0003' => 'CORE_PERSON_0003', 'CORE_PERSON_0004' => 'CORE_PERSON_0004' ); + + // fehler which are resolved the same way as they are produced + // structure: fehlercode => class (library) name for resolving + $this->_codeProducerLibMappings = array( + 'CORE_STUDENTSTATUS_0001' => 'AbbrecherAktiv', + ); } } diff --git a/application/core/IssueResolver_Controller.php b/application/core/IssueResolver_Controller.php index a9091045f..ea278ddb0 100755 --- a/application/core/IssueResolver_Controller.php +++ b/application/core/IssueResolver_Controller.php @@ -5,18 +5,18 @@ */ abstract class IssueResolver_Controller extends JOB_Controller { - protected $_codeLibMappings; + // mappings in form fehlercode -> resolverlibrary name, fehler which have explicit resolver class defined + protected $_codeLibMappings = []; + + // mappings in form fehlercode -> producer library name, fehler which are resolved the same way they are produced + protected $_codeProducerLibMappings = []; public function __construct() { parent::__construct(); // pass extension name if calling from extension - $extensionName = isset($this->_extensionName) ? $this->_extensionName : null; - $this->load->model('system/Issue_model', 'IssueModel'); - - $this->load->library('issues/PlausicheckResolverLib', ['extensionName' => $extensionName]); } /** @@ -24,14 +24,25 @@ abstract class IssueResolver_Controller extends JOB_Controller */ public function run() { + $this->load->library( + 'issues/PlausicheckResolverLib', + [ + 'extensionName' => $this->_extensionName ?? null, + 'codeLibMappings' => $this->_codeLibMappings, + 'codeProducerLibMappings' => $this->_codeProducerLibMappings + ] + ); + $this->logInfo("Issue resolve job started"); // load open issues with given errorcodes - $openIssuesRes = $this->IssueModel->getOpenIssues(array_keys($this->_codeLibMappings)); + $openIssuesRes = $this->IssueModel->getOpenIssues( + array_merge(array_keys($this->_codeLibMappings), array_keys($this->_codeProducerLibMappings)) + ); $openIssues = hasData($openIssuesRes) ? getData($openIssuesRes) : []; - $result = $this->plausicheckresolverlib->resolvePlausicheckIssues($this->_codeLibMappings, $openIssues); + $result = $this->plausicheckresolverlib->resolvePlausicheckIssues($openIssues); // log if error, or log info if inserted new issue foreach ($result->errors as $error) $this->logError($error); diff --git a/application/core/PlausiIssueProducer_Controller.php b/application/core/PlausiIssueProducer_Controller.php index d8eea61e9..5216d284c 100644 --- a/application/core/PlausiIssueProducer_Controller.php +++ b/application/core/PlausiIssueProducer_Controller.php @@ -5,25 +5,19 @@ */ abstract class PlausiIssueProducer_Controller extends JOB_Controller { - protected $_fehlerLibMappings; + protected $_fehlerLibMappings = []; protected $_app; - public function __construct($app = null) - { - parent::__construct(); - - // pass extension name if calling from extension - $extensionName = isset($this->_extensionName) ? $this->_extensionName : null; - - // load libraries - $this->load->library('issues/PlausicheckProducerLib', array('extensionName' => $extensionName, 'app' => $this->_app)); - } - protected function producePlausicheckIssues($params) { + $this->load->library( + 'issues/PlausicheckProducerLib', + ['extensionName' => $this->_extensionName ?? null, 'app' => $this->_app, 'fehlerLibMappings' => $this->_fehlerLibMappings] + ); + $this->logInfo("Plausicheck issue producer job started"); - $result = $this->plausicheckproducerlib->producePlausicheckIssues($this->_fehlerLibMappings, $params); + $result = $this->plausicheckproducerlib->producePlausicheckIssues($params); // log if error, or log info if inserted new issue foreach ($result->errors as $error) $this->logError($error); diff --git a/application/libraries/issues/PlausicheckProducerLib.php b/application/libraries/issues/PlausicheckProducerLib.php index e7a772e59..cea9967fb 100644 --- a/application/libraries/issues/PlausicheckProducerLib.php +++ b/application/libraries/issues/PlausicheckProducerLib.php @@ -12,12 +12,16 @@ class PlausicheckProducerLib private $_ci; // ci instance private $_extensionName; // name of extension - private $_konfiguration = array(); // configuration parameters + private $_konfiguration = []; // configuration parameters + private $_fehlerLibMappings = []; // mappings of fehler and libraries for producing them + private $_isForResolutionCheck = false; // mappings of fehler and libraries for producing them public function __construct($params = null) { // set extension name if called from extension if (isset($params['extensionName'])) $this->_extensionName = $params['extensionName']; + if (isset($params['fehlerLibMappings'])) $this->_fehlerLibMappings = $params['fehlerLibMappings']; + if (isset($params['isForResolutionCheck'])) $this->_isForResolutionCheck = $params['isForResolutionCheck']; // set application $app = isset($params['app']) ? $params['app'] : null; @@ -45,18 +49,17 @@ class PlausicheckProducerLib } /** - * Produces multiple plausicheck issues at once. - * @param array $fehlerLibMappings contains fehler type to check and library responsible for check (fehler_kurzbz => libName) + * Produces multiple plausicheck issues at once and saved them to db. * @param array $params passed to each plausicheck * @return result object with occured error and info */ - public function producePlausicheckIssues($fehlerLibMappings, $params) + public function producePlausicheckIssues($params) { $result = new StdClass(); $result->errors = []; $result->infos = []; - foreach ($fehlerLibMappings as $fehler_kurzbz => $libName) + foreach ($this->_fehlerLibMappings as $fehler_kurzbz => $libName) { $plausicheckRes = $this->producePlausicheckIssue( $libName, @@ -116,7 +119,10 @@ class PlausicheckProducerLib $config = isset($this->_konfiguration[$fehler_kurzbz]) ? $this->_konfiguration[$fehler_kurzbz] : null; // load library connected to fehlercode - $this->_ci->load->library($issuesLibPath . $libName, $config); + $this->_ci->load->library( + $issuesLibPath . $libName, + ['configurationParams' => $config, 'isForResolutionCheck' => $this->_isForResolutionCheck] + ); $lowercaseLibName = mb_strtolower($libName); diff --git a/application/libraries/issues/PlausicheckResolverLib.php b/application/libraries/issues/PlausicheckResolverLib.php index cd88cf5be..618611cee 100644 --- a/application/libraries/issues/PlausicheckResolverLib.php +++ b/application/libraries/issues/PlausicheckResolverLib.php @@ -12,15 +12,20 @@ class PlausicheckResolverLib private $_ci; // ci instance private $_extensionName; // name of extension + private $_codeLibMappings = []; // mappings for issues which explicitly defined resolver + private $_codeProducerLibMappings = []; // mappings for issues which are resolved as produced public function __construct($params = null) { // set extension name if called from extension if (isset($params['extensionName'])) $this->_extensionName = $params['extensionName']; + if (isset($params['codeLibMappings'])) $this->_codeLibMappings = $params['codeLibMappings']; + if (isset($params['codeProducerLibMappings'])) $this->_codeProducerLibMappings = $params['codeProducerLibMappings']; $this->_ci =& get_instance(); // get ci instance $this->_ci->load->library('IssuesLib'); + $this->_ci->load->library('issues/PlausicheckProducerLib', ['isForResolutionCheck' => true]); } /** @@ -29,7 +34,7 @@ class PlausicheckResolverLib * @param array $openIssues passed issues to resolve * @return result object with occured error and info */ - public function resolvePlausicheckIssues($codeLibMappings, $openIssues) + public function resolvePlausicheckIssues($openIssues) { $result = new StdClass(); $result->errors = []; @@ -37,11 +42,6 @@ class PlausicheckResolverLib foreach ($openIssues as $issue) { - // ignore if Fehlercode is not in libmappings (shouldn't be checked) - if (!isset($codeLibMappings[$issue->fehlercode])) continue; - - $libName = $codeLibMappings[$issue->fehlercode]; - // add person id and oe kurzbz automatically as params, merge it with additional params // decode bewerbung_parameter into assoc array $params = array_merge( @@ -49,58 +49,85 @@ class PlausicheckResolverLib isset($issue->behebung_parameter) ? json_decode($issue->behebung_parameter, true) : array() ); - // if called from extension (extension name set), path includes extension names - $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : ''; + $issueResolved = false; - // path for loading issue library - $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/'; - - // file path of library for check if file exists - $issuesLibFilePath = DOC_ROOT . self::CI_PATH - . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php'; - - // check if library file exists - if (!file_exists($issuesLibFilePath)) + // ignore if Fehlercode is not in libmappings (shouldn't be checked) + if (isset($this->_codeLibMappings[$issue->fehlercode])) { - // log error and continue with next issue if not - $result->errors[] = "Issue library file " . $issuesLibFilePath . " does not exist"; - continue; - } + $libName = $this->_codeLibMappings[$issue->fehlercode]; - // load library connected to fehlercode - $this->_ci->load->library($issuesLibPath . $libName); + // if called from extension (extension name set), path includes extension names + $libRootPath = isset($this->_extensionName) ? self::EXTENSIONS_FOLDER . '/' . $this->_extensionName . '/' : ''; - $lowercaseLibName = mb_strtolower($libName); + // path for loading issue library + $issuesLibPath = $libRootPath . self::ISSUE_RESOLVERS_FOLDER . '/'; - // check if method is defined in library class - if (!is_callable(array($this->_ci->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME))) - { - // log error and continue with next issue if not - $result->errors[] = "Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName"; - continue; - } + // file path of library for check if file exists + $issuesLibFilePath = DOC_ROOT . self::CI_PATH + . '/' . $libRootPath . self::CI_LIBRARY_FOLDER . '/' . self::ISSUE_RESOLVERS_FOLDER . '/' . $libName . '.php'; - // call the function for checking for issue resolution - $issueResolvedRes = $this->_ci->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); - - if (isError($issueResolvedRes)) - { - $result->errors[] = getError($issueResolvedRes); - } - else - { - $issueResolvedData = getData($issueResolvedRes); - - if ($issueResolvedData === true) + // check if library file exists + if (!file_exists($issuesLibFilePath)) { - // set issue to resolved if needed - $behobenRes = $this->_ci->issueslib->setBehoben($issue->issue_id, null); - - if (isError($behobenRes)) - $result->errors[] = getError($behobenRes); - else - $result->infos[] = "Issue " . $issue->issue_id . " successfully resolved"; + // log error and continue with next issue if not + $result->errors[] = "Issue library file " . $issuesLibFilePath . " does not exist"; + continue; } + + // load library connected to fehlercode + $this->_ci->load->library($issuesLibPath . $libName); + + $lowercaseLibName = mb_strtolower($libName); + + // check if method is defined in library class + if (!is_callable(array($this->_ci->{$lowercaseLibName}, self::CHECK_ISSUE_RESOLVED_METHOD_NAME))) + { + // log error and continue with next issue if not + $result->errors[] = "Method " . self::CHECK_ISSUE_RESOLVED_METHOD_NAME . " is not defined in library $lowercaseLibName"; + continue; + } + + // call the function for checking for issue resolution + $issueResolvedRes = $this->_ci->{$lowercaseLibName}->{self::CHECK_ISSUE_RESOLVED_METHOD_NAME}($params); + + if (isError($issueResolvedRes)) + { + $result->errors[] = getError($issueResolvedRes); + } + else + { + $issueResolved = getData($issueResolvedRes) === true; + } + } + elseif (isset($this->_codeProducerLibMappings[$issue->fehlercode])) + { + $libName = $this->_codeProducerLibMappings[$issue->fehlercode]; + + $issueResolvedRes = $this->_ci->plausicheckproducerlib->producePlausicheckIssue( + $libName, + $issue->fehler_kurzbz, + $params + ); + + if (isError($issueResolvedRes)) + { + $result->errors[] = getError($issueResolvedRes); + } + else + { + $issueResolved = !hasData($issueResolvedRes); + } + } + + // set issue to resolved if needed + if ($issueResolved) + { + $behobenRes = $this->_ci->issueslib->setBehoben($issue->issue_id, null); + + if (isError($behobenRes)) + $result->errors[] = getError($behobenRes); + else + $result->infos[] = "Issue " . $issue->issue_id . " successfully resolved"; } } diff --git a/application/libraries/issues/plausichecks/AbbrecherAktiv.php b/application/libraries/issues/plausichecks/AbbrecherAktiv.php index 9eae389b5..464b77a30 100644 --- a/application/libraries/issues/plausichecks/AbbrecherAktiv.php +++ b/application/libraries/issues/plausichecks/AbbrecherAktiv.php @@ -9,83 +9,21 @@ require_once('PlausiChecker.php'); */ class AbbrecherAktiv extends PlausiChecker { - public function executePlausiCheck($params) - { - $results = array(); + protected $_base_sql = " + SELECT + pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz + FROM + public.tbl_prestudentstatus pre_status + JOIN public.tbl_prestudent pre USING(prestudent_id) + JOIN public.tbl_student student USING(prestudent_id) + JOIN public.tbl_benutzer benutzer on(benutzer.uid=student.student_uid) + JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz + WHERE + pre_status.status_kurzbz ='Abbrecher' + AND benutzer.aktiv=true"; - // get parameters from config - $exkludierte_studiengang_kz = isset($this->_config['exkludierteStudiengaenge']) ? $this->_config['exkludierteStudiengaenge'] : null; - - // pass parameters needed for plausicheck - $studiengang_kz = isset($params['studiengang_kz']) ? $params['studiengang_kz'] : null; - - // get all students failing the plausicheck - $prestudentRes = $this->getAbbrecherAktiv($studiengang_kz, null, $exkludierte_studiengang_kz); - - if (isError($prestudentRes)) return $prestudentRes; - - if (hasData($prestudentRes)) - { - $prestudents = getData($prestudentRes); - - // populate results with data necessary for writing issues - foreach ($prestudents as $prestudent) - { - $results[] = array( - 'person_id' => $prestudent->person_id, - 'oe_kurzbz' => $prestudent->prestudent_stg_oe_kurzbz, - 'fehlertext_params' => array('prestudent_id' => $prestudent->prestudent_id), - 'resolution_params' => array('prestudent_id' => $prestudent->prestudent_id) - ); - } - } - - // return the results - return success($results); - } - - /** - * Abbrecher cannot be active. - * @param studiengang_kz int if check is to be executed for certain Studiengang - * @param prestudent_id int if check is to be executed only for one prestudent - * @param exkludierte_studiengang_kz array if certain Studiengänge have to be excluded from check - * @return success with prestudents or error - */ - public function getAbbrecherAktiv($studiengang_kz = null, $prestudent_id = null, $exkludierte_studiengang_kz = null) - { - $params = array(); - - $qry = " - SELECT - pre.person_id, pre.prestudent_id, stg.oe_kurzbz AS prestudent_stg_oe_kurzbz - FROM - public.tbl_prestudentstatus pre_status - JOIN public.tbl_prestudent pre USING(prestudent_id) - JOIN public.tbl_student student USING(prestudent_id) - JOIN public.tbl_benutzer benutzer on(benutzer.uid=student.student_uid) - JOIN public.tbl_studiengang stg ON pre.studiengang_kz = stg.studiengang_kz - WHERE - pre_status.status_kurzbz ='Abbrecher' - AND benutzer.aktiv=true"; - - if (isset($studiengang_kz)) - { - $qry .= " AND stg.studiengang_kz = ?"; - $params[] = $studiengang_kz; - } - - if (isset($prestudent_id)) - { - $qry .= " AND pre.prestudent_id = ?"; - $params[] = $prestudent_id; - } - - if (isset($exkludierte_studiengang_kz) && !isEmptyArray($exkludierte_studiengang_kz)) - { - $qry .= " AND stg.studiengang_kz NOT IN ?"; - $params[] = $exkludierte_studiengang_kz; - } - - return $this->_db->execReadOnlyQuery($qry, $params); - } + protected $_config_params = ['exkludierteStudiengaenge' => " AND stg.studiengang_kz NOT IN ?"]; + protected $_params_for_checking = ['studiengang_kz' => " AND stg.studiengang_kz = ?", 'prestudent_id' => " AND pre.prestudent_id = ?"]; + protected $_fehlertext_params = ['prestudent_id']; + protected $_resolution_params = ['prestudent_id']; } diff --git a/application/libraries/issues/plausichecks/PlausiChecker.php b/application/libraries/issues/plausichecks/PlausiChecker.php index 086a44cc4..5e9c2469f 100644 --- a/application/libraries/issues/plausichecks/PlausiChecker.php +++ b/application/libraries/issues/plausichecks/PlausiChecker.php @@ -6,15 +6,25 @@ abstract class PlausiChecker { protected $_ci; // code igniter instance - protected $_config; // configuration parameters for this plausicheck + protected $_config; // all applicable configuration parameters for this plausicheck protected $_db; // database for queries - public function __construct($configurationParams = null) + protected $_isForResolutionCheck; + + protected $_config_params = []; // name of all config params which should be applied for this plausicheck, with sql [name] => [sql] + protected $_params_for_checking = []; // name of all passed params for checking, with sql [name] => [sql] + + protected $_fehlertext_params = []; // parameter names for fehlertext params used for this plausicheck + protected $_resolution_params = []; // parameter names for resolution params used for this plausicheck + + public function __construct($params = null) { $this->_ci =& get_instance(); // get code igniter instance // set configuration - $this->_config = $configurationParams; + $this->_config = $params['configurationParams'] ?? []; + + $this->_isForResolutionCheck = $params['isForResolutionCheck'] ?? false; // get database for queries $this->_db = new DB_Model(); @@ -25,5 +35,83 @@ abstract class PlausiChecker * @param $paramsForChecking array parameters needed for executing the check * @return array with objects which failed the plausi check */ - abstract public function executePlausiCheck($paramsForChecking); + public function executePlausiCheck($paramsForChecking) + { + $results = []; + $params = []; + $qry = $this->_base_sql; + + if ($this->_isForResolutionCheck == true) + { + foreach ($this->_resolution_params as $resParam) + { + if (!isset($paramsForChecking[$resParam])) + return error("$resParam missing".(isset($paramsForChecking['issue_id']) ? ", issue ID: ".$paramsForChecking['issue_id'] : "")); + } + } + + // add config params to query + if (isset($this->_config_params) && !isEmptyArray($this->_config_params)) + { + foreach ($this->_config_params as $param_name => $param_sql) + { + if (isset($this->_config[$param_name])) + { + $qry .= $param_sql; + $params[] = $this->_config[$param_name]; + } + } + } + + // add check params to query + if (isset($this->_params_for_checking) && !isEmptyArray($this->_params_for_checking)) + { + foreach ($this->_params_for_checking as $param_name => $param_sql) + { + if (isset($paramsForChecking[$param_name])) + { + $qry .= $param_sql; + $params[] = $paramsForChecking[$param_name]; + } + } + } + + $result = $this->_db->execReadOnlyQuery($qry, $params); + + if (isError($result)) return $result; + + if (hasData($result)) + { + $data = getData($result); + + // populate results with data necessary for writing issues + foreach ($data as $d) + { + $fehlertext_params = []; + $resolution_params = []; + + // add params for error texts + foreach ($this->_fehlertext_params as $param) + { + if (isset($d->{$param})) $fehlertext_params[$param] = $d->{$param}; + } + + // add params for resolution of issue + foreach ($this->_resolution_params as $param) + { + if (isset($d->{$param})) $resolution_params[$param] = $d->{$param}; + } + + $results[] = array( + 'person_id' => $d->person_id, + 'oe_kurzbz' => $d->prestudent_stg_oe_kurzbz, + 'fehlertext_params' => $fehlertext_params, + 'resolution_params' => $resolution_params + ); + } + } + + // return the results + return success($results); + } } diff --git a/application/models/system/Issue_model.php b/application/models/system/Issue_model.php index 3d39e9879..331b0f050 100644 --- a/application/models/system/Issue_model.php +++ b/application/models/system/Issue_model.php @@ -22,13 +22,23 @@ class Issue_model extends DB_Model */ public function getOpenIssues($fehlercodes, $person_id = null, $oe_kurzbz = null, $fehlercode_extern = null) { - $params = array($fehlercodes); + $params = array(); // issue exists for a fehlercode (or fehlercode_extern), person_id, oe_kurzbz, if not verarbeitet yet - $qry = 'SELECT issue_id, fehlercode, inhalt, fehlercode_extern, inhalt_extern, person_id, oe_kurzbz, - behebung_parameter, datum, verarbeitetvon, verarbeitetamum - FROM system.tbl_issue - WHERE fehlercode IN ? - AND verarbeitetamum IS NULL'; + $qry = 'SELECT + iss.issue_id, iss.fehlercode, fe.fehler_kurzbz, iss.inhalt, iss.fehlercode_extern, + iss.inhalt_extern, iss.person_id, iss.oe_kurzbz, iss.behebung_parameter, + iss.datum, iss.verarbeitetvon, iss.verarbeitetamum + FROM + system.tbl_issue iss + JOIN system.tbl_fehler fe USING (fehlercode) + WHERE + verarbeitetamum IS NULL'; + + if (!isEmptyArray($fehlercodes)) + { + $qry .= ' AND fehlercode IN ?'; + $params[] = $fehlercodes; + } if (!isEmptyString($fehlercode_extern)) { From 4e053a4769183e5287d1a6aa562cc0d34790b348 Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 8 Jul 2024 12:24:44 +0200 Subject: [PATCH 09/54] Updated phrases: Added phrases for Softwareanforderung in category Softwarebereitstellung --- system/phrasesupdate.php | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 0c9b70261..1f6b19418 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -26700,6 +26700,46 @@ array( ) ) ), + 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' + ) + ) + ), ); From 4d48dfe0181dc43f78a6a518239a90381fb93f41 Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 8 Jul 2024 12:26:41 +0200 Subject: [PATCH 10/54] Added method getLvsByStudiensemesterAndOes to Lehrveranstaltung_model.php getLvsByStudiensemesterAndOes: Gets Lehrveranstaltungen with its Stg, OE and OE-type and filters by Studiensemester and Organisationseinheiten if necessary. --- .../education/Lehrveranstaltung_model.php | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index c7f32fef6..129e2af41 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -80,6 +80,65 @@ class Lehrveranstaltung_model extends DB_Model 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 + * @return array + */ + public function getLvsByStudiensemesterAndOes($studiensemester_kurzbz = null, $oes = null) + { + $params = []; + $qry = ' + SELECT DISTINCT ON (lv_oe_kurzbz, stg_bezeichnung, lehrveranstaltung_id) + le.studiensemester_kurzbz, + 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", + stg.studiengang_kz, + upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz", + stg.bezeichnung AS "stg_bezeichnung", + lv.semester, + lv.lehrveranstaltung_id, + lv.bezeichnung AS "lv_bezeichnung" + FROM + lehre.tbl_lehrveranstaltung lv + JOIN lehre.tbl_lehreinheit le USING (lehrveranstaltung_id) + JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz) + JOIN public.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz + WHERE + /* filter negative studiengaenge */ + stg.studiengang_kz > 0 '; + + if (isset($studiensemester_kurzbz) && is_string($studiensemester_kurzbz)) + { + /* filter studiensemester */ + $qry.= ' AND le.studiensemester_kurzbz = ? '; + $params[]= $studiensemester_kurzbz; + } + + if (isset($oes) && is_array($oes)) + { + /* filter organisationseinheit */ + $qry.= ' AND lv.oe_kurzbz IN ? '; + $params[]= $oes; + } + + $qry.= ' + /* filter active lehrveranstaltungen */ + AND lv.aktiv = TRUE + /* filter active organisationseinheiten */ + AND oe.aktiv = TRUE + '; + + return $this->execQuery($qry, $params); + } + /** * Gets unique Groupstrings for Lehrveranstaltungen, e.g. WS2018_BIF_1_PRJM_VZ_LV12345 * @param string $studiensemester_kurzbz From eead73f10cb69a2820cce9f294bb44a517808fdc Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 10 Jul 2024 14:44:01 +0200 Subject: [PATCH 11/54] Added phrases for core and softwarebereitstellung to phrasesupdate.php --- system/phrasesupdate.php | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 1f6b19418..6b1c0134d 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -26740,6 +26740,86 @@ array( ) ) ), + 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' + ) + ) + ), ); From ce7b368a8eae38fa7b16de08d8f922d85bc40ba4 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 11 Jul 2024 14:33:38 +0200 Subject: [PATCH 12/54] Adapted lv.orgform_kurzbz to selects in Lehrveranstaltung_model.php --- application/models/education/Lehrveranstaltung_model.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 129e2af41..de0bcbdbb 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -42,7 +42,8 @@ class Lehrveranstaltung_model extends DB_Model stg.bezeichnung AS "stg_bezeichnung", lv.semester, lv.lehrveranstaltung_id, - lv.bezeichnung AS "lv_bezeichnung" + lv.bezeichnung AS "lv_bezeichnung", + lv.orgform_kurzbz FROM lehre.tbl_lehrveranstaltung lv JOIN lehre.tbl_lehreinheit le USING (lehrveranstaltung_id) @@ -105,7 +106,8 @@ class Lehrveranstaltung_model extends DB_Model stg.bezeichnung AS "stg_bezeichnung", lv.semester, lv.lehrveranstaltung_id, - lv.bezeichnung AS "lv_bezeichnung" + lv.bezeichnung AS "lv_bezeichnung", + lv.orgform_kurzbz FROM lehre.tbl_lehrveranstaltung lv JOIN lehre.tbl_lehreinheit le USING (lehrveranstaltung_id) From 0df9385f3360a82aedb45235a8061c4d8f06e2d8 Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 22 Jul 2024 12:02:08 +0200 Subject: [PATCH 13/54] Adapted DB query to filter only Lehrveranstaltungen with lehrtyp_kurzbz 'lv' --- application/models/education/Lehrveranstaltung_model.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index de0bcbdbb..0889232a9 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -68,6 +68,8 @@ class Lehrveranstaltung_model extends DB_Model } $qry.= ' + /* filter lv type only */ + AND lv.lehrtyp_kurzbz = \'lv\' /* filter active lehrveranstaltungen */ AND lv.aktiv = TRUE /* filter active organisationseinheiten */ @@ -132,6 +134,8 @@ class Lehrveranstaltung_model extends DB_Model } $qry.= ' + /* filter lv type only */ + AND lv.lehrtyp_kurzbz = \'lv\' /* filter active lehrveranstaltungen */ AND lv.aktiv = TRUE /* filter active organisationseinheiten */ From 31a21954d9b09b048722b41c7a48444174c60b96 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Sun, 28 Jul 2024 19:12:40 +0200 Subject: [PATCH 14/54] issueresolver: improved comment --- application/controllers/jobs/IssueResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/controllers/jobs/IssueResolver.php b/application/controllers/jobs/IssueResolver.php index f0f13694e..d7e2aaeb4 100755 --- a/application/controllers/jobs/IssueResolver.php +++ b/application/controllers/jobs/IssueResolver.php @@ -51,7 +51,7 @@ class IssueResolver extends IssueResolver_Controller 'CORE_PERSON_0004' => 'CORE_PERSON_0004' ); - // fehler which are resolved the same way as they are produced + // fehler which are resolved by the job the same way as they are produced // structure: fehlercode => class (library) name for resolving $this->_codeProducerLibMappings = array( 'CORE_STUDENTSTATUS_0001' => 'AbbrecherAktiv', From 6680e9b8827f1704bf8c1bffdc9c352ea573da72 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Sun, 28 Jul 2024 19:15:27 +0200 Subject: [PATCH 15/54] issueresolver: improved another comment --- application/controllers/jobs/IssueResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/controllers/jobs/IssueResolver.php b/application/controllers/jobs/IssueResolver.php index d7e2aaeb4..ca07439c3 100755 --- a/application/controllers/jobs/IssueResolver.php +++ b/application/controllers/jobs/IssueResolver.php @@ -10,7 +10,7 @@ class IssueResolver extends IssueResolver_Controller parent::__construct(); // set fehler codes which can be resolved by the job, with own resolver defined - // structure: fehlercode => class (library) name for resolving + // structure: fehlercode => class (library) name for resolving in "resolvers" folder $this->_codeLibMappings = array( 'CORE_ZGV_0001' => 'CORE_ZGV_0001', 'CORE_ZGV_0002' => 'CORE_ZGV_0002', @@ -52,7 +52,7 @@ class IssueResolver extends IssueResolver_Controller ); // fehler which are resolved by the job the same way as they are produced - // structure: fehlercode => class (library) name for resolving + // structure: fehlercode => class (library) name for resolving in "plausichecks" folder $this->_codeProducerLibMappings = array( 'CORE_STUDENTSTATUS_0001' => 'AbbrecherAktiv', ); From f1d1c3cbfd27644919589b20e197a054d6a66e5c Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Sun, 28 Jul 2024 19:34:58 +0200 Subject: [PATCH 16/54] issueresolver: improved yet another comment --- application/libraries/issues/plausichecks/PlausiChecker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/libraries/issues/plausichecks/PlausiChecker.php b/application/libraries/issues/plausichecks/PlausiChecker.php index 5e9c2469f..7e5fe7db0 100644 --- a/application/libraries/issues/plausichecks/PlausiChecker.php +++ b/application/libraries/issues/plausichecks/PlausiChecker.php @@ -9,7 +9,7 @@ abstract class PlausiChecker protected $_config; // all applicable configuration parameters for this plausicheck protected $_db; // database for queries - protected $_isForResolutionCheck; + protected $_isForResolutionCheck; // if true, additional parameters only needed for resolution are checked protected $_config_params = []; // name of all config params which should be applied for this plausicheck, with sql [name] => [sql] protected $_params_for_checking = []; // name of all passed params for checking, with sql [name] => [sql] From 88b5fbc4c9a974c7ca0f4d6a189413a7992ff5e4 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Sun, 28 Jul 2024 19:40:10 +0200 Subject: [PATCH 17/54] PlausicheckResolverLib: resolving of issues without explicit resolver can also be used in extensions --- application/libraries/issues/PlausicheckResolverLib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/libraries/issues/PlausicheckResolverLib.php b/application/libraries/issues/PlausicheckResolverLib.php index 618611cee..26da985f6 100644 --- a/application/libraries/issues/PlausicheckResolverLib.php +++ b/application/libraries/issues/PlausicheckResolverLib.php @@ -25,7 +25,7 @@ class PlausicheckResolverLib $this->_ci =& get_instance(); // get ci instance $this->_ci->load->library('IssuesLib'); - $this->_ci->load->library('issues/PlausicheckProducerLib', ['isForResolutionCheck' => true]); + $this->_ci->load->library('issues/PlausicheckProducerLib', ['extensionName' => $this->_extensionName, 'isForResolutionCheck' => true]); } /** From 414a0d7d6e55daf6d7e875cc744bae477344eb1b Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 30 Jul 2024 15:36:16 +0200 Subject: [PATCH 18/54] Changed filter SoftwareManagement to display column anzahl_lizenzen --- system/filtersupdate.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/filtersupdate.php b/system/filtersupdate.php index fa8a361f4..915a59343 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": [] From 49bd14496aeba86338101bc0d96f2f0e2af29a85 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 30 Jul 2024 15:38:02 +0200 Subject: [PATCH 19/54] Adapted db query to get Lehrveranstaltungen via Studienplan instead of Lehreinheit --- .../education/Lehrveranstaltung_model.php | 142 +++++++----------- 1 file changed, 54 insertions(+), 88 deletions(-) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 0889232a9..5a9053f73 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -24,61 +24,16 @@ class Lehrveranstaltung_model extends DB_Model */ public function getAutocompleteSuggestions($eventQuery, $studiensemester_kurzbz = null, $oes = null) { + $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes); $params = []; - $eventQuery = '%' . $eventQuery . '%'; + /* filter by input string */ + if (is_string($eventQuery)) { + $subQry.= ' AND lv.bezeichnung ILIKE ?'; + $params[] = '%' . $eventQuery . '%'; + } - $qry = ' - SELECT DISTINCT ON (lv_oe_kurzbz, stg_bezeichnung, lehrveranstaltung_id) - le.studiensemester_kurzbz, - 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", - stg.studiengang_kz, - upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz", - stg.bezeichnung AS "stg_bezeichnung", - lv.semester, - lv.lehrveranstaltung_id, - lv.bezeichnung AS "lv_bezeichnung", - lv.orgform_kurzbz - FROM - lehre.tbl_lehrveranstaltung lv - JOIN lehre.tbl_lehreinheit le USING (lehrveranstaltung_id) - JOIN PUBLIC.tbl_organisationseinheit oe USING (oe_kurzbz) - JOIN PUBLIC.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz - WHERE - /* filter negative studiengaenge */ - stg.studiengang_kz > 0 '; - - if (isset($studiensemester_kurzbz) && is_string($studiensemester_kurzbz)) - { - /* filter studiensemester */ - $qry.= ' AND le.studiensemester_kurzbz = ? '; - $params[]= $studiensemester_kurzbz; - } - - if (isset($oes) && is_array($oes)) - { - /* filter organisationseinheit */ - $qry.= ' AND lv.oe_kurzbz IN ? '; - $params[]= $oes; - } - - $qry.= ' - /* filter lv type only */ - AND lv.lehrtyp_kurzbz = \'lv\' - /* filter active lehrveranstaltungen */ - AND lv.aktiv = TRUE - /* filter active organisationseinheiten */ - AND oe.aktiv = TRUE - /* filter by search entry */ - AND lv.bezeichnung ILIKE ? - '; - - $params[]= $eventQuery; + $qry = 'SELECT DISTINCT ON (lehrveranstaltung_id) * FROM ('. $subQry. ') AS tmp'; return $this->execQuery($qry, $params); } @@ -91,58 +46,69 @@ class Lehrveranstaltung_model extends DB_Model * @param array $oes Filter by Organisationseinheiten * @return array */ - public function getLvsByStudiensemesterAndOes($studiensemester_kurzbz = null, $oes = null) + public function getLvsByStudienplan($studiensemester_kurzbz = null, $oes = null) + { + $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes); + $qry = 'SELECT DISTINCT ON (lehrveranstaltung_id) * FROM ('. $subQry. ') AS tmp ORDER BY lehrveranstaltung_id, orgform_kurzbz DESC'; // TODO: hier VZ zuerst. aber eig nicht relevant...check + + 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') { - $params = []; $qry = ' - SELECT DISTINCT ON (lv_oe_kurzbz, stg_bezeichnung, lehrveranstaltung_id) - le.studiensemester_kurzbz, - lv.oe_kurzbz AS "lv_oe_kurzbz", - CASE + 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", - stg.studiengang_kz, - upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz", - stg.bezeichnung AS "stg_bezeichnung", - lv.semester, - lv.lehrveranstaltung_id, - lv.bezeichnung AS "lv_bezeichnung", - lv.orgform_kurzbz + 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" FROM - lehre.tbl_lehrveranstaltung lv - JOIN lehre.tbl_lehreinheit le USING (lehrveranstaltung_id) - JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz) - JOIN public.tbl_studiengang stg ON stg.studiengang_kz = lv.studiengang_kz - WHERE - /* filter negative studiengaenge */ - stg.studiengang_kz > 0 '; + 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 studiensemester */ - $qry.= ' AND le.studiensemester_kurzbz = ? '; - $params[]= $studiensemester_kurzbz; + /* filter by studiensemester */ + $qry.= ' AND stplsem.studiensemester_kurzbz = '. $this->db->escape($studiensemester_kurzbz); + } if (isset($oes) && is_array($oes)) { - /* filter organisationseinheit */ - $qry.= ' AND lv.oe_kurzbz IN ? '; - $params[]= $oes; + /* filter by organisationseinheit */ + $implodedOes = "'". implode("', '", $oes). "'"; + $qry.= ' AND lv.oe_kurzbz IN ('. $implodedOes. ')'; } - $qry.= ' - /* filter lv type only */ - AND lv.lehrtyp_kurzbz = \'lv\' - /* filter active lehrveranstaltungen */ - AND lv.aktiv = TRUE - /* filter active organisationseinheiten */ - AND oe.aktiv = TRUE - '; - - return $this->execQuery($qry, $params); + return $qry; } /** From 6f216dbe520b5f6cb6cf98a9279de773aeaaef3d Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 30 Jul 2024 15:38:36 +0200 Subject: [PATCH 20/54] Added phrases to Softwarebereitstellung --- system/phrasesupdate.php | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 6b1c0134d..75b8ce435 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -26820,6 +26820,66 @@ array( ) ) ), + 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' + ) + ) + ), ); From 085ca2a16d0f27da9ed14c881a1b575c22cf98c3 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 31 Jul 2024 11:44:42 +0200 Subject: [PATCH 21/54] Adapted getLvsByStudienplan query to get all LVs, not only VZ --- application/models/education/Lehrveranstaltung_model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 5a9053f73..09b635a58 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -49,7 +49,7 @@ class Lehrveranstaltung_model extends DB_Model public function getLvsByStudienplan($studiensemester_kurzbz = null, $oes = null) { $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes); - $qry = 'SELECT DISTINCT ON (lehrveranstaltung_id) * FROM ('. $subQry. ') AS tmp ORDER BY lehrveranstaltung_id, orgform_kurzbz DESC'; // TODO: hier VZ zuerst. aber eig nicht relevant...check + $qry = 'SELECT * FROM ('. $subQry. ') AS tmp ORDER BY stg_typ_kurzbz, orgform_kurzbz DESC'; return $this->execQuery($qry); } From 3213c051b3f08a46006a533ea580d5f9e7a7cc5a Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 1 Aug 2024 13:48:06 +0200 Subject: [PATCH 22/54] Adapted getLvsByStudienplan query to get by given Lehrveranstaltungen --- .../models/education/Lehrveranstaltung_model.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 09b635a58..928237118 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -44,12 +44,22 @@ class Lehrveranstaltung_model extends DB_Model * @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) + public function getLvsByStudienplan($studiensemester_kurzbz = null, $oes = null, $lv_ids = null) { $subQry = $this->_getQryLvsByStudienplan($studiensemester_kurzbz, $oes); - $qry = 'SELECT * FROM ('. $subQry. ') AS tmp ORDER BY stg_typ_kurzbz, orgform_kurzbz DESC'; + $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); } From b0821be46541d7c6ca305388c4880e1bf683726b Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 5 Aug 2024 10:52:15 +0200 Subject: [PATCH 23/54] Added methods getLastOrAktStudienjahr / getAktOrNextStudienjahr to retrieve the last or next Studienjahr during the summer term --- .../models/organisation/Studienjahr_model.php | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) 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); + } } From 7abe95ba5f0d1d49fc4a6eb48ae2efa7a6e54143 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 6 Aug 2024 10:48:20 +0200 Subject: [PATCH 24/54] Adapted LvsByStudienplan query to retrieve also Lehreinheitgruppen --- .../education/Lehrveranstaltung_model.php | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 928237118..904433439 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -73,24 +73,49 @@ class Lehrveranstaltung_model extends DB_Model { $qry = ' SELECT - lv.oe_kurzbz AS "lv_oe_kurzbz", + 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", + 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", + 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" + 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) From 20ed9ffc41c0de6bf8d611a3055b5b4ec8b406fb Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Sun, 11 Aug 2024 21:59:13 +0200 Subject: [PATCH 25/54] UHSTAT Formular: added "unknown" options to every input --- application/controllers/codex/UHSTAT1.php | 6 +- application/views/codex/uhstat1.php | 162 ++++++++++++++-------- system/phrasesupdate.php | 22 ++- 3 files changed, 128 insertions(+), 62 deletions(-) diff --git a/application/controllers/codex/UHSTAT1.php b/application/controllers/codex/UHSTAT1.php index 4486f9d74..38b0f3b6d 100644 --- a/application/controllers/codex/UHSTAT1.php +++ b/application/controllers/codex/UHSTAT1.php @@ -363,7 +363,11 @@ class UHSTAT1 extends FHC_Controller // get realistic birth years, dated back from current year $currYear = date("Y"); - $formMetaData['jahre'] = range($currYear - self::UPPER_BOUNDARY_YEARS, $currYear - self::LOWER_BOUNDARY_YEARS); + $yearRange = range($currYear - self::UPPER_BOUNDARY_YEARS, $currYear - self::LOWER_BOUNDARY_YEARS); + $formMetaData['jahre'] = array_combine($yearRange, $yearRange); + + // add "unknown" option + $formMetaData['jahre'][9999] = 'unbekannt'; return success($formMetaData); } diff --git a/application/views/codex/uhstat1.php b/application/views/codex/uhstat1.php index 78a30b3e5..a255781f1 100644 --- a/application/views/codex/uhstat1.php +++ b/application/views/codex/uhstat1.php @@ -74,16 +74,23 @@ $saved = isset($saved) && $saved === true;
- +
+ + + + +
@@ -94,16 +101,23 @@ $saved = isset($saved) && $saved === true; p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
- +
+ + + + +
@@ -114,16 +128,23 @@ $saved = isset($saved) && $saved === true; p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
- +
+ + + + +
@@ -161,16 +182,23 @@ $saved = isset($saved) && $saved === true;
- > + + $jahr): ?> + - - + + + + + +
@@ -181,16 +209,23 @@ $saved = isset($saved) && $saved === true; p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
- +
+ + + + +
@@ -201,16 +236,23 @@ $saved = isset($saved) && $saved === true; p->t('uhstat', 'inDenHeutigenGrenzen')).')' ?>
- +
+ + + + +
@@ -271,7 +313,7 @@ $saved = isset($saved) && $saved === true; - - + + load->view('templates/FHC-Footer'); ?> diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index ad2b6aa57..6fcaf4bf6 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -24698,7 +24698,7 @@ array( 'insertvon' => 'system' ) ) - ), + ), array( 'app' => 'personalverwaltung', 'category' => 'gehaltsband', @@ -26942,6 +26942,26 @@ array( ) ), // Betriebsmittel end + array( + 'app' => 'core', + 'category' => 'uhstat', + 'phrase' => 'unbekannt', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'unbekannt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'unknown', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ) ); From 8a9e040554f63d9310d97b9c9234c5808c7832f3 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Tue, 13 Aug 2024 16:57:05 +0200 Subject: [PATCH 26/54] added Gehaltstyp model --- .../vertragsbestandteil/GehaltsTyp_model.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 application/models/vertragsbestandteil/GehaltsTyp_model.php diff --git a/application/models/vertragsbestandteil/GehaltsTyp_model.php b/application/models/vertragsbestandteil/GehaltsTyp_model.php new file mode 100644 index 000000000..c933a3b38 --- /dev/null +++ b/application/models/vertragsbestandteil/GehaltsTyp_model.php @@ -0,0 +1,28 @@ +dbTable = 'hr.tbl_gehaltstyp'; + $this->pk = 'gehaltstyp_kurzbz'; + } + + /** + * Gets Gehaltstyp for a Gehaltsbestandteil. + * @param int gehaltsbestandteil_id + * @return object the typ + */ + public function getGehaltstypByGehaltsbestandteil($gehaltsbestandteil_id) + { + $gehaltsTyp = null; + $this->addJoin('hr.tbl_gehaltsbestandteil', 'gehaltstyp_kurzbz'); + $result = $this->loadWhere(['gehaltsbestandteil_id' => $gehaltsbestandteil_id]); + + if (hasData($result)) $gehaltsTyp = getData($result)[0]; + + return $gehaltsTyp; + } +} From 3963358d95aa1f08ff413b7c176c38e4d4a82568 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 13 Aug 2024 14:01:57 +0200 Subject: [PATCH 27/54] Added getTemplateLvTree method to Lehrveranstaltung_model.php This method gets all Templates and unions 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. --- .../education/Lehrveranstaltung_model.php | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 904433439..50d7b9ad4 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -146,6 +146,166 @@ class Lehrveranstaltung_model extends DB_Model 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 From 4dc698a6be000ae03bef6d36dbf421b847834724 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:17:54 +0200 Subject: [PATCH 28/54] Added navigation menu item 'Lehrveranstaltungen' > 'LV Template Uebersicht' --- application/config/navigation.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) 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'), From bff5d4ffbe80bf72cee3a163235784dcd8f95c37 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:22:15 +0200 Subject: [PATCH 29/54] Added api Controller Lehrveranstaltung.php + method getTemplateLvTree --- .../v1/education/Lehrveranstaltung.php | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 application/controllers/api/frontend/v1/education/Lehrveranstaltung.php 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..20e36f461 --- /dev/null +++ b/application/controllers/api/frontend/v1/education/Lehrveranstaltung.php @@ -0,0 +1,63 @@ + self::PERM_LOGGED + )); + + // 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) ?: [])); + } +} From d07f19d8936dbc4e99c25c0341ea225bf43ff4cf Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:23:26 +0200 Subject: [PATCH 30/54] Added api Controller Studiensemester.php + methods getAll and getAktNext --- .../v1/organisation/Studiensemester.php | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 application/controllers/api/frontend/v1/organisation/Studiensemester.php 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) ?: '')); + } +} From 6168a6b806bef926ab69c93456d51ea37e9d764f Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:26:20 +0200 Subject: [PATCH 31/54] Added Controller LvTemplateUebersicht.php --- .../lehre/lvplanung/LvTemplateUebersicht.php | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 application/controllers/lehre/lvplanung/LvTemplateUebersicht.php diff --git a/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php new file mode 100644 index 000000000..eb01d90c8 --- /dev/null +++ b/application/controllers/lehre/lvplanung/LvTemplateUebersicht.php @@ -0,0 +1,45 @@ + 'basis/vilesci: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 From eb308b78ef4691186f452172ac50a3c46ed6a95f Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:28:56 +0200 Subject: [PATCH 32/54] Added App LvTemplates.js --- public/js/apps/lehre/lvplanung/LvTemplates.js | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 public/js/apps/lehre/lvplanung/LvTemplates.js 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 From fc8c748bc4b0ba3bcfa18bb2d293534d58a4a27a Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:32:14 +0200 Subject: [PATCH 33/54] Added View LvTemplateUebersicht.php --- .../lehre/lvplanung/lvTemplateUebersicht.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 application/views/lehre/lvplanung/lvTemplateUebersicht.php diff --git a/application/views/lehre/lvplanung/lvTemplateUebersicht.php b/application/views/lehre/lvplanung/lvTemplateUebersicht.php new file mode 100644 index 000000000..54afad0a5 --- /dev/null +++ b/application/views/lehre/lvplanung/lvTemplateUebersicht.php @@ -0,0 +1,26 @@ + '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') +); + +$this->load->view('templates/FHC-Header', $includesArray); +?> + +
+ + + + +
+ +load->view('templates/FHC-Footer', $includesArray); ?> From e5e4bb2ea17fc0dda390595e285541efe03998dc Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:32:37 +0200 Subject: [PATCH 34/54] Added Component LvTemplateUebersicht.js --- .../lehre/lvplanung/LvTemplateUebersicht.js | 267 ++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 public/js/lehre/lvplanung/LvTemplateUebersicht.js diff --git a/public/js/lehre/lvplanung/LvTemplateUebersicht.js b/public/js/lehre/lvplanung/LvTemplateUebersicht.js new file mode 100644 index 000000000..6ffc02881 --- /dev/null +++ b/public/js/lehre/lvplanung/LvTemplateUebersicht.js @@ -0,0 +1,267 @@ +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 + cbGroupStartOpen: true, // checkbox group organisationseinheit start open + } + }, + watch: { + cbGroupStartOpen(newVal){ + this.table.setGroupStartOpen(newVal); + this.table.setData(); + } + }, + computed: { + tabulatorOptions() { + 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 + groupBy: ["lv_oe_bezeichnung"], + groupToggleElement:"header", //toggle group on click anywhere in the group header + groupStartOpen: self.cbGroupStartOpen, + 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: true, visible:true, width: 80}, + {title: 'Lehrtyp Kurzbz', field: 'lehrtyp_kurzbz', headerFilter: true, visible:false, width: 70}, + {title: 'Studiengangtyp', field: 'stg_typ_bezeichnung', headerFilter: true, width: 250}, + {title: 'OrgForm', field: 'orgform_kurzbz', headerFilter: true, 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: 'LE-Gruppen', field: 'lehreinheitgruppen_bezeichnung', headerFilter: true, width: 200}, + {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 + // TODO change with brandnew FHCAPI getUrl after merge master + this.table.setData(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + + '/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 + // TODO change with brandnew FHCAPI getUrl after merge master + // ...danach im SWB auch die core rest clients raus bzw. ggf änderung requests auf api/frontend/... wie hier und core rest client ggf raus. + this.table.setData(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + + '/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') }}
+
+ + + +
+
+
+
+ + + +
+
+ +
+` +}; From 7fb7263424d5ed7a40c337f58b30f6c7ed16cf6a Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:34:11 +0200 Subject: [PATCH 35/54] Added phrases for LV Templates Overview --- system/phrasesupdate.php | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 2390b2261..8a9c72831 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -27322,6 +27322,66 @@ array( ) ) ), + 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' + ) + ) + ), ); From f2be396e7aa7518f384c74ec80d0678525bd6953 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 21 Aug 2024 13:53:49 +0200 Subject: [PATCH 36/54] Adapted to use new fhcApi.getUri method --- public/js/lehre/lvplanung/LvTemplateUebersicht.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/js/lehre/lvplanung/LvTemplateUebersicht.js b/public/js/lehre/lvplanung/LvTemplateUebersicht.js index 6ffc02881..9724fd42a 100644 --- a/public/js/lehre/lvplanung/LvTemplateUebersicht.js +++ b/public/js/lehre/lvplanung/LvTemplateUebersicht.js @@ -118,8 +118,8 @@ export default { await this.loadAndSetStudiensemester(); // Set table data - // TODO change with brandnew FHCAPI getUrl after merge master - this.table.setData(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + + this.table.setData( + this.$fhcApi.getUri() + '/api/frontend/v1/education/Lehrveranstaltung/getTemplateLvTree' + '?studiensemester_kurzbz=' + this.selectedStudiensemester ); @@ -133,16 +133,16 @@ export default { }, onChangeStudiensemester(){ // Reset table data - // TODO change with brandnew FHCAPI getUrl after merge master - // ...danach im SWB auch die core rest clients raus bzw. ggf änderung requests auf api/frontend/... wie hier und core rest client ggf raus. - this.table.setData(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + + 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; + 'vilesci/lehre/lehrveranstaltung.php?stg_kz=&semester=-1&orgform=-1&lehrveranstaltung_id=' + + row.getData().lehrveranstaltung_id; window.open(url, '_blank').focus(); }, From 6076d59c4b35d683e75d61080e5b0ff6f4c7fb44 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 4 Sep 2024 10:59:25 +0200 Subject: [PATCH 37/54] Removed Group by Organisationseinheit Instead added Organisationseinheit as column for filtering reasons. Column is invisible by default. --- .../lehre/lvplanung/LvTemplateUebersicht.js | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/public/js/lehre/lvplanung/LvTemplateUebersicht.js b/public/js/lehre/lvplanung/LvTemplateUebersicht.js index 9724fd42a..13efeb0e3 100644 --- a/public/js/lehre/lvplanung/LvTemplateUebersicht.js +++ b/public/js/lehre/lvplanung/LvTemplateUebersicht.js @@ -16,14 +16,7 @@ export default { table: null, studiensemester: [], selectedStudiensemester: '', - cbDataTreeStartExpanded: false, // checkbox expand dataTree or not - cbGroupStartOpen: true, // checkbox group organisationseinheit start open - } - }, - watch: { - cbGroupStartOpen(newVal){ - this.table.setGroupStartOpen(newVal); - this.table.setData(); + cbDataTreeStartExpanded: false // checkbox expand dataTree or not } }, computed: { @@ -43,9 +36,6 @@ export default { dataTree: true, dataTreeStartExpanded: self.cbDataTreeStartExpanded, dataTreeChildIndent: 15, //indent child rows by 15 px - groupBy: ["lv_oe_bezeichnung"], - groupToggleElement:"header", //toggle group on click anywhere in the group header - groupStartOpen: self.cbGroupStartOpen, persistence:{ filter: false, //persist filter sorting }, @@ -53,8 +43,9 @@ export default { {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: true, 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: true, width: 250}, + {title: 'Studiengangtyp', field: 'stg_typ_bezeichnung', headerFilter: true, width: 150}, {title: 'OrgForm', field: 'orgform_kurzbz', headerFilter: true, width: 70}, {title: 'Semester', field: 'semester', headerFilter: true, width: 50}, {title: 'Lehrveranstaltung', field: 'lv_bezeichnung', headerFilter: true, minWidth: 250}, @@ -241,13 +232,6 @@ export default { :tabulator-events="[{event: 'tableBuilt', handler: onTableBuilt}]">